lib/ver.rb in ver-2009.11.29 vs lib/ver.rb in ver-2009.12.14

- old
+ new

@@ -1,7 +1,7 @@ -# Well begun is half done. -# -- Aristotle +# Man must shape his tools lest they shape him. +# -- Arthur R. Miller # lazy stdlib autoload :Benchmark, 'benchmark' autoload :FileUtils, 'fileutils' @@ -12,11 +12,14 @@ require 'digest/sha1' require 'json' # require 'pp' require 'securerandom' require 'set' +require 'pathname' +autoload :SizedArray, 'ver/vendor/sized_array' + module VER autoload :Entry, 'ver/entry' autoload :Help, 'ver/help' autoload :Font, 'ver/font' autoload :HoverCompletion, 'ver/hover_completion' @@ -29,66 +32,39 @@ autoload :Text, 'ver/text' autoload :Textpow, 'ver/vendor/textpow' autoload :Levenshtein, 'ver/vendor/levenshtein' autoload :Theme, 'ver/theme' autoload :View, 'ver/view' + autoload :ExceptionView, 'ver/exception_view' + autoload :Bookmarks, 'ver/methods/bookmark' + autoload :Bookmark, 'ver/methods/bookmark' + autoload :Undo, 'ver/undo' require 'ver/options' @options = Options.new(:ver) class << self - attr_reader :root, :layout, :status, :paths, :options + attr_reader(:root, :layout, :status, :paths, :options, :bookmarks, + :ctag_stack) end + # the rest of the options are in config/rc.rb options.dsl do - o "Default Font for all widgets", - :font, "TkFixedFont 10" + o "Fork off on startup to avoid dying with the terminal", + :fork, true o "Internal:External encoding", :encoding, "UTF-8:UTF-8" - o "Tk Tile Theme", - :tk_theme, 'clam' - - o "Syntax highlighting theme", - :theme, "Blackboard" - o "Keymap used", :keymap, 'vim' - o "Expand all tabs into spaces", - :expandtab, true - - o "Use automatic indentation", - :autoindent, true - - o "Number of spaces used in autoindent", - :shiftwidth, 2 - - o "Number of spaces a tab stands for", - :tabstop, 8 - - o "Number of characters after which wrap commands will wrap", - :textwidth, 80 - - o "In case of a total failure, this key binding should bail you out", - :emergency_exit, "<Control-q>" - - o "Fork off on startup to avoid dying with the terminal", - :fork, true - - o "Milliseconds that the cursor is visible when blinking", - :insertontime, 500 - - o "Milliseconds that the cursor is invisible when blinking", - :insertofftime, 0 - o "Width of one tab in pixel", :tabs, 10 - o "Default filetype if no matching syntax can be found", - :filetype, "Plain Text" + o "Minimum size of search term to start incremental highlighting", + :search_incremental_min, 1 o "Location of personal configuration", :home_conf_dir, Pathname('~/.config/ver').expand_path o "Location of system-wide configuration", @@ -102,43 +78,60 @@ def loadpath options.loadpath end - def run(given_options = {}) - @options.merge!(given_options) - + def run(given_options = {}, &block) setup_tk + run_startup(given_options) - if Tk::RUN_EVENTLOOP_ON_MAIN_THREAD - run_aqua - else - run_x11 + forking do + if Tk::RUN_EVENTLOOP_ON_MAIN_THREAD + run_aqua(&block) + else + run_x11(&block) + end end rescue => exception VER.error(exception) exit end - def run_aqua + def run_aqua(&block) run_core - EM.run{ Tk.mainloop } + EM.defer(&block) if block + Tk.mainloop end - def run_x11 - EM.run do - EM.defer do - run_core - Tk.mainloop + def run_x11(&block) + EM.defer do + run_core + EM.defer(&block) if block + Tk.mainloop + end + end + + def forking + if options.fork + fork do + trap(:HUP){ 'terminal disconnected' } + EM.run{ yield } end + else + EM.run{ yield } end end - def run_core + def run_startup(given_options) first_startup unless options.home_conf_dir.directory? load 'rc' + @options.merge!(given_options) + end + + def run_core sanitize_options + # dump_options setup_widgets open_argv || open_welcome emergency_bindings end @@ -149,17 +142,24 @@ def setup_widgets Tk::Tile.set_theme options.tk_theme @paths = Set.new + @root = Tk.root @root.wm_geometry = '160x80' + @layout = Layout.new(@root) @layout.strategy = Layout::VerticalTiling + @status = Entry.new(@root, font: options.font) @status.insert :end, 'For information about VER, type F1' @status.pack(fill: :x) + + @exception_view = nil + @bookmarks = Bookmarks.new + @ctag_stack = [] end def sanitize_options font = options.font @@ -266,102 +266,56 @@ def opened_file(text) @paths << text.filename end + def dump_options + out = [] + + options.each_pair do |key, value| + out << [key, + case value + when Tk::Font + "VER::Font[%p]" % [value.actual_hash] + when Pathname + value.to_s + else + value + end + ] + end + + out.each do |pair| + puts("VER.options.%s = %p" % pair) + end + end + def error(exception) @status.value = exception.message if @status - error_tree(exception) if @root + exception_view(exception) if @root $stderr.puts("#{exception.class}: #{exception}", *exception.backtrace) rescue Errno::EIO # The original terminal has disappeared, the $stderr pipe was closed on the # other side. [$stderr, $stdout, $stdin].each(&:close) rescue IOError # Our pipes are closed, maybe put some output to a file logger here, or display # in a nicer way, maybe let it bubble up to Tk handling. end - def error_tree(exception) - @tree ||= Tk::Tile::Treeview.new(@root) - @tree.clear + def exception_view(exception) + unless @exception_view + @exception_view ||= ExceptionView.new(@root) - @tree.configure( - columns: %w[line method], - displaycolumns: %w[line method] - ) - @tree.heading('#0', text: 'File') - @tree.heading('line', text: 'Line') - @tree.heading('method', text: 'Method') - @tree.tag_configure('error', background: '#f88') - @tree.tag_configure('backtrace', background: '#8f8') + @exception_view.bind '<<TreeviewOpen>>' do + @exception_view.on_treeview_open + end - context_size = 7 - frames = {} - error_tags = ['error'] - backtrace_tags = ['backtrace'] - - # from Rack::ShowExceptions - exception.backtrace.each do |line| - next unless line =~ /(.*?):(\d+)(:in `(.*)')?/ - filename, lineno, function = $1, $2.to_i, $4 - - item = @tree.insert(nil, :end, - text: filename, values: [lineno, function], tags: error_tags) - - begin - lines = ::File.readlines(filename) - _lineno = lineno - 1 - - first_lineno = [_lineno - context_size, 0].max - last_lineno = [_lineno + context_size, lines.size].min - context = lines[first_lineno..last_lineno] - - frames[item.id] = { - filename: filename, - lineno: lineno, - function: function, - first_lineno: first_lineno, - last_lineno: last_lineno, - context: context, - } - rescue => ex - puts ex, ex.backtrace + @exception_view.bind '<Escape>' do + @exception_view.pack_forget + @layout.views.first.focus end end - @tree.focus - @tree.pack expand: true, fill: :both - - @tree.bind('<<TreeviewOpen>>'){|event| - begin - item = @tree.focus_item - frame = frames[item.id] - - case frame - when Hash - filename, lineno, first_lineno, context = - frame.values_at(:filename, :lineno, :first_lineno, :context) - - context.each_with_index{|line, idx| - line_lineno = first_lineno + idx + 1 - tags = line_lineno == lineno ? error_tags : backtrace_tags - line_item = item.insert(:end, - text: line, values: [line_lineno], tags: tags) - frames[line_item.id] = [filename, lineno] - } - when Array - filename, lineno = frame - @layout.views.first.find_or_create(filename, lineno){|view| - @tree.pack_forget - } - end - rescue => ex - puts ex, ex.backtrace - end - } - @tree.bind('<Escape>'){ - @tree.pack_forget - @layout.views.first.focus - } + @exception_view.show(exception) end end