diff options
Diffstat (limited to 'Master/texmf-dist/scripts/lyluatex')
-rwxr-xr-x | Master/texmf-dist/scripts/lyluatex/lyluatex-lib.lua | 163 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua | 266 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/lyluatex/lyluatex.lua | 275 |
3 files changed, 145 insertions, 559 deletions
diff --git a/Master/texmf-dist/scripts/lyluatex/lyluatex-lib.lua b/Master/texmf-dist/scripts/lyluatex/lyluatex-lib.lua deleted file mode 100755 index ebe6745eb59..00000000000 --- a/Master/texmf-dist/scripts/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/Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua b/Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua deleted file mode 100755 index 62ec72a3c3c..00000000000 --- a/Master/texmf-dist/scripts/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/Master/texmf-dist/scripts/lyluatex/lyluatex.lua b/Master/texmf-dist/scripts/lyluatex/lyluatex.lua index 1023e20ef9a..adb17a63a01 100755 --- a/Master/texmf-dist/scripts/lyluatex/lyluatex.lua +++ b/Master/texmf-dist/scripts/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 |