textbringer 0.1.8 → 0.1.9
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/.travis.yml +22 -8
- data/CHANGES.md +11 -0
- data/Guardfile +1 -1
- data/exe/tbtags +26 -0
- data/exe/textbringer +1 -0
- data/lib/textbringer.rb +6 -0
- data/lib/textbringer/buffer.rb +158 -83
- data/lib/textbringer/commands.rb +18 -6
- data/lib/textbringer/commands/buffers.rb +187 -43
- data/lib/textbringer/commands/clipboard.rb +23 -6
- data/lib/textbringer/commands/ctags.rb +3 -23
- data/lib/textbringer/commands/files.rb +10 -7
- data/lib/textbringer/commands/help.rb +114 -0
- data/lib/textbringer/commands/isearch.rb +13 -7
- data/lib/textbringer/commands/keyboard_macro.rb +86 -0
- data/lib/textbringer/commands/misc.rb +43 -2
- data/lib/textbringer/commands/register.rb +128 -0
- data/lib/textbringer/commands/replace.rb +4 -3
- data/lib/textbringer/commands/windows.rb +49 -22
- data/lib/textbringer/config.rb +2 -1
- data/lib/textbringer/controller.rb +89 -23
- data/lib/textbringer/keymap.rb +60 -2
- data/lib/textbringer/modes/help_mode.rb +42 -0
- data/lib/textbringer/modes/programming_mode.rb +35 -28
- data/lib/textbringer/modes/ruby_mode.rb +28 -10
- data/lib/textbringer/plugin.rb +21 -0
- data/lib/textbringer/ring.rb +84 -0
- data/lib/textbringer/utils.rb +28 -0
- data/lib/textbringer/version.rb +1 -1
- data/lib/textbringer/window.rb +59 -5
- data/textbringer.gemspec +1 -1
- metadata +12 -4
data/lib/textbringer/commands.rb
CHANGED
@@ -4,26 +4,38 @@ require "open3"
|
|
4
4
|
require "io/wait"
|
5
5
|
|
6
6
|
module Textbringer
|
7
|
+
Command = Struct.new(:name, :block, :doc)
|
8
|
+
|
7
9
|
module Commands
|
8
10
|
include Utils
|
9
11
|
|
10
|
-
|
12
|
+
@command_table = {}
|
11
13
|
|
12
14
|
def self.list
|
13
|
-
|
15
|
+
@command_table.keys
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.command_table
|
19
|
+
@command_table
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.[](name)
|
23
|
+
@command_table[name.intern]
|
14
24
|
end
|
15
25
|
|
16
|
-
def define_command(name, &block)
|
26
|
+
def define_command(name, doc: "No documentation", &block)
|
27
|
+
name = name.intern
|
17
28
|
Commands.send(:define_method, name, &block)
|
18
|
-
|
29
|
+
Commands.command_table[name] = Command.new(name, block, doc)
|
19
30
|
name
|
20
31
|
end
|
21
32
|
module_function :define_command
|
22
33
|
|
23
34
|
def undefine_command(name)
|
24
|
-
|
35
|
+
name = name.intern
|
36
|
+
if Commands.command_table.key?(name)
|
25
37
|
Commands.send(:undef_method, name)
|
26
|
-
|
38
|
+
Commands.command_table.delete(name)
|
27
39
|
end
|
28
40
|
end
|
29
41
|
module_function :undefine_command
|
@@ -2,63 +2,175 @@
|
|
2
2
|
|
3
3
|
module Textbringer
|
4
4
|
module Commands
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
define_command(name) do |n = number_prefix_arg|
|
16
|
-
Buffer.current.send(name, n)
|
17
|
-
end
|
5
|
+
define_command(:forward_char,
|
6
|
+
doc: "Move point n characters forward.") do
|
7
|
+
|n = number_prefix_arg|
|
8
|
+
Buffer.current.forward_char(n)
|
9
|
+
end
|
10
|
+
|
11
|
+
define_command(:backward_char,
|
12
|
+
doc: "Move point n characters backward.") do
|
13
|
+
|n = number_prefix_arg|
|
14
|
+
Buffer.current.backward_char(n)
|
18
15
|
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
17
|
+
define_command(:forward_word,
|
18
|
+
doc: "Move point n words forward.") do
|
19
|
+
|n = number_prefix_arg|
|
20
|
+
Buffer.current.forward_word(n)
|
21
|
+
end
|
22
|
+
|
23
|
+
define_command(:backward_word,
|
24
|
+
doc: "Move point n words backward.") do
|
25
|
+
|n = number_prefix_arg|
|
26
|
+
Buffer.current.backward_word(n)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
define_command(:next_line,
|
31
|
+
doc: "Move point n lines forward.") do
|
32
|
+
|n = number_prefix_arg|
|
33
|
+
Buffer.current.next_line(n)
|
34
|
+
end
|
35
|
+
|
36
|
+
define_command(:previous_line,
|
37
|
+
doc: "Move point n lines backward.") do
|
38
|
+
|n = number_prefix_arg|
|
39
|
+
Buffer.current.previous_line(n)
|
40
|
+
end
|
41
|
+
|
42
|
+
define_command(:delete_char,
|
43
|
+
doc: "Delete n characters forward.") do
|
44
|
+
|n = number_prefix_arg|
|
45
|
+
Buffer.current.delete_char(n)
|
46
|
+
end
|
47
|
+
|
48
|
+
define_command(:backward_delete_char,
|
49
|
+
doc: "Delete n characters backward.") do
|
50
|
+
|n = number_prefix_arg|
|
51
|
+
Buffer.current.backward_delete_char(n)
|
52
|
+
end
|
53
|
+
|
54
|
+
define_command(:beginning_of_line,
|
55
|
+
doc: "Move point to the beginning of the current line.") do
|
56
|
+
Buffer.current.beginning_of_line
|
36
57
|
end
|
37
58
|
|
38
|
-
define_command(:
|
39
|
-
|
40
|
-
|
59
|
+
define_command(:end_of_line,
|
60
|
+
doc: "Move point to the end of the current line.") do
|
61
|
+
Buffer.current.end_of_line
|
41
62
|
end
|
42
63
|
|
43
|
-
define_command(:
|
44
|
-
|
45
|
-
Buffer.current.
|
64
|
+
define_command(:beginning_of_buffer,
|
65
|
+
doc: "Move point to the beginning of the buffer.") do
|
66
|
+
Buffer.current.beginning_of_buffer
|
67
|
+
end
|
68
|
+
|
69
|
+
define_command(:end_of_buffer,
|
70
|
+
doc: "Move point to the end of the buffer.") do
|
71
|
+
Buffer.current.end_of_buffer
|
72
|
+
end
|
73
|
+
|
74
|
+
define_command(:push_mark,
|
75
|
+
doc: <<~EOD) do
|
76
|
+
Set mark at pos, and push the mark on the mark ring.
|
77
|
+
Unlike Emacs, the new mark is pushed on the mark ring instead of
|
78
|
+
the old one.
|
79
|
+
EOD
|
80
|
+
|pos = Buffer.current.point|
|
81
|
+
Buffer.current.push_mark(pos)
|
82
|
+
end
|
83
|
+
|
84
|
+
define_command(:pop_mark,
|
85
|
+
doc: "Pop the mark from the mark ring.") do
|
86
|
+
Buffer.current.pop_mark
|
87
|
+
end
|
88
|
+
|
89
|
+
define_command(:pop_to_mark,
|
90
|
+
doc: <<~EOD) do
|
91
|
+
Move point to where the mark is, and pop the mark from
|
92
|
+
the mark ring.
|
93
|
+
EOD
|
94
|
+
Buffer.current.pop_to_mark
|
95
|
+
end
|
96
|
+
|
97
|
+
define_command(:exchange_point_and_mark,
|
98
|
+
doc: "Exchange the positions of point and mark.") do
|
99
|
+
Buffer.current.exchange_point_and_mark
|
100
|
+
end
|
101
|
+
|
102
|
+
define_command(:copy_region,
|
103
|
+
doc: "Copy the region to the kill ring.") do
|
104
|
+
Buffer.current.copy_region
|
105
|
+
end
|
106
|
+
|
107
|
+
define_command(:kill_region,
|
108
|
+
doc: "Copy and delete the region.") do
|
109
|
+
Buffer.current.kill_region
|
110
|
+
end
|
111
|
+
|
112
|
+
define_command(:yank,
|
113
|
+
doc: "Insert the last text copied in the kill ring.") do
|
114
|
+
Buffer.current.yank
|
115
|
+
end
|
116
|
+
|
117
|
+
define_command(:newline,
|
118
|
+
doc: "Insert a newline.") do
|
119
|
+
Buffer.current.newline
|
120
|
+
end
|
121
|
+
|
122
|
+
define_command(:delete_region,
|
123
|
+
doc: "Delete the region without copying.") do
|
124
|
+
Buffer.current.delete_region
|
125
|
+
end
|
126
|
+
|
127
|
+
define_command(:transpose_chars,
|
128
|
+
doc: "Transpose characters.") do
|
129
|
+
Buffer.current.transpose_chars
|
130
|
+
end
|
131
|
+
|
132
|
+
define_command(:set_mark_command,
|
133
|
+
doc: <<~EOD) do
|
134
|
+
Set the mark at point.
|
135
|
+
|
136
|
+
With C-u, move point to where the mark is, and pop the mark from
|
137
|
+
the mark ring.
|
138
|
+
EOD
|
139
|
+
|arg = current_prefix_arg|
|
140
|
+
buffer = Buffer.current
|
141
|
+
if arg
|
142
|
+
buffer.pop_to_mark
|
143
|
+
else
|
144
|
+
buffer.push_mark
|
145
|
+
message("Mark set")
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
define_command(:goto_char,
|
150
|
+
doc: "Move point to pos.") do
|
151
|
+
|pos = read_from_minibuffer("Go to char: ")|
|
152
|
+
Buffer.current.goto_char(pos.to_i)
|
46
153
|
Window.current.recenter_if_needed
|
47
154
|
end
|
48
155
|
|
49
|
-
define_command(:goto_line
|
156
|
+
define_command(:goto_line,
|
157
|
+
doc: "Move point to line n.") do
|
50
158
|
|n = read_from_minibuffer("Go to line: ")|
|
51
159
|
Buffer.current.goto_line(n.to_i)
|
52
160
|
Window.current.recenter_if_needed
|
53
161
|
end
|
54
162
|
|
55
|
-
define_command(:self_insert
|
163
|
+
define_command(:self_insert,
|
164
|
+
doc: "Insert the character typed.") do
|
165
|
+
|n = number_prefix_arg|
|
56
166
|
c = Controller.current.last_key
|
57
167
|
merge_undo = Controller.current.last_command == :self_insert
|
58
168
|
Buffer.current.insert(c * n, merge_undo)
|
59
169
|
end
|
60
170
|
|
61
|
-
define_command(:quoted_insert
|
171
|
+
define_command(:quoted_insert,
|
172
|
+
doc: "Read a character, and insert it.") do
|
173
|
+
|n = number_prefix_arg|
|
62
174
|
c = Controller.current.read_char
|
63
175
|
if !c.is_a?(String)
|
64
176
|
raise EditorError, "Invalid key"
|
@@ -66,17 +178,22 @@ module Textbringer
|
|
66
178
|
Buffer.current.insert(c * n)
|
67
179
|
end
|
68
180
|
|
69
|
-
define_command(:kill_line
|
181
|
+
define_command(:kill_line,
|
182
|
+
doc: "Kill the rest of the current line.") do
|
70
183
|
Buffer.current.kill_line(Controller.current.last_command == :kill_region)
|
71
184
|
Controller.current.this_command = :kill_region
|
72
185
|
end
|
73
186
|
|
74
|
-
define_command(:kill_word
|
187
|
+
define_command(:kill_word,
|
188
|
+
doc: "Kill a word.") do
|
75
189
|
Buffer.current.kill_word(Controller.current.last_command == :kill_region)
|
76
190
|
Controller.current.this_command = :kill_region
|
77
191
|
end
|
78
192
|
|
79
|
-
define_command(:yank_pop
|
193
|
+
define_command(:yank_pop,
|
194
|
+
doc: <<~EOD) do
|
195
|
+
Rotate the kill ring, and replace the yanked text.
|
196
|
+
EOD
|
80
197
|
if Controller.current.last_command != :yank
|
81
198
|
raise EditorError, "Previous command was not a yank"
|
82
199
|
end
|
@@ -84,14 +201,41 @@ module Textbringer
|
|
84
201
|
Controller.current.this_command = :yank
|
85
202
|
end
|
86
203
|
|
87
|
-
define_command(:undo
|
204
|
+
define_command(:undo,
|
205
|
+
doc: "Undo changes.") do
|
88
206
|
Buffer.current.undo
|
89
207
|
message("Undo!") unless Window.echo_area.current?
|
90
208
|
end
|
91
209
|
|
92
|
-
define_command(:
|
210
|
+
define_command(:redo_command,
|
211
|
+
doc: "Redo changes reverted by undo.") do
|
93
212
|
Buffer.current.redo
|
94
213
|
message("Redo!") unless Window.echo_area.current?
|
95
214
|
end
|
215
|
+
|
216
|
+
define_command(:back_to_indentation,
|
217
|
+
doc: "Move point to the first non-space character.") do
|
218
|
+
buffer = Buffer.current
|
219
|
+
buffer.beginning_of_line
|
220
|
+
while /[ \t]/ =~ buffer.char_after
|
221
|
+
buffer.forward_char
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
define_command(:delete_indentation,
|
226
|
+
doc: <<~EOD) do
|
227
|
+
Delete indentation and join the current line to the previous line.
|
228
|
+
EOD
|
229
|
+
buffer = Buffer.current
|
230
|
+
back_to_indentation
|
231
|
+
pos = buffer.point
|
232
|
+
buffer.skip_re_backward(/[^\n]/)
|
233
|
+
return if buffer.beginning_of_buffer?
|
234
|
+
buffer.backward_char
|
235
|
+
buffer.skip_re_backward(/[ \t]/)
|
236
|
+
buffer.delete_region(buffer.point, pos)
|
237
|
+
buffer.insert(" ")
|
238
|
+
buffer.backward_char
|
239
|
+
end
|
96
240
|
end
|
97
241
|
end
|
@@ -21,27 +21,41 @@ module Textbringer
|
|
21
21
|
GLOBAL_MAP.define_key("\ey", :clipboard_yank_pop)
|
22
22
|
end
|
23
23
|
|
24
|
-
define_command(:clipboard_copy_region) do
|
24
|
+
define_command(:clipboard_copy_region, doc: <<~EOD) do
|
25
|
+
Copy the region to the kill ring and the clipboard.
|
26
|
+
EOD
|
25
27
|
copy_region
|
26
28
|
Clipboard.copy(KILL_RING.current)
|
27
29
|
end
|
28
30
|
|
29
|
-
define_command(:clipboard_kill_region) do
|
31
|
+
define_command(:clipboard_kill_region, doc: <<~EOD) do
|
32
|
+
Copy the region to the kill ring and the clipboard, and delete
|
33
|
+
the region.
|
34
|
+
EOD
|
30
35
|
kill_region
|
31
36
|
Clipboard.copy(KILL_RING.current)
|
32
37
|
end
|
33
38
|
|
34
|
-
define_command(:clipboard_kill_line) do
|
39
|
+
define_command(:clipboard_kill_line, doc: <<~EOD) do
|
40
|
+
Kill the rest of the current line, and copy the killed text to
|
41
|
+
the clipboard.
|
42
|
+
EOD
|
35
43
|
kill_line
|
36
44
|
Clipboard.copy(KILL_RING.current)
|
37
45
|
end
|
38
46
|
|
39
|
-
define_command(:clipboard_kill_word) do
|
47
|
+
define_command(:clipboard_kill_word, doc: <<~EOD) do
|
48
|
+
Kill a word, and copy the word to the clipboard.
|
49
|
+
EOD
|
40
50
|
kill_word
|
41
51
|
Clipboard.copy(KILL_RING.current)
|
42
52
|
end
|
43
53
|
|
44
|
-
define_command(:clipboard_yank) do
|
54
|
+
define_command(:clipboard_yank, doc: <<~EOD) do
|
55
|
+
If the clipboard contents are different from the last killed text,
|
56
|
+
push the contents to the kill ring, and insert it.
|
57
|
+
Otherwise, just insert the last text copied in the kill ring.
|
58
|
+
EOD
|
45
59
|
s = Clipboard.paste.encode(Encoding::UTF_8).gsub(/\r\n/, "\n")
|
46
60
|
if !s.empty? && (KILL_RING.empty? || KILL_RING.current != s)
|
47
61
|
KILL_RING.push(s)
|
@@ -50,7 +64,10 @@ module Textbringer
|
|
50
64
|
Controller.current.this_command = :yank
|
51
65
|
end
|
52
66
|
|
53
|
-
define_command(:clipboard_yank_pop) do
|
67
|
+
define_command(:clipboard_yank_pop, doc: <<~EOD) do
|
68
|
+
Rotate the kill ring, and replace the yanked text, and copy
|
69
|
+
the text to the clipboard.
|
70
|
+
EOD
|
54
71
|
yank_pop
|
55
72
|
Clipboard.copy(KILL_RING.current)
|
56
73
|
end
|
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
module Textbringer
|
4
4
|
module Commands
|
5
|
-
GLOBAL_MAP.define_key("\e.", :find_tag)
|
6
|
-
GLOBAL_MAP.define_key("\e*", :pop_tag_mark)
|
7
|
-
|
8
5
|
CTAGS = {
|
9
6
|
path: nil,
|
10
7
|
tags: nil,
|
@@ -58,7 +55,8 @@ module Textbringer
|
|
58
55
|
push_tag_mark_and_find_file(file)
|
59
56
|
beginning_of_buffer
|
60
57
|
n.times do
|
61
|
-
|
58
|
+
s = Regexp.quote($1.gsub(/\\([\\\/])/, "\\1"))
|
59
|
+
re_search_forward("^" + s + "$")
|
62
60
|
end
|
63
61
|
beginning_of_line
|
64
62
|
when %r'\A\?\^(.*)\$\?\z'
|
@@ -92,28 +90,10 @@ module Textbringer
|
|
92
90
|
CTAGS[:tags]
|
93
91
|
end
|
94
92
|
|
95
|
-
define_command(:pop_tag_mark) do
|
96
|
-
tag_mark_stack = CTAGS[:tag_mark_stack]
|
97
|
-
if tag_mark_stack.empty?
|
98
|
-
raise EditorError, "No previous locations"
|
99
|
-
end
|
100
|
-
mark = tag_mark_stack.pop
|
101
|
-
begin
|
102
|
-
switch_to_buffer(mark.buffer)
|
103
|
-
mark.buffer.point_to_mark(mark)
|
104
|
-
ensure
|
105
|
-
mark.delete
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
93
|
private
|
110
94
|
|
111
95
|
def push_tag_mark_and_find_file(file)
|
112
|
-
|
113
|
-
if tag_mark_stack.size == CONFIG[:tag_mark_limit]
|
114
|
-
tag_mark_stack.shift.delete
|
115
|
-
end
|
116
|
-
tag_mark_stack.push(Buffer.current.new_mark)
|
96
|
+
Buffer.current.push_global_mark(force: true)
|
117
97
|
find_file(file)
|
118
98
|
end
|
119
99
|
end
|
@@ -4,7 +4,7 @@ require "editorconfig"
|
|
4
4
|
|
5
5
|
module Textbringer
|
6
6
|
module Commands
|
7
|
-
define_command(:find_file) do
|
7
|
+
define_command(:find_file, doc: "Open or create a file.") do
|
8
8
|
|file_name = read_file_name("Find file: ")|
|
9
9
|
config = EditorConfig.load_file(file_name)
|
10
10
|
buffer = Buffer.find_file(file_name)
|
@@ -48,7 +48,7 @@ module Textbringer
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
define_command(:save_buffer) do
|
51
|
+
define_command(:save_buffer, doc: "Save the current buffer to a file.") do
|
52
52
|
if Buffer.current.file_name.nil?
|
53
53
|
Buffer.current.file_name = read_file_name("File to save in: ")
|
54
54
|
next if Buffer.current.file_name.nil?
|
@@ -63,7 +63,8 @@ module Textbringer
|
|
63
63
|
message("Wrote #{Buffer.current.file_name}")
|
64
64
|
end
|
65
65
|
|
66
|
-
define_command(:write_file
|
66
|
+
define_command(:write_file,
|
67
|
+
doc: "Save the current buffer as the specified file.") do
|
67
68
|
|file_name = read_file_name("Write file: ")|
|
68
69
|
if File.directory?(file_name)
|
69
70
|
file_name = File.expand_path(Buffer.current.name, file_name)
|
@@ -78,23 +79,25 @@ module Textbringer
|
|
78
79
|
message("Wrote #{Buffer.current.file_name}")
|
79
80
|
end
|
80
81
|
|
81
|
-
define_command(:set_buffer_file_encoding
|
82
|
+
define_command(:set_buffer_file_encoding,
|
83
|
+
doc: "Set the file encoding of the current buffer.") do
|
82
84
|
|enc = read_from_minibuffer("File encoding: ",
|
83
85
|
default: Buffer.current.file_encoding.name)|
|
84
86
|
Buffer.current.file_encoding = enc
|
85
87
|
end
|
86
88
|
|
87
|
-
define_command(:set_buffer_file_format
|
89
|
+
define_command(:set_buffer_file_format,
|
90
|
+
doc: "Set the file format of the current buffer.") do
|
88
91
|
|format = read_from_minibuffer("File format: ",
|
89
92
|
default: Buffer.current.file_format.to_s)|
|
90
93
|
Buffer.current.file_format = format
|
91
94
|
end
|
92
95
|
|
93
|
-
define_command(:pwd) do
|
96
|
+
define_command(:pwd, doc: "Show the current working directory.") do
|
94
97
|
message(Dir.pwd)
|
95
98
|
end
|
96
99
|
|
97
|
-
define_command(:chdir) do
|
100
|
+
define_command(:chdir, doc: "Change the current working directory.") do
|
98
101
|
|dir_name = read_file_name("Change directory: ")|
|
99
102
|
Dir.chdir(dir_name)
|
100
103
|
end
|