aicli 0.3.0 → 0.4.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/README.md +23 -154
- data/lib/aicli/cli.rb +11 -32
- data/lib/aicli/commands/chat.rb +15 -37
- data/lib/aicli/commands/config.rb +29 -18
- data/lib/aicli/helpers/completion.rb +65 -103
- data/lib/aicli/helpers/config.rb +1 -5
- data/lib/aicli/helpers/constants.rb +1 -0
- data/lib/aicli/helpers/context.rb +1 -2
- data/lib/aicli/helpers/error.rb +1 -3
- data/lib/aicli/helpers/i18n.rb +6 -0
- data/lib/aicli/helpers/script_action_menu.rb +128 -0
- data/lib/aicli/helpers/script_editor.rb +65 -0
- data/lib/aicli/helpers/shell_exec.rb +14 -0
- data/lib/aicli/helpers/shell_history.rb +164 -27
- data/lib/aicli/helpers/theme.rb +40 -0
- data/lib/aicli/prompt.rb +77 -142
- data/lib/aicli/version.rb +1 -1
- data/lib/aicli.rb +4 -1
- data/locales/en.yml +11 -36
- data/locales/it.yml +14 -38
- metadata +19 -2
- data/lib/aicli/helpers/strip_regex_patterns.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf98faf6cbdbc3b6ec1597895520ab51c1a2c4d8f31e0ef80360497d57d6fdd6
|
|
4
|
+
data.tar.gz: 531e7e3941c6de76d4dbca4f284f2ba6f3017216398173c605448e8c4a036934
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1b9259c9ac632dcb4bb5324db52260a112b58ea087faf2d28a36f22c7099d234d6188ad406e6791e746b2d994d397d4d61b39a24f8940b1dc54f9b17af3adf85
|
|
7
|
+
data.tar.gz: 348882fccb22e28fcb3970e1a2f603b512ab6ca149e1d339debdb3a3feb29facd4133cfb34c29000334bc10121d6f4fb3432bebdef862fb61b3b4a3c4e916446
|
data/README.md
CHANGED
|
@@ -1,186 +1,55 @@
|
|
|
1
1
|
# aicli
|
|
2
2
|
|
|
3
|
-
Natural language
|
|
3
|
+
Natural language → shell commands. OpenAI or Anthropic.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The gem is named **aicli**; the shell command is **`ai`** (also available as `aicli`).
|
|
5
|
+
Install: `gem install aicli` (Ruby 3.0+). Command: **`ai`**.
|
|
8
6
|
|
|
9
7
|
## Setup
|
|
10
8
|
|
|
11
|
-
> Requires Ruby 3.0+
|
|
12
|
-
|
|
13
|
-
1. Install the gem:
|
|
14
|
-
|
|
15
|
-
```sh
|
|
16
|
-
gem install aicli
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Or from this repository:
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
bundle install
|
|
23
|
-
bundle exec rake install
|
|
24
|
-
# or
|
|
25
|
-
gem build aicli.gemspec && gem install ./aicli-*.gem
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
2. Choose a provider and set the matching API key.
|
|
29
|
-
|
|
30
|
-
**OpenAI** (default) — key from [OpenAI](https://platform.openai.com/account/api-keys):
|
|
31
|
-
|
|
32
|
-
```sh
|
|
33
|
-
ai config set PROVIDER=openai
|
|
34
|
-
ai config set OPENAI_KEY=<your token>
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Anthropic** — key from [Anthropic](https://console.anthropic.com/settings/keys):
|
|
38
|
-
|
|
39
|
-
```sh
|
|
40
|
-
ai config set PROVIDER=anthropic
|
|
41
|
-
ai config set ANTHROPIC_KEY=<your token>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Or use the interactive UI (`ai config`) to pick provider, key, and model.
|
|
45
|
-
Model lists come from the [RubyLLM](https://rubyllm.com/models/) registry.
|
|
46
|
-
|
|
47
|
-
Config lives in `~/.aicli/config`. Chat/prompt history is stored in `~/.aicli/context` (last 40 messages) and reloaded on the next run.
|
|
48
|
-
|
|
49
|
-
## Usage
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
ai <prompt>
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
For example:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
ai list all log files
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Then you will get an output where you can choose to run the suggested command, revise it via a prompt, edit it, copy it, or cancel.
|
|
62
|
-
|
|
63
|
-
### Special characters
|
|
64
|
-
|
|
65
|
-
Some shells handle characters like `?` or `*` specially. Wrap the prompt in quotes if needed:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
ai 'what is my ip address'
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Chat mode
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
ai chat
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Ask for shell commands in a multi-turn conversation. When the assistant suggests a command in a code fence, you are asked whether to run it; after it runs (or you decline), chat continues. Press `Ctrl+d` to quit.
|
|
78
|
-
|
|
79
|
-
### Silent mode (skip explanations)
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
ai -s list all log files
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Or save the preference:
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
ai config set SILENT_MODE=true
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Provider and model
|
|
92
|
-
|
|
93
9
|
```sh
|
|
94
|
-
ai config set PROVIDER=openai
|
|
95
|
-
ai config set
|
|
10
|
+
ai config set PROVIDER=openai
|
|
11
|
+
ai config set OPENAI_KEY=<token>
|
|
96
12
|
```
|
|
97
13
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
LLM calls go through [RubyLLM](https://rubyllm.com/), so chat streaming and model metadata stay provider-agnostic.
|
|
14
|
+
Or `ai config` for the interactive setup. Config: `~/.aicli/config`.
|
|
101
15
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Useful for OpenAI-compatible proxies (ignored for Anthropic):
|
|
16
|
+
Anthropic:
|
|
105
17
|
|
|
106
18
|
```sh
|
|
107
|
-
ai config set
|
|
19
|
+
ai config set PROVIDER=anthropic
|
|
20
|
+
ai config set ANTHROPIC_KEY=<token>
|
|
108
21
|
```
|
|
109
22
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
### Set Language
|
|
113
|
-
|
|
114
|
-
| Language | Key |
|
|
115
|
-
| ------------------- | ------- |
|
|
116
|
-
| English | en |
|
|
117
|
-
| Simplified Chinese | zh-Hans |
|
|
118
|
-
| Traditional Chinese | zh-Hant |
|
|
119
|
-
| Spanish | es |
|
|
120
|
-
| Japanese | jp |
|
|
121
|
-
| Korean | ko |
|
|
122
|
-
| French | fr |
|
|
123
|
-
| German | de |
|
|
124
|
-
| Russian | ru |
|
|
125
|
-
| Ukrainian | uk |
|
|
126
|
-
| Vietnamese | vi |
|
|
127
|
-
| Arabic | ar |
|
|
128
|
-
| Portuguese | pt |
|
|
129
|
-
| Turkish | tr |
|
|
130
|
-
| Indonesian | id |
|
|
131
|
-
| Italian | it |
|
|
23
|
+
Shell history (optional — ↑ recalls the run command, not `ai ...`):
|
|
132
24
|
|
|
133
25
|
```sh
|
|
134
|
-
ai config
|
|
26
|
+
ai config shell
|
|
27
|
+
source ~/.zshrc
|
|
135
28
|
```
|
|
136
29
|
|
|
137
|
-
|
|
30
|
+
## Usage
|
|
138
31
|
|
|
139
|
-
```
|
|
140
|
-
ai
|
|
32
|
+
```sh
|
|
33
|
+
ai list all log files
|
|
34
|
+
ai 'what is my ip address' # quote special chars
|
|
35
|
+
ai chat # multi-turn; Ctrl+d to quit
|
|
36
|
+
ai -s list log files # skip Explain in menu
|
|
141
37
|
```
|
|
142
38
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
ai
|
|
39
|
+
```sh
|
|
40
|
+
ai config set SILENT_MODE=true
|
|
41
|
+
ai config set MODEL=gpt-4o-mini
|
|
42
|
+
ai config set LANGUAGE=it
|
|
147
43
|
ai update
|
|
148
|
-
# or: gem update aicli
|
|
149
44
|
```
|
|
150
45
|
|
|
151
46
|
## Development
|
|
152
47
|
|
|
153
|
-
Run the local checkout (not the installed gem) with Bundler from this directory:
|
|
154
|
-
|
|
155
48
|
```sh
|
|
156
49
|
bundle install
|
|
157
|
-
|
|
158
|
-
bundle exec bin/ai --help
|
|
159
|
-
bundle exec bin/ai config
|
|
160
|
-
bundle exec bin/ai chat
|
|
161
50
|
bundle exec bin/ai list all log files
|
|
162
51
|
```
|
|
163
52
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Example config for local testing:
|
|
167
|
-
|
|
168
|
-
```sh
|
|
169
|
-
bundle exec bin/ai config set PROVIDER=openai
|
|
170
|
-
bundle exec bin/ai config set OPENAI_KEY=<your token>
|
|
171
|
-
# or: PROVIDER=anthropic + ANTHROPIC_KEY=<your token>
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
## Common Issues
|
|
175
|
-
|
|
176
|
-
### Rate limit / quota errors
|
|
177
|
-
|
|
178
|
-
Usually billing or quota on the configured provider (OpenAI or Anthropic). Check that provider’s console billing page and that the matching API key is set in `~/.aicli/config`.
|
|
179
|
-
|
|
180
|
-
## Motivation
|
|
181
|
-
|
|
182
|
-
I am not a bash wizard, and am dying for access to the copilot CLI, and got impatient.
|
|
183
|
-
|
|
184
|
-
## Credit
|
|
53
|
+
## License
|
|
185
54
|
|
|
186
|
-
|
|
55
|
+
[MIT](LICENSE)
|
data/lib/aicli/cli.rb
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'thor'
|
|
4
|
-
require 'pastel'
|
|
5
4
|
|
|
6
5
|
module AiCli
|
|
7
6
|
class CLI < Thor
|
|
8
|
-
KNOWN_COMMANDS = %w[config chat update help version
|
|
7
|
+
KNOWN_COMMANDS = %w[config chat update help version].freeze
|
|
9
8
|
|
|
10
9
|
def self.exit_on_failure?
|
|
11
10
|
true
|
|
@@ -13,8 +12,6 @@ module AiCli
|
|
|
13
12
|
|
|
14
13
|
def self.start(given_args = ARGV, config = {})
|
|
15
14
|
args = given_args.dup
|
|
16
|
-
|
|
17
|
-
# Extract global flags that may appear before the prompt text
|
|
18
15
|
silent = args.delete('--silent') || args.delete('-s')
|
|
19
16
|
version_flag = args.delete('--version') || args.delete('-v')
|
|
20
17
|
help_flag = args.delete('--help') || args.delete('-h')
|
|
@@ -29,7 +26,6 @@ module AiCli
|
|
|
29
26
|
return
|
|
30
27
|
end
|
|
31
28
|
|
|
32
|
-
# Prompt flag: -p / --prompt
|
|
33
29
|
prompt_from_flag = nil
|
|
34
30
|
if (idx = args.index('-p') || args.index('--prompt'))
|
|
35
31
|
prompt_from_flag = args[idx + 1]
|
|
@@ -38,51 +34,43 @@ module AiCli
|
|
|
38
34
|
|
|
39
35
|
first = args.first
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
# Treat remaining args as the natural-language prompt
|
|
37
|
+
unless first.nil? || KNOWN_COMMANDS.include?(first)
|
|
43
38
|
prompt_text = prompt_from_flag || args.join(' ')
|
|
44
39
|
invoke_prompt(prompt_text, silent: !silent.nil?)
|
|
45
40
|
return
|
|
46
41
|
end
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
thor_args = args
|
|
50
|
-
thor_args = ['--silent'] + thor_args if silent && first == 'chat'
|
|
43
|
+
thor_args = silent && first == 'chat' ? ['--silent'] + args : args
|
|
51
44
|
super(thor_args, config)
|
|
52
45
|
end
|
|
53
46
|
|
|
54
47
|
def self.invoke_prompt(prompt_text, silent: false)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
begin
|
|
58
|
-
config = Helpers::Config.get
|
|
59
|
-
Helpers::I18n.set_language(config['LANGUAGE'])
|
|
60
|
-
rescue StandardError
|
|
61
|
-
Helpers::I18n.set_language('en')
|
|
62
|
-
end
|
|
63
|
-
|
|
48
|
+
Helpers::I18n.load_from_config!
|
|
64
49
|
Prompt.run(use_prompt: prompt_text, silent_mode: silent)
|
|
50
|
+
rescue Interrupt
|
|
51
|
+
puts Helpers::I18n.t('Goodbye!')
|
|
52
|
+
exit 0
|
|
65
53
|
rescue Helpers::KnownError, StandardError => e
|
|
66
|
-
puts "\n#{pastel.red('✖')} #{e.message}"
|
|
54
|
+
puts "\n#{Helpers::Theme.pastel.red('✖')} #{e.message}"
|
|
67
55
|
Helpers::Error.handle_cli_error(e)
|
|
68
56
|
exit 1
|
|
69
57
|
end
|
|
70
58
|
|
|
71
59
|
desc 'config [MODE] [KEY=VALUE...]', 'Configure the CLI'
|
|
72
60
|
def config(mode = nil, *key_values)
|
|
73
|
-
|
|
61
|
+
Helpers::I18n.load_from_config!
|
|
74
62
|
Commands::Config.run(mode, *key_values)
|
|
75
63
|
end
|
|
76
64
|
|
|
77
65
|
desc 'chat', 'Start a new chat session'
|
|
78
66
|
def chat
|
|
79
|
-
|
|
67
|
+
Helpers::I18n.load_from_config!
|
|
80
68
|
Commands::Chat.run
|
|
81
69
|
end
|
|
82
70
|
|
|
83
71
|
desc 'update', 'Update the aicli gem to the latest version'
|
|
84
72
|
def update
|
|
85
|
-
|
|
73
|
+
Helpers::I18n.load_from_config!
|
|
86
74
|
Commands::Update.run
|
|
87
75
|
end
|
|
88
76
|
|
|
@@ -91,14 +79,5 @@ module AiCli
|
|
|
91
79
|
def version
|
|
92
80
|
puts AiCli::VERSION
|
|
93
81
|
end
|
|
94
|
-
|
|
95
|
-
private
|
|
96
|
-
|
|
97
|
-
def init_i18n
|
|
98
|
-
config = Helpers::Config.get
|
|
99
|
-
Helpers::I18n.set_language(config['LANGUAGE'])
|
|
100
|
-
rescue StandardError
|
|
101
|
-
Helpers::I18n.set_language('en')
|
|
102
|
-
end
|
|
103
82
|
end
|
|
104
83
|
end
|
data/lib/aicli/commands/chat.rb
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'io/console'
|
|
4
|
-
require 'pastel'
|
|
5
|
-
require 'tty-prompt'
|
|
6
4
|
require 'tty-spinner'
|
|
7
5
|
|
|
8
6
|
module AiCli
|
|
@@ -16,31 +14,27 @@ module AiCli
|
|
|
16
14
|
restored = Helpers::Context.load_messages
|
|
17
15
|
Helpers::Context.apply_to_chat(chat) if restored.any?
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
prompt = TTY::Prompt.new(interrupt: :error)
|
|
17
|
+
prompt = Helpers::Theme.prompt(interrupt: :error)
|
|
21
18
|
Helpers::Context.seed_prompt_history(prompt)
|
|
22
19
|
|
|
23
20
|
puts ''
|
|
24
|
-
puts "#{config
|
|
21
|
+
puts "#{Helpers::Theme.status(config)} #{Helpers::Theme.dim('Ctrl+d to quit')}"
|
|
25
22
|
|
|
26
23
|
catch(:chat_quit) do
|
|
27
24
|
prompt.on(:keyctrl_d) { throw :chat_quit }
|
|
28
25
|
|
|
29
26
|
loop do
|
|
30
27
|
begin
|
|
31
|
-
user_prompt = prompt.ask(
|
|
28
|
+
user_prompt = prompt.ask(Helpers::Theme.accent("#{Helpers::I18n.t('You')}:")) do |q|
|
|
32
29
|
q.required true
|
|
33
30
|
q.validate(/.+/, Helpers::I18n.t('Please enter a prompt.'))
|
|
34
31
|
end
|
|
35
32
|
rescue TTY::Reader::InputInterrupt
|
|
36
|
-
# Ctrl+C clears the current input line and re-prompts.
|
|
37
33
|
print "\r\e[2K"
|
|
38
34
|
next
|
|
39
35
|
end
|
|
40
36
|
|
|
41
|
-
if user_prompt.nil? || user_prompt.strip.downcase == 'exit'
|
|
42
|
-
throw :chat_quit
|
|
43
|
-
end
|
|
37
|
+
throw :chat_quit if user_prompt.nil? || user_prompt.strip.downcase == 'exit'
|
|
44
38
|
|
|
45
39
|
spinner = TTY::Spinner.new("[:spinner] #{Helpers::I18n.t('THINKING...')}", format: :dots)
|
|
46
40
|
spinner.auto_spin
|
|
@@ -51,7 +45,7 @@ module AiCli
|
|
|
51
45
|
user_prompt,
|
|
52
46
|
writer: lambda { |chunk|
|
|
53
47
|
unless started
|
|
54
|
-
spinner.success(pastel.green('ai:'))
|
|
48
|
+
spinner.success(Helpers::Theme.pastel.green('ai:'))
|
|
55
49
|
puts ''
|
|
56
50
|
started = true
|
|
57
51
|
end
|
|
@@ -60,14 +54,13 @@ module AiCli
|
|
|
60
54
|
)
|
|
61
55
|
|
|
62
56
|
unless started
|
|
63
|
-
spinner.success(pastel.green('ai:'))
|
|
57
|
+
spinner.success(Helpers::Theme.pastel.green('ai:'))
|
|
64
58
|
puts ''
|
|
65
59
|
end
|
|
66
|
-
puts
|
|
67
|
-
puts ''
|
|
60
|
+
puts "\n\n"
|
|
68
61
|
|
|
69
62
|
Helpers::Context.save_from_chat(chat)
|
|
70
|
-
offer_to_run_commands(response
|
|
63
|
+
offer_to_run_commands(response)
|
|
71
64
|
end
|
|
72
65
|
end
|
|
73
66
|
|
|
@@ -76,20 +69,16 @@ module AiCli
|
|
|
76
69
|
puts Helpers::I18n.t('Goodbye!')
|
|
77
70
|
end
|
|
78
71
|
|
|
79
|
-
def offer_to_run_commands(response
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
commands.each do |command|
|
|
84
|
-
puts pastel.dim(command)
|
|
72
|
+
def offer_to_run_commands(response)
|
|
73
|
+
Helpers::Completion.extract_commands(response).each do |command|
|
|
74
|
+
puts Helpers::Theme.dim(command)
|
|
85
75
|
next unless ask_to_run?
|
|
86
76
|
|
|
87
|
-
|
|
88
|
-
|
|
77
|
+
puts "#{Helpers::I18n.t('Running')}: #{command}\n\n"
|
|
78
|
+
Helpers::ShellExec.run(command)
|
|
89
79
|
end
|
|
90
80
|
end
|
|
91
81
|
|
|
92
|
-
# Only explicit `y` runs the command. Enter, Esc, n, Ctrl-C → skip.
|
|
93
82
|
def ask_to_run?
|
|
94
83
|
tty = File.open('/dev/tty', 'r+')
|
|
95
84
|
tty.print "#{Helpers::I18n.t('Run it?')} (y/n) "
|
|
@@ -98,24 +87,13 @@ module AiCli
|
|
|
98
87
|
tty.puts
|
|
99
88
|
char.to_s.downcase == 'y'
|
|
100
89
|
rescue Interrupt
|
|
101
|
-
|
|
102
|
-
tty&.puts
|
|
103
|
-
rescue StandardError
|
|
104
|
-
puts
|
|
105
|
-
end
|
|
90
|
+
tty&.puts
|
|
106
91
|
false
|
|
107
92
|
ensure
|
|
108
93
|
tty&.close
|
|
109
94
|
end
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
puts "#{Helpers::I18n.t('Running')}: #{command}"
|
|
113
|
-
puts ''
|
|
114
|
-
system(ENV['SHELL'] || 'bash', '-c', command)
|
|
115
|
-
Helpers::ShellHistory.append(command)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
private_class_method :offer_to_run_commands, :ask_to_run?, :run_command
|
|
96
|
+
private_class_method :offer_to_run_commands, :ask_to_run?
|
|
119
97
|
end
|
|
120
98
|
end
|
|
121
99
|
end
|
|
@@ -15,27 +15,38 @@ module AiCli
|
|
|
15
15
|
return
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
if key_values.empty?
|
|
19
|
-
puts "#{Helpers::I18n.t('Error')}: #{Helpers::I18n.t('Missing required parameter')} \"key=value\"\n"
|
|
20
|
-
exit 1
|
|
21
|
-
end
|
|
22
|
-
|
|
23
18
|
case mode
|
|
24
|
-
when '
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
when 'shell'
|
|
20
|
+
result = Helpers::ShellHistory.activate_shell_integration!
|
|
21
|
+
puts pastel.green('✔') + ' ' + Helpers::I18n.t('Shell integration installed.')
|
|
22
|
+
hint = Helpers::ShellHistory.shell_integration_hint(
|
|
23
|
+
activated: result[:activated],
|
|
24
|
+
rc_path: result[:rc_path],
|
|
25
|
+
source_path: result[:source_path]
|
|
26
|
+
)
|
|
27
|
+
puts hint unless hint.empty?
|
|
28
|
+
when 'get', 'set'
|
|
29
|
+
if key_values.empty?
|
|
30
|
+
puts "#{Helpers::I18n.t('Error')}: #{Helpers::I18n.t('Missing required parameter')} \"key=value\"\n"
|
|
31
|
+
exit 1
|
|
32
32
|
end
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
|
|
34
|
+
if mode == 'get'
|
|
35
|
+
config = Helpers::Config.get
|
|
36
|
+
key_values.each do |key|
|
|
37
|
+
if config.key?(key)
|
|
38
|
+
puts "#{key}=#{config[key]}"
|
|
39
|
+
else
|
|
40
|
+
raise Helpers::KnownError, "#{Helpers::I18n.t('Invalid config property')}: #{key}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
pairs = key_values.map do |kv|
|
|
45
|
+
k, v = kv.split('=', 2)
|
|
46
|
+
[k, v]
|
|
47
|
+
end
|
|
48
|
+
Helpers::Config.set(pairs)
|
|
37
49
|
end
|
|
38
|
-
Helpers::Config.set(pairs)
|
|
39
50
|
else
|
|
40
51
|
raise Helpers::KnownError, "#{Helpers::I18n.t('Invalid mode')}: #{mode}"
|
|
41
52
|
end
|