Skip to content

Commit 301de12

Browse files
authored
Merge pull request #84 from bashly-framework/add/stdin-stdout-support
Add support for reading config from stdin and writing to stdout
2 parents 830f425 + 0109f76 commit 301de12

File tree

20 files changed

+188
-39
lines changed

20 files changed

+188
-39
lines changed

lib/completely/commands/base.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,25 @@ def script
3535
end
3636

3737
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
3945
end
4046

4147
def config_path
4248
@config_path ||= args['CONFIG_PATH'] || ENV['COMPLETELY_CONFIG_PATH'] || 'completely.yaml'
4349
end
4450

4551
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
4757
end
4858

4959
def config_basename

lib/completely/commands/generate.rb

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Completely
44
module Commands
55
class Generate < Base
6-
help 'Generate the bash completion script to a file'
6+
help 'Generate the bash completion script to file or stdout'
77

88
usage 'completely generate [CONFIG_PATH OUTPUT_PATH --function NAME --wrap NAME]'
99
usage 'completely generate (-h|--help)'
@@ -12,10 +12,19 @@ class Generate < Base
1212
option '-w --wrap NAME', 'Wrap the completion script inside a function that echos the ' \
1313
'script. This is useful if you wish to embed it directly in your script.'
1414

15-
param_config_path
15+
param 'CONFIG_PATH', <<~USAGE
16+
Path to the YAML configuration file [default: completely.yaml].
17+
Use '-' to read from stdin.
18+
19+
Can also be set by an environment variable.
20+
USAGE
21+
1622
param 'OUTPUT_PATH', <<~USAGE
1723
Path to the output bash script.
18-
When not provided, the name of the input file will be used with a .bash extension.
24+
Use '-' for stdout.
25+
26+
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.
27+
1928
Can also be set by an environment variable.
2029
USAGE
2130

@@ -26,8 +35,12 @@ class Generate < Base
2635
def run
2736
wrap = args['--wrap']
2837
output = wrap ? wrapper_function(wrap) : script
29-
File.write output_path, output
30-
say "Saved m`#{output_path}`"
38+
if output_path == '-'
39+
puts output
40+
else
41+
File.write output_path, output
42+
say "Saved m`#{output_path}`"
43+
end
3144
syntax_warning unless completions.valid?
3245
end
3346

lib/completely/commands/install.rb

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require 'tempfile'
12
require 'completely/commands/base'
23

34
module Completely
@@ -17,9 +18,19 @@ class Install < Base
1718
option '-d --dry', 'Show the installation command but do not run it'
1819

1920
param 'PROGRAM', 'Name of the program the completions are for.'
20-
param 'SCRIPT_PATH', 'Path to the source bash script [default: completely.bash].'
21+
param 'SCRIPT_PATH', <<~USAGE
22+
Path to the source bash script [default: completely.bash].
23+
Use '-' to provide the script via stdin.
24+
USAGE
2125

2226
def run
27+
if script_path == '-'
28+
raise InstallError, "Nothing is piped on stdin" if $stdin.tty?
29+
30+
@script_path = tempfile.path
31+
File.write script_path, $stdin.read
32+
end
33+
2334
if args['--dry']
2435
puts installer.install_command_string
2536
return
@@ -32,14 +43,18 @@ def run
3243
say 'You may need to restart your session to test it'
3344
end
3445

46+
def tempfile
47+
@tempfile ||= Tempfile.new('stdin-completely-')
48+
end
49+
3550
private
3651

3752
def installer
38-
Installer.new program: args['PROGRAM'], script_path: script_path
53+
@installer ||= Installer.new(program: args['PROGRAM'], script_path: script_path)
3954
end
4055

4156
def script_path
42-
args['SCRIPT_PATH'] || 'completely.bash'
57+
@script_path ||= args['SCRIPT_PATH'] || 'completely.bash'
4358
end
4459
end
4560
end

lib/completely/commands/preview.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Completely
44
module Commands
55
class Preview < Base
6-
help 'Generate the bash completion script to STDOUT'
6+
help 'Generate the bash completion script to stdout'
77

88
usage 'completely preview [CONFIG_PATH --function NAME]'
99
usage 'completely preview (-h|--help)'

lib/completely/completions.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ class Completions
66
attr_reader :config
77

88
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
1215
end
1316
end
1417

@@ -26,7 +29,7 @@ def patterns
2629
end
2730

2831
def valid?
29-
pattern_prefixes.uniq.count == 1
32+
pattern_prefixes.uniq.one?
3033
end
3134

3235
def script

lib/completely/config.rb

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,14 @@ class Config
33
attr_reader :config, :options
44

55
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}"
1610
end
11+
12+
def load(path) = parse(File.read(path))
13+
def read(io) = parse(io.read)
1714
end
1815

1916
def initialize(config)

lib/completely/exceptions.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module Completely
22
class Error < StandardError; end
33
class InstallError < Error; end
4+
class ParseError < Error; end
45
end

lib/completely/installer.rb

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,13 @@ def root_user?
7373
end
7474

7575
def completions_path
76-
@completions_path ||= completions_path!
77-
end
76+
@completions_path ||= begin
77+
target_directories.each do |target|
78+
return target if Dir.exist? target
79+
end
7880

79-
def completions_path!
80-
target_directories.each do |target|
81-
return target if Dir.exist? target
81+
nil
8282
end
83-
84-
nil
8583
end
8684
end
8785
end

spec/approvals/cli/commands

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ Completely - Bash Completions Generator
22

33
Commands:
44
init Create a new sample YAML configuration file
5-
preview Generate the bash completion script to STDOUT
6-
generate Generate the bash completion script to a file
5+
preview Generate the bash completion script to stdout
6+
generate Generate the bash completion script to file or stdout
77
test Test completions
88
install Install a bash completion script
99
uninstall Uninstall a bash completion script
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Saved spec/tmp/stdin-to-file.bash

0 commit comments

Comments
 (0)