Class: TuiTui::Modal::CommandPalette

Inherits:
Modal
  • Object
show all
Defined in:
lib/tui_tui/modal/command_palette.rb

Overview

Fuzzy-filtered command palette modal (think Ctrl-P): type to narrow a list of commands, arrows or Ctrl-N/Ctrl-P to move, Enter to pick, Esc to cancel.

Items are arbitrary objects; pass a block to derive each one's display label (defaults to #to_s). Resolves to the chosen item on Enter and :cancel on escape; stays open (nil) while the query has no matches.

host.open(CommandPalette.new(commands) { |c| c.title }) { |cmd| cmd.run; self }

Constant Summary collapse

MAX_ROWS =
10
MIN_INNER =
28
WHEEL =
3

Instance Method Summary collapse

Constructor Details

#initialize(items, prompt: "> ", placeholder: "Type to search…", theme: Theme::DEFAULT, &label) ⇒ CommandPalette

Returns a new instance of CommandPalette.



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/tui_tui/modal/command_palette.rb', line 28

def initialize(items, prompt: "> ", placeholder: "Type to search…", theme: Theme::DEFAULT, &label)
  @items = items.to_a
  @label = label || :to_s.to_proc
  @prompt = DisplayText.new(prompt)
  @placeholder = DisplayText.new(placeholder)
  @theme = theme
  # The query buffer. Editing keys stay append-only here: the cursor is
  # pinned at the end (we never feed it left/right/Home/End), because those
  # keys drive the list below, not the query.
  @query = TextInput.new
  @list = Widget::ScrollList.new(0)
  refilter
end

Instance Method Details

#draw(canvas, size) ⇒ Object



79
80
81
82
83
84
85
86
87
# File 'lib/tui_tui/modal/command_palette.rb', line 79

def draw(canvas, size)
  rows = visible_rows(size)
  inner = [MIN_INNER, *@filtered.map { |_item, label, _pos| label.width }].max
  rect, col = panel(canvas, inner: inner, body_rows: rows + 2)

  draw_query(canvas, rect.row + 1, col, inner)
  draw_items(canvas, rect.row + 3, col, inner, rows)
  canvas
end

#handle(key) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/tui_tui/modal/command_palette.rb', line 47

def handle(key)
  case key
  when "\r"
    selection
  when :escape, KeyCode::CTRL_C
    :cancel
  when :up, KeyCode::CTRL_P
    move(-1)
  when :down, KeyCode::CTRL_N
    move(1)
  when :home
    move_to(0)
  when :end
    move_to(@list.last)
  when KeyCode::BACKSPACE, :backspace
    edit { @query.delete_back }
  when String
    edit { @query.type(key) }
  end
end

#handle_mouse(event) ⇒ Object

Wheel scrolls the highlight; a click on a row picks it (returns the item), otherwise nil to stay open.



70
71
72
73
74
75
76
77
# File 'lib/tui_tui/modal/command_palette.rb', line 70

def handle_mouse(event)
  case event.action
  when :wheel
    move(event.button == :wheel_up ? -WHEEL : WHEEL)
  when :press
    click(event)
  end
end

#queryObject



42
# File 'lib/tui_tui/modal/command_palette.rb', line 42

def query = @query.value

#selectionObject

The original item under the cursor, or nil when nothing matches.



45
# File 'lib/tui_tui/modal/command_palette.rb', line 45

def selection = @filtered[@list.cursor]&.first