textbringer 0.3.2 → 1.0.4
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/.gitattributes +1 -0
- data/.github/workflows/macos.yml +15 -0
- data/.github/workflows/ubuntu.yml +25 -0
- data/.github/workflows/windows.yml +19 -0
- data/CHANGES.md +29 -0
- data/README.md +4 -11
- data/exe/textbringer +5 -0
- data/lib/textbringer.rb +0 -2
- data/lib/textbringer/buffer.rb +43 -42
- data/lib/textbringer/color.rb +0 -2
- data/lib/textbringer/commands.rb +0 -2
- data/lib/textbringer/commands/buffers.rb +22 -2
- data/lib/textbringer/commands/clipboard.rb +3 -5
- data/lib/textbringer/commands/ctags.rb +3 -5
- data/lib/textbringer/commands/dabbrev.rb +1 -3
- data/lib/textbringer/commands/files.rb +10 -5
- data/lib/textbringer/commands/fill.rb +2 -2
- data/lib/textbringer/commands/help.rb +25 -18
- data/lib/textbringer/commands/isearch.rb +11 -4
- data/lib/textbringer/commands/keyboard_macro.rb +0 -2
- data/lib/textbringer/commands/misc.rb +29 -27
- data/lib/textbringer/commands/register.rb +0 -2
- data/lib/textbringer/commands/replace.rb +0 -2
- data/lib/textbringer/commands/server.rb +0 -2
- data/lib/textbringer/commands/windows.rb +0 -2
- data/lib/textbringer/config.rb +0 -2
- data/lib/textbringer/controller.rb +2 -4
- data/lib/textbringer/errors.rb +0 -2
- data/lib/textbringer/face.rb +0 -2
- data/lib/textbringer/faces/basic.rb +0 -2
- data/lib/textbringer/faces/programming.rb +0 -2
- data/lib/textbringer/keymap.rb +44 -26
- data/lib/textbringer/mode.rb +0 -2
- data/lib/textbringer/modes/backtrace_mode.rb +1 -3
- data/lib/textbringer/modes/buffer_list_mode.rb +1 -3
- data/lib/textbringer/modes/c_mode.rb +4 -2
- data/lib/textbringer/modes/completion_list_mode.rb +1 -3
- data/lib/textbringer/modes/fundamental_mode.rb +0 -2
- data/lib/textbringer/modes/help_mode.rb +1 -3
- data/lib/textbringer/modes/programming_mode.rb +25 -5
- data/lib/textbringer/modes/ruby_mode.rb +33 -10
- data/lib/textbringer/plugin.rb +0 -2
- data/lib/textbringer/ring.rb +0 -2
- data/lib/textbringer/utils.rb +8 -7
- data/lib/textbringer/version.rb +1 -3
- data/lib/textbringer/window.rb +5 -3
- data/logo/logo.jpg +0 -0
- data/logo/logo.png +0 -0
- metadata +12 -9
- data/.travis.yml +0 -56
- data/appveyor.yml +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cadae924b2e85758480d58a7f4ba6ff48fc6ac1971039159a8b81a1a0bbbd29
|
4
|
+
data.tar.gz: cb981c7fb394e1c4683cd1365f5da1ed1f372c4254d3e9d8ca5782cad18cf167
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a57df2132fc40661649106e25f523e7f866ae469020fb33b687d1bf05921f0b4f17915271df4745035737b3be0c65d34650ae55af3ca10d4f677d7c2ac4d7715
|
7
|
+
data.tar.gz: fd5081ffaa6a8f42466fdc9fd82d6acd4a732941c66d5e2d37fd1c2a66cafba947de668a08ea60ac87f171306aadcaeca6e815991666bcac47ac376a8cd16d73
|
data/.gitattributes
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.rb diff=ruby
|
@@ -0,0 +1,15 @@
|
|
1
|
+
name: macos
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: macos-latest
|
8
|
+
steps:
|
9
|
+
- uses: actions/checkout@master
|
10
|
+
- name: Install dependencies
|
11
|
+
run: |
|
12
|
+
gem install bundler --no-document
|
13
|
+
bundle install
|
14
|
+
- name: Run test
|
15
|
+
run: bundle exec rake test
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: ubuntu
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
ruby: [ head, 2.7, 2.6, 2.5, 2.4 ]
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
steps:
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- uses: ruby/setup-ruby@v1
|
14
|
+
with:
|
15
|
+
ruby-version: ${{ matrix.ruby }}
|
16
|
+
- name: Install dependencies
|
17
|
+
run: |
|
18
|
+
sudo apt install libncursesw5-dev
|
19
|
+
gem install bundler --no-document
|
20
|
+
bundle install
|
21
|
+
- name: Run test
|
22
|
+
run: xvfb-run bundle exec rake test
|
23
|
+
env:
|
24
|
+
UPLOAD_TO_CODECOV: 1
|
25
|
+
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
name: windows
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: windows-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby: [ 'mingw', 'mswin', '2.7', '2.6', '2.5' ]
|
11
|
+
steps:
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- name: Set up Ruby
|
14
|
+
uses: ruby/setup-ruby@v1
|
15
|
+
with:
|
16
|
+
ruby-version: ${{ matrix.ruby }}
|
17
|
+
bundler-cache: true
|
18
|
+
- name: Run test
|
19
|
+
run: bundle exec rake test
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
## 1.0.4
|
2
|
+
|
3
|
+
* Support Ruby 3.0.
|
4
|
+
* Do not record backtrace of Quit (C-g).
|
5
|
+
|
6
|
+
## 1.0.3
|
7
|
+
|
8
|
+
* Fix indentation bugs.
|
9
|
+
* Fix a bug of fourground! when it is called in the main thread.
|
10
|
+
|
11
|
+
## 1.0.2
|
12
|
+
|
13
|
+
* Add isearch_quoted_insert.
|
14
|
+
* Use M- notation instead of ESC in define_key and help.
|
15
|
+
* Add indent_new_comment_line_command.
|
16
|
+
* Add find_alternate_file.
|
17
|
+
* Fix indentation bugs in the Ruby mode.
|
18
|
+
|
19
|
+
## 1.0.1
|
20
|
+
|
21
|
+
* Support pattern matching in the Ruby mode.
|
22
|
+
* Bug fixes.
|
23
|
+
|
24
|
+
## 1.0.0
|
25
|
+
|
26
|
+
* Add mark_whole_buffer.
|
27
|
+
* Add zap_to_char.
|
28
|
+
* Exit on SIGTERM, SIGHUP etc.
|
29
|
+
|
1
30
|
## 0.3.2
|
2
31
|
|
3
32
|
* Drop Ruby 2.3 support.
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
# Textbringer
|
1
|
+
# 
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/textbringer)
|
4
|
-
[](https://github.com/shugo/textbringer/actions?query=workflow%3Aubuntu)
|
5
|
+
[](https://github.com/shugo/textbringer/actions?query=workflow%3Awindows)
|
6
|
+
[](https://github.com/shugo/textbringer/actions?query=workflow%3Amacos)
|
6
7
|
[](https://codecov.io/gh/shugo/textbringer)
|
7
8
|
|
8
9
|
Textbringer is a member of a demon race that takes on the form of an Emacs-like
|
@@ -18,14 +19,6 @@ text editor.
|
|
18
19
|
* Ruby Programming: https://asciinema.org/a/100156
|
19
20
|
* Japanese Text Editing: https://asciinema.org/a/100166
|
20
21
|
|
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
22
|
## Installation
|
30
23
|
|
31
24
|
$ gem install textbringer
|
data/exe/textbringer
CHANGED
data/lib/textbringer.rb
CHANGED
data/lib/textbringer/buffer.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "nkf"
|
4
2
|
require "unicode/display_width"
|
5
3
|
require "json"
|
@@ -205,7 +203,7 @@ def display_width(s)
|
|
205
203
|
end
|
206
204
|
|
207
205
|
# s might not be copied.
|
208
|
-
def initialize(s =
|
206
|
+
def initialize(s = +"", name: nil,
|
209
207
|
file_name: nil,
|
210
208
|
file_encoding: CONFIG[:default_file_encoding],
|
211
209
|
file_mtime: nil, new_file: true, undo_limit: UNDO_LIMIT,
|
@@ -524,7 +522,7 @@ def goto_char(pos)
|
|
524
522
|
if pos < 0 || pos > size
|
525
523
|
raise RangeError, "Out of buffer"
|
526
524
|
end
|
527
|
-
if !@binary && /[\x80-\xbf]/n
|
525
|
+
if !@binary && byte_after(pos)&.match?(/[\x80-\xbf]/n)
|
528
526
|
raise ArgumentError, "Position is in the middle of a character"
|
529
527
|
end
|
530
528
|
@goal_column = nil
|
@@ -578,12 +576,12 @@ def insert(x, merge_undo = false)
|
|
578
576
|
|
579
577
|
def newline
|
580
578
|
indentation = save_point { |saved|
|
581
|
-
if /[ \t]
|
579
|
+
if char_after&.match?(/[ \t]/)
|
582
580
|
next ""
|
583
581
|
end
|
584
582
|
beginning_of_line
|
585
583
|
s = @point
|
586
|
-
while /[ \t]
|
584
|
+
while char_after&.match?(/[ \t]/)
|
587
585
|
forward_char
|
588
586
|
end
|
589
587
|
str = substring(s, @point)
|
@@ -964,7 +962,7 @@ def replace(str, start: point_min, end: point_max)
|
|
964
962
|
|
965
963
|
def clear
|
966
964
|
check_read_only_flag
|
967
|
-
@contents =
|
965
|
+
@contents = +""
|
968
966
|
@point = @gap_start = @gap_end = 0
|
969
967
|
@marks.each do |m|
|
970
968
|
m.location = 0
|
@@ -1065,40 +1063,54 @@ def redo
|
|
1065
1063
|
end
|
1066
1064
|
end
|
1067
1065
|
|
1068
|
-
def re_search_forward(s, raise_error: true)
|
1066
|
+
def re_search_forward(s, raise_error: true, count: 1)
|
1067
|
+
if count < 0
|
1068
|
+
return re_search_backward(s, raise_error: raise_error, count: -count)
|
1069
|
+
end
|
1069
1070
|
re = new_regexp(s)
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1071
|
+
pos = @point
|
1072
|
+
count.times do
|
1073
|
+
i = byteindex(true, re, pos)
|
1074
|
+
if i.nil?
|
1075
|
+
if raise_error
|
1076
|
+
raise SearchError, "Search failed"
|
1077
|
+
else
|
1078
|
+
return nil
|
1079
|
+
end
|
1076
1080
|
end
|
1081
|
+
pos = match_end(0)
|
1077
1082
|
end
|
1078
|
-
goto_char(
|
1083
|
+
goto_char(pos)
|
1079
1084
|
end
|
1080
1085
|
|
1081
|
-
def re_search_backward(s, raise_error: true)
|
1086
|
+
def re_search_backward(s, raise_error: true, count: 1)
|
1087
|
+
if count < 0
|
1088
|
+
return re_search_forward(s, raise_error: raise_error, count: -count)
|
1089
|
+
end
|
1082
1090
|
re = new_regexp(s)
|
1083
1091
|
pos = @point
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1092
|
+
count.times do
|
1093
|
+
p = pos
|
1094
|
+
begin
|
1095
|
+
i = byteindex(false, re, p)
|
1096
|
+
if i.nil?
|
1097
|
+
if raise_error
|
1098
|
+
raise SearchError, "Search failed"
|
1099
|
+
else
|
1100
|
+
return nil
|
1101
|
+
end
|
1102
|
+
end
|
1103
|
+
p = get_pos(p, -1)
|
1104
|
+
rescue RangeError
|
1087
1105
|
if raise_error
|
1088
1106
|
raise SearchError, "Search failed"
|
1089
1107
|
else
|
1090
1108
|
return nil
|
1091
1109
|
end
|
1092
|
-
end
|
1093
|
-
pos =
|
1094
|
-
|
1095
|
-
|
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))
|
1110
|
+
end while match_end(0) > pos
|
1111
|
+
pos = match_beginning(0)
|
1112
|
+
end
|
1113
|
+
goto_char(pos)
|
1102
1114
|
end
|
1103
1115
|
|
1104
1116
|
def looking_at?(re)
|
@@ -1233,7 +1245,7 @@ def transpose_chars
|
|
1233
1245
|
end
|
1234
1246
|
|
1235
1247
|
def gap_filled_with_nul?
|
1236
|
-
|
1248
|
+
@contents[@gap_start...@gap_end]&.match?(/\A\0*\z/)
|
1237
1249
|
end
|
1238
1250
|
|
1239
1251
|
def composite_edit
|
@@ -1338,7 +1350,7 @@ def skip_re_backward(re)
|
|
1338
1350
|
def gsub(*args, &block)
|
1339
1351
|
if block
|
1340
1352
|
s = to_s.gsub(*args) { |*params|
|
1341
|
-
|
1353
|
+
block.binding.eval('->(backref) { $~ = backref }').call($~)
|
1342
1354
|
block.call(*params)
|
1343
1355
|
}
|
1344
1356
|
else
|
@@ -1576,17 +1588,6 @@ def fire_callbacks(name)
|
|
1576
1588
|
callback.call(self)
|
1577
1589
|
end
|
1578
1590
|
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
1591
|
end
|
1591
1592
|
|
1592
1593
|
class Mark
|
data/lib/textbringer/color.rb
CHANGED
data/lib/textbringer/commands.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Textbringer
|
4
2
|
module Commands
|
5
3
|
define_command(:forward_char,
|
@@ -244,5 +242,27 @@ module Commands
|
|
244
242
|
buffer.insert(" ")
|
245
243
|
buffer.backward_char
|
246
244
|
end
|
245
|
+
|
246
|
+
define_command(:mark_whole_buffer,
|
247
|
+
doc: <<~EOD) do
|
248
|
+
Put point at beginning and mark at end of buffer.
|
249
|
+
EOD
|
250
|
+
buffer = Buffer.current
|
251
|
+
buffer.push_mark
|
252
|
+
buffer.push_mark(buffer.point_max)
|
253
|
+
buffer.beginning_of_buffer
|
254
|
+
end
|
255
|
+
|
256
|
+
define_command(:zap_to_char,
|
257
|
+
doc: <<~EOD) do
|
258
|
+
Kill up to and including count-th occurrence of char.
|
259
|
+
EOD
|
260
|
+
|char = read_char, count: number_prefix_arg|
|
261
|
+
|
262
|
+
buffer = Buffer.current
|
263
|
+
s = buffer.point
|
264
|
+
e = buffer.re_search_forward(Regexp.quote(char), count: count)
|
265
|
+
buffer.kill_region(s, e)
|
266
|
+
end
|
247
267
|
end
|
248
268
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Clipboard
|
4
2
|
@implementation = nil
|
5
3
|
end
|
@@ -13,12 +11,12 @@ module Commands
|
|
13
11
|
(ENV["DISPLAY"] && system("which xclip > /dev/null 2>&1"))
|
14
12
|
|
15
13
|
if CLIPBOARD_AVAILABLE
|
16
|
-
GLOBAL_MAP.define_key("\
|
14
|
+
GLOBAL_MAP.define_key("\M-w", :clipboard_copy_region)
|
17
15
|
GLOBAL_MAP.define_key("\C-w", :clipboard_kill_region)
|
18
16
|
GLOBAL_MAP.define_key(?\C-k, :clipboard_kill_line)
|
19
|
-
GLOBAL_MAP.define_key("\
|
17
|
+
GLOBAL_MAP.define_key("\M-d", :clipboard_kill_word)
|
20
18
|
GLOBAL_MAP.define_key("\C-y", :clipboard_yank)
|
21
|
-
GLOBAL_MAP.define_key("\
|
19
|
+
GLOBAL_MAP.define_key("\M-y", :clipboard_yank_pop)
|
22
20
|
end
|
23
21
|
|
24
22
|
define_command(:clipboard_copy_region, doc: <<~EOD) do
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Textbringer
|
4
2
|
module Commands
|
5
3
|
CTAGS = {
|
@@ -51,12 +49,12 @@ module Commands
|
|
51
49
|
when /\A\d+\z/
|
52
50
|
push_tag_mark_and_find_file(file)
|
53
51
|
goto_line(addr.to_i)
|
54
|
-
when %r'\A/\^(
|
52
|
+
when %r'\A/\^(.*?)(\$)?/\z'
|
53
|
+
re = "^" + Regexp.quote($1.gsub(/\\([\\\/])/, "\\1")) + $2.to_s
|
55
54
|
push_tag_mark_and_find_file(file)
|
56
55
|
beginning_of_buffer
|
57
56
|
n.times do
|
58
|
-
|
59
|
-
re_search_forward("^" + s + "$")
|
57
|
+
re_search_forward(re)
|
60
58
|
end
|
61
59
|
beginning_of_line
|
62
60
|
when %r'\A\?\^(.*)\$\?\z'
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Textbringer
|
4
2
|
module DabbrevExtension
|
5
3
|
refine Buffer do
|
@@ -93,7 +91,7 @@ def dabbrev_regexp(stem, candidates)
|
|
93
91
|
using DabbrevExtension
|
94
92
|
|
95
93
|
module Commands
|
96
|
-
GLOBAL_MAP.define_key("\
|
94
|
+
GLOBAL_MAP.define_key("\M-/", :dabbrev_expand_command)
|
97
95
|
|
98
96
|
define_command(:dabbrev_expand_command) do
|
99
97
|
contd = Controller.current.last_command == :dabbrev_expand_command
|
@@ -1,11 +1,9 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "editorconfig"
|
4
2
|
|
5
3
|
module Textbringer
|
6
4
|
module Commands
|
7
5
|
define_command(:find_file, doc: "Open or create a file.") do
|
8
|
-
|file_name = read_file_name("Find file: ")|
|
6
|
+
|file_name = read_file_name("Find file: ", default: (Buffer.current.file_name ? File.dirname(Buffer.current.file_name) : Dir.pwd) + "/")|
|
9
7
|
config = EditorConfig.load_file(file_name)
|
10
8
|
buffer = Buffer.find_file(file_name)
|
11
9
|
if buffer.new_file?
|
@@ -88,12 +86,13 @@ module Commands
|
|
88
86
|
|
89
87
|
define_command(:write_file,
|
90
88
|
doc: "Save the current buffer as the specified file.") do
|
91
|
-
|file_name = read_file_name("Write file: "
|
89
|
+
|file_name = read_file_name("Write file: ",
|
90
|
+
default: Buffer.current.file_name)|
|
92
91
|
if File.directory?(file_name)
|
93
92
|
file_name = File.expand_path(Buffer.current.name, file_name)
|
94
93
|
end
|
95
94
|
if File.exist?(file_name)
|
96
|
-
unless y_or_n?("File
|
95
|
+
unless y_or_n?("File exists; overwrite?")
|
97
96
|
message("Cancelled")
|
98
97
|
next
|
99
98
|
end
|
@@ -126,5 +125,11 @@ module Commands
|
|
126
125
|
File.dirname(Buffer.current.file_name))|
|
127
126
|
Dir.chdir(dir_name)
|
128
127
|
end
|
128
|
+
|
129
|
+
define_command(:find_alternate_file, doc: "Find an alternate file.") do
|
130
|
+
|file_name = read_file_name("Find alternate file: ",
|
131
|
+
default: Buffer.current.file_name)|
|
132
|
+
find_file(file_name)
|
133
|
+
end
|
129
134
|
end
|
130
135
|
end
|