textbringer 0.1.4 → 0.1.5
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/.gitignore +1 -1
- data/.travis.yml +1 -1
- data/CHANGES.md +6 -0
- data/README.md +1 -1
- data/lib/textbringer.rb +12 -1
- data/lib/textbringer/buffer.rb +7 -2
- data/lib/textbringer/commands.rb +0 -677
- data/lib/textbringer/commands/buffers.rb +101 -0
- data/lib/textbringer/commands/clipboard.rb +35 -0
- data/lib/textbringer/commands/ctags.rb +14 -7
- data/lib/textbringer/commands/dabbrev.rb +39 -32
- data/lib/textbringer/commands/files.rb +76 -0
- data/lib/textbringer/commands/isearch.rb +144 -0
- data/lib/textbringer/commands/misc.rb +240 -0
- data/lib/textbringer/commands/replace.rb +82 -0
- data/lib/textbringer/commands/windows.rb +72 -0
- data/lib/textbringer/controller.rb +17 -19
- data/lib/textbringer/errors.rb +6 -0
- data/lib/textbringer/modes/ruby_mode.rb +73 -53
- data/lib/textbringer/utils.rb +21 -7
- data/lib/textbringer/version.rb +1 -1
- data/lib/textbringer/window.rb +27 -9
- data/textbringer.gemspec +6 -3
- metadata +57 -8
- data/lib/textbringer/modes.rb +0 -7
data/lib/textbringer/errors.rb
CHANGED
@@ -20,6 +20,7 @@ module Textbringer
|
|
20
20
|
def indent_line
|
21
21
|
result = false
|
22
22
|
level = calculate_indentation
|
23
|
+
return result if level.nil?
|
23
24
|
@buffer.save_excursion do
|
24
25
|
@buffer.beginning_of_line
|
25
26
|
has_space = @buffer.looking_at?(/[ \t]+/)
|
@@ -88,8 +89,8 @@ module Textbringer
|
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
91
|
-
def compile
|
92
|
-
|
92
|
+
def compile(cmd = read_from_minibuffer("Compile: ",
|
93
|
+
default: default_compile_command))
|
93
94
|
shell_execute(cmd, "*Ruby compile result*")
|
94
95
|
backtrace_mode
|
95
96
|
end
|
@@ -98,6 +99,59 @@ module Textbringer
|
|
98
99
|
/[\p{Letter}\p{Number}_$@!?]/
|
99
100
|
end
|
100
101
|
|
102
|
+
def default_compile_command
|
103
|
+
@buffer[:ruby_compile_command] ||
|
104
|
+
if File.exist?("Rakefile")
|
105
|
+
prefix = File.exist?("Gemfile") ? "bundle exec " : ""
|
106
|
+
prefix + "rake"
|
107
|
+
elsif @buffer.file_name
|
108
|
+
"ruby " + @buffer.file_name
|
109
|
+
else
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def toggle_test
|
115
|
+
case @buffer.file_name
|
116
|
+
when %r'(.*)/test/(.*/)?test_(.*?)\.rb\z'
|
117
|
+
base = $1
|
118
|
+
namespace = $2
|
119
|
+
name = $3
|
120
|
+
if namespace
|
121
|
+
paths = Dir.glob("#{base}/{lib,app}/**/#{namespace}#{name}.rb")
|
122
|
+
if !paths.empty?
|
123
|
+
find_file(paths.first)
|
124
|
+
return
|
125
|
+
end
|
126
|
+
end
|
127
|
+
paths = Dir.glob("#{base}/{lib,app}/**/#{name}.rb")
|
128
|
+
if !paths.empty?
|
129
|
+
find_file(paths.first)
|
130
|
+
return
|
131
|
+
end
|
132
|
+
raise EditorError, "Test subject not found"
|
133
|
+
when %r'(.*)/(?:lib|app)/(.*/)?(.*?)\.rb\z'
|
134
|
+
base = $1
|
135
|
+
namespace = $2
|
136
|
+
name = $3
|
137
|
+
if namespace
|
138
|
+
paths = Dir.glob("#{base}/test/**/#{namespace}test_#{name}.rb")
|
139
|
+
if !paths.empty?
|
140
|
+
find_file(paths.first)
|
141
|
+
return
|
142
|
+
end
|
143
|
+
end
|
144
|
+
paths = Dir.glob("#{base}/test/**/test_#{name}.rb")
|
145
|
+
if !paths.empty?
|
146
|
+
find_file(paths.first)
|
147
|
+
return
|
148
|
+
end
|
149
|
+
raise EditorError, "Test not found"
|
150
|
+
else
|
151
|
+
raise EditorError, "Unknown file type"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
101
155
|
private
|
102
156
|
|
103
157
|
def calculate_indentation
|
@@ -109,12 +163,29 @@ module Textbringer
|
|
109
163
|
bol_pos = @buffer.point
|
110
164
|
tokens = Ripper.lex(@buffer.substring(@buffer.point_min,
|
111
165
|
@buffer.point))
|
166
|
+
_, event, = tokens.last
|
167
|
+
if event == :on_tstring_beg ||
|
168
|
+
event == :on_heredoc_beg ||
|
169
|
+
event == :on_tstring_content
|
170
|
+
return nil
|
171
|
+
end
|
112
172
|
line, column, event, = find_nearest_beginning_token(tokens)
|
113
173
|
if event == :on_lparen
|
114
174
|
return column + 1
|
115
175
|
end
|
116
176
|
if line
|
117
177
|
@buffer.goto_line(line)
|
178
|
+
while !@buffer.beginning_of_buffer?
|
179
|
+
if @buffer.save_excursion {
|
180
|
+
@buffer.backward_char
|
181
|
+
@buffer.skip_re_backward(/\s/)
|
182
|
+
@buffer.char_before == ?,
|
183
|
+
}
|
184
|
+
@buffer.backward_line
|
185
|
+
else
|
186
|
+
break
|
187
|
+
end
|
188
|
+
end
|
118
189
|
else
|
119
190
|
@buffer.backward_line
|
120
191
|
end
|
@@ -183,56 +254,5 @@ module Textbringer
|
|
183
254
|
end
|
184
255
|
return nil
|
185
256
|
end
|
186
|
-
|
187
|
-
def default_compile_command
|
188
|
-
@buffer[:ruby_compile_command] ||
|
189
|
-
if File.exist?("Rakefile")
|
190
|
-
prefix = File.exist?("Gemfile") ? "bundle exec " : ""
|
191
|
-
prefix + "rake"
|
192
|
-
else
|
193
|
-
"ruby " + @buffer.file_name
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def toggle_test
|
198
|
-
case @buffer.file_name
|
199
|
-
when %r'(.*)/test/(.*/)?test_(.*?)\.rb\z'
|
200
|
-
base = $1
|
201
|
-
namespace = $2
|
202
|
-
name = $3
|
203
|
-
if namespace
|
204
|
-
paths = Dir.glob("#{base}/{lib,app}/**/#{namespace}#{name}.rb")
|
205
|
-
if !paths.empty?
|
206
|
-
find_file(paths.first)
|
207
|
-
return
|
208
|
-
end
|
209
|
-
end
|
210
|
-
paths = Dir.glob("#{base}/{lib,app}/**/#{name}.rb")
|
211
|
-
if !paths.empty?
|
212
|
-
find_file(paths.first)
|
213
|
-
return
|
214
|
-
end
|
215
|
-
raise EditorError, "Test subject not found"
|
216
|
-
when %r'(.*)/(?:lib|app)/(.*/)?(.*?)\.rb\z'
|
217
|
-
base = $1
|
218
|
-
namespace = $2
|
219
|
-
name = $3
|
220
|
-
if namespace
|
221
|
-
paths = Dir.glob("#{base}/test/**/#{namespace}test_#{name}.rb")
|
222
|
-
if !paths.empty?
|
223
|
-
find_file(paths.first)
|
224
|
-
return
|
225
|
-
end
|
226
|
-
end
|
227
|
-
paths = Dir.glob("#{base}/test/**/#{name}.rb")
|
228
|
-
if !paths.empty?
|
229
|
-
find_file(paths.first)
|
230
|
-
return
|
231
|
-
end
|
232
|
-
raise EditorError, "Test not found"
|
233
|
-
else
|
234
|
-
raise EditorError, "Unknown file type"
|
235
|
-
end
|
236
|
-
end
|
237
257
|
end
|
238
258
|
end
|
data/lib/textbringer/utils.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rbconfig"
|
4
|
+
|
3
5
|
module Textbringer
|
4
6
|
module Utils
|
7
|
+
module_function
|
8
|
+
|
5
9
|
def message(msg, log: true, sit_for: nil, sleep_for: nil)
|
6
10
|
if log && Buffer.current.name != "*Messages*"
|
7
11
|
buffer = Buffer["*Messages*"] ||
|
@@ -15,7 +19,7 @@ module Textbringer
|
|
15
19
|
if buffer.current_line > 1000
|
16
20
|
buffer.beginning_of_buffer
|
17
21
|
10.times do
|
18
|
-
buffer.
|
22
|
+
buffer.forward_line
|
19
23
|
end
|
20
24
|
buffer.delete_region(buffer.point_min, buffer.point)
|
21
25
|
buffer.end_of_buffer
|
@@ -52,7 +56,7 @@ module Textbringer
|
|
52
56
|
Controller.current.received_keyboard_quit?
|
53
57
|
end
|
54
58
|
|
55
|
-
def
|
59
|
+
def show_exception(e)
|
56
60
|
if e.is_a?(SystemExit)
|
57
61
|
raise
|
58
62
|
end
|
@@ -65,8 +69,10 @@ module Textbringer
|
|
65
69
|
begin
|
66
70
|
buffer.delete_region(buffer.point_min, buffer.point_max)
|
67
71
|
buffer.insert("#{e.class}: #{e}\n")
|
68
|
-
e.backtrace
|
69
|
-
|
72
|
+
if e.backtrace
|
73
|
+
e.backtrace.each do |line|
|
74
|
+
buffer.insert(line + "\n")
|
75
|
+
end
|
70
76
|
end
|
71
77
|
buffer.beginning_of_buffer
|
72
78
|
ensure
|
@@ -148,7 +154,7 @@ module Textbringer
|
|
148
154
|
File.expand_path(file)
|
149
155
|
end
|
150
156
|
|
151
|
-
def
|
157
|
+
def complete_for_minibuffer(s, candidates)
|
152
158
|
xs = candidates.select { |i| i.start_with?(s) }
|
153
159
|
if xs.size > 0
|
154
160
|
y, *ys = xs
|
@@ -163,13 +169,13 @@ module Textbringer
|
|
163
169
|
end
|
164
170
|
|
165
171
|
def read_buffer(prompt, default: (Buffer.last || Buffer.current)&.name)
|
166
|
-
f = ->(s) {
|
172
|
+
f = ->(s) { complete_for_minibuffer(s, Buffer.names) }
|
167
173
|
read_from_minibuffer(prompt, completion_proc: f, default: default)
|
168
174
|
end
|
169
175
|
|
170
176
|
def read_command_name(prompt)
|
171
177
|
f = ->(s) {
|
172
|
-
|
178
|
+
complete_for_minibuffer(s.tr("-", "_"), Commands.list.map(&:to_s))
|
173
179
|
}
|
174
180
|
read_from_minibuffer(prompt, completion_proc: f)
|
175
181
|
end
|
@@ -273,5 +279,13 @@ module Textbringer
|
|
273
279
|
add_hook(:pre_command_hook, hook)
|
274
280
|
Controller.current.overriding_map = map
|
275
281
|
end
|
282
|
+
|
283
|
+
def ruby_install_name
|
284
|
+
RbConfig::CONFIG["ruby_install_name"]
|
285
|
+
end
|
286
|
+
|
287
|
+
def insert(s)
|
288
|
+
Buffer.current.insert(s)
|
289
|
+
end
|
276
290
|
end
|
277
291
|
end
|
data/lib/textbringer/version.rb
CHANGED
data/lib/textbringer/window.rb
CHANGED
@@ -191,7 +191,8 @@ module Textbringer
|
|
191
191
|
Curses.beep
|
192
192
|
end
|
193
193
|
|
194
|
-
attr_reader :buffer, :lines, :columns, :y, :x
|
194
|
+
attr_reader :buffer, :lines, :columns, :y, :x, :window, :mode_line
|
195
|
+
attr_reader :top_of_window, :bottom_of_window
|
195
196
|
|
196
197
|
def initialize(lines, columns, y, x)
|
197
198
|
@lines = lines
|
@@ -336,8 +337,9 @@ module Textbringer
|
|
336
337
|
@window.attron(Curses::A_REVERSE)
|
337
338
|
end
|
338
339
|
while !@buffer.end_of_buffer?
|
340
|
+
cury, curx = @window.cury, @window.curx
|
339
341
|
if @buffer.point_at_mark?(point)
|
340
|
-
y, x =
|
342
|
+
y, x = cury, curx
|
341
343
|
if current? && @buffer.visible_mark
|
342
344
|
if @buffer.point_after_mark?(@buffer.visible_mark)
|
343
345
|
@window.attroff(Curses::A_REVERSE)
|
@@ -357,16 +359,31 @@ module Textbringer
|
|
357
359
|
c = @buffer.char_after
|
358
360
|
if c == "\n"
|
359
361
|
@window.clrtoeol
|
360
|
-
break if
|
362
|
+
break if cury == lines - 2 # lines include mode line
|
363
|
+
@window.setpos(cury + 1, 0)
|
364
|
+
@buffer.forward_char
|
365
|
+
next
|
361
366
|
elsif c == "\t"
|
362
|
-
n = calc_tab_width(
|
367
|
+
n = calc_tab_width(curx)
|
363
368
|
c = " " * n
|
364
369
|
else
|
365
370
|
c = escape(c)
|
366
371
|
end
|
372
|
+
if curx < columns - 4
|
373
|
+
newx = nil
|
374
|
+
else
|
375
|
+
newx = curx + Buffer.display_width(c)
|
376
|
+
if newx > columns
|
377
|
+
if cury == lines - 2
|
378
|
+
break
|
379
|
+
else
|
380
|
+
@window.clrtoeol
|
381
|
+
@window.setpos(cury + 1, 0)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
367
385
|
@window.addstr(c)
|
368
|
-
break if
|
369
|
-
@window.curx == columns
|
386
|
+
break if newx == columns && cury == lines - 2
|
370
387
|
@buffer.forward_char
|
371
388
|
end
|
372
389
|
if current? && @buffer.visible_mark
|
@@ -504,7 +521,7 @@ module Textbringer
|
|
504
521
|
@mode_line.addstr(unicode_codepoint(c))
|
505
522
|
@mode_line.addstr(" #{line},#{column}")
|
506
523
|
@mode_line.addstr(" (#{@buffer.mode&.name || 'None'})")
|
507
|
-
@mode_line.addstr(" " * (
|
524
|
+
@mode_line.addstr(" " * (columns - @mode_line.curx))
|
508
525
|
@mode_line.attroff(Curses::A_REVERSE)
|
509
526
|
@mode_line.noutrefresh
|
510
527
|
end
|
@@ -519,13 +536,13 @@ module Textbringer
|
|
519
536
|
|
520
537
|
def escape(s)
|
521
538
|
if @buffer.binary?
|
522
|
-
s.gsub(/[\0-\b\v-\x1f]/) { |c|
|
539
|
+
s.gsub(/[\0-\b\v-\x1f\x7f]/) { |c|
|
523
540
|
"^" + (c.ord ^ 0x40).chr
|
524
541
|
}.gsub(/[\x80-\xff]/n) { |c|
|
525
542
|
"<%02X>" % c.ord
|
526
543
|
}
|
527
544
|
else
|
528
|
-
s.gsub(/[\0-\b\v-\x1f]/) { |c|
|
545
|
+
s.gsub(/[\0-\b\v-\x1f\x7f]/) { |c|
|
529
546
|
"^" + (c.ord ^ 0x40).chr
|
530
547
|
}
|
531
548
|
end
|
@@ -620,6 +637,7 @@ module Textbringer
|
|
620
637
|
end
|
621
638
|
|
622
639
|
class EchoArea < Window
|
640
|
+
attr_reader :message
|
623
641
|
attr_accessor :prompt
|
624
642
|
attr_writer :active
|
625
643
|
|
data/textbringer.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Shugo Maeda"]
|
10
10
|
spec.email = ["shugo@ruby-lang.org"]
|
11
11
|
|
12
|
-
spec.summary = "
|
13
|
-
spec.description = "Textbringer is a member of a demon race that takes on the form of
|
12
|
+
spec.summary = "An Emacs-like text editor"
|
13
|
+
spec.description = "Textbringer is a member of a demon race that takes on the form of an Emacs-like text editor."
|
14
14
|
spec.homepage = "https://github.com/shugo/textbringer"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -23,11 +23,14 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_runtime_dependency "curses", "~> 1.1"
|
25
25
|
spec.add_runtime_dependency "unicode-display_width", "~> 1.1"
|
26
|
+
spec.add_runtime_dependency "clipboard", "~> 1.1"
|
27
|
+
spec.add_runtime_dependency "ffi"
|
26
28
|
|
27
29
|
spec.add_development_dependency "bundler", "~> 1.11"
|
28
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
-
spec.add_development_dependency "simplecov"
|
30
31
|
spec.add_development_dependency "test-unit"
|
32
|
+
spec.add_development_dependency "simplecov"
|
33
|
+
spec.add_development_dependency "codecov"
|
31
34
|
spec.add_development_dependency "bundler-audit"
|
32
35
|
spec.add_development_dependency "guard"
|
33
36
|
spec.add_development_dependency "guard-shell"
|
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.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -38,6 +38,34 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: clipboard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: ffi
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: bundler
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +94,20 @@ dependencies:
|
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
96
|
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: test-unit
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: simplecov
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,7 +123,7 @@ dependencies:
|
|
81
123
|
- !ruby/object:Gem::Version
|
82
124
|
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
126
|
+
name: codecov
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
86
128
|
requirements:
|
87
129
|
- - ">="
|
@@ -150,8 +192,8 @@ dependencies:
|
|
150
192
|
- - ">="
|
151
193
|
- !ruby/object:Gem::Version
|
152
194
|
version: '0'
|
153
|
-
description: Textbringer is a member of a demon race that takes on the form of
|
154
|
-
editor.
|
195
|
+
description: Textbringer is a member of a demon race that takes on the form of an
|
196
|
+
Emacs-like text editor.
|
155
197
|
email:
|
156
198
|
- shugo@ruby-lang.org
|
157
199
|
executables:
|
@@ -173,14 +215,20 @@ files:
|
|
173
215
|
- lib/textbringer.rb
|
174
216
|
- lib/textbringer/buffer.rb
|
175
217
|
- lib/textbringer/commands.rb
|
218
|
+
- lib/textbringer/commands/buffers.rb
|
219
|
+
- lib/textbringer/commands/clipboard.rb
|
176
220
|
- lib/textbringer/commands/ctags.rb
|
177
221
|
- lib/textbringer/commands/dabbrev.rb
|
222
|
+
- lib/textbringer/commands/files.rb
|
223
|
+
- lib/textbringer/commands/isearch.rb
|
224
|
+
- lib/textbringer/commands/misc.rb
|
225
|
+
- lib/textbringer/commands/replace.rb
|
226
|
+
- lib/textbringer/commands/windows.rb
|
178
227
|
- lib/textbringer/config.rb
|
179
228
|
- lib/textbringer/controller.rb
|
180
229
|
- lib/textbringer/errors.rb
|
181
230
|
- lib/textbringer/keymap.rb
|
182
231
|
- lib/textbringer/mode.rb
|
183
|
-
- lib/textbringer/modes.rb
|
184
232
|
- lib/textbringer/modes/backtrace_mode.rb
|
185
233
|
- lib/textbringer/modes/fundamental_mode.rb
|
186
234
|
- lib/textbringer/modes/programming_mode.rb
|
@@ -209,8 +257,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
257
|
version: '0'
|
210
258
|
requirements: []
|
211
259
|
rubyforge_project:
|
212
|
-
rubygems_version: 2.6.
|
260
|
+
rubygems_version: 2.6.10
|
213
261
|
signing_key:
|
214
262
|
specification_version: 4
|
215
|
-
summary:
|
263
|
+
summary: An Emacs-like text editor
|
216
264
|
test_files: []
|
265
|
+
has_rdoc:
|