texico 0.2.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 +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +46 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/texico +21 -0
- data/lib/texico.rb +19 -0
- data/lib/texico/cli.rb +5 -0
- data/lib/texico/cli/arg_parser.rb +63 -0
- data/lib/texico/cli/command.rb +11 -0
- data/lib/texico/cli/command/base.rb +58 -0
- data/lib/texico/cli/command/build.rb +41 -0
- data/lib/texico/cli/command/clean.rb +34 -0
- data/lib/texico/cli/command/config.rb +52 -0
- data/lib/texico/cli/command/init.rb +110 -0
- data/lib/texico/cli/command/release.rb +56 -0
- data/lib/texico/compiler.rb +60 -0
- data/lib/texico/config_file.rb +73 -0
- data/lib/texico/git.rb +27 -0
- data/lib/texico/template.rb +91 -0
- data/lib/texico/template/file.rb +106 -0
- data/lib/texico/template/file_status.rb +32 -0
- data/lib/texico/version.rb +3 -0
- data/templates/basic/.gitignore.erb +2 -0
- data/templates/basic/assets/test.txt +0 -0
- data/templates/basic/main.tex.erb +93 -0
- data/texico.gemspec +31 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 88fb2853d7789e04ac86329f0cdbd5e9f140a66e69ee24a707af14541e19e0b1
|
4
|
+
data.tar.gz: f8738047d2a26f108a1353e7803d9eed2c6e9a796a7d76b7d61ce2e6ea29906e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bcbdbcacd5bb859a342e4e96839851b9ae7a785d26967ab263026f4a9da7654308e828d5db9746b06c553adb440763f2fb937c82e21b5c4e79efaf2b1e43f0e2
|
7
|
+
data.tar.gz: 60f1c157554d8ffaf59b74c95fa3bc106b4e22dd323b395433d8c1e6b64f204473f80b3b464cd4ef5e2c228baea9ddbaf32da2d8dd52a3fa7f90ded5778b6615
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Sebastian Lindberg
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Texico
|
2
|
+
|
3
|
+
Texico is created to suit my Latex workflow. It can be used to
|
4
|
+
|
5
|
+
- setup new projects,
|
6
|
+
- build existing projects and
|
7
|
+
- tag versions for release.
|
8
|
+
|
9
|
+
More functionality is planned.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Building projects requires `latexmk`. You can install it by running
|
14
|
+
|
15
|
+
$ tlmgr install latexmk
|
16
|
+
|
17
|
+
Then install Texico with
|
18
|
+
|
19
|
+
$ gem install texico
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To setup a new project in the current directory, run
|
24
|
+
|
25
|
+
$ texico init
|
26
|
+
|
27
|
+
You will be guided through the setup process. When it completes you will be able to build the project using
|
28
|
+
|
29
|
+
$ texico
|
30
|
+
|
31
|
+
### Global Config
|
32
|
+
|
33
|
+
I find it useful to store my name and email address in the global config. You can either create a `.texico` file in your home directory and add the relevant fields, or run
|
34
|
+
|
35
|
+
$ texico config --global author='Your Name' email=name@example.com
|
36
|
+
|
37
|
+
## Development
|
38
|
+
|
39
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
40
|
+
|
41
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
42
|
+
|
43
|
+
## License
|
44
|
+
|
45
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
46
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "texico"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/exe/texico
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#require 'texico'
|
4
|
+
# require 'fileutils'
|
5
|
+
# require 'slop'
|
6
|
+
# require 'pastel'
|
7
|
+
# require 'tty-prompt'
|
8
|
+
|
9
|
+
require 'texico'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
# Notes:
|
14
|
+
# - Use 🌮 somewhere/everywhere
|
15
|
+
#
|
16
|
+
|
17
|
+
parser = Texico::CLI::ArgParser.new
|
18
|
+
command = parser.parse
|
19
|
+
|
20
|
+
command.run
|
21
|
+
#puts ""
|
data/lib/texico.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'texico/version'
|
2
|
+
require 'texico/cli'
|
3
|
+
require 'texico/template/file'
|
4
|
+
require 'texico/template/file_status'
|
5
|
+
require 'texico/template'
|
6
|
+
require 'texico/compiler'
|
7
|
+
require 'texico/config_file'
|
8
|
+
require 'texico/git'
|
9
|
+
require 'texico/cli/command/base'
|
10
|
+
require 'texico/cli/command/init'
|
11
|
+
require 'texico/cli/command/build'
|
12
|
+
require 'texico/cli/command/release'
|
13
|
+
require 'texico/cli/command/config'
|
14
|
+
require 'texico/cli/command/clean'
|
15
|
+
require 'texico/cli/command'
|
16
|
+
require 'texico/cli/arg_parser'
|
17
|
+
|
18
|
+
module Texico
|
19
|
+
end
|
data/lib/texico/cli.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'slop'
|
2
|
+
require 'tty-prompt'
|
3
|
+
|
4
|
+
module Texico
|
5
|
+
module CLI
|
6
|
+
class ArgParser
|
7
|
+
# Returns a hash with the options
|
8
|
+
#
|
9
|
+
# The method may call Kernel.exit
|
10
|
+
def parse(items = ARGV, prompt: TTY::Prompt.new)
|
11
|
+
title = prompt.decorate('texico', :yellow)
|
12
|
+
opts =
|
13
|
+
Slop.parse(items) do |o|
|
14
|
+
o.banner = "#{title} [options] ..."
|
15
|
+
|
16
|
+
o.bool '-v', '--verbose', 'enable verbose mode'
|
17
|
+
o.bool '-q', '--quiet', 'suppress output (quiet mode)'
|
18
|
+
o.bool '-h', '--help', 'Display this help'
|
19
|
+
o.bool '-f', '--force', "Force #{title} to act"
|
20
|
+
o.bool '-d', '--dry-run', 'Only show what files would be copied'
|
21
|
+
|
22
|
+
o.string '-c', '--config', 'Config file to use',
|
23
|
+
default: ConfigFile::DEFAULT_NAME
|
24
|
+
|
25
|
+
o.on '--version', 'print the version' do
|
26
|
+
puts VERSION
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
o.separator "\n#{title} [options] init [directory]"
|
31
|
+
o.separator " Initializes a new #{ICON} project in the " \
|
32
|
+
"current directory."
|
33
|
+
|
34
|
+
o.bool '--no-git', 'Do not initialize a new git repository'
|
35
|
+
|
36
|
+
o.separator "\n#{title} [options] config [--global] KEY=VALUE"
|
37
|
+
o.separator " Change configuration options."
|
38
|
+
o.bool '-g', '--global', 'edit the global configuration'
|
39
|
+
|
40
|
+
o.separator "\n#{title} [options] clean"
|
41
|
+
o.separator " Remove all build files"
|
42
|
+
|
43
|
+
o.separator "\n#{title} [options] release TAG_LABEL"
|
44
|
+
o.separator " Build and tag the project"
|
45
|
+
end
|
46
|
+
|
47
|
+
if opts[:help]
|
48
|
+
puts opts
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
command = opts.arguments[0]
|
53
|
+
|
54
|
+
Command.match command,
|
55
|
+
prompt,
|
56
|
+
{ cmd: command,
|
57
|
+
args: opts.arguments[1..-1],
|
58
|
+
title: title,
|
59
|
+
**opts.to_hash }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Texico
|
2
|
+
module CLI
|
3
|
+
module Command
|
4
|
+
class Base
|
5
|
+
attr_reader :prompt, :opts
|
6
|
+
|
7
|
+
def initialize(prompt, opts)
|
8
|
+
@prompt = prompt
|
9
|
+
@opts = opts
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
prompt.error "I don't know what you mean with '#{opts[:cmd]}'"
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_config(full = true)
|
17
|
+
ConfigFile.load(opts, full).tap do |config|
|
18
|
+
unless config
|
19
|
+
prompt.say 'I Couldn\'t find a valid config file. Run ' + \
|
20
|
+
prompt.decorate('texico init', :bold, :yellow) + \
|
21
|
+
' to setup a new project'
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def match?(command)
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def priority
|
35
|
+
0
|
36
|
+
end
|
37
|
+
|
38
|
+
def inherited(klass)
|
39
|
+
(@commands ||= []) << { klass: klass, prio: klass.priority }
|
40
|
+
end
|
41
|
+
|
42
|
+
def select(command)
|
43
|
+
@commands&.sort_by { |e| -e[:prio] }
|
44
|
+
&.map! { |e| e[:klass] }
|
45
|
+
&.each { |k| sk = k.select command; return sk if sk }
|
46
|
+
|
47
|
+
match?(command) && self
|
48
|
+
end
|
49
|
+
|
50
|
+
def match(command, *args)
|
51
|
+
klass = select(command)
|
52
|
+
klass.new(*args) if klass
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Texico
|
2
|
+
module CLI
|
3
|
+
module Command
|
4
|
+
class Build < Base
|
5
|
+
SHADOW_BUILD_DIR = '.build'.freeze
|
6
|
+
|
7
|
+
def run
|
8
|
+
config = load_config
|
9
|
+
|
10
|
+
prompt.say "#{ICON} Building project", color: :bold
|
11
|
+
|
12
|
+
build config
|
13
|
+
end
|
14
|
+
|
15
|
+
def build(config)
|
16
|
+
compiler = Compiler.new output_directory: SHADOW_BUILD_DIR
|
17
|
+
build_result = compiler.compile config[:main_file]
|
18
|
+
|
19
|
+
return false unless build_result
|
20
|
+
copy_build build_result[:file], config
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def copy_build(build_file, config)
|
27
|
+
dest = File.expand_path(config[:name] + '.pdf', config[:build])
|
28
|
+
|
29
|
+
FileUtils.mkdir config[:build] unless File.exist? config[:build]
|
30
|
+
FileUtils.mv build_file, dest
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def match?(command)
|
35
|
+
command == 'build' || command.nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Texico
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class Clean < Base
|
7
|
+
def run
|
8
|
+
config = load_config
|
9
|
+
build_dir = config[:build]
|
10
|
+
|
11
|
+
if remove(build_dir) || remove(Build::SHADOW_BUILD_DIR)
|
12
|
+
prompt.say "#{ICON} Removing old build files", color: :bold
|
13
|
+
else
|
14
|
+
prompt.say "#{ICON} Everything is already clean", color: :bold
|
15
|
+
return
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def remove(dir)
|
22
|
+
return false unless File.exist? dir
|
23
|
+
FileUtils.rm_r dir unless opts[:dry_run]
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def match?(command)
|
28
|
+
command == 'clean'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'tty-table'
|
2
|
+
|
3
|
+
module Texico
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class Config < Base
|
7
|
+
def run
|
8
|
+
config =
|
9
|
+
if opts[:global]
|
10
|
+
ConfigFile.global
|
11
|
+
else
|
12
|
+
load_config false
|
13
|
+
end.to_hash
|
14
|
+
|
15
|
+
did_change = false
|
16
|
+
opts[:args].each do |key_value|
|
17
|
+
key, value = key_value.split '='
|
18
|
+
key = key.to_sym
|
19
|
+
did_change = did_change || config[key] != value
|
20
|
+
config[key] = value
|
21
|
+
end
|
22
|
+
|
23
|
+
if did_change
|
24
|
+
prompt.say "#{ICON} Writing new configuration\n", color: :bold
|
25
|
+
else
|
26
|
+
prompt.say "#{ICON} Current configuration\n", color: :bold
|
27
|
+
end
|
28
|
+
|
29
|
+
table = TTY::Table.new \
|
30
|
+
header: %w(Option Value).map { |v| prompt.decorate v, :bold },
|
31
|
+
rows: config.to_a
|
32
|
+
|
33
|
+
prompt.say table.render(:basic)
|
34
|
+
|
35
|
+
return unless did_change
|
36
|
+
|
37
|
+
if opts[:global]
|
38
|
+
ConfigFile.store(config, opts, ConfigFile::GLOBAL_CONFIG_PATH)
|
39
|
+
else
|
40
|
+
ConfigFile.store(config, opts)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
def match?(command)
|
46
|
+
command == 'config'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'tty-tree'
|
2
|
+
|
3
|
+
module Texico
|
4
|
+
module CLI
|
5
|
+
module Command
|
6
|
+
class Init < Base
|
7
|
+
def run
|
8
|
+
# Show welcome text
|
9
|
+
welcome
|
10
|
+
# As for configuration options for this session
|
11
|
+
config = ask_config
|
12
|
+
# Indicate that the config was accepted
|
13
|
+
prompt.say "#{ICON} Creating new project\n", color: :bold
|
14
|
+
# Copy the template project
|
15
|
+
copy_template config
|
16
|
+
# Save the other config options to file
|
17
|
+
ConfigFile.store config, target, opts
|
18
|
+
|
19
|
+
Git.init(target, true) unless opts[:no_git]
|
20
|
+
|
21
|
+
# We are done
|
22
|
+
prompt.say "#{ICON} Done!", color: :bold
|
23
|
+
rescue TTY::Reader::InputInterrupt
|
24
|
+
prompt.error 'Aborting'
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def target
|
31
|
+
File.expand_path('', opts[:args][0] || '.')
|
32
|
+
end
|
33
|
+
|
34
|
+
def welcome
|
35
|
+
if ConfigFile.exist?(opts)
|
36
|
+
if opts[:force]
|
37
|
+
prompt.warn "#{ICON} Reinitializeing existing project."
|
38
|
+
else
|
39
|
+
prompt.say "#{ICON} Hey! This project has already been setup " \
|
40
|
+
"with #{opts[:title]}!", color: :bold
|
41
|
+
prompt.say ' Use -f to force me to reinitialize it.'
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
else
|
45
|
+
prompt.say "#{ICON} I just need a few details", color: :bold
|
46
|
+
end
|
47
|
+
prompt.say "\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
def ask_config
|
51
|
+
folder_name = File.basename target
|
52
|
+
template_choices =
|
53
|
+
Hash[Template.list.map { |p| [File.basename(p).capitalize, p] }]
|
54
|
+
|
55
|
+
answers =
|
56
|
+
prompt.collect do
|
57
|
+
key(:name).ask( 'What should be the name of the output PDF?',
|
58
|
+
default: folder_name.downcase.gsub(' ', '-'))
|
59
|
+
key(:title).ask( 'What is the title of your document?',
|
60
|
+
default: folder_name.gsub('_', ' ').capitalize)
|
61
|
+
key(:author).ask('What is your name?',
|
62
|
+
default: ConfigFile.default[:author])
|
63
|
+
key(:email).ask( 'What is your email address?',
|
64
|
+
default: ConfigFile.default[:email])
|
65
|
+
key(:template).select("Select a template", template_choices)
|
66
|
+
end
|
67
|
+
|
68
|
+
ConfigFile.new answers, ConfigFile::DEFAULT_CONFIG
|
69
|
+
end
|
70
|
+
|
71
|
+
def copy_template(config)
|
72
|
+
params = config.to_hash
|
73
|
+
template_path = params.delete :template
|
74
|
+
template = Template.load template_path
|
75
|
+
|
76
|
+
template_structure =
|
77
|
+
template.copy(target, params, opts) do |status|
|
78
|
+
file = status.file.basename
|
79
|
+
case status.status
|
80
|
+
when :successful then prompt.decorate(file, :green)
|
81
|
+
when :target_exist then prompt.decorate(file, :red)
|
82
|
+
when :replaced_target then prompt.decorate(file, :yellow)
|
83
|
+
when :template_error then prompt.decorate(file, :blue)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
tree = TTY::Tree.new template_structure
|
88
|
+
prompt.say tree.render + "\n"
|
89
|
+
file_copy_legend
|
90
|
+
end
|
91
|
+
|
92
|
+
def file_copy_legend
|
93
|
+
prompt.say \
|
94
|
+
format("%s Did copy %s Replaced existing %s File existed %s Template Error\n\n",
|
95
|
+
prompt.decorate("∎", :green),
|
96
|
+
prompt.decorate("∎", :yellow),
|
97
|
+
prompt.decorate("∎", :red),
|
98
|
+
prompt.decorate("∎", :blue)
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
class << self
|
103
|
+
def match?(command)
|
104
|
+
command == 'init'
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Texico
|
2
|
+
module CLI
|
3
|
+
module Command
|
4
|
+
class Release < Build
|
5
|
+
GIT_DIR = File.expand_path('.git').freeze
|
6
|
+
|
7
|
+
def run
|
8
|
+
unless File.exist? GIT_DIR
|
9
|
+
prompt.error "#{ICON} You don't seem to be using git."
|
10
|
+
exit
|
11
|
+
end
|
12
|
+
|
13
|
+
unless label
|
14
|
+
tags = Git.list_tags('.')
|
15
|
+
num_tags = tags.length
|
16
|
+
count = case num_tags
|
17
|
+
when 0 then 'no releases'
|
18
|
+
when 1 then 'one release'
|
19
|
+
else "#{num_tags} releases"
|
20
|
+
end
|
21
|
+
prompt.say "#{ICON} This project currently has #{count}\n",
|
22
|
+
color: :bold
|
23
|
+
|
24
|
+
if num_tags > 0
|
25
|
+
prompt.say tags.map { |t| "* #{t}" }.join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
success = super # Build the project
|
32
|
+
|
33
|
+
unless success
|
34
|
+
prompt.error "#{ICON} I will only tag the release when it builds " \
|
35
|
+
"without errors."
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
Git.tag '.', label, "Releasing #{label}"
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def label
|
45
|
+
opts[:args][0]
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
def match?(command)
|
50
|
+
command == 'release'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Texico
|
4
|
+
class Compiler
|
5
|
+
COMMAND = 'latexmk'
|
6
|
+
|
7
|
+
LATEXMK_OPTIONS = {
|
8
|
+
pdf: true,
|
9
|
+
output_directory: '.build',
|
10
|
+
latexoption: {
|
11
|
+
interaction: 'nonstopmode',
|
12
|
+
file_line_error: true
|
13
|
+
}.freeze
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
OUTPUT_PATTERN =
|
17
|
+
%r{\AOutput written on ([^\s]+) \((\d+) page, (\d+) bytes\)}
|
18
|
+
|
19
|
+
def initialize(**options)
|
20
|
+
@args = LATEXMK_OPTIONS
|
21
|
+
.merge(options)
|
22
|
+
.map { |k, v| transform_option(k, v) }.join ' '
|
23
|
+
end
|
24
|
+
|
25
|
+
def compile(file)
|
26
|
+
# TODO: This looks very hacky...
|
27
|
+
build_result = false
|
28
|
+
Open3.popen2("#{COMMAND} #@args #{file}") do |_, stdout, _|
|
29
|
+
stdout.each_line do |line|
|
30
|
+
if m = line.match(OUTPUT_PATTERN)
|
31
|
+
build_result = { file: m[1], pages: m[2], bytes: m[3] }
|
32
|
+
break
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
build_result
|
37
|
+
end
|
38
|
+
|
39
|
+
# Takes a symbol (or string) one the form :some_option and transforms it
|
40
|
+
# into the string "-some-option". If the value is
|
41
|
+
# a) false, the output string will be empty.
|
42
|
+
# b) true, only the key will be returned.
|
43
|
+
# c) some other value, an array with the transformed key and the value is
|
44
|
+
# returned.
|
45
|
+
private def transform_option(key, value)
|
46
|
+
# Skip the option if the value is nil or false
|
47
|
+
return '' unless value
|
48
|
+
# Transform the key into a format that is accepted by pdflatex
|
49
|
+
option = '-' + key.to_s.gsub('_', '-')
|
50
|
+
|
51
|
+
case value
|
52
|
+
when TrueClass then return option
|
53
|
+
when Hash
|
54
|
+
value.map { |k, v| "#{option}=#{transform_option k, v }" }.join ' '
|
55
|
+
else
|
56
|
+
"#{option}=#{value}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Texico
|
5
|
+
class ConfigFile
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
DEFAULT_NAME = '.texico'.freeze
|
9
|
+
GLOBAL_CONFIG_PATH = File.expand_path(DEFAULT_NAME, ENV['HOME']).freeze
|
10
|
+
DEFAULT_CONFIG = {
|
11
|
+
name: 'main',
|
12
|
+
title: 'Title',
|
13
|
+
author: 'Author',
|
14
|
+
email: 'author@example.com',
|
15
|
+
build: 'build',
|
16
|
+
main_file: 'main.tex'
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
def_delegator :@config, :[]
|
20
|
+
def_delegator :@config, :to_a
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
@config.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def initialize(config, defaults = {})
|
29
|
+
@config = defaults.merge(config).freeze
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def exist?(opts)
|
34
|
+
File.exist? opts[:config]
|
35
|
+
end
|
36
|
+
|
37
|
+
def global
|
38
|
+
new read_global
|
39
|
+
end
|
40
|
+
|
41
|
+
def default
|
42
|
+
return @default if @default
|
43
|
+
@default = DEFAULT_CONFIG.merge read_global
|
44
|
+
end
|
45
|
+
|
46
|
+
def load(opts, full = true)
|
47
|
+
return false unless File.exist? opts[:config]
|
48
|
+
new read_local(opts[:config]), (full ? default : {})
|
49
|
+
end
|
50
|
+
|
51
|
+
def store(config, dest = '', opts = {})
|
52
|
+
return if opts[:dry_run]
|
53
|
+
dest_path = File.expand_path opts[:config], dest
|
54
|
+
File.open dest_path, 'wb' do |file|
|
55
|
+
file.write YAML.dump(config.to_hash)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def read_local(filename)
|
62
|
+
yaml = File.open(filename, 'rb') { |f| f.read }
|
63
|
+
YAML.load(yaml) || {}
|
64
|
+
rescue Errno::ENOENT
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
|
68
|
+
def read_global
|
69
|
+
@global_defaults ||= read_local GLOBAL_CONFIG_PATH
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/texico/git.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Texico
|
4
|
+
module Git
|
5
|
+
module_function
|
6
|
+
def init(target, initial_commit = false)
|
7
|
+
if initial_commit
|
8
|
+
system "git init '#{target}' && git -C '#{target}' add . " \
|
9
|
+
"&& git -C '#{target}' commit -m 'Initial commit'"
|
10
|
+
else
|
11
|
+
system "git init '#{target}'"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module_function
|
16
|
+
def tag(target, label, message)
|
17
|
+
system "git -C '#{target}' tag -a #{label} -m '#{message}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
module_function
|
21
|
+
def list_tags(target)
|
22
|
+
Open3.popen2 "git -C '#{target}' tag -l" do |_, stdout, _|
|
23
|
+
stdout.each_line.map { |line| line.chomp }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Texico
|
5
|
+
# Template
|
6
|
+
#
|
7
|
+
# Class for handling Texico templates. A template is really just a folder with
|
8
|
+
# some files in it. The template object handles moving those files, as well as
|
9
|
+
# rendering any .erb files.
|
10
|
+
class Template
|
11
|
+
BASE_PATH = ::File.expand_path('../../../templates', __FILE__)
|
12
|
+
|
13
|
+
attr_reader :name
|
14
|
+
|
15
|
+
# Tree
|
16
|
+
#
|
17
|
+
# Returns the template structure in a format compatible with tty-tree.
|
18
|
+
def tree
|
19
|
+
{ name => self.class.map_tree(@file_tree, &:to_s) }
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a report of what files where copied.
|
23
|
+
def copy(dest, params, opts, &block)
|
24
|
+
map_status = block_given? ? block : ->(status) { status.to_s }
|
25
|
+
status_tree =
|
26
|
+
self.class.map_tree(@file_tree) do |file|
|
27
|
+
map_status.call(file.copy(params, dest, opts))
|
28
|
+
end
|
29
|
+
{ name => status_tree }
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def initialize(name, file_tree)
|
35
|
+
@name = name.freeze
|
36
|
+
@file_tree = file_tree
|
37
|
+
|
38
|
+
freeze
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
# List
|
43
|
+
#
|
44
|
+
# List available templates
|
45
|
+
def list
|
46
|
+
Dir.glob "#{BASE_PATH}/*"
|
47
|
+
end
|
48
|
+
|
49
|
+
def exist?(_)
|
50
|
+
raise RuntimeError
|
51
|
+
#::File.exist? template
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_file_tree(root, current_dir = '')
|
55
|
+
base_path = ::File.expand_path current_dir, root
|
56
|
+
Dir.entries(base_path)
|
57
|
+
.reject { |entry| ['.', '..'].include? entry }
|
58
|
+
.map do |entry|
|
59
|
+
local_path = (current_dir + entry).freeze
|
60
|
+
full_path = ::File.expand_path local_path, root
|
61
|
+
|
62
|
+
if ::File.file?(full_path)
|
63
|
+
File.new local_path, root
|
64
|
+
else
|
65
|
+
{ entry.freeze => load_file_tree(root, local_path + '/') }.freeze
|
66
|
+
end
|
67
|
+
end.freeze
|
68
|
+
end
|
69
|
+
|
70
|
+
def map_tree(tree, root = '', &block)
|
71
|
+
tree.map do |node|
|
72
|
+
if node.is_a? Hash
|
73
|
+
dir = node.keys[0]
|
74
|
+
{ dir => map_tree(node[dir], "#{root}#{dir}/", &block) }
|
75
|
+
else
|
76
|
+
yield node
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def load(template)
|
82
|
+
file_tree = load_file_tree template
|
83
|
+
template_name = ::File.basename(template).capitalize
|
84
|
+
|
85
|
+
new template_name, file_tree
|
86
|
+
rescue Errno::ENOENT
|
87
|
+
false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Texico
|
4
|
+
class Template
|
5
|
+
# File
|
6
|
+
#
|
7
|
+
# The Template File object is an internal object used by the Template class
|
8
|
+
# to copy and render template files transparently. It should never be used
|
9
|
+
# directly.
|
10
|
+
class File
|
11
|
+
TEMPLATE_EXTNAME = '.erb'.freeze
|
12
|
+
|
13
|
+
def initialize(relative_path, base_path)
|
14
|
+
@relative_path = relative_path.freeze
|
15
|
+
@base_path = base_path.freeze
|
16
|
+
|
17
|
+
freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
# Basename
|
21
|
+
#
|
22
|
+
# Returns the name of the file. In case of template files the .erb
|
23
|
+
# extension is removed.
|
24
|
+
def basename
|
25
|
+
::File.basename @relative_path, TEMPLATE_EXTNAME
|
26
|
+
end
|
27
|
+
|
28
|
+
# Basename
|
29
|
+
#
|
30
|
+
# Returns the extension of the file. In case of template files the
|
31
|
+
# extension of the target file is returned.
|
32
|
+
def extname
|
33
|
+
::File.extname basename
|
34
|
+
end
|
35
|
+
|
36
|
+
# Dirname
|
37
|
+
#
|
38
|
+
# Returns the local directory path of the file.
|
39
|
+
def dirname
|
40
|
+
::File.dirname @relative_path
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the filename
|
44
|
+
def to_s
|
45
|
+
basename
|
46
|
+
end
|
47
|
+
|
48
|
+
# Copy
|
49
|
+
#
|
50
|
+
# Copy the file with its relative path intact to the dest_base_path root.
|
51
|
+
#
|
52
|
+
# Returns a FileStatus object.
|
53
|
+
def copy(params, dest_base_path = '.', opts = {})
|
54
|
+
dest_dir = ::File.expand_path dirname, dest_base_path
|
55
|
+
dest_path = ::File.expand_path basename, dest_dir
|
56
|
+
force = false
|
57
|
+
|
58
|
+
if ::File.exist? dest_path
|
59
|
+
return FileStatus.new(self, :target_exist) unless opts[:force]
|
60
|
+
force = true
|
61
|
+
else
|
62
|
+
FileUtils.mkdir_p dest_dir unless opts[:dry_run]
|
63
|
+
end
|
64
|
+
|
65
|
+
if template?
|
66
|
+
err = copy_template src_path, dest_path, params,
|
67
|
+
noop: opts[:dry_run], verbose: opts[:verbose]
|
68
|
+
return err if err
|
69
|
+
else
|
70
|
+
FileUtils.cp src_path, dest_path,
|
71
|
+
noop: opts[:dry_run], verbose: opts[:verbose]
|
72
|
+
end
|
73
|
+
|
74
|
+
FileStatus.new(self, force ? :replaced_target : :successful)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def template?
|
80
|
+
::File.extname(@relative_path) == TEMPLATE_EXTNAME
|
81
|
+
end
|
82
|
+
|
83
|
+
def src_path
|
84
|
+
::File.expand_path @relative_path, @base_path
|
85
|
+
end
|
86
|
+
|
87
|
+
# Copy Template
|
88
|
+
#
|
89
|
+
# Returns a status object unless the operation was successful, in which
|
90
|
+
# case nil is returned.
|
91
|
+
def copy_template(src, dest, params, noop: nil, verbose: nil)
|
92
|
+
file_body =
|
93
|
+
::File.open src, 'rb' do |file|
|
94
|
+
ERB.new(file.read, 0).result_with_hash params
|
95
|
+
end
|
96
|
+
|
97
|
+
return if noop
|
98
|
+
|
99
|
+
::File.open(dest, 'wb') { |file| file.write file_body }
|
100
|
+
nil
|
101
|
+
rescue NameError => e
|
102
|
+
FileStatus.new self, e
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Texico
|
2
|
+
class Template
|
3
|
+
# FileStatus
|
4
|
+
#
|
5
|
+
# The FileStatus object represents the result of a copy command on a
|
6
|
+
# template file. This class should never be used directly.
|
7
|
+
class FileStatus
|
8
|
+
STATUS = %i[successful target_exist replaced_target].freeze
|
9
|
+
|
10
|
+
attr_reader :file
|
11
|
+
|
12
|
+
def initialize(file, status = STATUS[0])
|
13
|
+
unless STATUS.include?(status) || status.is_a?(Exception)
|
14
|
+
raise ArgumentError, 'Unknown status'
|
15
|
+
end
|
16
|
+
|
17
|
+
@status = status
|
18
|
+
@file = file
|
19
|
+
|
20
|
+
freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"#{file.basename} [#{status}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
def status
|
28
|
+
@status.is_a?(Exception) ? :template_error : @status
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
File without changes
|
@@ -0,0 +1,93 @@
|
|
1
|
+
\documentclass[a4paper,11pt]{article}
|
2
|
+
|
3
|
+
\usepackage[utf8]{inputenc}
|
4
|
+
\usepackage[english]{babel}
|
5
|
+
\usepackage{amsmath,amssymb,amsthm,amsfonts}
|
6
|
+
\usepackage[demo]{graphicx} % REMOVE "demo" to include figures!
|
7
|
+
\usepackage{hyperref}
|
8
|
+
\usepackage{cleveref}
|
9
|
+
\usepackage{autonum}
|
10
|
+
\usepackage[inline]{enumitem}
|
11
|
+
|
12
|
+
%
|
13
|
+
% ---- Global Document Properties ----
|
14
|
+
%
|
15
|
+
|
16
|
+
\title{<%= title %>}
|
17
|
+
\date{\today}
|
18
|
+
\author{
|
19
|
+
<%= author %>\\
|
20
|
+
<%= email %>
|
21
|
+
}
|
22
|
+
|
23
|
+
\topmargin=-0.45in
|
24
|
+
\evensidemargin=0in
|
25
|
+
\oddsidemargin=0in
|
26
|
+
\textwidth=6.3in
|
27
|
+
\textheight=9.6in
|
28
|
+
\headsep=0.25in
|
29
|
+
|
30
|
+
% Turn off numbering for sections
|
31
|
+
\setcounter{secnumdepth}{0}
|
32
|
+
|
33
|
+
\graphicspath{{./assets/}}
|
34
|
+
|
35
|
+
|
36
|
+
%
|
37
|
+
% ---- Enumeration Styles ----
|
38
|
+
%
|
39
|
+
|
40
|
+
% Set default style to a), b) ...
|
41
|
+
%\setlist[enumerate]{label=\alph*)}
|
42
|
+
% Use \begin{enumerate*} ... for inline lists
|
43
|
+
|
44
|
+
|
45
|
+
%
|
46
|
+
% ---- Custom Commands ----
|
47
|
+
%
|
48
|
+
|
49
|
+
% Usage: \image{file_name}{caption}
|
50
|
+
% \image[width=8cm]{file_name}{caption}
|
51
|
+
% Reference: \cref{fig:file_name}
|
52
|
+
\newcommand{\image}[3][width=1.0\columnwidth]{
|
53
|
+
\begin{figure}[h!]
|
54
|
+
\centering
|
55
|
+
\includegraphics[#1]{#2}
|
56
|
+
\caption{#3}
|
57
|
+
\label{fig:#2}
|
58
|
+
\end{figure}
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
%
|
63
|
+
% ---- Document ----
|
64
|
+
% Exported to build/<%= name %>.pdf
|
65
|
+
|
66
|
+
\begin{document}
|
67
|
+
\maketitle
|
68
|
+
|
69
|
+
\section{Introduction}
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
%
|
75
|
+
% ---- Bibliography ----
|
76
|
+
%
|
77
|
+
|
78
|
+
% Usage: \begin{thebibliography}{[max_number_citations]}
|
79
|
+
%
|
80
|
+
% Usage: \bibitem{author:year}
|
81
|
+
% Author, F., Authod, S.:
|
82
|
+
% Nonlinear oscillations and
|
83
|
+
% boundary-value problems for Hamiltonian systems.
|
84
|
+
% Arch. Rat. Mech. Anal. 78, 315--333 (1982)
|
85
|
+
% Cite: \cite{author:year}
|
86
|
+
|
87
|
+
% \begin{thebibliography}{5}
|
88
|
+
% \bibitem{gold:2003}
|
89
|
+
% Gold, E.
|
90
|
+
% TechRepublic Tutorial: How to diagnose a faulty power supply
|
91
|
+
% \url{https://tex.stackexchange.com/questions/3587/how-can-i-use-bibtex-to-cite-a-web-page#3608} (2003)
|
92
|
+
% \end{thebibliography}
|
93
|
+
\end{document}
|
data/texico.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'texico/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "texico"
|
8
|
+
spec.version = Texico::VERSION
|
9
|
+
spec.authors = ["Sebastian Lindberg"]
|
10
|
+
spec.email = ["seb.lindberg@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Command line utility for managing Latex projects."
|
13
|
+
spec.description = "Utility for handling project templates, build " \
|
14
|
+
"settings and project management"
|
15
|
+
spec.homepage = "https://github.com/seblindberg/texico"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "slop", "~> 4.6"
|
24
|
+
spec.add_dependency "tty-prompt", "~> 0.15"
|
25
|
+
spec.add_dependency "tty-tree", "~> 0.1"
|
26
|
+
spec.add_dependency "tty-table", "~> 0.10"
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: texico
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sebastian Lindberg
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: slop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tty-prompt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.15'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.15'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-tree
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tty-table
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.10'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.12'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.12'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5.0'
|
111
|
+
description: Utility for handling project templates, build settings and project management
|
112
|
+
email:
|
113
|
+
- seb.lindberg@gmail.com
|
114
|
+
executables:
|
115
|
+
- texico
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".travis.yml"
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- bin/console
|
126
|
+
- bin/setup
|
127
|
+
- exe/texico
|
128
|
+
- lib/texico.rb
|
129
|
+
- lib/texico/cli.rb
|
130
|
+
- lib/texico/cli/arg_parser.rb
|
131
|
+
- lib/texico/cli/command.rb
|
132
|
+
- lib/texico/cli/command/base.rb
|
133
|
+
- lib/texico/cli/command/build.rb
|
134
|
+
- lib/texico/cli/command/clean.rb
|
135
|
+
- lib/texico/cli/command/config.rb
|
136
|
+
- lib/texico/cli/command/init.rb
|
137
|
+
- lib/texico/cli/command/release.rb
|
138
|
+
- lib/texico/compiler.rb
|
139
|
+
- lib/texico/config_file.rb
|
140
|
+
- lib/texico/git.rb
|
141
|
+
- lib/texico/template.rb
|
142
|
+
- lib/texico/template/file.rb
|
143
|
+
- lib/texico/template/file_status.rb
|
144
|
+
- lib/texico/version.rb
|
145
|
+
- templates/basic/.gitignore.erb
|
146
|
+
- templates/basic/assets/test.txt
|
147
|
+
- templates/basic/main.tex.erb
|
148
|
+
- texico.gemspec
|
149
|
+
homepage: https://github.com/seblindberg/texico
|
150
|
+
licenses:
|
151
|
+
- MIT
|
152
|
+
metadata: {}
|
153
|
+
post_install_message:
|
154
|
+
rdoc_options: []
|
155
|
+
require_paths:
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubyforge_project:
|
169
|
+
rubygems_version: 2.7.3
|
170
|
+
signing_key:
|
171
|
+
specification_version: 4
|
172
|
+
summary: Command line utility for managing Latex projects.
|
173
|
+
test_files: []
|