• R/O
  • SSH
  • HTTPS

emacs-keybind: Commit


Commit MetaInfo

Revision4 (tree)
Time2009-03-15 23:51:43
Authortuto0621

Log Message

1stバージョン追加

Change Summary

Incremental Difference

--- trunk/emacs-keybind/emacs_keybind.rb (nonexistent)
+++ trunk/emacs-keybind/emacs_keybind.rb (revision 4)
@@ -0,0 +1,147 @@
1+#!/usr/bin/env ruby
2+
3+require 'optparse'
4+require File.join(File.dirname(__FILE__), 'keyboard_data')
5+require File.join(File.dirname(__FILE__), 'emacs_history')
6+
7+Version = "0.0.1"
8+
9+class EmacsKeybind
10+ def initialize(keyboard, filter, history)
11+ # キーバインドデータ
12+ src = []
13+
14+ while line = gets
15+ src << line.chomp.split(/\t+/)
16+ end
17+
18+ @keybind = src
19+
20+ # キーボードデータ
21+ @keyboard = keyboard
22+
23+ # フィルター名
24+ @filter = filter
25+
26+ # 履歴データ
27+ @history = history
28+ end
29+
30+ def functions(regexp)
31+ funcs = []
32+ @keybind.each do |data|
33+ funcs << data if data[0] =~ regexp
34+ end
35+ funcs
36+ end
37+
38+ def print_keybind(title, prefix, suffix, link_name='')
39+ puts %Q{<h3><a name=\"#{link_name}\">#{title}</a></h3>} if (@filter == 'html')
40+ puts %Q{*** #{title}} if (@filter == 'hatena')
41+
42+ puts %Q{<table cellspacing="2" cellpadding="0" border="1">}
43+ @keyboard.each do |row|
44+ puts %Q{<tr>}
45+ row.each do |key|
46+ funcs = []
47+
48+ if (key.size == 2)
49+ key[1].each do |s|
50+ f = functions(Regexp.new("#{prefix}#{s}#{suffix}"))
51+ f.each {|a| a[1] += "(#{s.sub(/\\/, '')})" if (a[1] !~ /\(.\)$/) }
52+ funcs.concat f
53+ end
54+ end
55+
56+ puts %Q{<td #{td_attr(key, funcs)}><p align="center">#{p_value(key, funcs)}</p></td>}
57+ end
58+ puts %Q{</tr>}
59+ end
60+ puts %Q{</table>}
61+ end
62+
63+ def td_attr(key, funcs)
64+ attr = []
65+ color = '#80ff00'
66+ color = @history.color(funcs[0][1].sub(/\(.*\)$/, '')) if (!funcs.empty? and @history)
67+ attr << "bgcolor=\"#{color}\"" if (funcs.size > 0)
68+ attr.join(' ')
69+ end
70+
71+ def p_value(key, funcs)
72+ str = "#{key[0]}"
73+
74+ funcs.each do |func|
75+ str += "<br><b><font size=\"-1\" color=\"#7F00FF\">#{func[1]}</font></b>"
76+ end
77+
78+ str
79+ end
80+
81+ def print_standard_keybind
82+ print_keybind("?", '^', '$', 'self')
83+ print_keybind("C-?", '^C-', '$', 'control')
84+ print_keybind("M-?", '^M-', '$', 'alt')
85+ print_keybind("C-M-?", '^C-M-', '$', 'control_alt')
86+ print_keybind("C-x C-?", '^C-x C-', '$', 'control_x_control')
87+ print_keybind("C-x ?", '^C-x ', '$', 'control_x')
88+ print_keybind("C-c C-?", '^C-c C-', '$', 'control_c_control')
89+ print_keybind("C-c ?", '^C-c ', '$', 'control_c')
90+ end
91+end
92+
93+if __FILE__ == $0
94+ keyboard_kind = nil
95+ filter = 'html'
96+ history_file_name = nil
97+
98+ opt = OptionParser.new('Usage: emacs_keybind [options] input_file')
99+ opt.on('-k', '--keyboard (ascii, japanese)') {|v| keyboard_kind = v }
100+ opt.on('-f', '--filter (html, hatena)') {|v| filter = v }
101+ opt.on('-h', '--history HISTORY_FILE_NAME') {|v| history_file_name = v }
102+ opt.parse!(ARGV)
103+
104+ case keyboard_kind
105+ when 'ascii'
106+ keyboard = KeyboardAscii
107+ when 'japanese'
108+ keyboard = KeyboardJapanese
109+ else
110+ if (keyboard_kind)
111+ abort "#{keyboard_kind} is not support. please set keyboard kind(ascci or japanese)"
112+ else
113+ abort "please set keyboard kind(ascci or japanese)"
114+ end
115+ end
116+
117+ case filter
118+ when 'html'
119+ when 'hatena'
120+ else
121+ abort "#{keyboard_kind} is not support. please set keyboard kind(ascci or japanese)"
122+ end
123+
124+ # セットアップ
125+ history = EmacsHistory.new(history_file_name) if (history_file_name)
126+ keybind = EmacsKeybind.new(keyboard, filter, history)
127+
128+ # HTML出力
129+ print Header if (filter == 'html')
130+ print HeaderHatena if (filter == 'hatena')
131+
132+ if (history)
133+ puts %Q{<h1><a name="frequency">Frequency in use</a></h3>}
134+
135+ puts %Q{<table cellspacing="2" cellpadding="0" border="1">}
136+ puts %Q{<tr><td><b>Ranking</b></td><td><b>Use Count</b></td><td><b>Emacs Command</b></td></tr>}
137+ history.ranking.each do |a|
138+ puts %Q{<tr><td>#{a[1].ranking}</td><td>#{a[1].use_count}</td><td bgcolor=#{history.color(a[0])}>#{a[0]}</td></tr>}
139+ end
140+ puts %Q{</table>}
141+ end
142+
143+ puts %Q{<h1><a name="keybind">Keybind</a></h1>}
144+ keybind.print_standard_keybind
145+
146+ print Footer if (filter == 'html')
147+end
--- trunk/emacs-keybind/emacs-keybind.el (nonexistent)
+++ trunk/emacs-keybind/emacs-keybind.el (revision 4)
@@ -0,0 +1,94 @@
1+;;; emacs-keybind.el
2+
3+;;; Commentary:
4+;; 全てのコマンド実行履歴をファイルに保存する
5+
6+;;; 設定用変数
7+(defvar emacs-keybind-program-file
8+ "~/.emacs.d/emacs_keybind.rb"
9+ "Place of emacs_keybind.rb")
10+
11+(defvar emacs-keybind-keyboard-kind
12+ "ascii"
13+ "ascii or japanese")
14+
15+(defvar emacs-keybind-work-dir
16+ "~/.emacs.d"
17+ "")
18+
19+(defvar emacs-keybind-history-save-file-name
20+ "emacs-keybind-history-save-file"
21+ "Name of file where history information is stored.")
22+
23+(defvar emacs-keybind-show-file-name
24+ "emacs-keybind.html"
25+ "")
26+
27+(defvar emacs-keybind-show-with-history-file-name
28+ "emacs-keybind-with-history.html"
29+ "")
30+
31+;; ユーティリティ関数
32+(defun emacs-keybind-make-path (fname)
33+ (concat emacs-keybind-work-dir "/" fname))
34+
35+;;; ヒストリの追加と保存
36+(setq emacs-keybind-history-work nil)
37+
38+(defun emacs-keybind-history-save ()
39+ "Save history information to file given by `emacs-keybind-history-save-file-name'."
40+ (interactive)
41+ (with-temp-buffer
42+ (insert ";; " (format-time-string "%Y/%m/%d %H:%M" (current-time)) "\n")
43+ (prin1 emacs-keybind-history-work (current-buffer))
44+ (insert ?\n)
45+ (write-region (point-min) (point-max) (emacs-keybind-make-path emacs-keybind-history-save-file-name) t)))
46+
47+(defun emacs-keybind-history-add (&optional arg)
48+ "The command history is added to `emacs-keybind-history-work'."
49+ (setq emacs-keybind-history-work (append (list this-command) emacs-keybind-history-work)))
50+
51+(add-hook 'kill-emacs-hook 'emacs-keybind-history-save)
52+(add-hook 'pre-command-hook 'emacs-keybind-history-add)
53+
54+;;; キーバインドレポートの表示
55+(defun emacs-keybind-show ()
56+ "The key bind report is displayed."
57+ (interactive)
58+ (describe-bindings)
59+ (switch-to-buffer "*Help*")
60+ (call-process-region
61+ (point-min) (point-max)
62+ emacs-keybind-program-file
63+ nil
64+ (generate-new-buffer "*emacs-report*")
65+ nil
66+ "-k" emacs-keybind-keyboard-kind
67+ "-f" "html")
68+ (switch-to-buffer "*emacs-report*")
69+ (let ((file-name (emacs-keybind-make-path emacs-keybind-show-file-name)))
70+ (write-file file-name)
71+ (browse-url-of-file file-name)
72+ (kill-buffer (current-buffer))))
73+
74+(defun emacs-keybind-show-with-history ()
75+ "The key bind report is displayed including history information."
76+ (interactive)
77+ (describe-bindings)
78+ (switch-to-buffer "*Help*")
79+ (call-process-region
80+ (point-min) (point-max)
81+ emacs-keybind-program-file
82+ nil
83+ (generate-new-buffer "*emacs-report*")
84+ nil
85+ "-k" emacs-keybind-keyboard-kind
86+ "-h" (emacs-keybind-make-path emacs-keybind-history-save-file-name)
87+ "-f" "html")
88+ (switch-to-buffer "*emacs-report*")
89+ (let ((file-name (emacs-keybind-make-path emacs-keybind-show-with-history-file-name)))
90+ (write-file file-name)
91+ (browse-url-of-file file-name)
92+ (kill-buffer (current-buffer))))
93+
94+(provide 'emacs-keybind)
--- trunk/emacs-keybind/emacs_history.rb (nonexistent)
+++ trunk/emacs-keybind/emacs_history.rb (revision 4)
@@ -0,0 +1,154 @@
1+require 'matrix'
2+
3+class String
4+ def to_sexp
5+ array = self.chomp.split(/([()])| /).delete_if{|c| c.size == 0}
6+ raise "The expression doesn't close." if array[-1] != ')'
7+ array.parse_sexp
8+ end
9+
10+ def to_s_sexp
11+ self
12+ end
13+end
14+
15+class Array
16+ def to_s_sexp
17+ str=""
18+ str += '('
19+ self.each do |s|
20+ str += ( s.class == Array ? s.to_s_sexp : s.to_s )
21+ str += ' '
22+ end
23+ str += ')'
24+ str
25+ end
26+
27+ def parse_sexp
28+ q = []
29+ q << '['
30+ self.each do |l|
31+ case l
32+ when '('
33+ q << '['
34+ when ')'
35+ q << '],'
36+ else
37+ q << '"' + l + '",'
38+ end
39+ end
40+ q << ']'
41+ return eval( q.join )
42+ end
43+end
44+
45+class Vector
46+ def []=(i,x)
47+ @elements[i]=x
48+ end
49+end
50+
51+class Color
52+ attr_accessor :vector
53+
54+ def initialize(r, g, b)
55+ @vector = Vector[r, g, b]
56+ end
57+
58+ def +(rhs)
59+ color = clone
60+ color.vector += rhs.vector
61+ color.limit
62+ end
63+
64+ def *(rhs)
65+ color = clone
66+ color.vector *= rhs
67+ color.limit
68+ end
69+
70+ def limit
71+ color = clone
72+ color.vector[0] = 255 if (color.vector[0] > 255)
73+ color.vector[1] = 255 if (color.vector[1] > 255)
74+ color.vector[2] = 255 if (color.vector[2] > 255)
75+ color
76+ end
77+
78+ def to_html
79+ "##{format("%02x", @vector[0])}#{format("%02x", @vector[1])}#{format("%02x", @vector[2])}"
80+ end
81+end
82+
83+class EmacsHistoryData
84+ attr_accessor :use_count, :ranking
85+
86+ def initialize
87+ @use_count = 0
88+ @ranking = 0
89+ end
90+end
91+
92+class EmacsHistory
93+ def initialize(file_name)
94+ @hash = Hash.new
95+ parse(file_name)
96+ setup_ranking
97+ end
98+
99+ def parse(file_name)
100+ open(file_name).each do |line|
101+ next if (line =~ /^;/)
102+
103+ line.chomp.to_sexp[0].each do |name|
104+ s_exp = name.to_s_sexp
105+ @hash[s_exp] = EmacsHistoryData.new if !@hash.key? s_exp
106+ @hash[s_exp].use_count += 1
107+ end
108+ end
109+ end
110+
111+ def setup_ranking
112+ @ranking = @hash.to_a.sort {|a, b| (b[1].use_count <=> a[1].use_count).nonzero? or a[0] <=> b[0] }
113+
114+ current = 1
115+ prev = @ranking[0]
116+
117+ @ranking.each do |a|
118+ current += 1 if (a[1].use_count != prev[1].use_count)
119+ a[1].ranking = current
120+ prev = a
121+ end
122+
123+ @ranking_total = current
124+ end
125+
126+ def count(name)
127+ @hash.fetch(name) {|| 0 }
128+ end
129+
130+ def ranking
131+ @ranking
132+ end
133+
134+ def color(s_exp)
135+ color1 = Color.new(255, 0, 0)
136+ color2 = Color.new(255, 255, 0)
137+ color3 = Color.new(0, 0, 255)
138+
139+ return color3.to_html if (!@hash.key?(s_exp))
140+
141+ data = @hash[s_exp]
142+
143+ index = data.ranking - 1
144+ half = @ranking_total / 2
145+
146+ if (index < half)
147+ rate = index.to_f / half
148+ (color1 * (1.0 - rate) + color2 * (rate)).to_html
149+ else
150+ rate = (index.to_f - half) / half
151+ (color2 * (1.0 - rate) + color3 * (rate)).to_html
152+ end
153+ end
154+end
--- trunk/emacs-keybind/keyboard_data.rb (nonexistent)
+++ trunk/emacs-keybind/keyboard_data.rb (revision 4)
@@ -0,0 +1,251 @@
1+Header = <<EOF
2+<html>
3+<head>
4+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5+<title></title>
6+</head>
7+<body>
8+<p>
9+<h1>Index</h1>
10+<ol>
11+ <li><a href="#frequency">frequency</a></li>
12+ <li><a href="#keybind">keybind</a></li>
13+ <ol>
14+ <li><a href="#self">?</a></li>
15+ <li><a href="#control">C-?</a></li>
16+ <li><a href="#alt">M-?</a></li>
17+ <li><a href="#control_alt">C-M-?</a></li>
18+ <li><a href="#control_x_control">C-x C-?</a></li>
19+ <li><a href="#control_x">C-x ?</a></li>
20+ <li><a href="#control_c_control">C-c C-?</a></li>
21+ <li><a href="#control_c">C-c ?</a></li>
22+ </ol>
23+</ol>
24+EOF
25+
26+Footer = <<EOF
27+</p>
28+</body>
29+</html>
30+EOF
31+
32+HeaderHatena = <<EOF
33+**Emacs Keybind
34+EOF
35+
36+KeyboardAscii =
37+ [
38+ # ESC 〜 DEL
39+ [
40+ ['ESC'],
41+ ['F1'],
42+ ['F2'],
43+ ['F3'],
44+ ['F4'],
45+ ['F5'],
46+ ['F6'],
47+ ['F7'],
48+ ['F8'],
49+ ['F9'],
50+ ['F10'],
51+ ['F11'],
52+ ['F12'],
53+ ['INS'],
54+ ['DEL'],
55+ ],
56+ # 半角/全角 〜 Backspace
57+ [
58+ ['`~', %w(` ~)],
59+ ['1!', %w(1 !)],
60+ ['2@', %w(2 @)],
61+ ['3#', %w(3 #)],
62+ ['4$', %w(4 \$)],
63+ ['5%', %w(5 %)],
64+ ['6^', %w(6 ^)],
65+ ["7&amp;", %w(7 &)],
66+ ['8*', %w(8 \*)],
67+ ['9(', %w(9 \\\()],
68+ ['0)', %w(0 \\\))],
69+ ['-_', %w(- _)],
70+ ['= +', %w(= \+)],
71+ ['BS'],
72+ ],
73+ # TAB 〜 RET
74+ [
75+ ['TAB', %w(TAB)],
76+ ['Q', %w(q Q)],
77+ ['W', %w(w W)],
78+ ['E', %w(e E)],
79+ ['R', %w(r R)],
80+ ['T', %w(t T)],
81+ ['Y', %w(y Y)],
82+ ['U', %w(u U)],
83+ ['I', %w(i I)],
84+ ['O', %w(o O)],
85+ ['P', %w(p P)],
86+ ['[{', %w(\[ \{)],
87+ [']}', %w(\] \})],
88+ ['\|', %w(\\\\ \|)],
89+ ],
90+ # Caps 〜 RET
91+ [
92+ ['Caps'],
93+ ['A', %w(a A)],
94+ ['S', %w(s S)],
95+ ['D', %w(d D)],
96+ ['F', %w(f F)],
97+ ['G', %w(g G)],
98+ ['H', %w(h H)],
99+ ['J', %w(j J)],
100+ ['K', %w(k K)],
101+ ['L', %w(l L)],
102+ [';:', %w(; :)],
103+ ["'\"", %w(' ")],
104+ [''],
105+ ['RET', %w(RET)],
106+ ],
107+ # Shift 〜 Shift
108+ [
109+ ['Shift'],
110+ ['Z', %w(z Z)],
111+ ['X', %w(x X)],
112+ ['C', %w(c C)],
113+ ['V', %w(v V)],
114+ ['B', %w(b B)],
115+ ['N', %w(n N)],
116+ ['M', %w(m M)],
117+ [',&lt;', %w(, <)],
118+ ['.&gt;', %w(\. >)],
119+ ['/?', %w(\/ \?)],
120+ [''],
121+ [''],
122+ ['Shift'],
123+ ],
124+ # Ctrl 〜 [right]
125+ [
126+ ['Ctrl'],
127+ ['Alt'],
128+ [''],
129+ [''],
130+ ['SPC', %w(SPC)],
131+ [''],
132+ [''],
133+ [''],
134+ ['Alt'],
135+ ['Ctrl'],
136+ ['[up]'],
137+ ['[down]'],
138+ ['[left]'],
139+ ['[right]'],
140+ ],
141+ ]
142+
143+KeyboardJapanese =
144+ [
145+ # ESC 〜 DEL
146+ [
147+ ['ESC'],
148+ ['F1'],
149+ ['F2'],
150+ ['F3'],
151+ ['F4'],
152+ ['F5'],
153+ ['F6'],
154+ ['F7'],
155+ ['F8'],
156+ ['F9'],
157+ ['F10'],
158+ ['F11'],
159+ ['F12'],
160+ ['INS'],
161+ ['DEL'],
162+ ],
163+ # 半角/全角 〜 Backspace
164+ [
165+ ['one byte/two byte'],
166+ ['1!', %w(1 !)],
167+ ['2"', %w(2 ")],
168+ ['3#', %w(3 #)],
169+ ['4$', %w(4 \$)],
170+ ['5%', %w(5 %)],
171+ ['6&amp;', %w(6 &)],
172+ ["7'", %w(7 ')],
173+ ['8(', %w(8 \\\()],
174+ ['9)', %w(9 \\\))],
175+ ['0', %w(0)],
176+ ['-=', %w(- =)],
177+ ['^~', %w(^ ~)],
178+ ['\|', %w(\\\\ \|)],
179+ ['BS'],
180+ ],
181+ # TAB 〜 RET
182+ [
183+ ['TAB', %w(TAB)],
184+ ['Q', %w(q Q)],
185+ ['W', %w(w W)],
186+ ['E', %w(e E)],
187+ ['R', %w(r R)],
188+ ['T', %w(t T)],
189+ ['Y', %w(y Y)],
190+ ['U', %w(u U)],
191+ ['I', %w(i I)],
192+ ['O', %w(o O)],
193+ ['P', %w(p P)],
194+ ['@`', %w(@ `)],
195+ ['[{', %w(\[ \{)],
196+ [''],
197+ ['RET', %w(RET)],
198+ ],
199+ # Caps 〜 RET
200+ [
201+ ['Caps'],
202+ ['A', %w(a A)],
203+ ['S', %w(s S)],
204+ ['D', %w(d D)],
205+ ['F', %w(f F)],
206+ ['G', %w(g G)],
207+ ['H', %w(h H)],
208+ ['J', %w(j J)],
209+ ['K', %w(k K)],
210+ ['L', %w(l L)],
211+ [';+', %w(; \+)],
212+ [':*', %w(: \*)],
213+ [']}', %w(\] \})],
214+ [''],
215+ [''], # RETのみ特殊で二列で表示する
216+ ],
217+ # Shift 〜 Shift
218+ [
219+ ['Shift'],
220+ ['Z', %w(z Z)],
221+ ['X', %w(x X)],
222+ ['C', %w(c C)],
223+ ['V', %w(v V)],
224+ ['B', %w(b B)],
225+ ['N', %w(n N)],
226+ ['M', %w(m M)],
227+ [',&lt;', %w(, <)],
228+ ['.&gt;', %w(\. >)],
229+ ['/?', %w(\/ \?)],
230+ ['\_', %w(\\\\ _)],
231+ [''],
232+ [''],
233+ ['Shift'],
234+ ],
235+ # Ctrl 〜 [right]
236+ [
237+ ['Ctrl'],
238+ [''],
239+ ['Alt'],
240+ ['No conversion'],
241+ ['SPC', %w(SPC)],
242+ ['Conversion'],
243+ ['Alt'],
244+ ['Ctrl'],
245+ ['[up]'],
246+ ['[down]'],
247+ ['[left]'],
248+ ['[right]'],
249+ ],
250+ ]
251+
Show on old repository browser