coque 0.1.0 → 0.2.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
  SHA1:
3
- metadata.gz: 344cd271557b02f3d3b01fc25a524fe44a2ecf4a
4
- data.tar.gz: 74a4a0f32297f6c2e7368fab1c89a3317e52168d
3
+ metadata.gz: c69c98fb67e7afee6ad27390978968a86ebc9bb8
4
+ data.tar.gz: 09d45720d414295f7c1b4f887702b5439a3cbfb7
5
5
  SHA512:
6
- metadata.gz: 4561c894a43b60ef8baaa903e1ac732473927deff5dc9fc9d3c8ce7c3bdba1aa361d783830f20762546574e82baeb252c0d5d8139ed569ffe84b8fa839e32068
7
- data.tar.gz: e3a6a90e1a67e085a4aab4c5261340599ac9941bdd86da01c645830cb051d2c85fac54fc038308eaba8598cb5b061e9f79de84b9c808561ae39a08774dd4bea9
6
+ metadata.gz: bd2afeb39c8afe1e1681a4fc7934d6116afdcc9616861c9abfe60ebbe86be469bd47af231568a4fc38c2e382cacf3ce0c6402fe5ab8ef232f804b1cbad699539
7
+ data.tar.gz: 7ee2833b41ecae0a0b9f7deb06d2a678bd2cb0eea1197a9aba826b2b5c2ea0ba5d38d57ec373e3dbe57d27c1ed53d212dc035f3646f2a2c11ee4f7acbac31540
data/README.md CHANGED
@@ -39,7 +39,7 @@ pipeline.run.to_a
39
39
 
40
40
  Coque can also create "Rb" commands, which integrate Ruby code with streaming, line-wise processing of other commands:
41
41
 
42
- ```
42
+ ```rb
43
43
  c1 = Coque["printf", '"a\nb\nc\n"']
44
44
  c2 = Coque.rb { |line| puts line.upcase }
45
45
  (c1 | c2).run.to_a
@@ -48,7 +48,7 @@ c2 = Coque.rb { |line| puts line.upcase }
48
48
 
49
49
  Rb commands can also take "pre" and "post" blocks
50
50
 
51
- ```
51
+ ```rb
52
52
  dict = Coque["cat", "/usr/share/dict/words"]
53
53
  rb_wc = Coque.rb { @lines += 1 }.pre { @lines = 0 }.post { puts @lines }
54
54
 
@@ -71,7 +71,7 @@ File.read("/tmp/error.txt")
71
71
  # => "cat: /doesntexist.txt: No such file or directory\n"
72
72
  ```
73
73
 
74
- Coque commands can also be derived from a `Coque::Context`:
74
+ Coque commands can also be derived from a `Coque::Context`, which enables changing directory, setting environment variables, and unsetting child env:
75
75
 
76
76
  ```rb
77
77
  c = Coque.context
@@ -83,6 +83,20 @@ Coque.context.chdir("/tmp")["pwd"].run.to_a
83
83
 
84
84
  Coque.context.setenv("my_key": "pizza")["echo", "$my_key"].run.to_a
85
85
  # => ["pizza"]
86
+
87
+ ENV["my_key"] = "pizza"
88
+ Coque["echo", "$my_key"].run.to_a
89
+ # => ["pizza"]
90
+
91
+ Coque.context.disinherit_env["echo", "$my_key"].to_a
92
+ # => [""]
93
+ ```
94
+
95
+ Coque also includes a `Coque.source` helper for feeding Ruby enumerables into shell pipelines:
96
+
97
+ ```rb
98
+ (Coque.source(1..500) | Coque["wc", "-l"]).run.to_a
99
+ # => ["500"]
86
100
  ```
87
101
 
88
102
  ### Streaming Performance
data/lib/coque/cmd.rb CHANGED
@@ -4,12 +4,11 @@ module Coque
4
4
  attr_reader :context
5
5
 
6
6
  def |(other)
7
- verify_redirectable(other)
8
7
  case other
9
8
  when Cmd
10
- Pipeline.new([self, other])
9
+ Pipeline.new([self.clone, other.clone])
11
10
  when Pipeline
12
- Pipeline.new([self] + other.commands)
11
+ Pipeline.new([self.clone] + other.commands)
13
12
  end
14
13
  end
15
14
 
@@ -17,19 +16,22 @@ module Coque
17
16
  raise "Not Implemented - Override"
18
17
  end
19
18
 
20
- def ensure_default_fds
21
- if self.stdin.nil?
22
- inr, inw = IO.pipe
23
- inw.close
24
- self.stdin = inr
25
- end
19
+ def get_default_fds
20
+ stdin = if self.stdin
21
+ self.stdin
22
+ else
23
+ inr, inw = IO.pipe
24
+ inw.close
25
+ inr
26
+ end
26
27
 
27
- if self.stdout.nil?
28
- outr, outw = IO.pipe
29
- self.stdout = outw
30
- # only used for Result if this is the last command in a pipe
31
- @stdout_read = outr
32
- end
28
+ stdoutr, stdoutw = if self.stdout
29
+ [self.stdout, self.stdout]
30
+ else
31
+ IO.pipe
32
+ end
33
+
34
+ [stdin, stdoutr, stdoutw]
33
35
  end
34
36
  end
35
37
  end
@@ -16,12 +16,11 @@ module Coque
16
16
  end
17
17
 
18
18
  def |(other)
19
- verify_redirectable(other)
20
19
  case other
21
20
  when Pipeline
22
21
  Pipeline.new(commands + other.commands)
23
22
  when Cmd
24
- Pipeline.new(commands + [other])
23
+ Pipeline.new(commands + [other.clone])
25
24
  end
26
25
  end
27
26
 
data/lib/coque/rb.rb CHANGED
@@ -32,10 +32,10 @@ module Coque
32
32
  end
33
33
 
34
34
  def run
35
- ensure_default_fds
35
+ stdin, stdoutr, stdoutw = get_default_fds
36
36
 
37
37
  pid = fork do
38
- STDOUT.reopen(stdout)
38
+ STDOUT.reopen(stdoutw)
39
39
  Dir.chdir(context.dir)
40
40
  if context.disinherits_env?
41
41
  ENV.clear
@@ -47,8 +47,8 @@ module Coque
47
47
  stdin.each_line(&@block)
48
48
  @post_block.call if @post_block
49
49
  end
50
- stdout.close
51
- Result.new(pid, stdout_read)
50
+ stdoutw.close
51
+ Result.new(pid, stdoutr)
52
52
  end
53
53
  end
54
54
  end
@@ -37,50 +37,20 @@ module Coque
37
37
  end
38
38
  end
39
39
 
40
- def stdin_redirected?
41
- defined? @stdin
42
- end
43
-
44
- def stdout_redirected?
45
- defined? @stdout
46
- end
47
-
48
- def stderr_redirected?
49
- defined? @stderr
50
- end
51
-
52
40
  def stderr=(s)
53
- if stderr_redirected?
54
- raise RedirectionError.new("Can't set stderr of #{self} to #{s}, is already set to #{stderr}")
55
- else
56
- @stderr = getio(s, "w")
57
- end
41
+ @stderr = getio(s, "w")
58
42
  end
59
43
 
60
44
  def stdout=(s)
61
- if stdout_redirected?
62
- raise RedirectionError.new("Can't set stdout of #{self} to #{s}, is already set to #{stdout}")
63
- else
64
- @stdout = getio(s, "w")
65
- end
45
+ @stdout = getio(s, "w")
66
46
  end
67
47
 
68
48
  def stdin=(s)
69
- if stdin_redirected?
70
- raise RedirectionError.new("Can't set stdin of #{self} to #{s}, is already set to #{stdin}")
71
- else
72
- @stdin = getio(s, "r")
73
- end
49
+ @stdin = getio(s, "r")
74
50
  end
75
51
 
76
- def verify_redirectable(other)
77
- if self.stdout_redirected?
78
- raise RedirectionError.new("Can't pipe #{self} into #{other} -- #{self}'s STDIN is already redirected")
79
- end
80
-
81
- if other.stdin_redirected?
82
- raise RedirectionError.new("Can't pipe #{self} into #{other} -- #{other}'s STDIN is already redirected")
83
- end
52
+ def to_a
53
+ run.to_a
84
54
  end
85
55
 
86
56
  private
data/lib/coque/sh.rb CHANGED
@@ -1,13 +1,16 @@
1
1
  module Coque
2
2
  class Sh < Cmd
3
3
  attr_reader :args, :context
4
- def initialize(context, args)
4
+ def initialize(context, args, stdin = nil, stdout = nil, stderr = nil)
5
5
  @context = context
6
6
  @args = args
7
+ self.stdin = stdin if stdin
8
+ self.stdout = stdout if stdout
9
+ self.stderr = stderr if stderr
7
10
  end
8
11
 
9
12
  def clone
10
- self.class.new(context, args)
13
+ self.class.new(context, args, stdin, stdout, stderr)
11
14
  end
12
15
 
13
16
  def to_s
@@ -23,9 +26,9 @@ module Coque
23
26
  end
24
27
 
25
28
  def run
26
- ensure_default_fds
29
+ stdin, stdoutr, stdoutw = get_default_fds
27
30
  opts = {in: stdin, stdin.fileno => stdin.fileno,
28
- out: stdout, stdout.fileno => stdout.fileno,
31
+ out: stdoutw, stdoutw.fileno => stdoutw.fileno,
29
32
  chdir: context.dir, unsetenv_others: context.disinherits_env?}
30
33
 
31
34
  # Redirect err to out: (e.g. for 2>&1)
@@ -38,8 +41,8 @@ module Coque
38
41
 
39
42
  pid = spawn(context.env, args.join(" "), opts.merge(err_opts))
40
43
 
41
- stdout.close
42
- Result.new(pid, stdout_read)
44
+ stdoutw.close
45
+ Result.new(pid, stdoutr)
43
46
  end
44
47
  end
45
48
  end
data/lib/coque/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Coque
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/coque.rb CHANGED
@@ -24,4 +24,8 @@ module Coque
24
24
  def self.pipeline(*commands)
25
25
  commands.reduce(:|)
26
26
  end
27
+
28
+ def self.source(enumerable)
29
+ Coque.rb.post { enumerable.each { |e| puts e} }
30
+ end
27
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coque
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Horace Williams
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-06 00:00:00.000000000 Z
11
+ date: 2018-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler