chirp 0.1.0 → 0.2.0

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.
Files changed (57) hide show
  1. data/History.txt +10 -3
  2. data/Manifest.txt +49 -1
  3. data/README.txt +4 -4
  4. data/Rakefile +3 -3
  5. data/bin/chirp +42 -0
  6. data/lib/chirp.rb +5 -223
  7. data/lib/chirp/application.rb +252 -0
  8. data/lib/chirp/statement.rb +91 -0
  9. data/test/account.dir/input +7 -0
  10. data/test/account.dir/output +1 -0
  11. data/test/account.dir/program.chirp +20 -0
  12. data/test/action.dir/input +7 -0
  13. data/test/action.dir/output +1 -0
  14. data/test/action.dir/program.chirp +3 -0
  15. data/test/beforeafter.dir/input +7 -0
  16. data/test/beforeafter.dir/output +11 -0
  17. data/test/beforeafter.dir/program.chirp +7 -0
  18. data/test/fields.dir/input +3 -0
  19. data/test/fields.dir/output +3 -0
  20. data/test/fields.dir/program.chirp +5 -0
  21. data/test/fields_sep.dir/input +7 -0
  22. data/test/fields_sep.dir/output +7 -0
  23. data/test/fields_sep.dir/program.chirp +6 -0
  24. data/test/files.dir/a.ignore +1 -0
  25. data/test/files.dir/a.txt +1 -0
  26. data/test/files.dir/b.txt +1 -0
  27. data/test/files.dir/c.stuff +1 -0
  28. data/test/files.dir/input +7 -0
  29. data/test/files.dir/output +2 -0
  30. data/test/files.dir/program.chirp +6 -0
  31. data/test/inplace.dir/a.txt +1 -0
  32. data/test/inplace.dir/b.txt +1 -0
  33. data/test/inplace.dir/input +7 -0
  34. data/test/inplace.dir/output +3 -0
  35. data/test/inplace.dir/program.chirp +9 -0
  36. data/test/line_no.dir/input +7 -0
  37. data/test/line_no.dir/output +1 -0
  38. data/test/line_no.dir/program.chirp +1 -0
  39. data/test/match.dir/input +14 -0
  40. data/test/match.dir/output +6 -0
  41. data/test/match.dir/program.chirp +1 -0
  42. data/test/proc.dir/input +8 -0
  43. data/test/proc.dir/output +3 -0
  44. data/test/proc.dir/program.chirp +3 -0
  45. data/test/span.dir/input +13 -0
  46. data/test/span.dir/output +7 -0
  47. data/test/span.dir/program.chirp +1 -0
  48. data/test/span2.dir/input +7 -0
  49. data/test/span2.dir/output +5 -0
  50. data/test/span2.dir/program.chirp +1 -0
  51. data/test/string.dir/input +14 -0
  52. data/test/string.dir/output +6 -0
  53. data/test/string.dir/program.chirp +1 -0
  54. data/test/test_application.rb +42 -0
  55. data/test/test_statement.rb +118 -0
  56. metadata +60 -7
  57. data/test/test_chirp.rb +0 -0
@@ -0,0 +1,91 @@
1
+ #
2
+ # Copyright 2006-2007 Russell Olsen
3
+ # Chirp is distributed under the same license as Ruby itself.
4
+ #
5
+
6
+ module Chirp
7
+
8
+ class StringPredicate
9
+ def initialize(string)
10
+ @string = string
11
+ end
12
+
13
+ def evaluate(context)
14
+ context.line == @string
15
+ end
16
+ end
17
+
18
+ class LambdaPredicate
19
+ def initialize(proc)
20
+ @proc = proc
21
+ end
22
+
23
+ def evaluate(context)
24
+ context.execute(@proc)
25
+ end
26
+ end
27
+
28
+ class LineNumberPredicate
29
+ def initialize(line_no)
30
+ @line_no = line_no
31
+ end
32
+
33
+ def evaluate(context)
34
+ context.line_no == @line_no
35
+ end
36
+ end
37
+
38
+ class MatchPredicate
39
+ def initialize(regex)
40
+ @regex = regex
41
+ end
42
+
43
+ def evaluate(context)
44
+ context.line =~ @regex
45
+ end
46
+ end
47
+
48
+ class RangePredicate
49
+ def initialize(range)
50
+ @range = range
51
+ end
52
+
53
+ def evaluate(context)
54
+ @range.===(context.line_no)
55
+ end
56
+ end
57
+
58
+ class SpanPredicate
59
+ BEFORE_SPAN = 0
60
+ IN_SPAN = 1
61
+ AFTER_SPAN = 2
62
+
63
+ def initialize(p1, p2)
64
+ @p1 = p1
65
+ @p2 = p2
66
+ @state = BEFORE_SPAN
67
+ end
68
+
69
+ def evaluate(context)
70
+ if @state == BEFORE_SPAN
71
+ @state = IN_SPAN if @p1.evaluate(context)
72
+ end
73
+ ret = @state == IN_SPAN
74
+ if @state == IN_SPAN
75
+ @state = AFTER_SPAN if @p2.evaluate(context)
76
+ end
77
+ ret
78
+ end
79
+ end
80
+
81
+ class Statement
82
+ def initialize(predicate, action)
83
+ @predicate = predicate
84
+ @action = action
85
+ end
86
+
87
+ def evaluate(context)
88
+ context.execute(@action) if @predicate.evaluate(context)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,7 @@
1
+ credit 1000
2
+ debit 10
3
+ debit 10
4
+ debit 0
5
+ credit 20
6
+ debit 1
7
+ debit 2
@@ -0,0 +1 @@
1
+ Balance is 997
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env chirp
2
+
3
+ #
4
+ # Simple bank acccount program, shows the use of fields
5
+ #
6
+ file do
7
+ before {@sum=0}
8
+
9
+ line(lambda{fields[0] =~ /credit/}) do
10
+ @sum += fields[1].to_i
11
+ end
12
+
13
+ line(lambda{fields[0] =~ /debit/}) do
14
+ @sum -= fields[1].to_i
15
+ end
16
+
17
+ after {puts "Balance is #{@sum}"}
18
+ end
19
+
20
+
@@ -0,0 +1,7 @@
1
+ 11
2
+ 22
3
+ 33
4
+ 44
5
+ 55
6
+ 66
7
+ 77
@@ -0,0 +1 @@
1
+ matched line 3 text is 33
@@ -0,0 +1,3 @@
1
+ file do
2
+ line(3) { puts "matched line #{line_no} text is #{line}" }
3
+ end
@@ -0,0 +1,7 @@
1
+ 11
2
+ 22
3
+ 33
4
+ 44
5
+ 55
6
+ 66
7
+ 77
@@ -0,0 +1,11 @@
1
+ before any processing
2
+ before file
3
+ 11
4
+ 22
5
+ 33
6
+ 44
7
+ 55
8
+ 66
9
+ 77
10
+ after file
11
+ after any processing
@@ -0,0 +1,7 @@
1
+ run { puts "before any processing" }
2
+ file do
3
+ before { puts "before file" }
4
+ line
5
+ after { puts "after file" }
6
+ end
7
+ run { puts "after any processing" }
@@ -0,0 +1,3 @@
1
+ the rain in
2
+ spain falls mainly on the pain
3
+ 11 22 33
@@ -0,0 +1,3 @@
1
+ ["the", "rain", "in"]
2
+ ["spain", "falls", "mainly", "on", "the", "pain"]
3
+ ["11", "22", "33"]
@@ -0,0 +1,5 @@
1
+ require 'pp'
2
+
3
+ file do
4
+ line { pp fields }
5
+ end
@@ -0,0 +1,7 @@
1
+ russ:olsen:1234:7717
2
+ tom:smith:1234:7717
3
+ russ:molsen:789:7717
4
+ guss:olsen:1234
5
+ aa:bb:cc:dd:ee:ff
6
+
7
+ after:blank:line
@@ -0,0 +1,7 @@
1
+ ["russ", "olsen", "1234", "7717"]
2
+ ["tom", "smith", "1234", "7717"]
3
+ ["russ", "molsen", "789", "7717"]
4
+ ["guss", "olsen", "1234"]
5
+ ["aa", "bb", "cc", "dd", "ee", "ff"]
6
+ []
7
+ ["after", "blank", "line"]
@@ -0,0 +1,6 @@
1
+ require 'pp'
2
+
3
+ file do
4
+ field_separator ':'
5
+ line { pp fields }
6
+ end
@@ -0,0 +1 @@
1
+ example file
@@ -0,0 +1 @@
1
+ example file
@@ -0,0 +1 @@
1
+ example file
@@ -0,0 +1 @@
1
+ example file
@@ -0,0 +1,7 @@
1
+ 11
2
+ 22
3
+ 33
4
+ 44
5
+ 55
6
+ 66
7
+ 77
@@ -0,0 +1,2 @@
1
+ paths: a.txtb.txt
2
+ paths: a.txtb.txt
@@ -0,0 +1,6 @@
1
+
2
+ files "*.txt"
3
+
4
+ file do
5
+ line {puts "paths: #{paths}"}
6
+ end
@@ -0,0 +1 @@
1
+ contents of a.txt
@@ -0,0 +1 @@
1
+ contents of b.txt
@@ -0,0 +1,7 @@
1
+ 11
2
+ 22
3
+ 33
4
+ 44
5
+ 55
6
+ 66
7
+ 77
@@ -0,0 +1,3 @@
1
+ before any processing
2
+ CONTENTS OF A.TXT
3
+ CONTENTS OF B.TXT
@@ -0,0 +1,9 @@
1
+ files "*.txt"
2
+
3
+ run { puts "before any processing" }
4
+ file do
5
+ edit_in_place
6
+ line { puts line.upcase }
7
+ end
8
+ run { puts File.read('a.txt') }
9
+ run { puts File.read('b.txt') }
@@ -0,0 +1,7 @@
1
+ 11
2
+ 22
3
+ 33
4
+ 44
5
+ 55
6
+ 66
7
+ 77
@@ -0,0 +1 @@
1
+ 33
@@ -0,0 +1 @@
1
+ file {line(3)}
@@ -0,0 +1,14 @@
1
+ does not match
2
+ does not match
3
+ matches abc
4
+ does not match
5
+ does not match
6
+ matches abc
7
+ matches abc
8
+ matches abc
9
+ matches abc
10
+ does not match
11
+
12
+ abc
13
+
14
+ sjklsjlksjkl
@@ -0,0 +1,6 @@
1
+ matches abc
2
+ matches abc
3
+ matches abc
4
+ matches abc
5
+ matches abc
6
+ abc
@@ -0,0 +1 @@
1
+ file { line(/abc/) }
@@ -0,0 +1,8 @@
1
+ russ this should match
2
+ no match
3
+ russ match
4
+ no russ match
5
+ russ match
6
+ no
7
+ no
8
+
@@ -0,0 +1,3 @@
1
+ russ this should match
2
+ russ match
3
+ russ match
@@ -0,0 +1,3 @@
1
+ file do
2
+ line(lambda{/russ/=~fields[0]})
3
+ end
@@ -0,0 +1,13 @@
1
+ no
2
+ no
3
+ no
4
+ start
5
+ this matches
6
+
7
+ jdjdjd
8
+
9
+ djjdj
10
+ end
11
+ no
12
+ djdjd
13
+ ndndn
@@ -0,0 +1,7 @@
1
+ start
2
+ this matches
3
+
4
+ jdjdjd
5
+
6
+ djjdj
7
+ end
@@ -0,0 +1 @@
1
+ file {line(/start/,/end/)}
@@ -0,0 +1,7 @@
1
+ 11
2
+ 22
3
+ 33
4
+ 44
5
+ 55
6
+ end
7
+ 66
@@ -0,0 +1,5 @@
1
+ 22
2
+ 33
3
+ 44
4
+ 55
5
+ end
@@ -0,0 +1 @@
1
+ file {line(2,/end/)}
@@ -0,0 +1,14 @@
1
+ does not match
2
+ does not match
3
+ abc
4
+ does not match
5
+ does not match
6
+ abc
7
+ abc
8
+ abc
9
+ abc
10
+ does not match
11
+
12
+ abc
13
+
14
+ sjklsjlksjkl
@@ -0,0 +1,6 @@
1
+ abc
2
+ abc
3
+ abc
4
+ abc
5
+ abc
6
+ abc
@@ -0,0 +1 @@
1
+ file {line('abc')}
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ require 'test/unit'
4
+ require 'stringio'
5
+ require 'fileutils'
6
+
7
+ TEST_DIR=File.dirname(__FILE__)
8
+ TEMP_DIR=File.join(TEST_DIR, 'temp')
9
+
10
+ class TestApplication < Test::Unit::TestCase
11
+ include Chirp
12
+
13
+ def setup
14
+ FileUtils.rm_rf(TEMP_DIR)
15
+ end
16
+
17
+ def teardown
18
+ FileUtils.rm_rf(TEMP_DIR)
19
+ end
20
+
21
+ def run_chirp_test(dir)
22
+ FileUtils.cp_r(dir, TEMP_DIR)
23
+
24
+ program = File.read(File.join(TEMP_DIR, 'program.chirp'))
25
+ input = File.read(File.join(TEMP_DIR, 'input'))
26
+ expected_output = File.read(File.join(TEMP_DIR, 'output'))
27
+
28
+ app = Application.new(program)
29
+ in_stream = StringIO.new(input)
30
+ out_stream = StringIO.new
31
+
32
+ FileUtils.chdir(TEMP_DIR) {app.evaluate(in_stream, out_stream)}
33
+
34
+ assert_equal(expected_output, out_stream.string)
35
+ end
36
+
37
+ Dir.glob("#{TEST_DIR}/*.dir").each do |dir|
38
+ method_name = File.basename(dir).sub(/\.dir$/,'')
39
+ define_method("test_#{method_name}") { run_chirp_test(dir) }
40
+ end
41
+
42
+ end