Class: Clacky::UI2::Components::CommandSuggestions

Inherits:
Object
  • Object
show all
Defined in:
lib/clacky/ui2/components/command_suggestions.rb

Overview

CommandSuggestions displays a dropdown menu of available commands Supports keyboard navigation and filtering

Constant Summary collapse

SYSTEM_COMMANDS =

System commands available by default

[
  { command: "/clear", description: "Clear chat history and restart session" },
  { command: "/config", description: "Open configuration (models, API keys, settings)" },
  { command: "/undo", description: "Undo the last task and restore previous state" },
  { command: "/help", description: "Show help information" },
  { command: "/exit", description: "Exit the chat session" },
  { command: "/quit", description: "Quit the application" }
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCommandSuggestions

Returns a new instance of CommandSuggestions.



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 24

def initialize
  @pastel = Pastel.new
  @commands = []
  @filtered_commands = []
  @selected_index = 0
  @visible = false
  @filter_text = ""
  @skill_commands = []
  
  # Initialize with system commands
  update_commands
end

Instance Attribute Details

#selected_indexObject (readonly)

Returns the value of attribute selected_index.



12
13
14
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 12

def selected_index
  @selected_index
end

#visibleObject (readonly)

Returns the value of attribute visible.



12
13
14
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 12

def visible
  @visible
end

Instance Method Details

#clear_from_screen(row:, col:) ⇒ Object

Clear the rendered dropdown from screen

Parameters:

  • row (Integer)

    Starting row position

  • col (Integer)

    Starting column position



178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 178

def clear_from_screen(row:, col:)
  return unless @visible

  height = required_height
  output = []
  
  height.times do |i|
    output << position_cursor(row + i, col) + clear_line
  end
  
  print output.join
  flush
end

#has_suggestions?Boolean

Check if there are any suggestions to show

Returns:

  • (Boolean)


123
124
125
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 123

def has_suggestions?
  @visible && !@filtered_commands.empty?
end

#hideObject

Hide the suggestions dropdown



73
74
75
76
77
78
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 73

def hide
  @visible = false
  @filter_text = ""
  @filtered_commands = []
  @selected_index = 0
end

#load_skill_commands(skill_loader, agent_profile = nil) ⇒ Object

Load skill commands from skill loader, filtered by agent profile whitelist

Parameters:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 45

def load_skill_commands(skill_loader, agent_profile = nil)
  return unless skill_loader

  skills = skill_loader.user_invocable_skills
  skills = skills.select { |s| s.allowed_for_agent?(agent_profile.name) } if agent_profile

  @skill_commands = skills.map do |skill|
    {
      command: skill.slash_command,
      description: skill.description || "No description available",
      type: :skill,
      argument_hint: skill.argument_hint
    }
  end

  update_commands
end

#render(row:, col:, width: 60) ⇒ String

Render the suggestions dropdown

Parameters:

  • row (Integer)

    Starting row position

  • col (Integer)

    Starting column position

  • width (Integer) (defaults to: 60)

    Maximum width for the dropdown

Returns:

  • (String)

    Rendered output



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 142

def render(row:, col:, width: 60)
  return "" unless @visible
  return "" if @filtered_commands.empty?

  output = []
  max_items = 5  # Maximum visible items

  # Sliding window: keep selected item visible
  start_idx = [@selected_index - max_items + 1, 0].max
  start_idx = [start_idx, [@filtered_commands.size - max_items, 0].max].min
  visible_commands = @filtered_commands[start_idx, max_items] || []

  # Header
  header = @pastel.dim("┌─ Commands ") + @pastel.dim("" * (width - 13)) + @pastel.dim("")
  output << position_cursor(row, col) + header

  # Items
  visible_commands.each_with_index do |cmd, idx|
    is_selected = (start_idx + idx == @selected_index)
    line = render_command_item(cmd, is_selected, width)
    output << position_cursor(row + 1 + idx, col) + line
  end

  # Footer with navigation hint
  footer_row = row + 1 + visible_commands.size
  total = @filtered_commands.size
  hint = total > max_items ? " (#{total - max_items} more...)" : ""
  footer = @pastel.dim("") + @pastel.dim("" * (width - 2)) + @pastel.dim("")
  output << position_cursor(footer_row, col) + footer

  output.join
end

#required_heightInteger

Calculate required height for rendering

Returns:

  • (Integer)

    Number of lines needed



129
130
131
132
133
134
135
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 129

def required_height
  return 0 unless @visible
  return 0 if @filtered_commands.empty?

  # Header + commands + footer
  1 + [@filtered_commands.size, 5].min + 1  # Max 5 visible items
end

#select_nextObject

Move selection down



95
96
97
98
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 95

def select_next
  return if @filtered_commands.empty?
  @selected_index = (@selected_index + 1) % @filtered_commands.size
end

#select_previousObject

Move selection up



89
90
91
92
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 89

def select_previous
  return if @filtered_commands.empty?
  @selected_index = (@selected_index - 1) % @filtered_commands.size
end

#selected_argument_hintString?

Get the argument hint for the currently selected command

Returns:

  • (String, nil)

    Argument hint string or nil if none



116
117
118
119
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 116

def selected_argument_hint
  cmd = selected_command
  cmd ? cmd[:argument_hint] : nil
end

#selected_commandHash?

Get the currently selected command

Returns:

  • (Hash, nil)

    Selected command hash or nil if none selected



102
103
104
105
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 102

def selected_command
  return nil if @filtered_commands.empty?
  @filtered_commands[@selected_index]
end

#selected_command_textString?

Get the currently selected command text

Returns:

  • (String, nil)

    Selected command text or nil if none selected



109
110
111
112
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 109

def selected_command_text
  cmd = selected_command
  cmd ? cmd[:command] : nil
end

#show(filter_text = "") ⇒ Object

Show the suggestions dropdown

Parameters:

  • filter_text (String) (defaults to: "")

    Initial filter text (everything after the /)



65
66
67
68
69
70
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 65

def show(filter_text = "")
  @filter_text = filter_text
  @visible = true
  update_filtered_commands
  @selected_index = 0
end

#themeObject

Get current theme from ThemeManager



38
39
40
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 38

def theme
  UI2::ThemeManager.current_theme
end

#update_filter(text) ⇒ Object

Update filter text and refresh filtered commands

Parameters:

  • text (String)

    Filter text (everything after the /)



82
83
84
85
86
# File 'lib/clacky/ui2/components/command_suggestions.rb', line 82

def update_filter(text)
  @filter_text = text
  update_filtered_commands
  @selected_index = 0  # Reset selection when filter changes
end