oleg 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/lib/leg.rb +1 -0
- data/lib/leg/commands/doc.rb +18 -111
- data/lib/leg/diff.rb +201 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2c98a618bee0b37cb5705e210ba7f8f68074852
|
4
|
+
data.tar.gz: a52a2608c0a829aa5ba152e42f110fb794841271
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32a1bde2f363fe02e851d11264b5eba3f6e8547dcf4cd165b9ef58b7ae6fed0730b8dcf89bd4318517e83319a9f844a354b8bd20c4a33d3dbaceff8ac6636c75
|
7
|
+
data.tar.gz: 4691effe76d202330e907159feed5c1df0190dbe0f96bd18af91f0951ae7699e432c82f3361789f65696004615a79bbd827d26595e6759ae1a9d2a95aaa1c12e
|
data/lib/leg.rb
CHANGED
data/lib/leg/commands/doc.rb
CHANGED
@@ -20,13 +20,28 @@ class Leg::Commands::Doc < Leg::Commands::BaseCommand
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
class HTMLLineByLine < Rouge::Formatter
|
24
|
+
def initialize(formatter)
|
25
|
+
@formatter = formatter
|
26
|
+
end
|
27
|
+
|
28
|
+
def stream(tokens, &b)
|
29
|
+
token_lines(tokens) do |line|
|
30
|
+
line.each do |tok, val|
|
31
|
+
yield @formatter.span(tok, val)
|
32
|
+
end
|
33
|
+
yield "\n"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
23
38
|
private
|
24
39
|
|
25
40
|
def copy_static_files
|
26
41
|
Dir["html_in/*"].each do |f|
|
27
42
|
name = File.basename(f)
|
28
43
|
unless %w(template.html style.css).include? name
|
29
|
-
FileUtils.
|
44
|
+
FileUtils.cp_r(f, "html_out/#{name}")
|
30
45
|
end
|
31
46
|
end
|
32
47
|
end
|
@@ -51,7 +66,6 @@ class Leg::Commands::Doc < Leg::Commands::BaseCommand
|
|
51
66
|
diffs = {}
|
52
67
|
FileUtils.cd("../steps") do
|
53
68
|
FileUtils.mkdir_p("0")
|
54
|
-
|
55
69
|
last_step = "0"
|
56
70
|
Dir["*"].sort_by(&:to_i).each do |step|
|
57
71
|
names = [step.to_i.to_s]
|
@@ -59,123 +73,16 @@ class Leg::Commands::Doc < Leg::Commands::BaseCommand
|
|
59
73
|
names << $1
|
60
74
|
end
|
61
75
|
|
62
|
-
|
63
|
-
section_stack = []
|
64
|
-
in_diff = false
|
65
|
-
lexer = nil
|
66
|
-
formatter = Rouge::Formatters::HTML.new
|
67
|
-
|
68
|
-
diff = `git diff --histogram --unified=100000 --ignore-space-change --no-index #{last_step} #{step}`
|
69
|
-
diff.lines.each do |line|
|
70
|
-
if !in_diff && line =~ /^\+\+\+ (.+)$/
|
71
|
-
filename = File.basename($1)
|
72
|
-
lexer = Rouge::Lexer.guess(filename: filename)
|
73
|
-
diffout << {type: :section, section_type: :file, summary: filename, content: []}
|
74
|
-
section_stack = [diffout.last]
|
75
|
-
elsif line.start_with? '@@'
|
76
|
-
in_diff = true
|
77
|
-
elsif in_diff && [' ', '+', '-'].include?(line[0])
|
78
|
-
line_hl = formatter.format(lexer.lex(line[1..-1])).gsub("\n", "")
|
79
|
-
type = {' ' => :nochange, '+' => :add, '-' => :remove }[line[0]]
|
80
|
-
|
81
|
-
section_stack.each { |s| s[:dirty] = true } if type != :nochange
|
82
|
-
|
83
|
-
if line[1..-1] =~ /^\/\*\*\* (.+) \*\*\*\/$/
|
84
|
-
section_stack = [section_stack[0]]
|
85
|
-
section_stack.last[:content] << {type: :section, section_type: :comment, summary: line[1..-1].chomp, content: []}
|
86
|
-
section_stack.push(section_stack.last[:content].last)
|
87
|
-
elsif line[1] =~ /\S/ && line.chomp[-1] == "{"
|
88
|
-
section_stack.pop if section_stack.length > 1 && section_stack.last[:section_type] == :braces
|
89
|
-
section_stack.last[:content] << {type: :section, section_type: :braces, summary: line[1..-1].chomp + " ... ", content: []}
|
90
|
-
section_stack.push(section_stack.last[:content].last)
|
91
|
-
end
|
92
|
-
|
93
|
-
section_stack.last[:content] << {type: type, content: line_hl}
|
94
|
-
|
95
|
-
if line[1..-1] =~ /^(}( \w+)?;?)$/ && section_stack.last[:section_type] == :braces
|
96
|
-
s = section_stack.pop
|
97
|
-
s[:summary] << $1
|
98
|
-
end
|
99
|
-
|
100
|
-
section_stack.each { |s| s[:dirty] = true } if type != :nochange
|
101
|
-
else
|
102
|
-
in_diff = false
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
change_chain = []
|
107
|
-
diffout.each do |file|
|
108
|
-
to_render = file[:content].dup
|
109
|
-
until to_render.empty?
|
110
|
-
cur = to_render.shift
|
111
|
-
if cur[:type] == :section
|
112
|
-
if cur[:dirty]
|
113
|
-
to_render = cur[:content] + to_render
|
114
|
-
else
|
115
|
-
if change_chain.first && change_chain.first[:content].empty?
|
116
|
-
change_chain.first[:type] = :nochange
|
117
|
-
end
|
118
|
-
if change_chain.last && change_chain.last[:content].empty?
|
119
|
-
change_chain.last[:type] = :nochange
|
120
|
-
end
|
121
|
-
change_chain = []
|
122
|
-
end
|
123
|
-
else
|
124
|
-
if cur[:type] == :nochange
|
125
|
-
if change_chain.first && change_chain.first[:content].empty?
|
126
|
-
change_chain.first[:type] = :nochange
|
127
|
-
end
|
128
|
-
if change_chain.last && change_chain.last[:content].empty?
|
129
|
-
change_chain.last[:type] = :nochange
|
130
|
-
end
|
131
|
-
change_chain = []
|
132
|
-
else
|
133
|
-
change_chain << cur
|
134
|
-
if cur[:type] == :add
|
135
|
-
change_chain.each { |c| c[:omit] = true if c[:type] == :remove }
|
136
|
-
elsif cur[:type] == :remove
|
137
|
-
cur[:omit] = true if change_chain.any? { |c| c[:type] == :add }
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
html = ""
|
145
|
-
diffout.each do |file|
|
146
|
-
html << "<div class=\"diff\">\n"
|
147
|
-
html << "<div class=\"filename\">#{file[:summary]}</div>\n"
|
148
|
-
html << "<pre class=\"highlight\"><code>"
|
149
|
-
|
150
|
-
to_render = file[:content].dup
|
151
|
-
until to_render.empty?
|
152
|
-
cur = to_render.shift
|
153
|
-
if cur[:type] == :section
|
154
|
-
if cur[:dirty]
|
155
|
-
to_render = cur[:content] + to_render
|
156
|
-
else
|
157
|
-
summary = formatter.format(lexer.lex(cur[:summary])).gsub("\n", "")
|
158
|
-
html << "<div class=\"line folded\">#{summary}</div>"
|
159
|
-
end
|
160
|
-
elsif !cur[:omit]
|
161
|
-
tag = {nochange: :div, add: :ins, remove: :del}[cur[:type]]
|
162
|
-
html << "<#{tag} class=\"line\">#{cur[:content]}</#{tag}>"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
html << "</code></pre>\n</div>\n"
|
167
|
-
end
|
76
|
+
diff = Leg::Diff.new(last_step, step)
|
168
77
|
|
169
78
|
names.each do |name|
|
170
|
-
diffs[name] = html
|
79
|
+
diffs[name] = diff.html.values.join("\n")
|
171
80
|
end
|
172
81
|
|
173
82
|
last_step = step
|
174
83
|
end
|
175
|
-
|
176
84
|
FileUtils.rmdir("0")
|
177
85
|
end
|
178
|
-
|
179
86
|
diffs
|
180
87
|
end
|
181
88
|
|
data/lib/leg/diff.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
class Leg::Diff
|
2
|
+
GIT_DIFF_OPTIONS = "--histogram --unified=100000 --ignore-space-change --no-index"
|
3
|
+
|
4
|
+
attr_reader :files, :html
|
5
|
+
|
6
|
+
def initialize(step_a, step_b)
|
7
|
+
git_diff = `git diff #{GIT_DIFF_OPTIONS} #{step_a} #{step_b}`
|
8
|
+
parse_git_diff(git_diff)
|
9
|
+
@files.values.each(&:omit_adjacent_removals!)
|
10
|
+
|
11
|
+
@html = {}
|
12
|
+
@files.each do |filename, file|
|
13
|
+
@html[filename] = file.to_html
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class DiffLine
|
18
|
+
attr_reader :type, :line
|
19
|
+
attr_writer :type
|
20
|
+
|
21
|
+
def initialize(type, line)
|
22
|
+
@type = type
|
23
|
+
@line = line
|
24
|
+
end
|
25
|
+
|
26
|
+
def empty!; @empty = true; end
|
27
|
+
def empty?; @empty; end
|
28
|
+
|
29
|
+
def omit!; @omit = true; end
|
30
|
+
def omit?; @omit; end
|
31
|
+
end
|
32
|
+
|
33
|
+
class DiffSection
|
34
|
+
attr_reader :type, :lines, :contents
|
35
|
+
|
36
|
+
def initialize(type, line=nil)
|
37
|
+
@type = type
|
38
|
+
@lines = Array(line)
|
39
|
+
@contents = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def <<(content)
|
43
|
+
@contents << content
|
44
|
+
end
|
45
|
+
|
46
|
+
def dirty!; @dirty = true; end
|
47
|
+
def dirty?; @dirty; end
|
48
|
+
end
|
49
|
+
|
50
|
+
class DiffFile < DiffSection
|
51
|
+
attr_reader :filename, :file_contents
|
52
|
+
|
53
|
+
def initialize(filename)
|
54
|
+
super(:file)
|
55
|
+
@filename = filename
|
56
|
+
@file_contents = ""
|
57
|
+
end
|
58
|
+
|
59
|
+
def append_line(line)
|
60
|
+
@file_contents << line
|
61
|
+
@file_contents << "\n" unless line.end_with? "\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
def new_file!; @new_file = true; end
|
65
|
+
def new_file?; @new_file; end
|
66
|
+
|
67
|
+
def omit_adjacent_removals!
|
68
|
+
change_chain = []
|
69
|
+
to_render = @contents.dup
|
70
|
+
until to_render.empty?
|
71
|
+
cur = to_render.shift
|
72
|
+
if cur.is_a? DiffSection
|
73
|
+
if cur.dirty?
|
74
|
+
to_render = cur.contents + to_render
|
75
|
+
else
|
76
|
+
[change_chain.first, change_chain.last].compact.each do |line|
|
77
|
+
line.type = :nochange if line.empty?
|
78
|
+
end
|
79
|
+
change_chain = []
|
80
|
+
end
|
81
|
+
else
|
82
|
+
if cur.type == :nochange
|
83
|
+
[change_chain.first, change_chain.last].compact.each do |line|
|
84
|
+
line.type = :nochange if line.empty?
|
85
|
+
end
|
86
|
+
change_chain = []
|
87
|
+
else
|
88
|
+
change_chain << cur
|
89
|
+
if cur.type == :add
|
90
|
+
change_chain.each { |c| c.omit! if c.type == :remove }
|
91
|
+
elsif cur.type == :remove
|
92
|
+
cur.omit! if change_chain.any? { |c| c.type == :add }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_html
|
100
|
+
formatter = Rouge::Formatters::HTML.new
|
101
|
+
formatter = HTMLLineByLine.new(formatter)
|
102
|
+
|
103
|
+
lexer = Rouge::Lexer.guess(filename: @filename)
|
104
|
+
code_hl = formatter.format(lexer.lex(@file_contents)).lines.each(&:chomp!)
|
105
|
+
|
106
|
+
html = ""
|
107
|
+
html << "<div class=\"diff\">\n"
|
108
|
+
html << "<div class=\"filename\">#{@filename}</div>\n"
|
109
|
+
html << "<pre class=\"highlight\"><code>"
|
110
|
+
|
111
|
+
to_render = @contents.dup
|
112
|
+
until to_render.empty?
|
113
|
+
cur = to_render.shift
|
114
|
+
if cur.is_a? DiffSection
|
115
|
+
if cur.dirty?
|
116
|
+
to_render = cur.contents + to_render
|
117
|
+
else
|
118
|
+
summary = cur.lines.map { |n| code_hl[n] }.join(" ... ").gsub("\n", "")
|
119
|
+
html << "<div class=\"line folded\">#{summary}</div>"
|
120
|
+
end
|
121
|
+
elsif !cur.omit?
|
122
|
+
tag = {nochange: :div, add: :ins, remove: :del}[cur.type]
|
123
|
+
tag = :div if new_file?
|
124
|
+
html << "<#{tag} class=\"line\">#{code_hl[cur.line]}</#{tag}>"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
html << "</code></pre>\n</div>\n"
|
128
|
+
|
129
|
+
html
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class HTMLLineByLine < Rouge::Formatter
|
134
|
+
def initialize(formatter)
|
135
|
+
@formatter = formatter
|
136
|
+
end
|
137
|
+
|
138
|
+
def stream(tokens, &b)
|
139
|
+
token_lines(tokens) do |line|
|
140
|
+
line.each do |tok, val|
|
141
|
+
yield @formatter.span(tok, val)
|
142
|
+
end
|
143
|
+
yield "\n"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def parse_git_diff(git_diff)
|
151
|
+
diff_file = nil
|
152
|
+
section_stack = nil
|
153
|
+
line_idx = nil
|
154
|
+
in_diff = false
|
155
|
+
@files = {}
|
156
|
+
|
157
|
+
git_diff.lines.each do |line|
|
158
|
+
if !in_diff && line =~ /^diff --git (\S+) (\S+)$/
|
159
|
+
diff_file = DiffFile.new(File.basename($2))
|
160
|
+
@files[diff_file.filename] = diff_file
|
161
|
+
section_stack = [diff_file]
|
162
|
+
line_idx = -1
|
163
|
+
elsif !in_diff && line.start_with?('new file')
|
164
|
+
diff_file.new_file!
|
165
|
+
elsif line.start_with? '@@'
|
166
|
+
in_diff = true
|
167
|
+
elsif in_diff && [' ', '+', '-'].include?(line[0])
|
168
|
+
type = {' ' => :nochange, '+' => :add, '-' => :remove }[line[0]]
|
169
|
+
diff_file.append_line(line[1..-1])
|
170
|
+
line_idx += 1
|
171
|
+
|
172
|
+
section_stack.each(&:dirty!) if type != :nochange
|
173
|
+
|
174
|
+
if line[1..-1] =~ /^\/\*\*\* (.+) \*\*\*\/$/
|
175
|
+
section = DiffSection.new(:comment, line_idx)
|
176
|
+
diff_file << section
|
177
|
+
section_stack = [diff_file, section]
|
178
|
+
elsif line[1] =~ /\S/ && line.chomp[-1] == "{"
|
179
|
+
section = DiffSection.new(:braces, line_idx)
|
180
|
+
section_stack.pop if section_stack.last.type == :braces
|
181
|
+
section_stack.last << section
|
182
|
+
section_stack.push(section)
|
183
|
+
end
|
184
|
+
|
185
|
+
diff_line = DiffLine.new(type, line_idx)
|
186
|
+
diff_line.empty! if line[1..-1].strip.empty?
|
187
|
+
section_stack.last << diff_line
|
188
|
+
|
189
|
+
if line[1..-1] =~ /^}( \w+)?;?$/ && section_stack.last.type == :braces
|
190
|
+
section = section_stack.pop
|
191
|
+
section.lines << line_idx
|
192
|
+
end
|
193
|
+
|
194
|
+
section_stack.each(&:dirty!) if type != :nochange
|
195
|
+
else
|
196
|
+
in_diff = false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oleg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Ruten
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rugged
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- lib/leg/commands/repo.rb
|
74
74
|
- lib/leg/commands/undiff.rb
|
75
75
|
- lib/leg/commands/unrepo.rb
|
76
|
+
- lib/leg/diff.rb
|
76
77
|
homepage: https://github.com/yjerem/leg
|
77
78
|
licenses:
|
78
79
|
- MIT
|