summaryrefslogtreecommitdiff
path: root/support/lyluatex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-10-31 03:04:01 +0000
committerNorbert Preining <norbert@preining.info>2022-10-31 03:04:01 +0000
commitc7892fe1a11367872de6f3ee0fa074b39824e59c (patch)
tree4879018aece4cb9f7549756ccadbb1808296d19d /support/lyluatex
parentb2c88e6cbb5203ec5d33819454f1499cada7e336 (diff)
CTAN sync 202210310303
Diffstat (limited to 'support/lyluatex')
-rw-r--r--support/lyluatex/Contributors.md6
-rw-r--r--support/lyluatex/LICENSE2
-rw-r--r--support/lyluatex/README.md53
-rw-r--r--support/lyluatex/lyluatex-lib.lua163
-rw-r--r--support/lyluatex/lyluatex-options.lua266
-rw-r--r--support/lyluatex/lyluatex.lua275
-rw-r--r--support/lyluatex/lyluatex.pdfbin1664216 -> 2028732 bytes
-rw-r--r--support/lyluatex/lyluatex.sty27
-rw-r--r--support/lyluatex/lyluatex.tex301
-rw-r--r--support/lyluatex/lyluatexbase.cls6
-rw-r--r--support/lyluatex/lyluatexmanual.cls8
11 files changed, 431 insertions, 676 deletions
diff --git a/support/lyluatex/Contributors.md b/support/lyluatex/Contributors.md
index 574ecf10a5..39fe7cc9c0 100644
--- a/support/lyluatex/Contributors.md
+++ b/support/lyluatex/Contributors.md
@@ -2,6 +2,6 @@
Lyluatex is developped by:
-- [Fr. Jacques Peron](mailto:catacolp@hotmail.com);
-- Urs Liska;
-- Br. Samuel Springuel.
+- [Fr. Jacques Peron](mailto:cataclop@hotmail.com); [@jperon](https://github.com/jperon)
+- [Urs Liska](mailto:git@ursliska.de); [@uliska](https://github.com/uliska), [@openlilylib](https://github.com/openlilylib)
+- Br. Samuel Springuel; [@rpspringuel](https://github.com/rpspringuel)
diff --git a/support/lyluatex/LICENSE b/support/lyluatex/LICENSE
index 515e3806df..9193cccea3 100644
--- a/support/lyluatex/LICENSE
+++ b/support/lyluatex/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2015--2019 jperon and others
+Copyright (c) 2015--2022 jperon and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/support/lyluatex/README.md b/support/lyluatex/README.md
index 18475559cc..7aa096a18d 100644
--- a/support/lyluatex/README.md
+++ b/support/lyluatex/README.md
@@ -1,6 +1,4 @@
-Main author: [Fr. Jacques Peron](mailto:cataclop@hotmail.com)
-This material is subject to the MIT license.
-
+Main author: [Fr. Jacques Peron](mailto:cataclop@hotmail.com)\nThis material is subject to the MIT license.\n
# Lyluatex
## Usage
@@ -23,33 +21,37 @@ Thereafter, you can include a lilypond file with the command:
\lilypondfile[staffsize=17]{PATH/TO/THE/FILE}
```
-The argument `staffsize`, which is optional, changes the size of the score. You
-can change the size for all the subsequent scores in a document by placing the
-following command before your first include statement to be so affected:
+The argument `staffsize`, which is optional, changes the size of the score.
+You can change the size for all the subsequent scores in a document by
+placing the following command before your first include statement to be so
+affected:
```TeX
-\lysetoption{staffsize}{24}
+\setluaoption{ly}{staffsize}{24}
```
Next, you simply need to compile the document normally with the command
-`lualatex -shell-escape` :
+`lualatex -shell-escape`:
```bash
lualatex -shell-escape DOCUMENT.TEX
```
-Another "more secure" option is to add `lilypond` and `gs` to default allowed commands :
+Another "more secure" option is to add `lilypond` and `gs` to default
+allowed commands:
```bash
shell_escape_commands=$(kpsewhich -expand-var '$shell_escape_commands'),lilypond,gs lualatex DOCUMENT.TEX
```
On systems with low RAM, when working on big documents, you could encounter
-*buffer overflows* in `lilypond` calls. In that case, first compile with option
-`-draftmode`, then compile again without this option.
+*buffer overflows* in `lilypond` calls. In that case, first compile with
+luatex's command line option `--draftmode` to generate all LilyPond output
+snippets, then compile again without this option to generate the output PDF.
-You can also input music directly into your docoment with the `lilypond` environment.
-This is only recommended for relatively short snippets. For example:
+You can also input music directly into your document with the `lilypond`
+environment. This is only recommended for relatively short snippets. For
+example:
```TeX
\begin{lilypond}
@@ -57,7 +59,8 @@ This is only recommended for relatively short snippets. For example:
\end{lilypond}
```
-Finally, for truly short snippets, there is also the `\lily` command. Example:
+Finally, for truly short snippets, there is also the `\lily` command.
+Example:
```TeX
\lilypond[staffsize=12]{c' d' g'}
@@ -70,9 +73,9 @@ code with explicit `\score` blocks. Such code must be included with the
## Migration from `lilypond-book`
In order to facilitate the migration from `lilypond-book`, `\lilypondfile`,
-the environment `lilypond` and the command `\lilypond` should work nearly
-as with `lilypond-book` ; for even more identical behaviour, call `lyluatex`
-like follows:
+the environment `lilypond` and the command `\lilypond` should work nearly as
+with `lilypond-book`; for even more identical behaviour, call `lyluatex`
+as follows:
```TeX
\usepackage[program=/opt/lilypond-dev/lilypond]{lyluatex}
@@ -83,15 +86,15 @@ That way, documents typeset with `lilypond-book` can be adapted to use
# Credits
-Cf. [Contributors.md](Contributors.md)
+See [Contributors.md](Contributors.md).
# Contributing
-If you want improvements or encounter an error, do not hesitate to
-to report the [issue](https://github.com/jperon/lyluatex/issues).
-If you have programming skills, you may also propose your changes
-via a [pull request](https://github.com/jperon/lyluatex/pulls).
+If you want improvements or encounter an error, do not hesitate to to report
+the [issue](https://github.com/jperon/lyluatex/issues). If you have
+programming skills, you may also propose your changes via a [pull
+request](https://github.com/jperon/lyluatex/pulls).
-This extension is and will remain free; if you find it useful and
-wish to encourage its development by a
-[donation](https://www.paypal.me/abjperon), many thanks!
+This extension is and will remain free; if you find it useful and wish to
+encourage its development by a [donation](https://www.paypal.me/abjperon),
+many thanks!
diff --git a/support/lyluatex/lyluatex-lib.lua b/support/lyluatex/lyluatex-lib.lua
deleted file mode 100644
index ebe6745eb5..0000000000
--- a/support/lyluatex/lyluatex-lib.lua
+++ /dev/null
@@ -1,163 +0,0 @@
--- luacheck: ignore ly log self luatexbase internalversion font fonts tex token kpse status
-local err, warn, info, log = luatexbase.provides_module({
- name = "lyluatex-lib",
- version = '1.0f', --LYLUATEX_VERSION
- date = "2019/05/27", --LYLUATEX_DATE
- description = "Module lyluatex-lib.",
- author = "The Gregorio Project − (see Contributors.md)",
- copyright = "2015-2019 - jperon and others",
- license = "MIT",
-})
-
-local lib = {}
-lib.TEX_UNITS = {'bp', 'cc', 'cm', 'dd', 'in', 'mm', 'pc', 'pt', 'sp', 'em',
-'ex'}
-
--------------------------
--- General tool functions
-
-function lib.basename(str)
---[[
- Given the full path to a file, return only the file name (without path).
- If there is no slash, return the full name.
---]]
- return str:gsub(".*/(.*)", "%1") or str
-end
-
-
-function lib.contains(table_var, value)
---[[
- Returns the key if the given table contains the given value, or nil.
- A value of 'false' (string) is considered equal to false (Boolean).
---]]
- for k, v in pairs(table_var) do
- if v == value then return k
- elseif v == 'false' and value == false then return k
- end
- end
-end
-
-
-function lib.contains_key(table_var, key)
--- Returs true if the given key is present in the table, nil otherwise.
- for k in pairs(table_var) do
- if k == key then return true end
- end
-end
-
-
-function lib.convert_unit(value)
---[[
- Convert a LaTeX unit, if possible.
- TODO: Understand what this *really* does, what is accepted and returned.
---]]
- if not value then return 0
- elseif value == '' then return false
- elseif value:match('\\') then
- local n, u = value:match('^%d*%.?%d*'), value:match('%a+')
- if n == '' then n = 1 end
- return tonumber(n) * tex.dimen[u] / tex.sp("1pt")
- else return ('%f'):format(tonumber(value) or tex.sp(value) / tex.sp("1pt"))
- end
-end
-
-
-function lib.dirname(str)
---[[
- Given the full path to a file, return only the path (without file name),
- including the last slash. If there is no slash, return an empty string.
---]]
- return str:gsub("(.*/).*", "%1") or ''
-end
-
-
-local fontdata = fonts.hashes.identifiers
-function lib.fontinfo(id)
---[[
- Return a LuaTeX font object based on the given ID
---]]
- return fontdata[id] or font.fonts[id]
-end
-
-
-function lib.max(a, b)
- a, b = tonumber(a), tonumber(b)
- if a > b then return a else return b end
-end
-
-
-function lib.min(a, b)
- a, b = tonumber(a), tonumber(b)
- if a < b then return a else return b end
-end
-
-
-function lib.mkdirs(str)
- local path
- if str:sub(1, 1) == '/' then path = '' else path = '.' end
- for dir in str:gmatch('([^%/]+)') do
- path = path .. '/' .. dir
- lfs.mkdir(path)
- end
-end
-
-
-function lib.orderedpairs(t)
- local key
- local i = 0
- local orderedIndex = {}
- for k in pairs(t) do table.insert(orderedIndex, k) end
- table.sort(orderedIndex)
- return function ()
- i = i + 1
- key = orderedIndex[i]
- if key then return key, t[key] end
- end
-end
-
-
-function lib.readlinematching(s, f)
- if f then
- local result = ''
- while result and not result:find(s) do result = f:read() end
- f:close()
- return result
- end
-end
-
-
-function lib.splitext(str, ext)
---[[
- If 'ext' is supplied return str stripped of the given extension,
- otherwise return the base and extension (if any)
---]]
- return ext and (str:match('(.*)%.'..ext..'$') or str)
- or (str:match('(.*)%.(%w*)$') or str)
-end
-
-
-------------------------------------
--- Engine, version, TeX distribution
-
-local tex_engine = {}
-setmetatable(tex_engine, tex_engine)
-
-function tex_engine:__call()
---[[
- Defines the properties extracted from the first line of jobname.log.
---]]
- local f = io.open(tex.jobname..'.log')
- if not f then return end
- self.engine, self.engine_version, self.dist, self.dist_version, self.format, self.format_version =
- f:read():match(
- 'This is ([^,]*), Version ([^%(]*) %(([^%)]*) ([^%)]*)%)%s+%(format=([^%)]*) ([^)]*)%)'
- )
- f:close()
- return self
-end
-
-function tex_engine:__index(k) return rawget(self(), k) end
-
-
-lib.tex_engine = tex_engine
-return lib
diff --git a/support/lyluatex/lyluatex-options.lua b/support/lyluatex/lyluatex-options.lua
deleted file mode 100644
index 62ec72a3c3..0000000000
--- a/support/lyluatex/lyluatex-options.lua
+++ /dev/null
@@ -1,266 +0,0 @@
--- luacheck: ignore ly warn info log self luatexbase internalversion font fonts tex token kpse status
-local err, warn, info, log = luatexbase.provides_module({
- name = "lyluatex-options",
- version = '1.0f', --LYLUATEX_VERSION
- date = "2019/05/27", --LYLUATEX_DATE
- description = "Module lyluatex-options.",
- author = "The Gregorio Project − (see Contributors.md)",
- copyright = "2015-2019 - jperon and others",
- license = "MIT",
-})
-
---[[
- This module provides functionality to handle package options and make them
- configurable in a fine-grained fashion as
- - package options
- - local options (for individual instances of commands/environments)
- - changed “from here on” within a document.
-
--- ]]
-
-local lib = require(kpse.find_file("lyluatex-lib.lua") or "lyluatex-lib.lua")
-local optlib = {} -- namespace for the returned table
-local Opts = {options = {}} -- Options class
-Opts.__index = function (self, k) return self.options[k] or rawget(Opts, k) end
-setmetatable(Opts, Opts)
-
-
-function Opts:new(opt_prefix, declarations)
---[[
- Declare package options along with their default and
- accepted values. To *some* extent also provide type checking.
- - opt_prefix: the prefix/name by which the lyluatex-options module is
- referenced in the parent LaTeX document (preamble or package).
- This is required to write the code calling optlib.set_option into
- the option declaration.
- - declarations: a definition table stored in the calling module (see below)
- Each entry in the 'declarations' table represents one package option, with each
- value being an array (table with integer indexes instead of keys). For
- details please refer to the manual.
---]]
- local o = setmetatable(
- {
- declarations = declarations,
- options = {}
- },
- self
- )
- local exopt = ''
- for k, v in pairs(declarations) do
- o.options[k] = v[1] or ''
- tex.sprint(string.format([[
-\DeclareOptionX{%s}{\directlua{
- %s:set_option('%s', '\luatexluaescapestring{#1}')
-}}%%
-]],
- k, opt_prefix, k
- ))
- exopt = exopt..k..'='..(v[1] or '')..','
- end
- tex.sprint([[\ExecuteOptionsX{]]..exopt..[[}%%]], [[\ProcessOptionsX]])
- return o
-end
-
-function Opts:check_local_options(opts, ignore_declarations)
---[[
- Parse the given options (options passed to a command/environment),
- sanitize them against the global package options and return a table
- with the local options that should then supersede the global options.
- If ignore_declaration is given any non-false value the sanitization
- step is skipped (i.e. local options are only parsed and duplicates
- rejected).
---]]
- local options = {}
- local next_opt = opts:gmatch('([^,]+)') -- iterator over options
- for opt in next_opt do
- local k, v = opt:match('([^=]+)=?(.*)')
- if k then
- if v and v:sub(1, 1) == '{' then -- handle keys with {multiple, values}
- while select(2, v:gsub('{', '')) ~= select(2, v:gsub('}', '')) do v = v..','..next_opt() end
- v = v:sub(2, -2) -- remove { }
- end
- if not ignore_declarations then
- k, v = self:sanitize_option(k:gsub('^%s', ''), v:gsub('^%s', ''))
- end
- if k then
- if options[k] then err('Option %s is set two times for the same score.', k)
- else options[k] = v
- end
- end
- end
- end
- return options
-end
-
-function Opts:is_neg(k)
---[[
- Type check for a 'negative' option. This is an existing option
- name prefixed with 'no' (e.g. 'noalign')
---]]
- local _, i = k:find('^no')
- return i and lib.contains_key(self.declarations, k:sub(i + 1))
-end
-
-function Opts:sanitize_option(k, v)
---[[
- Check and (if necessary) adjust the value of a given option.
- Reject undefined options
- Check 'negative' options
- Handle boolean options (empty strings or 'false'), set them to real booleans
---]]
- local declarations = self.declarations
- if k == '' or k == 'noarg' then return end
- if not lib.contains_key(declarations, k) then err('Unknown option: '..k) end
- -- aliases
- if declarations[k] and declarations[k][2] == optlib.is_alias then
- if declarations[k][1] == v then return
- else k = declarations[k] end
- end
- -- boolean
- if v == 'false' then v = false end
- -- negation (for example, noindent is the negation of indent)
- if self:is_neg(k) then
- if v ~= nil and v ~= 'default' then
- k = k:gsub('^no(.*)', '%1')
- v = not v
- else return
- end
- end
- return k, v
-end
-
-function Opts:set_option(k, v)
---[[
- Set an option for the given prefix to be in effect from this point on.
- Raises an error if the option is not declared or does not meet the
- declared expectations. (TODO: The latter has to be integrated by extracting
- optlib.validate_option from optlib.validate_options and call it in
- sanitize_option).
---]]
- k, v = self:sanitize_option(k, v)
- if k then
- self.options[k] = v
- self:validate_option(k)
- end
-end
-
-function Opts:validate_option(key, options_obj)
---[[
- Validate an (already sanitized) option against its expected values.
- With options_obj a local options table can be provided,
- otherwise the global options stored in OPTIONS are checked.
---]]
- local package_opts = self.declarations
- local options = options_obj or self.options
- local unexpected
- if options[key] == 'default' then
- -- Replace 'default' with an actual value
- options[key] = package_opts[key][1]
- unexpected = options[key] == nil
- end
- if not lib.contains(package_opts[key], options[key]) and package_opts[key][2] then
- -- option value is not in the array of accepted values
- if type(package_opts[key][2]) == 'function' then package_opts[key][2](key, options[key])
- else unexpected = true
- end
- end
- if unexpected then
- err([[
- Unexpected value "%s" for option %s:
- authorized values are "%s"
- ]],
- options[key], key, table.concat(package_opts[key], ', ')
- )
- end
-end
-
-function Opts:validate_options(options_obj)
---[[
- Validate the given set of options against the option declaration
- table for the given prefix.
- With options_obj a local options table can be provided,
- otherwise the global options stored in OPTIONS are checked.
---]]
- for k, _ in lib.orderedpairs(self.declarations) do
- self:validate_option(k, options_obj)
- end
-end
-
-
-function optlib.is_alias()
---[[
- This function doesn't do anything, but if an option is defined
- as an alias, its second parameter will be this function, so the
- test declarations[k][2] == optlib.is_alias in Opts:sanitize_options
- will return true.
---]]
-end
-
-
-function optlib.is_dim(k, v)
---[[
- Type checking for options that accept a LaTeX dimension.
- This can be
- - a number (integer or float)
- - a number with unit
- - a (multiplied) TeX length
- (see error message in code for examples)
---]]
- if v == '' or v == false or tonumber(v) then return true end
- local n, sl, u = v:match('^%d*%.?%d*'), v:match('\\'), v:match('%a+')
- -- a value of number - backslash - length is a dimension
- -- invalid input will be prevented in by the LaTeX parser already
- if n and sl and u then return true end
- if n and lib.contains(lib.TEX_UNITS, u) then return true end
- err([[
-Unexpected value "%s" for dimension %s:
-should be either a number (for example "12"),
-a number with unit, without space ("12pt"),
-or a (multiplied) TeX length (".8\linewidth")
-]],
- v, k
- )
-end
-
-
-function optlib.is_neg(k, _)
---[[
- Type check for a 'negative' option. At this stage,
- we only check that it begins with 'no'.
---]]
- return k:find('^no')
-end
-
-
-function optlib.is_num(_, v)
---[[
- Type check for number options
---]]
- return v == '' or tonumber(v)
-end
-
-
-function optlib.is_str(_, v)
---[[
- Type check for string options
---]]
- return type(v) == 'string'
-end
-
-
-function optlib.merge_options(base_opt, super_opt)
---[[
- Merge two tables.
- Create a new table as a copy of base_opt, then merge with
- super_opt. Entries in super_opt supersede (i.e. overwrite)
- colliding entries in base_opt.
---]]
- local result = {}
- for k, v in pairs(base_opt) do result[k] = v end
- for k, v in pairs(super_opt) do result[k] = v end
- return result
-end
-
-
-optlib.Opts = Opts
-return optlib
diff --git a/support/lyluatex/lyluatex.lua b/support/lyluatex/lyluatex.lua
index 1023e20ef9..adb17a63a0 100644
--- a/support/lyluatex/lyluatex.lua
+++ b/support/lyluatex/lyluatex.lua
@@ -1,21 +1,20 @@
-- luacheck: ignore ly log self luatexbase internalversion font fonts tex token kpse status ly_opts
local err, warn, info, log = luatexbase.provides_module({
name = "lyluatex",
- version = '1.0f', --LYLUATEX_VERSION
- date = "2019/05/27", --LYLUATEX_DATE
+ version = '1.1', --LYLUATEX_VERSION
+ date = "2022/10/30", --LYLUATEX_DATE
description = "Module lyluatex.",
author = "The Gregorio Project − (see Contributors.md)",
- copyright = "2015-2019 - jperon and others",
+ copyright = "2015-2022 - jperon and others",
license = "MIT",
})
-local lib = require(kpse.find_file("lyluatex-lib.lua") or "lyluatex-lib.lua")
-local ly_opts = ly_opts -- global ly_opts has been defined before in lyluatex.sty
+local lib = require(kpse.find_file("luaoptions-lib.lua") or "luaoptions-lib.lua")
+local ly_opts = lua_options.client('ly')
local md5 = require 'md5'
local lfs = require 'lfs'
-local latex = {}
local ly = {
err = err,
varwidth_available = kpse.find_file('varwidth.sty')
@@ -67,19 +66,16 @@ local LY_HEAD = [[
%%File header
\version "<<<version>>>"
<<<language>>>
-
-<<<preamble>>>
-
#(define inside-lyluatex #t)
#(set-global-staff-size <<<staffsize>>>)
+<<<preamble>>>
\header {
copyright = ""
tagline = ##f
}
\paper{
- <<<paper>>>
- two-sided = ##<<<twoside>>>
+ <<<paper>>> two-sided = ##<<<twoside>>>
line-width = <<<linewidth>>>\pt
<<<indent>>>
<<<raggedright>>>
@@ -88,8 +84,7 @@ local LY_HEAD = [[
\layout{
<<<staffprops>>>
<<<fixbadlycroppedstaffgroupbrackets>>>
-}
-<<<header>>>
+}<<<header>>>
%%Follows original score
]]
@@ -121,13 +116,16 @@ end
local function font_default_staffsize()
- return lib.fontinfo(font.current()).size/39321.6
+ return lib.current_font_size()/39321.6
end
local function includes_parse(list)
local includes = ''
if list then
+ includes = [[
+
+]]
list = list:explode(',')
for _, included_file in ipairs(list) do
warn(included_file)
@@ -197,12 +195,11 @@ end
--[[ ================ Bounding box calculations =========================== --]]
-local bbox = {}
-function bbox.get(filename, line_width)
- return bbox.read(filename) or bbox.parse(filename, line_width)
+function bbox_get(filename, line_width)
+ return bbox_read(filename) or bbox_parse(filename, line_width)
end
-function bbox.calc(x_1, x_2, y_1, y_2, line_width)
+function bbox_calc(x_1, x_2, y_1, y_2, line_width)
local bb = {
['protrusion'] = -lib.convert_unit(("%fbp"):format(x_1)),
['r_protrusion'] = lib.convert_unit(("%fbp"):format(x_2)) - line_width,
@@ -216,7 +213,7 @@ function bbox.calc(x_1, x_2, y_1, y_2, line_width)
return bb
end
-function bbox.parse(filename, line_width)
+function bbox_parse(filename, line_width)
-- get BoundingBox from EPS file
local bbline = lib.readlinematching('^%%%%BoundingBox', io.open(filename..'.eps', 'r'))
if not bbline then return end
@@ -239,24 +236,24 @@ function bbox.parse(filename, line_width)
end
local f = io.open(filename .. '.bbox', 'w')
f:write(
- string.format("return %s, %s, %s, %s, %s", x_1, y_1, x_2, y_2, line_width)
+ string.format("return %f, %f, %f, %f, %f", x_1, y_1, x_2, y_2, line_width)
)
f:close()
- return bbox.calc(x_1, x_2, y_1, y_2, line_width)
+ return bbox_calc(x_1, x_2, y_1, y_2, line_width)
end
-function bbox.read(f)
+function bbox_read(f)
f = f .. '.bbox'
if lfs.isfile(f) then
local x_1, y_1, x_2, y_2, line_width = dofile(f)
- return bbox.calc(x_1, x_2, y_1, y_2, line_width)
+ return bbox_calc(x_1, x_2, y_1, y_2, line_width)
end
end
--[[ =============== Functions that output LaTeX code ===================== --]]
-function latex.filename(printfilename, insert, input_file)
+function latex_filename(printfilename, insert, input_file)
if printfilename and input_file then
if insert ~= 'systems' then
warn('`printfilename` only works with `insert=systems`')
@@ -267,7 +264,7 @@ function latex.filename(printfilename, insert, input_file)
end
end
-function latex.fullpagestyle(style, ppn)
+function latex_fullpagestyle(style, ppn)
local function texoutput(s) tex.sprint('\\includepdfset{pagecommand='..s..'}%') end
if style == '' then
if ppn then texoutput('\\thispagestyle{empty}')
@@ -277,7 +274,7 @@ function latex.fullpagestyle(style, ppn)
end
end
-function latex.includeinline(pdfname, height, valign, hpadding, voffset)
+function latex_includeinline(pdfname, height, valign, hpadding, voffset)
local v_base
if valign == 'bottom' then v_base = 0
elseif valign == 'top' then v_base = lib.convert_unit('1em') - height
@@ -285,27 +282,25 @@ function latex.includeinline(pdfname, height, valign, hpadding, voffset)
end
tex.sprint(
string.format(
- [[\hspace{%fpt}\raisebox{%fpt}{\includegraphics{%s-1.pdf}}\hspace{%fpt}]],
+ [[\hspace{%fpt}\raisebox{%fpt}{\includegraphics{%s-1}}\hspace{%fpt}]],
hpadding, v_base + voffset, pdfname, hpadding
)
)
end
-function latex.includepdf(pdfname, range, papersize)
- local noautoscale = ''
- if papersize then noautoscale = 'noautoscale' end
+function latex_includepdf(pdfname, range, papersize)
tex.sprint(string.format(
[[\includepdf[pages={%s},%s]{%s}]],
- table.concat(range, ','), noautoscale, pdfname
+ table.concat(range, ','), papersize and 'noautoscale' or '', pdfname
))
end
-function latex.includesystems(filename, range, protrusion, gutter, staffsize, indent_offset)
+function latex_includesystems(filename, range, protrusion, gutter, staffsize, indent_offset)
local h_offset = protrusion + indent_offset
local texoutput = '\\ifx\\preLilyPondExample\\undefined\\else\\preLilyPondExample\\fi\n'
texoutput = texoutput..'\\par\n'
for index, system in pairs(range) do
- if not lfs.isfile(filename..'-'..system..'.pdf') then break end
+ if not lfs.isfile(filename..'-'..system..'.eps') then break end
texoutput = texoutput..
string.format([[
\noindent\hspace*{%fpt}\includegraphics{%s}%%
@@ -327,13 +322,13 @@ function latex.includesystems(filename, range, protrusion, gutter, staffsize, in
tex.sprint(texoutput:explode('\n'))
end
-function latex.label(label, labelprefix)
+function latex_label(label, labelprefix)
if label then tex.sprint('\\label{'..labelprefix..label..'}%%') end
end
ly.verbenv = {[[\begin{verbatim}]], [[\end{verbatim}]]}
-function latex.verbatim(verbatim, ly_code, intertext, version)
+function latex_verbatim(verbatim, ly_code, intertext, version)
if verbatim then
if version then tex.sprint('\\lyVersion{'..version..'}') end
local content = table.concat(ly_code:explode('\n'), '\n'):gsub(
@@ -372,12 +367,12 @@ function Score:bbox(system)
if not self.bboxes then
self.bboxes = {}
for i = 1, self:count_systems() do
- table.insert(self.bboxes, bbox.get(self.output..'-'..i, self['line-width']))
+ table.insert(self.bboxes, bbox_get(self.output..'-'..i, self['line-width']))
end
end
return self.bboxes[system]
else
- if not self.bbox then self.bbox = bbox.get(self.output, self['line-width']) end
+ if not self.bbox then self.bbox = bbox_get(self.output, self['line-width']) end
return self.bbox
end
end
@@ -707,26 +702,27 @@ function Score:content()
end
function Score:count_systems(force)
- if force or not self.system_count then
- local f = io.open(self.output..'-systems.count', 'r')
- if f then
- self.system_count = tonumber(f:read('*all'))
- f:close()
- else self.system_count = 0
+ local count = self.system_count
+ if force or not count then
+ count = 0
+ local systems = self.output:match("[^/]*$").."%-%d+%.eps"
+ for f in lfs.dir(self.tmpdir) do
+ if f:match(systems) then
+ count = count + 1
+ end
end
+ self.system_count = count
end
- return self.system_count
+ return count
end
function Score:delete_intermediate_files()
for _, filename in pairs(self.output_names) do
if self.insert == 'fullpage' then os.remove(filename..'.ps')
else
- for i = 1, self:count_systems() do os.remove(filename..'-'..i..'.eps') end
os.remove(filename..'-systems.tex')
os.remove(filename..'-systems.texi')
os.remove(filename..'.eps')
- os.remove(filename..'.pdf')
end
end
end
@@ -785,7 +781,7 @@ end
function Score:is_compiled()
if self['force-compilation'] then return false end
- return lfs.isfile(self.output..'.pdf') or self:count_systems(true) ~= 0
+ return lfs.isfile(self.output..'.pdf') or lfs.isfile(self.output..'.eps') or self:count_systems(true) ~= 0
end
function Score:is_odd_page() return tex.count['c@page'] % 2 == 1 end
@@ -799,11 +795,10 @@ function Score:lilypond_cmd()
input = self.output..".ly 2>&1"
mode = 'r'
end
- local cmd = '"'..self.program..'" '..
- "-dno-point-and-click "..
- "-djob-count=2 "..
- "-dno-delete-intermediate-files "
- if self['optimize-pdf'] and self:lilypond_has_TeXGS() then cmd = cmd.."-O TeX-GS " end
+ local cmd = '"'..self.program..'" '
+ .. (self.insert == "fullpage" and "" or "-E ")
+ .. "-dno-point-and-click -djob-count=2 -dno-delete-intermediate-files "
+ if self['optimize-pdf'] and self:lilypond_has_TeXGS() then cmd = cmd.."-O TeX-GS -dgs-never-embed-fonts " end
if self.input_file then
cmd = cmd..'-I "'..lib.dirname(self.input_file):gsub('^%./', lfs.currentdir()..'/')..'" '
end
@@ -844,6 +839,7 @@ function Score:ly_fixbadlycroppedstaffgroupbrackets()
(ly:grob-set-property! grob 'Y-extent
(cons (- (car Y-off) 1.7) (+ (cdr Y-off) 1.7)))))
}]]
+ or '%% no fix for badly cropped StaffGroup brackets'
end
function Score:ly_fonts()
@@ -859,6 +855,8 @@ function Score:ly_fonts()
self.sffamily,
self.ttfamily
)
+ else
+ return '%% fonts not set'
end
end
@@ -869,11 +867,16 @@ end
function Score:ly_indent()
if not (self.indent == false and self.insert == 'fullpage') then
return [[indent = ]]..(self.indent or 0)..[[\pt]]
+ else
+ return '%% no indent set'
end
end
function Score:ly_language()
- if self.language then return '\\language "'..self.language..'"' end
+ if self.language then return '\\language "'..self.language..'"'..[[
+
+]]
+ else return '' end
end
function Score:ly_linewidth() return self['line-width'] end
@@ -883,16 +886,16 @@ function Score:ly_staffsize() return self.staffsize end
function Score:ly_margins()
local horizontal_margins =
self.twoside and string.format([[
- inner-margin = %s\pt]], self:tex_margin_inner())
+ inner-margin = %f\pt]], self:tex_margin_inner())
or string.format([[
- left-margin = %s\pt]], self:tex_margin_left())
+ left-margin = %f\pt]], self:tex_margin_left())
local tex_top = self['extra-top-margin'] + self:tex_margin_top()
local tex_bottom = self['extra-bottom-margin'] + self:tex_margin_bottom()
if self.fullpagealign == 'crop' then
return string.format([[
- top-margin = %s\pt
- bottom-margin = %s\pt
+ top-margin = %f\pt
+ bottom-margin = %f\pt
%s]],
tex_top, tex_bottom, horizontal_margins
)
@@ -904,18 +907,18 @@ function Score:ly_margins()
bottom-margin = 0\pt
%s
top-system-spacing =
- #'((basic-distance . %s)
- (minimum-distance . %s)
+ #'((basic-distance . %f)
+ (minimum-distance . %f)
(padding . 0)
(stretchability . 0))
top-markup-spacing =
- #'((basic-distance . %s)
- (minimum-distance . %s)
+ #'((basic-distance . %f)
+ (minimum-distance . %f)
(padding . 0)
(stretchability . 0))
last-bottom-spacing =
- #'((basic-distance . %s)
- (minimum-distance . %s)
+ #'((basic-distance . %f)
+ (minimum-distance . %f)
(padding . 0)
(stretchability . 0))
]],
@@ -940,7 +943,7 @@ end
function Score:ly_paper()
local system_count =
- self['system-count'] == 0 and ''
+ self['system-count'] == '0' and ''
or 'system-count = '..self['system-count']..'\n '
local papersize = '#(set-paper-size "'..(self.papersize or 'lyluatexfmt')..'")'
@@ -949,33 +952,33 @@ function Score:ly_paper()
local pfpn = self['print-first-page-number'] and 't' or 'f'
local ppn = self['print-page-number'] and 't' or 'f'
return string.format([[
-%s%s
+ %s%s
print-page-number = ##%s
print-first-page-number = ##%s
- first-page-number = %s
+ first-page-number = %d
%s]],
- system_count, papersize, ppn, pfpn,
- first_page_number, self:ly_margins()
+ system_count, papersize, ppn, pfpn,
+ first_page_number, self:ly_margins()
)
else
- if self.papersize then
- papersize = papersize..[[
-]]
- else
- papersize = ''
- end
+ return string.format([[%s%s]], papersize..[[
- return string.format([[%s%s]], papersize, system_count)
+]], system_count)
end
end
function Score:ly_preamble()
+ local result = string.format(
+ [[#(set! paper-alist (cons '("lyluatexfmt" . (cons (* %f pt) (* %f pt))) paper-alist))]],
+ self.paperwidth, self.paperheight
+ )
if self.insert == 'fullpage' then
- return string.format(
- [[#(set! paper-alist (cons '("lyluatexfmt" . (cons (* %s pt) (* %s pt))) paper-alist))]],
- self.paperwidth, self.paperheight
- )
- else return [[\include "lilypond-book-preamble.ly"]]
+ return result
+ else
+ return result..[[
+
+
+\include "lilypond-book-preamble.ly"]]
end
end
@@ -984,11 +987,17 @@ function Score:ly_raggedright()
if self['ragged-right'] then return 'ragged-right = ##t'
else return 'ragged-right = ##f'
end
+ else
+ return '%% no alignment set'
end
end
function Score:ly_staffprops()
- local clef, timing, timesig, staff = '', '', '', ''
+ local clef, timing, timesig, staff =
+ '%% no clef set',
+ ' %% timing not suppressed',
+ ' %% no time signature set',
+ ' %% staff symbol not suppressed'
if self.noclef then clef = [[\context { \Staff \remove "Clef_engraver" }]] end
if self.notiming then timing = [[\context { \Score timing = ##f }]] end
if self.notimesig then timesig = [[\context { \Staff \remove "Time_signature_engraver" }]] end
@@ -1015,28 +1024,29 @@ function Score:optimize_pdf()
end,
'lyluatex optimize-pdf'
)
- end
- local pdf2ps, ps2pdf, path
- for file in lfs.dir(self.tmpdir) do
- path = self.tmpdir..'/'..file
- if path:match(self.output) and path:sub(-4) == '.pdf' then
- pdf2ps = io.popen(
- 'gs -q -sDEVICE=ps2write -sOutputFile=- -dNOPAUSE '..path..' -c quit',
- 'r'
- )
- ps2pdf = io.popen(
- 'gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile='..path..'-gs -',
- 'w'
- )
- if pdf2ps then
- ps2pdf:write(pdf2ps:read('*a'))
- pdf2ps:close()
- ps2pdf:close()
- os.rename(path..'-gs', path)
- else
- warn(
- [[You have asked for pdf optimization, but gs wasn't found.]]
+ else
+ local pdf2ps, ps2pdf, path
+ for file in lfs.dir(self.tmpdir) do
+ path = self.tmpdir..'/'..file
+ if path:match(self.output) and path:sub(-4) == '.pdf' then
+ pdf2ps = io.popen(
+ 'gs -q -sDEVICE=ps2write -sOutputFile=- -dNOPAUSE '..path..' -c quit',
+ 'r'
+ )
+ ps2pdf = io.popen(
+ 'gs -q -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile='..path..'-gs -',
+ 'w'
)
+ if pdf2ps then
+ ps2pdf:write(pdf2ps:read('*a'))
+ pdf2ps:close()
+ ps2pdf:close()
+ os.rename(path..'-gs', path)
+ else
+ warn(
+ [[You have asked for pdf optimization, but gs wasn't found.]]
+ )
+ end
end
end
end
@@ -1081,9 +1091,9 @@ points to a valid LilyPond executable.
err(warning)
end
end
- -- with bbox.read check_protrusion will only execute with
+ -- with bbox_read check_protrusion will only execute with
-- a prior compilation, otherwise it will be ignored
- local do_compile = not self:check_protrusion(bbox.read)
+ local do_compile = not self:check_protrusion(bbox_read)
if self['force-compilation'] or do_compile then
repeat
self.complete_ly_code = self:header()..self:content()..self:footer()
@@ -1094,7 +1104,7 @@ points to a valid LilyPond executable.
self:clean_failed_compilation()
break
end
- until self:check_protrusion(bbox.get)
+ until self:check_protrusion(bbox_get)
self:optimize_pdf()
else table.insert(self.output_names, self.output)
end
@@ -1112,9 +1122,9 @@ end
function Score:run_lily_proc(p)
if self.debug then
- local f = io.open(self.output..".log", 'w')
- f:write(p:read('*a'))
- f:close()
+ local f = io.open(self.output..".log", 'w')
+ f:write(p:read('*a'))
+ f:close()
else p:write(self.complete_ly_code)
end
return p:close()
@@ -1127,6 +1137,11 @@ function Score:run_lilypond()
self.debug = true
self.lilypond_error = not self:run_lily_proc(io.popen(self:lilypond_cmd(self.complete_ly_code)))
end
+ local lilypond_pdf, mode = self:lilypond_cmd(self.complete_ly_code)
+ if lilypond_pdf:match"-E" then
+ lilypond_pdf = lilypond_pdf:gsub(" %-E", " --pdf")
+ self:run_lily_proc(io.popen(lilypond_pdf, mode))
+ end
end
function Score:tex_margin_bottom()
@@ -1140,7 +1155,7 @@ end
function Score:tex_margin_inner()
self._tex_margin_inner = self._tex_margin_inner or
lib.convert_unit((
- tex.sp('1in') + tex.dimen.oddsidemargin + tex.dimen.hoffset
+ tex.sp('1in') + tex.dimen.oddsidemargin + tex.dimen.hoffset
)..'sp')
return self._tex_margin_inner
end
@@ -1174,16 +1189,16 @@ function Score:tex_margin_top()
end
function Score:write_latex(do_compile)
- latex.filename(self.printfilename, self.insert, self.input_file)
- latex.verbatim(self.verbatim, self.ly_code, self.intertext, self.addversion)
+ latex_filename(self.printfilename, self.insert, self.input_file)
+ latex_verbatim(self.verbatim, self.ly_code, self.intertext, self.addversion)
if do_compile and not self:check_compilation() then return end
--[[ Now we know there is a proper score --]]
- latex.fullpagestyle(self.fullpagestyle, self['print-page-number'])
- latex.label(self.label, self.labelprefix)
+ latex_fullpagestyle(self.fullpagestyle, self['print-page-number'])
+ latex_label(self.label, self.labelprefix)
if self.insert == 'fullpage' then
- latex.includepdf(self.output, self.range, self.papersize)
+ latex_includepdf(self.output, self.range, self.papersize)
elseif self.insert == 'systems' then
- latex.includesystems(
+ latex_includesystems(
self.output, self.range, self.protrusion_left,
self.leftgutter, self.staffsize, self.indent_offset
)
@@ -1196,7 +1211,7 @@ This will probably cause bad output.]]
end
local bb = self:bbox(1)
if bb then
- latex.includeinline(
+ latex_includeinline(
self.output, bb.height, self.valign, self.hpadding, self.voffset
)
end
@@ -1342,20 +1357,20 @@ end
function ly.set_fonts(rm, sf, tt)
-if ly.score.rmfamily..ly.score.sffamily..ly.score.ttfamily ~= '' then
- ly.score['pass-fonts'] = 'true'
- info("At least one font family set explicitly. Activate 'pass-fonts'")
-end
- if ly.score.rmfamily == '' then ly.score.rmfamily = ly.get_font_family(rm)
- else
- -- if explicitly set don't override rmfamily with 'current' font
- if ly.score['current-font-as-main'] then
- info("rmfamily set explicitly. Deactivate 'current-font-as-main'")
- end
- ly.score['current-font-as-main'] = false
- end
- if ly.score.sffamily == '' then ly.score.sffamily = ly.get_font_family(sf) end
- if ly.score.ttfamily == '' then ly.score.ttfamily = ly.get_font_family(tt) end
+ if ly.score.rmfamily..ly.score.sffamily..ly.score.ttfamily ~= '' then
+ ly.score['pass-fonts'] = 'true'
+ info("At least one font family set explicitly. Activate 'pass-fonts'")
+ end
+ if ly.score.rmfamily == '' then ly.score.rmfamily = ly.get_font_family(rm)
+ else
+ -- if explicitly set don't override rmfamily with 'current' font
+ if ly.score['current-font-as-main'] then
+ info("rmfamily set explicitly. Deactivate 'current-font-as-main'")
+ end
+ ly.score['current-font-as-main'] = false
+ end
+ if ly.score.sffamily == '' then ly.score.sffamily = ly.get_font_family(sf) end
+ if ly.score.ttfamily == '' then ly.score.ttfamily = ly.get_font_family(tt) end
end
diff --git a/support/lyluatex/lyluatex.pdf b/support/lyluatex/lyluatex.pdf
index adc9003791..8f546a0f9b 100644
--- a/support/lyluatex/lyluatex.pdf
+++ b/support/lyluatex/lyluatex.pdf
Binary files differ
diff --git a/support/lyluatex/lyluatex.sty b/support/lyluatex/lyluatex.sty
index f0d70d9878..e0108513d9 100644
--- a/support/lyluatex/lyluatex.sty
+++ b/support/lyluatex/lyluatex.sty
@@ -1,22 +1,20 @@
%Lyluatex LaTeX style.
%
-% Copyright (C) 2015-2019 jperon and others (see CONTRIBUTORS.md)
+% Copyright (C) 2015-2022 jperon and others (see CONTRIBUTORS.md)
% License: MIT
% This file is part of lyluatex.
\NeedsTeXFormat{LaTeX2e}%
-\ProvidesPackage{lyluatex}[2019/05/27 v1.0f] %%LYLUATEX_DATE LYLUATEX_VERSION
+\ProvidesPackage{lyluatex}[2022/10/30 v1.1] %%LYLUATEX_DATE LYLUATEX_VERSION
% Dependencies
-\RequirePackage{luatexbase}
-\RequirePackage{luaotfload}
-\RequirePackage{xkeyval}
\RequirePackage{graphicx}
\RequirePackage{minibox}
\RequirePackage{environ}
\RequirePackage{currfile}
\RequirePackage{pdfpages}
\IfFileExists{varwidth.sty}{\RequirePackage{varwidth}}{}
+\RequirePackage{luaoptions}
\RequirePackage{metalogo}
\newcommand{\lyluatex}{\textit{ly}\LuaTeX}
@@ -43,10 +41,8 @@
% Options
\catcode`-=11
\directlua{
- local _opt = require(
- kpse.find_file("lyluatex-options.lua") or "lyluatex-options.lua"
- )
- ly_opts = _opt.Opts:new('ly_opts', {
+ local _opt = lua_options
+ lua_options.register('ly', {
['addversion'] = {'false', 'true', ''},
['autoindent'] = {'true', 'false', ''},
['cleantmp'] = {'false', 'true', ''},
@@ -133,7 +129,7 @@
\directlua{
ly = require(kpse.find_file("lyluatex.lua") or "lyluatex.lua")
ly.make_list_file()
- if ly_opts.cleantmp then
+ if lua_options.client('ly').cleantmp then
luatexbase.add_to_callback('stop_run', ly.clean_tmp_dir, 'lyluatex cleantmp')
luatexbase.add_to_callback('stop_run', ly.conclusion_text, 'lyluatex conclusion')
end
@@ -157,9 +153,6 @@
\setlength{\hfuzz}{\ly@old@hfuzz}%
}
-% Command to change options during the document
-\newcommand{\lysetoption}[2]{\directlua{ly_opts:set_option([[#1]], [[#2]])}}
-
% How the filename of a score will look like (if printed)
\newcommand{\lyFilename}[1]{\noindent #1\par\bigskip}
@@ -174,7 +167,9 @@
% *current* font for optional use.
\newcommand{\ly@currentfonts}{%
\begingroup%
- \directlua{ly_opts:set_option('current-font', ly.get_font_family(font.current()))}%
+ \setluaoption{ly}{current-font}{%
+ \directlua{ly.get_font_family(font.current())}
+ }
\rmfamily \edef\rmfamilyid{\fontid\font}%
\sffamily \edef\sffamilyid{\fontid\font}%
\ttfamily \edef\ttfamilyid{\fontid\font}%
@@ -188,9 +183,9 @@
% Score processing
\newcommand*{\ly@compilescore}[1]{%
\ly@setunits%
+ \setluaoption{ly}{currfiledir}{\currfiledir}
+ \setluaoption{ly}{twoside}{\ly@istwosided}
\directlua{
- ly_opts:set_option('currfiledir', [[\currfiledir]])
- ly_opts:set_option('twoside', '\ly@istwosided')
#1
ly.newpage_if_fullpage()
}%
diff --git a/support/lyluatex/lyluatex.tex b/support/lyluatex/lyluatex.tex
index aaa95d7848..a804663555 100644
--- a/support/lyluatex/lyluatex.tex
+++ b/support/lyluatex/lyluatex.tex
@@ -1,38 +1,45 @@
-\PassOptionsToPackage{unicode=true}{hyperref} % options for packages loaded elsewhere
+% Options for packages loaded elsewhere
+\PassOptionsToPackage{unicode}{hyperref}
\PassOptionsToPackage{hyphens}{url}
%
-\documentclass[]{lyluatexmanual}
+\documentclass[
+]{lyluatexmanual}
+\usepackage{amsmath,amssymb}
\usepackage[]{libertine}
-\usepackage{amssymb,amsmath}
-\usepackage{ifxetex,ifluatex}
-\usepackage{fixltx2e} % provides \textsubscript
-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
+\usepackage{iftex}
+\ifPDFTeX
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
- \usepackage{textcomp} % provides euro and other symbols
-\else % if luatex or xelatex
+ \usepackage{textcomp} % provide euro and other symbols
+\else % if luatex or xetex
\usepackage{unicode-math}
- \defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase}
+ \defaultfontfeatures{Scale=MatchLowercase}
+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
\fi
-% use upquote if available, for straight quotes in verbatim environments
+% Use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
-% use microtype if available
-\IfFileExists{microtype.sty}{%
-\usepackage[]{microtype}
-\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
+\IfFileExists{microtype.sty}{% use microtype if available
+ \usepackage[]{microtype}
+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
-\IfFileExists{parskip.sty}{%
-\usepackage{parskip}
-}{% else
-\setlength{\parindent}{0pt}
-\setlength{\parskip}{6pt plus 2pt minus 1pt}
-}
-\usepackage{hyperref}
+\makeatletter
+\@ifundefined{KOMAClassName}{% if non-KOMA class
+ \IfFileExists{parskip.sty}{%
+ \usepackage{parskip}
+ }{% else
+ \setlength{\parindent}{0pt}
+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}
+}{% if KOMA class
+ \KOMAoptions{parskip=half}}
+\makeatother
+\usepackage{xcolor}
+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
+\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}
\hypersetup{
- pdfauthor={Fr. Jacques Peron; Urs Liska; Br. Samuel Springuel},
- pdfborder={0 0 0},
- breaklinks=true}
-\urlstyle{same} % don't use monospace font for urls
+ pdfauthor={Fr.~Jacques Peron; Urs Liska; Br. Samuel Springuel},
+ hidelinks,
+ pdfcreator={LaTeX via pandoc}}
+\urlstyle{same} % disable monospaced font for URLs
\usepackage{color}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
@@ -44,7 +51,7 @@
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}}
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
-\newcommand{\BuiltInTok}[1]{#1}
+\newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{#1}}
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}}
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
@@ -57,7 +64,7 @@
\newcommand{\ExtensionTok}[1]{#1}
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}}
-\newcommand{\ImportTok}[1]{#1}
+\newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{\textbf{#1}}}
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
\newcommand{\NormalTok}[1]{#1}
@@ -71,30 +78,23 @@
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}}
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
-\setlength{\emergencystretch}{3em} % prevent overfull lines
+\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
-\setcounter{secnumdepth}{0}
-% Redefines (sub)paragraphs to behave more like sections
-\ifx\paragraph\undefined\else
-\let\oldparagraph\paragraph
-\renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}}
-\fi
-\ifx\subparagraph\undefined\else
-\let\oldsubparagraph\subparagraph
-\renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}}
+\setcounter{secnumdepth}{-\maxdimen} % remove section numbering
+\ifLuaTeX
+ \usepackage{selnolig} % disable illegal ligatures
\fi
-% set default figure placement to htbp
+\title{\lyluatex}
+\usepackage{etoolbox}
\makeatletter
-\def\fps@figure{htbp}
+\providecommand{\subtitle}[1]{% add subtitle to \maketitle
+ \apptocmd{\@title}{\par {\large #1 \par}}{}{}
+}
\makeatother
-
-
-\title{\lyluatex}
-\providecommand{\subtitle}[1]{}
-\subtitle{1.0f}
-\author{Fr. Jacques Peron \and Urs Liska \and Br. Samuel Springuel}
+\subtitle{1.1}
+\author{Fr.~Jacques Peron \and Urs Liska \and Br. Samuel Springuel}
\date{\lyluatexmanualdate}
\begin{document}
@@ -317,8 +317,8 @@ Linux with TeXLive:
\begin{Shaded}
\begin{Highlighting}[]
-\ExtensionTok{%}\NormalTok{ export shell_escape_commands=}\VariableTok{$(}\ExtensionTok{kpsewhich}\NormalTok{ -expand-var }\StringTok{'$shell_escape_commands'}\VariableTok{)}\NormalTok{,lilypond,gs}
-\ExtensionTok{%}\NormalTok{ lualatex --shell-restricted DOCUMENT.tex}
+\ExtensionTok{\%}\NormalTok{ export shell\_escape\_commands=}\VariableTok{$(}\ExtensionTok{kpsewhich} \AttributeTok{{-}expand{-}var} \StringTok{\textquotesingle{}$shell\_escape\_commands\textquotesingle{}}\VariableTok{)}\NormalTok{,lilypond,gs}
+\ExtensionTok{\%}\NormalTok{ lualatex }\AttributeTok{{-}{-}shell{-}restricted}\NormalTok{ DOCUMENT.tex}
\end{Highlighting}
\end{Shaded}
@@ -347,13 +347,13 @@ The basic mode of inserting scores into text documents is the
\KeywordTok{\textbackslash{}score} \KeywordTok{\{}
\KeywordTok{\textbackslash{}new} \DataTypeTok{ChoirStaff}\NormalTok{ \textbackslash{}with}\KeywordTok{ \{}
\DataTypeTok{instrumentName}\NormalTok{ = "}\StringTok{2 Fl."}
- \KeywordTok{\}} \KeywordTok{<<}
- \KeywordTok{\textbackslash{}new} \DataTypeTok{Staff} \FunctionTok{\textbackslash{}transpose c c'} \FunctionTok{\textbackslash{}music}
+ \KeywordTok{\}} \KeywordTok{\textless{}\textless{}}
+ \KeywordTok{\textbackslash{}new} \DataTypeTok{Staff} \FunctionTok{\textbackslash{}transpose c c\textquotesingle{}} \FunctionTok{\textbackslash{}music}
\KeywordTok{\textbackslash{}new} \DataTypeTok{Staff} \KeywordTok{\{}
\FunctionTok{\textbackslash{}clef bass}
\FunctionTok{\textbackslash{}music}
\KeywordTok{\}}
- \KeywordTok{>>}
+ \KeywordTok{\textgreater{}\textgreater{}}
\KeywordTok{\}}
\FunctionTok{\textbackslash{}end}\KeywordTok{\{}\NormalTok{lilypond}\KeywordTok{\}}
\end{Highlighting}
@@ -510,23 +510,23 @@ arguments to the individual command or environments:
\begin{Highlighting}[]
\FunctionTok{\textbackslash{}lilypondfile}\NormalTok{[key1=value1]\{path/to/file.ly\}}
-\FunctionTok{\textbackslash{}lilypond}\NormalTok{[key1=value1]\{ c' d' e' \}}
+\FunctionTok{\textbackslash{}lilypond}\NormalTok{[key1=value1]\{ c\textquotesingle{} d\textquotesingle{} e\textquotesingle{} \}}
\KeywordTok{\textbackslash{}begin}\NormalTok{\{}\ExtensionTok{lilypond}\NormalTok{\}[key1=value1]}
\NormalTok{\{}
-\NormalTok{ c' d' e'}
+\NormalTok{ c\textquotesingle{} d\textquotesingle{} e\textquotesingle{}}
\NormalTok{\}}
\KeywordTok{\textbackslash{}end}\NormalTok{\{}\ExtensionTok{lilypond}\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
-\lyCmd{lysetoption}
+\lyCmd{setluaoption{ly}}
At any place in the document the value of an option can be changed using
\begin{Shaded}
\begin{Highlighting}[]
-\FunctionTok{\textbackslash{}lysetoption}\NormalTok{\{key\}\{new-value\}}
+\FunctionTok{\textbackslash{}setluaoption}\NormalTok{\{ly\}\{key\}\{new{-}value\}}
\end{Highlighting}
\end{Shaded}
@@ -756,7 +756,7 @@ detail.
If not stated otherwise dimensions can be given in arbitrary \TeX~units,
e.g. \texttt{200pt}, \texttt{1ex} or \texttt{3cm} or as \TeX~lengths,
-e.g. \texttt{0.4\textbackslash{}textwidth}.
+e.g.~\texttt{0.4\textbackslash{}textwidth}.
\hypertarget{general}{%
\paragraph{General}\label{general}}
@@ -1169,7 +1169,7 @@ example:
\begin{Shaded}
\begin{Highlighting}[]
-\FunctionTok{\textbackslash{}lilypond}\NormalTok{\{a' b' c'\}}
+\FunctionTok{\textbackslash{}lilypond}\NormalTok{\{a\textquotesingle{} b\textquotesingle{} c\textquotesingle{}\}}
\end{Highlighting}
\end{Shaded}
@@ -1372,8 +1372,8 @@ monospace:
\begin{Shaded}
\begin{Highlighting}[]
-\FunctionTok{\textbackslash{}renewcommand}\NormalTok{\{}\ExtensionTok{\textbackslash{}lyFilename}\NormalTok{\}[1]\{}\CommentTok{%}
-\FunctionTok{\textbackslash{}noindent} \FunctionTok{\textbackslash{}texttt}\NormalTok{\{#1\}}\FunctionTok{\textbackslash{}par\textbackslash{}bigskip}\CommentTok{%}
+\FunctionTok{\textbackslash{}renewcommand}\NormalTok{\{}\ExtensionTok{\textbackslash{}lyFilename}\NormalTok{\}[1]\{}\CommentTok{\%}
+\FunctionTok{\textbackslash{}noindent} \FunctionTok{\textbackslash{}texttt}\NormalTok{\{\#1\}}\FunctionTok{\textbackslash{}par\textbackslash{}bigskip}\CommentTok{\%}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
@@ -1425,8 +1425,8 @@ indent and prints the text blue:
\begin{Shaded}
\begin{Highlighting}[]
-\FunctionTok{\textbackslash{}renewcommand}\NormalTok{\{}\ExtensionTok{\textbackslash{}lyIntertext}\NormalTok{\}[1]\{}\CommentTok{%}
-\FunctionTok{\textbackslash{}noindent} \FunctionTok{\textbackslash{}textcolor}\NormalTok{\{blue\}\{#1\}}\FunctionTok{\textbackslash{}par\textbackslash{}bigskip}\CommentTok{%}
+\FunctionTok{\textbackslash{}renewcommand}\NormalTok{\{}\ExtensionTok{\textbackslash{}lyIntertext}\NormalTok{\}[1]\{}\CommentTok{\%}
+\FunctionTok{\textbackslash{}noindent} \FunctionTok{\textbackslash{}textcolor}\NormalTok{\{blue\}\{\#1\}}\FunctionTok{\textbackslash{}par\textbackslash{}bigskip}\CommentTok{\%}
\NormalTok{\}}
\end{Highlighting}
\end{Shaded}
@@ -1452,11 +1452,11 @@ match today is to use the \texttt{TeX} highlighting of the
\begin{Shaded}
\begin{Highlighting}[]
-\CommentTok{% In the document header:}
+\CommentTok{\% In the document header:}
\BuiltInTok{\textbackslash{}usepackage}\NormalTok{\{}\ExtensionTok{minted}\NormalTok{\}}
-\CommentTok{% anywhere in the header or the body:}
-\FunctionTok{\textbackslash{}lysetverbenv}\NormalTok{\{}\KeywordTok{\textbackslash{}begin}\NormalTok{\{}\ExtensionTok{minted}\NormalTok{\}\{TeX\}\}\{\textbackslash{}end\{minted\}\}}
+\CommentTok{\% anywhere in the header or the body:}
+\FunctionTok{\textbackslash{}lysetverbenv}\NormalTok{\{}\KeywordTok{\textbackslash{}begin}\NormalTok{\{}\ExtensionTok{minted}\NormalTok{\}\{TeX\}}\VerbatimStringTok{\}\{}\KeywordTok{\textbackslash{}end}\NormalTok{\{}\ExtensionTok{minted}\NormalTok{\}\}}
\end{Highlighting}
\end{Shaded}
@@ -1505,9 +1505,9 @@ absolute paths in that process.
\begin{Shaded}
\begin{Highlighting}[]
-\FunctionTok{\textbackslash{}lysetoption}\NormalTok{\{includepaths\}\{}\FunctionTok{\textbackslash{}string}\NormalTok{~/lilypond-lib\}}
+\FunctionTok{\textbackslash{}setluaoption}\NormalTok{\{ly\}\{includepaths\}\{}\FunctionTok{\textbackslash{}string}\NormalTok{\textasciitilde{}/lilypond{-}lib\}}
-\FunctionTok{\textbackslash{}lilypondfile}\NormalTok{[includepaths=\{}\FunctionTok{\textbackslash{}string}\NormalTok{~/lilypond-lib,/home/johndoe/project-lib\}]}
+\FunctionTok{\textbackslash{}lilypondfile}\NormalTok{[includepaths=\{}\FunctionTok{\textbackslash{}string}\NormalTok{\textasciitilde{}/lilypond{-}lib,/home/johndoe/project{-}lib\}]}
\end{Highlighting}
\end{Shaded}
@@ -1774,22 +1774,31 @@ Those examples and others may be found in
\addcontentsline{toc}{subsection}{Insert Systems}
\hypertarget{insert-systems}{}
+
\section*{Insert System-by-System}
+
By default scores defined by the \option{lilypond} environment or the \cmd{lilypondfile} command are inserted as a sequence of systems.
+
\lyluatex\ determines the vertical space between the systems as a flexible length calculated from the \emph{staff size} of the score (as opposed to from the font size) to produce an regular-looking vertical spacing:
+
\begin{lilypond}[]
{
\repeat unfold 30 { c' d' e' d' }
}
\end{lilypond}
+
The following score has a significantly smaller staff size, and consequently the inter-system space is reduced:
+
\begin{lilypond}[staffsize=12]
{
\repeat unfold 36 { c' d' e' d' }
}
\end{lilypond}
+
\subsection*{Before and After the Score}
+
\cmd{preLilyPondExample} and \cmd{postLilyPondExample} allow some code to be printed before and after the score. This may for example be used to wrap the resulting score in an environment. In the following example rules are printed:
+
\def\preLilyPondExample{%
\par\bigskip
\noindent Before the score:
@@ -1798,35 +1807,43 @@ The following score has a significantly smaller staff size, and consequently the
\par\bigskip
\hrule\par\medskip\noindent After the score
\par\bigskip}
+
\begin{verbatim}
\newcommand{\preLilyPondExample}{%
\par\bigskip
\noindent Before the score:
\par\medskip\hrule\par\medskip}
+
\newcommand{\postLilyPondExample}{%
\par\bigskip
\hrule\par\medskip\noindent After the score
\par\bigskip}
\end{verbatim}
+
\begin{lilypond}[]
{
\repeat unfold 30 { c' d' e' d' }
}
\end{lilypond}
+
\subsection*{Configuring the Inter-System Content}
+
\let\preLilyPondExample\undefined
\let\postLilyPondExample\undefined
+
Using \cmd{betweenLilyPondSystem} it is possible to define a macro that is
expanded between each system pair. It is given the index of the previous system
as an argument to work with. The following example simply prints that index
between the systems, but with some programming more complicated and useful
things could be done, for example printing a rule after every third system or
conditionally insert a page break.
+
\def\betweenLilyPondSystem#1{%
\begin{center}
System #1
\end{center}
}
+
\begin{verbatim}
\newcommand{\betweenLilyPondSystem}[1]{%
\begin{center}
@@ -1834,42 +1851,53 @@ System #1
\end{center}
}
\end{verbatim}
+
\bigskip
+
\begin{lilypond}[]
{
\repeat unfold 30 { c' d' e' d' }
}
\end{lilypond}
+
\let\betweenLilyPondSystem\undefined
+
\addcontentsline{toc}{subsection}{Insert Inline}
\hypertarget{insert-inline}{}
+
\section*{Insert Scores Inline}
+
With the \option{insert=inline} option it is simple to insert arbitrary
notational fragments in the \lilypond{ e'8 d'16 e' } continuous text of a
document. By default the staffsize is scaled to be 2/3 of the staffsize a
regular score would have at this point. This means if the \option{staffsize}
option is modified globally or locally then the staffsize of the inline score is
changed too.
+
In order to make the size of inline scores independent from the regular
staffsize the option \option{inline-staffsize} can be used the same way as
\option{staffsize}. \lilypond[inline-staffsize=8]{ e'8 d'16 e' } has the inline
staffsize manually set to \texttt{8}.
+
\paragraph{Alignment and padding} By default inline scores are vertically
centered to a line 1/2em above the text's baseline. \lilypond[valign=top]{ e'8
d'16 e' } but the score can also be aligned \lilypond[valign=bottom]{ e'8 d'16
e' } to the top or the baseline of the text.
+
Unfortunately this can only consider the borders of the \emph{image} and not
those of the \emph{score} or the staff lines. To alleviate this situation a
specific vertical offset can be given with \option{voffset=-3pt} (or any other
\TeX\ lengths). This offset is calculated after the alignment.
\lilypond[valign=bottom,voffset=-6pt]{ e'8 d'16 e' } is inserted with
\option{valign=bottom,voffset=-4pt}.
+
Horizontally inline scores are padded by \option{hpadding=0.75ex} -- except if
they happen to appear at the beginning or end of a line, as can be seen in the
last score in the previous paragraph. \lilypond[hpadding=2em]{ e'8 d'16 e' }
Increasing the \option{hpadding} will ensure more space around the score.
+
\paragraph{Bare Inline scores} \option{insert=bare-inline} will remove all the
staff elements (staff symbol, time signature, clef) by implicitly applying
\option{nostaff}, which is most useful for including notational symbols like
@@ -1885,121 +1913,165 @@ possibility of inserting arbitrary LilyPond material without having to prepare
precompiled PDF images.
+
\addcontentsline{toc}{subsection}{Choosing Systems}
\hypertarget{print-only}{}
+
\def\postLilyPondExample{\par\bigskip\hrule\par\bigskip}
+
\section*{Print only Selected Systems or Pages}
+
The \texttt{print-only} and \texttt{do-not-print} options allow to limit
the printed systems or pages from a score. A typical use case is to print
a score interspersed with comments. The advantage of this approach is that
the score is compiled only once while the individual systems are simply
reused by \LaTeX.
+
Throughout this document we'll demonstrate the different options to
select systems from the following score:
+
\lilypondfile[verbatim]{eight-systems.ly}
+
The simplest selection is a single system: \texttt{print-only=4}
+
\lilypondfile[print-only=4]{eight-systems.ly}
+
Ranges are also possible: \texttt{print-only=3-5}, with the special form of
\texttt{print-only=6-} which prints from the given system throughout the end of
the score. Negative ranges can be given with \texttt{print-only=7-5}
+
\lilypondfile[print-only=3-5]{eight-systems.ly}
+
\lilypondfile[print-only=6-]{eight-systems.ly}
+
\lilypondfile[print-only=7-5]{eight-systems.ly}
+
With a comma-separated list an arbitrary sequence of systems can be specified.
The list has to be enclosed in curly brackets: \texttt{print-only={4,1,2}}
+
\lilypondfile[print-only={4,1,2}]{eight-systems.ly}
+
Each element of the list can include any of the forms described above:\\
\texttt{print-only={3,5-7,4,7-}}
+
\lilypondfile[print-only={3,5-7,4,7-}]{eight-systems.ly}
+
\texttt{do-not-print} does the opposite: it prevents the list of systems from
being printed. It might be used alone, or in combination with
\texttt{print-only}:\\
\texttt{print-only=3-,do-not-print=6}
+
\lilypondfile[print-only=3-,do-not-print=6]{eight-systems.ly}
+
The functionality is identical with fullpage scores where the selection applies
to \emph{pages} instead. This can for example be used when the “score” file
contains a number of individual pieces (e.g. songs for a song book), and
individual selections are to be printed.
+
Systems have some specific behaviour with regard to \emph{indent},
but this is demonstrated in its own file \texttt{dynamic-indent.tex}.
+
\let\postLilyPondExample\undefined
+
\addcontentsline{toc}{subsection}{Dynamic Indent Handling}
\hypertarget{dynamic-indent}{}
+
\def\postLilyPondExample{\par\bigskip\hrule\par\bigskip}
+
\section*{Dynamic Indent}
+
This document demonstrates the use of \texttt{indent} and \texttt{autoindent},
partially in combination with \texttt{print-only}.
+
\texttt{indent=1cm} indents the first line, but if the resulting score contains
only one system this indent is suppressed (issuing a warning on the console):
+
\begin{lilypond}[indent=1cm]
\set Staff.instrumentName = "Violin"
\repeat unfold 12 { c' d' e' d' }
\end{lilypond}
+
\begin{lilypond}[indent=1cm]
{
\set Staff.instrumentName = "Violin"
c' d' e' d'
}
\end{lilypond}
+
If the output of a score which contains more than one system is limited to the
first system using \texttt{print-only=1} then the indent is removed but the
score is recompiled to ensure a full-length system. The following score shows
the two-system score from above (with \texttt{indent=1cm}), limited to its first
system:
+
\begin{lilypond}[indent=1cm,print-only=1]
\set Staff.instrumentName = "Violin"
\repeat unfold 12 { c' d' e' d' }
\end{lilypond}
+
Note that this behaviour also applies when \texttt{print-only} causes the first
system to be printed at another position, e.g. with \texttt{print-only={3,1,2}}.
In this case the indent of the first system is suppressed in order to avoid a
“hole”. Of course this is a corner case, but might be useful when a score
consists of separate entities (examples, exercises) per system.
+
\begin{lilypond}[indent=1cm,print-only={3,1,2},max-protrusion=0.5cm]
\repeat unfold 25 { c' d' e' d' }
\end{lilypond}
+
If a protrusion limit has been set with \texttt{max-protrusion=0.5cm} and the
score exceeds that limit in spite of \texttt{indent=1cm} then the whole score
will appropriately be narrowed:
+
\begin{lilypond}[indent=1cm,max-protrusion=0.5cm]
\set Staff.instrumentName = "Violin I. and II."
\repeat unfold 11 { c' d' e' d' }
\end{lilypond}
+
+
This doesn't really look good because the indentation of the second system
wouldn't have been necessary since only the first system exceeds the protrusion
limit. The solution to this situation is the option \texttt{autoindent} which
handles the indentation \emph{automatically} and set the indent to a value that
will make the \emph{first} system fit into the protrusion limit and leave the
remaining systems unchanged:
+
\begin{lilypond}[autoindent=true,max-protrusion=0.5cm]
\set Staff.instrumentName = "Violin I. and II."
\repeat unfold 11 { c' d' e' d' }
\end{lilypond}
+
+
However, if the protrusion limit is not only exceeded by the \emph{first} system
(which should be the typical case due to the instrument name) \texttt{lyluatex}
will deal with the situation by narrowing the \emph{whole} score by the
appropriate amount and adjusting the indent of the first system so all systems
will just fit into the protrusion limit:
+
\begin{lilypond}[autoindent=true,max-protrusion=0.5cm]
\set Staff.instrumentName = "Violin I. and II."
\set Staff.shortInstrumentName = "Violin I/II"
\repeat unfold 11 { c' d' e' d' }
\end{lilypond}
+
There is one special case to be mentioned. As described above the indent is
deactivated if the first system of a score is printed at a later position.
However, if this score will exceed the left protrusion limit \texttt{autoindent}
will be automatically activated to avoid having the \emph{whole} score narrowed:
+
\begin{lilypond}[indent=1cm,print-only={3,1,2},max-protrusion=0.5cm]
\set Staff.instrumentName = "Violin"
\repeat unfold 25 { c' d' e' d' }
\end{lilypond}
+
\paragraph{Right protrusion}
The dynamic handling of (automatic) indent also works correctly when there is
protrusion handling to the right. The following score has the ties manually
shaped to exceed the staff symbol by 10, and 7 staff spaces, and
\texttt{max-protrusion=1cm} .
+
\begin{lilypond}[nofragment,max-protrusion=1cm,]
{
\set Staff.instrumentName = "Violin 1 & 2"
@@ -2011,42 +2083,57 @@ shaped to exceed the staff symbol by 10, and 7 staff spaces, and
c'
}
\end{lilypond}
+
+
\paragraph{Performance considerations}
The handling of indent suppression may require up to four compilations of the
score, but these are handled automatically, and the resulting intermediate
stages of the score are cached just like the scores actually used in the
document.
+
The \texttt{autoindent} option is active by default but will be deactivated if
\texttt{indent} is set explicitly. It has to be noted that this option will add
more LilyPond compilations and therefore compilation time. But it will only
apply and be executed if the score exceeds the protrusion limit, so it can only
occur in circumstances where multiple LilyPond runs are expected anyway.
+
\let\postLilyPondExample\undefined
+
\addcontentsline{toc}{subsection}{Font Handling}
\hypertarget{fonts}{}
+
\defaultfontfeatures{Ligatures=TeX,Numbers=OldStyle,Scale=MatchLowercase}
\setmainfont{Linux Libertine O}
\setsansfont[BoldFont={Linux Biolinum O Bold}]{Linux Biolinum O}
\setmonofont{Inconsolata}
+
\section*{Font Handling}
+
To demonstrate the font handling features of \lyluatex\ we will repeatedly
include the following score from an external file. It includes roman (lyrics,
instrument name), sans (rehearsal mark), and mono (tempo) text, first using
LilyPond's built-in default fonts.
+
\lilypondfile[verbatim]{fonts}
+
\bigskip
The current document uses \option{fontspec} to set roman font to \emph{Linux
Libertine O}, sans font to \emph{Linux Biolinum O}, and mono font to
\emph{Inconsolata}. So if you compile this document yourself and don't have
these fonts installed you will receive unexpected results.
+
\subsection*{Passing Document Fonts to Score}
+
With \option{pass-fonts} the currently active font families for roman, sans, and
mono fonts are passed to LilyPond in order to achieve the most coherent
appearance between text and music.
+
\bigskip
+
\lilypondfile[pass-fonts]{fonts}
+
\bigskip
Note that LilyPond loads fonts differently than \LaTeX\ and can only make use of
fonts installed as system fonts, fonts that are only installed through a \LaTeX\
@@ -2054,11 +2141,14 @@ distribution are not accessible to it. That means that if the document fonts are
not installed system-wide (e.\,g. the default fonts) LilyPond will use rather
ugly fallback fonts. This can't be demonstrated here but the section about
explicitly setting font families will include an example.
+
The inherent problem of fallback fonts, especially with \LaTeX's default
settings, is the reason \option{pass-fonts} is inactive by default. But the
general recommendation is to set \option{pass-fonts} as package option if the
text document uses fonts that are available to LilyPond.
+
\bigskip
+
\sffamily \option{current-font-as-main} will use the font that is
\emph{currently} used for typesetting as LilyPond's main (roman) font. This can
make sure that the score's main font (and roman is usually the font used most in
@@ -2069,9 +2159,12 @@ is one of the two others. Additionally this \emph{may} introduce an
inconsistency not between the score and the surrounding text but between
different scores in a document. For all these reasons the option is by default
set to \texttt{false}.
+
\bigskip
\lilypondfile[pass-fonts,current-font-as-main]{fonts}
+
\subsection*{Setting Score Fonts Explicitly}
+
With \option{rmfamily}, \option{sffamily}, and \option{ttfamily} specific
families can be set to arbitrary fonts, independently from the text document.
For the following score \option{ttfamily=\{TeXGyre Adventor\}} is
@@ -2079,24 +2172,31 @@ used.\footnote{Note that this font (which is included in TeXLive) has to be
installed if you want to successfully compile this document.} Note that this
implicitly sets \option{pass-fonts=true}, and \emph{Linux Libertine O} and
\emph{Linux Biolinum O} are used from the text document.
+
\bigskip
\lilypondfile[ttfamily={TeXGyre Adventor}]{fonts}
+
\highlight{NOTE:} when \option{rmfamily} is set explicitly
\option{current-font-as-main} is forced to \texttt{false} to ensure that the
roman font is actually used. The next score sets \option{rmfamily=\{TeXGyre
Adventor\}} and \option{current-font-as-main}, and despite the current font still being \cmd{sffamily}
\emph{Adventor} is used as the score's main font:
+
\bigskip
\lilypondfile[current-font-as-main,rmfamily={TeXGyre Adventor}]{fonts}
+
\subsection*{LilyPond's Font Fallback}
+
If unavailable fonts are set in a LilyPond document they will \emph{silently} be
replaced with fallback fonts that tend to cause ugly results. This will be shown
by setting \option{rmfamily=FantasyFontOne}, \option{sffamily=FantasyFontTwo},
and \option{tfamily=FantasyFontThree}:
+
\bigskip
\lilypondfile[rmfamily=FantasyFontOne,%
sffamily=FantasyFontTwo,%
ttfamily=FantasyFontThree]{fonts}
+
This can happen in several contexts: apart from compiling the document on a
different computer where the used fonts are missing it is most likely to occur
with the \option{pass-fonts} option, when the text document uses internal
@@ -2104,6 +2204,7 @@ with the \option{pass-fonts} option, when the text document uses internal
family is specified explicitly with an option and the other families are passed
from the text document.
+
\defaultfontfeatures{Ligatures=TeX,Numbers=OldStyle,Scale=MatchLowercase}
\setmainfont{Linux Libertine O}
\setsansfont[BoldFont={Linux Biolinum O Bold}]{Linux Biolinum O}
@@ -2111,18 +2212,29 @@ from the text document.
\addcontentsline{toc}{subsection}{Wrapping Commands}
\hypertarget{wrappingcommands}{}
+
\VerbatimFootnotes
+
\section*{Wrapping Commands}
+
\subsection*{Command within commands}
+
\cmd{lily} can be wrapped within another command as usual:
+
\begin{verbatim}
\newcommand\mylily[2][1]{\lily[inline-staffsize=10, #1]{#2}}
+
This is \mylily[voffset=10pt]{a' b' c''} an example.
\end{verbatim}
+
\newcommand\mylily[2][1]{\lily[inline-staffsize=10, #1]{#2}}
+
This is \mylily[voffset=10pt]{a' b' c''} an example.\par
+
\subsection*{Environment within environments}
+
\emph{It isn't possible to wrap \highlight{ly} environment within a command.}\par
+
It's possible to wrap \highlight{ly} within and environment, but there are
several drawbacks\footnote{%
Those drawbacks are:
@@ -2140,8 +2252,10 @@ Those drawbacks are:
\end{itemize}
\end{itemize}%
}.
+
To avoid those drawbacks, \lyluatex\ defines a special command, \verb`\lynewenvironment`,
that behaves as you'd expect from \verb`\newenvironment`.
+
\begin{verbatim}
\lynewenvironment{myly}{%
This is \emph{my} lilypond environment.
@@ -2149,19 +2263,23 @@ that behaves as you'd expect from \verb`\newenvironment`.
}{%
\end{ly}
}
+
\begin{myly}
a b c
\end{myly}
\end{verbatim}
+
\newenvironment{myly}{%
This is \emph{my} lilypond environment.
\begin{ly}%
}{%
\end{ly}
}
+
\begin{myly}
a b c
\end{myly}
+
\begin{verbatim}
\lynewenvironment{lyfigure}[2][]{%
\edef\mycaption{#2}
@@ -2174,11 +2292,13 @@ that behaves as you'd expect from \verb`\newenvironment`.
\end{center}
\end{figure}
}
+
\begin{lyfigure}{This is a caption}
a' b' c
d' e' f
\end{lyfigure}
\end{verbatim}
+
\lynewenvironment{lyfigure}[2][]{%
\edef\mycaption{#2}
\begin{figure}
@@ -2190,10 +2310,12 @@ d' e' f
\end{center}
\end{figure}
}
+
\begin{lyfigure}{This is a caption}
a' b' c
d' e' f
\end{lyfigure}
+
\begin{verbatim}
\lynewenvironment{lyotherfigure}[1][]{%
\edef\option{#1}
@@ -2206,11 +2328,13 @@ d' e' f
\endcenter
\endfigure
}
+
\begin{lyotherfigure}
d' e' f
a' b' c
\end{lyotherfigure}
\end{verbatim}
+
\lynewenvironment{lyotherfigure}[1][]{%
\edef\option{#1}
\figure
@@ -2222,23 +2346,28 @@ a' b' c
\endcenter
\endfigure
}
+
\begin{lyotherfigure}
d' e' f
a' b' c
\end{lyotherfigure}
+
\begin{verbatim}
\begin{lyotherfigure}[This time with a caption]
d' e' f
a' b' c
\end{lyotherfigure}
\end{verbatim}
+
\begin{lyotherfigure}[This time with a caption]
d' e' f
a' b' c
\end{lyotherfigure}
+
\textbf{Important note:} \verb`\lynewenvironment` is intended to insert \LaTeX\ code before
and after the scores; due to the special behavior of \verb`ly` environment, it isn't possible
to insert \emph{LilyPond} code that way. So this won't work:
+
\begin{verbatim}
\lynewenvironment{myly}{%
\begin{ly}
@@ -2247,26 +2376,33 @@ to insert \emph{LilyPond} code that way. So this won't work:
\end{ly}
}
\end{verbatim}
+
To do such a thing, \lyluatex\ defines a command and four options:
\begin{itemize}
\item \verb`\lysavefrag` lets one save a LilyPond fragment to be re-used afterward;
\item \verb`include_header`, \verb`include_footer`, \verb`include_before_body` and \verb`include_after_body` options
let one insert such fragments at designed places within inserted score.
\end{itemize}
+
So this works:
+
\begin{verbatim}
\begin{lysavefrag}{head}
a b c
\end{lysavefrag}
+
\begin{lysavefrag}{foot}
g a' b
\end{lysavefrag}
+
\begin{lysavefrag}{mymark}
\mark \default
\end{lysavefrag}
+
\begin{lysavefrag}{mymark}
\mark \default
\end{lysavefrag}
+
begin{ly}[
include_before_body={head,mymark,head},
include_after_body=foot,
@@ -2274,17 +2410,22 @@ begin{ly}[
d e f
\end{ly}
\end{verbatim}
+
It's also possible to use \verb`\lynewenvironment` to wrap such a command:
+
\begin{verbatim}
\begin{lysavefrag}{head}
a b c
\end{lysavefrag}
+
\begin{lysavefrag}{foot}
g a' b
\end{lysavefrag}
+
\begin{lysavefrag}{mymark}
\mark \default
\end{lysavefrag}
+
\lynewenvironment{yourly}[1][]{%
{\centering test \par}
\begin{ly}[
@@ -2294,19 +2435,24 @@ g a' b
}{
\end{ly}
}
+
\begin{yourly}
d e f
\end{yourly}
\end{verbatim}
+
\begin{lysavefrag}{head}
a b c
\end{lysavefrag}
+
\begin{lysavefrag}{foot}
g a' b
\end{lysavefrag}
+
\begin{lysavefrag}{mymark}
\mark \default
\end{lysavefrag}
+
\lynewenvironment{yourly}[1][]{%
{\centering test \par}
\begin{ly}[
@@ -2316,27 +2462,34 @@ g a' b
}{
\end{ly}
}
+
\begin{yourly}
d e f
\end{yourly}
+
\addcontentsline{toc}{subsection}{Wrapping Raw PDF Filenames}
\hypertarget{insert-raw-pdf}{}
+
\section*{Wrapping Raw PDF Filenames}
+
With the \option{raw-pdf} option it is possible to create wrapping commands that
circumvent \lyluatex's layout considerations by working with the raw PDF
filename of the generated score. This is especially useful for developing
packages or personal class and style files. For this scores generated with
\option{raw-pdf} define a command \cmd{lyscore} that can be used in the wrapping
commands or environments.
+
All examples in this document could also be realized using “default” \lyluatex\
without \option{raw-pdf}, but they are intended to show how this low-level
access can be used to retrieve the information from the generated score in order
to build custom versions of commands that don't have to adhere to \lyluatex's
pre-built strategies of including the score in the document
+
The easiest way to use a “raw” score is to simply access \cmd{lyscore} in a
command and pass it to an \cmd{includegraphics} macro:
+
\begin{verbatim}
\newcommand\lilyinline[2][]{%
\lily[raw-pdf,%
@@ -2348,27 +2501,33 @@ command and pass it to an \cmd{includegraphics} macro:
\includegraphics{\lyscore{}}%
}
\end{verbatim}
+
\newcommand\lilyinline[2][]{%
\lily[raw-pdf,insert=bare-inline,inline-staffsize=8,hpadding=0.25ex,#1]{
\omit Stem
#2}%
\includegraphics{\lyscore{}}%
}
+
This basically is a way to provide pre-configured commands. In this case
\lilyinline{ c'8 d' c' d'} it is used to pre-configure an inline
type, entered as \verb+\lilyinline{ c'8 d' c' d'}+.
+
+
\bigskip \cmd{lyscore} takes one mandatory argument which can be empty -- as in
the example above --, receive a number, one of the keywords \texttt{nsystems}
and \texttt{hoffset}, or any of the score's options. If passed a number it will
return the filename of the N-th system. With \texttt{nsystems} the number of
systems in the generated score will be returned, while \texttt{hoffset}
generates the code that shifts the score to the left to accommodate protrusion.
+
The following example takes an optional argument with options that are passed to
\lyluatex, and one mandatory argument which expects the system to be used. It
prints the given system centered in a figure and uses the file name as the
caption and makes use of the score's \texttt{label}. Figure \ref{centered} shows
the centering of a short fragment, figure \ref{fifth} the selection of the fifth
system from a larger score.
+
\begin{verbatim}
\newenvironment{centeredlilypondsystem}[2][]{%
\def\usesystem{#2}
@@ -2383,13 +2542,16 @@ system from a larger score.
\end{center}
\end{figure}
}
+
\begin{centeredlilypondsystem}[label=centered]{1}
c'1 d' e'
\end{centeredlilypondsystem}
+
\begin{centeredlilypondsystem}[label=fifth]{5}
\repeat unfold 8 { c'1 \break }
\end{centeredlilypondsystem}
\end{verbatim}
+
\newenvironment{centeredlilypondsystem}[2][]{%
\def\usesystem{#2}
\begin{figure}
@@ -2403,17 +2565,22 @@ system from a larger score.
\end{center}
\end{figure}
}
+
\begin{centeredlilypondsystem}[label=centered]{1}
c'1 d' e'
\end{centeredlilypondsystem}
+
\begin{centeredlilypondsystem}[label=fifth]{5}
\repeat unfold 8 { c'1 \break }
\end{centeredlilypondsystem}
+
+
Finally there's an example showing how to iterate over the systems of a score
using \cmd{foreach} from the \option{pgffor} package. It iterates over all the
systems in the given score, prints them using the protrusion adjustment seen
before, and if the system is the third it prints this information, otherwise
just a line break:
+
\begin{verbatim}
\newcommand\myforlily[2][]{%
\lily[insert=systems,raw-pdf,#1]{#2}%
@@ -2422,10 +2589,12 @@ just a line break:
\ifthenelse{\equal{\n}{3}}{\par Third system\par}{\\}
}%
}
+
\myforlily[staffsize=24]{
\set Staff.instrumentName = "Vl. "
\repeat unfold 4 { c'1 \break } }
\end{verbatim}
+
\newcommand\myforlily[2][]{%
\lily[insert=systems,raw-pdf,#1]{#2}%
\foreach \n in {1,...,\lyscore{nsystems}}%
@@ -2433,9 +2602,11 @@ just a line break:
\ifthenelse{\equal{\n}{3}}{\par\bigskip Third system\par\bigskip}{\\}
}%
}
+
\myforlily[staffsize=24]{
\set Staff.instrumentName = "Vl. "
\repeat unfold 4 { c'1 \break } }
+
\end{document}
diff --git a/support/lyluatex/lyluatexbase.cls b/support/lyluatex/lyluatexbase.cls
index 1e8b048dd8..fb72c667d6 100644
--- a/support/lyluatex/lyluatexbase.cls
+++ b/support/lyluatex/lyluatexbase.cls
@@ -1,11 +1,11 @@
%Lyluatex LaTeX class.
%
-% Copyright (C) 2015-2019 jperon and others (see CONTRIBUTORS.md)
+% Copyright (C) 2015-2022 jperon and others (see CONTRIBUTORS.md)
% License: MIT
% This file is part of lyluatex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{lyluatexbase}[2019/05/27 v1.0f] %%LYLUATEX_DATE LYLUATEX_VERSION
+\ProvidesClass{lyluatexbase}[2022/10/30 v1.1] %%LYLUATEX_DATE LYLUATEX_VERSION
\LoadClass[DIV=11]{scrartcl}
\RequirePackage{lyluatex}
@@ -16,7 +16,7 @@
\RequirePackage{pgffor}
\RequirePackage{fancyvrb}
\RequirePackage[colorlinks=true]{hyperref}
-\lysetoption{includepaths}{./, ly/}
+\setluaoption{ly}{includepaths}{./, ly/}
% Common formatting elements for manual and examples
diff --git a/support/lyluatex/lyluatexmanual.cls b/support/lyluatex/lyluatexmanual.cls
index 8e1a85d290..16399004c2 100644
--- a/support/lyluatex/lyluatexmanual.cls
+++ b/support/lyluatex/lyluatexmanual.cls
@@ -1,11 +1,11 @@
%Lyluatex LaTeX class for the manual.
%
-% Copyright (C) 2015-2019 jperon and others (see CONTRIBUTORS.md)
+% Copyright (C) 2015-2022 jperon and others (see CONTRIBUTORS.md)
% License: MIT
% This file is part of lyluatex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{lyluatexmanual}[2019/05/27 v1.0f] %%LYLUATEX_DATE LYLUATEX_VERSION
+\ProvidesClass{lyluatexmanual}[2022/10/30 v1.1] %%LYLUATEX_DATE LYLUATEX_VERSION
\LoadClass{lyluatexbase}
@@ -35,7 +35,7 @@
local PC = string.char(37)
local date_fmt = PC..'Y-'..PC..'m-'..PC..'d'
local p = io.popen('git log -n1 --date=short --format='..PC..'"ad"', 'r')
- tex.sprint(p and p:read('*a') or os.date(date_fmt))
+ tex.sprint(p and p:read('*a'):sub(1,-2) or os.date(date_fmt))
if p then p:close() end
}
-} \ No newline at end of file
+}