Class: Architext::TUI
- Inherits:
-
Object
- Object
- Architext::TUI
- Defined in:
- lib/architext/tui.rb
Overview
rubocop:disable Metrics/ClassLength
Defined Under Namespace
Classes: QueryPrompt, Selection, VaultConfigAction
Constant Summary collapse
- HELP =
'Up/k Down/j move space select a all / filter n new search v vault enter confirm q back'- KEY_BINDINGS =
{ ' ' => :space, 'k' => :up, 'j' => :down, 'a' => :all, '/' => :filter, 'n' => :new_query, 'v' => :new_vault, 'q' => :quit }.freeze
- LOGO =
[ ' ___ __ _ __ __ ', ' / | __________/ /_ (_) /____ _ __/ /_', ' / /| | / ___/ ___/ __ \\/ / __/ _ \\| |/_/ __/', ' / ___ |/ / / /__/ / / / / /_/ __/> </ /_ ', '/_/ |_/_/ \\___/_/ /_/_/\\__/\\___/_/|_|\\__/ ' ].freeze
Instance Method Summary collapse
-
#initialize(stdin:, stdout:, stderr:, app_name:) ⇒ TUI
constructor
A new instance of TUI.
- #prompt_query(default:, context:) ⇒ Object
-
#prompt_vault_config(active_vault:, active_vault_source:, default_vault:, default_vault_path:) ⇒ Object
rubocop:disable Metrics/AbcSize.
-
#select(paths, query:, vault:, vault_source:) ⇒ Object
rubocop:disable Metrics/BlockLength, Metrics/MethodLength.
- #show_copied(bytes) ⇒ Object
- #show_dry_run(selected_paths, bytes) ⇒ Object
- #show_error(message) ⇒ Object
- #show_info(message) ⇒ Object
-
#show_no_results(query, vault:, vault_source:, default_vault_path:, obsidian_executable:) ⇒ Object
rubocop:enable Metrics/BlockLength, Metrics/MethodLength.
- #show_no_selection ⇒ Object
Constructor Details
#initialize(stdin:, stdout:, stderr:, app_name:) ⇒ TUI
Returns a new instance of TUI.
34 35 36 37 38 39 40 41 |
# File 'lib/architext/tui.rb', line 34 def initialize(stdin:, stdout:, stderr:, app_name:) @stdin = stdin @stdout = stdout @stderr = stderr @app_name = app_name @color = Terminal.enabled?(@stdout) @intro_rendered = false end |
Instance Method Details
#prompt_query(default:, context:) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/architext/tui.rb', line 43 def prompt_query(default:, context:) draw_intro draw_startup_vault_status( context[:vault], context[:vault_source], context[:default_vault], context[:default_vault_path], context[:connection_report] ) @stdout.print render("[bold][cyan]Search query[/] [dim](default: #{default})[/] [dim]| type 'v' for vault config, 'q' to quit:[/] ") input = @stdin.gets&.strip return QueryPrompt.new(query: nil, open_vault_config: false, quit: true) if input.nil? normalized = input.strip return QueryPrompt.new(query: nil, open_vault_config: true, quit: false) if %w[v /v vault /vault].include?(normalized.downcase) return QueryPrompt.new(query: nil, open_vault_config: false, quit: true) if %w[q /q quit /quit].include?(normalized.downcase) QueryPrompt.new(query: normalized.empty? ? default : normalized, open_vault_config: false, quit: false) end |
#prompt_vault_config(active_vault:, active_vault_source:, default_vault:, default_vault_path:) ⇒ Object
rubocop:disable Metrics/AbcSize
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/architext/tui.rb', line 64 def prompt_vault_config(active_vault:, active_vault_source:, default_vault:, default_vault_path:) draw_intro @stdout.puts render('[bold][cyan]Vault Configuration[/]') @stdout.puts render("[dim]active:[/] #{format_vault_label(active_vault, active_vault_source)}") @stdout.puts render("[dim]saved default:[/] #{format_saved_default(default_vault)}") @stdout.puts render("[dim]default config path:[/] #{default_vault_path}") @stdout.puts render('[dim]vault path resolution is handled by Obsidian CLI via vault=<name_or_id>.[/]') @stdout.puts @stdout.puts render('[dim]Commands:[/]') @stdout.puts render(' [cyan]use <vault>[/] [dim]set active vault for this run[/]') @stdout.puts render(' [cyan]save <vault>[/] [dim]save persistent default vault[/]') @stdout.puts render(' [cyan]clear[/] [dim]clear persistent default vault[/]') @stdout.puts render(' [cyan]none[/] [dim]clear active vault (use Obsidian CLI default)[/]') @stdout.puts render(' [cyan]back[/] [dim]return to search prompt[/]') @stdout.puts @stdout.print render('[bold][cyan]vault-config[/]> ') input = @stdin.gets&.strip return VaultConfigAction.new(session_vault: nil, set_default_vault: nil, clear_default: false, back: true) if input.nil? command = input.strip return VaultConfigAction.new(session_vault: nil, set_default_vault: nil, clear_default: false, back: true) if command.empty? return VaultConfigAction.new(session_vault: nil, set_default_vault: nil, clear_default: false, back: true) if command.casecmp('back').zero? return VaultConfigAction.new(session_vault: '', set_default_vault: nil, clear_default: false, back: false) if command.casecmp('none').zero? return VaultConfigAction.new(session_vault: nil, set_default_vault: nil, clear_default: true, back: false) if command.casecmp('clear').zero? if (match = command.match(/\Asave\s+(.+)\z/i)) return VaultConfigAction.new(session_vault: nil, set_default_vault: match[1].strip, clear_default: false, back: false) end if (match = command.match(/\Ause\s+(.+)\z/i)) return VaultConfigAction.new(session_vault: match[1].strip, set_default_vault: nil, clear_default: false, back: false) end VaultConfigAction.new(session_vault: command, set_default_vault: nil, clear_default: false, back: false) end |
#select(paths, query:, vault:, vault_source:) ⇒ Object
rubocop:disable Metrics/BlockLength, Metrics/MethodLength
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/architext/tui.rb', line 102 def select(paths, query:, vault:, vault_source:) state = { query: query, vault: vault, vault_source: vault_source, filter: '', cursor: 0, offset: 0, selected: {} } with_screen do loop do visible = filtered_paths(paths, state[:filter]) clamp_cursor!(state, visible.length) draw_selector(paths:, visible:, state:) case read_key when :up state[:cursor] -= 1 when :down state[:cursor] += 1 when :space toggle_current(visible, state) when :all toggle_all(visible, state) when :filter state[:filter] = prompt_inline('Filter visible results', state[:filter]) when :new_query return Selection.new( paths: [], new_query: prompt_inline('New Obsidian search', state[:query]), new_vault: nil, reprompt_query: false ) when :new_vault return Selection.new( paths: [], new_query: nil, new_vault: prompt_inline('Vault name or id (blank clears)', state[:vault].to_s), reprompt_query: false ) when :enter selected = selected_paths(paths, state) return Selection.new(paths: selected, new_query: nil, new_vault: nil, reprompt_query: false) when :quit return Selection.new(paths: [], new_query: nil, new_vault: nil, reprompt_query: true) when :ctrl_c return Selection.new(paths: [], new_query: nil, new_vault: nil, reprompt_query: false) end clamp_cursor!(state, visible.length) keep_cursor_visible!(state, visible.length) end end end |
#show_copied(bytes) ⇒ Object
172 173 174 |
# File 'lib/architext/tui.rb', line 172 def show_copied(bytes) @stdout.puts render("[green]Copied[/] [bold]#{bytes} bytes[/] [dim]to clipboard.[/]") end |
#show_dry_run(selected_paths, bytes) ⇒ Object
184 185 186 187 188 189 190 191 |
# File 'lib/architext/tui.rb', line 184 def show_dry_run(selected_paths, bytes) draw_intro @stdout.puts render("[bold][green]Dry run[/] [dim]#{selected_paths.length} selected file(s)[/]") @stdout.puts selected_paths.each { |path| @stdout.puts render(" [cyan]•[/] #{path}") } @stdout.puts @stdout.puts render("[dim]Estimated context size:[/] [bold]#{bytes} bytes[/]") end |
#show_error(message) ⇒ Object
176 177 178 |
# File 'lib/architext/tui.rb', line 176 def show_error() @stderr.puts render("[red]#{}[/]") end |
#show_info(message) ⇒ Object
180 181 182 |
# File 'lib/architext/tui.rb', line 180 def show_info() @stdout.puts render("[green]#{}[/]") end |
#show_no_results(query, vault:, vault_source:, default_vault_path:, obsidian_executable:) ⇒ Object
rubocop:enable Metrics/BlockLength, Metrics/MethodLength
160 161 162 163 164 165 166 |
# File 'lib/architext/tui.rb', line 160 def show_no_results(query, vault:, vault_source:, default_vault_path:, obsidian_executable:) vault_label = format_vault_label(vault, vault_source) @stderr.puts render("[red]No Obsidian notes matched[/] [amber]#{query.inspect}[/] #{vault_label}") @stderr.puts render("[dim]default vault config:[/] #{default_vault_path}") @stderr.puts render("[dim]obsidian cli:[/] #{obsidian_executable}") @stderr.puts render('[amber]Tip:[/] at search prompt type [bold]v[/] for vault config, or pass [bold]--vault[/].') end |
#show_no_selection ⇒ Object
168 169 170 |
# File 'lib/architext/tui.rb', line 168 def show_no_selection @stderr.puts render('[amber]No files selected.[/]') end |