aia 0.0.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +24 -2
- data/lib/aia/cli.rb +2 -32
- data/lib/aia/external/,keep +0 -0
- data/lib/aia/external/.irbrc +11 -0
- data/lib/aia/external/ag.rb +103 -0
- data/lib/aia/external/bat.rb +189 -0
- data/lib/aia/external/fzf.rb +147 -0
- data/lib/aia/external/glow.rb +37 -0
- data/lib/aia/external/mods.rb +57 -0
- data/lib/aia/external/rg.rb +1163 -0
- data/lib/aia/external/sgpt.rb +58 -0
- data/lib/aia/external/subl.rb +47 -0
- data/lib/aia/external/temp.md +37 -0
- data/lib/aia/external/tool.rb +73 -0
- data/lib/aia/external.rb +259 -0
- data/lib/aia/external_two.rb +43 -0
- data/lib/aia/main.rb +2 -2
- data/lib/aia/prompt_processing.rb +67 -13
- data/lib/aia/version.rb +1 -1
- metadata +16 -3
- data/lib/aia/external_commands.rb +0 -116
@@ -0,0 +1,58 @@
|
|
1
|
+
# lib/aia/external/sgpt.rb
|
2
|
+
|
3
|
+
class AIA::External::Sgpt < AIA::External::Tool
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
@role = :backend
|
7
|
+
@desc = "shell-gpt"
|
8
|
+
@url = "https://github.com/TheR1D/shell_gpt"
|
9
|
+
@install = "pip install shell-gpt"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
__END__
|
14
|
+
|
15
|
+
Usage: sgpt [OPTIONS] [PROMPT]
|
16
|
+
|
17
|
+
╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────╮
|
18
|
+
│ prompt [PROMPT] The prompt to generate completions for. │
|
19
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
|
20
|
+
╭─ Options ───────────────────────────────────────────────────────────────────────────────────╮
|
21
|
+
│ --model TEXT Large language model to use. │
|
22
|
+
│ [default: gpt-3.5-turbo] │
|
23
|
+
│ --temperature FLOAT RANGE [0.0<=x<=2.0] Randomness of generated │
|
24
|
+
│ output. │
|
25
|
+
│ [default: 0.1] │
|
26
|
+
│ --top-probability FLOAT RANGE [0.1<=x<=1.0] Limits highest probable │
|
27
|
+
│ tokens (words). │
|
28
|
+
│ [default: 1.0] │
|
29
|
+
│ --editor --no-editor Open $EDITOR to provide a │
|
30
|
+
│ prompt. │
|
31
|
+
│ [default: no-editor] │
|
32
|
+
│ --cache --no-cache Cache completion results. │
|
33
|
+
│ [default: cache] │
|
34
|
+
│ --help Show this message and exit. │
|
35
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
|
36
|
+
╭─ Assistance Options ────────────────────────────────────────────────────────────────────────╮
|
37
|
+
│ --shell -s Generate and execute shell commands. │
|
38
|
+
│ --describe-shell -d Describe a shell command. │
|
39
|
+
│ --code --no-code Generate only code. [default: no-code] │
|
40
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
|
41
|
+
╭─ Chat Options ──────────────────────────────────────────────────────────────────────────────╮
|
42
|
+
│ --chat TEXT Follow conversation with id, use "temp" for quick │
|
43
|
+
│ session. │
|
44
|
+
│ [default: None] │
|
45
|
+
│ --repl TEXT Start a REPL (Read–eval–print loop) session. │
|
46
|
+
│ [default: None] │
|
47
|
+
│ --show-chat TEXT Show all messages from provided chat id. │
|
48
|
+
│ [default: None] │
|
49
|
+
│ --list-chats --no-list-chats List all existing chat ids. │
|
50
|
+
│ [default: no-list-chats] │
|
51
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
|
52
|
+
╭─ Role Options ──────────────────────────────────────────────────────────────────────────────╮
|
53
|
+
│ --role TEXT System role for GPT model. [default: None] │
|
54
|
+
│ --create-role TEXT Create role. [default: None] │
|
55
|
+
│ --show-role TEXT Show role. [default: None] │
|
56
|
+
│ --list-roles --no-list-roles List roles. [default: no-list-roles] │
|
57
|
+
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
|
58
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# lib/aia/external/subl.rb
|
2
|
+
|
3
|
+
class AIA::External::Subl < AIA::External::Tool
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
@role = :editor
|
7
|
+
@desc = "Sublime Text Editor"
|
8
|
+
@url = "https://www.sublimetext.com/"
|
9
|
+
@install = "echo 'Download from website'"
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def open(file)
|
14
|
+
`#{name} #{file}`
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
__END__
|
19
|
+
|
20
|
+
$ subl --help
|
21
|
+
Sublime Text build 4166
|
22
|
+
|
23
|
+
Usage: subl [arguments] [files] Edit the given files
|
24
|
+
or: subl [arguments] [directories] Open the given directories
|
25
|
+
or: subl [arguments] -- [files] Edit files that may start with '-'
|
26
|
+
or: subl [arguments] - Edit stdin
|
27
|
+
or: subl [arguments] - >out Edit stdin and write the edit to stdout
|
28
|
+
|
29
|
+
Arguments:
|
30
|
+
--project <project>: Load the given project
|
31
|
+
--command <command>: Run the given command
|
32
|
+
-n or --new-window: Open a new window
|
33
|
+
--launch-or-new-window: Only open a new window if the application is open
|
34
|
+
-a or --add: Add folders to the current window
|
35
|
+
-w or --wait: Wait for the files to be closed before returning
|
36
|
+
-b or --background: Don't activate the application
|
37
|
+
-s or --stay: Keep the application activated after closing the file
|
38
|
+
--safe-mode: Launch using a sandboxed (clean) environment
|
39
|
+
-h or --help: Show help (this message) and exit
|
40
|
+
-v or --version: Show version and exit
|
41
|
+
|
42
|
+
--wait is implied if reading from stdin. Use --stay to not switch back
|
43
|
+
to the terminal when a file is closed (only relevant if waiting for a file).
|
44
|
+
|
45
|
+
Filenames may be given a :line or :line:column suffix
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
If you want to find out which classes have inherited from a class named `Tool`, you can leverage Ruby's `ObjectSpace` module to iterate through all the classes and select those that are descendants of `Tool`. Here's how you could write the code:
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
class Tool
|
5
|
+
# Tool class implementation
|
6
|
+
end
|
7
|
+
|
8
|
+
# Other classes that inherit from Tool
|
9
|
+
class Hammer < Tool; end
|
10
|
+
class Screwdriver < Tool; end
|
11
|
+
class Wrench < Tool; end
|
12
|
+
|
13
|
+
# Non-inheriting classes
|
14
|
+
class RandomClass; end
|
15
|
+
|
16
|
+
def find_descendants_of(klass)
|
17
|
+
ObjectSpace.each_object(Class).select { |c| c < klass }.map(&:name)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get the list of class names that inherit from Tool
|
21
|
+
descendant_classes = find_descendants_of(Tool)
|
22
|
+
|
23
|
+
# Format the list as markdown (as required)
|
24
|
+
markdown_list = descendant_classes.map { |name| "- #{name}" }.join("\n")
|
25
|
+
puts markdown_list
|
26
|
+
```
|
27
|
+
|
28
|
+
When you run this code, you will get an output similar to the following (the actual order may vary):
|
29
|
+
|
30
|
+
```
|
31
|
+
- Hammer
|
32
|
+
- Screwdriver
|
33
|
+
- Wrench
|
34
|
+
```
|
35
|
+
|
36
|
+
This list shows the class names that have inherited from the `Tool` class, and it is formatted as a markdown list without enclosing backticks as requested.
|
37
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# lib/aia/external/tool.rb
|
2
|
+
|
3
|
+
class AIA::External::Tool
|
4
|
+
@@subclasses = []
|
5
|
+
|
6
|
+
# This method is called whenever a subclass is created
|
7
|
+
def self.inherited(subclass)
|
8
|
+
@@subclasses << subclass
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
attr_reader :name, :description, :url
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@role = :role
|
16
|
+
@name = self.class.name.split('::').last.downcase
|
17
|
+
@desc = "description"
|
18
|
+
@url = "URL"
|
19
|
+
@install = "brew install #{name}"
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def self.tools
|
24
|
+
@@subclasses.map(&:name)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def installed?
|
29
|
+
path = `which #{name}`.chomp
|
30
|
+
!path.empty? && File.executable?(path)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def help = `#{name} --help`
|
35
|
+
def version = `#{name} --version`
|
36
|
+
|
37
|
+
|
38
|
+
###################################################
|
39
|
+
class << self
|
40
|
+
def verify_tools(tools)
|
41
|
+
missing_tools = tools.reject(&:installed?)
|
42
|
+
unless missing_tools.empty?
|
43
|
+
puts format_missing_tools_response(missing_tools)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def format_missing_tools_response(missing_tools)
|
49
|
+
response = <<~EOS
|
50
|
+
|
51
|
+
WARNING: AIA makes use of external CLI tools that are missing.
|
52
|
+
|
53
|
+
Please install the following tools:
|
54
|
+
|
55
|
+
EOS
|
56
|
+
|
57
|
+
missing_tools.each do |tool|
|
58
|
+
response << " #{tool.name}: install from #{tool.url}\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
response
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
Pathname.new(__dir__)
|
68
|
+
.glob('*.rb')
|
69
|
+
.reject{|f| f.basename.to_s.end_with?('tool.rb') }
|
70
|
+
.each do |tool|
|
71
|
+
require_relative tool.basename.to_s
|
72
|
+
end
|
73
|
+
|
data/lib/aia/external.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
# lib/aia/external.rb
|
2
|
+
|
3
|
+
# TODO: move stuff associated with the CLI options for
|
4
|
+
# external commands to this module.
|
5
|
+
# Is the EDITOR considered an external command? Yes.
|
6
|
+
|
7
|
+
=begin
|
8
|
+
|
9
|
+
There are at least 4 processes handled by external tools:
|
10
|
+
|
11
|
+
search .......... default PromptManager::Prompt or search_proc
|
12
|
+
review/select ... using fzf either exact or fuzzy
|
13
|
+
edit ............ ENV['EDITOR']
|
14
|
+
execute ......... mods or sgpt or ???
|
15
|
+
with different models / settings
|
16
|
+
|
17
|
+
sgpt is the executable for "shell-gpt" a python project
|
18
|
+
|
19
|
+
=end
|
20
|
+
|
21
|
+
module AIA::External
|
22
|
+
class Mods; end
|
23
|
+
class Fzf; end
|
24
|
+
class Rg; end
|
25
|
+
class Editor; end
|
26
|
+
end
|
27
|
+
|
28
|
+
module AIA::External
|
29
|
+
TOOLS = {
|
30
|
+
'fzf' => [ 'Command-line fuzzy finder written in Go',
|
31
|
+
'https://github.com/junegunn/fzf'],
|
32
|
+
|
33
|
+
'mods' => [ 'AI on the command-line',
|
34
|
+
'https://github.com/charmbracelet/mods'],
|
35
|
+
|
36
|
+
'rg' => [ 'Search tool like grep and The Silver Searcher',
|
37
|
+
'https://github.com/BurntSushi/ripgrep']
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
HELP = <<~EOS
|
42
|
+
External Tools Used
|
43
|
+
-------------------
|
44
|
+
|
45
|
+
To install the external CLI programs used by aia:
|
46
|
+
brew install #{TOOLS.keys.join(' ')}
|
47
|
+
|
48
|
+
#{TOOLS.to_a.map{|t| t.join("\n ") }.join("\n\n")}
|
49
|
+
|
50
|
+
A text editor whose executable is setup in the
|
51
|
+
system environment variable 'EDITOR' like this:
|
52
|
+
|
53
|
+
export EDITOR="#{ENV['EDITOR']}"
|
54
|
+
|
55
|
+
EOS
|
56
|
+
|
57
|
+
|
58
|
+
# Setup the AI CLI program with necessary variables
|
59
|
+
def setup_external_programs
|
60
|
+
verify_external_tools
|
61
|
+
|
62
|
+
ai_default_opts = "-m #{MODS_MODEL} --no-limit "
|
63
|
+
ai_default_opts += "-f " if markdown?
|
64
|
+
@ai_options = ai_default_opts.dup
|
65
|
+
|
66
|
+
|
67
|
+
@ai_options += @extra_options.join(' ')
|
68
|
+
|
69
|
+
@ai_command = "#{AI_CLI_PROGRAM} #{@ai_options} "
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Check if the external tools are present on the system
|
74
|
+
def verify_external_tools
|
75
|
+
missing_tools = []
|
76
|
+
|
77
|
+
TOOLS.each do |tool, url|
|
78
|
+
path = `which #{tool}`.chomp
|
79
|
+
if path.empty? || !File.executable?(path)
|
80
|
+
missing_tools << { name: tool, url: url }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
if missing_tools.any?
|
85
|
+
puts format_missing_tools_response(missing_tools)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def format_missing_tools_response(missing_tools)
|
91
|
+
response = <<~EOS
|
92
|
+
|
93
|
+
WARNING: #{MY_NAME} makes use of a few external CLI tools.
|
94
|
+
#{MY_NAME} may not respond as designed without these.
|
95
|
+
|
96
|
+
The following tools are missing on your system:
|
97
|
+
|
98
|
+
EOS
|
99
|
+
|
100
|
+
missing_tools.each do |tool|
|
101
|
+
response << " #{tool[:name]}: install from #{tool[:url]}\n"
|
102
|
+
end
|
103
|
+
|
104
|
+
response
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
# Build the command to interact with the AI CLI program
|
109
|
+
def build_command
|
110
|
+
command = @ai_command + %Q["#{@prompt.to_s}"]
|
111
|
+
|
112
|
+
@arguments.each do |input_file|
|
113
|
+
file_path = Pathname.new(input_file)
|
114
|
+
abort("File does not exist: #{input_file}") unless file_path.exist?
|
115
|
+
command += " < #{input_file}"
|
116
|
+
end
|
117
|
+
|
118
|
+
command
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# Execute the command and log the results
|
123
|
+
def send_prompt_to_external_command
|
124
|
+
command = build_command
|
125
|
+
|
126
|
+
puts command if verbose?
|
127
|
+
@result = `#{command}`
|
128
|
+
|
129
|
+
if output.nil?
|
130
|
+
puts @result
|
131
|
+
else
|
132
|
+
output.write @result
|
133
|
+
end
|
134
|
+
|
135
|
+
@result
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
__END__
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
MODS_MODEL = ENV['MODS_MODEL'] || 'gpt-4-1106-preview'
|
145
|
+
|
146
|
+
AI_CLI_PROGRAM = "mods"
|
147
|
+
ai_default_opts = "-m #{MODS_MODEL} --no-limit -f"
|
148
|
+
ai_options = ai_default_opts.dup
|
149
|
+
|
150
|
+
extra_inx = ARGV.index('--')
|
151
|
+
|
152
|
+
if extra_inx
|
153
|
+
ai_options += " " + ARGV[extra_inx+1..].join(' ')
|
154
|
+
ARGV.pop(ARGV.size - extra_inx)
|
155
|
+
end
|
156
|
+
|
157
|
+
AI_COMMAND = "#{AI_CLI_PROGRAM} #{ai_options} "
|
158
|
+
EDITOR = ENV['EDITOR']
|
159
|
+
PROMPT_DIR = HOME + ".prompts"
|
160
|
+
PROMPT_LOG = PROMPT_DIR + "_prompts.log"
|
161
|
+
PROMPT_EXTNAME = ".txt"
|
162
|
+
DEFAULTS_EXTNAME = ".json"
|
163
|
+
# SEARCH_COMMAND = "ag -l"
|
164
|
+
KEYWORD_REGEX = /(\[[A-Z _|]+\])/
|
165
|
+
|
166
|
+
AVAILABLE_PROMPTS = PROMPT_DIR
|
167
|
+
.children
|
168
|
+
.select{|c| PROMPT_EXTNAME == c.extname}
|
169
|
+
.map{|c| c.basename.to_s.split('.')[0]}
|
170
|
+
|
171
|
+
AVAILABLE_PROMPTS_HELP = AVAILABLE_PROMPTS
|
172
|
+
.map{|c| " * " + c}
|
173
|
+
.join("\n")
|
174
|
+
|
175
|
+
|
176
|
+
AI_CLI_PROGRAM_HELP = `#{AI_CLI_PROGRAM} --help`
|
177
|
+
|
178
|
+
HELP = <<EOHELP
|
179
|
+
AI CLI Program
|
180
|
+
==============
|
181
|
+
|
182
|
+
The AI cli program being used is: #{AI_CLI_PROGRAM}
|
183
|
+
|
184
|
+
The defaul options to #{AI_CLI_PROGRAM} are:
|
185
|
+
"#{ai_default_opts}"
|
186
|
+
|
187
|
+
You can pass additional CLI options to #{AI_CLI_PROGRAM} like this:
|
188
|
+
"#{my_name} my options -- options for #{AI_CLI_PROGRAM}"
|
189
|
+
|
190
|
+
#{AI_CLI_PROGRAM_HELP}
|
191
|
+
|
192
|
+
EOHELP
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
AG_COMMAND = "ag --file-search-regex '\.txt$' e" # searching for the letter "e"
|
197
|
+
CD_COMMAND = "cd #{PROMPT_DIR}"
|
198
|
+
FIND_COMMAND = "find . -name '*.txt'"
|
199
|
+
|
200
|
+
FZF_OPTIONS = [
|
201
|
+
"--tabstop=2", # 2 soaces for a tab
|
202
|
+
"--header='Prompt contents below'",
|
203
|
+
"--header-first",
|
204
|
+
"--prompt='Search term: '",
|
205
|
+
'--delimiter :',
|
206
|
+
"--preview 'ww {1}'", # ww comes from the word_wrap gem
|
207
|
+
"--preview-window=down:50%:wrap"
|
208
|
+
].join(' ')
|
209
|
+
|
210
|
+
FZF_OPTIONS += " --exact" unless fuzzy?
|
211
|
+
|
212
|
+
FZF_COMMAND = "#{CD_COMMAND} ; #{FIND_COMMAND} | fzf #{FZF_OPTIONS}"
|
213
|
+
AG_FZF_COMMAND = "#{CD_COMMAND} ; #{AG_COMMAND} | fzf #{FZF_OPTIONS}"
|
214
|
+
|
215
|
+
# use `ag` ti build a list of text lines from each prompt
|
216
|
+
# use `fzf` to search through that list to select a prompt file
|
217
|
+
|
218
|
+
def ag_fzf = `#{AG_FZF_COMMAND}`.split(':')&.first&.strip&.gsub('.txt','')
|
219
|
+
|
220
|
+
|
221
|
+
if configatron.prompt.empty?
|
222
|
+
unless first_argument_is_a_prompt?
|
223
|
+
configatron.prompt = ag_fzf
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
###############################################
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
#!/usr/bin/env bash
|
232
|
+
# ~/scripts/ripfzfsubl
|
233
|
+
#
|
234
|
+
# Uses Sublime Text (subl) as the text editor
|
235
|
+
#
|
236
|
+
# brew install bat ripgrep fzf
|
237
|
+
#
|
238
|
+
# bat Clone of cat(1) with syntax highlighting and Git integration
|
239
|
+
# |__ https://github.com/sharkdp/bat
|
240
|
+
#
|
241
|
+
# ripgrep Search tool like grep and The Silver Searcher
|
242
|
+
# |__ https://github.com/BurntSushi/ripgrep
|
243
|
+
#
|
244
|
+
# fzf Command-line fuzzy finder written in Go
|
245
|
+
# |__ https://github.com/junegunn/fzf
|
246
|
+
#
|
247
|
+
#
|
248
|
+
# 1. Search for text in files using Ripgrep
|
249
|
+
# 2. Interactively narrow down the list using fzf
|
250
|
+
# 3. Open the file in Sublime Text Editor
|
251
|
+
|
252
|
+
rg --color=always --line-number --no-heading --smart-case "${*:-}" |
|
253
|
+
fzf --ansi \
|
254
|
+
--color "hl:-1:underline,hl+:-1:underline:reverse" \
|
255
|
+
--delimiter : \
|
256
|
+
--preview 'bat --color=always {1} --highlight-line {2}' \
|
257
|
+
--preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
|
258
|
+
--bind 'enter:become(subl {1}:{2})'
|
259
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# lib/aia/external_two.rb
|
2
|
+
#
|
3
|
+
# Maybe something like this ...
|
4
|
+
#
|
5
|
+
# or a class structure based upon function where the external
|
6
|
+
# tool and its default options can be injected.
|
7
|
+
#
|
8
|
+
module AIA::External
|
9
|
+
EDITOR = ENV['EDITOR']
|
10
|
+
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
# Usage example:
|
15
|
+
|
16
|
+
# Verify and install tools if needed
|
17
|
+
mods = AIA::External::Mods.new
|
18
|
+
fzf = AIA::External::Fzf.new
|
19
|
+
rg = AIA::External::Rg.new
|
20
|
+
tools = [mods, fzf, rg]
|
21
|
+
AIA::External.verify_tools(tools)
|
22
|
+
|
23
|
+
# Build command for Mods tool with extra_options
|
24
|
+
extra_options = ['--some-extra-option']
|
25
|
+
mods_command = mods.command(extra_options)
|
26
|
+
puts "Mods command: #{mods_command}"
|
27
|
+
|
28
|
+
# Open a file with the system editor
|
29
|
+
AIA::External::Editor.open('path/to/file.txt')
|
30
|
+
|
31
|
+
# Search and select a file using Fzf tool
|
32
|
+
fzf_options = {
|
33
|
+
prompt_dir: 'path/to/prompts',
|
34
|
+
fuzzy: true
|
35
|
+
}
|
36
|
+
fzf_command = fzf.command(fzf_options)
|
37
|
+
puts "Fzf command: #{fzf_command}"
|
38
|
+
|
39
|
+
# Use Rg tool to search within files
|
40
|
+
search_term = 'search_query'
|
41
|
+
rg_command = rg.command(search_term, fzf_options: fzf.options)
|
42
|
+
puts "Rg command: #{rg_command}"
|
43
|
+
|
data/lib/aia/main.rb
CHANGED
@@ -6,7 +6,7 @@ require_relative 'configuration'
|
|
6
6
|
|
7
7
|
require_relative 'cli'
|
8
8
|
require_relative 'prompt_processing'
|
9
|
-
require_relative '
|
9
|
+
require_relative 'external'
|
10
10
|
require_relative 'logging'
|
11
11
|
|
12
12
|
# Everything is being handled within the context
|
@@ -16,7 +16,7 @@ class AIA::Main
|
|
16
16
|
include AIA::Configuration
|
17
17
|
include AIA::Cli
|
18
18
|
include AIA::PromptProcessing
|
19
|
-
include AIA::
|
19
|
+
include AIA::External
|
20
20
|
include AIA::Logging
|
21
21
|
|
22
22
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# lib/aia/prompt_processing.rb
|
2
2
|
|
3
3
|
module AIA::PromptProcessing
|
4
|
+
KW_HISTORY_MAX = 5
|
4
5
|
|
5
6
|
# Fetch the first argument which should be the prompt id
|
6
7
|
def get_prompt
|
@@ -18,6 +19,19 @@ module AIA::PromptProcessing
|
|
18
19
|
# Check if a prompt with the given id already exists
|
19
20
|
def existing_prompt?(prompt_id)
|
20
21
|
@prompt = PromptManager::Prompt.get(id: prompt_id)
|
22
|
+
|
23
|
+
# FIXME: Kludge until prompt_manager is changed
|
24
|
+
# prompt_manager v0.3.0 now supports this feature.
|
25
|
+
# keeping the kludge in for legacy JSON files
|
26
|
+
# files which have not yet been reformatted.
|
27
|
+
@prompt.keywords.each do |kw|
|
28
|
+
if @prompt.parameters[kw].nil? || @prompt.parameters[kw].empty?
|
29
|
+
@prompt.parameters[kw] = []
|
30
|
+
else
|
31
|
+
@prompt.parameters[kw] = Array(@prompt.parameters[kw])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
21
35
|
true
|
22
36
|
rescue ArgumentError
|
23
37
|
false
|
@@ -36,31 +50,45 @@ module AIA::PromptProcessing
|
|
36
50
|
|
37
51
|
|
38
52
|
def replace_keywords
|
39
|
-
|
53
|
+
puts
|
54
|
+
puts "ID: #{@prompt.id}"
|
40
55
|
|
41
|
-
|
56
|
+
show_prompt_without_comments
|
42
57
|
|
58
|
+
puts "\nPress up/down arrow to scroll through history."
|
59
|
+
puts "Type new input or edit the current input."
|
60
|
+
puts "Quit #{MY_NAME} with a CNTL-D or a CNTL-C"
|
61
|
+
puts
|
43
62
|
@prompt.keywords.each do |kw|
|
44
|
-
|
63
|
+
value = keyword_value(kw, @prompt.parameters[kw])
|
64
|
+
|
65
|
+
unless value.nil? || value.strip.empty?
|
66
|
+
value_inx = @prompt.parameters[kw].index(value)
|
67
|
+
|
68
|
+
if value_inx
|
69
|
+
@prompt.parameters[kw].delete_at(value_inx)
|
70
|
+
end
|
71
|
+
|
72
|
+
# The most recent value for this kw will always be
|
73
|
+
# in the last position
|
74
|
+
@prompt.parameters[kw] << value
|
75
|
+
@prompt.parameters[kw].shift if @prompt.parameters[kw].size > KW_HISTORY_MAX
|
76
|
+
end
|
45
77
|
end
|
46
|
-
|
47
|
-
@prompt.parameters = defaults
|
48
78
|
end
|
49
79
|
|
50
80
|
|
51
|
-
|
52
|
-
|
53
81
|
# query the user for a value to the keyword allow the
|
54
82
|
# reuse of the previous value shown as the default
|
55
|
-
def keyword_value(kw,
|
56
|
-
|
83
|
+
def keyword_value(kw, history_array)
|
84
|
+
|
85
|
+
Readline::HISTORY.clear
|
86
|
+
Array(history_array).each { |entry| Readline::HISTORY.push(entry) unless entry.nil? || entry.empty? }
|
87
|
+
|
57
88
|
puts "Parameter #{kw} ..."
|
58
|
-
default_wrapped = default.wrap(indent: label.size)
|
59
|
-
default_wrapped[0..label.size] = label
|
60
|
-
puts default_wrapped
|
61
89
|
|
62
90
|
begin
|
63
|
-
a_string = Readline.readline("\n-=> ",
|
91
|
+
a_string = Readline.readline("\n-=> ", true)
|
64
92
|
rescue Interrupt
|
65
93
|
a_string = nil
|
66
94
|
end
|
@@ -155,4 +183,30 @@ module AIA::PromptProcessing
|
|
155
183
|
@prompt = PromptManager::Prompt.get(id: @prompt.id)
|
156
184
|
end
|
157
185
|
|
186
|
+
|
187
|
+
def show_prompt_without_comments
|
188
|
+
puts remove_comments.wrap(indent: 4)
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
def remove_comments
|
193
|
+
lines = @prompt.text
|
194
|
+
.split("\n")
|
195
|
+
.reject{|a_line| a_line.strip.start_with?('#')}
|
196
|
+
|
197
|
+
# Remove empty lines at the start of the prompt
|
198
|
+
#
|
199
|
+
lines = lines.drop_while(&:empty?)
|
200
|
+
|
201
|
+
# Drop all the lines at __END__ and after
|
202
|
+
#
|
203
|
+
logical_end_inx = lines.index("__END__")
|
204
|
+
|
205
|
+
if logical_end_inx
|
206
|
+
lines[0...logical_end_inx] # NOTE: ... means to not include last index
|
207
|
+
else
|
208
|
+
lines
|
209
|
+
end.join("\n")
|
210
|
+
end
|
158
211
|
end
|
212
|
+
|
data/lib/aia/version.rb
CHANGED