mnogootex 0.2.0 → 1.1.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/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
|
+
[](https://travis-ci.org/paolobrasolin/mnogootex)
|
4
|
+
[](https://badge.fury.io/rb/mnogootex)
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
6
|
+
[](https://codeclimate.com/github/paolobrasolin/mnogootex)
|
7
|
+
<!-- [](https://codeclimate.com/github/paolobrasolin/mnogootex/coverage) -->
|
8
|
+
<!-- [](http://inch-ci.org/github/paolobrasolin/mnogootex) -->
|
9
|
+
<!-- [](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
|
+

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