completely 0.1.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba5123d5b0bf95ed7ea2140188a6079e0510456a754d5fd93830df1382862274
4
- data.tar.gz: 0f98b90e1515d753b94817932916aad966b8b3f81ede79f1bbb40a898b82662e
3
+ metadata.gz: '0949e2f6df08b0582dc2efd748523bf63732f8c59a5ad41bd479e444568304d2'
4
+ data.tar.gz: fe1bf68cbec745eeed052c218f77e42040ae378c36fa99ad36e5d45c6c64a202
5
5
  SHA512:
6
- metadata.gz: e3618affd00e4a624b288ae7c37fd0d857fd9cf0672d6bcc8c558eb7870e2e3001e86a1c6997bc177def3b245bdc1142287539d99423dc175f6e208a9bf8a3b9
7
- data.tar.gz: a34bc567cbf492e437168afeb0a509f392eb1600a49622136d50728a936c024ad90e757d3a3ede18b0b7204302b09e08567054c73f75ea03fd3cdea9d39074e3
6
+ metadata.gz: a80c321109ac11ec6cc3be603d713e460fb838818c1fe2c56c2fdde9e903f1677fb0027a4dbfc1f0605123658181aa067b48f167c4061221bd85c754c0006f1b
7
+ data.tar.gz: a0d7283193046401a94971fcb7cd5f6e58b10087f6fe3b346f5a8d414c0f1252ef59cf9ee6f2ac338618652d54003e6cea9442948806a7b50832fa3c2bccc868
data/README.md CHANGED
@@ -13,7 +13,10 @@ This tool is for you if:
13
13
 
14
14
  1. You develop your own command line tools.
15
15
  2. Your life feels empty without bash completions.
16
- 3. Bash completion scripts scare you.
16
+ 3. Bash completion scripts seem overly complex to you.
17
+
18
+ Note that if you are building bash command line scripts with [bashly][bashly],
19
+ then this functionality is already integrated with it.
17
20
 
18
21
  ---
19
22
 
@@ -29,15 +32,18 @@ $ gem install completely
29
32
  The `completely` command line works with a simple YAML configuration file as
30
33
  input, and generates a bash completions script as output.
31
34
 
32
- The configuration file is built like this:
35
+ The configuration file is built of blocks that look like this:
33
36
 
34
37
  ```yaml
35
38
  pattern:
36
- - --argument
37
- - --param
38
- - command
39
+ - --argument
40
+ - --param
41
+ - command
39
42
  ```
40
43
 
44
+ Each pattern contains an array of words (or functions) that will be suggested
45
+ for the auto complete process.
46
+
41
47
  You can save a sample YAML file by running:
42
48
 
43
49
  ```
@@ -58,6 +64,7 @@ mygit status:
58
64
  - --help
59
65
  - --verbose
60
66
  - --branch
67
+ - $(git branch 2> /dev/null)
61
68
 
62
69
  mygit init:
63
70
  - --bare
@@ -92,21 +99,66 @@ For more options (like setting input/output path), run
92
99
  $ completely --help
93
100
  ```
94
101
 
95
- ### Suggesting files and directories
102
+ ### Suggesting files, directories and other bash built-ins
96
103
 
97
- You may have noticed that the sample file contains two special entries:
104
+ In addition to specifying a simple array of completion words, you may use
105
+ the special syntax `<..>` to suggest more advanced functions.
98
106
 
99
- - `<file>`
100
- - `<directory>`
107
+ ```yaml
108
+ pattern:
109
+ - <file>
110
+ - <directory>
111
+ ```
101
112
 
102
- These patterns will add the list of files and directories
103
- (when `<file>` is used) or just directories (when `<directory` is used) to
113
+ These suggestions will add the list of files and directories
114
+ (when `<file>` is used) or just directories (when `<directory>` is used) to
104
115
  the list of suggestions.
105
116
 
117
+ You may use any of the below keywords to add additional suggestions:
118
+
119
+ | Keyword | Meaning
120
+ |---------------|---------------------
121
+ | `<alias>` | Alias names
122
+ | `<arrayvar>` | Array variable names
123
+ | `<binding>` | Readline key binding names
124
+ | `<builtin>` | Names of shell builtin commands
125
+ | `<command>` | Command names
126
+ | `<directory>` | Directory names
127
+ | `<disabled>` | Names of disabled shell builtins
128
+ | `<enabled>` | Names of enabled shell builtins
129
+ | `<export>` | Names of exported shell variables
130
+ | `<file>` | File names
131
+ | `<function>` | Names of shell functions
132
+ | `<group>` | Group names
133
+ | `<helptopic>` | Help topics as accepted by the help builtin
134
+ | `<hostname>` | Hostnames, as taken from the file specified by the HOSTFILE shell variable
135
+ | `<job>` | Job names
136
+ | `<keyword>` | Shell reserved words
137
+ | `<running>` | Names of running jobs
138
+ | `<service>` | Service names
139
+ | `<signal>` | Signal names
140
+ | `<stopped>` | Names of stopped jobs
141
+ | `<user>` | User names
142
+ | `<variable>` | Names of all shell variables
143
+
106
144
  For those interested in the technical details, any word between `<...>` will
107
145
  simply be added using the [`compgen -A action`][compgen] function, so you can
108
146
  in fact use any of its supported arguments.
109
147
 
148
+ ### Suggesting custom dynamic suggestions
149
+
150
+ You can also use any command that outputs a whitespace-delimited list as a
151
+ suggestions list, by wrapping it in `$(..)`. For example, in order to add git
152
+ branches to your suggestions, use the following:
153
+
154
+ ```yaml
155
+ mygit:
156
+ - $(git branch 2> /dev/null)
157
+ ```
158
+
159
+ The `2> /dev/null` is used so that if the command is executed in a directory
160
+ without a git repository, it will still behave as expected.
161
+
110
162
 
111
163
  ## Using the generated completion scripts
112
164
 
@@ -136,6 +188,10 @@ completions = Completely::Completions.new input
136
188
 
137
189
  # Generate the script
138
190
  puts completions.script
191
+
192
+ # Or, generate a function that echos the script
193
+ puts completions.wrapper_function
194
+ puts completions.wrapper_function "custom_function_name"
139
195
  ```
140
196
 
141
197
 
@@ -148,3 +204,4 @@ to contribute, feel free to [open an issue][issues].
148
204
 
149
205
  [issues]: https://github.com/DannyBen/completely/issues
150
206
  [compgen]: https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
207
+ [bashly]: https://bashly.dannyb.co/
@@ -5,7 +5,7 @@ module Completely
5
5
 
6
6
  usage "completely new [CONFIG_PATH]"
7
7
  usage "completely preview [CONFIG_PATH --function NAME]"
8
- usage "completely generate [CONFIG_PATH OUTPUT_PATH --function NAME]"
8
+ usage "completely generate [CONFIG_PATH OUTPUT_PATH --function NAME --wrap NAME]"
9
9
  usage "completely (-h|--help|--version)"
10
10
 
11
11
  command "new", "Create a new sample YAML configuration file"
@@ -13,16 +13,18 @@ module Completely
13
13
  command "generate", "Generate the bash completion script to a file"
14
14
 
15
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"
16
17
 
17
18
  param "CONFIG_PATH", "Path to the YAML configuration file"
18
19
  param "OUTPUT_PATH", "Path to the output bash script"
19
20
 
20
21
  example "completely new"
21
22
  example "completely new input.yaml"
22
- example "completely preview --function my_completions"
23
+ example "completely preview --function _my_completions"
23
24
  example "completely generate"
24
25
  example "completely generate input.yaml"
25
- example "completely generate input.yaml output.sh -f my_completions"
26
+ example "completely generate input.yaml output.sh -f _my_completions"
27
+ example "completely generate -w give_comps -f my_completions"
26
28
 
27
29
  def new_command
28
30
  if File.exist? config_path
@@ -35,11 +37,15 @@ module Completely
35
37
 
36
38
  def preview_command
37
39
  puts script
40
+ syntax_warning unless completions.valid?
38
41
  end
39
42
 
40
43
  def generate_command
41
- File.write output_path, script
44
+ wrap = args['--wrap']
45
+ output = wrap ? wrapper_function(wrap) : script
46
+ File.write output_path, output
42
47
  say "Saved !txtpur!#{output_path}"
48
+ syntax_warning unless completions.valid?
43
49
  end
44
50
 
45
51
  private
@@ -64,9 +70,18 @@ module Completely
64
70
  @script ||= completions.script
65
71
  end
66
72
 
73
+ def wrapper_function(wrapper_name)
74
+ completions.wrapper_function wrapper_name
75
+ end
76
+
67
77
  def completions
68
78
  @completions ||= Completions.load(config_path, function_name: args['--function'])
69
79
  end
70
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
+
71
86
  end
72
87
  end
@@ -15,12 +15,37 @@ module Completely
15
15
  @config, @function_name = config, function_name
16
16
  end
17
17
 
18
+ def patterns
19
+ @patterns ||= patterns!
20
+ end
21
+
22
+ def valid?
23
+ pattern_prefixes.uniq.count == 1
24
+ end
25
+
18
26
  def script
19
27
  ERB.new(template, trim_mode: '%-').result(binding)
20
28
  end
21
29
 
30
+ def wrapper_function(name = nil)
31
+ name ||= "send_completions"
32
+
33
+ script_lines = script.split("\n").map do |line|
34
+ clean_line = line.gsub("'") { "\\'" }
35
+ %Q[ echo $'#{clean_line}']
36
+ end.join("\n")
37
+
38
+ "#{name}() {\n#{script_lines}\n}"
39
+ end
40
+
22
41
  private
23
42
 
43
+ def patterns!
44
+ config.map do |text, completions|
45
+ Pattern.new text, completions
46
+ end.sort_by { |pattern| -pattern.length }
47
+ end
48
+
24
49
  def template_path
25
50
  @template_path ||= File.expand_path("template.erb", __dir__)
26
51
  end
@@ -30,16 +55,16 @@ module Completely
30
55
  end
31
56
 
32
57
  def command
33
- @command ||= config.keys.first
34
- end
35
-
36
- def patterns
37
- @patterns ||= config.to_a.sort_by { |k, v| -k.size }.to_h
58
+ @command ||= config.keys.first.split(' ').first
38
59
  end
39
60
 
40
61
  def function_name
41
62
  @function_name ||= "_#{command}_completions"
42
63
  end
43
64
 
65
+ def pattern_prefixes
66
+ patterns.map &:prefix
67
+ end
68
+
44
69
  end
45
70
  end
@@ -0,0 +1,50 @@
1
+ module Completely
2
+ class Pattern
3
+ attr_reader :text, :completions
4
+
5
+ def initialize(text, completions)
6
+ @text = text
7
+ @completions = completions || []
8
+ end
9
+
10
+ def length
11
+ @length ||= text.size
12
+ end
13
+
14
+ def empty?
15
+ completions.empty?
16
+ end
17
+
18
+ def words
19
+ @words ||= completions.reject { |w| w =~ /^<.*>$/ }
20
+ end
21
+
22
+ def actions
23
+ @actions ||= completions.filter_map do |word|
24
+ action = word[/^<(.+)>$/, 1]
25
+ "-A #{action}" if action
26
+ end
27
+ end
28
+
29
+ def prefix
30
+ text.split(' ')[0]
31
+ end
32
+
33
+ def text_without_prefix
34
+ text.split(' ')[1..-1].join ' '
35
+ end
36
+
37
+ def compgen
38
+ @compgen ||= compgen!
39
+ end
40
+
41
+ private
42
+
43
+ def compgen!
44
+ result = []
45
+ result << %Q[#{actions.join ' '}] if actions.any?
46
+ result << %Q[-W "#{words.join ' '}"] if words.any?
47
+ result.any? ? result.join(' ') : nil
48
+ end
49
+ end
50
+ end
@@ -9,6 +9,7 @@ mygit status:
9
9
  - --help
10
10
  - --verbose
11
11
  - --branch
12
+ - $(git branch 2> /dev/null)
12
13
 
13
14
  mygit init:
14
15
  - --bare
@@ -5,14 +5,12 @@
5
5
  # Modifying it manually is not recommended
6
6
  <%= function_name %>() {
7
7
  local cur=${COMP_WORDS[COMP_CWORD]}
8
+ local comp_line="${COMP_WORDS[@]:1}"
8
9
 
9
- case "$COMP_LINE" in
10
- % patterns.each do |pattern, words|
11
- % next unless words
12
- % clean_words = words.reject { |w| w =~ /^<.*>$/ }.join " "
13
- % functions = words.filter_map { |w| func = w[/^<(.+)>$/, 1] ; "-A #{func}" if func }
14
- % flags = functions.any? ? "#{functions.join ' '} -W" : "-W"
15
- '<%= pattern %>'*) COMPREPLY=($(compgen <%= flags %> "<%= clean_words %>" -- "$cur")) ;;
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")) ;;
16
14
  % end
17
15
  esac
18
16
  }
@@ -1,3 +1,3 @@
1
1
  module Completely
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/completely.rb CHANGED
@@ -3,5 +3,5 @@ if ENV['BYEBUG']
3
3
  require 'lp'
4
4
  end
5
5
 
6
- # requires 'completely'
6
+ require 'completely/pattern'
7
7
  require 'completely/completions'
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.1.1
4
+ version: 0.3.0
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: 2021-07-20 00:00:00.000000000 Z
11
+ date: 2022-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -51,6 +51,7 @@ files:
51
51
  - lib/completely/cli.rb
52
52
  - lib/completely/command.rb
53
53
  - lib/completely/completions.rb
54
+ - lib/completely/pattern.rb
54
55
  - lib/completely/sample.yaml
55
56
  - lib/completely/template.erb
56
57
  - lib/completely/version.rb
@@ -73,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  - !ruby/object:Gem::Version
74
75
  version: '0'
75
76
  requirements: []
76
- rubygems_version: 3.2.16
77
+ rubygems_version: 3.2.15
77
78
  signing_key:
78
79
  specification_version: 4
79
80
  summary: Bash Completions Generator