Class | DCModelThumbnail |
In: |
dcmodel-thum.rb
|
Parent: | Object |
「dcmodel お絵描きサムネイル HTML 作成スクリプト」の作成用のクラス
COPYRIGHT | = | "GFD Dennou Club" | CopyRight | |
INFO_DELIMITER | = | ":" | 項目の区切り文字 |
copyright | [RW] | copyright |
css | [RW] | スタイルシートファイル |
ext_list | [RW] | 画像ファイルとして認識する拡張子 |
figdir | [RW] | 絵のあるディレクトリ名。カレントディレクトリから "#{@figdir}" の場所を探査する。 |
figtable_num | [RW] | 横にならべるファイル数 |
headlimit | [RW] | 接頭子制限 @headlimit = "figure_head"。 これにより、@headlimit に当てはまらないものは無視される |
html_author | [RW] | html の作成者情報 (ユーザアカウント名) |
img_height | [RW] | 画像ファイルサイズ (高さ) |
img_width | [RW] | 画像ファイルサイズ (幅) |
index | [RW] | 作成されるサムネイルのファイル名 (拡張子除く) |
index_ext | [RW] | 作成されるサムネイルの拡張子名 |
infofile | [RW] | 情報ファイル, $PWD/${infofile} |
message | [RW] | 本体。サムネイルの部分よりも上に出力される。 この変数自体は Array オブジェクトで、その内部に String オブジェクトが 格納される。 |
rd2_path | [RW] | rd2 ファイルのパス |
rd2htmlextlib | [RW] | rd2-ext-lib へのライブラリのパス |
title | [RW] | html ヘッダのタイトル |
tmp | [RW] | テンポラリファイル置き場 (UNIX 系ならば変える必要なし) |
これを呼ぶことで、最低限必要な情報が生成される。 最終的には DCModelThumbnail.create メソッドを呼ぶことで ファイルが作成される。
# File dcmodel-thum.rb, line 235 235: def initialize() 236: # 237: # copyright 238: # 239: @copyright = COPYRIGHT 240: 241: # html の置き場・ファイル名・拡張子。カレントディレクトリから 242: # 243: # "#{@index}#{index_ext}" 244: # 245: #に置かれる。 246: @index = "../htmlname" 247: @index_ext = ".htm" 248: 249: # 絵のあるディレクトリ名。カレントディレクトリから 250: # "#{@figdir}" の場所を探査する。 251: @figdir = "../figdir" 252: 253: # 情報ファイル, $PWD/${infofile} 254: @infofile = File.basename(@index).chomp.strip + ".txt" 255: 256: # 画像ファイルとして認識する拡張子 257: @ext_list = ["gif", "png", "jpg", "jpeg"] 258: 259: # 接頭子制限 @headlimit = "figure_head"。 260: # これにより、@headlimit に当てはまらないものは無視される 261: @headlimit = "" 262: 263: # スタイルシートファイル 264: @css = "/GFD_Dennou_Club/ftp/arch/dcmodel/htmltools/dcmodel.css" 265: 266: # rd2 ファイルのパス 267: @rd2_path = "/usr/bin/rd2" 268: 269: # rd2-ext-lib へのライブラリのパス 270: @rd2htmlextlib = "/GFD_Dennou_Club/ftp/arch/dcmodel/lib" 271: 272: # テンポラリファイル置き場 (UNIX 系ならば変える必要なし) 273: @tmp = "/tmp" 274: 275: # 画像ファイルサイズ 276: @img_width = 200 277: @img_height = 150 278: 279: # 横にならべるファイル数 280: @figtable_num = 3 281: 282: # html の作成者情報 (ユーザアカウント名) 283: @html_author = username_from_gid 284: 285: # html ヘッダタイトル 286: @title = "タイトル" 287: 288: # 本体 (サムネイルの部分よりも上にメッセージ) 289: @message = Array.new 290: @message << "=begin\n[((<\303\317\265\345\316\256\302\316\305\305\307\276\266\346\263\332\311\364|URL:http://www.gfd-dennou.org>))]\n[((<dcmodel|URL:http://www.gfd-dennou.org/arch/dcmodel>)) |\n((<dcmodel-tools|URL:http://www.gfd-dennou.org/arch/dcmodel/bin>))]\n\n= \#{@title}\n\n== \314\334\274\241\n\n=== \303\346\314\334\274\241\n\n* \245\352\245\271\245\310\n* \276\256\271\340\314\334\n\n* ((<\276\360\312\363\245\325\245\241\245\244\245\353\244\330\244\316\245\352\245\363\245\257|URL:thum/htmlname.txt>))\n* \262\350\301\374\245\325\245\241\245\244\245\353\244\330\244\316\245\352\245\363\245\257((<URL:figdir>))\n=end\n\n" 291: @message << "=begin RT\ncaption = \311\275\245\306\245\271\245\310\n\n, \277\315\264\326, == , \270\244 , ==\n|| , \303\313 , \275\367 ,\245\252\245\271,\245\341\245\271\n\nx , 1.0 , 2.0, 1.1, 1.2\ny , 0.4 , 0.5, 0.3, 0.1\n\n=end\n" 292: @message << "<br>\n\274\302\270\263\300\337\304\352\244\312\244\311\244\317\244\263\244\263\244\313\275\361\244\255\271\376\244\340. <br>\n\244\263\244\263\244\313\275\361\244\244\244\277\312\270\273\372\244\317\245\273\245\363\245\277\245\352\245\363\245\260\244\265\244\354\244\306\244\267\244\336\244\246. <br>\n\244\301\244\347\244\303\244\310\263\346\271\245\260\255\244\244. <br><br>\n<table BORDER=\\\\\"0\\\\\" cellspacing=\\\\\"10\\\\\" align=\\\\\"center\\\\\">\n<tr><td><small>\n\245\306\241\274\245\326\245\353\244\362\244\265\244\351\244\313\272\356\244\303\244\306\244\275\244\316\303\346\244\313\275\361\244\255\271\376\244\340. <br>\n\244\275\244\246\244\271\244\353\244\310\244\263\244\363\244\312\264\266\244\270.\n</small></td></tr></table>\n<br><br>\n[<a href =\\\\\"http://www.gfd-dennou.org/arch/dcmodel\\\\\">HOME</a>]\n<hr>\n" 293: 294: debug(@message) 295: end
HTML ファイルの最終的な作成メソッド。最後にこのメソッドを呼ぶことで 作業が完了する。
overwrite に false を与えると、上書きを禁止する。
quiet を true にするとエラーを除く全てのメッセージが表示されなくなる。
verbose を true にすると作業の進捗状況がメッセージとして出力される。
err を true にした場合、意図しない動作が起きた場合にすぐに エラーを起こす。
# File dcmodel-thum.rb, line 913 913: def create(overwrite=true, quiet=nil, verbose=true, err=true) 914: 915: # 916: # サムネイルファイル名 917: # 918: index_file_name = @index.chomp.strip + 919: @index_ext.chomp.strip 920: 921: # 922: # 元ファイル削除 (overwrite が nil の場合はエラー) 923: # 924: if File.exist?(index_file_name) 925: if overwrite then 926: File.delete(index_file_name) 927: else 928: raise ArgumentError, "Error : \"#{index_file_name}\" exist already.\n" 929: end 930: end 931: 932: 933: # 934: # infofile の作成 (既に存在する場合はそのまま)。 935: # DCModelThumbnail.info_make メソッドを呼ぶ 936: # 937: status = info_make(@figdir, @infofile, @ext_list, 938: @headlimit, nil, nil, 939: true, err) 940: if verbose then 941: if /create/ =~ status 942: $stdout.print " Message : Infofile \"#{@infofile}\" is created.\n" 943: elsif /exist/ =~ status 944: $stdout.print " Message : Infofile \"#{@infofile}\" is already exist.\n" 945: end 946: end 947: 948: # 949: # @message が Array オブジェクト以外の場合はエラーを返す。 950: # 951: if !@message.instance_of?(Array) then 952: warn_or_err( 953: "\"message\" must be Array Object. " + 954: "Please \"message = Array.new\" initially.\n", 955: true, nil, ArgumentError) 956: end 957: 958: # 959: # infofile から情報の取得。 960: # DCModelThumbnail.info_get メソッドを呼ぶ。 961: # 962: info_list = info_get(@infofile, @headlimit, nil, quiet, err) 963: # 964: # infofile からの情報のうち、画像ファイル名を "title" にしている 965: # ものに関して @title に上書きして、info_list から除く。 966: # 967: # infofile からの情報のうち、画像ファイル名を "message" にしている 968: # ものに関して @message に追加して、info_list から除く。 969: # 970: info_list_buff = Array.new 971: info_list.each{ |info_part| 972: if /title/ =~ info_part['fig_name'] 973: @title = info_part['comment'] 974: elsif /message/ =~ info_part['fig_name'] 975: @message << info_part['comment'] 976: else 977: info_list_buff << info_part 978: end 979: } 980: info_list = Array.new 981: info_list << info_list_buff 982: info_list.flatten! # 配列の平滑化 (1次元配列化) 983: 984: $stdout.print " Message : Get information from \"#{@infofile}\".\n" if verbose 985: 986: # 987: # @message のフォーマットを解析し、HTML に変換する。 988: # 989: html_message = Array.new 990: @message.each{ |mess| 991: format = format_parser(mess) 992: 993: if /rd/ =~ format then 994: html_buff = rd2html(mess, true) 995: elsif /rt/ =~ format then 996: html_buff = rd2html(mess, true) 997: else 998: html_buff = mess 999: end 1000: 1001: html_message << html_buff if html_buff 1002: debug(html_message) 1003: } 1004: debug(html_message) 1005: 1006: 1007: # 初期化 1008: html_entire = "" 1009: 1010: # ヘッダ部分 1011: $stdout.print " Message : Generate HTML Header...." if verbose 1012: html_entire << html_header 1013: $stdout.print " done.\n" if verbose 1014: 1015: # 本文 1016: $stdout.print " Message : Insert body messages...." if verbose 1017: html_message.each { |message| 1018: html_entire << message 1019: } 1020: $stdout.print " done.\n" if verbose 1021: 1022: # サムネイル部分 1023: $stdout.print " Message : Generate Thumbnail Lists...." if verbose 1024: html_entire << html_thum(info_list, quiet, true) 1025: $stdout.print " done.\n" if verbose 1026: 1027: # フッタ部分 1028: $stdout.print " Message : Generate HTML Footer...." if verbose 1029: html_entire << html_footer 1030: $stdout.print " done.\n" if verbose 1031: 1032: # ファイルの書きだし 1033: $stdout.print " Message : Output to #{index_file_name}...." if verbose 1034: ifile = open(index_file_name, "w") 1035: ifile.print html_entire 1036: ifile.close 1037: $stdout.print " Successfull. \n" if verbose 1038: end
サンプルスクリプト出力用のメソッド。 この DCModelThumnail クラスに依存するサンプルスクリプトを 引数 filename という名前で出力する。実際には、このファイル を編集・実行することでサムネイルが作成される寸法である。
# File dcmodel-thum.rb, line 1227 1227: def create_sample_rb(filename) 1228: if !(str_and_notspace?(filename)) then 1229: return warn_or_err("filename is invalid.\n", 1230: true, nil, ArgumentError) 1231: end 1232: 1233: rb_file_body = "#!/usr/bin/env ruby\n#\n#= dcmodel thumnail generate ruby script\n#\n# Editor :: \#{username_from_uid}\n# Version:: \#{Time.now.strftime(\"%Y/%m/%d %H:%M:%S\")}\n#\n#== Overview\n#\n#This file is generate by following ruby script automatically.\n#\n# \#{File.expand_path($0.to_s)}\n#\n#Please edit this file according to your purpose.\n#\n#== Usage\n#\n#\n##################################################\n\nrequire \"\#{File.expand_path($0.to_s)}\"\n\n######################################################\nif $0 == __FILE__ then\nthumb = DCModelThumbnail.new\n\n# thumb.copyright = \"\#{@copyright}\"\nthumb.index = \"\#{@index}\"\n# thumb.index_ext = \"\#{@index_ext}\"\nthumb.infofile = \"\#{@infofile}\"\n# thumb.ext_list.push(\"bmp\")\n# thumb.headlimit = \"headlimit_\"\n# thumb.figdir = \"\#{@figdir}\"\n# thumb.css = \"\#{@css}\"\n# thumb.rd2_path = \"\#{@rd2_path}\"\n# thumb.rd2htmlextlib = \"\#{@rd2htmlextlib}\"\n# thumb.img_width = \#{@img_width}\n# thumb.img_height = \#{@img_height}\n# thumb.figtable_num = \#{@figtable_num}\n# thumb.html_author = \"\#{@html_author}\"\nthumb.title = \"\#{@title}\"\nthumb.message = Array.new\nthumb.message << <<-MSG\n\#{@message[0]}\nMSG\n\nthumb.message << <<-MSG\n\#{@message[1]}\nMSG\n\nthumb.message << <<-MSG\n\#{@message[2]}\nMSG\nthumb.create\nend\n\n" 1234: 1235: # 1236: # ファイルの作成 1237: # 1238: ifile = open(filename, "w") 1239: ifile.print "#{rb_file_body}" 1240: ifile.close 1241: 1242: # 1243: # パーミッションの設定 1244: # 1245: File.chmod(0755, filename) 1246: 1247: end
mes で与えられる本文の行頭を解析し、その本文が HTML であるか、 RD であるか、RT であるのかを判別する。現在、以下のように判定している。
返り値は "html", "rd", "rt" のいづれかである。なお、body に String オブジェクト以外、もしくは完全に空白のみが入っている場合、 nil を返す。
# File dcmodel-thum.rb, line 1057 1057: def format_parser(body=nil) 1058: debug(body) 1059: if !(str_and_notspace?(body)) then 1060: return warn_or_err("\"body\" is not String Object.\n") 1061: end 1062: 1063: Kconv::toeuc(body) 1064: body_parts = body.split("\n") 1065: 1066: body_parts.each{ |line| 1067: next unless /\w+/e =~ line.chomp.strip 1068: if /=begin\s+(rt)/ie =~ line.chomp.strip 1069: return "rt" 1070: elsif /=begin/ie =~ line.chomp.strip 1071: return "rd" 1072: elsif /=begin\s+(rd)/ie =~ line.chomp.strip 1073: return "rd" 1074: else 1075: return "html" 1076: end 1077: } 1078: return nil 1079: end
フッター作成用メソッド。相当する文字列を返す。 DCModelThumbnail.html_header で得られる文字列で始まる HTML を 閉じることを想定している。
# File dcmodel-thum.rb, line 873 873: def html_footer() 874: # @index のディレクトリから見た、生成スクリプトの相対的な位置 875: generator = relative_str("#{$0}", @index) 876: 877: # @index のディレクトリから見た、情報ファイルの相対的な位置 878: infofile = relative_str(@infofile, @index) 879: 880: # 881: # フッターとして書き出し 882: # 883: html_footer = "<hr size=\"1\">\n<center>\n<small>\nThis page is generated by <a href=\\\"\#{generator}\\\">\#{generator}</a>\nand <a href=\\\"\#{infofile}\\\">\#{infofile}</a>\n(\#{Time.now.strftime(\"%Y/%m/%d %H:%M:%S\")} \#{username_from_uid})<br>\nCopyright © \#{@copyright} \#{Time.now.strftime(\"%Y\")}\n</small>\n</center>\n</body>\n</html>\n" 884: return html_footer 885: end
HTML のヘッダ部分の作成メソッド。相当する文字列を返す。 作成した HTML は DCModelThumbnail.html_footer で得られる文字列で 閉じられることを想定している。
# File dcmodel-thum.rb, line 642 642: def html_header() 643: # @index のディレクトリから見た、生成スクリプトの相対的な位置 644: generator = relative_str("#{$0}", @index) 645: 646: # @index のディレクトリから見た、css の相対的な位置 647: css = relative_str(@css, @index) 648: 649: header = "<?xml version=\"1.0\" encoding=\"euc-jp\" ?>\n<!DOCTYPE html\nPUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html lang=\"ja\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>\#{@title}</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=x-euc-jp\" />\n<meta name=\"Author\" content=\"\#{@html_author}\" />\n<meta name=\"robots\" content=\"noindex,nofollow\" />\n<meta name=\"robots\" content=\"noarchive\" />\n<meta name=\"generator\" content=\"\#{generator}\" />\n<link href=\"\#{css}\" type=\"text/css\" rel=\"stylesheet\" />\n</head>\n<body>\n" 650: return header 651: end
HTML のサムネイル部分 (画像の数に応じて繰り返す部分) を作成するメソッド。 相当する文字列を返す。info_list には DCModelThumbnail.info_get で 取得される形式の情報ファイルが与えられる。
それ以外の形のデータが与えられる場合には警告を発して nil を返す。 ただし、err に true を与えると、エラーが生じる。 quiet が true の場合には警告メッセージも表示しない。
内部で DCModelThumbnail.html_thum_parts を呼び、各要素はそちらで 作成する。
# File dcmodel-thum.rb, line 682 682: def html_thum(info_list=nil, quiet=nil, err=nil) 683: 684: # 685: # 引数に与えられたデータの検証 686: # 687: if !array_and_notzero?(info_list) then 688: return warn_or_err( 689: "\"info_list\" is invalid.\n", 690: err, quiet, ArgumentError) 691: end 692: 693: # 694: # table タグを作成 695: # 696: html_table = "" 697: 698: html_table = "<table border=\"0\" cellspacing=\"10\" align=\"center\">\n" 699: 700: # 701: # 中身を作成 702: # 703: info_list.size.times{ |num| 704: html_table << html_thum_parts(info_list, num, quiet, err) 705: } 706: 707: # 708: # もしも、info_list.size が @figtable_num で割り切れない場合、 709: # 残り分の空白 td を作成する 710: # 711: remain = @figtable_num - (info_list.size % @figtable_num) 712: td_width = (100 / @figtable_num).truncate.to_s + "%" # 一つの td の幅 713: 714: if !(remain == 0) then 715: remain.times{ |time| 716: html_table << "<td width=\"\#{td_width}\" valign=\"top\">\n \n</td>\n" 717: } 718: html_table << "</tr>\n" 719: end 720: 721: # 722: # /table タグを作成 723: # 724: html_table << "</table>\n" 725: 726: return html_table 727: end
HTML のサムネイル部分の内部 (テーブルの1要素毎) を作成するメソッド。 相当する文字列を返す。info_list には DCModelThumbnail.info_get で 取得される形式の情報ファイルを、num には何番目のデータなのかを 示す Numerical オブジェクトを与える。
それ以外の形のデータが与えられる場合には警告を発して nil を返す。 ただし、err に true を与えると、エラーが生じる。 quiet が true の場合には警告メッセージも表示しない。
# File dcmodel-thum.rb, line 754 754: def html_thum_parts(info_list=nil, num=nil, quiet=nil, err=nil) 755: # 756: # 引数に与えられたデータの検証 757: # 758: if !array_and_notzero?(info_list) then 759: return warn_or_err( 760: "\"info_list\" is invalid.\n", 761: err, quiet, ArgumentError) 762: end 763: 764: if !num.kind_of?(Integer) 765: return warn_or_err( 766: "\"num\" is not integer.\n", 767: err, quiet, ArgumentError) 768: end 769: 770: # 771: # info_list からデータの取得 772: # 773: fig_name = info_list[num]['fig_name'] # 画像ファイル名 774: comment = info_list[num]['comment'] # コメント 775: align = info_list[num]['align'] # 文字寄せ 776: fig_name_nohead = info_list[num]['fig_name_nohead'] # 省略画像ファイル名 777: format = info_list[num]['format'] # comment のフォーマット 778: debug(fig_name, comment, align, fig_name_nohead) 779: 780: # 781: # format から、comment の変換処理 782: # 783: if /rd/ =~ format then 784: comment_buff = rd2html(comment) 785: elsif /rt/ =~ format then 786: comment_buff = rd2html(comment) 787: else 788: comment_buff = "#{comment}" 789: end 790: comment = "#{comment_buff}" 791: 792: # 793: # @index からの相対的な @figdir の設定 794: # 795: rel_figdir = relative_str(@figdir, @index) 796: 797: # 798: # テーブルの配置によって <tr> のつけたしをおこなう。 799: # (num はゼロからスタートすることに注意) 800: # 左端 : @figtable_num * n (remainder == 0) 801: # 右端 : @figtable_num * n - 1 (remainder == @figtable - 1) 802: # 803: remainder = num % @figtable_num # 余り 804: figtable_1 = @figtable_num - 1 # 列数 - 1 805: td_width = (100 / @figtable_num).truncate.to_s + "%" # 一つの td の幅 806: debug(num, remainder, figtable_1, @figtable_num, td_width) 807: 808: html_table_part = "" 809: 810: # 左端用の <tr> タグ 811: if remainder == 0 then 812: html_table_part = "<tr valign=\"center\">\n" 813: end 814: 815: # 画像ファイル名が "label" の場合には comment をそのまま書き出す。 816: if /^label$/ =~ fig_name_nohead.chomp.strip then 817: html_table_part << "<td align=\"\#{align}\" width=\"\#{td_width}\" valign=\"center\">\n<small>\n\#{comment}\n</small>\n</td>\n" 818: 819: # 画像ファイル名が存在しない場合は空白を書き出す。 820: elsif !(str_and_notspace?(fig_name_nohead)) then 821: html_table_part << "<td align=\"\#{align}\" width=\"\#{td_width}\" valign=\"top\">\n \n</td>\n" 822: 823: # 上記以外の場合には、絵の縮小版とそのリンクを張り込む 824: else 825: html_table_part << "<td align=\"center\" width=\"\#{td_width}\" valign=\"top\">\n<a href=\"\#{rel_figdir}/\#{fig_name}\">\n<img src=\"\#{rel_figdir}/\#{fig_name}\" border=\"1\" width=\"\#{@img_width.to_s}\" height=\"\#{@img_height.to_s}\">\n</a>\n<br>\n<div align=\"\#{align}\">\n<small>\n\#{fig_name_nohead}<br>\n\#{comment}<br><br>\n</small>\n</div>\n</td>\n" 826: end 827: 828: # 右端用の </tr> タグ 829: if remainder == figtable_1 then 830: html_table_part << "</tr>\n" 831: end 832: 833: return html_table_part 834: end
DCModelThumbnail.info_make によって作成される「情報ファイル」 infofile から画像ファイル名とコメント、および修飾情報を取り出し、 Array[Hash, …] にして返す。 各要素の Hash にはキーに値の種類の文字列を格納してある。 以下は現在 Hash のキーとして取得されるものである。
* fig_name * ファイル名である。1 つ目の区切り文字 (DCModelThumbnail.info_make の INFO_DELIMITER 参照) よりも前の文字列をこのキーの値として取得する。なお、 引数 headlimit が与えられる場合、情報ファイルの文字列の 頭に headlimit を付加する。 * fig_name_nohead * fig_name と同様にファイル名である。ただし、こちらは 引数 headlimit が与えられる場合でも、情報ファイルから得られる 文字列のみを格納する。 * comment * サムネイルの個々の画像の下に付加されるコメントである。 2 つ目の区切り文字以降の文字列がこのキーの値として取得される。 なお、デフォルトでは改行文字までをコメントとして読み込むが、 将来的には修飾情報に "m" が入る場合、"{" と "}" の間の文字 を読み込むようにする予定である。(改行文字も含める)。 * align * コメントの文字寄せ情報である。1つ目と2つ目の区切り文字の間に 下記の文字列を入れることで、下記のそれに対応する値が格納される。 なお、デフォルトでは "center" が格納される。 * "<" : 左寄せを示し、値に "left" を格納する。 * ">" : 右寄せを示し、値に "right" を格納する。 * format * フォーマットの情報である。 下記の文字列を入れることで、下記のそれに対応する値が格納される。 なお、デフォルトでは "html" が格納される。 * "r" : RD フォーマットであることを示す。 * "t" : RT フォーマットであることを示す。 * line * 情報ファイルの該当情報の「行数」が格納される。 複数行が指定される場合は "4-10" というように格納される。
delimiter (String オブジェクト) は情報ファイルの 画像ファイル名・修飾情報・コメントの区切り文字を設定する ものであり、デフォルトは定数 INFO_DELIMITER にて設定されている。 一応変更できるようになっているが、原則的に変更しない 事を薦める。
quiet を真にすると、ファイルがない際にもメッセージを表示しない。
err を真にすると、ファイルが見つからない際にエラー処理をする。
# File dcmodel-thum.rb, line 541 541: def info_get(infofile=nil, headlimit=nil, delimiter=nil, 542: quiet=nil, err=nil) 543: 544: # delimiter のセット 545: if !(str_and_notspace?(delimiter)) then 546: delimiter = INFO_DELIMITER 547: end 548: 549: info_list = Array.new 550: 551: # ファイルが読み取れるかチェック 552: if !(File.readable?(infofile)) then 553: return warn_or_err("\"#{infofile}\" is not readable. \n", 554: err, quiet, ArgumentError) 555: end 556: 557: # 実際にファイルを開く 558: ifile = open(infofile, "r") 559: 560: line_num = 0 561: ifile.each { |line| 562: 563: # 探索したデータの格納用配列とハッシュ 564: info_part = Array.new 565: info_hash = Hash.new 566: 567: # 行数を数える 568: line_num += 1 569: 570: info_part = line.chomp.split(/#{delimiter}/, 3) 571: info_hash['fig_name_nohead'] = info_part[0] 572: info_hash['comment'] = info_part[2] 573: info_hash['line'] = line_num.to_s 574: 575: # 行頭が "#" の場合はコメントアウトと考えて無視。 576: if /^\s*#/ =~ info_part[0] then 577: next 578: end 579: 580: # info_hash['fig_name'] の設定 581: if str_and_notspace?(headlimit) then 582: info_hash['fig_name'] = headlimit.chomp.strip + info_part[0].chomp.strip 583: else 584: info_hash['fig_name'] = info_part[0] 585: end 586: 587: # 588: # 修飾子の解析 (万が一のことを考え、日本語も処理) 589: # 590: modifier = Kconv::toeuc(info_part[1].chomp.strip) 591: 592: # 593: # 日本語らしきものが入っていたら警告またはエラー 594: # 595: if !(modifier == Kconv::toeuc(modifier)) || 596: !(modifier == Kconv::tojis(modifier)) || 597: !(modifier == Kconv::tosjis(modifier)) then 598: 599: warn_or_err( 600: "\"#{modifier}\" include 2 bite code, " + 601: "so this may not be parsed correctly.\n", 602: err, quiet, ArgumentError) 603: end 604: 605: # 文字寄せ情報の解析 606: if />/ =~ modifier.chomp.strip then 607: info_hash['align'] = "right" 608: elsif /</ =~ modifier.chomp.strip then 609: info_hash['align'] = "left" 610: else 611: info_hash['align'] = "center" 612: end 613: 614: # フォーマット情報の解析 615: if /r/ =~ modifier.chomp.strip then 616: info_hash['format'] = "rd" 617: elsif /t/ =~ modifier.chomp.strip then 618: info_hash['format'] = "rt" 619: else 620: info_hash['format'] = "html" 621: end 622: 623: # 複数行を取得するかどうかの解析 624: if /m/ =~ modifier.chomp.strip then 625: warn_or_err( 626: "Still multi-line option is invalid.\n" 627: ) 628: end 629: 630: info_list.push(info_hash) 631: } 632: ifile.close 633: 634: return info_list 635: end
画像ファイル名・修飾情報・コメントを含む「情報ファイル」を作成するための メソッド。
figdir (String オブジェクト) 内の拡張子 ext_list (Array オブジェクト) にヒットするファイル名 をリストにし、infofile (String オブジェクト) に書き出す。
headlimit (String オブジェクト) を渡すと、ファイル名の頭が headlimit にヒットするものだけを拾い、リストからはその部分を 取り除くようにする。
overwrite を true にすると、infofile が存在する場合でも 上書きする。また、quiet を true にすると警告メッセージを表示しない。
delimiter (String オブジェクト) は情報ファイルの 画像ファイル名・修飾情報・コメントの区切り文字を設定する ものであり、デフォルトは定数 INFO_DELIMITER にて設定されている。 一応変更できるようになっているが、原則的に変更しない 事を薦める。
ファイルを作成したときは "create", 既存のものがすでに存在する 場合には "exist" を返し、既存のものが無く、なおかつ作成に失敗 した場合は false を返す。
ここで作成されるファイルは DCModelThumbnail.info_get で取得される ファイルの雛形である。
# File dcmodel-thum.rb, line 403 403: def info_make(figdir=nil, infofile=nil, ext_list=nil, 404: headlimit=nil, overwrite=nil, delimiter=nil, 405: quiet=nil, err=true) 406: 407: # infofile があり、overwrite が false の場合は終了。 408: if File.exist?(infofile) && !overwrite then 409: $stdout.print "[#{caller.first}] \n Warning: Infofile \"#{infofile}\" already exist. So not generate infofile once again.\n" unless quiet 410: return "exist" 411: end 412: 413: # 引数の有効性の検証 414: if !(str_and_notspace?(figdir)) then 415: if err then 416: raise ArgumentError, "Error: \"figdir\" is not specified. So \"infofile\" is not generated.\n. \n" 417: elsif !quiet 418: $stdout.print "[#{caller.first}] \n Warning: \"figdir\" is not specified. So \"infofile\" is not generated.\n\n" 419: return nil 420: end 421: 422: elsif !(str_and_notspace?(infofile)) then 423: if err then 424: raise ArgumentError, "Error: \"infofile\" is not specified. So \"infofile\" is not generated.\n. \n" 425: elsif !quiet 426: $stdout.print "[#{caller.first}] \n Warning: \"infofile\" is not specified. So \"infofile\" is not generated.\n\n" 427: return nil 428: end 429: 430: elsif !(array_and_notzero?(ext_list)) then 431: if err then 432: raise ArgumentError, "Error: \"ext_list\" is not specified. So \"infofile\" is not generated.\n. \n" 433: elsif !quiet 434: $stdout.print "[#{caller.first}] \n Warning: \"ext_list\" is not specified. So \"infofile\" is not generated.\n\n" 435: return nil 436: end 437: end 438: 439: # delimiter のセット 440: if !(str_and_notspace?(delimiter)) then 441: delimiter = INFO_DELIMITER 442: end 443: 444: # headlimit の整形 445: if !(str_and_notspace?(headlimit)) then 446: headlimit = "" 447: end 448: 449: # figdir から画像ファイル名一覧をとりだし, 配列 imgfiles へ代入 450: imgfiles = Array.new 451: Dir.foreach("#{figdir}") { |item| 452: ext_list.each{ |ext| 453: next if !(str_and_notspace?(ext)) 454: 455: # ドットが付いていない場合はドットをつける 456: if !(/^\.(.*)/ =~ ext) then 457: ext = "." + ext.chomp.strip 458: end 459: 460: # 拡張から有効か判定 461: next unless /#{ext}$/i =~ item 462: 463: # headlimit から有効か判定 464: if str_and_notspace?(headlimit) then 465: if /^#{headlimit}(.+)$/ =~ item 466: bodyname = $1 467: else 468: next 469: end 470: else 471: bodyname = item 472: end 473: 474: # imgfiles への格納 475: #imgfiles.push( (File.basename(bodyname, ext) ) ) 476: imgfiles.push( bodyname ) 477: } 478: } 479: 480: imgfiles = imgfiles.sort 481: 482: # infofile に書き込み 483: ifile = open(infofile, "w") 484: imgfiles.each{ |filename| 485: ifile.print "#{filename}#{delimiter}#{delimiter}\n" 486: } 487: ifile.close 488: 489: return "create" 490: end
引数 rd に与えられた文字列を rd2html を掛けた文字列として 返す。デフォルトでは "=begin" や "=end" が存在しない文字列を 想定している。この場合、rd 文字列を "=begin" と "=end" ではさまれたものとして自動的に解釈する。もしも "=begin" や "=end" が書き込まれた文字列を rd として与えたい場合は 引数 beginend を true にすること。返される html は <body> 以上と </body> 以下は省かれた本文部分のみである。
もしも rd2 コマンドが存在しない場合には nil を返す。
なお、現在は rd2html-ext-lib を必ず利用するようになっているので インスタンス変数 rd2htmlextlib を適宜設定しないとまともに 動かないので注意すること。
# File dcmodel-thum.rb, line 1096 1096: def rd2html(rd=nil, beginend=nil, quiet=nil, err=nil) 1097: debug(rd) 1098: 1099: if !(FileTest.executable?(@rd2_path)) then 1100: return warn_or_err( 1101: "\"#{@rd2_path}\" is not excutable.\n", 1102: err, quiet, ArgumentError) 1103: elsif !rd 1104: return warn_or_err( 1105: "\"rd\" is invalid.\n", 1106: err, quiet, ArgumentError) 1107: end 1108: 1109: debug(@rd2_path) 1110: 1111: # "=begin" や "=end" を消去するための処理 1112: rd_body = "" 1113: if beginend then 1114: rd_parts = rd.split("\n") 1115: debug(rd_parts) 1116: rd_parts.each { |line| 1117: if /\s*=begin\s+.*/ =~ line then 1118: next 1119: elsif /\s*=begin$/ =~ line then 1120: next 1121: elsif /\s*=end\s+.*/ =~ line then 1122: next 1123: elsif /\s*=end$/ =~ line then 1124: next 1125: else 1126: rd_body << line + "\n" 1127: end 1128: } 1129: else 1130: rd_body = "#{rd}" 1131: end 1132: debug(rd_body) 1133: 1134: # rd で得られた文字列を /tmp/dcmodel-thum-$$.rd に一時的に格納 1135: rdfile_tmp = @tmp + "/" + File.basename($0.to_s) + "-" + $$.to_s 1136: debug(rdfile_tmp) 1137: 1138: tmpfile = open(rdfile_tmp, "w") 1139: tmpfile.print "=begin\n" 1140: tmpfile.print rd_body 1141: tmpfile.print "\n=end\n" 1142: tmpfile.close 1143: 1144: debug(open(rdfile_tmp){|io| io.read}) 1145: # print "#{open(rdfile_tmp){|io| io.read}}" 1146: 1147: # # ライブラリパスを $: に追加 1148: # @rd2lib.each{ |path| 1149: # next if !(str_and_notspace?(path)) 1150: ## $:.push(path) 1151: # $:.unshift(path) 1152: # } 1153: # debug($:) 1154: 1155: # 1156: # コマンドの文字列を整形 1157: # 1158: cmd = "#{@rd2_path}" 1159: cmd << " -r rd/rd2html-ext-lib" 1160: cmd << " --with-css=#{@css}" 1161: cmd << " --with-part=\'RT:rt\'" 1162: cmd << " --with-part=\'HTML:html\'" 1163: cmd << " --out-code=euc" 1164: cmd << " --ref-extension" 1165: cmd << " --native-inline" 1166: cmd << " --head-element" 1167: # cmd << " --headline-secno" 1168: # cmd << " --enable-br" 1169: 1170: debug(cmd) 1171: html_org = IO.popen("export RUBYLIB=#{@rd2htmlextlib} ; #{cmd} #{rdfile_tmp}").read 1172: debug(html_org) 1173: 1174: html_body_each_line = html_org.split(/\n/) 1175: debug(html_body_each_line) 1176: 1177: html_body = "" 1178: bodyflag = false 1179: html_body_each_line.each{ |line| 1180: if /^.*<body.*$/ =~ line then 1181: bodyflag = true 1182: next 1183: elsif /^.*<\/body.*$/ =~ line 1184: bodyflag = false 1185: else 1186: html_body << line + "\n" if bodyflag 1187: end 1188: } 1189: 1190: # テンポラリファイルを削除 1191: File.delete(rdfile_tmp) 1192: 1193: debug(html_body) 1194: return html_body 1195: end
target で与えられたパス (String オブジェクト) を from (String オブジェクト) から見た相対パスとして String オブジェクトで返す。 内部で Pathname クラスを利用している。 与えられるパスは絶対パスでも相対パスでもかまわない。
# File dcmodel-thum.rb, line 1203 1203: def relative_str(target=nil, from=nil) 1204: return nil unless str_and_notspace?(target) 1205: return target unless str_and_notspace?(from) 1206: 1207: from_dir = File.dirname(from) 1208: target_dir = File.dirname(target) 1209: target_base = File.basename(target) 1210: 1211: from_ab_path = Pathname.new(File.expand_path(from_dir)) 1212: target_ab_path = Pathname.new(File.expand_path(target_dir)) 1213: 1214: target_re_path = target_ab_path.relative_path_from(from_ab_path) 1215: 1216: result = target_re_path.to_s + "/" + target_base 1217: 1218: return result 1219: end
代入された変数が、配列で、且つゼロ配列ではないことを 調べるメソッド
# File dcmodel-thum.rb, line 1372 1372: def array_and_notzero?(obj) 1373: debug(obj) 1374: 1375: if obj.instance_of?(Array) && obj.size > 0 then 1376: return true 1377: else 1378: return false 1379: end 1380: 1381: end
デバッグ出力用メソッド。組み込み関数 $DEBUG が真の場合 (つまり、 プログラムを $ ruby -d ./xxxxxx.rb として呼び出した場合) に debug メソッドに代入された変数を出力する。
# File dcmodel-thum.rb, line 348 348: def debug(*args) 349: p [caller.first, *args] if $DEBUG 350: end
代入された変数が、文字列で、且つ空白文字のみではないことを 調べるメソッド。日本語であっても、文字列が入っていれば true を返す。
# File dcmodel-thum.rb, line 1350 1350: def str_and_notspace?(obj) 1351: debug(obj) 1352: 1353: if !obj.instance_of?(String) then 1354: return false 1355: end 1356: 1357: # 日本語の文字列も対応できるように 1358: Kconv::toeuc(obj) 1359: 1360: if /\w+/e =~ obj.chomp.strip then 1361: return true 1362: else 1363: return false 1364: end 1365: end
引数 gid に対応するユーザ名 (ログイン名) を返す。 gid に nil を与えた場合はプロセスの gid に対応するユーザ名 (ログイン名) を返す。gid が無効なものである場合、エラーを返す。
# File dcmodel-thum.rb, line 1333 1333: def username_from_gid(gid=nil) 1334: unless gid 1335: pw = Etc.getpwuid(Process.gid) or return nil 1336: else 1337: pw = Etc.getpwuid(gid) or return nil 1338: end 1339: 1340: user_name = pw.name 1341: return user_name 1342: end
引数 uid に対応するユーザ名 (ログイン名) を返す。 uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (ログイン名) を返す。uid が無効なものである場合、エラーを返す。
# File dcmodel-thum.rb, line 1316 1316: def username_from_uid(uid=nil) 1317: unless uid 1318: pw = Etc.getpwuid(Process.uid) or return nil 1319: else 1320: pw = Etc.getpwuid(uid) or return nil 1321: end 1322: 1323: user_name = pw.name 1324: return user_name 1325: end
警告またはエラー。 err が nil や false の場合、mes に与えられたメッセージを 警告として表示する。err が真の場合はそのメッセージの出力 と同時にエラーを発生させ、プログラムを終了させる。 errvar に変数を与えると、エラーの種類を指定できる。 quiet を true にすると、err が nil の場合、何も動作しなくなる。
# File dcmodel-thum.rb, line 361 361: def warn_or_err(mes=nil, err=nil, quiet=nil, errvar=nil) 362: return nil if !mes 363: 364: errvar = RuntimeError if !errvar 365: 366: if err then 367: raise errvar, "Error: #{mes}" 368: elsif !quiet 369: $stdout.print "[#{caller.first}] \n Warning: #{mes}" 370: return nil 371: end 372: end