completely 0.1.1 → 0.3.0

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: 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