gliss 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/gliss.rb +81 -21
- data/spec/gliss_spec.rb +90 -1
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/lib/gliss.rb
CHANGED
@@ -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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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 ||
|
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
|
82
|
+
|
83
|
+
match = begins_gloss(line, sha, allow_indented)
|
76
84
|
if match
|
77
|
-
continuing =
|
78
|
-
|
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
|
-
|
109
|
-
@
|
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
|
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|
|
data/spec/gliss_spec.rb
CHANGED
@@ -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 ==
|
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:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
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-
|
18
|
+
date: 2011-07-20 00:00:00 -05:00
|
19
19
|
default_executable: gliss
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|