Class: TuiTui::CommandPalette

Inherits:
Modal
  • Object
show all
Defined in:
lib/tui_tui/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

Constants inherited from Modal

Modal::PAD

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of CommandPalette.



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

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
  @graphemes = []
  @list = ScrollList.new(0)
  refilter
end

Instance Method Details

#draw(canvas, size) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/tui_tui/command_palette.rb', line 77

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



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

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 { @graphemes.pop }
  when String
    edit { @graphemes.concat(key.grapheme_clusters) if TextSanitizer.printable?(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.



68
69
70
71
72
73
74
75
# File 'lib/tui_tui/command_palette.rb', line 68

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

#queryObject



40
# File 'lib/tui_tui/command_palette.rb', line 40

def query = @graphemes.join

#selectionObject

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



43
# File 'lib/tui_tui/command_palette.rb', line 43

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