diff --git a/.gitignore b/.gitignore index 0361a56..ec98ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ vendor/bundle .cache .byebug_history shared +build/* diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..687d960 --- /dev/null +++ b/Rakefile @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +MRUBY_REV = '1c765dc37a80bf681bbab271b0ba90711d935be9' +MRUBY_ROOT = 'build/mruby' +RUBY_FILES = [ + 'lib/tmux.rb', + 'lib/tmux_format_printer.rb', + 'lib/huffman.rb', + 'lib/priority_queue.rb', + 'lib/fingers/version.rb', + 'lib/fingers/dirs.rb', + 'lib/fingers/config.rb', + 'lib/fingers/commands.rb', + 'lib/fingers/commands/base.rb', + 'lib/fingers/commands/show_version.rb', + 'lib/fingers/commands/load_config.rb', + 'lib/fingers/commands/start.rb', + 'lib/fingers/cli.rb', + + 'lib/fingers/hinter.rb', + 'lib/fingers/logger.rb', + 'lib/fingers/view.rb', + 'lib/fingers/match_formatter.rb', + + 'lib/main.rb' +].freeze + +directory MRUBY_ROOT do |_t| + sh "git clone git@github.com:mruby/mruby #{MRUBY_ROOT}" + Dir.chdir('build/mruby') do + sh "git checkout #{MRUBY_REV}" + end +end + +desc 'Compile mruby' +task build_mruby: [MRUBY_ROOT] do + Dir.chdir('build/mruby') do + sh 'MRUBY_CONFIG=../../build_config.rb rake' + end +end + +desc 'Compile tmux-fingers' +task compile: ['build_mruby'] do + sh "#{MRUBY_ROOT}/bin/mrbc -B main_ruby -o build/bytecode.c #{RUBY_FILES.join(' ')}" + sh "gcc -std=c99 -I#{MRUBY_ROOT}/include main.c -o build/tmux-fingers #{MRUBY_ROOT}/build/host/lib/libmruby.a -lm" + sh 'echo tmux-fingers build complete' +end diff --git a/build_config.rb b/build_config.rb new file mode 100644 index 0000000..8920d51 --- /dev/null +++ b/build_config.rb @@ -0,0 +1,90 @@ +MRuby::Build.new do |conf| + # load specific toolchain settings + conf.toolchain + + # Use mrbgems + conf.gem :core => 'mruby-sleep' + conf.gem :github => 'iij/mruby-env' + conf.gem :github => 'mttech/mruby-getopts' + conf.gem :github => 'ksss/mruby-singleton' + conf.gem :github => 'iij/mruby-tempfile' + conf.gem :github => 'mattn/mruby-onig-regexp' do |g| + g.bundle_onigmo + end + conf.gem :github => 'katzer/mruby-logger' + conf.gem :github => 'mattn/mruby-json' + # conf.gem 'examples/mrbgems/ruby_extension_example' + # conf.gem 'examples/mrbgems/c_extension_example' do |g| + # g.cc.flags << '-g' # append cflags in this gem + # end + # conf.gem 'examples/mrbgems/c_and_ruby_extension_example' + conf.gem :core => 'mruby-eval' + # conf.gem :mgem => 'mruby-onig-regexp' + # conf.gem :github => 'mattn/mruby-onig-regexp' + # conf.gem :git => 'git@github.com:mattn/mruby-onig-regexp.git', :branch => 'master', :options => '-v' + + # include the GEM box + conf.gembox 'default' + + # C compiler settings + # conf.cc do |cc| + # cc.command = ENV['CC'] || 'gcc' + # cc.flags = [ENV['CFLAGS'] || %w()] + # cc.include_paths = ["#{root}/include"] + # cc.defines = %w() + # cc.option_include_path = %q[-I"%s"] + # cc.option_define = '-D%s' + # cc.compile_options = %Q[%{flags} -MMD -o "%{outfile}" -c "%{infile}"] + # end + + # mrbc settings + # conf.mrbc do |mrbc| + # mrbc.compile_options = "-g -B%{funcname} -o-" # The -g option is required for line numbers + # end + + # Linker settings + # conf.linker do |linker| + # linker.command = ENV['LD'] || 'gcc' + # linker.flags = [ENV['LDFLAGS'] || []] + # linker.flags_before_libraries = [] + # linker.libraries = %w() + # linker.flags_after_libraries = [] + # linker.library_paths = [] + # linker.option_library = '-l%s' + # linker.option_library_path = '-L%s' + # linker.link_options = %Q[%{flags} -o "%{outfile}" %{objs} %{libs}] + # end + + # Archiver settings + # conf.archiver do |archiver| + # archiver.command = ENV['AR'] || 'ar' + # archiver.archive_options = 'rs "%{outfile}" %{objs}' + # end + + # Parser generator settings + # conf.yacc do |yacc| + # yacc.command = ENV['YACC'] || 'bison' + # yacc.compile_options = %q[-o "%{outfile}" "%{infile}"] + # end + + # gperf settings + # conf.gperf do |gperf| + # gperf.command = 'gperf' + # gperf.compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"] + # end + + # file extensions + # conf.exts do |exts| + # exts.object = '.o' + # exts.executable = '' # '.exe' if Windows + # exts.library = '.a' + # end + + # file separator + # conf.file_separator = '/' + + # Turn on `enable_debug` for better debugging + # conf.enable_debug + conf.enable_bintest + conf.enable_test +end diff --git a/build_config.rb.lock b/build_config.rb.lock new file mode 100644 index 0000000..892e658 --- /dev/null +++ b/build_config.rb.lock @@ -0,0 +1,47 @@ +--- +mruby: + version: 3.2.0 + release_no: 30200 + git_commit: 1c765dc37a80bf681bbab271b0ba90711d935be9 +builds: + host: + https://github.com/iij/mruby-env.git: + url: https://github.com/iij/mruby-env.git + branch: HEAD + commit: 056ae324451ef16a50c7887e117f0ea30921b71b + version: 0.0.0 + https://github.com/mttech/mruby-getopts.git: + url: https://github.com/mttech/mruby-getopts.git + branch: HEAD + commit: 32878292c1162a911b39e1e0810a28ab2cb83f6a + version: 0.0.0 + https://github.com/ksss/mruby-singleton.git: + url: https://github.com/ksss/mruby-singleton.git + branch: HEAD + commit: 73dd4bae1a47d82e49b8f85bf27f49ec4462052e + version: 0.0.0 + https://github.com/iij/mruby-tempfile.git: + url: https://github.com/iij/mruby-tempfile.git + branch: HEAD + commit: 9b883438547020dae328e34c8a2fe736171cd0ab + version: 0.0.0 + https://github.com/mattn/mruby-onig-regexp.git: + url: https://github.com/mattn/mruby-onig-regexp.git + branch: HEAD + commit: 074325207f9181ad242ffb8de34072607164f57f + version: 0.0.0 + https://github.com/katzer/mruby-logger.git: + url: https://github.com/katzer/mruby-logger.git + branch: HEAD + commit: f794ef6f6ceff1794d02a6d9cfc1d281bdfcad21 + version: 0.0.0 + https://github.com/iij/mruby-iijson.git: + url: https://github.com/iij/mruby-iijson.git + branch: HEAD + commit: c5e730c30090d3cddae258f57ab9508edb3e9fce + version: 0.0.0 + https://github.com/mattn/mruby-json.git: + url: https://github.com/mattn/mruby-json.git + branch: HEAD + commit: f99d9428025469f2400f93c53b185f65f963e507 + version: 0.0.0 diff --git a/lib/fingers/cli.rb b/lib/fingers/cli.rb index 4020288..cb8b5f8 100755 --- a/lib/fingers/cli.rb +++ b/lib/fingers/cli.rb @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - module Fingers class CLI def initialize(args, cli_path) @@ -15,6 +13,8 @@ module Fingers Fingers::Commands::Start when "check_version" Fingers::Commands::CheckVersion + when "show_version" + Fingers::Commands::ShowVersion when "send_input" Fingers::Commands::SendInput when "load_config" @@ -28,6 +28,7 @@ module Fingers begin command_class.new(args, cli_path).run rescue => e + puts e Fingers.logger.error(e) end end diff --git a/lib/fingers/commands/load_config.rb b/lib/fingers/commands/load_config.rb index 21bf19f..ece07a7 100644 --- a/lib/fingers/commands/load_config.rb +++ b/lib/fingers/commands/load_config.rb @@ -4,12 +4,12 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base FINGERS_FILE_PATH = "#{ENV["HOME"]}/.fingersrc" DEFAULT_PATTERNS = { - ip: '\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}', - uuid: "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", - sha: "[0-9a-f]{7,128}", + #ip: '\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}', + #uuid: "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", + #sha: "[0-9a-f]{7,128}", digit: "[0-9]{4,}", - url: "((https?://|git@|git://|ssh://|ftp://|file:///)[^ ()'\"]+)", - path: '(([.\\w\\-~\\$@]+)?(/[.\\w\\-@]+)+/?)' + #url: "((https?://|git@|git://|ssh://|ftp://|file:///)[^ ()'\"]+)", + #path: '(([.\\w\\-~\\$@]+)?(/[.\\w\\-@]+)+/?)' }.freeze ALPHABET_MAP = { @@ -74,17 +74,6 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base Fingers.config.alphabet = ALPHABET_MAP[Fingers.config.keyboard_layout.to_sym].split("") - fingers_file_require_path = File.expand_path(FINGERS_FILE_PATH, __dir__) - - Fingers.logger.debug("Config: #{FINGERS_FILE_PATH}") - Fingers.logger.debug("fingers_file_require_path: #{fingers_file_require_path}") - - if File.exist?(FINGERS_FILE_PATH) - `cp #{FINGERS_FILE_PATH} /tmp/fingersrc.rb` - require "/tmp/fingersrc" - `rm /tmp/fingersrc.rb` - end - Fingers.save_config end @@ -94,10 +83,9 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base def setup_bindings input_mode = "fingers-mode" - ruby_bin = "#{RbConfig.ruby} --disable-gems" - `tmux bind-key #{Fingers.config.key} run-shell -b "#{ruby_bin} #{cli} start '#{input_mode}' '\#{pane_id}' self >>#{Fingers::Dirs::LOG_PATH} 2>&1"` - `tmux bind-key O run-shell -b "#{ruby_bin} #{cli} start '#{input_mode}' '\#{pane_id}' other >>#{Fingers::Dirs::LOG_PATH} 2>&1"` + `tmux bind-key #{Fingers.config.key} run-shell -b "#{cli} start '#{input_mode}' '\#{pane_id}' self >>#{Fingers::Dirs::LOG_PATH} 2>&1"` + `tmux bind-key O run-shell -b "#{cli} start '#{input_mode}' '\#{pane_id}' other >>#{Fingers::Dirs::LOG_PATH} 2>&1"` setup_fingers_mode_bindings if input_mode == "fingers-mode" end @@ -148,12 +136,12 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base def valid_option?(option) option_method = option_to_method(option) + puts "option method #{option_method}" Fingers.config.respond_to?(option_method) || option.match(/^@fingers-pattern-\d+$/) end def ensure_cache_folder - require "fileutils" - FileUtils.mkdir_p(Fingers::Dirs::CACHE) unless File.exist?(Fingers::Dirs::CACHE) + `mkdir -p #{Fingers::Dirs::CACHE}` end def fingers_options_names diff --git a/lib/fingers/commands/show_version.rb b/lib/fingers/commands/show_version.rb new file mode 100644 index 0000000..9e1312a --- /dev/null +++ b/lib/fingers/commands/show_version.rb @@ -0,0 +1,5 @@ +class Fingers::Commands::ShowVersion < Fingers::Commands::Base + def run + puts "tmux-fingers #{Fingers::VERSION}" + end +end diff --git a/lib/fingers/commands/start.rb b/lib/fingers/commands/start.rb index 1025092..9f9245e 100644 --- a/lib/fingers/commands/start.rb +++ b/lib/fingers/commands/start.rb @@ -29,6 +29,7 @@ class Fingers::Commands::Start < Fingers::Commands::Base ) def run + Fingers.logger.info("args: #{args.to_json}") _, _input_mode, from_pane_id, target = args Fingers.logger.debug("from_pane_id: #{from_pane_id}") @@ -39,7 +40,9 @@ class Fingers::Commands::Start < Fingers::Commands::Base track_options_to_restore! show_hints - handle_input + + sleep 2 + #handle_input teardown end @@ -174,6 +177,8 @@ class Fingers::Commands::Start < Fingers::Commands::Base from_pane = tmux.pane_by_id(from_pane_id) return from_pane if target == "self" + Fingers.logger.info("from pane #{from_pane_id}") + Fingers.logger.info("target #{target}") sibling_panes = tmux.panes_by_window_id(from_pane.window_id) # TODO display message or pick pane diff --git a/lib/fingers/config.rb b/lib/fingers/config.rb index 1a34df6..dc499fa 100644 --- a/lib/fingers/config.rb +++ b/lib/fingers/config.rb @@ -43,7 +43,7 @@ module Fingers def self.config $config ||= Fingers.load_from_cache - rescue + rescue StandardError => e $config ||= ConfigStruct.new end @@ -52,14 +52,54 @@ module Fingers end def self.save_config - File.write(CONFIG_PATH, Marshal.dump(Fingers.config)) + f = File.open(CONFIG_PATH, 'w') + json = {} + output = "_config = ConfigStruct.new\n" + ConfigStruct.members.map do |member| + value = Fingers.escape_control_chars(Fingers.config.send(member)) + + if value.is_a?(String) + output += "_config.#{member} = \"#{value.gsub('"', '\"')}\"\n" + end + + # Assuming all arrays are string arrays for now + if value.is_a?(Array) + output += "_config.#{member} = [" + output += value.map {|val| "\"#{val.gsub('"', '\"')}\"" }.join(", ") + output += "]\n" + end + end + output += '_config' + f.write(output) + f.close end def self.load_from_cache - Fingers.benchmark_stamp("load-config-from-cache:start") - result = Marshal.load(File.open(CONFIG_PATH)) - Fingers.benchmark_stamp("load-config-from-cache:end") - result + #Fingers.benchmark_stamp("load-config-from-cache:start") + config_file = File.open(CONFIG_PATH) + + config = Kernel.eval(config_file.read) + #json.keys.each do |member| + #config.send("#{member}=".to_sym, json[member]) + #end + config + #Fingers.benchmark_stamp("load-config-from-cache:end") + #result + end + + def self.escape_control_chars(value) + if value.is_a?(String) + value = value.gsub(/[\x00-\x1f]/) do |match| + "\\u%04x" % match.ord + end + elsif value.is_a?(Array) + value.map! { |v| escape_control_chars(v) } + elsif value.is_a?(Hash) + value.each do |k, v| + value[k] = escape_control_chars(v) + end + end + value end def self.configure diff --git a/lib/fingers/dirs.rb b/lib/fingers/dirs.rb index b707e74..68f8d06 100644 --- a/lib/fingers/dirs.rb +++ b/lib/fingers/dirs.rb @@ -1,11 +1,9 @@ module Fingers::Dirs tmux_pid = (ENV["TMUX"] || ",0000").split(",")[1] - FINGERS_REPO_ROOT = Pathname.new(__dir__).parent.parent + root = "#{Dir.tmpdir}/tmux-fingers".freeze - root = Pathname.new(Dir.tmpdir) / "tmux-fingers" - - LOG_PATH = FINGERS_REPO_ROOT / "fingers.log" - CACHE = root / "tmux-#{tmux_pid}" - CONFIG_PATH = CACHE / "fingers.config" - SOCKET_PATH = CACHE / "fingers.sock" + LOG_PATH = "#{root}/mruby-fingers.log".freeze + CACHE = "#{root}/tmux-#{tmux_pid}".freeze + CONFIG_PATH = "#{CACHE}/fingers.mruby.config".freeze + SOCKET_PATH = "#{CACHE}/fingers.mruby.sock".freeze end diff --git a/lib/fingers/hinter.rb b/lib/fingers/hinter.rb index e4398c8..2903425 100644 --- a/lib/fingers/hinter.rb +++ b/lib/fingers/hinter.rb @@ -56,6 +56,7 @@ class ::Fingers::Hinter end def process_line(line, ending) + Fingers.logger.info("processing line") result = line.gsub(pattern) { |_m| replace($~) } output.print(result + ending) end @@ -73,16 +74,18 @@ class ::Fingers::Hinter def replace(match) text = match[0] - captured_text = match && match.named_captures["capture"] || text + #captured_text = match && match.named_captures["capture"] || text + captured_text = match && match || text - if match.named_captures["capture"] - match_start, match_end = match.offset(0) - capture_start, capture_end = match.offset(:capture) + #if match.named_captures["capture"] + #match_start, match_end = match.offset(0) + #capture_start, capture_end = match.offset(:capture) - capture_offset = [capture_start - match_start, capture_end - capture_start] - else + #capture_offset = [capture_start - match_start, capture_end - capture_start] + #else capture_offset = nil - end + #end + if hints_by_text.has_key?(captured_text) hint = hints_by_text[captured_text] @@ -91,6 +94,7 @@ class ::Fingers::Hinter hints_by_text[captured_text] = hint end + # TODO: this should be output hint without ansi escape sequences formatter.format( hint: hint, @@ -98,10 +102,11 @@ class ::Fingers::Hinter selected: state.selected_hints.include?(hint), offset: capture_offset ) + end def lines - @lines ||= input.force_encoding("UTF-8").split("\n") + @lines ||= input.split("\n") end def n_matches @@ -112,6 +117,9 @@ class ::Fingers::Hinter Fingers.benchmark_stamp("counting-matches:start") lines.each do |line| + Fingers.logger.info("line: #{line}") + Fingers.logger.info("pattern: #{pattern}") + Fingers.logger.info("----") line.scan(pattern) do |match| match_set.add($&) end diff --git a/lib/fingers/logger.rb b/lib/fingers/logger.rb index 56159ba..2378dc2 100644 --- a/lib/fingers/logger.rb +++ b/lib/fingers/logger.rb @@ -1,5 +1,3 @@ -require "logger" - module Fingers def self.logger return @logger if @logger @@ -12,7 +10,7 @@ module Fingers end def self.benchmark_stamp(tag) - Fingers.logger.debug("benchmark:#{tag} #{Process.clock_gettime(Process::CLOCK_MONOTONIC)}") + #Fingers.logger.debug("benchmark:#{tag} #{Process.clock_gettime(Process::CLOCK_MONOTONIC)}") end def self.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences(msg) diff --git a/lib/main.rb b/lib/main.rb new file mode 100644 index 0000000..633a88f --- /dev/null +++ b/lib/main.rb @@ -0,0 +1,18 @@ +module Kernel + def system(*args) + `#{args.join(' ')}` + $? == 0 + end +end + +puts "hello" +begin + absolute_fingers_path = "/home/morantron/hacking/tmux-fingers/build/tmux-fingers" + ARGV.shift + Fingers::CLI.new(ARGV, absolute_fingers_path).run +rescue StandardError => e + puts "error" + puts e + puts e.backtrace +end +puts "goodbye" diff --git a/lib/tmux.rb b/lib/tmux.rb index 438ad11..f31c1ed 100644 --- a/lib/tmux.rb +++ b/lib/tmux.rb @@ -209,7 +209,7 @@ class Tmux end def socket_flag_value - return ENV["FINGERS_TMUX_SOCKET"] if ENV["FINGERS_TMUX_SOCKET"] + #return ENV["FINGERS_TMUX_SOCKET"] if ENV["FINGERS_TMUX_SOCKET"] socket end end diff --git a/main.c b/main.c new file mode 100644 index 0000000..5000063 --- /dev/null +++ b/main.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include "./build/bytecode.c" + +int +main(int argc, char *argv[]) +{ + mrb_state *mrb = mrb_open(); + if (!mrb) { /* handle error */ } + + // Create a new mrb_value array to hold the command-line arguments + mrb_value args = mrb_ary_new_capa(mrb, argc); + + // Convert each command-line argument to an mrb_value and add it to the array + for (int i = 0; i < argc; i++) { + mrb_ary_push(mrb, args, mrb_str_new_cstr(mrb, argv[i])); + } + + // Set the ARGV constant to the array of command-line arguments + mrb_define_global_const(mrb, "ARGV", args); + + mrb_load_irep(mrb, main_ruby); + mrb_close(mrb); + return 0; +}