gliss 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/VERSION +1 -1
  2. data/lib/gliss.rb +81 -21
  3. data/spec/gliss_spec.rb +90 -1
  4. metadata +4 -4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
@@ -24,19 +24,25 @@ require 'set'
24
24
  module Gliss
25
25
  Gloss = Struct.new(:sha, :tag, :text)
26
26
  CommitMsg = Struct.new(:sha, :log)
27
- GLOSS_RE=/^((?:[^\s]){3})(-?)(.*?)\1(.*)/
28
- GLOSS_TAG=3
29
- GLOSS_TEXT=4
30
- GLOSS_STRIP=2
31
- INDENT_RE=/^(\s+)(.*)$/
27
+ GLOSS_TAG_RE=/(([^\s])\3\3)(-?)(.*?)\2(.*)/
28
+ GLOSS_INDENTED_RE=/^(\s*)#{GLOSS_TAG_RE}/
29
+ GLOSS_MIDLINE_RE=/^(.*?)#{GLOSS_TAG_RE}/
30
+ GLOSS_RE=/^()#{GLOSS_TAG_RE}/
31
+
32
+ GLOSS_TAG=5
33
+ GLOSS_TEXT=6
34
+ GLOSS_STRIP=4
35
+ GLOSS_BEFORE=1
36
+
37
+ BARE_INDENT_RE=/(\s+)(.*)/
32
38
  INDENT_AMOUNT=1
33
39
  INDENTED_TEXT=2
34
40
 
35
41
  attr_reader :filter
36
42
 
37
- def self.glosses_between(repo, older, newer)
43
+ def self.glosses_between(repo, older, newer, allow_indented=false)
38
44
  commits_between(repo, older, newer).inject([]) do |acc, commit|
39
- acc + glosses_in(commit.log, commit.sha)
45
+ acc + glosses_in(commit.log, commit.sha, allow_indented)
40
46
  end
41
47
  end
42
48
 
@@ -51,40 +57,79 @@ module Gliss
51
57
  end
52
58
  end
53
59
 
54
- def self.glosses_in(message, sha=nil)
60
+ def self.glosses_in(message, sha=nil, allow_indented=false)
55
61
  result = []
56
62
  continuing = false
63
+ ws = ""
57
64
  indent_matcher = nil
58
65
 
59
66
  message.each_line do |line|
60
67
  line.chomp!
61
68
  match = nil
62
69
  if continuing
63
- match = line.match((indent_matcher || INDENT_RE))
70
+ match = line.match((indent_matcher || /^(?:#{ws})#{BARE_INDENT_RE}$/))
64
71
 
65
72
  if match
66
- indent_matcher ||= /^(#{match[INDENT_AMOUNT]})(.*)$/
73
+ indent_matcher ||= /^(?:#{ws})(#{match[INDENT_AMOUNT]})(.*)$/
67
74
  text = match[INDENTED_TEXT].strip
68
75
  result[-1].text << text
76
+ next
69
77
  else
70
78
  indent_matcher = nil
71
79
  continuing = false
72
80
  end
73
81
  end
74
-
75
- match = line.match(GLOSS_RE)
82
+
83
+ match = begins_gloss(line, sha, allow_indented)
76
84
  if match
77
- continuing = true
78
- indent_matcher = nil
79
- tag = match[GLOSS_TAG].strip
80
- text = match[GLOSS_TEXT].strip
81
- result << Gloss.new(sha, tag, [text])
85
+ continuing, indent_matcher, ws, new_gloss = match
86
+ result << new_gloss
82
87
  end
83
88
  end
84
89
 
85
90
  result.each {|g| g.text.reject! {|t| t == ''}; g.text = g.text.join(" ")}
86
91
  end
87
92
 
93
+ def self.begins_gloss(line, sha, allow_indented=false)
94
+ match = line.match(allow_indented ? GLOSS_INDENTED_RE : GLOSS_RE)
95
+ if match
96
+ ws = match[GLOSS_BEFORE]
97
+ tag = match[GLOSS_TAG].strip
98
+ text = match[GLOSS_TEXT].strip
99
+ return [true, nil, ws, Gloss.new(sha, tag, [text])]
100
+ end
101
+ nil
102
+ end
103
+
104
+ def self.split_glosses(gloss, split_glosses=false)
105
+ if split_glosses
106
+ result_glosses = [gloss]
107
+ text = gloss.text
108
+ match = text.match(GLOSS_MIDLINE_RE)
109
+ while match
110
+ result_glosses[-1].text = match[GLOSS_BEFORE].strip if result_glosses[-1]
111
+ tag = match[GLOSS_TAG].strip
112
+ text = match[GLOSS_TEXT].strip
113
+ result_glosses << Gloss.new(gloss.sha, tag, text)
114
+ match = text.match(GLOSS_MIDLINE_RE)
115
+ end
116
+
117
+ if block_given?
118
+ result_glosses.each do |g|
119
+ yield g
120
+ end
121
+ else
122
+ result_glosses
123
+ end
124
+ else
125
+ if block_given?
126
+ yield gloss
127
+ else
128
+ return [gloss]
129
+ end
130
+ end
131
+ end
132
+
88
133
  class App
89
134
  def initialize(args=nil)
90
135
  @args = (args || ARGV.dup)
@@ -104,9 +149,11 @@ module Gliss
104
149
 
105
150
  private
106
151
  def output_glosses(repo)
107
- Gliss::glosses_between(repo, @from, @to).each do |gloss|
108
- if gloss.tag =~ @filter
109
- @output_proc.call(gloss)
152
+ Gliss::glosses_between(repo, @from, @to, @allow_indented_glosses).each do |gloss|
153
+ Gliss::split_glosses(gloss, @split_glosses) do |gl|
154
+ if gl.tag =~ @filter
155
+ @output_proc.call(gl)
156
+ end
110
157
  end
111
158
  end
112
159
  end
@@ -147,11 +194,24 @@ module Gliss
147
194
  @repo = repo
148
195
  end
149
196
 
150
- opts.on("-f REGEX", "--filter REGEX", "Output only messages with tags matching REGEX", "(default is all tags)") do |filter|
197
+ opts.on("-f REGEX", "--filter REGEX", "Output only messages with tags matching", "REGEX (default is all tags)") do |filter|
151
198
  new_filter = Regexp.new(filter)
152
199
  @filter = @filter ? Regexp.union(@filter, new_filter) : new_filter
153
200
  end
154
201
 
202
+ opts.on("--split-glosses", "Attempt to find multiple glosses in a line.", "Note that this option may return","spurious glosses") do
203
+ @split_glosses = true
204
+ end
205
+
206
+ opts.on("--allow-indented-glosses", "Find glosses that don't begin at","the beginning of a line") do
207
+ @allow_indented_glosses = true
208
+ end
209
+
210
+ opts.on("--permissive", "Find as many malformed glosses as possible.","Implies --allow-indented-glosses and", "--split-glosses") do
211
+ @split_glosses = true
212
+ @allow_indented_glosses = true
213
+ end
214
+
155
215
  opts.on("-w", "--whole-commit", "Output entire commit messages that contain glosses") do
156
216
  @seen_messages = Set.new
157
217
  @output_proc = Proc.new do |gloss|
@@ -17,15 +17,104 @@ This line does not contain a gloss.
17
17
 
18
18
  This is a gloss in paragraph format.
19
19
  This is a good format for longer comments.
20
+ ===UGH=== this is a gloss that has a ===MALFORMED=== gloss attached
21
+
22
+ ===YUCK=== this is a gloss that has two ===MALFORMED=== glosses attached ===TO=== it
23
+
24
+ ===BLEAH=== this is a gloss that has two ===MALFORMED=== glosses attached
25
+ ===ONE=== of which is on the second line
26
+
27
+ Foo
28
+
29
+ ===INDENTED=== this should only be a gloss if indenting is allowed
30
+ ===INDENTED2=== this should not be part of the preceding gloss
31
+ but these lines should be appended on
32
+
33
+ abcCRUFTabc this should not be a gloss
34
+ END
35
+
36
+ SECOND_TEST = <<-END
37
+ This is a test commit.
38
+ ===FOO=== this is a bogus gloss
39
+
40
+ ===BAR=== this is not a bogus gloss, but ===MIDLINE=== this is
41
+ ===MIDLINE2=== and so is this
42
+
43
+
20
44
  END
21
45
 
22
46
  before(:each) do
23
47
  @glosses = Gliss.glosses_in(TEST_MESSAGE)
24
48
  end
25
49
 
50
+ it "correctly splits glosses when asked to" do
51
+ ugh = @glosses.select {|g| g.tag == "UGH"}
52
+ ugh.size.should == 1
53
+ splits = Gliss::split_glosses(ugh[0], true)
54
+ splits.size.should == 2
55
+ splits[0].tag.should == "UGH"
56
+ splits[0].text.should == "this is a gloss that has a"
57
+ splits[1].text.should == "gloss attached"
58
+ splits[1].tag.should == "MALFORMED"
59
+ end
60
+
61
+ it "correctly splits malformed glosses with more than one midline gloss when asked to" do
62
+ yuck = @glosses.select {|g| g.tag == "YUCK"}
63
+ yuck.size.should == 1
64
+ splits = Gliss::split_glosses(yuck[0], true)
65
+ splits.size.should == 3
66
+ splits.map{|g| g.tag}.should == %w{YUCK MALFORMED TO}
67
+ splits.map{|g| g.text}.should == ["this is a gloss that has two", "glosses attached", "it"]
68
+ end
69
+
70
+ it "correctly splits malformed glosses with more than one mid-multiline gloss gloss when asked to" do
71
+ bleah = @glosses.select {|g| g.tag == "BLEAH"}
72
+ bleah.size.should == 1
73
+ splits = Gliss::split_glosses(bleah[0], true)
74
+ splits.size.should == 3
75
+ splits.map{|g| g.tag}.should == %w{BLEAH MALFORMED ONE}
76
+ splits.map{|g| g.text}.should == ["this is a gloss that has two", "glosses attached", "of which is on the second line"]
77
+ end
78
+
79
+ it "correctly operates in permissive mode" do
80
+ @glosses = Gliss.glosses_in(SECOND_TEST, nil, true)
81
+ @glosses.size.should == 2
82
+ bar = @glosses.select {|g| g.tag == "BAR"}
83
+ bar.size.should == 1
84
+ splits = Gliss::split_glosses(bar[0], true)
85
+ splits.size.should == 3
86
+ splits.map{|g| g.tag}.should == %w{BAR MIDLINE MIDLINE2}
87
+ splits.map{|g| g.text}.should == ["this is not a bogus gloss, but", "this is", "and so is this"]
88
+ end
89
+
26
90
  it "correctly identifies single-line glosses" do
27
91
  @glosses.select {|g| g.tag == "FOO" && g.text == "is an example gloss of type FOO"}.size.should == 1
28
92
  end
93
+
94
+ it "does not spuriously identify indented glosses" do
95
+ @glosses.select {|g| g.tag == "INDENTED"}.size.should == 0
96
+ @glosses.select {|g| g.tag == "INDENTED2"}.size.should == 0
97
+ end
98
+
99
+ it "correctly identifies indented glosses when told to" do
100
+ @glosses = Gliss.glosses_in(TEST_MESSAGE, nil, true)
101
+ @glosses.select {|g| g.tag == "INDENTED"}.size.should == 1
102
+ end
103
+
104
+ it "correctly identifies consecutive indented glosses" do
105
+ @glosses = Gliss.glosses_in(TEST_MESSAGE, nil, true)
106
+ @glosses.select {|g| g.tag == "INDENTED"}.size.should == 1
107
+ @glosses.select {|g| g.tag == "INDENTED" && g.text == "this should only be a gloss if indenting is allowed"}.size.should == 1
108
+ @glosses.select {|g| g.tag == "INDENTED" && g.text =~ /INDENTED2/}.size.should == 0
109
+ @glosses.select {|g| g.tag == "INDENTED2"}.size.should == 1
110
+ @glosses.select {|g| g.tag == "INDENTED2" && g.text =~ /not be part of the preceding gloss/}.size.should == 1
111
+ end
112
+
113
+ it "correctly identifies indented multiline glosses when told to" do
114
+ @glosses = Gliss.glosses_in(TEST_MESSAGE, nil, true)
115
+ @glosses.select {|g| g.tag == "INDENTED2"}.size.should == 1
116
+ @glosses.select {|g| g.tag == "INDENTED2" && g.text =~ /but these lines should be appended on/}.size.should == 1
117
+ end
29
118
 
30
119
  it "correctly identifies multiple-line glosses" do
31
120
  @glosses.select {|g| g.tag == "BAR" && g.text == "is a gloss that spans several lines because each line has the same indent or at least that much"}.size.should == 1
@@ -46,7 +135,7 @@ END
46
135
  end
47
136
 
48
137
  it "finds multiple glosses in a message" do
49
- @glosses.size.should == 5
138
+ @glosses.size.should == 8
50
139
  end
51
140
 
52
141
  it "does not create spurious glosses" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gliss
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 2
10
- version: 0.1.2
9
+ - 3
10
+ version: 0.1.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Will Benton
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-28 00:00:00 -05:00
18
+ date: 2011-07-20 00:00:00 -05:00
19
19
  default_executable: gliss
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency