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 +4 -4
- data/README.md +16 -19
- data/lib/backticks.rb +5 -5
- data/lib/backticks/cli.rb +12 -20
- data/lib/backticks/command.rb +3 -7
- data/lib/backticks/runner.rb +5 -5
- data/lib/backticks/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b155f73a14fe3ee0afa0d26a7e72187cca00a7b3
|
4
|
+
data.tar.gz: 403f3296c832847f3ba8cde407f7bf2e75ba7a29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae13cb81eabdee1ae6e8ee49688aa9224bb3764c3376e759bf71ff5b184a2de2dc5e4bb9752caf6457be5c0cb82d1bcec18c6b28972da09d26c087246f730faf
|
7
|
+
data.tar.gz: bb8367fb27bf005dd592b6eaaff7532ae3e9663423007c640d1b01c288367af6f0c3b102e488de4f3fa8c145da9e954ac855456cf67dfa2ac2ec9c9887cd3793
|
data/README.md
CHANGED
@@ -1,28 +1,25 @@
|
|
1
|
-
#
|
1
|
+
# Introduction
|
2
2
|
|
3
|
-
Backticks is
|
4
|
-
interacting with them.
|
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
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
12
|
+
"Intuitive" comes from a DSL that lets you provide command-line arguments as if they were
|
13
|
+
Ruby method arguments:
|
16
14
|
|
17
|
-
```
|
18
|
-
|
19
|
-
Backticks.run '
|
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
|
-
|
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.
|
9
|
+
# the running process.
|
10
10
|
#
|
11
|
-
# @
|
11
|
+
# @param [String] cmd
|
12
12
|
# @return [Backticks::Command] a running command
|
13
|
-
def self.new(
|
14
|
-
Backticks::Runner.new.command(
|
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(
|
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
|
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
|
-
|
81
|
-
|
82
|
-
|
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 << "
|
93
|
+
flags << "--#{kw}"
|
102
94
|
elsif arg
|
103
95
|
# truthey: option that has a value
|
104
|
-
flags << "
|
96
|
+
flags << "--#{kw}=#{arg}"
|
105
97
|
else
|
106
98
|
# falsey: omit boolean flag
|
107
99
|
end
|
data/lib/backticks/command.rb
CHANGED
@@ -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
|
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
|
data/lib/backticks/runner.rb
CHANGED
@@ -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
|
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
|
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
|
-
|
98
|
+
def run_buffered(argv)
|
99
99
|
stdin, stdout, stderr, thr = Open3.popen3(*argv)
|
100
100
|
unless @interactive
|
101
101
|
stdin.close
|
data/lib/backticks/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2016-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|