#!/usr/bin/env ruby1.8 # #= dcmodel 用お絵描きサムネイル作成スクリプト # #Developers :: Yukiko YAMADA, Yasuhiro MORIKAWA, Shin-ichi TAKEHIRO #Version :: $Id: dcmodel-thum.rb,v 1.24 2005/12/09 07:45:36 morikawa Exp $ #Source :: $Source: /GFD_Dennou_Club/ftp/arch/dcmodel/cvsroot/dcmodel-tools/dcmodel-thum.rb,v $ # #== Overview # #実験結果 (主に dcmodel のモデル群によって得られた結果を描画したもの) #を手っ取り早くサムネイル化して表示するためのしまうためのクラスライブラリ #である。 # #このクラスを用いたサンプルスクリプトを出力するメソッドも持っている。 # # #= Operation Environment # #本プログラムは、ruby 1.8.2 (2005-01-10) [i386-linux] での #動作を確認している。 # #なお、ruby 1.6.7 (2002-03-19) [i386-linux] でならば、 #pathname.rb を RUBYPATH の通ったところに置けば動作可能である。 # # #== Usage # #まず、画像ファイル置き場として figdir を作成する。 #(ここでカレントディレクトリは ~/model とする。 #そして次に、thum ディレクトリを作成する。 #そしてそこで、このスクリプト本体を実行してほしい。 # # $ ruby dcmodel-thum.rb # #すると、サンプルとなる Ruby スクリプトが出力されるはずである。 # #まずはそのスクリプトを実行する。 # # $ ruby dcmodel-thum-make.rb # #すると、../sample_thum.htm などのようなファイルが生成されるはずである。 #チュートリアル的なことがそこに載っているので、手引きとしては #そちらを見て欲しい。同様に sample_thum.txt というファイルも作成される #はずである。そちらはサムネイルの個々の画像用のコメント等を記述する #ファイルである。 # #大雑把な流れは以下のようになる。 # #* dcmodel-thum.rb を実行して dcmodel-thum-make.rb を作成。 #* dcmodel-thum-make.rb を編集。(主に、サムネイル HTML のスタイル # などを設定することになる) #* sample_thum.txt を編集 #* dcmodel-thum-make.rb を再度実行 # #なお、生成された Ruby スクリプトは本スクリプトに依存しており、 #生成される際に絶対パスで本スクリプトを指定するようになっている。 #本スクリプトの移動や他のホストでの利用の際には注意すること。 # # #== Desctiption # #このプログラムの内部仕様に関しては、この Ruby スクリプトに rdoc を #使うと見やすいドキュメントが生成されるだろう。 # # $ rdoc --op doc --title DCModelThumbnail --charset euc-jp --inline-source --line-numbers --all dcmodel-thum.rb # #機能の拡張以外にも、外部から別箇呼べるメソッドもあるので、 #参考にして欲しい。 # #== Future Plans # #* rttool を用いた DCModelThumbnail.rt2html を作成する。 # * DCModelThumbnail.rd2html と同様にしてやってみる。 #* DCModelThumbnail.rd2html において、現在 rd2html-ext-lib の使用が # 必須になっているが、ライブラリが存在するかサーチする必要があるだろう。 # サーチして存在しない場合は、Warning を発して rd2html-lib を用いるか、 # エラーを吐くようにする。 # #== Notes # #今のところ、特になし。 # #== Acknowledgements # #本プログラムは、 #dcphoto.pl #Ver 1.02 - 写真用 HTML作成スクリプト (Chihiro MITSUDA) を元に #ruby で作成された ape-thum.rb (Yukiko YAMADA) を dcmodel の開発者が #共有できるように改良したものである。そのオリジナルは # (Yukiko Yamada) である。 #これはちょうど本プログラムのバージョン 1.1 に対応する。 # #== History # #These entries is generated by CVS automatically. #So don't add new information manually. #(But please adjust old log format to latest log format manually, #if format gap between them causes). # #$Log: dcmodel-thum.rb,v $ #Revision 1.24 2005/12/09 07:45:36 morikawa #* If "DCModelThumbnail.convert_overwrite" is false, modified time of # files are checked too. # #* フラグ DCModelThumbnail.convert_overwrite のチェックの際, # ファイルの存在だけでなく, タイムスタンプでチェックするよう修正. # #Revision 1.23 2005/12/09 07:23:12 morikawa #* "DCModelThumbnail.convert_overwrite" is added. If this variable is # false and converted files are exist, convert command is not executed. # #* convert コマンドが実行される, 既に出力先のファイルがある場合に上書きする # ためのフラグ DCModelThumbnail.convert_overwrite を追加. # これが false の場合, 出力先のファイルが存在する時は変換コマンドの # 実行をスキップする. # #Revision 1.22 2005/12/07 14:57:31 yukiko #* Fixed bug which cannot generate of thumbnail figures when the "thumb.headlimit" is specified # #* "thumb.headlimit" を指定すると convert 出来ないバグを修正 # #Revision 1.21 2005/11/09 10:43:15 morikawa #* If the "verbose" argument is nil in "DCModelThumbnail.create" # method, messages about generation of images for the thumbnail are # not outputted. # #* DCModelThumbnail.create メソッドの verbose に nil を与えた場合に, # サムネイル用画像生成メッセージも出力しないよう修正. # #Revision 1.20 2005/11/05 01:06:32 takepiro #* Regular expression for extracting tailing suffix from the figure filenames modified. #* 画像ファイルの拡張子を取りだす正規表現を変更した。 # #Revision 1.19 2005/11/02 03:50:29 morikawa #* When the label of the info file is "title" or "message", # images are not converted. # #* 情報ファイルのラベルが "title", "message" の場合には画像変換 # しないよう修正. # #Revision 1.18 2005/11/02 00:59:59 takepiro #* Cheking the status of thumnail generation process. #* サムネイル画像生成プロセスステータスのチェックを追加. # #Revision 1.17 2005/11/01 09:31:00 morikawa #* New instance variable "convert_cmd" is added to change "convert" # command by users. #* The command for image conversion is checked. #* Messages in process of conversion are decorated. #* The SIGEN file for the directory for thumbnail images is created # automatically. #* "Maintainer" in SIGEN file is specified to account name when # "gate-toroku-system" is not available. # #* convert コマンドをユーザレベルで変更できるよう新たなインスタンス # 変数 convert_cmd を追加. #* 画像変換ツールの有無をチェックする機能を追加. #* 画像変換中のメッセージを装飾. #* サムネイル画像置き場ディレクトリの SIGEN ファイルを作成するようにし # た. #* gate システムからユーザ名を取得できない場合, アカウント名を SIGEN # ファイルに書き出すよう修正. # #Revision 1.16 2005/11/01 06:46:24 takepiro #* Automatic generation of thumbnail figures implemented. #* Each one page can be extracted as a thumbnail from each animation file, such as gif-anime. # #* サムネイル画像の自動生成機能を追加した。 #* アニメーションファイル(gif-anime 等)から 1 ページを取りだしてサムネイル化できるようにした。 # #Revision 1.15 2005/10/31 02:41:34 morikawa #* Methods "DCModelThumbnail.create", "DCModelThumbnail.create_sample_rb" # are moved up. # #* DCModelThumbnail.create メソッドと DCModelThumbnail.create_sample_rb # メソッドを上の方に移動する. # #Revision 1.14 2005/05/25 15:54:32 morikawa #* Enable to specify whether to allow search of robots by # DCModelThumbnail.norobots . #* Allow search of robots by default. #* Add to tutorial about generation of SIGEN file. #* Add to tutorial about search of robots. # #* HTML のロボット検索を許可するかどうか指定できるようにした。 #* デフォルトでロボット検索を許可するようにした。 #* SIGEN ファイル生成に関してチュートリアルにも記載した。 #* ロボット検索の指定に関してチュートリアルにも記載した。 # #Revision 1.13 2005/05/15 20:21:51 morikawa #* Use "ruby1.8" instead of "ruby" in dcmodel-thum-make.rb . # (This should be modified by modification before). # #Revision 1.12 2005/05/15 19:58:29 morikawa #* Use "ruby1.8" instead of "ruby". (This program depends on # pathname.rb that is included ruby 1.8). # #Revision 1.11 2005/04/30 20:30:37 morikawa #* Create SIGEN file automatically. # #Revision 1.10 2005/04/30 18:54:24 morikawa #* Add directly css setting to DCModelThumbnail.html_header by # DCModelThumbnail.style . # #Revision 1.9 2005/04/30 18:18:02 morikawa #* Modify DCModelThumbnail.info_get to get correct default value. # #Revision 1.8 2005/04/30 17:50:05 morikawa #* Hard code "dcmodel-thum.rb" to @self_name. (Otherwise, not # "dcmodel-thum.rb" but executed file is wrote footer of HTML). # #Revision 1.7 2005/04/30 09:43:19 morikawa #* In "info_get", when multi-line input, permit input ":". # #Revision 1.6 2005/04/30 09:07:14 morikawa #* In "info_make", cause error if any image files are not found. # #Revision 1.5 2005/04/21 13:03:17 morikawa #* Change comment of DCModelThumbnail.info_get format. # #Revision 1.4 2005/04/21 12:57:23 morikawa #* Change log format. # #Revision 1.3 2005/04/21 09:24:06 morikawa #* Add "Operation Environment" #* Output detail sample messages. #* In DCModelThumbnail.rd2html , modify to remove only "^=begin" and # "^=end" #* Add Comment for sample rb script. #* Output Help message when argument is given. # #Revision 1.2 2005/04/19 20:32:19 morikawa #* Modify internal structure. #* Revise for "rdoc" documentation format. #* RD format context is supported. #* Add various options in "infofile". #* Use "keyword substitution" in CVS for version control. # #Revision 1.1 2005/04/19 19:54:23 morikawa #* This script generate Thumbnail HTML for calculation result figures. # The author of the original is Yukiko Yamada. She rename her "ape-thum.rb" # to "dcmodel-thum.rb" for sharing by dcmodel developers and users. # ################################################## require 'date' require 'etc' require 'kconv' require 'pathname' ################################################## # #== DCModelThumbnail # # 「dcmodel お絵描きサムネイル HTML 作成スクリプト」の作成用のクラス # class DCModelThumbnail # # 定数の設定 # # CopyRight COPYRIGHT = "GFD Dennou Club" # 項目の区切り文字 INFO_DELIMITER = ":" # 情報ファイルにおける、複数行の開始文字 INFO_MULTI_START = "{" # 情報ファイルにおける、複数行の終了 INFO_MULTI_STOP = "}" # SIGEN ファイル作成時の情報を得るための gate コマンド GATE_USER_SHOW = "/usr/local/bin/gate-user-show" # 公開本体置き場 PUB_BIN_URL = "http://www.gfd-dennou.org/arch/dcmodel/bin/dcmodel-thum.rb" # 公開ドキュメントの URL PUB_DOC_URL = "http://www.gfd-dennou.org/arch/dcmodel/doc/dcmodel-tools/dcmodel-thum-rdoc" # 公開サンプルの URL PUB_SAMPLE_URL = "http://www.gfd-dennou.org/arch/dcmodel/doc/dcmodel-tools/dcmodel-thum-sample" # CVSHOST CVS_HOST = "www.gfd-dennou.org" # CVSROOT CVS_ROOT = "/GFD_Dennou_Club/ftp/arch/dcmodel/cvsroot" # CVS のプロジェクト名 CVS_PROJECT = "dcmodel-tools" # バージョンナンバー (CVS により自動管理) VER = "$Revision: 1.24 $ : $Date: 2005/12/09 07:45:36 $" # # インスタンス変数群 # # バージョン attr_reader :version # copyright attr_accessor :copyright # 公開ドキュメントの URL attr_reader :pub_doc_url # 公開サンプルの URL attr_reader :pub_sample_url # 実行ファイルの basename attr_reader :self_name # サンプル ruby スクリプト名 attr_reader :sub_rb_name # 作成されるサムネイルのファイル名 (拡張子除く) attr_accessor :index # 作成されるサムネイルの拡張子名 attr_accessor :index_ext # 「情報ファイル (infofile)」のファイル名 attr_accessor :infofile # 画像ファイルとして認識する拡張子 attr_accessor :ext_list # headlimit に当てはまらないものは画像としては無視され、 # 当てはまるものは「情報ファイル」において、接頭部分 headlimit が # 省略可能になる。 attr_accessor :headlimit # 絵のあるディレクトリの名前。必ず存在していなければならない。 attr_accessor :figdir # サムネイル画像を置くディレクトリ名。カレントディレクトリから # "#{@thumbaildir}" の場所に指定される. attr_accessor :thumbnaildir # サムネイル画像の最後部名. # サムネイル画像名は元画像の拡張子と置換された名前になる. attr_accessor :thumbnailtail # サムネイル画像化する元画像のページ番号 attr_accessor :thumbnailpage # convert コマンドおよびオプション. この後ろに画像サイズが 200x150 # のような形式で指定される. attr_accessor :convert_cmd # convert コマンドが実行される際, 既に出力先のファイルがある場合に # 上書きするためのフラグ. これが false の場合, 出力先のファイルが # 存在し, 且つ元のファイルよりも新しい場合は変換を行わない. attr_accessor :convert_overwrite # スタイルシートファイル attr_accessor :css # スタイルシートを直接設定するためのもの # (css ファイルに書き込む情報を直接指定できる) attr_accessor :style # rd2 コマンドへのパス attr_accessor :rd2_path # rd2-ext-lib へのライブラリへのパス attr_accessor :rd2htmlextlib # SIGEN ファイル作成時の情報を得るための gate コマンド attr_accessor :gate_user_show # 画像ファイルサイズ (幅) attr_accessor :img_width # 画像ファイルサイズ (高さ) attr_accessor :img_height # 横にならべるファイル数 attr_accessor :figtable_num # html の作成者情報 (デフォルトはユーザアカウント名が自動取得される) attr_accessor :html_author # html ヘッダのタイトル attr_accessor :title # 本体に書き出すメッセージ。サムネイルの部分よりも上に出力される。 # この変数自体は Array オブジェクトで、その内部に String オブジェクトが # 格納される。 attr_accessor :message # テンポラリファイル置き場 (UNIX 系ならば変える必要なし) attr_accessor :tmp # SIGEN ファイルを作らない場合は false にセットする attr_accessor :mksigen # HTML のロボット検索を禁止する attr_accessor :norobots # # これを呼ぶことで、最低限必要な情報が生成される。 # 最終的には DCModelThumbnail.create メソッドを呼ぶことで # ファイルが作成される。 # def initialize() # # version # @version = VER # # copyright # @copyright = COPYRIGHT # 公開ドキュメントの URL @pub_doc_url = PUB_DOC_URL # 公開サンプルの URL @pub_sample_url = PUB_SAMPLE_URL # dcmodel-thum.rb 自身の名前 # @self_name = File.basename($0.to_s) @self_name = "dcmodel-thum.rb" # サンプル ruby スクリプト名 @sub_rb_name = "#{File.basename($0, ".*")}" + "-make.rb" # html の置き場・ファイル名・拡張子。カレントディレクトリから # # "#{@index}#{index_ext}" # #に置かれる。 @index = "../sample_thum" @index_ext = ".htm" # 絵のあるディレクトリ名。カレントディレクトリから # "#{@figdir}" の場所を探査する。 @figdir = "../figdir" # サムネイル画像を置くディレクトリ名。カレントディレクトリから # "#{@thumbaildir}" の場所に指定される. @thumbnaildir = "../thumbdir" # サムネイル画像の最後部名. # サムネイル画像名は元画像の拡張子と置換された名前になる. @thumbnailtail = "_thumb.png" # サムネイル画像化する元画像のページ番号 @thumbnailpage = "1" # convert コマンドおよびオプション。この後ろに画像サイズが 200x150 # のような形式で指定される。 @convert_cmd = "convert -depth 8 -geometry" # convert コマンドが実行される際, 既に出力先のファイルがある場合に # 上書きするためのフラグ. これが false の場合, 出力先のファイルが # 存在し, 且つ元のファイルよりも新しい場合は変換を行わない. @convert_overwrite = false # 情報ファイル, $PWD/${infofile} @infofile = File.basename(@index).chomp.strip + ".txt" # 画像ファイルとして認識する拡張子 @ext_list = ["gif", "png", "jpg", "jpeg"] # 接頭子制限 @headlimit = "figure_head"。 # これにより、@headlimit に当てはまらないものは無視される @headlimit = "" # スタイルシートファイル # @css = "../dcmodel.css" # for morikawa (I'm sorry...) @css = "/GFD_Dennou_Club/ftp/arch/dcmodel/htmltools/dcmodel.css" # スタイルシートを直接設定するためのもの # (css ファイルに書き込む情報を直接指定できる) @style = nil # rd2 ファイルのパス @rd2_path = "/usr/bin/rd2" # rd2-ext-lib へのライブラリのパス # @rd2htmlextlib = ".." # for morikawa (I'm sorry...) @rd2htmlextlib = "/GFD_Dennou_Club/ftp/arch/dcmodel/lib/ruby/1.8" # SIGEN ファイル作成時の情報を得るための gate コマンド @gate_user_show = GATE_USER_SHOW # テンポラリファイル置き場 (UNIX 系ならば変える必要なし) @tmp = "/tmp" # SIGEN ファイルを作らない場合は false にセットする @mksigen = true # HTML のロボット検索を禁止する場合には true にセットする @norobots = false # 画像ファイルサイズ @img_width = 200 @img_height = 150 # 横にならべるファイル数 @figtable_num = 3 # html の作成者情報 (ユーザアカウント名) @html_author = username_from_gid # html ヘッダタイトル @title = "dcmodel-thum : 実験結果サムネイル簡易作成スクリプト" # 本体 (サムネイルの部分よりも上にメッセージ) @message = Array.new @message << <<-EndOfTutorial =begin [((<地球流体電脳倶楽部|URL:http://www.gfd-dennou.org>))] [(()) | (())] [((<#{@self_name}|URL:#{PUB_DOC_URL}>))] = #{@title} * ((<概要・利用・動作環境の概説>)) * ((<バージョン 1.1 (オリジナルやまだ由ツール) からの仕様変更>)) * ((<利用の手引き>)) * ((<画像の用意>)) * ((<#{@self_name} の用意>)) * ((<とりあえず実行>)) * ((<子スクリプトの実行>)) * ((<できたものを見てみる>)) * ((<スクリプトの編集 (入門編)>)) * ((<再度実行>)) * ((<「情報ファイル」の編集 (入門編)>)) * ((<もう一度実行>)) * ((<スクリプトの編集 (応用編)>)) * ((<「情報ファイル」の編集 (応用編)>)) == 概要・利用・動作環境の概説 ((<#{@self_name} の rdoc マニュアル|URL:#{PUB_DOC_URL}>)) Overview と Operation Environment と Usage をさらっと読んだら戻ってきてね。 なお、以下の URL にはこの出力結果と同等のものが置いてあるはずです。 ((<#{@self_name} の サンプル|URL:#{PUB_SAMPLE_URL}>)) == バージョン 1.1 (オリジナルやまだ由ツール) からの仕様変更 ここは、バージョン 1.2 以降から利用している人には不要です。 バージョン 1.1 のオリジナルのやまだ由ツールから利用している 方は、以下の変更点にご注意ください。 * 「情報ファイル (infofile)」の書式 * 画像名に拡張子を加えるようになった * 1.1 では <画像名> : <コメント> だったが、 現在は <画像名> : <修飾子> : <コメント> になっている。 * pathname.rb を利用するため、ruby 1.8 を利用するか、1.6 ならば 実行の際に RUBYLIB のパスが通ったところに pathname.rb が必要 である。 == 利用の手引き === #{@self_name} の入手の方法 ((<#{@self_name} スクリプト本体|URL:#{PUB_BIN_URL}>)) をダウンロード してください。もしくは cvsroot をもっている #{CVS_HOST} にログインが 可能であれば、cvs からも直接取得が可能です。 $ CVS_RSH=ssh; export CVS_RSH $ cvs -d :ext:#{CVS_HOST}:#{CVS_ROOT} checkout #{CVS_PROJECT} 既に #{CVS_HOST} にログインした状態であれば、以下のコマンドのみで 取得可能です。 $ cvs -d #{CVS_ROOT} checkout #{CVS_PROJECT} == 画像の用意 サムネイル化しようとする画像を (({#{File.basename(@figdir)} })) という ディレクトリに置いてください。現在、画像として認識されるのは、 (({ #{@ext_list.join(", ")}, #{@ext_list.join(", ").swapcase} })) です。アニメーション gif にも一応対応していますが, サムネイル化する ページ番号は全画像共通にしか設定できません. 他の形式の画像を認識させたい場合は ((<スクリプトの編集 (入門編)>)) を参照してください。とりあえず、 まずは (({#{File.basename(@figdir)} })) を作成して下さい。 == #{@self_name} の用意 ((<#{@self_name} の入手の方法>)) で取得した #{@self_name} は (({ thum-src })) というディレクトリを作ってそこに置いて下さい。 結果的に、以下のような構成になっていると良いです。 ./#{File.basename(@figdir)}/*****.jpg *****.gif ./thum-src/dcmodel-thum.rb == とりあえず実行 (({ thum-src })) へ移動し、#{@self_name} を実行してください。 $ cd thum-src $ ruby #{@self_name} すると、#{@sub_rb_name} という実行スクリプトが作成される はずです。 == 子スクリプトの実行 今度は #{@sub_rb_name} を実行します。 $ ruby #{@sub_rb_name} すると、(({ #{@index}#{@index_ext} }))というファイルが作成されます。 これがサムネイルの HTML です。 == できたものを見てみる (({ #{@index}#{@index_ext} })) をブラウザで見てみてください。 このページと同様のメッセージが書かれたページが出力されている はずです。 #{File.basename(@figdir)} に画像をおいてあった場合、それらが 下にサムネイル化されているはずです。 == スクリプトの編集 (入門編) このままでは使えないので、(({ #{@sub_rb_name} })) を編集してください。 まず、ここに記述されるコメントを削除しましょう。 以下の部分以降を全て消してください。 thumb.message << <<-Message =begin [((<地球流体電脳倶楽部|URL:http://www.gfd-dennou.org>))] [(()) | : : 次に、作成される HTML ファイルの名前を希望のものに変更してください。 下記のように infofile を設定しておくと「情報ファイル」(後述) の 名前も一緒に変更されて便利です。 thumb.index = "../result" thumb.infofile = "\\\#\\\{File.basename(thumb.index)\\\}.txt" 画像として認識したい拡張子を増やしたい場合は以下のようにしてください。 thumb.ext_list.push("bmp") 画像ファイル名が長く、ファイル名の頭の部分を取り除いて表示したい、 またはファイル名の頭で出力するファイルの選択を行いたい場合は 以下のように設定してください。 thumb.headlimit = "exp_name_" 画像の縦横サイズや、サムネイルで横に表示する画像の数は以下のように 設定してください。 thumb.img_width = 200 thumb.img_height = 150 thumb.figtable_num = 3 自動生成されるサムネイル画像の置き場と画像の名前の最後部を 次のように指定して下さい. thumb.thumbnaildir = "../thumb" # サムネイル画像を置くディレクトリ名 thumb.thumbnailtail = "_thumb.png" # サムネイル画像の拡張子名 アニメーション gif 等複数ページを束ねた画像に対してはサムネイル化する ページ番号を 1 より大きい値に設定できます. thumb.thumbnailpage = "50" # サムネイル画像化する元画像のページ番号 スタイルシートに書き込む設定を単体でも指定可能です。 例えば、リンクに関する動作を設定するには以下のようにします。 thumb.style = <<-STYLE a:link { color:#269900; } a:visited { color:#269900; } a:hover { color:#99FF33; } STYLE 元々の (({ thumb.title ... })) の行を例えば以下のように書き換え、 タイトルを設定してください。(これは HTML の head タグ内の title タグに設定されます ) thumb.title = "実験結果" ちょうどこのチュートリアルが作成される場所に書き出す、 メッセージを設定してください。ここに書き込む内容がそのまま HTML として出力されるので、HTML タグも書き込んでください。 ((* 注意!! *)) message に代入するときの記号は必ず 「=」 ではなく、「<<」にしてください。 thumb.message << <<-MSG 実験結果 以下は実験結果を一覧したものである 実験設定 解像度 : T42L20 時間ステップ : 30 s : : MSG == 再度実行 再度 #{@sub_rb_name} を実行します。 $ ruby #{@sub_rb_name} すると、上記の記述が反映された (({ #{@index}#{@index_ext} })) が 作成されます。ブラウザで確認してください。 ただし、これだけでは、サムネイル内のコメントを編集できないので、 以下の ((<「情報ファイル」の編集 (入門編)>)) を参照してください。 == 「情報ファイル」の編集 (入門編) #{@sub_rb_name} を実行したディレクトリには上記で設定した infofile に対応したファイルが作成されるはずです。 thumb.infofile = "\\\#\\\{File.basename(thumb.index)\\\}.txt" このファイルを編集することで、サムネイル内にコメントを記述できます。 まず中身を見てみてください。 fig1.png:: fig2.gif:: fig3.jpg:: fig3.png:: これは、以下のようなフォーマットになっています。 <画像名> : <修飾子> : <コメント> <修飾子> に関しては ((<「情報ファイル」の編集 (応用編)>)) を参照してください。 === 画像の順序の入れ替え サムネイルには「情報ファイル」に書き込まれた順に書き出されます。 入れ替えたい時には行ごとその位置を入れ替えてください。 fig2.gif:: fig3.jpg:: fig3.png:: fig1.png:: === コメント付け コメントをつけたいときには、以下のようにしてください。 fig1.png:: 1 回目の実験 fig2.gif:: 2 回目の実験 fig3.jpg:: 3 回目の実験 (jpg 画像) fig3.png:: 3 回目の実験 (png 画像) HTML タグはそのまま認識されるので、以下のように書き込むことが 可能です。 fig1.png:: 1 回目の実験 失敗 === コメントアウト コメントアウトしたい場合は行頭に 「#」を書き込みます。 # fig2.gif:: 2 回目の実験 === ラベル 画像ではなく、コメントのみを書き込みたいときは、<画像名> に 「label」と記述します。 label:: 実験設定 2パラメータ 3 === スペース 一つ分飛ばして表示したい時は以下のように <画像名> の部分に何も書かないで 下さい。 :: == もう一度実行 再度 #{@sub_rb_name} を実行します。 $ ruby #{@sub_rb_name} すると、上記の記述が反映された (({ #{@index}#{@index_ext} })) が 作成されます。ブラウザで確認してください。 == スクリプトの編集 (応用編) ((<スクリプトの編集 (入門編)>)) の応用版です。 ((<#{@self_name} の rdoc マニュアル|URL:#{PUB_DOC_URL}>)) の DCModelThumbnail クラスの Attribute に設定できる全ての値 の情報があるので、詳しくはそちらを参照ください。 === 電脳サーバ以外で使うために 電脳サーバ以外での利用を考える場合には、下記の設定も編集する 必要があるかもしれません。 コピーライト thumb.copyright = "GFD Dennou Club" スタイルシート thumb.css = "/GFD_Dennou_Club/ftp/arch/dcmodel/htmltools/dcmodel.css" rd2 コマンドへのパス (これは、下記で紹介する RD という書法で 書く必要が無ければ、設定の必要はありません) thumb.rd2_path = "/usr/bin/rd2" rd2html-ext-lib の設定 (これも、下記で紹介する RD という書法で 書く必要が無ければ、設定の必要はありません) thumb.rd2htmlextlib = "/GFD_Dennou_Club/ftp/arch/dcmodel/lib" === RD を使いたい人のために 中には、「RD ((- RD (Ruby Documents) や rdtool に関しては、 (()) や (()) を参照してください。 -)) で書きたい!! HTML でなんか書きたくない!!」という わがままは方もいるかもしれません。(これを書いている私が正にそうです。 そのためにこのツールを改良したと言っても過言ではありません…)。 そういう方は、メッセージの設定の際に、頭に 「=begin」、一番最後に 「=end」と記述してください。 thumb.message << <<-MSG =begin = 実験結果 以下は実験結果を一覧したものである == 実験設定 * 解像度 : T42L20 * 時間ステップ : 30 s : : =end MSG すると、この情報を rdtool で HTML 化したものをサムネイルのファイルに 埋め込みます。 === RT を使いたい人のために (未実装) ((* 注意: *)) この機能はまだバージョン #{VER} では組み込まれていません。 他にも、「RT ((- (()) を参照してください。 -)) で書いてみたい!!」という方もいるかもしれません。 そういう方は、メッセージの設定の際に、頭に 「=begin RT」、一番最後に 「=end」と記述してください。 thumb.message << <<-MSG =begin RT caption = 表テスト , 人間, == , 犬 , == || , 男 , 女 ,オス,メス x , 1.0 , 2.0, 1.1, 1.2 y , 0.4 , 0.5, 0.3, 0.1 =end MSG すると、この情報を rttool で HTML 化したものをサムネイルのファイルに 埋め込みます。 === SIGEN ファイル生成のコントロール デフォルトではサムネイルファイルの作成と同時に SIGEN ファイル を 作成しますが、不要である場合は mksigen を false にしてください。 thumb.mksigen = false === ロボット検索の禁止 生成するサムネイルをロボット検索して欲しくない場合には norobots を true にしてください。 thumb.norobots = true === サムネイル画像変換ツールの変更 デフォルトでサムネイルを変換するコマンドおよびオプションは 以下の通りです。 #{@convert_cmd} これを変換したい場合には以下のように設定を行ってください。 ただし、空白の場合やシステムに存在しないコマンドが設定されている 場合にはエラーを返します。 thumb.convert_cmd = "mogrify -geometry" デフォルトでは既に出力先にファイルが存在し、且つ元のファイルよりも 新しい場合、時間の短縮のため、画像ファイルの変換を行いません。 もしも毎回必ずファイルの変換を行いたい場合は以下のように設定してください。 thumb.convert_overwrite = true == 「情報ファイル」の編集 (応用編) ((<「情報ファイル」の編集 (入門編)>)) の応用版です。 === 右寄せ・左寄せ <修飾子>に ">" を書き込むと右寄せに、"<" を書き込むと左寄せになります。 fig1.png:>: 右寄せだよ fig2.gif:<: 左寄せだよ fig3.jpg:: デフォルトは真ん中寄せだよ === 複数行入力 <修飾子>に "m" を書き込むことで複数行入力が可能です。 なお、上記の ((<右寄せ・左寄せ>)) と併用する場合にはカンマ "," で 区切ります。内容自体は "{" と "}" でくくります。 fig1.png:m:{ 複数行入力を行うよ。 こういうことできるよ。 便利だねー。テーブルも書きやすいね。 } fig2.gif:>,m:{ 併用するにはこうするよ。 } === RD を使いたい人のために <修飾子>に "rd" を書き込むことで、文字列は RD として解釈され、 rdtool で HTML に変換されます。 fig1.png:m,rd:{ ((<りんく|URL:./>)) はこんな感じで書けるよ。 * リストも * 簡単 } === RT を使いたい人のために (未実装) ((* 注意: *)) この機能はまだバージョン #{VER} では組み込まれていません。 <修飾子>に "rt" を書き込むことで、文字列は RT として解釈され、 rttool で HTML に変換されます。 fig1.png:m,rt:{ caption = 表テスト , 人間, == , 犬 , == || , 男 , 女 ,オス,メス x , 1.0 , 2.0, 1.1, 1.2 y , 0.4 , 0.5, 0.3, 0.1 } === 「情報ファイル」からタイトルの設定 ((<スクリプトの編集 (入門編)>)) でタイトルの設定に関して 記述しましたが、「情報ファイル」からの設定も可能です。 <画像名> に title と記述し <コメント> にタイトルを書き込んでください。 title:: 実験設定 其の弐 ((<スクリプトの編集 (入門編)>)) は上書きされます。 === 「情報ファイル」から本文メッセージの追加 ((<スクリプトの編集 (入門編)>)) で本文メッセージの設定に関して 記述しましたが、「情報ファイル」から追加も可能です。 <画像名> に message と記述し本文メッセージをタイトルを書き込んでください。 message:m,rd:{ = サンプルだー == 目次です === さらに目次です ((<ほげ|URL:thum/sample_thum.txt>)) } message:m:{ HTML ですが何か問題でも? ちいさな テーブルを 作って みたよ♪ } =end EndOfTutorial debug(@message) end # # HTML ファイルの最終的な作成メソッド。最後にこのメソッドを呼ぶことで # 作業が完了する。 # # overwrite に false を与えると、上書きを禁止する。 # # quiet を true にするとエラーを除く全てのメッセージが表示されなくなる。 # # verbose を true にすると作業の進捗状況がメッセージとして出力される。 # # err を true にした場合、意図しない動作が起きた場合にすぐに # エラーを起こす。 # def create(overwrite=true, quiet=nil, verbose=true, err=true) # # サムネイルファイル名 # index_file_name = @index.chomp.strip + @index_ext.chomp.strip # # 元ファイル削除 (overwrite が nil の場合はエラー) # if File.exist?(index_file_name) if overwrite then File.delete(index_file_name) else raise ArgumentError, "\n\n Error : \"#{index_file_name}\" exist already.\n\n" end end # # infofile の作成 (既に存在する場合はそのまま)。 # DCModelThumbnail.info_make メソッドを呼ぶ # status = info_make(@figdir, @infofile, @ext_list, @headlimit, nil, nil, true, err) if verbose then if /create/ =~ status $stdout.print " Message : Infofile \"#{@infofile}\" is created.\n" elsif /exist/ =~ status $stdout.print " Message : Infofile \"#{@infofile}\" is already exist.\n" end end # # @message が Array オブジェクト以外の場合はエラーを返す。 # if !@message.instance_of?(Array) then warn_or_err( "\"message\" must be Array Object. " + "Please \"message = Array.new\" initially.\n", true, nil, ArgumentError) end # # infofile から情報の取得。 # DCModelThumbnail.info_get メソッドを呼ぶ。 # $stdout.print " Message : Get information from \"#{@infofile}\".... " if verbose info_list = info_get(@infofile, @headlimit, nil, quiet, err) # # infofile からの情報のうち、画像ファイル名を "title" にしている # ものに関して @title に上書きして、info_list から除く。 # # infofile からの情報のうち、画像ファイル名を "message" にしている # ものに関して @message に追加して、info_list から除く。 # info_list_buff = Array.new info_list.each{ |info_part| if /title/ =~ info_part['fig_name'] @title = info_part['comment'] elsif /message/ =~ info_part['fig_name'] # フォーマットの情報を受けて、"=begin" 等の補完 if /rd/ =~ info_part['format'] then mess_body = "=begin\n" mess_body << info_part['comment'] mess_body << "\n=end\n" elsif /rt/ =~ info_part['format'] then mess_body = "=begin RT\n" mess_body << info_part['comment'] mess_body << "\n=end\n" else mess_body = info_part['comment'] end @message << mess_body # サムネイルに書き込む情報 (これが本命) else info_list_buff << info_part end } info_list = Array.new info_list << info_list_buff info_list.flatten! # 配列の平滑化 (1次元配列化) $stdout.print " done.\n" if verbose # @convert_cmd が存在するかどうかチェック $stdout.print " Message : Check converter command .... " if verbose convert_cmd_no_opt = @convert_cmd.strip.gsub(/\s+.*/, '') convert_cmd_check1 = convert_cmd_no_opt + " -help &> /dev/null" convert_cmd_check2 = convert_cmd_no_opt + " --help &> /dev/null" raise ArgumentError, "\n\n Error : \"#{convert_cmd_no_opt}\": command not found.\n\n" \ if !system(convert_cmd_check1) && !system(convert_cmd_check2) $stdout.print " done.\n" if verbose # サムネイル画像置き場の作成 raise IOError, "\n\n Error: Existing #{@thumbnaildir} is not a directory.\n\n" \ if File.exists?(@thumbnaildir) && ! File.stat(@thumbnaildir).directory? Dir.mkdir(@thumbnaildir) unless File.exists?(@thumbnaildir) # サムネイル画像の作成 $stdout.print " Message : Create small images for thumbnail ....\n" if verbose info_list.each_index{ |i| thumbnail_name = info_list[i]['fig_name'].sub(/\.\w+$/, @thumbnailtail) fig_name = info_list[i]['fig_name'] $stdout.print " [#{i + 1}/#{info_list.size}]: " if verbose if info_list[i]['fig_name_nohead'].strip.chomp == "label" || info_list[i]['fig_name_nohead'].strip.chomp == "message" || info_list[i]['fig_name_nohead'].strip.chomp == "title" || info_list[i]['fig_name_nohead'].strip.chomp.empty? $stdout.print "Skip: No image file.\n" if verbose elsif !@convert_overwrite && \ File.exists?("#{@thumbnaildir}/#{thumbnail_name}") && \ File.mtime("#{@thumbnaildir}/#{thumbnail_name}") > \ File.mtime("#{@figdir}/#{fig_name}") $stdout.print "Skip: \"#{@thumbnaildir}/#{thumbnail_name}\" is already exist, and newer than \"#{@figdir}/#{fig_name}\"\n" if verbose else cmd = "#{@convert_cmd} #{@img_width.to_s}x#{@img_height.to_s} '#{@figdir}/#{fig_name}[#{@thumbnailpage}]' '#{@thumbnaildir}/#{thumbnail_name}'" $stdout.print cmd if verbose $stdout.print "\n" if verbose raise "\n\n Error : \"#{cmd}\": failed.\n\n" if !system(cmd) end info_list[i]['thumbnail_name']=thumbnail_name } # # @message のフォーマットを解析し、HTML に変換する。 # html_message = Array.new @message.each{ |mess| format = format_parser(mess) if /rd/ =~ format then html_buff = rd2html(mess, true) elsif /rt/ =~ format then html_buff = rd2html(mess, true) else html_buff = mess end html_message << html_buff if html_buff debug(html_message) } debug(html_message) # 初期化 html_entire = "" # ヘッダ部分 $stdout.print " Message : Generate HTML Header...." if verbose html_entire << html_header $stdout.print " done.\n" if verbose # 本文 $stdout.print " Message : Insert body messages...." if verbose html_message.each { |message| html_entire << message } $stdout.print " done.\n" if verbose # サムネイル部分 $stdout.print " Message : Generate Thumbnail Lists...." if verbose html_entire << html_thum(info_list, quiet, true) $stdout.print " done.\n" if verbose # フッタ部分 $stdout.print " Message : Generate HTML Footer...." if verbose html_entire << html_footer $stdout.print " done.\n" if verbose # ファイルの書きだし $stdout.print " Message : Output to \"#{index_file_name}\"...." if verbose ifile = open(index_file_name, "w") ifile.print html_entire ifile.close $stdout.print " Successfull. \n" if verbose # 最後までうまくいったら、SIGEN ファイルも作成する。 if @mksigen then mksigen_file = index_file_name.chomp.strip + ".SIGEN" mksigen_thumbdir = @thumbnaildir + ".SIGEN" mksigen_thumbdir_title = @title || "" mksigen_thumbdir_title << " サムネイル画像置き場ディレクトリ" mksigen_src = relative_str("#{$0}" , mksigen_file) mksigen_info = relative_str(@infofile, mksigen_file) mksigen_desc = <<-DESC relative:#{mksigen_src} と relative:#{mksigen_info} により自動生成 DESC mksigen_note = <<-NOTE この SIGEN ファイル自体も relative:#{mksigen_src} からの自動生成である NOTE $stdout.print " Message : Create \"#{mksigen_file}\"...." if verbose mksigen_write(mksigen_file, @title, nil, nil, "自動生成", mksigen_desc, mksigen_note) mksigen_write(mksigen_thumbdir, mksigen_thumbdir_title, nil, nil, "自動生成", mksigen_desc, mksigen_note) if File.exists?(@thumbnaildir) $stdout.print " Successfull. \n" if verbose end end # # サンプルスクリプト出力用のメソッド。 # この DCModelThumbnail クラスに依存するサンプルスクリプトを # 引数 filename という名前で出力する。実際には、このファイル # を編集・実行することでサムネイルが作成される寸法である。 # def create_sample_rb(filename) if !(str_and_notspace?(filename)) then return warn_or_err("filename is invalid.\n", true, nil, ArgumentError) end rb_file_body = <<-EndOfFile #!/usr/bin/env ruby1.8 # #= dcmodel thumbnail generate ruby script # # Editor :: #{username_from_uid} # Version:: #{Time.now.strftime("%Y/%m/%d %H:%M:%S")} # #== Overview # #This file is generate by following ruby script automatically. # # #{File.expand_path($0.to_s)} # version "#{VER}" # #Please edit this file according to your purpose. # #== Usage # #Please check following sample page and reference manual. # # #{PUB_SAMPLE_URL} # #{PUB_DOC_URL} # ################################################## require "#{File.expand_path($0.to_s)}" ###################################################### # DCModelThumbnail のインスタンスを作成 (必須) thumb = DCModelThumbnail.new # サムネイル実行コマンド (必須)。最後に実行すること END{ thumb.create } # コピーライト #thumb.copyright = "#{@copyright}" # 作成されるサムネイルのファイル名 (拡張子除く) thumb.index = "#{@index}" # 作成されるサムネイルの拡張子名 #thumb.index_ext = "#{@index_ext}" # 「情報ファイル (infofile)」のファイル名 thumb.infofile = "\#\{File.basename(thumb.index)\}.txt" # 画像ファイルとして認識させたい拡張子の追加。 # デフォルトでは #{@ext_list.join(", ")}, #{@ext_list.join(", ").swapcase} が認識される。 #thumb.ext_list.push("bmp") # headlimit に当てはまらないものは画像としては無視され、 # 当てはまるものは「情報ファイル」において、接頭部分 headlimit が # 省略可能になる。 #thumb.headlimit = "headlimit_" # 絵のあるディレクトリの名前。必ず存在していなければならない。 #thumb.figdir = "#{@figdir}" # サムネイル画像を置くディレクトリの名前 #thumb.thumbnaildir = "#{@thumbnaildir}" # サムネイル画像の拡張子名 #thumb.thumbnailtail = "#{@thumbnailtail}" # サムネイル画像化する元画像のページ番号 #thumb.thumbnailpage = "1" # convert コマンドおよびオプション。この後ろに画像サイズが 200x150 # のような形式で指定される。 #thumb.convert_cmd = "#{@convert_cmd}" # convert コマンドが実行される際、既に出力先のファイルがある場合に # 上書きするためのフラグ。これが false の場合、出力先のファイルが # 存在し、且つ元のファイルよりも新しい場合は変換を行わない。 #thumb.convert_overwrite = #{@convert_overwrite} # スタイルシートファイル #thumb.css = "#{@css}" # rd2 コマンドへのパス #thumb.rd2_path = "#{@rd2_path}" # rd2-ext-lib へのライブラリへのパス #thumb.rd2htmlextlib = "#{@rd2htmlextlib}" # SIGEN ファイルを作らない場合は false にセットする #thumb.mksigen = false # HTML のロボット検索を禁止する場合には true にセットする #thumb.norobots = true # 画像ファイルサイズ (幅) #thumb.img_width = #{@img_width} # 画像ファイルサイズ (高さ) #thumb.img_height = #{@img_height} # 横にならべるファイル数 #thumb.figtable_num = #{@figtable_num} # スタイルシートを直接設定するためのもの # (css ファイルに書き込む情報を直接指定できる) #thumb.style = <<-STYLE # a:link { color:#269900; } # a:visited { color:#269900; } # a:hover { color:#99FF33; } #STYLE # html の作成者情報 (デフォルトはユーザアカウント名が自動取得される) #thumb.html_author = "#{@html_author}" # html ヘッダのタイトル thumb.title = "#{@title}" # 本体に書き出すメッセージ。サムネイルの部分よりも上に出力される。 # この変数自体は Array オブジェクトで、その内部に String オブジェクトが # 格納される。 thumb.message = Array.new # "=" ではなく、"<<" で代入することに注意!! thumb.message << <<-Message #{@message.join("\n\n")} Message EndOfFile # # ファイルの作成 # ifile = open(filename, "w") ifile.print "#{rb_file_body}" ifile.close # # パーミッションの設定 # File.chmod(0755, filename) end # # デバッグ出力用メソッド。組み込み関数 $DEBUG が真の場合 (つまり、 # プログラムを $ ruby -d ./xxxxxx.rb として呼び出した場合) に # debug メソッドに代入された変数を出力する。 # def debug(*args) p [caller.first, *args] if $DEBUG end private :debug # # 警告またはエラー。 # err が nil や false の場合、mes に与えられたメッセージを # 警告として表示する。err が真の場合はそのメッセージの出力 # と同時にエラーを発生させ、プログラムを終了させる。 # errvar に変数を与えると、エラーの種類を指定できる。 # quiet を true にすると、err が nil の場合、何も動作しなくなる。 # def warn_or_err(mes=nil, err=nil, quiet=nil, errvar=nil) return nil if !mes errvar = RuntimeError if !errvar if err then raise errvar, "Error: #{mes}" elsif !quiet $stdout.print "[#{caller.first}] \n Warning: #{mes}" return nil end end private :warn_or_err # #画像ファイル名・修飾情報・コメントを含む「情報ファイル」を作成するための #メソッド。 # #figdir (String オブジェクト) #内の拡張子 ext_list (Array オブジェクト) にヒットするファイル名 #をリストにし、infofile (String オブジェクト) に書き出す。 # #headlimit (String オブジェクト) を渡すと、ファイル名の頭が #headlimit にヒットするものだけを拾い、リストからはその部分を #取り除くようにする。 # #overwrite を true にすると、infofile が存在する場合でも #上書きする。また、quiet を true にすると警告メッセージを表示しない。 # #delimiter (String オブジェクト) は情報ファイルの #画像ファイル名・修飾情報・コメントの区切り文字を設定する #ものであり、デフォルトは定数 INFO_DELIMITER にて設定されている。 #一応変更できるようになっているが、原則的に変更しない #事を薦める。 # #ファイルを作成したときは "create"、既存のものがすでに存在する #場合には "exist" を返す。画像ファイルが一つも読み込めない、 #すなわち空のファイルを作成してしまった時や、既存のものが無く、 #なおかつ作成に失敗した場合はエラーを起こす。(引数 err を #false にした場合には警告を表示するだけである) # #ここで作成されるファイルは DCModelThumbnail.info_get で取得される #ファイルの雛形である。 # def info_make(figdir=nil, infofile=nil, ext_list=nil, headlimit=nil, overwrite=nil, delimiter=nil, quiet=nil, err=true) # infofile があり、overwrite が false の場合は終了。 if File.exist?(infofile) && !overwrite then warn_or_err("Infofile \"#{infofile}\" already exist. " + "So not generate infofile once again.\n", nil, quiet) return "exist" end # 引数の有効性の検証 if !(str_and_notspace?(figdir)) then return warn_or_err("\"figdir\" is not specified. " + "So \"infofile\" is not generated. \n", err, quiet, ArgumentError) elsif !(str_and_notspace?(infofile)) then return warn_or_err("\"infofile\" is not specified. " + "So \"infofile\" is not generated. \n", err, quiet, ArgumentError) elsif !(array_and_notzero?(ext_list)) then return warn_or_err("\"ext_list\" is not specified. " + "So \"infofile\" is not generated. \n", err, quiet, ArgumentError) end # delimiter のセット if !(str_and_notspace?(delimiter)) then delimiter = INFO_DELIMITER end # headlimit の整形 if !(str_and_notspace?(headlimit)) then headlimit = "" end # figdir から画像ファイル名一覧をとりだし, 配列 imgfiles へ代入 imgfiles = Array.new Dir.foreach("#{figdir}") { |item| ext_list.each{ |ext| next if !(str_and_notspace?(ext)) # ドットが付いていない場合はドットをつける if !(/^\.(.*)/ =~ ext) then ext = "." + ext.chomp.strip end # 拡張から有効か判定 next unless /#{ext}$/i =~ item # headlimit から有効か判定 if str_and_notspace?(headlimit) then if /^#{headlimit}(.+)$/ =~ item bodyname = $1 else next end else bodyname = item end # imgfiles への格納 #imgfiles.push( (File.basename(bodyname, ext) ) ) imgfiles.push( bodyname ) } } # もしも画像情報が取り出せていなかったら警告 or エラー if !(imgfiles.size > 0) then if str_and_notspace?(headlimit) errmsg = "Image files \"#{headlimit}...\" are not found in \"#{figdir}\".\n" else errmsg = "Image files are not found in \"#{figdir}\".\n" end return warn_or_err(errmsg, err, quiet, ArgumentError) end imgfiles = imgfiles.sort # infofile に書き込み ifile = open(infofile, "w") imgfiles.each{ |filename| ifile.print "#{filename}#{delimiter}#{delimiter}\n" } ifile.close return "create" 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" が格納される。 # * "rd" : RD フォーマットであることを示す。 # * "rt" : RT フォーマットであることを示す。 # * line # * 情報ファイルの該当情報の「行数」が格納される。 # 複数行が指定される場合は "4-10" というように格納される。 # # delimiter (String オブジェクト) は情報ファイルの # 画像ファイル名・修飾情報・コメントの区切り文字を設定する # ものであり、デフォルトは定数 INFO_DELIMITER にて設定されている。 # 一応変更できるようになっているが、原則的に変更しない # 事を薦める。 # # quiet を真にすると、ファイルがない際にもメッセージを表示しない。 # # err を真にすると、ファイルが見つからない際にエラー処理をする。 # def info_get(infofile=nil, headlimit=nil, delimiter=nil, quiet=nil, err=nil) # delimiter のセット if !(str_and_notspace?(delimiter)) then delimiter = INFO_DELIMITER end info_list = Array.new # ファイルが読み取れるかチェック if !(File.readable?(infofile)) then return warn_or_err("\"#{infofile}\" is not readable. \n", err, quiet, ArgumentError) end # 実際にファイルを開く ifile = open(infofile, "r") line_num = 0 multi_valid = false # 複数行取得用のフラグ multi_first = true # 複数行取得用のフラグ start_char = Regexp.quote(INFO_MULTI_START) # 複数行開始 "{" stop_char = Regexp.quote(INFO_MULTI_STOP) # 複数行停止 "}" info_hash_tmp = Hash.new ifile.each { |line| # 探索したデータの格納用配列とハッシュ info_part = Array.new info_hash = Hash.new # 行数を数える line_num += 1 debug("line=", line_num, ":", "multi=", multi_valid) info_part = line.chomp.split(/#{delimiter}/, 3) info_hash['fig_name_nohead'] = info_part[0] || "" info_hash['comment'] = info_part[2] || "" info_hash['line'] = line_num.to_s # 行頭が "#", または完全に空行の場合はコメントアウトと考えて無視。 if /^\s*#/ =~ info_part[0] then next elsif !(str_and_notspace?(line)) then next end # info_hash['fig_name'] の設定 if str_and_notspace?(headlimit) then info_hash['fig_name'] = headlimit.chomp.strip + info_hash['fig_name_nohead'].chomp.strip else info_hash['fig_name'] = info_hash['fig_name_nohead'] end # # 修飾子の解析 (万が一のことを考え、日本語も処理)。 # if !(str_and_notspace?(info_part[1])) then modifier = "" else modifier = Kconv::toeuc(info_part[1].chomp.strip) # # 日本語らしきものが入っていたら警告またはエラー # ただし、複数行処理の場合は気にしない。(文中に「:」が # 入っていることも考えられるので # if !(modifier == Kconv::toeuc(modifier)) || !(modifier == Kconv::tojis(modifier)) || !(modifier == Kconv::tosjis(modifier)) then if !(multi_valid) then warn_or_err( "\"#{modifier}\" include 2 bite code, " + "so this may not be parsed correctly.\n", err, quiet, ArgumentError) end end end # # 修飾子の分割 # modifier_parts = modifier.split(",") # 文字寄せ情報の解析 info_hash['align'] = "center" # デフォルト値 modifier_parts.each{ |char| if />/ =~ char.chomp.strip then info_hash['align'] = "right" break elsif / =~ char.chomp.strip then info_hash['align'] = "left" break end } # フォーマット情報の解析 info_hash['format'] = "html" # デフォルト値 modifier_parts.each{ |char| if /rd/ =~ char.chomp.strip then info_hash['format'] = "rd" break elsif /rt/ =~ char.chomp.strip then info_hash['format'] = "rt" break end } # 複数行を取得するかどうかの解析 modifier_parts.each{ |char| if /m/ =~ char.chomp.strip then debug(info_hash['comment']) debug(str_and_notspace?(info_hash['comment'])) if str_and_notspace?(info_hash['comment']) && /#{start_char}/e =~ Kconv::toeuc(info_hash['comment']) then multi_valid = true break end end } # 複数行取得が有効になっている場合は、値を一時 # ここで止め、次のループへ回す。 if multi_valid then # 文字コード変換等をまともに行うため、line および # info_hash['comment'] を別の文字列に置き換え if !(str_and_notspace?(line)) then line_tmp = "\n" else line_tmp = line end if !(str_and_notspace?(info_hash['comment'])) then comment_tmp = "\n" else comment_tmp = info_hash['comment'] end # 初回の場合は、各値を保持しておく。 if multi_first then info_hash_tmp = info_hash.dup # "{" 以降のみを comment として保持 if !(line_tmp.split(INFO_MULTI_START)[1]) info_hash_tmp['comment'] = "\n" else info_hash_tmp['comment'] = line_tmp.split(INFO_MULTI_START)[1] end multi_first = false # もしも同じ行に "}" もある場合にはそこで終了 if /#{stop_char}/e =~ Kconv::toeuc(info_hash_tmp['comment']) then info_hash_tmp['comment'] = info_hash_tmp['comment'].split(INFO_MULTI_STOP)[0] # フラグの初期化 multi_valid = false multi_first = true # 値を info_hash に戻す。 info_hash = info_hash_tmp.dup # 脱出して info_hash を info_list へ (next で脱出しない) # 同じ行に "}" が無い場合は info_list へ格納せずに次の行へ else next end # 初回以降、まだ "}" がコメントに無い場合 elsif !(/#{stop_char}/e =~ Kconv::toeuc(line_tmp)) then info_hash_tmp['comment'] << line_tmp # info_list に渡さずにループを回す next # コメントに "}" が現れ、終了する際 else if !(line_tmp.split(INFO_MULTI_STOP)[0]) last_comment = "" else last_comment = line_tmp.split(INFO_MULTI_STOP)[0] end info_hash_tmp['comment'] << last_comment # フラグの初期化 multi_valid = false multi_first = true # 値を info_hash に戻す。 info_hash = info_hash_tmp.dup end end # 値を info_list に格納。 info_list.push(info_hash) } ifile.close return info_list end # # HTML のヘッダ部分の作成メソッド。相当する文字列を返す。 # 作成した HTML は DCModelThumbnail.html_footer で得られる文字列で # 閉じられることを想定している。 # def html_header() # @index のディレクトリから見た、生成スクリプトの相対的な位置 generator = relative_str("#{$0}", @index) # @index のディレクトリから見た、css の相対的な位置 css = relative_str(@css, @index) # @norobots が ture であれば、meta タグに書き込み。 if @norobots then robots = <<-ROBOTS ROBOTS end # @style で指定されているものがあれば、それも書き込み。 if str_and_notspace?(@style) then style = <<-CSS CSS else style = "" end # # ヘッダ全体の生成 # header = <<-HTMLHEADER #{@title} #{robots} #{style} HTMLHEADER return header end # # HTML のサムネイル部分 (画像の数に応じて繰り返す部分) を作成するメソッド。 # 相当する文字列を返す。info_list には DCModelThumbnail.info_get で # 取得される形式の情報ファイルが与えられる。 # # それ以外の形のデータが与えられる場合には警告を発して nil を返す。 # ただし、err に true を与えると、エラーが生じる。 # quiet が true の場合には警告メッセージも表示しない。 # # 内部で DCModelThumbnail.html_thum_parts を呼び、各要素はそちらで # 作成する。 # def html_thum(info_list=nil, quiet=nil, err=nil) # # 引数に与えられたデータの検証 # if !array_and_notzero?(info_list) then return warn_or_err( "\"info_list\" is invalid.\n", err, quiet, ArgumentError) end # # table タグを作成 # html_table = "" html_table = <<-HTMLEOF HTMLEOF # # 中身を作成 # info_list.size.times{ |num| html_table << html_thum_parts(info_list, num, quiet, err) } # # もしも、info_list.size が @figtable_num で割り切れない場合、 # 残り分の空白 td を作成する # remain = @figtable_num - (info_list.size % @figtable_num) td_width = (100 / @figtable_num).truncate.to_s + "%" # 一つの td の幅 if !(remain == 0) then remain.times{ |time| html_table << <<-HTMLEOF HTMLEOF } html_table << <<-HTMLEOF HTMLEOF end # # /table タグを作成 # html_table << <<-HTMLEOF HTMLEOF return html_table end # # HTML のサムネイル部分の内部 (テーブルの1要素毎) を作成するメソッド。 # 相当する文字列を返す。info_list には DCModelThumbnail.info_get で # 取得される形式の情報ファイルを、num には何番目のデータなのかを # 示す Numerical オブジェクトを与える。 # # それ以外の形のデータが与えられる場合には警告を発して nil を返す。 # ただし、err に true を与えると、エラーが生じる。 # quiet が true の場合には警告メッセージも表示しない。 # def html_thum_parts(info_list=nil, num=nil, quiet=nil, err=nil) # # 引数に与えられたデータの検証 # if !array_and_notzero?(info_list) then return warn_or_err( "\"info_list\" is invalid.\n", err, quiet, ArgumentError) end if !num.kind_of?(Integer) return warn_or_err( "\"num\" is not integer.\n", err, quiet, ArgumentError) end # # info_list からデータの取得 # fig_name = info_list[num]['fig_name'] # 画像ファイル名 thumbnail_name = info_list[num]['thumbnail_name'] # サムネイル画像名 comment = info_list[num]['comment'] # コメント align = info_list[num]['align'] # 文字寄せ fig_name_nohead = info_list[num]['fig_name_nohead'] # 省略画像ファイル名 format = info_list[num]['format'] # comment のフォーマット debug(fig_name, comment, align, fig_name_nohead) # # format から、comment の変換処理 # if /rd/ =~ format then comment_buff = rd2html(comment) elsif /rt/ =~ format then comment_buff = rd2html(comment) else comment_buff = "#{comment}" end comment = "#{comment_buff}" # # @index からの相対的な @figdir の設定 # rel_figdir = relative_str(@figdir, @index) # # @index からの相対的な @thumbaildir の設定 # rel_thumbnaildir = relative_str(@thumbnaildir, @index) # # テーブルの配置によって のつけたしをおこなう。 # (num はゼロからスタートすることに注意) # 左端 : @figtable_num * n (remainder == 0) # 右端 : @figtable_num * n - 1 (remainder == @figtable - 1) # remainder = num % @figtable_num # 余り figtable_1 = @figtable_num - 1 # 列数 - 1 td_width = (100 / @figtable_num).truncate.to_s + "%" # 一つの td の幅 debug(num, remainder, figtable_1, @figtable_num, td_width) html_table_part = "" # 左端用の タグ if remainder == 0 then html_table_part = <<-HTMLEOF HTMLEOF end # 画像ファイル名が "label" の場合には comment をそのまま書き出す。 if /^label$/ =~ fig_name_nohead.chomp.strip then html_table_part << <<-HTMLEOF #{comment} HTMLEOF # 画像ファイル名が存在しない場合は空白を書き出す。 elsif !(str_and_notspace?(fig_name_nohead)) then html_table_part << <<-HTMLEOF HTMLEOF # 上記以外の場合には、絵の縮小版とそのリンクを張り込む else html_table_part << <<-HTMLEOF #{fig_name_nohead} #{comment} HTMLEOF end # 右端用の タグ if remainder == figtable_1 then html_table_part << <<-HTMLEOF HTMLEOF end return html_table_part end # # フッター作成用メソッド。相当する文字列を返す。 # DCModelThumbnail.html_header で得られる文字列で始まる HTML を # 閉じることを想定している。 # def html_footer() # @index のディレクトリから見た、生成スクリプトの相対的な位置 generator = relative_str("#{$0}", @index) # @index のディレクトリから見た、情報ファイルの相対的な位置 infofile = relative_str(@infofile, @index) # # フッターとして書き出し # html_footer = <<-HTMLEOF This page is generated by #{generator} and #{infofile} (#{Time.now.strftime("%Y/%m/%d %H:%M:%S")} #{username_from_uid}) #{@self_name} [Script | Doc | Sample] is provided by dcmodel project in GFD Dennou Club Copyright © #{@copyright} #{Time.now.strftime("%Y")} HTMLEOF return html_footer end # # mes で与えられる本文の行頭を解析し、その本文が HTML であるか、 # RD であるか、RT であるのかを判別する。現在、以下のように判定している。 # # * 行頭文字が「=begin」、「=begin RD」、「=begin rd」 # * RD のフォーマットであると判別 # # * 行頭文字が「=begin RT」、「=begin rt」 # * RT のフォーマットであると判別 # # * 上記以外 # * HTML フォーマットであると判別 # # 返り値は "html", "rd", "rt" のいづれかである。なお、body に # String オブジェクト以外、もしくは完全に空白のみが入っている場合、 # nil を返す。 # def format_parser(body=nil) debug(body) if !(str_and_notspace?(body)) then return warn_or_err("\"body\" is not String Object.\n") end Kconv::toeuc(body) body_parts = body.split("\n") body_parts.each{ |line| next unless /\w+/e =~ line.chomp.strip if /=begin\s+(rt)/ie =~ line.chomp.strip return "rt" elsif /=begin/ie =~ line.chomp.strip return "rd" elsif /=begin\s+(rd)/ie =~ line.chomp.strip return "rd" else return "html" end } return nil end # # 引数 rd に与えられた文字列を rd2html を掛けた文字列として # 返す。デフォルトでは "=begin" や "=end" が存在しない文字列を # 想定している。この場合、rd 文字列を "=begin" と "=end" # ではさまれたものとして自動的に解釈する。もしも "=begin" # や "=end" が書き込まれた文字列を rd として与えたい場合は # 引数 beginend を true にすること。返される html は 以上と # 以下は省かれた本文部分のみである。 # # もしも rd2 コマンドが存在しない場合には nil を返す。 # # なお、現在は rd2html-ext-lib を必ず利用するようになっているので # インスタンス変数 rd2htmlextlib を適宜設定しないとまともに # 動かないので注意すること。 # def rd2html(rd=nil, beginend=true, quiet=nil, err=nil) debug(rd) if !(FileTest.executable?(@rd2_path)) then return warn_or_err( "\"#{@rd2_path}\" is not excutable.\n", err, quiet, ArgumentError) elsif !rd return warn_or_err( "\"rd\" is invalid.\n", err, quiet, ArgumentError) end debug(@rd2_path) # "=begin" や "=end" を消去するための処理 (行頭のものしか消さない) rd_body = "" if beginend then rd_parts = rd.split("\n") debug(rd_parts) rd_parts.each { |line| if /^=begin\s+.*/ =~ line then next elsif /^=begin$/ =~ line then next elsif /^=end\s+.*/ =~ line then next elsif /^=end$/ =~ line then next else rd_body << line + "\n" end } else rd_body = "#{rd}" end debug(rd_body) # rd で得られた文字列を /tmp/dcmodel-thum-$$.rd に一時的に格納 rdfile_tmp = @tmp + "/" + File.basename($0.to_s) + "-" + $$.to_s debug(rdfile_tmp) tmpfile = open(rdfile_tmp, "w") tmpfile.print "=begin\n" tmpfile.print rd_body tmpfile.print "\n=end\n" tmpfile.close debug(open(rdfile_tmp){|io| io.read}) # print "#{open(rdfile_tmp){|io| io.read}}" # # ライブラリパスを $: に追加 # @rd2lib.each{ |path| # next if !(str_and_notspace?(path)) ## $:.push(path) # $:.unshift(path) # } # debug($:) # # コマンドの文字列を整形 # cmd = "#{@rd2_path}" cmd << " -r rd/rd2html-ext-lib" cmd << " --with-css=#{@css}" cmd << " --with-part=\'RT:rt\'" cmd << " --with-part=\'HTML:html\'" cmd << " --out-code=euc" cmd << " --ref-extension" cmd << " --native-inline" cmd << " --head-element" # cmd << " --headline-secno" # cmd << " --enable-br" debug(cmd) html_org = IO.popen("export RUBYLIB=#{@rd2htmlextlib} ; #{cmd} #{rdfile_tmp}").read debug(html_org) html_body_each_line = html_org.split(/\n/) debug(html_body_each_line) html_body = "" bodyflag = false html_body_each_line.each{ |line| if /^.* # を参照のこと # def mksigen_write(file=nil , subject=nil , maintainer=nil, update=nil, update_info=nil, desc=nil , note=nil , prune=nil , quiet=nil , err=true) # 引数の検査 if !(str_and_notspace?(file)) then return warn_or_err("\"file\" is not specified.", err, quiet, ArgumentError) end if !(str_and_notspace?(subject)) then return warn_or_err("\"subject\" is not specified.", err, quiet, ArgumentError) end # 引数が無効でも補完するもの if !(str_and_notspace?(maintainer)) then maintainer = jpname_from_uid || username_from_uid || "Unknown" end if !(str_and_notspace?(update)) then update = Time.now.strftime("%Y/%m/%d") end if !(str_and_notspace?(update_info)) then update_info = "" end if !(str_and_notspace?(desc)) then desc = "" end if !(str_and_notspace?(note)) then note = "" end if prune then prune = "Prune: 1" else prune = "" end # # 出力内容の格納 # sigen = <<-SIGEN Subject: #{subject.chomp} Maintainer: #{maintainer.chomp} Description: #{desc.chomp} Note: #{note.chomp} Update: #{update.chomp} #{update_info.chomp} #{prune} SIGEN # # 文字コード設定 # Kconv::toeuc(sigen) # # ファイルの作成 # ifile = open(file, "w") ifile.print "#{sigen}" ifile.close end # # 以降は Private メソッド # # # 引数 uid に対応するユーザ名 (ログイン名) を返す。 # uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (ログイン名) # を返す。uid が無効なものである場合、エラーを返す。 # def username_from_uid(uid=nil) unless uid pw = Etc.getpwuid(Process.uid) or return nil else pw = Etc.getpwuid(uid) or return nil end user_name = pw.name return user_name end private :username_from_uid # # 引数 gid に対応するユーザ名 (ログイン名) を返す。 # gid に nil を与えた場合はプロセスの gid に対応するユーザ名 (ログイン名) # を返す。gid が無効なものである場合、エラーを返す。 # def username_from_gid(gid=nil) unless gid pw = Etc.getpwuid(Process.gid) or return nil else pw = Etc.getpwuid(gid) or return nil end user_name = pw.name return user_name end private :username_from_gid # # 引数 uid に対応するユーザ名 (日本語) を返す。 # uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (日本語) # を返す。 # # 日本語名は gate-toroku-system # によるデータベースから取得するため、このシステムがインストールされて # いない場合には nil を返す。 # # 引数 family_name に true を与えた場合、姓のみを返そうと試みる。 # データベースの和名が半角空白または全角空白で区切られる場合、 # 姓のみを返すことが可能である。 # def jpname_from_uid(uid=nil, family_name=nil) if FileTest.executable?(@gate_user_show) gate_user_database = IO.popen("#{@gate_user_show} #{username_from_uid(uid)}") # # 以下は、完全に gate-toroku-system のデータベース依存である。 # 詳しくは # を参照せよ。 # while gate_user_data = gate_user_database.gets do gate_user_data.chomp! if /^kname/ =~ gate_user_data jpname_key, jpname_value = gate_user_data.split(/: /, 2) Kconv::toeuc(jpname_value) end # 名字だけ取り出そうと試みる。 # (姓名の間に半角空白または全角空白が無い時は無理) if family_name && /(.+)[\s| ]+.+/e =~ jpname_value then jpname = $1 else jpname = jpname_value end end else jpname = nil end return jpname end private :jpname_from_uid # # 代入された変数が、文字列で、且つ空白文字のみではないことを # 調べるメソッド。日本語であっても、文字列が入っていれば true を返す。 # def str_and_notspace?(obj) debug(obj) if !obj.instance_of?(String) then return false end # 日本語の文字列も対応できるように Kconv::toeuc(obj) if /\S+/e =~ obj.chomp.strip then return true else return false end end private :str_and_notspace? # # 代入された変数が、配列で、且つゼロ配列ではないことを # 調べるメソッド # def array_and_notzero?(obj) debug(obj) if obj.instance_of?(Array) && obj.size > 0 then return true else return false end end private :array_and_notzero? end ###################################################### if $0 == __FILE__ thumb = DCModelThumbnail.new # 引数が与えられたらヘルプを表示 if ARGV.size > 0 then $stdout.print <<-EndOfHelp #{thumb.self_name} -- version \"#{thumb.version}\" Please see following documents. (Sorry, I do not prepare enough help message, and roff format for man(1).) #{thumb.pub_sample_url} #{thumb.pub_doc_url} EndOfHelp exit(1) end # 子プログラムの存在をチェック if File.exist?(thumb.sub_rb_name) raise IOError, "\n\n Error : \"#{thumb.sub_rb_name}\" is already exist.\n\n" end # 子プログラム生成 $stdout.print "\n#{thumb.self_name} -- version \"#{thumb.version}\" ...\n\n" $stdout.print " Message : Generating Sample Ruby script \"#{thumb.sub_rb_name}\"...." thumb.create_sample_rb(thumb.sub_rb_name) $stdout.print " done.\n\n" end
以下は実験結果を一覧したものである
複数行入力を行うよ。 こういうことできるよ。 便利だねー。テーブルも書きやすいね。