completely 0.3.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f19143967a28107018c600c7f302bfccd2cf34d70a88be661f68e340e515c07
4
- data.tar.gz: 6037bb0f6944627f97abf37c51f76d1db213b42402db092fa6c36fb257892c22
3
+ metadata.gz: cb9fe8791d64ddc71e8ee082ce9fc9cf028376f61c71bf354b758f38ecfded86
4
+ data.tar.gz: 9fa6a5ced31c2fafdebfbd0172f939cccd9aa95b48eedd5ca528ab5a3b03eee2
5
5
  SHA512:
6
- metadata.gz: c46ac169ab59595c67d3d8a8c320ea7fb56e78715fbc2dd55e4e20534c8543c66f0b62dda01a6802bbaf9f071a5ebd7ffa55a17c70443e05bba8ab8c3bedce71
7
- data.tar.gz: ac9a7a7934e115957271ec1e5cc736c0df29368f18da6f9eb409069f9690cb2594d6b9bdbf6d4fd18388ce79f7285e66a357d4bb241083ca083fd57102c95746
6
+ metadata.gz: ea9dcf451393c1b242bebcf0766a2d56e847005da451557aa601893536fdb7a2773bd1abbeb6a3b510abae3ffa87258fd6bbc45641405a991690c2bd0441a623
7
+ data.tar.gz: 77ee32ac693f7cdee5953e173974e84ddee4380b0298b3caf3a68a79208bae2ab6f856ae0e8f49b9c15d152b171ad7ad5186837e56cfcbc69b5abe4bd82a6873
data/README.md CHANGED
@@ -27,6 +27,13 @@ then this functionality is already integrated with it.
27
27
  $ gem install completely
28
28
  ```
29
29
 
30
+ or with homebrew:
31
+
32
+ ```bash
33
+ $ brew install brew-gem
34
+ $ brew gem install completely
35
+ ````
36
+
30
37
  ## Using the `completely` command line
31
38
 
32
39
  The `completely` command line works with a simple YAML configuration file as
@@ -47,7 +54,7 @@ for the auto complete process.
47
54
  You can save a sample YAML file by running:
48
55
 
49
56
  ```
50
- $ completely new
57
+ $ completely init
51
58
  ```
52
59
 
53
60
  This will generate a file named `completely.yaml` with this content:
@@ -159,6 +166,37 @@ mygit:
159
166
  The `2> /dev/null` is used so that if the command is executed in a directory
160
167
  without a git repository, it will still behave as expected.
161
168
 
169
+ ### Suggesting flag arguments
170
+
171
+ Adding a `*` wildcard in the middle of a pattern can be useful for suggesting
172
+ arguments for flags. For example:
173
+
174
+ ```yaml
175
+ mygit checkout:
176
+ - --branch
177
+ - -b
178
+
179
+ mygit checkout*--branch:
180
+ - $(git branch 2> /dev/null)
181
+
182
+ mygit checkout*-b:
183
+ - $(git branch 2> /dev/null)
184
+ ```
185
+
186
+ The above will suggest git branches for commands that end with `-b` or `--branch`.
187
+ To avoid code duplication, you may use YAML aliases, so the above can also be
188
+ written like this:
189
+
190
+ ```yaml
191
+ mygit checkout:
192
+ - --branch
193
+ - -b
194
+
195
+ mygit checkout*--branch: &branches
196
+ - $(git branch 2> /dev/null)
197
+
198
+ mygit checkout*-b: *branches
199
+ ```
162
200
 
163
201
  ## Using the generated completion scripts
164
202
 
@@ -168,8 +206,23 @@ In order to enable the completions, simply source the generated script:
168
206
  $ source completely.bash
169
207
  ```
170
208
 
171
- You may wish to add this to your `~/.bashrc` file to enable this for future
172
- sessions (just be sure to use absolute path).
209
+ In order to load these completions on startup, you may want to place them in
210
+ the completions directory of your operating system, which can be either of
211
+ these (whichever exists):
212
+
213
+ - `/usr/share/bash-completion/completions`
214
+ - `/usr/local/etc/bash_completion.d`
215
+
216
+ ## Testing and debugging completion scripts
217
+
218
+ You can use the built in completions script tester by running `completely test`.
219
+
220
+ This command lets you test completions for your completions script.
221
+
222
+ In addition, you can set the `COMPLETELY_DEBUG` environment variable to any value
223
+ in order to generate scripts with some additional debugging functionality. Run
224
+ `completely generate --help` for additional information.
225
+
173
226
 
174
227
  ## Using from within Ruby code
175
228
 
@@ -192,6 +245,9 @@ puts completions.script
192
245
  # Or, generate a function that echos the script
193
246
  puts completions.wrapper_function
194
247
  puts completions.wrapper_function "custom_function_name"
248
+
249
+ # Or, test the completions with the Tester object
250
+ p completions.tester.test "mygit status "
195
251
  ```
196
252
 
197
253
 
@@ -1,11 +1,23 @@
1
1
  require 'mister_bin'
2
+ require 'completely/commands/init'
3
+ require 'completely/commands/preview'
4
+ require 'completely/commands/generate'
5
+ require 'completely/commands/test'
2
6
  require 'completely/version'
3
- require 'completely/command'
4
7
 
5
8
  module Completely
6
9
  class CLI
7
10
  def self.runner
8
- MisterBin::Runner.new handler: Command
11
+ runner = MisterBin::Runner.new version: Completely::VERSION,
12
+ header: "Completely - Bash Completions Generator",
13
+ footer: "Run !txtpur!completely COMMAND --help!txtrst! for more information"
14
+
15
+ runner.route 'init', to: Commands::Init
16
+ runner.route 'preview', to: Commands::Preview
17
+ runner.route 'generate', to: Commands::Generate
18
+ runner.route 'test', to: Commands::Test
19
+
20
+ runner
9
21
  end
10
22
  end
11
23
  end
@@ -0,0 +1,53 @@
1
+ require 'mister_bin'
2
+
3
+ module Completely
4
+ module Commands
5
+ class Base < MisterBin::Command
6
+
7
+ class << self
8
+ def param_config_path
9
+ param "CONFIG_PATH", "Path to the YAML configuration file [default: completely.yaml]\nCan also be set by an environment variable"
10
+ end
11
+
12
+ def option_function
13
+ option "-f --function NAME", "Modify the name of the function in the generated script"
14
+ end
15
+
16
+ def environment_config_path
17
+ environment "COMPLETELY_CONFIG_PATH", "Path to a completely configuration file [default: completely.yaml]"
18
+ end
19
+
20
+ def environment_debug
21
+ environment "COMPLETELY_DEBUG", "It not empty, the generated script will include an additional debugging snippet that outputs the compline and current word to a text file when a completion is requested"
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def script
28
+ @script ||= completions.script
29
+ end
30
+
31
+ def completions
32
+ @completions ||= Completions.load(config_path, function_name: args['--function'])
33
+ end
34
+
35
+ def config_path
36
+ @config_path ||= args['CONFIG_PATH'] || ENV['COMPLETELY_CONFIG_PATH'] || 'completely.yaml'
37
+ end
38
+
39
+ def output_path
40
+ @output_path ||= args['OUTPUT_PATH'] || ENV['COMPLETELY_OUTPUT_PATH'] || "#{config_basename}.bash"
41
+ end
42
+
43
+ def config_basename
44
+ File.basename config_path, File.extname(config_path)
45
+ end
46
+
47
+ def syntax_warning
48
+ say! "\n!txtred!WARNING:\nYour configuration is invalid."
49
+ say! "!txtred!All patterns must start with the same word."
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ require 'completely/commands/base'
2
+
3
+ module Completely
4
+ module Commands
5
+ class Generate < Base
6
+ help "Generate the bash completion script to a file"
7
+
8
+ usage "completely generate [CONFIG_PATH OUTPUT_PATH --function NAME --wrap NAME]"
9
+ usage "completely generate (-h|--help)"
10
+
11
+ option_function
12
+ option "-w --wrap NAME", "Wrap the completion script inside a function that echos the script. This is useful if you wish to embed it directly in your script"
13
+
14
+ param_config_path
15
+ param "OUTPUT_PATH", "Path to the output bash script. When not provided, the name of the input file will be used with a .bash extension\nCan also be set by an environment variable"
16
+
17
+ environment_config_path
18
+ environment "COMPLETELY_OUTPUT_PATH", "Path to the output bash script"
19
+ environment_debug
20
+
21
+ def run
22
+ wrap = args['--wrap']
23
+ output = wrap ? wrapper_function(wrap) : script
24
+ File.write output_path, output
25
+ say "Saved !txtpur!#{output_path}"
26
+ syntax_warning unless completions.valid?
27
+ end
28
+
29
+ private
30
+
31
+ def wrapper_function(wrapper_name)
32
+ completions.wrapper_function wrapper_name
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ require 'completely/commands/base'
2
+
3
+ module Completely
4
+ module Commands
5
+ class Init < Base
6
+ help "Create a new sample YAML configuration file"
7
+
8
+ usage "completely init [CONFIG_PATH]"
9
+ usage "completely init (-h|--help)"
10
+
11
+ param_config_path
12
+ environment_config_path
13
+
14
+ def run
15
+ if File.exist? config_path
16
+ raise "File already exists: #{config_path}"
17
+ else
18
+ File.write config_path, sample
19
+ say "Saved !txtpur!#{config_path}"
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def sample
26
+ @sample ||= File.read sample_path
27
+ end
28
+
29
+ def sample_path
30
+ @sample_path ||= File.expand_path "../templates/sample.yaml", __dir__
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ require 'completely/commands/base'
2
+
3
+ module Completely
4
+ module Commands
5
+ class Preview < Base
6
+ help "Generate the bash completion script to STDOUT"
7
+
8
+ usage "completely preview [CONFIG_PATH --function NAME]"
9
+ usage "completely preview (-h|--help)"
10
+
11
+ option_function
12
+ param_config_path
13
+ environment_config_path
14
+ environment_debug
15
+
16
+ def run
17
+ puts script
18
+ syntax_warning unless completions.valid?
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,51 @@
1
+ require 'completely/commands/base'
2
+
3
+ module Completely
4
+ module Commands
5
+ class Test < Base
6
+ summary "Test completions"
7
+
8
+ help "This command can be used to test that your completions script responds with the right completions. It works by reading your completely.yaml file, generating a completions script, and generating a temporary testing script."
9
+
10
+ usage "completely test [--keep] COMPLINE"
11
+ usage "completely test (-h|--help)"
12
+
13
+ option "-k --keep", "Keep the temporary testing script in the current directory"
14
+
15
+ param "COMPLINE", "The command to test completions for. This will be handled as if a TAB was pressed immediately at the end of it, so the last word is considered the active cursor. If you wish to complete for the next word instead, end your command with a space."
16
+
17
+ environment_config_path
18
+ environment_debug
19
+
20
+ example %q[completely test "mygit pu"]
21
+ example %q[completely test "mygit pull "]
22
+
23
+ def run
24
+ puts tester.test(compline).join "\n"
25
+ if args['--keep']
26
+ File.write 'completely-tester.sh', tester_script
27
+ puts 'saved completely-tester.sh'
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def compline
34
+ args['COMPLINE']
35
+ end
36
+
37
+ def completions
38
+ @completions ||= Completions.load config_path
39
+ end
40
+
41
+ def tester
42
+ @tester ||= completions.tester
43
+ end
44
+
45
+ def tester_script
46
+ @tester_script ||= tester.tester_script compline
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -10,7 +10,9 @@ module Completely
10
10
  begin
11
11
  data = YAML.load_file config_path, aliases: true
12
12
  rescue ArgumentError
13
+ # :nocov:
13
14
  data = YAML.load_file config_path
15
+ # :nocov:
14
16
  end
15
17
 
16
18
  new data, function_name: function_name
@@ -44,6 +46,10 @@ module Completely
44
46
  "#{name}() {\n#{script_lines}\n}"
45
47
  end
46
48
 
49
+ def tester
50
+ @tester ||= Tester.new script: script, function_name: function_name
51
+ end
52
+
47
53
  private
48
54
 
49
55
  def patterns!
@@ -53,7 +59,7 @@ module Completely
53
59
  end
54
60
 
55
61
  def template_path
56
- @template_path ||= File.expand_path("template.erb", __dir__)
62
+ @template_path ||= File.expand_path("templates/template.erb", __dir__)
57
63
  end
58
64
 
59
65
  def template
@@ -30,8 +30,18 @@ module Completely
30
30
  text.split(' ')[0]
31
31
  end
32
32
 
33
+ def case_string
34
+ if text_without_prefix.empty?
35
+ "*"
36
+ elsif text_without_prefix.include? "*"
37
+ %Q['#{text_without_prefix.gsub "*", "'*'"}']
38
+ else
39
+ %Q['#{text_without_prefix}'*]
40
+ end
41
+ end
42
+
33
43
  def text_without_prefix
34
- text.split(' ')[1..-1].join ' '
44
+ @text_without_prefix ||= text.split(' ')[1..-1].join ' '
35
45
  end
36
46
 
37
47
  def compgen
@@ -0,0 +1,30 @@
1
+ # <%= "#{command} completion".ljust 56 %> -*- shell-script -*-
2
+
3
+ # This bash completions script was generated by
4
+ # completely (https://github.com/dannyben/completely)
5
+ # Modifying it manually is not recommended
6
+
7
+ <%= function_name %>() {
8
+ local cur=${COMP_WORDS[COMP_CWORD]}
9
+ local compline="${COMP_WORDS[@]:1:$COMP_CWORD-1}"
10
+
11
+ % if ENV['COMPLETELY_DEBUG']
12
+ if [[ -n "$COMPLETELY_DEBUG" ]]; then
13
+ echo "compline: '$compline'" > 'completely-debug.txt'
14
+ echo "cur: '$cur'" >> 'completely-debug.txt'
15
+ fi
16
+
17
+ %end
18
+ case "$compline" in
19
+ % patterns.each do |pattern|
20
+ % next if pattern.empty?
21
+ <%= pattern.case_string %>)
22
+ COMPREPLY=($(compgen <%= pattern.compgen %> -- "$cur"))
23
+ ;;
24
+
25
+ % end
26
+ esac
27
+ } &&
28
+ complete -F <%= function_name %> <%= command %>
29
+
30
+ # ex: filetype=sh
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+ if [[ -n $ZSH_VERSION ]]; then
3
+ autoload -U +X bashcompinit && bashcompinit
4
+ autoload -U +X compinit && compinit
5
+ fi
6
+
7
+ # === COMPLETION SCRIPT START ===
8
+
9
+ <%= script || %Q[source "#{absolute_script_path}"] %>
10
+
11
+ # === COMPLETION SCRIPT END ===
12
+
13
+ COMP_WORDS=( <%= compline %> )
14
+ COMP_LINE="<%= compline %>"
15
+ COMP_POINT=${#COMP_LINE}
16
+ COMP_CWORD=<%= cword %>
17
+
18
+ <%= function_name %>
19
+ echo "${COMPREPLY[*]}"
@@ -0,0 +1,48 @@
1
+ require 'erb'
2
+ require 'tempfile'
3
+
4
+ module Completely
5
+ class Tester
6
+ attr_reader :script, :script_path, :function_name, :cword, :compline
7
+
8
+ def initialize(script: nil, script_path: nil, function_name: )
9
+ @script, @script_path, @function_name = script, script_path, function_name
10
+ end
11
+
12
+ def test(compline)
13
+ Tempfile.create "completely-tester" do |f|
14
+ f << tester_script(compline)
15
+ f.flush
16
+ `bash #{f.path}`
17
+ end.split " "
18
+ end
19
+
20
+ def tester_script(compline)
21
+ set_compline_vars compline
22
+ ERB.new(template, trim_mode: '%-').result(binding)
23
+ end
24
+
25
+ protected
26
+
27
+ def set_compline_vars(compline)
28
+ @compline = compline
29
+ @cword = compline.split(' ').size - 1
30
+ @cword += 1 if compline.end_with? ' '
31
+ end
32
+
33
+ def absolute_script_path
34
+ @absolute_script_path ||= begin
35
+ script_path ? File.expand_path(script_path) : nil
36
+ end
37
+ end
38
+
39
+ def template_path
40
+ @template_path ||= File.expand_path "templates/tester-template.erb", __dir__
41
+ end
42
+
43
+ def template
44
+ @template ||= File.read template_path
45
+ end
46
+
47
+ end
48
+ end
@@ -1,3 +1,3 @@
1
1
  module Completely
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.2"
3
3
  end
data/lib/completely.rb CHANGED
@@ -5,3 +5,4 @@ end
5
5
 
6
6
  require 'completely/pattern'
7
7
  require 'completely/completions'
8
+ require 'completely/tester'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completely
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-20 00:00:00.000000000 Z
11
+ date: 2022-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -49,11 +49,17 @@ files:
49
49
  - bin/completely
50
50
  - lib/completely.rb
51
51
  - lib/completely/cli.rb
52
- - lib/completely/command.rb
52
+ - lib/completely/commands/base.rb
53
+ - lib/completely/commands/generate.rb
54
+ - lib/completely/commands/init.rb
55
+ - lib/completely/commands/preview.rb
56
+ - lib/completely/commands/test.rb
53
57
  - lib/completely/completions.rb
54
58
  - lib/completely/pattern.rb
55
- - lib/completely/sample.yaml
56
- - lib/completely/template.erb
59
+ - lib/completely/templates/sample.yaml
60
+ - lib/completely/templates/template.erb
61
+ - lib/completely/templates/tester-template.erb
62
+ - lib/completely/tester.rb
57
63
  - lib/completely/version.rb
58
64
  homepage: https://github.com/dannyben/completely
59
65
  licenses:
@@ -74,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
80
  - !ruby/object:Gem::Version
75
81
  version: '0'
76
82
  requirements: []
77
- rubygems_version: 3.2.15
83
+ rubygems_version: 3.3.3
78
84
  signing_key:
79
85
  specification_version: 4
80
86
  summary: Bash Completions Generator
@@ -1,87 +0,0 @@
1
- module Completely
2
- class Command < MisterBin::Command
3
- help "Bash completion script generator"
4
- version Completely::VERSION
5
-
6
- usage "completely new [CONFIG_PATH]"
7
- usage "completely preview [CONFIG_PATH --function NAME]"
8
- usage "completely generate [CONFIG_PATH OUTPUT_PATH --function NAME --wrap NAME]"
9
- usage "completely (-h|--help|--version)"
10
-
11
- command "new", "Create a new sample YAML configuration file"
12
- command "preview", "Generate the bash completion script to STDOUT"
13
- command "generate", "Generate the bash completion script to a file"
14
-
15
- option "-f --function NAME", "Modify the name of the function in the generated script"
16
- option "-w --wrap NAME", "Wrap the completion script inside a function that echos the script. This is useful if you wish to embed it directly in your script"
17
-
18
- param "CONFIG_PATH", "Path to the YAML configuration file"
19
- param "OUTPUT_PATH", "Path to the output bash script"
20
-
21
- example "completely new"
22
- example "completely new input.yaml"
23
- example "completely preview --function _my_completions"
24
- example "completely generate"
25
- example "completely generate input.yaml"
26
- example "completely generate input.yaml output.sh -f _my_completions"
27
- example "completely generate -w give_comps -f my_completions"
28
-
29
- def new_command
30
- if File.exist? config_path
31
- raise "File already exists: #{config_path}"
32
- else
33
- File.write config_path, sample
34
- say "Saved !txtpur!#{config_path}"
35
- end
36
- end
37
-
38
- def preview_command
39
- puts script
40
- syntax_warning unless completions.valid?
41
- end
42
-
43
- def generate_command
44
- wrap = args['--wrap']
45
- output = wrap ? wrapper_function(wrap) : script
46
- File.write output_path, output
47
- say "Saved !txtpur!#{output_path}"
48
- syntax_warning unless completions.valid?
49
- end
50
-
51
- private
52
-
53
- def config_path
54
- @config_path ||= args['CONFIG_PATH'] || "completely.yaml"
55
- end
56
-
57
- def output_path
58
- @output_path ||= args['OUTPUT_PATH'] || "completely.bash"
59
- end
60
-
61
- def sample
62
- @sample ||= File.read(sample_path)
63
- end
64
-
65
- def sample_path
66
- @sample_path ||= File.expand_path("sample.yaml", __dir__)
67
- end
68
-
69
- def script
70
- @script ||= completions.script
71
- end
72
-
73
- def wrapper_function(wrapper_name)
74
- completions.wrapper_function wrapper_name
75
- end
76
-
77
- def completions
78
- @completions ||= Completions.load(config_path, function_name: args['--function'])
79
- end
80
-
81
- def syntax_warning
82
- say! "\n!txtred!WARNING:\nYour configuration is invalid."
83
- say! "!txtred!All patterns must start with the same word."
84
- end
85
-
86
- end
87
- end
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # This bash completions script was generated by
4
- # completely (https://github.com/dannyben/completely)
5
- # Modifying it manually is not recommended
6
- <%= function_name %>() {
7
- local cur=${COMP_WORDS[COMP_CWORD]}
8
- local comp_line="${COMP_WORDS[@]:1}"
9
-
10
- case "$comp_line" in
11
- % patterns.each do |pattern|
12
- % next if pattern.empty?
13
- '<%= pattern.text_without_prefix %>'*) COMPREPLY=($(compgen <%= pattern.compgen %> -- "$cur")) ;;
14
- % end
15
- esac
16
- }
17
-
18
- complete -F <%= function_name %> <%= command %>