rushed 0.0.1 → 0.0.2

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: dae72683722b3ea17333d30989e8ae541ae4c2a1
4
- data.tar.gz: 96664f0b07656fe6e9f30ce50745585996ff95f0
3
+ metadata.gz: 9298010fb349cb3dbfcb5daf568877950fd6b740
4
+ data.tar.gz: 101d17cf9b43fec0d153e1feb9cf7329c26da798
5
5
  SHA512:
6
- metadata.gz: 6a67ad28873da7a143cf8a0dfbcabb90ee24ceafc3831430a299da80a957e2f39af8f6903045d7739baef13ba651a306a89a537d7e63de5c93449c5b7323fc38
7
- data.tar.gz: 8fb0d440a743c33457590277a46b3a9288d667f244decf3c7fb455387196b33a37f4c657cef3c327b2b53d89d9f34541eea5d97318d396c96f344e1ee6de4b9d
6
+ metadata.gz: 05113721883a37413444b9e1b637d1480acbc203f03392e676a78792df5f6c4b71db04aed32bb1d45fb4ab428d258c4680b151b54cd725ee3f7c6902aca55282
7
+ data.tar.gz: e44b016b715e39190bf28c0730b989cee82558213141a51aeb164827637ba59cda9350e917f320645b9c9266e5af5837163e5d2573487f0d69af8e13e836c2ae
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ Gemfile.lock
3
+ *.gem
4
+ log/*.log
5
+ .bundle/
6
+ pkg/
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ script: bundle exec rspec
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1
7
+ - 2.2
@@ -0,0 +1,7 @@
1
+ appraise "activesupport-3" do
2
+ gem "activesupport", "3.2.20"
3
+ end
4
+
5
+ appraise "activesupport-4" do
6
+ gem "activesupport", "4.1.7"
7
+ end
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Tom Benner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,253 @@
1
+ Rushed
2
+ =====
3
+ Ruby in your shell!
4
+
5
+ <img src="https://raw.github.com/tombenner/rushed/master/doc/logo.png" />
6
+
7
+ Overview
8
+ --------
9
+
10
+ Rushed brings Ruby's expressiveness, cleanliness, and readability to the command line.
11
+
12
+ It lets you avoid looking up pesky options in man pages and Googling how to write a transformation in bash that would take you approximately 1s to write in Ruby.
13
+
14
+ For example, to center a file's lines, use [String#center](http://ruby-doc.org/core-2.0/String.html#method-i-center):
15
+
16
+ ```bash
17
+ ru 'map(:center, 80)' myfile
18
+ ```
19
+
20
+ Using traditional tools, this isn't as easy or readable:
21
+
22
+ ```bash
23
+ awk 'printf "%" int(40+length($0)/2) "s\n", $0' myfile
24
+ ```
25
+
26
+ For another example, let's compare summing the lines of a list of integers using Rushed vs. a traditional approach:
27
+
28
+ ```bash
29
+ ru 'map(:to_i).sum' myfile
30
+ ```
31
+
32
+ ```bash
33
+ awk '{s+=$1} END {print s}' myfile
34
+ ```
35
+
36
+ Any method from Ruby Core and Active Support can be used. Rushed also provides some new methods to make transformations easier. Here are some variations on the above example:
37
+
38
+ ```bash
39
+ ru 'map(:to_i, 10).sum' myfile
40
+ ru 'map(:to_i).reduce(&:+)' myfile
41
+ ru 'each_line.to_i.to_a.sum' myfile
42
+ ru 'grep(/^\d+$/).map(:to_i).sum' myfile
43
+ ru 'reduce(0) { |sum, n| sum + n.to_i }' myfile
44
+ ru 'each_line.match(/(\d+)/)[1].to_i.to_a.sum' myfile
45
+ ```
46
+
47
+ See [Examples](#examples) and [Methods](#methods) for more.
48
+
49
+ Installation
50
+ ------------
51
+
52
+ ```bash
53
+ gem install rushed
54
+ ```
55
+
56
+ You can now use Ruby in your shell!
57
+
58
+ For example, to sum a list of integers:
59
+
60
+ ```bash
61
+ $ echo "2\n3" | ru 'map(:to_i).sum'
62
+ 5
63
+ ```
64
+
65
+ Usage
66
+ -----
67
+
68
+ See [Examples](#examples) below, too!
69
+
70
+ Rushed reads from stdin:
71
+
72
+ ```bash
73
+ $ echo "2\n3" | ru 'map(:to_i).sum'
74
+ 5
75
+ $ cat myfile | ru 'map(:to_i).sum'
76
+ 5
77
+ ```
78
+
79
+ Or from file(s):
80
+
81
+ ```bash
82
+ $ ru 'map(:to_i).sum' myfile
83
+ 5
84
+ $ ru 'map(:to_i).sum' myfile myfile
85
+ 10
86
+ ```
87
+
88
+ You can also run Ruby code without any input by prepending a `! `:
89
+
90
+ ```bash
91
+ $ ru '! 2 + 3'
92
+ 5
93
+ ```
94
+
95
+ In addition to the methods provided by Ruby Core and Active Support, Rushed provides other methods for performing transformations, like `each_line`, `files`, and `grep`. See [Methods](#methods) for more.
96
+
97
+ Examples
98
+ --------
99
+
100
+ Let's compare the readability and conciseness of Rushed relative to existing tools:
101
+
102
+ #### Center lines
103
+
104
+ ##### ru
105
+ ```bash
106
+ ru 'map(:center, 80)' myfile
107
+ ```
108
+
109
+ ##### awk
110
+ ```bash
111
+ awk 'printf "%" int(40+length($0)/2) "s\n", $0' myfile
112
+ ```
113
+
114
+ ##### sed
115
+ [Script](https://www.gnu.org/software/sed/manual/sed.html#Centering-lines)
116
+
117
+ #### Sum a list of integers
118
+
119
+ ##### ru
120
+ ```bash
121
+ ru 'map(:to_i).sum' myfile
122
+ ```
123
+
124
+ ##### awk
125
+ ```bash
126
+ awk '{s+=$1} END {print s}' myfile
127
+ ```
128
+
129
+ ##### paste
130
+ ```bash
131
+ paste -s -d+ myfile | bc
132
+ ```
133
+
134
+ #### Print the 5th line
135
+
136
+ ##### ru
137
+ ```bash
138
+ ru '[4]' myfile
139
+ ```
140
+
141
+ ##### sed
142
+ ```bash
143
+ sed '5q;d' myfile
144
+ ```
145
+
146
+ #### Print all lines except the first and last
147
+
148
+ ##### ru
149
+ ```bash
150
+ ru '[1..-2]' myfile
151
+ ```
152
+
153
+ ##### sed
154
+ ```bash
155
+ sed '1d;$d' myfile
156
+ ```
157
+
158
+ #### Sort an Apache access log by response time (decreasing, with time prepended)
159
+
160
+ ##### ru
161
+ ```bash
162
+ ru 'map { |line| [line[/(\d+)( ".+"){2}$/, 1].to_i, line] }.sort.reverse.map(:join, " ")' access.log
163
+ ```
164
+
165
+ ##### awk
166
+ ```bash
167
+ awk --re-interval '{ match($0, /(([^[:space:]]+|\[[^\]]+\]|"[^"]+")[[:space:]]+){7}/, m); print m[2], $0 }' access.log | sort -nk 1
168
+ ```
169
+ [Source](https://coderwall.com/p/ueazhw)
170
+
171
+ Methods
172
+ -------
173
+
174
+ In addition to the methods provided by Ruby Core and Active Support, Rushed provides other methods for performing transformations.
175
+
176
+ #### each_line
177
+
178
+ Provides a shorthand for calling methods on each iteration of the input. Best explained by example:
179
+
180
+ ```bash
181
+ ru 'each_line.strip.center(80)' myfile
182
+ ```
183
+
184
+ If you'd like to transform it back into a list, call `to_a`:
185
+
186
+ ```bash
187
+ ru 'each_line.strip.to_a.map(:center, 80)' myfile
188
+ ```
189
+
190
+ #### files
191
+
192
+ Converts the lines to `Rushed::File` objects (see Dotsch::File below).
193
+
194
+ ```bash
195
+ $ echo "foo.txt" | ru 'files.map(:updated_at).map(:strftime, ""%Y-%m-%d")'
196
+ 2014-11-08
197
+ ```
198
+
199
+ #### format(format='l')
200
+
201
+ Formats a list of `Dotsch::File`s. You'll typically call this after calling `files` to transform them into strings:
202
+
203
+ ```bash
204
+ $ ru 'files.format'
205
+ 644 tom staff 3 2014-10-26 09:06 bar.txt
206
+ 644 tom staff 11 2014-11-04 08:29 foo.txt
207
+ ```
208
+
209
+ The default format, `'l'`, is shown above. It prints `[omode, owner, group, size, date, name]`.
210
+
211
+ #### grep
212
+
213
+ Selects lines which match the given regex.
214
+
215
+ ```bash
216
+ $ echo "john\npaul\ngeorge" | ru 'grep(/o[h|r]/)'
217
+ john
218
+ george
219
+ ```
220
+
221
+ #### map
222
+
223
+ This is the same as `Array#map`, but it adds a new syntax that allows you to easily pass arguments to a method. For example:
224
+
225
+ ```bash
226
+ $ echo "john\npaul" | ru 'map(:[], 0)'
227
+ j
228
+ p
229
+ $ echo "john\npaul" | ru 'map(:center, 8, ".")'
230
+ ..john..
231
+ ..paul..
232
+ ```
233
+
234
+ Note that the examples above can also be performed with `each_line`:
235
+
236
+ ```bash
237
+ $ echo "john\npaul" | ru 'each_line[0]'
238
+ $ echo "john\npaul" | ru 'each_line.center(8, ".")'
239
+ ```
240
+
241
+ Testing
242
+ -------
243
+
244
+ Nested Hstore is tested against ActiveRecord 3 and 4. If you'd like to submit a PR, please be sure to use [Appraisal](https://github.com/thoughtbot/appraisal) to test your changes in both contexts:
245
+
246
+ ```bash
247
+ appraisal rspec
248
+ ```
249
+
250
+ License
251
+ -------
252
+
253
+ Rushed is released under the MIT License. Please see the MIT-LICENSE file for details.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "lib"
9
+ t.libs << "test"
10
+ t.test_files = FileList["test/**/*_test.rb"]
11
+ t.verbose = true
12
+ end
data/bin/ru ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/rushed'
4
+
5
+ begin
6
+ args = ARGV
7
+ command = args.shift
8
+ stdin = nil
9
+ # If the command starts with a '!', run it without stdin
10
+ if command.present? && command.start_with?('! ')
11
+ command = command[2..-1]
12
+ # If args is empty, read from stdin
13
+ elsif args.empty?
14
+ stdin = STDIN.read
15
+ end
16
+ process = Rushed::Process.new({
17
+ command: command,
18
+ args: args,
19
+ stdin: stdin
20
+ })
21
+ puts process.run
22
+ rescue => e
23
+ STDERR.puts e.message
24
+ STDERR.puts e.backtrace.join("\n")
25
+ exit 1
26
+ end
Binary file
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "3.2.20"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ rushed (0.0.1)
5
+ activesupport
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (3.2.20)
11
+ i18n (~> 0.6, >= 0.6.4)
12
+ multi_json (~> 1.0)
13
+ appraisal (1.0.2)
14
+ bundler
15
+ rake
16
+ thor (>= 0.14.0)
17
+ diff-lcs (1.2.5)
18
+ i18n (0.6.11)
19
+ multi_json (1.10.1)
20
+ rake (10.3.2)
21
+ rspec (3.1.0)
22
+ rspec-core (~> 3.1.0)
23
+ rspec-expectations (~> 3.1.0)
24
+ rspec-mocks (~> 3.1.0)
25
+ rspec-core (3.1.7)
26
+ rspec-support (~> 3.1.0)
27
+ rspec-expectations (3.1.2)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.1.0)
30
+ rspec-mocks (3.1.3)
31
+ rspec-support (~> 3.1.0)
32
+ rspec-support (3.1.2)
33
+ thor (0.19.1)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ activesupport (= 3.2.20)
40
+ appraisal
41
+ rspec
42
+ rushed!
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activesupport", "4.1.7"
6
+
7
+ gemspec :path => "../"
@@ -0,0 +1,49 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ rushed (0.0.1)
5
+ activesupport
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (4.1.7)
11
+ i18n (~> 0.6, >= 0.6.9)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.1)
15
+ tzinfo (~> 1.1)
16
+ appraisal (1.0.2)
17
+ bundler
18
+ rake
19
+ thor (>= 0.14.0)
20
+ diff-lcs (1.2.5)
21
+ i18n (0.6.11)
22
+ json (1.8.1)
23
+ minitest (5.4.2)
24
+ rake (10.3.2)
25
+ rspec (3.1.0)
26
+ rspec-core (~> 3.1.0)
27
+ rspec-expectations (~> 3.1.0)
28
+ rspec-mocks (~> 3.1.0)
29
+ rspec-core (3.1.7)
30
+ rspec-support (~> 3.1.0)
31
+ rspec-expectations (3.1.2)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.1.0)
34
+ rspec-mocks (3.1.3)
35
+ rspec-support (~> 3.1.0)
36
+ rspec-support (3.1.2)
37
+ thor (0.19.1)
38
+ thread_safe (0.3.4)
39
+ tzinfo (1.2.2)
40
+ thread_safe (~> 0.1)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ activesupport (= 4.1.7)
47
+ appraisal
48
+ rspec
49
+ rushed!
@@ -0,0 +1,7 @@
1
+ require 'active_support/all'
2
+
3
+ directory = File.dirname(File.absolute_path(__FILE__))
4
+ Dir.glob("#{directory}/rushed/*.rb") { |file| require file }
5
+
6
+ module Rushed
7
+ end
@@ -0,0 +1,86 @@
1
+ module Rushed
2
+ class Array
3
+ def initialize(array)
4
+ @data = array.to_a
5
+ end
6
+
7
+ def each_line
8
+ Rushed::Iterator.new(self)
9
+ end
10
+
11
+ def files
12
+ @data.map! do |line|
13
+ Rushed::File.new(line)
14
+ end
15
+ self
16
+ end
17
+
18
+ def format(format='l')
19
+ @data.map! do |item|
20
+ item.format(format)
21
+ end
22
+ self
23
+ end
24
+
25
+ def grep(pattern)
26
+ if pattern.kind_of?(String)
27
+ pattern = Regexp.new(pattern)
28
+ end
29
+ select! do |item|
30
+ item.to_s =~ pattern
31
+ end
32
+ self
33
+ end
34
+
35
+ def map(method=nil, *args, &block)
36
+ if method.nil? && !block_given?
37
+ to_a.map
38
+ elsif method.nil?
39
+ array = to_a.map(&block)
40
+ self.class.new(array)
41
+ else
42
+ array = to_a.map { |item| item.send(method, *args) }
43
+ self.class.new(array)
44
+ end
45
+ end
46
+
47
+ def select(*args, &block)
48
+ delegate_to_array(:select, *args, &block)
49
+ end
50
+
51
+ def to_stdout
52
+ self
53
+ end
54
+
55
+ def to_a
56
+ @data
57
+ end
58
+
59
+ def to_ary
60
+ to_a
61
+ end
62
+
63
+ def to_s
64
+ self.to_a.join("\n")
65
+ end
66
+
67
+ def ==(other)
68
+ self.to_a == other.to_a
69
+ end
70
+
71
+ def method_missing(method, *args, &block)
72
+ delegate_to_array(method, *args, &block)
73
+ end
74
+
75
+ private
76
+
77
+ def delegate_to_array(method, *args, &block)
78
+ result = to_a.send(method, *args, &block)
79
+ if result.kind_of?(Enumerable)
80
+ self.class.new(result)
81
+ else
82
+ result
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,94 @@
1
+ require 'etc'
2
+
3
+ module Rushed
4
+ class File
5
+ def initialize(path)
6
+ @path = path
7
+ end
8
+
9
+ def basename
10
+ delegate_to_file(:basename)
11
+ end
12
+
13
+ def ctime
14
+ delegate_to_file(:ctime)
15
+ end
16
+
17
+ def extname
18
+ delegate_to_file(:extname)
19
+ end
20
+
21
+ def format(format='l')
22
+ separator = "\t"
23
+ case format
24
+ when 'l'
25
+ datetime = ctime.strftime(%w{%Y-%m-%d %H:%M}.join(separator))
26
+ return [omode, owner, group, size, datetime, name].join(separator)
27
+ else
28
+ raise 'format not supported'
29
+ end
30
+ end
31
+
32
+ def ftype
33
+ delegate_to_file(:ftype)
34
+ end
35
+
36
+ def gid
37
+ delegate_to_stat(:gid)
38
+ end
39
+
40
+ def group
41
+ Etc.getgrgid(gid).name
42
+ end
43
+
44
+ def mode
45
+ delegate_to_stat(:mode)
46
+ end
47
+
48
+ def mtime
49
+ delegate_to_file(:mtime)
50
+ end
51
+
52
+ def omode
53
+ '%o' % world_readable?
54
+ end
55
+
56
+ def owner
57
+ Etc.getpwuid(uid).name
58
+ end
59
+
60
+ def size
61
+ delegate_to_file(:size)
62
+ end
63
+
64
+ def to_s
65
+ name
66
+ end
67
+
68
+ def uid
69
+ delegate_to_stat(:uid)
70
+ end
71
+
72
+ def world_readable?
73
+ delegate_to_stat(:world_readable?)
74
+ end
75
+
76
+ def <=>(other)
77
+ name <=> other.name
78
+ end
79
+
80
+ alias_method :name, :basename
81
+ alias_method :created_at, :ctime
82
+ alias_method :updated_at, :mtime
83
+
84
+ private
85
+
86
+ def delegate_to_file(method)
87
+ ::File.send(method, @path)
88
+ end
89
+
90
+ def delegate_to_stat(method)
91
+ ::File.stat(@path).send(method)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,44 @@
1
+ module Rushed
2
+ class Iterator
3
+ class << self
4
+ def redefined_methods
5
+ @redefined_methods ||= begin
6
+ preserved_methods = %{initialize method_missing respond_to? to_a}
7
+ [].public_methods.select do |method|
8
+ method = method.to_s
9
+ method =~ /^[a-z]/ && !preserved_methods.include?(method)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ def initialize(array)
16
+ @array = array
17
+ end
18
+
19
+ def to_a
20
+ Rushed::Array.new(@array)
21
+ end
22
+
23
+ def to_dotsch_output
24
+ to_a.join("\n")
25
+ end
26
+
27
+ private
28
+
29
+ def method_missing(method, *args, &block)
30
+ map_method(method, *args, &block)
31
+ end
32
+
33
+ def map_method(method, *args, &block)
34
+ @array.map! { |item| item.send(method, *args, &block) }
35
+ self
36
+ end
37
+
38
+ redefined_methods.each do |method|
39
+ define_method(method) do |*args|
40
+ map_method(method, *args)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ module Rushed
2
+ class Process
3
+ def initialize(options={})
4
+ @command = options[:command]
5
+ @args = options[:args]
6
+ @stdin = options[:stdin]
7
+ if @command.kind_of?(String) && @command.start_with?('[')
8
+ @command = 'to_stdout' + @command
9
+ end
10
+ end
11
+
12
+ def run
13
+ paths = @args
14
+ if @stdin.blank? && paths.present?
15
+ @stdin = paths.map { |path| ::File.open(path).read }.join("\n")
16
+ end
17
+ lines = @stdin.present? ? @stdin.split("\n") : []
18
+ array = Rushed::Array.new(lines)
19
+ output = array.instance_eval(@command) || @stdin
20
+ if output.respond_to?(:to_dotsch_output)
21
+ output = output.to_dotsch_output
22
+ end
23
+ if output.kind_of?(::Array)
24
+ output = output.join("\n")
25
+ end
26
+ output.to_s
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Rushed
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../lib/rushed/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.authors = ['Tom Benner']
5
+ s.email = ['tombenner@gmail.com']
6
+ s.description = s.summary = %q{Ruby in your shell!}
7
+ s.homepage = 'https://github.com/tombenner/rushed'
8
+
9
+ s.files = `git ls-files`.split($\)
10
+ s.name = 'rushed'
11
+ s.executables = ['ru']
12
+ s.require_paths = ['lib']
13
+ s.version = Rushed::VERSION
14
+ s.license = 'MIT'
15
+
16
+ s.add_dependency 'activesupport'
17
+
18
+ s.add_development_dependency 'appraisal'
19
+ s.add_development_dependency 'rspec'
20
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'misc examples' do
4
+ include FixturesHelper
5
+ include ProcessHelper
6
+
7
+ # http://stackoverflow.com/questions/450799/shell-command-to-sum-integers-one-per-line
8
+ context "summing integers" do
9
+ it "sums" do
10
+ lines = (1..10).to_a.map(&:to_s)
11
+ out = run(lines, 'map(:to_i).sum')
12
+ out.should == '55'
13
+ end
14
+ end
15
+
16
+ # http://stackoverflow.com/questions/6022384/bash-tool-to-get-nth-line-from-a-file
17
+ context "printing the nth line" do
18
+ it "prints" do
19
+ lines = (1..10).to_a.map(&:to_s)
20
+ out = run(lines, '[4]')
21
+ out.should == '5'
22
+ end
23
+ end
24
+
25
+ # https://coderwall.com/p/ueazhw
26
+ context "sorting an Apache access log by response time" do
27
+ it "sorts" do
28
+ file = fixture_path('files', 'access.log')
29
+ out = run('', 'map { |line| [line[/(\d+)( ".+"){2}$/, 1].to_i, line] }.sort.reverse.map(:join, " ")', file)
30
+ out.should == <<-EOF.strip
31
+ 584912 66.249.64.14 - - [18/Sep/2004:11:07:48 +1000] "GET /file.txt HTTP/1.0" 200 584912 "-" "Googlebot/2.1"
32
+ 6433 66.249.64.14 - - [18/Sep/2004:11:07:48 +1000] "GET / HTTP/1.0" 200 6433 "-" "Googlebot/2.1"
33
+ 6433 66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET / HTTP/1.0" 200 6433 "-" "Googlebot/2.1"
34
+ 468 66.249.64.14 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
35
+ 468 66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
36
+ EOF
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ # https://www.gnu.org/software/sed/manual/sed.html#Examples
4
+ describe 'sed examples' do
5
+ include FixturesHelper
6
+ include ProcessHelper
7
+
8
+ context "centering lines" do
9
+ it "centers" do
10
+ lines = %w{john paul george} + [' ringo ']
11
+ out = run(lines, 'each_line.strip.center(10)')
12
+ out.should == " john \n paul \n george \n ringo "
13
+ end
14
+ end
15
+
16
+ context "increment a number" do
17
+ it "increments" do
18
+ lines = ('5'..'10').to_a
19
+ out = run(lines, '(each_line.to_i+1)')
20
+ out.should == ('6'..'11').to_a.join("\n")
21
+ end
22
+ end
23
+
24
+ context "reverse characters of lines" do
25
+ it "reverses" do
26
+ lines = %w{john paul george ringo}
27
+ out = run(lines, 'each_line.reverse')
28
+ out.should == "nhoj\nluap\negroeg\nognir"
29
+ end
30
+ end
31
+
32
+ context "numbering lines" do
33
+ it "numbers" do
34
+ lines = %w{john paul george ringo}
35
+ out = run(lines, 'map.with_index { |line, index| "#{(index+1).to_s.rjust(6)} #{line}" }')
36
+ out.should == " 1 john\n 2 paul\n 3 george\n 4 ringo"
37
+ end
38
+ end
39
+
40
+ context "counting lines" do
41
+ it "counts" do
42
+ lines = %w{john paul george ringo}
43
+ out = run(lines, 'length')
44
+ out.should == "4"
45
+ end
46
+ end
47
+
48
+ context "printing the first lines" do
49
+ it "prints" do
50
+ lines = %w{john paul george ringo}
51
+ out = run(lines, '[0,2]')
52
+ out.should == "john\npaul"
53
+ end
54
+ end
55
+
56
+ context "printing the last lines" do
57
+ it "prints" do
58
+ lines = %w{john paul george ringo}
59
+ out = run(lines, '[2..-1]')
60
+ out.should == "george\nringo"
61
+ end
62
+ end
63
+
64
+ context "make duplicate lines unique" do
65
+ it "dedupes" do
66
+ lines = %w{john john paul george george george ringo}
67
+ out = run(lines, 'uniq')
68
+ out.should == "john\npaul\ngeorge\nringo"
69
+ end
70
+ end
71
+
72
+ context "print duplicated lines of input" do
73
+ it "prints" do
74
+ lines = %w{john john paul george george george ringo}
75
+ out = run(lines, 'select { |line| self.count(line) > 1 }')
76
+ out.should == "john\njohn\ngeorge\ngeorge\ngeorge"
77
+ end
78
+ end
79
+
80
+ context "remove all duplicated lines" do
81
+ it "removes" do
82
+ lines = %w{john john paul george george george ringo}
83
+ out = run(lines, 'select { |line| self.count(line) == 1 }')
84
+ out.should == "paul\nringo"
85
+ end
86
+ end
87
+
88
+ context "squeezing blank lines" do
89
+ it "squeezes" do
90
+ lines = "john\n\npaul\ngeorge\n\n\nringo"
91
+ out = run(lines, 'to_s.squeeze("\n")')
92
+ out.should == "john\npaul\ngeorge\nringo"
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,5 @@
1
+ 66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
2
+ 66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET / HTTP/1.0" 200 6433 "-" "Googlebot/2.1"
3
+ 66.249.64.14 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
4
+ 66.249.64.14 - - [18/Sep/2004:11:07:48 +1000] "GET / HTTP/1.0" 200 6433 "-" "Googlebot/2.1"
5
+ 66.249.64.14 - - [18/Sep/2004:11:07:48 +1000] "GET /file.txt HTTP/1.0" 200 584912 "-" "Googlebot/2.1"
@@ -0,0 +1 @@
1
+ bar
@@ -0,0 +1,3 @@
1
+ foo
2
+ foo
3
+ foo
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rushed::Array do
4
+ describe "Array method" do
5
+ it "returns a Rushed::Array" do
6
+ array = described_class.new(%w{john paul george ringo})
7
+ array.sort.should be_a(Rushed::Array)
8
+ end
9
+ end
10
+
11
+ describe "#each_line" do
12
+ it "calls to_s" do
13
+ array = described_class.new((1..3).to_a)
14
+ array.each_line.to_s.to_a.should == described_class.new(('1'..'3'))
15
+ end
16
+
17
+ it "calls methods with arguments" do
18
+ array = described_class.new((1..3).to_a)
19
+ array.each_line.modulo(2).to_a.should == [1, 0, 1]
20
+ end
21
+ end
22
+
23
+ describe "#map" do
24
+ it "takes one argument" do
25
+ array = described_class.new(%w{john paul george ringo})
26
+ array.map(:reverse).should == %w{nhoj luap egroeg ognir}
27
+ end
28
+ it "takes two arguments" do
29
+ array = described_class.new(%w{john paul george ringo})
30
+ array.map(:[], 0).should == %w{j p g r}
31
+ end
32
+
33
+ it "returns a Rushed::Array" do
34
+ array = described_class.new(%w{john paul george ringo})
35
+ array.map(:[], 0).should be_a(Rushed::Array)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rushed::Iterator do
4
+ describe "#to_a" do
5
+ it "returns the array" do
6
+ iterator = described_class.new(%w{john paul george ringo})
7
+ iterator.to_a.should == %w{john paul george ringo}
8
+ end
9
+ end
10
+
11
+ describe "#to_dotsch_output" do
12
+ it "returns the string" do
13
+ iterator = described_class.new(%w{john paul george ringo})
14
+ iterator.to_dotsch_output.should == "john\npaul\ngeorge\nringo"
15
+ end
16
+
17
+ context "with a method called on it" do
18
+ it "returns the string" do
19
+ iterator = described_class.new(%w{john paul george ringo})
20
+ iterator.to_s.to_dotsch_output.should == "john\npaul\ngeorge\nringo"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rushed::Process do
4
+ include FixturesHelper
5
+ include ProcessHelper
6
+
7
+ describe "#run" do
8
+ it "runs []" do
9
+ lines = %w{john paul george ringo}
10
+ out = run(lines, '[1,2]')
11
+ out.should == "paul\ngeorge"
12
+ end
13
+
14
+ it "runs files" do
15
+ paths = [
16
+ fixture_path('files', 'bar.txt'),
17
+ fixture_path('files', 'foo.txt')
18
+ ]
19
+ out = run(paths, 'files')
20
+ out.should == "bar.txt\nfoo.txt"
21
+ end
22
+
23
+ it "runs format" do
24
+ paths = [
25
+ fixture_path('files', 'bar.txt'),
26
+ fixture_path('files', 'foo.txt')
27
+ ]
28
+ out = run(paths, "files.format('l')")
29
+ lines = out.split("\n")
30
+ lines.length.should == 2
31
+ lines.each do |line|
32
+ # 644 tom staff 11 2014-11-04 08:29 foo.txt
33
+ line.should =~ /^\d{3}\t\w+\t\w+\t\d+\t\d{4}\-\d{2}-\d{2}\t\d{2}:\d{2}\t[\w\.]+$/
34
+ end
35
+ end
36
+
37
+ it "runs grep" do
38
+ lines = %w{john paul george ringo}
39
+ out = run(lines, "grep(/o[h|r]/)")
40
+ out.should == "john\ngeorge"
41
+ end
42
+
43
+ it "runs map with two arguments" do
44
+ lines = %w{john paul george ringo}
45
+ out = run(lines, 'map(:[], 0)')
46
+ out.should == %w{j p g r}.join("\n")
47
+ end
48
+
49
+ it "runs sort" do
50
+ lines = %w{john paul george ringo}
51
+ out = run(lines, 'sort')
52
+ out.should == lines.sort.join("\n")
53
+ end
54
+
55
+ it "takes files as arguments" do
56
+ out = run('', 'to_s', fixture_path('files', 'foo.txt'))
57
+ out.should == "foo\nfoo\nfoo"
58
+ end
59
+
60
+ context "an undefined method" do
61
+ it "raises a NoMethodError" do
62
+ lines = %w{john paul george ringo}
63
+ expect { out = run(lines, 'foo') }.to raise_error(NoMethodError)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ require 'rushed'
2
+
3
+ require 'support/fixtures_helper'
4
+ require 'support/process_helper'
5
+
6
+ RSpec.configure do |config|
7
+ # ## Mock Framework
8
+ #
9
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
10
+ #
11
+ # config.mock_with :mocha
12
+ # config.mock_with :flexmock
13
+ # config.mock_with :rr
14
+
15
+ # Run specs in random order to surface order dependencies. If you find an
16
+ # order dependency and want to debug it, you can fix the order by providing
17
+ # the seed, which is printed after each run.
18
+ # --seed 1234
19
+ config.order = "random"
20
+ end
@@ -0,0 +1,6 @@
1
+ module FixturesHelper
2
+ def fixture_path(*args)
3
+ directory = Pathname.new(File.dirname(File.absolute_path(__FILE__)))
4
+ directory.join('..', 'fixtures', *args)
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ module ProcessHelper
2
+ def run(stdin, *args)
3
+ if stdin.kind_of?(Array)
4
+ stdin = stdin.join("\n")
5
+ end
6
+ command = args.shift
7
+ process = Rushed::Process.new({
8
+ command: command,
9
+ args: args,
10
+ stdin: stdin
11
+ })
12
+ process.run
13
+ end
14
+ end
metadata CHANGED
@@ -1,52 +1,96 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rushed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Benner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-27 00:00:00.000000000 Z
11
+ date: 2014-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: appraisal
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - '>='
31
+ - - ">="
18
32
  - !ruby/object:Gem::Version
19
33
  version: '0'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - '>='
38
+ - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - '>='
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
47
  version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - '>='
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
- description: ''
55
+ description: Ruby in your shell!
42
56
  email:
43
57
  - tombenner@gmail.com
44
- executables: []
58
+ executables:
59
+ - ru
45
60
  extensions: []
46
61
  extra_rdoc_files: []
47
62
  files:
48
- - lib/dotsh.rb
49
- - lib/dotsh/version.rb
63
+ - ".gitignore"
64
+ - ".travis.yml"
65
+ - Appraisals
66
+ - Gemfile
67
+ - MIT-LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - bin/ru
71
+ - doc/logo.png
72
+ - gemfiles/activesupport_3.gemfile
73
+ - gemfiles/activesupport_3.gemfile.lock
74
+ - gemfiles/activesupport_4.gemfile
75
+ - gemfiles/activesupport_4.gemfile.lock
76
+ - lib/rushed.rb
77
+ - lib/rushed/array.rb
78
+ - lib/rushed/file.rb
79
+ - lib/rushed/iterator.rb
80
+ - lib/rushed/process.rb
81
+ - lib/rushed/version.rb
82
+ - rushed.gemspec
83
+ - spec/examples/misc_examples_spec.rb
84
+ - spec/examples/sed_examples_spec.rb
85
+ - spec/fixtures/files/access.log
86
+ - spec/fixtures/files/bar.txt
87
+ - spec/fixtures/files/foo.txt
88
+ - spec/lib/array_spec.rb
89
+ - spec/lib/iterator_spec.rb
90
+ - spec/lib/process_spec.rb
91
+ - spec/spec_helper.rb
92
+ - spec/support/fixtures_helper.rb
93
+ - spec/support/process_helper.rb
50
94
  homepage: https://github.com/tombenner/rushed
51
95
  licenses:
52
96
  - MIT
@@ -57,12 +101,12 @@ require_paths:
57
101
  - lib
58
102
  required_ruby_version: !ruby/object:Gem::Requirement
59
103
  requirements:
60
- - - '>='
104
+ - - ">="
61
105
  - !ruby/object:Gem::Version
62
106
  version: '0'
63
107
  required_rubygems_version: !ruby/object:Gem::Requirement
64
108
  requirements:
65
- - - '>='
109
+ - - ">="
66
110
  - !ruby/object:Gem::Version
67
111
  version: '0'
68
112
  requirements: []
@@ -70,6 +114,5 @@ rubyforge_project:
70
114
  rubygems_version: 2.2.2
71
115
  signing_key:
72
116
  specification_version: 4
73
- summary: ''
117
+ summary: Ruby in your shell!
74
118
  test_files: []
75
- has_rdoc:
@@ -1,5 +0,0 @@
1
- directory = File.dirname(File.absolute_path(__FILE__))
2
- Dir.glob("#{directory}/dotsh/*.rb") { |file| require file }
3
-
4
- module Dotsh
5
- end
@@ -1,3 +0,0 @@
1
- module Dotsh
2
- VERSION = '0.0.1'
3
- end