Module: VER::Methods::Control

Defined in:
lib/ver/methods/control.rb

Constant Summary collapse

ENV_EXPORTERS =
%w[
  current_line current_word directory filepath line_index line_number
  scope selected_text
]

Class Method Summary collapse

Class Method Details

.chdir(text) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/ver/methods/control.rb', line 95

def chdir(text)
  text.ask 'Change to: ' do |path, action|
    case action
    when :attempt
      path = File.expand_path(path.to_s)

      begin
        Dir.chdir(path)
        text.message 'Changed working directory to %s' % [path]
        :abort
      rescue Errno::ENOENT => ex
        VER.warn ex
      end
    end
  end
end

.clean_line(text, index, record = text) ⇒ Object



404
405
406
407
408
409
410
# File 'lib/ver/methods/control.rb', line 404

def clean_line(text, index, record = text)
  index = text.index(index)
  from, to = index.linestart, index.lineend
  line = text.get(from, to)
  bare = line.rstrip
  record.replace(from, to, bare) if bare.empty?
end

.cursor_horizontal_center(buffer) ⇒ Object



88
89
90
91
92
93
# File 'lib/ver/methods/control.rb', line 88

def cursor_horizontal_center(buffer)
  x, y, width, height = *buffer.bbox('insert')
  line_middle = y + (height / 2) # gives less room for error?
  buffer_middle = buffer.winfo_width / 2
  set("@#{buffer_middle},#{y}")
end

.cursor_vertical_bottom(text) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/ver/methods/control.rb', line 73

def cursor_vertical_bottom(text)
  insert = text.count('1.0', 'insert', :displaylines) + 1
  last   = text.count('1.0', 'end', :displaylines)
  shown  = text.count('@0,0', "@0,#{text.winfo_height}", :displaylines)

  fraction = ((100.0 / last) * (insert - shown)) / 100

  text.yview_moveto(fraction)
end

.cursor_vertical_bottom_sol(text) ⇒ Object



83
84
85
86
# File 'lib/ver/methods/control.rb', line 83

def cursor_vertical_bottom_sol(text)
  cursor_vertical_bottom(text)
  start_of_line(text)
end

.cursor_vertical_center(text, index = :insert) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'lib/ver/methods/control.rb', line 58

def cursor_vertical_center(text, index = :insert)
  insert = text.count('1.0', index, :displaylines)
  last   = text.count('1.0', 'end', :displaylines)
  shown  = text.count('@0,0', "@0,#{text.winfo_height}", :displaylines)

  fraction = ((100.0 / last) * (insert - (shown / 2))) / 100

  text.yview_moveto(fraction)
end

.cursor_vertical_center_sol(text) ⇒ Object



68
69
70
71
# File 'lib/ver/methods/control.rb', line 68

def cursor_vertical_center_sol(text)
  cursor_vertical_center(text)
  Move.start_of_line(text)
end

.cursor_vertical_top(text) ⇒ Object



44
45
46
47
48
49
50
51
# File 'lib/ver/methods/control.rb', line 44

def cursor_vertical_top(text)
  insert = text.count('1.0', 'insert', :displaylines)
  last   = text.count('1.0', 'end', :displaylines)

  fraction = ((100.0 / last) * insert) / 100

  text.yview_moveto(fraction)
end

.cursor_vertical_top_sol(text) ⇒ Object



53
54
55
56
# File 'lib/ver/methods/control.rb', line 53

def cursor_vertical_top_sol(text)
  cursor_vertical_top(text)
  Move.start_of_line(text)
end

.enter(text, old_mode, new_mode) ⇒ Object



6
7
8
# File 'lib/ver/methods/control.rb', line 6

def enter(text, old_mode, new_mode)
  clean_line(text, :insert)
end

.exec_bundleObject

Set up the env for a script, then execute it. For now, I only setup the env, until we figure out a good way to find bundle commands.



179
180
181
182
183
184
185
186
# File 'lib/ver/methods/control.rb', line 179

def exec_bundle
  ENV_EXPORTERS.each do |exporter|
    ENV["VER_#{exporter.upcase}"] = ENV["TM_#{exporter.upcase}"] =
      send("exec_env_#{exporter}").to_s
  end

  yield if block_given?
end

.exec_env_current_lineObject

textual content of the current line



189
190
191
# File 'lib/ver/methods/control.rb', line 189

def exec_env_current_line
  get('insert linestart', 'insert lineend')
end

.exec_env_current_wordObject

the word in which the caret is located.



194
195
196
# File 'lib/ver/methods/control.rb', line 194

def exec_env_current_word
  get('insert wordstart', 'insert wordend')
end

.exec_env_directoryObject

the folder of the current document (may not be set).



199
200
201
# File 'lib/ver/methods/control.rb', line 199

def exec_env_directory
  filename.dirname.to_s
end

.exec_env_filepathObject

path (including file name) for the current document (may not be set).



204
205
206
# File 'lib/ver/methods/control.rb', line 204

def exec_env_filepath
  filename.to_s
end

.exec_env_line_indexObject

the index in the current line which marks the caret’s location. This index is zero-based and takes the utf-8 encoding of the line (e.g. read as TM_CURRENT_LINE) into account.



211
212
213
# File 'lib/ver/methods/control.rb', line 211

def exec_env_line_index
  index('insert').x
end

.exec_env_line_numberObject

the carets line position (counting from 1).



216
217
218
# File 'lib/ver/methods/control.rb', line 216

def exec_env_line_number
  index('insert').y
end

.exec_env_scopeObject



220
221
222
# File 'lib/ver/methods/control.rb', line 220

def exec_env_scope
  tag_names('insert').join(', ')
end

.exec_env_selected_textObject

full content of the selection (may not be set). Note that environment variables have a size limitation of roughly 64 KB, so if the user selects more than that, this variable will not reflect the actual selection (commands that need to work with the selection should generally set this to be the standard input).



229
230
231
232
233
234
235
236
237
# File 'lib/ver/methods/control.rb', line 229

def exec_env_selected_text
  content = []

  each_selected_line do |y, fx, tx|
    content << get("#{y}.#{fx}", "#{y}.#{tx}")
  end

  content.join("\n")
end

.exec_into_new(text, command = nil) ⇒ Object



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/ver/methods/control.rb', line 239

def exec_into_new(text, command = nil)
  if command
    target = text.options.home_conf_dir/'shell-result.txt'
    prepare_exec(command)
    system(command)
    target.open('w+'){|io| io.write(`#{command}`) }
    VER.find_or_create_buffer(target)
  else
    text.ask 'Command: ' do |answer, action|
      case action
      when :attempt
        begin
          exec_into_new(answer)
          :abort
        rescue => ex
          VER.warn(ex)
        end
      end
    end
  end
end

.exec_into_void(text) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/ver/methods/control.rb', line 261

def exec_into_void(text)
  text.ask 'Command: ' do |command, action|
    case action
    when :attempt
      begin
        system(command)
        text.message("Exit code: #{$?}")
        :abort
      rescue => ex
        VER.warn(ex)
      end
    end
  end
end

.executor(text, action = nil) ⇒ Object Also known as: ex



305
306
307
# File 'lib/ver/methods/control.rb', line 305

def executor(text, action = nil)
  VER::Executor.new(text, action: action)
end

.gsub(text, regexp, with) ⇒ Object

Substitute over all lines of the buffer



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/ver/methods/control.rb', line 277

def gsub(text, regexp, with)
  total = 0
  Undo.record text do |record|
    text.index('1.0').upto(text.index('end')) do |index|
      lineend = index.lineend
      line = text.get(index, lineend)

      if line.gsub!(regexp, with)
        record.replace(index, lineend, line)
        total += 1
      end
    end
  end

  text.message "Performed gsub on #{total} lines"
end

.indent_line(text, count = text.prefix_count) ⇒ Object



383
384
385
386
# File 'lib/ver/methods/control.rb', line 383

def indent_line(text, count = text.prefix_count)
  indent = (' ' * text.options[:shiftwidth] * count)
  text.insert('insert linestart', indent)
end

.insert_at(text, motion, *count) ⇒ Object



18
19
20
21
# File 'lib/ver/methods/control.rb', line 18

def insert_at(text, motion, *count)
  Move.send(motion, text, *count)
  text.minor_mode(:control, :insert)
end

.insert_indented_newline_above(text) ⇒ Object



23
24
25
# File 'lib/ver/methods/control.rb', line 23

def insert_indented_newline_above(text)
  Insert.insert_indented_newline_above(text)
end

.insert_indented_newline_below(text) ⇒ Object



27
28
29
# File 'lib/ver/methods/control.rb', line 27

def insert_indented_newline_below(text)
  Insert.insert_indented_newline_below(text)
end

.join_backward(text) ⇒ Object



377
378
379
380
381
# File 'lib/ver/methods/control.rb', line 377

def join_backward(text)
  from, to = 'insert - 1 lines linestart', 'insert lineend'
  lines = text.get(from, to)
  text.replace(from, to, lines.gsub(/\s*\n\s*/, ' '))
end

.join_forward(buffer, count = buffer.prefix_count) ⇒ Object

for some odd reason, vim likes to have arbitrary commands that reduce the argument by one if it’s greater 1…



357
358
359
360
361
362
363
364
365
# File 'lib/ver/methods/control.rb', line 357

def join_forward(buffer, count = buffer.prefix_count)
  count = count > 1 ? (count - 1) : count
  buffer.undo_record do |record|
    count.times do
      buffer.insert = buffer.at_insert.lineend
      record.replace('insert', 'insert + 1 chars', ' ')
    end
  end
end

.join_forward_nospace(buffer, count = buffer.prefix_count) ⇒ Object



367
368
369
370
371
372
373
374
375
# File 'lib/ver/methods/control.rb', line 367

def join_forward_nospace(buffer, count = buffer.prefix_count)
  count = count > 1 ? (count - 1) : count
  buffer.undo_record do |record|
    count.times do
      buffer.insert = buffer.at_insert.lineend
      record.replace('insert', 'insert + 1 chars', '')
    end
  end
end

.leave(text, old_mode, new_mode) ⇒ Object



10
11
12
# File 'lib/ver/methods/control.rb', line 10

def leave(text, old_mode, new_mode)
  # clean_line(text, :insert)
end

.line_evaluate(text) ⇒ Object



329
330
331
332
333
334
335
# File 'lib/ver/methods/control.rb', line 329

def line_evaluate(text)
  code = text.get('insert linestart', 'insert lineend')
  file = (text.filename || text.uri).to_s
  stdout_capture_evaluate(code, file, binding) do |res, out|
    text.at_insert.lineend.insert("\n%s%p" % [out, res])
  end
end

.open_file_under_cursor(text) ⇒ Object



31
32
33
# File 'lib/ver/methods/control.rb', line 31

def open_file_under_cursor(text)
  Open.open_file_under_cursor(text)
end

.prepare_exec(text, command) ⇒ Object

Assigns env variables used in the given command.

  • $f: The current buffer’s filename

  • $d: The current buffer’s directory

  • $F: A space-separated list of all buffer filenames

  • $i: A string acquired from the user with a prompt

  • $c: The current clipboard text

  • $s: The currently selected text

Parameters:

  • command (String)

    The string containing the command executed



132
133
134
135
136
137
138
139
# File 'lib/ver/methods/control.rb', line 132

def prepare_exec(text, command)
  prepare_exec_f(text) if command =~ /\$f/
  prepare_exec_d(text) if command =~ /\$d/
  prepare_exec_F(text) if command =~ /\$F/
  prepare_exec_i(text) if command =~ /\$i/
  prepare_exec_c(text) if command =~ /\$c/
  prepare_exec_s(text) if command =~ /\$s/
end

.prepare_exec_c(text) ⇒ Object



157
158
159
# File 'lib/ver/methods/control.rb', line 157

def prepare_exec_c(text)
  p c: (ENV['c'] = clipboard_get)
end

.prepare_exec_d(text) ⇒ Object



145
146
147
# File 'lib/ver/methods/control.rb', line 145

def prepare_exec_d(text)
  p d: (ENV['d'] = filename.directory.to_s)
end

.prepare_exec_F(text) ⇒ Object



149
150
151
# File 'lib/ver/methods/control.rb', line 149

def prepare_exec_F(text)
  p F: (ENV['F'] = VER.buffers.map{|key, buffer| buffer.filename }.join(' '))
end

.prepare_exec_f(text) ⇒ Object



141
142
143
# File 'lib/ver/methods/control.rb', line 141

def prepare_exec_f(text)
  p f: (ENV['f'] = filename.to_s)
end

.prepare_exec_i(text) ⇒ Object

Raises:

  • (NotImplementedError)


153
154
155
# File 'lib/ver/methods/control.rb', line 153

def prepare_exec_i(text)
  raise NotImplementedError
end

.prepare_exec_s(text) ⇒ Object



161
162
163
164
165
166
167
168
169
# File 'lib/ver/methods/control.rb', line 161

def prepare_exec_s(text)
  content = []

  each_selected_line do |y, fx, tx|
    content << get("#{y}.#{fx}", "#{y}.#{tx}")
  end

  ENV['s'] = content.join("\n")
end

.smart_evaluate(text) ⇒ Object



320
321
322
323
324
325
326
327
# File 'lib/ver/methods/control.rb', line 320

def smart_evaluate(text)
  if sel = text.tag_ranges(:sel)
    from, to = sel.first
    return Selection.evaluate(text) if from && to
  end

  line_evaluate(text)
end

.source_buffer(buffer) ⇒ Object



35
36
37
38
39
40
41
42
# File 'lib/ver/methods/control.rb', line 35

def source_buffer(buffer)
  if filename = buffer.filename
    buffer.message("Source #{filename}")
    load(filename.to_s)
  else
    buffer.warn("#{buffer.uri} is no file")
  end
end

.stdout_capture_evaluate(code, file, binding = binding) ⇒ Object



337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/ver/methods/control.rb', line 337

def stdout_capture_evaluate(code, file, binding = binding)
  begin
    old_stdout = $stdout.dup
    rd, wr = IO.pipe
    $stdout.reopen(wr)
    result = eval(code, binding, file.to_s)
    $stdout.reopen old_stdout; wr.close
    stdout = rd.read

    yield(result, stdout)
  rescue Exception => exception
    yield(exception, '')
  ensure
    wr.closed? || $stdout.reopen(old_stdout) && wr.close
    rd.closed? || rd.close
  end
end

.sub(text, regexp, with) ⇒ Object

Substitute on current line



295
296
297
298
299
300
301
302
303
# File 'lib/ver/methods/control.rb', line 295

def sub(text, regexp, with)
  linestart = text.index('insert linestart')
  lineend = linestart.lineend
  line = text.get(linestart, lineend)

  if line.sub!(regexp, with)
    text.replace(linestart, lineend, line)
  end
end

.temporary(buffer, action) ⇒ Object



14
15
16
# File 'lib/ver/methods/control.rb', line 14

def temporary(buffer, action)
  action.to_method(buffer).call
end

.toggle_case(text, count = text.prefix_count) ⇒ Object

Toggle case of the character under the cursor up to count characters forward (count is inclusive the first character). This only works for alphabetic ASCII characters, no other encodings.



115
116
117
118
119
120
# File 'lib/ver/methods/control.rb', line 115

def toggle_case(text, count = text.prefix_count)
  from, to = 'insert', "insert + #{count} chars"
  chunk = text.get(from, to)
  chunk.tr!('a-zA-Z', 'A-Za-z')
  text.replace(from, to, chunk)
end

.unindent_line(text, count = text.prefix_count) ⇒ Object



388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/ver/methods/control.rb', line 388

def unindent_line(text, count = text.prefix_count)
  indent = ' ' * text.options[:shiftwidth]
  replace_from = 'insert linestart'
  replace_to = "insert linestart + #{indent.size} chars"

  Undo.record text do |record|
    count.times do
      line = text.get('insert linestart', 'insert lineend')

      return unless line.start_with?(indent)

      record.replace(replace_from, replace_to, '')
    end
  end
end

.wrap_line(text) ⇒ Object



311
312
313
314
315
316
317
318
# File 'lib/ver/methods/control.rb', line 311

def wrap_line(text)
  content = text.get('insert linestart', 'insert lineend')
  textwidth = text.options.textwidth
  lines = wrap_lines_of(content, textwidth).join("\n")
  lines.rstrip!

  text.replace('insert linestart', 'insert lineend', lines)
end

.wrap_lines_of(content, wrap = 80) ⇒ Object



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/ver/methods/control.rb', line 412

def wrap_lines_of(content, wrap = 80)
  Kernel.raise ArgumentError, "+wrap+ must be > 1" unless wrap > 1
  wrap -= 1

  indent = content[/^\s+/] || ''
  indent_size = indent.size
  lines = [indent.dup]

  content.scan(/\S+/) do |chunk|
    last = lines.last
    last_size = last.size
    chunk_size = chunk.size

    if last_size + chunk_size > wrap
      lines << indent + chunk
    elsif last_size == indent_size
      last << chunk
    elsif chunk =~ /\.$/
      last << ' ' << chunk
      lines << indent.dup
    else
      last << ' ' << chunk
    end
  end

  lines.pop if lines.last == indent
  lines
end