sherlock 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/collection/base.rb +76 -0
- data/lib/collection/files.rb +61 -0
- data/lib/collection/lines.rb +33 -0
- data/lib/collection/matched_line.rb +57 -0
- data/lib/collection.rb +8 -0
- data/lib/core_ext.rb +42 -0
- data/lib/latex.rb +45 -0
- data/lib/sherlock.rb +33 -0
- data/spec/collection/base_spec.rb +142 -0
- data/spec/collection/files_spec.rb +47 -0
- data/spec/collection/lines_spec.rb +35 -0
- data/spec/collection/matched_line_spec.rb +26 -0
- data/spec/detective_spec.rb +15 -0
- data/spec/fixtures/simple/lines.txt +5 -0
- data/spec/fixtures/simple/lorem.txt +19 -0
- data/spec/spec_helper.rb +39 -0
- metadata +97 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
module Sherlock
|
4
|
+
module Collection
|
5
|
+
class Base < Array
|
6
|
+
def initialize(arr = [], opts = {})
|
7
|
+
super(0)
|
8
|
+
self.concat filter_array_by_options(arr, opts)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns the first value of the collection (matching the value, if given).
|
12
|
+
def first(*value)
|
13
|
+
item = if value.empty?
|
14
|
+
super
|
15
|
+
else
|
16
|
+
filter(value)[0]
|
17
|
+
end
|
18
|
+
new([item])
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns a collection with all files matching the
|
22
|
+
# given pattern.
|
23
|
+
def select_items_matching(*pattern)
|
24
|
+
opts = pattern.last.is_a?(Hash) ? pattern.pop : {}
|
25
|
+
pattern = [pattern].flatten
|
26
|
+
arr = select { |f| pattern.empty? || matching?(f, pattern) }
|
27
|
+
arr = filter_array_by_options(arr, opts)
|
28
|
+
new(arr, opts)
|
29
|
+
end
|
30
|
+
alias filter select_items_matching
|
31
|
+
|
32
|
+
def [](value, *args)
|
33
|
+
if [String, Regexp, Array, Hash].include?(value.class) #value.is_a?(Regexp)
|
34
|
+
filter(value, *args)
|
35
|
+
else
|
36
|
+
super(value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def -(other)
|
41
|
+
new(super)
|
42
|
+
end
|
43
|
+
|
44
|
+
def +(other)
|
45
|
+
new(super.uniq)
|
46
|
+
end
|
47
|
+
|
48
|
+
def &(other)
|
49
|
+
new(super)
|
50
|
+
end
|
51
|
+
|
52
|
+
def |(other)
|
53
|
+
new(super)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def filter_array_by_options(arr, opts = {})
|
59
|
+
arr = arr.select { |f| matching?(f, opts[:only]) } if opts[:only]
|
60
|
+
arr = arr.reject { |f| matching?(f, opts[:except]) } if opts[:except]
|
61
|
+
arr
|
62
|
+
end
|
63
|
+
|
64
|
+
def matching?(str, string_or_regexp_or_array)
|
65
|
+
[string_or_regexp_or_array].flatten.each { |pattern|
|
66
|
+
return true if str.match(pattern)
|
67
|
+
}
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def new(*args)
|
72
|
+
self.class.new(*args)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
module Sherlock
|
4
|
+
module Collection
|
5
|
+
class Files < Base
|
6
|
+
|
7
|
+
def initialize(glob_or_regex, opts = {})
|
8
|
+
if glob_or_regex.is_a?(Hash)
|
9
|
+
opts = glob_or_regex
|
10
|
+
elsif glob_or_regex.is_a?(Array)
|
11
|
+
opts[:arr] = glob_or_regex
|
12
|
+
elsif glob_or_regex.is_a?(String)
|
13
|
+
opts[:glob] = glob_or_regex
|
14
|
+
elsif glob_or_regex.is_a?(Regexp)
|
15
|
+
if opts[:only]
|
16
|
+
raise "Cannot use regexp and :only-option at the same time."
|
17
|
+
else
|
18
|
+
opts[:only] = glob_or_regex
|
19
|
+
end
|
20
|
+
end
|
21
|
+
opts = {:glob => '*'}.merge(opts)
|
22
|
+
super(opts[:arr] || Dir[opts[:glob]], opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns all the lines matching the given pattern.
|
26
|
+
def collect_lines_matching(pattern, &block)
|
27
|
+
pattern = [pattern].flatten
|
28
|
+
lines = Lines.new
|
29
|
+
self.each { |f|
|
30
|
+
io = File.open(f)
|
31
|
+
io.each { |line|
|
32
|
+
if matching?(line, pattern)
|
33
|
+
lines << MatchedLine.new(line, :file => f, :line_number => io.lineno, :pattern => pattern)
|
34
|
+
end
|
35
|
+
}
|
36
|
+
}
|
37
|
+
lines
|
38
|
+
end
|
39
|
+
alias old_collect collect
|
40
|
+
alias collect collect_lines_matching
|
41
|
+
|
42
|
+
# Returns a FileCollection with all files containing the
|
43
|
+
# given content / matching the given pattern.
|
44
|
+
def select_files_containing(pattern)
|
45
|
+
pattern = [pattern].flatten
|
46
|
+
arr = select { |f| matching?(File.read(f), pattern) }
|
47
|
+
new(arr)
|
48
|
+
end
|
49
|
+
alias containing select_files_containing
|
50
|
+
|
51
|
+
# Returns a FileCollection with all files not containing the
|
52
|
+
# given content / matching the given pattern.
|
53
|
+
def select_files_not_containing(pattern)
|
54
|
+
pattern = [pattern].flatten
|
55
|
+
arr = select { |f| !matching?(File.read(f), pattern) }
|
56
|
+
new(arr)
|
57
|
+
end
|
58
|
+
alias not_containing select_files_not_containing
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
module Sherlock
|
4
|
+
module Collection
|
5
|
+
class Lines < Base
|
6
|
+
# Executes gsub on all lines in the collection and returns
|
7
|
+
# the modified collection.
|
8
|
+
def gsub(*args, &block)
|
9
|
+
arr = map { |line| line.gsub(*args, &block) }
|
10
|
+
new(arr)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns an array of the lines' match_data objects without the
|
14
|
+
# 'overall' match (the first element of the MatchData object).
|
15
|
+
def matches
|
16
|
+
map { |line| line.match_data[1..line.match_data.length-1] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def new(arr, opts = {}) # :nodoc:
|
20
|
+
self.class.new(arr)
|
21
|
+
end
|
22
|
+
|
23
|
+
def save!
|
24
|
+
sort_by { |line| line.line_number }.reverse.each(&:save!)
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
map { |line| (line.changed? ? '[C] ' : '[ ] ') + line.inspect }.join("\n")
|
29
|
+
end
|
30
|
+
alias inspect to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
module Sherlock
|
4
|
+
module Collection
|
5
|
+
|
6
|
+
# ==== Attributes
|
7
|
+
#
|
8
|
+
# * <tt>:file</tt>
|
9
|
+
# * <tt>:line_number</tt>
|
10
|
+
# * <tt>:pattern</tt>
|
11
|
+
#
|
12
|
+
class MatchedLine < String
|
13
|
+
attr_accessor :attributes
|
14
|
+
|
15
|
+
def initialize(line, _attributes = {})
|
16
|
+
super(line)
|
17
|
+
self.attributes = {:original => line}.merge(_attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
def changed?
|
21
|
+
attributes[:original] != self
|
22
|
+
end
|
23
|
+
|
24
|
+
def gsub(*args, &block)
|
25
|
+
self.class.new(super, attributes)
|
26
|
+
end
|
27
|
+
|
28
|
+
def match_data
|
29
|
+
attributes[:pattern].each do |p|
|
30
|
+
if m = self.match(p)
|
31
|
+
return m
|
32
|
+
end
|
33
|
+
end
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(m)
|
38
|
+
if attributes && value = attributes[m.to_s.intern]
|
39
|
+
value
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def save!
|
46
|
+
all_lines = File.open(file, 'r') { |f| f.readlines }
|
47
|
+
index = line_number - 1
|
48
|
+
if original == all_lines[index]
|
49
|
+
all_lines[index] = self.to_s
|
50
|
+
else
|
51
|
+
raise "File seems modified: #{file}"
|
52
|
+
end
|
53
|
+
File.open(file, 'w') {|f| f.write(all_lines) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/collection.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
sub_dir = File.basename(__FILE__, '.rb')
|
4
|
+
all_files = Dir[File.join(File.dirname(__FILE__), sub_dir, '*.rb')]
|
5
|
+
all_files.sort.map { |f| File.basename(f, '.rb') }.each do |_module|
|
6
|
+
require File.join(File.dirname(__FILE__), sub_dir, _module)
|
7
|
+
end
|
8
|
+
|
data/lib/core_ext.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
class ::Object
|
3
|
+
#:call-seq:
|
4
|
+
# obj.full?
|
5
|
+
# obj.full? { |f| ... }
|
6
|
+
#
|
7
|
+
# Returns wheter or not the given obj is not blank?.
|
8
|
+
# If a block is given and the obj is full?, the obj is yielded to that block.
|
9
|
+
#
|
10
|
+
# salary = nil
|
11
|
+
# salary.full? # => nil
|
12
|
+
# salary.full? { |s| "#{s} $" } # => nil
|
13
|
+
# salary = 100
|
14
|
+
# salary.full? { |s| "#{s} $" } # => "100 $"
|
15
|
+
#
|
16
|
+
# With ActiveSupport's implementation of Symbol#to_proc it is possible to write:
|
17
|
+
#
|
18
|
+
# current_user.full?(&:name) # => "Dave"
|
19
|
+
def full?
|
20
|
+
f = blank? ? nil : self
|
21
|
+
if block_given? and f
|
22
|
+
yield f
|
23
|
+
else
|
24
|
+
f
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ::Symbol
|
30
|
+
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
|
31
|
+
#
|
32
|
+
# # The same as people.collect { |p| p.name }
|
33
|
+
# people.collect(&:name)
|
34
|
+
#
|
35
|
+
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
|
36
|
+
# people.select(&:manager?).collect(&:salary)
|
37
|
+
#
|
38
|
+
# (borrowed from ActiveSupport)
|
39
|
+
def to_proc
|
40
|
+
Proc.new { |*args| args.shift.__send__(self, *args) }
|
41
|
+
end
|
42
|
+
end
|
data/lib/latex.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
module Sherlock
|
4
|
+
module LaTex
|
5
|
+
class << self
|
6
|
+
def included(base)
|
7
|
+
base.__send__(:include, InstanceMethods)
|
8
|
+
Sherlock::Collection::Files.__send__(:include, Collection::Files::InstanceMethods)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def tex_files(opts = {})
|
14
|
+
investigate('**/*.tex', opts)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Collection
|
19
|
+
module Files
|
20
|
+
module InstanceMethods
|
21
|
+
def collect_macros(pattern)
|
22
|
+
collect(/\\(#{pattern})(\{([^\}]+)\})*/)
|
23
|
+
end
|
24
|
+
alias macros collect_macros
|
25
|
+
|
26
|
+
def inputs(opts = {})
|
27
|
+
macros(:input).filter(opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
def tagged(with_tag)
|
31
|
+
tag_prefix = "%%!!"
|
32
|
+
arr = [with_tag].flatten.map { |tag| "#{tag_prefix} #{tag}" }
|
33
|
+
containing(arr)
|
34
|
+
end
|
35
|
+
|
36
|
+
def not_tagged(with_tag)
|
37
|
+
tag_prefix = "%%!!"
|
38
|
+
arr = [with_tag].flatten.map { |tag| "#{tag_prefix} #{tag}" }
|
39
|
+
not_containing(arr)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/sherlock.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
# TODO: Output-Methoden für File- und Line-Collections, Tabellen, success & failure inkl. optionaler Colorierung.
|
4
|
+
# TODO: vielleicht LaTex shortcuts à la tex_files.inputs(:only => 'generated/schema')
|
5
|
+
|
6
|
+
%w(collection core_ext latex).each do |_module|
|
7
|
+
require File.join(File.dirname(__FILE__), _module)
|
8
|
+
end
|
9
|
+
|
10
|
+
module Sherlock
|
11
|
+
module VERSION #:nodoc:
|
12
|
+
MAJOR = 0
|
13
|
+
MINOR = 1
|
14
|
+
BUILD = 0
|
15
|
+
|
16
|
+
STRING = [MAJOR, MINOR, BUILD].join('.').freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
def collect_files_matching(*args)
|
21
|
+
Sherlock::Collection::Files.new(*args)
|
22
|
+
end
|
23
|
+
alias investigate collect_files_matching
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def included(base)
|
28
|
+
base.__send__(:include, InstanceMethods)
|
29
|
+
end
|
30
|
+
include InstanceMethods
|
31
|
+
alias [] collect_files_matching
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Sherlock::Collection::Base do
|
4
|
+
def new_collection(arr = nil, opts = {})
|
5
|
+
arr ||= %w(eins zwei drei vier fünf)
|
6
|
+
Sherlock::Collection::Base.new(arr, opts)
|
7
|
+
end
|
8
|
+
|
9
|
+
def filter_arguments
|
10
|
+
[
|
11
|
+
[['ei']],
|
12
|
+
[[/ei/]],
|
13
|
+
[['sieben', 'sechs', 'fünf', 'vier']],
|
14
|
+
[[/ei/, 'fünf'], {:only => /ei$/, :except => 'zwei'}],
|
15
|
+
[{:only => /ei$/, :except => 'zwei'}],
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#initialize" do
|
20
|
+
it "creates an empty collection without arguments" do
|
21
|
+
empty_collection = Sherlock::Collection::Base.new
|
22
|
+
empty_collection.should be_empty
|
23
|
+
end
|
24
|
+
it "creates a full collection for a given array" do
|
25
|
+
collection = new_collection([:foo, :bar])
|
26
|
+
collection.should_not be_empty
|
27
|
+
end
|
28
|
+
it "creates a full collection for a given collection" do
|
29
|
+
collection = new_collection(new_collection)
|
30
|
+
collection.should_not be_empty
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#first" do
|
35
|
+
it "should give a collection with the first matching element for a string" do
|
36
|
+
collection = new_collection.first('ei')
|
37
|
+
collection.should == new_collection(%w(eins))
|
38
|
+
end
|
39
|
+
it "should give a collection with the first matching element for a regexp" do
|
40
|
+
collection = new_collection.first(/ei/)
|
41
|
+
collection.should == new_collection(%w(eins))
|
42
|
+
end
|
43
|
+
it "should give a collection with the first matching element for an array of strings" do
|
44
|
+
collection = new_collection.first(%w(sieben sechs fünf))
|
45
|
+
collection.should == new_collection(%w(fünf))
|
46
|
+
end
|
47
|
+
it "should give a collection with the first matching element for an array of regexps" do
|
48
|
+
collection = new_collection.first([/sieben/, /sechs/, /fünf/])
|
49
|
+
collection.should == new_collection(%w(fünf))
|
50
|
+
end
|
51
|
+
it "should give a collection with the first matching element for an array of strings and regexps" do
|
52
|
+
collection = new_collection.first([/sieben/, /sechs/, 'fünf'])
|
53
|
+
collection.should == new_collection(%w(fünf))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#filter" do
|
58
|
+
# without real arguments
|
59
|
+
it "should give the same collection without arguments" do
|
60
|
+
collection = new_collection.filter
|
61
|
+
collection.should == new_collection
|
62
|
+
end
|
63
|
+
it "should give the same collection with empty arguments" do
|
64
|
+
collection = new_collection.filter([], {})
|
65
|
+
collection.should == new_collection
|
66
|
+
end
|
67
|
+
|
68
|
+
# without options
|
69
|
+
it "should give a collection with the matching elements for a string" do
|
70
|
+
collection = new_collection.filter('ei')
|
71
|
+
collection.should == new_collection(%w(eins zwei drei))
|
72
|
+
end
|
73
|
+
it "should give a collection with the matching elements for a regexp" do
|
74
|
+
collection = new_collection.filter(/ei/)
|
75
|
+
collection.should == new_collection(%w(eins zwei drei))
|
76
|
+
end
|
77
|
+
it "should give a collection with the matching elements for an array of strings" do
|
78
|
+
collection = new_collection.filter(%w(sieben sechs fünf vier))
|
79
|
+
collection.should == new_collection(%w(vier fünf))
|
80
|
+
end
|
81
|
+
it "should give a collection with the matching elements for an array of regexps" do
|
82
|
+
collection = new_collection.filter([/ei/, /sechs/, /fünf/])
|
83
|
+
collection.should == new_collection(%w(eins zwei drei fünf))
|
84
|
+
end
|
85
|
+
it "should give a collection with the matching elements for an array of strings and regexps" do
|
86
|
+
collection = new_collection.filter([/ei/, 'fünf'])
|
87
|
+
collection.should == new_collection(%w(eins zwei drei fünf))
|
88
|
+
end
|
89
|
+
|
90
|
+
# with options
|
91
|
+
it "should accept options as only argument" do
|
92
|
+
collection = new_collection.filter(:except => 'zwei')
|
93
|
+
collection.should == new_collection(%w(eins drei vier fünf))
|
94
|
+
end
|
95
|
+
it "should accept options as only argument (chained)" do
|
96
|
+
collection = new_collection.filter([/ei/, 'fünf']).filter(:except => 'zwei')
|
97
|
+
collection.should == new_collection(%w(eins drei fünf))
|
98
|
+
end
|
99
|
+
it "should filter results with :except option" do
|
100
|
+
collection = new_collection.filter([/ei/, 'fünf'], :except => 'zwei')
|
101
|
+
collection.should == new_collection(%w(eins drei fünf))
|
102
|
+
end
|
103
|
+
it "should filter results with :only option" do
|
104
|
+
collection = new_collection.filter([/ei/, 'fünf'], :only => /ei$/)
|
105
|
+
collection.should == new_collection(%w(zwei drei))
|
106
|
+
end
|
107
|
+
it "should filter results with :only option first and :except option afterwards" do
|
108
|
+
collection = new_collection.filter([/ei/, 'fünf'], :only => /ei$/, :except => 'zwei')
|
109
|
+
collection.should == new_collection(%w(drei))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#[]" do
|
114
|
+
it "should be a shortcut for 'filter'" do
|
115
|
+
filter_arguments.each do |args|
|
116
|
+
new_collection[*args].should == new_collection.filter(*args)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "#+" do
|
122
|
+
it "should combine two collections" do
|
123
|
+
collection1 = new_collection(nil, :only => 'eins')
|
124
|
+
collection2 = new_collection(nil, :only => 'zwei')
|
125
|
+
result = collection1 + collection2
|
126
|
+
result.should == new_collection(%w(eins zwei))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "#-" do
|
131
|
+
it "should reduce two collections" do
|
132
|
+
collection1 = new_collection(nil, :only => /ei/)
|
133
|
+
collection2 = new_collection(nil, :only => 'zwei')
|
134
|
+
result = collection1 - collection2
|
135
|
+
result.should == new_collection(%w(eins drei))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# TODO: tests für #& und #| schreiben
|
140
|
+
# TODO: testen, dass filter(), und first() und containing und so alle String, Regexp sowie [String/Regexp] nehmen
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Sherlock::Collection::Files do
|
4
|
+
def filtered_by_initialize(filter = {:only => /lines/})
|
5
|
+
text_files(filter)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
it "creates an collection of all text files" do
|
10
|
+
files = text_files
|
11
|
+
files.should_not be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it "filters text files by name" do
|
15
|
+
filtered_by_method = text_files.filter(:only => /lines/)
|
16
|
+
filtered_by_initialize.should == filtered_by_method
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#collect" do
|
21
|
+
it "collects all lines beginning with a number and a dot." do
|
22
|
+
lines = text_files(:only => /lines/).collect(/^\d+\./)
|
23
|
+
lines.should_not be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
it "tries to collect all lines beginning with a number and a dot." do
|
27
|
+
lines = text_files(:except => /lines/).collect(/^\d+\./)
|
28
|
+
lines.should be_empty
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#select_files_containing" do
|
33
|
+
it "selects all text files containing numbered lists" do
|
34
|
+
files = text_files.containing(/^.*\d+\./)
|
35
|
+
files.should_not be_empty
|
36
|
+
files.should == text_files(:only => 'lines.txt')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#select_files_not_containing" do
|
41
|
+
it "selects all text files not containing numbered lists" do
|
42
|
+
files = text_files.not_containing(/^.*\d+\./)
|
43
|
+
files.should_not be_empty
|
44
|
+
files.should == text_files(:except => 'lines.txt')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Sherlock::Collection::Files do
|
4
|
+
def numbered_lines
|
5
|
+
text_files(:only => /lines/).collect(/^.*(\d+\.)(.+)/)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
it "creates an collection of lines looking like numbered lists" do
|
10
|
+
lines = numbered_lines
|
11
|
+
lines.should_not be_empty
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#filter" do
|
16
|
+
it "filters a collection of lines" do
|
17
|
+
lines = numbered_lines
|
18
|
+
new_lines = lines.filter(:except => /^\d\./)
|
19
|
+
lines.count.should be > new_lines.count
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#gsub" do
|
24
|
+
it "modifies a collection of lines" do
|
25
|
+
lines = numbered_lines
|
26
|
+
new_lines = lines.gsub(/^(.*)(\d+)(\..+)/) do |match|
|
27
|
+
"X #{match}"
|
28
|
+
end
|
29
|
+
new_lines.each do |line|
|
30
|
+
line.changed?.should == true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Sherlock::Collection::Files do
|
4
|
+
def some_line
|
5
|
+
lines = text_files.collect('Zeile')
|
6
|
+
lines[0]
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
it "should be an unchanged line" do
|
11
|
+
some_line.changed?.should == false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#gsub" do
|
16
|
+
it "modifies a line" do
|
17
|
+
line = some_line
|
18
|
+
new_line = line.gsub(/^(.*)/, 'X \1')
|
19
|
+
new_line[0..0].should == 'X'
|
20
|
+
new_line.changed?.should == true
|
21
|
+
new_line[0..0].should != 'X'
|
22
|
+
line.changed?.should == false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Sherlock do
|
4
|
+
describe "#investigate" do
|
5
|
+
it "creates a collection of all text files" do
|
6
|
+
files = Sherlock.investigate('**/*.txt')
|
7
|
+
files.should_not be_empty
|
8
|
+
end
|
9
|
+
|
10
|
+
it "creates an empty collection" do
|
11
|
+
files = Sherlock.investigate('**/not-there')
|
12
|
+
files.should be_empty
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
2
|
+
|
3
|
+
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
4
|
+
|
5
|
+
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
6
|
+
|
7
|
+
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
8
|
+
|
9
|
+
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
|
10
|
+
|
11
|
+
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.
|
12
|
+
|
13
|
+
Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus.
|
14
|
+
|
15
|
+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
16
|
+
|
17
|
+
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
18
|
+
|
19
|
+
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
4
|
+
|
5
|
+
require 'sherlock'
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rspec'
|
9
|
+
|
10
|
+
require 'fileutils'
|
11
|
+
|
12
|
+
def text_files(opts = {})
|
13
|
+
Sherlock::Collection::Files.new('**/*.txt', opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def rebuild_test_data_dir!
|
17
|
+
FileUtils.rm_rf(test_data_dir)
|
18
|
+
FileUtils.mkdir_p(test_data_dir)
|
19
|
+
FileUtils.cp_r(original_test_data_dir, tmp_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def original_test_data_dir
|
23
|
+
File.join(File.dirname(__FILE__), 'fixtures')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_data_dir
|
27
|
+
File.join(tmp_dir, 'fixtures')
|
28
|
+
end
|
29
|
+
|
30
|
+
def tmp_dir
|
31
|
+
File.join(File.dirname(__FILE__), '..', 'tmp')
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec.configure do |config|
|
35
|
+
config.before(:each) {
|
36
|
+
rebuild_test_data_dir!
|
37
|
+
Dir.chdir(test_data_dir)
|
38
|
+
}
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sherlock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Ren\xC3\xA9 F\xC3\xB6hring"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-10 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 27
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 3
|
33
|
+
- 0
|
34
|
+
version: 1.3.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description: A library for filtering lists of files and performing actions on their content.
|
38
|
+
email: rf@bamaru.de
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- lib/collection/base.rb
|
47
|
+
- lib/collection/files.rb
|
48
|
+
- lib/collection/lines.rb
|
49
|
+
- lib/collection/matched_line.rb
|
50
|
+
- lib/collection.rb
|
51
|
+
- lib/core_ext.rb
|
52
|
+
- lib/latex.rb
|
53
|
+
- lib/sherlock.rb
|
54
|
+
- spec/collection/base_spec.rb
|
55
|
+
- spec/collection/files_spec.rb
|
56
|
+
- spec/collection/lines_spec.rb
|
57
|
+
- spec/collection/matched_line_spec.rb
|
58
|
+
- spec/detective_spec.rb
|
59
|
+
- spec/fixtures/simple/lines.txt
|
60
|
+
- spec/fixtures/simple/lorem.txt
|
61
|
+
- spec/spec_helper.rb
|
62
|
+
has_rdoc: true
|
63
|
+
homepage: http://bamaru.com
|
64
|
+
licenses: []
|
65
|
+
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 3
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
version: "0"
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
requirements:
|
90
|
+
- none
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.3.7
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: A library for filtering lists of files and performing actions on their content.
|
96
|
+
test_files: []
|
97
|
+
|