gliss 0.1.2 → 0.1.3
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.
- 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
|