textbringer 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2244343a4baaddd8efff307da619579a102c66d61c14f5dcebdba589b7f809ba
4
- data.tar.gz: 0e59492b0f35673c3d0658d7c96c55288734017ace2edb1c58fddcdf22ca9976
3
+ metadata.gz: 670221472ba70164a2f44759e11011d8e70a5f467e067e4e400d732fe4082323
4
+ data.tar.gz: 26d15a0030cc1217f131ba761309b3d9bb17078fa5cfd1db24c651bdd5384fb1
5
5
  SHA512:
6
- metadata.gz: 680ea08b6a0c55e0a514f8da5708cbbcde48efe50747b9f7fdf96ec39264619abfbfbab32a7ca03577885e8691c2d221e563d2fcd98c8bc3dd4e3cd9b647ac10
7
- data.tar.gz: bac76f72017761cb3c46ff83a0d3f0dee86e811940dc97bd79c6665231f621989c262be1c17ca70d75eb5f1885fd55190062240e5b6d886c29894172a2c3c39c
6
+ metadata.gz: 000e800e06a430312b133dce7017c560723a473866cbb2c82754ac6af1da6f398be2cdf17b9708f20109784b698b70bb073c744afa4d7f7cc0e086b51db17ffc
7
+ data.tar.gz: ccb23431483eabe736e285d9ee72a17f7cb4f72be07fd049ec091f727a5671cd396e30504cd725d0938614a0fd58a56b8c5547a9e4d1275fd8faf8b654c6b25d
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.0.0
2
+
3
+ * Add mark_whole_buffer.
4
+ * Add zap_to_char.
5
+ * Exit on SIGTERM, SIGHUP etc.
6
+
1
7
  ## 0.3.2
2
8
 
3
9
  * Drop Ruby 2.3 support.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Textbringer
1
+ # ![Textbringer](logo/logo.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/textbringer.svg)](https://badge.fury.io/rb/textbringer)
4
4
  [![Build Status](https://travis-ci.org/shugo/textbringer.svg?branch=master)](https://travis-ci.org/shugo/textbringer)
@@ -18,14 +18,6 @@ text editor.
18
18
  * Ruby Programming: https://asciinema.org/a/100156
19
19
  * Japanese Text Editing: https://asciinema.org/a/100166
20
20
 
21
- ## WARNING
22
-
23
- Textbringer is beta software, and you may lose your text. Unsaved buffers will
24
- be dumped in ~/.textbringer/buffer_dump on crash.
25
-
26
- APIs are undocumented and unstable. There is no compatibility even in the same
27
- minor versions.
28
-
29
21
  ## Installation
30
22
 
31
23
  $ gem install textbringer
@@ -115,3 +107,8 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/shugo/
115
107
  ## License
116
108
 
117
109
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
110
+
111
+
112
+ ## Credit
113
+
114
+ Logo made with [DesignEvo](https://www.designevo.com/en/).
@@ -15,6 +15,11 @@ end
15
15
 
16
16
  $VERBOSE = nil
17
17
 
18
+ unless STDIN.tty?
19
+ STDERR.puts("textbringer: standard input is not a tty")
20
+ exit 1
21
+ end
22
+
18
23
  Controller.current = Controller.new
19
24
  begin
20
25
  Window.start do
@@ -205,7 +205,7 @@ module Textbringer
205
205
  end
206
206
 
207
207
  # s might not be copied.
208
- def initialize(s = String.new, name: nil,
208
+ def initialize(s = +"", name: nil,
209
209
  file_name: nil,
210
210
  file_encoding: CONFIG[:default_file_encoding],
211
211
  file_mtime: nil, new_file: true, undo_limit: UNDO_LIMIT,
@@ -964,7 +964,7 @@ module Textbringer
964
964
 
965
965
  def clear
966
966
  check_read_only_flag
967
- @contents = String.new
967
+ @contents = +""
968
968
  @point = @gap_start = @gap_end = 0
969
969
  @marks.each do |m|
970
970
  m.location = 0
@@ -1065,40 +1065,54 @@ module Textbringer
1065
1065
  end
1066
1066
  end
1067
1067
 
1068
- def re_search_forward(s, raise_error: true)
1068
+ def re_search_forward(s, raise_error: true, count: 1)
1069
+ if count < 0
1070
+ return re_search_backward(s, raise_error: raise_error, count: -count)
1071
+ end
1069
1072
  re = new_regexp(s)
1070
- i = byteindex(true, re, @point)
1071
- if i.nil?
1072
- if raise_error
1073
- raise SearchError, "Search failed"
1074
- else
1075
- return nil
1073
+ pos = @point
1074
+ count.times do
1075
+ i = byteindex(true, re, pos)
1076
+ if i.nil?
1077
+ if raise_error
1078
+ raise SearchError, "Search failed"
1079
+ else
1080
+ return nil
1081
+ end
1076
1082
  end
1083
+ pos = match_end(0)
1077
1084
  end
1078
- goto_char(match_end(0))
1085
+ goto_char(pos)
1079
1086
  end
1080
1087
 
1081
- def re_search_backward(s, raise_error: true)
1088
+ def re_search_backward(s, raise_error: true, count: 1)
1089
+ if count < 0
1090
+ return re_search_forward(s, raise_error: raise_error, count: -count)
1091
+ end
1082
1092
  re = new_regexp(s)
1083
1093
  pos = @point
1084
- begin
1085
- i = byteindex(false, re, pos)
1086
- if i.nil?
1094
+ count.times do
1095
+ p = pos
1096
+ begin
1097
+ i = byteindex(false, re, p)
1098
+ if i.nil?
1099
+ if raise_error
1100
+ raise SearchError, "Search failed"
1101
+ else
1102
+ return nil
1103
+ end
1104
+ end
1105
+ p = get_pos(p, -1)
1106
+ rescue RangeError
1087
1107
  if raise_error
1088
1108
  raise SearchError, "Search failed"
1089
1109
  else
1090
1110
  return nil
1091
1111
  end
1092
- end
1093
- pos = get_pos(pos, -1)
1094
- rescue RangeError
1095
- if raise_error
1096
- raise SearchError, "Search failed"
1097
- else
1098
- return nil
1099
- end
1100
- end while match_end(0) > @point
1101
- goto_char(match_beginning(0))
1112
+ end while match_end(0) > pos
1113
+ pos = match_beginning(0)
1114
+ end
1115
+ goto_char(pos)
1102
1116
  end
1103
1117
 
1104
1118
  def looking_at?(re)
@@ -1233,7 +1247,7 @@ module Textbringer
1233
1247
  end
1234
1248
 
1235
1249
  def gap_filled_with_nul?
1236
- /\A\0*\z/ =~ @contents[@gap_start...@gap_end] ? true : false
1250
+ /\A\0*\z/.match?(@contents[@gap_start...@gap_end])
1237
1251
  end
1238
1252
 
1239
1253
  def composite_edit
@@ -1338,7 +1352,7 @@ module Textbringer
1338
1352
  def gsub(*args, &block)
1339
1353
  if block
1340
1354
  s = to_s.gsub(*args) { |*params|
1341
- set_block_backref(block, $~)
1355
+ block.binding.eval('->(backref) { $~ = backref }').call($~)
1342
1356
  block.call(*params)
1343
1357
  }
1344
1358
  else
@@ -1576,17 +1590,6 @@ module Textbringer
1576
1590
  callback.call(self)
1577
1591
  end
1578
1592
  end
1579
-
1580
- def set_block_backref(block, backref)
1581
- Thread.current[:__textbringer_backref] = backref
1582
- begin
1583
- block.binding.eval(<<-EOC)
1584
- $~ = Thread.current[:__textbringer_backref]
1585
- EOC
1586
- ensure
1587
- Thread.current[:__textbringer_backref] = nil
1588
- end
1589
- end
1590
1593
  end
1591
1594
 
1592
1595
  class Mark
@@ -244,5 +244,27 @@ module Textbringer
244
244
  buffer.insert(" ")
245
245
  buffer.backward_char
246
246
  end
247
+
248
+ define_command(:mark_whole_buffer,
249
+ doc: <<~EOD) do
250
+ Put point at beginning and mark at end of buffer.
251
+ EOD
252
+ buffer = Buffer.current
253
+ buffer.push_mark
254
+ buffer.push_mark(buffer.point_max)
255
+ buffer.beginning_of_buffer
256
+ end
257
+
258
+ define_command(:zap_to_char,
259
+ doc: <<~EOD) do
260
+ Kill up to and including count-th occurrence of char.
261
+ EOD
262
+ |char = read_char, count: number_prefix_arg|
263
+
264
+ buffer = Buffer.current
265
+ s = buffer.point
266
+ e = buffer.re_search_forward(Regexp.quote(char), count: count)
267
+ buffer.kill_region(s, e)
268
+ end
247
269
  end
248
270
  end
@@ -38,7 +38,7 @@ module Textbringer
38
38
 
39
39
  def fill_string(str, column)
40
40
  input = StringIO.new(str)
41
- output = String.new
41
+ output = +""
42
42
  fill_column = CONFIG[:fill_column]
43
43
  prev_c = nil
44
44
  while c = input.getc
@@ -43,7 +43,7 @@ module Textbringer
43
43
 
44
44
  def isearch_mode(forward, recursive_edit: false)
45
45
  ISEARCH_STATUS[:forward] = forward
46
- ISEARCH_STATUS[:string] = String.new
46
+ ISEARCH_STATUS[:string] = +""
47
47
  ISEARCH_STATUS[:recursive_edit] = recursive_edit
48
48
  Controller.current.overriding_map = ISEARCH_MODE_MAP
49
49
  run_hooks(:isearch_mode_hook)
@@ -282,31 +282,35 @@ module Textbringer
282
282
  if CONFIG[:shell_file_name]
283
283
  cmd = [CONFIG[:shell_file_name], CONFIG[:shell_command_switch], cmd]
284
284
  end
285
- Open3.popen2e(*cmd, opts) do |input, output, wait_thread|
285
+ Open3.popen3(*cmd, opts) do |input, output, error, wait_thread|
286
286
  input.close
287
- loop do
288
- status = output.wait_readable(0.5)
289
- if status
290
- begin
291
- s = output.read_nonblock(1024).force_encoding("utf-8").
292
- scrub("\u{3013}").gsub(/\r\n/, "\n")
293
- buffer.insert(s)
294
- Window.redisplay
295
- rescue EOFError
296
- break
297
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
298
- next
287
+ catch(:finish) do
288
+ loop do
289
+ rs, = IO.select([output, error], nil, nil, 0.5)
290
+ Window.redisplay
291
+ rs&.each do |r|
292
+ begin
293
+ s = r.read_nonblock(1024).force_encoding("utf-8").
294
+ scrub("\u{3013}").gsub(/\r\n/, "\n")
295
+ buffer.insert(s)
296
+ Window.redisplay
297
+ rescue EOFError
298
+ throw(:finish)
299
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
300
+ Window.redisplay
301
+ next
302
+ end
299
303
  end
300
- end
301
- if received_keyboard_quit?
302
- if signals.empty?
303
- keyboard_quit
304
- else
305
- sig = signals.shift
306
- pid = wait_thread.pid
307
- pid = -pid if /mswin32|mingw32/ !~ RUBY_PLATFORM
308
- message("Send #{sig} to #{pid}")
309
- Process.kill(sig, pid)
304
+ if received_keyboard_quit?
305
+ if signals.empty?
306
+ keyboard_quit
307
+ else
308
+ sig = signals.shift
309
+ pid = wait_thread.pid
310
+ pid = -pid if /mswin32|mingw32/ !~ RUBY_PLATFORM
311
+ message("Send #{sig} to #{pid}")
312
+ Process.kill(sig, pid)
313
+ end
310
314
  end
311
315
  end
312
316
  end
@@ -128,7 +128,7 @@ module Textbringer
128
128
  else
129
129
  wait_files = [STDIN, @next_tick_input]
130
130
  end
131
- files, = IO.select(wait_files, [], [], 1)
131
+ files, = IO.select(wait_files, nil, nil, 1)
132
132
  # KEY_RESIZE may be returned even if STDIN is not included in files.
133
133
  event = read_event_nonblock
134
134
  if event
@@ -178,7 +178,7 @@ module Textbringer
178
178
  return if wait_input(1000)
179
179
  end
180
180
  @echo_immediately = true
181
- s = String.new
181
+ s = +""
182
182
  if @prefix_arg
183
183
  s << "C-u"
184
184
  if @prefix_arg != [4]
@@ -144,6 +144,8 @@ module Textbringer
144
144
  GLOBAL_MAP.define_key("\C-o", :open_line)
145
145
  GLOBAL_MAP.define_key("\em", :back_to_indentation)
146
146
  GLOBAL_MAP.define_key("\e^", :delete_indentation)
147
+ GLOBAL_MAP.define_key("\C-xh", :mark_whole_buffer)
148
+ GLOBAL_MAP.define_key("\ez", :zap_to_char)
147
149
  GLOBAL_MAP.define_key("\C-l", :recenter)
148
150
  GLOBAL_MAP.define_key("\C-v", :scroll_up)
149
151
  GLOBAL_MAP.define_key(:npage, :scroll_up)
@@ -104,7 +104,7 @@ module Textbringer
104
104
  end
105
105
 
106
106
  def show_exception(e)
107
- if e.is_a?(SystemExit)
107
+ if e.is_a?(SystemExit) || e.is_a?(SignalException)
108
108
  raise
109
109
  end
110
110
  if Buffer.current&.name != "*Backtrace*"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Textbringer
4
- VERSION = "0.3.2"
4
+ VERSION = "1.0.0"
5
5
  end
Binary file
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: textbringer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-08 00:00:00.000000000 Z
11
+ date: 2019-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -227,6 +227,8 @@ files:
227
227
  - lib/textbringer/utils.rb
228
228
  - lib/textbringer/version.rb
229
229
  - lib/textbringer/window.rb
230
+ - logo/logo.jpg
231
+ - logo/logo.png
230
232
  - screenshot.png
231
233
  - textbringer.gemspec
232
234
  homepage: https://github.com/shugo/textbringer
@@ -248,8 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
248
250
  - !ruby/object:Gem::Version
249
251
  version: '0'
250
252
  requirements: []
251
- rubyforge_project:
252
- rubygems_version: 3.0.0.beta3
253
+ rubygems_version: 3.1.0.pre1
253
254
  signing_key:
254
255
  specification_version: 4
255
256
  summary: An Emacs-like text editor