oleg 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe515e58859a107bbab71359a195c02320c7103f
4
- data.tar.gz: 9e6be5fa4d23ca96d0bb5818bec9aaf4d5f37f25
3
+ metadata.gz: e2c98a618bee0b37cb5705e210ba7f8f68074852
4
+ data.tar.gz: a52a2608c0a829aa5ba152e42f110fb794841271
5
5
  SHA512:
6
- metadata.gz: 0616f537ca77cb5e405e4704f50043e54d8a217fe8e29de6b8e08859063bf46ebf11677461b23b05214e9b0e817c17d0264eaee172bd0b95876e6f9da0eb2a31
7
- data.tar.gz: f315be05ebda93d8e3ac796f8456f872b39f3b53857d9068272a6b8629fbcb241b41cc099bc12c027893bacd81f52846bed34aaf4514623fd0659cebfeb554c3
6
+ metadata.gz: 32a1bde2f363fe02e851d11264b5eba3f6e8547dcf4cd165b9ef58b7ae6fed0730b8dcf89bd4318517e83319a9f844a354b8bd20c4a33d3dbaceff8ac6636c75
7
+ data.tar.gz: 4691effe76d202330e907159feed5c1df0190dbe0f96bd18af91f0951ae7699e432c82f3361789f65696004615a79bbd827d26595e6759ae1a9d2a95aaa1c12e
data/lib/leg.rb CHANGED
@@ -9,4 +9,5 @@ end
9
9
 
10
10
  require 'leg/cli'
11
11
  require 'leg/commands'
12
+ require 'leg/diff'
12
13
 
@@ -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.cp(f, "html_out/#{name}")
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
- diffout = []
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.7.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-13 00:00:00.000000000 Z
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