textbringer 1.0.3 → 1.1.1
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/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
|
[](https://github.com/shugo/textbringer/actions?query=workflow%3Aubuntu)
|
5
5
|
[](https://github.com/shugo/textbringer/actions?query=workflow%3Awindows)
|
6
6
|
[](https://github.com/shugo/textbringer/actions?query=workflow%3Amacos)
|
7
|
-
[](https://github.com/shugo/textbringer/actions?query=workflow%3Aruby-head)
|
8
|
-
[](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
|