backticks 0.3.0 → 0.3.1

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
  SHA1:
3
- metadata.gz: 8093e055335a1040855c560d8c94d9fb7a5cecd1
4
- data.tar.gz: 2145905dfafbc820072d832f789b65d7c99b5638
3
+ metadata.gz: b155f73a14fe3ee0afa0d26a7e72187cca00a7b3
4
+ data.tar.gz: 403f3296c832847f3ba8cde407f7bf2e75ba7a29
5
5
  SHA512:
6
- metadata.gz: fc987a7287c7662a5d9207eeebf429b74ead2b15c7ebaccfab73763ba73650b4197ef81cfc3654472bbf1bf818d56168b2e6d22994432502dd8defea1e75f1e8
7
- data.tar.gz: d1aa0d1ae781ebed53753562d6c1799e091d7a91fad42f442a8c589efab60501af35618e9052a9bf86513b65f60b4691b5f3fc4c2a19f8991b3c4862b9d1f79c
6
+ metadata.gz: ae13cb81eabdee1ae6e8ee49688aa9224bb3764c3376e759bf71ff5b184a2de2dc5e4bb9752caf6457be5c0cb82d1bcec18c6b28972da09d26c087246f730faf
7
+ data.tar.gz: bb8367fb27bf005dd592b6eaaff7532ae3e9663423007c640d1b01c288367af6f0c3b102e488de4f3fa8c145da9e954ac855456cf67dfa2ac2ec9c9887cd3793
data/README.md CHANGED
@@ -1,28 +1,25 @@
1
- # Backticks
1
+ # Introduction
2
2
 
3
- Backticks is an intuitive OOP wrapper for invoking command-line processes and
4
- interacting with them. It improves on Ruby's built-in invocation methods in a
5
- few ways:
6
- - Uses [pseudoterminals](https://en.wikipedia.org/wiki/Pseudoterminal) for unbuffered I/O
7
- - Captures input as well as output
8
- - Intuitive API that accepts CLI parameters as Ruby positional and keyword args
3
+ Backticks is a powerful, intuitive OOP wrapper for invoking command-line processes and
4
+ interacting with them.
9
5
 
10
- If you want to write a record/playback application for the terminal, or write
11
- functional tests that verify your program's output in real time, Backticks is
12
- exactly what you've been looking for!
6
+ "Powerful" comes from features that make Backticks especially well suited for time-sensitive
7
+ or record/playback applications:
8
+ - Uses [pseudoterminals](https://en.wikipedia.org/wiki/Pseudoterminal) for realtime stdout/stdin
9
+ - Captures input as well as output
10
+ - Separates stdout from stderr
13
11
 
14
- For an example of the intuitive API, let's consider how we list a bunch of
15
- files or search for some text with Backticks:
12
+ "Intuitive" comes from a DSL that lets you provide command-line arguments as if they were
13
+ Ruby method arguments:
16
14
 
17
- ```ruby
18
- # invokes "ls -l -R"
19
- Backticks.run 'ls', l:true, R:true
20
-
21
- # invokes "grep -H --context=2 --regexp=needle haystack.txt"
22
- Backticks.run 'grep', {H:true, context:2, regexp:'needle'}, 'haystack.txt'
15
+ ```
16
+ Backticks.run 'ls', R:true, ignore_backups:true, hide:'.git'
17
+ Backticks.run 'cp' {f:true}, '*.rb', '/mnt/awesome'
23
18
  ```
24
19
 
25
- Notice how running commands feels like a plain old Ruby method call.
20
+ If you want to write a record/playback application for the terminal, or write
21
+ functional tests that verify your program's output in real time, Backticks is
22
+ exactly what you've been looking for!
26
23
 
27
24
  ## Installation
28
25
 
data/lib/backticks.rb CHANGED
@@ -6,19 +6,19 @@ require_relative 'backticks/ext'
6
6
 
7
7
  module Backticks
8
8
  # Run a command; return a Command object that can be used to interact with
9
- # the running process. Method parameters are passed through to the Runner.
9
+ # the running process.
10
10
  #
11
- # @see Backticks::Runner#command
11
+ # @param [String] cmd
12
12
  # @return [Backticks::Command] a running command
13
- def self.new(*cmd)
14
- Backticks::Runner.new.command(*cmd)
13
+ def self.new(cmd)
14
+ Backticks::Runner.new.command(cmd)
15
15
  end
16
16
 
17
17
  # Run a command; return its stdout.
18
18
  #
19
19
  # @param [String] cmd
20
20
  # @return [String] the command's output
21
- def self.run(*cmd)
21
+ def self.run(cmd)
22
22
  command = self.new(*cmd)
23
23
  command.join
24
24
  command.captured_output
data/lib/backticks/cli.rb CHANGED
@@ -73,35 +73,27 @@ module Backticks
73
73
  def self.options(**opts)
74
74
  flags = []
75
75
 
76
- # Transform opts into getopt-style command line parameters;
76
+ # Transform opts into golang flags-style command line parameters;
77
77
  # append them to the command.
78
78
  opts.each do |kw, arg|
79
79
  if kw.length == 1
80
- # short-form option e.g. "-a" or "-x hello"
81
- pre='-'
82
- eql=' '
80
+ if arg == true
81
+ # true: boolean flag
82
+ flags << "-#{kw}"
83
+ elsif arg
84
+ # truthey: option that has a value
85
+ flags << "-#{kw}" << arg.to_s
86
+ else
87
+ # falsey: omit boolean flag
88
+ end
83
89
  else
84
- # long-form option e.g. "--ask" or "--extra=hello"
85
90
  kw = kw.to_s.gsub('_','-')
86
- pre='--'
87
- eql='='
88
- end
89
-
90
- # options can be single- or multi-valued; normalize the processing
91
- # of both by "upconverting" single options to an array or values.
92
- if arg.kind_of?(Array)
93
- values = arg
94
- else
95
- values = [arg]
96
- end
97
-
98
- values.each do |arg|
99
91
  if arg == true
100
92
  # true: boolean flag
101
- flags << "#{pre}#{kw}"
93
+ flags << "--#{kw}"
102
94
  elsif arg
103
95
  # truthey: option that has a value
104
- flags << "#{pre}#{kw}#{eql}#{arg}"
96
+ flags << "--#{kw}=#{arg}"
105
97
  else
106
98
  # falsey: omit boolean flag
107
99
  end
@@ -46,8 +46,6 @@ module Backticks
46
46
  #
47
47
  # @param [Float,Integer] limit number of seconds to wait before returning
48
48
  def join(limit=nil)
49
- return self if @status # preserve idempotency
50
-
51
49
  if limit
52
50
  tf = Time.now + limit
53
51
  else
@@ -77,7 +75,8 @@ module Backticks
77
75
  #
78
76
  # @param [Float,Integer] number of seconds to wait before returning nil
79
77
  # @return [String,nil] fresh bytes from stdout/stderr, or nil if no output
80
- private def capture(limit=nil)
78
+ private
79
+ def capture(limit=nil)
81
80
  streams = [@stdout, @stderr]
82
81
  streams << STDIN if interactive?
83
82
 
@@ -117,12 +116,9 @@ module Backticks
117
116
  if data
118
117
  @captured_error << data
119
118
  STDERR.write(data) if interactive?
120
- fresh_error = data
121
119
  end
122
120
  end
123
-
124
- # return freshly-captured text(if any)
125
- fresh_output || fresh_error
121
+ fresh_output
126
122
  rescue Interrupt
127
123
  # Proxy Ctrl+C to the child
128
124
  (Process.kill('INT', @pid) rescue nil) if @interactive
@@ -56,8 +56,9 @@ module Backticks
56
56
  #
57
57
  # @example Run docker-compose with complex parameters
58
58
  # command('docker-compose', {file: 'joe.yml'}, 'up', {d:true}, 'mysvc')
59
- def run(*args)
59
+ def command(*args)
60
60
  argv = @cli.parameters(*args)
61
+
61
62
  if self.buffered
62
63
  run_buffered(argv)
63
64
  else
@@ -65,14 +66,13 @@ module Backticks
65
66
  end
66
67
  end
67
68
 
68
- alias command run
69
-
70
69
  # Run a command. Use a pty to capture the unbuffered output.
71
70
  #
72
71
  # @param [Array] argv command to run; argv[0] is program name and the
73
72
  # remaining elements are parameters and flags
74
73
  # @return [Command] the running command
75
- private def run_unbuffered(argv)
74
+ private
75
+ def run_unbuffered(argv)
76
76
  stdout, stdout_w = PTY.open
77
77
  stdin_r, stdin = PTY.open
78
78
  stderr, stderr_w = PTY.open
@@ -95,7 +95,7 @@ module Backticks
95
95
  # @param [Array] argv command to run; argv[0] is program name and the
96
96
  # remaining elements are command-line arguments.
97
97
  # @return [Command] the running command
98
- private def run_buffered(argv)
98
+ def run_buffered(argv)
99
99
  stdin, stdout, stderr, thr = Open3.popen3(*argv)
100
100
  unless @interactive
101
101
  stdin.close
@@ -1,3 +1,3 @@
1
1
  module Backticks
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backticks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Spataro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-03 00:00:00.000000000 Z
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler