textbringer 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,4 +9,10 @@ module Textbringer
9
9
 
10
10
  class ReadOnlyError < EditorError
11
11
  end
12
+
13
+ class Quit < EditorError
14
+ def initialize
15
+ super("Quit")
16
+ end
17
+ end
12
18
  end
@@ -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
- cmd = read_from_minibuffer("Compile: ", default: default_compile_command)
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
@@ -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.next_line
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 handle_exception(e)
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.each do |line|
69
- buffer.insert(line + "\n")
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 complete(s, candidates)
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) { complete(s, Buffer.names) }
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
- complete(s.tr("-", "_"), Commands.list.map(&:to_s))
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
@@ -1,3 +1,3 @@
1
1
  module Textbringer
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -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 = @window.cury, @window.curx
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 @window.cury == lines - 2 # lines include mode line
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(@window.curx)
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 @window.cury == lines - 2 && # lines include mode line
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(" " * (@mode_line.maxx - @mode_line.curx))
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
 
@@ -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 = "A text editor"
13
- spec.description = "Textbringer is a member of a demon race that takes on the form of a text editor."
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
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-01-29 00:00:00.000000000 Z
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: test-unit
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 a text
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.8
260
+ rubygems_version: 2.6.10
213
261
  signing_key:
214
262
  specification_version: 4
215
- summary: A text editor
263
+ summary: An Emacs-like text editor
216
264
  test_files: []
265
+ has_rdoc: