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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68977203d454a58e4191f2b74aba7239793f01ed
|
4
|
+
data.tar.gz: fc172a9d8466197a4cd2383d1fd25a04b5f31056
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 428028614b59f7c75b9740ce2567f7f40887e2df3b13f4a860416c0b742ffcc41c117011a77d5b31f9138bb79f79e8b5142c288f72d803ee676881ceaf1b4eeb
|
7
|
+
data.tar.gz: 5da641c9f7a42d4535a3f3889200fb97c83987f8223fba81a2c7d5e7324649804281c4965dcefce897762ba7dac400a406d93f483601ec9745f201fafe5e5ded
|
data/.travis.yml
CHANGED
@@ -1,13 +1,27 @@
|
|
1
|
-
sudo: false
|
2
|
-
os:
|
3
|
-
- linux
|
4
|
-
- osx
|
5
1
|
language: ruby
|
6
|
-
rvm:
|
7
|
-
- 2.3.3
|
8
|
-
- 2.4.0
|
9
|
-
- ruby-head
|
10
2
|
matrix:
|
3
|
+
include:
|
4
|
+
- os: linux
|
5
|
+
dist: trusty
|
6
|
+
sudo: false
|
7
|
+
rvm: 2.3.3
|
8
|
+
- os: linux
|
9
|
+
dist: trusty
|
10
|
+
sudo: false
|
11
|
+
rvm: 2.4.0
|
12
|
+
- os: linux
|
13
|
+
dist: trusty
|
14
|
+
sudo: false
|
15
|
+
rvm: ruby-head
|
16
|
+
- os: osx
|
17
|
+
osx_image: xcode8.2
|
18
|
+
rvm: 2.3.3
|
19
|
+
- os: osx
|
20
|
+
osx_image: xcode8.2
|
21
|
+
rvm: 2.4.0
|
22
|
+
- os: osx
|
23
|
+
osx_image: xcode8.2
|
24
|
+
rvm: ruby-head
|
11
25
|
allow_failures:
|
12
26
|
- os: osx
|
13
27
|
- rvm: ruby-head
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## 0.1.9
|
2
|
+
|
3
|
+
* Support registers.
|
4
|
+
* Support plugins.
|
5
|
+
* Support global mark ring.
|
6
|
+
* Support keyboard macro.
|
7
|
+
* Support help (describe_bindings, describe_command, and describe_key).
|
8
|
+
* Add tbtags.
|
9
|
+
* Add the commands back_to_indentation, indent_region, delete_indentation,
|
10
|
+
shrink_window, and shrink_window_if_larger_than_buffer.
|
11
|
+
|
1
12
|
## 0.1.8
|
2
13
|
|
3
14
|
* Support syntax highlighting.
|
data/Guardfile
CHANGED
data/exe/tbtags
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "ripper-tags"
|
4
|
+
|
5
|
+
module Textbringer
|
6
|
+
module TagParser
|
7
|
+
def on_method_add_arg(call, args)
|
8
|
+
call_name = call&.slice(0)
|
9
|
+
first_arg = args&.slice(0) == :args && args[1]
|
10
|
+
if call_name == :fcall && first_arg && call[1][0] == "define_command"
|
11
|
+
[:def, args[1][0], call[1][1]]
|
12
|
+
else
|
13
|
+
super(call, args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
RipperTags::Parser.prepend(Textbringer::TagParser)
|
20
|
+
|
21
|
+
begin
|
22
|
+
RipperTags.process_args(ARGV)
|
23
|
+
rescue => e
|
24
|
+
STDERR.printf("%s: %s\n", File.basename($0), e)
|
25
|
+
exit(1)
|
26
|
+
end
|
data/exe/textbringer
CHANGED
data/lib/textbringer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative "textbringer/version"
|
2
2
|
require_relative "textbringer/config"
|
3
3
|
require_relative "textbringer/errors"
|
4
|
+
require_relative "textbringer/ring"
|
4
5
|
require_relative "textbringer/buffer"
|
5
6
|
require_relative "textbringer/window"
|
6
7
|
require_relative "textbringer/keymap"
|
@@ -17,6 +18,9 @@ require_relative "textbringer/commands/replace"
|
|
17
18
|
require_relative "textbringer/commands/dabbrev"
|
18
19
|
require_relative "textbringer/commands/ctags"
|
19
20
|
require_relative "textbringer/commands/clipboard"
|
21
|
+
require_relative "textbringer/commands/register"
|
22
|
+
require_relative "textbringer/commands/keyboard_macro"
|
23
|
+
require_relative "textbringer/commands/help"
|
20
24
|
require_relative "textbringer/mode"
|
21
25
|
require_relative "textbringer/modes/fundamental_mode"
|
22
26
|
require_relative "textbringer/modes/programming_mode"
|
@@ -24,4 +28,6 @@ require_relative "textbringer/modes/ruby_mode"
|
|
24
28
|
require_relative "textbringer/modes/c_mode"
|
25
29
|
require_relative "textbringer/modes/backtrace_mode"
|
26
30
|
require_relative "textbringer/modes/completion_list_mode"
|
31
|
+
require_relative "textbringer/modes/help_mode"
|
32
|
+
require_relative "textbringer/plugin"
|
27
33
|
require_relative "textbringer/controller"
|
data/lib/textbringer/buffer.rb
CHANGED
@@ -52,6 +52,7 @@ module Textbringer
|
|
52
52
|
@@list = []
|
53
53
|
@@current = nil
|
54
54
|
@@minibuffer = nil
|
55
|
+
@@global_mark_ring = nil
|
55
56
|
|
56
57
|
def self.auto_detect_encodings
|
57
58
|
@@auto_detect_encodings
|
@@ -90,6 +91,10 @@ module Textbringer
|
|
90
91
|
@@minibuffer ||= Buffer.new(name: "*Minibuffer*")
|
91
92
|
end
|
92
93
|
|
94
|
+
def self.global_mark_ring
|
95
|
+
@@global_mark_ring ||= Ring.new(CONFIG[:global_mark_ring_max])
|
96
|
+
end
|
97
|
+
|
93
98
|
def self.last
|
94
99
|
if @@list.last == @@current
|
95
100
|
@@list[-2]
|
@@ -210,13 +215,16 @@ module Textbringer
|
|
210
215
|
@gap_end = 0
|
211
216
|
@marks = []
|
212
217
|
@mark = nil
|
218
|
+
@mark_ring = Ring.new(CONFIG[:mark_ring_max],
|
219
|
+
on_delete: ->(mark) { mark.delete })
|
213
220
|
@current_line = 1
|
214
221
|
@current_column = 1 # One-based character count
|
215
222
|
@goal_column = nil # Zero-based display width count
|
216
|
-
@yank_start = new_mark
|
217
223
|
@undo_stack = []
|
218
224
|
@redo_stack = []
|
219
225
|
@undoing = false
|
226
|
+
@composite_edit_level = 0
|
227
|
+
@composite_edit_actions = []
|
220
228
|
@version = 0
|
221
229
|
@modified = false
|
222
230
|
@mode = FundamentalMode.new(self)
|
@@ -283,12 +291,24 @@ module Textbringer
|
|
283
291
|
end
|
284
292
|
end
|
285
293
|
|
294
|
+
def read_only_edit
|
295
|
+
self.read_only = false
|
296
|
+
begin
|
297
|
+
yield
|
298
|
+
ensure
|
299
|
+
self.read_only = true
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
286
303
|
def kill
|
287
304
|
@@table.delete(@name)
|
288
305
|
@@list.delete(self)
|
289
306
|
if @@current == self
|
290
307
|
@@current = nil
|
291
308
|
end
|
309
|
+
@marks.each do |mark|
|
310
|
+
mark.detach
|
311
|
+
end
|
292
312
|
end
|
293
313
|
|
294
314
|
def current?
|
@@ -767,8 +787,63 @@ module Textbringer
|
|
767
787
|
end
|
768
788
|
|
769
789
|
def set_mark(pos = @point)
|
770
|
-
@mark
|
790
|
+
if @mark
|
791
|
+
@mark.location = pos
|
792
|
+
else
|
793
|
+
push_mark(pos)
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
797
|
+
# Set mark at pos, and push the mark on the mark ring.
|
798
|
+
# Unlike Emacs, the new mark is pushed on the mark ring instead of
|
799
|
+
# the old one.
|
800
|
+
def push_mark(pos = @point)
|
801
|
+
@mark = new_mark
|
771
802
|
@mark.location = pos
|
803
|
+
@mark_ring.push(@mark)
|
804
|
+
if self != Buffer.minibuffer
|
805
|
+
global_mark_ring = Buffer.global_mark_ring
|
806
|
+
if global_mark_ring.empty? || global_mark_ring.current.buffer != self
|
807
|
+
push_global_mark(pos)
|
808
|
+
end
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
def on_global_mark_ring?
|
813
|
+
mark_ring = Buffer.global_mark_ring
|
814
|
+
if mark_ring.empty?
|
815
|
+
return false
|
816
|
+
end
|
817
|
+
current = mark_ring.current
|
818
|
+
if current&.buffer == self
|
819
|
+
return true
|
820
|
+
end
|
821
|
+
next_mark = mark_ring[-1]
|
822
|
+
if next_mark&.buffer == self
|
823
|
+
return true
|
824
|
+
end
|
825
|
+
false
|
826
|
+
end
|
827
|
+
|
828
|
+
def push_global_mark(pos = @point, force: false)
|
829
|
+
if force || !on_global_mark_ring?
|
830
|
+
mark = new_mark
|
831
|
+
mark.location = pos
|
832
|
+
Buffer.global_mark_ring.push(mark)
|
833
|
+
true
|
834
|
+
else
|
835
|
+
false
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
def pop_mark
|
840
|
+
return if @mark_ring.empty?
|
841
|
+
@mark = @mark_ring.rotate(1)
|
842
|
+
end
|
843
|
+
|
844
|
+
def pop_to_mark
|
845
|
+
goto_char(mark)
|
846
|
+
pop_mark
|
772
847
|
end
|
773
848
|
|
774
849
|
def set_visible_mark(pos = @point)
|
@@ -783,8 +858,17 @@ module Textbringer
|
|
783
858
|
end
|
784
859
|
end
|
785
860
|
|
861
|
+
def self.region_boundaries(s, e)
|
862
|
+
if s > e
|
863
|
+
[e, s]
|
864
|
+
else
|
865
|
+
[s, e]
|
866
|
+
end
|
867
|
+
end
|
868
|
+
|
786
869
|
def copy_region(s = @point, e = mark, append = false)
|
787
|
-
|
870
|
+
s, e = Buffer.region_boundaries(s, e)
|
871
|
+
str = substring(s, e)
|
788
872
|
if append && !KILL_RING.empty?
|
789
873
|
KILL_RING.current.concat(str)
|
790
874
|
else
|
@@ -800,9 +884,7 @@ module Textbringer
|
|
800
884
|
def delete_region(s = @point, e = mark)
|
801
885
|
check_read_only_flag
|
802
886
|
old_pos = @point
|
803
|
-
|
804
|
-
s, e = e, s
|
805
|
-
end
|
887
|
+
s, e = Buffer.region_boundaries(s, e)
|
806
888
|
update_line_and_column(old_pos, s)
|
807
889
|
save_point do
|
808
890
|
str = substring(s, e)
|
@@ -868,7 +950,9 @@ module Textbringer
|
|
868
950
|
end
|
869
951
|
|
870
952
|
def insert_for_yank(s)
|
871
|
-
|
953
|
+
if @mark.nil? || !point_at_mark?(@mark)
|
954
|
+
push_mark
|
955
|
+
end
|
872
956
|
insert(s)
|
873
957
|
end
|
874
958
|
|
@@ -877,8 +961,8 @@ module Textbringer
|
|
877
961
|
end
|
878
962
|
|
879
963
|
def yank_pop
|
880
|
-
delete_region
|
881
|
-
insert_for_yank(KILL_RING.
|
964
|
+
delete_region
|
965
|
+
insert_for_yank(KILL_RING.rotate(1))
|
882
966
|
end
|
883
967
|
|
884
968
|
def undo
|
@@ -963,7 +1047,7 @@ module Textbringer
|
|
963
1047
|
|
964
1048
|
def looking_at?(re)
|
965
1049
|
if re.is_a?(Regexp)
|
966
|
-
r =
|
1050
|
+
r = /\G#{re}/
|
967
1051
|
else
|
968
1052
|
r = "\\G(?:#{re})"
|
969
1053
|
end
|
@@ -1049,19 +1133,21 @@ module Textbringer
|
|
1049
1133
|
b = match_beginning(0)
|
1050
1134
|
e = match_end(0)
|
1051
1135
|
goto_char(b)
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1136
|
+
composite_edit do
|
1137
|
+
delete_region(b, e)
|
1138
|
+
insert(new_str)
|
1139
|
+
end
|
1055
1140
|
end
|
1056
1141
|
|
1057
1142
|
def replace_regexp_forward(regexp, to_str)
|
1058
1143
|
result = 0
|
1059
1144
|
rest = substring(point, point_max)
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1145
|
+
composite_edit do
|
1146
|
+
delete_region(point, point_max)
|
1147
|
+
new_str = rest.gsub(new_regexp(regexp)) {
|
1148
|
+
result += 1
|
1149
|
+
m = Regexp.last_match
|
1150
|
+
to_str.gsub(/\\(?:([0-9]+)|(&)|(\\))/) { |s|
|
1065
1151
|
case
|
1066
1152
|
when $1
|
1067
1153
|
m[$1.to_i]
|
@@ -1070,10 +1156,10 @@ module Textbringer
|
|
1070
1156
|
when $3
|
1071
1157
|
"\\"
|
1072
1158
|
end
|
1159
|
+
}
|
1073
1160
|
}
|
1074
|
-
|
1075
|
-
|
1076
|
-
merge_undo(2)
|
1161
|
+
insert(new_str)
|
1162
|
+
end
|
1077
1163
|
result
|
1078
1164
|
end
|
1079
1165
|
|
@@ -1095,16 +1181,22 @@ module Textbringer
|
|
1095
1181
|
/\A\0*\z/ =~ @contents[@gap_start...@gap_end] ? true : false
|
1096
1182
|
end
|
1097
1183
|
|
1098
|
-
def
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1184
|
+
def composite_edit
|
1185
|
+
@composite_edit_level += 1
|
1186
|
+
begin
|
1187
|
+
yield
|
1188
|
+
ensure
|
1189
|
+
@composite_edit_level -= 1
|
1190
|
+
if @composite_edit_level == 0 && !@composite_edit_actions.empty?
|
1191
|
+
action = CompositeAction.new(self,
|
1192
|
+
@composite_edit_actions.first.location)
|
1193
|
+
@composite_edit_actions.each do |i|
|
1194
|
+
action.add_action(i)
|
1195
|
+
end
|
1196
|
+
action.version = @composite_edit_actions.first.version
|
1197
|
+
push_undo(action)
|
1198
|
+
@composite_edit_actions.clear
|
1105
1199
|
end
|
1106
|
-
action.version = actions.first.version
|
1107
|
-
@undo_stack.push(action)
|
1108
1200
|
end
|
1109
1201
|
end
|
1110
1202
|
|
@@ -1189,9 +1281,10 @@ module Textbringer
|
|
1189
1281
|
|
1190
1282
|
def gsub(*args, &block)
|
1191
1283
|
s = to_s.gsub(*args, &block)
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1284
|
+
composite_edit do
|
1285
|
+
delete_region(point_min, point_max)
|
1286
|
+
insert(s)
|
1287
|
+
end
|
1195
1288
|
self
|
1196
1289
|
end
|
1197
1290
|
|
@@ -1343,14 +1436,18 @@ module Textbringer
|
|
1343
1436
|
|
1344
1437
|
def push_undo(action)
|
1345
1438
|
return if @undoing || @undo_limit == 0
|
1346
|
-
if @
|
1347
|
-
@
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1439
|
+
if @composite_edit_level > 0
|
1440
|
+
@composite_edit_actions.push(action)
|
1441
|
+
else
|
1442
|
+
if @undo_stack.size >= @undo_limit
|
1443
|
+
@undo_stack[0, @undo_stack.size + 1 - @undo_limit] = []
|
1444
|
+
end
|
1445
|
+
if !modified?
|
1446
|
+
action.version = @version
|
1447
|
+
end
|
1448
|
+
@undo_stack.push(action)
|
1449
|
+
@redo_stack.clear
|
1351
1450
|
end
|
1352
|
-
@undo_stack.push(action)
|
1353
|
-
@redo_stack.clear
|
1354
1451
|
end
|
1355
1452
|
|
1356
1453
|
def new_regexp(s)
|
@@ -1369,70 +1466,48 @@ module Textbringer
|
|
1369
1466
|
end
|
1370
1467
|
|
1371
1468
|
class Mark
|
1372
|
-
attr_reader :buffer
|
1469
|
+
attr_reader :buffer, :file_name
|
1373
1470
|
attr_accessor :location
|
1374
1471
|
|
1375
1472
|
def initialize(buffer, location)
|
1376
1473
|
@buffer = buffer
|
1474
|
+
@file_name = nil
|
1377
1475
|
@location = location
|
1378
1476
|
end
|
1379
1477
|
|
1380
|
-
def
|
1381
|
-
@buffer
|
1382
|
-
end
|
1383
|
-
|
1384
|
-
def dup
|
1385
|
-
mark = @buffer.new_mark
|
1386
|
-
mark.location = @location
|
1387
|
-
mark
|
1388
|
-
end
|
1389
|
-
end
|
1390
|
-
|
1391
|
-
class KillRing
|
1392
|
-
def initialize(max = 30)
|
1393
|
-
@max = max
|
1394
|
-
@ring = []
|
1395
|
-
@current = -1
|
1478
|
+
def inspect
|
1479
|
+
"#<Mark:#{@buffer&.name || @file_name}:#{@location}>"
|
1396
1480
|
end
|
1397
1481
|
|
1398
|
-
def
|
1399
|
-
@
|
1400
|
-
|
1482
|
+
def delete
|
1483
|
+
if @buffer
|
1484
|
+
@buffer.marks.delete(self)
|
1485
|
+
end
|
1401
1486
|
end
|
1402
1487
|
|
1403
|
-
def
|
1404
|
-
|
1405
|
-
if @ring.size < @max
|
1406
|
-
@ring.insert(@current, str)
|
1407
|
-
else
|
1408
|
-
if @current == @max
|
1409
|
-
@current = 0
|
1410
|
-
end
|
1411
|
-
@ring[@current] = str
|
1412
|
-
end
|
1488
|
+
def deleted?
|
1489
|
+
!@buffer.marks.include?(self)
|
1413
1490
|
end
|
1414
1491
|
|
1415
|
-
def
|
1416
|
-
if @
|
1417
|
-
|
1418
|
-
|
1419
|
-
@current -= n
|
1420
|
-
if @current < 0
|
1421
|
-
@current += @ring.size
|
1492
|
+
def detach
|
1493
|
+
if @buffer
|
1494
|
+
@file_name = @buffer.file_name
|
1495
|
+
@buffer = nil
|
1422
1496
|
end
|
1423
|
-
@ring[@current]
|
1424
1497
|
end
|
1425
1498
|
|
1426
|
-
def
|
1427
|
-
@
|
1499
|
+
def detached?
|
1500
|
+
@buffer.nil?
|
1428
1501
|
end
|
1429
1502
|
|
1430
|
-
def
|
1431
|
-
@
|
1503
|
+
def dup
|
1504
|
+
mark = @buffer.new_mark
|
1505
|
+
mark.location = @location
|
1506
|
+
mark
|
1432
1507
|
end
|
1433
1508
|
end
|
1434
1509
|
|
1435
|
-
KILL_RING =
|
1510
|
+
KILL_RING = Ring.new
|
1436
1511
|
|
1437
1512
|
class UndoableAction
|
1438
1513
|
attr_accessor :version
|