completely 0.7.2 → 0.7.3

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: 3e2d4ef0dc7d503f77387c199d75989c8aca7408f73421086219bfab91823dd0
4
- data.tar.gz: 4c5650a43490f9d35417a808c532391c9a0e7cf52d47b36ef5ffe56ab0d28ed2
3
+ metadata.gz: 1d6353c59bdf0d9ea55a2618a06f40b14d844ad7d40827d50f3bb38949b5263f
4
+ data.tar.gz: bbdcddef491b55bc6554fdcdf804b48bfddddbe744360bff99a19e9e105f2b2b
5
5
  SHA512:
6
- metadata.gz: 655e9090c78451ffc8ba5f8b4f309e92756c02b769b4f60d9df2520f5ddc572b6eb7e761aeb8d0a2e1f3113bd1bcf05be186c75a95d833fc9938ad6bf706057c
7
- data.tar.gz: 81b519ae5db4f3eed6475b1a8b601c8bb873ed6cf0a67c2862b893e878342e031c60b3c58b600c2bc80b080f9c63a0a6ead68d37ef5b42924d5e687ac514feb1
6
+ metadata.gz: 5fab1170310c441fded2bdac3770edbaab6ce20100be7b005971371361513926b5492016e4abacf0bceb528824c1f80b30d1874d4bd6d8bb566e4f3ebaebd23e
7
+ data.tar.gz: 01cdc71f95b09bc73492c2d65fd70e272505e1d5145d5aabe69a58cdab1a924316f9919951dbbf64243a24c0c435d60ca4e2f559d843716c82e27352f5f4bf1c
@@ -35,7 +35,13 @@ module Completely
35
35
  end
36
36
 
37
37
  def completions
38
- @completions ||= Completions.load(config_path, function_name: args['--function'])
38
+ @completions ||= if config_path == '-'
39
+ raise Error, 'Nothing is piped on stdin' if $stdin.tty?
40
+
41
+ Completions.read $stdin, function_name: args['--function']
42
+ else
43
+ Completions.load config_path, function_name: args['--function']
44
+ end
39
45
  end
40
46
 
41
47
  def config_path
@@ -43,7 +49,11 @@ module Completely
43
49
  end
44
50
 
45
51
  def output_path
46
- @output_path ||= args['OUTPUT_PATH'] || ENV['COMPLETELY_OUTPUT_PATH'] || "#{config_basename}.bash"
52
+ @output_path ||= args['OUTPUT_PATH'] || ENV['COMPLETELY_OUTPUT_PATH'] || stdout || "#{config_basename}.bash"
53
+ end
54
+
55
+ def stdout
56
+ @stdout ||= config_path == '-' ? '-' : nil
47
57
  end
48
58
 
49
59
  def config_basename
@@ -3,19 +3,31 @@ require 'completely/commands/base'
3
3
  module Completely
4
4
  module Commands
5
5
  class Generate < Base
6
- help 'Generate the bash completion script to a file'
6
+ help 'Generate the bash completion script to file or stdout'
7
7
 
8
8
  usage 'completely generate [CONFIG_PATH OUTPUT_PATH --function NAME --wrap NAME]'
9
+ usage 'completely generate [CONFIG_PATH --install PROGRAM --function NAME]'
9
10
  usage 'completely generate (-h|--help)'
10
11
 
11
12
  option_function
12
13
  option '-w --wrap NAME', 'Wrap the completion script inside a function that echos the ' \
13
14
  'script. This is useful if you wish to embed it directly in your script.'
14
15
 
15
- param_config_path
16
+ option '-i --install PROGRAM', 'Install the generated script as completions for PROGRAM.'
17
+
18
+ param 'CONFIG_PATH', <<~USAGE
19
+ Path to the YAML configuration file [default: completely.yaml].
20
+ Use '-' to read from stdin.
21
+
22
+ Can also be set by an environment variable.
23
+ USAGE
24
+
16
25
  param 'OUTPUT_PATH', <<~USAGE
17
26
  Path to the output bash script.
18
- When not provided, the name of the input file will be used with a .bash extension.
27
+ Use '-' for stdout.
28
+
29
+ When not provided, the name of the input file will be used with a .bash extension, unless the input is stdin - in this case the default will be to output to stdout.
30
+
19
31
  Can also be set by an environment variable.
20
32
  USAGE
21
33
 
@@ -26,13 +38,35 @@ module Completely
26
38
  def run
27
39
  wrap = args['--wrap']
28
40
  output = wrap ? wrapper_function(wrap) : script
29
- File.write output_path, output
30
- say "Saved m`#{output_path}`"
31
- syntax_warning unless completions.valid?
41
+
42
+ if args['--install']
43
+ install output
44
+ elsif output_path == '-'
45
+ show output
46
+ else
47
+ save output
48
+ end
32
49
  end
33
50
 
34
51
  private
35
52
 
53
+ def install(content)
54
+ installer = Installer.from_string program: args['--install'], string: content
55
+ success = installer.install force: true
56
+ raise InstallError, "Failed running command:\nnb`#{installer.install_command_string}`" unless success
57
+
58
+ say "Saved m`#{installer.target_path}`"
59
+ say 'You may need to restart your session to test it'
60
+ end
61
+
62
+ def show(content) = puts content
63
+
64
+ def save(content)
65
+ File.write output_path, content
66
+ say "Saved m`#{output_path}`"
67
+ syntax_warning unless completions.valid?
68
+ end
69
+
36
70
  def wrapper_function(wrapper_name)
37
71
  completions.wrapper_function wrapper_name
38
72
  end
@@ -17,7 +17,10 @@ module Completely
17
17
  option '-d --dry', 'Show the installation command but do not run it'
18
18
 
19
19
  param 'PROGRAM', 'Name of the program the completions are for.'
20
- param 'SCRIPT_PATH', 'Path to the source bash script [default: completely.bash].'
20
+ param 'SCRIPT_PATH', <<~USAGE
21
+ Path to the source bash script [default: completely.bash].
22
+ Use '-' to provide the script via stdin.
23
+ USAGE
21
24
 
22
25
  def run
23
26
  if args['--dry']
@@ -32,15 +35,19 @@ module Completely
32
35
  say 'You may need to restart your session to test it'
33
36
  end
34
37
 
35
- private
36
-
37
38
  def installer
38
- Installer.new program: args['PROGRAM'], script_path: script_path
39
+ @installer ||= if stdin?
40
+ Installer.from_io program:
41
+ else
42
+ Installer.new program:, script_path: input_script_path
43
+ end
39
44
  end
40
45
 
41
- def script_path
42
- args['SCRIPT_PATH'] || 'completely.bash'
43
- end
46
+ private
47
+
48
+ def program = args['PROGRAM']
49
+ def stdin? = input_script_path == '-'
50
+ def input_script_path = args['SCRIPT_PATH'] || 'completely.bash'
44
51
  end
45
52
  end
46
53
  end
@@ -3,7 +3,7 @@ require 'completely/commands/base'
3
3
  module Completely
4
4
  module Commands
5
5
  class Preview < Base
6
- help 'Generate the bash completion script to STDOUT'
6
+ help 'Generate the bash completion script to stdout'
7
7
 
8
8
  usage 'completely preview [CONFIG_PATH --function NAME]'
9
9
  usage 'completely preview (-h|--help)'
@@ -6,9 +6,12 @@ module Completely
6
6
  attr_reader :config
7
7
 
8
8
  class << self
9
- def load(config_path, function_name: nil)
10
- config = Config.load config_path
11
- new config, function_name: function_name
9
+ def load(path, function_name: nil)
10
+ new Config.load(path), function_name: function_name
11
+ end
12
+
13
+ def read(io, function_name: nil)
14
+ new Config.read(io), function_name: function_name
12
15
  end
13
16
  end
14
17
 
@@ -26,7 +29,7 @@ module Completely
26
29
  end
27
30
 
28
31
  def valid?
29
- pattern_prefixes.uniq.count == 1
32
+ pattern_prefixes.uniq.one?
30
33
  end
31
34
 
32
35
  def script
@@ -3,17 +3,14 @@ module Completely
3
3
  attr_reader :config, :options
4
4
 
5
5
  class << self
6
- def load(config_path)
7
- begin
8
- config = YAML.load_file config_path, aliases: true
9
- rescue ArgumentError
10
- # :nocov:
11
- config = YAML.load_file config_path
12
- # :nocov:
13
- end
14
-
15
- new config
6
+ def parse(str)
7
+ new YAML.load(str, aliases: true)
8
+ rescue Psych::Exception => e
9
+ raise ParseError, "Invalid YAML: #{e.message}"
16
10
  end
11
+
12
+ def load(path) = parse(File.read(path))
13
+ def read(io) = parse(io.read)
17
14
  end
18
15
 
19
16
  def initialize(config)
@@ -1,4 +1,5 @@
1
1
  module Completely
2
2
  class Error < StandardError; end
3
3
  class InstallError < Error; end
4
+ class ParseError < Error; end
4
5
  end
@@ -1,5 +1,36 @@
1
1
  module Completely
2
2
  class Installer
3
+ class << self
4
+ def from_io(program:, io: nil)
5
+ io ||= $stdin
6
+
7
+ raise InstallError, 'io must respond to #read' unless io.respond_to?(:read)
8
+ raise InstallError, 'io is closed' if io.respond_to?(:closed?) && io.closed?
9
+
10
+ from_string program:, string: io.read
11
+ end
12
+
13
+ def from_string(program:, string:)
14
+ tempfile = create_tempfile
15
+ script_path = tempfile.path
16
+ begin
17
+ File.write script_path, string
18
+ ensure
19
+ tempfile.close
20
+ end
21
+
22
+ new program:, script_path:
23
+ end
24
+
25
+ def create_tempfile
26
+ tempfile = Tempfile.new ['completely-', '.bash']
27
+ tempfiles.push tempfile
28
+ tempfile
29
+ end
30
+
31
+ def tempfiles = @tempfiles ||= []
32
+ end
33
+
3
34
  attr_reader :program, :script_path
4
35
 
5
36
  def initialize(program:, script_path: nil)
@@ -73,15 +104,17 @@ module Completely
73
104
  end
74
105
 
75
106
  def completions_path
76
- @completions_path ||= completions_path!
77
- end
78
-
79
- def completions_path!
80
- target_directories.each do |target|
81
- return target if Dir.exist? target
107
+ @completions_path ||= begin
108
+ result = nil
109
+ target_directories.each do |target|
110
+ if Dir.exist? target
111
+ result = target
112
+ break
113
+ end
114
+ end
115
+
116
+ result
82
117
  end
83
-
84
- nil
85
118
  end
86
119
  end
87
120
  end
@@ -9,24 +9,46 @@
9
9
  local cur=${COMP_WORDS[COMP_CWORD]}
10
10
  local result=()
11
11
 
12
+ # words the user already typed (excluding the command itself)
13
+ local used=()
14
+ if ((COMP_CWORD > 1)); then
15
+ used=("${COMP_WORDS[@]:1:$((COMP_CWORD - 1))}")
16
+ fi
17
+
12
18
  if [[ "${cur:0:1}" == "-" ]]; then
19
+ # Completing an option: offer everything (including options)
13
20
  echo "$words"
14
21
 
15
22
  else
23
+ # Completing a non-option: offer only non-options,
24
+ # and don't re-offer ones already used earlier in the line.
16
25
  for word in $words; do
17
- [[ "${word:0:1}" != "-" ]] && result+=("$word")
26
+ [[ "${word:0:1}" == "-" ]] && continue
27
+
28
+ local seen=0
29
+ for u in "${used[@]}"; do
30
+ if [[ "$u" == "$word" ]]; then
31
+ seen=1
32
+ break
33
+ fi
34
+ done
35
+ ((!seen)) && result+=("$word")
18
36
  done
19
37
 
20
38
  echo "${result[*]}"
21
-
22
39
  fi
23
40
  }
24
41
 
25
42
  <%= function_name %>() {
26
43
  local cur=${COMP_WORDS[COMP_CWORD]}
27
- local compwords=("${COMP_WORDS[@]:1:$COMP_CWORD-1}")
44
+ local compwords=()
45
+ if ((COMP_CWORD > 0)); then
46
+ compwords=("${COMP_WORDS[@]:1:$((COMP_CWORD - 1))}")
47
+ fi
28
48
  local compline="${compwords[*]}"
29
49
 
50
+ COMPREPLY=()
51
+
30
52
  % if ENV['COMPLETELY_DEBUG']
31
53
  if [[ -n "$COMPLETELY_DEBUG" ]]; then
32
54
  echo "compline: '$compline'" > 'completely-debug.txt'
@@ -1,3 +1,3 @@
1
1
  module Completely
2
- VERSION = '0.7.2'
2
+ VERSION = '0.7.3'
3
3
  end
data/lib/completely.rb CHANGED
@@ -4,3 +4,4 @@ require 'completely/pattern'
4
4
  require 'completely/completions'
5
5
  require 'completely/tester'
6
6
  require 'completely/installer'
7
+ require 'debug' if ENV['COMPLETELY_DEV']
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completely
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit