pcut 0.0.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.
- data/.gemtest +0 -0
- data/History.txt +4 -0
- data/Manifest.txt +24 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +46 -0
- data/Rakefile +28 -0
- data/bin/pcut +63 -0
- data/lib/pcut.rb +6 -0
- data/lib/pcut/cli.rb +154 -0
- data/lib/pcut/line_parser.rb +95 -0
- data/lib/pcut/query.rb +37 -0
- data/lib/pcut/range_collector.rb +31 -0
- data/lib/pcut/range_index.rb +59 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/lib/pcut/cli_spec.rb +50 -0
- data/spec/lib/pcut/line_parser_spec.rb +223 -0
- data/spec/lib/pcut/query_spec.rb +45 -0
- data/spec/lib/pcut/range_collector_spec.rb +65 -0
- data/spec/lib/pcut/range_index_spec.rb +76 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/rspec.rake +20 -0
- data/test +1 -0
- metadata +155 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
bin/pcut
|
7
|
+
lib/pcut.rb
|
8
|
+
lib/pcut/cli.rb
|
9
|
+
lib/pcut/line_parser.rb
|
10
|
+
lib/pcut/query.rb
|
11
|
+
lib/pcut/range_collector.rb
|
12
|
+
lib/pcut/range_index.rb
|
13
|
+
script/console
|
14
|
+
script/destroy
|
15
|
+
script/generate
|
16
|
+
spec/lib/pcut/cli_spec.rb
|
17
|
+
spec/lib/pcut/line_parser_spec.rb
|
18
|
+
spec/lib/pcut/query_spec.rb
|
19
|
+
spec/lib/pcut/range_collector_spec.rb
|
20
|
+
spec/lib/pcut/range_index_spec.rb
|
21
|
+
spec/spec.opts
|
22
|
+
spec/spec_helper.rb
|
23
|
+
tasks/rspec.rake
|
24
|
+
test
|
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
= pcut
|
2
|
+
|
3
|
+
* http://github.com/bonar/pcut
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Yet another cutting tool.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
== SYNOPSIS:
|
12
|
+
|
13
|
+
FIX (code sample of usage)
|
14
|
+
|
15
|
+
== REQUIREMENTS:
|
16
|
+
|
17
|
+
term-ansicolor
|
18
|
+
|
19
|
+
== INSTALL:
|
20
|
+
|
21
|
+
sudo gem install pcut
|
22
|
+
|
23
|
+
== LICENSE:
|
24
|
+
|
25
|
+
(The MIT License)
|
26
|
+
|
27
|
+
Copyright (c) 2012 Nakano Kyohei
|
28
|
+
|
29
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
30
|
+
a copy of this software and associated documentation files (the
|
31
|
+
'Software'), to deal in the Software without restriction, including
|
32
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
33
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
34
|
+
permit persons to whom the Software is furnished to do so, subject to
|
35
|
+
the following conditions:
|
36
|
+
|
37
|
+
The above copyright notice and this permission notice shall be
|
38
|
+
included in all copies or substantial portions of the Software.
|
39
|
+
|
40
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
41
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
42
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
43
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
44
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
45
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
46
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
require 'fileutils'
|
5
|
+
require './lib/pcut'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'pcut' do
|
14
|
+
self.developer 'Nakano Kyohei (bonar)', 'bonar@me.com'
|
15
|
+
# self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
16
|
+
self.rubyforge_name = self.name # TODO this is default value
|
17
|
+
self.extra_deps = [
|
18
|
+
['term-ansicolor','>= 1.0.7']
|
19
|
+
]
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'newgem/tasks'
|
24
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
25
|
+
|
26
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
27
|
+
# remove_task :default
|
28
|
+
# task :default => [:spec, :features]
|
data/bin/pcut
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'pcut'
|
6
|
+
require 'pcut/cli'
|
7
|
+
|
8
|
+
cli = Pcut::CLI.new
|
9
|
+
|
10
|
+
opt = OptionParser.new
|
11
|
+
opt.version = Pcut::VERSION
|
12
|
+
|
13
|
+
opt.on('-d DELIMITER', 'cut delimiter (tab is the default)') do |v|
|
14
|
+
cli.delimiter = v
|
15
|
+
cli.joiner = v
|
16
|
+
end
|
17
|
+
# opt.on('-j JOIN', 'specifies char used to join cut result') do
|
18
|
+
# end
|
19
|
+
opt.on('-f FIELD',
|
20
|
+
"FIELD specifies the list of field to pickup.",
|
21
|
+
"example)",
|
22
|
+
" single field: -f 2,3,4",
|
23
|
+
" range: -f 2- / -f -3",
|
24
|
+
" sub query: -f \"2.[/ /, 4].[/./, 2]\""
|
25
|
+
) do |v|
|
26
|
+
fields = cli.parse_field(v)
|
27
|
+
cli.fields = fields
|
28
|
+
end
|
29
|
+
opt.on('-q QUOTE', '--quote QUOTE',
|
30
|
+
'QUOTE specifies quoting characters. If quoting characters are specified,',
|
31
|
+
'quoted strings are treated as one string (not separated).',
|
32
|
+
'Variations:',
|
33
|
+
' - D: double quote',
|
34
|
+
' - S: single quote',
|
35
|
+
' - [: []',
|
36
|
+
' - (: ()',
|
37
|
+
'You can specify multiple quotes like: "-q DS[("'
|
38
|
+
) do |v|
|
39
|
+
cli.quote = v
|
40
|
+
end
|
41
|
+
opt.on('-k', '--keep-quote', 'not delete quote chars') do
|
42
|
+
cli.keep_quote = true
|
43
|
+
end
|
44
|
+
opt.on('-p', '--preview', 'show field number header') do
|
45
|
+
cli.preview = true
|
46
|
+
end
|
47
|
+
opt.on('-t', '--vertical', 'print cut result vertically') do
|
48
|
+
cli.vertical = true
|
49
|
+
end
|
50
|
+
opt.on('-n', '--no-color', 'turn colot output off') do
|
51
|
+
cli.color = false
|
52
|
+
end
|
53
|
+
|
54
|
+
begin
|
55
|
+
opt.parse!(ARGV)
|
56
|
+
rescue => e
|
57
|
+
$stderr.puts e.to_s
|
58
|
+
exit(1)
|
59
|
+
end
|
60
|
+
|
61
|
+
Signal.trap(:INT) { exit(0) }
|
62
|
+
cli.start(ARGV.shift)
|
63
|
+
|
data/lib/pcut.rb
ADDED
data/lib/pcut/cli.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'term/ansicolor'
|
4
|
+
require 'pcut/line_parser'
|
5
|
+
require 'pcut/range_index'
|
6
|
+
require 'pcut/range_collector'
|
7
|
+
require 'pcut/query'
|
8
|
+
|
9
|
+
module Pcut
|
10
|
+
|
11
|
+
class CLI
|
12
|
+
include Term::ANSIColor
|
13
|
+
|
14
|
+
attr_accessor \
|
15
|
+
:delimiter,
|
16
|
+
:joiner,
|
17
|
+
:fields,
|
18
|
+
:quote,
|
19
|
+
:keep_quote,
|
20
|
+
:preview,
|
21
|
+
:vertical,
|
22
|
+
:color
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@delimiter = "\t"
|
26
|
+
@joiner = @delimiter
|
27
|
+
@fields = []
|
28
|
+
@quote = nil
|
29
|
+
@keep_quote = false
|
30
|
+
@preview = false
|
31
|
+
@vertical = false
|
32
|
+
@color = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_field(str)
|
36
|
+
targets = []
|
37
|
+
|
38
|
+
begin
|
39
|
+
field_parser = Pcut::LineParser.new
|
40
|
+
field_parser.set_delimiter(",")
|
41
|
+
field_parser.set_quote_guard("[")
|
42
|
+
field_parser.keep_quotes = true
|
43
|
+
fields = field_parser.parse(str)
|
44
|
+
|
45
|
+
fields.each do |field|
|
46
|
+
index = nil
|
47
|
+
queries = []
|
48
|
+
|
49
|
+
query_parser = Pcut::LineParser.new
|
50
|
+
query_parser.set_delimiter(".")
|
51
|
+
query_parser.set_quote_guard("[")
|
52
|
+
query_parser.keep_quotes = true
|
53
|
+
|
54
|
+
if field =~ /\./
|
55
|
+
result = query_parser.parse(field)
|
56
|
+
first = result.shift
|
57
|
+
index = Pcut::RangeIndex.parse(first)
|
58
|
+
result.each do |query_str|
|
59
|
+
queries << Pcut::Query.parse(query_str)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
index = Pcut::RangeIndex.parse(field)
|
63
|
+
end
|
64
|
+
targets << [index, queries]
|
65
|
+
end
|
66
|
+
rescue => e
|
67
|
+
STDOUT.puts e.to_s
|
68
|
+
exit(1)
|
69
|
+
end
|
70
|
+
targets
|
71
|
+
end
|
72
|
+
|
73
|
+
def start(filepath)
|
74
|
+
begin
|
75
|
+
parser = Pcut::LineParser.new
|
76
|
+
parser.set_delimiter(@delimiter)
|
77
|
+
@quote.each_char { |c| parser.set_quote_guard(c) } if @quote
|
78
|
+
parser.keep_quotes = true if @keep_quote
|
79
|
+
rescue => e
|
80
|
+
STDOUT.puts e.to_s
|
81
|
+
exit(1)
|
82
|
+
end
|
83
|
+
|
84
|
+
io = nil
|
85
|
+
if filepath
|
86
|
+
begin
|
87
|
+
if File.directory?(filepath)
|
88
|
+
raise ArgumentError, "#{filepath} is directory"
|
89
|
+
end
|
90
|
+
io = File.open(filepath, 'r')
|
91
|
+
rescue => e
|
92
|
+
$stdout.puts e.to_s
|
93
|
+
exit(1)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
io ||= STDIN
|
97
|
+
io.each_line do |line|
|
98
|
+
line.chomp!
|
99
|
+
buff = [] # selected fields
|
100
|
+
result = parser.parse(line)
|
101
|
+
|
102
|
+
joiner = @vertical ? "\n" : @joiner
|
103
|
+
|
104
|
+
# apply -f fields specification
|
105
|
+
# (value pickup)
|
106
|
+
if !@fields.empty?
|
107
|
+
@fields.each do |setting|
|
108
|
+
index = setting[0]
|
109
|
+
queries = setting[1]
|
110
|
+
value = Pcut::RangeCollector.collect(result, index).join(@joiner)
|
111
|
+
if queries.empty?
|
112
|
+
buff << index_labeL(index.index) + (value || "")
|
113
|
+
else
|
114
|
+
queries.each do |query|
|
115
|
+
last if value.nil?
|
116
|
+
sliced = Pcut::RangeCollector.collect(
|
117
|
+
value.split(query.delimiter), query.index)
|
118
|
+
value = sliced.join(query.delimiter)
|
119
|
+
end
|
120
|
+
buff << query_label(index.index, queries.size) + (value || "")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
# no @fields is "all the fields"
|
124
|
+
else
|
125
|
+
result.each_with_index do |field, index|
|
126
|
+
buff << index_labeL(index + 1) + (field || "")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
puts buff.join(joiner)
|
131
|
+
puts "" if @vertical
|
132
|
+
end
|
133
|
+
exit(0)
|
134
|
+
end
|
135
|
+
|
136
|
+
def index_labeL(index)
|
137
|
+
return "" unless @preview
|
138
|
+
(@color ? red : '') + "[" +
|
139
|
+
(@color ? yellow : '' ) + "#{index}" +
|
140
|
+
(@color ? red : '') + "]" + (@color ? reset : '')
|
141
|
+
end
|
142
|
+
|
143
|
+
def query_label(index, query_size)
|
144
|
+
return "" unless @preview
|
145
|
+
(@color ? red : '') + "[" +
|
146
|
+
(@color ? yellow : '' ) + "#{index}" +
|
147
|
+
(@color ? green : '' ) + "+#{query_size}" +
|
148
|
+
(@color ? red : '') + "]" + (@color ? reset : '')
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
|
2
|
+
module Pcut
|
3
|
+
|
4
|
+
class LineParser
|
5
|
+
|
6
|
+
DOUBLE_QUOTE = "\""
|
7
|
+
SINGLE_QUOTE = "'"
|
8
|
+
|
9
|
+
QUOTES = {
|
10
|
+
DOUBLE_QUOTE => [DOUBLE_QUOTE, DOUBLE_QUOTE],
|
11
|
+
SINGLE_QUOTE => [SINGLE_QUOTE, SINGLE_QUOTE],
|
12
|
+
"D" => [DOUBLE_QUOTE, DOUBLE_QUOTE], # shortcut
|
13
|
+
"S" => [SINGLE_QUOTE, SINGLE_QUOTE], # shortcut
|
14
|
+
"[" => ["[", "]"],
|
15
|
+
"(" => ["(", ")"],
|
16
|
+
"<" => ["<", ">"]
|
17
|
+
}
|
18
|
+
DELIMITER = "\t"
|
19
|
+
|
20
|
+
attr_reader :quote_guard
|
21
|
+
attr_accessor :keep_quotes
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@quote_guard = {}
|
25
|
+
@delimiter = DELIMITER
|
26
|
+
@keep_quotes = false # do not delete quoting chars
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_quote_guard(quote)
|
30
|
+
unless QUOTES.has_key?(quote)
|
31
|
+
raise ArgumentError, "invalid quote: #{quote}"
|
32
|
+
end
|
33
|
+
@quote_guard[QUOTES[quote].first] = QUOTES[quote]
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_delimiter(char)
|
37
|
+
if !char.is_a?(String) || char.size != 1
|
38
|
+
raise ArgumentError, "invalid delimiter: #{char.to_s}"
|
39
|
+
end
|
40
|
+
@delimiter = char
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse(str)
|
44
|
+
buffer = nil
|
45
|
+
previous_char = nil
|
46
|
+
current_quote = nil
|
47
|
+
finalizer = nil
|
48
|
+
partials = []
|
49
|
+
|
50
|
+
str.each_char do |c|
|
51
|
+
|
52
|
+
# check starting quote
|
53
|
+
if @quote_guard.include?(c) &&
|
54
|
+
previous_char != "\\" # not escaped
|
55
|
+
starter = @quote_guard[c].first
|
56
|
+
|
57
|
+
if !current_quote && c == starter
|
58
|
+
current_quote = c
|
59
|
+
finalizer = @quote_guard[c].last
|
60
|
+
if @keep_quotes
|
61
|
+
buffer ||= ""
|
62
|
+
buffer += c
|
63
|
+
end
|
64
|
+
next
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# check end of quote
|
69
|
+
if current_quote && c == finalizer
|
70
|
+
current_quote = nil
|
71
|
+
finalizer = nil
|
72
|
+
if @keep_quotes
|
73
|
+
buffer ||= ""
|
74
|
+
buffer += c
|
75
|
+
end
|
76
|
+
next
|
77
|
+
end
|
78
|
+
|
79
|
+
if !current_quote && c == @delimiter
|
80
|
+
partials << buffer
|
81
|
+
buffer = nil
|
82
|
+
elsif current_quote || c != @delimiter
|
83
|
+
buffer ||= ""
|
84
|
+
buffer += c
|
85
|
+
end
|
86
|
+
previous_char = c
|
87
|
+
end
|
88
|
+
partials << buffer if buffer
|
89
|
+
partials
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
data/lib/pcut/query.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'pcut/range_index'
|
3
|
+
|
4
|
+
module Pcut
|
5
|
+
|
6
|
+
class Query
|
7
|
+
|
8
|
+
FORMAT = %r{\A\s*\[\s*/\\?(.)/\s*,\s*([0-9\-]+)\s*\]\z}
|
9
|
+
|
10
|
+
attr_accessor :delimiter, :index
|
11
|
+
|
12
|
+
def initialize(delimiter, index)
|
13
|
+
if !delimiter.is_a?(String) || delimiter.size != 1
|
14
|
+
raise ArgumentError, "invalid delimiter: #{delimiter}"
|
15
|
+
end
|
16
|
+
if !index.is_a?(Pcut::RangeIndex)
|
17
|
+
raise ArgumentError, "index must be a RangeIndex: #{index}"
|
18
|
+
end
|
19
|
+
|
20
|
+
@delimiter = delimiter
|
21
|
+
@index = index
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse(str)
|
25
|
+
unless str.is_a?(String)
|
26
|
+
raise ArgumentError, "#{str.to_s} is not a string"
|
27
|
+
end
|
28
|
+
unless str =~ FORMAT
|
29
|
+
raise ArgumentError, "invalid format: #{str}"
|
30
|
+
end
|
31
|
+
index = Pcut::RangeIndex.parse($2)
|
32
|
+
self.new($1, index)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
require 'pcut/range_index'
|
3
|
+
|
4
|
+
module Pcut
|
5
|
+
|
6
|
+
class RangeCollector
|
7
|
+
|
8
|
+
def self.collect(array, range_index)
|
9
|
+
unless array.is_a?(Array)
|
10
|
+
raise ArgumentError, "#{array.to_s} is not an array"
|
11
|
+
end
|
12
|
+
unless range_index.is_a?(Pcut::RangeIndex)
|
13
|
+
raise ArgumentError, "#{range_index.to_s} is not a range_index"
|
14
|
+
end
|
15
|
+
|
16
|
+
return [] if array.empty?
|
17
|
+
array_index = range_index.index - 1
|
18
|
+
|
19
|
+
if range_index.include_backward?
|
20
|
+
array[0..array_index]
|
21
|
+
elsif range_index.include_forward?
|
22
|
+
array[array_index..-1]
|
23
|
+
else
|
24
|
+
value = array[array_index]
|
25
|
+
value ? [value] : []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
module Pcut
|
3
|
+
|
4
|
+
class RangeIndex
|
5
|
+
|
6
|
+
FORMAT = %r/\A\s*(\-)?(\d+)(\-)?\s*\z/
|
7
|
+
|
8
|
+
attr_reader :index
|
9
|
+
|
10
|
+
def initialize(index, backward, forward)
|
11
|
+
unless index.is_a?(Fixnum)
|
12
|
+
raise ArgumentError, "invalid index: #{index}"
|
13
|
+
end
|
14
|
+
unless backward == true || backward == false
|
15
|
+
raise ArgumentError, "invalid backward spec: #{backward}"
|
16
|
+
end
|
17
|
+
unless forward == true || forward == false
|
18
|
+
raise ArgumentError, "invalid forward spec: #{forward}"
|
19
|
+
end
|
20
|
+
|
21
|
+
@index = index
|
22
|
+
@backward = backward
|
23
|
+
@forward = forward
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.parse(str)
|
27
|
+
unless str.is_a?(String)
|
28
|
+
raise ArgumentError, "#{str.to_s} is not string"
|
29
|
+
end
|
30
|
+
unless str =~ FORMAT
|
31
|
+
raise ArgumentError, "invalid range index expression: #{str}"
|
32
|
+
end
|
33
|
+
|
34
|
+
backward = $1 ? true : false
|
35
|
+
forward = $3 ? true : false
|
36
|
+
index = $2.to_i
|
37
|
+
|
38
|
+
if backward && forward
|
39
|
+
raise ArgumentError, "backward, forward both specified: #{str}"
|
40
|
+
end
|
41
|
+
if 0 == index
|
42
|
+
raise ArgumentError, "zero cannot be specified: #{str}"
|
43
|
+
end
|
44
|
+
|
45
|
+
self.new(index, backward, forward)
|
46
|
+
end
|
47
|
+
|
48
|
+
def include_backward?
|
49
|
+
@backward
|
50
|
+
end
|
51
|
+
|
52
|
+
def include_forward?
|
53
|
+
@forward
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/pcut.rb'}"
|
9
|
+
puts "Loading pcut gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
require 'pcut/cli'
|
3
|
+
|
4
|
+
describe Pcut::CLI do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@cli = Pcut::CLI.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'parse_field' do
|
11
|
+
|
12
|
+
it 'can parse single index' do
|
13
|
+
targets = @cli.parse_field("3")
|
14
|
+
targets.size.should == 1
|
15
|
+
targets[0][0].index.should == 3
|
16
|
+
targets[0][1].should == []
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'can parse multi index' do
|
20
|
+
targets = @cli.parse_field("-4,5-")
|
21
|
+
targets.size.should == 2
|
22
|
+
targets[0][0].index.should == 4
|
23
|
+
targets[0][1].should == []
|
24
|
+
targets[1][0].index.should == 5
|
25
|
+
targets[1][1].should == []
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can parse index with sub queries' do
|
29
|
+
targets = @cli.parse_field("-4,3.[/ /,4].[/,/,12].[/./,-2],5-")
|
30
|
+
targets.size.should == 3
|
31
|
+
targets[0][0].index.should == 4
|
32
|
+
targets[0][1].should == []
|
33
|
+
|
34
|
+
targets[1][0].index.should == 3
|
35
|
+
targets[1][1].size.should == 3
|
36
|
+
targets[1][1][0].delimiter.should == " "
|
37
|
+
targets[1][1][0].index.index.should == 4
|
38
|
+
targets[1][1][1].delimiter.should == ","
|
39
|
+
targets[1][1][1].index.index.should == 12
|
40
|
+
targets[1][1][2].delimiter.should == "."
|
41
|
+
targets[1][1][2].index.index.should == 2
|
42
|
+
|
43
|
+
targets[2][0].index.should == 5
|
44
|
+
targets[2][1].should == []
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,223 @@
|
|
1
|
+
|
2
|
+
require 'pcut/line_parser'
|
3
|
+
|
4
|
+
describe Pcut::LineParser do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@parser = Pcut::LineParser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'can parse plain line' do
|
11
|
+
result = @parser.parse("foo\tbar\tbuz")
|
12
|
+
result.size.should == 3
|
13
|
+
result[0].should == "foo"
|
14
|
+
result[1].should == "bar"
|
15
|
+
result[2].should == "buz"
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns empty array for empty string' do
|
19
|
+
@parser.parse("").should == []
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns one element array for string without delimiter' do
|
23
|
+
str = "string_without_delimiter"
|
24
|
+
@parser.parse(str).should == [str]
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'can handle continuous delimiters' do
|
28
|
+
result = @parser.parse("one\t\ttwo\t\t\tthree")
|
29
|
+
result.size.should == 6
|
30
|
+
result[0].should == "one"
|
31
|
+
result[1].should == nil
|
32
|
+
result[2].should == "two"
|
33
|
+
result[3].should == nil
|
34
|
+
result[4].should == nil
|
35
|
+
result[5].should == "three"
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'cares about pre/post delimiters' do
|
39
|
+
result = @parser.parse("\t\tfolk\tspoon\t\t\t")
|
40
|
+
result[0].should == nil
|
41
|
+
result[1].should == nil
|
42
|
+
result[2].should == "folk"
|
43
|
+
result[3].should == "spoon"
|
44
|
+
result[4].should == nil
|
45
|
+
result[5].should == nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'can change delimiter' do
|
49
|
+
result = @parser.parse("foo\tbar\thoge,fuga")
|
50
|
+
result.should == ["foo", "bar", "hoge,fuga"]
|
51
|
+
|
52
|
+
@parser.set_delimiter(",")
|
53
|
+
result = @parser.parse("foo bar hoge,fuga")
|
54
|
+
result.should == ["foo bar hoge", "fuga"]
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'raise error with invalid delimiter' do
|
58
|
+
lambda {
|
59
|
+
@parser.set_delimiter(nil)
|
60
|
+
}.should raise_error(ArgumentError)
|
61
|
+
|
62
|
+
lambda {
|
63
|
+
@parser.set_delimiter("")
|
64
|
+
}.should raise_error(ArgumentError)
|
65
|
+
|
66
|
+
lambda {
|
67
|
+
@parser.set_delimiter("ab")
|
68
|
+
}.should raise_error(ArgumentError)
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'quote guard' do
|
72
|
+
|
73
|
+
it 'can set_quote_guard' do
|
74
|
+
@parser.set_quote_guard(Pcut::LineParser::DOUBLE_QUOTE)
|
75
|
+
@parser.quote_guard.keys.sort.should == [
|
76
|
+
Pcut::LineParser::DOUBLE_QUOTE]
|
77
|
+
|
78
|
+
@parser.set_quote_guard(Pcut::LineParser::SINGLE_QUOTE)
|
79
|
+
@parser.quote_guard.keys.sort.should == [
|
80
|
+
Pcut::LineParser::DOUBLE_QUOTE,
|
81
|
+
Pcut::LineParser::SINGLE_QUOTE
|
82
|
+
]
|
83
|
+
@parser.set_quote_guard("[")
|
84
|
+
@parser.quote_guard.keys.sort.should == [
|
85
|
+
Pcut::LineParser::DOUBLE_QUOTE,
|
86
|
+
Pcut::LineParser::SINGLE_QUOTE,
|
87
|
+
"["
|
88
|
+
]
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'understands quoter shortcuts' do
|
92
|
+
@parser.set_quote_guard("D")
|
93
|
+
@parser.set_delimiter(" ")
|
94
|
+
result = @parser.parse("foo \"bar baz\" hoge")
|
95
|
+
result.should == [
|
96
|
+
"foo",
|
97
|
+
"bar baz",
|
98
|
+
"hoge"
|
99
|
+
]
|
100
|
+
@parser.set_quote_guard("S")
|
101
|
+
result = @parser.parse("foo 'bar baz' hoge")
|
102
|
+
result.should == [
|
103
|
+
"foo",
|
104
|
+
"bar baz",
|
105
|
+
"hoge"
|
106
|
+
]
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'can keep quotes' do
|
110
|
+
@parser.keep_quotes.should be_false
|
111
|
+
|
112
|
+
@parser.set_delimiter(" ")
|
113
|
+
@parser.set_quote_guard("[")
|
114
|
+
result = @parser.parse("foo bar [hoge fuga] baz")
|
115
|
+
result.should == ["foo", "bar", "hoge fuga", "baz"]
|
116
|
+
|
117
|
+
@parser.keep_quotes = true
|
118
|
+
result = @parser.parse("foo bar [hoge fuga] baz")
|
119
|
+
result.should == ["foo", "bar", "[hoge fuga]", "baz"]
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'raises error if quote letter is invalid' do
|
123
|
+
lambda {
|
124
|
+
@parser.set_quote_guard("A")
|
125
|
+
}.should raise_error(ArgumentError)
|
126
|
+
|
127
|
+
lambda {
|
128
|
+
@parser.set_quote_guard()
|
129
|
+
}.should raise_error(ArgumentError)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'can parse line with quote guard' do
|
133
|
+
@parser.set_quote_guard(Pcut::LineParser::DOUBLE_QUOTE)
|
134
|
+
@parser.set_delimiter(" ")
|
135
|
+
@parser.parse('172cm 62kg "Nakano Kyohei" Male')\
|
136
|
+
.should == ['172cm', '62kg', 'Nakano Kyohei', 'Male']
|
137
|
+
|
138
|
+
@parser.set_quote_guard("(")
|
139
|
+
@parser.parse('Foo (Bar, Buz) Hoge')\
|
140
|
+
.should == ['Foo', 'Bar, Buz', 'Hoge']
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'can parse line with multiple quote guard' do
|
144
|
+
@parser.set_quote_guard(Pcut::LineParser::DOUBLE_QUOTE)
|
145
|
+
@parser.set_delimiter(" ")
|
146
|
+
@parser.set_quote_guard("(")
|
147
|
+
@parser.set_quote_guard("[")
|
148
|
+
result = @parser.parse(
|
149
|
+
'Bonar "Nakano Kyohei" [Software Engineer] (172 62)')
|
150
|
+
result = [
|
151
|
+
"Bonar",
|
152
|
+
"Nakano Kyohei",
|
153
|
+
"Software Engineer",
|
154
|
+
"172 62"
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'ignores quotes which is not specified' do
|
159
|
+
@parser.set_quote_guard("(")
|
160
|
+
@parser.set_delimiter(" ")
|
161
|
+
result = @parser.parse("\"Nakano Kyohei\" (172 62)")
|
162
|
+
result.should == [
|
163
|
+
'"Nakano',
|
164
|
+
'Kyohei"',
|
165
|
+
'172 62'
|
166
|
+
]
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'treat quoting char as normal char in quoted section' do
|
170
|
+
@parser.set_quote_guard(Pcut::LineParser::DOUBLE_QUOTE)
|
171
|
+
@parser.set_quote_guard(Pcut::LineParser::SINGLE_QUOTE)
|
172
|
+
@parser.set_quote_guard("(")
|
173
|
+
@parser.set_delimiter(" ")
|
174
|
+
|
175
|
+
result = @parser.parse("123 \"Nakano 'aka bonar' Kyohei (32)\" engineer")
|
176
|
+
result.should == [
|
177
|
+
"123",
|
178
|
+
"Nakano 'aka bonar' Kyohei (32)",
|
179
|
+
"engineer"
|
180
|
+
]
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
describe 'real world sample' do
|
186
|
+
|
187
|
+
before(:each) do
|
188
|
+
@sample1 = '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326'
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'case 1' do
|
192
|
+
@parser.set_delimiter(" ")
|
193
|
+
result = @parser.parse(@sample1)
|
194
|
+
result[0].should == '127.0.0.1'
|
195
|
+
result[1].should == '-'
|
196
|
+
result[2].should == 'frank'
|
197
|
+
result[3].should == '[10/Oct/2000:13:55:36'
|
198
|
+
result[4].should == '-0700]'
|
199
|
+
result[5].should == '"GET'
|
200
|
+
result[6].should == '/apache_pb.gif'
|
201
|
+
result[7].should == 'HTTP/1.0"'
|
202
|
+
result[8].should == '200'
|
203
|
+
result[9].should == '2326'
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'case 1 with quoting' do
|
207
|
+
@parser.set_delimiter(" ")
|
208
|
+
@parser.set_quote_guard("\"")
|
209
|
+
@parser.set_quote_guard("[")
|
210
|
+
result = @parser.parse(@sample1)
|
211
|
+
result[0].should == '127.0.0.1'
|
212
|
+
result[1].should == '-'
|
213
|
+
result[2].should == 'frank'
|
214
|
+
result[3].should == '10/Oct/2000:13:55:36 -0700'
|
215
|
+
result[4].should == 'GET /apache_pb.gif HTTP/1.0'
|
216
|
+
result[5].should == '200'
|
217
|
+
result[6].should == '2326'
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
require 'pcut/query'
|
3
|
+
|
4
|
+
describe Pcut::Query do
|
5
|
+
|
6
|
+
it 'can be initialized with delimiter and range index' do
|
7
|
+
query = Pcut::Query.new(" ", Pcut::RangeIndex.parse("-2"))
|
8
|
+
query.delimiter.should == " "
|
9
|
+
query.index.index.should == 2
|
10
|
+
query.index.include_backward?.should be_true
|
11
|
+
query.index.include_forward?.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'can parse query string' do
|
15
|
+
query = Pcut::Query.parse(%q|[/ /, -23]|)
|
16
|
+
query.delimiter.should == " "
|
17
|
+
query.index.index.should == 23
|
18
|
+
query.index.include_backward?.should be_true
|
19
|
+
query.index.include_forward?.should be_false
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'allows white speces on parsing' do
|
23
|
+
query = Pcut::Query.parse(%q|[ /// , 456- ]|)
|
24
|
+
query.delimiter.should == "/"
|
25
|
+
query.index.index.should == 456
|
26
|
+
query.index.include_backward?.should be_false
|
27
|
+
query.index.include_forward?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises error on bad delimiter' do
|
31
|
+
# empty string
|
32
|
+
lambda { Pcut::Query.parse(%q|[//, -23]|) }.
|
33
|
+
should raise_error(ArgumentError, %r/invalid format/)
|
34
|
+
# 2 letters string
|
35
|
+
lambda { Pcut::Query.parse(%q|[/ /, -23]|) }.
|
36
|
+
should raise_error(ArgumentError, %r/invalid format/)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises error on bad index expression' do
|
40
|
+
lambda { Pcut::Query.parse(%q|[/ /, 0]|) }.
|
41
|
+
should raise_error(ArgumentError, %r/zero/)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'implements to_s'
|
45
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
require 'pcut/range_collector'
|
3
|
+
|
4
|
+
describe Pcut::RangeCollector do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'collects values with range index' do
|
11
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("1")).
|
12
|
+
should == [1]
|
13
|
+
|
14
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("5")).
|
15
|
+
should == [5]
|
16
|
+
|
17
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("10")).
|
18
|
+
should == [10]
|
19
|
+
|
20
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("11")).
|
21
|
+
should == []
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'collects values with backward range index' do
|
25
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("-1")).
|
26
|
+
should == [1]
|
27
|
+
|
28
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("-4")).
|
29
|
+
should == [1, 2, 3, 4]
|
30
|
+
|
31
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("-8")).
|
32
|
+
should == [1, 2, 3, 4, 5, 6, 7, 8]
|
33
|
+
|
34
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("-10")).
|
35
|
+
should == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
36
|
+
|
37
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("-11")).
|
38
|
+
should == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'collects values with forward range index' do
|
42
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("1-")).
|
43
|
+
should == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
44
|
+
|
45
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("5-")).
|
46
|
+
should == [5, 6, 7, 8, 9, 10]
|
47
|
+
|
48
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("10-")).
|
49
|
+
should == [10]
|
50
|
+
|
51
|
+
Pcut::RangeCollector.collect(@array, Pcut::RangeIndex.parse("11-")).
|
52
|
+
should == []
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'raises error on invalid input' do
|
56
|
+
lambda {
|
57
|
+
Pcut::RangeCollector.collect(nil, Pcut::RangeIndex.parse("5-"))
|
58
|
+
}.should raise_error(ArgumentError, %r/not an array/)
|
59
|
+
|
60
|
+
lambda { Pcut::RangeCollector.collect(nil, 5) }.
|
61
|
+
should raise_error(ArgumentError, %r/not an array/)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
require 'pcut/range_index'
|
3
|
+
|
4
|
+
describe Pcut::RangeIndex do
|
5
|
+
|
6
|
+
it 'can create instance with new' do
|
7
|
+
index = Pcut::RangeIndex.new(1, true, false)
|
8
|
+
index.index.should == 1
|
9
|
+
index.include_backward?.should be_true
|
10
|
+
index.include_forward?.should be_false
|
11
|
+
|
12
|
+
index = Pcut::RangeIndex.new(2, false, true)
|
13
|
+
index.index.should == 2
|
14
|
+
index.include_backward?.should be_false
|
15
|
+
index.include_forward?.should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'raises error on invalid index, backward or forward' do
|
19
|
+
lambda { Pcut::RangeIndex.new(nil, true, true) }.
|
20
|
+
should raise_error(ArgumentError, %r/invalid index/)
|
21
|
+
|
22
|
+
lambda { Pcut::RangeIndex.new(1, "true", true) }.
|
23
|
+
should raise_error(ArgumentError, %r/invalid backward/)
|
24
|
+
|
25
|
+
lambda { Pcut::RangeIndex.new(1, true, "true") }.
|
26
|
+
should raise_error(ArgumentError, %r/invalid forward/)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can parse single index string' do
|
30
|
+
index = Pcut::RangeIndex.parse("123")
|
31
|
+
index.index.should == 123
|
32
|
+
index.include_backward?.should be_false
|
33
|
+
index.include_forward?.should be_false
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'can parse index string including backward' do
|
37
|
+
index = Pcut::RangeIndex.parse("-92")
|
38
|
+
index.index.should == 92
|
39
|
+
index.include_backward?.should be_true
|
40
|
+
index.include_forward?.should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'can parse index string including forward' do
|
44
|
+
index = Pcut::RangeIndex.parse("4-")
|
45
|
+
index.index.should == 4
|
46
|
+
index.include_backward?.should be_false
|
47
|
+
index.include_forward?.should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'raises error on string including both backward and forward' do
|
51
|
+
lambda { index = Pcut::RangeIndex.parse("-5-") }.
|
52
|
+
should raise_error(ArgumentError, %r/both specified/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'raises error on zero index' do
|
56
|
+
lambda { index = Pcut::RangeIndex.parse("0") }.
|
57
|
+
should raise_error(ArgumentError, %r/zero/)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'ignores white spaces arround the target' do
|
61
|
+
Pcut::RangeIndex.parse(" 321 ").index.should == 321
|
62
|
+
Pcut::RangeIndex.parse(" -72 ").index.should == 72
|
63
|
+
Pcut::RangeIndex.parse(" 90- ").index.should == 90
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises error on invalid string' do
|
67
|
+
lambda { Pcut::RangeIndex.parse(nil) }.
|
68
|
+
should raise_error(ArgumentError, %r/not string/)
|
69
|
+
|
70
|
+
lambda { Pcut::RangeIndex.parse("1-1") }.
|
71
|
+
should raise_error(ArgumentError, %r/invalid range index expression/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'implements to_s'
|
75
|
+
|
76
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
begin
|
2
|
+
require 'rspec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
require 'rspec'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
rescue LoadError
|
10
|
+
puts <<-EOS
|
11
|
+
To use rspec for testing you must install rspec gem:
|
12
|
+
gem install rspec
|
13
|
+
EOS
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
18
|
+
t.rspec_opts = ['--options=' "spec/spec.opts"]
|
19
|
+
end
|
20
|
+
|
data/test
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pcut
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Nakano Kyohei (bonar)
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-04-14 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: term-ansicolor
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 25
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 0
|
32
|
+
- 7
|
33
|
+
version: 1.0.7
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rdoc
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 19
|
45
|
+
segments:
|
46
|
+
- 3
|
47
|
+
- 10
|
48
|
+
version: "3.10"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: newgem
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 5
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 5
|
63
|
+
- 3
|
64
|
+
version: 1.5.3
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: hoe
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 7
|
76
|
+
segments:
|
77
|
+
- 3
|
78
|
+
- 0
|
79
|
+
version: "3.0"
|
80
|
+
type: :development
|
81
|
+
version_requirements: *id004
|
82
|
+
description: Yet another cutting tool.
|
83
|
+
email:
|
84
|
+
- bonar@me.com
|
85
|
+
executables:
|
86
|
+
- pcut
|
87
|
+
extensions: []
|
88
|
+
|
89
|
+
extra_rdoc_files:
|
90
|
+
- History.txt
|
91
|
+
- Manifest.txt
|
92
|
+
- PostInstall.txt
|
93
|
+
- README.rdoc
|
94
|
+
files:
|
95
|
+
- History.txt
|
96
|
+
- Manifest.txt
|
97
|
+
- PostInstall.txt
|
98
|
+
- README.rdoc
|
99
|
+
- Rakefile
|
100
|
+
- bin/pcut
|
101
|
+
- lib/pcut.rb
|
102
|
+
- lib/pcut/cli.rb
|
103
|
+
- lib/pcut/line_parser.rb
|
104
|
+
- lib/pcut/query.rb
|
105
|
+
- lib/pcut/range_collector.rb
|
106
|
+
- lib/pcut/range_index.rb
|
107
|
+
- script/console
|
108
|
+
- script/destroy
|
109
|
+
- script/generate
|
110
|
+
- spec/lib/pcut/cli_spec.rb
|
111
|
+
- spec/lib/pcut/line_parser_spec.rb
|
112
|
+
- spec/lib/pcut/query_spec.rb
|
113
|
+
- spec/lib/pcut/range_collector_spec.rb
|
114
|
+
- spec/lib/pcut/range_index_spec.rb
|
115
|
+
- spec/spec.opts
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- tasks/rspec.rake
|
118
|
+
- test
|
119
|
+
- .gemtest
|
120
|
+
homepage: http://github.com/bonar/pcut
|
121
|
+
licenses: []
|
122
|
+
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options:
|
125
|
+
- --main
|
126
|
+
- README.rdoc
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
hash: 3
|
135
|
+
segments:
|
136
|
+
- 0
|
137
|
+
version: "0"
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
hash: 3
|
144
|
+
segments:
|
145
|
+
- 0
|
146
|
+
version: "0"
|
147
|
+
requirements: []
|
148
|
+
|
149
|
+
rubyforge_project: pcut
|
150
|
+
rubygems_version: 1.8.21
|
151
|
+
signing_key:
|
152
|
+
specification_version: 3
|
153
|
+
summary: Yet another cutting tool.
|
154
|
+
test_files: []
|
155
|
+
|