mnogootex 1.1.0 → 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 +4 -4
- data/.github/actions/setup-ruby/action.yml +34 -0
- data/.github/workflows/main.yml +22 -19
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +55 -0
- data/README.md +200 -106
- data/demo/.mnogootexrc +4 -0
- data/demo/demo.asciicast +114 -0
- data/demo/demo.gif +0 -0
- data/demo/main.tex +5 -0
- data/lib/mnogootex/cfg.rb +22 -12
- data/lib/mnogootex/cli.rb +37 -54
- data/lib/mnogootex/job/porter.rb +12 -2
- data/lib/mnogootex/job/runner.rb +20 -3
- data/lib/mnogootex/job/warden.rb +11 -7
- data/lib/mnogootex/version.rb +1 -1
- data/spec/mnogootex/job/porter_spec.rb +4 -4
- data/spec/mnogootex/log/processor_spec.rb +2 -2
- metadata +8 -6
- data/lib/mnogootex/core_ext.rb +0 -11
- data/lib/mnogootex/defaults.yml +0 -7
- data/lib/mnogootex/mnogoo.sh +0 -21
- data/tty.gif +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edf454b8fab7fe98488bade01dd2c59b3419d5afb9bc4a6c7cadca1cd36bf296
|
4
|
+
data.tar.gz: 1036a5f4e565b1deef11daa6c5418eeb4f357e942fc55009d92f7fc6cfd9dcbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c47604bd0302b39ab98ac7417fd0b1b720360c6e54650cc99383237ef2c42cbc65b2edebad71b44d7a662a21aa3740b6f71a66712b87af09d253d86de142989
|
7
|
+
data.tar.gz: 7e00d8a660f75ac7e04e0ba8befea9553f33d8f94b692f31bd634f333043a29abf0eb6eef619389dbf1cc31496ea299ed101b0f4311080ce0e47904983aa939a
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Setup Ruby
|
2
|
+
description: Setup Ruby
|
3
|
+
inputs:
|
4
|
+
ruby-version:
|
5
|
+
required: false
|
6
|
+
default: '2.7'
|
7
|
+
cache-path:
|
8
|
+
required: false
|
9
|
+
default: vendor/bundle
|
10
|
+
cache-key:
|
11
|
+
required: false
|
12
|
+
default: gems-
|
13
|
+
cache-restore-keys:
|
14
|
+
required: false
|
15
|
+
default: gems-
|
16
|
+
outputs: {}
|
17
|
+
runs:
|
18
|
+
using: "composite"
|
19
|
+
steps:
|
20
|
+
- name: Setup Ruby
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ inputs.ruby-version }}
|
24
|
+
- name: Cache Ruby gems
|
25
|
+
uses: actions/cache@v2
|
26
|
+
with:
|
27
|
+
path: ${{ inputs.cache-path }}
|
28
|
+
key: ${{ inputs.cache-key }}
|
29
|
+
restore-keys: ${{ inputs.cache-restore-keys }}
|
30
|
+
- name: Install Ruby gems
|
31
|
+
shell: bash
|
32
|
+
run: |
|
33
|
+
bundle config path ${{ inputs.cache-path }}
|
34
|
+
bundle install --jobs 4 --retry 3
|
data/.github/workflows/main.yml
CHANGED
@@ -5,37 +5,40 @@ on:
|
|
5
5
|
pull_request:
|
6
6
|
|
7
7
|
jobs:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
runs-on: ${{ matrix.os }}-latest
|
8
|
+
|
9
|
+
test:
|
10
|
+
runs-on: ${{ matrix.os }}
|
12
11
|
strategy:
|
13
12
|
fail-fast: false
|
14
13
|
matrix:
|
15
|
-
os: [ ubuntu, macos ]
|
14
|
+
os: [ 'ubuntu-latest', 'macos-latest' ]
|
16
15
|
ruby: [ '2.6', '2.7', '3.0' ]
|
16
|
+
include:
|
17
|
+
- os: ubuntu-latest
|
18
|
+
ruby: '2.7'
|
19
|
+
coverage: true
|
17
20
|
|
18
21
|
steps:
|
19
22
|
|
20
23
|
- name: Checkout repo
|
21
24
|
uses: actions/checkout@v2
|
22
25
|
|
23
|
-
- name:
|
24
|
-
uses:
|
26
|
+
- name: Setup Ruby
|
27
|
+
uses: ./.github/actions/setup-ruby
|
25
28
|
with:
|
26
29
|
ruby-version: ${{ matrix.ruby }}
|
27
|
-
|
28
|
-
|
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
|
30
|
+
cache-key: gems-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('Gemfile', 'mnogootex.gemspec') }}
|
31
|
+
cache-restore-keys: gems-${{ matrix.os }}-${{ matrix.ruby }}-
|
39
32
|
|
40
33
|
- name: Run tests
|
41
34
|
run: bundle exec rake spec:rspec
|
35
|
+
|
36
|
+
- name: Test and publish coverage to Code Climate
|
37
|
+
uses: paambaati/codeclimate-action@v3.0.0
|
38
|
+
if: ${{ matrix.coverage && github.ref == 'refs/heads/main' }}
|
39
|
+
env:
|
40
|
+
CC_TEST_REPORTER_ID: 890ed5ee01002c7149920883256f8e4790000127faa9ddf14d86dd3ceb3b8179
|
41
|
+
COVERAGE: true
|
42
|
+
with:
|
43
|
+
coverageCommand: bundle exec rspec
|
44
|
+
coverageLocations: ${{ github.workspace }}/coverage/coverage.json:simplecov
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [2.0.0] - 2021-11-19
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
- `exec` command to run `latexmk` directly.
|
15
|
+
- `clobber` command to delete both unessential files and artifacts.
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- `go` command renamed to `build`.
|
20
|
+
- `clean` command simply deletes unessential files (instead of everything).
|
21
|
+
- Configuration must be named `.mnogootexrc` (instead of `.mnogootex.yml`).
|
22
|
+
|
23
|
+
### Removed
|
24
|
+
|
25
|
+
- `mnogoo` shell integration no longer exists.
|
26
|
+
- `dir` and `pdf` commands no longer exist.
|
27
|
+
|
28
|
+
### Fixed
|
29
|
+
|
30
|
+
- Avoid deleting files before buils so viewers can reload.
|
31
|
+
- Caught nasty IO timing bug when polling `latexmk -pv` for logs.
|
32
|
+
|
33
|
+
## [1.1.0] - 2021-11-06
|
34
|
+
|
35
|
+
### Added
|
36
|
+
|
37
|
+
- New option `work_path` in configuration file to simplify access to build folders.
|
38
|
+
|
39
|
+
## [1.0.1] - 2018-09-03
|
40
|
+
|
41
|
+
### Fixed
|
42
|
+
|
43
|
+
- `mnogootex mnogoo` now produces correct path.
|
44
|
+
|
45
|
+
## [1.0.0] - 2018-04-24
|
46
|
+
|
47
|
+
### Added
|
48
|
+
|
49
|
+
- First public release.
|
50
|
+
|
51
|
+
[unreleased]: https://github.com/paolobrasolin/mnogootex/compare/v2.0.0...HEAD
|
52
|
+
[2.0.0]: https://github.com/paolobrasolin/mnogootex/compare/v1.1.0...v2.0.0
|
53
|
+
[1.1.0]: https://github.com/paolobrasolin/mnogootex/compare/v1.0.1...v1.1.0
|
54
|
+
[1.0.1]: https://github.com/paolobrasolin/mnogootex/compare/v1.0.0...v1.0.1
|
55
|
+
[1.0.0]: https://github.com/paolobrasolin/mnogootex/releases/tag/v1.0.0
|
data/README.md
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
# Многоꙮтех
|
2
2
|
|
3
|
-
[![
|
4
|
-
[![
|
5
|
-
[![License
|
6
|
-
[![
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
[![CI tests status badge][build-shield]][build-url]
|
4
|
+
[![Latest release badge][rubygems-shield]][rubygems-url]
|
5
|
+
[![License badge][license-shield]][license-url]
|
6
|
+
[![Maintainability badge][cc-maintainability-shield]][cc-maintainability-url]
|
7
|
+
[![Test coverage badge][cc-coverage-shield]][cc-coverage-url]
|
8
|
+
|
9
|
+
[build-shield]: https://img.shields.io/github/workflow/status/paolobrasolin/mnogootex/CI/main?label=tests&logo=github
|
10
|
+
[build-url]: https://github.com/paolobrasolin/mnogootex/actions/workflows/main.yml "CI tests status"
|
11
|
+
[rubygems-shield]: https://img.shields.io/gem/v/mnogootex?logo=ruby
|
12
|
+
[rubygems-url]: https://rubygems.org/gems/mnogootex "Latest release"
|
13
|
+
[license-shield]: https://img.shields.io/github/license/paolobrasolin/mnogootex
|
14
|
+
[license-url]: https://github.com/paolobrasolin/mnogootex/blob/main/LICENSE "License"
|
15
|
+
[cc-maintainability-shield]: https://img.shields.io/codeclimate/maintainability/paolobrasolin/mnogootex?logo=codeclimate
|
16
|
+
[cc-maintainability-url]: https://codeclimate.com/github/paolobrasolin/mnogootex "Maintainability"
|
17
|
+
[cc-coverage-shield]: https://img.shields.io/codeclimate/coverage/paolobrasolin/mnogootex?logo=codeclimate&label=test%20coverage
|
18
|
+
[cc-coverage-url]: https://codeclimate.com/github/paolobrasolin/mnogootex/coverage "Test coverage"
|
10
19
|
|
11
20
|
Многоꙮтех (mnogootex) is a utility that parallelizes compilation
|
12
21
|
of a LaTeX document using different classes and offers a
|
@@ -16,174 +25,259 @@ The motivating use case is maintaining a single preamble while
|
|
16
25
|
submitting a paper to many journals using their outdated or crummy
|
17
26
|
document classes.
|
18
27
|
|
19
|
-
##
|
28
|
+
## Getting started
|
20
29
|
|
21
|
-
|
30
|
+
### Prerequisites
|
31
|
+
|
32
|
+
Многоꙮтех is written in [**Ruby**](https://www.ruby-lang.org) and requires version `>=2.5` (earlier ones are untested).
|
33
|
+
You can check whether it's installed by running `ruby --version`.
|
34
|
+
For installation instructions you can refer to the [official documentation](https://www.ruby-lang.org/en/documentation/installation/).
|
35
|
+
|
36
|
+
|
37
|
+
Многоꙮтех heavily relies on [**`latexmk`**](https://ctan.org/pkg/latexmk).
|
38
|
+
You can check whether it's installed by running `latexmk --version`.
|
39
|
+
If you are missing it, follow the documentation of your specific LaTeX distribution and install the `latexmk` package.
|
40
|
+
|
41
|
+
### Installation
|
22
42
|
|
23
43
|
To install многоꙮтех execute
|
24
44
|
|
25
|
-
|
26
|
-
|
27
|
-
|
45
|
+
```bash
|
46
|
+
gem install mnogootex
|
47
|
+
```
|
48
|
+
|
49
|
+
If you're upgrading from a previous version, execute
|
28
50
|
|
29
|
-
|
51
|
+
```bash
|
52
|
+
gem update mnogootex
|
53
|
+
```
|
30
54
|
|
31
|
-
|
55
|
+
and remove any mention of `mnogootex` from your shell profile (it's not needed anymore).
|
32
56
|
|
33
|
-
|
57
|
+
### Quick start
|
34
58
|
|
35
|
-
|
36
|
-
containing the list of document classes you want to compile your
|
37
|
-
project against:
|
59
|
+
First you write a LaTeX document:
|
38
60
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
61
|
+
```latex
|
62
|
+
% ~/demo/main.tex
|
63
|
+
\documentclass{scrarticle}
|
64
|
+
\begin{document}
|
65
|
+
\abstract{Simply put, my article is awesome.}
|
66
|
+
Let's port my \KOMAScript\ article to other classes!
|
67
|
+
\end{document}
|
68
|
+
```
|
45
69
|
|
46
|
-
|
70
|
+
Then you list the desided classes in a Многоꙮтех configuration file:
|
71
|
+
|
72
|
+
```yaml
|
73
|
+
# ~/demo/.mnogootexrc
|
74
|
+
jobs:
|
75
|
+
- scrartcl
|
76
|
+
- article
|
77
|
+
- book
|
78
|
+
```
|
79
|
+
|
80
|
+
Finally you run `mnogootex build` and enjoy the technicolor:
|
81
|
+
|
82
|
+

|
47
83
|
|
48
84
|
## Usage
|
49
85
|
|
50
|
-
|
51
|
-
1.
|
52
|
-
2.
|
53
|
-
3.
|
54
|
-
4.
|
86
|
+
A Многоꙮтех run does the following:
|
87
|
+
1. copy the _source_ folder of a project to many _target_ folders, one for each _job_;
|
88
|
+
2. replace the document class in the source of each _target_ folder with the name of the relative _job_;
|
89
|
+
3. call `latexmk` in parallel on each _target_ folder to compile the documents (or do other tasks);
|
90
|
+
4. wait for the outcomes and print the logs, filtered and colour-coded in a meaningful way.
|
55
91
|
|
56
92
|
Its convenience lies in the fact that it
|
57
93
|
* automates the setup process,
|
58
94
|
* parallelizes compilation,
|
59
|
-
*
|
60
|
-
* allows you to easily navigate through targets/source folders.
|
95
|
+
* improves the readability of the infamous waterfall logs.
|
61
96
|
|
62
|
-
Многоꙮтех can be invoked from
|
63
|
-
|
97
|
+
Многоꙮтех can be invoked from CLI using `mnogootex`.
|
98
|
+
It accepts various [commands](#mnogootex-commands) detailed below.
|
64
99
|
|
65
|
-
|
100
|
+
To leverage the full power of this tool you will need to learn writing [`mnogootex` configurations](#mnogootex-configuration) and ['latexmk' configurations](#latexmk-configuration).
|
101
|
+
It might sound daunting but they're really just a few lines.
|
66
102
|
|
67
|
-
###
|
103
|
+
### `mnogootex` commands
|
68
104
|
|
69
|
-
> **
|
70
|
-
|
71
|
-
#### `help [COMMAND]`
|
105
|
+
> **Notation:** `[FOO]` means that _`FOO` is optional_ while `FOO ...` means _one or more `FOO`s_.
|
72
106
|
|
73
|
-
|
107
|
+
All commands except `help` accept the same parameters, so let's examine them in advance to avoid repeating ourselves later.
|
108
|
+
Here is their syntax:
|
74
109
|
|
75
|
-
|
110
|
+
```bash
|
111
|
+
mnogootex COMMAND [JOB ...] [FLAG ...] ROOT
|
112
|
+
```
|
76
113
|
|
77
|
-
|
78
|
-
|
114
|
+
`JOB`s are the names of the document classes to compile your document with.
|
115
|
+
Zero or more can be provided, and when none is given the job list is loaded from the [configuration](#jobs).
|
79
116
|
|
80
|
-
|
117
|
+
`FLAG`s are `latexmk` options.
|
118
|
+
Zero or more can be provided to override the behaviour of the `latexmk` call underlying the `mnogootex` command.
|
119
|
+
You can obtain a list of available options with the inline help `latexmk --help`, and the full documentation with `man latexmk`.
|
120
|
+
Generally speaking, if you find yourself always using a `FLAG` you should properly [configure `latexmk`](#latexmk-configuration) instead.
|
81
121
|
|
82
|
-
|
122
|
+
The last mandatory parameter is the `ROOT` file for compiling of your document.
|
83
123
|
|
84
|
-
|
85
|
-
They are deduced from the [configuration](#configuration).
|
124
|
+
Let's examine the details of each command now.
|
86
125
|
|
87
|
-
|
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.
|
126
|
+
#### `help [COMMAND]`
|
93
127
|
|
94
|
-
|
128
|
+
This command prints the help for `COMMAND` (or all commands if none is given).
|
95
129
|
|
96
|
-
|
97
|
-
your current working directory or the [configuration](#configuration).
|
130
|
+
#### `exec [JOB ...] [FLAG ...] ROOT`
|
98
131
|
|
99
|
-
|
132
|
+
This command simply runs `latexmk` on the `ROOT` document for each of your `JOB`s passing the given `FLAG`s.
|
100
133
|
|
101
|
-
|
134
|
+
All other commands below are specializations of this one.
|
135
|
+
However you'll seldom use it unless you're debugging.
|
102
136
|
|
103
|
-
|
137
|
+
#### `build [JOB ...] [FLAG ...] ROOT`
|
104
138
|
|
105
|
-
|
139
|
+
This command builds your document.
|
106
140
|
|
107
|
-
|
108
|
-
your current working directory or the [configuration](#configuration).
|
141
|
+
It is equivalent to `exec [JOB ...] -interaction=nonstopmode ROOT`.
|
109
142
|
|
110
|
-
|
143
|
+
You will probably need to pass some `FLAG`s (e.g. to use the correct engine) but it is not recommended: [configure `latexmk`](#latexmk-configuration) instead.
|
111
144
|
|
112
|
-
|
113
|
-
Useful to free up some space from time to time.
|
145
|
+
#### `open [JOB ...] [FLAG ...] ROOT`
|
114
146
|
|
115
|
-
|
147
|
+
This command opens the final compilation artifact (after running the build if necessary).
|
116
148
|
|
117
|
-
|
149
|
+
It is equivalent to `exec [JOB ...] -pv -interaction=nonstopmode ROOT`.
|
118
150
|
|
119
|
-
|
120
|
-
They are deduced from the [configuration](#configuration).
|
151
|
+
You might need to pass some `FLAG`s (e.g. to use the correct viewer) but it is not recommended: [configure `latexmk`](#latexmk-configuration) instead.
|
121
152
|
|
122
|
-
|
123
|
-
your current working directory or the [configuration](#configuration).
|
153
|
+
#### `clean [JOB ...] [FLAG ...] ROOT`
|
124
154
|
|
125
|
-
|
155
|
+
This command deletes all nonessential build files while keeping the compiled artifacts.
|
126
156
|
|
127
|
-
|
157
|
+
It is equivalent to `exec [JOB ...] -c ROOT`.
|
128
158
|
|
129
|
-
|
159
|
+
#### `clobber [JOB ...] [FLAG ...] ROOT`
|
130
160
|
|
131
|
-
|
132
|
-
They are deduced from the [configuration](#configuration).
|
161
|
+
This command deletes all nonessential build files including the compiled artifacts.
|
133
162
|
|
134
|
-
|
135
|
-
your current working directory or the [configuration](#configuration).
|
163
|
+
It is equivalent to `exec [JOB ...] -C ROOT`.
|
136
164
|
|
137
|
-
###
|
165
|
+
### `mnogootex` configuration
|
138
166
|
|
139
|
-
|
140
|
-
files named `.
|
167
|
+
`mnogootex` is configured through [`YAML`](https://learnxinyminutes.com/docs/yaml/)
|
168
|
+
files named `.mnogootexrc` put into your projects' root directory.
|
141
169
|
|
142
|
-
When
|
170
|
+
When `mnogootex` loads a configuration it also looks up for `.mnogootexrc`
|
143
171
|
files in all parent directories to merge then together (from the
|
144
172
|
shallowest to the deepest path). This means that e.g. you can keep
|
145
173
|
a configuration file in your home folder and use it as a global
|
146
174
|
configuration for all you projects, while overwriting only specific
|
147
175
|
options in the configuration files of each one.
|
148
176
|
|
149
|
-
|
177
|
+
`mnogootex` currently accepts three options.
|
150
178
|
|
151
|
-
#### `
|
179
|
+
#### `jobs`
|
180
|
+
|
181
|
+
This option represents the `JOB`s to build your document (when none are given via CLI).
|
152
182
|
|
153
|
-
|
154
|
-
animate the spinners for the command line interface.
|
183
|
+
It must contain valid document class names, given as a list of strings.
|
155
184
|
|
156
|
-
|
157
|
-
spinner: ⣾⣽⣻⢿⡿⣟⣯⣷
|
185
|
+
By default there are no `JOB`s:
|
158
186
|
|
159
|
-
|
187
|
+
```yaml
|
188
|
+
# Default value:
|
189
|
+
jobs: []
|
190
|
+
```
|
160
191
|
|
161
|
-
|
162
|
-
to compile documents.
|
192
|
+
Here is a slightly more interesting example:
|
163
193
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
194
|
+
```yaml
|
195
|
+
jobs:
|
196
|
+
- scrartcl
|
197
|
+
- article
|
198
|
+
- book
|
199
|
+
```
|
169
200
|
|
170
201
|
#### `work_path`
|
171
202
|
|
172
|
-
This option is
|
203
|
+
This option is the folder where all elaboration happens.
|
204
|
+
|
205
|
+
It must be a well formed path, given as a string.
|
206
|
+
|
207
|
+
By default none is given, meaning that each run of any given job happens in a dedicated temporary folder:
|
208
|
+
|
209
|
+
```yaml
|
210
|
+
# Default value:
|
211
|
+
work_path: null
|
212
|
+
```
|
213
|
+
|
214
|
+
Overriding this allows you to have easier access to the compilation artifacts.
|
215
|
+
A good choice is setting it to `./build` and keep everything below your source folder:
|
216
|
+
|
217
|
+
```yaml
|
218
|
+
work_path: ./build
|
219
|
+
```
|
220
|
+
|
221
|
+
#### `spinner`
|
222
|
+
|
223
|
+
This option is the spinner animation shown by the CLI.
|
224
|
+
|
225
|
+
It is a series of frames given as characters of a string.
|
226
|
+
|
227
|
+
By default it's a hole looping around in a blister:
|
228
|
+
|
229
|
+
```yaml
|
230
|
+
# Default value:
|
231
|
+
spinner: ⣾⣽⣻⢿⡿⣟⣯⣷
|
232
|
+
```
|
233
|
+
|
234
|
+
Here is a couple more in case your terminal doesn't like Unicode:
|
235
|
+
|
236
|
+
```yaml
|
237
|
+
# A wriggly ASCII worm:
|
238
|
+
spinner: )}]|[{({[|]}
|
239
|
+
# An extended ASCII boomerang:
|
240
|
+
spinner: ╒┍┌┎╓╖┒┐┑╕╛┙┘┚╜╙┖└┕╘
|
241
|
+
```
|
242
|
+
|
243
|
+
Feel free to get creative!
|
244
|
+
|
245
|
+
### `latexmk` configuration
|
246
|
+
|
247
|
+
`latexmk` is configured through [`Perl`](https://www.perl.org/)
|
248
|
+
files named `.latexmkrc` put into your projects' root directory.
|
249
|
+
|
250
|
+
When `latexmk` loads a configuration it also looks up for `.latexmkrc`
|
251
|
+
files in all parent directories to merge then together (from the
|
252
|
+
shallowest to the deepest path). This means that e.g. you can keep
|
253
|
+
a configuration file in your home folder and use it as a global
|
254
|
+
configuration for all you projects, while overwriting only specific
|
255
|
+
options in the configuration files of each one.
|
173
256
|
|
174
|
-
|
175
|
-
|
257
|
+
`latexmk` has a gazillion of options.
|
258
|
+
We'll just skim over the most common ones here.
|
176
259
|
|
177
|
-
|
260
|
+
First of all, one must pick the correct engine.
|
261
|
+
Assuming you want to produce a PDF artifact, you have a few choices:
|
178
262
|
|
179
|
-
|
263
|
+
```perl
|
264
|
+
$pdf_mode = 1; # create PDF with pdflatex
|
265
|
+
# $pdf_mode = 2; # create PDF with ps2pdf (via PS)
|
266
|
+
# $pdf_mode = 3; # create PDF with dvipdf (via DVI)
|
267
|
+
# $pdf_mode = 4; # create PDF with lualatex
|
268
|
+
# $pdf_mode = 5; # create PDF with xelatex
|
269
|
+
```
|
180
270
|
|
181
|
-
|
271
|
+
Then, if your PDF previewer is not being detected, you might need to configure it.
|
272
|
+
Assuming you want to use evince:
|
182
273
|
|
183
|
-
|
274
|
+
```perl
|
275
|
+
$pdf_previewer = 'start evince';
|
276
|
+
```
|
184
277
|
|
185
|
-
|
278
|
+
Most people won't probably need anything more than that.
|
279
|
+
However, for further details read the documentation in the commandline with `man latexmk` or on [CTAN](https://ctan.mirror.garr.it/mirrors/ctan/support/latexmk/latexmk.txt)
|
186
280
|
|
187
|
-
##
|
281
|
+
## Acknowledgements
|
188
282
|
|
189
|
-
|
283
|
+
* Thanks to [@tetrapharmakon](https://github.com/tetrapharmakon) for being the first tester and user.
|
data/demo/.mnogootexrc
ADDED
data/demo/demo.asciicast
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
{"version": 2, "width": 92, "height": 26, "timestamp": 1637333757, "env": {"SHELL": "/bin/zsh", "TERM": "alacritty"}}
|
2
|
+
[0.017014, "o", "\u001b[?2004h$ "]
|
3
|
+
[0.816219, "o", "m"]
|
4
|
+
[0.880306, "o", "n"]
|
5
|
+
[1.120106, "o", "o"]
|
6
|
+
[1.328005, "o", "g"]
|
7
|
+
[1.431937, "o", "o"]
|
8
|
+
[1.560266, "o", "o"]
|
9
|
+
[1.664007, "o", "t"]
|
10
|
+
[1.824229, "o", "e"]
|
11
|
+
[2.096341, "o", "x"]
|
12
|
+
[2.208064, "o", " "]
|
13
|
+
[2.416225, "o", "b"]
|
14
|
+
[2.488119, "o", "u"]
|
15
|
+
[2.528114, "o", "i"]
|
16
|
+
[2.775867, "o", "l"]
|
17
|
+
[2.927851, "o", "d"]
|
18
|
+
[3.048131, "o", " "]
|
19
|
+
[3.18416, "o", "m"]
|
20
|
+
[3.30414, "o", "a"]
|
21
|
+
[3.360091, "o", "i"]
|
22
|
+
[3.463861, "o", "n"]
|
23
|
+
[3.664082, "o", "."]
|
24
|
+
[3.768087, "o", "t"]
|
25
|
+
[3.872092, "o", "e"]
|
26
|
+
[4.072065, "o", "x"]
|
27
|
+
[4.19206, "o", "\r\n\u001b[?2004l\r"]
|
28
|
+
[4.610511, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
29
|
+
[4.630807, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
30
|
+
[4.652109, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
31
|
+
[4.672831, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
32
|
+
[4.693597, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
33
|
+
[4.71437, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
34
|
+
[4.735132, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
35
|
+
[4.755441, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
36
|
+
[4.776142, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;33;49m⣽\u001b[0m\u001b[0;33;49m⣽\u001b[0m\r"]
|
37
|
+
[4.796857, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;33;49m⣻\u001b[0m\u001b[0;33;49m⣻\u001b[0m\r"]
|
38
|
+
[4.817161, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;33;49m⢿\u001b[0m\u001b[0;33;49m⢿\u001b[0m\r"]
|
39
|
+
[4.837458, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;33;49m⡿\u001b[0m\u001b[0;33;49m⡿\u001b[0m\r"]
|
40
|
+
[4.857789, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;33;49m⣟\u001b[0m\u001b[0;33;49m⣟\u001b[0m\r"]
|
41
|
+
[4.878122, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣯\u001b[0m\u001b[0;33;49m⣯\u001b[0m\r"]
|
42
|
+
[4.898448, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;33;49m⣷\u001b[0m\u001b[0;33;49m⣷\u001b[0m\r"]
|
43
|
+
[4.918754, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣾\u001b[0m\r"]
|
44
|
+
[4.939493, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;33;49m⣽\u001b[0m\u001b[0;33;49m⣽\u001b[0m\r"]
|
45
|
+
[4.960303, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;33;49m⣻\u001b[0m\u001b[0;33;49m⣻\u001b[0m\r"]
|
46
|
+
[4.980995, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;33;49m⢿\u001b[0m\u001b[0;33;49m⢿\u001b[0m\r"]
|
47
|
+
[5.001721, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;33;49m⡿\u001b[0m\u001b[0;33;49m⡿\u001b[0m\r"]
|
48
|
+
[5.022407, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;33;49m⣟\u001b[0m\u001b[0;33;49m⣟\u001b[0m\r"]
|
49
|
+
[5.042661, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
50
|
+
[5.062924, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
51
|
+
[5.083219, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
52
|
+
[5.10347, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
53
|
+
[5.123727, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
54
|
+
[5.143997, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
55
|
+
[5.164261, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
56
|
+
[5.18454, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
57
|
+
[5.204898, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
58
|
+
[5.225157, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
59
|
+
[5.245427, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
60
|
+
[5.265709, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
61
|
+
[5.285988, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
62
|
+
[5.306276, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
63
|
+
[5.326587, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
64
|
+
[5.346862, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
65
|
+
[5.367137, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
66
|
+
[5.387471, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
67
|
+
[5.407789, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
68
|
+
[5.428094, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
69
|
+
[5.448427, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
70
|
+
[5.468685, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
71
|
+
[5.48902, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
72
|
+
[5.509286, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
73
|
+
[5.529559, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
74
|
+
[5.549834, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
75
|
+
[5.570114, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
76
|
+
[5.590495, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
77
|
+
[5.610773, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
78
|
+
[5.631053, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
79
|
+
[5.651328, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
80
|
+
[5.671634, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
81
|
+
[5.691885, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
82
|
+
[5.712144, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
83
|
+
[5.732409, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
84
|
+
[5.752725, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
85
|
+
[5.77299, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
86
|
+
[5.793269, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
87
|
+
[5.81354, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
88
|
+
[5.833802, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
89
|
+
[5.854091, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
90
|
+
[5.874667, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
91
|
+
[5.894903, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
92
|
+
[5.915157, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
93
|
+
[5.935432, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
94
|
+
[5.955706, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
95
|
+
[5.975985, "o", "Runners: \u001b[0;33;49m⢿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
96
|
+
[5.996281, "o", "Runners: \u001b[0;33;49m⡿\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
97
|
+
[6.016565, "o", "Runners: \u001b[0;33;49m⣟\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
98
|
+
[6.03685, "o", "Runners: \u001b[0;33;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
99
|
+
[6.057124, "o", "Runners: \u001b[0;33;49m⣷\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
100
|
+
[6.077406, "o", "Runners: \u001b[0;33;49m⣾\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
101
|
+
[6.097789, "o", "Runners: \u001b[0;33;49m⣽\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
102
|
+
[6.118073, "o", "Runners: \u001b[0;33;49m⣻\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r"]
|
103
|
+
[6.138511, "o", "Runners: \u001b[0;32;49m⣯\u001b[0m\u001b[0;31;49m⣾\u001b[0m\u001b[0;31;49m⢿\u001b[0m\r\r\nOutcome:\r\n"]
|
104
|
+
[6.138712, "o", " \u001b[0;32;49m✔\u001b[0m scrarticle\r\n \u001b[0;31;49m✘\u001b[0m article\r\n"]
|
105
|
+
[6.139693, "o", " \u001b[0;97;49mLatexmk: This is Latexmk, John Collins, 21 September 2021, version: 4.75.\u001b[0m\r\n \u001b[0;97;49mThis is pdfTeX, Version 3.141592653-2.6-1.40.23 (TeX Live 2021) (preloaded format=latex)\u001b[0m\r\n \u001b[0;91;49m! Undefined control sequence.\u001b[0m\r\n \u001b[0;91;49ml.4 Let's port my \\KOMAScript\u001b[0m\r\n \u001b[0;91;49m \\ article!\u001b[0m\r\n \u001b[0;97;49mOutput written on main.dvi (1 page, 424 bytes).\u001b[0m\r\n \u001b[0;91;49mLatexmk: Errors, so I did not complete making targets\u001b[0m\r\n \u001b[0;31;49m✘\u001b[0m book\r\n"]
|
106
|
+
[6.140624, "o", " \u001b[0;97;49mLatexmk: This is Latexmk, John Collins, 21 September 2021, version: 4.75.\u001b[0m\r\n \u001b[0;97;49mThis is pdfTeX, Version 3.141592653-2.6-1.40.23 (TeX Live 2021) (preloaded format=latex)\u001b[0m\r\n \u001b[0;91;49m! Undefined control sequence.\u001b[0m\r\n \u001b[0;91;49ml.3 \\abstract\u001b[0m\r\n \u001b[0;91;49m {Simply put, my article is awesome.}\u001b[0m\r\n \u001b[0;91;49m! Undefined control sequence.\u001b[0m\r\n \u001b[0;91;49ml.4 Let's port my \\KOMAScript\u001b[0m\r\n"]
|
107
|
+
[6.140752, "o", " \u001b[0;91;49m \\ article!\u001b[0m\r\n \u001b[0;97;49mOutput written on main.dvi (1 page, 324 bytes).\u001b[0m\r\n \u001b[0;91;49mLatexmk: Errors, so I did not complete making targets\u001b[0m\r\n"]
|
108
|
+
[6.145564, "o", "\u001b[?2004h$ "]
|
109
|
+
[9.623727, "o", "e"]
|
110
|
+
[9.720091, "o", "x"]
|
111
|
+
[9.904131, "o", "i"]
|
112
|
+
[10.016153, "o", "t"]
|
113
|
+
[10.496203, "o", "\r\n\u001b[?2004l\r"]
|
114
|
+
[10.49658, "o", "exit\r\n"]
|
data/demo/demo.gif
ADDED
Binary file
|
data/demo/main.tex
ADDED
data/lib/mnogootex/cfg.rb
CHANGED
@@ -3,12 +3,14 @@
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'pathname'
|
5
5
|
|
6
|
-
require 'mnogootex/core_ext'
|
7
|
-
|
8
6
|
module Mnogootex
|
9
7
|
module Cfg
|
10
|
-
BASENAME = '.
|
11
|
-
DEFAULTS =
|
8
|
+
BASENAME = '.mnogootexrc'
|
9
|
+
DEFAULTS = {
|
10
|
+
'jobs' => [],
|
11
|
+
'spinner' => '⣾⣽⣻⢿⡿⣟⣯⣷',
|
12
|
+
'work_path' => nil,
|
13
|
+
}.freeze
|
12
14
|
|
13
15
|
def self.load_descending(pathname:, basename:)
|
14
16
|
pathname.realpath.descend.
|
@@ -25,15 +27,22 @@ module Mnogootex
|
|
25
27
|
class << self
|
26
28
|
private
|
27
29
|
|
30
|
+
def split_jobs_and_flags(args)
|
31
|
+
# TODO: some kind of validation?
|
32
|
+
flags = args.drop_while { |arg| !arg.start_with?('-') }
|
33
|
+
jobs = args.take_while { |arg| !arg.start_with?('-') }
|
34
|
+
[(jobs unless jobs.empty?), (flags unless flags.empty?)]
|
35
|
+
end
|
36
|
+
|
28
37
|
def try_args(*args)
|
29
38
|
main = Pathname.new(args.fetch(-1, ''))
|
30
39
|
return unless main.file?
|
31
40
|
|
32
41
|
main = main.realpath
|
33
42
|
cfg = load_descending(pathname: main.dirname, basename: BASENAME)
|
34
|
-
jobs = args[0..-2]
|
43
|
+
jobs, flags = split_jobs_and_flags(args[0..-2])
|
35
44
|
|
36
|
-
[jobs, main, cfg]
|
45
|
+
[jobs, flags, main, cfg]
|
37
46
|
end
|
38
47
|
|
39
48
|
def try_link(*args)
|
@@ -42,20 +51,21 @@ module Mnogootex
|
|
42
51
|
|
43
52
|
main = link.readlink.realpath
|
44
53
|
cfg = load_descending(pathname: main.dirname, basename: BASENAME)
|
45
|
-
jobs = args
|
54
|
+
jobs, flags = split_jobs_and_flags(args)
|
46
55
|
|
47
|
-
[jobs, main, cfg]
|
56
|
+
[jobs, flags, main, cfg]
|
48
57
|
end
|
49
58
|
|
50
59
|
def try_cfgs(*args)
|
51
|
-
yaml = Pathname.pwd.ascend.map { |p| p.join('.
|
60
|
+
yaml = Pathname.pwd.ascend.map { |p| p.join('.mnogootexrc') }.detect(&:file?)
|
52
61
|
return if yaml.nil?
|
53
62
|
|
54
63
|
cfg = load_descending(pathname: yaml.dirname, basename: BASENAME)
|
55
|
-
main = yaml.dirname.join(cfg.fetch('main', ''))
|
56
|
-
|
64
|
+
main = yaml.dirname.join(cfg.fetch('main', ''))
|
65
|
+
main = main.file? ? main.realpath : nil
|
66
|
+
jobs, flags = split_jobs_and_flags(args)
|
57
67
|
|
58
|
-
[jobs, main, cfg]
|
68
|
+
[jobs, flags, main, cfg]
|
59
69
|
end
|
60
70
|
end
|
61
71
|
end
|
data/lib/mnogootex/cli.rb
CHANGED
@@ -10,71 +10,54 @@ require 'mnogootex/cfg'
|
|
10
10
|
|
11
11
|
module Mnogootex
|
12
12
|
class CLI < Thor
|
13
|
-
|
14
|
-
|
15
|
-
def
|
16
|
-
|
13
|
+
desc 'exec [JOB ...] [FLAG ...] ROOT',
|
14
|
+
'Execute latexmk with FLAGs on each JOB for ROOT document'
|
15
|
+
def exec(*args)
|
16
|
+
execute_latexmk(*args, default_flags: [])
|
17
17
|
end
|
18
18
|
|
19
|
-
desc '
|
20
|
-
'
|
21
|
-
def
|
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
|
19
|
+
desc 'build [JOB ...] [FLAG ...] ROOT',
|
20
|
+
'Build each JOB for ROOT document'
|
21
|
+
def build(*args)
|
22
|
+
execute_latexmk(*args, default_flags: ['-interaction=nonstopmode'])
|
33
23
|
end
|
34
24
|
|
35
|
-
desc '
|
36
|
-
'
|
37
|
-
def
|
38
|
-
|
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.'
|
25
|
+
desc 'open [JOB ...] [FLAG ...] ROOT',
|
26
|
+
'(Build and) open the artifact of each JOB for ROOT document'
|
27
|
+
def open(*args)
|
28
|
+
execute_latexmk(*args, default_flags: ['-interaction=nonstopmode', '-pv'])
|
45
29
|
end
|
46
30
|
|
47
|
-
desc '
|
48
|
-
'
|
49
|
-
def
|
50
|
-
|
51
|
-
cfg = Mnogootex::Cfg::DEFAULTS.merge cfg
|
52
|
-
Mnogootex::Job::Warden.new(source: main, configuration: cfg).start
|
31
|
+
desc 'clean [JOB ...] [FLAG ...] ROOT',
|
32
|
+
'Delete nonessential files of each JOB for ROOT document'
|
33
|
+
def clean(*args)
|
34
|
+
execute_latexmk(*args, default_flags: ['-c'])
|
53
35
|
end
|
54
36
|
|
55
|
-
desc '
|
56
|
-
'
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
37
|
+
desc 'clobber [JOB ...] [FLAG ...] ROOT',
|
38
|
+
'Delete nonessential files and artifacts of each JOB for ROOT document'
|
39
|
+
def clobber(*args)
|
40
|
+
execute_latexmk(*args, default_flags: ['-C'])
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'help [COMMAND]',
|
44
|
+
'Describe available commands or one specific COMMAND'
|
45
|
+
def help(*args)
|
46
|
+
super
|
47
|
+
|
48
|
+
puts <<~EXTRA_HELP
|
49
|
+
JOBs are document class names. The default is the whole list in your configuration file.
|
50
|
+
FLAGs are options passed to latexmk. Please refer to `latexmk -help` for details.
|
51
|
+
EXTRA_HELP
|
67
52
|
end
|
68
53
|
|
69
|
-
|
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)
|
54
|
+
private
|
73
55
|
|
74
|
-
|
75
|
-
jobs
|
76
|
-
|
77
|
-
|
56
|
+
def execute_latexmk(*args, default_flags: [])
|
57
|
+
jobs, flags, main, cfg = Mnogootex::Cfg.recombobulate(*args)
|
58
|
+
cfg = Mnogootex::Cfg::DEFAULTS.merge(cfg).merge({ 'jobs' => jobs }.compact)
|
59
|
+
flags = [*default_flags, *flags]
|
60
|
+
Mnogootex::Job::Warden.new(source: main, configuration: cfg, flags: flags).start
|
78
61
|
end
|
79
62
|
end
|
80
63
|
end
|
data/lib/mnogootex/job/porter.rb
CHANGED
@@ -33,12 +33,22 @@ module Mnogootex
|
|
33
33
|
providable_files = @source_path.dirname.children
|
34
34
|
providable_files.reject!(&@work_path.method(:==))
|
35
35
|
FileUtils.cp_r providable_files, target_dir
|
36
|
-
target_dir
|
37
|
-
target_dir
|
36
|
+
remove_configuration(target_dir)
|
37
|
+
create_link_to_source(target_dir)
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
|
+
def remove_configuration(folder_path)
|
43
|
+
path = folder_path.join('.mnogootexrc')
|
44
|
+
path.delete if path.file?
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_link_to_source(folder_path)
|
48
|
+
path = folder_path.join('.mnogootex.src')
|
49
|
+
path.make_symlink(@source_path) unless path.symlink?
|
50
|
+
end
|
51
|
+
|
42
52
|
def calc_work_path(path)
|
43
53
|
return Pathname.new(path) unless path.nil?
|
44
54
|
|
data/lib/mnogootex/job/runner.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'open3'
|
4
|
+
require 'io/wait'
|
4
5
|
|
5
6
|
module Mnogootex
|
6
7
|
module Job
|
7
8
|
class Runner
|
9
|
+
POLLING_TIMEOUT = 0.02
|
10
|
+
|
8
11
|
attr_reader :hid, :log_lines
|
9
12
|
|
10
13
|
def initialize(cmd:, chdir:)
|
@@ -31,13 +34,27 @@ module Mnogootex
|
|
31
34
|
|
32
35
|
def start_poller
|
33
36
|
Thread.new do
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
+
polling_loop
|
38
|
+
|
37
39
|
# NOTE: waits on @thread and returns its value
|
38
40
|
@thread.value
|
39
41
|
end
|
40
42
|
end
|
43
|
+
|
44
|
+
def polling_loop
|
45
|
+
loop do
|
46
|
+
if @stream.wait_readable(POLLING_TIMEOUT).nil?
|
47
|
+
# If the stream timeouts and the thread is dead we expect no nore data.
|
48
|
+
# This happens on commands like `latexmk -pv` which fork other processes.
|
49
|
+
break unless @thread.alive?
|
50
|
+
else
|
51
|
+
# If we reach EOF, we expect no more data.
|
52
|
+
break if (line = @stream.gets).nil?
|
53
|
+
|
54
|
+
log_lines << line
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
41
58
|
end
|
42
59
|
end
|
43
60
|
end
|
data/lib/mnogootex/job/warden.rb
CHANGED
@@ -11,9 +11,12 @@ require 'mnogootex/job/logger'
|
|
11
11
|
module Mnogootex
|
12
12
|
module Job
|
13
13
|
class Warden
|
14
|
-
|
14
|
+
LATEXMK_PATH = 'latexmk'
|
15
|
+
|
16
|
+
def initialize(source:, configuration:, flags:)
|
15
17
|
@source = source
|
16
18
|
@configuration = configuration
|
19
|
+
@flags = flags
|
17
20
|
|
18
21
|
@processor = nil
|
19
22
|
@porters = []
|
@@ -44,7 +47,7 @@ module Mnogootex
|
|
44
47
|
|
45
48
|
def exec_porters
|
46
49
|
@porters.each do |porter|
|
47
|
-
porter.clobber
|
50
|
+
# porter.clobber
|
48
51
|
porter.provide
|
49
52
|
transformer(porter.hid, porter.target_path)
|
50
53
|
end
|
@@ -54,7 +57,7 @@ module Mnogootex
|
|
54
57
|
@runners = @porters.map do |porter|
|
55
58
|
Mnogootex::Job::Runner.new(
|
56
59
|
cmd: commandline(porter.target_path),
|
57
|
-
chdir: porter.target_dir
|
60
|
+
chdir: porter.target_dir,
|
58
61
|
)
|
59
62
|
end
|
60
63
|
end
|
@@ -65,7 +68,7 @@ module Mnogootex
|
|
65
68
|
levels: Mnogootex::Log::DEFAULT_LEVELS,
|
66
69
|
min_level: :info,
|
67
70
|
colorize: true,
|
68
|
-
indent_width: 4
|
71
|
+
indent_width: 4,
|
69
72
|
)
|
70
73
|
end
|
71
74
|
|
@@ -74,14 +77,15 @@ module Mnogootex
|
|
74
77
|
spinner: @configuration['spinner'],
|
75
78
|
processor: @processor.method(:run),
|
76
79
|
runners: @runners,
|
77
|
-
porters: @porters
|
80
|
+
porters: @porters,
|
78
81
|
)
|
79
82
|
end
|
80
83
|
|
81
84
|
# TODO: generalize, integrate with Runner
|
82
85
|
def commandline(target_pathname)
|
83
86
|
[
|
84
|
-
|
87
|
+
LATEXMK_PATH,
|
88
|
+
*@flags,
|
85
89
|
target_pathname.basename.to_s
|
86
90
|
]
|
87
91
|
end
|
@@ -91,7 +95,7 @@ module Mnogootex
|
|
91
95
|
old_code = target_pathname.read
|
92
96
|
new_code = old_code.sub(
|
93
97
|
/\\documentclass(\[.*?\])?{.*?}/,
|
94
|
-
"\\documentclass{#{new_class_name}}"
|
98
|
+
"\\documentclass{#{new_class_name}}",
|
95
99
|
)
|
96
100
|
target_pathname.write(new_code)
|
97
101
|
end
|
data/lib/mnogootex/version.rb
CHANGED
@@ -76,7 +76,7 @@ describe Mnogootex::Job::Porter do
|
|
76
76
|
before do
|
77
77
|
test_dir.join('A', 'B').mkpath
|
78
78
|
test_dir.join('A', 'main.file').write('')
|
79
|
-
test_dir.join('A', '.
|
79
|
+
test_dir.join('A', '.mnogootexrc').write('')
|
80
80
|
test_dir.join('A', '.dotfile').write('')
|
81
81
|
test_dir.join('A', 'B', 'ancillary.file').write('')
|
82
82
|
end
|
@@ -89,9 +89,9 @@ describe Mnogootex::Job::Porter do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'ignores configuration file' do
|
92
|
-
test_dir.join('A', '.
|
92
|
+
test_dir.join('A', '.mnogootexrc').unlink
|
93
93
|
subject.provide
|
94
|
-
expect(subject.target_dir.join('.
|
94
|
+
expect(subject.target_dir.join('.mnogootexrc')).to_not exist
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'creates link to source' do
|
@@ -108,7 +108,7 @@ describe Mnogootex::Job::Porter do
|
|
108
108
|
it 'copies all source files' do
|
109
109
|
subject.provide
|
110
110
|
subject.target_dir.join('.mnogootex.src').unlink
|
111
|
-
source_path.dirname.join('.
|
111
|
+
source_path.dirname.join('.mnogootexrc').unlink
|
112
112
|
# NOTE: unlinking so comparison is easier to write
|
113
113
|
expect(relative_subtree(source_path.dirname)).
|
114
114
|
to eq(relative_subtree(subject.target_dir))
|
@@ -172,7 +172,7 @@ describe Mnogootex::Log::Processor do
|
|
172
172
|
|
173
173
|
expect(my_processor.run(log.lines)).to eq(
|
174
174
|
[" \e[0;33;49mHey, I'm warning you, dude. Stuff is gonna get bad.\e[0m\n",
|
175
|
-
" \e[0;31;49mI warned you, dude. Here's an ERROR. :(\e[0m\n"]
|
175
|
+
" \e[0;31;49mI warned you, dude. Here's an ERROR. :(\e[0m\n"],
|
176
176
|
)
|
177
177
|
end
|
178
178
|
|
@@ -185,7 +185,7 @@ describe Mnogootex::Log::Processor do
|
|
185
185
|
|
186
186
|
expect(my_processor.run(log.lines)).to eq(
|
187
187
|
[" Hey, I'm warning you, dude. Stuff is gonna get bad.\n",
|
188
|
-
" I warned you, dude. Here's an ERROR. :(\n"]
|
188
|
+
" I warned you, dude. Here's an ERROR. :(\n"],
|
189
189
|
)
|
190
190
|
end
|
191
191
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mnogootex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paolo Brasolin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -175,22 +175,26 @@ executables:
|
|
175
175
|
extensions: []
|
176
176
|
extra_rdoc_files: []
|
177
177
|
files:
|
178
|
+
- ".github/actions/setup-ruby/action.yml"
|
178
179
|
- ".github/workflows/main.yml"
|
179
180
|
- ".gitignore"
|
180
181
|
- ".rspec"
|
181
182
|
- ".rubocop.yml"
|
183
|
+
- CHANGELOG.md
|
182
184
|
- CODE_OF_CONDUCT.md
|
183
185
|
- Gemfile
|
184
186
|
- Guardfile
|
185
187
|
- LICENSE.txt
|
186
188
|
- README.md
|
187
189
|
- Rakefile
|
190
|
+
- demo/.mnogootexrc
|
191
|
+
- demo/demo.asciicast
|
192
|
+
- demo/demo.gif
|
193
|
+
- demo/main.tex
|
188
194
|
- exe/mnogootex
|
189
195
|
- lib/mnogootex.rb
|
190
196
|
- lib/mnogootex/cfg.rb
|
191
197
|
- lib/mnogootex/cli.rb
|
192
|
-
- lib/mnogootex/core_ext.rb
|
193
|
-
- lib/mnogootex/defaults.yml
|
194
198
|
- lib/mnogootex/job/logger.rb
|
195
199
|
- lib/mnogootex/job/porter.rb
|
196
200
|
- lib/mnogootex/job/runner.rb
|
@@ -202,7 +206,6 @@ files:
|
|
202
206
|
- lib/mnogootex/log/matcher.rb
|
203
207
|
- lib/mnogootex/log/matchers.yml
|
204
208
|
- lib/mnogootex/log/processor.rb
|
205
|
-
- lib/mnogootex/mnogoo.sh
|
206
209
|
- lib/mnogootex/utils.rb
|
207
210
|
- lib/mnogootex/version.rb
|
208
211
|
- mnogootex.gemspec
|
@@ -212,7 +215,6 @@ files:
|
|
212
215
|
- spec/mnogootex/log/processor_spec.rb
|
213
216
|
- spec/mnogootex/utils_spec.rb
|
214
217
|
- spec/spec_helper.rb
|
215
|
-
- tty.gif
|
216
218
|
homepage: https://github.com/tetrapharmakon/mnogootex
|
217
219
|
licenses:
|
218
220
|
- MIT
|
data/lib/mnogootex/core_ext.rb
DELETED
data/lib/mnogootex/defaults.yml
DELETED
data/lib/mnogootex/mnogoo.sh
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# Usage: source this in your bash profile as
|
2
|
-
# [ -s "$(mnogootex mnogoo)" ] && . "$(mnogootex mnogoo)"
|
3
|
-
|
4
|
-
mnogoo () {
|
5
|
-
if [ "$1" = cd ]; then
|
6
|
-
MN_PATH="$(IS_MNOGOO=true mnogootex dir "${@:2}")" || return
|
7
|
-
cd "$MN_PATH" || exit
|
8
|
-
elif [ "$1" = open ]; then
|
9
|
-
MN_PATH="$(IS_MNOGOO=true mnogootex pdf "${@:2}")" || return
|
10
|
-
if command -v open >/dev/null 2>&1; then
|
11
|
-
printf '%s\n' "$MN_PATH" | while read -r line; do open "$line"; done
|
12
|
-
elif command -v xdg-open >/dev/null 2>&1; then
|
13
|
-
printf '%s\n' "$MN_PATH" | while read -r line; do xdg-open "$line"; done
|
14
|
-
else
|
15
|
-
echo "No known file opener (open, xdg-open) found on your system."
|
16
|
-
echo "Please do chime in with suggestions: <paolo.brasolin@gmail.com>"
|
17
|
-
fi
|
18
|
-
else
|
19
|
-
IS_MNOGOO=true mnogootex "$@"
|
20
|
-
fi
|
21
|
-
}
|
data/tty.gif
DELETED
Binary file
|