filtri 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +61 -2
- data/bin/filtri +24 -0
- data/filtri.gemspec +8 -6
- data/lib/filtri/command.rb +108 -0
- data/lib/filtri/version.rb +1 -1
- data/lib/filtri.rb +43 -9
- data/resource/filtri_rules.tmLanguage +75 -0
- data/spec/command_spec.rb +127 -0
- metadata +18 -15
data/README.md
CHANGED
@@ -11,8 +11,6 @@ Filtri is a tiny DSL for text substitution.
|
|
11
11
|
|
12
12
|
Define a set of substitution rules using `rule` and apply to an input string:
|
13
13
|
|
14
|
-
in_str = "foobazbarfoo"
|
15
|
-
expected = "barbugbarbar"
|
16
14
|
|
17
15
|
f = filtri do
|
18
16
|
rule /fo+/ => "bar"
|
@@ -36,8 +34,69 @@ Load with `Filtri::load`:
|
|
36
34
|
Filtri.load("foo.rules").apply("foobarfoobar")
|
37
35
|
=> "**b**!!a!!z**b**!!a!!g**b**!!a!!z**b**!!a!!g"
|
38
36
|
|
37
|
+
## Command line tool
|
38
|
+
|
39
|
+
A command line tool is included in this gem, `filtri`
|
40
|
+
|
41
|
+
### Usage
|
42
|
+
|
43
|
+
Usage: filtri [options] [input]
|
44
|
+
|
45
|
+
Options:
|
46
|
+
-r, --rule STRING Single rule
|
47
|
+
-f, --file RULE_FILE File containing rules
|
48
|
+
-v, --version Version information
|
49
|
+
-h, --help Help
|
50
|
+
|
51
|
+
|
52
|
+
### Examples
|
53
|
+
|
54
|
+
An example applying rules from the files `f1.rule` and `f2.rule` to the input files `input1` and `input2`
|
55
|
+
|
56
|
+
File `f1.rules`:
|
57
|
+
|
58
|
+
rule /(foo+)/ => 'THIS WAS \1'
|
59
|
+
rule /(ba+r)/ => 'THIS WAS \1'
|
60
|
+
|
61
|
+
File `f1.rules`:
|
62
|
+
|
63
|
+
rule /(ba+z)/ => 'THIS WAS \1'
|
64
|
+
rule /bag/ => 'THIS WAS BAG'
|
65
|
+
|
66
|
+
File `input1`:
|
67
|
+
|
68
|
+
foooo
|
69
|
+
baaaaaaaaaaaaaaaaz
|
70
|
+
bag
|
71
|
+
|
72
|
+
File `input2`:
|
73
|
+
|
74
|
+
and baaaaaaaaaaar
|
75
|
+
|
76
|
+
Running `filtri` as
|
77
|
+
|
78
|
+
$ filtri -f f1.rules -f f2.rules input1 input2 > result.txt
|
79
|
+
|
80
|
+
..gives `result.txt`:
|
81
|
+
|
82
|
+
THIS WAS foooo
|
83
|
+
THIS WAS baaaaaaaaaaaaaaaaz
|
84
|
+
THIS WAS BAG
|
85
|
+
and THIS WAS baaaaaaaaaaar
|
86
|
+
|
87
|
+
Single rules can be provided using the option `-r`:
|
88
|
+
|
89
|
+
$ echo "foo" | filtri -r '"foo" => "bar"'
|
90
|
+
bar
|
91
|
+
|
92
|
+
|
93
|
+
## Syntax highlighting
|
94
|
+
|
95
|
+
Definitions for syntax highlighting of `.rule` files in Sublime Text 2 and TextMate is available (`resource/filtri_rules.tmLanguage`)
|
96
|
+
|
39
97
|
## Version information
|
40
98
|
|
99
|
+
* 0.1.0 - Added filtri tool and syntax highlighting
|
41
100
|
* 0.0.1 - Initial version
|
42
101
|
|
43
102
|
## License
|
data/bin/filtri
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require_relative '../lib/filtri/command'
|
5
|
+
|
6
|
+
begin
|
7
|
+
|
8
|
+
debug = true
|
9
|
+
|
10
|
+
opts = FiltriCmd.parse_opts
|
11
|
+
|
12
|
+
unless FiltriCmd.validate_opts(opts)
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
result = FiltriCmd.run(opts, opts[:input])
|
16
|
+
puts result
|
17
|
+
rescue SystemExit => sys_exit
|
18
|
+
exit sys_exit.status
|
19
|
+
rescue Exception => ex
|
20
|
+
|
21
|
+
puts "[Error] #{ex.message}"
|
22
|
+
puts " -----> #{ex.backtrace.join("\n ")}" if debug
|
23
|
+
|
24
|
+
end
|
data/filtri.gemspec
CHANGED
@@ -9,12 +9,14 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.version = Filtri::VERSION
|
10
10
|
spec.authors = ["karl l"]
|
11
11
|
spec.email = ["karl@ninjacontrol.com"]
|
12
|
-
spec.date = '2013-04-
|
13
|
-
spec.summary = "A tiny
|
14
|
-
spec.description = "Filtri is a
|
12
|
+
spec.date = '2013-04-07'
|
13
|
+
spec.summary = "A tiny tool for text substitution"
|
14
|
+
spec.description = "Filtri is a tool that simplifies the work of applying multiple substitution rules to a string."
|
15
15
|
spec.homepage = "https://github.com/karlll/filtri/"
|
16
16
|
spec.license = "MIT"
|
17
|
-
|
17
|
+
|
18
|
+
spec.required_ruby_version = '>= 1.9.3'
|
19
|
+
|
18
20
|
spec.files = `git ls-files`.split($/)
|
19
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
@@ -22,9 +24,9 @@ Gem::Specification.new do |spec|
|
|
22
24
|
|
23
25
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
26
|
spec.add_development_dependency "rake"
|
25
|
-
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "rspec", ">= 2.11"
|
26
28
|
spec.add_runtime_dependency "docile"
|
27
|
-
spec.add_runtime_dependency "str2hash"
|
29
|
+
spec.add_runtime_dependency "str2hash", ">= 0.1.0"
|
28
30
|
spec.add_runtime_dependency "to_regexp"
|
29
31
|
|
30
32
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require_relative 'version'
|
3
|
+
require_relative '../filtri'
|
4
|
+
|
5
|
+
class FiltriCmd
|
6
|
+
def self.parse_opts
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
OptionParser.new do |o|
|
10
|
+
o.banner = "Usage: filtri [options] [input]"
|
11
|
+
o.separator ""
|
12
|
+
o.separator "Options:"
|
13
|
+
|
14
|
+
o.on("-r", "--rule STRING", "Single rule") do |rule|
|
15
|
+
if options.include?(:rules)
|
16
|
+
options[:rules] << rule
|
17
|
+
else
|
18
|
+
options[:rules] = [rule]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
o.on("-f", "--file RULE_FILE", "File containing rules") do |rule_files|
|
23
|
+
if options.include?(:rule_files)
|
24
|
+
options[:rule_files] << rule_files
|
25
|
+
else
|
26
|
+
options[:rule_files] = [rule_files]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
o.on( '-v', '--version', 'Version information' ) do
|
31
|
+
puts "version #{Filtri::VERSION}"
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
o.on( '-h', '--help', 'Help' ) do
|
36
|
+
puts o
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
end.parse!
|
43
|
+
|
44
|
+
options[:input] = ARGV unless ARGV.length <= 0
|
45
|
+
options
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.validate_opts(opts)
|
50
|
+
|
51
|
+
|
52
|
+
unless opts.include?(:rules) || opts.include?(:rule_files)
|
53
|
+
puts "Error: provide a rule or a rule file."
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
[:rule_files, :input].each do |f|
|
58
|
+
if opts.include?(f)
|
59
|
+
opts[f].each do |i|
|
60
|
+
unless File.exist?(i)
|
61
|
+
puts "Error: file #{i} does not exist."
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
true
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# Apply rules to the provided input
|
73
|
+
#
|
74
|
+
# @param [Hash{Symbol => Array<String>}] rules Where :rules contain single rule strings and :rule_files contain filename(s) of the rule file(s)
|
75
|
+
# @param [Array<String>] input Where :input contain the input file(s)
|
76
|
+
# @return [String] The rules applied to the input
|
77
|
+
# @raise [FiltriInitError, IOError] if an error occurs when initialising the rules from the provided strings or files
|
78
|
+
def self.run(rules, input)
|
79
|
+
rule_strs = rules[:rules] || []
|
80
|
+
rule_files = rules[:rule_files] || []
|
81
|
+
result = []
|
82
|
+
|
83
|
+
|
84
|
+
# Allow for shorthand format of rules
|
85
|
+
|
86
|
+
upd_rule_strs = rule_strs.reduce([]) do |r,v|
|
87
|
+
if v =~ /^(#{Filtri.valid_rules.join("|")})/
|
88
|
+
r << v
|
89
|
+
else
|
90
|
+
r << "rule #{v}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
f = Filtri.new
|
94
|
+
if upd_rule_strs.length > 0
|
95
|
+
f.add_rule_str(upd_rule_strs.join("\n"))
|
96
|
+
end
|
97
|
+
|
98
|
+
rule_files.each do |rf|
|
99
|
+
f.load rf
|
100
|
+
end
|
101
|
+
|
102
|
+
ARGV.replace(input || [])
|
103
|
+
result << f.apply(ARGF.read)
|
104
|
+
|
105
|
+
result.join("")
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
data/lib/filtri/version.rb
CHANGED
data/lib/filtri.rb
CHANGED
@@ -21,6 +21,7 @@ class Filtri
|
|
21
21
|
@rules = []
|
22
22
|
@meta_rules = []
|
23
23
|
@passes = 1
|
24
|
+
@meta_applied = false
|
24
25
|
end
|
25
26
|
|
26
27
|
# Add a filtering rule
|
@@ -92,7 +93,10 @@ class Filtri
|
|
92
93
|
@passes.times do
|
93
94
|
|
94
95
|
unless @meta_rules.empty?
|
95
|
-
|
96
|
+
unless @meta_applied
|
97
|
+
@rules = rewrite(@rules, @meta_rules)
|
98
|
+
@meta_applied = true
|
99
|
+
end
|
96
100
|
end
|
97
101
|
|
98
102
|
@rules.each do |rule|
|
@@ -103,8 +107,6 @@ class Filtri
|
|
103
107
|
in_str
|
104
108
|
end
|
105
109
|
|
106
|
-
# Factory, init with rule-set from a string
|
107
|
-
#
|
108
110
|
# The input string is expected to contain rules and comments, one per line,
|
109
111
|
# separated by a line break.
|
110
112
|
# The expected format of a line is "{operation} <space> {argument} <eol>".
|
@@ -112,11 +114,8 @@ class Filtri
|
|
112
114
|
# is trimmed.
|
113
115
|
#
|
114
116
|
# @param [String] rule_str
|
115
|
-
# @return [Filtri] A new Filtri object with the rules parsed from the provided string(s).
|
116
117
|
# @raise [FiltriInitError] if an error occurs when initialising the rules from the provided strings
|
117
|
-
def
|
118
|
-
|
119
|
-
inst = Filtri.new
|
118
|
+
def add_rule_str(rule_str)
|
120
119
|
|
121
120
|
rule_str.strip.lines do |l|
|
122
121
|
|
@@ -133,7 +132,7 @@ class Filtri
|
|
133
132
|
raise FiltriInitError, "Invalid rule format: '#{op_arg}' (#{err.message})"
|
134
133
|
end
|
135
134
|
# add rule
|
136
|
-
|
135
|
+
self.send(op.to_sym,arg_hash)
|
137
136
|
else
|
138
137
|
raise FiltriInitError, "Unknown rule: #{op}" unless op == "#"
|
139
138
|
end
|
@@ -141,12 +140,42 @@ class Filtri
|
|
141
140
|
end
|
142
141
|
end
|
143
142
|
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
# Factory, init with rule-set from a string
|
148
|
+
#
|
149
|
+
# The input string is expected to contain rules and comments, one per line,
|
150
|
+
# separated by a line break.
|
151
|
+
# The expected format of a line is '{operation} <space> {argument} <eol>'.
|
152
|
+
# Empty lines and lines starting with a '#' are ignored. Whitespace at the beginning of a line
|
153
|
+
# is trimmed.
|
154
|
+
#
|
155
|
+
# @param [String] rule_str
|
156
|
+
# @return [Filtri] A new Filtri object with the rules parsed from the provided string(s).
|
157
|
+
# @raise [FiltriInitError] if an error occurs when initialising the rules from the provided strings
|
158
|
+
def self.from_str(rule_str)
|
159
|
+
|
160
|
+
inst = Filtri.new
|
161
|
+
inst.add_rule_str rule_str
|
144
162
|
inst
|
145
163
|
|
146
164
|
end
|
147
165
|
|
148
166
|
# Load rules from a file
|
149
167
|
# @param [String] file_name
|
168
|
+
# @raise [IOError,SystemCallError] If an error occurs when opening the file
|
169
|
+
# @raise [FiltriInitError] If an error occurs when parsing the rules in the file
|
170
|
+
def load(file_name)
|
171
|
+
|
172
|
+
data = IO.read(file_name)
|
173
|
+
add_rule_str(data)
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
# Factory, Init by loading rules from a file
|
178
|
+
# @param [String] file_name
|
150
179
|
# @return [Filtri] A new Filtri object with the rules contained in the file
|
151
180
|
# @raise [IOError,SystemCallError] If an error occurs when opening the file
|
152
181
|
# @raise [FiltriInitError] If an error occurs when parsing the rules in the file
|
@@ -158,6 +187,10 @@ class Filtri
|
|
158
187
|
end
|
159
188
|
|
160
189
|
|
190
|
+
def self.valid_rules
|
191
|
+
Filtri::RULES
|
192
|
+
end
|
193
|
+
|
161
194
|
end
|
162
195
|
|
163
196
|
class FiltriInitError < StandardError
|
@@ -180,4 +213,5 @@ end
|
|
180
213
|
# @return [Filtri] A new Filtri object containing the provided rules
|
181
214
|
def filtri(&block)
|
182
215
|
Docile.dsl_eval(Filtri.new, &block)
|
183
|
-
end
|
216
|
+
end
|
217
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>fileTypes</key>
|
6
|
+
<array>
|
7
|
+
<string>rules</string>
|
8
|
+
</array>
|
9
|
+
<key>name</key>
|
10
|
+
<string>Filtri rules</string>
|
11
|
+
<key>patterns</key>
|
12
|
+
<array>
|
13
|
+
<dict>
|
14
|
+
<key>comment</key>
|
15
|
+
<string>A comment</string>
|
16
|
+
<key>match</key>
|
17
|
+
<string>^\s*(#.*)$</string>
|
18
|
+
<key>name</key>
|
19
|
+
<string>comment.line.numer-sign.rules</string>
|
20
|
+
</dict>
|
21
|
+
<dict>
|
22
|
+
<key>comment</key>
|
23
|
+
<string>A rule</string>
|
24
|
+
<key>match</key>
|
25
|
+
<string>^\s*rule</string>
|
26
|
+
<key>name</key>
|
27
|
+
<string>support.function.rules</string>
|
28
|
+
</dict>
|
29
|
+
<dict>
|
30
|
+
<key>comment</key>
|
31
|
+
<string>A meta rule</string>
|
32
|
+
<key>match</key>
|
33
|
+
<string>^\s*meta</string>
|
34
|
+
<key>name</key>
|
35
|
+
<string>support.function.rules</string>
|
36
|
+
</dict>
|
37
|
+
<dict>
|
38
|
+
<key>comment</key>
|
39
|
+
<string>A string</string>
|
40
|
+
<key>match</key>
|
41
|
+
<string>"([^"]*)"</string>
|
42
|
+
<key>name</key>
|
43
|
+
<string>string.quoted.double.rules</string>
|
44
|
+
</dict>
|
45
|
+
<dict>
|
46
|
+
<key>comment</key>
|
47
|
+
<string>A string</string>
|
48
|
+
<key>match</key>
|
49
|
+
<string>'([^']*)'</string>
|
50
|
+
<key>name</key>
|
51
|
+
<string>string.quoted.single.rules</string>
|
52
|
+
</dict>
|
53
|
+
<dict>
|
54
|
+
<key>comment</key>
|
55
|
+
<string>A regular expression</string>
|
56
|
+
<key>match</key>
|
57
|
+
<string>/([^']*)/</string>
|
58
|
+
<key>name</key>
|
59
|
+
<string>string.regexp.rules</string>
|
60
|
+
</dict>
|
61
|
+
<dict>
|
62
|
+
<key>comment</key>
|
63
|
+
<string>A mapping</string>
|
64
|
+
<key>match</key>
|
65
|
+
<string>=></string>
|
66
|
+
<key>name</key>
|
67
|
+
<string>keyword.operator.rules</string>
|
68
|
+
</dict>
|
69
|
+
</array>
|
70
|
+
<key>scopeName</key>
|
71
|
+
<string>text.rules</string>
|
72
|
+
<key>uuid</key>
|
73
|
+
<string>7d1b615b-cfb6-41e1-83e1-6ff8508e0133</string>
|
74
|
+
</dict>
|
75
|
+
</plist>
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'filtri/command'
|
3
|
+
|
4
|
+
describe FiltriCmd do
|
5
|
+
|
6
|
+
describe "#parse_opts" do
|
7
|
+
|
8
|
+
it 'parses multiple rules' do
|
9
|
+
|
10
|
+
stub_const("ARGV",["-r", "{:foo => 'bar'}", "--rule", "{:foo2 => 'bar2'}"])
|
11
|
+
out_opts = FiltriCmd.parse_opts
|
12
|
+
out_opts.should eq({:rules=>["{:foo => 'bar'}", "{:foo2 => 'bar2'}"]})
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'parses multiple rule files' do
|
17
|
+
|
18
|
+
stub_const("ARGV",["-f", "file1", "--file", "file2"])
|
19
|
+
out_opts = FiltriCmd.parse_opts
|
20
|
+
out_opts.should eq({:rule_files=>["file1", "file2"]})
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'parses multiple input files' do
|
25
|
+
|
26
|
+
stub_const("ARGV",["-f", "file1", "input1", "input2"])
|
27
|
+
out_opts = FiltriCmd.parse_opts
|
28
|
+
out_opts.should eq({:rule_files=>["file1"], :input=> ["input1", "input2"]})
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#validate_opts" do
|
36
|
+
|
37
|
+
it 'requires a rule or a rule file' do
|
38
|
+
|
39
|
+
stub_const("ARGV",["-f", "file1", "input1", "input2"])
|
40
|
+
out_opts = FiltriCmd.parse_opts
|
41
|
+
File.stub!(:exist?).and_return true
|
42
|
+
FiltriCmd.validate_opts(out_opts).should be_true
|
43
|
+
|
44
|
+
stub_const("ARGV",["--rule", "{:foo => 'bar'}", "input2"])
|
45
|
+
out_opts = FiltriCmd.parse_opts
|
46
|
+
FiltriCmd.validate_opts(out_opts).should be_true
|
47
|
+
|
48
|
+
stub_const("ARGV",["input1", "input2"])
|
49
|
+
out_opts = FiltriCmd.parse_opts
|
50
|
+
$stdout.should_receive(:puts).with(/Error/i)
|
51
|
+
FiltriCmd.validate_opts(out_opts).should be_false
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'checks if files exist' do
|
56
|
+
|
57
|
+
stub_const("ARGV",["-f", "existing_file", "input_file1", "input_file2"])
|
58
|
+
out_opts = FiltriCmd.parse_opts
|
59
|
+
File.stub!(:exist?).with("existing_file").and_return true
|
60
|
+
File.stub!(:exist?).with("input_file1").and_return true
|
61
|
+
File.stub!(:exist?).with("input_file2").and_return true
|
62
|
+
FiltriCmd.validate_opts(out_opts).should be_true
|
63
|
+
|
64
|
+
stub_const("ARGV",["-f", "existing_file", "input_file1", "bad_input_file2"])
|
65
|
+
out_opts = FiltriCmd.parse_opts
|
66
|
+
File.stub!(:exist?).with("existing_file").and_return true
|
67
|
+
File.stub!(:exist?).with("input_file1").and_return true
|
68
|
+
File.stub!(:exist?).with("bad_input_file2").and_return false
|
69
|
+
$stdout.should_receive(:puts).with(/Error/i)
|
70
|
+
FiltriCmd.validate_opts(out_opts).should be_false
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#run" do
|
78
|
+
|
79
|
+
let(:rules) { %q(
|
80
|
+
|
81
|
+
# this is a comment
|
82
|
+
rule /fo+bar/ => "bazbag"
|
83
|
+
rule /go+blin/ => "NILBOG"
|
84
|
+
|
85
|
+
) }
|
86
|
+
|
87
|
+
let(:input1) { %q(
|
88
|
+
|
89
|
+
fooooooooooooooobar
|
90
|
+
cookie
|
91
|
+
goooooblin
|
92
|
+
|
93
|
+
) }
|
94
|
+
|
95
|
+
let(:result1) { %q(
|
96
|
+
|
97
|
+
bazbag
|
98
|
+
cookie
|
99
|
+
NILBOG
|
100
|
+
|
101
|
+
) }
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
it 'reads rules from a file and applies to input file' do
|
106
|
+
opts = {:rule_files=>["rule_file"], :input=> ["input_file"]}
|
107
|
+
|
108
|
+
IO.stub(:read).with("rule_file").and_return rules
|
109
|
+
ARGF.stub!(:read).and_return input1
|
110
|
+
|
111
|
+
result = FiltriCmd.run(opts, opts[:input])
|
112
|
+
result.should eq(result1)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'reads single rules applies to input file' do
|
116
|
+
opts = {:rules=>['rule /fo+bar/ => "bazbag"','rule /go+blin/ => "NILBOG"'], :input=> ["input_file"]}
|
117
|
+
|
118
|
+
ARGF.stub!(:read).and_return input1
|
119
|
+
|
120
|
+
result = FiltriCmd.run(opts, opts[:input])
|
121
|
+
result.should eq(result1)
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filtri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '2.11'
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.11'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: docile
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,7 +82,7 @@ dependencies:
|
|
82
82
|
requirements:
|
83
83
|
- - ! '>='
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
85
|
+
version: 0.1.0
|
86
86
|
type: :runtime
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -90,7 +90,7 @@ dependencies:
|
|
90
90
|
requirements:
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
93
|
+
version: 0.1.0
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: to_regexp
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,11 +107,12 @@ dependencies:
|
|
107
107
|
- - ! '>='
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
|
-
description: Filtri is a
|
111
|
-
|
110
|
+
description: Filtri is a tool that simplifies the work of applying multiple substitution
|
111
|
+
rules to a string.
|
112
112
|
email:
|
113
113
|
- karl@ninjacontrol.com
|
114
|
-
executables:
|
114
|
+
executables:
|
115
|
+
- filtri
|
115
116
|
extensions: []
|
116
117
|
extra_rdoc_files: []
|
117
118
|
files:
|
@@ -120,9 +121,13 @@ files:
|
|
120
121
|
- LICENSE.txt
|
121
122
|
- README.md
|
122
123
|
- Rakefile
|
124
|
+
- bin/filtri
|
123
125
|
- filtri.gemspec
|
124
126
|
- lib/filtri.rb
|
127
|
+
- lib/filtri/command.rb
|
125
128
|
- lib/filtri/version.rb
|
129
|
+
- resource/filtri_rules.tmLanguage
|
130
|
+
- spec/command_spec.rb
|
126
131
|
- spec/filtri_spec.rb
|
127
132
|
homepage: https://github.com/karlll/filtri/
|
128
133
|
licenses:
|
@@ -136,10 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
141
|
requirements:
|
137
142
|
- - ! '>='
|
138
143
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
140
|
-
segments:
|
141
|
-
- 0
|
142
|
-
hash: 1607576313604211744
|
144
|
+
version: 1.9.3
|
143
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
146
|
none: false
|
145
147
|
requirements:
|
@@ -148,12 +150,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
150
|
version: '0'
|
149
151
|
segments:
|
150
152
|
- 0
|
151
|
-
hash:
|
153
|
+
hash: 107123931516266263
|
152
154
|
requirements: []
|
153
155
|
rubyforge_project:
|
154
156
|
rubygems_version: 1.8.24
|
155
157
|
signing_key:
|
156
158
|
specification_version: 3
|
157
|
-
summary: A tiny
|
159
|
+
summary: A tiny tool for text substitution
|
158
160
|
test_files:
|
161
|
+
- spec/command_spec.rb
|
159
162
|
- spec/filtri_spec.rb
|