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