aia 0.3.4 → 0.3.20
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/.semver +6 -0
- data/CHANGELOG.md +16 -0
- data/README.md +165 -55
- data/Rakefile +2 -0
- data/justfile +167 -0
- data/lib/aia/cli.rb +228 -115
- data/lib/aia/config.rb +7 -0
- data/lib/aia/logging.rb +49 -12
- data/lib/aia/main.rb +46 -15
- data/lib/aia/prompt_processing.rb +208 -4
- data/lib/aia/tools/editor.rb +52 -0
- data/lib/aia/{external → tools}/mods.rb +108 -12
- data/lib/aia/{external → tools}/sgpt.rb +12 -7
- data/lib/aia/{external → tools}/subl.rb +32 -11
- data/lib/aia/tools/temp.md +97 -0
- data/lib/aia/tools/vim.rb +93 -0
- data/lib/aia/tools.rb +50 -0
- data/lib/aia/version.rb +5 -1
- data/lib/aia.rb +18 -3
- data/main.just +56 -0
- data/man/aia.1 +134 -0
- data/man/aia.1.md +107 -0
- metadata +87 -18
- data/lib/aia/configuration.rb +0 -39
- data/lib/aia/external/,keep +0 -0
- data/lib/aia/external/.irbrc +0 -11
- data/lib/aia/external/ag.rb +0 -103
- data/lib/aia/external/bat.rb +0 -189
- data/lib/aia/external/fzf.rb +0 -147
- data/lib/aia/external/glow.rb +0 -37
- data/lib/aia/external/rg.rb +0 -1163
- data/lib/aia/external/tool.rb +0 -73
- data/lib/aia/external.rb +0 -259
- data/lib/aia/external_two.rb +0 -43
@@ -5,14 +5,20 @@ module AIA::PromptProcessing
|
|
5
5
|
|
6
6
|
# Fetch the first argument which should be the prompt id
|
7
7
|
def get_prompt
|
8
|
-
prompt_id =
|
8
|
+
prompt_id = AIA.config.arguments.shift
|
9
9
|
|
10
10
|
# TODO: or maybe go to a generic search and select process
|
11
11
|
|
12
|
+
# TODO: if external options were provided but no prompt id
|
13
|
+
# then by pass prompt process and send the extra
|
14
|
+
# options to the backend. For example:
|
15
|
+
# aia -- --settings
|
16
|
+
# should send --settings to mods and nothing else
|
17
|
+
|
12
18
|
abort("Please provide a prompt id") unless prompt_id
|
13
19
|
|
14
20
|
search_for_a_matching_prompt(prompt_id) unless existing_prompt?(prompt_id)
|
15
|
-
edit_prompt if edit?
|
21
|
+
edit_prompt if AIA.config.edit?
|
16
22
|
end
|
17
23
|
|
18
24
|
|
@@ -178,8 +184,17 @@ module AIA::PromptProcessing
|
|
178
184
|
|
179
185
|
|
180
186
|
def edit_prompt
|
181
|
-
|
182
|
-
|
187
|
+
# FIXME: replace with the editor from the configuration
|
188
|
+
|
189
|
+
@editor = AIA::Subl.new(
|
190
|
+
file: @prompt.path
|
191
|
+
)
|
192
|
+
|
193
|
+
@editor.run # blocks until file is closed
|
194
|
+
|
195
|
+
@options[:edit?][0] = false # turn off the --edit switch
|
196
|
+
|
197
|
+
# reload the edited prompt
|
183
198
|
@prompt = PromptManager::Prompt.get(id: @prompt.id)
|
184
199
|
end
|
185
200
|
|
@@ -210,3 +225,192 @@ module AIA::PromptProcessing
|
|
210
225
|
end
|
211
226
|
end
|
212
227
|
|
228
|
+
|
229
|
+
|
230
|
+
__END__
|
231
|
+
|
232
|
+
# lib/aia/prompt_processing.rb
|
233
|
+
|
234
|
+
class AIA::PromptProcessing
|
235
|
+
KW_HISTORY_MAX = 5
|
236
|
+
|
237
|
+
def initialize(arguments, options)
|
238
|
+
@arguments = arguments
|
239
|
+
@options = options
|
240
|
+
@prompt = nil
|
241
|
+
end
|
242
|
+
|
243
|
+
def execute
|
244
|
+
get_prompt
|
245
|
+
process_prompt
|
246
|
+
end
|
247
|
+
|
248
|
+
private
|
249
|
+
|
250
|
+
def get_prompt
|
251
|
+
prompt_id = @arguments.shift
|
252
|
+
abort("Please provide a prompt id") unless prompt_id
|
253
|
+
search_for_a_matching_prompt(prompt_id) unless existing_prompt?(prompt_id)
|
254
|
+
edit_prompt if edit?
|
255
|
+
end
|
256
|
+
|
257
|
+
def existing_prompt?(prompt_id)
|
258
|
+
@prompt = PromptManager::Prompt.get(id: prompt_id)
|
259
|
+
@prompt.keywords.each do |kw|
|
260
|
+
@prompt.parameters[kw] = Array(@prompt.parameters[kw])
|
261
|
+
end
|
262
|
+
true
|
263
|
+
rescue ArgumentError
|
264
|
+
false
|
265
|
+
end
|
266
|
+
|
267
|
+
def process_prompt
|
268
|
+
return if @prompt.keywords.empty?
|
269
|
+
replace_keywords
|
270
|
+
@prompt.build
|
271
|
+
@prompt.save
|
272
|
+
end
|
273
|
+
|
274
|
+
def replace_keywords
|
275
|
+
puts "ID: #{@prompt.id}"
|
276
|
+
show_prompt_without_comments
|
277
|
+
puts_instructions
|
278
|
+
@prompt.keywords.each do |kw|
|
279
|
+
value = keyword_value(kw, @prompt.parameters[kw])
|
280
|
+
update_keyword_history(kw, value) unless value.nil? || value.strip.empty?
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def puts_instructions
|
285
|
+
puts "\nPress up/down arrow to scroll through history."
|
286
|
+
puts "Type new input or edit the current input."
|
287
|
+
puts "Quit #{MY_NAME} with a CNTL-D or a CNTL-C"
|
288
|
+
puts
|
289
|
+
end
|
290
|
+
|
291
|
+
def update_keyword_history(kw, value)
|
292
|
+
params = @prompt.parameters[kw]
|
293
|
+
params.delete(value)
|
294
|
+
params << value
|
295
|
+
params.shift if params.size > KW_HISTORY_MAX
|
296
|
+
end
|
297
|
+
|
298
|
+
def keyword_value(kw, history_array)
|
299
|
+
Readline::HISTORY.clear
|
300
|
+
Array(history_array).each { |entry| Readline::HISTORY.push(entry) unless entry.nil? || entry.empty? }
|
301
|
+
puts "Parameter #{kw} ..."
|
302
|
+
begin
|
303
|
+
a_string = Readline.readline("\n-=> ", true)
|
304
|
+
rescue Interrupt
|
305
|
+
a_string = nil
|
306
|
+
end
|
307
|
+
abort("okay. Come back soon.") if a_string.nil?
|
308
|
+
a_string.empty? ? history_array.first : a_string
|
309
|
+
end
|
310
|
+
|
311
|
+
def search_for_a_matching_prompt(prompt_id)
|
312
|
+
found_prompts = PromptManager::Prompt.search(prompt_id)
|
313
|
+
handle_no_prompts_found(prompt_id) if found_prompts.empty?
|
314
|
+
prompt_id = found_prompts.size == 1 ? found_prompts.first : handle_multiple_prompts(found_prompts, prompt_id)
|
315
|
+
@prompt = PromptManager::Prompt.get(id: prompt_id)
|
316
|
+
end
|
317
|
+
|
318
|
+
def handle_no_prompts_found(prompt_id)
|
319
|
+
if edit?
|
320
|
+
create_prompt(prompt_id)
|
321
|
+
edit_prompt
|
322
|
+
else
|
323
|
+
abort_no_prompts_error(prompt_id)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def abort_no_prompts_error(prompt_id)
|
328
|
+
abort <<~EOS
|
329
|
+
|
330
|
+
No prompts were found for: #{prompt_id}
|
331
|
+
To create a prompt with this ID use the --edit option
|
332
|
+
like this:
|
333
|
+
#{MY_NAME} #{prompt_id} --edit
|
334
|
+
|
335
|
+
EOS
|
336
|
+
end
|
337
|
+
|
338
|
+
def handle_multiple_prompts(found_these, while_looking_for_this)
|
339
|
+
raise ArgumentError, "Argument is not an Array" unless found_these.is_a?(Array)
|
340
|
+
result = execute_fzf(found_these, while_looking_for_this)
|
341
|
+
abort unless result
|
342
|
+
result
|
343
|
+
end
|
344
|
+
|
345
|
+
def execute_fzf(found_these, while_looking_for_this)
|
346
|
+
fzf_options = build_fzf_options(while_looking_for_this)
|
347
|
+
temp_file = create_tempfile_with_entries(found_these)
|
348
|
+
selected = `cat #{temp_file.path} | fzf #{fzf_options}`.strip
|
349
|
+
temp_file.unlink
|
350
|
+
selected.empty? ? nil : selected
|
351
|
+
end
|
352
|
+
|
353
|
+
def build_fzf_options(search_term)
|
354
|
+
[
|
355
|
+
"--tabstop=2",
|
356
|
+
"--header='Prompt IDs which contain: #{search_term}\nPress ESC to cancel.'",
|
357
|
+
"--header-first",
|
358
|
+
"--prompt='Search term: '",
|
359
|
+
'--delimiter :',
|
360
|
+
"--preview 'cat $PROMPTS_DIR/{1}.txt'",
|
361
|
+
"--preview-window=down:50%:wrap"
|
362
|
+
].join(' ')
|
363
|
+
end
|
364
|
+
|
365
|
+
def create_tempfile_with_entries(entries)
|
366
|
+
temp_file = Tempfile.new('fzf-input')
|
367
|
+
temp_file.puts(entries)
|
368
|
+
temp_file.close
|
369
|
+
temp_file
|
370
|
+
end
|
371
|
+
|
372
|
+
def create_prompt(prompt_id)
|
373
|
+
@prompt = PromptManager::Prompt.create(id: prompt_id)
|
374
|
+
# Additional prompt config...
|
375
|
+
end
|
376
|
+
|
377
|
+
|
378
|
+
|
379
|
+
def edit_prompt
|
380
|
+
# FIXME: replace with the editor from the configuration
|
381
|
+
|
382
|
+
@editor = AIA::Subl.new(
|
383
|
+
file: @prompt.path
|
384
|
+
)
|
385
|
+
|
386
|
+
@editor.run # blocks until file is closed
|
387
|
+
|
388
|
+
@options[:edit?][0] = false # turn off the --edit switch
|
389
|
+
|
390
|
+
# reload the edited prompt
|
391
|
+
@prompt = PromptManager::Prompt.get(id: @prompt.id)
|
392
|
+
end
|
393
|
+
|
394
|
+
|
395
|
+
def show_prompt_without_comments
|
396
|
+
puts remove_comments.wrap(indent: 4)
|
397
|
+
end
|
398
|
+
|
399
|
+
def remove_comments
|
400
|
+
lines = @prompt.text.lines
|
401
|
+
.reject { |a_line| a_line.strip.start_with?('#') }
|
402
|
+
.drop_while(&:empty?)
|
403
|
+
logical_end_inx = lines.index("__END__")
|
404
|
+
lines = lines[0...logical_end_inx] if logical_end_inx
|
405
|
+
lines.join("\n")
|
406
|
+
end
|
407
|
+
|
408
|
+
def edit?
|
409
|
+
@options[:edit?] && @options[:edit?][0] == true
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
|
414
|
+
|
415
|
+
|
416
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# lib/aia/tools/editor.rb
|
2
|
+
# This is the default editor setup in the
|
3
|
+
# system environment variable EDITOR
|
4
|
+
|
5
|
+
|
6
|
+
class AIA::Editor < AIA::Tools
|
7
|
+
|
8
|
+
meta(
|
9
|
+
name: 'editor',
|
10
|
+
role: :editor,
|
11
|
+
desc: "Your default system $EDITOR",
|
12
|
+
url: "unknown",
|
13
|
+
install: "should already be installed",
|
14
|
+
)
|
15
|
+
|
16
|
+
DEFAULT_PARAMETERS = ""
|
17
|
+
|
18
|
+
attr_accessor :command
|
19
|
+
|
20
|
+
|
21
|
+
def initialize(file: "")
|
22
|
+
@file = file
|
23
|
+
|
24
|
+
discover_editor
|
25
|
+
|
26
|
+
build_command
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def discover_editor
|
31
|
+
editor = ENV['EDITOR'] # This might be nil
|
32
|
+
|
33
|
+
if editor.nil?
|
34
|
+
@name = "echo"
|
35
|
+
@description = "You have no default editor"
|
36
|
+
@install = "Set your system environment variable EDITOR"
|
37
|
+
else
|
38
|
+
@name = editor
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def build_command
|
44
|
+
@command = "#{meta.name} #{DEFAULT_PARAMETERS} #{@file}"
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def run
|
49
|
+
`#{command}`
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -1,22 +1,118 @@
|
|
1
|
-
# lib/aia/
|
2
|
-
|
3
|
-
class AIA::
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
# lib/aia/tools/mods.rb
|
2
|
+
|
3
|
+
class AIA::Mods < AIA::Tools
|
4
|
+
|
5
|
+
meta(
|
6
|
+
name: 'mods',
|
7
|
+
role: :backend,
|
8
|
+
desc: 'AI on the command-line',
|
9
|
+
url: 'https://github.com/charmbracelet/mods',
|
10
|
+
install: 'brew install mods',
|
11
|
+
)
|
12
|
+
|
13
|
+
|
14
|
+
DEFAULT_PARAMETERS = [
|
15
|
+
"--no-limit" # no limit on input context
|
16
|
+
].join(' ').freeze
|
17
|
+
|
18
|
+
attr_accessor :command, :text, :files
|
19
|
+
|
20
|
+
|
21
|
+
def initialize(
|
22
|
+
text: "", # prompt text after keyword replacement
|
23
|
+
files: [] # context file paths (Array of Pathname)
|
24
|
+
)
|
25
|
+
|
26
|
+
@text = text
|
27
|
+
@files = files
|
28
|
+
|
29
|
+
build_command
|
9
30
|
end
|
10
31
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
32
|
+
|
33
|
+
def sanitize(input)
|
34
|
+
Shellwords.escape(input)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def build_command
|
39
|
+
parameters = DEFAULT_PARAMETERS.dup + " "
|
40
|
+
parameters += "-f " if AIA.config.markdown?
|
41
|
+
parameters += "-m #{AIA.config.model} " if AIA.config.model
|
42
|
+
parameters += AIA.config.extra
|
43
|
+
@command = "mods #{parameters} "
|
44
|
+
@command += sanitize(@text)
|
45
|
+
|
46
|
+
# context = @files.join(' ')
|
47
|
+
#
|
48
|
+
# unless context.empty?
|
49
|
+
# if @files.size > 1
|
50
|
+
# # FIXME: This syntax breaks mods which does not know how
|
51
|
+
# # to read the temporary file descriptor created
|
52
|
+
# # by the shell
|
53
|
+
# @command += " <(cat #{context})"
|
54
|
+
# else
|
55
|
+
# @command += " < #{context}"
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
|
59
|
+
@command
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def run
|
64
|
+
case @files.size
|
65
|
+
when 0
|
66
|
+
@result = `#{build_command}`
|
67
|
+
when 1
|
68
|
+
@result = `#{build_command} < #{@files.first}`
|
69
|
+
else
|
70
|
+
create_temp_file_with_contexts
|
71
|
+
run_mods_with_temp_file
|
72
|
+
clean_up_temp_file
|
73
|
+
end
|
74
|
+
|
75
|
+
@result
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Create a temporary file that concatenates all contexts,
|
80
|
+
# to be used as STDIN for the 'mods' utility
|
81
|
+
def create_temp_file_with_contexts
|
82
|
+
@temp_file = Tempfile.new('mods-context')
|
83
|
+
|
84
|
+
@files.each do |file|
|
85
|
+
content = File.read(file)
|
86
|
+
@temp_file.write(content)
|
87
|
+
@temp_file.write("\n")
|
88
|
+
end
|
89
|
+
|
90
|
+
@temp_file.close
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# Run 'mods' with the temporary file as STDIN
|
95
|
+
def run_mods_with_temp_file
|
96
|
+
command = "#{build_command} < #{@temp_file.path}"
|
97
|
+
@result = `#{command}`
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Clean up the temporary file after use
|
102
|
+
def clean_up_temp_file
|
103
|
+
@temp_file.unlink if @temp_file
|
15
104
|
end
|
16
105
|
end
|
17
106
|
|
18
107
|
__END__
|
19
108
|
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
##########################################################
|
114
|
+
|
115
|
+
|
20
116
|
GPT on the command line. Built for pipelines.
|
21
117
|
|
22
118
|
Usage:
|
@@ -1,12 +1,17 @@
|
|
1
|
-
# lib/aia/
|
1
|
+
# lib/aia/tools/sgpt.rb
|
2
|
+
|
3
|
+
class AIA::Sgpt < AIA::Tools
|
4
|
+
|
5
|
+
meta(
|
6
|
+
name: 'sgpt',
|
7
|
+
role: :backend,
|
8
|
+
desc: "shell-gpt",
|
9
|
+
url: "https://github.com/TheR1D/shell_gpt",
|
10
|
+
install: "pip install shell-gpt",
|
11
|
+
)
|
2
12
|
|
3
|
-
class AIA::External::Sgpt < AIA::External::Tool
|
4
13
|
def initialize
|
5
|
-
|
6
|
-
@role = :backend
|
7
|
-
@desc = "shell-gpt"
|
8
|
-
@url = "https://github.com/TheR1D/shell_gpt"
|
9
|
-
@install = "pip install shell-gpt"
|
14
|
+
# TODO: something
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
@@ -1,17 +1,38 @@
|
|
1
|
-
# lib/aia/
|
2
|
-
|
3
|
-
class AIA::
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
# lib/aia/tools/subl.rb
|
2
|
+
|
3
|
+
class AIA::Subl < AIA::Tools
|
4
|
+
|
5
|
+
meta(
|
6
|
+
name: 'subl',
|
7
|
+
role: :editor,
|
8
|
+
desc: "Sublime Text Editor",
|
9
|
+
url: "https://www.sublimetext.com/",
|
10
|
+
install: "echo 'Download from website'",
|
11
|
+
)
|
12
|
+
|
13
|
+
|
14
|
+
DEFAULT_PARAMETERS = [
|
15
|
+
"--new-window", # Open a new window
|
16
|
+
"--wait", # Wait for the files to be closed before returning
|
17
|
+
].join(' ')
|
18
|
+
|
19
|
+
attr_accessor :command
|
20
|
+
|
21
|
+
|
22
|
+
def initialize(file: "")
|
23
|
+
@file = file
|
24
|
+
|
25
|
+
build_command
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def build_command
|
30
|
+
@command = "#{meta.name} #{DEFAULT_PARAMETERS} #{@file}"
|
10
31
|
end
|
11
32
|
|
12
33
|
|
13
|
-
def
|
14
|
-
`#{
|
34
|
+
def run
|
35
|
+
`#{command}`
|
15
36
|
end
|
16
37
|
end
|
17
38
|
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# lib/aia/tools.rb
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
require 'hashie'
|
5
|
+
|
6
|
+
module AIA
|
7
|
+
class Tools
|
8
|
+
@subclasses = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_reader :subclasses, :metadata
|
12
|
+
|
13
|
+
def inherited(subclass)
|
14
|
+
@subclasses[subclass.name.split('::').last.downcase] = subclass
|
15
|
+
subclass.instance_variable_set(:@metadata, Jashie::Mash.new)
|
16
|
+
end
|
17
|
+
|
18
|
+
def meta
|
19
|
+
@metadata ||= Jashie::Mash.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_metadata(&block)
|
23
|
+
meta.instance_eval(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def search_for(name: nil, role: nil)
|
27
|
+
return subclasses[name.downcase] if name
|
28
|
+
return subclasses.values.select { |subclass| subclass.meta.role == role } if role
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.method_missing(name, *args, &block)
|
33
|
+
@metadata.public_send(name, *args, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.respond_to_missing?(method_name, include_private = false)
|
37
|
+
@metadata.respond_to?(method_name) || super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
# lib/aia/tools/mods.rb
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
require_relative 'tools'
|
47
|
+
|
48
|
+
module AIA
|
49
|
+
class Mods < Tools
|
50
|
+
DEFAULT_PARAMETERS = "--no-limit".freeze
|
51
|
+
|
52
|
+
attr_accessor :command, :extra_options, :text, :files
|
53
|
+
|
54
|
+
define_metadata do
|
55
|
+
role :backend
|
56
|
+
desc 'AI on the command-line'
|
57
|
+
url 'https://github.com/charmbracelet/mods'
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(extra_options: "", text: "", files: [])
|
61
|
+
@extra_options = extra_options
|
62
|
+
@text = text
|
63
|
+
@files = files
|
64
|
+
build_command
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_command
|
68
|
+
parameters = DEFAULT_PARAMETERS.dup + " "
|
69
|
+
parameters += "-f " if ::AIA.config.markdown?
|
70
|
+
parameters += "-m #{AIA.config.model} " if ::AIA.config.model
|
71
|
+
parameters += @extra_options
|
72
|
+
@command = "mods #{parameters}"
|
73
|
+
@command += %Q["#{@text}"]
|
74
|
+
|
75
|
+
@files.each { |f| @command += " < #{f}" }
|
76
|
+
|
77
|
+
@command
|
78
|
+
end
|
79
|
+
|
80
|
+
def run
|
81
|
+
`#{@command}`
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
# Example usage:
|
89
|
+
# mods_class = AIA::Tools.search_for(name: 'mods')
|
90
|
+
# mods_instance = mods_class.new(text: "Hello, mods!")
|
91
|
+
# result = mods_instance.run
|
92
|
+
|
93
|
+
# backend_tools = AIA::Tools.search_for(role: :backend)
|
94
|
+
```
|
95
|
+
|
96
|
+
Note: The `Jashie::Mash` class is assumed to behave like `Hashie::Mash` (or similar) in providing a flexible object for storing metadata. You'll need to define `Jashie::Mash` or import a library that provides a similar functionality to match this example.
|
97
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# lib/aia/tools/vim.rb
|
2
|
+
|
3
|
+
class AIA::Vim < AIA::Tools
|
4
|
+
|
5
|
+
meta(
|
6
|
+
name: 'vim',
|
7
|
+
role: :editor,
|
8
|
+
desc: "Vi IMproved (VIM)",
|
9
|
+
url: "https://www.vim.org",
|
10
|
+
install: "brew install vim",
|
11
|
+
)
|
12
|
+
|
13
|
+
DEFAULT_PARAMETERS = [
|
14
|
+
" ", # no parameters
|
15
|
+
].join(' ')
|
16
|
+
|
17
|
+
attr_accessor :command
|
18
|
+
|
19
|
+
|
20
|
+
def initialize(file: "")
|
21
|
+
@file = file
|
22
|
+
|
23
|
+
build_command
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def build_command
|
28
|
+
@command = "#{meta.name} #{DEFAULT_PARAMETERS} #{@file}"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def run
|
33
|
+
# Using 'system' instead of backticks becuase
|
34
|
+
# with the back ticks vim was complaining that it
|
35
|
+
# was not connected to a terminal.
|
36
|
+
system command
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
__END__
|
41
|
+
|
42
|
+
VIM - Vi IMproved 9.0 (2022 Jun 28, compiled Sep 30 2023 05:45:56)
|
43
|
+
|
44
|
+
Usage: vim [arguments] [file ..] edit specified file(s)
|
45
|
+
or: vim [arguments] - read text from stdin
|
46
|
+
or: vim [arguments] -t tag edit file where tag is defined
|
47
|
+
or: vim [arguments] -q [errorfile] edit file with first error
|
48
|
+
|
49
|
+
Arguments:
|
50
|
+
-- Only file names after this
|
51
|
+
-v Vi mode (like "vi")
|
52
|
+
-e Ex mode (like "ex")
|
53
|
+
-E Improved Ex mode
|
54
|
+
-s Silent (batch) mode (only for "ex")
|
55
|
+
-d Diff mode (like "vimdiff")
|
56
|
+
-y Easy mode (like "evim", modeless)
|
57
|
+
-R Readonly mode (like "view")
|
58
|
+
-Z Restricted mode (like "rvim")
|
59
|
+
-m Modifications (writing files) not allowed
|
60
|
+
-M Modifications in text not allowed
|
61
|
+
-b Binary mode
|
62
|
+
-l Lisp mode
|
63
|
+
-C Compatible with Vi: 'compatible'
|
64
|
+
-N Not fully Vi compatible: 'nocompatible'
|
65
|
+
-V[N][fname] Be verbose [level N] [log messages to fname]
|
66
|
+
-D Debugging mode
|
67
|
+
-n No swap file, use memory only
|
68
|
+
-r List swap files and exit
|
69
|
+
-r (with file name) Recover crashed session
|
70
|
+
-L Same as -r
|
71
|
+
-T <terminal> Set terminal type to <terminal>
|
72
|
+
--not-a-term Skip warning for input/output not being a terminal
|
73
|
+
--ttyfail Exit if input or output is not a terminal
|
74
|
+
-u <vimrc> Use <vimrc> instead of any .vimrc
|
75
|
+
--noplugin Don't load plugin scripts
|
76
|
+
-p[N] Open N tab pages (default: one for each file)
|
77
|
+
-o[N] Open N windows (default: one for each file)
|
78
|
+
-O[N] Like -o but split vertically
|
79
|
+
+ Start at end of file
|
80
|
+
+<lnum> Start at line <lnum>
|
81
|
+
--cmd <command> Execute <command> before loading any vimrc file
|
82
|
+
-c <command> Execute <command> after loading the first file
|
83
|
+
-S <session> Source file <session> after loading the first file
|
84
|
+
-s <scriptin> Read Normal mode commands from file <scriptin>
|
85
|
+
-w <scriptout> Append all typed commands to file <scriptout>
|
86
|
+
-W <scriptout> Write all typed commands to file <scriptout>
|
87
|
+
-x Edit encrypted files
|
88
|
+
--startuptime <file> Write startup timing messages to <file>
|
89
|
+
--log <file> Start logging to <file> early
|
90
|
+
-i <viminfo> Use <viminfo> instead of .viminfo
|
91
|
+
--clean 'nocompatible', Vim defaults, no plugins, no viminfo
|
92
|
+
-h or --help Print Help (this message) and exit
|
93
|
+
--version Print version information and exit
|