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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a4d3643869a923b01642fd4faecfdf36a530822193049c6d05458bd62afeb94
4
- data.tar.gz: 5e04d0bcfbfc5e20143ca5fe06669001f563eede4ae75c52b6200101dcc4be7d
3
+ metadata.gz: 04d0f8e23504a6d3ae1ce1ccc4cf1ca4c8308525cd61356d22e50631474408bc
4
+ data.tar.gz: a16eefeef6df621bf2272a4437b1321c999b7ffd3f0cf7f1353d0a41baabd7b6
5
5
  SHA512:
6
- metadata.gz: 4001fb9d0e71fce380ab475782730bac8ca3a4bf663dd70b1d86d9292b83c3228ecf63632d7359b80408e248c1a413131a30fbc3ff2a3d47cece701bffb3bfb0
7
- data.tar.gz: 02cd15438c13cdb52bd5e6f34199aa12f8840349f71ad33b6e61fdeefad543a41b9d9167ce02439bda78605dce6d290e1c95f27563c8647094547d4ef8a20704
6
+ metadata.gz: f03f8d34e41b099d3b9dcaecbb1fa40b3e9c9f3c43a7aba7917dcfe8a7cccbd1dec97599c46e657839af70d8abf67681f339d5ba97f6abb308e76fe1ffbd93f0
7
+ data.tar.gz: 643f15490cc3ce708c8b6aced38b1249b7c4074a6a5fcb9c7fd927ee1493778fdefd9c9f393a968630e89a85823e13deb036c481691651b02580b2bc150a1a14
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -24,7 +24,7 @@ jobs:
24
24
  steps:
25
25
  # Set up
26
26
  - name: Harden Runner
27
- uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
27
+ uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2
28
28
  with:
29
29
  egress-policy: audit
30
30
 
@@ -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
- options = { UNIXFileMode: 0600 }.merge(CONFIG[:server_options] || {})
10
- DRb.start_service(uri, Server.new, options)
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
@@ -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)
@@ -1,3 +1,3 @@
1
1
  module Textbringer
2
- VERSION = "11"
2
+ VERSION = "12"
3
3
  end
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: '11'
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"