WOP
This commit is contained in:
parent
4d45983f71
commit
661c6210a9
11
Gemfile
11
Gemfile
|
@ -1,8 +1,9 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'irb'
|
gem "byebug"
|
||||||
gem 'byebug'
|
gem "irb"
|
||||||
gem 'rspec'
|
gem "rspec"
|
||||||
gem 'rspec-retry'
|
gem "rspec-retry"
|
||||||
|
gem "standardrb"
|
||||||
end
|
end
|
||||||
|
|
29
Gemfile.lock
29
Gemfile.lock
|
@ -1,13 +1,20 @@
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
|
ast (2.4.2)
|
||||||
byebug (11.1.3)
|
byebug (11.1.3)
|
||||||
diff-lcs (1.3)
|
diff-lcs (1.3)
|
||||||
io-console (0.5.6)
|
io-console (0.5.6)
|
||||||
irb (1.2.4)
|
irb (1.2.4)
|
||||||
reline (>= 0.0.1)
|
reline (>= 0.0.1)
|
||||||
|
parallel (1.22.1)
|
||||||
|
parser (3.1.2.0)
|
||||||
|
ast (~> 2.4.1)
|
||||||
|
rainbow (3.1.1)
|
||||||
|
regexp_parser (2.5.0)
|
||||||
reline (0.1.4)
|
reline (0.1.4)
|
||||||
io-console (~> 0.5)
|
io-console (~> 0.5)
|
||||||
|
rexml (3.2.5)
|
||||||
rspec (3.9.0)
|
rspec (3.9.0)
|
||||||
rspec-core (~> 3.9.0)
|
rspec-core (~> 3.9.0)
|
||||||
rspec-expectations (~> 3.9.0)
|
rspec-expectations (~> 3.9.0)
|
||||||
|
@ -23,6 +30,27 @@ GEM
|
||||||
rspec-retry (0.6.2)
|
rspec-retry (0.6.2)
|
||||||
rspec-core (> 3.3)
|
rspec-core (> 3.3)
|
||||||
rspec-support (3.9.3)
|
rspec-support (3.9.3)
|
||||||
|
rubocop (1.29.1)
|
||||||
|
parallel (~> 1.10)
|
||||||
|
parser (>= 3.1.0.0)
|
||||||
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
|
rexml (>= 3.2.5, < 4.0)
|
||||||
|
rubocop-ast (>= 1.17.0, < 2.0)
|
||||||
|
ruby-progressbar (~> 1.7)
|
||||||
|
unicode-display_width (>= 1.4.0, < 3.0)
|
||||||
|
rubocop-ast (1.18.0)
|
||||||
|
parser (>= 3.1.1.0)
|
||||||
|
rubocop-performance (1.13.3)
|
||||||
|
rubocop (>= 1.7.0, < 2.0)
|
||||||
|
rubocop-ast (>= 0.4.0)
|
||||||
|
ruby-progressbar (1.11.0)
|
||||||
|
standard (1.12.1)
|
||||||
|
rubocop (= 1.29.1)
|
||||||
|
rubocop-performance (= 1.13.3)
|
||||||
|
standardrb (1.0.1)
|
||||||
|
standard
|
||||||
|
unicode-display_width (2.2.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -33,6 +61,7 @@ DEPENDENCIES
|
||||||
irb
|
irb
|
||||||
rspec
|
rspec
|
||||||
rspec-retry
|
rspec-retry
|
||||||
|
standardrb
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.2.2
|
2.2.2
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
# requires nfs-utils on host
|
# requires nfs-utils on host
|
||||||
|
|
||||||
Vagrant.configure(2) do |config|
|
Vagrant.configure(2) do |config|
|
||||||
config.vm.provider 'virtualbox' do |v|
|
config.vm.provider "virtualbox" do |v|
|
||||||
v.customize ['modifyvm', :id, '--cpuexecutioncap', '50']
|
v.customize ["modifyvm", :id, "--cpuexecutioncap", "50"]
|
||||||
end
|
end
|
||||||
|
|
||||||
config.vm.define 'ubuntu' do |machine|
|
config.vm.define "ubuntu" do |machine|
|
||||||
machine.vm.box = 'ubuntu/focal64'
|
machine.vm.box = "ubuntu/focal64"
|
||||||
machine.vm.synced_folder '.', '/home/vagrant/shared'
|
machine.vm.synced_folder ".", "/home/vagrant/shared"
|
||||||
machine.vm.provision 'shell', path: './spec/provisioning/ubuntu.sh'
|
machine.vm.provision "shell", path: "./spec/provisioning/ubuntu.sh"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,41 +1,41 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'logger'
|
require "logger"
|
||||||
require 'json'
|
require "json"
|
||||||
require 'singleton'
|
require "singleton"
|
||||||
require 'timeout'
|
require "timeout"
|
||||||
require 'socket'
|
require "socket"
|
||||||
require 'pathname'
|
require "pathname"
|
||||||
require 'tmpdir'
|
require "tmpdir"
|
||||||
require 'set'
|
require "set"
|
||||||
|
|
||||||
# Top level fingers namespace
|
# Top level fingers namespace
|
||||||
module Fingers
|
module Fingers
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'tmux'
|
require "tmux"
|
||||||
require 'tmux_format_printer'
|
require "tmux_format_printer"
|
||||||
require 'huffman'
|
require "huffman"
|
||||||
require 'priority_queue'
|
require "priority_queue"
|
||||||
|
|
||||||
require 'fingers/version'
|
require "fingers/version"
|
||||||
require 'fingers/dirs'
|
require "fingers/dirs"
|
||||||
require 'fingers/config'
|
require "fingers/config"
|
||||||
|
|
||||||
# commands
|
# commands
|
||||||
# TODO dynamically require command?
|
# TODO dynamically require command?
|
||||||
require 'fingers/commands'
|
require "fingers/commands"
|
||||||
require 'fingers/commands/base'
|
require "fingers/commands/base"
|
||||||
require 'fingers/commands/check_version'
|
require "fingers/commands/check_version"
|
||||||
require 'fingers/commands/load_config'
|
require "fingers/commands/load_config"
|
||||||
require 'fingers/commands/send_input'
|
require "fingers/commands/send_input"
|
||||||
require 'fingers/commands/start'
|
require "fingers/commands/start"
|
||||||
require 'fingers/commands/trace_start'
|
require "fingers/commands/trace_start"
|
||||||
|
|
||||||
require 'fingers/action_runner'
|
require "fingers/action_runner"
|
||||||
require 'fingers/hinter'
|
require "fingers/hinter"
|
||||||
require 'fingers/input_socket'
|
require "fingers/input_socket"
|
||||||
require 'fingers/logger'
|
require "fingers/logger"
|
||||||
require 'fingers/view'
|
require "fingers/view"
|
||||||
require 'fingers/match_formatter'
|
require "fingers/match_formatter"
|
||||||
require 'fingers/cli'
|
require "fingers/cli"
|
||||||
|
|
|
@ -25,23 +25,23 @@ class Fingers::ActionRunner
|
||||||
return @final_shell_command if @final_shell_command
|
return @final_shell_command if @final_shell_command
|
||||||
|
|
||||||
@final_shell_command = case action
|
@final_shell_command = case action
|
||||||
when ':copy:'
|
when ":copy:"
|
||||||
copy
|
copy
|
||||||
when ':open:'
|
when ":open:"
|
||||||
open
|
open
|
||||||
when ':paste:'
|
when ":paste:"
|
||||||
paste
|
paste
|
||||||
when nil
|
when nil
|
||||||
# do nothing
|
# do nothing
|
||||||
else
|
else
|
||||||
shell_action
|
shell_action
|
||||||
end
|
end
|
||||||
|
|
||||||
@final_shell_command = prepend_pane_path(@final_shell_command)
|
@final_shell_command = prepend_pane_path(@final_shell_command)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepend_pane_path(cmd)
|
def prepend_pane_path(cmd)
|
||||||
return if (cmd || '').empty?
|
return if (cmd || "").empty?
|
||||||
|
|
||||||
"cd #{original_pane.pane_current_path}; #{cmd}"
|
"cd #{original_pane.pane_current_path}; #{cmd}"
|
||||||
end
|
end
|
||||||
|
@ -61,7 +61,7 @@ class Fingers::ActionRunner
|
||||||
end
|
end
|
||||||
|
|
||||||
def paste
|
def paste
|
||||||
'tmux paste-buffer'
|
"tmux paste-buffer"
|
||||||
end
|
end
|
||||||
|
|
||||||
def shell_action
|
def shell_action
|
||||||
|
@ -69,7 +69,7 @@ class Fingers::ActionRunner
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_env
|
def action_env
|
||||||
{ 'MODIFIER' => modifier, 'HINT' => hint }
|
{"MODIFIER" => modifier, "HINT" => hint}
|
||||||
end
|
end
|
||||||
|
|
||||||
def action
|
def action
|
||||||
|
@ -77,33 +77,33 @@ class Fingers::ActionRunner
|
||||||
end
|
end
|
||||||
|
|
||||||
def system_copy_command
|
def system_copy_command
|
||||||
@system_copy_command ||= if program_exists?('pbcopy')
|
@system_copy_command ||= if program_exists?("pbcopy")
|
||||||
if program_exists?('reattach-to-user-namespace')
|
if program_exists?("reattach-to-user-namespace")
|
||||||
'reattach-to-user-namespace'
|
"reattach-to-user-namespace"
|
||||||
else
|
else
|
||||||
'pbcopy'
|
"pbcopy"
|
||||||
end
|
end
|
||||||
elsif program_exists?('clip.exe')
|
elsif program_exists?("clip.exe")
|
||||||
'cat | clip.exe'
|
"cat | clip.exe"
|
||||||
elsif program_exists?('wl-copy')
|
elsif program_exists?("wl-copy")
|
||||||
'wl-copy'
|
"wl-copy"
|
||||||
elsif program_exists?('xclip')
|
elsif program_exists?("xclip")
|
||||||
'xclip -selection clipboard'
|
"xclip -selection clipboard"
|
||||||
elsif program_exists?('xsel')
|
elsif program_exists?("xsel")
|
||||||
'xsel -i --clipboard'
|
"xsel -i --clipboard"
|
||||||
elsif program_exists?('putclip')
|
elsif program_exists?("putclip")
|
||||||
'putclip'
|
"putclip"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def system_open_command
|
def system_open_command
|
||||||
@system_open_command ||= if program_exists?('cygstart')
|
@system_open_command ||= if program_exists?("cygstart")
|
||||||
'xargs cygstart'
|
"xargs cygstart"
|
||||||
elsif program_exists?('xdg-open')
|
elsif program_exists?("xdg-open")
|
||||||
'xargs xdg-open'
|
"xargs xdg-open"
|
||||||
elsif program_exists?('open')
|
elsif program_exists?("open")
|
||||||
'xargs open'
|
"xargs open"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def program_exists?(program)
|
def program_exists?(program)
|
||||||
|
|
|
@ -8,26 +8,26 @@ module Fingers
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
Fingers.benchmark_stamp('boot:end') if ARGV[0] == 'start'
|
Fingers.benchmark_stamp("boot:end") if ARGV[0] == "start"
|
||||||
|
|
||||||
command_class = case ARGV[0]
|
command_class = case ARGV[0]
|
||||||
when 'start'
|
when "start"
|
||||||
Fingers::Commands::Start
|
Fingers::Commands::Start
|
||||||
when 'check_version'
|
when "check_version"
|
||||||
Fingers::Commands::CheckVersion
|
Fingers::Commands::CheckVersion
|
||||||
when 'send_input'
|
when "send_input"
|
||||||
Fingers::Commands::SendInput
|
Fingers::Commands::SendInput
|
||||||
when 'load_config'
|
when "load_config"
|
||||||
Fingers::Commands::LoadConfig
|
Fingers::Commands::LoadConfig
|
||||||
when 'trace_start'
|
when "trace_start"
|
||||||
Fingers::Commands::TraceStart
|
Fingers::Commands::TraceStart
|
||||||
else
|
else
|
||||||
raise "Unknown command #{ARGV[0]}"
|
raise "Unknown command #{ARGV[0]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
command_class.new(args, cli_path).run
|
command_class.new(args, cli_path).run
|
||||||
rescue StandardError => e
|
rescue => e
|
||||||
Fingers.logger.error(e)
|
Fingers.logger.error(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
class Fingers::Commands::CheckVersion < Fingers::Commands::Base
|
class Fingers::Commands::CheckVersion < Fingers::Commands::Base
|
||||||
def run
|
def run
|
||||||
require 'net/https'
|
require "net/https"
|
||||||
|
|
||||||
puts 'Checking version...'
|
puts "Checking version..."
|
||||||
uri = URI('https://api.github.com/repos/morantron/tmux-fingers/tags')
|
uri = URI("https://api.github.com/repos/morantron/tmux-fingers/tags")
|
||||||
|
|
||||||
response = Net::HTTP.get_response(uri)
|
response = Net::HTTP.get_response(uri)
|
||||||
json_response = JSON.parse(response.body)
|
json_response = JSON.parse(response.body)
|
||||||
|
|
||||||
latest_release = json_response.map { |tag| Gem::Version.new(tag['name']) }.max
|
latest_release = json_response.map { |tag| Gem::Version.new(tag["name"]) }.max
|
||||||
|
|
||||||
current_release = Gem::Version.new(Fingers::VERSION)
|
current_release = Gem::Version.new(Fingers::VERSION)
|
||||||
|
|
||||||
puts "There is a new tmux-fingers release: #{latest_release}" if latest_release > current_release
|
puts "There is a new tmux-fingers release: #{latest_release}" if latest_release > current_release
|
||||||
rescue StandardError => e
|
rescue => e
|
||||||
puts 'Could not check version'
|
puts "Could not check version"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
DISALLOWED_CHARS = /cimqn/.freeze
|
DISALLOWED_CHARS = /cimqn/
|
||||||
|
|
||||||
FINGERS_FILE_PATH = "#{ENV['HOME']}/.fingersrc"
|
FINGERS_FILE_PATH = "#{ENV["HOME"]}/.fingersrc"
|
||||||
|
|
||||||
DEFAULT_PATTERNS = {
|
DEFAULT_PATTERNS = {
|
||||||
"ip": '\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}',
|
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}',
|
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}',
|
sha: "[0-9a-f]{7,128}",
|
||||||
"digit": '[0-9]{4,}',
|
digit: "[0-9]{4,}",
|
||||||
"url": "((https?://|git@|git://|ssh://|ftp://|file:///)[^ ()'\"]+)",
|
url: "((https?://|git@|git://|ssh://|ftp://|file:///)[^ ()'\"]+)",
|
||||||
"path": '(([.\\w\\-~\\$@]+)?(/[.\\w\\-@]+)+/?)'
|
path: '(([.\\w\\-~\\$@]+)?(/[.\\w\\-@]+)+/?)'
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
ALPHABET_MAP = {
|
ALPHABET_MAP = {
|
||||||
"qwerty": 'asdfqwerzxcvjklmiuopghtybn',
|
qwerty: "asdfqwerzxcvjklmiuopghtybn",
|
||||||
"qwerty-homerow": 'asdfjklgh',
|
"qwerty-homerow": "asdfjklgh",
|
||||||
"qwerty-left-hand": 'asdfqwerzcxv',
|
"qwerty-left-hand": "asdfqwerzcxv",
|
||||||
"qwerty-right-hand": 'jkluiopmyhn',
|
"qwerty-right-hand": "jkluiopmyhn",
|
||||||
"azerty": 'qsdfazerwxcvjklmuiopghtybn',
|
azerty: "qsdfazerwxcvjklmuiopghtybn",
|
||||||
"azerty-homerow": 'qsdfjkmgh',
|
"azerty-homerow": "qsdfjkmgh",
|
||||||
"azerty-left-hand": 'qsdfazerwxcv',
|
"azerty-left-hand": "qsdfazerwxcv",
|
||||||
"azerty-right-hand": 'jklmuiophyn',
|
"azerty-right-hand": "jklmuiophyn",
|
||||||
"qwertz": 'asdfqweryxcvjkluiopmghtzbn',
|
qwertz: "asdfqweryxcvjkluiopmghtzbn",
|
||||||
"qwertz-homerow": 'asdfghjkl',
|
"qwertz-homerow": "asdfghjkl",
|
||||||
"qwertz-left-hand": 'asdfqweryxcv',
|
"qwertz-left-hand": "asdfqweryxcv",
|
||||||
"qwertz-right-hand": 'jkluiopmhzn',
|
"qwertz-right-hand": "jkluiopmhzn",
|
||||||
"dvorak": 'aoeuqjkxpyhtnsgcrlmwvzfidb',
|
dvorak: "aoeuqjkxpyhtnsgcrlmwvzfidb",
|
||||||
"dvorak-homerow": 'aoeuhtnsid',
|
"dvorak-homerow": "aoeuhtnsid",
|
||||||
"dvorak-left-hand": 'aoeupqjkyix',
|
"dvorak-left-hand": "aoeupqjkyix",
|
||||||
"dvorak-right-hand": 'htnsgcrlmwvz',
|
"dvorak-right-hand": "htnsgcrlmwvz",
|
||||||
"colemak": 'arstqwfpzxcvneioluymdhgjbk',
|
colemak: "arstqwfpzxcvneioluymdhgjbk",
|
||||||
"colemak-homerow": 'arstneiodh',
|
"colemak-homerow": "arstneiodh",
|
||||||
"colemak-left-hand": 'arstqwfpzxcv',
|
"colemak-left-hand": "arstqwfpzxcv",
|
||||||
"colemak-right-hand": 'neioluymjhk'
|
"colemak-right-hand": "neioluymjhk"
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
@ -56,9 +56,9 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
|
|
||||||
option = option
|
option = option
|
||||||
|
|
||||||
if option.match(/pattern/)
|
if /pattern/.match?(option)
|
||||||
user_defined_patterns.push(value)
|
user_defined_patterns.push(value)
|
||||||
elsif option.match(/format/)
|
elsif /format/.match?(option)
|
||||||
parsed_format = Tmux.instance.parse_format(value)
|
parsed_format = Tmux.instance.parse_format(value)
|
||||||
|
|
||||||
Fingers.config.send("#{option}=".to_sym, parsed_format)
|
Fingers.config.send("#{option}=".to_sym, parsed_format)
|
||||||
|
@ -68,21 +68,20 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
Fingers.config.patterns = clean_up_patterns([
|
Fingers.config.patterns = clean_up_patterns([
|
||||||
*enabled_default_patterns,
|
*enabled_default_patterns,
|
||||||
*user_defined_patterns
|
*user_defined_patterns
|
||||||
])
|
])
|
||||||
|
|
||||||
Fingers.config.alphabet = ALPHABET_MAP[Fingers.config.keyboard_layout.to_sym].split('')
|
Fingers.config.alphabet = ALPHABET_MAP[Fingers.config.keyboard_layout.to_sym].split("")
|
||||||
|
|
||||||
fingers_file_require_path = File.expand_path(FINGERS_FILE_PATH, __dir__)
|
fingers_file_require_path = File.expand_path(FINGERS_FILE_PATH, __dir__)
|
||||||
|
|
||||||
Fingers.logger.debug("Config: #{FINGERS_FILE_PATH}")
|
Fingers.logger.debug("Config: #{FINGERS_FILE_PATH}")
|
||||||
Fingers.logger.debug("fingers_file_require_path: #{fingers_file_require_path}")
|
Fingers.logger.debug("fingers_file_require_path: #{fingers_file_require_path}")
|
||||||
|
|
||||||
|
|
||||||
if File.exist?(FINGERS_FILE_PATH)
|
if File.exist?(FINGERS_FILE_PATH)
|
||||||
`cp #{FINGERS_FILE_PATH} /tmp/fingersrc.rb`
|
`cp #{FINGERS_FILE_PATH} /tmp/fingersrc.rb`
|
||||||
require "/tmp/fingersrc.rb"
|
require "/tmp/fingersrc"
|
||||||
`rm /tmp/fingersrc.rb`
|
`rm /tmp/fingersrc.rb`
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -94,17 +93,17 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_bindings
|
def setup_bindings
|
||||||
input_mode = 'fingers-mode'
|
input_mode = "fingers-mode"
|
||||||
ruby_bin = "#{RbConfig.ruby} --disable-gems"
|
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 #{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 O run-shell -b "#{ruby_bin} #{cli} start '#{input_mode}' '\#{pane_id}' other >>#{Fingers::Dirs::LOG_PATH} 2>&1"`
|
||||||
|
|
||||||
setup_fingers_mode_bindings if input_mode == 'fingers-mode'
|
setup_fingers_mode_bindings if input_mode == "fingers-mode"
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_fingers_mode_bindings
|
def setup_fingers_mode_bindings
|
||||||
('a'..'z').to_a.each do |char|
|
("a".."z").to_a.each do |char|
|
||||||
next if char.match(DISALLOWED_CHARS)
|
next if char.match(DISALLOWED_CHARS)
|
||||||
|
|
||||||
fingers_mode_bind(char, "hint:#{char}:main")
|
fingers_mode_bind(char, "hint:#{char}:main")
|
||||||
|
@ -113,17 +112,17 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
fingers_mode_bind("M-#{char}", "hint:#{char}:alt")
|
fingers_mode_bind("M-#{char}", "hint:#{char}:alt")
|
||||||
end
|
end
|
||||||
|
|
||||||
fingers_mode_bind('Space', 'fzf')
|
fingers_mode_bind("Space", "fzf")
|
||||||
fingers_mode_bind('C-c', 'exit')
|
fingers_mode_bind("C-c", "exit")
|
||||||
fingers_mode_bind('q', 'exit')
|
fingers_mode_bind("q", "exit")
|
||||||
fingers_mode_bind('Escape', 'exit')
|
fingers_mode_bind("Escape", "exit")
|
||||||
|
|
||||||
fingers_mode_bind('?', 'toggle-help')
|
fingers_mode_bind("?", "toggle-help")
|
||||||
|
|
||||||
fingers_mode_bind('Enter', 'noop')
|
fingers_mode_bind("Enter", "noop")
|
||||||
fingers_mode_bind('Tab', 'toggle_multi_mode')
|
fingers_mode_bind("Tab", "toggle_multi_mode")
|
||||||
|
|
||||||
fingers_mode_bind('Any', 'noop')
|
fingers_mode_bind("Any", "noop")
|
||||||
end
|
end
|
||||||
|
|
||||||
def enabled_default_patterns
|
def enabled_default_patterns
|
||||||
|
@ -131,7 +130,7 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_bool(input)
|
def to_bool(input)
|
||||||
input == '1'
|
input == "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
def shell_safe_options
|
def shell_safe_options
|
||||||
|
@ -153,12 +152,12 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_cache_folder
|
def ensure_cache_folder
|
||||||
require 'fileutils'
|
require "fileutils"
|
||||||
FileUtils.mkdir_p(Fingers::Dirs::CACHE) unless File.exist?(Fingers::Dirs::CACHE)
|
FileUtils.mkdir_p(Fingers::Dirs::CACHE) unless File.exist?(Fingers::Dirs::CACHE)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fingers_options_names
|
def fingers_options_names
|
||||||
@fingers_options_names ||= `tmux show-options -g | grep ^@fingers`.split("\n").map { |line| line.split(' ')[0] }
|
@fingers_options_names ||= `tmux show-options -g | grep ^@fingers`.split("\n").map { |line| line.split(" ")[0] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def unset_tmux_option!(option)
|
def unset_tmux_option!(option)
|
||||||
|
@ -177,13 +176,13 @@ class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
||||||
|
|
||||||
return if errors.empty?
|
return if errors.empty?
|
||||||
|
|
||||||
puts '[tmux-fingers] Errors found in tmux.conf:'
|
puts "[tmux-fingers] Errors found in tmux.conf:"
|
||||||
errors.each { |error| puts " - #{error}" }
|
errors.each { |error| puts " - #{error}" }
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
def option_to_method(option)
|
def option_to_method(option)
|
||||||
option.gsub(/^@fingers-/, '').tr('-', '_')
|
option.gsub(/^@fingers-/, "").tr("-", "_")
|
||||||
end
|
end
|
||||||
|
|
||||||
def fingers_mode_bind(key, command)
|
def fingers_mode_bind(key, command)
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
class PanePrinter
|
class PanePrinter
|
||||||
def initialize(pane_tty)
|
def initialize(pane_tty)
|
||||||
@pane_tty = pane_tty
|
@pane_tty = pane_tty
|
||||||
@buf = ''
|
@buf = ""
|
||||||
@file = File.open(@pane_tty, 'w')
|
@file = File.open(@pane_tty, "w")
|
||||||
end
|
end
|
||||||
|
|
||||||
def print(msg)
|
def print(msg)
|
||||||
@file.print(msg)
|
@file.print(msg)
|
||||||
#@buf += msg
|
# @buf += msg
|
||||||
end
|
end
|
||||||
|
|
||||||
def flush
|
def flush
|
||||||
#@file.print(@buf)
|
# @file.print(@buf)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class Fingers::Commands::Start < Fingers::Commands::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def fingers_window
|
def fingers_window
|
||||||
@fingers_window ||= tmux.create_window('[fingers]', 'cat', 80, 24)
|
@fingers_window ||= tmux.create_window("[fingers]", "cat", 80, 24)
|
||||||
end
|
end
|
||||||
|
|
||||||
def target_pane
|
def target_pane
|
||||||
|
@ -94,8 +94,8 @@ class Fingers::Commands::Start < Fingers::Commands::Base
|
||||||
|
|
||||||
@state.multi_mode = false
|
@state.multi_mode = false
|
||||||
@state.show_help = false
|
@state.show_help = false
|
||||||
@state.input = ''
|
@state.input = ""
|
||||||
@state.modifier = ''
|
@state.modifier = ""
|
||||||
@state.selected_hints = []
|
@state.selected_hints = []
|
||||||
@state.selected_matches = []
|
@state.selected_matches = []
|
||||||
@state.multi_matches = []
|
@state.multi_matches = []
|
||||||
|
@ -119,12 +119,12 @@ class Fingers::Commands::Start < Fingers::Commands::Base
|
||||||
input_socket = InputSocket.new
|
input_socket = InputSocket.new
|
||||||
|
|
||||||
tmux.disable_prefix
|
tmux.disable_prefix
|
||||||
tmux.set_key_table 'fingers'
|
tmux.set_key_table "fingers"
|
||||||
|
|
||||||
Fingers.benchmark_stamp('ready-for-input:end')
|
Fingers.benchmark_stamp("ready-for-input:end")
|
||||||
Fingers.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences('fingers-ready')
|
Fingers.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences("fingers-ready")
|
||||||
|
|
||||||
return if Fingers.config.trace_perf == '1'
|
return if Fingers.config.trace_perf == "1"
|
||||||
|
|
||||||
input_socket.on_input do |input|
|
input_socket.on_input do |input|
|
||||||
view.process_input(input)
|
view.process_input(input)
|
||||||
|
@ -153,11 +153,11 @@ class Fingers::Commands::Start < Fingers::Commands::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def pane_was_zoomed?
|
def pane_was_zoomed?
|
||||||
target_pane.window_zoomed_flag == '1'
|
target_pane.window_zoomed_flag == "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
tmux.set_key_table 'root'
|
tmux.set_key_table "root"
|
||||||
|
|
||||||
tmux.swap_panes(fingers_pane_id, target_pane.pane_id)
|
tmux.swap_panes(fingers_pane_id, target_pane.pane_id)
|
||||||
tmux.kill_pane(fingers_pane_id)
|
tmux.kill_pane(fingers_pane_id)
|
||||||
|
@ -167,7 +167,7 @@ class Fingers::Commands::Start < Fingers::Commands::Base
|
||||||
restore_options
|
restore_options
|
||||||
view.run_action if state.result
|
view.run_action if state.result
|
||||||
|
|
||||||
Fingers.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences('fingers-finish')
|
Fingers.trace_for_tests_do_not_remove_or_the_whole_fabric_of_reality_will_tear_apart_with_unforeseen_consequences("fingers-finish")
|
||||||
end
|
end
|
||||||
|
|
||||||
def compute_target_pane
|
def compute_target_pane
|
||||||
|
|
|
@ -18,20 +18,20 @@ module Fingers
|
||||||
:trace_perf
|
:trace_perf
|
||||||
) do
|
) do
|
||||||
def initialize(
|
def initialize(
|
||||||
key = 'F',
|
key = "F",
|
||||||
keyboard_layout = 'qwerty',
|
keyboard_layout = "qwerty",
|
||||||
alphabet = [],
|
alphabet = [],
|
||||||
patterns = [],
|
patterns = [],
|
||||||
main_action = ':copy:',
|
main_action = ":copy:",
|
||||||
ctrl_action = ':open:',
|
ctrl_action = ":open:",
|
||||||
alt_action = '',
|
alt_action = "",
|
||||||
shift_action = ':paste:',
|
shift_action = ":paste:",
|
||||||
hint_position = 'left',
|
hint_position = "left",
|
||||||
hint_format = Tmux.instance.parse_format('fg=yellow,bold'),
|
hint_format = Tmux.instance.parse_format("fg=yellow,bold"),
|
||||||
selected_hint_format = Tmux.instance.parse_format('fg=green,bold'),
|
selected_hint_format = Tmux.instance.parse_format("fg=green,bold"),
|
||||||
selected_highlight_format = Tmux.instance.parse_format('fg=green,nobold,dim'),
|
selected_highlight_format = Tmux.instance.parse_format("fg=green,nobold,dim"),
|
||||||
highlight_format = Tmux.instance.parse_format('fg=yellow,nobold,dim'),
|
highlight_format = Tmux.instance.parse_format("fg=yellow,nobold,dim"),
|
||||||
trace_perf = '0'
|
trace_perf = "0"
|
||||||
)
|
)
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
@ -43,7 +43,7 @@ module Fingers
|
||||||
|
|
||||||
def self.config
|
def self.config
|
||||||
$config ||= Fingers.load_from_cache
|
$config ||= Fingers.load_from_cache
|
||||||
rescue StandardError
|
rescue
|
||||||
$config ||= ConfigStruct.new
|
$config ||= ConfigStruct.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,15 +52,13 @@ module Fingers
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.save_config
|
def self.save_config
|
||||||
File.open(CONFIG_PATH, 'w') do |f|
|
File.write(CONFIG_PATH, Marshal.dump(Fingers.config))
|
||||||
f.write(Marshal.dump(Fingers.config))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.load_from_cache
|
def self.load_from_cache
|
||||||
Fingers.benchmark_stamp('load-config-from-cache:start')
|
Fingers.benchmark_stamp("load-config-from-cache:start")
|
||||||
result = Marshal.load(File.open(CONFIG_PATH))
|
result = Marshal.load(File.open(CONFIG_PATH))
|
||||||
Fingers.benchmark_stamp('load-config-from-cache:end')
|
Fingers.benchmark_stamp("load-config-from-cache:end")
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
module Fingers::Dirs
|
module Fingers::Dirs
|
||||||
tmux_pid = (ENV['TMUX'] || ',0000').split(',')[1]
|
tmux_pid = (ENV["TMUX"] || ",0000").split(",")[1]
|
||||||
FINGERS_REPO_ROOT = Pathname.new(__dir__).parent.parent
|
FINGERS_REPO_ROOT = Pathname.new(__dir__).parent.parent
|
||||||
|
|
||||||
root = Pathname.new(Dir.tmpdir) / 'tmux-fingers'
|
root = Pathname.new(Dir.tmpdir) / "tmux-fingers"
|
||||||
|
|
||||||
LOG_PATH = FINGERS_REPO_ROOT / 'fingers.log'
|
LOG_PATH = FINGERS_REPO_ROOT / "fingers.log"
|
||||||
CACHE = root / "tmux-#{tmux_pid}"
|
CACHE = root / "tmux-#{tmux_pid}"
|
||||||
CONFIG_PATH = CACHE / 'fingers.config'
|
CONFIG_PATH = CACHE / "fingers.config"
|
||||||
SOCKET_PATH = CACHE / 'fingers.sock'
|
SOCKET_PATH = CACHE / "fingers.sock"
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,9 +3,8 @@ class ::Fingers::Hinter
|
||||||
input:,
|
input:,
|
||||||
width:,
|
width:,
|
||||||
state:,
|
state:,
|
||||||
patterns: Fingers.config.patterns,
|
output:, patterns: Fingers.config.patterns,
|
||||||
alphabet: Fingers.config.alphabet,
|
alphabet: Fingers.config.alphabet,
|
||||||
output:,
|
|
||||||
huffman: Huffman.new,
|
huffman: Huffman.new,
|
||||||
formatter: ::Fingers::MatchFormatter.new
|
formatter: ::Fingers::MatchFormatter.new
|
||||||
)
|
)
|
||||||
|
@ -22,7 +21,7 @@ class ::Fingers::Hinter
|
||||||
|
|
||||||
def run
|
def run
|
||||||
lines[0..-2].each { |line| process_line(line, "\n") }
|
lines[0..-2].each { |line| process_line(line, "\n") }
|
||||||
process_line(lines[-1], '')
|
process_line(lines[-1], "")
|
||||||
|
|
||||||
STDOUT.flush
|
STDOUT.flush
|
||||||
output.flush
|
output.flush
|
||||||
|
@ -41,16 +40,16 @@ class ::Fingers::Hinter
|
||||||
private
|
private
|
||||||
|
|
||||||
attr_reader :hints,
|
attr_reader :hints,
|
||||||
:hints_by_text,
|
:hints_by_text,
|
||||||
:input,
|
:input,
|
||||||
:lookup_table,
|
:lookup_table,
|
||||||
:width,
|
:width,
|
||||||
:state,
|
:state,
|
||||||
:formatter,
|
:formatter,
|
||||||
:huffman,
|
:huffman,
|
||||||
:output,
|
:output,
|
||||||
:patterns,
|
:patterns,
|
||||||
:alphabet
|
:alphabet
|
||||||
|
|
||||||
def build_lookup_table!
|
def build_lookup_table!
|
||||||
@lookup_table = hints_by_text.invert
|
@lookup_table = hints_by_text.invert
|
||||||
|
@ -62,7 +61,7 @@ class ::Fingers::Hinter
|
||||||
end
|
end
|
||||||
|
|
||||||
def pattern
|
def pattern
|
||||||
@pattern ||= Regexp.compile("(#{patterns.join('|')})")
|
@pattern ||= Regexp.compile("(#{patterns.join("|")})")
|
||||||
end
|
end
|
||||||
|
|
||||||
def hints
|
def hints
|
||||||
|
@ -74,9 +73,9 @@ class ::Fingers::Hinter
|
||||||
def replace(match)
|
def replace(match)
|
||||||
text = match[0]
|
text = match[0]
|
||||||
|
|
||||||
captured_text = match && match.named_captures['capture'] || text
|
captured_text = match && match.named_captures["capture"] || text
|
||||||
|
|
||||||
if match.named_captures['capture']
|
if match.named_captures["capture"]
|
||||||
match_start, match_end = match.offset(0)
|
match_start, match_end = match.offset(0)
|
||||||
capture_start, capture_end = match.offset(:capture)
|
capture_start, capture_end = match.offset(:capture)
|
||||||
|
|
||||||
|
@ -85,7 +84,6 @@ class ::Fingers::Hinter
|
||||||
capture_offset = nil
|
capture_offset = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if hints_by_text.has_key?(captured_text)
|
if hints_by_text.has_key?(captured_text)
|
||||||
hint = hints_by_text[captured_text]
|
hint = hints_by_text[captured_text]
|
||||||
else
|
else
|
||||||
|
@ -103,7 +101,7 @@ class ::Fingers::Hinter
|
||||||
end
|
end
|
||||||
|
|
||||||
def lines
|
def lines
|
||||||
@lines ||= input.force_encoding('UTF-8').split("\n")
|
@lines ||= input.force_encoding("UTF-8").split("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def n_matches
|
def n_matches
|
||||||
|
@ -111,7 +109,7 @@ class ::Fingers::Hinter
|
||||||
|
|
||||||
match_set = ::Set.new
|
match_set = ::Set.new
|
||||||
|
|
||||||
Fingers.benchmark_stamp('counting-matches:start')
|
Fingers.benchmark_stamp("counting-matches:start")
|
||||||
|
|
||||||
lines.each do |line|
|
lines.each do |line|
|
||||||
line.scan(pattern) do |match|
|
line.scan(pattern) do |match|
|
||||||
|
@ -119,7 +117,7 @@ class ::Fingers::Hinter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Fingers.benchmark_stamp('counting-matches:end')
|
Fingers.benchmark_stamp("counting-matches:end")
|
||||||
|
|
||||||
@n_matches = match_set.length
|
@n_matches = match_set.length
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ class InputSocket
|
||||||
socket = server.accept
|
socket = server.accept
|
||||||
message = socket.readline
|
message = socket.readline
|
||||||
|
|
||||||
next if message == 'ping'
|
next if message == "ping"
|
||||||
|
|
||||||
yield message
|
yield message
|
||||||
end
|
end
|
||||||
|
@ -23,7 +23,7 @@ class InputSocket
|
||||||
end
|
end
|
||||||
|
|
||||||
def wait_for_input
|
def wait_for_input
|
||||||
send_message 'ping'
|
send_message "ping"
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'logger'
|
require "logger"
|
||||||
|
|
||||||
module Fingers
|
module Fingers
|
||||||
def self.logger
|
def self.logger
|
||||||
|
@ -7,7 +7,7 @@ module Fingers
|
||||||
@logger = Logger.new(
|
@logger = Logger.new(
|
||||||
Fingers::Dirs::LOG_PATH
|
Fingers::Dirs::LOG_PATH
|
||||||
)
|
)
|
||||||
@logger.level = Logger.const_get(ENV.fetch('FINGERS_LOG_LEVEL', 'INFO'))
|
@logger.level = Logger.const_get(ENV.fetch("FINGERS_LOG_LEVEL", "INFO"))
|
||||||
@logger
|
@logger
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ class ::Fingers::MatchFormatter
|
||||||
|
|
||||||
def format(hint:, highlight:, selected:, offset: nil)
|
def format(hint:, highlight:, selected:, offset: nil)
|
||||||
before_offset(offset, highlight) +
|
before_offset(offset, highlight) +
|
||||||
format_offset(selected, hint, within_offset(offset, highlight)) +
|
format_offset(selected, hint, within_offset(offset, highlight)) +
|
||||||
after_offset(offset, highlight)
|
after_offset(offset, highlight)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -57,7 +57,7 @@ class ::Fingers::MatchFormatter
|
||||||
end
|
end
|
||||||
|
|
||||||
def chop_highlight(hint, highlight)
|
def chop_highlight(hint, highlight)
|
||||||
if hint_position == 'right'
|
if hint_position == "right"
|
||||||
highlight[0..-(hint.length + 1)] || ""
|
highlight[0..-(hint.length + 1)] || ""
|
||||||
else
|
else
|
||||||
highlight[hint.length..-1] || ""
|
highlight[hint.length..-1] || ""
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module Fingers
|
module Fingers
|
||||||
VERSION = '2.0.0'.freeze
|
VERSION = "2.0.0".freeze
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ class Fingers::View
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_input(input)
|
def process_input(input)
|
||||||
command, *args = input.gsub(/-/, '_').split(':')
|
command, *args = input.tr("-", "_").split(":")
|
||||||
send("#{command}_message".to_sym, *args)
|
send("#{command}_message".to_sym, *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -42,10 +42,11 @@ class Fingers::View
|
||||||
|
|
||||||
def toggle_help_message
|
def toggle_help_message
|
||||||
output.print CLEAR_ESCAPE_SEQUENCE
|
output.print CLEAR_ESCAPE_SEQUENCE
|
||||||
output.print 'Help message'
|
output.print "Help message"
|
||||||
end
|
end
|
||||||
|
|
||||||
def noop_message; end
|
def noop_message
|
||||||
|
end
|
||||||
|
|
||||||
def toggle_multi_mode_message
|
def toggle_multi_mode_message
|
||||||
prev_state = state.multi_mode
|
prev_state = state.multi_mode
|
||||||
|
@ -53,7 +54,7 @@ class Fingers::View
|
||||||
current_state = state.multi_mode
|
current_state = state.multi_mode
|
||||||
|
|
||||||
if prev_state == true && current_state == false
|
if prev_state == true && current_state == false
|
||||||
state.result = state.multi_matches.join(' ')
|
state.result = state.multi_matches.join(" ")
|
||||||
request_exit!
|
request_exit!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -73,7 +74,7 @@ class Fingers::View
|
||||||
end
|
end
|
||||||
|
|
||||||
def fzf_message
|
def fzf_message
|
||||||
file = File.open('/tmp/fingers_fzf', 'w')
|
file = File.open("/tmp/fingers_fzf", "w")
|
||||||
hinter.matches.each do |match|
|
hinter.matches.each do |match|
|
||||||
file.puts match
|
file.puts match
|
||||||
end
|
end
|
||||||
|
@ -86,7 +87,7 @@ class Fingers::View
|
||||||
if state.multi_mode
|
if state.multi_mode
|
||||||
state.multi_matches << match
|
state.multi_matches << match
|
||||||
state.selected_hints << state.input
|
state.selected_hints << state.input
|
||||||
state.input = ''
|
state.input = ""
|
||||||
render
|
render
|
||||||
else
|
else
|
||||||
state.result = match
|
state.result = match
|
||||||
|
|
|
@ -111,6 +111,6 @@ class Huffman
|
||||||
end
|
end
|
||||||
|
|
||||||
def translate_path(path)
|
def translate_path(path)
|
||||||
path.map { |i| alphabet[i] }.join('')
|
path.map { |i| alphabet[i] }.join("")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
57
lib/tmux.rb
57
lib/tmux.rb
|
@ -1,6 +1,5 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# rubocop:disable Metrics/ClassLength
|
|
||||||
class Tmux
|
class Tmux
|
||||||
include Singleton
|
include Singleton
|
||||||
|
|
||||||
|
@ -58,34 +57,34 @@ class Tmux
|
||||||
def new_session(name, cmd, width, height)
|
def new_session(name, cmd, width, height)
|
||||||
flags = []
|
flags = []
|
||||||
|
|
||||||
flags.push('-f', config_file) if config_file
|
flags.push("-f", config_file) if config_file
|
||||||
|
|
||||||
`env -u TMUX #{tmux} #{flags.join(' ')} new-session -d -s #{name} -x #{width} -y #{height} '#{cmd}'`
|
`env -u TMUX #{tmux} #{flags.join(" ")} new-session -d -s #{name} -x #{width} -y #{height} '#{cmd}'`
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_server
|
def start_server
|
||||||
flags = []
|
flags = []
|
||||||
|
|
||||||
flags.push('-f', config_file) if config_file
|
flags.push("-f", config_file) if config_file
|
||||||
|
|
||||||
`#{tmux} #{flags.join(' ')} start-server &`
|
`#{tmux} #{flags.join(" ")} start-server &`
|
||||||
end
|
end
|
||||||
|
|
||||||
def pane_by_id(id)
|
def pane_by_id(id)
|
||||||
panes.find { |pane| pane['pane_id'] == id }
|
panes.find { |pane| pane["pane_id"] == id }
|
||||||
end
|
end
|
||||||
|
|
||||||
def window_by_id(id)
|
def window_by_id(id)
|
||||||
windows.find { |window| window['window_id'] == id }
|
windows.find { |window| window["window_id"] == id }
|
||||||
end
|
end
|
||||||
|
|
||||||
def panes_by_window_id(window_id)
|
def panes_by_window_id(window_id)
|
||||||
panes.select { |pane| pane['window_id'] == window_id }
|
panes.select { |pane| pane["window_id"] == window_id }
|
||||||
end
|
end
|
||||||
|
|
||||||
def pane_exec(pane_id, cmd)
|
def pane_exec(pane_id, cmd)
|
||||||
send_keys(pane_id, " #{cmd}")
|
send_keys(pane_id, " #{cmd}")
|
||||||
send_keys(pane_id, 'Enter')
|
send_keys(pane_id, "Enter")
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_keys(pane_id, keys)
|
def send_keys(pane_id, keys)
|
||||||
|
@ -95,7 +94,7 @@ class Tmux
|
||||||
def capture_pane(pane_id)
|
def capture_pane(pane_id)
|
||||||
pane = pane_by_id(pane_id)
|
pane = pane_by_id(pane_id)
|
||||||
|
|
||||||
if pane.pane_in_mode == '1'
|
if pane.pane_in_mode == "1"
|
||||||
start_line = -pane.scroll_position.to_i
|
start_line = -pane.scroll_position.to_i
|
||||||
end_line = pane.pane_height.to_i - pane.scroll_position.to_i - 1
|
end_line = pane.pane_height.to_i - pane.scroll_position.to_i - 1
|
||||||
|
|
||||||
|
@ -117,7 +116,7 @@ class Tmux
|
||||||
|
|
||||||
def swap_panes(src_id, dst_id)
|
def swap_panes(src_id, dst_id)
|
||||||
# TODO: -Z not supported on all tmux versions
|
# TODO: -Z not supported on all tmux versions
|
||||||
system(tmux, 'swap-pane', '-d', '-s', src_id, '-t', dst_id)
|
system(tmux, "swap-pane", "-d", "-s", src_id, "-t", dst_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def kill_pane(id)
|
def kill_pane(id)
|
||||||
|
@ -130,12 +129,12 @@ class Tmux
|
||||||
|
|
||||||
# TODO: this command is version dependant D:
|
# TODO: this command is version dependant D:
|
||||||
def resize_window(window_id, width, height)
|
def resize_window(window_id, width, height)
|
||||||
system(tmux, 'resize-window', '-t', window_id, '-x', width.to_s, '-y', height.to_s)
|
system(tmux, "resize-window", "-t", window_id, "-x", width.to_s, "-y", height.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: this command is version dependant D:
|
# TODO: this command is version dependant D:
|
||||||
def resize_pane(pane_id, width, height)
|
def resize_pane(pane_id, width, height)
|
||||||
system(tmux, 'resize-pane', '-t', pane_id, '-x', width.to_s, '-y', height.to_s)
|
system(tmux, "resize-pane", "-t", pane_id, "-x", width.to_s, "-y", height.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_pane_id
|
def last_pane_id
|
||||||
|
@ -143,21 +142,21 @@ class Tmux
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_window_option(name, value)
|
def set_window_option(name, value)
|
||||||
system(tmux, 'set-window-option', name, value)
|
system(tmux, "set-window-option", name, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_key_table(table)
|
def set_key_table(table)
|
||||||
system(tmux, 'set-window-option', 'key-table', table)
|
system(tmux, "set-window-option", "key-table", table)
|
||||||
system(tmux, 'switch-client', '-T', table)
|
system(tmux, "switch-client", "-T", table)
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_prefix
|
def disable_prefix
|
||||||
set_global_option('prefix', 'None')
|
set_global_option("prefix", "None")
|
||||||
set_global_option('prefix2', 'None')
|
set_global_option("prefix2", "None")
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_global_option(name, value)
|
def set_global_option(name, value)
|
||||||
system(tmux, 'set-option', '-g', name, value)
|
system(tmux, "set-option", "-g", name, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_global_option(name)
|
def get_global_option(name)
|
||||||
|
@ -167,15 +166,15 @@ class Tmux
|
||||||
def set_buffer(value)
|
def set_buffer(value)
|
||||||
return unless value
|
return unless value
|
||||||
|
|
||||||
system(tmux, 'set-buffer', value)
|
system(tmux, "set-buffer", value)
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_pane(id)
|
def select_pane(id)
|
||||||
system(tmux, 'select-pane', '-t', id)
|
system(tmux, "select-pane", "-t", id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def zoom_pane(id)
|
def zoom_pane(id)
|
||||||
system(tmux, 'resize-pane', '-Z', '-t', id)
|
system(tmux, "resize-pane", "-Z", "-t", id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_format(format)
|
def parse_format(format)
|
||||||
|
@ -191,29 +190,29 @@ class Tmux
|
||||||
def tmux
|
def tmux
|
||||||
flags = []
|
flags = []
|
||||||
|
|
||||||
flags.push('-L', socket_flag_value) if socket_flag_value
|
flags.push("-L", socket_flag_value) if socket_flag_value
|
||||||
|
|
||||||
return "tmux #{flags.join(' ')}" unless flags.empty?
|
return "tmux #{flags.join(" ")}" unless flags.empty?
|
||||||
|
|
||||||
'tmux'
|
"tmux"
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_tmux_output_format(fields)
|
def build_tmux_output_format(fields)
|
||||||
fields.map { |field| format("\#{%<field>s}", field: field) }.join(';')
|
fields.map { |field| format("\#{%<field>s}", field: field) }.join(";")
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_tmux_formatted_output(output)
|
def parse_tmux_formatted_output(output)
|
||||||
output.split("\n").map do |line|
|
output.split("\n").map do |line|
|
||||||
fields = line.split(';')
|
fields = line.split(";")
|
||||||
yield fields
|
yield fields
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def socket_flag_value
|
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
|
socket
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#Tmux = TmuxControl
|
# Tmux = TmuxControl
|
||||||
# rubocop:enable Metrics/ClassLength
|
# rubocop:enable Metrics/ClassLength
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class TmuxFormatPrinter
|
class TmuxFormatPrinter
|
||||||
FORMAT_SEPARATOR = /[ ,]+/.freeze
|
FORMAT_SEPARATOR = /[ ,]+/
|
||||||
|
|
||||||
COLOR_MAP = {
|
COLOR_MAP = {
|
||||||
black: 0,
|
black: 0,
|
||||||
|
@ -13,17 +13,17 @@ class TmuxFormatPrinter
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
LAYER_MAP = {
|
LAYER_MAP = {
|
||||||
bg: 'setab',
|
bg: "setab",
|
||||||
fg: 'setaf'
|
fg: "setaf"
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
STYLE_MAP = {
|
STYLE_MAP = {
|
||||||
bright: 'bold',
|
bright: "bold",
|
||||||
bold: 'bold',
|
bold: "bold",
|
||||||
dim: 'dim',
|
dim: "dim",
|
||||||
underscore: 'smul',
|
underscore: "smul",
|
||||||
reverse: 'rev',
|
reverse: "rev",
|
||||||
italics: 'sitm'
|
italics: "sitm"
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
class ShellExec
|
class ShellExec
|
||||||
|
@ -39,7 +39,7 @@ class TmuxFormatPrinter
|
||||||
def print(input, reset_styles_after: false)
|
def print(input, reset_styles_after: false)
|
||||||
@applied_styles = {}
|
@applied_styles = {}
|
||||||
|
|
||||||
output = ''
|
output = ""
|
||||||
|
|
||||||
input.split(FORMAT_SEPARATOR).each do |format|
|
input.split(FORMAT_SEPARATOR).each do |format|
|
||||||
output += parse_format(format)
|
output += parse_format(format)
|
||||||
|
@ -51,7 +51,7 @@ class TmuxFormatPrinter
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_format(format)
|
def parse_format(format)
|
||||||
if format.match(/^(bg|fg)=/)
|
if /^(bg|fg)=/.match?(format)
|
||||||
parse_color(format)
|
parse_color(format)
|
||||||
else
|
else
|
||||||
parse_style(format)
|
parse_style(format)
|
||||||
|
@ -65,7 +65,7 @@ class TmuxFormatPrinter
|
||||||
color = match[:color].to_sym
|
color = match[:color].to_sym
|
||||||
color_code = match[:color_code]
|
color_code = match[:color_code]
|
||||||
|
|
||||||
if match[:color] == 'default'
|
if match[:color] == "default"
|
||||||
@applied_styles.delete(layer)
|
@applied_styles.delete(layer)
|
||||||
return reset_to_applied_styles!
|
return reset_to_applied_styles!
|
||||||
end
|
end
|
||||||
|
@ -81,7 +81,7 @@ class TmuxFormatPrinter
|
||||||
|
|
||||||
def parse_style(format)
|
def parse_style(format)
|
||||||
match = format.match(/(?<remove>no)?(?<style>.*)/)
|
match = format.match(/(?<remove>no)?(?<style>.*)/)
|
||||||
should_remove_style = match[:remove] == 'no'
|
should_remove_style = match[:remove] == "no"
|
||||||
style = match[:style].to_sym
|
style = match[:style].to_sym
|
||||||
|
|
||||||
result = shell.exec("tput #{STYLE_MAP[style]}")
|
result = shell.exec("tput #{STYLE_MAP[style]}")
|
||||||
|
@ -101,7 +101,7 @@ class TmuxFormatPrinter
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_sequence
|
def reset_sequence
|
||||||
@reset_sequence ||= shell.exec('tput sgr0').chomp.freeze
|
@reset_sequence ||= shell.exec("tput sgr0").chomp.freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -1,141 +1,141 @@
|
||||||
require 'spec_helper'
|
require "spec_helper"
|
||||||
require_relative '../tmuxomatic_setup.rb'
|
require_relative "../tmuxomatic_setup"
|
||||||
|
|
||||||
describe 'acceptance', :retry => 3 do
|
describe "acceptance", retry: 3 do
|
||||||
include_context 'tmuxomatic setup'
|
include_context "tmuxomatic setup"
|
||||||
let(:config_name) { 'basic' }
|
let(:config_name) { "basic" }
|
||||||
|
|
||||||
context 'basic yank' do
|
context "basic yank" do
|
||||||
before do
|
before do
|
||||||
exec('cat spec/fixtures/grep-output')
|
exec("cat spec/fixtures/grep-output")
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
|
|
||||||
send_keys('b')
|
send_keys("b")
|
||||||
|
|
||||||
echo_yanked
|
echo_yanked
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('yanked text is scripts/debug.sh') }
|
it { should contain_content("yanked text is scripts/debug.sh") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'custom patterns' do
|
context "custom patterns" do
|
||||||
let(:config_name) { 'custom-patterns' }
|
let(:config_name) { "custom-patterns" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
exec('cat spec/fixtures/custom-patterns')
|
exec("cat spec/fixtures/custom-patterns")
|
||||||
|
|
||||||
send_keys('echo yanked text is ')
|
send_keys("echo yanked text is ")
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('y')
|
send_keys("y")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
paste
|
paste
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('b')
|
send_keys("b")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
paste
|
paste
|
||||||
|
|
||||||
send_keys('Enter')
|
send_keys("Enter")
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('yanked text is W00TW00TW00TYOLOYOLOYOLO') }
|
it { should contain_content("yanked text is W00TW00TW00TYOLOYOLOYOLO") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'more than one match per line' do
|
context "more than one match per line" do
|
||||||
before do
|
before do
|
||||||
exec('cat spec/fixtures/ip-output')
|
exec("cat spec/fixtures/ip-output")
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('i')
|
send_keys("i")
|
||||||
echo_yanked
|
echo_yanked
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('yanked text is 10.0.3.255') }
|
it { should contain_content("yanked text is 10.0.3.255") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'preserve zoom state' do
|
context "preserve zoom state" do
|
||||||
let(:config_name) { 'basic' }
|
let(:config_name) { "basic" }
|
||||||
before do
|
before do
|
||||||
send_prefix_and('%')
|
send_prefix_and("%")
|
||||||
# TODO: moving back to pane with PS1="# ". If you have emojis in PS1 it
|
# TODO: moving back to pane with PS1="# ". If you have emojis in PS1 it
|
||||||
# will break with this exception when splitting lines in hinter
|
# will break with this exception when splitting lines in hinter
|
||||||
#
|
#
|
||||||
# invalid byte sequence in US-ASCII (ArgumentError)
|
# invalid byte sequence in US-ASCII (ArgumentError)
|
||||||
#
|
#
|
||||||
send_prefix_and('Left')
|
send_prefix_and("Left")
|
||||||
send_prefix_and('z')
|
send_prefix_and("z")
|
||||||
|
|
||||||
exec('echo 123456')
|
exec("echo 123456")
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('C-c')
|
send_keys("C-c")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
exec('echo current pane is $(tmux list-panes -F "#{?window_zoomed_flag,zoomed,not_zoomed}" | head -1)')
|
exec('echo current pane is $(tmux list-panes -F "#{?window_zoomed_flag,zoomed,not_zoomed}" | head -1)')
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('current pane is zoomed') }
|
it { should contain_content("current pane is zoomed") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'alt action' do
|
context "alt action" do
|
||||||
let(:config_name) { 'alt-action' }
|
let(:config_name) { "alt-action" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
`rm -rf /tmp/fingers-stub-output`
|
`rm -rf /tmp/fingers-stub-output`
|
||||||
exec('cat spec/fixtures/grep-output')
|
exec("cat spec/fixtures/grep-output")
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('M-y')
|
send_keys("M-y")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
|
|
||||||
exec('cat /tmp/fingers-stub-output')
|
exec("cat /tmp/fingers-stub-output")
|
||||||
|
|
||||||
zzz 10
|
zzz 10
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('action-stub => scripts/hints.sh') }
|
it { should contain_content("action-stub => scripts/hints.sh") }
|
||||||
|
|
||||||
after do
|
after do
|
||||||
`rm -rf /tmp/fingers-stub-output`
|
`rm -rf /tmp/fingers-stub-output`
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'shift action' do
|
context "shift action" do
|
||||||
before do
|
before do
|
||||||
exec('cat spec/fixtures/grep-output')
|
exec("cat spec/fixtures/grep-output")
|
||||||
|
|
||||||
send_keys('yanked text is ')
|
send_keys("yanked text is ")
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('Y')
|
send_keys("Y")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('yanked text is scripts/hints.sh') }
|
it { should contain_content("yanked text is scripts/hints.sh") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'ctrl action' do
|
context "ctrl action" do
|
||||||
let(:config_name) { 'ctrl-action' }
|
let(:config_name) { "ctrl-action" }
|
||||||
let(:prefix) { 'C-b' }
|
let(:prefix) { "C-b" }
|
||||||
let(:hint_to_press) { 'C-y' }
|
let(:hint_to_press) { "C-y" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
`rm -rf /tmp/fingers-stub-output`
|
`rm -rf /tmp/fingers-stub-output`
|
||||||
exec('cat spec/fixtures/grep-output')
|
exec("cat spec/fixtures/grep-output")
|
||||||
|
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys(hint_to_press)
|
send_keys(hint_to_press)
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
|
|
||||||
exec('cat /tmp/fingers-stub-output')
|
exec("cat /tmp/fingers-stub-output")
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('action-stub => scripts/hints.sh') }
|
it { should contain_content("action-stub => scripts/hints.sh") }
|
||||||
|
|
||||||
context 'and is sending prefix' do
|
context "and is sending prefix" do
|
||||||
let(:hint_to_press) { prefix }
|
let(:hint_to_press) { prefix }
|
||||||
|
|
||||||
it { should contain_content('action-stub => scripts/debug.sh') }
|
it { should contain_content("action-stub => scripts/debug.sh") }
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
|
@ -143,20 +143,20 @@ describe 'acceptance', :retry => 3 do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'copy stuff with quotes' do
|
context "copy stuff with quotes" do
|
||||||
let(:config_name) { 'quotes' }
|
let(:config_name) { "quotes" }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
# zleep 3
|
# zleep 3
|
||||||
exec('cat spec/fixtures/quotes')
|
exec("cat spec/fixtures/quotes")
|
||||||
send_keys('echo yanked text is ')
|
send_keys("echo yanked text is ")
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('b')
|
send_keys("b")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
paste
|
paste
|
||||||
send_keys(' ')
|
send_keys(" ")
|
||||||
invoke_fingers
|
invoke_fingers
|
||||||
send_keys('y')
|
send_keys("y")
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
paste
|
paste
|
||||||
end
|
end
|
||||||
|
@ -164,15 +164,15 @@ describe 'acceptance', :retry => 3 do
|
||||||
it { should contain_content(%(yanked text is "laser" 'laser')) }
|
it { should contain_content(%(yanked text is "laser" 'laser')) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'config options validation' do
|
context "config options validation" do
|
||||||
let(:config_name) { 'invalid' }
|
let(:config_name) { "invalid" }
|
||||||
let(:wait_for_initial_clear) { false }
|
let(:wait_for_initial_clear) { false }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
zzz 5
|
zzz 5
|
||||||
end
|
end
|
||||||
|
|
||||||
it { should contain_content('@fingers-lol is not a valid option') }
|
it { should contain_content("@fingers-lol is not a valid option") }
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: multi match spec
|
# TODO: multi match spec
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
require 'spec_helper'
|
require "spec_helper"
|
||||||
require_relative '../tmuxomatic_setup.rb'
|
require_relative "../tmuxomatic_setup"
|
||||||
require 'benchmark'
|
require "benchmark"
|
||||||
|
|
||||||
describe 'performance', performance: true do
|
describe "performance", performance: true do
|
||||||
include_context 'tmuxomatic setup'
|
include_context "tmuxomatic setup"
|
||||||
let(:config_name) { 'benchmark' }
|
let(:config_name) { "benchmark" }
|
||||||
let(:tmuxomatic_window_width) { 100 }
|
let(:tmuxomatic_window_width) { 100 }
|
||||||
let(:tmuxomatic_window_height) { 100 }
|
let(:tmuxomatic_window_height) { 100 }
|
||||||
|
|
||||||
it 'runs smooooooth' do
|
it "runs smooooooth" do
|
||||||
ruby = RbConfig.ruby
|
ruby = RbConfig.ruby
|
||||||
exec('COLUMNS=$COLUMNS LINES=$LINES ruby spec/fill_screen.rb')
|
exec("COLUMNS=$COLUMNS LINES=$LINES ruby spec/fill_screen.rb")
|
||||||
exec(%(hyperfine --export-json /tmp/perf.json "#{ruby} --disable-gems bin/fingers start fingers-mode $TMUX_PANE self"))
|
exec(%(hyperfine --export-json /tmp/perf.json "#{ruby} --disable-gems bin/fingers start fingers-mode $TMUX_PANE self"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
require 'securerandom'
|
require "securerandom"
|
||||||
|
|
||||||
ENV['LINES'].to_i.times do
|
ENV["LINES"].to_i.times do
|
||||||
codes = []
|
codes = []
|
||||||
(ENV['COLUMNS'].to_i / 16 - 1).times do
|
(ENV["COLUMNS"].to_i / 16 - 1).times do
|
||||||
codes << SecureRandom.hex(8).to_s.tr('abcdef', '123456')
|
codes << SecureRandom.hex(8).to_s.tr("abcdef", "123456")
|
||||||
end
|
end
|
||||||
|
|
||||||
puts codes.join(' ')
|
puts codes.join(" ")
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
describe Fingers::Hinter do
|
describe Fingers::Hinter do
|
||||||
let(:input) do
|
let(:input) do
|
||||||
'
|
'
|
||||||
ola ke ase
|
ola ke ase
|
||||||
ke ase ola
|
ke ase ola
|
||||||
ke olaola ke
|
ke olaola ke
|
||||||
|
@ -23,7 +23,7 @@ beep beep
|
||||||
let(:output) do
|
let(:output) do
|
||||||
class TextOutput
|
class TextOutput
|
||||||
def initialize
|
def initialize
|
||||||
@contents = ''
|
@contents = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
def print(msg)
|
def print(msg)
|
||||||
|
@ -42,17 +42,17 @@ beep beep
|
||||||
|
|
||||||
let(:formatter) do
|
let(:formatter) do
|
||||||
::Fingers::MatchFormatter.new(
|
::Fingers::MatchFormatter.new(
|
||||||
hint_format: '%s',
|
hint_format: "%s",
|
||||||
highlight_format: '%s',
|
highlight_format: "%s",
|
||||||
selected_hint_format: '%s',
|
selected_hint_format: "%s",
|
||||||
selected_highlight_format: '%s',
|
selected_highlight_format: "%s",
|
||||||
hint_position: 'left'
|
hint_position: "left"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:patterns) { ['ola'] }
|
let(:patterns) { ["ola"] }
|
||||||
|
|
||||||
let(:alphabet) { 'asdf'.split('') }
|
let(:alphabet) { "asdf".split("") }
|
||||||
|
|
||||||
let(:hinter) do
|
let(:hinter) do
|
||||||
::Fingers::Hinter.new(
|
::Fingers::Hinter.new(
|
||||||
|
@ -62,11 +62,11 @@ beep beep
|
||||||
patterns: patterns,
|
patterns: patterns,
|
||||||
alphabet: alphabet,
|
alphabet: alphabet,
|
||||||
output: output,
|
output: output,
|
||||||
formatter: formatter,
|
formatter: formatter
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'works' do
|
it "works" do
|
||||||
hinter.run
|
hinter.run
|
||||||
|
|
||||||
puts output.contents
|
puts output.contents
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
require 'spec_helper'
|
require "spec_helper"
|
||||||
|
|
||||||
describe Fingers::MatchFormatter do
|
describe Fingers::MatchFormatter do
|
||||||
let(:hint_format) { '#[fg=yellow,bold]' }
|
let(:hint_format) { "#[fg=yellow,bold]" }
|
||||||
let(:highlight_format) { '#[fg=yellow]' }
|
let(:highlight_format) { "#[fg=yellow]" }
|
||||||
let(:hint_position) { 'left' }
|
let(:hint_position) { "left" }
|
||||||
let(:selected_hint_format) { '#[fg=green,bold]' }
|
let(:selected_hint_format) { "#[fg=green,bold]" }
|
||||||
let(:selected_highlight_format) { '#[fg=green]' }
|
let(:selected_highlight_format) { "#[fg=green]" }
|
||||||
let(:selected) { false }
|
let(:selected) { false }
|
||||||
let(:offset) { nil }
|
let(:offset) { nil }
|
||||||
|
|
||||||
let(:hint) { 'a' }
|
let(:hint) { "a" }
|
||||||
let(:highlight) { 'yolo' }
|
let(:highlight) { "yolo" }
|
||||||
|
|
||||||
let(:formatter) do
|
let(:formatter) do
|
||||||
described_class.new(
|
described_class.new(
|
||||||
|
@ -19,7 +19,7 @@ describe Fingers::MatchFormatter do
|
||||||
selected_highlight_format: selected_highlight_format,
|
selected_highlight_format: selected_highlight_format,
|
||||||
selected_hint_format: selected_hint_format,
|
selected_hint_format: selected_hint_format,
|
||||||
hint_position: hint_position,
|
hint_position: hint_position,
|
||||||
reset_sequence: '#[reset]'
|
reset_sequence: "#[reset]"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -27,39 +27,39 @@ describe Fingers::MatchFormatter do
|
||||||
formatter.format(hint: hint, highlight: highlight, selected: selected, offset: offset)
|
formatter.format(hint: hint, highlight: highlight, selected: selected, offset: offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when hint position' do
|
context "when hint position" do
|
||||||
context 'is set to left' do
|
context "is set to left" do
|
||||||
let(:hint_position) { 'left' }
|
let(:hint_position) { "left" }
|
||||||
|
|
||||||
it 'places the hint on the left side' do
|
it "places the hint on the left side" do
|
||||||
expect(result).to eq('#[fg=yellow,bold]a#[fg=yellow]olo#[reset]')
|
expect(result).to eq("#[fg=yellow,bold]a#[fg=yellow]olo#[reset]")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'is set to right' do
|
context "is set to right" do
|
||||||
let(:hint_position) { 'right' }
|
let(:hint_position) { "right" }
|
||||||
|
|
||||||
it 'places the hint on the right side' do
|
it "places the hint on the right side" do
|
||||||
expect(result).to eq('#[fg=yellow]yol#[fg=yellow,bold]a#[reset]')
|
expect(result).to eq("#[fg=yellow]yol#[fg=yellow,bold]a#[reset]")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when a hint is selected' do
|
context "when a hint is selected" do
|
||||||
let(:selected) { true }
|
let(:selected) { true }
|
||||||
|
|
||||||
it 'selects the correct format' do
|
it "selects the correct format" do
|
||||||
expect(result).to eq('#[fg=green,bold]a#[fg=green]olo#[reset]')
|
expect(result).to eq("#[fg=green,bold]a#[fg=green]olo#[reset]")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when offset is provided' do
|
context "when offset is provided" do
|
||||||
let(:offset) { [1, 5] }
|
let(:offset) { [1, 5] }
|
||||||
let(:highlight) { 'yoloyoloyolo' }
|
let(:highlight) { "yoloyoloyolo" }
|
||||||
let(:hint) { 'a' }
|
let(:hint) { "a" }
|
||||||
|
|
||||||
it 'only highlights at specified offset' do
|
it "only highlights at specified offset" do
|
||||||
expect(result).to eq('y#[fg=yellow,bold]a#[fg=yellow]loyo#[reset]loyolo')
|
expect(result).to eq("y#[fg=yellow,bold]a#[fg=yellow]loyo#[reset]loyolo")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'spec_helper'
|
require "spec_helper"
|
||||||
|
|
||||||
describe TmuxFormatPrinter do
|
describe TmuxFormatPrinter do
|
||||||
let(:printer) do
|
let(:printer) do
|
||||||
|
@ -11,21 +11,21 @@ describe TmuxFormatPrinter do
|
||||||
TmuxFormatPrinter.new(shell: FakeShell.new)
|
TmuxFormatPrinter.new(shell: FakeShell.new)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'transforms tmux status line format into escape sequences' do
|
it "transforms tmux status line format into escape sequences" do
|
||||||
result = printer.print('bg=red,fg=yellow,bold', reset_styles_after: true)
|
result = printer.print("bg=red,fg=yellow,bold", reset_styles_after: true)
|
||||||
expected = '$(tput setab 1)$(tput setaf 3)$(tput bold)$(tput sgr0)'
|
expected = "$(tput setab 1)$(tput setaf 3)$(tput bold)$(tput sgr0)"
|
||||||
|
|
||||||
expect(result).to eq(expected)
|
expect(result).to eq(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'transforms tmux status line format into escape sequences' do
|
it "transforms tmux status line format into escape sequences" do
|
||||||
result = printer.print('bg=red,fg=yellow,bold', reset_styles_after: true)
|
result = printer.print("bg=red,fg=yellow,bold", reset_styles_after: true)
|
||||||
expected = '$(tput setab 1)$(tput setaf 3)$(tput bold)$(tput sgr0)'
|
expected = "$(tput setab 1)$(tput setaf 3)$(tput bold)$(tput sgr0)"
|
||||||
|
|
||||||
expect(result).to eq(expected)
|
expect(result).to eq(expected)
|
||||||
end
|
end
|
||||||
|
|
||||||
xit 'raises on unknown formats' do
|
xit "raises on unknown formats" do
|
||||||
# TODO
|
# TODO
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
$LOAD_PATH.unshift File.expand_path("lib", __dir__)
|
||||||
|
|
||||||
require 'byebug'
|
require "byebug"
|
||||||
require 'fingers'
|
require "fingers"
|
||||||
require 'rspec/retry'
|
require "rspec/retry"
|
||||||
|
|
||||||
# This file was generated by the `rspec --init` command. Conventionally, all
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
||||||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
||||||
|
@ -57,7 +57,7 @@ RSpec.configure do |config|
|
||||||
# # is tagged with `:focus`, all examples get run. RSpec also provides
|
# # is tagged with `:focus`, all examples get run. RSpec also provides
|
||||||
# # aliases for `it`, `describe`, and `context` that include `:focus`
|
# # aliases for `it`, `describe`, and `context` that include `:focus`
|
||||||
# # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
# # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
||||||
#config.filter_run_excluding :performance
|
# config.filter_run_excluding :performance
|
||||||
#
|
#
|
||||||
# # Allows RSpec to persist some state between runs in order to support
|
# # Allows RSpec to persist some state between runs in order to support
|
||||||
# # the `--only-failures` and `--next-failure` CLI options. We recommend
|
# # the `--only-failures` and `--next-failure` CLI options. We recommend
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
require 'rspec/expectations'
|
require "rspec/expectations"
|
||||||
require 'byebug'
|
require "byebug"
|
||||||
require 'timeout'
|
require "timeout"
|
||||||
|
|
||||||
shared_context 'tmuxomatic setup', a: :b do
|
shared_context "tmuxomatic setup", a: :b do
|
||||||
let(:tmuxomatic) do
|
let(:tmuxomatic) do
|
||||||
Tmux.instance.socket = 'tmuxomatic'
|
Tmux.instance.socket = "tmuxomatic"
|
||||||
Tmux.instance.config_file = '/dev/null'
|
Tmux.instance.config_file = "/dev/null"
|
||||||
|
|
||||||
# TODO: resize window to 80x24?
|
# TODO: resize window to 80x24?
|
||||||
|
|
||||||
Tmux.instance
|
Tmux.instance
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:config_name) { 'basic' }
|
let(:config_name) { "basic" }
|
||||||
let(:prefix) { 'C-a' }
|
let(:prefix) { "C-a" }
|
||||||
let(:fingers_key) { 'F' }
|
let(:fingers_key) { "F" }
|
||||||
let(:tmuxomatic_window_width) { 80 }
|
let(:tmuxomatic_window_width) { 80 }
|
||||||
let(:tmuxomatic_window_height) { 24 }
|
let(:tmuxomatic_window_height) { 24 }
|
||||||
|
|
||||||
let(:tmuxomatic_pane_id) { tmuxomatic.panes.first['pane_id'] }
|
let(:tmuxomatic_pane_id) { tmuxomatic.panes.first["pane_id"] }
|
||||||
let(:tmuxomatic_window_id) { tmuxomatic.panes.first['window_id'] }
|
let(:tmuxomatic_window_id) { tmuxomatic.panes.first["window_id"] }
|
||||||
let(:wait_for_initial_clear) { true }
|
let(:wait_for_initial_clear) { true }
|
||||||
|
|
||||||
# Like sleep, but slower on CI lol
|
# Like sleep, but slower on CI lol
|
||||||
def zzz(amount)
|
def zzz(amount)
|
||||||
sleep ENV['CI'] ? amount * 2 : amount
|
sleep ENV["CI"] ? amount * 2 : amount
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_keys(keys, trace_benchmark: false)
|
def send_keys(keys, trace_benchmark: false)
|
||||||
|
@ -36,7 +36,7 @@ shared_context 'tmuxomatic setup', a: :b do
|
||||||
end
|
end
|
||||||
|
|
||||||
def exec(cmd, wait: true)
|
def exec(cmd, wait: true)
|
||||||
wait_for_trace(trace: 'command-completed', wait: wait) do
|
wait_for_trace(trace: "command-completed", wait: wait) do
|
||||||
tmuxomatic.pane_exec(tmuxomatic_pane_id, cmd)
|
tmuxomatic.pane_exec(tmuxomatic_pane_id, cmd)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -58,7 +58,7 @@ shared_context 'tmuxomatic setup', a: :b do
|
||||||
|
|
||||||
def wait_for_fingers_teardown
|
def wait_for_fingers_teardown
|
||||||
Timeout.timeout(10) do
|
Timeout.timeout(10) do
|
||||||
sleep 0.2 while tmuxomatic.capture_pane(tmuxomatic_pane_id).include?('[fingers]')
|
sleep 0.2 while tmuxomatic.capture_pane(tmuxomatic_pane_id).include?("[fingers]")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,11 +67,11 @@ shared_context 'tmuxomatic setup', a: :b do
|
||||||
end
|
end
|
||||||
|
|
||||||
def count_in_log_file(str)
|
def count_in_log_file(str)
|
||||||
File.open(Fingers::Dirs::LOG_PATH).read.scan(str).length
|
File.read(Fingers::Dirs::LOG_PATH).scan(str).length
|
||||||
end
|
end
|
||||||
|
|
||||||
def invoke_fingers(trace_benchmark: false)
|
def invoke_fingers(trace_benchmark: false)
|
||||||
wait_for_trace(trace: 'fingers-ready', wait: true) do
|
wait_for_trace(trace: "fingers-ready", wait: true) do
|
||||||
send_keys(prefix)
|
send_keys(prefix)
|
||||||
send_keys(fingers_key, trace_benchmark: trace_benchmark)
|
send_keys(fingers_key, trace_benchmark: trace_benchmark)
|
||||||
end
|
end
|
||||||
|
@ -80,14 +80,14 @@ shared_context 'tmuxomatic setup', a: :b do
|
||||||
|
|
||||||
def echo_yanked
|
def echo_yanked
|
||||||
wait_for_fingers_teardown
|
wait_for_fingers_teardown
|
||||||
exec('clear')
|
exec("clear")
|
||||||
send_keys('echo yanked text is ')
|
send_keys("echo yanked text is ")
|
||||||
paste
|
paste
|
||||||
end
|
end
|
||||||
|
|
||||||
def paste
|
def paste
|
||||||
send_keys(prefix)
|
send_keys(prefix)
|
||||||
send_keys(']')
|
send_keys("]")
|
||||||
zzz 0.5
|
zzz 0.5
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -97,33 +97,33 @@ shared_context 'tmuxomatic setup', a: :b do
|
||||||
end
|
end
|
||||||
|
|
||||||
def tmuxomatic_unlock_path
|
def tmuxomatic_unlock_path
|
||||||
File.expand_path(File.join(File.dirname(__FILE__), '.tmuxomatic_unlock_command_prompt'))
|
File.expand_path(File.join(File.dirname(__FILE__), ".tmuxomatic_unlock_command_prompt"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def fingers_root
|
def fingers_root
|
||||||
File.expand_path(File.join(File.dirname(__FILE__), '../'))
|
File.expand_path(File.join(File.dirname(__FILE__), "../"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def fingers_stubs_path
|
def fingers_stubs_path
|
||||||
File.expand_path(File.join(
|
File.expand_path(File.join(
|
||||||
fingers_root,
|
fingers_root,
|
||||||
'./spec/stubs'
|
"./spec/stubs"
|
||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
conf_path = File.expand_path(
|
conf_path = File.expand_path(
|
||||||
File.join(
|
File.join(
|
||||||
File.dirname(__FILE__),
|
File.dirname(__FILE__),
|
||||||
'../spec/conf/',
|
"../spec/conf/",
|
||||||
"#{config_name}.conf"
|
"#{config_name}.conf"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
tmuxomatic
|
tmuxomatic
|
||||||
tmuxomatic.new_session('tmuxomatic', "PATH=\"#{fingers_root}:#{fingers_stubs_path}:$PATH\" TMUX='' tmux -L tmuxomatic_inner -f #{conf_path}", tmuxomatic_window_width, tmuxomatic_window_height)
|
tmuxomatic.new_session("tmuxomatic", "PATH=\"#{fingers_root}:#{fingers_stubs_path}:$PATH\" TMUX='' tmux -L tmuxomatic_inner -f #{conf_path}", tmuxomatic_window_width, tmuxomatic_window_height)
|
||||||
tmuxomatic.set_global_option('prefix', 'None')
|
tmuxomatic.set_global_option("prefix", "None")
|
||||||
tmuxomatic.set_global_option('status', 'off')
|
tmuxomatic.set_global_option("status", "off")
|
||||||
tmuxomatic.resize_window(tmuxomatic_window_id, tmuxomatic_window_width, tmuxomatic_window_height)
|
tmuxomatic.resize_window(tmuxomatic_window_id, tmuxomatic_window_width, tmuxomatic_window_height)
|
||||||
|
|
||||||
`touch #{Fingers::Dirs::LOG_PATH}`
|
`touch #{Fingers::Dirs::LOG_PATH}`
|
||||||
|
@ -136,7 +136,7 @@ shared_context 'tmuxomatic setup', a: :b do
|
||||||
exec("export PROMPT_COMMAND='#{tmuxomatic_unlock_path}'", wait: false)
|
exec("export PROMPT_COMMAND='#{tmuxomatic_unlock_path}'", wait: false)
|
||||||
zzz 1.0
|
zzz 1.0
|
||||||
|
|
||||||
exec('clear', wait: wait_for_initial_clear)
|
exec("clear", wait: wait_for_initial_clear)
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
|
@ -149,7 +149,7 @@ def wrap_in_box(output, width)
|
||||||
output.split("\n").map do |line|
|
output.split("\n").map do |line|
|
||||||
"│" + line.ljust(width, " ") + "│"
|
"│" + line.ljust(width, " ") + "│"
|
||||||
end.join("\n") + "\n" +
|
end.join("\n") + "\n" +
|
||||||
"└" + "─" * width + "┘"
|
"└" + "─" * width + "┘"
|
||||||
end
|
end
|
||||||
|
|
||||||
RSpec::Matchers.define :contain_content do |expected|
|
RSpec::Matchers.define :contain_content do |expected|
|
||||||
|
@ -164,6 +164,6 @@ RSpec::Matchers.define :contain_content do |expected|
|
||||||
|
|
||||||
failure_message do |_actual|
|
failure_message do |_actual|
|
||||||
"Could not find '#{expected}' in:\n" +
|
"Could not find '#{expected}' in:\n" +
|
||||||
wrap_in_box(pane_output, pane.pane_width.to_i)
|
wrap_in_box(pane_output, pane.pane_width.to_i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit e727260def12b0df311e71b73f94e85ab0b00e31
|
|
Loading…
Reference in New Issue