Class: BruteCLI::REPL::QuestionScreen

Inherits:
Object
  • Object
show all
Includes:
Bubbletea::Model
Defined in:
lib/brute_cli/repl/question_screen.rb

Overview

Full-screen alternate-buffer question form built directly on Bubbletea.

Opens a new terminal screen (like fzf/vim) via alt_screen: true, renders select/multi-select forms with Lipgloss styling, handles keyboard input through Bubbletea’s raw-mode event loop (termios), and restores the original screen when done.

Constant Summary collapse

ACCENT =

── Styles ──

"#FFCC00"
DIM =
"#666666"
SELECTED =
"#00FF88"
HELP_COLOR =
"#555555"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(questions) ⇒ QuestionScreen

Returns a new instance of QuestionScreen.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/brute_cli/repl/question_screen.rb', line 35

def initialize(questions)
  @questions = questions.map { |q| normalize(q) }
  @question_idx = 0
  @cursor = 0
  @selected = Set.new         # for multi-select
  @answers = []               # collected answers per question
  @state = :selecting         # :selecting | :other_input | :done | :aborted
  @text_input = Bubbles::TextInput.new
  @text_input.prompt = "  > "
  @text_input.placeholder = "Type your response..."
  @width = 80
  @height = 24

  build_styles
end

Class Method Details

.ask(questions) ⇒ Object

── Public API ──



30
31
32
33
# File 'lib/brute_cli/repl/question_screen.rb', line 30

def self.ask(questions)
  screen = new(questions)
  screen.run
end

Instance Method Details

#initObject

── Bubbletea::Model interface ──



69
70
71
# File 'lib/brute_cli/repl/question_screen.rb', line 69

def init
  [self, nil]
end

#runObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/brute_cli/repl/question_screen.rb', line 51

def run
  # Release the terminal from reline before bubbletea takes over.
  # Reline may hold termios flags (cooked mode, echo, signal handling)
  # that prevent bubbletea's Go FFI from entering raw mode and reading
  # escape sequences (arrow keys). deprep_terminal restores the
  # terminal to its pre-reline state so bubbletea gets a clean slate.
  reline_active = defined?(Reline) && Reline.respond_to?(:deprep_terminal)
  Reline.deprep_terminal if reline_active

  Bubbletea.run(self, alt_screen: true)
  @state == :aborted ? @questions.map { [] } : @answers
ensure
  # Re-prep reline so the REPL prompt works when we return.
  Reline.prep_terminal if reline_active
end

#update(message) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/brute_cli/repl/question_screen.rb', line 73

def update(message)
  case message
  when Bubbletea::WindowSizeMessage
    @width = message.width
    @height = message.height
    [self, nil]
  when Bubbletea::KeyMessage
    handle_key(message)
  else
    [self, nil]
  end
end

#viewObject



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/brute_cli/repl/question_screen.rb', line 86

def view
  return "" if @state == :done || @state == :aborted

  case @state
  when :selecting
    view_selecting
  when :other_input
    view_other_input
  else
    ""
  end
end