rubyshell 1.0.1 → 1.1.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 +166 -12
- data/lib/rubyshell/chain_context.rb +4 -3
- data/lib/rubyshell/chainer.rb +11 -8
- data/lib/rubyshell/command.rb +19 -11
- data/lib/rubyshell/executor.rb +16 -3
- data/lib/rubyshell/version.rb +1 -1
- data/lib/rubyshell.rb +2 -22
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3dc52bfe0cf67de6392904a19c61eecd1ba03d309ed0b71fe7c9f62c43a99389
|
4
|
+
data.tar.gz: 99ec7930b2fb5223efe6533fee5357ea1a18ee8501267479157d533e9be687e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f44145f622774e54812697bb03a16e06f5b1a5f4dedbe3832879af9f500144a1b81a67424a0567b0a738efa713c5d849321f58ba6281fe8c2d573e53d04343b3
|
7
|
+
data.tar.gz: 6b213e46dd112c32449cfab374cafefaa41265dfdc4b32152bfeac6757757266bdb56e81dc975f9c816c8818edc1d5533e28bebacdda510310f2fb43c7a2b83b
|
data/README.md
CHANGED
@@ -1,24 +1,172 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
<h1 align="center">
|
2
|
+
<img alt="RubyShell" src="./docs/images/rubyshelllogo.png" width="60%">
|
3
|
+
</h1>
|
4
|
+
|
5
|
+
<h3 align="center">✨ Rubist way to create shell scripts ✨</h3>
|
6
|
+
|
7
|
+
<p align="center">
|
8
|
+
<a href="https://rubygems.org/gems/rubyshell">
|
9
|
+
<img src="https://img.shields.io/gem/v/rubyshell?color=red&logo=ruby" alt="Gem Version">
|
10
|
+
</a>
|
11
|
+
<a href="https://rubygems.org/gems/rubyshell">
|
12
|
+
<img src="https://img.shields.io/gem/dt/rubyshell.svg?label=Downloads&colorA=004d99&colorB=0073e6" alt="Gem Version">
|
13
|
+
</a>
|
14
|
+
<a href="https://github.com/albertalef/rubyshell/actions/workflows/main.yml">
|
15
|
+
<img src="https://github.com/albertalef/rubyshell/actions/workflows/main.yml/badge.svg" alt="Build Status">
|
16
|
+
</a>
|
17
|
+
<a href="https://opensource.org/licenses/MIT">
|
18
|
+
<img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License">
|
19
|
+
</a>
|
20
|
+
|
21
|
+
<p align="center">
|
22
|
+
<a href="#installation">Installation</a>
|
23
|
+
·
|
24
|
+
<a href="#usage">Usage</a>
|
25
|
+
·
|
26
|
+
<a href="#complete-example">Examples</a>
|
27
|
+
·
|
28
|
+
<a href="#contributing">Contributing</a>
|
29
|
+
·
|
30
|
+
<a href="#sponsors">Sponsors</a>
|
31
|
+
</p>
|
32
|
+
</p>
|
33
|
+
<br />
|
34
|
+
<br />
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
cd "/log" do
|
38
|
+
ls.each_line do |line|
|
39
|
+
puts cat(line)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
Yes, that’s valid Ruby!
|
45
|
+
`ls` and `cat` are just shell commands, but **RubyShell** makes them behave like Ruby methods.
|
6
46
|
|
7
47
|
## Installation
|
8
48
|
|
9
|
-
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
10
|
-
|
11
49
|
Install the gem and add to the application's Gemfile by executing:
|
12
50
|
|
13
|
-
$ bundle add
|
51
|
+
$ bundle add rubyshell
|
14
52
|
|
15
53
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
16
54
|
|
17
|
-
$ gem install
|
55
|
+
$ gem install rubyshell
|
18
56
|
|
19
57
|
## Usage
|
20
58
|
|
21
|
-
|
59
|
+
### Calling a shell command
|
60
|
+
With RubyShell, every shell command can be used inside the ruby, you just need to call
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
sh do
|
64
|
+
puts pwd # => /Users/albertalef/projects/rubyshell
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
### Passing arguments
|
69
|
+
Here we have different ways to pass arguments to a command.
|
70
|
+
You can separate strings, use only one, use hashes, anyway will work
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
sh do
|
74
|
+
docker("ps", all: true) # Using hash syntax = docker ps --all
|
75
|
+
|
76
|
+
docker("ps", a: true) # Using hash syntax = docker ps -a
|
77
|
+
|
78
|
+
docker("ps", '-a') # Passing multiple strings = docker ps -a
|
79
|
+
|
80
|
+
docker("ps -a") # Passing one string = docker ps -a
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
### Changing folder
|
85
|
+
Has two possible ways, changing the folder of the code, or running code only inside a folder
|
86
|
+
|
87
|
+
##### Chaging code folder
|
88
|
+
```ruby
|
89
|
+
sh do
|
90
|
+
puts pwd # => /Users/albertalef/projects/rubyshell
|
91
|
+
|
92
|
+
cd 'examples'
|
93
|
+
|
94
|
+
puts pwd # => /Users/albertalef/projects/rubyshell/examples
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
##### Executing code inside another folder
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
sh do
|
102
|
+
cd 'examples' do
|
103
|
+
puts pwd # => /Users/albertalef/projects/rubyshell/examples
|
104
|
+
end
|
105
|
+
|
106
|
+
puts pwd # => /Users/albertalef/projects/rubyshell
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
### Chaining commands
|
111
|
+
The `chain` method make possible we use shell operators inside the ruby, like `& && | > >> < <<`
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
sh do
|
115
|
+
chain { echo "Dummy text" >> "dummy.txt" }
|
116
|
+
|
117
|
+
puts cat("dummy.txt") # => "Dummy text"
|
118
|
+
end
|
119
|
+
|
120
|
+
sh do
|
121
|
+
number_of_files = chain { ls | wc('-l') }.chomp
|
122
|
+
|
123
|
+
puts number_of_files # => 5
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
## Complete example
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
#!/usr/bin/env ruby
|
131
|
+
|
132
|
+
require "rubyshell"
|
133
|
+
require "securerandom"
|
134
|
+
|
135
|
+
sh do
|
136
|
+
mkdir "files"
|
137
|
+
|
138
|
+
cd "files" do
|
139
|
+
5.times do |i|
|
140
|
+
chain do
|
141
|
+
echo(SecureRandom.alphanumeric(16)) >> "#{i}.txt"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
puts "Number of Files: #{ls.lines.count}"
|
146
|
+
|
147
|
+
ls.each_line do |filename|
|
148
|
+
puts cat(filename)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
ensure
|
152
|
+
rm "-rf files"
|
153
|
+
end
|
154
|
+
|
155
|
+
# Running:
|
156
|
+
#
|
157
|
+
# ❯ ./examples/example1.rb
|
158
|
+
#
|
159
|
+
# Number of Files: 5
|
160
|
+
# o6Kw8KHvWJnLGSeQ
|
161
|
+
# qkRKcZHqu2Moq1se
|
162
|
+
# nUPluln9GM1ydtoz
|
163
|
+
# rkdYsc1RBhkeN1dq
|
164
|
+
# ZPXZMqzYfyFfjPHF
|
165
|
+
```
|
166
|
+
|
167
|
+
## Coming
|
168
|
+
|
169
|
+
- Support to Streams
|
22
170
|
|
23
171
|
## Development
|
24
172
|
|
@@ -28,7 +176,13 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
28
176
|
|
29
177
|
## Contributing
|
30
178
|
|
31
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/albertalef/
|
179
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/albertalef/rubyshell. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/albertalef/rubyshell/blob/master/CODE_OF_CONDUCT.md).
|
180
|
+
|
181
|
+
## Sponsors
|
182
|
+
|
183
|
+
<a href="https://avantsoft.com.br">
|
184
|
+
<img alt="Avantsoft" src="./docs/images/LogoAvantsoft.png" width="40%">
|
185
|
+
</a>
|
32
186
|
|
33
187
|
## License
|
34
188
|
|
@@ -36,4 +190,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
36
190
|
|
37
191
|
## Code of Conduct
|
38
192
|
|
39
|
-
Everyone interacting in the Rubysh project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
193
|
+
Everyone interacting in the Rubysh project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/albertalef/rubyshell/blob/master/CODE_OF_CONDUCT.md).
|
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module RubyShell
|
3
4
|
class ChainContext
|
4
|
-
def self.method_missing(method_name, *args, &)
|
5
|
-
RubyShell::Chainer.new(RubyShell::Command.new(method_name, *(args << {_manual: true}), &))
|
5
|
+
def self.method_missing(method_name, *args, &block)
|
6
|
+
RubyShell::Chainer.new(RubyShell::Command.new(method_name, *(args << { _manual: true }), &block))
|
6
7
|
end
|
7
8
|
|
8
|
-
def self.respond_to_missing?(
|
9
|
+
def self.respond_to_missing?(_name, _include_private)
|
9
10
|
false
|
10
11
|
end
|
11
12
|
end
|
data/lib/rubyshell/chainer.rb
CHANGED
@@ -1,17 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module RubyShell
|
3
4
|
class Chainer
|
5
|
+
attr_reader :parts
|
6
|
+
|
4
7
|
def initialize(command)
|
5
8
|
@parts = [command]
|
6
9
|
end
|
7
10
|
|
8
11
|
def handle_chain(operator, chainer)
|
9
|
-
@parts = [
|
12
|
+
@parts = [
|
13
|
+
*@parts,
|
14
|
+
operator.to_s,
|
15
|
+
*(chainer.is_a?(RubyShell::Chainer) ? chainer.parts : chainer)
|
16
|
+
]
|
10
17
|
|
11
18
|
self
|
12
19
|
end
|
13
20
|
|
14
|
-
def method_missing(method_name, *args, &)
|
21
|
+
def method_missing(method_name, *args, &block)
|
15
22
|
if method_name.start_with?(/[^A-Za-z0-9]/)
|
16
23
|
handle_chain(method_name, args.first)
|
17
24
|
else
|
@@ -19,16 +26,12 @@ module RubyShell
|
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
|
-
def respond_to_missing?(
|
29
|
+
def respond_to_missing?(_name, _include_private)
|
23
30
|
false
|
24
31
|
end
|
25
32
|
|
26
33
|
def exec_commands
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def parts
|
31
|
-
@parts
|
34
|
+
`#{to_shell}`.chomp
|
32
35
|
end
|
33
36
|
|
34
37
|
def to_shell
|
data/lib/rubyshell/command.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RubyShell
|
2
4
|
class Command
|
3
5
|
def initialize(command_name, *args, &block)
|
@@ -22,21 +24,27 @@ module RubyShell
|
|
22
24
|
@args.map do |arg|
|
23
25
|
case arg
|
24
26
|
when Hash
|
25
|
-
arg
|
26
|
-
next if k.start_with?("_")
|
27
|
-
|
28
|
-
key = if k.length == 1
|
29
|
-
"-#{k}"
|
30
|
-
else
|
31
|
-
"--#{k}"
|
32
|
-
end
|
33
|
-
|
34
|
-
[key, v.is_a?(TrueClass) ? nil : v].compact.join(" ")
|
35
|
-
end.compact
|
27
|
+
map_hash_arg(arg)
|
36
28
|
else
|
37
29
|
arg.to_s
|
38
30
|
end
|
39
31
|
end.flatten
|
40
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def map_hash_arg(arg)
|
37
|
+
arg.map do |k, v|
|
38
|
+
next if k.start_with?("_")
|
39
|
+
|
40
|
+
key = if k.length == 1
|
41
|
+
"-#{k}"
|
42
|
+
else
|
43
|
+
"--#{k}"
|
44
|
+
end
|
45
|
+
|
46
|
+
[key, v.is_a?(TrueClass) ? nil : v].compact.join(" ")
|
47
|
+
end.compact
|
48
|
+
end
|
41
49
|
end
|
42
50
|
end
|
data/lib/rubyshell/executor.rb
CHANGED
@@ -1,11 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
module RubyShell
|
3
4
|
class Executor
|
4
|
-
def self.
|
5
|
-
|
5
|
+
def self.cd(path, &block)
|
6
|
+
Dir.chdir(path, &block)
|
6
7
|
end
|
7
8
|
|
8
|
-
def self.
|
9
|
+
def self.chain(&block)
|
10
|
+
result = RubyShell::ChainContext.class_eval(&block).exec_commands
|
11
|
+
|
12
|
+
raise "Command Failed" unless $?.success?
|
13
|
+
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.method_missing(method_name, *args)
|
18
|
+
RubyShell::Command.new(method_name, *args).exec_command
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.respond_to_missing?(_name, _include_private)
|
9
22
|
false
|
10
23
|
end
|
11
24
|
end
|
data/lib/rubyshell/version.rb
CHANGED
data/lib/rubyshell.rb
CHANGED
@@ -8,30 +8,10 @@ require_relative "rubyshell/executor"
|
|
8
8
|
|
9
9
|
module Kernel
|
10
10
|
def sh(&block)
|
11
|
-
if
|
12
|
-
RubyShell::Executor.class_eval(&block)
|
13
|
-
else
|
11
|
+
if block.nil?
|
14
12
|
RubyShell::Executor
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def sh_unsafe_mode(value)
|
19
|
-
@sh_unsafe_mode = value
|
20
|
-
end
|
21
|
-
|
22
|
-
def cd(path, &)
|
23
|
-
Dir.chdir(path, &)
|
24
|
-
end
|
25
|
-
|
26
|
-
def method_missing(method_name, *args, &)
|
27
|
-
if @sh_unsafe_mode
|
28
|
-
RubyShell::Executor.send(method_name.to_s.gsub('!', ''), *args, &)
|
29
13
|
else
|
30
|
-
|
14
|
+
RubyShell::Executor.class_eval(&block)
|
31
15
|
end
|
32
16
|
end
|
33
|
-
|
34
|
-
def chain(&)
|
35
|
-
RubyShell::ChainContext.class_eval(&).exec_commands
|
36
|
-
end
|
37
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyshell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- albertalef
|
@@ -33,6 +33,7 @@ metadata:
|
|
33
33
|
homepage_uri: https://github.com/albertalef/rubyshell
|
34
34
|
source_code_uri: https://github.com/albertalef/rubyshell
|
35
35
|
changelog_uri: https://github.com/albertalef/rubyshell
|
36
|
+
rubygems_mfa_required: 'true'
|
36
37
|
rdoc_options: []
|
37
38
|
require_paths:
|
38
39
|
- lib
|