cmds 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5caaa2f3116bf7e3a3d0d177334117a3877a0c30
4
+ data.tar.gz: a9c58cb91f4f58eec0317d6dadf19d5b645d9d74
5
+ SHA512:
6
+ metadata.gz: d1386ff56087d5031e83ec65e26e0582c551f0df1a7df48661448a046a4b04d5e1391f4133804762a17783b3daa982594227d48702a73e28567ac42c91fd7901
7
+ data.tar.gz: d8f87632411dca1a6195eafaf66f45ab0636190e4771a19a2e30bb6859a5d2725c860dd2c44be9867404efc0df0f9c5e808877eac019f3f43a0b6eae61846052
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ ref/repos
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # use local
4
+ gem 'nrser', '~> 0.0', :path => '../nrser-ruby'
5
+
6
+ # Specify your gem's dependencies in cmds.gemspec
7
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 nrser
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,333 @@
1
+ # cmds
2
+
3
+ cmds tries to make it easier to read, write and remember using shell commands in Ruby.
4
+
5
+ it treats generating shell the in a similar fashion to generating SQL or HTML.
6
+
7
+
8
+ ## status
9
+
10
+ eh, it's kinda starting to work... i'll be using it for stuff and seeing how it goes, but no promises until `1.0` of course.
11
+
12
+
13
+ ## installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```
18
+ gem 'cmds'
19
+ ```
20
+
21
+
22
+ And then execute:
23
+
24
+ ```
25
+ $ bundle
26
+ ```
27
+
28
+
29
+ Or install it yourself as:
30
+
31
+ ```
32
+ $ gem install cmds
33
+ ```
34
+
35
+
36
+
37
+ ## real-world examples
38
+
39
+ instead of
40
+
41
+ ```
42
+ `psql -U #{ db_config['username'] || ENV['USER'] } #{ db_config['database']} < #{ filepath.shellescape }`
43
+ ```
44
+
45
+ write
46
+
47
+ ```
48
+ Cmds 'psql %{opts} %{db} < %{dump}',
49
+ db: db_config['database'],
50
+ dump: filepath,
51
+ opts: {
52
+ username: db_config['username'] || ENV['USER']
53
+ }
54
+ ```
55
+
56
+ instead of
57
+
58
+ ```
59
+ `aws s3 sync s3://#{ PROD_APP_NAME } #{ s3_path.shellescape }`
60
+ ```
61
+
62
+ write
63
+
64
+ ```
65
+ Cmds 'aws s3 sync %{uri} %{path}', uri: "s3://#{ PROD_APP_NAME }"
66
+ path: s3_path
67
+ ```
68
+
69
+ instead of
70
+
71
+ ```
72
+ `PGPASSWORD=#{ config[:password].shellescape } pg_dump -U #{ config[:username].shellescape } -h #{ config[:host].shellescape } -p #{ config[:port] } #{ config[:database].shellescape } > #{ filepath.shellescape }`
73
+ ```
74
+
75
+ write
76
+
77
+ ```
78
+ Cmds 'PGPASSWORD=%{password} pg_dump %{opts} %{database} > %{filepath}',
79
+ password: config[:password],
80
+ database: config[:database],
81
+ filepath: filepath,
82
+ opts: {
83
+ username: config[:username],
84
+ host: config[:host],
85
+ port: config[:port],
86
+ }
87
+ ```
88
+
89
+
90
+
91
+ ## substitutions
92
+
93
+ substitutions can be positional, keyword, or both.
94
+
95
+ ### positional
96
+
97
+ positional arguments can be substituted in order using the `arg` method call:
98
+
99
+ ```
100
+ Cmds.sub "psql <%= arg %> <%= arg %> < <%= arg %>", [
101
+ {
102
+ username: "bingo bob",
103
+ host: "localhost",
104
+ port: 12345,
105
+ },
106
+ "blah",
107
+ "/where ever/it/is.psql",
108
+ ]
109
+ # => 'psql --host=localhost --port=12345 --username=bingo\ bob blah < /where\ ever/it/is.psql'
110
+ ```
111
+
112
+ internally this translates to calling `@args.fetch(@arg_index)` and increments `@arg_index` by 1.
113
+
114
+ this will raise an error if it's called after using the last positional argument, but will not complain if all positional arguments are not used. this prevents using a keyword arguments named `arg` without accessing the keywords hash directly.
115
+
116
+ the arguments may also be accessed directly though the bound class's `@args` instance variable:
117
+
118
+ ```
119
+ Cmds.sub "psql <%= @args[2] %> <%= @args[0] %> < <%= @args[1] %>", [
120
+ "blah",
121
+ "/where ever/it/is.psql",
122
+ {
123
+ username: "bingo bob",
124
+ host: "localhost",
125
+ port: 12345,
126
+ },
127
+ ]
128
+ # => 'psql --host=localhost --port=12345 --username=bingo\ bob blah < /where\ ever/it/is.psql'
129
+ ```
130
+
131
+ note that `@args` is a standard Ruby array and will simply return `nil` if there is no value at that index (though you can use `args.fetch(i)` to get the same behavior as the `arg` method with a specific index `i`).
132
+
133
+ ### keyword
134
+
135
+ keyword arguments can be accessed by making a method call with their key:
136
+
137
+ ```
138
+ Cmds.sub "psql <%= opts %> <%= database %> < <%= filepath %>",
139
+ [],
140
+ database: "blah",
141
+ filepath: "/where ever/it/is.psql",
142
+ opts: {
143
+ username: "bingo bob",
144
+ host: "localhost",
145
+ port: 12345,
146
+ }
147
+ # => 'psql --host=localhost --port=12345 --username=bingo\ bob blah < /where\ ever/it/is.psql'
148
+ ```
149
+
150
+ this translates to a call of `@kwds.fetch(key)`, which will raise an error if `key` isn't present.
151
+
152
+ there are four key names that may not be accessed this way due to method definition on the context object:
153
+
154
+ * `arg` (see above)
155
+ * `initialize`
156
+ * `get_binding`
157
+ * `method_missing`
158
+
159
+ though keys with those names may be accessed directly via `@kwds.fetch(key)` and the like.
160
+
161
+ to test for a key's presence or optionally include a value, append `?` to the method name:
162
+
163
+ ```
164
+ c = Cmds.new <<-BLOCK
165
+ defaults
166
+ <% if current_host? %>
167
+ -currentHost <%= current_host %>
168
+ <% end %>
169
+ export <%= domain %> <%= filepath %>
170
+ BLOCK
171
+
172
+ c.call domain: 'com.nrser.blah', filepath: '/tmp/export.plist'
173
+ # defaults export com.nrser.blah /tmp/export.plist
174
+
175
+ c.call current_host: 'xyz', domain: 'com.nrser.blah', filepath: '/tmp/export.plist'
176
+ # defaults -currentHost xyz export com.nrser.blah /tmp/export.plist
177
+ ```
178
+
179
+ ### both
180
+
181
+ both positional and keyword substitutions may be provided:
182
+
183
+ ```
184
+ Cmds.sub "psql <%= opts %> <%= arg %> < <%= filepath %>",
185
+ ["blah"],
186
+ filepath: "/where ever/it/is.psql",
187
+ opts: {
188
+ username: "bingo bob",
189
+ host: "localhost",
190
+ port: 12345,
191
+ }
192
+ # => 'psql --host=localhost --port=12345 --username=bingo\ bob blah < /where\ ever/it/is.psql'
193
+ ```
194
+
195
+ this might be useful if you have a simple positional command like
196
+
197
+ ```
198
+ Cmds "blah <%= arg %>", ["value"]
199
+ ```
200
+
201
+ and you want to quickly add in some optional value
202
+
203
+ ```
204
+ Cmds "blah <%= maybe? %> <%= arg %>", ["value"]
205
+ Cmds "blah <%= maybe? %> <%= arg %>", ["value"], maybe: "yes!"
206
+ ```
207
+
208
+ ### shortcuts
209
+
210
+ there are support for `sprintf`-style shortcuts.
211
+
212
+ **positional**
213
+
214
+ `%s` is replaced with `<%= arg %>`.
215
+
216
+ so
217
+
218
+ ```
219
+ Cmds.sub "./test/echo_cmd.rb %s", ["hello world!"]
220
+ ```
221
+
222
+ is the same as
223
+
224
+ ```
225
+ Cmds "./test/echo_cmd.rb <%= arg %>", ["hello world!"]
226
+ ```
227
+
228
+ **keyword**
229
+
230
+ `%{key}` and `%<key>s` are replaced with `<%= key %>`, and `%{key?}` and `%<key?>s` are replaced with `<%= key? %>` for optional keywords.
231
+
232
+ so
233
+
234
+ ```
235
+ Cmds "./test/echo_cmd.rb %{key}", key: "hello world!"
236
+ ```
237
+
238
+ and
239
+
240
+ ```
241
+ Cmds "./test/echo_cmd.rb %<key>s", key: "hello world!"
242
+ ```
243
+
244
+ are the same is
245
+
246
+ ```
247
+ Cmds "./test/echo_cmd.rb <%= key %>", key: "hello world!"
248
+ ```
249
+
250
+ **escaping**
251
+
252
+ strings that would be replaced as shortcuts can be escaped by adding one more `%` to the front of them:
253
+
254
+ ```
255
+ Cmds.sub "%%s" # => "%s"
256
+ Cmds.sub "%%%<key>s" # => "%%<key>s"
257
+ ```
258
+
259
+ note that unlike `sprintf`, which has a much more general syntax, this is only necessary for patterns that exactly match a shortcut, not `%` in general:
260
+
261
+ ```
262
+ Cmds.sub "50%" # => "50%"
263
+ ```
264
+
265
+
266
+
267
+ ## reuse commands
268
+
269
+ ```
270
+ playbook = Cmds.new "ansible-playbook -i %{inventory} %{playbook}"
271
+ playbook.call inventory: "./hosts", playbook: "blah.yml"
272
+ ```
273
+
274
+ currying
275
+
276
+ ```
277
+ dev_playbook = playbook.curry inventory: "inventory/dev"
278
+ prod_playbook = playbook.curry inventory: "inventory/prod"
279
+
280
+ # run setup.yml on the development hosts
281
+ dev_playbook.call playbook: "setup.yml"
282
+
283
+ # run setup.yml on the production hosts
284
+ prod_playbook.call playbook: "setup.yml"
285
+ ```
286
+
287
+
288
+
289
+ ## defaults
290
+
291
+ NEEDS TEST
292
+
293
+ can be accomplished with reuse and currying stuff
294
+
295
+ ```
296
+ playbook = Cmds.new "ansible-playbook -i %{inventory} %{playbook}", inventory: "inventory/dev"
297
+
298
+ # run setup.yml on the development hosts
299
+ playbook.call playbook: "setup.yml"
300
+
301
+ # run setup.yml on the production hosts
302
+ prod_playbook.call playbook: "setup.yml", inventory: "inventory/prod"
303
+ ```
304
+
305
+
306
+
307
+ ## future..?
308
+
309
+ ### formatters
310
+
311
+ kinda like `sprintf` formatters or string escape helpers in Rails, they would be exposed as functions in ERB and as format characters in the shorthand versions:
312
+
313
+ ```
314
+ Cmds "blah <%= j obj %>", obj: {x: 1}
315
+ # => blah \{\"x\":1\}
316
+
317
+ Cmds "blah %j", [{x: 1}]
318
+ # => blah \{\"x\":1\}
319
+
320
+ Cmds "blah %<obj>j", obj: {x: 1}
321
+ # => blah \{\"x\":1\}
322
+ ```
323
+
324
+ the `s` formatter would just format as an escaped string (no different from `<%= %>`).
325
+
326
+ other formatters could include
327
+
328
+ * `j` for JSON (as shown above)
329
+ * `r` for raw (unescaped)
330
+ * `l` or `,` for comma-separated list (which some commands like as input)
331
+ * `y` for YAML
332
+ * `p` for path, joining with `File.join`
333
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/ansible/dev.yml ADDED
@@ -0,0 +1,25 @@
1
+ ---
2
+ - hosts: localhost
3
+
4
+ vars:
5
+
6
+ ref_repos:
7
+ github:
8
+ - owner: rails
9
+ name: rails
10
+ version: master
11
+ dir_name: rails
12
+
13
+ tasks:
14
+
15
+ - name: install gems
16
+ command: bundle install --path=.bundle
17
+ args:
18
+ chdir: ..
19
+
20
+ - name: clone reference repos
21
+ git: repo=git@github.com:{{ item.owner }}/{{ item.name }}
22
+ dest="../ref/repos/{{ item.dir_name }}"
23
+ update=no
24
+ version={{ item.version }}
25
+ with_items: ref_repos.github
data/ansible/hosts ADDED
@@ -0,0 +1,6 @@
1
+ localhost ansible_connection=local
2
+
3
+ alamo.beiarea.com ansible_connection=ssh ansible_ssh_user=root
4
+
5
+ [production]
6
+ alamo.beiarea.com
data/cmds.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cmds/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cmds"
8
+ spec.version = Cmds::VERSION
9
+ spec.authors = ["nrser"]
10
+ spec.email = ["neil@ztkae.com"]
11
+ spec.summary = %q{helps read, write and remember commands.}
12
+ # spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'nrser', '~> 0.0.11'
22
+ spec.add_dependency 'erubis', '~> 2.7.0'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.5"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ end
@@ -0,0 +1,3 @@
1
+ class Cmds
2
+ VERSION = "0.0.1"
3
+ end