207 lines
5.2 KiB
Crystal
207 lines
5.2 KiB
Crystal
require "file_utils"
|
|
require "./base"
|
|
require "../dirs"
|
|
require "../config"
|
|
require "../../tmux"
|
|
|
|
class Fingers::Commands::LoadConfig < Fingers::Commands::Base
|
|
@fingers_options_names : Array(String) | Nil
|
|
|
|
property config : Fingers::Config
|
|
|
|
DISALLOWED_CHARS = /[cimqn]/
|
|
|
|
def initialize(*args)
|
|
super(*args)
|
|
@config = Fingers::Config.new
|
|
end
|
|
|
|
def run
|
|
validate_options!
|
|
parse_tmux_conf
|
|
setup_bindings
|
|
end
|
|
|
|
# private
|
|
|
|
def parse_tmux_conf
|
|
options = shell_safe_options
|
|
|
|
user_defined_patterns = [] of String
|
|
|
|
Fingers.reset_config
|
|
|
|
config.tmux_version = `tmux -V`.chomp.split(" ").last
|
|
|
|
options.each do |option, value|
|
|
# TODO generate an enum somehow and use an exhaustive case
|
|
case option
|
|
when "key"
|
|
config.key = value
|
|
when "jump_key"
|
|
config.jump_key = value
|
|
when "keyboard_layout"
|
|
config.keyboard_layout = value
|
|
when "main_action"
|
|
config.main_action = value
|
|
when "ctrl_action"
|
|
config.ctrl_action = value
|
|
when "alt_action"
|
|
config.alt_action = value
|
|
when "shift_action"
|
|
config.shift_action = value
|
|
when "benchmark_mode"
|
|
config.benchmark_mode = value
|
|
when "hint_position"
|
|
config.hint_position = value
|
|
when "hint_style"
|
|
config.hint_style = tmux.parse_style(value)
|
|
when "selected_hint_style"
|
|
config.selected_hint_style = tmux.parse_style(value)
|
|
when "highlight_style"
|
|
config.highlight_style = tmux.parse_style(value)
|
|
when "backdrop_style"
|
|
config.backdrop_style = tmux.parse_style(value)
|
|
when "selected_highlight_style"
|
|
config.selected_highlight_style = tmux.parse_style(value)
|
|
when "show_copied_notification"
|
|
config.show_copied_notification = value
|
|
end
|
|
|
|
if option.match(/pattern/)
|
|
check_pattern!(value)
|
|
user_defined_patterns.push(value)
|
|
end
|
|
end
|
|
|
|
config.patterns = clean_up_patterns([
|
|
*enabled_default_patterns,
|
|
*user_defined_patterns,
|
|
])
|
|
|
|
config.alphabet = ::Fingers::Config::ALPHABET_MAP[Fingers.config.keyboard_layout].split("").reject do |char|
|
|
char.match(DISALLOWED_CHARS)
|
|
end
|
|
|
|
config.save
|
|
|
|
Fingers.reset_config
|
|
rescue e : TmuxStylePrinter::InvalidFormat
|
|
puts "[tmux-fingers] #{e.message}"
|
|
exit(1)
|
|
end
|
|
|
|
def clean_up_patterns(patterns)
|
|
patterns.reject(&.empty?)
|
|
end
|
|
|
|
def setup_bindings
|
|
`tmux bind-key #{Fingers.config.key} run-shell -b "#{cli} start "\#{pane_id}" self >>#{Fingers::Dirs::LOG_PATH} 2>&1"`
|
|
`tmux bind-key #{Fingers.config.jump_key} run-shell -b "#{cli} start "\#{pane_id}" jump >>#{Fingers::Dirs::LOG_PATH} 2>&1"`
|
|
setup_fingers_mode_bindings
|
|
end
|
|
|
|
def setup_fingers_mode_bindings
|
|
("a".."z").to_a.each do |char|
|
|
next if char.match(DISALLOWED_CHARS)
|
|
|
|
fingers_mode_bind(char, "hint:#{char}:main")
|
|
fingers_mode_bind(char.upcase, "hint:#{char}:shift")
|
|
fingers_mode_bind("C-#{char}", "hint:#{char}:ctrl")
|
|
fingers_mode_bind("M-#{char}", "hint:#{char}:alt")
|
|
end
|
|
|
|
fingers_mode_bind("Space", "fzf")
|
|
fingers_mode_bind("C-c", "exit")
|
|
fingers_mode_bind("q", "exit")
|
|
fingers_mode_bind("Escape", "exit")
|
|
|
|
fingers_mode_bind("?", "toggle-help")
|
|
|
|
fingers_mode_bind("Enter", "noop")
|
|
fingers_mode_bind("Tab", "toggle-multi-mode")
|
|
|
|
fingers_mode_bind("Any", "noop")
|
|
end
|
|
|
|
def enabled_default_patterns
|
|
::Fingers::Config::DEFAULT_PATTERNS.values
|
|
end
|
|
|
|
def to_bool(input)
|
|
input == "1"
|
|
end
|
|
|
|
def shell_safe_options
|
|
options = {} of String => String
|
|
|
|
fingers_options_names.each do |option|
|
|
option_method = option_to_method(option)
|
|
|
|
options[option_method] = `tmux show-option -gv #{option}`.chomp
|
|
end
|
|
|
|
options
|
|
end
|
|
|
|
def valid_option?(option)
|
|
option_method = option_to_method(option)
|
|
|
|
@config.members.includes?(option_method) || option_method.match(/pattern_[0-9]+/) || option_method == "skip_wizard"
|
|
end
|
|
|
|
def fingers_options_names
|
|
@fingers_options_names ||= `tmux show-options -g | grep ^@fingers`
|
|
.chomp.split("\n")
|
|
.map { |line| line.split(" ")[0] }
|
|
.reject { |option| option.empty? }
|
|
end
|
|
|
|
def unset_tmux_option!(option)
|
|
`tmux set-option -ug #{option}`
|
|
end
|
|
|
|
def check_pattern!(pattern)
|
|
begin
|
|
Regex.new(pattern)
|
|
rescue e: ArgumentError
|
|
puts "[tmux-fingers] Invalid pattern: #{pattern}"
|
|
puts "[tmux-fingers] #{e.message}"
|
|
exit(1)
|
|
end
|
|
end
|
|
|
|
def validate_options!
|
|
errors = [] of String
|
|
|
|
fingers_options_names.each do |option|
|
|
unless valid_option?(option)
|
|
errors << "'#{option}' is not a valid option"
|
|
unset_tmux_option!(option)
|
|
end
|
|
end
|
|
|
|
return if errors.empty?
|
|
|
|
puts "[tmux-fingers] Errors found in tmux.conf:"
|
|
errors.each { |error| puts " - #{error}" }
|
|
exit(1)
|
|
end
|
|
|
|
def option_to_method(option)
|
|
option.gsub(/^@fingers-/, "").tr("-", "_")
|
|
end
|
|
|
|
def fingers_mode_bind(key, command)
|
|
`tmux bind-key -Tfingers "#{key}" run-shell -b "#{cli} send-input #{command}"`
|
|
end
|
|
|
|
def cli
|
|
Process.executable_path
|
|
end
|
|
|
|
def tmux
|
|
Tmux.new(`tmux -V`.chomp.split(" ").last)
|
|
end
|
|
end
|