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 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