hikiutils 0.2.3.4 → 0.2.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hiki +1 -3
  3. data/exe/hiki_thor +0 -3
  4. data/exe/hiki_thor~ +8 -0
  5. data/exe/hiki~ +8 -0
  6. data/hikiutils.gemspec +1 -0
  7. data/hikiutils_bob/Rakefile +10 -27
  8. data/hikiutils_bob/figs/hikiutils_bob.004.jpeg +0 -0
  9. data/hikiutils_bob/{private_dir.graffle → hikiutils_bob.graffle} +1 -1
  10. data/hikiutils_bob/hikiutils_bob.key +0 -0
  11. data/hikiutils_bob/hikiutils_bob/hikiutils_bob.004.jpeg +0 -0
  12. data/hikiutils_bob/latex_all.hiki +7 -3
  13. data/hikiutils_bob/latex_dir/hikiutils_bob.log +99 -84
  14. data/hikiutils_bob/latex_dir/hikiutils_bob.pdf +0 -0
  15. data/hikiutils_bob/latex_dir/hikiutils_bob.synctex.gz +0 -0
  16. data/hikiutils_bob/latex_dir/hikiutils_bob.toc +14 -10
  17. data/hikiutils_bob/latex_dir/latex_all.aux +10 -10
  18. data/hikiutils_bob/latex_dir/latex_all.tex +14 -5
  19. data/hikiutils_bob/latex_dir/sync.aux +14 -8
  20. data/hikiutils_bob/latex_dir/sync.tex +70 -17
  21. data/hikiutils_bob/sync.hiki +44 -7
  22. data/hikiutils_yamane/Rakefile +32 -31
  23. data/hikiutils_yamane/abstract.hiki +1 -0
  24. data/hikiutils_yamane/backup/hikiutils%28optparse%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%29 +309 -0
  25. data/hikiutils_yamane/backup/hikiutils%28thor%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%29 +1 -0
  26. data/hikiutils_yamane/backup/hikiutils_yamane +703 -0
  27. data/hikiutils_yamane/backup/hikiutils_yamane.hiki +0 -0
  28. data/hikiutils_yamane/backup/hikiutils_yamane_#hikiutils_yamane +1 -0
  29. data/hikiutils_yamane/backup/hikiutils_yamane_command_table +19 -0
  30. data/hikiutils_yamane/backup/hikiutils_yamane_introduction +7 -0
  31. data/hikiutils_yamane/figs/hikiutils_yamane.001.jpeg +0 -0
  32. data/hikiutils_yamane/figs/hikiutils_yamane.001.jpg +0 -0
  33. data/hikiutils_yamane/figs/hikiutils_yamane.002.jpeg +0 -0
  34. data/hikiutils_yamane/figs/hikiutils_yamane.002.jpg +0 -0
  35. data/hikiutils_yamane/figs/hikiutils_yamane.003.jpeg +0 -0
  36. data/hikiutils_yamane/figs/hikiutils_yamane.003.jpg +0 -0
  37. data/hikiutils_yamane/figs/hikiutils_yamane.004.jpeg +0 -0
  38. data/hikiutils_yamane/figs/hikiutils_yamane.004.jpg +0 -0
  39. data/hikiutils_yamane/figs/hikiutils_yamane.005.jpeg +0 -0
  40. data/hikiutils_yamane/figs/hikiutils_yamane.005.jpg +0 -0
  41. data/hikiutils_yamane/figs/hikiutils_yamane.006.jpeg +0 -0
  42. data/hikiutils_yamane/figs/hikiutils_yamane.007.jpeg +0 -0
  43. data/hikiutils_yamane/hikiutils_yamane.hiki +37 -1
  44. data/hikiutils_yamane/hikiutils_yamane.key +0 -0
  45. data/hikiutils_yamane/hikiutils_yamane.key~11b9dba1272d2104b420497d11c6eda206ace6c2 +0 -0
  46. data/hikiutils_yamane/introduction.hiki +27 -0
  47. data/hikiutils_yamane/latex_dir/abstract.aux +22 -0
  48. data/hikiutils_yamane/latex_dir/abstract.tex +1 -0
  49. data/hikiutils_yamane/latex_dir/command_table.tex +1 -1
  50. data/hikiutils_yamane/latex_dir/head.tex +2 -2
  51. data/hikiutils_yamane/latex_dir/hikiutils_yamane.aux +3 -0
  52. data/hikiutils_yamane/latex_dir/hikiutils_yamane.log +224 -84
  53. data/hikiutils_yamane/latex_dir/hikiutils_yamane.pdf +0 -0
  54. data/hikiutils_yamane/latex_dir/hikiutils_yamane.synctex.gz +0 -0
  55. data/hikiutils_yamane/latex_dir/hikiutils_yamane.tex +16 -2
  56. data/hikiutils_yamane/latex_dir/hikiutils_yamane.toc +20 -0
  57. data/hikiutils_yamane/latex_dir/introduction.aux +26 -0
  58. data/hikiutils_yamane/latex_dir/introduction.tex +33 -0
  59. data/hikiutils_yamane/latex_dir/results.aux +45 -0
  60. data/hikiutils_yamane/latex_dir/results.tex +342 -0
  61. data/hikiutils_yamane/latex_dir/system.tex +23 -0
  62. data/hikiutils_yamane/results.hiki +376 -0
  63. data/hikiutils_yamane/system.hiki +18 -0
  64. data/lib/hikiutils.rb +7 -3
  65. data/lib/hikiutils.rb~ +387 -0
  66. data/lib/hikiutils/version.rb +1 -1
  67. data/lib/hikiutils_thor.rb +36 -20
  68. data/lib/hikiutils_thor.rb~ +324 -0
  69. data/lib/templates/Rakefile_hiki_sync +35 -31
  70. metadata +57 -3
@@ -0,0 +1,23 @@
1
+ \subsubsection{hiki}
2
+ hikiとはプログラミング言語Rubyを用いられることで作られたwikiクローンの1つである.\verb|{{br}}|
3
+ hikiの主な特徴として
4
+
5
+ \begin{itemize}
6
+ \item オリジナルwikiに似たシンプルな書式
7
+ \item プラグインによる機能拡張
8
+ \item 出力するHTMLを柔軟に変更可能
9
+ \item ページにカテゴリ付けできる
10
+ \item CSSを使ったテーマ機能
11
+ \item 携帯端末可能
12
+ \item InterWikiのサポート
13
+ \item HikiFarmに対応
14
+ \item ページの追加,編集がしやすい
15
+ \end{itemize}
16
+ 等がある
17
+
18
+ \subsubsection{hikiutils}
19
+ hikiutils は hiki の編集作業を容易に行うことができるよう にするツール群であり,プログラミング言語 Ruby のライブ ラリである gem フォーマットに従って提供されている.
20
+ hikiutils は CLI(Command Line Interface) で操作するため, オプション解析をおこなう必要がある.
21
+ gem には,この用途 に適合したライブラリがいくつも提供されている.
22
+ この中 で,あまり利用頻度は高くないが古くから開発され,使用例 が広く紹介されている optparse を利用している.
23
+
@@ -0,0 +1,376 @@
1
+ {{toc}}
2
+ !結果
3
+ //!!開発の結果
4
+ !!コマンド名の検討
5
+ !!!コマンドの命名原則
6
+ 機能ごとの動作はコマンドのオプションによって指定されます.
7
+ このオプションにどのような名前をつけるかは,どれだけコマンドを覚えやすいかという
8
+ 意味で重要です.コマンドの振る舞いを的確に表す名称をつける必要があります.
9
+
10
+ この振る舞いとしてもっとも受け入れやすいのがshellで用意されているコマンドです.
11
+ pwd, ls, rm, touch, openなどはもっとも直感的に動作がわかるコマンドです.
12
+ hikiutilsの振る舞いを予測できるシェルコマンドと同じ名前でオプションを提供する
13
+ ようにします.
14
+
15
+
16
+ !!!hikiutilsがあらかじめ想定している利用形態
17
+ ここでhikiutilsがあらかじめ想定している利用形態を解説しておきます.
18
+ !!!!caption:hikiutilsがあらかじめ想定している利用形態
19
+ {{attach_view(hikiutils_yamane.007.jpeg,hikiutils_yamane)}}
20
+ hikiutilsはlocal PCとglobal serverとが用意されており,それらのデータをrsyncで
21
+ 同期することで動作することを想定しています.これは,ネットに繋がっていないオフラインの状況でも
22
+ テキストなどの編集ができ,さらに不用意な書き換えを防ぐための機構です.さらに,
23
+ どちらもがバックアップともなっています.
24
+
25
+ これらの設定は,~/.hikircにyaml形式で保存されています.
26
+ <<< yaml
27
+ bob% cat ~/.hikirc
28
+ :srcs:
29
+ - :nick_name: new_ist
30
+ :local_dir: "/Users/bob/Sites/new_ist_data/ist_data"
31
+ :local_uri: http://localhost/ist
32
+ :global_dir: nishitani@ist.ksc.kwansei.ac.jp:/home/nishitani/new_ist_data/ist_data
33
+ :global_uri: http://ist.ksc.kwansei.ac.jp/~nishitani/
34
+ - :nick_name: dmz0
35
+ :local_dir: "/Users/bob/Sites/nishitani0/Internal/data"
36
+ :local_uri: http://localhost/~bob/nishitani0/Internal
37
+ :global_dir: bob@dmz0:/Users/bob/Sites/nishitani0/Internal/data
38
+ :global_uri: http://nishitani0.kwansei.ac.jp/~bob/nishitani0/Internal
39
+ >>>
40
+ また,一般的に一人のユーザがいくつものまとまりとしてのlocal-globalペアを
41
+ 保持して管理することが普通です.それぞれにnicke_nameをつけて管理しています.
42
+ <<< bash
43
+ bob% hiki -s
44
+ hikiutils: provide utilities for helping hiki editing.
45
+ "open -a mi"
46
+ target_no:1
47
+ editor_command:open -a mi
48
+ id | name | local directory | global uri
49
+ ---------------------------------------------------------------------------------
50
+ 0 | new_ist | /Users/bob/Sites/new_ist_data/ist_data | http://ist.ksc.k
51
+ *1 | dmz0 | /Users/bob/Sites/nishitani0/Internal/data | http://nishitani
52
+ 2 | ist | /Users/bob/Sites/hiki-data/data | http://ist.ksc.k
53
+ 3 | new_maple | /Users/bob/Sites/new_ist_data/maple_hiki_data | http://ist.ksc.k
54
+ >>>
55
+ とすると,それらの一覧と,いまtargetにしているnick_nameディレクリが表示されます.
56
+
57
+ !!!コメンド名と振る舞いの詳細
58
+ 開発の結果コマンドを以下のように書き換えました.
59
+ 上部に記した,特によく使うコマンドに関しては,shellでよく使われるコマンド名と一致するにようにしました.
60
+
61
+ ||変更前||変更後||動作の解説
62
+ ||edit FILE ||open|| open file
63
+ ||list [FILE] ||ls|| list files
64
+ ||rsync ||rsync|| rsync files
65
+ ||update FILE ||touch|| update file
66
+ ||show ||pwd|| show nick_names
67
+ ||target VAL ||cd|| targetを変える,change directoryとのメタファ
68
+ || || ||
69
+ ||move [FILE] ||mv|| move file
70
+ ||remove [FILE] ||rm|| remove files
71
+ ||add || || add sources info
72
+ ||checkdb || || check database file
73
+ ||datebase FILE || || read datebase file
74
+ ||display FILE |||| display converted hikifile
75
+ ||euc FILE || || translate file to euc
76
+ ||help [COMMAND] || || Describe available commands or one specific command
77
+ ||version || || show program version
78
+ それぞれの意図を動作の解説として記述しています.
79
+ !!!! open FILE
80
+ ファイルを編集のためにeditorでopen.Editorは~/.hikircに
81
+ :editor_command: open -a mi
82
+ として保存されている.open -a miをemacsなどに適宜変更して使用.
83
+
84
+ !!!! ls [FILE]
85
+ local_dirにあるファイル名を[FILE*]として表示.例えば,hikiutils_yamane以下の拡張子が
86
+ ついたファイルを表示.hikiシステムではtextディレクトリーは階層構造を取ることができない.
87
+ 西谷研ではdirectoryの代わりにスネーク表記で階層構造を表している.
88
+
89
+ !!!! rsync
90
+ local_dirの内容をglobal_dirにrsyncする.逆方向は同期に誤差が生じたり,permissionが
91
+ おかしくなるので,現在のところ一方向の同期のみとしている.したがって,作業手順としては
92
+ テキストの変更はlocal_dirで飲み行うようにしている.
93
+
94
+ !!!! touch FILE
95
+ loccal_dirで書き換えたFILEの内容をlocal_uriに反映させ,ブラウザで表示.シェルコマンドの
96
+ touchによって,変更時間を現在に変え,最新状態とするのに似せてコマンド名をtouchとしている.
97
+
98
+ !!!! pwd
99
+ nick_nameの一覧とtargetを表示,current targetをcurrent dirとみなして,
100
+ コマンド名をpwdとした.
101
+
102
+ !!!! cd VAL
103
+ targetを変える,change directoryとのメタファ.ただし,いまのところnick_nameでは
104
+ 対応しておらず,nick_nameの番号をVAL入力することで変更する.
105
+
106
+ !!thorとoptparseのコードの比較
107
+ hikiutilsのコマンドライン解析ツールをoptparseからthorに換えることでコマンドの書き換えを行うことができた.
108
+ また,プログラムのコードもoptparseよりthorのほうが短く書け,簡単にコマンドを作成することができた.
109
+ !!!Thorとは
110
+ Thorとは,コマンドラインツールの作成を支援するライブラリのことである.
111
+ gitやbundlerのようにサブコマンドを含むコマンドラインツールを簡単に作成することができる[4].
112
+ !!!!Thorの基本的な流れ
113
+ #Thorを継承したクラスのパブリックメソッドがコマンドになる
114
+ #クラス.start(ARGV)でコマンドラインの処理をスタートする
115
+ という流れである[4].
116
+ !!!optparseとは
117
+ optparseモジュールとは,getoptよりも簡便で,柔軟性に富み,かつ強力なコマンドライン解析ライブラリである.
118
+ optparseでは,より宣言的なスタイルのコマンドライン解析手法,すなわちOptionParserのインスタンスでコマンドラインを解析するという手法をとっている.
119
+ これを使うと,GNU/POSIX構文でオプションを指定できるだけでなく,使用法やヘルプメッセージの生成も行える[5].
120
+ !!!!optparseの基本的な流れ
121
+ #OptionParserオブジェクトoptを生成する
122
+ #オプションを取り扱うブロックをoptに登録する
123
+ #opt.parse(ARGV)でコマンドラインを実際にparseする
124
+ という流れである[6].
125
+ !!!コードの解説
126
+ !!!!Thorの定義
127
+ {{attach_view(hikiutils_yamane.003.jpg,hikiutils_yamane)}}
128
+ #Hikithor::CLI.start(ARGV)が呼ばれる
129
+ #initializeメソッドが呼ばれる
130
+ #これではThorのinitializeメソッドが呼ばれない
131
+ #superを書くことでThorのinitializeメソッドが呼ばれる
132
+ optparseではrequireでoptparseを呼ぶだけでいいが,ThorではrequireでThorを呼びCLIクラスで継承しinitializeメソッドにsuperを書くことでThorのinitializeを呼ぶ必要がある.
133
+ !!!!!実際のコード
134
+ <<< ruby
135
+ # -*- coding: utf-8 -*-
136
+ require 'thor'
137
+ require 'kconv'
138
+ require 'hikidoc'
139
+ require 'erb'
140
+ require "hikiutils/version"
141
+ require "hikiutils/tmarshal"
142
+ require "hikiutils/infodb"
143
+ require 'systemu'
144
+ require 'fileutils'
145
+ require 'yaml'
146
+ require 'pp'
147
+
148
+ module Hikithor
149
+
150
+ DATA_FILE=File.join(ENV['HOME'],'.hikirc')
151
+ attr_accessor :src, :target, :editor_command, :browser, :data_name, :l_dir
152
+
153
+ class CLI < Thor
154
+ def initialize(*args)
155
+ super
156
+ @data_name=['nick_name','local_dir','local_uri','global_dir','global_uri']
157
+ data_path = File.join(ENV['HOME'], '.hikirc')
158
+ DataFiles.prepare(data_path)
159
+
160
+ file = File.open(DATA_FILE,'r')
161
+ @src = YAML.load(file.read)
162
+ file.close
163
+ @target = @src[:target]
164
+ @l_dir=@src[:srcs][@target][:local_dir]
165
+ browser = @src[:browser]
166
+ @browser = (browser==nil) ? 'firefox' : browser
167
+ p editor_command = @src[:editor_command]
168
+ @editor_command = (editor_command==nil) ? 'open -a mi' : editor_command
169
+ end
170
+ >>>
171
+ !!!!hikiutilsの実行
172
+ *Thor
173
+ {{attach_view(hikiutils_yamane.004.jpg,hikiutils_yamane)}}{{br}}
174
+ #hiki_thorのHikithor::CLI.start(ARGV)でhikiutils_thor.rbのCLIクラスを呼ぶ{{br}}
175
+ #hikiutils_thor.rbのCLIクラスのメソッドを順に実行していく{{br}}
176
+ *optparse
177
+ {{attach_view(hikiutils_yamane.001.jpg,hikiutils_yamane)}}
178
+ #HikiのHikiUtils::Command.run(ARGV)でhikiutils.rbのrunメソッドを呼ぶ
179
+ #new(argv).executeでexecuteメソッドが実行される
180
+ このようにoptparseでは実行を行うためのメソッドが必要であるが,Thorではクラスのメソッドを順に実行していくため
181
+ runメソッドとexecuteメソッドは必要ない.
182
+ !!!!!実際のコード
183
+ *Thor
184
+ <<< ruby
185
+ #!/usr/bin/env ruby
186
+
187
+ require "hikiutils_thor"
188
+
189
+ Hikithor::CLI.start(ARGV)
190
+ >>>
191
+ <<< ruby
192
+ # -*- coding: utf-8 -*-
193
+ require 'thor'
194
+ require 'kconv'
195
+ require 'hikidoc'
196
+ require 'erb'
197
+ require "hikiutils/version"
198
+ require "hikiutils/tmarshal"
199
+ require "hikiutils/infodb"
200
+ require 'systemu'
201
+ require 'fileutils'
202
+ require 'yaml'
203
+ require 'pp'
204
+
205
+ module Hikithor
206
+
207
+ DATA_FILE=File.join(ENV['HOME'],'.hikirc')
208
+ attr_accessor :src, :target, :editor_command, :browser, :data_name, :l_dir
209
+
210
+ class CLI < Thor
211
+ def initialize(*args)
212
+ super
213
+ @data_name=['nick_name','local_dir','local_uri','global_dir','global_uri']
214
+ data_path = File.join(ENV['HOME'], '.hikirc')
215
+ DataFiles.prepare(data_path)
216
+
217
+ file = File.open(DATA_FILE,'r')
218
+ @src = YAML.load(file.read)
219
+ file.close
220
+ @target = @src[:target]
221
+ @l_dir=@src[:srcs][@target][:local_dir]
222
+ browser = @src[:browser]
223
+ @browser = (browser==nil) ? 'firefox' : browser
224
+
225
+ >>>
226
+ *optparse
227
+ <<< ruby
228
+ #!/usr/bin/env ruby
229
+
230
+ require "hikiutils"
231
+
232
+ HikiUtils::Command.run(ARGV)
233
+ >>>
234
+ <<< ruby
235
+ def self.run(argv=[])
236
+ print "hikiutils: provide utilities for helping hiki editing.\n"
237
+ new(argv).execute
238
+ end
239
+
240
+ def execute
241
+ @argv << '--help' if @argv.size==0
242
+ command_parser = OptionParser.new do |opt|
243
+ opt.on('-v', '--version','show program Version.') { |v|
244
+ opt.version = HikiUtils::VERSION
245
+ puts opt.ver
246
+ }
247
+ opt.on('-s', '--show','show sources') {show_sources}
248
+ opt.on('-a', '--add','add sources info') {add_sources }
249
+ opt.on('-t', '--target VAL','set target id') {|val| set_target(val) }
250
+ opt.on('-e', '--edit FILE','open file') {|file| edit_file(file) }
251
+ opt.on('-l', '--list [FILE]','list files') {|file| list_files(file) }
252
+ opt.on('-u', '--update FILE','update file') {|file| update_file(file) }
253
+ opt.on('-r', '--rsync','rsync files') {rsync_files}
254
+ opt.on('--database FILE','read database file') {|file| db_file(file)}
255
+ opt.on('--display FILE','display converted hikifile') {|file| display(f\
256
+ ile)}
257
+ opt.on('-c', '--checkdb','check database file') {check_db}
258
+ opt.on('--remove FILE','remove file') {|file| remove_file(file)}
259
+ opt.on('--move FILES','move file1,file2',Array) {|files| move_file(file\
260
+ s)}
261
+ opt.on('--euc FILE','translate file to euc') {|file| euc_file(file) }
262
+ opt.on('--initialize','initialize source directory') {dir_init() }
263
+ end
264
+ begin
265
+ command_parser.parse!(@argv)
266
+ rescue=> eval
267
+ p eval
268
+ end
269
+ dump_sources
270
+ exit
271
+ end
272
+ >>>
273
+ !!!!コマンドの表示と実行
274
+ *Thor
275
+ {{attach_view(hikiutils_yamane.002.jpg,hikiutils_yamane)}}
276
+ #コマンド名,コマンドの説明を一覧に表示させる
277
+ #パブリックメソッドのコマンドを別のコマンド名でも実行できるようにする
278
+ #コマンドの命令の実行コード
279
+ *optparse
280
+ {{attach_view(hikiutils_yamane.005.jpg,hikiutils_yamane)}}
281
+ よって,optparseではOptionParserオブジェクトoptを生成を行い,コマンドをoptに登録して一覧に表示するメソッドとそれぞれコマンドの実行処理が書かれたメソッドがあるが,
282
+ thorではそれぞれのdescで一覧を表示しmapとパブリックメソッドでコマンドの実行処理を行うためコードが短くなる.
283
+ !!!!!実際のコード
284
+ *Thor
285
+ <<< ruby
286
+ desc 'show,--show', 'show sources'
287
+ map "--show" => "show"
288
+ def show
289
+ printf("target_no:%i\n",@src[:target])
290
+ printf("editor_command:%s\n",@src[:editor_command])
291
+ @i_size,@n_size,@l_size,@g_size=3,5,30,15 #i,g_size are fixed
292
+ n_l,l_l=0,0
293
+ @src[:srcs].each_with_index{|src,i|
294
+ n_l =(n_l= src[:nick_name].length)>@n_size? n_l:@n_size
295
+ l_l =(l_l= src[:local_dir].length)>@l_size? l_l:@l_size
296
+ }
297
+ @n_size,@l_size=n_l,l_l
298
+ command = Command.new
299
+ header = command.display_format('id','name','local directory','global uri',@i_size,@n_size,@l_size,@g_size)
300
+
301
+ puts header
302
+ puts '-' * header.size
303
+
304
+ @src[:srcs].each_with_index{|src,i|
305
+ target = i==@src[:target] ? '*':' '
306
+ id = target+i.to_s
307
+ name=src[:nick_name]
308
+ local=src[:local_dir]
309
+ global=src[:global_uri]
310
+ puts command.display_format(id,name,local,global,@i_size,@n_size,@l_size,@g_size)
311
+ }
312
+ end
313
+ >>>
314
+ *optparse
315
+ <<< ruby
316
+ def execute
317
+ @argv << '--help' if @argv.size==0
318
+ command_parser = OptionParser.new do |opt|
319
+ opt.on('-v', '--version','show program Version.') { |v|
320
+ opt.version = HikiUtils::VERSION
321
+ puts opt.ver
322
+ }
323
+ opt.on('-s', '--show','show sources') {show_sources}
324
+ opt.on('-a', '--add','add sources info') {add_sources }
325
+ opt.on('-t', '--target VAL','set target id') {|val| set_target(val)}
326
+ opt.on('-e', '--edit FILE','open file') {|file| edit_file(file) }
327
+ opt.on('-l', '--list [FILE]','list files') {|file| list_files(file)}
328
+ opt.on('-u', '--update FILE','update file') {|file| update_file(file) }
329
+ opt.on('-r', '--rsync','rsync files') {rsync_files}
330
+ opt.on('--database FILE','read database file') {|file| db_file(file)}
331
+ opt.on('--display FILE','display converted hikifile') {|file| display(file)}
332
+ opt.on('-c', '--checkdb','check database file') {check_db}
333
+ opt.on('--remove FILE','remove file') {|file| remove_file(file)}
334
+ opt.on('--move FILES','move file1,file2',Array) {|files| move_file(files)}
335
+ opt.on('--euc FILE','translate file to euc') {|file| euc_file(file)}
336
+ opt.on('--initialize','initialize source directory') {dir_init() }
337
+ end
338
+ begin
339
+ command_parser.parse!(@argv)
340
+ rescue=> eval
341
+ p eval
342
+ end
343
+ dump_sources
344
+ exit
345
+ end
346
+
347
+ def show_sources()
348
+ printf("target_no:%i\n",@src[:target])
349
+ printf("editor_command:%s\n",@src[:editor_command])
350
+ check_display_size()
351
+ header = display_format('id','name','local directory','global uri')
352
+
353
+ puts header
354
+ puts '-' * header.size
355
+
356
+ @src[:srcs].each_with_index{|src,i|
357
+ target = i==@src[:target] ? '*':' '
358
+ id = target+i.to_s
359
+ name=src[:nick_name]
360
+ local=src[:local_dir]
361
+ global=src[:global_uri]
362
+ puts display_format(id,name,local,global)
363
+ }
364
+ end
365
+
366
+ def add_sources
367
+ cont = {}
368
+ @data_name.each{|name|
369
+ printf("%s ? ", name)
370
+ tmp = gets.chomp
371
+ cont[name.to_sym] = tmp
372
+ }
373
+ @src[:srcs] << cont
374
+ show_sources
375
+ end
376
+ >>>
@@ -0,0 +1,18 @@
1
+ !!!hiki
2
+ hikiとはプログラミング言語Rubyを用いられることで作られたwikiクローンの1つである.{{br}}
3
+ hikiの主な特徴として
4
+ *オリジナルwikiに似たシンプルな書式
5
+ *プラグインによる機能拡張
6
+ *出力するHTMLを柔軟に変更可能
7
+ *ページにカテゴリ付けできる
8
+ *CSSを使ったテーマ機能
9
+ *携帯端末可能
10
+ *InterWikiのサポート
11
+ *HikiFarmに対応
12
+ *ページの追加,編集がしやすい
13
+ 等がある
14
+ !!!hikiutils
15
+ hikiutils は hiki の編集作業を容易に行うことができるよう にするツール群であり,プログラミング言語 Ruby のライブ ラリである gem フォーマットに従って提供されている.
16
+ hikiutils は CLI(Command Line Interface) で操作するため, オプション解析をおこなう必要がある.
17
+ gem には,この用途 に適合したライブラリがいくつも提供されている.
18
+ この中 で,あまり利用頻度は高くないが古くから開発され,使用例 が広く紹介されている optparse を利用している.
@@ -64,7 +64,7 @@ EOS
64
64
  opt.on('-r', '--rsync','rsync files') {rsync_files}
65
65
  opt.on('--database FILE','read database file') {|file| db_file(file)}
66
66
  opt.on('--display FILE','display converted hikifile') {|file| display(file)}
67
- opt.on('-c', '--checkdb','check database file') {check_db}
67
+ opt.on('-c', '--checkdb','check database file') {check_db}
68
68
  opt.on('--remove FILE','remove file') {|file| remove_file(file)}
69
69
  opt.on('--move FILES','move file1,file2',Array) {|files| move_file(files)}
70
70
  opt.on('--euc FILE','translate file to euc') {|file| euc_file(file) }
@@ -99,10 +99,14 @@ EOS
99
99
  ['hiki_help.yml','hiki_help.yml'],
100
100
  ['head.tex','latex_dir/head.tex'],
101
101
  ['pre.tex','latex_dir/pre.tex']]
102
- cp_files.each{|files|
102
+ cp_files.each_with_index{|files,i|
103
103
  p source = File.join(File.expand_path('..', __FILE__),'templates',files[0])
104
104
  p target = File.join(Dir.pwd,files[1])
105
- FileUtils.cp(source,target,:verbose=>true)
105
+ if i==0 #force cp of new Rakefile
106
+ FileUtils.cp(source,target,:verbose=>true)
107
+ else #avoid latex files overwritten
108
+ FileUtils.cp(source,target,:verbose=>true) unless File.exist?(target)
109
+ end
106
110
  }
107
111
  # arrange gitignore
108
112
  begin
@@ -0,0 +1,387 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'kconv'
3
+ require 'hikidoc'
4
+ require 'erb'
5
+ require "hikiutils/version"
6
+ require "hikiutils/tmarshal"
7
+ require "hikiutils/infodb"
8
+ require 'systemu'
9
+ require 'optparse'
10
+ require 'fileutils'
11
+ require 'yaml'
12
+ require 'pp'
13
+
14
+ module HikiUtils
15
+ DATA_FILE=File.join(ENV['HOME'],'.hikirc')
16
+ attr_accessor :src, :target, :editor_command, :browser, :data_name, :l_dir
17
+
18
+ class Command
19
+
20
+
21
+ HTML_TEMPLATE = <<EOS
22
+ <!DOCTYPE html
23
+ PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
24
+ "http://www.w3.org/TR/html4/loose.dtd">
25
+ <html lang="ja">
26
+ <html>
27
+ <head>
28
+ <meta http-equiv="Content-Language" content="ja">
29
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
30
+ <title><%= title %></title>
31
+ </head>
32
+ <body>
33
+ <%= body %>
34
+ </body>
35
+ </html>
36
+ EOS
37
+
38
+ def self.run(argv=[])
39
+ print "hikiutils: provide utilities for helping hiki editing.\n"
40
+ new(argv).execute
41
+ end
42
+
43
+ def initialize(argv=[])
44
+ @argv = argv
45
+ @data_name=['nick_name','local_dir','local_uri','global_dir','global_uri']
46
+ data_path = File.join(ENV['HOME'], '.hikirc')
47
+ DataFiles.prepare(data_path)
48
+ read_sources
49
+ end
50
+
51
+ def execute
52
+ @argv << '--help' if @argv.size==0
53
+ command_parser = OptionParser.new do |opt|
54
+ opt.on('-v', '--version','show program Version.') { |v|
55
+ opt.version = HikiUtils::VERSION
56
+ puts opt.ver
57
+ }
58
+ opt.on('-s', '--show','show sources') {show_sources}
59
+ opt.on('-a', '--add','add sources info') {add_sources }
60
+ opt.on('-t', '--target VAL','set target id') {|val| set_target(val) }
61
+ opt.on('-e', '--edit FILE','open file') {|file| edit_file(file) }
62
+ opt.on('-l', '--list [FILE]','list files') {|file| list_files(file) }
63
+ opt.on('-u', '--update FILE','update file') {|file| update_file(file) }
64
+ opt.on('-r', '--rsync','rsync files') {rsync_files}
65
+ opt.on('--database FILE','read database file') {|file| db_file(file)}
66
+ opt.on('--display FILE','display converted hikifile') {|file| display(file)}
67
+ opt.on('-c', '--checkdb','check database file') {check_db}
68
+ opt.on('--remove FILE','remove file') {|file| remove_file(file)}
69
+ opt.on('--move FILES','move file1,file2',Array) {|files| move_file(files)}
70
+ opt.on('--euc FILE','translate file to euc') {|file| euc_file(file) }
71
+ opt.on('--initialize','initialize source directory') {dir_init() }
72
+ end
73
+ begin
74
+ command_parser.parse!(@argv)
75
+ rescue=> eval
76
+ p eval
77
+ end
78
+ dump_sources
79
+ exit
80
+ end
81
+
82
+ def dir_init()
83
+ begin
84
+ p target_dir = File.readlines('./.hikirc')[0]
85
+ rescue
86
+ p target_dir=@src[:srcs][@target][:local_dir]
87
+ File.open('./.hikirc','w'){|file| file.print "#{target_dir}\n"}
88
+ end
89
+ # make dirs
90
+ ['figs','data','latex_dir'].each{|dir|
91
+ begin
92
+ Dir.mkdir(dir)
93
+ rescue => e
94
+ print e
95
+ end
96
+ }
97
+ # cp default files
98
+ cp_files=[['Rakefile_hiki_sync','Rakefile'],
99
+ ['hiki_help.yml','hiki_help.yml'],
100
+ ['head.tex','latex_dir/head.tex'],
101
+ ['pre.tex','latex_dir/pre.tex']]
102
+ cp_files.each_with_index{|files,i|
103
+ p source = File.join(File.expand_path('..', __FILE__),'templates',files[0])
104
+ p target = File.join(Dir.pwd,files[1])
105
+ if i==0 #force cp of new Rakefile
106
+ FileUtils.cp(source,target,:verbose=>true)
107
+ else #avoid latex files overwritten
108
+ FileUtils.cp(source,target,:verbose=>true) unless File.exist?(target)
109
+ end
110
+ }
111
+ # arrange gitignore
112
+ begin
113
+ p cont=File.read('./.gitignore')
114
+ unless cont.include?('.hikirc')
115
+ File.open('./.gitignore','w'){|file| file.print(".hikirc\n")}
116
+ end
117
+ rescue
118
+ File.open('./.gitignore','w'){|file| file.print(".hikirc\n")}
119
+ end
120
+ end
121
+
122
+ def display(file)
123
+ body = HikiDoc.to_html(File.read(file))
124
+ source = HTML_TEMPLATE
125
+ title = File.basename(file)
126
+ erb = ERB.new(source)
127
+ t = File.open(file+".html",'w')
128
+ t.puts(erb.result(binding))
129
+ t.close
130
+ system "open #{t.path}"
131
+ end
132
+
133
+ def euc_file(file)
134
+ p file_path = File.join(@l_dir,'text',file)
135
+ cont = File.readlines(file_path)
136
+ cont.each{|line| puts line.toeuc }
137
+ end
138
+
139
+ def move_file(files)
140
+ begin
141
+ p file1_path = File.join(@l_dir,'text',files[0])
142
+ p file2_path = File.join(@l_dir,'text',files[1])
143
+ rescue => evar
144
+ puts evar.to_s
145
+ puts "error on move_files, check the input format, especially comma separation."
146
+ exit
147
+ end
148
+ return if file1_path==file2_path
149
+ if File.exist?(file2_path) then
150
+ print ("moving target #{files[1]} exists.\n")
151
+ print ("first remove#{files[1]}.\n")
152
+ return
153
+ else
154
+ File.rename(file1_path,file2_path)
155
+ end
156
+
157
+ info=InfoDB.new(@l_dir)
158
+
159
+ db = info.db
160
+
161
+ pp file0=db[files[0]]
162
+ db.delete(files[0])
163
+ db[files[1]]=file0
164
+ db[files[1]][:title]=files[1] if db[files[1]][:title]==files[0]
165
+ pp db[files[1]]
166
+
167
+ db.each{|ele|
168
+ ref = ele[1][:references]
169
+ if ref.include?(files[0]) then
170
+ p link_file=ele[0]
171
+ link_path = File.join(@l_dir,'text',link_file)
172
+
173
+ cont = File.read(link_path)
174
+ if Kconv.iseuc(cont) then
175
+ print "euc\n"
176
+ utf8_cont=cont.toutf8
177
+ utf8_cont.gsub!(/#{files[0]}/,"#{files[1]}")
178
+ cont = utf8_cont.toeuc
179
+ else
180
+ cont.gsub!(/#{files[0]}/,"#{files[1]}")
181
+ end
182
+
183
+ File.write(link_path,cont)
184
+
185
+ ref.delete(files[0])
186
+ ref << files[1]
187
+
188
+ p cache_path = File.join(@l_dir,'cache/parser',link_file)
189
+ begin
190
+ File.delete(cache_path)
191
+ rescue => evar
192
+ puts evar.to_s
193
+ end
194
+ end
195
+ }
196
+
197
+ info.dump
198
+ end
199
+
200
+ def remove_file(file_name)
201
+ p text_path = File.join(@l_dir,'text',file_name)
202
+ p attach_path = File.join(@l_dir,'cache/attach',file_name)
203
+ begin
204
+ File.delete(text_path)
205
+ rescue => evar
206
+ puts evar.to_s
207
+ end
208
+ begin
209
+ Dir.rmdir(attach_path)
210
+ rescue => evar
211
+ puts evar.to_s
212
+ end
213
+
214
+ info=InfoDB.new(@l_dir)
215
+ p "delete "
216
+ del_file=info.delete(file_name)
217
+ info.show_link(file_name)
218
+ info.dump
219
+ end
220
+
221
+ def check_db
222
+ result= InfoDB.new(@l_dir).show_inconsist
223
+ print (result=='') ? "db agrees with text dir.\n" : result
224
+ end
225
+
226
+ def db_file(file_name)
227
+ info=InfoDB.new(@l_dir)
228
+ p info.show(file_name)
229
+ end
230
+
231
+ def rsync_files
232
+ p local = @l_dir
233
+ p global = @src[:srcs][@target][:global_dir]
234
+ #"/Users/bob/Sites/nishitani0/Internal/data"
235
+ #"bob@dmz0:/Users/bob/nishitani0/Internal/data"
236
+ # p command="rsync -auvz -e ssh #{local}/ #{global}"
237
+ p command="rsync -auvz -e ssh #{local}/ #{global}"
238
+ # system 'rsync -auvz -e ssh ~/Sites/nishitani0 bob@nishitani0.kwansei.ac.jp:Sites/'
239
+ system command
240
+ end
241
+
242
+ def update_file(file0)
243
+ file = (file0==nil) ? 'FrontPage' : file0
244
+ #rm cache file
245
+ t_file=File.join(@l_dir,'cache/parser',file)
246
+ begin
247
+ FileUtils.rm(t_file,:verbose=>true)
248
+ #update info file
249
+ info=InfoDB.new(@l_dir)
250
+ info.update(file0)
251
+
252
+ rescue
253
+ print "some errors on touch, but dont mind...\n"
254
+ end
255
+
256
+ #open file on browser
257
+ l_path = @src[:srcs][@target][:local_uri]
258
+ # p command="open -a #{@browser} \'#{l_path}/?c=edit;p=#{file}\'"
259
+ p command="open -a #{@browser} \'#{l_path}/?#{file}\'"
260
+ system command
261
+ p "If you get open error, try rackup from the src_dir."
262
+ p "If you get 整形式になっていません, try login as a valid user."
263
+ end
264
+
265
+ def list_files(file)
266
+ file ='' if file==nil
267
+ t_file=File.join(@l_dir,'text')
268
+ print "target_dir : "+t_file+"\n"
269
+ print `cd #{t_file} ; ls -lt #{file}*`
270
+ end
271
+
272
+ def edit_file(file)
273
+ t_file=File.join(@l_dir,'text',file)
274
+ if !File.exist?(t_file) then
275
+ file=File.open(t_file,'w')
276
+ file.close
277
+ File.chmod(0777,t_file)
278
+ end
279
+ p command="#{@editor_command} #{t_file}"
280
+ system command
281
+ end
282
+
283
+ def dump_sources
284
+ file = File.open(DATA_FILE,'w')
285
+ YAML.dump(@src, file)
286
+ file.close
287
+ end
288
+
289
+ def set_target(val)
290
+ @src[:target] = val.to_i
291
+ show_sources
292
+ end
293
+
294
+ def show_sources()
295
+ printf("target_no:%i\n",@src[:target])
296
+ printf("editor_command:%s\n",@src[:editor_command])
297
+ check_display_size()
298
+ header = display_format('id','name','local directory','global uri')
299
+
300
+ puts header
301
+ puts '-' * header.size
302
+
303
+ @src[:srcs].each_with_index{|src,i|
304
+ target = i==@src[:target] ? '*':' '
305
+ id = target+i.to_s
306
+ name=src[:nick_name]
307
+ local=src[:local_dir]
308
+ global=src[:global_uri]
309
+ puts display_format(id,name,local,global)
310
+ }
311
+
312
+ end
313
+
314
+ def check_display_size
315
+ @i_size,@n_size,@l_size,@g_size=3,5,30,15 #i,g_size are fixed
316
+ n_l,l_l=0,0
317
+ @src[:srcs].each_with_index{|src,i|
318
+ n_l =(n_l= src[:nick_name].length)>@n_size? n_l:@n_size
319
+ l_l =(l_l= src[:local_dir].length)>@l_size? l_l:@l_size
320
+ }
321
+ @n_size,@l_size=n_l,l_l
322
+ end
323
+
324
+ def display_format(id, name, local, global)
325
+ name_length = @n_size-full_width_count(name)
326
+ local_length = @l_size-full_width_count(local)
327
+ global_string= global.size < @g_size ? global : global[0..@g_size]
328
+ [id.to_s.rjust(@i_size), name.ljust(name_length),
329
+ local.ljust(local_length),
330
+ global_string.ljust(@g_size)].join(' | ')
331
+ end
332
+
333
+ def full_width_count(string)
334
+ string.each_char.select{|char| !(/[ -~。-゚]/.match(char))}.count
335
+ end
336
+
337
+ def add_sources
338
+ cont = {}
339
+ @data_name.each{|name|
340
+ printf("%s ? ", name)
341
+ tmp = gets.chomp
342
+ cont[name.to_sym] = tmp
343
+ }
344
+ @src[:srcs] << cont
345
+ show_sources
346
+ end
347
+
348
+ def read_sources
349
+ file = File.open(DATA_FILE,'r')
350
+ @src = YAML.load(file.read)
351
+ file.close
352
+ @target = @src[:target]
353
+ @l_dir=@src[:srcs][@target][:local_dir]
354
+ browser = @src[:browser]
355
+ @browser = (browser==nil) ? 'firefox' : browser
356
+ p editor_command = @src[:editor_command]
357
+ @editor_command = (editor_command==nil) ? 'open -a mi' : editor_command
358
+ end
359
+ end
360
+ end
361
+
362
+ module DataFiles
363
+ def self.prepare(data_path)
364
+ create_file_if_not_exists(data_path)
365
+ end
366
+
367
+ def self.create_file_if_not_exists(data_path)
368
+ return if File::exists?(data_path)
369
+ create_data_file(data_path)
370
+ end
371
+
372
+ def self.create_data_file(data_path)
373
+ print "make #{data_path}\n"
374
+ init_data_file(data_path)
375
+ end
376
+
377
+ # initialize source file by dummy data
378
+ def self.init_data_file(data_path)
379
+ @src = {:target => 0, :editor_command => 'open -a mi',
380
+ :srcs=>[{:nick_name => 'hoge', :local_dir => 'hogehoge', :local_uri => 'http://localhost/~hoge',
381
+ :global_dir => 'hoge@global_host:/hoge', :global_uri => 'http://hoge'}]}
382
+ file = File.open(data_path,'w')
383
+ YAML.dump(@src,file)
384
+ file.close
385
+ end
386
+ private_class_method :create_file_if_not_exists, :create_data_file, :init_data_file
387
+ end