Class: Legion::TTY::App
- Inherits:
-
Object
- Object
- Legion::TTY::App
- Extended by:
- Logging::Helper
- Includes:
- Logging::Helper
- Defined in:
- lib/legion/tty/app.rb
Overview
rubocop:disable Metrics/ClassLength
Constant Summary collapse
- CONFIG_DIR =
File.('~/.legionio/settings')
- KEY_MAP =
Key normalization: raw escape sequences and control chars to symbols
{ "\e[A" => :up, "\e[B" => :down, "\e[C" => :right, "\e[D" => :left, "\r" => :enter, "\n" => :enter, "\e" => :escape, "\e[5~" => :page_up, "\e[6~" => :page_down, "\e[H" => :home, "\eOH" => :home, "\e[F" => :end, "\eOF" => :end, "\e[1~" => :home, "\e[4~" => :end, "\x7f" => :backspace, "\b" => :backspace, "\t" => :tab, "\x03" => :ctrl_c, "\x04" => :ctrl_d, "\x01" => :ctrl_a, "\x05" => :ctrl_e, "\x0B" => :ctrl_k, "\x0C" => :ctrl_l, "\x13" => :ctrl_s, "\x15" => :ctrl_u }.freeze
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#credentials ⇒ Object
readonly
Returns the value of attribute credentials.
-
#hotkeys ⇒ Object
readonly
Returns the value of attribute hotkeys.
-
#input_bar ⇒ Object
readonly
Returns the value of attribute input_bar.
-
#llm_chat ⇒ Object
readonly
Returns the value of attribute llm_chat.
-
#screen_manager ⇒ Object
readonly
Returns the value of attribute screen_manager.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(config_dir: CONFIG_DIR, skip_rain: false) ⇒ App
constructor
A new instance of App.
-
#render_frame ⇒ Object
Public: called by screens (e.g., Chat during LLM streaming) to force a re-render rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity.
- #shutdown ⇒ Object
- #start ⇒ Object
- #toggle_dashboard ⇒ Object
-
#with_cooked_mode ⇒ Object
Temporarily exit raw mode for blocking prompts (TTY::Prompt, etc.).
Constructor Details
#initialize(config_dir: CONFIG_DIR, skip_rain: false) ⇒ App
Returns a new instance of App.
59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/legion/tty/app.rb', line 59 def initialize(config_dir: CONFIG_DIR, skip_rain: false) @config_dir = config_dir @skip_rain = skip_rain @config = load_config @credentials = load_credentials @screen_manager = ScreenManager.new @hotkeys = Hotkeys.new @llm_chat = nil @input_bar = nil @running = false @prev_frame = [] @raw_mode = false end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
38 39 40 |
# File 'lib/legion/tty/app.rb', line 38 def config @config end |
#credentials ⇒ Object (readonly)
Returns the value of attribute credentials.
38 39 40 |
# File 'lib/legion/tty/app.rb', line 38 def credentials @credentials end |
#hotkeys ⇒ Object (readonly)
Returns the value of attribute hotkeys.
38 39 40 |
# File 'lib/legion/tty/app.rb', line 38 def hotkeys @hotkeys end |
#input_bar ⇒ Object (readonly)
Returns the value of attribute input_bar.
38 39 40 |
# File 'lib/legion/tty/app.rb', line 38 def @input_bar end |
#llm_chat ⇒ Object (readonly)
Returns the value of attribute llm_chat.
38 39 40 |
# File 'lib/legion/tty/app.rb', line 38 def llm_chat @llm_chat end |
#screen_manager ⇒ Object (readonly)
Returns the value of attribute screen_manager.
38 39 40 |
# File 'lib/legion/tty/app.rb', line 38 def screen_manager @screen_manager end |
Class Method Details
.first_run?(config_dir: CONFIG_DIR) ⇒ Boolean
55 56 57 |
# File 'lib/legion/tty/app.rb', line 55 def self.first_run?(config_dir: CONFIG_DIR) !File.exist?(File.join(config_dir, 'identity.json')) end |
.parse_argv(argv) ⇒ Object
49 50 51 52 53 |
# File 'lib/legion/tty/app.rb', line 49 def self.parse_argv(argv) opts = {} opts[:skip_rain] = true if argv.include?('--skip-rain') opts end |
.run(argv = []) ⇒ Object
40 41 42 43 44 45 46 47 |
# File 'lib/legion/tty/app.rb', line 40 def self.run(argv = []) opts = parse_argv(argv) app = new(**opts) app.start rescue Interrupt => e log.debug { "app interrupted: #{e.}" } app&.shutdown end |
Instance Method Details
#render_frame ⇒ Object
Public: called by screens (e.g., Chat during LLM streaming) to force a re-render rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/legion/tty/app.rb', line 82 def render_frame width = terminal_width height = terminal_height active = @screen_manager.active_screen return unless active has_input = active.respond_to?(:needs_input_bar?) && active. screen_height = has_input ? height - 1 : height lines = active.render(width, screen_height) lines << @input_bar.render_line(width: width) if has_input && @input_bar lines = lines[0, height] if lines.size > height lines += Array.new(height - lines.size, '') if lines.size < height lines = (lines, width, height) if @screen_manager. write_differential(lines, width) if has_input && @input_bar col = [@input_bar.cursor_column, width - 1].min $stdout.print cursor.move_to(col, height - 1) end $stdout.flush rescue StandardError => e log.warn { "render_frame failed: #{e.}" } end |
#shutdown ⇒ Object
133 134 135 136 |
# File 'lib/legion/tty/app.rb', line 133 def shutdown @running = false @screen_manager.teardown_all end |
#start ⇒ Object
73 74 75 76 77 78 |
# File 'lib/legion/tty/app.rb', line 73 def start setup_hotkeys run_onboarding if self.class.first_run?(config_dir: @config_dir) setup_for_chat run_loop end |
#toggle_dashboard ⇒ Object
122 123 124 125 126 127 128 129 130 131 |
# File 'lib/legion/tty/app.rb', line 122 def toggle_dashboard active = @screen_manager.active_screen if active.is_a?(Screens::Dashboard) @screen_manager.pop else require_relative 'screens/dashboard' dashboard = Screens::Dashboard.new(self) @screen_manager.push(dashboard) end end |
#with_cooked_mode ⇒ Object
Temporarily exit raw mode for blocking prompts (TTY::Prompt, etc.)
113 114 115 116 117 118 119 120 |
# File 'lib/legion/tty/app.rb', line 113 def with_cooked_mode(&) return yield unless @raw_mode $stdout.print cursor.show $stdin.cooked(&) $stdout.print cursor.hide @prev_frame = [] end |