Module: Textbringer::Commands

Includes:
Utils
Included in:
Mode, Mode
Defined in:
lib/textbringer/commands.rb,
lib/textbringer/commands/fill.rb,
lib/textbringer/commands/help.rb,
lib/textbringer/commands/misc.rb,
lib/textbringer/commands/ctags.rb,
lib/textbringer/commands/files.rb,
lib/textbringer/commands/buffers.rb,
lib/textbringer/commands/dabbrev.rb,
lib/textbringer/commands/isearch.rb,
lib/textbringer/commands/replace.rb,
lib/textbringer/commands/windows.rb,
lib/textbringer/commands/register.rb,
lib/textbringer/commands/clipboard.rb,
lib/textbringer/commands/keyboard_macro.rb

Defined Under Namespace

Modules: SymbolDump Classes: BufferPosition

Constant Summary collapse

HELP_RING =
Ring.new
UNIVERSAL_ARGUMENT_MAP =
Keymap.new
CTAGS =
{
  path: nil,
  tags: nil,
  tags_mtime: nil,
  name: nil,
  candidates: nil,
  index: nil,
  tag_mark_stack: []
}
ISEARCH_MODE_MAP =
Keymap.new
ISEARCH_STATUS =
{
  forward: true,
  string: "",
  last_string: "",
  start: 0,
  last_pos: 0,
  recursive_edit: false
}
RE_SEARCH_STATUS =
{
  last_regexp: nil
}
REGISTERS =
{}
CLIPBOARD_AVAILABLE =
Clipboard.implementation.name != "Clipboard::Linux" ||
(ENV["DISPLAY"] && system("which xclip > /dev/null 2>&1"))
KEYBOARD_MACROS =
{}

Constants included from Utils

Utils::COMPLETION, Utils::HOOKS, Utils::Y_OR_N_MAP

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

add_hook, background, complete_for_minibuffer, message, next_tick, next_tick!, read_buffer, read_char, read_command_name, read_encoding, read_event, read_file_name, read_from_minibuffer, read_key_sequence, read_single_char, received_keyboard_quit?, remove_hook, ruby_install_name, run_hooks, self_insert_and_exit_minibuffer, set_transient_map, show_exception, sit_for, sleep_for, y_or_n?, yes_or_no?

Class Method Details

.[](name) ⇒ Object



22
23
24
# File 'lib/textbringer/commands.rb', line 22

def self.[](name)
  @command_table[name.intern]
end

.command_tableObject



18
19
20
# File 'lib/textbringer/commands.rb', line 18

def self.command_table
  @command_table
end

.define_command(name, doc: "No documentation", &block) ⇒ Object



26
27
28
29
30
31
32
# File 'lib/textbringer/commands.rb', line 26

def define_command(name, doc: "No documentation", &block)
  name = name.intern
  Commands.send(:define_method, name, &block)
  Commands.send(:module_function, name)
  Commands.command_table[name] = Command.new(name, block, doc)
  name
end

.listObject



14
15
16
# File 'lib/textbringer/commands.rb', line 14

def self.list
  @command_table.keys
end

.undefine_command(name) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/textbringer/commands.rb', line 35

def undefine_command(name)
  name = name.intern
  if Commands.command_table.key?(name)
    Commands.send(:undef_method, name)
    Commands.command_table.delete(name)
  end
end

Instance Method Details

#command_help(cmd) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/textbringer/commands/help.rb', line 52

def command_help(cmd)
  s = format("%s:%d\n", *cmd.block.source_location)
  s << "-" * (Window.columns - 2) + "\n"
  s << "#{cmd.name}"
  if !cmd.block.parameters.empty?
    s << "("
    s << cmd.block.parameters.map { |_, param| param }.join(", ")
    s << ")"
  end
  s << "\n\n"
  s << "-" * (Window.columns - 2) + "\n\n"
  s << cmd.doc
  s << "\n"
  s
end

#current_prefix_argObject



161
162
163
# File 'lib/textbringer/commands/misc.rb', line 161

def current_prefix_arg
  Controller.current.current_prefix_arg
end

#execute_keyboard_macro(macro, n = 1) ⇒ Object



40
41
42
# File 'lib/textbringer/commands/keyboard_macro.rb', line 40

def execute_keyboard_macro(macro, n = 1)
  Controller.current.execute_keyboard_macro(macro, n)
end

#get_tagsObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/textbringer/commands/ctags.rb', line 75

def get_tags
  path = File.expand_path("tags")
  mtime = File.mtime(path)
  if CTAGS[:path] != path || CTAGS[:tags_mtime] != mtime
    CTAGS[:path] = path
    tags = Hash.new { |h, k| h[k] = [] }
    File.read(path).scan(/^(.*?)\t(.*?)\t(.*?)(?:;".*)?$/) do
      |name, file, addr|
      n = tags[name].count { |f,| f == file } + 1
      tags[name].push([file, addr, n])
    end
    CTAGS[:tags] = tags
    CTAGS[:tags_mtime] = mtime
    message("Loaded #{path}")
  end
  CTAGS[:tags]
end

#isearch_doneObject



74
75
76
77
78
79
80
81
82
# File 'lib/textbringer/commands/isearch.rb', line 74

def isearch_done
  Buffer.current.delete_visible_mark
  Controller.current.overriding_map = nil
  remove_hook(:pre_command_hook, :isearch_pre_command_hook)
  ISEARCH_STATUS[:last_string] = ISEARCH_STATUS[:string]
  if ISEARCH_STATUS[:recursive_edit]
    exit_recursive_edit
  end
end

#isearch_mode(forward, recursive_edit: false) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/textbringer/commands/isearch.rb', line 44

def isearch_mode(forward, recursive_edit: false)
  ISEARCH_STATUS[:forward] = forward
  ISEARCH_STATUS[:string] = String.new
  ISEARCH_STATUS[:recursive_edit] = recursive_edit
  Controller.current.overriding_map = ISEARCH_MODE_MAP
  run_hooks(:isearch_mode_hook)
  add_hook(:pre_command_hook, :isearch_pre_command_hook)
  ISEARCH_STATUS[:start] = ISEARCH_STATUS[:last_pos] = Buffer.current.point
  if Buffer.current != Buffer.minibuffer
    message(isearch_prompt, log: false)
  end
  if recursive_edit
    recursive_edit()
  end
end

#isearch_pre_command_hookObject



68
69
70
71
72
# File 'lib/textbringer/commands/isearch.rb', line 68

def isearch_pre_command_hook
  if /\Aisearch_/ !~ Controller.current.this_command
    isearch_done
  end
end

#isearch_promptObject



60
61
62
63
64
65
66
# File 'lib/textbringer/commands/isearch.rb', line 60

def isearch_prompt
  if ISEARCH_STATUS[:forward]
    "I-search: "
  else
    "I-search backward: "
  end
end

#isearch_repeat(forward) ⇒ Object



152
153
154
155
156
157
158
159
# File 'lib/textbringer/commands/isearch.rb', line 152

def isearch_repeat(forward)
  ISEARCH_STATUS[:forward] = forward
  ISEARCH_STATUS[:last_pos] = Buffer.current.point
  if ISEARCH_STATUS[:string].empty?
    ISEARCH_STATUS[:string] = ISEARCH_STATUS[:last_string]
  end
  isearch_search
end

#isearch_repeat_backwardObject



148
149
150
# File 'lib/textbringer/commands/isearch.rb', line 148

def isearch_repeat_backward
  isearch_repeat(false)
end

#isearch_repeat_forwardObject



144
145
146
# File 'lib/textbringer/commands/isearch.rb', line 144

def isearch_repeat_forward
  isearch_repeat(true)
end

#isearch_searchObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/textbringer/commands/isearch.rb', line 119

def isearch_search
  forward = ISEARCH_STATUS[:forward]
  options = if /\A[A-Z]/ =~ ISEARCH_STATUS[:string]
              nil
            else
              Regexp::IGNORECASE
            end
  re = Regexp.new(Regexp.quote(ISEARCH_STATUS[:string]), options)
  last_pos = ISEARCH_STATUS[:last_pos]
  offset = forward ? last_pos : last_pos - ISEARCH_STATUS[:string].bytesize
  if Buffer.current.byteindex(forward, re, offset)
    if Buffer.current != Buffer.minibuffer
      message(isearch_prompt + ISEARCH_STATUS[:string], log: false)
    end
    Buffer.current.set_visible_mark(forward ? match_beginning(0) :
                                    match_end(0))
    goto_char(forward ? match_end(0) : match_beginning(0))
  else
    if Buffer.current != Buffer.minibuffer
      message("Failing " + isearch_prompt + ISEARCH_STATUS[:string],
              log: false)
    end
  end
end

#match_beginning(n) ⇒ Object



23
24
25
# File 'lib/textbringer/commands/replace.rb', line 23

def match_beginning(n)
  Buffer.current.match_beginning(n)
end

#match_end(n) ⇒ Object



27
28
29
# File 'lib/textbringer/commands/replace.rb', line 27

def match_end(n)
  Buffer.current.match_end(n)
end

#match_string(n) ⇒ Object



31
32
33
# File 'lib/textbringer/commands/replace.rb', line 31

def match_string(n)
  Buffer.current.match_string(n)
end

#number_prefix_argObject



178
179
180
# File 'lib/textbringer/commands/misc.rb', line 178

def number_prefix_arg
  prefix_numeric_value(current_prefix_arg)
end

#prefix_numeric_value(arg) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/textbringer/commands/misc.rb', line 165

def prefix_numeric_value(arg)
  case arg
  when Integer
    arg
  when Array
    arg.first
  when :-
    -1
  else
    1
  end
end

#read_keyboard_macro(prompt) ⇒ Object



56
57
58
59
60
# File 'lib/textbringer/commands/keyboard_macro.rb', line 56

def read_keyboard_macro(prompt)
  macros = KEYBOARD_MACROS.keys.map(&:to_s)
  f = ->(s) { complete_for_minibuffer(s, macros) }
  read_from_minibuffer(prompt, completion_proc: f)
end

#read_register(prompt) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/textbringer/commands/register.rb', line 28

def read_register(prompt)
  Window.echo_area.show(prompt)
  Window.redisplay
  begin
    register = read_char
    register
  ensure
    Window.echo_area.clear
    Window.redisplay
  end
end

#replace_match(s) ⇒ Object



35
36
37
# File 'lib/textbringer/commands/replace.rb', line 35

def replace_match(s)
  Buffer.current.replace_match(s)
end

#universal_argument_modeObject



152
153
154
# File 'lib/textbringer/commands/misc.rb', line 152

def universal_argument_mode
  set_transient_map(UNIVERSAL_ARGUMENT_MAP)
end