pmlcode 0.1.1 → 0.2.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/README.md +9 -5
- data/lib/pmlcode.rb +8 -2
- data/lib/pmlcode/cli.rb +22 -8
- data/lib/pmlcode/content.rb +98 -0
- data/lib/pmlcode/display.rb +31 -0
- data/lib/pmlcode/source.rb +25 -0
- data/lib/pmlcode/updater.rb +56 -19
- data/lib/pmlcode/updaters/full_updater.rb +10 -4
- data/lib/pmlcode/updaters/sparse_updater.rb +8 -8
- data/lib/pmlcode/version.rb +1 -1
- data/pmlcode.gemspec +1 -0
- metadata +18 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7c9d54c8aff1abb04b6b9c83b086c937cc95faa
|
4
|
+
data.tar.gz: 05225b9edfdfa6ea2eeff33bca12b24bea7e5098
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7bc407d5a5a7b7edb8fc1fad07d616fc7609dbcc3dfdb4c216d1eed5d05e59b13f6250415223bf5471425782635228d0ac852faba56a04fc80b32f75b4eb7a0
|
7
|
+
data.tar.gz: 192249c2ab7b04ebfa7441f20facdc4300771834104437c723d12344098faff726667b9acf2e28597dbbfc141f3b6e17e468a977b776f233d71fb284c121e45c
|
data/README.md
CHANGED
@@ -23,15 +23,19 @@ Will generate the referenced file, extracting it from the
|
|
23
23
|
`origin/02-testing.01-start` ref of `/path/to/git/working/copy`.
|
24
24
|
|
25
25
|
You can also extract the entire branch using the `-t full` option,
|
26
|
-
process as many `.pml` files as you like at once,
|
27
|
-
|
26
|
+
process as many `.pml` files as you like at once, be warned of missing
|
27
|
+
parts, see the file content (incl highlights), customize the
|
28
|
+
pattern used to extract the metadata from the filename, and more.
|
28
29
|
|
29
|
-
See `pmlcode --help` for more details
|
30
|
+
See `pmlcode --help` for more details (or read `USAGE`
|
31
|
+
and the options in [PMLCode::CLI](./lib/pmlcode/cli.rb)).
|
30
32
|
|
31
33
|
## Contributing
|
32
34
|
|
33
|
-
Bug reports and pull requests are welcome on GitHub at
|
35
|
+
Bug reports and pull requests are welcome on GitHub at
|
36
|
+
https://github.com/bruce/pmlcode.
|
34
37
|
|
35
38
|
## License
|
36
39
|
|
37
|
-
The gem is available as open source under the terms of
|
40
|
+
The gem is available as open source under the terms of
|
41
|
+
the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/pmlcode.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
-
require "pmlcode/version"
|
2
|
-
|
3
1
|
require "nokogiri"
|
2
|
+
require "rainbow"
|
3
|
+
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
require "pmlcode/version"
|
4
7
|
|
5
8
|
module PMLCode
|
6
9
|
autoload :CLI, 'pmlcode/cli'
|
7
10
|
autoload :Updater, 'pmlcode/updater'
|
11
|
+
autoload :Content, 'pmlcode/content'
|
12
|
+
autoload :Display, 'pmlcode/display'
|
13
|
+
autoload :Source, 'pmlcode/source'
|
8
14
|
end
|
data/lib/pmlcode/cli.rb
CHANGED
@@ -8,6 +8,8 @@ module PMLCode::CLI
|
|
8
8
|
|
9
9
|
pmlcode [PML_PATH, ...] [OPTIONS]
|
10
10
|
|
11
|
+
PML_PATHs can optionally include a :LINENUM suffix.
|
12
|
+
|
11
13
|
## SYNOPSIS
|
12
14
|
|
13
15
|
Looks for `<embed>` tags whose `file` attribute match `--pattern`, extracting the
|
@@ -80,11 +82,11 @@ module PMLCode::CLI
|
|
80
82
|
parser = build_parser(options)
|
81
83
|
parser.parse!(args)
|
82
84
|
|
83
|
-
|
85
|
+
sources = prepare(options, parser, args)
|
84
86
|
|
85
|
-
|
86
|
-
options.
|
87
|
-
options.output = File.dirname(
|
87
|
+
sources.each do |source|
|
88
|
+
options.source = source
|
89
|
+
options.output = File.dirname(source.path)
|
88
90
|
update!(options)
|
89
91
|
end
|
90
92
|
|
@@ -119,14 +121,14 @@ module PMLCode::CLI
|
|
119
121
|
$stderr.puts parser
|
120
122
|
exit
|
121
123
|
end
|
122
|
-
|
123
|
-
missing =
|
124
|
+
sources = args.map { |pml| PMLCode::Source.parse(pml) }
|
125
|
+
missing = sources.select(&:missing?)
|
124
126
|
unless missing.empty?
|
125
|
-
$stderr.puts "PML
|
127
|
+
$stderr.puts "PML sources #{missing} not found"
|
126
128
|
puts parser
|
127
129
|
exit
|
128
130
|
end
|
129
|
-
|
131
|
+
sources
|
130
132
|
end
|
131
133
|
|
132
134
|
def self.build_parser(options)
|
@@ -145,6 +147,18 @@ module PMLCode::CLI
|
|
145
147
|
options.pattern = Regexp.new(value)
|
146
148
|
end
|
147
149
|
|
150
|
+
opts.on('-c', '--content', "Show content") do
|
151
|
+
options.content = true
|
152
|
+
end
|
153
|
+
|
154
|
+
opts.on("-V", "--verbose", "Verbose output (Only useful with --content)") do
|
155
|
+
options.verbose = true
|
156
|
+
end
|
157
|
+
|
158
|
+
opts.on('-x', '--dry-run', "Dry run (do not write files)") do
|
159
|
+
options.dry_run = true
|
160
|
+
end
|
161
|
+
|
148
162
|
opts.on_tail("-h", "--help", "Show this message") do
|
149
163
|
puts opts
|
150
164
|
exit
|
@@ -0,0 +1,98 @@
|
|
1
|
+
class PMLCode::Content
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
def self.parse(text)
|
5
|
+
parser = Parser.new(text)
|
6
|
+
new(parser.result)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(lines)
|
10
|
+
@lines = lines
|
11
|
+
end
|
12
|
+
|
13
|
+
def has_part?(name)
|
14
|
+
@lines.any? { |l| l.in_part?(name) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def each(&block)
|
18
|
+
@lines.each(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
@lines.map(&:text)
|
23
|
+
end
|
24
|
+
|
25
|
+
class Line
|
26
|
+
|
27
|
+
attr_reader :text
|
28
|
+
|
29
|
+
def initialize(text, parts = [], highlighted = false)
|
30
|
+
@text = text
|
31
|
+
@parts = parts
|
32
|
+
@highlighted = highlighted
|
33
|
+
end
|
34
|
+
|
35
|
+
def in_part?(part = nil)
|
36
|
+
if part
|
37
|
+
@parts.include?(part)
|
38
|
+
else
|
39
|
+
!@parts.empty?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def highlighted?
|
44
|
+
@highlighted
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class Parser
|
50
|
+
|
51
|
+
PART_START = /START:\s?(\S+)/
|
52
|
+
PART_END = /END:\s?(\S+)/
|
53
|
+
|
54
|
+
HL_START = /START_HIGHLIGHT/
|
55
|
+
HL_END = /END_HIGHLIGHT/
|
56
|
+
|
57
|
+
def initialize(raw)
|
58
|
+
@raw = raw
|
59
|
+
end
|
60
|
+
|
61
|
+
def result
|
62
|
+
@result ||= run
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def run
|
68
|
+
@parts = []
|
69
|
+
@highlighted = nil
|
70
|
+
lines.map(&method(:process)).compact
|
71
|
+
end
|
72
|
+
|
73
|
+
def process(text)
|
74
|
+
case text
|
75
|
+
when PART_START
|
76
|
+
@parts << $1
|
77
|
+
nil
|
78
|
+
when PART_END
|
79
|
+
@parts.reject! { |part| part == $1 }
|
80
|
+
nil
|
81
|
+
when HL_START
|
82
|
+
@highlighted = true
|
83
|
+
nil
|
84
|
+
when HL_END
|
85
|
+
@highlighted = false
|
86
|
+
nil
|
87
|
+
else
|
88
|
+
Line.new(text, @parts.dup, @highlighted)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def lines
|
93
|
+
@raw.split(/\r?\n/)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class PMLCode::Display
|
2
|
+
|
3
|
+
INDENT = " " * 4
|
4
|
+
|
5
|
+
def initialize(content, part, options)
|
6
|
+
@content = content
|
7
|
+
@part = part
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
INDENT + "```\n" + \
|
13
|
+
@content.map(&method(:format_line)).compact.map { |l| INDENT + l }.join("\n") + "\n" + \
|
14
|
+
INDENT + "```"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def format_line(line)
|
20
|
+
if @part && !line.in_part?(@part) && @options.verbose
|
21
|
+
Rainbow(line.text).black
|
22
|
+
elsif !@part || (@part && line.in_part?(@part))
|
23
|
+
if line.highlighted?
|
24
|
+
Rainbow(line.text).yellow.bold
|
25
|
+
else
|
26
|
+
line.text
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class PMLCode::Source
|
2
|
+
|
3
|
+
PATTERN = /^(?<path>.+?)(:(?<line>\d+):?)?$/
|
4
|
+
|
5
|
+
def self.parse(text)
|
6
|
+
if (match = text.match(PATTERN))
|
7
|
+
new(match[:path], match[:line] ? Integer(match[:line]) : nil)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :path, :line
|
12
|
+
def initialize(path, line)
|
13
|
+
@path = File.expand_path(path)
|
14
|
+
@line = line
|
15
|
+
end
|
16
|
+
|
17
|
+
def missing?
|
18
|
+
!File.exists?(@path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
[@path, @line].join(":")
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/pmlcode/updater.rb
CHANGED
@@ -42,47 +42,84 @@ class PMLCode::Updater
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def initialize(options)
|
45
|
-
@
|
45
|
+
@source = options.source
|
46
46
|
@options = options
|
47
47
|
@current_prefix = nil
|
48
48
|
@wrote = {}
|
49
|
+
@files = {}
|
49
50
|
end
|
50
51
|
|
51
52
|
def embeds
|
52
53
|
@embeds ||= begin
|
53
|
-
doc = Nokogiri::XML(File.read(@
|
54
|
-
doc.css('embed')
|
54
|
+
doc = Nokogiri::XML(File.read(@source.path))
|
55
|
+
doc.css('embed').select do |embed|
|
56
|
+
if @source.line
|
57
|
+
embed.line == @source.line
|
58
|
+
else
|
59
|
+
true
|
60
|
+
end
|
61
|
+
end
|
55
62
|
end
|
56
63
|
end
|
57
64
|
|
58
|
-
def log(location, text)
|
59
|
-
$stderr.puts "#{location}#{text}"
|
60
|
-
end
|
61
|
-
|
62
65
|
def run
|
63
66
|
embeds.each do |embed|
|
64
|
-
|
67
|
+
puts Rainbow(File.basename(@source.path) + ":#{embed.line} ").bold.underline
|
65
68
|
match = @options.pattern.match(embed[:file])
|
66
69
|
if match
|
67
|
-
dedup(
|
70
|
+
text = dedup(match) { |already_wrote| update(match, already_wrote) }
|
71
|
+
if text
|
72
|
+
print Rainbow("OK").green
|
73
|
+
puts " : FILE #{embed[:file]} #{write_flag}"
|
74
|
+
check_part!(text, embed[:part])
|
75
|
+
else
|
76
|
+
print Rainbow("ERROR").red
|
77
|
+
puts " : FILE #{embed[:file]}"
|
78
|
+
end
|
68
79
|
else
|
69
|
-
|
80
|
+
print Rainbow("BAD MATCH").red
|
81
|
+
puts " : FILE #{embed[:file]}"
|
70
82
|
end
|
83
|
+
puts
|
71
84
|
end
|
72
85
|
end
|
73
86
|
|
74
|
-
def dedup(
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
87
|
+
def dedup(match, &block)
|
88
|
+
update_id = generate_update_id(match)
|
89
|
+
content_id = generate_content_id(match)
|
90
|
+
@files[content_id] ||= block.(@wrote[update_id])
|
91
|
+
@wrote[update_id] = true
|
92
|
+
@files[content_id]
|
93
|
+
end
|
94
|
+
|
95
|
+
def check_part!(text, part)
|
96
|
+
content = PMLCode::Content.parse(text)
|
97
|
+
if part
|
98
|
+
if content.has_part?(part)
|
99
|
+
print Rainbow("OK").green
|
82
100
|
else
|
83
|
-
|
101
|
+
print Rainbow("MISSING").red
|
84
102
|
end
|
103
|
+
else
|
104
|
+
print Rainbow("--").gray
|
85
105
|
end
|
106
|
+
puts " : PART #{part}"
|
107
|
+
puts "\n"
|
108
|
+
if @options.content
|
109
|
+
puts PMLCode::Display.new(content, part, @options)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def write_flag
|
114
|
+
if @options.dry_run
|
115
|
+
Rainbow(" DRY RUN ").green.inverse
|
116
|
+
else
|
117
|
+
Rainbow(" WRITTEN ").yellow.inverse
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def generate_content_id(match)
|
122
|
+
match.string
|
86
123
|
end
|
87
124
|
|
88
125
|
def generate_update_id(match)
|
@@ -6,15 +6,21 @@ class PMLCode::FullUpdater < PMLCode::Updater
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
def update(match)
|
9
|
+
def update(match, already_wrote)
|
10
10
|
full_path = directory(match)
|
11
11
|
FileUtils.mkdir_p(full_path)
|
12
12
|
success = false
|
13
|
+
content = nil
|
13
14
|
Dir.chdir(@options.app) do
|
14
|
-
|
15
|
-
|
15
|
+
content = `git show origin/#{match[:chapter]}.#{match[:snapshot]}:#{match[:path]}`
|
16
|
+
if already_wrote || @options.dry_run
|
17
|
+
success = true
|
18
|
+
else
|
19
|
+
system "git archive '#{match[:chapter]}.#{match[:snapshot]}' | tar -x -C '#{full_path}'"
|
20
|
+
success = $?
|
21
|
+
end
|
16
22
|
end
|
17
|
-
success
|
23
|
+
success ? content : nil
|
18
24
|
end
|
19
25
|
|
20
26
|
def generate_update_id(match)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
1
|
class PMLCode::SparseUpdater < PMLCode::Updater
|
4
2
|
|
5
3
|
handles do |criteria|
|
@@ -8,7 +6,7 @@ class PMLCode::SparseUpdater < PMLCode::Updater
|
|
8
6
|
|
9
7
|
private
|
10
8
|
|
11
|
-
def update(match)
|
9
|
+
def update(match, already_wrote)
|
12
10
|
success = false
|
13
11
|
content = nil
|
14
12
|
Dir.chdir(@options.app) do
|
@@ -16,12 +14,14 @@ class PMLCode::SparseUpdater < PMLCode::Updater
|
|
16
14
|
success = $?.success?
|
17
15
|
end
|
18
16
|
if success
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
unless already_wrote || @options.dry_run
|
18
|
+
full_path = File.join(directory(match), match[:path])
|
19
|
+
FileUtils.mkdir_p(File.dirname(full_path))
|
20
|
+
File.open(full_path, 'w') do |f|
|
21
|
+
f.write(content)
|
22
|
+
end
|
23
23
|
end
|
24
|
-
|
24
|
+
content
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
data/lib/pmlcode/version.rb
CHANGED
data/pmlcode.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
23
|
spec.add_runtime_dependency 'nokogiri', '~> 1.8', '>= 1.8.0'
|
24
|
+
spec.add_runtime_dependency 'rainbow', '~> 2.2'
|
24
25
|
|
25
26
|
spec.add_development_dependency "bundler", "~> 1.15"
|
26
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pmlcode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruce Williams
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.8.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rainbow
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.2'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.2'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: bundler
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,6 +105,9 @@ files:
|
|
91
105
|
- exe/pmlcode
|
92
106
|
- lib/pmlcode.rb
|
93
107
|
- lib/pmlcode/cli.rb
|
108
|
+
- lib/pmlcode/content.rb
|
109
|
+
- lib/pmlcode/display.rb
|
110
|
+
- lib/pmlcode/source.rb
|
94
111
|
- lib/pmlcode/updater.rb
|
95
112
|
- lib/pmlcode/updaters/full_updater.rb
|
96
113
|
- lib/pmlcode/updaters/sparse_updater.rb
|