textbringer 1.0.3 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ubuntu.yml +5 -9
- data/.github/workflows/windows.yml +4 -7
- data/CHANGES.md +38 -0
- data/README.md +0 -2
- data/bin/merge_mazegaki_dic +25 -0
- data/exe/textbringer +6 -5
- data/lib/textbringer/buffer.rb +40 -3
- data/lib/textbringer/commands/files.rb +12 -3
- data/lib/textbringer/commands/help.rb +25 -16
- data/lib/textbringer/commands/input_method.rb +18 -0
- data/lib/textbringer/commands/isearch.rb +13 -1
- data/lib/textbringer/commands/misc.rb +7 -2
- data/lib/textbringer/commands/server.rb +1 -1
- data/lib/textbringer/commands/windows.rb +8 -4
- data/lib/textbringer/config.rb +2 -1
- data/lib/textbringer/controller.rb +7 -1
- data/lib/textbringer/input_method.rb +63 -0
- data/lib/textbringer/input_methods/hiragana_input_method.rb +70 -0
- data/lib/textbringer/input_methods/t_code_input_method/tables.rb +64 -0
- data/lib/textbringer/input_methods/t_code_input_method.rb +458 -0
- data/lib/textbringer/keymap.rb +1 -0
- data/lib/textbringer/modes/ruby_mode.rb +43 -6
- data/lib/textbringer/utils.rb +6 -4
- data/lib/textbringer/version.rb +1 -1
- data/lib/textbringer/window.rb +25 -10
- data/lib/textbringer.rb +4 -0
- data/textbringer.gemspec +4 -5
- metadata +19 -28
- data/.github/workflows/ruby-head.yml +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b83487edc5f542afe9444b4393375aedd1ea82b4893997b17c6c4a33a3a4d76
|
4
|
+
data.tar.gz: 60b6f47109aad0c55ed9832b97a8a54a65ad7cf7cac95341a20b2f01ba23234d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17399f8a6297f0b77cd03cdac6c24c64b6e6da82dc596b6e5bdfa7ba807cdcb8c9e32d12e376b219941ee14a2ef4a60e63bab9e2a07723a107b5e01b259eb034
|
7
|
+
data.tar.gz: 27b5e0e6011257b5beafc563b439944a72c7018cd058060bde55618369a55ec2c6596840f0de661a075f361485f5f27e76d908c6b04360f1342986a48b78797d
|
@@ -3,15 +3,14 @@ name: ubuntu
|
|
3
3
|
on: [push]
|
4
4
|
|
5
5
|
jobs:
|
6
|
-
|
7
|
-
runs-on: ubuntu-latest
|
6
|
+
test:
|
8
7
|
strategy:
|
9
8
|
matrix:
|
10
|
-
ruby: [
|
9
|
+
ruby: [ head, 3.1, 3.0, 2.7, 2.6 ]
|
10
|
+
runs-on: ubuntu-latest
|
11
11
|
steps:
|
12
|
-
- uses: actions/checkout@
|
13
|
-
-
|
14
|
-
uses: actions/setup-ruby@v1
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- uses: ruby/setup-ruby@v1
|
15
14
|
with:
|
16
15
|
ruby-version: ${{ matrix.ruby }}
|
17
16
|
- name: Install dependencies
|
@@ -21,6 +20,3 @@ jobs:
|
|
21
20
|
bundle install
|
22
21
|
- name: Run test
|
23
22
|
run: xvfb-run bundle exec rake test
|
24
|
-
env:
|
25
|
-
UPLOAD_TO_CODECOV: 1
|
26
|
-
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
|
@@ -7,16 +7,13 @@ jobs:
|
|
7
7
|
runs-on: windows-latest
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
ruby: [ '
|
10
|
+
ruby: [ 'mingw', 'mswin', '3.0', '2.7', '2.6' ]
|
11
11
|
steps:
|
12
|
-
- uses: actions/checkout@
|
12
|
+
- uses: actions/checkout@v2
|
13
13
|
- name: Set up Ruby
|
14
|
-
uses:
|
14
|
+
uses: ruby/setup-ruby@v1
|
15
15
|
with:
|
16
16
|
ruby-version: ${{ matrix.ruby }}
|
17
|
-
|
18
|
-
run: gem install bundler --no-document
|
19
|
-
- name: Install dependencies
|
20
|
-
run: bundle install
|
17
|
+
bundler-cache: true
|
21
18
|
- name: Run test
|
22
19
|
run: bundle exec rake test
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
+
## 1.1.1
|
2
|
+
|
3
|
+
* Bug fixes.
|
4
|
+
|
5
|
+
## 1.1.0
|
6
|
+
|
7
|
+
* Show unsaved buffers on exit
|
8
|
+
* Bug fixes.
|
9
|
+
|
10
|
+
## 1.0.9
|
11
|
+
|
12
|
+
* Remove mazegaki.dic and bushu.rev
|
13
|
+
|
14
|
+
## 1.0.8
|
15
|
+
|
16
|
+
* Updated mazegaki.dic
|
17
|
+
* Add licenses of dictionary data to LEGAL.txt
|
18
|
+
|
19
|
+
## 1.0.7
|
20
|
+
|
21
|
+
* Support endless method definitions in ruby-mode.
|
22
|
+
* Updated mazegaki.dic.
|
23
|
+
|
24
|
+
## 1.0.6
|
25
|
+
|
26
|
+
* Add the Hiragana input method.
|
27
|
+
* Add make_directory.
|
28
|
+
* Bug fixes.
|
29
|
+
|
30
|
+
## 1.0.5
|
31
|
+
|
32
|
+
* Support the Japanese input method T-Code.
|
33
|
+
|
34
|
+
## 1.0.4
|
35
|
+
|
36
|
+
* Support Ruby 3.0.
|
37
|
+
* Do not record backtrace of Quit (C-g).
|
38
|
+
|
1
39
|
## 1.0.3
|
2
40
|
|
3
41
|
* Fix indentation bugs.
|
data/README.md
CHANGED
@@ -4,8 +4,6 @@
|
|
4
4
|
[![ubuntu](https://github.com/shugo/textbringer/workflows/ubuntu/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Aubuntu)
|
5
5
|
[![windows](https://github.com/shugo/textbringer/workflows/windows/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Awindows)
|
6
6
|
[![macos](https://github.com/shugo/textbringer/workflows/macos/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Amacos)
|
7
|
-
[![ruby-head](https://github.com/shugo/textbringer/workflows/ruby-head/badge.svg)](https://github.com/shugo/textbringer/actions?query=workflow%3Aruby-head)
|
8
|
-
[![codecov](https://codecov.io/gh/shugo/textbringer/branch/master/graph/badge.svg)](https://codecov.io/gh/shugo/textbringer)
|
9
7
|
|
10
8
|
Textbringer is a member of a demon race that takes on the form of an Emacs-like
|
11
9
|
text editor.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Usage: merge_mazegaki_dic /path/to/mazegaki.dic /path/to/skkdic/SKK-JISYO.* > ~/.textbringer/tcode/mazegaki.dic
|
4
|
+
|
5
|
+
MAZEGAKI_DIC = Hash.new([])
|
6
|
+
|
7
|
+
ARGF.each_line do |line|
|
8
|
+
next if /^\p{ascii}/.match?(line)
|
9
|
+
x, y = line.split
|
10
|
+
key = x.sub(/\A(\p{hiragana}+)[a-z>]\z/, "\\1—")
|
11
|
+
values = y.split("/").map { |i|
|
12
|
+
i.sub(/;.*/, "")
|
13
|
+
}.reject { |i|
|
14
|
+
i.empty? || i == key
|
15
|
+
}
|
16
|
+
MAZEGAKI_DIC[key] |= values
|
17
|
+
end
|
18
|
+
|
19
|
+
MAZEGAKI_DIC.sort_by { |key,|
|
20
|
+
key
|
21
|
+
}.each do |key, values|
|
22
|
+
puts "#{key} /#{values.join('/')}/"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
data/exe/textbringer
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
$VERBOSE = nil
|
4
|
+
|
3
5
|
require "textbringer"
|
4
6
|
|
5
7
|
include Textbringer
|
6
8
|
include Commands
|
7
9
|
|
8
|
-
def load_user_config
|
9
|
-
config_file = File.expand_path(
|
10
|
+
def load_user_config(path)
|
11
|
+
config_file = File.expand_path(path)
|
10
12
|
begin
|
11
13
|
load(config_file)
|
12
14
|
rescue LoadError
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
|
-
$VERBOSE = nil
|
17
|
-
|
18
18
|
unless STDIN.tty?
|
19
19
|
STDERR.puts("textbringer: standard input is not a tty")
|
20
20
|
exit 1
|
@@ -24,8 +24,9 @@ Controller.current = Controller.new
|
|
24
24
|
begin
|
25
25
|
Window.start do
|
26
26
|
begin
|
27
|
+
load_user_config("~/.textbringer/init.rb")
|
27
28
|
Plugin.load_plugins
|
28
|
-
load_user_config
|
29
|
+
load_user_config("~/.textbringer.rb")
|
29
30
|
ruby_mode
|
30
31
|
if ARGV.size > 0
|
31
32
|
ARGV.each do |arg|
|
data/lib/textbringer/buffer.rb
CHANGED
@@ -11,6 +11,7 @@ module Textbringer
|
|
11
11
|
attr_accessor :mode, :keymap
|
12
12
|
attr_reader :name, :file_name, :file_encoding, :file_format, :point, :marks
|
13
13
|
attr_reader :current_line, :current_column, :visible_mark
|
14
|
+
attr_reader :input_method
|
14
15
|
|
15
16
|
GAP_SIZE = 256
|
16
17
|
UNDO_LIMIT = 1000
|
@@ -240,6 +241,7 @@ module Textbringer
|
|
240
241
|
@visible_mark = nil
|
241
242
|
@read_only = read_only
|
242
243
|
@callbacks = {}
|
244
|
+
@input_method = nil
|
243
245
|
end
|
244
246
|
|
245
247
|
def inspect
|
@@ -410,6 +412,7 @@ module Textbringer
|
|
410
412
|
f.flock(File::LOCK_EX)
|
411
413
|
write_to_file(f)
|
412
414
|
f.flush
|
415
|
+
f.fsync
|
413
416
|
end
|
414
417
|
@file_mtime = File.mtime(file_name)
|
415
418
|
rescue Errno::EISDIR
|
@@ -1384,6 +1387,35 @@ module Textbringer
|
|
1384
1387
|
end
|
1385
1388
|
end
|
1386
1389
|
|
1390
|
+
def toggle_input_method(name)
|
1391
|
+
if name.nil?
|
1392
|
+
@input_method ||= InputMethod.find(CONFIG[:default_input_method])
|
1393
|
+
else
|
1394
|
+
@input_method = InputMethod.find(name)
|
1395
|
+
end
|
1396
|
+
@input_method.toggle
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
def disable_input_method
|
1400
|
+
@input_method&.disable
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
def filter_event(event)
|
1404
|
+
if @input_method
|
1405
|
+
@input_method.filter_event(event)
|
1406
|
+
else
|
1407
|
+
event
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
|
1411
|
+
def input_method_status
|
1412
|
+
if @input_method&.enabled?
|
1413
|
+
@input_method.status
|
1414
|
+
else
|
1415
|
+
"--"
|
1416
|
+
end
|
1417
|
+
end
|
1418
|
+
|
1387
1419
|
private
|
1388
1420
|
|
1389
1421
|
def set_contents(s, enc)
|
@@ -1555,15 +1587,15 @@ module Textbringer
|
|
1555
1587
|
|
1556
1588
|
def push_undo(action)
|
1557
1589
|
return if @undoing || @undo_limit == 0
|
1590
|
+
if !modified?
|
1591
|
+
action.version = @version
|
1592
|
+
end
|
1558
1593
|
if @composite_edit_level > 0
|
1559
1594
|
@composite_edit_actions.push(action)
|
1560
1595
|
else
|
1561
1596
|
if @undo_stack.size >= @undo_limit
|
1562
1597
|
@undo_stack[0, @undo_stack.size + 1 - @undo_limit] = []
|
1563
1598
|
end
|
1564
|
-
if !modified?
|
1565
|
-
action.version = @version
|
1566
|
-
end
|
1567
1599
|
@undo_stack.push(action)
|
1568
1600
|
@redo_stack.clear
|
1569
1601
|
end
|
@@ -1649,6 +1681,7 @@ module Textbringer
|
|
1649
1681
|
def initialize(buffer, location, string)
|
1650
1682
|
super(buffer, location)
|
1651
1683
|
@string = string
|
1684
|
+
@copied = false
|
1652
1685
|
end
|
1653
1686
|
|
1654
1687
|
def undo
|
@@ -1662,6 +1695,10 @@ module Textbringer
|
|
1662
1695
|
end
|
1663
1696
|
|
1664
1697
|
def merge(s)
|
1698
|
+
unless @copied
|
1699
|
+
@string = @string.dup
|
1700
|
+
@copied = true
|
1701
|
+
end
|
1665
1702
|
@string.concat(s)
|
1666
1703
|
end
|
1667
1704
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require "editorconfig"
|
2
|
+
require "fileutils"
|
2
3
|
|
3
4
|
module Textbringer
|
4
5
|
module Commands
|
5
6
|
define_command(:find_file, doc: "Open or create a file.") do
|
6
|
-
|file_name = read_file_name("Find file: ")|
|
7
|
+
|file_name = read_file_name("Find file: ", default: (Buffer.current.file_name ? File.dirname(Buffer.current.file_name) : Dir.pwd) + "/")|
|
7
8
|
config = EditorConfig.load_file(file_name)
|
8
9
|
buffer = Buffer.find_file(file_name)
|
9
10
|
if buffer.new_file?
|
@@ -86,12 +87,13 @@ module Textbringer
|
|
86
87
|
|
87
88
|
define_command(:write_file,
|
88
89
|
doc: "Save the current buffer as the specified file.") do
|
89
|
-
|file_name = read_file_name("Write file: "
|
90
|
+
|file_name = read_file_name("Write file: ",
|
91
|
+
default: Buffer.current.file_name)|
|
90
92
|
if File.directory?(file_name)
|
91
93
|
file_name = File.expand_path(Buffer.current.name, file_name)
|
92
94
|
end
|
93
95
|
if File.exist?(file_name)
|
94
|
-
unless y_or_n?("File
|
96
|
+
unless y_or_n?("File exists; overwrite?")
|
95
97
|
message("Cancelled")
|
96
98
|
next
|
97
99
|
end
|
@@ -130,5 +132,12 @@ module Textbringer
|
|
130
132
|
default: Buffer.current.file_name)|
|
131
133
|
find_file(file_name)
|
132
134
|
end
|
135
|
+
|
136
|
+
define_command(:make_directory, doc: "Create a new directory.") do
|
137
|
+
|dir_name = read_file_name("Make directory: ",
|
138
|
+
default: Buffer.current.file_name &&
|
139
|
+
File.dirname(Buffer.current.file_name))|
|
140
|
+
FileUtils.mkdir_p(dir_name)
|
141
|
+
end
|
133
142
|
end
|
134
143
|
end
|
@@ -21,27 +21,36 @@ module Textbringer
|
|
21
21
|
end
|
22
22
|
private :show_help
|
23
23
|
|
24
|
+
def keymap_bindings(keymap)
|
25
|
+
s = format("%-16s %s\n", "Key", "Binding")
|
26
|
+
s << format("%-16s %s\n", "---", "-------")
|
27
|
+
s << "\n"
|
28
|
+
keymap.each do |key_sequence, command|
|
29
|
+
if command != :self_insert
|
30
|
+
s << format("%-16s [%s]\n",
|
31
|
+
Keymap.key_sequence_string(key_sequence),
|
32
|
+
command)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
s
|
36
|
+
end
|
37
|
+
|
24
38
|
define_command(:describe_bindings,
|
25
39
|
doc: "Display the key bindings.") do
|
26
40
|
show_help do |help|
|
27
|
-
s =
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
GLOBAL_MAP,
|
33
|
-
Buffer.current.keymap,
|
34
|
-
Controller.current.overriding_map
|
35
|
-
].each do |map|
|
36
|
-
map&.each do |key_sequence, command|
|
37
|
-
bindings[key_sequence] = command
|
38
|
-
end
|
41
|
+
s = ""
|
42
|
+
if Controller.current.overriding_map
|
43
|
+
s << "Overriding Bindings:\n"
|
44
|
+
s << keymap_bindings(Controller.current.overriding_map)
|
45
|
+
s << "\n"
|
39
46
|
end
|
40
|
-
|
41
|
-
s <<
|
42
|
-
|
43
|
-
|
47
|
+
if Buffer.current.keymap
|
48
|
+
s << "Current Buffer Bindings:\n"
|
49
|
+
s << keymap_bindings(Buffer.current.keymap)
|
50
|
+
s << "\n"
|
44
51
|
end
|
52
|
+
s << "Global Bindings:\n"
|
53
|
+
s << keymap_bindings(GLOBAL_MAP)
|
45
54
|
help.insert(s)
|
46
55
|
end
|
47
56
|
push_help_command([:describe_bindings])
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Textbringer
|
2
|
+
module Commands
|
3
|
+
define_command(:toggle_input_method,
|
4
|
+
doc: "Toggel input method.") do |name = nil|
|
5
|
+
if name.nil? && current_prefix_arg
|
6
|
+
name = read_input_method_name("Input method: ")
|
7
|
+
end
|
8
|
+
Buffer.current.toggle_input_method(name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def read_input_method_name(prompt, default: CONFIG[:default_input_method])
|
12
|
+
f = ->(s) {
|
13
|
+
complete_for_minibuffer(s.tr("-", "_"), InputMethod.list)
|
14
|
+
}
|
15
|
+
read_from_minibuffer(prompt, completion_proc: f, default: default)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -14,12 +14,14 @@ module Textbringer
|
|
14
14
|
end
|
15
15
|
ISEARCH_MODE_MAP.define_key(:backspace, :isearch_delete_char)
|
16
16
|
ISEARCH_MODE_MAP.define_key(?\C-h, :isearch_delete_char)
|
17
|
+
ISEARCH_MODE_MAP.define_key(?\C-?, :isearch_delete_char)
|
17
18
|
ISEARCH_MODE_MAP.define_key(?\C-s, :isearch_repeat_forward)
|
18
19
|
ISEARCH_MODE_MAP.define_key(?\C-r, :isearch_repeat_backward)
|
19
20
|
ISEARCH_MODE_MAP.define_key(?\C-w, :isearch_yank_word_or_char)
|
20
21
|
ISEARCH_MODE_MAP.define_key(?\C-m, :isearch_exit)
|
21
22
|
ISEARCH_MODE_MAP.define_key(?\C-g, :isearch_abort)
|
22
23
|
ISEARCH_MODE_MAP.define_key(?\C-q, :isearch_quoted_insert)
|
24
|
+
ISEARCH_MODE_MAP.define_key(?\C-\\, :isearch_toggle_input_method)
|
23
25
|
|
24
26
|
ISEARCH_STATUS = {
|
25
27
|
forward: true,
|
@@ -56,6 +58,10 @@ module Textbringer
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
61
|
+
def isearch_mode?
|
62
|
+
Controller.current.overriding_map == ISEARCH_MODE_MAP
|
63
|
+
end
|
64
|
+
|
59
65
|
def isearch_prompt
|
60
66
|
if ISEARCH_STATUS[:forward]
|
61
67
|
"I-search: "
|
@@ -133,7 +139,7 @@ module Textbringer
|
|
133
139
|
re = Regexp.new(Regexp.quote(ISEARCH_STATUS[:string]), options)
|
134
140
|
last_pos = ISEARCH_STATUS[:last_pos]
|
135
141
|
offset = forward ? last_pos : last_pos - ISEARCH_STATUS[:string].bytesize
|
136
|
-
if Buffer.current.byteindex(forward, re, offset)
|
142
|
+
if offset >= 0 && Buffer.current.byteindex(forward, re, offset)
|
137
143
|
if Buffer.current != Buffer.minibuffer
|
138
144
|
message(isearch_prompt + ISEARCH_STATUS[:string], log: false)
|
139
145
|
end
|
@@ -164,5 +170,11 @@ module Textbringer
|
|
164
170
|
end
|
165
171
|
isearch_search
|
166
172
|
end
|
173
|
+
|
174
|
+
define_command(:isearch_toggle_input_method,
|
175
|
+
doc: "Toggle input method.") do
|
176
|
+
toggle_input_method
|
177
|
+
message(isearch_prompt + ISEARCH_STATUS[:string], log: false)
|
178
|
+
end
|
167
179
|
end
|
168
180
|
end
|
@@ -6,7 +6,12 @@ module Textbringer
|
|
6
6
|
end
|
7
7
|
|
8
8
|
define_command(:exit_textbringer) do |status = 0|
|
9
|
-
|
9
|
+
unsaved_buffers = Buffer.filter { |buffer|
|
10
|
+
/\A\*/ !~ buffer.name && buffer.modified?
|
11
|
+
}
|
12
|
+
if !unsaved_buffers.empty?
|
13
|
+
list_buffers(unsaved_buffers)
|
14
|
+
Window.redisplay
|
10
15
|
return unless yes_or_no?("Unsaved buffers exist; exit anyway?")
|
11
16
|
end
|
12
17
|
exit(status)
|
@@ -276,7 +281,7 @@ module Textbringer
|
|
276
281
|
Window.redisplay
|
277
282
|
signals = [:INT, :TERM, :KILL]
|
278
283
|
begin
|
279
|
-
opts = /
|
284
|
+
opts = /mswin|mingw/ =~ RUBY_PLATFORM ? {} : {pgroup: true}
|
280
285
|
if CONFIG[:shell_file_name]
|
281
286
|
cmd = [CONFIG[:shell_file_name], CONFIG[:shell_command_switch], cmd]
|
282
287
|
end
|
@@ -6,7 +6,7 @@ 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 = CONFIG[:server_options] || {
|
9
|
+
options = { UNIXFileMode: 0600 }.merge(CONFIG[:server_options] || {})
|
10
10
|
DRb.start_service(uri, Server.new, options)
|
11
11
|
end
|
12
12
|
|
@@ -69,9 +69,13 @@ module Textbringer
|
|
69
69
|
define_command(:switch_to_buffer, doc: <<~EOD) do
|
70
70
|
Display buffer in the current window.
|
71
71
|
EOD
|
72
|
-
|buffer = read_buffer("Switch to buffer: ")|
|
72
|
+
|buffer = read_buffer("Switch to buffer: "), arg = current_prefix_arg|
|
73
73
|
if buffer.is_a?(String)
|
74
|
-
|
74
|
+
if arg
|
75
|
+
buffer = Buffer.find_or_new(buffer)
|
76
|
+
else
|
77
|
+
buffer = Buffer[buffer]
|
78
|
+
end
|
75
79
|
end
|
76
80
|
if buffer
|
77
81
|
Window.current.buffer = Buffer.current = buffer
|
@@ -80,7 +84,7 @@ module Textbringer
|
|
80
84
|
end
|
81
85
|
end
|
82
86
|
|
83
|
-
define_command(:list_buffers, doc: <<~EOD) do
|
87
|
+
define_command(:list_buffers, doc: <<~EOD) do |buffers = Buffer.list|
|
84
88
|
List the existing buffers.
|
85
89
|
EOD
|
86
90
|
buffer = Buffer.find_or_new("*Buffer List*",
|
@@ -88,7 +92,7 @@ module Textbringer
|
|
88
92
|
buffer.apply_mode(BufferListMode)
|
89
93
|
buffer.read_only_edit do
|
90
94
|
buffer.clear
|
91
|
-
buffer.insert(
|
95
|
+
buffer.insert(buffers.map(&:name).join("\n"))
|
92
96
|
buffer.beginning_of_buffer
|
93
97
|
end
|
94
98
|
switch_to_buffer(buffer)
|
data/lib/textbringer/config.rb
CHANGED
@@ -264,7 +264,13 @@ module Textbringer
|
|
264
264
|
end
|
265
265
|
|
266
266
|
def call_read_event_method(read_event_method)
|
267
|
-
Window.current.send(read_event_method)
|
267
|
+
Window.current.send(read_event_method)&.then { |event|
|
268
|
+
if @key_sequence.empty?
|
269
|
+
Buffer.current.filter_event(event)
|
270
|
+
else
|
271
|
+
event
|
272
|
+
end
|
273
|
+
}
|
268
274
|
end
|
269
275
|
end
|
270
276
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Textbringer
|
2
|
+
class InputMethod
|
3
|
+
extend Commands
|
4
|
+
include Commands
|
5
|
+
|
6
|
+
@@list = []
|
7
|
+
|
8
|
+
def self.inherited(subclass)
|
9
|
+
name = subclass.name.sub(/Textbringer::/, "").sub(/InputMethod/, "").
|
10
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
11
|
+
downcase
|
12
|
+
@@list.push(name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.list
|
16
|
+
@@list
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.find(name)
|
20
|
+
class_name = name.split(/_/).map(&:capitalize).join + "InputMethod"
|
21
|
+
Textbringer.const_get(class_name).new
|
22
|
+
rescue NameError
|
23
|
+
raise EditorError, "No such input method: #{name}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@enabled = false
|
28
|
+
@skip_next_event = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def toggle
|
32
|
+
@enabled = !@enabled
|
33
|
+
end
|
34
|
+
|
35
|
+
def disable
|
36
|
+
@enabled = false
|
37
|
+
end
|
38
|
+
|
39
|
+
def enabled?
|
40
|
+
@enabled
|
41
|
+
end
|
42
|
+
|
43
|
+
def filter_event(event)
|
44
|
+
if @enabled
|
45
|
+
if event == "\e"
|
46
|
+
@skip_next_event = true
|
47
|
+
event
|
48
|
+
elsif @skip_next_event
|
49
|
+
@skip_next_event = false
|
50
|
+
event
|
51
|
+
else
|
52
|
+
handle_event(event)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
event
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def handle_event(event)
|
60
|
+
raise EditorError, "subclass must override InputMethod#handle_event"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Textbringer
|
4
|
+
class HiraganaInputMethod < InputMethod
|
5
|
+
HIRAGANA_TABLE = {
|
6
|
+
"a" => "あ", "i" => "い", "u" => "う", "e" => "え", "o" => "お",
|
7
|
+
"ka" => "か", "ki" => "き", "ku" => "く", "ke" => "け", "ko" => "こ",
|
8
|
+
"ga" => "が", "gi" => "ぎ", "gu" => "ぐ", "ge" => "げ", "go" => "ご",
|
9
|
+
"sa" => "さ", "si" => "し", "su" => "す", "se" => "せ", "so" => "そ",
|
10
|
+
"za" => "ざ", "zi" => "じ", "zu" => "ず", "ze" => "ぜ", "zo" => "ぞ",
|
11
|
+
"sha" => "しゃ", "shi" => "し", "shu" => "しゅ", "she" => "しぇ", "sho" => "しょ",
|
12
|
+
"ja" => "じゃ", "ji" => "じ", "ju" => "じゅ", "je" => "じぇ", "jo" => "じょ",
|
13
|
+
"ta" => "た", "ti" => "ち", "tu" => "つ", "te" => "て", "to" => "と",
|
14
|
+
"da" => "だ", "di" => "ぢ", "du" => "づ", "de" => "で", "do" => "ど",
|
15
|
+
"cha" => "ちゃ", "chi" => "ち", "chu" => "ちゅ", "che" => "ちぇ", "cho" => "ちょ",
|
16
|
+
"na" => "な", "ni" => "に", "nu" => "ぬ", "ne" => "ね", "no" => "の",
|
17
|
+
"ha" => "は", "hi" => "ひ", "hu" => "ふ", "he" => "へ", "ho" => "ほ",
|
18
|
+
"ba" => "ば", "bi" => "び", "bu" => "ぶ", "be" => "べ", "bo" => "ぼ",
|
19
|
+
"pa" => "ぱ", "pi" => "ぴ", "pu" => "ぷ", "pe" => "ぺ", "po" => "ぽ",
|
20
|
+
"ma" => "ま", "mi" => "み", "mu" => "む", "me" => "め", "mo" => "も",
|
21
|
+
"ya" => "や", "yi" => "い", "yu" => "ゆ", "ye" => "いぇ", "yo" => "よ",
|
22
|
+
"ra" => "ら", "ri" => "り", "ru" => "る", "re" => "れ", "ro" => "ろ",
|
23
|
+
"wa" => "わ", "wi" => "ゐ", "wu" => "う", "we" => "ゑ", "wo" => "を",
|
24
|
+
"nn" => "ん"
|
25
|
+
}
|
26
|
+
HIRAGANA_PREFIXES = HIRAGANA_TABLE.keys.flat_map { |s|
|
27
|
+
(s.size - 1).times.map { |i| s[0, i + 1] }
|
28
|
+
}.uniq
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
super
|
32
|
+
@input_buffer = +""
|
33
|
+
end
|
34
|
+
|
35
|
+
def status
|
36
|
+
"あ"
|
37
|
+
end
|
38
|
+
|
39
|
+
def handle_event(event)
|
40
|
+
if !event.is_a?(String)
|
41
|
+
if !@input_buffer.empty?
|
42
|
+
@input_buffer = +""
|
43
|
+
end
|
44
|
+
return event
|
45
|
+
end
|
46
|
+
@input_buffer << event
|
47
|
+
s = HIRAGANA_TABLE[@input_buffer]
|
48
|
+
if s
|
49
|
+
return flush(s)
|
50
|
+
end
|
51
|
+
if HIRAGANA_PREFIXES.include?(@input_buffer)
|
52
|
+
return nil
|
53
|
+
end
|
54
|
+
flush(@input_buffer)
|
55
|
+
end
|
56
|
+
|
57
|
+
def flush(s)
|
58
|
+
if !@input_buffer.empty?
|
59
|
+
@input_buffer = +""
|
60
|
+
end
|
61
|
+
if s.size == 1
|
62
|
+
s
|
63
|
+
else
|
64
|
+
Buffer.current.insert(s)
|
65
|
+
Window.redisplay
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|