textbringer 11 → 12
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/.github/dependabot.yml +6 -0
- data/.github/workflows/push_gem.yml +1 -1
- data/lib/textbringer/buffer.rb +180 -0
- data/lib/textbringer/commands/buffers.rb +25 -0
- data/lib/textbringer/commands/server.rb +52 -2
- data/lib/textbringer/keymap.rb +5 -0
- data/lib/textbringer/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04d0f8e23504a6d3ae1ce1ccc4cf1ca4c8308525cd61356d22e50631474408bc
|
4
|
+
data.tar.gz: a16eefeef6df621bf2272a4437b1321c999b7ffd3f0cf7f1353d0a41baabd7b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f03f8d34e41b099d3b9dcaecbb1fa40b3e9c9f3c43a7aba7917dcfe8a7cccbd1dec97599c46e657839af70d8abf67681f339d5ba97f6abb308e76fe1ffbd93f0
|
7
|
+
data.tar.gz: 643f15490cc3ce708c8b6aced38b1249b7c4074a6a5fcb9c7fd927ee1493778fdefd9c9f393a968630e89a85823e13deb036c481691651b02580b2bc150a1a14
|
@@ -24,7 +24,7 @@ jobs:
|
|
24
24
|
steps:
|
25
25
|
# Set up
|
26
26
|
- name: Harden Runner
|
27
|
-
uses: step-security/harden-runner@
|
27
|
+
uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
|
28
28
|
with:
|
29
29
|
egress-policy: audit
|
30
30
|
|
data/lib/textbringer/buffer.rb
CHANGED
@@ -1089,6 +1089,185 @@ module Textbringer
|
|
1089
1089
|
insert_for_yank(KILL_RING.rotate(1))
|
1090
1090
|
end
|
1091
1091
|
|
1092
|
+
def rectangle_boundaries(s = @point, e = mark)
|
1093
|
+
s, e = Buffer.region_boundaries(s, e)
|
1094
|
+
save_excursion do
|
1095
|
+
goto_char(s)
|
1096
|
+
start_line = @current_line
|
1097
|
+
beginning_of_line
|
1098
|
+
start_col = display_width(substring(@point, s)) + 1
|
1099
|
+
goto_char(e)
|
1100
|
+
end_line = @current_line
|
1101
|
+
beginning_of_line
|
1102
|
+
end_col = display_width(substring(@point, e)) + 1
|
1103
|
+
|
1104
|
+
# Ensure start_col <= end_col
|
1105
|
+
if start_col > end_col
|
1106
|
+
start_col, end_col = end_col, start_col
|
1107
|
+
end
|
1108
|
+
[start_line, start_col, end_line, end_col]
|
1109
|
+
end
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def extract_rectangle(s = @point, e = mark)
|
1113
|
+
start_line, start_col, end_line, end_col = rectangle_boundaries(s, e)
|
1114
|
+
lines = []
|
1115
|
+
rectangle_width = end_col - start_col
|
1116
|
+
|
1117
|
+
save_excursion do
|
1118
|
+
goto_line(start_line)
|
1119
|
+
(start_line..end_line).each do |line_num|
|
1120
|
+
beginning_of_line
|
1121
|
+
line_start = @point
|
1122
|
+
|
1123
|
+
# Move to start column
|
1124
|
+
col = 1
|
1125
|
+
while col < start_col && !end_of_line?
|
1126
|
+
forward_char
|
1127
|
+
col = 1 + display_width(substring(line_start, @point))
|
1128
|
+
end
|
1129
|
+
start_pos = @point
|
1130
|
+
|
1131
|
+
# If we haven't reached start_col, the line is too short
|
1132
|
+
if col < start_col
|
1133
|
+
# Line is shorter than start column, extract all spaces
|
1134
|
+
lines << " " * rectangle_width
|
1135
|
+
else
|
1136
|
+
# Move to end column
|
1137
|
+
while col < end_col && !end_of_line?
|
1138
|
+
forward_char
|
1139
|
+
col = 1 + display_width(substring(line_start, @point))
|
1140
|
+
end
|
1141
|
+
end_pos = @point
|
1142
|
+
|
1143
|
+
# Extract the rectangle text for this line
|
1144
|
+
if end_pos > start_pos
|
1145
|
+
extracted = substring(start_pos, end_pos)
|
1146
|
+
# Pad with spaces if the extracted text is shorter than rectangle width
|
1147
|
+
extracted_width = display_width(extracted)
|
1148
|
+
if extracted_width < rectangle_width
|
1149
|
+
extracted += " " * (rectangle_width - extracted_width)
|
1150
|
+
end
|
1151
|
+
lines << extracted
|
1152
|
+
else
|
1153
|
+
lines << " " * rectangle_width
|
1154
|
+
end
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
# Move to next line
|
1158
|
+
break if line_num == end_line
|
1159
|
+
forward_line
|
1160
|
+
end
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
lines
|
1164
|
+
end
|
1165
|
+
|
1166
|
+
def copy_rectangle(s = @point, e = mark)
|
1167
|
+
lines = extract_rectangle(s, e)
|
1168
|
+
@@killed_rectangle = lines
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
def kill_rectangle(s = @point, e = mark)
|
1172
|
+
copy_rectangle(s, e)
|
1173
|
+
delete_rectangle(s, e)
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
def delete_rectangle(s = @point, e = mark)
|
1177
|
+
check_read_only_flag
|
1178
|
+
start_line, start_col, end_line, end_col = rectangle_boundaries(s, e)
|
1179
|
+
|
1180
|
+
save_excursion do
|
1181
|
+
# Delete from bottom to top to avoid position shifts
|
1182
|
+
(start_line..end_line).reverse_each do |line_num|
|
1183
|
+
goto_line(line_num)
|
1184
|
+
beginning_of_line
|
1185
|
+
line_start = @point
|
1186
|
+
|
1187
|
+
# Move to start column
|
1188
|
+
col = 1
|
1189
|
+
while col < start_col && !end_of_line?
|
1190
|
+
forward_char
|
1191
|
+
col = 1 + display_width(substring(line_start, @point))
|
1192
|
+
end
|
1193
|
+
start_pos = @point
|
1194
|
+
|
1195
|
+
# Only delete if we're within the line bounds
|
1196
|
+
if col >= start_col
|
1197
|
+
# Move to end column
|
1198
|
+
while col < end_col && !end_of_line?
|
1199
|
+
forward_char
|
1200
|
+
col = 1 + display_width(substring(line_start, @point))
|
1201
|
+
end
|
1202
|
+
end_pos = @point
|
1203
|
+
|
1204
|
+
# Delete the rectangle text for this line
|
1205
|
+
if end_pos > start_pos
|
1206
|
+
delete_region(start_pos, end_pos)
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
end
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
def yank_rectangle
|
1214
|
+
raise "No rectangle in kill ring" if @@killed_rectangle.nil?
|
1215
|
+
lines = @@killed_rectangle
|
1216
|
+
start_line, start_col = get_line_and_column(@point)
|
1217
|
+
|
1218
|
+
save_excursion do
|
1219
|
+
lines.each_with_index do |line, i|
|
1220
|
+
goto_line(start_line + i)
|
1221
|
+
beginning_of_line
|
1222
|
+
line_start = @point
|
1223
|
+
|
1224
|
+
# Move to start column, extending line if necessary
|
1225
|
+
col = 1
|
1226
|
+
while col < start_col && !end_of_line?
|
1227
|
+
forward_char
|
1228
|
+
col = 1 + display_width(substring(line_start, @point))
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
# If line is shorter than start_col, extend it with spaces
|
1232
|
+
if col < start_col
|
1233
|
+
insert(" " * (start_col - col))
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
# Insert the rectangle line
|
1237
|
+
insert(line)
|
1238
|
+
end
|
1239
|
+
end
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
def open_rectangle(s = @point, e = mark)
|
1243
|
+
check_read_only_flag
|
1244
|
+
start_line, start_col, end_line, end_col = rectangle_boundaries(s, e)
|
1245
|
+
width = end_col - start_col
|
1246
|
+
|
1247
|
+
save_excursion do
|
1248
|
+
(start_line..end_line).each do |line_num|
|
1249
|
+
goto_line(line_num)
|
1250
|
+
beginning_of_line
|
1251
|
+
line_start = @point
|
1252
|
+
|
1253
|
+
# Move to start column, extending line if necessary
|
1254
|
+
col = 1
|
1255
|
+
while col < start_col && !end_of_line?
|
1256
|
+
forward_char
|
1257
|
+
col = 1 + display_width(substring(line_start, @point))
|
1258
|
+
end
|
1259
|
+
|
1260
|
+
# If line is shorter than start_col, extend it with spaces
|
1261
|
+
if col < start_col
|
1262
|
+
insert(" " * (start_col - col))
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
# Insert spaces to create the rectangle
|
1266
|
+
insert(" " * width)
|
1267
|
+
end
|
1268
|
+
end
|
1269
|
+
end
|
1270
|
+
|
1092
1271
|
def undo
|
1093
1272
|
undo_or_redo(:undo, @undo_stack, @redo_stack)
|
1094
1273
|
end
|
@@ -1750,6 +1929,7 @@ module Textbringer
|
|
1750
1929
|
end
|
1751
1930
|
|
1752
1931
|
KILL_RING = Ring.new
|
1932
|
+
@@killed_rectangle = nil
|
1753
1933
|
|
1754
1934
|
class UndoableAction
|
1755
1935
|
attr_accessor :version
|
@@ -129,6 +129,31 @@ module Textbringer
|
|
129
129
|
Buffer.current.delete_region
|
130
130
|
end
|
131
131
|
|
132
|
+
define_command(:kill_rectangle,
|
133
|
+
doc: "Kill the text of the region-rectangle, saving its contents as the last killed rectangle.") do
|
134
|
+
Buffer.current.kill_rectangle
|
135
|
+
end
|
136
|
+
|
137
|
+
define_command(:copy_rectangle_as_kill,
|
138
|
+
doc: "Save the text of the region-rectangle as the last killed rectangle.") do
|
139
|
+
Buffer.current.copy_rectangle
|
140
|
+
end
|
141
|
+
|
142
|
+
define_command(:delete_rectangle,
|
143
|
+
doc: "Delete the text of the region-rectangle.") do
|
144
|
+
Buffer.current.delete_rectangle
|
145
|
+
end
|
146
|
+
|
147
|
+
define_command(:yank_rectangle,
|
148
|
+
doc: "Yank the last killed rectangle with its upper left corner at point.") do
|
149
|
+
Buffer.current.yank_rectangle
|
150
|
+
end
|
151
|
+
|
152
|
+
define_command(:open_rectangle,
|
153
|
+
doc: "Insert blank space to fill the space of the region-rectangle. This pushes the previous contents of the region-rectangle to the right.") do
|
154
|
+
Buffer.current.open_rectangle
|
155
|
+
end
|
156
|
+
|
132
157
|
define_command(:transpose_chars,
|
133
158
|
doc: "Transpose characters.") do
|
134
159
|
Buffer.current.transpose_chars
|
@@ -6,8 +6,8 @@ module Textbringer
|
|
6
6
|
doc: "Start Textbringer server.") do
|
7
7
|
uri = CONFIG[:server_uri] ||
|
8
8
|
"drbunix:" + File.expand_path("server.sock", "~/.textbringer")
|
9
|
-
|
10
|
-
|
9
|
+
server = Server.new(uri)
|
10
|
+
server.start
|
11
11
|
end
|
12
12
|
|
13
13
|
define_command(:server_kill,
|
@@ -31,6 +31,56 @@ module Textbringer
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class Server
|
34
|
+
def initialize(uri)
|
35
|
+
@uri = uri
|
36
|
+
end
|
37
|
+
|
38
|
+
def start
|
39
|
+
front = FrontObject.new
|
40
|
+
default_options = unix_domain? ? { UNIXFileMode: 0600 } : {}
|
41
|
+
options = default_options.merge(CONFIG[:server_options] || {})
|
42
|
+
begin
|
43
|
+
DRb.start_service(@uri, front, options)
|
44
|
+
rescue Errno::EADDRINUSE
|
45
|
+
if unix_domain? && !unix_domain_server_alive?
|
46
|
+
# Remove the socket file in case another server died unexpectedly before.
|
47
|
+
File.unlink(unix_domain_socket_path)
|
48
|
+
DRb.start_service(@uri, front, options)
|
49
|
+
else
|
50
|
+
raise ExistError, "There is an existing Textbringer server"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def unix_domain?
|
58
|
+
@uri.start_with?("drbunix:")
|
59
|
+
end
|
60
|
+
|
61
|
+
def unix_domain_socket_path
|
62
|
+
@uri.sub(/\Adrbunix:/, "")
|
63
|
+
end
|
64
|
+
|
65
|
+
def unix_domain_server_alive?
|
66
|
+
socket = Socket.new(:UNIX, :STREAM)
|
67
|
+
sockaddr = Socket.sockaddr_un(unix_domain_socket_path)
|
68
|
+
begin
|
69
|
+
socket.connect_nonblock(sockaddr)
|
70
|
+
rescue Errno::EINPROGRESS
|
71
|
+
return true
|
72
|
+
rescue Errno::ECONNREFUSED
|
73
|
+
return false
|
74
|
+
ensure
|
75
|
+
socket.close
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Server::ExistError < EditorError
|
81
|
+
end
|
82
|
+
|
83
|
+
class Server::FrontObject
|
34
84
|
def eval(s)
|
35
85
|
with_redisplay do
|
36
86
|
Controller.current.instance_eval(s).inspect
|
data/lib/textbringer/keymap.rb
CHANGED
@@ -203,6 +203,11 @@ module Textbringer
|
|
203
203
|
GLOBAL_MAP.define_key("\C-xri", :insert_register)
|
204
204
|
GLOBAL_MAP.define_key("\C-xrn", :number_to_register)
|
205
205
|
GLOBAL_MAP.define_key("\C-xr+", :increment_register)
|
206
|
+
GLOBAL_MAP.define_key("\C-xrk", :kill_rectangle)
|
207
|
+
GLOBAL_MAP.define_key("\C-xr\M-w", :copy_rectangle_as_kill)
|
208
|
+
GLOBAL_MAP.define_key("\C-xrd", :delete_rectangle)
|
209
|
+
GLOBAL_MAP.define_key("\C-xry", :yank_rectangle)
|
210
|
+
GLOBAL_MAP.define_key("\C-xro", :open_rectangle)
|
206
211
|
GLOBAL_MAP.define_key("\C-x(", :start_keyboard_macro)
|
207
212
|
GLOBAL_MAP.define_key(:f3, :start_keyboard_macro)
|
208
213
|
GLOBAL_MAP.define_key("\C-x)", :end_keyboard_macro)
|
data/lib/textbringer/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: textbringer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '
|
4
|
+
version: '12'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
@@ -330,6 +330,7 @@ extra_rdoc_files: []
|
|
330
330
|
files:
|
331
331
|
- ".editorconfig"
|
332
332
|
- ".gitattributes"
|
333
|
+
- ".github/dependabot.yml"
|
333
334
|
- ".github/workflows/macos.yml"
|
334
335
|
- ".github/workflows/push_gem.yml"
|
335
336
|
- ".github/workflows/ubuntu.yml"
|