helpline 0.1.12 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/00README +8 -1
- data/HelpLine.json +1690 -0
- data/Makefile +6 -3
- data/exe/helpline +146 -96
- data/index.html +32 -42
- data/keydef.zsh +1 -1
- data/lib/helpline/curses.rb +7 -0
- data/lib/helpline/version.rb +1 -1
- metadata +3 -2
data/Makefile
CHANGED
data/exe/helpline
CHANGED
@@ -20,74 +20,100 @@ class HelpLine
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def initialize
|
23
|
-
@pagedata = {}
|
24
|
-
@project = Scrapbox::Project.new("HelpLine")
|
23
|
+
# @pagedata = {}
|
24
|
+
# @project = Scrapbox::Project.new("HelpLine")
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
#
|
29
|
-
# ページデータ取得
|
30
|
-
#
|
31
|
-
puts "-----------------ページデータを取得"
|
32
|
-
@project.pages.each { |title,page|
|
33
|
-
puts "...#{title}"
|
34
|
-
@pagedata[title] = page.text.split(/\n/)
|
35
|
-
}
|
36
|
-
|
27
|
+
def update(sources) # sources = ['HelpLine', '~/ScrapboxData/masui.json', ...]
|
37
28
|
dumpdata = {}
|
38
29
|
dumpdata['codes'] = []
|
39
30
|
dumpdata['defs'] = []
|
40
31
|
dumpdata['pages'] = []
|
41
32
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
33
|
+
sources.each { |source|
|
34
|
+
pagedata = {}
|
35
|
+
source = File.expand_path(source)
|
36
|
+
if File.exist?(source)
|
37
|
+
puts "-----------------ページデータをJSONデータ(#{source})から取得"
|
38
|
+
data = JSON.parse(File.read(source))
|
39
|
+
data['pages'].each { |page|
|
40
|
+
title = page['title']
|
41
|
+
puts "...#{title}"
|
42
|
+
pagedata[title] = page['lines']
|
43
|
+
}
|
44
|
+
elsif source =~ /^[a-zA-Z\-]+$/ # たぶんHelpLineプロジェクト
|
45
|
+
puts "-----------------ページデータをScrapbox(#{source})から取得"
|
46
|
+
project = Scrapbox::Project.new(source)
|
47
|
+
project.pages.each { |title,page|
|
48
|
+
puts "...#{title}"
|
49
|
+
pagedata[title] = page.text.split(/\n/)
|
50
|
+
}
|
51
|
+
else
|
52
|
+
next
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# 関数/定数を評価"
|
57
|
+
#
|
58
|
+
puts "-----------------関数/定数を取得"
|
59
|
+
src = nil
|
60
|
+
indent = ''
|
61
|
+
code = []
|
62
|
+
pagedata.each { |title,lines|
|
63
|
+
puts "...#{title}"
|
64
|
+
lines.each { |line|
|
65
|
+
if src && line =~ /^#{indent}\s+/ then
|
66
|
+
code << line
|
67
|
+
elsif line =~ /^code:(.*\.rb)$/ then
|
68
|
+
src = $2
|
69
|
+
indent = $1
|
70
|
+
code = []
|
71
|
+
elsif src then
|
72
|
+
dumpdata['codes'] << code.join("\n")
|
73
|
+
src = nil
|
74
|
+
indent = ''
|
75
|
+
code = []
|
76
|
+
else
|
77
|
+
end
|
78
|
+
}
|
79
|
+
if code.length > 0
|
80
|
+
dumpdata['codes'] << code.join("\n")
|
54
81
|
end
|
55
82
|
}
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
else
|
70
|
-
line =~ /^(\s*)/
|
71
|
-
if line.length < codeindent
|
72
|
-
codeindent = nil
|
83
|
+
puts "-----------------HelpLineデータを検出"
|
84
|
+
pagedata.each { |title,pagedata|
|
85
|
+
puts "...#{title}"
|
86
|
+
dumpdata['pages'] << title
|
87
|
+
processing_defs = false
|
88
|
+
codeindent = nil
|
89
|
+
pagedata.each { |line|
|
90
|
+
if !codeindent
|
91
|
+
if line =~ /^code:/
|
92
|
+
codeindent = $1.length
|
93
|
+
next
|
94
|
+
end
|
73
95
|
else
|
74
|
-
|
96
|
+
line =~ /^(\s*)/
|
97
|
+
if line.length < codeindent
|
98
|
+
codeindent = nil
|
99
|
+
else
|
100
|
+
next
|
101
|
+
end
|
75
102
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
103
|
+
if line =~ /^\s*[\$\%\?]/
|
104
|
+
if line =~ /^\%/ && !processing_defs
|
105
|
+
puts "'$'で始まる用例定義なしでコマンドを定義しようとしています"
|
106
|
+
exit
|
107
|
+
end
|
108
|
+
dumpdata['defs'] << "#{line} {#{dumpdata['pages'].length-1}}"
|
109
|
+
processing_defs = true
|
110
|
+
else
|
111
|
+
processing_defs = false
|
82
112
|
end
|
83
|
-
|
84
|
-
processing_defs = true
|
85
|
-
else
|
86
|
-
processing_defs = false
|
87
|
-
end
|
113
|
+
}
|
88
114
|
}
|
89
115
|
}
|
90
|
-
|
116
|
+
|
91
117
|
File.open(datafile,"w"){ |f|
|
92
118
|
f.puts dumpdata.to_json
|
93
119
|
}
|
@@ -98,23 +124,23 @@ class HelpLine
|
|
98
124
|
lines = list.length
|
99
125
|
lines = LINES if lines > LINES
|
100
126
|
(0...lines).each { |i|
|
101
|
-
Curses.move(i,0)
|
102
|
-
s = "
|
127
|
+
Curses.move(i*2,0)
|
128
|
+
s = "#{list[i][0]}"
|
103
129
|
if i == sel
|
104
130
|
Curses.print_inverse s
|
105
131
|
else
|
106
|
-
Curses.
|
132
|
+
Curses.print_bold s
|
107
133
|
end
|
134
|
+
Curses.move(i*2+1,0)
|
135
|
+
Curses.print " % " + list[i][1]
|
108
136
|
}
|
109
|
-
Curses.move(sel,0)
|
110
|
-
# Curses.down
|
111
|
-
# Curses.tol
|
137
|
+
Curses.move(sel*2,0)
|
112
138
|
end
|
113
139
|
|
114
|
-
def helpline
|
140
|
+
def helpline(sources,test=nil,debug=nil)
|
115
141
|
data = JSON.parse(File.read(datafile))
|
116
142
|
unless data['pages'] # データ型式変換があったので
|
117
|
-
|
143
|
+
update sources
|
118
144
|
data = JSON.parse(File.read(datafile))
|
119
145
|
end
|
120
146
|
|
@@ -130,27 +156,34 @@ class HelpLine
|
|
130
156
|
#
|
131
157
|
# HelpLineエントリ
|
132
158
|
#
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
159
|
+
|
160
|
+
logfile = (debug ? "/tmp/helpline-defs" : "/dev/null")
|
161
|
+
File.open(logfile,"w"){ |f| # ログを残す場合
|
162
|
+
entries = []
|
163
|
+
data['defs'].each { |line|
|
164
|
+
if line =~ /^\s*[\$\?]\s*(.*)$/ # $....
|
165
|
+
entries << $1
|
166
|
+
elsif line =~ /^\s*\%\s*(.*)$/ # %....
|
167
|
+
cmd = $1
|
168
|
+
entries.each { |l|
|
169
|
+
desc = eval('"' + l + '"')
|
170
|
+
f.puts "desc: #{desc}"
|
171
|
+
g.add desc.force_encoding('utf-8'), cmd.force_encoding('utf-8')
|
172
|
+
}
|
173
|
+
f.puts "cmd: #{cmd}"
|
174
|
+
entries = []
|
175
|
+
end
|
176
|
+
}
|
145
177
|
}
|
146
178
|
|
147
179
|
res = g.generate " #{ARGV.join(' ').sub(/\[/,'').sub(/\]/,'')} "
|
148
180
|
|
181
|
+
File.open("/tmp/helpline.cmd","w"){ |f|
|
182
|
+
f.puts ARGV.join(' ')
|
183
|
+
}
|
184
|
+
|
149
185
|
if res[0].length == 0
|
150
186
|
puts "ヘルプがみつかりません"
|
151
|
-
File.open("/tmp/helpline.cmd","w"){ |f|
|
152
|
-
f.puts ARGV.join(' ')
|
153
|
-
}
|
154
187
|
exit
|
155
188
|
end
|
156
189
|
|
@@ -158,7 +191,9 @@ class HelpLine
|
|
158
191
|
listed = {}
|
159
192
|
list = res[0].find_all { |a| # 0 ambig
|
160
193
|
# a = ["現在の状況を表示する {56}", "git status {56}"], etc.
|
161
|
-
if a[0] =~
|
194
|
+
if a[0] =~ /voidvoidvoid/
|
195
|
+
false
|
196
|
+
elsif a[0] =~ /^git:/ && !git_repository
|
162
197
|
false
|
163
198
|
else
|
164
199
|
if listed[a[1]]
|
@@ -169,10 +204,15 @@ class HelpLine
|
|
169
204
|
end
|
170
205
|
}
|
171
206
|
|
207
|
+
# if options['t'] || options['test'] then
|
208
|
+
if test
|
209
|
+
puts list
|
210
|
+
exit
|
211
|
+
end
|
212
|
+
|
172
213
|
#
|
173
214
|
# HelpLineメニュー表示し、カーソル移動で選択
|
174
215
|
#
|
175
|
-
|
176
216
|
help_number = {}
|
177
217
|
list.each_with_index { |entry,ind|
|
178
218
|
entry[0].sub!(/\s*{(\d*)}$/,'')
|
@@ -225,36 +265,46 @@ class HelpLine
|
|
225
265
|
desc = list[sel.to_i][0]
|
226
266
|
cmd = list[sel][1]
|
227
267
|
|
228
|
-
Curses.move(lines,0)
|
268
|
+
Curses.move(lines*2,0)
|
229
269
|
Curses.tol
|
230
270
|
|
231
271
|
#Curses.move(0,0)
|
232
272
|
##Curses.down
|
233
|
-
|
234
|
-
|
273
|
+
|
274
|
+
# Curses.print_inverse("「#{desc}」を実行")
|
275
|
+
# puts " (ソース: http://scrapbox.io/HelpLine/#{data['pages'][help_number[desc]]})"
|
235
276
|
File.open("/tmp/helpline.cmd","w"){ |f|
|
236
277
|
f.puts cmd
|
237
278
|
}
|
238
279
|
end
|
239
280
|
end
|
240
281
|
|
241
|
-
#
|
242
|
-
#
|
243
|
-
#
|
244
|
-
#
|
245
|
-
#
|
246
|
-
|
247
|
-
|
282
|
+
# アップデート
|
283
|
+
# % helpline -u
|
284
|
+
# データを指定してアップデート
|
285
|
+
# % helpline -u -s HelpLine,/Users/masui/ScrapboxData/masui-HelpLine.json
|
286
|
+
# テスト
|
287
|
+
# % helpline -t
|
288
|
+
#
|
248
289
|
|
249
290
|
helpline = HelpLine.new
|
250
291
|
|
251
|
-
|
292
|
+
options = ARGV.getopts('utds:','update','test','source:','debug')
|
293
|
+
update = options['u'] || options['update']
|
294
|
+
test = options['t'] || options['test']
|
295
|
+
debug = options['d'] || options['debug']
|
296
|
+
sources = ['HelpLine']
|
297
|
+
if options['s'] || options['source']
|
298
|
+
sources = (options['s'] || options['source']).split(/,/)
|
299
|
+
end
|
300
|
+
|
301
|
+
if !File.exist?(helpline.datafile) && !update
|
252
302
|
puts "#{helpline.datafile}を作成します..."
|
253
|
-
helpline.
|
303
|
+
helpline.update sources
|
254
304
|
end
|
255
|
-
|
256
|
-
if
|
257
|
-
helpline.
|
258
|
-
else
|
259
|
-
helpline.helpline
|
305
|
+
|
306
|
+
if update then
|
307
|
+
helpline.update sources
|
308
|
+
else
|
309
|
+
helpline.helpline sources, test, debug
|
260
310
|
end
|
data/index.html
CHANGED
@@ -20,16 +20,13 @@
|
|
20
20
|
<section class="main-content">
|
21
21
|
|
22
22
|
<center>
|
23
|
-
<video src="https://s3-ap-northeast-1.amazonaws.com/masui.org/
|
23
|
+
<video src="https://s3-ap-northeast-1.amazonaws.com/masui.org/b/9/b9b2ae65a3a977857b5487f280785b47.mp4" width=600 controls></video>
|
24
24
|
</center>
|
25
25
|
|
26
|
-
<p>
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
<p>
|
31
|
-
Gitのような複雑なシステムは使い方が難しい。
|
32
|
-
ある程度使い方を知っている場合でも、あまり一般的でない機能を使うのは難しい。
|
26
|
+
<p></p>
|
27
|
+
|
28
|
+
コマンドラインのオプションは難しいものが多い。
|
29
|
+
Gitのような複雑なシステムの場合、概念もオプションも難しい。
|
33
30
|
たとえば以下のような場合はどういうコマンドを使えばいいだろうか?
|
34
31
|
</p>
|
35
32
|
|
@@ -170,19 +167,19 @@
|
|
170
167
|
誰でも情報を足したり修正したりできたら嬉しいだろう。
|
171
168
|
</p>
|
172
169
|
|
173
|
-
<h3>
|
170
|
+
<h3>HelpLineのアプローチ</h3>
|
174
171
|
|
175
172
|
<p>
|
176
|
-
|
173
|
+
HelpLineは、以下のような方針で上のような課題をすべて解決しようというものである。
|
177
174
|
|
178
175
|
<ul>
|
179
176
|
<li>ユーザのあらゆる曖昧な表現にマッチするようにヘルプ文字列を正規表現で表現し、
|
180
|
-
|
177
|
+
コマンドに変換する</li>
|
181
178
|
- ExpandHelp(<a href="https://github.com/masui/expand-ruby">ソース</a> /
|
182
179
|
<a href="http://www.interaction-ipsj.org/archives/paper2012/data/Interaction2012/oral/data/pdf/12INT012.pdf">論文</a>)を利用
|
183
180
|
<li>データをすべてクラウド上に置いて編集可能にすることにより、
|
184
181
|
誰でもデータを追加/修正できるようにする</li>
|
185
|
-
- <a href="https://Scrapbox.io/
|
182
|
+
- <a href="https://Scrapbox.io/HelpLine">Scrapbox</a>を利用
|
186
183
|
<li>ユーザが指定したパラメタはそのまま利用して実行に使う</li>
|
187
184
|
- ユーザが「4」「時間」などと指定すると「時刻を4時にセットする」のようなものを提案して実行可能にする
|
188
185
|
<li>多少の誤入力を許す</li>
|
@@ -193,43 +190,48 @@
|
|
193
190
|
|
194
191
|
<h3>利用例</h3>
|
195
192
|
|
196
|
-
|
197
|
-
<code>
|
198
|
-
候補のリストが表示され、
|
193
|
+
タスクのキーワードやパラメタを指定してCtrl-Jを押すと
|
194
|
+
<code>helpline</code>が起動して候補のリストが表示され、
|
199
195
|
カーソルで選択すると実行される。
|
200
196
|
|
201
197
|
<ul>
|
202
|
-
<li><code>$
|
203
|
-
|
204
|
-
<img src="https://gyazo.com/6cc87cef5f28185199074b61716454de.png" width=500>
|
198
|
+
<li><code>$ 2 README</code>と入力してからCtrl-Jを押すと
|
199
|
+
以下のような候補リストが提示される</li>
|
205
200
|
|
201
|
+
<img src="https://gyazo.com/806cb4c2c14781465949ec3aa85d563b.png" width=500>
|
206
202
|
<p></p>
|
207
203
|
<li>カーソルで選択してリターンを押すと実行される</li>
|
208
204
|
|
209
|
-
<img src="https://gyazo.com/
|
205
|
+
<img src="https://gyazo.com/b72f97a2664d504c5465fd11bac92184.png" width=700>
|
210
206
|
</ul>
|
211
207
|
|
212
208
|
<a name="install"><h3>インストール</h3></a>
|
213
|
-
|
214
|
-
<pre>
|
215
|
-
% gem install githelp </pre>
|
216
|
-
|
209
|
+
|
217
210
|
<ul>
|
218
|
-
<li
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
</
|
211
|
+
<li> <code>gem</code>でHelpLineをインストール
|
212
|
+
<pre>
|
213
|
+
% gem install helpline</pre>
|
214
|
+
</li>
|
215
|
+
<li> <code>~/.zshrc</code>に以下の記述を追加
|
216
|
+
<pre>
|
217
|
+
function run-help() {
|
218
|
+
helpline "${BUFFER}" < $TTY
|
219
|
+
BUFFER=$(cat /tmp/helpline.cmd)
|
220
|
+
CURSOR=${#BUFFER}
|
221
|
+
zle redisplay
|
222
|
+
}
|
223
|
+
zle -N run-help
|
224
|
+
bindkey "^j" run-help</pre>
|
225
|
+
</li>
|
223
226
|
</ul>
|
224
227
|
|
225
228
|
<h3>実装</h3>
|
226
|
-
|
227
229
|
<ul>
|
228
230
|
<li><a href="https://github.com/masui/expand_ruby">re_expand</a>
|
229
231
|
という正規表現展開ライブラリを利用</li>
|
230
232
|
<li><a href="https://Scrapbox.io/GitHelp">Scrapbox</a>にあらゆる情報を書いておく</li>
|
231
233
|
<br>
|
232
|
-
<img src="https://gyazo.com/
|
234
|
+
<img src="https://gyazo.com/cd1529fe082c57d4295e8660ba3cb932.png" width=550>
|
233
235
|
<li>
|
234
236
|
様々なタスクの説明と実際の操作を組にして記述しておき、
|
235
237
|
ユーザが与えたキーワードやパラメタにマッチするものを
|
@@ -259,23 +261,11 @@
|
|
259
261
|
翻訳作業があまり気にならないものなのかもしれないが、
|
260
262
|
そういう「翻訳」は少ない方が良いのは確かだろう。
|
261
263
|
</li>
|
262
|
-
<li>そういえば先日「らくらくホン」画面に出てくる鬱陶しい「羊」を消す方法が全くわからなかったのだが、
|
263
|
-
あれは「マチキャラ」と呼ばれるものなので
|
264
|
-
「マチキャラ」を消すという操作が必要だった。
|
265
|
-
お前はMSのイルカか。
|
266
|
-
「羊 消す」とか「消す」とかで消せるべきだろう。
|
267
|
-
githelpでは <code>$ githelp 削除</code> と入力すれば削除関連で何ができるのかわかるだろうし、
|
268
|
-
<code>(鬱陶しい|不快な)羊を(消す|殺す)</code>
|
269
|
-
のようなエントリをユーザが足すこともできるだろう。
|
270
|
-
</li>
|
271
|
-
<img src="http://service.smt.docomo.ne.jp/site/iconcier/img/iconcier_ptl_cha_img01.png" width=300>
|
272
|
-
<li>というわけで<b>Gitは単なる適用例であり、広い範囲で使いたいと思っている。</b></li>
|
273
264
|
</ul>
|
274
265
|
|
275
266
|
<h3> 注意</h3>
|
276
267
|
|
277
268
|
<ul>
|
278
|
-
<li><code>githelp</code>コマンドはGitリポジトリのディレクトリで実行する必要がある</li>
|
279
269
|
<li><a href="https://github.com/masui/expand_ruby">re_expand</a>の実装が富豪的なので
|
280
270
|
大きなリポジトリだと不具合があるかも</li>
|
281
271
|
<li>データが全然足りない... 特にリモートリポジトリ関連のデータは皆無だが、
|