mnogootex 0.2.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +41 -0
- data/.gitignore +3 -0
- data/.rspec +0 -2
- data/.rubocop.yml +13 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +4 -3
- data/Guardfile +56 -0
- data/README.md +163 -17
- data/Rakefile +25 -4
- data/exe/mnogootex +2 -92
- data/lib/mnogootex/cfg.rb +62 -0
- data/lib/mnogootex/cli.rb +80 -0
- data/lib/mnogootex/core_ext.rb +11 -0
- data/lib/mnogootex/defaults.yml +7 -0
- data/lib/mnogootex/job/logger.rb +53 -0
- data/lib/mnogootex/job/porter.rb +53 -0
- data/lib/mnogootex/job/runner.rb +43 -0
- data/lib/mnogootex/job/warden.rb +100 -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/mnogoo.sh +21 -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
- data/tty.gif +0 -0
- metadata +148 -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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 654469a2719e7a34e16be659b3b59cbf8611f1f5025ccba19ba1bea60e35d87b
|
4
|
+
data.tar.gz: cc026af91f6270d36fd5affa76565e49ba781638965cb0b377c8775d84cbc8fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2cf80aa5a52753bfec92a5ce7a6ff1c0a1d3d84376fdc897ed364097b52126245e5852284b474e81adee288c30d316753cb0bd38b8d75fbf541345512c834754
|
7
|
+
data.tar.gz: a71bda28d8eded4790cb3b40b6b673c58e3f96e630e42bb512c80afd004f869f559938ff83c7fb358780f59007c4117cad5bd0cf0b20e9d956c9c1d81425cfac
|
@@ -0,0 +1,41 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
pull_request:
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
main:
|
9
|
+
name: >-
|
10
|
+
${{ matrix.os }} ${{ matrix.ruby }}
|
11
|
+
runs-on: ${{ matrix.os }}-latest
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
os: [ ubuntu, macos ]
|
16
|
+
ruby: [ '2.6', '2.7', '3.0' ]
|
17
|
+
|
18
|
+
steps:
|
19
|
+
|
20
|
+
- name: Checkout repo
|
21
|
+
uses: actions/checkout@v2
|
22
|
+
|
23
|
+
- name: Set up Ruby
|
24
|
+
uses: ruby/setup-ruby@v1
|
25
|
+
with:
|
26
|
+
ruby-version: ${{ matrix.ruby }}
|
27
|
+
|
28
|
+
- name: Cache Ruby gems
|
29
|
+
uses: actions/cache@v2
|
30
|
+
with:
|
31
|
+
path: vendor/bundle
|
32
|
+
key: gems-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'mnogootex.gemspec') }}
|
33
|
+
restore-keys: gems-${{ matrix.os }}-${{ matrix.ruby }}-
|
34
|
+
|
35
|
+
- name: Install Ruby gems
|
36
|
+
run: |
|
37
|
+
bundle config path vendor/bundle
|
38
|
+
bundle install --jobs 3 --retry 3
|
39
|
+
|
40
|
+
- name: Run tests
|
41
|
+
run: bundle exec rake spec:rspec
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
data/CODE_OF_CONDUCT.md
CHANGED
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
|
|
55
55
|
## Enforcement
|
56
56
|
|
57
57
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
-
reported by contacting the project team at
|
58
|
+
reported by contacting the project team at <paolo.brasolin@gmail.com>. All
|
59
59
|
complaints will be reviewed and investigated and will result in a response that
|
60
60
|
is deemed necessary and appropriate to the circumstances. The project team is
|
61
61
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
data/Gemfile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
6
|
|
5
|
-
# Specify your gem's dependencies in mnogootex.gemspec
|
6
7
|
gemspec
|
data/Guardfile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
4
|
+
require 'guard/rspec/dsl'
|
5
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
6
|
+
|
7
|
+
# RSpec files
|
8
|
+
watch(dsl.rspec.spec_helper) { dsl.rspec.spec_dir }
|
9
|
+
watch(dsl.rspec.spec_files)
|
10
|
+
|
11
|
+
# Ruby files
|
12
|
+
dsl.watch_spec_files_for(dsl.ruby.lib_files)
|
13
|
+
end
|
14
|
+
|
15
|
+
# # TODO: refactor the following into a new version of guard-mutant
|
16
|
+
|
17
|
+
# require 'mutant'
|
18
|
+
# require 'dry/inflector'
|
19
|
+
# require 'guard/compat/plugin'
|
20
|
+
|
21
|
+
# # NOTE: :: is mandatory for inline guards
|
22
|
+
# module ::Guard
|
23
|
+
# class Mutant < Plugin
|
24
|
+
# def initialize(options = {})
|
25
|
+
# opts = options.dup
|
26
|
+
# # @my_option = opts.delete(:my_special_option)
|
27
|
+
# super(opts) # important to call + avoid passing options Guard doesn't understand
|
28
|
+
# end
|
29
|
+
|
30
|
+
# # TODO: how would this make sense?
|
31
|
+
# # def run_all; end
|
32
|
+
|
33
|
+
# def run_on_modifications(paths)
|
34
|
+
# inflector = Dry::Inflector.new
|
35
|
+
# subjects = paths.map do |path|
|
36
|
+
# match = path.match(%r{(?:spec|lib)\/(.*?)(?:_spec)?.rb}).captures.first
|
37
|
+
# inflector.camelize match
|
38
|
+
# end
|
39
|
+
# succesful = ::Mutant::CLI.run(%w[--use rspec --fail-fast] + subjects)
|
40
|
+
# throw :task_has_failed unless succesful
|
41
|
+
# self
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
|
46
|
+
# guard :mutant do
|
47
|
+
# require 'guard/rspec/dsl'
|
48
|
+
# dsl = Guard::RSpec::Dsl.new(self)
|
49
|
+
|
50
|
+
# # RSpec files
|
51
|
+
# # watch(dsl.rspec.spec_helper) { dsl.rspec.spec_dir }
|
52
|
+
# watch(dsl.rspec.spec_files)
|
53
|
+
|
54
|
+
# # Ruby files
|
55
|
+
# dsl.watch_spec_files_for(dsl.ruby.lib_files)
|
56
|
+
# end
|
data/README.md
CHANGED
@@ -1,38 +1,184 @@
|
|
1
1
|
# Многоꙮтех
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/paolobrasolin/mnogootex.svg?branch=master)](https://travis-ci.org/paolobrasolin/mnogootex)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/mnogootex.svg)](https://badge.fury.io/rb/mnogootex)
|
5
|
+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/paolobrasolin/mnogootex/badges/gpa.svg)](https://codeclimate.com/github/paolobrasolin/mnogootex)
|
7
|
+
<!-- [![Test Coverage](https://codeclimate.com/github/paolobrasolin/mnogootex/badges/coverage.svg)](https://codeclimate.com/github/paolobrasolin/mnogootex/coverage) -->
|
8
|
+
<!-- [![Inline docs](http://inch-ci.org/github/paolobrasolin/mnogootex.svg?branch=master)](http://inch-ci.org/github/paolobrasolin/mnogootex) -->
|
9
|
+
<!-- [![Issue Count](https://codeclimate.com/github/paolobrasolin/mnogootex/badges/issue_count.svg)](https://codeclimate.com/github/paolobrasolin/mnogootex) -->
|
10
|
+
|
11
|
+
Многоꙮтех (mnogootex) is a utility that parallelizes compilation
|
12
|
+
of a LaTeX document using different classes and offers a
|
13
|
+
meaningfully filtered output.
|
14
|
+
|
15
|
+
The motivating use case is maintaining a single preamble while
|
16
|
+
submitting a paper to many journals using their outdated or crummy
|
17
|
+
document classes.
|
6
18
|
|
7
19
|
## Installation
|
8
20
|
|
9
|
-
|
21
|
+
The only requirement is [Ruby](https://www.ruby-lang.org) (>=2.5 as earlier versions are untested).
|
22
|
+
|
23
|
+
To install многоꙮтех execute
|
24
|
+
|
25
|
+
gem install mnogootex
|
26
|
+
|
27
|
+
To install `mnogoo` (strongly recommended shell integration) add this to your shell profile
|
10
28
|
|
11
|
-
|
12
|
-
gem 'mnogootex'
|
13
|
-
```
|
29
|
+
[ -s "$(mnogootex mnogoo)" ] && . "$(mnogootex mnogoo)"
|
14
30
|
|
15
|
-
|
31
|
+
## Quick start
|
16
32
|
|
17
|
-
|
33
|
+
Set up your `LaTeX` project as usual - let's say its main file is `~/project/main.tex` and contains `\documentclass{...}`.
|
18
34
|
|
19
|
-
|
35
|
+
Create a configuration file `~/project/.mnogootex.yml`
|
36
|
+
containing the list of document classes you want to compile your
|
37
|
+
project against:
|
20
38
|
|
21
|
-
|
39
|
+
jobs:
|
40
|
+
- scrartcl
|
41
|
+
- article
|
42
|
+
- book
|
43
|
+
|
44
|
+
Run `mnogootex go ~/project/main.tex` and enjoy the technicolor:
|
45
|
+
|
46
|
+
![Demo TTY GIF](tty.gif?raw=true "Demo TTY GIF")
|
22
47
|
|
23
48
|
## Usage
|
24
49
|
|
25
|
-
|
50
|
+
In essence, Многоꙮтех
|
51
|
+
1. takes the _source_ directory of a project,
|
52
|
+
2. clones it into _target_ directories (one for each _job_),
|
53
|
+
3. applies a different source code transformation to each one and then
|
54
|
+
4. attempts to compile them.
|
55
|
+
|
56
|
+
Its convenience lies in the fact that it
|
57
|
+
* automates the setup process,
|
58
|
+
* parallelizes compilation,
|
59
|
+
* filters and colour codes the infamous waterfall logs and
|
60
|
+
* allows you to easily navigate through targets/source folders.
|
61
|
+
|
62
|
+
Многоꙮтех can be invoked from commandline in two ways: `mnogootex` and `mnogoo`.
|
63
|
+
The latter is more powerful and requires an extra [installation](#installation) step.
|
64
|
+
|
65
|
+
Commands listed below can be passed to both unless otherwise stated.
|
66
|
+
|
67
|
+
### Commands
|
68
|
+
|
69
|
+
> **NOTATION:** `[FOO]` means that _`FOO` is optional_ while `FOO ...` means _one or more `FOO`s_.
|
70
|
+
|
71
|
+
#### `help [COMMAND]`
|
72
|
+
|
73
|
+
Prints the help for `COMMAND` (or all commands if none is given).
|
74
|
+
|
75
|
+
#### `mnogoo`
|
76
|
+
|
77
|
+
Prints the location of the `mnogoo` shell integration script.
|
78
|
+
Useful only for its [installation](#installation).
|
79
|
+
|
80
|
+
#### `go [JOB ...] [MAIN]`
|
81
|
+
|
82
|
+
Run given compilation `JOB`s for the `MAIN` document.
|
83
|
+
|
84
|
+
If no `JOB` list is given then all of them are run.
|
85
|
+
They are deduced from the [configuration](#configuration).
|
86
|
+
|
87
|
+
If no `MAIN` document is given then it's deduced from either
|
88
|
+
your current working directory or the [configuration](#configuration).
|
89
|
+
|
90
|
+
#### `dir [JOB] [MAIN]`
|
91
|
+
|
92
|
+
Print `JOB`'s temporary directory for the `MAIN` document.
|
93
|
+
|
94
|
+
If no `JOB` is given then it prints the source directory.
|
95
|
+
|
96
|
+
If no `MAIN` document is given then it's deduced from either
|
97
|
+
your current working directory or the [configuration](#configuration).
|
98
|
+
|
99
|
+
#### `cd [JOB] [MAIN]`
|
100
|
+
|
101
|
+
> **NOTE:** recognized by `mnogoo` only.
|
102
|
+
|
103
|
+
Checks into `JOB`'s temporary directory for the `MAIN` document.
|
104
|
+
|
105
|
+
If no `JOB` is given then it checks into the source directory.
|
106
|
+
|
107
|
+
If no `MAIN` document is given then it's deduced from either
|
108
|
+
your current working directory or the [configuration](#configuration).
|
109
|
+
|
110
|
+
#### `clobber`
|
111
|
+
|
112
|
+
Deletes all temporary files.
|
113
|
+
Useful to free up some space from time to time.
|
114
|
+
|
115
|
+
#### `pdf [JOB ...] [MAIN]`
|
116
|
+
|
117
|
+
Print `JOB`'s output PDF path for the `MAIN` document.
|
118
|
+
|
119
|
+
If no `JOB` list is given then all their output PDFs paths are printed.
|
120
|
+
They are deduced from the [configuration](#configuration).
|
121
|
+
|
122
|
+
If no `MAIN` document is given then it's deduced from either
|
123
|
+
your current working directory or the [configuration](#configuration).
|
124
|
+
|
125
|
+
#### `open [JOB ...] [MAIN]`
|
126
|
+
|
127
|
+
> **NOTE:** recognized by `mnogoo` only.
|
128
|
+
|
129
|
+
Open `JOB`'s output PDF for the `MAIN` document with your default viewer.
|
130
|
+
|
131
|
+
If no `JOB` list is given then all their output PDFs are opened.
|
132
|
+
They are deduced from the [configuration](#configuration).
|
133
|
+
|
134
|
+
If no `MAIN` document is given then it's deduced from either
|
135
|
+
your current working directory or the [configuration](#configuration).
|
136
|
+
|
137
|
+
### Configuration
|
138
|
+
|
139
|
+
Многоꙮтех is configured through [`YAML`](https://learnxinyminutes.com/docs/yaml/)
|
140
|
+
files named `.mnogootex.yml` put into your projects' root directory.
|
141
|
+
|
142
|
+
When loads a configuration it also looks up for `.mnogootex.yml`
|
143
|
+
files in all parent directories to merge then together (from the
|
144
|
+
shallowest to the deepest path). This means that e.g. you can keep
|
145
|
+
a configuration file in your home folder and use it as a global
|
146
|
+
configuration for all you projects, while overwriting only specific
|
147
|
+
options in the configuration files of each one.
|
148
|
+
|
149
|
+
Многоꙮтех currently accepts three options.
|
150
|
+
|
151
|
+
#### `spinner`
|
152
|
+
|
153
|
+
This option is a string whose characters are the frames used to
|
154
|
+
animate the spinners for the command line interface.
|
155
|
+
|
156
|
+
# Default value:
|
157
|
+
spinner: ⣾⣽⣻⢿⡿⣟⣯⣷
|
158
|
+
|
159
|
+
#### `commandline`
|
160
|
+
|
161
|
+
This option is an array of the components for the commandline used
|
162
|
+
to compile documents.
|
163
|
+
|
164
|
+
# Default value:
|
165
|
+
commandline:
|
166
|
+
- latexmk
|
167
|
+
- -pdf
|
168
|
+
- --interaction=nonstopmode
|
169
|
+
|
170
|
+
#### `work_path`
|
26
171
|
|
27
|
-
|
172
|
+
This option is an override for the path where compilation happens.
|
28
173
|
|
29
|
-
|
174
|
+
# Default value:
|
175
|
+
work_path: null
|
30
176
|
|
31
|
-
|
177
|
+
By default each run happens in a new empty folder. Overriding this allows you to easily reach the compilation artifacts, but leaves handling cleanup and conflicts with previous runs up to you.
|
32
178
|
|
33
179
|
## Contributing
|
34
180
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
181
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/paolobrasolin/mnogootex. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
182
|
|
37
183
|
## License
|
38
184
|
|
@@ -40,4 +186,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
40
186
|
|
41
187
|
## Code of Conduct
|
42
188
|
|
43
|
-
Everyone interacting in the
|
189
|
+
Everyone interacting in the многоꙮтех project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/paolobrasolin/mnogootex/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
@@ -1,6 +1,27 @@
|
|
1
|
-
|
2
|
-
require "rspec/core/rake_task"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
# require 'mutant'
|
4
|
+
# require 'dry/inflector'
|
5
5
|
|
6
|
-
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
namespace :spec do
|
9
|
+
desc 'run RSpec'
|
10
|
+
RSpec::Core::RakeTask.new(:rspec) do |task|
|
11
|
+
task.rspec_opts = '--format documentation'
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'run SimpleCov'
|
15
|
+
task :simplecov do
|
16
|
+
ENV['COVERAGE'] = 'true'
|
17
|
+
Rake::Task['spec:rspec'].invoke
|
18
|
+
end
|
19
|
+
|
20
|
+
# desc 'run Mutant'
|
21
|
+
# task :mutant, [:subject] do |_, args|
|
22
|
+
# subjects = [args[:subject]].compact
|
23
|
+
# subjects << 'Mnogootex*' if subjects.empty?
|
24
|
+
# successful = ::Mutant::CLI.run(%w[--use rspec --fail-fast] + subjects)
|
25
|
+
# raise('Mutant task is not successful') unless successful
|
26
|
+
# end
|
27
|
+
end
|
data/exe/mnogootex
CHANGED
@@ -1,96 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'mnogootex'
|
5
5
|
|
6
|
-
|
7
|
-
# require 'pathname'
|
8
|
-
|
9
|
-
# target = ARGV[0]
|
10
|
-
# target_path = File.expand_path target
|
11
|
-
# cfg = Mnogootex::Configuration.new
|
12
|
-
# cfg.load target_path
|
13
|
-
|
14
|
-
require 'tmpdir'
|
15
|
-
require 'fileutils'
|
16
|
-
require 'open3'
|
17
|
-
|
18
|
-
require 'colorize'
|
19
|
-
|
20
|
-
target = ARGV[0]
|
21
|
-
|
22
|
-
|
23
|
-
raise "No parameters given." if ARGV.length.zero?
|
24
|
-
|
25
|
-
if ARGV.length == 3
|
26
|
-
raise "Unknown command." unless %w{show view open}.include? ARGV[1].downcase
|
27
|
-
job = Mnogootex::Job.new cls: ARGV[2], target: File.expand_path(target)
|
28
|
-
pdf = Dir.glob("#{job.tmp_dirname}/*.pdf").first
|
29
|
-
raise "PDF non esiste." unless File.exist? pdf
|
30
|
-
`open #{pdf}`
|
31
|
-
exit
|
32
|
-
end
|
33
|
-
|
34
|
-
puts "Mnogootex v#{Mnogootex::VERSION}"
|
35
|
-
|
36
|
-
main_path = File.expand_path(target)
|
37
|
-
main_basename = File.basename main_path
|
38
|
-
main_dirname = File.dirname main_path
|
39
|
-
|
40
|
-
cfg = Mnogootex::Configuration.new
|
41
|
-
cfg.load main_dirname
|
42
|
-
|
43
|
-
raise "File non esiste." unless File.exist? main_path
|
44
|
-
|
45
|
-
@documentclasses = cfg['compile_with']
|
46
|
-
|
47
|
-
$jobs = []
|
48
|
-
$threads = []
|
49
|
-
$draw_threads = []
|
50
|
-
|
51
|
-
$threads = []
|
52
|
-
|
53
|
-
$anim = cfg['animation'].freeze
|
54
|
-
|
55
|
-
STDOUT.sync = true
|
56
|
-
|
57
|
-
def draw_status
|
58
|
-
icons = $jobs.map do |j|
|
59
|
-
icon = $anim[j.ticks % $anim.length]
|
60
|
-
case j.thread.status
|
61
|
-
when 'sleep', 'run', 'aborting'
|
62
|
-
icon.yellow
|
63
|
-
when false, nil # exited (normally or w/ error)
|
64
|
-
j.success? ? icon.green : icon.red
|
65
|
-
end
|
66
|
-
end
|
67
|
-
print ' Jobs: ' + icons.join + "\r"
|
68
|
-
end
|
69
|
-
|
70
|
-
draw_status
|
71
|
-
|
72
|
-
@documentclasses.each_with_index do |cls, index|
|
73
|
-
job = Mnogootex::Job.new cls: cls, target: main_path
|
74
|
-
job.setup
|
75
|
-
job.run
|
76
|
-
|
77
|
-
$jobs << job
|
78
|
-
|
79
|
-
$draw_threads << job.tick_thread
|
80
|
-
$threads << job.thread
|
81
|
-
end
|
82
|
-
|
83
|
-
$threads.map(&:join)
|
84
|
-
$draw_threads.map(&:join)
|
85
|
-
|
86
|
-
puts
|
87
|
-
|
88
|
-
puts ' Details:'
|
89
|
-
$jobs.each do |job|
|
90
|
-
if job.success?
|
91
|
-
puts ' ' + "✔".green + ' ' + File.basename(job.cls)
|
92
|
-
else
|
93
|
-
puts ' ' + "✘".red + ' ' + File.basename(job.cls)
|
94
|
-
puts job.log[2..-2].join.gsub(/^/,' '*6).chomp.red
|
95
|
-
end
|
96
|
-
end
|
6
|
+
Mnogootex::CLI.start ARGV
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
require 'mnogootex/core_ext'
|
7
|
+
|
8
|
+
module Mnogootex
|
9
|
+
module Cfg
|
10
|
+
BASENAME = '.mnogootex.yml'
|
11
|
+
DEFAULTS = YAML.load_file(Pathname.new(__dir__).join('defaults.yml'))
|
12
|
+
|
13
|
+
def self.load_descending(pathname:, basename:)
|
14
|
+
pathname.realpath.descend.
|
15
|
+
map { |path| path.join(basename) }.
|
16
|
+
select(&:exist?).reject(&:zero?).
|
17
|
+
map { |path| YAML.load_file(path) }.
|
18
|
+
reduce(&:merge!)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.recombobulate(*args)
|
22
|
+
try_args(*args) || try_link(*args) || try_cfgs(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
private
|
27
|
+
|
28
|
+
def try_args(*args)
|
29
|
+
main = Pathname.new(args.fetch(-1, ''))
|
30
|
+
return unless main.file?
|
31
|
+
|
32
|
+
main = main.realpath
|
33
|
+
cfg = load_descending(pathname: main.dirname, basename: BASENAME)
|
34
|
+
jobs = args[0..-2].unless(&:empty?)
|
35
|
+
|
36
|
+
[jobs, main, cfg]
|
37
|
+
end
|
38
|
+
|
39
|
+
def try_link(*args)
|
40
|
+
link = Pathname.pwd.ascend.map { |p| p.join('.mnogootex.src') }.detect(&:symlink?)
|
41
|
+
return if link.nil?
|
42
|
+
|
43
|
+
main = link.readlink.realpath
|
44
|
+
cfg = load_descending(pathname: main.dirname, basename: BASENAME)
|
45
|
+
jobs = args
|
46
|
+
|
47
|
+
[jobs, main, cfg]
|
48
|
+
end
|
49
|
+
|
50
|
+
def try_cfgs(*args)
|
51
|
+
yaml = Pathname.pwd.ascend.map { |p| p.join('.mnogootex.yml') }.detect(&:file?)
|
52
|
+
return if yaml.nil?
|
53
|
+
|
54
|
+
cfg = load_descending(pathname: yaml.dirname, basename: BASENAME)
|
55
|
+
main = yaml.dirname.join(cfg.fetch('main', '')).if(&:file?)&.realpath
|
56
|
+
jobs = args
|
57
|
+
|
58
|
+
[jobs, main, cfg]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
require 'mnogootex/utils'
|
7
|
+
require 'mnogootex/job/warden'
|
8
|
+
require 'mnogootex/job/porter'
|
9
|
+
require 'mnogootex/cfg'
|
10
|
+
|
11
|
+
module Mnogootex
|
12
|
+
class CLI < Thor
|
13
|
+
IS_MNOGOO = (ENV['IS_MNOGOO'] == 'true')
|
14
|
+
|
15
|
+
def self.basename
|
16
|
+
IS_MNOGOO ? 'mnogoo' : super
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'cd [JOB] [MAIN]',
|
20
|
+
'Check into dir of JOB (or source) for MAIN (or inferred) document'
|
21
|
+
def cd(*args); end
|
22
|
+
|
23
|
+
desc 'open [JOB ...] [MAIN]',
|
24
|
+
'Open PDF of each (or every) JOB for MAIN (or inferred) document'
|
25
|
+
def open(*args); end
|
26
|
+
|
27
|
+
remove_command :cd, :open unless IS_MNOGOO
|
28
|
+
|
29
|
+
desc 'mnogoo',
|
30
|
+
'Print path of the shell wrapper script'
|
31
|
+
def mnogoo
|
32
|
+
puts Pathname.new(__dir__).join('mnogoo.sh').realpath
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'clobber',
|
36
|
+
'Clean up all temporary files'
|
37
|
+
def clobber
|
38
|
+
# NOTE: this is a tad slow - using shell would improve that
|
39
|
+
# TODO: this does not account for custom work_path
|
40
|
+
tmp_dir = Pathname.new(Dir.tmpdir).join('mnogootex')
|
41
|
+
tmp_dir_size = Mnogootex::Utils.humanize_bytes Mnogootex::Utils.dir_size(tmp_dir)
|
42
|
+
print "Freeing up #{tmp_dir_size}... "
|
43
|
+
FileUtils.rm_r tmp_dir, secure: true if tmp_dir.directory?
|
44
|
+
puts 'Done.'
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'go [JOB ...] [MAIN]',
|
48
|
+
'Run each (or every) JOB for MAIN (or inferred) document'
|
49
|
+
def go(*args)
|
50
|
+
_, main, cfg = Mnogootex::Cfg.recombobulate(*args)
|
51
|
+
cfg = Mnogootex::Cfg::DEFAULTS.merge cfg
|
52
|
+
Mnogootex::Job::Warden.new(source: main, configuration: cfg).start
|
53
|
+
end
|
54
|
+
|
55
|
+
desc 'dir [JOB] [MAIN]',
|
56
|
+
'Print dir of JOB (or source) for MAIN (or inferred) document'
|
57
|
+
def dir(*args)
|
58
|
+
jobs, main, cfg = Mnogootex::Cfg.recombobulate(*args)
|
59
|
+
|
60
|
+
if jobs.empty?
|
61
|
+
puts main.dirname
|
62
|
+
else
|
63
|
+
jobs.map! { |hid| Mnogootex::Job::Porter.new hid: hid, source_path: main, work_path: cfg['work_path'] }
|
64
|
+
jobs.map!(&:target_dir)
|
65
|
+
puts jobs
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc 'pdf [JOB ...] [MAIN]',
|
70
|
+
'Print PDF path of each (or every) JOB for MAIN (or inferred) document'
|
71
|
+
def pdf(*args)
|
72
|
+
jobs, main, cfg = Mnogootex::Cfg.recombobulate(*args)
|
73
|
+
|
74
|
+
jobs = cfg['jobs'] if jobs.empty?
|
75
|
+
jobs.map! { |hid| Mnogootex::Job::Porter.new hid: hid, source_path: main, work_path: cfg['work_path'] }
|
76
|
+
jobs.map! { |porter| porter.target_path.sub_ext('.pdf') }
|
77
|
+
puts jobs
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|