mnogootex 0.2.1 → 2.0.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 +5 -5
- data/.github/actions/setup-ruby/action.yml +34 -0
- data/.github/workflows/main.yml +44 -0
- data/.gitignore +3 -0
- data/.rspec +0 -2
- data/.rubocop.yml +15 -0
- data/CHANGELOG.md +55 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +4 -3
- data/Guardfile +56 -0
- data/README.md +260 -20
- data/Rakefile +25 -4
- data/demo/.mnogootexrc +4 -0
- data/demo/demo.asciicast +114 -0
- data/demo/demo.gif +0 -0
- data/demo/main.tex +5 -0
- data/exe/mnogootex +2 -92
- data/lib/mnogootex/cfg.rb +72 -0
- data/lib/mnogootex/cli.rb +63 -0
- data/lib/mnogootex/job/logger.rb +53 -0
- data/lib/mnogootex/job/porter.rb +63 -0
- data/lib/mnogootex/job/runner.rb +60 -0
- data/lib/mnogootex/job/warden.rb +104 -0
- data/lib/mnogootex/log/level.rb +17 -0
- data/lib/mnogootex/log/levels.yml +29 -0
- data/lib/mnogootex/log/line.rb +14 -0
- data/lib/mnogootex/log/matcher.rb +17 -0
- data/lib/mnogootex/log/matchers.yml +205 -0
- data/lib/mnogootex/log/processor.rb +115 -0
- data/lib/mnogootex/log.rb +23 -0
- data/lib/mnogootex/utils.rb +27 -0
- data/lib/mnogootex/version.rb +3 -1
- data/lib/mnogootex.rb +4 -4
- data/mnogootex.gemspec +43 -18
- data/spec/mnogootex/cfg_spec.rb +54 -0
- data/spec/mnogootex/job/porter_spec.rb +140 -0
- data/spec/mnogootex/job/runner_spec.rb +74 -0
- data/spec/mnogootex/log/processor_spec.rb +203 -0
- data/spec/mnogootex/utils_spec.rb +52 -0
- data/spec/spec_helper.rb +124 -0
- metadata +150 -29
- data/.gitmodules +0 -3
- data/.travis.yml +0 -5
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/mnogootex/configuration.rb +0 -46
- data/lib/mnogootex/job.rb +0 -75
@@ -0,0 +1,29 @@
|
|
1
|
+
- !ruby/struct:Mnogootex::Log::Level
|
2
|
+
priority: -.inf
|
3
|
+
name: !ruby/symbol all
|
4
|
+
# NOTE: merely symbolic, not to be used in matchers
|
5
|
+
|
6
|
+
- !ruby/struct:Mnogootex::Log::Level
|
7
|
+
priority: 0
|
8
|
+
name: !ruby/symbol trace
|
9
|
+
color: !ruby/symbol white
|
10
|
+
|
11
|
+
- !ruby/struct:Mnogootex::Log::Level
|
12
|
+
priority: 1
|
13
|
+
name: !ruby/symbol info
|
14
|
+
color: !ruby/symbol light_white
|
15
|
+
|
16
|
+
- !ruby/struct:Mnogootex::Log::Level
|
17
|
+
priority: 2
|
18
|
+
name: !ruby/symbol warning
|
19
|
+
color: !ruby/symbol light_yellow
|
20
|
+
|
21
|
+
- !ruby/struct:Mnogootex::Log::Level
|
22
|
+
priority: 3
|
23
|
+
name: !ruby/symbol error
|
24
|
+
color: !ruby/symbol light_red
|
25
|
+
|
26
|
+
- !ruby/struct:Mnogootex::Log::Level
|
27
|
+
priority: .inf
|
28
|
+
name: !ruby/symbol off
|
29
|
+
# NOTE: merely symbolic, not to be used in matchers
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mnogootex
|
4
|
+
module Log
|
5
|
+
# This data structure represents a log line.
|
6
|
+
# It can have a log {level} along with its {text}.
|
7
|
+
#
|
8
|
+
# @!attribute text
|
9
|
+
# @return [String] the contents of the line
|
10
|
+
# @!attribute level
|
11
|
+
# @return [Symbol] the associated log level
|
12
|
+
Line = Struct.new(:text, :level)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mnogootex
|
4
|
+
module Log
|
5
|
+
# This data structure represents a typology of log line chunks
|
6
|
+
# belonging to a given log {level}.
|
7
|
+
# They start with a line matching {regexp} and have a fixed {length}.
|
8
|
+
#
|
9
|
+
# @!attribute regexp
|
10
|
+
# @return [Regexp] the regexp to match the first line
|
11
|
+
# @!attribute level
|
12
|
+
# @return [Symbol] the associated log level
|
13
|
+
# @!attribute length
|
14
|
+
# @return [Integer] the number of matched lines
|
15
|
+
Matcher = Struct.new(:regexp, :level, :length) # rubocop:disable Lint/StructNewOverride
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
2
|
+
regexp: !ruby/regexp '/LaTeX Warning: You have requested package/'
|
3
|
+
level: !ruby/symbol trace
|
4
|
+
length: 1
|
5
|
+
|
6
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
7
|
+
regexp: !ruby/regexp '/LaTeX Font Warning: Some font shapes/'
|
8
|
+
level: !ruby/symbol trace
|
9
|
+
length: 1
|
10
|
+
|
11
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
12
|
+
regexp: !ruby/regexp '/LaTeX Font Warning: Size substitutions/'
|
13
|
+
level: !ruby/symbol trace
|
14
|
+
length: 1
|
15
|
+
|
16
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
17
|
+
regexp: !ruby/regexp '/Package caption Warning: Unsupported document class/'
|
18
|
+
level: !ruby/symbol trace
|
19
|
+
length: 1
|
20
|
+
|
21
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
22
|
+
regexp: !ruby/regexp '/Package fixltx2e Warning: fixltx2e is not required/'
|
23
|
+
level: !ruby/symbol trace
|
24
|
+
length: 1
|
25
|
+
|
26
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
27
|
+
regexp: !ruby/regexp '/Package frenchb?\.ldf Warning: (Figures|The definition)/'
|
28
|
+
level: !ruby/symbol trace
|
29
|
+
length: 1
|
30
|
+
|
31
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
32
|
+
regexp: !ruby/regexp '/\*\*\* Reloading Xunicode for encoding/' # spurious ***
|
33
|
+
level: !ruby/symbol trace
|
34
|
+
length: 1
|
35
|
+
|
36
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
37
|
+
regexp: !ruby/regexp '/This is `?(epsf\.tex|.*\.sty|TAP)/' # so what
|
38
|
+
level: !ruby/symbol trace
|
39
|
+
length: 1
|
40
|
+
|
41
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
42
|
+
regexp: !ruby/regexp '/pdfTeX warning:.*inclusion: fou/'
|
43
|
+
level: !ruby/symbol trace
|
44
|
+
length: 1
|
45
|
+
sample: |
|
46
|
+
pdfTeX warning: pdflatex.exe (file ./fig.pdf): PDF inclusion: found PDF version <1.6>, but at most version <1.5> allowed
|
47
|
+
|
48
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
49
|
+
regexp: !ruby/regexp '/pdfTeX warning:.*inclusion: mul/'
|
50
|
+
level: !ruby/symbol trace
|
51
|
+
length: 1
|
52
|
+
sample: |
|
53
|
+
pdfTeX warning: pdflatex (file ./doc.pdf): PDF inclusion: multiple pdfs with page group included in a single page
|
54
|
+
|
55
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
56
|
+
regexp: !ruby/regexp '/libpng warning: iCCP: Not recognizing/'
|
57
|
+
level: !ruby/symbol trace
|
58
|
+
length: 1
|
59
|
+
|
60
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
61
|
+
regexp: !ruby/regexp '/! $/'
|
62
|
+
level: !ruby/symbol trace
|
63
|
+
length: 1
|
64
|
+
|
65
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
66
|
+
regexp: !ruby/regexp '/This is/'
|
67
|
+
level: !ruby/symbol info
|
68
|
+
length: 1
|
69
|
+
|
70
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
71
|
+
regexp: !ruby/regexp '/Output written/'
|
72
|
+
level: !ruby/symbol info
|
73
|
+
length: 1
|
74
|
+
|
75
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
76
|
+
regexp: !ruby/regexp '/No pages of output/'
|
77
|
+
level: !ruby/symbol info
|
78
|
+
length: 1
|
79
|
+
|
80
|
+
# TODO: better classification below this point
|
81
|
+
|
82
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
83
|
+
regexp: !ruby/regexp '/\(.*end occurred inside a group/'
|
84
|
+
level: !ruby/symbol warning
|
85
|
+
length: 1
|
86
|
+
|
87
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
88
|
+
regexp: !ruby/regexp '/\\endL.*problem/' # XeTeX?
|
89
|
+
level: !ruby/symbol warning
|
90
|
+
length: 1
|
91
|
+
|
92
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
93
|
+
regexp: !ruby/regexp '/\*\*\*\s/' # *** from some packages or subprograms
|
94
|
+
level: !ruby/symbol warning
|
95
|
+
length: 1
|
96
|
+
|
97
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
98
|
+
regexp: !ruby/regexp '/all text was ignored after line/'
|
99
|
+
level: !ruby/symbol warning
|
100
|
+
length: 1
|
101
|
+
|
102
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
103
|
+
regexp: !ruby/regexp '/.*for symbol.*on input line/'
|
104
|
+
level: !ruby/symbol warning
|
105
|
+
length: 1
|
106
|
+
|
107
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
108
|
+
regexp: !ruby/regexp '/^.*?:[0-9]+:/' # usual file:lineno: form
|
109
|
+
level: !ruby/symbol warning
|
110
|
+
length: 1
|
111
|
+
|
112
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
113
|
+
regexp: !ruby/regexp '/l\.[0-9]+/' # line number marking
|
114
|
+
level: !ruby/symbol warning
|
115
|
+
length: 1
|
116
|
+
|
117
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
118
|
+
regexp: !ruby/regexp '/(LaTeX|Package|Class).*Warning/'
|
119
|
+
level: !ruby/symbol warning
|
120
|
+
length: 1
|
121
|
+
|
122
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
123
|
+
regexp: !ruby/regexp '/(Und|Ov)erfull/'
|
124
|
+
level: !ruby/symbol warning
|
125
|
+
length: 1
|
126
|
+
|
127
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
128
|
+
regexp: !ruby/regexp '/.*Citation.*undefined/'
|
129
|
+
level: !ruby/symbol warning
|
130
|
+
length: 1
|
131
|
+
|
132
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
133
|
+
regexp: !ruby/regexp '/Missing character:/' # good to show (need \tracinglostchars=1)
|
134
|
+
level: !ruby/symbol warning
|
135
|
+
length: 1
|
136
|
+
|
137
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
138
|
+
regexp: !ruby/regexp '/.*Fatal error/'
|
139
|
+
level: !ruby/symbol error
|
140
|
+
length: 1
|
141
|
+
|
142
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
143
|
+
regexp: !ruby/regexp '/.* Error/' # as in \Url Error ->...
|
144
|
+
level: !ruby/symbol error
|
145
|
+
length: 1
|
146
|
+
|
147
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
148
|
+
regexp: !ruby/regexp '/(LaTeX|Package|Class).*Error/'
|
149
|
+
level: !ruby/symbol error
|
150
|
+
length: 1
|
151
|
+
|
152
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
153
|
+
regexp: !ruby/regexp '/^> [^<]/' # from \show..., but not "> <img.whatever"
|
154
|
+
level: !ruby/symbol error
|
155
|
+
length: 2
|
156
|
+
|
157
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
158
|
+
regexp: !ruby/regexp '/^.*pdfTeX warning/' # pdftex complaints often cross lines
|
159
|
+
level: !ruby/symbol error
|
160
|
+
length: 2
|
161
|
+
|
162
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
163
|
+
regexp: !ruby/regexp '/^LaTeX Font Warning: Font shape/'
|
164
|
+
level: !ruby/symbol error
|
165
|
+
length: 2
|
166
|
+
|
167
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
168
|
+
regexp: !ruby/regexp '/^Package hyperref Warning: Token not allowed/'
|
169
|
+
level: !ruby/symbol error
|
170
|
+
length: 2
|
171
|
+
|
172
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
173
|
+
regexp: !ruby/regexp '/^removed on input line/' # hyperref
|
174
|
+
level: !ruby/symbol error
|
175
|
+
length: 2
|
176
|
+
|
177
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
178
|
+
regexp: !ruby/regexp '/^Runaway argument/'
|
179
|
+
level: !ruby/symbol error
|
180
|
+
length: 2
|
181
|
+
|
182
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
183
|
+
regexp: !ruby/regexp "/^! Undefined control sequence./"
|
184
|
+
level: !ruby/symbol error
|
185
|
+
length: 3
|
186
|
+
|
187
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
188
|
+
regexp: !ruby/regexp "/^! Too many }'s./"
|
189
|
+
level: !ruby/symbol error
|
190
|
+
length: 3
|
191
|
+
sample: |
|
192
|
+
! Too many }'s.
|
193
|
+
l.7 ...d foo bar baz qux zod foo bar baz qux zod }
|
194
|
+
foo
|
195
|
+
|
196
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
197
|
+
regexp: !ruby/regexp '/^!/' # usual ! form
|
198
|
+
level: !ruby/symbol error
|
199
|
+
length: 2
|
200
|
+
|
201
|
+
- !ruby/struct:Mnogootex::Log::Matcher
|
202
|
+
# NOTE: do not remove, this is a catch-all filter to mark untagged lines as :trace
|
203
|
+
regexp: !ruby/regexp '/.*/'
|
204
|
+
level: !ruby/symbol trace
|
205
|
+
length: 1
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mnogootex/log'
|
4
|
+
require 'mnogootex/log/line'
|
5
|
+
|
6
|
+
require 'colorize'
|
7
|
+
|
8
|
+
module Mnogootex
|
9
|
+
module Log
|
10
|
+
# This class exposes methods to
|
11
|
+
# {Processor.strings_to_lines! convert} strings into {Line}s that can be
|
12
|
+
# {Processor.tag_lines! tagged},
|
13
|
+
# {Processor.filter_lines! filtered},
|
14
|
+
# {Processor.colorize_lines! colored} (using {Level}s and {Matcher}s to define how)
|
15
|
+
# and finally
|
16
|
+
# {Processor.render_lines! rendered} into printable content.
|
17
|
+
#
|
18
|
+
# It can also be {Processor.initialize instantiated} with a specific configuration
|
19
|
+
# to {#run} the whole process repeatably on multiple inputs.
|
20
|
+
class Processor
|
21
|
+
# Converts strings into {Line}s.
|
22
|
+
#
|
23
|
+
# @param strings [Array<String>]
|
24
|
+
# @return [Array<Line>]
|
25
|
+
def self.strings_to_lines!(strings)
|
26
|
+
strings.map! do |line|
|
27
|
+
Line.new line.chomp
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Updates {Line#level}s of the given {Line}s using the {Matcher}s.
|
32
|
+
#
|
33
|
+
# @param lines [Array<Line>]
|
34
|
+
# @param matchers [Array<Matcher>]
|
35
|
+
# @return [Array<Line>]
|
36
|
+
def self.tag_lines!(lines, matchers:)
|
37
|
+
tail_length, matcher = 0 # , nil
|
38
|
+
lines.each do |line|
|
39
|
+
if tail_length.zero?
|
40
|
+
matcher = matchers.detect { |m| line.text =~ m.regexp }
|
41
|
+
tail_length = matcher&.length&.-(1) || 0
|
42
|
+
else # still on the tail of the previous match
|
43
|
+
tail_length -= 1
|
44
|
+
end
|
45
|
+
line.level = matcher&.level
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Discards {Line}s having {Line.level}s with {Level#priority}
|
50
|
+
# lower than the minimum, according the {Level}s hash.
|
51
|
+
#
|
52
|
+
# @param lines [Array<Line>]
|
53
|
+
# @param levels [Hash<Symbol, Level>]
|
54
|
+
# @param min_level [Symbol]
|
55
|
+
# @return [Array<Line>]
|
56
|
+
def self.filter_lines!(lines, levels:, min_level:)
|
57
|
+
lines.select! do |line|
|
58
|
+
levels.fetch(line.level).priority >= levels.fetch(min_level).priority
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Applies {Level#color}s to the {Line}s, according the {Level}s hash.
|
63
|
+
#
|
64
|
+
# @param lines [Array<Line>]
|
65
|
+
# @param levels [Array<Level>]
|
66
|
+
# @return [Array<Line>]
|
67
|
+
def self.colorize_lines!(lines, levels:)
|
68
|
+
lines.each do |line|
|
69
|
+
line.text = line.text.colorize(levels.fetch(line.level).color)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Renders {Line}s to space-indented strings terminated by a newline.
|
74
|
+
#
|
75
|
+
# @param lines [Array<Line>]
|
76
|
+
# @param indent_width [Fixnum]
|
77
|
+
# @return [Array<String>]
|
78
|
+
def self.render_lines!(lines, indent_width:)
|
79
|
+
lines.map! { |line| "#{' ' * indent_width}#{line.text}\n" }
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param matchers [Array<Matcher>]
|
83
|
+
# @param levels [Array<Level>]
|
84
|
+
# @param indent_width [Fixnum]
|
85
|
+
# @param min_level [Symbol]
|
86
|
+
def initialize(matchers:, levels:, min_level:, colorize:, indent_width:)
|
87
|
+
@matchers = matchers
|
88
|
+
@levels = levels
|
89
|
+
@min_level = min_level
|
90
|
+
@colorize = colorize
|
91
|
+
@indent_width = indent_width
|
92
|
+
end
|
93
|
+
|
94
|
+
# Runs the {Processor Processor} on the given strings to
|
95
|
+
# {Processor.strings_to_lines! convert},
|
96
|
+
# {Processor.tag_lines! tag},
|
97
|
+
# {Processor.filter_lines! filter},
|
98
|
+
# {Processor.colorize_lines! color} and
|
99
|
+
# {Processor.render_lines! render} them
|
100
|
+
# using its {Processor.initialize initialization} parameters.
|
101
|
+
#
|
102
|
+
# @param lines [Array<String>]
|
103
|
+
# @return [Array<String>]
|
104
|
+
def run(lines)
|
105
|
+
@lines = lines.dup
|
106
|
+
Processor.strings_to_lines! @lines
|
107
|
+
Processor.tag_lines! @lines, matchers: @matchers
|
108
|
+
Processor.filter_lines! @lines, levels: @levels, min_level: @min_level
|
109
|
+
Processor.colorize_lines! @lines, levels: @levels if @colorize
|
110
|
+
Processor.render_lines! @lines, indent_width: @indent_width
|
111
|
+
@lines
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mnogootex/log/level'
|
4
|
+
require 'mnogootex/log/matcher'
|
5
|
+
|
6
|
+
require 'pathname'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
module Mnogootex
|
10
|
+
# {Log} implements means to reduce log floods into filtered, color coded and human friendly summaries.
|
11
|
+
#
|
12
|
+
# * {Line}s are log lines.
|
13
|
+
# * {Level}s define log levels, their priority and color coding.
|
14
|
+
# * {Matcher}s define patterns to determine the level of log lines.
|
15
|
+
# * {Processor}s implement all transformations.
|
16
|
+
#
|
17
|
+
module Log
|
18
|
+
DEFAULT_LEVELS_PATH = Pathname.new(__dir__).join('log', 'levels.yml')
|
19
|
+
DEFAULT_MATCHERS_PATH = Pathname.new(__dir__).join('log', 'matchers.yml')
|
20
|
+
DEFAULT_LEVELS = YAML.load_file(DEFAULT_LEVELS_PATH).map { |l| [l.name, l] }.to_h.freeze
|
21
|
+
DEFAULT_MATCHERS = YAML.load_file(DEFAULT_MATCHERS_PATH).freeze
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
|
5
|
+
module Mnogootex
|
6
|
+
module Utils
|
7
|
+
def self.short_md5(input)
|
8
|
+
[Digest::MD5.digest(input)]. # get 16 bytes of MD5
|
9
|
+
pack('m0'). # pack them into 22+2 base64 bytes (w/o trailing newline)
|
10
|
+
tr('+/', '-_'). # make then url/path-safe
|
11
|
+
chomp('==') # drop last 2 padding bytes
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.humanize_bytes(size)
|
15
|
+
%w[b Kb Mb Gb Tb Pb Eb Zb Yb].reduce(size) do |magnitude, unit|
|
16
|
+
break "#{magnitude}#{unit}" if magnitude < 1024
|
17
|
+
|
18
|
+
magnitude / 1024
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.dir_size(mask)
|
23
|
+
Dir.glob(Pathname.new(mask).join('**', '*')).
|
24
|
+
map! { |f| Pathname.new(f).size }.inject(:+) || 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/mnogootex/version.rb
CHANGED
data/lib/mnogootex.rb
CHANGED
data/mnogootex.gemspec
CHANGED
@@ -1,30 +1,55 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require 'mnogootex/version'
|
6
6
|
|
7
|
-
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
7
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
8
|
+
spec.name = 'mnogootex'
|
9
9
|
spec.version = Mnogootex::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
10
|
+
spec.authors = ['Paolo Brasolin']
|
11
|
+
spec.email = ['paolo.brasolin@gmail.com']
|
12
12
|
|
13
|
-
spec.summary =
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
spec.summary = <<~SUMMARY.tr("\n", ' ').squeeze(' ').strip
|
14
|
+
Многоꙮтех (mnogootex) is a utility that parallelizes compilation
|
15
|
+
of a LaTeX document using different classes and offers a
|
16
|
+
meaningfully filtered output.
|
17
|
+
SUMMARY
|
18
|
+
|
19
|
+
spec.description = <<~DESCRIPTION.tr("\n", ' ').squeeze(' ').strip
|
20
|
+
Многоꙮтех (mnogootex) is a utility that parallelizes compilation
|
21
|
+
of a LaTeX document using different classes and offers a
|
22
|
+
meaningfully filtered output.
|
23
|
+
The motivating use case is maintaining a single preamble while
|
24
|
+
submitting a paper to many journals using their outdated or crummy
|
25
|
+
document classes.
|
26
|
+
DESCRIPTION
|
27
|
+
|
28
|
+
spec.homepage = 'https://github.com/tetrapharmakon/mnogootex'
|
29
|
+
spec.license = 'MIT'
|
17
30
|
|
18
31
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
-
f.match(%r{^(test|
|
32
|
+
f.match(%r{^(test|mwe)/})
|
20
33
|
end
|
21
|
-
spec.bindir =
|
34
|
+
spec.bindir = 'exe'
|
22
35
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
-
spec.require_paths = [
|
36
|
+
spec.require_paths = ['lib']
|
37
|
+
|
38
|
+
spec.required_ruby_version = '>= 2.6'
|
24
39
|
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
40
|
+
spec.add_development_dependency 'bundler', '~> 2.2.30'
|
41
|
+
spec.add_development_dependency 'byebug', '~> 11.1.3'
|
42
|
+
# spec.add_development_dependency 'dry-inflector', '~> 0.1.1'
|
43
|
+
spec.add_development_dependency 'guard', '~> 2.18.0'
|
44
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
|
45
|
+
# spec.add_development_dependency 'mutant', '~> 0.8.14'
|
46
|
+
# spec.add_development_dependency 'mutant-rspec', '~> 0.8.14'
|
47
|
+
spec.add_development_dependency 'rake', '~> 13.0.6'
|
48
|
+
spec.add_development_dependency 'rspec', '~> 3.10.0'
|
49
|
+
spec.add_development_dependency 'rubocop', '~> 1.22.3'
|
50
|
+
spec.add_development_dependency 'simplecov', '~> 0.21.2'
|
51
|
+
spec.add_development_dependency 'yard', '~> 0.9.26'
|
28
52
|
|
29
|
-
spec.add_dependency
|
53
|
+
spec.add_dependency 'colorize', '~> 0.8.1'
|
54
|
+
spec.add_dependency 'thor', '~> 0.20.0'
|
30
55
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
require 'yaml'
|
6
|
+
require 'tmpdir'
|
7
|
+
|
8
|
+
require 'mnogootex/cfg'
|
9
|
+
|
10
|
+
describe Mnogootex::Cfg do
|
11
|
+
describe 'load_descending' do
|
12
|
+
context 'fake file structure' do
|
13
|
+
subject { described_class.load_descending(pathname: Pathname.new('foobar'), basename: 'cfg.yml') }
|
14
|
+
|
15
|
+
it 'raises an error on loading a fake path' do
|
16
|
+
expect { subject }.to raise_exception Errno::ENOENT
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'real file structure' do
|
21
|
+
subject { described_class.load_descending(pathname: tmp_dir.join('A', 'B'), basename: 'cfg.yml') }
|
22
|
+
let(:defaults) { { default: true, winner: 'default' } }
|
23
|
+
let(:tmp_dir) { Pathname.new(Dir.mktmpdir).join('mnogootex-test') }
|
24
|
+
|
25
|
+
before do
|
26
|
+
tmp_dir.join('A', 'B').mkpath
|
27
|
+
tmp_dir.join('cfg.yml').write('') # NOTE: empty file
|
28
|
+
tmp_dir.join('A', 'cfg.yml').write({ parent: true, winner: 'parent', merged: { deep: true } }.to_yaml)
|
29
|
+
tmp_dir.join('A', 'B', 'cfg.yml').write({ child: true, winner: 'child', merged: {} }.to_yaml)
|
30
|
+
end
|
31
|
+
|
32
|
+
after do
|
33
|
+
tmp_dir.rmtree
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'merges paths' do
|
37
|
+
expect(subject).to include(:parent)
|
38
|
+
expect(subject).to include(:child)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'merges shallowly' do
|
42
|
+
expect(subject[:merged]).to_not include(:deep)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'privileges deeper paths' do
|
46
|
+
expect(subject[:winner]).to eq('child')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'privileges non defaults' do
|
50
|
+
expect(subject[:winner]).to_not eq('default')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|