textbringer 1.0.1 → 1.1.0

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ubuntu.yml +5 -9
  3. data/.github/workflows/windows.yml +4 -7
  4. data/CHANGES.md +47 -0
  5. data/README.md +0 -2
  6. data/bin/merge_mazegaki_dic +25 -0
  7. data/exe/textbringer +6 -5
  8. data/lib/textbringer.rb +4 -0
  9. data/lib/textbringer/buffer.rb +40 -3
  10. data/lib/textbringer/commands/clipboard.rb +3 -3
  11. data/lib/textbringer/commands/ctags.rb +3 -3
  12. data/lib/textbringer/commands/dabbrev.rb +1 -1
  13. data/lib/textbringer/commands/files.rb +18 -3
  14. data/lib/textbringer/commands/help.rb +25 -16
  15. data/lib/textbringer/commands/input_method.rb +18 -0
  16. data/lib/textbringer/commands/isearch.rb +23 -2
  17. data/lib/textbringer/commands/misc.rb +8 -3
  18. data/lib/textbringer/commands/windows.rb +8 -4
  19. data/lib/textbringer/config.rb +2 -1
  20. data/lib/textbringer/controller.rb +7 -1
  21. data/lib/textbringer/input_method.rb +63 -0
  22. data/lib/textbringer/input_methods/hiragana_input_method.rb +70 -0
  23. data/lib/textbringer/input_methods/t_code_input_method.rb +458 -0
  24. data/lib/textbringer/input_methods/t_code_input_method/tables.rb +64 -0
  25. data/lib/textbringer/keymap.rb +45 -26
  26. data/lib/textbringer/modes/backtrace_mode.rb +1 -1
  27. data/lib/textbringer/modes/buffer_list_mode.rb +1 -1
  28. data/lib/textbringer/modes/c_mode.rb +4 -0
  29. data/lib/textbringer/modes/completion_list_mode.rb +1 -1
  30. data/lib/textbringer/modes/help_mode.rb +1 -1
  31. data/lib/textbringer/modes/programming_mode.rb +24 -2
  32. data/lib/textbringer/modes/ruby_mode.rb +70 -12
  33. data/lib/textbringer/utils.rb +10 -5
  34. data/lib/textbringer/version.rb +1 -1
  35. data/lib/textbringer/window.rb +25 -10
  36. data/textbringer.gemspec +4 -5
  37. metadata +19 -28
  38. data/.github/workflows/ruby-head.yml +0 -30
@@ -0,0 +1,64 @@
1
+ module Textbringer
2
+ class TCodeInputMethod
3
+ KEYBOARD = "1234567890" "qwertyuiop" "asdfghjkl;" "zxcvbnm,./"
4
+
5
+ KEY_TABLE = KEYBOARD.each_char.with_index.map { |c, i|
6
+ [c, i]
7
+ }.to_h
8
+
9
+ KANJI_TABLE = [
10
+ "■■■■■■■■■■ヮヰヱヵヶ請境系探象ゎゐゑ■■盛革突温捕■■■■■依繊借須訳",
11
+ "■■■■■■■■■■丑臼宴縁曳尚賀岸責漁於汚乙穏■益援周域荒■■■■■織父枚乱香",
12
+ "■■■■■■■■■■鬼虚狭脅驚舎喜幹丘糖奇既菊却享康徒景処ぜ■■■■■譲ヘ模降走",
13
+ "■■■■■■■■■■孤誇黄后耕布苦圧恵固巧克懇困昏邦舞雑漢緊■■■■■激干彦均又",
14
+ "■■■■⑤■■■■■奉某貌卜■姿絶密秘押■■■■■衆節杉肉除■■■■■測血散笑弁",
15
+ "■■■■■■■■■■湖礼著移郷■■■■■償欧努底亜■■■■■禁硝樹句礎■■■■■",
16
+ "■■■■■■■■■■端飾郵塩群■星析遷宣紅傷豪維脱鼠曹奏尊■絹被源願臨■■■■■",
17
+ "■■■■◈■■■■■刷寿順危砂庶粧丈称蒸舗充喫腕暴■■■■■批慶渉竜併■■■■■",
18
+ "■■■■■■■■■■震扱片札乞■乃如尼帳輪倒操柄魚■■■■■就駐揮丹鮮■■■■■",
19
+ "■■■■■■■■■■弘痛票訴遺欄龍略慮累則存倍牛釈■■■■■綱潟創背皮■■■■■",
20
+ "ヲ哀暇啓把酸昼炭稲湯果告策首農歩回務島開報紙館夜位給員ど代レ欠夏彼妻善相家的対歴",
21
+ "ゥ逢牙掲伐貿捜異隣旧概買詳由死キせ区百木音王放々応分よル千ア財針裏居差付プばュ作",
22
+ "ヴ宛壊携避攻焼闘奈夕武残両在!や出タ手保案曲情引職7か(トれ従骨厚顔量内工八テ見",
23
+ "ヂ囲較劇卑盤帯易速拡風階能論増コ山者発立横興刺側覚きっ日国二適類御宇推九名川機チ",
24
+ "ヅ庵寒賢藩汽換延雪互細古利ペゃナ金マ和女崎白ぐ官球上く8え年母奥因酒伸サ建パ第入",
25
+ "簡徴触宗植■索射濁慢害賃整軽評佐法数郎談服声任検豊美題井洋実爆仲茶率比昔短岩巨敗",
26
+ "承章候途複■冊需詑迷撃折追隊角接備最急験変審改昇芸宿制集安画陽構旅施曜遠ォ将ぞ塚",
27
+ "快否歯筆里■皿輯蓄戻浴秀糸春幸記朝知ワ送限研労統役セ運ツ特谷ァ導認健尾序振練念働",
28
+ "包納頼逃寝■賛瞬貯羊積程断低減モ資士費ィ逆企精ざ印神び打勤ャ殺負何履般耳授版効視",
29
+ "唱暮憲勉罪■■盾虫■故鉱提児敷無石屋解募令違装然確優公品語演券悪秋非便示即難普辺",
30
+ "ぱ慰我兼菱桜瀬鳥催障収際太園船中スもお定種岡結進真3と〇てるヒ江別考権ッ人三京ち",
31
+ "ぴ為掛嫌紐典博筋忠乳若雄査ふ賞わラ東生ろ宅熟待取科ーした一が及久蔵早造ロク万方フ",
32
+ "ぷ陰敢顕描採謡希仏察指氏丸続ェう4)十リ料土活ね参い、の51投義算半県んまンつ四",
33
+ "ぺ隠甘牽憤君純副盟標ぎ格次習火あこ6学月受予切育池。◆0・2込沢軍青清けイす電地",
34
+ "ぽ胃患厳弊犯余堀肩療思術広門聞本さら高シ英ボ加室少ではになを転空性使級業時「長み",
35
+ "朱遅甲致汎■衰滋沈己病終起路越む南原駅物勢必講愛管要設水藤有素兵専親寮ホ共ブ平楽",
36
+ "陣鶴鹿貨絡■趨湿添已常張薬防得ケ式戦関男輸形助◇流連鉄教力ベ毛永申袋良私ゴ来信午",
37
+ "眼繁誌招季■垂甚徹巳寺質づ港条話座線ダ橋基好味宝争デ現エ他度等浅頃落命村ガ製校ご",
38
+ "執紹夢卸阿■粋■爪巴停領容玉右べ民ソ点遇足草築観言車成天世文板客師税飛ノ完重約各",
39
+ "岳刑弱雲窓■寸瞳陶■河置供試席期ゾ歳強係婦段衛額渋主映書可へ伝庭課着坂近外米ョ光",
40
+ "ぁ■瓦■■呼幅歓功盗徳渡守登退店持町所ほ件友卒初慣行ド円小ジヨ誤証含%海道ず西げ",
41
+ "ぃ■■■■紀破郡抗幡械刊訪融雨全じ自議明宮伊求技写通カ社野同判規感値ギ当理メウグ",
42
+ "ぅ■■■■房績識属衣帝始了極熱バ部六経動局頭配黒院だり—め大済吉ゆ器照不合面政オ",
43
+ "ぇ■■■■去疑ぢ綿離読鈴恐督況後間場ニ産向府富直倉新」9子五説週号葉派委化ビ目市",
44
+ "ぉ■■■■秒範核影麻族丁未才返問ム七住北割ぶ番望元事田会前そ休省央福毎気売下都株",
45
+ "欲巣茂述朗■■■■■帰庁昨跡ゲ洗羽個医静億録赤想消支協用表正図挙険ゼ波ヤ心界意今",
46
+ "迫災恋脳老■■■■■監寄裁達芝響忘討史環色貸販編仕先多商ハ交之末ぼ街免再ネ〜口台",
47
+ "留列刻豆看■■■■■竹注介具失司迎華許補左態花栄ザ調混ポ決ミ州払乗庫状団計夫食総",
48
+ "替沼?辞献■■■■■ゅ修究答養復並浦ユ冷ぬ展警型誰組選党択体例満津準遊戸ひょ価与",
49
+ "還更占箱矢■■■■■志抜航層深担陸巻競護根様独止堂銀以ヌ営治字材過諸単身ピ勝反ズ"
50
+ ]
51
+
52
+ # Key positions
53
+ # 0 1 2 3 4 5 6 7 8 9
54
+ # 10 11 12 13 14 15 16 17 18 19
55
+ # 20 21 22 23 24 25 26 27 28 29
56
+ # 30 31 32 33 34 35 36 37 38 39
57
+ MAZEGAKI_STROKE_PRIORITY_LIST = [
58
+ 22, 23, 21, 24, 20,
59
+ 12, 13, 11, 14, 10,
60
+ 27, 26, 28, 25, 29,
61
+ 17, 16, 18, 15, 19
62
+ ]
63
+ end
64
+ end
@@ -1,3 +1,11 @@
1
+ class Module
2
+ def define_keymap(name)
3
+ unless const_defined?(name, false)
4
+ const_set(name, Textbringer::Keymap.new)
5
+ end
6
+ end
7
+ end
8
+
1
9
  module Textbringer
2
10
  class Keymap
3
11
  include Enumerable
@@ -72,7 +80,16 @@ def self.key_name(key)
72
80
  end
73
81
 
74
82
  def self.key_sequence_string(key_sequence)
75
- key_sequence.map { |key| key_name(key) }.join(" ")
83
+ ks = key_sequence.dup
84
+ key_names = []
85
+ while key = ks.shift
86
+ if key == "\e" && !ks.empty?
87
+ key_names.push("M-" + key_name(ks.shift))
88
+ else
89
+ key_names.push(key_name(key))
90
+ end
91
+ end
92
+ key_names.join(" ")
76
93
  end
77
94
 
78
95
  private
@@ -82,7 +99,7 @@ def kbd(key)
82
99
  when Symbol
83
100
  [key]
84
101
  when String
85
- key.chars
102
+ key.b.gsub(/[\x80-\xff]/n) { |c| "\e" + (c.ord & 0x7f).chr }.chars
86
103
  when Array
87
104
  key
88
105
  else
@@ -91,17 +108,17 @@ def kbd(key)
91
108
  end
92
109
  end
93
110
 
94
- GLOBAL_MAP = Keymap.new
111
+ define_keymap :GLOBAL_MAP
95
112
  GLOBAL_MAP.define_key(:resize, :resize_window)
96
113
  GLOBAL_MAP.define_key(:right, :forward_char)
97
114
  GLOBAL_MAP.define_key(?\C-f, :forward_char)
98
115
  GLOBAL_MAP.define_key(:left, :backward_char)
99
116
  GLOBAL_MAP.define_key(?\C-b, :backward_char)
100
- GLOBAL_MAP.define_key("\ef", :forward_word)
101
- GLOBAL_MAP.define_key("\eb", :backward_word)
102
- GLOBAL_MAP.define_key("\egc", :goto_char)
103
- GLOBAL_MAP.define_key("\egg", :goto_line)
104
- GLOBAL_MAP.define_key("\eg\eg", :goto_line)
117
+ GLOBAL_MAP.define_key("\M-f", :forward_word)
118
+ GLOBAL_MAP.define_key("\M-b", :backward_word)
119
+ GLOBAL_MAP.define_key("\M-gc", :goto_char)
120
+ GLOBAL_MAP.define_key("\M-gg", :goto_line)
121
+ GLOBAL_MAP.define_key("\M-g\M-g", :goto_line)
105
122
  GLOBAL_MAP.define_key(:down, :next_line)
106
123
  GLOBAL_MAP.define_key(?\C-n, :next_line)
107
124
  GLOBAL_MAP.define_key(:up, :previous_line)
@@ -115,8 +132,8 @@ def kbd(key)
115
132
  GLOBAL_MAP.define_key(:home, :beginning_of_line)
116
133
  GLOBAL_MAP.define_key(?\C-e, :end_of_line)
117
134
  GLOBAL_MAP.define_key(:end, :end_of_line)
118
- GLOBAL_MAP.define_key("\e<", :beginning_of_buffer)
119
- GLOBAL_MAP.define_key("\e>", :end_of_buffer)
135
+ GLOBAL_MAP.define_key("\M-<", :beginning_of_buffer)
136
+ GLOBAL_MAP.define_key("\M->", :end_of_buffer)
120
137
  (?\x20..?\x7e).each do |c|
121
138
  GLOBAL_MAP.define_key(c, :self_insert)
122
139
  end
@@ -124,15 +141,15 @@ def kbd(key)
124
141
  GLOBAL_MAP.define_key(?\C-q, :quoted_insert)
125
142
  GLOBAL_MAP.define_key("\C-@", :set_mark_command)
126
143
  GLOBAL_MAP.define_key("\C-x\C-@", :pop_global_mark)
127
- GLOBAL_MAP.define_key("\e*", :next_global_mark)
128
- GLOBAL_MAP.define_key("\e?", :previous_global_mark)
144
+ GLOBAL_MAP.define_key("\M-*", :next_global_mark)
145
+ GLOBAL_MAP.define_key("\M-?", :previous_global_mark)
129
146
  GLOBAL_MAP.define_key("\C-x\C-x", :exchange_point_and_mark)
130
- GLOBAL_MAP.define_key("\ew", :copy_region)
147
+ GLOBAL_MAP.define_key("\M-w", :copy_region)
131
148
  GLOBAL_MAP.define_key(?\C-w, :kill_region)
132
149
  GLOBAL_MAP.define_key(?\C-k, :kill_line)
133
- GLOBAL_MAP.define_key("\ed", :kill_word)
150
+ GLOBAL_MAP.define_key("\M-d", :kill_word)
134
151
  GLOBAL_MAP.define_key(?\C-y, :yank)
135
- GLOBAL_MAP.define_key("\ey", :yank_pop)
152
+ GLOBAL_MAP.define_key("\M-y", :yank_pop)
136
153
  GLOBAL_MAP.define_key(?\C-_, :undo)
137
154
  GLOBAL_MAP.define_key("\C-xu", :undo)
138
155
  GLOBAL_MAP.define_key("\C-x\C-_", :redo_command)
@@ -140,14 +157,14 @@ def kbd(key)
140
157
  GLOBAL_MAP.define_key("\C-j", :newline)
141
158
  GLOBAL_MAP.define_key("\C-m", :newline)
142
159
  GLOBAL_MAP.define_key("\C-o", :open_line)
143
- GLOBAL_MAP.define_key("\em", :back_to_indentation)
144
- GLOBAL_MAP.define_key("\e^", :delete_indentation)
160
+ GLOBAL_MAP.define_key("\M-m", :back_to_indentation)
161
+ GLOBAL_MAP.define_key("\M-^", :delete_indentation)
145
162
  GLOBAL_MAP.define_key("\C-xh", :mark_whole_buffer)
146
- GLOBAL_MAP.define_key("\ez", :zap_to_char)
163
+ GLOBAL_MAP.define_key("\M-z", :zap_to_char)
147
164
  GLOBAL_MAP.define_key("\C-l", :recenter)
148
165
  GLOBAL_MAP.define_key("\C-v", :scroll_up)
149
166
  GLOBAL_MAP.define_key(:npage, :scroll_up)
150
- GLOBAL_MAP.define_key("\ev", :scroll_down)
167
+ GLOBAL_MAP.define_key("\M-v", :scroll_down)
151
168
  GLOBAL_MAP.define_key(:ppage, :scroll_down)
152
169
  GLOBAL_MAP.define_key("\C-x0", :delete_window)
153
170
  GLOBAL_MAP.define_key("\C-x1", :delete_other_windows)
@@ -158,6 +175,7 @@ def kbd(key)
158
175
  GLOBAL_MAP.define_key("\C-x\C-c", :exit_textbringer)
159
176
  GLOBAL_MAP.define_key("\C-z", :suspend_textbringer)
160
177
  GLOBAL_MAP.define_key("\C-x\C-f", :find_file)
178
+ GLOBAL_MAP.define_key("\C-x\C-v", :find_alternate_file)
161
179
  GLOBAL_MAP.define_key("\C-xb", :switch_to_buffer)
162
180
  GLOBAL_MAP.define_key("\C-x\C-b", :list_buffers)
163
181
  GLOBAL_MAP.define_key("\C-x\C-s", :save_buffer)
@@ -166,15 +184,15 @@ def kbd(key)
166
184
  GLOBAL_MAP.define_key("\C-x\C-mf", :set_buffer_file_encoding)
167
185
  GLOBAL_MAP.define_key("\C-x\C-mn", :set_buffer_file_format)
168
186
  GLOBAL_MAP.define_key("\C-x\C-mr", :revert_buffer_with_encoding)
169
- GLOBAL_MAP.define_key("\e.", :find_tag)
170
- GLOBAL_MAP.define_key("\ex", :execute_command)
171
- GLOBAL_MAP.define_key("\e:", :eval_expression)
187
+ GLOBAL_MAP.define_key("\M-.", :find_tag)
188
+ GLOBAL_MAP.define_key("\M-x", :execute_command)
189
+ GLOBAL_MAP.define_key("\M-:", :eval_expression)
172
190
  GLOBAL_MAP.define_key(?\C-u, :universal_argument)
173
191
  GLOBAL_MAP.define_key(?\C-g, :keyboard_quit)
174
192
  GLOBAL_MAP.define_key(?\C-s, :isearch_forward)
175
193
  GLOBAL_MAP.define_key(?\C-r, :isearch_backward)
176
- GLOBAL_MAP.define_key("\e%", :query_replace_regexp)
177
- GLOBAL_MAP.define_key("\e!", :shell_execute)
194
+ GLOBAL_MAP.define_key("\M-%", :query_replace_regexp)
195
+ GLOBAL_MAP.define_key("\M-!", :shell_execute)
178
196
  GLOBAL_MAP.define_key("\C-xr ", :point_to_register)
179
197
  GLOBAL_MAP.define_key("\C-xrj", :jump_to_register)
180
198
  GLOBAL_MAP.define_key("\C-xrx", :copy_to_register)
@@ -188,11 +206,12 @@ def kbd(key)
188
206
  GLOBAL_MAP.define_key("\C-x)", :end_keyboard_macro)
189
207
  GLOBAL_MAP.define_key("\C-xe", :end_and_call_keyboard_macro)
190
208
  GLOBAL_MAP.define_key(:f4, :end_or_call_keyboard_macro)
191
- GLOBAL_MAP.define_key("\eq", :fill_paragraph)
209
+ GLOBAL_MAP.define_key("\M-q", :fill_paragraph)
192
210
  GLOBAL_MAP.define_key([:f1, "b"], :describe_bindings)
193
211
  GLOBAL_MAP.define_key([:f1, "f"], :describe_command)
194
212
  GLOBAL_MAP.define_key([:f1, "k"], :describe_key)
195
213
  GLOBAL_MAP.define_key("\C-x#", :server_edit_done)
214
+ GLOBAL_MAP.define_key("\C-\\", :toggle_input_method)
196
215
  GLOBAL_MAP.handle_undefined_key do |key|
197
216
  if key.is_a?(String) && /[\0-\x7f]/ !~ key
198
217
  :self_insert
@@ -201,7 +220,7 @@ def kbd(key)
201
220
  end
202
221
  end
203
222
 
204
- MINIBUFFER_LOCAL_MAP = Keymap.new
223
+ define_keymap :MINIBUFFER_LOCAL_MAP
205
224
  MINIBUFFER_LOCAL_MAP.define_key("\C-j", :exit_recursive_edit)
206
225
  MINIBUFFER_LOCAL_MAP.define_key("\C-m", :exit_recursive_edit)
207
226
  MINIBUFFER_LOCAL_MAP.define_key(?\t, :complete_minibuffer)
@@ -2,7 +2,7 @@ module Textbringer
2
2
  class BacktraceMode < Mode
3
3
  define_generic_command :jump_to_source_location
4
4
 
5
- BACKTRACE_MODE_MAP = Keymap.new
5
+ define_keymap :BACKTRACE_MODE_MAP
6
6
  BACKTRACE_MODE_MAP.define_key("\C-m", :jump_to_source_location_command)
7
7
 
8
8
  define_syntax :link, /^\S*?:\d+:(?:\d+:)?/
@@ -1,6 +1,6 @@
1
1
  module Textbringer
2
2
  class BufferListMode < Mode
3
- BUFFER_LIST_MODE_MAP = Keymap.new
3
+ define_keymap :BUFFER_LIST_MODE_MAP
4
4
  BUFFER_LIST_MODE_MAP.define_key("\C-m", :this_window_command)
5
5
 
6
6
  def initialize(buffer)
@@ -34,6 +34,10 @@ class CMode < ProgrammingMode
34
34
  (?: ' (?: [^\\'] | \\ (?:.|\n) )* ' )
35
35
  /x
36
36
 
37
+ def comment_start
38
+ "//"
39
+ end
40
+
37
41
  def initialize(buffer)
38
42
  super(buffer)
39
43
  @buffer[:indent_level] = CONFIG[:c_indent_level]
@@ -2,7 +2,7 @@ module Textbringer
2
2
  class CompletionListMode < Mode
3
3
  define_generic_command :choose_completion
4
4
 
5
- COMPLETION_LIST_MODE_MAP = Keymap.new
5
+ define_keymap :COMPLETION_LIST_MODE_MAP
6
6
  COMPLETION_LIST_MODE_MAP.define_key("\C-m", :choose_completion_command)
7
7
 
8
8
  define_syntax :link, /^.+$/
@@ -2,7 +2,7 @@ module Textbringer
2
2
  class HelpMode < Mode
3
3
  define_generic_command :jump_to_link
4
4
 
5
- HELP_MODE_MAP = Keymap.new
5
+ define_keymap :HELP_MODE_MAP
6
6
  HELP_MODE_MAP.define_key(?\C-m, :jump_to_link_command)
7
7
  HELP_MODE_MAP.define_key(?l, :help_go_back)
8
8
  HELP_MODE_MAP.define_key("\C-c\C-b", :help_go_back)
@@ -10,16 +10,18 @@ class ProgrammingMode < FundamentalMode
10
10
  define_generic_command :backward_definition
11
11
  define_generic_command :compile
12
12
  define_generic_command :toggle_test
13
+ define_generic_command :indent_new_comment_line
13
14
 
14
- PROGRAMMING_MODE_MAP = Keymap.new
15
+ define_keymap :PROGRAMMING_MODE_MAP
15
16
  PROGRAMMING_MODE_MAP.define_key("\t", :indent_line_command)
16
17
  PROGRAMMING_MODE_MAP.define_key("\C-m",
17
18
  :reindent_then_newline_and_indent_command)
18
- PROGRAMMING_MODE_MAP.define_key("\e\C-\\", :indent_region_command)
19
+ PROGRAMMING_MODE_MAP.define_key("\M-\C-\\", :indent_region_command)
19
20
  PROGRAMMING_MODE_MAP.define_key("\C-c\C-n", :forward_definition_command)
20
21
  PROGRAMMING_MODE_MAP.define_key("\C-c\C-p", :backward_definition_command)
21
22
  PROGRAMMING_MODE_MAP.define_key("\C-c\C-c", :compile_command)
22
23
  PROGRAMMING_MODE_MAP.define_key("\C-c\C-t", :toggle_test_command)
24
+ PROGRAMMING_MODE_MAP.define_key("\ej", :indent_new_comment_line_command)
23
25
 
24
26
  def initialize(buffer)
25
27
  super(buffer)
@@ -86,6 +88,26 @@ def indent_region(s = @buffer.mark, e = @buffer.point)
86
88
  end
87
89
  end
88
90
 
91
+ def indent_new_comment_line
92
+ if comment_start.nil?
93
+ @buffer.newline
94
+ return
95
+ end
96
+ s = @buffer.save_excursion {
97
+ @buffer.beginning_of_line
98
+ if @buffer.looking_at?(/[ \t]*#{comment_start}+[ \t]*/)
99
+ @buffer.match_string(0)
100
+ else
101
+ ""
102
+ end
103
+ }
104
+ @buffer.insert("\n" + s)
105
+ end
106
+
107
+ def comment_start
108
+ nil
109
+ end
110
+
89
111
  private
90
112
 
91
113
  def calculate_indentation
@@ -21,7 +21,7 @@ class | module | def | undef | begin | rescue | ensure | end |
21
21
  if | unless | then | elsif | else | case | when | while | until |
22
22
  for | break | next | redo | retry | in | do | return | yield |
23
23
  super | self | nil | true | false | and | or | not | alias
24
- ) \b | defined\? )
24
+ ) \b (?![!?]) | defined\? )
25
25
  /x
26
26
 
27
27
  define_syntax :string, /
@@ -85,6 +85,10 @@ class | module | def | undef | begin | rescue | ensure | end |
85
85
  )
86
86
  /x
87
87
 
88
+ def comment_start
89
+ "#"
90
+ end
91
+
88
92
  def initialize(buffer)
89
93
  super(buffer)
90
94
  @buffer[:indent_level] = CONFIG[:ruby_indent_level]
@@ -173,7 +177,7 @@ def toggle_test
173
177
 
174
178
  private
175
179
 
176
- INDENT_BEG_RE = /^([ \t]*)(class|module|def|if|unless|case|while|until|for|begin|end)\b/
180
+ INDENT_BEG_RE = /^([ \t]*)(class|module|def|if|unless|case|while|until|for|begin)\b/
177
181
 
178
182
  def space_width(s)
179
183
  s.gsub(/\t/, " " * @buffer[:tab_width]).size
@@ -194,6 +198,22 @@ def beginning_of_indentation
194
198
  0
195
199
  end
196
200
 
201
+ def lex(source)
202
+ line_count = source.count("\n")
203
+ s = source
204
+ lineno = 1
205
+ tokens = []
206
+ loop do
207
+ lexer = Ripper::Lexer.new(s, "-", lineno)
208
+ tokens.concat(lexer.lex)
209
+ last_line = tokens.dig(-1, 0, 0)
210
+ return tokens if last_line.nil? || last_line >= line_count
211
+ s = source.sub(/(.*\n?){#{last_line}}/, "")
212
+ return tokens if last_line + 1 <= lineno
213
+ lineno = last_line + 1
214
+ end
215
+ end
216
+
197
217
  def calculate_indentation
198
218
  if @buffer.current_line == 1
199
219
  return 0
@@ -205,7 +225,7 @@ def calculate_indentation
205
225
  base_indentation = beginning_of_indentation
206
226
  start_pos = @buffer.point
207
227
  start_line = @buffer.current_line
208
- tokens = Ripper.lex(@buffer.substring(start_pos, bol_pos))
228
+ tokens = lex(@buffer.substring(start_pos, bol_pos))
209
229
  _, event, text = tokens.last
210
230
  if event == :on_nl
211
231
  _, event, text = tokens[-2]
@@ -217,7 +237,7 @@ def calculate_indentation
217
237
  event == :on_tstring_content
218
238
  return nil
219
239
  end
220
- i = find_nearest_beginning_token(tokens)
240
+ i, extra_end_count = find_nearest_beginning_token(tokens)
221
241
  (line, column), event, = i ? tokens[i] : nil
222
242
  if event == :on_lparen && tokens.dig(i + 1, 1) != :on_ignored_nl
223
243
  return column + 1
@@ -240,7 +260,8 @@ def calculate_indentation
240
260
  end
241
261
  @buffer.goto_char(bol_pos)
242
262
  if line.nil?
243
- indentation = base_indentation
263
+ indentation =
264
+ base_indentation - extra_end_count * @buffer[:indent_level]
244
265
  else
245
266
  indentation = base_indentation + @buffer[:indent_level]
246
267
  end
@@ -252,6 +273,7 @@ def calculate_indentation
252
273
  }
253
274
  if start_with_period ||
254
275
  (last_event == :on_op && last_text != "|") ||
276
+ (last_event == :on_kw && /\A(and|or)\z/.match?(last_text)) ||
255
277
  last_event == :on_period ||
256
278
  (last_event == :on_comma && event != :on_lbrace &&
257
279
  event != :on_lparen && event != :on_lbracket)
@@ -262,6 +284,7 @@ def calculate_indentation
262
284
  end
263
285
 
264
286
  BLOCK_END = {
287
+ '#{' => "}",
265
288
  "{" => "}",
266
289
  "(" => ")",
267
290
  "[" => "]"
@@ -278,10 +301,12 @@ def find_nearest_beginning_token(tokens)
278
301
  case text
279
302
  when "class", "module", "def", "if", "unless", "case",
280
303
  "do", "for", "while", "until", "begin"
281
- if /\A(if|unless|while|until)\z/.match?(text)
282
- ts = tokens[0...i].reverse_each.take_while { |(l,_),| l == line }
283
- t = ts.find { |_, e| e != :on_sp }
284
- next if t && !(t[1] == :on_op && t[2] == "=")
304
+ if /\A(if|unless|while|until)\z/.match?(text) &&
305
+ modifier?(tokens, i)
306
+ next
307
+ end
308
+ if text == "def" && endless_method_def?(tokens, i)
309
+ next
285
310
  end
286
311
  if stack.empty?
287
312
  return i
@@ -293,9 +318,9 @@ def find_nearest_beginning_token(tokens)
293
318
  when "end"
294
319
  stack.push(text)
295
320
  end
296
- when :on_rbrace, :on_rparen, :on_rbracket
321
+ when :on_rbrace, :on_rparen, :on_rbracket, :on_embexpr_end
297
322
  stack.push(text)
298
- when :on_lbrace, :on_lparen, :on_lbracket, :on_tlambeg
323
+ when :on_lbrace, :on_lparen, :on_lbracket, :on_tlambeg, :on_embexpr_beg
299
324
  if stack.empty?
300
325
  return i
301
326
  end
@@ -305,7 +330,40 @@ def find_nearest_beginning_token(tokens)
305
330
  stack.pop
306
331
  end
307
332
  end
308
- return nil
333
+ return nil, stack.grep_v(/[)\]]/).size
334
+ end
335
+
336
+ def modifier?(tokens, i)
337
+ (line,), = tokens[i]
338
+ ts = tokens[0...i].reverse_each.take_while { |(l,_),| l == line }
339
+ t = ts.find { |_, e| e != :on_sp }
340
+ t && !(t[1] == :on_op && t[2] == "=")
341
+ end
342
+
343
+ def endless_method_def?(tokens, i)
344
+ ts = tokens.drop(i + 1)
345
+ ts.shift while ts[0][1] == :on_sp
346
+ _, event = ts.shift
347
+ return false if event != :on_ident
348
+ ts.shift while ts[0][1] == :on_sp
349
+ if ts[0][1] == :on_lparen
350
+ ts.shift
351
+ count = 1
352
+ while count > 0
353
+ _, event = ts.shift
354
+ return false if event.nil?
355
+ case event
356
+ when :on_lparen
357
+ count +=1
358
+ when :on_rparen
359
+ count -=1
360
+ end
361
+ end
362
+ ts.shift while ts[0][1] == :on_sp
363
+ end
364
+ ts[0][1] == :on_op && ts[0][2] == "="
365
+ rescue NoMethodError # no token
366
+ return false
309
367
  end
310
368
 
311
369
  def find_test_target_path(base, namespace, name)