textbringer 18 → 20

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/exe/txtb +1 -1
  3. data/lib/textbringer/buffer.rb +23 -2
  4. data/lib/textbringer/commands/clipboard.rb +21 -6
  5. data/lib/textbringer/commands/completion.rb +133 -0
  6. data/lib/textbringer/commands/ctags.rb +1 -1
  7. data/lib/textbringer/commands/files.rb +11 -1
  8. data/lib/textbringer/commands/help.rb +1 -1
  9. data/lib/textbringer/commands/ispell.rb +0 -2
  10. data/lib/textbringer/commands/lsp.rb +389 -0
  11. data/lib/textbringer/commands/misc.rb +2 -1
  12. data/lib/textbringer/commands.rb +7 -3
  13. data/lib/textbringer/completion_popup.rb +188 -0
  14. data/lib/textbringer/faces/basic.rb +1 -0
  15. data/lib/textbringer/faces/completion.rb +4 -0
  16. data/lib/textbringer/floating_window.rb +327 -0
  17. data/lib/textbringer/input_methods/skk_input_method.rb +773 -0
  18. data/lib/textbringer/lsp/client.rb +568 -0
  19. data/lib/textbringer/lsp/server_registry.rb +138 -0
  20. data/lib/textbringer/mode.rb +3 -1
  21. data/lib/textbringer/modes/programming_mode.rb +17 -8
  22. data/lib/textbringer/modes/transient_mark_mode.rb +5 -2
  23. data/lib/textbringer/utils.rb +14 -10
  24. data/lib/textbringer/version.rb +1 -1
  25. data/lib/textbringer/window.rb +36 -9
  26. data/lib/textbringer.rb +7 -0
  27. data/sig/lib/textbringer/buffer.rbs +483 -0
  28. data/sig/lib/textbringer/color.rbs +9 -0
  29. data/sig/lib/textbringer/commands/buffers.rbs +93 -0
  30. data/sig/lib/textbringer/commands/clipboard.rbs +17 -0
  31. data/sig/lib/textbringer/commands/completion.rbs +20 -0
  32. data/sig/lib/textbringer/commands/ctags.rbs +11 -0
  33. data/sig/lib/textbringer/commands/dabbrev.rbs +4 -0
  34. data/sig/lib/textbringer/commands/files.rbs +29 -0
  35. data/sig/lib/textbringer/commands/fill.rbs +5 -0
  36. data/sig/lib/textbringer/commands/help.rbs +28 -0
  37. data/sig/lib/textbringer/commands/input_method.rbs +6 -0
  38. data/sig/lib/textbringer/commands/isearch.rbs +38 -0
  39. data/sig/lib/textbringer/commands/ispell.rbs +39 -0
  40. data/sig/lib/textbringer/commands/keyboard_macro.rbs +25 -0
  41. data/sig/lib/textbringer/commands/lsp.rbs +8 -0
  42. data/sig/lib/textbringer/commands/misc.rbs +74 -0
  43. data/sig/lib/textbringer/commands/rectangle.rbs +19 -0
  44. data/sig/lib/textbringer/commands/register.rbs +31 -0
  45. data/sig/lib/textbringer/commands/replace.rbs +17 -0
  46. data/sig/lib/textbringer/commands/server.rbs +31 -0
  47. data/sig/lib/textbringer/commands/ucs_normalize.rbs +9 -0
  48. data/sig/lib/textbringer/commands/windows.rbs +45 -0
  49. data/sig/lib/textbringer/commands.rbs +21 -0
  50. data/sig/lib/textbringer/completion_popup.rbs +40 -0
  51. data/sig/lib/textbringer/controller.rbs +58 -0
  52. data/sig/lib/textbringer/default_output.rbs +7 -0
  53. data/sig/lib/textbringer/errors.rbs +3 -0
  54. data/sig/lib/textbringer/face.rbs +19 -0
  55. data/sig/lib/textbringer/floating_window.rbs +42 -0
  56. data/sig/lib/textbringer/global_minor_mode.rbs +7 -0
  57. data/sig/lib/textbringer/input_method.rbs +28 -0
  58. data/sig/lib/textbringer/input_methods/hangul_input_method.rbs +12 -0
  59. data/sig/lib/textbringer/input_methods/hiragana_input_method.rbs +12 -0
  60. data/sig/lib/textbringer/input_methods/t_code_input_method.rbs +49 -0
  61. data/sig/lib/textbringer/keymap.rbs +33 -0
  62. data/sig/lib/textbringer/lsp/client.rbs +21 -0
  63. data/sig/lib/textbringer/lsp/server_registry.rbs +23 -0
  64. data/sig/lib/textbringer/minor_mode.rbs +12 -0
  65. data/sig/lib/textbringer/mode.rbs +70 -0
  66. data/sig/lib/textbringer/modes/backtrace_mode.rbs +8 -0
  67. data/sig/lib/textbringer/modes/buffer_list_mode.rbs +5 -0
  68. data/sig/lib/textbringer/modes/c_mode.rbs +21 -0
  69. data/sig/lib/textbringer/modes/completion_list_mode.rbs +5 -0
  70. data/sig/lib/textbringer/modes/fundamental_mode.rbs +3 -0
  71. data/sig/lib/textbringer/modes/help_mode.rbs +7 -0
  72. data/sig/lib/textbringer/modes/overwrite_mode.rbs +15 -0
  73. data/sig/lib/textbringer/modes/programming_mode.rbs +14 -0
  74. data/sig/lib/textbringer/modes/ruby_mode.rbs +57 -0
  75. data/sig/lib/textbringer/plugin.rbs +3 -0
  76. data/sig/lib/textbringer/ring.rbs +36 -0
  77. data/sig/lib/textbringer/utils.rbs +95 -0
  78. data/sig/lib/textbringer/window.rbs +183 -0
  79. data/textbringer.gemspec +1 -0
  80. metadata +76 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6880825c5cf726a2e49e28052cb09c0e8f0a15eadbf98b38e8806e6b486b9475
4
- data.tar.gz: 79cef469e62da96630672057fda32b69ccdd349f76df36821f45a71be7e552d5
3
+ metadata.gz: 965d78b83028b05174c4dae6ddb2f0f367650333f605f625a12f898a0fc77f7b
4
+ data.tar.gz: c2e895bf76071590e42ad89e26c6d97d246fe68aeba741b9a2ee9eeb8f1110f1
5
5
  SHA512:
6
- metadata.gz: 868b9d1cce93bf0dc1dabdb4e59c0dd775210c700b794b7093bfedb82d95d7d9e82191fc1d05daa9342e282d151567aa4d0d85a93f489ced5165e7d537d1e102
7
- data.tar.gz: afad73fc5062774e6aa9b4d7cfa175be24f2dc25c9345218359ddce61f0049dcd7059709fe72c52c71d15d5625393a46987d0df04a36dbdc19d3855df02a8dab
6
+ metadata.gz: 17a23041efd23bf5dcb1dec4671cefb0645c194435e4f6fbf332fad79959bfb71e47da2d52b07bf7c964438cfb6fc08cb43c804e01f6c59597a50659a2fae7b2
7
+ data.tar.gz: cdec4c57a320056d392cced17e7f24dcf17bbfea21bc7053b65f612e84f4353abb8f4a372a3b572b2e18d3180c325b3b4801a16b97ef904ac06dd8f98ef9bef7
data/exe/txtb CHANGED
@@ -27,11 +27,11 @@ end
27
27
  Controller.current = Controller.new
28
28
  begin
29
29
  Window.start do
30
+ load_user_config("~/.textbringer/init.rb")
30
31
  $stdout = DefaultOutput.new
31
32
  begin
32
33
  transient_mark_mode(true)
33
34
  Window.echo_area.clear_message
34
- load_user_config("~/.textbringer/init.rb")
35
35
  Plugin.load_plugins
36
36
  load_user_config("~/.textbringer.rb")
37
37
  ruby_mode
@@ -277,11 +277,15 @@ module Textbringer
277
277
  end
278
278
 
279
279
  def file_name=(file_name)
280
+ old_file_name = @file_name
280
281
  @file_name = file_name
281
282
  basename = File.basename(file_name)
282
283
  if /\A#{Regexp.quote(basename)}(<\d+>)?\z/ !~ name
283
284
  self.name = basename
284
285
  end
286
+ if old_file_name != file_name && current?
287
+ Utils.run_hooks(:after_set_visited_file_name_hook, old_file_name)
288
+ end
285
289
  end
286
290
 
287
291
  def file_encoding=(enc)
@@ -343,7 +347,7 @@ module Textbringer
343
347
  end
344
348
 
345
349
  def on_killed(&callback)
346
- add_callback(:killed, callback)
350
+ on(:killed, &callback)
347
351
  end
348
352
 
349
353
  def current?
@@ -367,7 +371,7 @@ module Textbringer
367
371
  end
368
372
 
369
373
  def on_modified(&callback)
370
- add_callback(:modified, callback)
374
+ on(:modified, &callback)
371
375
  end
372
376
 
373
377
  def [](name)
@@ -610,6 +614,7 @@ module Textbringer
610
614
  end
611
615
  self.modified = true
612
616
  @goal_column = nil
617
+ Utils.run_hooks(:after_change_functions, pos, @point, "") unless @undoing || !current?
613
618
  self
614
619
  end
615
620
 
@@ -651,6 +656,7 @@ module Textbringer
651
656
  end
652
657
  push_undo(DeleteAction.new(self, s, s, str))
653
658
  self.modified = true
659
+ Utils.run_hooks(:after_change_functions, s, s, str) unless @undoing || !current?
654
660
  elsif n < 0
655
661
  str = substring(pos, s)
656
662
  update_line_and_column(@point, pos)
@@ -666,6 +672,7 @@ module Textbringer
666
672
  @point = @gap_start = pos
667
673
  push_undo(DeleteAction.new(self, s, pos, str))
668
674
  self.modified = true
675
+ Utils.run_hooks(:after_change_functions, pos, pos, str) unless @undoing || !current?
669
676
  end
670
677
  @goal_column = nil
671
678
  end
@@ -1020,6 +1027,7 @@ module Textbringer
1020
1027
  end
1021
1028
  push_undo(DeleteAction.new(self, old_pos, s, str))
1022
1029
  self.modified = true
1030
+ Utils.run_hooks(:after_change_functions, s, s, str) unless @undoing || !current?
1023
1031
  end
1024
1032
  end
1025
1033
 
@@ -1490,6 +1498,19 @@ module Textbringer
1490
1498
  end
1491
1499
  end
1492
1500
 
1501
+ def pos_to_line_and_column(pos)
1502
+ return [1, 1] if pos == 0
1503
+ text_before = substring(0, pos)
1504
+ line = text_before.count("\n") + 1
1505
+ last_newline = text_before.rindex("\n")
1506
+ column = if last_newline
1507
+ text_before.size - last_newline
1508
+ else
1509
+ text_before.size + 1
1510
+ end
1511
+ [line, column]
1512
+ end
1513
+
1493
1514
  private
1494
1515
 
1495
1516
  def set_contents(s, enc)
@@ -29,23 +29,38 @@ module Textbringer
29
29
  Copy the region to the kill ring and the clipboard, and delete
30
30
  the region.
31
31
  EOD
32
- kill_region
33
- Clipboard.copy(KILL_RING.current)
32
+ begin
33
+ kill_region
34
+ Clipboard.copy(KILL_RING.current)
35
+ rescue ReadOnlyError
36
+ Clipboard.copy(KILL_RING.current)
37
+ raise
38
+ end
34
39
  end
35
40
 
36
41
  define_command(:clipboard_kill_line, doc: <<~EOD) do
37
42
  Kill the rest of the current line, and copy the killed text to
38
43
  the clipboard.
39
44
  EOD
40
- kill_line
41
- Clipboard.copy(KILL_RING.current)
45
+ begin
46
+ kill_line
47
+ Clipboard.copy(KILL_RING.current)
48
+ rescue ReadOnlyError
49
+ Clipboard.copy(KILL_RING.current)
50
+ raise
51
+ end
42
52
  end
43
53
 
44
54
  define_command(:clipboard_kill_word, doc: <<~EOD) do
45
55
  Kill a word, and copy the word to the clipboard.
46
56
  EOD
47
- kill_word
48
- Clipboard.copy(KILL_RING.current)
57
+ begin
58
+ kill_word
59
+ Clipboard.copy(KILL_RING.current)
60
+ rescue ReadOnlyError
61
+ Clipboard.copy(KILL_RING.current)
62
+ raise
63
+ end
49
64
  end
50
65
 
51
66
  define_command(:clipboard_yank, doc: <<~EOD) do
@@ -0,0 +1,133 @@
1
+ module Textbringer
2
+ module Commands
3
+ define_keymap :COMPLETION_POPUP_MAP
4
+
5
+ # Navigation keys
6
+ COMPLETION_POPUP_MAP.define_key("\C-n", :completion_popup_next)
7
+ COMPLETION_POPUP_MAP.define_key(:down, :completion_popup_next)
8
+ COMPLETION_POPUP_MAP.define_key("\C-p", :completion_popup_previous)
9
+ COMPLETION_POPUP_MAP.define_key(:up, :completion_popup_previous)
10
+
11
+ # Accept keys
12
+ COMPLETION_POPUP_MAP.define_key("\C-m", :completion_popup_accept) # RET
13
+ COMPLETION_POPUP_MAP.define_key("\t", :completion_popup_accept) # Tab
14
+
15
+ # Cancel keys
16
+ COMPLETION_POPUP_MAP.define_key("\C-g", :completion_popup_cancel)
17
+
18
+ # Handle undefined keys - close popup and forward the key
19
+ COMPLETION_POPUP_MAP.handle_undefined_key do |key|
20
+ :completion_popup_self_insert_and_close
21
+ end
22
+
23
+ COMPLETION_POPUP_STATUS = {
24
+ active: false,
25
+ start_point: nil
26
+ }
27
+
28
+ def self.completion_popup_mode_active?
29
+ COMPLETION_POPUP_STATUS[:active]
30
+ end
31
+
32
+ define_command(:completion_popup_next,
33
+ doc: "Select next completion candidate.") do
34
+ CompletionPopup.instance.select_next
35
+ end
36
+
37
+ define_command(:completion_popup_previous,
38
+ doc: "Select previous completion candidate.") do
39
+ CompletionPopup.instance.select_previous
40
+ end
41
+
42
+ define_command(:completion_popup_accept,
43
+ doc: "Accept the selected completion.") do
44
+ popup = CompletionPopup.instance
45
+ item = popup.accept
46
+ if item
47
+ insert_completion(item)
48
+ end
49
+ completion_popup_done
50
+ end
51
+
52
+ define_command(:completion_popup_cancel,
53
+ doc: "Cancel completion popup.") do
54
+ CompletionPopup.instance.cancel
55
+ completion_popup_done
56
+ end
57
+
58
+ define_command(:completion_popup_self_insert_and_close,
59
+ doc: "Close popup and process the key.") do
60
+ CompletionPopup.instance.close
61
+ completion_popup_done
62
+ # Execute the command for the key that closed the popup
63
+ key = Controller.current.last_key
64
+ buffer = Buffer.current
65
+ cmd = buffer&.keymap&.lookup([key]) || GLOBAL_MAP.lookup([key])
66
+ if cmd.is_a?(Symbol)
67
+ send(cmd)
68
+ elsif cmd.respond_to?(:call)
69
+ cmd.call
70
+ end
71
+ end
72
+
73
+ def completion_popup_start(items:, start_point:, prefix: "")
74
+ return if items.empty?
75
+
76
+ CompletionPopup.instance.show(
77
+ items: items,
78
+ start_point: start_point,
79
+ prefix: prefix
80
+ )
81
+
82
+ COMPLETION_POPUP_STATUS[:active] = true
83
+ COMPLETION_POPUP_STATUS[:start_point] = start_point
84
+
85
+ Controller.current.overriding_map = COMPLETION_POPUP_MAP
86
+ add_hook(:pre_command_hook, :completion_popup_pre_command_hook)
87
+ end
88
+
89
+ def completion_popup_done
90
+ COMPLETION_POPUP_STATUS[:active] = false
91
+ COMPLETION_POPUP_STATUS[:start_point] = nil
92
+ Controller.current.overriding_map = nil
93
+ remove_hook(:pre_command_hook, :completion_popup_pre_command_hook)
94
+ end
95
+
96
+ def completion_popup_pre_command_hook
97
+ # Close popup if command is not a completion popup command
98
+ if /\Acompletion_popup_/ !~ Controller.current.this_command.to_s
99
+ CompletionPopup.instance.close
100
+ completion_popup_done
101
+ end
102
+ end
103
+
104
+ def insert_completion(item)
105
+ buffer = Buffer.current
106
+ start_point = COMPLETION_POPUP_STATUS[:start_point]
107
+ return unless start_point
108
+
109
+ insert_text = item[:insert_text] || item[:label]
110
+ return unless insert_text
111
+
112
+ # The server may return an insert_text that covers more than the typed
113
+ # symbol prefix (e.g. "Textbringer::Buffer" when the symbol pattern only
114
+ # backed up to "Buf"). Find the longest prefix of insert_text that is a
115
+ # suffix of the buffer text ending at point, and use that as the
116
+ # replacement range.
117
+ look_back = [buffer.point, insert_text.length].min
118
+ actual_start = start_point
119
+ if look_back > 0
120
+ text_before_point = buffer.substring(buffer.point - look_back, buffer.point)
121
+ look_back.downto(1) do |n|
122
+ if text_before_point.end_with?(insert_text[0, n])
123
+ actual_start = buffer.point - n
124
+ break
125
+ end
126
+ end
127
+ end
128
+
129
+ buffer.delete_region(actual_start, buffer.point)
130
+ buffer.insert(insert_text)
131
+ end
132
+ end
133
+ end
@@ -76,7 +76,7 @@ module Textbringer
76
76
  if CTAGS[:path] != path || CTAGS[:tags_mtime] != mtime
77
77
  CTAGS[:path] = path
78
78
  tags = Hash.new { |h, k| h[k] = [] }
79
- File.read(path).scan(/^(.*?)\t(.*?)\t(.*?)(?:;".*)?$/) do
79
+ File.binread(path).scan(/^(.*?)\t(.*?)\t(.*?)(?:;".*)?$/) do
80
80
  |name, file, addr|
81
81
  n = tags[name].count { |f,| f == file } + 1
82
82
  tags[name].push([file, addr, n])
@@ -45,6 +45,7 @@ module Textbringer
45
45
  if config.key?("tab_width")
46
46
  Buffer.current[:tab_width] = config["tab_width"].to_i
47
47
  end
48
+ run_hooks(:find_file_hook)
48
49
  end
49
50
 
50
51
  define_command(:revert_buffer, doc: <<~EOD) do
@@ -102,10 +103,19 @@ module Textbringer
102
103
  next
103
104
  end
104
105
  end
105
- Buffer.current.save(file_name)
106
+ set_visited_file_name(file_name)
107
+ Buffer.current.save
106
108
  message("Wrote #{Buffer.current.file_name}")
107
109
  end
108
110
 
111
+ define_command(:set_visited_file_name,
112
+ doc: "Change the file name of the current buffer.") do
113
+ |file_name = read_file_name("Set visited file name: ",
114
+ default: Buffer.current.file_name)|
115
+ file_name = File.expand_path(file_name)
116
+ Buffer.current.file_name = file_name
117
+ end
118
+
109
119
  define_command(:set_buffer_file_encoding,
110
120
  doc: "Set the file encoding of the current buffer.") do
111
121
  |enc = read_encoding("File encoding: ",
@@ -65,7 +65,7 @@ module Textbringer
65
65
  end
66
66
 
67
67
  def command_help(cmd)
68
- file, line = *cmd.block.source_location
68
+ file, line = *cmd.source_location
69
69
  s = format("%s:%d\n", file, line)
70
70
  s << "-" * (Window.columns - 2) + "\n"
71
71
  s << "#{cmd.name}"
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "open3"
4
2
  require "uri"
5
3