mnogootex 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![A user types `mnogootex build main.tex` in the console. Some spinners indicating progress appear. Then the outcome for each class is presented. Failing ones include abridged and color coded logs, to pinpoint the errors.](demo/demo.gif?raw=true "TTY demo GIF")
|
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
|