Class: RubyAiGemContext::Interactive

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_ai_gem_context/interactive.rb

Overview

Interactive terminal UI for rake tasks

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_root = Dir.pwd) ⇒ Interactive

Returns a new instance of Interactive.



11
12
13
14
# File 'lib/ruby_ai_gem_context/interactive.rb', line 11

def initialize(project_root = Dir.pwd)
  @prompt = TTY::Prompt.new
  @project_root = project_root
end

Instance Attribute Details

#project_root ⇒ Object (readonly)

Returns the value of attribute project_root.



9
10
11
# File 'lib/ruby_ai_gem_context/interactive.rb', line 9

def project_root
  @project_root
end

#prompt ⇒ Object (readonly)

Returns the value of attribute prompt.



9
10
11
# File 'lib/ruby_ai_gem_context/interactive.rb', line 9

def prompt
  @prompt
end

Instance Method Details

#ask_folder_list ⇒ Object

Ask for specific folder list



83
84
85
86
87
88
89
90
# File 'lib/ruby_ai_gem_context/interactive.rb', line 83

def ask_folder_list
  input = prompt.ask(
    "Enter folder paths (comma-separated, relative to project root):",
    default: "lib, app"
  )

  input.split(",").map(&:strip).reject(&:empty?)
end

#ask_gem_name ⇒ Object

Ask for gem name



119
120
121
122
123
124
# File 'lib/ruby_ai_gem_context/interactive.rb', line 119

def ask_gem_name
  prompt.ask("Enter the gem name:") do |q|
    q.required true
    q.validate(/\A[\w-]+\z/, "Invalid gem name format")
  end
end

#confirm_source_folders(folders, summary) ⇒ Object

Confirm source folders and show what will be scanned



93
94
95
96
97
98
99
100
# File 'lib/ruby_ai_gem_context/interactive.rb', line 93

def confirm_source_folders(folders, summary)
  puts
  puts "Will scan #{summary[:total_files]} files (#{format_size(summary[:total_size])})"
  puts "File types: #{summary[:by_extension].map { |ext, count| "#{ext || 'no ext'}: #{count}" }.join(', ')}"
  puts

  prompt.yes?("Proceed with generation?")
end

#error(message) ⇒ Object



150
151
152
# File 'lib/ruby_ai_gem_context/interactive.rb', line 150

def error(message)
  puts prompt.decorate("✗ #{message}", :red)
end

#handle_collision(platform_class) ⇒ Object

Handle collision when file exists



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ruby_ai_gem_context/interactive.rb', line 33

def handle_collision(platform_class)
  prompt.select(
    "#{platform_class.filename} already exists. What would you like to do?",
    [
      { name: "Skip (keep existing)", value: :skip },
      { name: "Backup & overwrite (saves #{platform_class.filename}.backup)", value: :backup },
      { name: "Show diff (compare before deciding)", value: :diff },
      { name: "Overwrite (replace existing)", value: :overwrite }
    ]
  )
end

#header(message) ⇒ Object



158
159
160
161
162
163
164
# File 'lib/ruby_ai_gem_context/interactive.rb', line 158

def header(message)
  puts
  puts prompt.decorate("═" * 50, :blue)
  puts prompt.decorate(" #{message}", :blue, :bold)
  puts prompt.decorate("═" * 50, :blue)
  puts
end

#info(message) ⇒ Object



154
155
156
# File 'lib/ruby_ai_gem_context/interactive.rb', line 154

def info(message)
  puts prompt.decorate("ℹ #{message}", :cyan)
end

#review_reminder ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/ruby_ai_gem_context/interactive.rb', line 166

def review_reminder
  puts
  warning "IMPORTANT: Review the generated files carefully!"
  puts "  AI-generated context is a first draft. The quality of your future"
  puts "  AI interactions depends on the accuracy of these files."
  puts
  puts "  Suggested review steps:"
  puts "    1. Read through each generated file"
  puts "    2. Fix any inaccuracies or missing information"
  puts "    3. Add project-specific details the AI might have missed"
  puts "    4. Remove any incorrect assumptions"
  puts
end

#select_platforms ⇒ Object

Ask which platforms to generate boilerplate for



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/ruby_ai_gem_context/interactive.rb', line 19

def select_platforms
  choices = RubyAiGemContext::PLATFORMS.map do |key, platform_class|
    { name: "#{platform_class.name} (#{platform_class.filename})", value: key }
  end

  prompt.multi_select(
    "Which platforms do you want to generate context files for?",
    choices,
    help: "(Use space to select, enter to confirm)",
    min: 1
  )
end

#select_platforms_to_regenerate(existing_platforms) ⇒ Object

Select which existing platforms to regenerate



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ruby_ai_gem_context/interactive.rb', line 103

def select_platforms_to_regenerate(existing_platforms)
  choices = existing_platforms.map do |key|
    platform_class = RubyAiGemContext.platform(key)
    { name: "#{platform_class.name} (#{platform_class.filename})", value: key }
  end

  prompt.multi_select(
    "Which context files do you want to regenerate?",
    choices,
    help: "(Use space to select, enter to confirm)"
  )
end

#select_source_folders ⇒ Object

Ask about source folders



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ruby_ai_gem_context/interactive.rb', line 65

def select_source_folders
  choice = prompt.select(
    "Where should we read source files from?",
    [
      { name: "Project root (scan everything)", value: :root },
      { name: "Specific folders (you'll provide a list)", value: :specific }
    ]
  )

  case choice
  when :root
    nil # nil means scan from root
  when :specific
    ask_folder_list
  end
end

#show_diff(existing, new_content) ⇒ Object

Show diff between existing and new content



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/ruby_ai_gem_context/interactive.rb', line 46

def show_diff(existing, new_content)
  puts "\n--- Existing content ---"
  puts existing.lines.first(20).join
  puts "..." if existing.lines.size > 20
  puts "\n--- New content ---"
  puts new_content.lines.first(20).join
  puts "..." if new_content.lines.size > 20
  puts

  prompt.select("What would you like to do?", [
    { name: "Keep existing", value: :skip },
    { name: "Use new content", value: :overwrite },
    { name: "Backup & use new", value: :backup }
  ])
end

#success(message) ⇒ Object

Output Helpers ===



142
143
144
# File 'lib/ruby_ai_gem_context/interactive.rb', line 142

def success(message)
  puts prompt.decorate("✓ #{message}", :green)
end

#warning(message) ⇒ Object



146
147
148
# File 'lib/ruby_ai_gem_context/interactive.rb', line 146

def warning(message)
  puts prompt.decorate("⚠ #{message}", :yellow)
end

#with_spinner(message) ⇒ Object

Show spinner while doing work



129
130
131
132
133
134
135
136
137
138
# File 'lib/ruby_ai_gem_context/interactive.rb', line 129

def with_spinner(message)
  spinner = TTY::Spinner.new("[:spinner] #{message}", format: :dots)
  spinner.auto_spin
  result = yield
  spinner.success("Done!")
  result
rescue StandardError => e
  spinner.error("Failed!")
  raise e
end