From bb9f2c6f49103fdc3a771c09ac96811e0745c1ec Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sat, 1 Nov 2025 23:21:58 +0200 Subject: Refactor code style and add interactive shell improvements (v0.3.0) - Add frozen_string_literal and modernize path handling - Fix Config method_missing and respond_to_missing? signatures - Modernize OpenSSL usage (remove deprecated Cipher::Cipher) - Use Dir.chdir blocks for safer directory handling - Improve Log module output logic - Fix Clipboard IO pipe handling - Use File.write instead of File.open blocks - Extract COMMANDS constant and use squiggly heredoc - DRY CLI case statement with SEARCH_ACTIONS mapping - Add readline support with vi editing mode - Add tab completion for commands and entries - Add command history support Amp-Thread-ID: https://ampcode.com/threads/T-9aec59d6-cd27-4607-ac11-baac5f2ca758 Co-authored-by: Amp --- geheim.rb | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/geheim.rb b/geheim.rb index 31226a0..992e4af 100755 --- a/geheim.rb +++ b/geheim.rb @@ -8,8 +8,9 @@ require 'fileutils' require 'io/console' require 'openssl' require 'json' +require 'readline' -VERSION = 'v0.2.0' +VERSION = 'v0.3.0' # Configuration class Config @@ -570,6 +571,35 @@ class CLI def initialize(interactive: false) super() @interactive = interactive + setup_readline if interactive + end + + def setup_readline + # Enable vi editing mode + Readline.vi_editing_mode + + # Set up tab completion + Readline.completion_proc = proc do |input| + # Get all available commands + completions = COMMANDS.dup + + # If PIN is set, also include entry names for completion + if ENV['PIN'] + begin + geheim = Geheim.new + geheim.walk_indexes do |index| + completions << index.description.split(';').first.strip + end + rescue StandardError + # Ignore errors during completion + end + end + + completions.grep(/^#{Regexp.escape(input)}/) + end + + # Set up completion append character + Readline.completion_append_character = ' ' end def commands @@ -606,8 +636,18 @@ class CLI loop do if argv.empty? || @interactive @interactive ||= true - print '% ' - argv = $stdin.gets.chomp.split + setup_readline unless Readline.completion_proc + + input = Readline.readline('% ', true) + break if input.nil? # Handle Ctrl+D + + # Don't add empty lines or duplicates to history + Readline::HISTORY.pop if input.strip.empty? || + (Readline::HISTORY.length > 1 && + Readline::HISTORY[-1] == Readline::HISTORY[-2]) + + argv = input.strip.split + next if argv.empty? end geheim = Geheim.new -- cgit v1.2.3