hammer_cli 0.19.2 → 2.0.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/bin/hammer-complete +28 -0
- data/config/cli_config.template.yml +2 -0
- data/config/hammer.completion +5 -0
- data/doc/creating_commands.md +27 -0
- data/doc/installation.md +47 -4
- data/doc/release_notes.md +17 -9
- data/lib/hammer_cli.rb +1 -0
- data/lib/hammer_cli/abstract.rb +32 -2
- data/lib/hammer_cli/apipie/api_connection.rb +5 -1
- data/lib/hammer_cli/apipie/command.rb +3 -2
- data/lib/hammer_cli/bash.rb +2 -0
- data/lib/hammer_cli/bash/completion.rb +159 -0
- data/lib/hammer_cli/bash/prebuild_command.rb +21 -0
- data/lib/hammer_cli/connection.rb +4 -0
- data/lib/hammer_cli/exception_handler.rb +10 -1
- data/lib/hammer_cli/main.rb +5 -3
- data/lib/hammer_cli/options/normalizers.rb +7 -3
- data/lib/hammer_cli/options/option_definition.rb +22 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +1 -5
- data/lib/hammer_cli/output/adapter/base.rb +1 -1
- data/lib/hammer_cli/output/adapter/csv.rb +3 -2
- data/lib/hammer_cli/output/adapter/json.rb +14 -3
- data/lib/hammer_cli/output/adapter/silent.rb +1 -1
- data/lib/hammer_cli/output/adapter/table.rb +26 -7
- data/lib/hammer_cli/output/adapter/yaml.rb +6 -3
- data/lib/hammer_cli/output/output.rb +2 -4
- data/lib/hammer_cli/settings.rb +2 -1
- data/lib/hammer_cli/utils.rb +5 -0
- data/lib/hammer_cli/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
- data/man/hammer.1.gz +0 -0
- data/test/unit/apipie/api_connection_test.rb +1 -0
- data/test/unit/bash_test.rb +138 -0
- data/test/unit/exception_handler_test.rb +44 -0
- data/test/unit/output/adapter/base_test.rb +58 -0
- data/test/unit/output/adapter/csv_test.rb +63 -1
- data/test/unit/output/adapter/json_test.rb +61 -0
- data/test/unit/output/adapter/table_test.rb +70 -1
- data/test/unit/output/adapter/yaml_test.rb +59 -0
- data/test/unit/output/output_test.rb +3 -3
- metadata +75 -68
- data/hammer_cli_complete +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1beb690641cf038528a35bee7964c73e60acbe8a70e94bb9d1a72af372218ea1
|
4
|
+
data.tar.gz: 516fd63e88f8df2996aefd0d3276a9ff56e1bf5f17c1a7a8b656210512f2896c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b35646b4dc9c494687b7bbd38c578ce5cf70e90080025f622b89a28f1c1d29abeafc11dbe1e16cb0786fe8ae3ac4c8673b905e8bf03cf87de86383817c653a6
|
7
|
+
data.tar.gz: 3a01e546cf71e7f015ec27d8c127328e380c3736106bc01b95d1b81593f2c7fa0a027e90a95bbf179407a953da871911e8dd0349c0ed980ed5cad613bd98363b
|
data/bin/hammer-complete
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
@project_root = File.expand_path('../..', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(File.join(@project_root, 'lib'))
|
6
|
+
HAMMER = ENV['HAMMER'] || File.join(@project_root, 'bin/hammer')
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
completion_cache_file = ENV['HAMMER_COMPLETION_CACHE'] || '~/.cache/hammer_completion.yml'
|
11
|
+
completion_cache_file = File.expand_path(completion_cache_file)
|
12
|
+
|
13
|
+
# build the cache if it does not exist
|
14
|
+
unless File.exist?(completion_cache_file)
|
15
|
+
require 'hammer_cli'
|
16
|
+
`#{HAMMER} prebuild-bash-completion`
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'hammer_cli/bash/completion'
|
20
|
+
|
21
|
+
dict = HammerCLI::Bash::Completion.load_description(completion_cache_file)
|
22
|
+
|
23
|
+
comp_line = ENV['COMP_LINE'] || ''
|
24
|
+
comp_args = comp_line.split(' ', 2).last || ''
|
25
|
+
|
26
|
+
result = HammerCLI::Bash::Completion.new(dict).complete(comp_args)
|
27
|
+
|
28
|
+
puts result.join("\n")
|
data/doc/creating_commands.md
CHANGED
@@ -494,6 +494,33 @@ You first create an _output definition_ that you apply to your data. The result
|
|
494
494
|
is a collection of fields, each having its type. The collection is then passed to an
|
495
495
|
_output adapter_ which handles the actual formatting and printing.
|
496
496
|
|
497
|
+
Adapters support printing by chunks, e.g. if you want to print a large set of
|
498
|
+
data (1000+ records), but you make several calls to the server instead of one,
|
499
|
+
you may want to print received data right away instead of waiting for the rest.
|
500
|
+
This can be achieved via `:current_chunk` option for
|
501
|
+
`print_collection` and `print_data` methods. Allowed values for `:current_chunk`
|
502
|
+
are `:first`, `:another`, `:last`. By default adapters use `:single` value that
|
503
|
+
means only one record will be printed.
|
504
|
+
|
505
|
+
##### Printing by chunks
|
506
|
+
```ruby
|
507
|
+
# ...
|
508
|
+
def execute
|
509
|
+
loop do
|
510
|
+
# ...
|
511
|
+
data = send_request
|
512
|
+
print_data(data, current_chunk: :first)
|
513
|
+
# ...
|
514
|
+
data = send_request
|
515
|
+
print_data(data, current_chunk: :another)
|
516
|
+
# ...
|
517
|
+
data = send_request
|
518
|
+
print_data(data, current_chunk: :last)
|
519
|
+
end
|
520
|
+
end
|
521
|
+
# ...
|
522
|
+
```
|
523
|
+
|
497
524
|
Hammer provides a DSL for defining the output. Next rather complex example will
|
498
525
|
explain how to use it in action.
|
499
526
|
|
data/doc/installation.md
CHANGED
@@ -132,8 +132,51 @@ And you are done. Your hammer client is configured and ready to use.
|
|
132
132
|
Autocompletion
|
133
133
|
--------------
|
134
134
|
|
135
|
-
|
136
|
-
|
137
|
-
|
135
|
+
The completion offers suggestion of possible command-line subcommands and their
|
136
|
+
options as usual. It can also suggest values for options and params where file
|
137
|
+
or directory path is expected.
|
138
|
+
|
139
|
+
Bash completion is automatically installed by RPM. To use it for development
|
140
|
+
setup `cp ./config/hammer.completion /etc/bash_completion.d/hammer` and load it
|
141
|
+
to the current shell `source /etc/bash_completion.d/hammer`. Make sure
|
142
|
+
the `$PWD/bin` is in `PATH` or there is full path to `hammer-complete`
|
143
|
+
executable specified in `/etc/bash_completion.d/hammer`.
|
144
|
+
|
145
|
+
Bash completion for hammer needs pre-built cache that holds description of
|
146
|
+
all subcommands and its parameters. The cache is located by default in
|
147
|
+
`~/.cache/hammer_completion.yml`. The location can be changed in hammer's
|
148
|
+
config file. The cache can be built manually with
|
149
|
+
`hammer prebuild-bash-completion` or is built automatically when completion is
|
150
|
+
used and the cache is missing (this may cause slight delay). The cache expires
|
151
|
+
if your API cache was changed (it indicates that the features on the instance
|
152
|
+
may have changed which has impact on hammer CLI options and subcommands).
|
153
|
+
|
154
|
+
#### Available value types
|
155
|
+
|
156
|
+
Completion of values is dependent on CLI option and prameter settings, e.g.:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
option '--value', 'VALUE', 'One of a, b, c', completion: { type: :enum, values: %w[a b c] }
|
160
|
+
```
|
138
161
|
|
139
|
-
|
162
|
+
Possible options for the `:completion` attribute are:
|
163
|
+
- `{ type: :flag }` option has no value, default for flags.
|
164
|
+
- `{ type: :value }` option has value of unknown type, no suggestions for the
|
165
|
+
value, default.
|
166
|
+
- `{ type: :list }` option has value of list type, no suggestions for the
|
167
|
+
value.
|
168
|
+
- `{ type: :key_value_list }` option has value of key=value list type, no
|
169
|
+
suggestions for the value.
|
170
|
+
- `{ type: :directory }` value is directory, suggestions follow directory
|
171
|
+
structure.
|
172
|
+
- `{ type: :file, filter: '\.txt$' }` value is file, suggestions follow
|
173
|
+
directory structure, optional `:filter` is regexp to filter the results.
|
174
|
+
- `{ type: :enum, values: ['first', 'second']}` option can have one of the
|
175
|
+
listed values, suggestions follow specified `values`.
|
176
|
+
- `{ type: :multienum, values: ['first', 'second']}` option can have one or
|
177
|
+
more of the listed values, suggestions follow specified `values`.
|
178
|
+
- `{ type: :schema, schema: 'a=int\,b=string' }` option should have value
|
179
|
+
according to specified schema, suggestion is the specified schema.
|
180
|
+
|
181
|
+
All those completion attributes are generated automatically, specify you own to
|
182
|
+
override.
|
data/doc/release_notes.md
CHANGED
@@ -1,18 +1,26 @@
|
|
1
1
|
Release notes
|
2
2
|
=============
|
3
|
-
### 0.
|
4
|
-
*
|
5
|
-
|
6
|
-
|
3
|
+
### 2.0.0 (2020-02-12)
|
4
|
+
* Bump version to 2.0.0
|
5
|
+
* Bump version to 2.0 ([PR #324](https://github.com/theforeman/hammer-cli/pull/324))
|
6
|
+
* Better promts for missing arguments, [#28793](http://projects.theforeman.org/issues/28793)
|
7
7
|
* Allow column max width more than 80, [#28503](http://projects.theforeman.org/issues/28503)
|
8
|
+
* Remove computing sha, [#27728](http://projects.theforeman.org/issues/27728)
|
9
|
+
* Fixed userdata false display in image list, [#28134](http://projects.theforeman.org/issues/28134)
|
10
|
+
* Add new bash completion, [#27728](http://projects.theforeman.org/issues/27728)
|
11
|
+
* Allow adapters print page by page, [#17819](http://projects.theforeman.org/issues/17819)
|
12
|
+
* Add release documentation ([PR #317](https://github.com/theforeman/hammer-cli/pull/317)), [#28149](http://projects.theforeman.org/issues/28149)
|
13
|
+
* Fix pr links in release notes ([PR #318](https://github.com/theforeman/hammer-cli/pull/318)), [#28202](http://projects.theforeman.org/issues/28202)
|
8
14
|
* Extract table generator into reusable component ([PR #314](https://github.com/theforeman/hammer-cli/pull/314)), [#27318](http://projects.theforeman.org/issues/27318)
|
15
|
+
* Better prompts for missing arguments ([PR #313](https://github.com/theforeman/hammer-cli/pull/313)), [#27595](http://projects.theforeman.org/issues/27595)
|
16
|
+
* Bump to 0.20-develop
|
9
17
|
|
10
18
|
### 0.19.0 (2019-10-26)
|
11
|
-
* Allow schema building for custom options ([PR #316](https://github.com/
|
12
|
-
* New lines in text attr dont break output ([PR #300](https://github.com/
|
13
|
-
* Added error to wrong --output ([PR #315](https://github.com/
|
14
|
-
* Pr review checklist ([PR #305](https://github.com/
|
15
|
-
* List items in help with customization ([PR #309](https://github.com/
|
19
|
+
* Allow schema building for custom options ([PR #316](https://github.com/theforeman/hammer-cli/pull/316)), [#27899](http://projects.theforeman.org/issues/27899)
|
20
|
+
* New lines in text attr dont break output ([PR #300](https://github.com/theforeman/hammer-cli/pull/300)), [#25878](http://projects.theforeman.org/issues/25878)
|
21
|
+
* Added error to wrong --output ([PR #315](https://github.com/theforeman/hammer-cli/pull/315)), [#21590](http://projects.theforeman.org/issues/21590)
|
22
|
+
* Pr review checklist ([PR #305](https://github.com/theforeman/hammer-cli/pull/305)), [#26950](http://projects.theforeman.org/issues/26950)
|
23
|
+
* List items in help with customization ([PR #309](https://github.com/theforeman/hammer-cli/pull/309)), [#27237](http://projects.theforeman.org/issues/27237)
|
16
24
|
|
17
25
|
### 0.18.0 (2019-08-01)
|
18
26
|
* Unsure minimal label length ([PR #310](https://github.com/theforeman/hammer-cli/pull/310)) ([#26960](http://projects.theforeman.org/issues/26960))
|
data/lib/hammer_cli.rb
CHANGED
data/lib/hammer_cli/abstract.rb
CHANGED
@@ -74,6 +74,7 @@ module HammerCLI
|
|
74
74
|
begin
|
75
75
|
begin
|
76
76
|
exit_code = super
|
77
|
+
context.delete(:fields)
|
77
78
|
raise "exit code must be integer" unless exit_code.is_a? Integer
|
78
79
|
rescue => e
|
79
80
|
exit_code = handle_exception(e)
|
@@ -194,6 +195,7 @@ module HammerCLI
|
|
194
195
|
block ||= option.default_conversion_block
|
195
196
|
define_accessors_for(option, &block)
|
196
197
|
extend_options_help(option) if option.value_formatter.is_a?(HammerCLI::Options::Normalizers::ListNested)
|
198
|
+
completion_type_for(option)
|
197
199
|
end
|
198
200
|
end
|
199
201
|
|
@@ -242,8 +244,8 @@ module HammerCLI
|
|
242
244
|
output.print_record(definition, record)
|
243
245
|
end
|
244
246
|
|
245
|
-
def print_collection(definition, collection)
|
246
|
-
output.print_collection(definition, collection)
|
247
|
+
def print_collection(definition, collection, options = {})
|
248
|
+
output.print_collection(definition, collection, options)
|
247
249
|
end
|
248
250
|
|
249
251
|
def print_message(msg, msg_params = {}, options = {})
|
@@ -314,6 +316,7 @@ module HammerCLI
|
|
314
316
|
declared_options << option
|
315
317
|
block ||= option.default_conversion_block
|
316
318
|
define_accessors_for(option, &block)
|
319
|
+
completion_type_for(option, opts)
|
317
320
|
end
|
318
321
|
extend_options_help(option) if option.value_formatter.is_a?(HammerCLI::Options::Normalizers::ListNested)
|
319
322
|
option
|
@@ -352,6 +355,33 @@ module HammerCLI
|
|
352
355
|
sources
|
353
356
|
end
|
354
357
|
|
358
|
+
def self.completion_map
|
359
|
+
completion = {}
|
360
|
+
# collect options
|
361
|
+
recognised_options.each do |opt|
|
362
|
+
opt.switches.each do |switch|
|
363
|
+
completion[switch] = completion_types.fetch(switch, {})
|
364
|
+
end
|
365
|
+
end
|
366
|
+
# collect subcommands recursively
|
367
|
+
recognised_subcommands.each do |cmd|
|
368
|
+
completion[cmd.names.first] = cmd.subcommand_class.completion_map
|
369
|
+
end
|
370
|
+
# collect params
|
371
|
+
completion[:params] = completion_types[:params] unless completion_types[:params].empty?
|
372
|
+
completion
|
373
|
+
end
|
374
|
+
|
375
|
+
def self.completion_types
|
376
|
+
@completion_types ||= { :params => [] }
|
377
|
+
end
|
378
|
+
|
379
|
+
def self.completion_type_for(option, opts = {})
|
380
|
+
completion_type = opts.delete(:completion)
|
381
|
+
completion_type ||= option.completion_type(opts[:format])
|
382
|
+
[option.switches].flatten(1).each { |s| completion_types[s] = completion_type }
|
383
|
+
end
|
384
|
+
|
355
385
|
private
|
356
386
|
|
357
387
|
def self.inherited_output_definition
|
@@ -10,7 +10,11 @@ module HammerCLI::Apipie
|
|
10
10
|
@api = ApipieBindings::API.new(params, HammerCLI::SSLOptions.new.get_options(params[:uri]))
|
11
11
|
if options[:reload_cache]
|
12
12
|
@api.clean_cache
|
13
|
-
|
13
|
+
HammerCLI.clear_cache
|
14
|
+
unless @logger.nil?
|
15
|
+
@logger.debug 'Apipie cache was cleared'
|
16
|
+
@logger.debug 'Completion cache was cleared'
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
@@ -65,8 +65,8 @@ module HammerCLI::Apipie
|
|
65
65
|
method_options(options)
|
66
66
|
end
|
67
67
|
|
68
|
-
def print_data(data)
|
69
|
-
print_collection(output_definition, data) unless output_definition.empty?
|
68
|
+
def print_data(data, options = {})
|
69
|
+
print_collection(output_definition, data, options) unless output_definition.empty?
|
70
70
|
print_success_message(data) unless success_message.nil?
|
71
71
|
end
|
72
72
|
|
@@ -86,6 +86,7 @@ module HammerCLI::Apipie
|
|
86
86
|
declared_options << option
|
87
87
|
block ||= option.default_conversion_block
|
88
88
|
define_accessors_for(option, &block)
|
89
|
+
completion_type_for(option, opts)
|
89
90
|
end
|
90
91
|
extend_options_help(option) if option.value_formatter.is_a?(HammerCLI::Options::Normalizers::ListNested)
|
91
92
|
option
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module HammerCLI
|
4
|
+
module Bash
|
5
|
+
class Completion
|
6
|
+
def initialize(dict)
|
7
|
+
@dict = dict
|
8
|
+
end
|
9
|
+
|
10
|
+
def complete(line)
|
11
|
+
@complete_line = line.end_with?(' ')
|
12
|
+
full_path = line.split(' ')
|
13
|
+
complete_path = @complete_line ? full_path : full_path[0..-2]
|
14
|
+
dict, path = traverse_tree(@dict, complete_path)
|
15
|
+
|
16
|
+
return [] unless path.empty? # lost during traversing
|
17
|
+
|
18
|
+
partial = @complete_line ? '' : full_path.last
|
19
|
+
finish_word(dict, partial)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.load_description(path)
|
23
|
+
JSON.load(File.open(path))
|
24
|
+
rescue Errno::ENOENT
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def finish_word(dict, incomplete)
|
31
|
+
finish_option_value(dict, incomplete) ||
|
32
|
+
(finish_option_or_subcommand(dict, incomplete) + finish_param(dict, incomplete))
|
33
|
+
end
|
34
|
+
|
35
|
+
def finish_option_or_subcommand(dict, incomplete)
|
36
|
+
dict.keys.select { |k| k.is_a?(String) && k =~ /^#{incomplete}/ }.map { |k| k + ' ' }
|
37
|
+
end
|
38
|
+
|
39
|
+
def complete_value(value_description, partial, is_param)
|
40
|
+
case value_description['type']
|
41
|
+
when 'value'
|
42
|
+
if !partial.empty?
|
43
|
+
[]
|
44
|
+
elsif is_param
|
45
|
+
['--->', 'Add parameter']
|
46
|
+
else
|
47
|
+
['--->', 'Add option <value>']
|
48
|
+
end
|
49
|
+
when 'directory'
|
50
|
+
directories(partial)
|
51
|
+
when 'file'
|
52
|
+
files(partial, value_description)
|
53
|
+
when 'enum'
|
54
|
+
enum(partial, value_description['values'])
|
55
|
+
when 'multienum'
|
56
|
+
multienum(partial, value_description['values'])
|
57
|
+
when 'schema'
|
58
|
+
schema(value_description['schema'])
|
59
|
+
when 'list'
|
60
|
+
['--->', 'Add comma-separated list of values']
|
61
|
+
when 'key_value_list'
|
62
|
+
['--->', 'Add comma-separated list of key=value']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def finish_param(dict, incomplete)
|
67
|
+
if dict['params'] && !dict['params'].empty?
|
68
|
+
complete_value(dict['params'].first, incomplete, true)
|
69
|
+
else
|
70
|
+
[]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def finish_option_value(dict, incomplete)
|
75
|
+
complete_value(dict, incomplete, false) if dict.key?('type')
|
76
|
+
end
|
77
|
+
|
78
|
+
def traverse_tree(dict, path)
|
79
|
+
return [dict, []] if path.nil? || path.empty?
|
80
|
+
result = if dict.key?(path.first)
|
81
|
+
if path.first.start_with?('-')
|
82
|
+
parse_option(dict, path)
|
83
|
+
else
|
84
|
+
parse_subcommand(dict, path)
|
85
|
+
end
|
86
|
+
elsif dict['params']
|
87
|
+
# traverse params one by one
|
88
|
+
parse_params(dict, path)
|
89
|
+
else
|
90
|
+
# not found
|
91
|
+
[{}, path]
|
92
|
+
end
|
93
|
+
result
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_params(dict, path)
|
97
|
+
traverse_tree({ 'params' => dict['params'][1..-1] }, path[1..-1])
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse_subcommand(dict, path)
|
101
|
+
traverse_tree(dict[path.first], path[1..-1])
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_option(dict, path)
|
105
|
+
if dict[path.first]['type'] == 'flag' # flag
|
106
|
+
traverse_tree(dict, path[1..-1])
|
107
|
+
elsif path.length >= 2 # option with value
|
108
|
+
traverse_tree(dict, path[2..-1])
|
109
|
+
else # option with value missing
|
110
|
+
[dict[path.first], path[1..-1]]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def directories(partial = '')
|
115
|
+
dirs = []
|
116
|
+
dirs += Dir.glob("#{partial}*").select { |f| File.directory?(f) }
|
117
|
+
dirs = dirs.map { |d| d + '/' } if dirs.length == 1
|
118
|
+
dirs
|
119
|
+
end
|
120
|
+
|
121
|
+
def files(partial = '', opts = {})
|
122
|
+
filter = opts.fetch('filter', '.*')
|
123
|
+
file_names = []
|
124
|
+
file_names += Dir.glob("#{partial}*").select do |f|
|
125
|
+
File.directory?(f) || f =~ /#{filter}/
|
126
|
+
end
|
127
|
+
file_names.map { |f| File.directory?(f) ? f + '/' : f + ' ' }
|
128
|
+
end
|
129
|
+
|
130
|
+
def enum(partial = '', values = [])
|
131
|
+
values.select { |v| v.start_with?(partial) }.map { |v| v + ' ' }
|
132
|
+
end
|
133
|
+
|
134
|
+
def multienum(partial = '', values = [])
|
135
|
+
return values if partial.empty?
|
136
|
+
|
137
|
+
parts = partial.split(',')
|
138
|
+
resolved = []
|
139
|
+
to_complete = parts.each_with_object([]) do |part, res|
|
140
|
+
next resolved << part if values.include?(part)
|
141
|
+
|
142
|
+
res << part
|
143
|
+
end
|
144
|
+
|
145
|
+
hints = to_complete.map do |p|
|
146
|
+
values.select { |v| v.start_with?(p) }
|
147
|
+
end.flatten(1).uniq
|
148
|
+
return values - parts if hints.empty?
|
149
|
+
return [(resolved + hints).join(',')] if hints.size == 1
|
150
|
+
|
151
|
+
hints
|
152
|
+
end
|
153
|
+
|
154
|
+
def schema(template = '')
|
155
|
+
['--->', "Add value by following schema: #{template}"]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|