lib/textbringer/commands.rb in textbringer-0.1.4 vs lib/textbringer/commands.rb in textbringer-0.1.5
- old
+ new
@@ -24,684 +24,7 @@
Commands.send(:undef_method, name)
@@command_list.delete(name)
end
end
module_function :undefine_command
-
- define_command(:version) do
- message("Textbringer #{Textbringer::VERSION} "\
- "(ruby #{RUBY_VERSION} [#{RUBY_PLATFORM}])")
- end
-
- [
- :forward_char,
- :backward_char,
- :forward_word,
- :backward_word,
- :next_line,
- :previous_line,
- :delete_char,
- :backward_delete_char,
- ].each do |name|
- define_command(name) do |n = number_prefix_arg|
- Buffer.current.send(name, n)
- end
- end
-
- [
- :beginning_of_line,
- :end_of_line,
- :beginning_of_buffer,
- :end_of_buffer,
- :exchange_point_and_mark,
- :copy_region,
- :kill_region,
- :yank,
- :newline,
- :delete_region,
- :transpose_chars
- ].each do |name|
- define_command(name) do
- Buffer.current.send(name)
- end
- end
-
- define_command(:set_mark_command) do
- Buffer.current.set_mark
- message("Mark set")
- end
-
- define_command(:goto_char) do
- |n = read_from_minibuffer("Go to char: ")|
- Buffer.current.goto_char(n.to_i)
- Window.current.recenter_if_needed
- end
-
- define_command(:goto_line) do
- |n = read_from_minibuffer("Go to line: ")|
- Buffer.current.goto_line(n.to_i)
- Window.current.recenter_if_needed
- end
-
- define_command(:self_insert) do |n = number_prefix_arg|
- c = Controller.current.last_key
- merge_undo = Controller.current.last_command == :self_insert
- n.times do
- Buffer.current.insert(c, merge_undo)
- end
- end
-
- define_command(:quoted_insert) do |n = number_prefix_arg|
- c = Controller.current.read_char
- if !c.is_a?(String)
- raise "Invalid key"
- end
- n.times do
- Buffer.current.insert(c)
- end
- end
-
- define_command(:kill_line) do
- Buffer.current.kill_line(Controller.current.last_command == :kill_region)
- Controller.current.this_command = :kill_region
- end
-
- define_command(:kill_word) do
- Buffer.current.kill_word(Controller.current.last_command == :kill_region)
- Controller.current.this_command = :kill_region
- end
-
- define_command(:yank_pop) do
- if Controller.current.last_command != :yank
- raise EditorError, "Previous command was not a yank"
- end
- Buffer.current.yank_pop
- Controller.current.this_command = :yank
- end
-
- RE_SEARCH_STATUS = {
- last_regexp: nil
- }
-
- define_command(:re_search_forward) do
- |s = read_from_minibuffer("RE search: ",
- default: RE_SEARCH_STATUS[:last_regexp])|
- RE_SEARCH_STATUS[:last_regexp] = s
- Buffer.current.re_search_forward(s)
- end
-
- define_command(:re_search_backward) do
- |s = read_from_minibuffer("RE search backward: ",
- default: RE_SEARCH_STATUS[:last_regexp])|
- RE_SEARCH_STATUS[:last_regexp] = s
- Buffer.current.re_search_backward(s)
- end
-
- def match_beginning(n)
- Buffer.current.match_beginning(n)
- end
-
- def match_end(n)
- Buffer.current.match_end(n)
- end
-
- def match_string(n)
- Buffer.current.match_string(n)
- end
-
- def replace_match(s)
- Buffer.current.replace_match(s)
- end
-
- define_command(:query_replace_regexp) do
- |regexp = read_from_minibuffer("Query replace regexp: "),
- to_str = read_from_minibuffer("with: ")|
- n = 0
- begin
- loop do
- re_search_forward(regexp)
- Window.current.recenter_if_needed
- Buffer.current.set_visible_mark(match_beginning(0))
- begin
- Window.redisplay
- c = read_single_char("Replace?", [?y, ?n, ?!, ?q, ?.])
- case c
- when ?y
- replace_match(to_str)
- n += 1
- when ?n
- # do nothing
- when ?!
- replace_match(to_str)
- n += 1 + Buffer.current.replace_regexp_forward(regexp, to_str)
- Buffer.current.merge_undo(2)
- break
- when ?q
- break
- when ?.
- replace_match(to_str)
- n += 1
- break
- end
- ensure
- Buffer.current.delete_visible_mark
- end
- end
- rescue SearchError
- end
- if n == 1
- message("Replaced 1 occurrence")
- else
- message("Replaced #{n} occurrences")
- end
- end
-
- define_command(:undo) do
- Buffer.current.undo
- message("Undo!")
- end
-
- define_command(:redo) do
- Buffer.current.redo
- message("Redo!")
- end
-
- define_command(:resize_window) do
- Window.resize
- end
-
- define_command(:recenter) do
- Window.current.recenter
- Window.redraw
- end
-
- define_command(:scroll_up) do
- Window.current.scroll_up
- end
-
- define_command(:scroll_down) do
- Window.current.scroll_down
- end
-
- define_command(:delete_window) do
- Window.delete_window
- end
-
- define_command(:delete_other_windows) do
- Window.delete_other_windows
- end
-
- define_command(:split_window) do
- Window.current.split
- end
-
- define_command(:other_window) do
- Window.other_window
- end
-
- define_command(:exit_textbringer) do |status = 0|
- if Buffer.any? { |buffer| /\A\*/ !~ buffer.name && buffer.modified? }
- return unless yes_or_no?("Unsaved buffers exist; exit anyway?")
- end
- exit(status)
- end
-
- define_command(:suspend_textbringer) do
- Curses.close_screen
- Process.kill(:STOP, $$)
- end
-
- define_command(:pwd) do
- message(Dir.pwd)
- end
-
- define_command(:chdir) do
- |dir_name = read_file_name("Change directory: ")|
- Dir.chdir(dir_name)
- end
-
- define_command(:find_file) do
- |file_name = read_file_name("Find file: ")|
- buffer = Buffer.find_file(file_name)
- if buffer.new_file?
- message("New file")
- end
- switch_to_buffer(buffer)
- shebang = buffer.save_excursion {
- buffer.beginning_of_buffer
- buffer.looking_at?(/#!.*$/) ? buffer.match_string(0) : nil
- }
- mode = Mode.list.find { |m|
- (m.file_name_pattern &&
- m.file_name_pattern =~ File.basename(buffer.file_name)) ||
- (m.interpreter_name_pattern &&
- m.interpreter_name_pattern =~ shebang)
- } || FundamentalMode
- send(mode.command_name)
- end
-
- define_command(:switch_to_buffer) do
- |buffer_name = read_buffer("Switch to buffer: ")|
- if buffer_name.is_a?(Buffer)
- buffer = buffer_name
- else
- buffer = Buffer[buffer_name]
- end
- if buffer
- Window.current.buffer = Buffer.current = buffer
- else
- message("No such buffer: #{buffer_name}")
- end
- end
-
- define_command(:save_buffer) do
- if Buffer.current.file_name.nil?
- Buffer.current.file_name = read_file_name("File to save in: ")
- next if Buffer.current.file_name.nil?
- end
- if Buffer.current.file_modified?
- unless yes_or_no?("File changed on disk. Save anyway?")
- message("Cancelled")
- next
- end
- end
- Buffer.current.save
- message("Wrote #{Buffer.current.file_name}")
- end
-
- define_command(:write_file) do
- |file_name = read_file_name("Write file: ")|
- if File.directory?(file_name)
- file_name = File.expand_path(Buffer.current.name, file_name)
- end
- if File.exist?(file_name)
- unless y_or_n?("File `#{file_name}' exists; overwrite?")
- message("Cancelled")
- next
- end
- end
- Buffer.current.save(file_name)
- message("Wrote #{Buffer.current.file_name}")
- end
-
- define_command(:kill_buffer) do
- |name = read_buffer("Kill buffer: ", default: Buffer.current.name)|
- if name.is_a?(Buffer)
- buffer = name
- else
- buffer = Buffer[name]
- end
- if buffer.modified?
- next unless yes_or_no?("The last change is not saved; kill anyway?")
- message("Arioch! Arioch! Blood and souls for my Lord Arioch!")
- end
- buffer.kill
- if Buffer.count == 0
- buffer = Buffer.new_buffer("*scratch*")
- switch_to_buffer(buffer)
- elsif Buffer.current.nil?
- switch_to_buffer(Buffer.last)
- end
- end
-
- define_command(:set_buffer_file_encoding) do
- |enc = read_from_minibuffer("File encoding: ",
- default: Buffer.current.file_encoding.name)|
- Buffer.current.file_encoding = Encoding.find(enc)
- end
-
- define_command(:set_buffer_file_format) do
- |format = read_from_minibuffer("File format: ",
- default: Buffer.current.file_format.to_s)|
- Buffer.current.file_format = format
- end
-
- define_command(:execute_command) do
- |cmd = read_command_name("M-x ").strip.intern|
- unless Commands.list.include?(cmd)
- raise EditorError, "Undefined command: #{cmd}"
- end
- Controller.current.this_command = cmd
- send(cmd)
- end
-
- define_command(:eval_expression) do
- |s = read_from_minibuffer("Eval: ")|
- message(eval(s, TOPLEVEL_BINDING, "(eval_expression)", 1).inspect)
- end
-
- define_command(:eval_buffer) do
- buffer = Buffer.current
- result = eval(buffer.to_s, TOPLEVEL_BINDING,
- buffer.file_name || buffer.name, 1)
- message(result.inspect)
- end
-
- define_command(:eval_region) do
- buffer = Buffer.current
- b, e = buffer.point, buffer.mark
- if e < b
- b, e = e, b
- end
- result = eval(buffer.substring(b, e), TOPLEVEL_BINDING,
- "(eval_region)", 1)
- message(result.inspect)
- end
-
- define_command(:exit_recursive_edit) do
- if @recursive_edit_level == 0
- raise EditorError, "No recursive edit is in progress"
- end
- throw RECURSIVE_EDIT_TAG, false
- end
-
- define_command(:abort_recursive_edit) do
- if @recursive_edit_level == 0
- raise EditorError, "No recursive edit is in progress"
- end
- throw RECURSIVE_EDIT_TAG, true
- end
-
- define_command(:top_level) do
- throw TOP_LEVEL_TAG
- end
-
- define_command(:complete_minibuffer) do
- minibuffer = Buffer.minibuffer
- completion_proc = minibuffer[:completion_proc]
- if completion_proc
- s = completion_proc.call(minibuffer.to_s)
- if s
- minibuffer.delete_region(minibuffer.point_min,
- minibuffer.point_max)
- minibuffer.insert(s)
- end
- end
- end
-
- UNIVERSAL_ARGUMENT_MAP = Keymap.new
- (?0..?9).each do |c|
- UNIVERSAL_ARGUMENT_MAP.define_key(c, :digit_argument)
- GLOBAL_MAP.define_key("\e#{c}", :digit_argument)
- end
- UNIVERSAL_ARGUMENT_MAP.define_key(?-, :negative_argument)
- UNIVERSAL_ARGUMENT_MAP.define_key(?\C-u, :universal_argument_more)
-
- def universal_argument_mode
- set_transient_map(UNIVERSAL_ARGUMENT_MAP)
- end
-
- define_command(:universal_argument) do
- Controller.current.prefix_arg = [4]
- universal_argument_mode
- end
-
- def current_prefix_arg
- Controller.current.current_prefix_arg
- end
-
- def number_prefix_arg
- arg = current_prefix_arg
- case arg
- when Integer
- arg
- when Array
- arg.first
- when :-
- -1
- else
- 1
- end
- end
-
- define_command(:digit_argument) do
- |arg = current_prefix_arg|
- n = last_key.to_i
- Controller.current.prefix_arg =
- case arg
- when Integer
- arg * 10 + (arg < 0 ? -n : n)
- when :-
- -n
- else
- n
- end
- universal_argument_mode
- end
-
- define_command(:negative_argument) do
- |arg = current_prefix_arg|
- Controller.current.prefix_arg =
- case arg
- when Integer
- -arg
- when :-
- nil
- else
- :-
- end
- universal_argument_mode
- end
-
- define_command(:universal_argument_more) do
- |arg = current_prefix_arg|
- Controller.current.prefix_arg =
- case arg
- when Array
- [4 * arg.first]
- when :-
- [-4]
- else
- nil
- end
- if Controller.current.prefix_arg
- universal_argument_mode
- end
- end
-
- define_command(:keyboard_quit) do
- raise Quit
- end
-
- define_command(:recursive_edit) do
- Controller.current.recursive_edit
- end
-
- ISEARCH_MODE_MAP = Keymap.new
- (?\x20..?\x7e).each do |c|
- ISEARCH_MODE_MAP.define_key(c, :isearch_printing_char)
- end
- ISEARCH_MODE_MAP.define_key(?\t, :isearch_printing_char)
- ISEARCH_MODE_MAP.handle_undefined_key do |key|
- if key.is_a?(String) && /[\0-\x7f]/ !~ key
- :isearch_printing_char
- else
- nil
- end
- end
- ISEARCH_MODE_MAP.define_key(:backspace, :isearch_delete_char)
- ISEARCH_MODE_MAP.define_key(?\C-h, :isearch_delete_char)
- ISEARCH_MODE_MAP.define_key(?\C-s, :isearch_repeat_forward)
- ISEARCH_MODE_MAP.define_key(?\C-r, :isearch_repeat_backward)
- ISEARCH_MODE_MAP.define_key(?\n, :isearch_exit)
- ISEARCH_MODE_MAP.define_key(?\C-g, :isearch_abort)
-
- ISEARCH_STATUS = {
- forward: true,
- string: "",
- last_string: "",
- start: 0,
- last_pos: 0
- }
-
- define_command(:isearch_forward) do
- isearch_mode(true)
- end
-
- define_command(:isearch_backward) do
- isearch_mode(false)
- end
-
- def isearch_mode(forward)
- ISEARCH_STATUS[:forward] = forward
- ISEARCH_STATUS[:string] = String.new
- 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
- end
-
- def isearch_prompt
- if ISEARCH_STATUS[:forward]
- "I-search: "
- else
- "I-search backward: "
- end
- end
-
- def isearch_pre_command_hook
- if /\Aisearch_/ !~ Controller.current.this_command
- isearch_done
- end
- end
-
- 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]
- end
-
- define_command(:isearch_exit) do
- isearch_done
- end
-
- define_command(:isearch_abort) do
- goto_char(Buffer.current[:isearch_start])
- isearch_done
- raise Quit
- end
-
- define_command(:isearch_printing_char) do
- c = Controller.current.last_key
- ISEARCH_STATUS[:string].concat(c)
- isearch_search
- end
-
- define_command(:isearch_delete_char) do
- ISEARCH_STATUS[:string].chop!
- isearch_search
- end
-
- 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("Falling " + isearch_prompt + ISEARCH_STATUS[:string],
- log: false)
- end
- end
- end
-
- def isearch_repeat_forward
- isearch_repeat(true)
- end
-
- def isearch_repeat_backward
- isearch_repeat(false)
- end
-
- 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
-
- define_command(:shell_execute) do
- |cmd = read_from_minibuffer("Shell execute: "),
- buffer_name = "*Shell output*"|
- buffer = Buffer.find_or_new(buffer_name)
- switch_to_buffer(buffer)
- buffer.read_only = false
- buffer.clear
- Window.redisplay
- signals = [:INT, :TERM, :KILL]
- begin
- if /mswin32|mingw32/ =~ RUBY_PLATFORM
- opts = {}
- else
- opts = {pgroup: true}
- end
- Open3.popen2e(cmd, opts) do |input, output, wait_thread|
- input.close
- loop do
- status = output.wait_readable(0.5)
- if status == false
- break # EOF
- end
- if status
- begin
- s = output.read_nonblock(1024).force_encoding("utf-8").
- scrub("\u{3013}").gsub(/\r\n/, "\n")
- buffer.insert(s)
- Window.redisplay
- rescue EOFError
- break
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
- next
- end
- end
- if received_keyboard_quit?
- if signals.empty?
- keyboard_quit
- else
- sig = signals.shift
- message("Send #{sig} to #{wait_thread.pid}")
- Process.kill(sig, -wait_thread.pid)
- end
- end
- end
- status = wait_thread.value
- pid = status.pid
- if status.exited?
- code = status.exitstatus
- message("Process #{pid} exited with status code #{code}")
- elsif status.signaled?
- signame = Signal.signame(status.termsig)
- message("Process #{pid} was killed by #{signame}")
- else
- message("Process #{pid} exited")
- end
- end
- ensure
- buffer.read_only = true
- end
- end
- end
-
- class Quit < StandardError
- def initialize
- super("Quit")
- end
end
end