TUGBOAT

Volume 39, Number 2 / 2018 TUG 2018 Conference Proceedings

TUG 2018 98 Conference sponsors, participants, program 100 Joseph Wright / TUG goes to Rio 104 Joseph Wright / TEX Users Group 2018 Annual Meeting notes Graphics 105 Susanne Raab / The tikzducks package A L TEX 107 Frank Mittelbach / A rollback concept for packages and classes 113 Will Robertson / Font loading in LATEX using the fontspec package: Recent updates 117 Joseph Wright / Supporting color and graphics in expl3 119 Joseph Wright / siunitx: Past, present and future & Tools 122 Paulo Cereda / Arara — TEX automation made easy 126 Will Robertson / The Canvas learning management system and LATEXML 131 Ross Moore / Implementing PDF standards for mathematical publishing Fonts 136 Jaeyoung Choi, Ammar Ul Hassan, Geunho Jeong / FreeType MF Module: A module for using METAFONT directly inside the FreeType rasterizer Methods 143 S.K. Venkatesan / WeTEX and Hegelian contradictions in classical mathematics Abstracts 147 TUG 2018 abstracts (Behrendt, Coriasco et al., Heinze, Hejda, Loretan, Mittelbach, Moore, Ochs, Veytsman, Wright)

149 MAPS: Contents of issue 48 (2018) 150 Die TEXnische Kom¨odie: Contents of issues 2–3/2018 151 Eutypon: Contents of issue 38–39 (October 2017) General Delivery 151 Bart Childs and Rick Furuta / Don Knuth awarded Trotter Prize 152 Barbara Beeton / Hyphenation exception log Book Reviews 153 Boris Veytsman / Book review: W. A. Dwiggins: A Life in Design by Bruce Kennett Hints & Tricks 155 Karl Berry / The treasure chest Cartoon 156 John Atkinson / Hyphe-nation; Clumsy Advertisements 157 TEX consulting and production services TUG Business 158 TUG institutional members 159 TUG 2019 election News 160 Calendar TEX Users Group Board of Directors † TUGboat (ISSN 0896-3207) is published by the Donald Knuth, Grand Wizard of TEX-arcana ∗ TEX Users Group. Web: tug.org/TUGboat. Boris Veytsman, President Arthur Reutenauer∗, Vice President ∗ Individual memberships Karl Berry , Treasurer ∗ 2018 dues for individual members are as follows: Susan DeMeritt , Secretary Regular members: $105. Barbara Beeton Special rate: $75. Johannes Braams The special rate is available to students, seniors, and Kaja Christiansen citizens of countries with modest economies, as de- Taco Hoekwater tailed on our web site. Members also have the op- Klaus H¨oppner tion to receive TUGboat and other benefits electron- Frank Mittelbach ically, at a discount. Ross Moore Membership in the TEX Users Group is for the Cheryl Ponchin calendar year, and includes all issues of TUGboat for Norbert Preining the year in which membership begins or is renewed, Will Robertson as well as software distributions and other benefits. Herbert Voß Individual membership carries with it such rights Raymond Goucher, Founding Executive Director † and responsibilities as voting in TUG elections. All Hermann Zapf (1918–2015), Wizard of Fonts ∗ the details are on the TUG web site. member of executive committee †honorary Journal subscriptions See tug.org/board.html for a roster of all past and TUGboat subscriptions (non-voting) are available to present board members, and other official positions. organizations and others wishing to receive TUG- boat in a name other than that of an individual. Addresses Electronic Mail The subscription rate for 2018 is $110. TEX Users Group General correspondence, P.O. Box 2311 membership, subscriptions: Institutional memberships Portland, OR 97208-2311 [email protected] U.S.A. Institutional membership is primarily a means of Submissions to TUGboat, showing continuing interest in and support for TEX letters to the Editor: Telephone and TUG. It also provides a discounted membership [email protected] +1 503 223-9994 rate, site-wide electronic access, and other benefits. Technical support for Fax For further information, see tug.org/instmem.html T X users: +1 815 301-3568 E or contact the TUG office. [email protected] Web Contact the Trademarks tug.org Board of Directors: Many trademarked names appear in the pages of tug.org/TUGboat [email protected] TUGboat. If there is any question about whether a name is or is not a trademark, prudence dictates that it should be treated as if it is. Copyright c 2018 TEX Users Group. Copyright to individual articles within this publication remains with their authors, so the articles may not be reproduced, distributed or translated without the authors’ permission. For the editorial and other material not ascribed to a particular author, permission is granted to make and distribute verbatim copies without royalty, in any medium, provided the copyright notice and this permission notice are preserved. Permission is also granted to make, copy and distribute translations of such editorial material into another language, except that the TEX Users Group must approve [printing date: September 2018] translations of this permission notice itself. Lacking such approval, the original English permission notice must Printed in U.S.A. be included. 2018 Conference Proceedings TEX Users Group Thirty-eighth annual TUG meeting Rio de Janeiro, Brazil July 20–22, 2018

COMMUNICATIONS OF THE TEX USERS GROUP TUGBOAT EDITOR BARBARA BEETON PROCEEDINGS EDITOR KARL BERRY

VOLUME 39, NUMBER 2, 2018 PORTLAND,OREGON, U.S.A. 98 TUGboat, Volume 39 (2018), No. 2

TUG 2018 — Rio de Janeiro, Brazil https://tug.org/tug2018 [email protected] Room 232 IMPA — Instituto de Matem´atica Pura e Aplicada Estr. Dona Castorina, 110 Jardim Botˆanico Rio de Janeiro, RJ 22460-320

TUG 2018 was an official satellite conference of ICM 2018.

Sponsors TEX Users Group DANTE e.V. ICM’18 with special assistance from individual contributors. Thanks to all! Special guests from the Lua team Waldemar Celes Luiz Henrique de Figueiredo Roberto Ierusalimschy Conference committee Karl Berry Paulo Cereda Robin Laakso Paulo Ney de Souza Boris Veytsman

Participants Francisco J Alves, Rio de Janeiro Mico Loretan, Zurich, Switzerland Maynara Azevedo Aredes, Federal University of Jonas Malaco, Rio de Janeiro Rio de Janeiro Frank Mittelbach, LATEX Project Felipe da Silva Barreto, Rio de Janeiro Ross Moore, Macquarie University Nelson Beebe, University of Utah Eduardo Ochs, UFF Doris Behrendt, DANTE e.V. Matheus Rocha de Souza Ramos, Ufes Waldemar Celes, PUC-Rio & Lua team Ana Claudia Ribeiro, E-papers Servi¸cos Editoriais Paulo Cereda, University of S˜aoPaulo Will Robertson, University of Adelaide Jaeyoung Choi, Soongsil University Chris Rowley, PCEC and LATEX Marcel de Sena Dall’Agnol, Rio de Janeiro Volker RW Schaa, DANTE e.V. Luiz Henrique de Figueiredo, IMPA & Lua team Paulo Ney de Souza, University of California, Gert Fischer, M¨onchengladbach, Germany Berkeley & BooksInBytes Ulrike Fischer, M¨onchengladbach, Germany Arthur Szasz, Protocubo Mylena da Silva Gomes, Rio de Janeiro S.K. Venkatesan, TNQ Joachim Heinze, Senior Advisor Mathematics Boris Veytsman, George Mason University Sciences, Heidelberg & Chan Zuckerberg Initiative Tom Hejda, Charles University Prague Joseph Wright, LATEX Project Roberto Ierusalimschy, PUC-Rio & Lua team Eduardo Kalinowski, Brasilia TUG 2018 program

Friday 8:00 am registration July 20 8:55 am Paulo Ney de Souza, Opening UC Berkeley & BooksInBytes 9:00 am Roberto Ierusalimschy, The making of Lua PUC-Rio & Lua team 9:45 am Eduardo Ochs, UFF Dednat6: An extensible (semi-)preprocessor for LuaLATEX that understands diagrams in ASCII art 10:20 am break 10:45 am Mico Loretan, Zurich, Switzerland Selective ligature suppression with the selnolig package 11:15 am Joseph Wright, LATEX Project Fly me to the moon: (LA)TEX testing (and more) using Lua 11:50 am Paulo Cereda, University of S˜aoPaulo From parrot 1.0 to phoenix 4.0: 6 years of arara, the beginning of a new era 12:25 pm lunch 1:45 pm Will Robertson, University of Creating teaching material with LATEXML for the Canvas Adelaide Learning Management System 2:25 pm Ross Moore, Macquarie University Authoring accessible ‘Tagged PDF’ documents using LATEX 3:00 pm break 3:20 pm S. Coriascoet al., Universit`adi Torino An automated method based on LATEX for the realization of accessible PDF documents containing formulae 3:55 pm Doris Behrendt, DANTE e.V. The General Data Protection Regulation (GDPR) in the European Union 4:30 pm TUG Annual General Meeting 4:30 pm Workshop: Accessibility challenges in LATEX Saturday 8:55 am announcements July 21 9:00 am Frank Mittelbach, LATEX Project A quarter century of doc 9:35 am Joseph Wright Through the looking glass, and what Joseph found there 10:10 am break 10:30 am Boris Veytsman, George Mason Univ. Stubborn leaders six years later & Chan Zuckerberg Initiative 11:05 am Joseph Wright siunitx: Past, present and future 11:40 am Frank Mittelbach Compatibility in the world of LATEX 12:40 pm lunch 2:00 pm Paulo Ney de Souza Minimizing LATEX files — First steps to automated journal processing 2:35 pm Tom Hejda, Charles University yoin — Yet another package for automation of journal Prague typesetting 3:10 pm break 3:30 pm Joachim Heinze The unchanged changing world of mathematical publishing 4:05 pm Boris Veytsman R+ workshop (tug.org/tug2018/workshops.html) Sunday 8:55 am announcements July 22 9:00 am S.K. Venkatesan and TNQ Lab WeTEX(WYSIWYG and LATEX) and Hegelian contradictions in classical mathematics 9:35 am Susanne Raab, Paulo Cereda* A short introduction to the TikZducks package 10:10 am break 10:30 am Jaeyoung Choi, Soongsil University FreeType MF Module: A module for using METAFONT directly inside FreeType’s rasterizer 11:05 pm Will Robertson Unicode fonts with fontspec and unicode-math 11:40 am lunch 1:00 pm bus to Sugarloaf ≈ 5:30 pm return to hotel * = presenter 100 TUGboat, Volume 39 (2018), No. 2

TUG goes to Rio classes of words with only a small number of discrete settings. An interesting aspect of this work is how Joseph Wright variable the ligature support is in OpenType fonts, TUG 2018 took place in Rio de Janeiro, Brazil, at in particular what constitutes a ‘common’ ligature. the Instituto de Matem´atica Pura e Aplicada (IMPA). I spoke next, focussing on l3build [11]. I gave Most of the foreign attendees had chosen to stay at a brief overview of LATEX testing, from the earliest the ‘official’ hotel, which meant that as well as the days of the team to the current day. I covered why formal business, there was plenty of time to talk over we’ve picked Lua for our current testing set-up, what breakfast and in the evenings. That was evident in works and what (currently) doesn’t. Looking forward reception the evening before the meeting, and even to other talks, the need for PDF-based testing came more so at breakfast on the first morning. This was up in discussions of tagging, and is very much on the a good chance to catch up with old friends. l3build ‘to do’ list. Paulo Cereda then talked about his build tool, 1 Day one arara [1]. He started with an overview of other tools, After a (brief) introduction from the conference chair, before explaining how arara is different: it is at heart Paulo Ney de Souza, the floor was handed to Roberto a ‘no-guesswork’ approach. He showed us the core, Ierusalimschy to start us with a bang: an overview simple, syntax, before moving on to a time-line of of Lua development. He gave us an insight into releases to date. He summed up the new features in how Lua grew from early beginnings, and how it got version 4.0, before moving to a series of live demon- picked up by games developers: a big part of Lua’s strations. These started with simple ideas and moved importance. He then gave us an insight into the two on to new, complex ideas such as conditionals and key aspects of Lua’s success: the ability to embed taking user input. He then finished by looking to the and extend the language. That led to Lua being future, both of arara and of araras (macaws). embedded in a range of applications, not only games Lunch was arranged in the IMPA caf´e, giving but also devices as varied as cars and routers. We us all a chance to absorb the morning’s information had a lively question session, ranging from Unicode and take on all-important sustenance. The caf´eis support to what might have been done differently if right by the forest, so we also took the opportunity the Lua team didn’t have any users to worry about! to take in the local wildlife. We then moved on to Eduardo Ochs, talking We started back after lunch with a couple of about using Lua as a pre-parser to convert ‘ASCII art’ slides from Barbara Beeton, absent from the meeting, into complex mathematical diagrams. He explained presented by TUG President Boris Veytsman. I think the history: the origin of ASCII art as comments to everyone was pleased to hear from Barbara, even if help understand sometimes complex TEX code! After at one remove. a summary of the original pre-processor, he showed Will Robertson then took the podium. He star- how using Lua(TEX), the processing can be done ted with some thoughts on questions he gets as an in-line in the file with no true pre-processing step. Australian (no TEX involved). His koala pictures He showed how this can be set up in an extensible were particularly fun. His talk proper was on his and powerful way, using Lua to do the ‘heavy lifting’. work with the Learning Management System (LMS) After the coffee break, we reconvened for three used by his employer. This system (Canvas) has a talks. Mico Loretan started, describing his package programmable API for controlling information made selnolig [4]. He started by showing us examples of available to students. He laid out the issues with the ‘unfortunate’ ligatures in English words, and how documentation he had: a very large, unmaintainable they can appear when suppressed by babel and by word processing document. Will talked about various selnolig. He then focussed in on some details: what tools for creating HTML from LATEX, the workflow a ligature is, why they are needed and how different he has chosen, and then showed more detail on the fonts provide them. He moved on to describe why system he is using, LATEXML. He then expanded on you need to suppress ligatures, in particular where how using LATEXML plus scripting, he can populate they cross morpheme boundaries. Mico then gave us the LMS in a (semi)automated way, making his work a very useful summary of how the linguists work here more efficient. and how they need to link to typography. After show- The second speaker in the ‘Australian panel’ ing us the issues with other approaches, he moved on session was Ross Moore. Ross started with a demo to how selnolig uses LuaTEX callbacks to influence of why tagging PDFs is needed: making the informa- ligatures ‘late’ in processing. His rule-based interface tion accessible not just to people but widely to the means that ligatures can be suppressed for whole computer, to allow re-use in alternative views. He

Joseph Wright TUGboat, Volume 39 (2018), No. 2 101

expanded on the drivers for this, in particular legal to the expandable FPU we have there. I then looked requirements for accessible documents. at creating graphics, particularly how I’ve been in- Our next talk came in remotely from Sandro spired by pgf/TikZ[9]. I showed how I’ve used the Coriasco, also dealing with aspects of tagged PDFs fact that pgf has a clear structure, and mapped that for accessibility. He started by outlining the team to expl3 concepts. I showed some examples of the involved in this work, focussed on making material existing drawing setup, and where I’ll be going next. accessible to the blind. The aim of their work has We returned after coffee for a short talk from been targeted at mathematical formula, generating Boris Veytsman on tackling an apparently simple ‘actual text’ which can then be used by screen readers issue: putting leaders level with the first line of a or similar. He finished with a ‘live demo’, and left long title! He showed that this is non-trivial, and us with lots to think about. how as a contractor he has to explain this to clients. We then had a non-TEX talk: Doris Behrendt He then showed how he solved the issue, leading to on GDPR. She started by looking at the EU Official a lively discussion about other possible approaches. Journal on the GDPR, and we had an excursion into I then came back for my second talk of the day, the font used for typesetting (Albertina). She then this time about siunitx [13]. I started by explain- gave details of the regulations, along with a number ing the history of the package, starting with the of extremely amusing examples of how people have initial comp.text. post that led to its creation. approached them. I outlined the core features, present from version 1, Presentations over, Boris Veytsman took up the and why I’ve now twice re-written it. I finished by baton again as TUG President, and led a lively TUG promising a first alpha version of version 3. AGM discussion: details in a separate item. Frank then returned for a morning of symmetry, The business of the day ended with a discussion talking about compatibility requirements. He talked (workshop) session looking at technical aspects of about the historical situation, starting from Knuth’s tagging PDFs. As one might expect, this large topic introduction of TEX and taking us through the de- could have filled the entire day, and it was clear that velopment of LATEX, PDF support and Unicode en- the hour we had available was very much laying out gines. He then moved on to look at the LATEX 2ε a framework for future meetings. approach to compatibility, starting with the 1994 Those of us staying at the official hotel took approach, fixltx2e. He explained how that was inten- the minibus back to Ipanema, heading out in the ded to work, and why it didn’t. The new approach, evening to what became the unofficial ‘team bar’ for latexrelease [12], tackles the same problems but starts the meeting. We split into small groups, and talking with the idea that it applies to both the kernel and about TEX or otherwise went on for quite some time! to packages. Frank covered the idea of roll-back for packages, and how this works at the user and de- 2 Day two veloper levels. Frank finished off with some thoughts Frank Mittelbach started the day’s proceedings, talk- about the future, and the fact that most new users ing about his doc [5] package for literate program- probably pick up these ideas without issue. ming. He explained the background, what works and Our conference chair, Paulo Ney de Souza, took more importantly what didn’t. The success of doc the first slot after lunch to speak on how he’s ap- as a standard makes change challenging, but at the proached a major challenge, managing the abstracts same time there is a need for updates. He then laid for the upcoming ICM 2018 meeting. His talk ranged out goals for a new version: backward-compatibility, over topics such as citation formatting, small device new markup and out-of-the-box hyperref support. output, production workflows and dealing with au- He showed us the features for creating new markup. thor preambles. He covered the wide range of tools There are some wrinkles, for example that hyperref his team has assembled to automate PDF creation support still has to be manually activated. Frank from a heterogeneous set of sources. His wide-ranging wrapped up by pointing to the testing version, and talk was a tour de force in automated publication. gave us a likely release date (for TL’19). After a brief break, we moved to Tom Hejda I then gave my first talk of the day, looking at (who TeX.sx users know as yo’), on his tool yoin [2]. expl3 [10] concepts related to colour and graphics. I He explained that his current workflow for producing outlined the LATEX 2ε background, what is happen- journal issues is at present a mix of tools, and this is ing with the LATEX 2ε drivers and then moved on to likely not long-term sustainable. He then moved to my expl3 experiments. First I talked about colo(u)r, showing how yoin can be used to compile both the and the idea of colour expressions as introduced by master file for an issue and, as required, each article xcolor [3]. These are trivial to work out in expl3 due within it.

TUG goes to Rio 102 TUGboat, Volume 39 (2018), No. 2

on to look at how to integrate Metafont directly into the TrueType rasteriser. The final talk came from Will Robertson, on TEX fontspec [7] and unicode-math [6]. He started by showing us some issues in the fonts in books for Figure 1: Knuthduck children, before reviewing unicode-math. He showed how it handles complex maths, allowing re-use of copied material and changing the style of output. The last talk of the day was from Joachim He then looked at the development approach he’s Heinze, formerly of Springer. He talked about journal taken in ‘cleaning up’ unicode-math and fontspec. He publishing, and how online accessibility of publica- covered various aspects of the expl3/l3build/Git(Hub) tions has changed the landscape for publishers. He workflow he’s now perfected. He then moved on to gave an entertaining look into this world, posing the fontspec, talking about the background, current inter- question ‘Where is the information we have lost in faces and possible future developments. It was a great data?’ final talk: wide-ranging, thought-provoking and fun. With the formal business done, some of the With the formal business done, we headed to group remained at IMPA for a workshop on R and the roof of IMPA for the traditional conference pho- Knitr, led by Boris Veytsman. I decided to skip that, tograph. After a lunch break, it was off for most of and to conserve energy for the real business of the us to the excursion to Sugarloaf Mountain, and the meeting: the conference meal! We all met up again end of the meeting proper. We of course managed for that event at Rubaiyat Rio. This was a chance to pick the one afternoon of the week where the top to unwind, compare notes and of course to present of the mountain was hidden in cloud, but the trip the all-important Duane Bibby original: this year it up was great fun. Almost all of the foreign delegates was given to the Lua team. were staying for Sunday evening, and several of us availed ourselves once again of the ‘team bar’ for a 3 Day three well-deserved evening of informal chat. The final day of TUG2018 followed the conference References banquet, which of course meant that there were a few tired (or missing!) delegates. Luckily, the talks [1] P. Cereda, M. Daniel, et al. arara: The cool TEX kept us all awake. automation tool, 2018. ctan.org/pkg/arara The first talk of the day came from S. K. Ven- [2] T. Hejda. yoin, 2018. https://github.com/ katesan, focussing on his WaTEX tool, and the link tohecz/yoin to countability of computing problems. He ranged [3] U. Kern. Extending LATEX’s color facilities: The over several fundamental questions in computability. xcolor package, 2016. ctan.org/pkg/xcolor We then moved to Paulo Cereda (on behalf of [4] M. Loretan. The selnolig package: Selective Susanne Raab), looking at the TikZducks package [8]. suppression of typographic ligatures, 2018. He started by pointing out that whilst drawing ducks ctan.org/pkg/selnolig is fun, there is serious coding behind it. He showed [5] F. Mittelbach. The doc and shortvrb packages, us a range of examples of how key–value settings 2018. ctan.org/pkg/doc,shortvrb allow a wide range of (wacky) customisation of duck [6] W. Robertson. Experimental Unicode drawings. A particular highlight was rendering Don mathematical typesetting: The unicode-math Knuth as a TikZduck (Figure 1). package, 2018. ctan.org/pkg/unicode-math Once we’d all refuelled, Jaeyoung Choi took the [7] W. Robertson. The fontspec package: Font podium to describe work on using Metafont directly selection for X LE ATEX and LuaLATEX, 2018. inside FreeType. He laid out the advantages of Meta- ctan.org/pkg/fontspec font, and the problems for use by font designers. He [8] samcarter. The TikZducks package: Using ducks in then moved to look at the particular challenges faced TikZ, 2018. ctan.org/pkg/tikzducks in developing CJK fonts: the very large number of [9] T. Tantau and C. Feuers¨anger. TikZ and pgf, 2015. characters, and resulting significant time/cost invest- ctan.org/pkg/pgf ment required. With modern computing power, this [10] The LATEX Project. The expl3 package and LATEX3 can be solved using Metafont to parametrise this programming, 2018. ctan.org/pkg/l3kernel large number of glyphs. Jaeyoung demonstrated a [11] The LATEX Project. The l3build package: GUI which allows control of the appearance of char- Checking and building packages, 2018. acters in an (almost) interactive way. He then moved ctan.org/pkg/l3build

Joseph Wright TUGboat, Volume 39 (2018), No. 2 103

(1)? (2)E.Ochs (3)A.Ribeiro (4)D.Behrendt [12] The LATEX Project. The latexrelease package, 2018. (5)B.Veytsman (6)V.R.W.Schaa (7)W.Robertson ctan.org/pkg/latexrelease (8)U.Fischer (9)S.K.Venkatesan (10)M.Beebe [13] J. Wright. siunitx: A comprehensive (SI) units (11)P.Cereda (12)N.Beebe (13)P.NeydeSouza (14)Mrs.Heinze (15)? (16)C.Mittelbach (17)R.Ierusalimschy ctan.org/pkg/siunitx package, 2018. (18)J.Choi (19)E.Kalinowski (20)C.Rowley (21)R.Moore (22)M.RochadeSouzaRamos (23)L.deFigueiredo Joseph Wright (24)J.Malaco (25)F.Mittelbach (26)J.Heinze ⋄ Morning Star (27)M.Loretan (28)A.Szasz (29)J.Wright (30)T.Hejda 2, Dowthorpe End (∗) Der B¨ar Earls Barton 29 16 20 212324 27 Northampton NN6 0NH 18 26 30 1517 25 28 United Kingdom 14 19 22 6 1112 13 2 5 7 ∗ 8 9 10 joseph dot wright (at) 1 3 4 morningstar2.co.uk

Photos in first column c Joachim Heinze; in second column, c Volker RW Schaa. Thanks to both.

TUG goes to Rio 104 TUGboat, Volume 39 (2018), No. 2

TUG 2018 Annual General Meeting notes TUG”. Mico takes the electronic-only option and agreed that he looks at the membership fee in just Notes recorded by Joseph Wright this way. The TUG annual meeting took place in conjunction Membership drive with the TUG’18 conference in Rio de Janeiro on 22 July 2018. The meeting was conducted by the TUG Boris outlined the issue: membership has been falling president, Boris Veytsman. (though not this year). There are lots of TEX users: A letter from Jonathan Fine was read verbatim, see the scale of, e.g., Overleaf. per his request, by Boris, and the two questions it Boris posed the question of how to convert those contained were answered as follows: users to TUG members. Frank suggested, “Maybe you can’t”. TUG arguably missed the opportunity Q: First, please report on any Board actions and for development of “cloud” services offered, which discussions relating to the TUG website. And what was picked up by Overleaf (and others). The cloud intentions does the Board have regarding the TUG services, and so ultimately the users, rely on TUG website? for the “back end” part of their business. A: There is general agreement on making tug.org Boris asked the question: Our work is important, more mobile-friendly, and some discussion has been and the TEX community needs us, but do other directed to that end. people see this? Q: Second, is there any potential conflict between The nature of TUG the personal interests of any Board member and the interests of TUG? And if so, what action has the Tom asked, are we now the “TEX Developers Group”? Board taken to protect both sides from this potential Frank: “Yes, to a large extent”. Others agreed conflict of interest? with this as reflecting the current reality. A: There are no conflicts that we are aware of. Paulo Cereda: The nature of TUG meetings has changed: a few “power” users attend, mainly for Question regarding TUGboat open access developer discussion. The question was posed: should TUGboat be open Frank: Why does one join? To support the “mis- access? Boris laid out the idea and background. sion” as a user. Perhaps TUGboat is an exception Joseph Wright said that (a) articles are often in print (per library comment from Paulo) but “sup- available anyway from authors, and (b) people would porting the mission” is what drives the size of the still join: members join for other reasons. group; this is not linked to the size of the user base. Tom Hejda also agreed that people would still Joseph: This seems to be the case for UK-TUG join, and good articles could be linked on, e.g., Face- too. Ross Moore: Some form of shareware approach book which would then link back to TUG. Mico Loretan agreed with the previous points, might highlight the need for developer support. and in particular the marketing possibilities that this Tom: SageMath has gone this route; they could would make possible. not operate without income. Similarly for MatLab. Will Robertson pointed out that open access Other examples were given. Open question: What makes our lives easier, however, the counter argu- were their original license/copyright situations? ment is that there is a push for joining from wanting Boris: The legal/moral right could be problem- articles that currently cannot be accessed unless one atic, as TUG doesn’t own the tools. is a member. Suggestion: Post a “Support us” link on down- Frank Mittelbach suggested that there are few loading, similar to Ubuntu. such people today. He suggested that TUGboat is Paulo C.: Current members tend to expect oth- partly a research journal in document engineering: it ers to join for the same reasons (“support”), i.e., the is referenced by other researchers in this field. It also need to provide help particularly to new users, e.g., carries a number of articles focused on engine and through workshops. macro development, and these may be important for Tom: There are two types of members, people and institutions. Among the latter, there are 10 other developers in the TEX community. The current embargo may slow down work in both areas. universities, one publisher, four commercial entities. Paulo Ney de Souza pointed out that a print Is this a possibility to raise money? journal may be picked up by (e.g.) libraries. Boris has explored this, with very little response. Frank felt that most people who join electronic- Persuasion works best as an employee. only are most likely mainly doing so for “supporting Other business: None. TUGboat, Volume 39 (2018), No. 2 105

The tikzducks Package Or accessories can be added: Susanne Raab \duck[cap=blue,cricket] Abstract TikZducks is a funny little package to draw rubber ducks in TikZ. The following article will give a short overview of the package and show some examples of As can be seen in the above example, the colour how the TikZducks package can be used. of additional components can usually be changed in the same way as for the body parts. A complete 1 Introduc(k)tion list of all the available options would exceed the The host country of TUG’18, Brazil, is also the home scope of this TUGboat article; please see the package country of Hevea brasiliensis, commonly known as documentation [3, Section 2]. rubber tree. This tree is the source of natural , The customisation of the TikZducks is not lim- which (or some of its synthetic replacements) can be ited to the predefined accessories included in the used to produce rubber ducks. package. In the end, the ducks are just shapes in a This raises the question if rubber ducks can tikzpicture. This means that the essentially infi- also be made of LATEX? Yes, they can — using the nite amount of possibilities of TikZ are available for TikZducks package! This package originates from a further customisation. A trivial example: post on TEX.StackExchange [2] which showed that the TEX community a) has a great sense of humour and b) seemed to be in desperate need of a package to \duck easily add ducks to their documents. The package is \fill (2,0) rectangle (1,1); now available on CTAN (ctan.org/pkg/tikzducks) and included in both TEX Live and MiKTEX. The basic usage is fairly simple: To ease customisation, the TikZducks package \documentclass{standalone} predefines some coordinates at prominent positions: \usepackage{tikzducks} head \begin{document} tail \begin{tikzpicture} bill \duck wing \end{tikzpicture} \end{document} Instead of loading it as a package, there is also 3 Football ducks a TikZ library with the same functionality: TUG’18 is taking place in the football nation Brazil, \documentclass[tikz]{standalone} so it is only appropriate that the TikZducks can not \usetikzlibrary{ducks} just play football (\duck[football]), but also have \begin{document} customisable jerseys. The special macro \stripes \begin{tikzpicture} adds a highly adjustable stripe pattern which allows \draw (0,0) pic {duck}; emulating jerseys from nearly every team. The fol- \end{tikzpicture} lowing example shows how to reproduce the jerseys \end{document} of the Brazil national team: 2 Modularity Drawing a simple yellow duck is by far not the only \duck[tshirt=Green,jacket=Gold, thing which this package is capable of. It comes with football,stripes={ \stripes[color=Blue, many accessories and the ability to adjust colours to rotate=-75,width=0.5, customise the ducks. Both can be controlled with distance=1.5]}] an intuitive key-value interface. For example, the colour of the various body parts can be changed: 4 Duckify a person \duck[body=blue,head=yellow, A nice application of the TikZducks is to “duckify” bill=red,eye=green] persons. In the following a short tutorial will give an idea how this can be done based on a photograph.

The tikzducks Package 106 TUGboat, Volume 39 (2018), No. 2

As an example, let’s use this photo of Don Knuth (image by J. Appelbaum [1]):

Scouting for Ducklings

Wir m¨ussen wissen. Wir werden wissen. E = mc 2 1 + 1 = 2

From top left to bottom right: Frenchman duck, crowned duck, duck scout, bee duck, Royal Swan Up- per, Albert Einstein, witch duck and David Hilbert. To see more examples, there are some collections As a first step, suitable colours have to be de- available online termined. For all non-artists, this process can be github.com/samcarter8/tikzducks/tree/ simplified with a colour picker tool, which is included • master/duckpond in many image manipulation programs (e.g., gimp) tex.stackexchange.com/questions/387047 • or as standalone applications. The following colours to which users can also contribute their creations. are extracted from the example image: There are even several videos produced by Ulrike sweater: RGB = (95, 42, 50) and Gert Fischer, Carla Maggi and Paulo Cereda, shirt: RGB = (241, 238, 254) featuring the TikZducks: skin: RGB = (229, 175, 166) The great TikZducks Christmas Extravaganza, • If colours derived from a photo are used to fill vimeo.com/246256860 International Pizza Day, vimeo.com/254643482 large shapes of solid colour, they are sometimes per- • Happy Groundhog Day, vimeo.com/252719006 ceived as too dark. This problem can be solved by • Aquarela with TikZducks, vimeo.com/270727100 mixing them with white to make them a bit lighter. • With slightly lightened colours and some suitable 6 Suggestions or problems accessories the following “duckified” version of Don The package source is hosted at https://github. Knuth can be drawn: com/samcarter8/tikzducks, along with a tracker \definecolor{jacket}{RGB}{95,42,50} for bug reports, feature requests or contributions. For \definecolor{skin}{RGB}{229,175,166} questions related to the package there is a special \definecolor{shirt}{RGB}{241,238,254} {tikzducks} tag available at TEX.StackExchange. \duck[% 7 Acknowledgments body=skin!50!white, bill=skin!80!gray, I would like to thank the TEX Users Group for the tshirt=shirt, jacket=jacket, possibility to present the TikZducks package at their recedinghair=lightgray!80!brown, annual meeting and especially Paulo Cereda for the squareglasses=brown!30!lightgray, vivid presentation he gave in Rio de Janeiro! eyebrow, book=\TeX, The author of the TikZducks package is grate- bookcolour=black!40!brown ful for the valuable contributions and suggestions ] received from Ulrike Fischer, Carla Maggi, Enrico Gregorio, Andrew Stacey and many others. References [1] J. Appelbaum. Licensed under CC BY-SA. https://en.wikipedia.org/wiki/File: T EX KnuthAtOpenContentAlliance.jpg [2] How can we draw a duck?, 2017. tex.stackexchange.com/q/346695 5 Examples [3] samcarter. The TikZducks package, Version 0.7, 2018. ctan.org/pkg/tikzducks As mentioned above, see the package documentation for all of TikZducks’s myriad possibilities, but as a Susanne Raab teaser, here are a few examples: ⋄ Susanne.Raab (at) fau (dot) de

Susanne Raab TUGboat, Volume 39 (2018), No. 2 107

1 A rollback concept for packages and classes January 2016 and the current date. Undoing means reinstalling the definitions current at the requested Frank Mittelbach date and normally also removing new commands Abstract from TEX’s memory so that \newcommand and simi- lar declarations do not fall over because a name is In 2015 a rollback concept for the LAT X kernel was E already declared. introduced. Providing this feature allowed us to This mechanism helps in correctly processing make corrections to the software (which more or older documents that contain workarounds for issues less didn’t happen for nearly two decades) while with an older kernel, issues that have since been fixed continuing to maintain backward compatibility to in a way that would make the old document fail, or the highest degree. produce different output, when processed with the In this paper we explain how we have now ex- newer, fixed kernel. tended this concept to the world of packages and If necessary, the latexrelease package also allows classes, which was not covered initially. As classes for rolling the kernel forward without installing a and extension packages have different requirements new format. For example, if the current installation compared to the kernel, the approach is different (and is dated 2016-04-01 but you have a document that simplified). This should make it easy for package requires a kernel with date 2018-01-01, then this can developers to apply it to their packages and authors be achieved by starting it with to use when necessary. \RequirePackage[2018-01-01]{latexrelease} Contents provided you have a version of the latexrelease pack- age that knows about the kernel changes between the 1Introduction 107 date of your kernel and the requested date. Getting this version of the package is simple as the latest 2 Typical scenarios 108 version can always be downloaded from CTAN. Thus 3 The document interface 108 you will be able to process your document correctly 3.1 Globalrollback ...... 108 even when updating your complete installation is not 3.2 Individualrollback ...... 108 advisable or impossible for one or another reason. However, rolling back the kernel state is only 3.3 Specifying a version instead of a date 109 A 3.4 Erroneousinput...... 109 doing half of the job: the LTEX universe consists of 3.5 Adviceforearlyadopters ...... 109 many add-on packages and those were not affected by a kernel rollback request. We are therefore now 4 The package/class interface 110 extending the concept by providing a much simpler method for use in packages and classes, one that we 5 Special considerations for developers 110 think will be straightforward for developers and also 5.1 Earlyadopters ...... 111 easy for document authors to use. 5.2 Newmajorreleaseinbeta ...... 111 Unlike the method used by the kernel, which 5.3 Twomajorreleasesinuse ...... 111 tracks every change individually and is able to roll 5.4 Fine grained control (if needed) . . . 112 back the code to precisely the state it had on any 5.5 Using l3build for source management 112 given day, the new method for packages and classes is intended to cover only major change points, e.g., the 6 Command summary 112 introduction of major new features or (incompatible) 6.1 Document interface, for users . . . . 112 changes in syntax or interfaces. 6.2 Package and class interface, As we will have only a few rollback points per fordevelopers ...... 112 package or class, the different releases are all stored in separate files. In the main file it therefore only needs 1 Introduction a single declaration per release to enable rollback. In 2015 we introduced a rollback concept for the The downside is, of course, that for each release the LATEX kernel that enables a user to request a kernel whole package code is stored, instead of managing rollback to its state at a given date by using the the differences between releases. This is one of the latexrelease package [1]. For example, 1 There are a few exceptions as some modifications are kept: \RequirePackage[2016-01-01]{latexrelease} for example, the ability to accept date strings in ISO format (e.g., 2016-01-01) in addition to the older LATEX convention would result in undoing all kernel modifications (cor- (e.g., 2016/01/01). These are not rolled back because removing rections or extensions) released between the first of such a feature would result in unnecessary failures.

A rollback concept for packages and classes 108 TUGboat, Volume 39 (2018), No. 2

reasons why this approach should be used only for A somewhat different example is the amsmath major changes, i.e., at most a handful in the lifetime package, which for nearly a decade didn’t see any of a package. corrections even though several problems have been From a technical perspective it is also possible found in it over the years. If such bugs finally get to use the method introduced with latexrelease in corrected, then that would affect many of the doc- package and class files, i.e., to mark up modifica- uments written since 2000, since their authors may tions using the commands \IncludeInRelease and have manually worked around one or another of the \EndIncludeInRelease — the package’s documenta- deficiencies. Of course, as with the caption pack- tion [1] gives some advice on how to apply it in a age, one could introduce an amsmath2, amsmath3, package scenario — but the use of these commands . . . package, but that puts the burden on the user in package code is cumbersome and results in fairly to always select the latest version (instead of auto- unreadable code, especially when there are many matically using the latest version unless an earlier minor changes. This is an acceptable price to pay one is really needed). for fairly stable code, such as the kernel itself, since 3 The document interface it offers complete control over the rollback to any date, but it is not truly practical in package or class By default LATEX will automatically use the current development and so, to our knowledge, it has there- version of any class or package — and prior to offering fore never been used up to now. Section 5.4 gives the new rollback concept it always did that unless some advice on how to achieve fine-grain control in the package or class had its own scheme for providing a somewhat simpler manner. versioning, either using alternative names or by hand- coded options to select a version. 2 Typical scenarios 3.1 Global rollback A typical example, for which such a rollback func- tionality would have provided a major benefit (and With the new rollback concept all the user has to do will do so for packages in the future), is the cap- (if he or she wants their document processed with tion package by Axel Sommerfeldt. This package a specific version of the kernel and packages) is to latexrelease started out under the name of caption with a certain add the package at the beginning of the user interface. Over time it became clear that there document and specify a desired date as the package were some deficiencies in the user interface; to rectify option, e.g., just as in the first example: these without making older documents fail, Axel in- \RequirePackage[2018-01-01]{latexrelease} troduced caption2. At a later point the syntax of that This will roll back the kernel to its state on that day package itself was superseded, resulting in caption3 (as described earlier) and for each package and the and then, finally, that got renamed back to caption. document class it will check if there are alternate So now older documents using caption will fail whilst releases available and select the most appropriate documents from the intermediate period will require release of that package or class in relation to the caption2 (which is listed as superseded on CTAN but given date. is still distributed in the major distributions). So 3.2 Individual rollback users accustomed to copying their document pream- ble from one document to the next are probably still There is further fine-grain adjustment possible: both continuing to use it without noticing that they are \documentclass as well as \usepackage have a sec- in fact using a version with defective and limited ond (little known) optional argument that up to now interfaces. was used to allow the specification of a “minimal Another example is the fixltx2e package that for date”. For example, by declaring many years contained fixes to the LATEX kernel. In \usepackage[colaction] 2015 these were integrated into the kernel so that {multicol}[2018-01-01] today this package is an empty shell, only telling the you specify that multicol is expected to be no older user that it is no longer needed. However, if you pro- than the beginning of 2018. If only an older version cess an old document (from before 2015) that loads is found, then processing such a document results in fixltx2e then of course the fixes originally provided a warning message: by this package (like the corrections to the floats LaTeX Warning: You have requested, on input algorithm) would get lost as they are now neither in line 12, version ‘2018-01-01’ of package the kernel nor in the “empty” fixltx2e package if that multicol, but only version doesn’t roll back as well — fortunately it does and ‘2017/04/11 v1.8q multicolumn formatting always did, so in reality it isn’t quite an empty shell. (FMi)’ is available.

Frank Mittelbach TUGboat, Volume 39 (2018), No. 2 109

The idea behind this approach is that packages sel- longtable and the old (now current) version is labeled dom change syntax in an incompatible way, but more “v4”, then all that is necessary to select that old often add new features: with such a declaration you version is can indicate that you need a version that provides \usepackage{longtable}[=v4] certain new features. The new rollback concept now extends the use Note that there is no need to know that the new of this optional argument by letting you additionally version is dated 2018-04-01 (nor to request a date supply a target date for the rollback. This is done before that) to get the old version back. by prefixing a date string with an equal sign. For The version “name” is an arbitrary string at example, the discretion of the package author — but note that it must not resemble a date specification, i.e., it \usepackage{multicol}[=2017-06-01] must not contain hyphens or slashes, since these will would request a release of multicol that corresponds confuse the parsing routine.2 to its version in June 2017. So assuming that at some point in the future 3.4 Erroneous input there is a major rewrite of this package that changes The user interface is fairly simple and to keep the the way columns are balanced, the above would re- processing speed high the syntax checking is therefore quest a fallback to what right now is the current rather light. Basically the standard date parsing from version from 2017-04-11. The old use of this op- the kernel is used, which is rather unforgiving if it tional argument is still available because presence finds unexpected data. or absence of the = determines how the date will be Basically any string containing a hyphen or a interpreted. slash will trigger the date parsing which then expects The same mechanism is available for document two hyphens (for the case of an ISO date) or two classes via the \documentclass declaration, and for slashes (otherwise) and other than these separators, \RequirePackage if that is ever needed. only digits. If it does find anything else, chances are that you will get a “Missing \begin{document}” 3.3 Specifying a version instead of a date error or, perhaps even more puzzling, a strange selec- Specifying a rollback date is most appropriate if you tion being made. For example, 2011/02 may mean want to ensure that the behavior of the processing to us February 2011 but for the parsing routine it is engine (i.e., the kernel and all packages) corresponds some day in the year 20 a.d. That is, it gets converted to that specific date. In fact, once you are finished to the single number 201102, so that, when this num- with editing a document, you can preserve it for ber is compared numerically to, say, 20000101, it posterity by adding this line: will be the smaller number, i.e., earlier, even though \RequirePackage[htoday’s-datei] the latter is the numerical representation of Jan- st {latexrelease} uary 1 2000. So, bottom line: do not misspell your dates and This would mean that it will be processed a little all is fine. That hasn’t been a problem in the past, more slowly (since the kernel may get rolled back so hopefully it will be okay to continue with just this and each package gets checked for alternate versions), light checking. If not, then we may have to extend but it would have the advantage that processing it the checks made during parsing. a long time in the future will probably still work without the need to add that line later. 3.5 Advice for early adopters However, in a case such as the caption package or, say, the longtable package, that might eventually If your document makes use of the new global roll- see a major new release after several years, it would back features, then it should be processable at any be nice to allow the specification of a “named” release installation later than early 2015, when the latex- instead of a date: for example, a user might want release package was first introduced. If the instal- to explicitly use version 4 rather than 5 of longtable lation is even older, then it needs upgrading or, at when these versions have incompatible syntax, or least, one has to add a current latexrelease package produce different results. to the installation. This is also now possible if the developer declares However, if your document uses the new concept “named” releases for a package or class: one can then for individual rollbacks of packages or classes (i.e., request a named version simply by using this second 2 Of course more sophisticated parsing could fix this, but optional argument with the “name” prefixed by an we use fast and simple parsing that scans for slashes or hyphens equal sign. For example, if there is a new version of with no further analysis.

A rollback concept for packages and classes 110 TUGboat, Volume 39 (2018), No. 2 with the =... syntax in the optional argument), then \DeclareRelease it is essential to use a LATEX distribution from 2018 or {hnamei}{hdatei}{hexternal-filei} 3 later. Earlier distributions will choke on the equal Either the hnamei or the hdatei can be empty, but sign inside the argument as they will only expect to not both at the same time. Not specifying a hdatei see a date specification there. is mainly intended for providing “beta” versions that people can explicitly select but that should play no 4 The package/class interface role in date rollbacks. The rollback mechanism for packages or classes is The current release also gets a declaration, but provided by putting, at the beginning of the file con- this time with only two arguments: a hnamei (again taining the code, a declaration section that informs possibly empty) and a hdatei since the code for this the kernel about existing alternative releases. release will be the rest of the current file: These declarations have to come first and have \DeclareCurrentRelease{hnamei}{hdatei} to be ordered by date because the loading mechanism will evaluate them one by one and, once a suitable This declaration has to be the last one in sequence release is found, it will be loaded and then processing as it will end the release selection processing. of the main package or class file will end. If there are The order of the other releases has to be from no such declarations, or if the older releases are all the oldest to the newest since the loading mechanism ruled out for one reason or another, processing will compares every release declaration with the target continue as normal by reading all of the main file. rollback date and stops the moment it finds one that The old releases are stored in separate files, one is newer than this target date. It will then select the for each release, and we suggest using a scheme such one before, i.e., the last one that is at least as old as as hpackage-namei-hdatei.sty as this is easy to un- the target. Since the \DeclareRelease declarations derstand and will sort nicely within a directory. How- with an empty hdatei argument do not play a role in ever, any other scheme will do as well, as the name date rollbacks, they can be placed anywhere within is part of the declaration. the sequence. The contents of this release file is simply the As a typical example of a release section the package or class file as used in the past. This means start of the multicol package currently looks as fol- that before making a new version all you need to do lows because there was a major internal rewrite in is to make a verbatim copy of the current file and April 2018. Note that because of some minor fixes give it a new suitable name.4 afterwards the actual package date is already June. This way it is also straightforward to include \NeedsTeXFormat{LaTeX2e}[2018-04-01] older releases after the fact, e.g., to take our famous \DeclareRelease{}{2017-04-11} caption example, Axel could provide the very first {multicol-2017-04-11.sty} version of his package as caption-hsome-datei.sty \DeclareCurrentRelease{}{2018-04-01} and caption2 as caption-hanother-datei.sty in ad- \ProvidesPackage{multicol}[2018/06/26 v1.8t dition to adding the necessary declarations to the multicolumn formatting (FMi)] current release. If the rollback target is not a date but a name, The necessary declarations in the main file are the mechanism works in the same way with the ex- provided by the two commands, \DeclareRelease, ception that a release is selected only if the name and \DeclareCurrentRelease, that must be used in matches. If none of the names is a match, then the a release selection section at the beginning of the file. mechanism will raise an error and continue by using For each old release you can specify a hnamei, the the current release. hdatei when it was first available and the hexternal- filei that contains the code. 5 Special considerations for developers While loading an older release of a package or class, 3 Alternatively you could try to roll the installation for- both types of release declarations are made no-ops, latexrelease ward, by using a current package together with a so that, in case the files containing the code also suitable date option. 4 Instead of making a verbatim copy you may want to have such declarations, they will not be looked at or adjust the commentary added by docstrip at the top of the acted upon. This makes it possible to simply move file. Though technically correct, it is a bit misleading if the file the code from an old release into a new file without still contains the phrase “was generated from . . . ”, given that it the need to touch it at all. Of course, removing those is now a frozen version representing a particular state in time, rather than being a generated one that can be regenerated declarations doesn’t hurt and will make loading a any time as necessary. tiny fraction faster.

Frank Mittelbach TUGboat, Volume 39 (2018), No. 2 111

As mentioned earlier, best practice for release so that testers can explicitly access your new version names is to append the release date to the package by asking for it via or class name, but the hexternal filei argument also \usepackage[hoptionsi]{hpackagei}[=beta] allows other naming schemes. while everyone loading the package without the extra You may have wondered why you have to make optional argument would get the current release. a declaration for the current release, given that later on there will be a \Provides... declaration that 5.3 Two major releases in use also contains a date and a version string and thus One special scenario for which this method is only could signal the end of the release declaration section. partially suitable is the case where we have two The reason is as follows: if you want to give your major releases that are in continuing parallel use current release a name, then it is best practice to and that are both under active maintenance (i.e., v4 make that name something simple like (and keep receive bug fixes and other updates once in a while). it that way) even though your current package is In that case it is necessary to make one version the v4.2c technically already at and is listed that way primary release and allow the other (and its updates) \ProvidesPackage in the declaration. For the same to be accessed only via names: a date rollback can reason (given that not every minor change will be obviously work for only one line of development. provided as a separate version to which people can For example, if both v4 and v5 of package foo are \DeclareCurrentRelease roll back), the hdatei in in use and you consider v5 as being the go-forward reflects when that major release was first introduced. version (even though you are still fixing bugs in the Thus, after a while that date may well be earlier v4 code), then you can deploy a strategy as in the than the current package date. following example: 5.1 Early adopters % last v4 only release: For one or two years after the introduction of this \DeclareRelease{}{2017-06-23} new method, there is a danger that people with older {foo-2017-06-23.sty} installations will pick up an individual package from, % first v5 release: say, CTAN that contains release declarations with \DeclareRelease{}{2017-08-01} which their kernel (from 2017 or earlier) is unable to {foo-2017-08-01.sty} cope. It may therefore be a good idea for developers % patch to v4 after v5 got introduced: to additionally add the following lines at the top \DeclareRelease{v4.1}{} of packages or classes when using the new rollback {foo-v4-2017-09-20.sty} feature: % patch to v5: \providecommand\DeclareRelease[3]{} \DeclareRelease{}{2017-08-25} \providecommand\DeclareCurrentRelease[2]{} {foo-2017-08-25.sty} % another patch to v4: This way the declarations will be bypassed in case \DeclareRelease{v4.2}{} the kernel doesn’t know how to deal with them. {foo-v4-2017-10-01.sty} As an alternative one could add a statement % nickname for the latest v4 if you want that requires a minimal kernel version, i.e.: % users to have simple access via a name: \NeedsTeXFormat{LaTeX2e}[2018-04-01] \DeclareRelease{v4}{} so that users get a clear error message that they need {foo-v4-2017-10-01.sty} to update their installation if they want to use the % current v5 with further patches: current file. \DeclareCurrentRelease{v5}{2018-01-01} 5.2 New major release in beta This way users can use \usepackage{foo}[=v4] to get the latest v4 release or use the more detailed If you are working on a new major release of your release names such as [v4.1]. This means that if package or class, you may want to get it out into the package foo is requested at version v4 (or one of its open so that people can try it and provide feedback. sub-releases), it will not change even if there is a In that case the current release is still the official general rollback request via latexrelease. release which should be selected by default, and the Normally, this should be just fine, but if you “beta” version should only be selected if explicitly really require automatic date rollback functionality requested. To achieve that you could add on both major versions, because the two are really \DeclareRelease{beta}{}{hexternal-filei} equal in rank, then you are essentially saying they before are independent works with some common root. In \DeclareCurrentRelease{}{hsome-datei} that case you should give them two separate names,

A rollback concept for packages and classes 112 TUGboat, Volume 39 (2018), No. 2

e.g., call the older version foo-v4 when you introduce sourcefiles = {"*.dtx", ".ins", version 5 of foo and from that point on manage the "*-????-??-??.sty"} 5 history independently. i.e., all .dtx and .ins files, together with all .sty files matching the naming convention suggested in 5.4 Fine grained control (if needed) this article, are automatically included in the build. As mentioned earlier, the interface is deliberately If you prefer a different naming convention you designed to be simple and easy to use. As a price, have to adjust this setting in the build.lua file of each rollback point is (by default) a separate file. The your project. Otherwise you are ready to go without idea behind this is that there is not much point in any adjustments. managing each and every small change as a rollback 6 Command summary point, but only those that possibly alter the behavior 6.1 Document interface, for users of a package within the document so that, when processing older documents, it is important to be For a global rollback of kernel and packages, use able to get back to an earlier state. \RequirePackage[htarget-datei]{latexrelease} However, if you find yourself in a situation where at the beginning of your document. you have many rollback files with only minor differ- To request a rollback for a single package or ences, and you consider this unsatisfactory, then here class, use the second optional argument with the is one other command at your disposal that you can date preceded by an equal sign, i.e., use to combine several files into a single file. Within a \documentclass[hoptionsi]{hclassi}[=hdatei] file corresponding to a \DeclareRelease declaration \usepackage [hoptionsi]{hpackagei}[=hdatei] you can use 6.2 Package and class interface, \IfTargetDateBefore{hdatei} for developers {hbefore-date-codei}{hafter-or-at-date-codei} To declare an old or special release, use This must be used after the release selection section \DeclareRelease (if present) and has the following effect: If the user {hnamei}{hdatei}{hexternal-filei} requested, say, [=2017-06-01] then the mechanism Leave the hnamei argument empty if rollback should first selects the file that is supposed to be current on be only via dates. Leave the hdatei empty if this that date, i.e., the release that was introduced on that special release should be accessible only via its name. date or is the last one that was introduced before that Always finish this release selection section with date. Now, if in this file we have a statement like the a declaration for the current release: above, then the hdatei is compared to 2017-06-01 and depending on the outcome either hbefore-date- \DeclareCurrentRelease{hnamei}{hdatei} codei or hafter-or-at-date-codei is executed. In this declaration you must provide a hdatei but the This way a single external file can hold rollback hnamei can be left empty (which is the usual case). information for several patches on distinct dates, but Within a release file (but after the release selec- of course, the burden is then on the developer to add tion section), you can specify conditional code to be the appropriate declarations, which is a little more selected based on a requested rollback date by using: work than just copying and renaming files. \IfTargetDateBefore{hdatei} The alternative is to use \IncludeInRelease {hbefore-date-codei}{hafter-or-at-date-codei} and \EndIncludeInRelease. The latexrelease pack- age documentation [1] gives some advice on how to References apply those commands. [1] The LATEX Team. The latexrelease package, April 2015. Available at https://www. 5.5 Using l3build for source management latex-project.org/help/documentation. [2] The LAT X Team. The l3build package — If you use l3build [2] for managing your sources, E Checking and building packages, March 2018. then it is necessary to ensure that the files for the old The manual l3build.pdf should be part releases are copied into the distribution. To support of your installation. Run “texdoc l3build” this, the default configuration for l3build specifies to find it. See also https://ctan.org/pkg/ l3build. 5 While in rare cases this might be the best approach, try to avoid it as long term management will be problematic, to Frank Mittelbach ⋄ say the least. https://www.latex-project.org

Frank Mittelbach TUGboat, Volume 39 (2018), No. 2 113

Font loading in LATEX using the fontspec the TEX Gyre fonts are included in the standard TEX package: Recent updates distributions. However, loading font families in these ways Will Robertson has confusing edge cases, and it increases document 1 Introduction portability problems, and it can be slow. Over time I have moved away from using this feature and I think The fontspec package (ctan.org/pkg/fontspec) is, long term it would be better to de-emphasise its use. I am astonished to say, close to 15 years old. I hon- I now recommend all users to load their fonts by estly don’t know where all the time has gone. The filename. interface that fontspec provides was originally very The most straightforward means to do this is simple: load a font. The font feature interface fol- like so: lowed quickly after, and was originally based around \setmainfont{texgyrepagella-regular.otf}[ macOS’s AAT font technology, which is largely obso- ItalicFont = texgyrepagella-italic.otf , lete these days. Today, fontspec is targeted mainly BoldFont = texgyrepagella-bold.otf , towards the use of OpenType fonts, although the BoldItalicFont = texgyrepagella-bolditalic.otf, legacy AAT code is still functional. Another font ] technology, Graphite, can be used when running the But here there is a lot of duplication and a more X TE EX engine but the fontspec interface is extremely streamlined way is: minimal (and rather undocumented). \setmainfont{texgyrepagella}[ This article will discuss some of its more recent Extension = .otf , updates, possible future interfaces, and what I now UprightFont = *-regular , consider to be some ‘best practices’ for fontspec use. ItalicFont = *-italic , BoldFont = *-bold , 2 Font loading BoldItalicFont = *-bolditalic, There are a number of ways to load or set up fonts ] in fontspec: Whereas in the first case the mandatory argument • \fontspec {texgyrepagella-regular.otf} was a direct refer- ence to the ‘regular upright’ font file, in the second • \setmainfont case {texgyrepagella} is merely a shorthand name • \newfontfamily from which the filenames are constructed. • \defaultfontfeatures 2.1 The case against loading by font name As the package has grown, the best way to combine I claimed above that there were some problems with these possibilities is probably not so clear, especially loading fonts by their external name instead of their to new users. filename. Let’s discuss these in more detail. Originally, fontspec was written for the X TE EX engine on Mac OS X, with fonts being accessed via Edge cases. Modern font families aren’t the font the operating system, which provided automated families as we once knew them. It’s now common to interfaces for selecting, e.g., ‘italic’ and ‘bold’. Thus, purchase families with literally tens of styles, with early on, users became accustomed to the idea of weights from extra light to ultra black and a multi- using the human-oriented font names known to the tude of styles. (I recently purchased Gill Sans Nova system, as in writing and it arrived as 43 separate .otf files.) Now that we have OpenType variable fonts, families of arbi- \setmainfont{Hoefler Text} trary complexity may start to appear. Software such in their document, and then everything ‘just worked’ as luaotfload needs to use heuristics to establish the without additional configuration. This feature later relationships between fonts, and there can be no influenced luaotfload (for LuaTEX) to provide a sim- general solution to this task. Therefore, sometimes ilar mechanism, by scanning through known font it fails to select the correct ‘bold’ font in particu- directories and constructing its own database of font lar circumstances; therefore, sometimes I get bug files, their ‘logical’ names, and the relationships be- reports. tween shapes within a particular family. And thus it Document portability. If you are loading a font is that, right now, you can write by name, it has to be installed somehow on that local \setmainfont{TeX Gyre Pagella} computer. Well, of course any font that you load has in a LuaLATEX document and the correct font will be to be installed; but if it is by name it’s possible for it chosen and bold and italic styles will ‘just work’ since to be installed in a(ny) number of different locations,

Font loading in LATEX using the fontspec package: Recent updates \k T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,jN hl:#Qi- oQHmK2 y UNNNNV- LQX y

iQ .`QT#Qt AǶHH #2 #H2 iQ HQ/ HH i?2 7QMib A ?p2 biQ`2/ BM i?i i`22X \k \k T`2HBKBM`vT`2HBKBM`v /`7i- /`7i- m;mbi m;mbi R3- kyR3 R3- kyR3 ky,j9 ky,je hl:#Qi-hl:#Qi- oQHmK2 oQHmK2 y yUNNNNV- UNNNNV- LQX LQX y y aHQr h?Bb Bb M Q#pBQmb QM2X q?2M HmQi~Q/ b+Mb i?`Qm;? vQm` 7QMi /B`2+iQ`B2b- Bi +M iF2 [mBi2 &Q8OWUD/LJKW &Q/LJKW &Q%RRN &Q0HGLXP &Q6HPLEROG &Q%ROG iQ .`QT#Qt AǶHH #2 #H2 iQ HQ/ HH i?2 7QMib A ?p2 'HFR5HJXODU bQK2 iBK2 B7 Bi ?bMǶi `mM 7Q`  r?BH2X GQ/BM;\k 7QMib \k &Q+HDY\ &Q([WUD%ROGT`2HBKBM`vT`2HBKBM`v&Q8OWUD%ROG /`7i- /`7i- m;mbi m;mbi R3- kyR3 R3- kyR3 ky,j9 ky,je hl:#Qi-hl:#Qi- oQHmK2 oQHmK2 y yUNNNNV- UNNNNV- LQX LQX y y #v }H2MK2 bBKTHv /Q2bMǶi ?p2 i?Bb T`Q#H2KXbiQ`2/ M@ BM i?i i`22X 6KDGRZHG/LJKW Qi?2` bT2+i Q7 i?2 ǵbHQrǶ T`Q#H2K Bb i?i 7`QK M aHQr h?Bb Bb&Q8OWUD/LJKW M Q#pBQmb&Q/LJKW &Q%RRN QM2X&Q0HGLXP q?2M&Q6HPLEROGHmQi~Q/&Q%ROG 6KDGRZHG0HGLXP QT2`iBM; bvbi2K T2`bT2+iBp2 Bi +M ;2i bHQr2`iQ .`QT#Qt UQM iQ AǶHH .`QT#Qt #2 #H2 AǶHH iQ #2 HQ/ #H2 HH iQ HQ/ i?2 HH7QMib i?2 A 7QMib ?p2 A ?p2 'HFR5HJXODU b+Mb i?`Qm;?biQ`2/ vQm`&Q+HDY\ BM 7QMi i?i /B`2+iQ`B2b- i`22X&Q([WUD%ROG Bi +M&Q8OWUD%ROG iF2 [mBi2 6KDGRZHG2XWOQ QH/2` +QKTmi2`b T2`?TbV b QM2 BMbiHHb i2MbbiQ`2/ Q` ?mM@ BM i?i i`22X bQK2quaA@ iBK2 B7 Bi ?bMǶi `mM 7Q`  r?BH2X GQ/BM; 7QMib 6KDGRZHG/LJKW,QOLQH&RQG /`2/b Q7 //BiBQMH 7QMibX UJB+`QbQ7i qQ`/Ƕb aHQr h?Bb Bb M Q#pBQmb QM2X q?2M HmQi~Q/ 6KDGRZHG0HGLXP qu: 7QMi K2Mm Bb  T`iB+mH`Hv 2;`2;BQmb#vaHQr 2tKTH2 }H2MK2h?Bbb+MbiQ6B;m`2 bBKTHv Bb .`QT#Qt M i?`Qm;? R, Q#pBQmb/Q2bMǶi lT`B;?i AǶHH vQm` #2 ǵMQ`KHǶ?p2 #H2QM2X7QMi /B`2+iQ`B2b- iQ i?Bb M/q?2M HQ/ T`Q#H2KX ǵ+QM/2Mb2/Ƕ HHHmQi~Q/ i?2Bi +M 7QMib iF2 M@ r2B;?ib A [mBi2 ?p2 Q7 ,QOLQH([WUD/W :BHH aMb LQpX 6KDGRZHG2XWOQ Q7 i?BbXV Qi?2`b+Mb i?`Qm;? bT2+ibQK2biQ`2/ Q7 vQm` i?2 iBK2 BM 7QMi i?i ǵbHQrǶ B7 Bi /B`2+iQ`B2b- i`22X ?bMǶi T`Q#H2K `mM 7Q` Bi Bb  +M i?ir?BH2X iF2 7`QK GQ/BM; [mBi2 M 7QMib ,QOLQH/LJKW #v }H2MK2 bBKTHv /Q2bMǶi ?p2 i?Bb T`Q#H2KX M@ QT2`iBM;bQK2 iBK2 bvbi2K B7aHQr Bi ?bMǶi T2`bT2+iBp2h?Bb `mM Bb M 7Q` Q#pBQmb  Bi r?BH2X +M QM2X ;2i GQ/BM; bHQr2` q?2M 7QMibHmQi~Q/ UQM ,QOLQH&RQG j h?2 BMi2`7+2 7Q` 7QMi 72im`2b Qi?2` bT2+i Q7 i?2 ǵbHQrǶ T`Q#H2K Bb i?i 7`QK M ,QOLQH5HJXODU QH/2`#v }H2MK2 +QKTmi2`bb+Mb bBKTHv T2`?TbV i?`Qm;? /Q2bMǶi vQm` b ?p2 QM2 7QMiBMbiHHb /B`2+iQ`B2b- i?Bb T`Q#H2KX i2Mb Bi +M Q` ?mM@ iF2 M@ [mBi2 ,QOLQH([WUD/W h?2 ǵTHBMǶ TT`Q+? iQ b2H2+iBM; PT2MhvT2 7QMi QT2`iBM; bvbi2K T2`bT2+iBp2 Bi +M ;2i bHQr2` UQM bQK2 iBK2 B7 Bi ?bMǶi `mM 7Q`  r?BH2X GQ/BM;quaA@ 7QMib ,QOLQH%ROG /`2/bQi?2` Q7bT2+i //BiBQMHQH/2` Q7 i?2 +QKTmi2`b 7QMibX ǵbHQrǶ T2`?TbV UJB+`QbQ7i T`Q#H2K b BbQM2 qQ`/Ƕb i?i BMbiHHb 7`QK i2Mb M Q` ?mM@ ,QOLQH/LJKW 72im`2b `2[mB`2b i?2 mb2 Q7 `r 72im`2 i;b- HBF2 #v }H2MK2 bBKTHv /Q2bMǶi ?p2 i?Bb T`Q#H2KX M@ YHMmK114 Y/HB;qu:QT2`iBM;7QMi bvbi2K K2Mm/`2/b Bb Q7 T2`bT2+iBp2  //BiBQMH T`iB+mH`HvTUGboat, 7QMibX Bi +M 2;`2;BQmb UJB+`QbQ7i Volume ;2i bHQr2` 39 2tKTH2 qQ`/Ƕb (2018), UQMquaA@ No. 2 iQ +iBpi2 ǵHBMBM; MmK#2`bǶ Q` iQ +iB@ Qi?2` bT2+i Q7 i?2 ǵbHQrǶ T`Q#H2K Bb i?i 7`QK M 6B;m`2 R, //BiBQMH,QOLQH5HJXODU ǵmMmbmHǶ 7QMib BM i?2 :BHH aMb pi2 ǵ/Bb+`2iBQM`v HB;im`2bǶX Q7QH/2` i?BbXV +QKTmi2`bqu: T2`?TbV7QMi K2Mm b Bb QM2 T`iB+mH`Hv BMbiHHb i2Mb 2;`2;BQmb Q` ?mM@ 2tKTH2 QT2`iBM; bvbi2K T2`bT2+iBp2 Bi +M ;2i bHQr2` UQMh?2b2LQp +QK2 7KBHvX BM #Qi? ǵMQ`KHǶ M/ ǵ+QM/2Mb2/Ƕ rB/i?bX \k /`2/b Q7 //BiBQMH\kQ78OWUD/LJKW i?BbXV 7QMibX/LJKW UJB+`QbQ7i%RRNT`2HBKBM`v0HGLXPT`2HBKBM`v qQ`/Ƕb /`7i-6HPLEROGquaA@ /`7i- m;mbi%ROG m;mbi R3- kyR3 R3- kyR3 ky,j9 ky,je,QOLQH%ROGhl:#Qi-hl:#Qi- oQHmK2 oQHmK2 y yUNNNNV- UNNNNV- LQX LQX y y $7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]and the way that the font loading heuristics work, QH/2` +QKTmi2`b T2`?TbV b QM2 BMbiHHb i2Mb Q` ?mM@ULQi2 i?i 7QMibT2+ biBHH /Q2bMǶi ?p2  72im`2 iQ there could be a(ny) number of valid namesjqu: that h?2 the7QMi BMi2`7+2 K2Mm+HDY\ Bb  7Q` T`iB+mH`Hv 7QMi([WUD%ROG 72im`2b 2;`2;BQmb8OWUD%ROG 2tKTH2 PT2MhvT2 ?b [mBi2  MmK#2` Q7 biM/`/ 72im`2 j/`2/b h?2 Q7 //BiBQMHBMi2`7+2 7Q`7QMibX 7QMi UJB+`QbQ7i 72im`2b qQ`/Ƕb quaA@HQ/6B;m`2 HH Q7 R i?2b2, //BiBQMH BM QM2 ǵmMmbmHǶ ;Q M/ 7QMib i?2M BM i?2 brBi+? :BHH aMb #2ir22M font can be referred to. When failure happens,Q7 i?BbXV is it qu:&Q8OWUD/LJKW7QMi&Q/LJKW K2Mm&Q%RRN Bb  T`iB+mH`Hv&Q0HGLXP &Q6HPLEROG 2;`2;BQmb 2tKTH2&Q%ROG i;b- #mi i?2v `2 MQi Q`;MBb2/ BMiQ  ?B2``+?vXh?2 ǵTHBMǶ AM h?2 TT`Q+? ǵTHBMǶ TT`Q+?iQ b2H2+iBM; iQ b2H2+iBM; PT2MhvT2 PT2MhvT2 7QMi 7QMii?2Kh?2b2lHi`LQp rBi? +QK2 7KBHvX GB;?i +QKKM/b BM f #Qi? GB;?i ǵMQ`KHǶ f HBF2 "QQF'HFR5HJXODU$i2ti#QH/2` f M/ J2/BmK ǵ+QM/2Mb2/Ƕ f a2KB#QH/f$i2tiHB;?i2` rB/i?bX f i?2because 2`Hv you /vb haven’t Q7 i?2 installed7QMibT2+ T+F;2- it correctly,iQ .`QT#QtBib or 72im`2 have AǶHHQ7 i?BbXV#2 #H2 iQ&Q([WUD%ROG HQ/ HH i?2&Q8OWUD%ROG 7QMib A ?p2 72im`2b `2[mB`2b72im`2b&Q+HDY\ i?2 `2[mB`2b mb2 Q7 i?2 `r mb2 72im`2 Q7 `r 72im`2 i;b- i;b- HBF2 HBF2 "QH/7QMibT2+ f >2pv f 1ti` "QH/ f lHi` "QH/ \k T`2HBKBM`vother /`7i- software changes m;mbi made the R3- namesbiQ`2/ kyR3jh no longerh?2 BM ky,j9 i?i BMi2`7+2 i`22X 7Q`hl:#Qi- 7QMi 72im`2b oQHmK2 y UNNNNV-ěULQi2 r?BH2 i?i i?Bb LQX Bb QM y KvbiBHH iQ/Q /Q2bMǶi HBbi Bi ?p2 ?bMǶi  72im`2 #22M 7`2@ iQ HQ/BM; BMi2`7+2 rb KQ/2HH2/ QM TTH2ǶbYHMmK7QMiiQ +iBpi2YHMmKj h?2iQ ǵHBMBM; BMi2`7+2 +iBpi2 MmK#2`bǶ ǵHBMBM; 7Q` 7QMi MmK#2`bǶ Q` 72im`2bY/HB; Q` Y/HB;iQ +iB@iQ +iB@ 6KDGRZHG/LJKW i2+?MQHQ;vXmatch, or has h?Bb a database +QKT2iBiQ` not iQ been PT2MhvT2- updated when[mB2iHv it Figure 1: Upright ‘normal’ and ‘condensed’ weights of[m2MiHvHQ/h?2b2 HH Q7`2[m2bi2/ +QK2 i?2b2 BM #Qi? BM 7`QK QM2 ǵMQ`KHǶ ;Q mb2`bX M/ M/ PM2 i?2M ǵ+QM/2Mb2/Ƕ `2bQM brBi+? rB/i?bX KB;?i #2ir22M #2 h?2 ǵTHBMǶpi2Gill TT`Q+? Sans ǵ/Bb+`2iBQM`v Nova. iQ b2H2+iBM; HB;im`2bǶX PT2MhvT2 7QMi lHi` GB;?i f GB;?i6KDGRZHG0HGLXP f "QQF f J2/BmK f a2KB#QH/ f 7/BM;should BM have, TQTmH`Biv- or is it mb2/ a X TE E F2vpHX vs LuaT TT`Q+?aHQrEXpi2difference, iQh?Bbǵ/Bb+`2iBQM`v 7QMi iQ Bbh?2 .`QT#Qt M ǵTHBMǶ Q#pBQmb HB;im`2bǶX AǶHH TT`Q+? #2 #H2QM2X iQ iQ b2H2+iBM; q?2M HQ/ HH PT2MhvT2HmQi~Q/ i?2 7QMib 7QMiA ?p2i?ii?2KULQi2 i?2`2 rBi? i?i +QKKM/b Bb MQi7QMibT2+  ?m;2biBHH HBF2 $i2ti#QH/2` /Q2bMǶiM22/ 7Q` ?p2 bm+? f 72im`2$i2tiHB;?i2` +QKKM/bX iQ $7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;] "QH/ f >2pv f 1ti` "QH/ f lHi` "QH/ 72im`2bor . . . ? BMbi2/- r?B+? KTT2/ KQ`2b+Mb Mim`HHv$7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]72im`2b i?`Qm;? iQ  `2[mB`2bbiQ`2/72im`2b vQm` BM i?27QMi i?i `2[mB`2b mb2 /B`2+iQ`B2b- i`22X Q7 i?2 `r mb2 72im`2 Q7 Bi `r +M 72im`2 i;b- iF2 i;b-[mBi2 HBF2 HBF2ě r?BH2HQ/ HH i?Bb Q7 i?2b2 Bb6KDGRZHG2XWOQ QM BM Kv QM2iQ/Q ;Q M/ HBbi i?2M Bi brBi+? ?bMǶi #2ir22M #22M 7`2@ PT2MhvT2 ?b [mBi2  MmK#2` Q7 biM/`/ 72im`2aT2+B}+ r2B;?ib rBHH #2 mb2/ BM bT2+B}+ +QMi2tib- M/ mb2` BMi2`7+2XWhereas if h?2 a font7QMibT2+ is loadedBMi2`7+2 by filename iQYHMmK i?2 THBM itiQ is +iBpi2YHMmK iQ ǵHBMBM; +iBpi2'HFR5HJXODU MmK#2`bǶ&Q%RRN ǵHBMBM;&Q0HGLXP MmK#2`bǶ Q` Y/HB;&Q6HPLEROG Q` Y/HB;iQ +iB@&Q%ROGiQ +iB@ i?2K rBi? +QKKM/b HBF2 $i2ti#QH/2`f$i2tiHB;?i2` iQ .`QT#Qt AǶHH #2 #H2 iQ HQ/ HH i?2 7QMib A ?p2 bQK2PT2MhvT2 iBK2 B7aHQr Bi ?bi;b- ?bMǶi&Q8OWUD/LJKW [mBi2 #mih?Bb i?2v `mM&Q/LJKW  Bb MmK#2` `2 M 7Q` MQi Q#pBQmb  r?BH2XQ`;MBb2/ Q7 biM/`/ QM2X GQ/BM; BMiQ q?2M  72im`2 ?B2``+?vX 7QMibHmQi~Q/ AM+M[m2MiHvh?2b2 #2 HQ/2/ `2[m2bi2/ +QK2 BM rBi? #Qi? 7`QK b2KMiB+ ǵMQ`KHǶ mb2`bX,QOLQH&RQG M/ +QKKM/b PM2 ǵ+QM/2Mb2/Ƕ `2bQM BMbi2/XV rB/i?bX KB;?i #2 2tKTH2generally #Qp2 clear, Bb, or at least discoverable, wherepi2 to ǵ/Bb+`2iBQM`v look pi2 ǵ/Bb+`2iBQM`v HB;im`2bǶX HB;im`2bǶX ě r?BH2 i?Bb Bb QM Kv iQ/Q HBbi Bi ?bMǶi #22M 7`2@ &Q+HDY\ &Q([WUD%ROG7QMibT2+&Q8OWUD%ROG i?iULQi2q?2M i?2`2 i?i Bb mbBM; MQi7QMibT2+ :BHH ?m;2biBHH aMb /Q2bMǶiM22/ LQp 7Q` ?p2 Kvb2H7- bm+?  72im`2 +QKKM/bX A mbmHHv iQ biQ`2/ BM i?i i`22X and what to fix if the font cannot be found.#v }H2MK2i;b- It’s #mialso i?2vb+Mb bBKTHvi?2$7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;] `2 i?`Qm;? 2`Hv MQi/Q2bMǶi /vb Q`;MBb2/ vQm` Q7 ?p2 i?2 7QMi /B`2+iQ`B2b-BMiQ i?Bb  T`Q#H2KX ?B2``+?vXT+F;2- Bi +M Bib iF2 M@AM 72im`2 [mBi2 [m2MiHv `2[m2bi2/ 7`QK,QOLQH([WUD/W mb2`bX PM2 `2bQM KB;?i #2 $7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'(easier to set up a multiple-computer environment$7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]bQK2HQ/BM; iBK2 BMi2`7+26KDGRZHG/LJKW B7 Bi ?bMǶi rb `mMKQ/2HH2/ 7Q`  QM r?BH2X TTH2Ƕb GQ/BM;h 7QMi 7QMibrMiaT2+B}+HQ/ J2/BmK HHr2B;?ib Q7 i?2b2 M/ rBHH BM "QH/#2 QM2 mb2/ ;Q BM M/  BM TB`- i?2M bT2+B}+ bQ brBi+? A +QMi2tib- ?p2 #2ir22M  }H2 M/ BM LmK#2`b4GBMBM; - Qi?2`i?2 bT2+i 2`Hv /vb Q7PT2MhvT2 i?2 Q7 i?2 ǵbHQrǶ ?b7QMibT2+ [mBi2 T`Q#H2K T+F;2- MmK#2` Bb i?i Q7 Bib biM/`/ 72im`27`QK 72im`2 M i?i i?2`2 Bb MQi  ?m;2 M22/ 7Q` bm+? +QKKM/bX where all your fonts are stored, say, in Dropbox i2+?MQHQ;vX h?Bb +QKT2iBiQ` iQ PT2MhvT2- [mB2iHv i?2K rBi? +QKKM/b,QOLQH/LJKW HBF2 $i2ti#QH/2`f$i2tiHB;?i2` GB;im`2b4.Bb+`2iBQM`v- HQ/BM;PT2MhvT2 BMi2`7+2#v ?bi;b- }H2MK2 [mBi2 #mi rb i?2v bBKTHvKQ/2HH2/  MmK#2` `2 MQi /Q2bMǶi Q`;MBb2/ QM Q7 TTH2Ƕb biM/`/ ?p2 BMiQ i?Bbh  72im`2 ?B2``+?vX T`Q#H2KX7QMi AM M@Kv+M HQ+HaT2+B}+ #2 HQ/2/i2tK7 r2B;?ib rBi?/B`2+iQ`v rBHH b2KMiB+ #2 mb2/ +HH2/ BM +QKKM/b bT2+B}+;BHH@bMb@MQpX7QMibT2+ +QMi2tib- BMbi2/XV M/ X or on a secureHmQi~Q/ network drive, and thereQT2`iBM; is no ‘font bvbi2K7/BM;6KDGRZHG0HGLXP T2`bT2+iBp2 BM TQTmH`Biv- mb2/Bi +M  F2vpH ;2i TT`Q+? bHQr2` UQM iQ 7QMi ě r?BH2 i?Bb Bb QM Kv iQ/Q HBbi Bi ?bMǶi #22M 7`2@ aHQr h?Bb Bb M Q#pBQmb QM2X q?2M) Qi?2`i?2 bT2+i2`Hv /vb Q7 i?2 Q7 i?2 ǵbHQrǶ7QMibT2+ T`Q#H2KT+F;2- Bb i?i Bib 72im`2 7`QKh?2 M +Mq?2M }`bi #2 Q7 HQ/2/ mbBM; i?2b2 rBi? :BHH?b,QOLQH5HJXODU b2KMiB+ +QMi2Mib aMb LQp +QKKM/b i?i Kvb2H7- HQQFb BMbi2/XV HBF2 A mbmHHv i?Bb, installation’ process anymore. As an example,QH/2`i2+?MQHQ;vXi;b- +QKTmi2`b I store #mi i?2v72im`2b h?Bb T2`?TbV`2 +QKT2iBiQ` MQi BMbi2/- Q`;MBb2/ b r?B+? QM2 iQ KTT2/BMbiHHb BMiQPT2MhvT2-  ?B2``+?vX KQ`2 i2Mb Mim`HHv [mB2iHv Q` ?mM@ AM iQ  [m2MiHv `2[m2bi2/ 7`QK mb2`bX PM2 `2bQM KB;?i #2 QT2`iBM;HQ/BM;6KDGRZHG2XWOQ BMi2`7+2 bvbi2K rb T2`bT2+iBp2 KQ/2HH2/Bi QM +M TTH2Ƕb ;2ih bHQr2`7QMi UQMrMi J2/BmKq?2M mbBM; M/ "QH/:BHH aMb BM  LQp TB`- Kvb2H7- bQ A ?p2 A mbmHHv  }H2 BM b+Mb i?`Qm;? vQm` 7QMi /B`2+iQ`B2b-\k BiaBM+2my +M ‘local’ i?2 iF2 2`Hvtexmf /vbT`2HBKBM`v [mBi2tree Bi in ?b Dropbox #22M /`7i- TQbbB#H2 and m;mbihave7/BM;i?2 iQ +?M;2 a 2`Hv shell R3- BM TQTmH`Biv- /vbkyR3mb2` ky,j9Q7 BMi2`7+2X i?2 mb2/7QMibT2+hl:#Qi- h?2  F2vpH7QMibT2+T+F;2- TT`Q+? oQHmK2BMi2`7+2 Bib 72im`2y iQ iQquaA@ UNNNNV- 7QMi i?2 THBM LQX$/27mHi7QMi72im`2b(;BHH@bMb@MQp)& yi?i i?2`2 Bb MQi ,QOLQH%ROG ?m;2 M22/ 7Q` bm+? +QKKM/bX /`2/b Q7 //BiBQMHQH/2`i2+?MQHQ;vX +QKTmi2`b 7QMibX h?Bb T2`?TbV UJB+`QbQ7i +QKT2iBiQ` b QM2 iQ qQ`/Ƕb PT2MhvT2- BMbiHHb i2Mb [mB2iHv Q` ?mM@ rMi J2/BmK M/ "QH/ BM  TB`- bQ A ?p2  }H2 BM i?2alias +m``2MiHv@b2H2+i2/ set up as 7QMi 72im`2b mbBM; i?272im`2bHQ/BM;$//7QMi72im`2 BMi2`7+2 BMbi2/-2tKTH2 r?B+?rb #Qp2 KQ/2HH2/ KTT2/ Bb, QM KQ`2 TTH2Ƕb Mim`HHvh 7QMi iQ  KvlT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- HQ+HaT2+B}+i2tK7 r2B;?ib/B`2+iQ`v rBHH #2 mb2/ +HH2/ BM bT2+B}+;BHH@bMb@MQpX7QMibT2+ +QMi2tib- M/ X qu: 7QMi K2Mm7/BM; Bb  BM T`iB+mH`Hv TQTmH`Biv- mb2/ 2;`2;BQmb  F2vpH TT`Q+? 2tKTH2 iQ 7QMi Kv HQ+H i2tK7 /B`2+iQ`v +HH2/ ;BHH@bMb@MQpX7QMibT2+X bQK2 iBK2 B7 Bi ?bMǶi `mM 7Q`  r?BH2X+QKKM/X GQ/BM;  `2HiBp2Hv 7QMib `2+2Mi BKT`Qp2K2Mi iQ 7QMibT2+/`2/b Q7 //BiBQMH,QOLQH&RQG 7QMibX UJB+`QbQ7i qQ`/Ƕb quaA@h?2AiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7-+M }`bi6B;m`2 #2 Q7 HQ/2/ i?2b2 R, rBi? //BiBQMH ?b b2KMiB+ +QMi2Mib ǵmMmbmHǶ +QKKM/b i?i 7QMib HQQFb BMbi2/XV BM HBF2 i?2 :BHH i?Bb, aMb alias texmf="sudo tlmgr conf texmf \ mb2`i2+?MQHQ;vX BMi2`7+2X$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'(72im`2b h?Bb h?2 +QKT2iBiQ` BMbi2/-7QMibT2+ r?B+? iQBMi2`7+2 KTT2/ PT2MhvT2- iQKQ`2 i?2 Mim`HHv [mB2iHv THBM iQ  h?2 }`bi Q7 i?2b2 ?b +QMi2Mib i?i HQQFb HBF2 i?Bb, iQ .`QT#Qt/`KiB+HHv AǶHH #2 #H2 BKT`Qp2/ iQ HQ/ HH i?2 i?2 `2HB#BHBiv 7QMibQ7 M/A i?BbXV ?p2 BMi2`MH qu:LmK#2`b4GBMBM;7QMi K2Mm Bb'HFR5HJXODU-  T`iB+mH`Hv 2;`2;BQmb 2tKTH2 LQpq?2M 7KBHvX mbBM; :BHH aMb LQp Kvb2H7- A mbmHHv TEXMFHOME ’~/Dropbox/texmf’"2tKTH27/BM; BM #Qp2 TQTmH`Biv-mb2` Bb, BMi2`7+2X mb2/ h?2  F2vpH7QMibT2+ TT`Q+?BMi2`7+2 iQ iQ 7QMi i?2 THBM$/27mHi7QMi72im`2b(;BHH@bMb@MQp)&"QH/6QMi4h?2b2 +QK2 :BHHaMbLQp@"QH/XQi7- BM #Qi? ǵMQ`KHǶ M/ ǵ+QM/2Mb2/Ƕ rB/i?bX #v }H2MK2 bBKTHv /Q2bMǶi ?p2 i?BbHQ;B+ T`Q#H2KX iQ bm+? +QKKM/bX M@ LQr- r`BiBM; Q7 i?BbXVGB;im`2b4.Bb+`2iBQM`v-,QOLQH([WUD/W $/27mHi7QMi72im`2b(;BHH@bMb@MQp)&rMi J2/BmK M/ "QH/ BM  TB`- bQ A ?p2  }H2 BM biQ`2/ BM i?i i`22X texmf 72im`2b BMbi2/-2tKTH2 r?B+? #Qp2 KTT2/6KDGRZHG/LJKW Bb, KQ`2 Mim`HHv iQ  "QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7-lT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- $//7QMi72im`2b&LmK#2`b4PH/aivH2'This allows me to run on a newj (or$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'( h?2 freshly BMi2`7+2) 7Q` 7QMi 72im`2b ULQi2KvlT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- HQ+H i?ii2tK77QMibT2+/B`2+iQ`v +HH2/biBHH;BHH@bMb@MQpX7QMibT2+ /Q2bMǶi ?p2  72im`2X iQ Qi?2` bT2+i Q7 i?2 ǵbHQrǶ T`Q#H2K Bbupdated) i?i computer 7`QK and M as long as I’m connected j$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'( h?2 BMi2`7+26KDGRZHG0HGLXP 7Q` 7QMi 72im`2b ' AiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7-AiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7- aHQr h?Bb Bb M Q#pBQmb QM2X q?2M HmQi~Q/mb2`LmK#2`b4GBMBM; BMi2`7+2XaBM+2 h?2 i?2 - ,QOLQH/LJKW 2`Hv7QMibT2+ /vbBMi2`7+2 Bi ?b #22M iQ TQbbB#H2 i?2 THBM iQ +?M;2 HQ/h?2 }`bi HH Q7 Q7 i?2b2 i?2b2 ?b BM +QMi2Mib QM2 ;Q i?i M/ HQQFb i?2M HBF2 brBi+?i?Bb, #2ir22M rBHHto Dropbox 2tTHB+Biv /2+iBpi2I’ll be ableLmK#2`b4GBMBM; to load all the fonts}`bi I have #2@ LmK#2`b4GBMBM; - "QH/6QMi4"QH/6QMi4 :BHHaMbLQp@"QH/XQi7- :BHHaMbLQp@"QH/XQi7- b+Mb i?`Qm;? vQm` 7QMi /B`2+iQ`B2b- Bi +M iF2h?2 [mBi22tKTH2 ǵTHBMǶGB;im`2b4.Bb+`2iBQM`v- #Qp2h?2 TT`Q+?i?2 ǵTHBMǶ +m``2MiHv@b2H2+i2/ Bb, 6KDGRZHG2XWOQ TT`Q+? iQ b2H2+iBM; 7QMi iQ 72im`2bb2H2+iBM; PT2MhvT2 mbBM; PT2MhvT2 i?2 7QMi$//7QMi72im`2 7QMih?Bb }H2lHi` HHQrb GB;?i K2 f iQ GB;?i r`Bi2 f$b2iKBM7QMi&;BHH@bMb@MQp' "QQF f J2/BmK f a2KB#QH/ f QT2`iBM; bvbi2K T2`bT2+iBp2 Bi +M7Q`2stored ;2i //BM; in bHQr2` that i?2 tree. M2r UQMYQMmK PT2MhvT2 i;X PT2M@ GB;im`2b4.Bb+`2iBQM`v- i?2K$/27mHi7QMi72im`2b(;BHH@bMb@MQp)&"QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7- rBi? +QKKM/b HBF2 $i2ti#QH/2`f$i2tiHB;?i2` ) ,QOLQH5HJXODU7QMibT2+b"QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7-  b?Q`i?M/X"QH/ b f >2pv r2HH- A f +QmH/ 1ti` r`Bi2, "QH/ f lHi` "QH/ bQK2 iBK2 B7hvT2 Bi ?bMǶi 72im`2b `mM `2 7Q` MQr  r?BH2X T`QpB/2/ GQ/BM; +QMbBbi2MiHv72im`2b 7QMib$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'( rBi? `2[mB`2b72im`2b+QKKM/X) i?2 `2[mB`2b mb2  `2HiBp2Hv Q7 i?2 `r,QOLQH&RQG mb2 `2+2Mi 72im`2 Q7BKT`Qp2K2Mi `r 72im`2 i;b- iQ i;b- HBF2 HBF2ě' lT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- r?BH2 i?Bb Bb QM Kv iQ/Q HBbi Bi ?bMǶi #22M 7`2@ QH/2` +QKTmi2`b T2`?TbV b QM2 BMbiHHbSlow. i2MbThis Q` is an ?mM@ obvious one. When luaotfload /`KiB+HHv BKT`Qp2/ i?2 `2HB#BHBiv M/ BMi2`MH' AiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7- #v }H2MK2P77 bBKTHvM/ _2b2i /Q2bMǶip`BMib ?p2 U2X;X- i?BbLmK#2`b4PH/aivH2P77 T`Q#H2KXYHMmKaBM+2 M@LmK#2`b4GBMBM;iQ i?2 +iBpi2YHMmK 2`HvaBM+2 /vbiQ ǵHBMBM; i?2 - +iBpi2 2`Hv Bi ?b,QOLQH([WUD/W MmK#2`bǶ /vb ǵHBMBM; #22M Bi ?b TQbbB#H2MmK#2`bǶ Q` #22MY/HB; TQbbB#H2 iQ Q` +?M;2Y/HB;iQ iQ +iB@ +?M;2iQ +iB@$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF' scans through your font directories, it can take quite HQ;B+ iQ bm+?,QOLQH%ROG +QKKM/bX LQr- r`BiBM; [m2MiHvh?Bb"QH/6QMi4h?2b2 }H2 HHQrb `2[m2bi2/ +QK2 :BHHaMbLQp@"QH/XQi7- K2 BM iQ #Qi? r`Bi2 7`QK ǵMQ`KHǶ$b2iKBM7QMi&;BHH@bMb@MQp' mb2`bX M/ PM2 ǵ+QM/2Mb2/Ƕ `2bQM rB/i?bX KB;?i #2 Qi?2` bT2+iM/ Q7LmK#2`b4PH/aivH2_2b2i i?2 ǵbHQrǶquaA@ T`Q#H2K Bb i?iV r?B+? 7`QK BMi2`+ii?2 MGB;im`2b4.Bb+`2iBQM`v- +m``2MiHv@b2H2+i2/ T`QT@pi2i?2 ǵ/Bb+`2iBQM`v +m``2MiHv@b2H2+i2/ 7QMi 72im`2b HB;im`2bǶX 7QMi 72im`2b mbBM; i?2 mbBM;$//7QMi72im`2 i?2 $//7QMi72im`2h?Bb }H2 HHQrb K2 iQ r`Bi2 $b2iKBM7QMi&;BHH@bMb@MQp' /`2/b Q7 //BiBQMH 7QMibX UJB+`QbQ7isome qQ`/Ƕb time. Loading fonts by filenamepi2 simply ǵ/Bb+`2iBQM`v doesn’t $//7QMi72im`2b&LmK#2`b4PH/aivH2' HB;im`2bǶX,QOLQH/LJKW rBi?b bBKBH`"QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7- ULQi2 b?Q`i?M/X Ki+?BM; i?i b7QMibT2+ r2HH-X7QMibT2+ AbiBHH +QmH/ /Q2bMǶi r`Bi2,}H2- M/?p2 i?2M  72im`2 mb2 iQ 2`Hv rBi? i?2 72im`2 HQ/BM; HQ;B+ iQ 2Bi?2`) 7Q`+B#Hv $7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]+QKKM/XFigure 2: Additional  `2HiBp2Hv ‘unusual’ `2+2Mi BKT`Qp2K2Mi fonts in the Gill iQ 7QMibT2+ Sans bi?i  b?Q`i?M/X i?2`2 Bb b MQi r2HH-  ?m;2 A +QmH/ M22/ r`Bi2, 7Q` bm+? +QKKM/bX QT2`iBM; bvbi2Khave this T2`bT2+iBp2 problem. Bi Another +M ;2i aspect bHQr2` of+QKKM/X theUQM ‘slow’  `2HiBp2Hv `2+2Mi BKT`Qp2K2Mi iQ 7QMibT2+ $#QQF7QMi' HQ/ HHBM Q7 i?2 i?2b2 b2imT BM QM2 Q7 i?2 ;Q M/ ivTQ;`T?v i?2M brBi+? Q7 #2ir22M i?2 qu: /2+iBpi2  72im`2 Q` iQ `2b2i i?i T`iB+mH`$7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]7QMibT2+ rBHH/`KiB+HHvNova 2tTHB+Biv family. ,QOLQH5HJXODU /2+iBpi2 BKT`Qp2/LmK#2`b4GBMBM; i?2 `2HB#BHBiv M/ BMi2`MH}`bi #2@ aT2+B}+$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF' r2B;?ib rBHH #2 mb2/ BM bT2+B}+ +QMi2tib- M/ 7QMi K2Mm Bb  T`iB+mH`HvQH/2` +QKTmi2`b 2;`2;BQmbproblem T2`?TbV is that 2tKTH2 fromb QM2 an BMbiHHb operating i2Mb system Q` perspective?mM@/`KiB+HHvaBM+2 i?2PT2MhvT2 2`Hv BKT`Qp2/ /vb ?b Bi ?b i?2 [mBi2 #22M `2HB#BHBiv  MmK#2` TQbbB#H2 M/ Q7 iQ biM/`/ BMi2`MH +?M;2 72im`2$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF'$i2ti#QH/2` $i2tiHB;?i2` 72im`2 iQ Bib /27mHi bii2X 7Q`2HQ;B+ //BM; iQ bm+? i?2 +QKKM/bX,QOLQH%ROG M2r YQMmK LQr-PT2MhvT2 r`BiBM; i;X PT2M@/Q+mK2MiXh?Bbi?2K }H2 HHQrb rBi? K2+QKKM/b iQ r`Bi2 $b2iKBM7QMi&;BHH@bMb@MQp' HBF2 f /`2/b Q7 //BiBQMHit can get 7QMibX slower UJB+`QbQ7i (on older qQ`/Ƕb computersPT2MhvT2quaA@ especially)i?2 +m``2MiHv@b2H2+i2/ ?bi;b- [mBi2 #mi i?2v  7QMi MmK#2` `2 72im`2b MQi Q`;MBb2/ Q7 mbBM; biM/`/ BMiQi?2 $//7QMi72im`2  72im`2 ?B2``+?vX AM+M #2 HQ/2/ rBi?X7QMibT2+ b2KMiB+ +QKKM/b BMbi2/XV Q7 i?BbXV HQ;B+ iQ bm+?hvT2$//7QMi72im`2b&LmK#2`b4PH/aivH2' +QKKM/bX 72im`2b `2 LQr- MQr r`BiBM; T`QpB/2/ +QMbBbi2MiHv rBi?rBi?rBi?bLQr- bBKBH` ě b?Q`i?M/X bBKBH` r?BH2 i?2 Ki+?BM; +QKKM/ Ki+?BM; i?Bb b Bb r2HH- QMX7QMibT2+ bi`iBM; A Kv +QmH/ iQ/Q r`Bi2,$/27mHi7QMi72im`2b(;BHH@bMb@MQp)}H2- HBbi}H2- M/ Bi M/ ?bMǶii?2M i?2M mb2 #22M mb2 7`2@ qu: 7QMi K2Mm9as hvTB+Hone Bb installs  T`iB+mH`Hv 2tKTH2 tens or hundreds 2;`2;BQmb ofh?2b2 additional 2tKTH2i;b-+QKKM/X #mi +QK2 fonts. i?2vi?2 P77It `2BM `2HiBp2Hv2`Hv isM/ also #Qi? MQi_2b2i /vb possible Q`;MBb2/ `2+2Mi Q7ǵMQ`KHǶp`BMib i?2 to changeBKT`Qp2K2Mi7QMibT2+ U2X;X- BMiQ theLmK#2`b4PH/aivH2P77  M/ font ?B2``+?vXT+F;2- featuresiQ ǵ+QM/2Mb2/Ƕ7QMibT2+ Bib for AM 72im`2 the $#QQF7QMi[m2MiHv rB/i?bXq?2MBM `2[m2bi2/ mbBM; i?2 b2imT :BHH 7`QK Q7 aMb i?2 mb2`bX ivTQ;`T?v LQp PM2 `2bQM Kvb2H7- Q7 i?2 KB;?i A mbmHHv #2 $//7QMi72im`2b&LmK#2`b4PH/aivH2'rBHH6B;m`2 2tTHB+Biv k, //BiBQMH /2+iBpi2 ǵmMmbmHǶLmK#2`b4GBMBM; 7QMib BM i?2 :BHH}`bi aMb #2@/Q2bMǶi$#QQF7QMi M22/BM iQ i?2 #2 b2imT BM  Q77KBHv i?2 ivTQ;`T?v MK2 X7QMibT2+ Q7 i?2 Q7 i?BbXV G2iǶb(Microsoft ;Q #+F Word’s iQ i?2WYSIWYG :BHH aMbfont LQp menu 2tKTH2X is a good Ai HQ/BM;M/currently-selectedLmK#2`b4PH/aivH2_2b2i BMi2`7+2 rb font KQ/2HH2/ using \addfontfeatures QMV r?B+? TTH2Ƕb BMi2`+ih T`[email protected]Mi/Q+mK2MiX$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF' J2/BmK M/ "QH/ BM  TB`- bQ A ?p2  }H2 BM i?2/`KiB+HHv 2`Hv /vbh?2b27Q`2LQp Q7BKT`Qp2/ +QK2 //BM; 7KBHvX i?2 BM7QMibT2+ i?2#Qi? i?2 M2r ǵMQ`KHǶ `2HB#BHBivYQMmKT+F;2-PT2MhvT2 M/ M/ ǵ+QM/2Mb2/Ƕ Bib BMi2`MH 72im`2i;X PT2M@ rB/i?bX}H2c/Q+mK2MiX Bii?i +QmH/ i?2`2 #2 BM Bb MQi +Hbb  ?m;2 Q` T+F;2 M22/ 7Q` }H2- bm+? Q` +QKKM/bX 2p2M +QMiBMbexample 7QMib of this.) BM i?2 7QHHQrBM; r2B;?ib,ULQi2rBHH 2tTHB+Biv i?ii2+?MQHQ;vX2`Hvrelatively7QMibT2+ /2+iBpi2 rBi? i?2 recent h?Bb 72im`2LmK#2`b4GBMBM; +QKT2iBiQ`biBHH improvement HQ/BM; /Q2bMǶi HQ;B+ iQ to PT2MhvT2-fontspec iQ}`bi 2Bi?2` ?p2 #2@dramati- 7Q`+B#Hv [mB2iHv  72im`2LQr- i?2 iQ +QKKM/ bi`iBM; $/27mHi7QMi72im`2b(;BHH@bMb@MQp) j h?2 BMi2`7+2 7Q` 7QMi 72im`2b HQ;B+ iQ bm+?hvT2 +QKKM/bX 72im`2b `2 LQr- MQr r`BiBM; T`QpB/2/ +QMbBbi2MiHvh rBi? KvrBi?LQr- HQ+HaT2+B}+ bBKBH` i?2i2tK7 +QKKM/ r2B;?ib Ki+?BM;/B`2+iQ`v rBHHX7QMibT2+ bi`iBM; #2 mb2/ +HH2/$/27mHi7QMi72im`2b(;BHH@bMb@MQp)}H2- BM bT2+B}+ M/;BHH@bMb@MQpX7QMibT2+ i?2M +QMi2tib- mb2 M/ X HQ/BM;7Q`2 //BM; BMi2`7+2ULQi2/2+iBpi2cally i?2 i?i rb M2r improved7QMibT2+ KQ/2HH2/ YQMmK 72im`2 thePT2MhvT2 Q`reliabilitybiBHH QMiQ `2b2i /Q2bMǶi TTH2Ƕb i?i and i;X T`iB+mH`internal ?p2 PT2M@  logic7QMi 72im`27QMibT2+ forDmbi iQ/Q2bMǶi Tbi2/ M22/ BMiQ iQ  /Q+mK2Mi #2 BM  7KBHv T`2K#H2X MK2 X7QMibT2+ "mi i?Bb T@ j h?2 BMi2`7+2lHi` GB;?i 7Q` f 7QMi GB;?i 72im`2bf "QQF f J2/BmK f a2KB#QH/ f 7/BM;P77 M/ BM TQTmH`Biv-_2b2i p`BMib mb2/ U2X;X-  F2vpHLmK#2`b4PH/aivH2P77 TT`Q+? iQ 7QMi $#QQF7QMi+M #2 HQ/2/BM i?2 b2imT rBi? b2KMiB+ Q7 i?2 ivTQ;`T?v +QKKM/b Q7 i?2BMbi2/XV 3 The interface for font featuresHQ/i2+?MQHQ;vX$//7QMi72im`2b&LmK#2`b4PH/aivH2' HH Q7HQ/ h?Bb i?2b272im`2such HH +QKT2iBiQ` Q7 commands. iQ i?2b2 BM Bib /27mHi QM2 BM Now, QM2 iQ bii2X ;Q ;Qwriting PT2MhvT2- M/ M/ i?2M i?2M brBi+? [mB2iHv brBi+? #2ir22MT`Q+?/Q2bMǶih?2}H2c #2ir22M }`biBiF22Tb M22/ +QmH/ Q7 iQvQm` #2 i?2b2 #2 BM T`2K#H2 BM ?b+Hbb  +QMi2Mib7KBHv Q` T+F;2b iB/v MK2 i?i }H2- bX7QMibT2+ TQbbB#H2Q` HQQFb 2p2M HBF2 B7 i?Bb, "QH/ f >2pv f 1ti` "QH/ f lHi` "QH/hvT2 72im`2b72im`2bM/ `2LmK#2`b4PH/aivH2_2b2i BMbi2/- MQr T`QpB/2/ r?B+? KTT2/ +QMbBbi2MiHvV KQ`2 r?B+? Mim`HHv BMi2`+i rBi? T`QT@ iQ  /Q+mK2MiXq?2M mbBM; :BHH aMb LQp Kvb2H7- A mbmHHv h?2 ǵTHBMǶ TT`Q+? iQ b2H2+iBM;h?2 ǵTHBMǶ PT2MhvT2 TT`Q+?The ‘plain’ approach iQ b2H2+iBM; 7QMi to selecting PT2MhvT2 OpenType 7QMi font fea- vQm}H2cDmbi ?p2 Bi +QmH/ Tbi2/  b2`B2b #2 BMiQ BM  Q7 /Q+mK2Mi  7QMi +Hbb 7KBHv Q` T`2K#H2X T+F;2 /2}MBiBQMb "mi }H2- i?Bb vQm Q` T@ 2p2M rBHH i?2K7/BM;P77rBHH rBi? BMM/2tTHB+Biv TQTmH`Biv-i?2K_2b2imb2` +QKKM/b2`Hv\addfontfeatures{Numbers /2+iBpi2 rBi? BMi2`7+2Xp`BMib rBi? +QKKM/b mb2/ i?2 U2X;X- 72im`2LmK#2`b4GBMBM; h?2  F2vpHHBF2LmK#2`b4PH/aivH2P777QMibT2+ HBF2 HQ/BM;$i2ti#QH/2` =TT`Q+? OldStyle}HQ;B+BMi2`7+2 iQ}`bi 2Bi?2` iQ iQf$i2tiHB;?i2` #2@ 7QMi 7Q`+B#Hv i?2 THBMf$i2tiHB;?i2`$/27mHi7QMi72im`2b(;BHH@bMb@MQp)&LQr- i?2 +QKKM/ bi`iBM; $/27mHi7QMi72im`2b(;BHH@bMb@MQp) 72im`2b `2[mB`2btures requires i?2 mb2 the Q7 use `r of raw 72im`2 feature i;b- tags, like HBF2+lnum 9 hvTB+H 2tKTH2 T`Q+?rMi F22Tb J2/BmK vQm` M/T`2K#H2 "QH/ b BM iB/v  TB`- b TQbbB#H2 bQ A ?p2 B7  }H2 BM T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,jN72im`2bM/7Q`2LmK#2`b4PH/aivH2_2b2i //BM; BMbi2/-ě2tKTH2 r?BH2/2+iBpi2will i?2 r?B+? explicitly M2r i?Bb #Qp2 T`2HBKBM`vYQMmK Bb 72im`2KTT2/ Bb,deactivate QM KvPT2MhvT2 Q` iQ /`7i-V iQ/QKQ`2 `2b2ir?B+?Numbers m;mbi HBbii?i Mim`HHv BMi2`+i i;X BiT`iB+mH` = R3-Lining?bMǶi PT2M@ kyR3 T`QT@ iQ7QMibT2+before #22M ky,jN  UT`Q##HvVDmbi 7`2@/Q2bMǶi Tbi2/lT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- M22/ `2mb2 BMiQ iQ  #2ir22M /Q+mK2Mi #2 BM  /Q+mK2MibX7KBHv T`2K#H2X MK2 X7QMibT2+ "mi i?Bb T@ 72im`2b `2[mB`2b i?2 mb2 Q7YHMmK `riQ 72im`2 +iBpi2to activate ǵHBMBM; i;b- ‘lining MmK#2`bǶ numbers’ HBF2 Q` Y/HB; or +dligiQto +iB@ activate G2iǶb ;Q #+F iQ i?2 :BHH aMb LQp 2tKTH2X Ai vQmKv ?p2 HQ+H  b2`B2bi2tK7 Q7/B`2+iQ`v 7QMi 7KBHv +HH2/ /2}MBiBQMb;BHH@bMb@MQpX7QMibT2+ vQm rBHH X ě r?BH2[m2MiHv i?Bb72im`2adding Bb `2[m2bi2/ iQ the QM Bib new /27mHi Kv+onum 7`QK bii2X iQ/Q mb2`bXOpenType PM2 HBbi tag. `2bQM Bi OpenType ?bMǶi KB;?iT`Q+? #2}H2c #22M BiF22Tb +QmH/ 7`2@ vQm` #2 BM T`2K#H2  +Hbb Q` T+F;2b iB/v }H2- b TQbbB#H2Q` 2p2M B7 ‘discretionary ligatures’. mb2`2`HvhvT2 BMi2`7+2X rBi? 72im`2b$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'( i?2+QMiBMb 72im`2 h?2 `2 MQr7QMibT2+ 7QMib HQ/BM; BMT`QpB/2/ i?2 HQ;B+BMi2`7+2 7QHHQrBM; +QMbBbi2MiHv iQ 2Bi?2` r2B;?ib, iQ i?2 7Q`+B#Hv rBi? THBM UT`Q##HvVAiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7-h?2 }`bi `2mb2 Q7L6aa i?2b2 #2ir22M ?b /Q+mK2MibX +QMi2Mib i?i HQQFb HBF2 i?Bb, YHMmK iQ +iBpi2 ǵHBMBM; MmK#2`bǶpi2 ǵ/Bb+`2iBQM`v Q` Y/HB; HB;im`2bǶXiQ +iB@ features are now provided consistently with Off and8vQm //BiBQMHDmbi ?p2 Tbi2/  b2`B2b BMiQ  Q7 /Q+mK2Mi 7QMi/2+H`iBQMb 7KBHv T`2K#H2X /2}MBiBQMb "mi i?Bb vQm T@ rBHH [m2MiHv/2+iBpi2P77 M/ `2[m2bi2/i?i_2b2i LmK#2`b4GBMBM;9 72im`2 i?2`2p`BMib hvTB+H Bb Q` MQi iQ 7`QK2tKTH2 U2X;X- `2b2i  - ?m;2LmK#2`b4PH/aivH2P77 i?i mb2`bX M22/ T`iB+mH` 7Q` PM2 bm+?7QMibT2+ +QKKM/bX `2bQM KB;?i"QH/6QMi4 #2 :BHHaMbLQp@"QH/XQi7- \font\x="[EBGaramond12-Regular.otf]:+lnum;+dlig"2tKTH2 #Qp2Reset Bb, variants (e.g., Numbers = OldStyleOff and T`Q+? F22Tb vQm` T`2K#H2 b iB/v b TQbbB#H2 B7 $7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]72im`2M/ LmK#2`b4PH/aivH2_2b2i iQaT2+B}+ BibGB;im`2b4.Bb+`2iBQM`v-T`2HBKBM`v /27mHi r2B;?ib bii2X /`7i- rBHH m;mbi #2 mb2/V r?B+? R3- BM kyR3 bT2+B}+ BMi2`+i ky,je +QMi2tib- T`QT@ h?2UT`Q##HvV M/ "QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7- biM/`/$/27mHi7QMi72im`2b(;BHH@bMb@MQp)& `2mb2 T`2HBKBM`v ǵ7QMibǶ #2ir22M i?i /`7i- /Q+mK2MibX +QmH/ m;mbi #2 R3- HQ/2/ kyR3 ky,je rBi?BM pi2 ǵ/Bb+`2iBQM`v HB;im`2bǶX OpenType has quite a number of standard$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'( feature G2iǶbNumbers ;Q #+F = OldStyleReset iQ i?2 :BHH aMb) which LQp interact 2tKTH2X properly Ai vQm ?p2lT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7-  b2`B2b Q7 7QMi 7KBHv /2}MBiBQMb vQm rBHH i?i2`Hv i?2`2 rBi?+M) i?2 Bb #2 72im`2 MQiHQ/2/ HQ/BM;  rBi? ?m;2 b2KMiB+ HQ;B+ M22/ iQ 2Bi?2`+QKKM/b 7Q` 7Q`+B#Hv bm+? BMbi2/XV7QMibT2+ +QKKM/bX' ?p2 #22M `2bi`B+i2/ iQ i?2 `2HiBp2Hv biM@ PT2MhvT2 ?btags, [mBi2 but they  MmK#2` are not organised Q7 biM/`/ into a 72im`2 hierarchy. In +QMiBMbwith the 7QMibfeature BM loading i?2 7QHHQrBM; logic to r2B;?ib, either forcibly deac-8 //BiBQMHUT`Q##HvVAiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7- `2mb2L6aa #2ir22M/2+H`iBQMb /Q+mK2MibX LmK#2`b4GBMBM;9 hvTB+HaBM+2q?2M 2tKTH2 i?2 - 2`Hv mbBM; /vb :BHH Bi aMb ?b #22M LQp TQbbB#H2 Kvb2H7- iQ A +?M;2 mbmHHv/`/ b2i Q7, $7QMi$t4](1":`KQM/Rk@_2;mH`XQi7),YHMmKcY/HB;]i;b- #mi i?2vthe `2 early MQi days Q`;MBb2/ of the fontspec BMiQ  ?B2``+?vXpackage,aT2+B}+ its/2+iBpi2 AM feature r2B;?ib tivate 72im`2 a rBHH feature Q` iQ `2b2i #2 or to mb2/i?i reset T`iB+mH` that BM particular bT2+B}+7QMibT2+fontspec +QMi2tib-"QH/6QMi4 M/ :BHHaMbLQp@"QH/XQi7- GB;im`2b4.Bb+`2iBQM`v- i?2 +m``2MiHv@b2H2+i2/ 7QMi 72im`2b mbBM; i?2 $//7QMi72im`2h?Bb }H2 HHQrb K2 iQ r`Bi2 $b2iKBM7QMi&;BHH@bMb@MQp' i?2 2`Hv /vbloading Q7 i?2 interface7QMibT2+ was modelledT+F;2- on Bib Apple’s 72im`2G2iǶb72im`2AAT font ;Q iQrMi #+F BibT`2HBKBM`vfeature /27mHiJ2/BmK iQ i?2 to its bii2X :BHH/`7i- M/ default aMb"QH/ m;mbi state. BMLQp R3-  TB`- kyR3 2tKTH2X ky,je bQ A ?p2 Ai  }H2lT`B;?ih?2 BM biM/`/"QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7-f AiHB+ T`2HBKBM`v ǵ7QMibǶf "QH/ i?i /`7i-f +QmH/"QH/AiHB+ m;mbi #2 R3- HQ/2/ kyR3f aHMi2/ ky,je rBi?BM ) +QKKM/X  `2HiBp2Hv `2+2Mi BKT`Qp2K2Mi iQ 7QMibT2+b  b?Q`i?M/X b r2HH- A +QmH/ r`Bi2, PT2MhvT2 ?b [mBi2  MmK#2`HQ/BM; Q7 BMi2`7+2 biM/`/technology. rb KQ/2HH2/ This 72im`2 competitor QM TTH2Ƕb to OpenType,+Mh 7QMi #2 quietly HQ/2/Kv HQ+H rBi?i2tK7 /B`2+iQ`v b2KMiB+ +HH2/ ;BHH@bMb@MQpX7QMibT2+ +QKKM/b7QMibT2+ BMbi2/XV' ?p2X #22M `2bi`B+i2/"QH/aHMi2/ iQ i?2 `2HiBp2Hv biM@ +QMiBMb 7QMib4 BM Typical i?2 7QHHQrBM; example r2B;?ib, f i2+?MQHQ;vX h?Bbfading +QKT2iBiQ` in popularity, iQ used PT2MhvT2- a keyval approachaBM+2 [mB2iHv9 i?2to hvTB+H font 2`Hvh?2/`KiB+HHv 2tKTH2}`bi /vb Q7 Bi i?2b2 ?bBKT`Qp2/ ?b #22M +QMi2Mib i?2 TQbbB#H2 `2HB#BHBiv i?i iQ HQQFb +?M;2 M/ HBF2 BMi2`MH i?Bb,/`/$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF' b2i Q7, i;b- #mi i?2v `2 MQi Q`;MBb2/ BMiQ features ?B2``+?vX instead, which AM mapped more naturallylHi`q?2M GB;?i to HQ;B+ fmbBM;Let’s GB;?i iQ now bm+? f introduce "QQF:BHH +QKKM/bX f aMba J2/BmK commercial LQr- LQp f r`BiBM; a2KB#QH/ font, and Kvb2H7- use f thisUM/ A rBi?BMh?Bb mbmHHv }H2 i?2b2 HHQrb 7QMib K2 #Qi?iQ r`Bi2 MQ`KH$b2iKBM7QMi&;BHH@bMb@MQp' M/ bKHH +Tb 7/BM; BM TQTmH`Biv- mb2/  F2vpH TT`Q+? iQG2iǶb 7QMi ;Q$/27mHi7QMi72im`2b(;BHH@bMb@MQp)& #+F iQ i?2 :BHH aMb LQp 2tKTH2X Ai lT`B;?i f AiHB+ f "QH/ f "QH/AiHB+ f aHMi2/ a user interface. The fontspec interfacei?2 to +m``2MiHv@b2H2+i2/ the plain"QH/ fin >2pv an example f 7QMi 1ti` 72im`2b of "QH/ setting f mbBM; uplHi` a custom i?2 "QH/$//7QMi72im`2 font fromb?T2brBi?b `2 bBKBH`  HHQr2/XVb?Q`i?M/X Ki+?BM; b r2HH-X7QMibT2+ A +QmH/ r`Bi2,}H2- M/ i?2M mb2 rMi J2/BmK$//7QMi72im`2b&LmK#2`b4PH/aivH2'lT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- M/ "QH/ BM  TB`- bQ A ?p2  }H2 BM i?2 2`Hv /vb Q7 i?2 7QMibT2+72im`2bT+F;2- BMbi2/-example r?B+? Bib above KTT2/ 72im`2 is: KQ`2 Mim`HHv+QKKM/X+QMiBMb iQ  7QMib `2HiBp2Hvscratch; BM i?2 I’ll 7QHHQrBM; `2+2Mi use ‘Gill BKT`Qp2K2Mi r2B;?ib,Sans Nova’ as it iQ comes7QMibT2+ with $#QQF7QMi BMf i?2"QH/aHMi2/ b2imT Q7 i?2 ivTQ;`T?v Q7 i?2 mb2` BMi2`7+2X h?2 7QMibT2+ BMi2`7+2 iQ i?2 THBM rBHHAiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7- 2tTHB+Biv /2+iBpi2 LmK#2`b4GBMBM; }`bi #2@ $M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF' \fontspec{EBGaramond12-Regular.otf}[ T`2HBKBM`vlHi` GB;?i fa /`7i- rangeGB;?i m;mbi of f weights "QQF R3- f and J2/BmK kyR3 styles. ky,j9 Thisf a2KB#QH/ font family f hasUM/ rBi?BM T`2HBKBM`v i?2b2 7QMib /`7i- #Qi? MQ`KHm;mbi M/ R3- kyR3 bKHH ky,j9 +Tb HQ/BM; BMi2`7+2 rb KQ/2HH2/ QM TTH2Ƕb h 7QMi Kv/`KiB+HHv HQ+H i2tK77Q`2"QH/6QMi4 BKT`Qp2/ //BM;/B`2+iQ`v:BHHaMbLQp@"QH/XQi7- i?2 i?2 M2r `2HB#BHBivYQMmK +HH2/PT2MhvT2 M/;BHH@bMb@MQpX7QMibT2+ BMi2`MH i;X PT2M@/Q+mK2MiX X 2tKTH2 #Qp2Numbers Bb, = Lining , upright and italic fonts in both ‘normal’ and ‘con- HQ;B+ iQ"QH/ bm+?hvT2"QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7- f +QKKM/bX >2pv 72im`2b f 1ti` `2 LQr- MQr"QH/ r`BiBM; T`QpB/2/ f lHi` "QH/ +QMbBbi2MiHv rBi?b?T2brBi? `2LQr- HHQr2/XV bBKBH` i?2 +QKKM/ Ki+?BM; X7QMibT2+ bi`iBM; $/27mHi7QMi72im`2b(;BHH@bMb@MQp)}H2- M/ i?2M mb2 i2+?MQHQ;vX h?Bb +QKT2iBiQ`$7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'( iQ PT2MhvT2-Ligatures = [mB2iHv Discretionary , h?2 }`bi Q7densed’ i?2b2 widths ?b with +QMi2Mib a large range i?i of weights HQQFb (see HBF2 i?Bb, ] $//7QMi72im`2b&LmK#2`b4PH/aivH2'' P77FiguresM/ _2b2i 1 andp`BMib 2). U2X;X- LmK#2`b4PH/aivH2P77 /Q2bMǶi$#QQF7QMi M22/BM iQ i?2 #2 b2imT BM  Q77KBHv i?2 ivTQ;`T?v MK2 X7QMibT2+ Q7 i?2 LmK#2`b4GBMBM; - T`2HBKBM`vM/ /`7i-LmK#2`b4PH/aivH2_2b2i m;mbi R3- kyR3 ky,j9V r?B+? BMi2`+i T`QT@ /Q+mK2MiX T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,j9 7/BM; BM TQTmH`Biv- mb2/  F2vpH TT`Q+? iQ 7QMi $/27mHi7QMi72im`2b(;BHH@bMb@MQp)&h?Bb }H2 HHQrb K2 iQ r`Bi2 $b2iKBM7QMi&;BHH@bMb@MQp'}H2c Bi +QmH/ #2 BM  +Hbb Q` T+F;2 }H2- Q` 2p2M GB;im`2b4.Bb+`2iBQM`v- rBHH 2tTHB+Biv2`Hv /2+iBpi2 rBi? i?2 72im`2LmK#2`b4GBMBM; HQ/BM; HQ;B+ iQ}`bi 2Bi?2` #2@ 7Q`+B#Hv LQr- i?2 +QKKM/ bi`iBM; $/27mHi7QMi72im`2b(;BHH@bMb@MQp) ) Will Robertson b  b?Q`i?M/X b r2HH- A +QmH/ r`Bi2, 72im`2b BMbi2/- r?B+? KTT2/ KQ`2 Mim`HHv iQ  7Q`2lT`B;?i6QMi4:BHHaMbLQp@J2/BmKXQi7- //BM;/2+iBpi2 i?2 M2r YQMmK 72im`2PT2MhvT2 Q` iQ `2b2i i?i i;X T`iB+mH` PT2M@7QMibT2+Dmbi/Q2bMǶi Tbi2/ M22/ BMiQ iQ  /Q+mK2Mi #2 BM  7KBHv T`2K#H2X MK2 X7QMibT2+ "mi i?Bb T@ mb2` BMi2`7+2X h?2 7QMibT2+aBM+2BMi2`7+2 i?2 2`Hv /vb iQ i?2Bi ?b THBM#22M TQbbB#H2 iQhvT2 +?M;2AiHB+6QMi4:BHHaMbLQp@J2/BmKAiHB+XQi7- 72im`2b$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF'72im`2 `2 iQ MQr Bib /27mHi T`QpB/2/ bii2X +QMbBbi2MiHv rBi? T`Q+?}H2c BiF22Tb +QmH/ vQm` #2 BM T`2K#H2  +Hbb Q` T+F;2b iB/v }H2- b TQbbB#H2Q` 2p2M B7 i?2 +m``2MiHv@b2H2+i2/ 7QMi 72im`2b mbBM; i?2 P77$//7QMi72im`2M/ _2b2irBi?p`BMib bBKBH` Ki+?BM; U2X;X- LmK#2`b4PH/aivH2P77X7QMibT2+ }H2- M/ i?2M mb2vQmDmbi ?p2 Tbi2/  b2`B2b BMiQ  Q7 /Q+mK2Mi 7QMi 7KBHv T`2K#H2X /2}MBiBQMb "mi i?Bb vQm T@ rBHH "QH/6QMi49 hvTB+H :BHHaMbLQp@"QH/XQi7- 2tKTH2 T`Q+? F22Tb vQm` T`2K#H2 b iB/v b TQbbB#H2 B7 2tKTH2 #Qp2 Bb, +QKKM/X  `2HiBp2Hv `2+2Mi BKT`Qp2K2Mi iQM/7QMibT2+LmK#2`b4PH/aivH2_2b2i$#QQF7QMi BM i?2 b2imTV r?B+? Q7 i?2 BMi2`+i ivTQ;`T?v T`QT@ Q7 i?2UT`Q##HvV `2mb2 #2ir22M /Q+mK2MibX /`KiB+HHv BKT`Qp2/ i?2 `2HB#BHBiv M/ BMi2`MH G2iǶb ;Q #+F iQ i?2 :BHH aMb LQp 2tKTH2X Ai vQm ?p2  b2`B2b Q7 7QMi 7KBHv /2}MBiBQMb vQm rBHH 2`Hv"QH/AiHB+6QMi4:BHHaMbLQp@"QH/AiHB+XQi7- rBi? i?2/Q+mK2MiX 72im`2 HQ/BM; HQ;B+ iQ 2Bi?2` 7Q`+B#Hv $7QMibT2+&1":`KQM/Rk@_2;mH`XQi7'(HQ;B+ iQ bm+? +QKKM/bX LQr- r`BiBM; +QMiBMb 7QMib BM i?2 7QHHQrBM; r2B;?ib, 8 //BiBQMHUT`Q##HvV `2mb2L6aa #2ir22M/2+H`iBQMb /Q+mK2MibX ' /2+iBpi2  72im`2LQr- Q` i?2 iQ +QKKM/ `2b2i i?i bi`iBM; T`iB+mH`$/27mHi7QMi72im`2b(;BHH@bMb@MQp)7QMibT2+ $//7QMi72im`2b&LmK#2`b4PH/aivH2' /Q2bMǶi M22/ iQ #2 BM  7KBHv MK2 X7QMibT2+ LmK#2`b4GBMBM; - 72im`2 iQ BibT`2HBKBM`v /27mHi bii2X /`7i- m;mbi R3- kyR3 ky,jeh?2 biM/`/ T`2HBKBM`v ǵ7QMibǶ i?i /`7i- +QmH/ m;mbi #2 R3- HQ/2/ kyR3 ky,je rBi?BM rBHH 2tTHB+Biv /2+iBpi2 LmK#2`b4GBMBM; h?Bb}`bi #2@ }H2 HHQrb}H2c Bi +QmH/ K2 #2 iQ BM r`Bi2  +Hbb$b2iKBM7QMi&;BHH@bMb@MQp' Q` T+F;2 }H2- Q` 2p2M7QMibT2+ ?p2 #22M `2bi`B+i2/ iQ i?2 `2HiBp2Hv biM@ GB;im`2b4.Bb+`2iBQM`v- Dmbi Tbi2/ BMiQ  /Q+mK2Mi T`2K#H2X "mi i?Bb T@ 7Q`2 //BM; i?2 M2r YQMmK PT2MhvT2 i;X9 PT2M@ hvTB+H 2tKTH2 /`/ b2i Q7, ) hvT2 72im`2b `2 MQr T`QpB/2/ +QMbBbi2MiHvb  rBi? b?Q`i?M/XT`Q+? F22Tb b vQm` r2HH- T`2K#H2 A +QmH/ b iB/v r`Bi2, b TQbbB#H2 B7 P77 M/ _2b2i p`BMib U2X;X- LmK#2`b4PH/aivH2P77G2iǶb ;Q #+FvQm ?p2 iQ i?2  b2`B2b :BHH Q7 aMb 7QMi LQp 7KBHv 2tKTH2X /2}MBiBQMb Ai vQm rBHHlT`B;?i f AiHB+ f "QH/ f "QH/AiHB+ f aHMi2/ aBM+2 i?2 2`Hv /vb Bi ?b #22MM/ LmK#2`b4PH/aivH2_2b2i TQbbB#H2 iQ +?M;2V r?B+? BMi2`+i$M2r7QMi7KBHv$#QQF7QMi&;BHH@bMb@MQp@#QQF'+QMiBMb T`QT@ 7QMibUT`Q##HvV BM i?2 `2mb2 7QHHQrBM; #2ir22M r2B;?ib, /Q+mK2MibX f "QH/aHMi2/ i?2 +m``2MiHv@b2H2+i2/ 7QMi 72im`2b2`Hv rBi? mbBM; i?2 72im`2 i?2 HQ/BM;$//7QMi72im`2 HQ;B+ iQ 2Bi?2`rBi?lHi` 7Q`+B#Hv bBKBH` GB;?i8 f //BiBQMHGB;?i Ki+?BM; f "QQFL6aa f J2/BmKX7QMibT2+/2+H`iBQMb f a2KB#QH/}H2- f M/UM/ i?2M rBi?BM mb2 i?2b2 7QMib #Qi? MQ`KH M/ bKHH +Tb /2+iBpi2  72im`2 Q` iQ `2b2i i?i T`iB+mH` 7QMibT2+"QH/ f >2pv f 1ti` "QH/ f lHi` "QH/ b?T2b `2 HHQr2/XV +QKKM/X  `2HiBp2Hv `2+2Mi72im`2 BKT`Qp2K2Mi iQ Bib /27mHi bii2X iQ 7QMibT2+ $#QQF7QMih?2BM biM/`/ i?2 ǵ7QMibǶ b2imT i?i Q7 +QmH/ i?2 #2 ivTQ;`T?v HQ/2/ rBi?BM Q7 i?2 7QMibT2+ ?p2 #22M `2bi`B+i2/ iQ i?2 `2HiBp2Hv biM@ /`KiB+HHv BKT`Qp2/ i?2 `2HB#BHBiv9 hvTB+H 2tKTH2 M/ BMi2`MH /Q+mK2MiXT`2HBKBM`v/`/ /`7i- b2i m;mbiQ7, R3- kyR3 ky,j9 T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,j9 HQ;B+ iQ bm+? +QKKM/bX LQr-G2iǶb r`BiBM; ;Q #+F iQ i?2 :BHH aMb LQp 2tKTH2XLQr- Ai lT`B;?i i?2 +QKKM/f AiHB+ f "QH/ bi`iBM;f "QH/AiHB+$/27mHi7QMi72im`2b(;BHH@bMb@MQp)f aHMi2/ +QMiBMb 7QMib BM i?2 7QHHQrBM; r2B;?ib, f "QH/aHMi2/ $//7QMi72im`2b&LmK#2`b4PH/aivH2' /Q2bMǶi M22/ iQ #2 BM  7KBHv MK2 X7QMibT2+ lHi` GB;?i f GB;?i f "QQF f J2/BmK f a2KB#QH/ f UM/ rBi?BM i?2b2 7QMib #Qi? MQ`KH M/ bKHH +Tb rBHH 2tTHB+Biv /2+iBpi2 LmK#2`b4GBMBM;"QH/ f >2pv f 1ti`}`bi "QH/ #2@ f lHi` "QH/}H2c Bi +QmH/b?T2b #2 `2 HHQr2/XV BM  +Hbb Q` T+F;2 }H2- Q` 2p2M 7Q`2 //BM; i?2 M2r YQMmK PT2MhvT2T`2HBKBM`v /`7i- i;X m;mbi PT2M@ R3- kyR3 ky,j9Dmbi Tbi2/ BMiQ T`2HBKBM`v  /Q+mK2Mi /`7i- m;mbi T`2K#H2X R3- kyR3 ky,j9 "mi i?Bb T@ hvT2 72im`2b `2 MQr T`QpB/2/ +QMbBbi2MiHv rBi? T`Q+? F22Tb vQm` T`2K#H2 b iB/v b TQbbB#H2 B7 P77 M/ _2b2i p`BMib U2X;X- LmK#2`b4PH/aivH2P77 vQm ?p2  b2`B2b Q7 7QMi 7KBHv /2}MBiBQMb vQm rBHH M/ LmK#2`b4PH/aivH2_2b2i V r?B+? BMi2`+i T`QT@ UT`Q##HvV `2mb2 #2ir22M /Q+mK2MibX 2`Hv rBi? i?2 72im`2 HQ/BM; HQ;B+ iQ 2Bi?2` 7Q`+B#Hv 8 //BiBQMH L6aa /2+H`iBQMb /2+iBpi2  72im`2 Q` iQ `2b2i i?i T`iB+mH` 7QMibT2+ 72im`2 iQ Bib /27mHi bii2X h?2 biM/`/ ǵ7QMibǶ i?i +QmH/ #2 HQ/2/ rBi?BM 7QMibT2+ ?p2 #22M `2bi`B+i2/ iQ i?2 `2HiBp2Hv biM@ 9 hvTB+H 2tKTH2 /`/ b2i Q7, G2iǶb ;Q #+F iQ i?2 :BHH aMb LQp 2tKTH2X Ai lT`B;?i f AiHB+ f "QH/ f "QH/AiHB+ f aHMi2/ +QMiBMb 7QMib BM i?2 7QHHQrBM; r2B;?ib, f "QH/aHMi2/ lHi` GB;?i f GB;?i f "QQF f J2/BmK f a2KB#QH/ f UM/ rBi?BM i?2b2 7QMib #Qi? MQ`KH M/ bKHH +Tb "QH/ f >2pv f 1ti` "QH/ f lHi` "QH/ b?T2b `2 HHQr2/XV

T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,j9 T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,j9 TUGboat, Volume 39 (2018), No. 2 115

When using Gill Sans Nova myself, I usually 5 Additional NFSS declarations want the Medium and Bold weights paired, so I The standard ‘...Font’ variants that could be loaded created a file in my local texmf directory named within fontspec have thus far been restricted to the gill-sans-nova.fontspec, which looks like this: relatively standard set of: \defaultfontfeatures[gill-sans-nova]{ UprightFont / ItalicFont / BoldFont / UprightFont = GillSansNova-Medium.otf , ItalicFont = GillSansNova-MediumItalic.otf, BoldItalicFont / SlantedFont / BoldFont = GillSansNova-Bold.otf , BoldSlantedFont BoldItalicFont = GillSansNova-BoldItalic.otf , (And for each of these variants both normal and } small caps shapes are allowed.) This file allows me to write, without any additional However, LATEX’s font selection scheme allows options, \setmainfont{gill-sans-nova} or other complex mappings along what it terms the ‘shape’ fontspec font selection command. Additionally, I and the ‘series’ axes. These can be assigned using could write: fontspec’s FontFace option: \newfontfamily\bookfont{gill-sans-nova} \defaultfontfeature+[gill-sans-nova]{ and then use \bookfont in the setup of the typogra- FontFace = {uu}{n}{GillSansNova-UltraLight.otf}, phy of the document. FontFace = {ll}{n}{GillSansNova-Light.otf }, To use a different selection of fonts from the FontFace = {hh}{n}{GillSansNova-Heavy.otf }, FontFace = {xx}{n}{GillSansNova-ExtraBold.otf }, family, I can create another .fontspec file and load } that in the same way. The \defaultfontfeatures command isn’t re- Now, for fonts in which only a range of weights need quired to be in a .fontspec file; it could be in a class to be defined, as here, the fontspec interface to this or package file, or even just pasted into a document is a little awkward. I have been discussing the idea preamble. But this approach keeps your preamble of a more friendly syntax with a number of users as tidy as possible if you have a series of font family recently. On the other hand, for truly arbitrary font definitions you will (probably) reuse between docu- shapes that cannot be categorised in a standard way ments. (e.g., the ‘Deco’ Gill Sans font shown in Figure 2), the more flexible FontFace option provides the most 4.1 Feature possibility: font collections? generic interface. In the example above, \newfontfamily was briefly 6 ‘Inner’ emphasis and ‘Strong’ emphasis mentioned for creating a macro that switches the font to a pre-defined family. This is akin to extending By default, writing \emph{\emph{abc}} produces the selections provided in LATEX with its \rmfamily, an upright ‘abc’ as LATEX knows that italic text \sffamily, and \ttfamily definitions. needs to switch (back) to upright text for emphasis. In other contexts it may be desirable to define Some typesetters prefer instead to emphasise within a single command to replace all of the standard italic text with small caps, and LATEX 2ε provides the rm/sf/tt fonts. One interface we could imagine here \eminnershape interface for defining the behaviour might look like of nested emphasis beyond a single level. \setmainfont{pagella}% default ‘collection’ In fontspec, I became interested in the idea of \setmainfont{aldus}[Collection={examples}] supporting arbitrary levels of nesting. For emphasis to support a book with a series of ‘examples’, which this is presumably of limited utility, but later in this are typeset in a different style than the main text. section it will become more clear why this is useful. The document might look like: Therefore, fontspec now supports arbitrary nesting using (say) this is the \textsf{main} text % uses the default fonts \emfontdeclare{\itshape , \upshape\scshape, \selectfontcollection{examples} \itshape , this is some \textsf{example} text } % uses fonts from the "examples" collection which will ask emphasised text to switch to italic, Over the next few months (or years, if my plans then upright small caps, then italic small caps, as go awry), I’ll experiment with implementing some shown in Figure 3. Each command sequence sepa- interfaces along these lines for user testing. Please rated by commas is applied successively. keep an eye out; I would certainly welcome additional Just above, we saw that fontspec provides the feedback. FontFace option to load a range of font weights in

Font loading in LATEX using the fontspec package: Recent updates \9 116 T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,8N hl:#Qi- oQHmK2 y UNNNNV- LQX y TUGboat, Volume 39 (2018), No. 2

5P $2KT?{$DD $2KT?{(ƳƳ $2KT?{,ǙǙ}}} Of course, this needs some extra setup beforehand: \9 T`2HBKBM`v /`7i- m;mbi R3- kyR3 kR,yk hl:#Qi- oQHmK2 y UNNNNV- LQX\DeclareUnicodeEncoding{fakedotaccent}{ y Figure 3: An example of nested emphasis. \input{tuenc.def} h?2M Hi2` BM i?2 /Q+mK2Mi- MQ //BiBQMH rQ`F Bb M22/2/, \EncodingCommand{\d}[1]{% $EF $bi`QM; $EF $bi`QM; $EF $bi`QM; $EF XXX&$iBiH27QMiEGAh$/J'XXX { { { }}} \hmode@bgroup XXX&$bMbFBi7QMiEGAh$/J'XXX \o@lign{\relax#1\crcr\hidewidth Figure 4: An example of nested \strong emphases. L6aa1M+Q/BM;47F2/Qi++2Mi \ltx@sh@ft{-1ex}.\hidewidth}% h?2 }`bi mb2b) i?2 ǵ7F2Ƕ ++2Mic i?2 b2+QM/ i?2 `2H lMB+Q/2 ;HvT?XP7 +Qm`b2- i?Bb M22/b bQK2 2ti` b2imT #27Q`2?M/, \egroup h?2`2 Bb$.2+H`2lMB+Q/21M+Q/BM;&7F2/Qi++2Mi'&  ?m;2 +p2i iQ i?Bb- r?B+? Bb i?i } a single family. Inspired by HTML’s tag, Gh1s +MǶi BMi2`+2Ti$BMTmi&im2M+X/27' lMB+Q/2 ++2MibX aQ B7 vQm } $1M+Q/BM;*QKKM/&$/'(R)&WI have added \strong to fontspec as a sibling to ?p2 i2ti i?i Bb$?KQ/2!#;`QmT r`Bii2M HBi2`HHv b ǵEGAhƆǶ BM i?2 bQm`+2- Gh1s +MǶi$Q!HB;M&$`2HtOR$+`+`$?B/2rB/i?\emph +Q``2+i. i?Bb This 7Q` vQm-is the M/ command vQmǶHH which makes it sensible Then later in the document, no additional work is 2M/ mT rBi? r?i2p2`$Hit!b?!7i&@R2t'X$?B/2rB/i?'W i?2 7QMi ;Bp2b vQmX h?Bb HBKB@ $2;`QmTto support arbitrary nesting, given the large range needed: iiBQM +QmH/ #2' //`2bb2/ #v //BM;  T`2@T`Q+2bbBM;  of weights seen in modern font families. ...{\titlefont KALITA\d M}... bi;2 iQ i?2' Gh1s ivT2b2iiBM;- #mi i?2`2 Bb MQ #mBHi@ BM K2+?MBbKh?2M iQ Hi2` /Q i?BbX BM i?2 /Q+mK2Mi-To follow MQ //BiBQMH from therQ`F Bb previous Gill Sans Nova ex- ...{\sanskritfont KALITA\d M}... M22/2/, 3 *QM+HmbBQMXXX&$iBiH27QMiEGAh$/J'XXXample, to setup \strong with nesting I can write: The first uses the ‘fake’ accent; the second the real XXX&$bMbFBi7QMiEGAh$/J'XXX \strongfontdeclare{ Unicode glyph. iQ/Q h?2 }`bi mb2b i?2 ǵ7F2Ƕ ++2Mic i?2 b2+QM/ i?2 `2H lMB+Q/2 ;HvT?X\bfseries , There is a huge caveat to this, which is that h?2`2 Bb \fontseries{hh}\selectfont ?m;2 +p2i iQ i?Bb- r?B+? Bb i?i , LAT X can’t intercept Unicode accents. So if you Gh1s +MǶi BMi2`+2Ti lMB+Q/2 ++2MibX aQ B7 vQm E ?p2 i2ti i?i Bb\fontseries{xx}\selectfont r`Bii2M HBi2`HHv b ǵEGAhƆǶ BM i?2 , have text that is written literally as ‘KALITAM’ in the  . bQm`+2- Gh1}s +MǶi +Q``2+i i?Bb 7Q` vQm- M/ vQmǶHH A 2M/ mT rBi? r?i2p2` i?2 7QMi ;Bp2b vQmX h?Bb HBKB@ source, LTEX can’t correct this for you, and you’ll iiBQM +QmH/This #2 //`2bb2/ will #v produce //BM;  T`2@T`Q+2bbBM; the results shown in Figure 4. end up with whatever the font gives you. This limi- bi;2 iQ i?2 Gh1s ivT2b2iiBM;- #mi i?2`2 Bb MQ #mBHi@ BM K2+?MBbK iQ /QNote i?BbX there is no \weaken command to change tation could be addressed by adding a pre-processing 3 *QM+HmbBQMweights in the opposite direction! More seriously, I stage to the LATEX typesetting, but there is no built- iQ/Q can imagine generalising the interfaces here to a pair in mechanism to do this. of code-level interfaces such as \fontseriesup and \fontseriesdown to change weights along a scale. 8 Conclusion These interfaces will be subject to change as im- While the fontspec package has undergone extensive proved methods for loading additional bold weights development over the years, the core concepts are are developed. At the moment the \emfontdeclare the same: load fonts in a flexible way. But I think and \strongfontdeclare commands are global for it’s fair to say that as the package has grown and all fonts; there is no current way to have font-specific the interfaces have become more complex, the in- declarations there. terface is not as clear as it could be. Will I ever 7 Custom encodings re-write fontspec entirely? Probably not. But with LATEX3 interfaces to consider, it’s probable that a We all know that fonts aren’t perfect, and while many slimmed-down version of fontspec will need to make problems can be solved by choosing a better font, an appearance somewhere or another. this is not always possible. The fontspec package, in T`2HBKBM`v /`7i- m;mbi R3- kyR3 kR,yk T`2HBKBM`v /`7i- m;mbi R3- kyR3 kR,yk concert with recent LATEX 2ε changes around the TU font encoding, now allows per-font customisation for Will Robertson ⋄ symbols and accent support. As an example, say I’m School of Mechanical Engineering creating a poster with some Sanskrit text but I’m The University of Adelaide, SA using a Western font; I can choose to redefine the Australia underdot accent \d by loading two fonts like so: will.robertson (at) adelaide dot edu dot au wspr.io/fontspec T`2HBKBM`v /`7i- m;mbi\newfontfamily\sanskritfont{CharisSIL} R3- kyR3 ky,8N T`2HBKBM`v /`7i- m;mbi R3- kyR3 ky,8N \newfontfamily\titlefont{Posterama}[ NFSSEncoding=fakedotaccent ]

Will Robertson TUGboat, Volume 39 (2018), No. 2 117

Supporting color and graphics in expl3 Supporting this mixing, conversion between dif- ferent color models, and other features such as spot Joseph Wright colors, are all (largely) covered in the experimental 1 Introduction l3color package [3]. Using the LATEX3 FPU makes much of the core support very easy to implement: The expl3 language has grown over the past decade the various pieces of mathematics can be expressed to cover a wide range of programming tasks [4]. How- directly, rather than requiring complex dimension ever, at present there are a number of areas where shuffling. expl3 offers little or no ‘core’ support and which will At present, the nature of input in l3color is lim- need functionality at this level. Here, I’ll be focussing ited to the ‘simple’ color expressions defined by xcolor: on one in particular: color and graphics support. feedback on what is helpful to end users would be In the classical LAT X 2 setup, the picture E ε very welcome. environment along with the packages graphics [5] and color provide the basis for this area. To allow 4 Image inclusion driver-dependent operations, a set of definition files is loaded by graphics to map user operations to driver- At present, expl3 support for image inclusion is only specific instructions. Nowadays, these are managed ready at the driver level. Implementing a code-level by the LATEX team in the bundle graphics-def [2]. set of \image_... functions is on the ‘to do’ list, In addition to this core support, a number of and is likely straightforward. well-established contributed packages offer significant additional features. Particularly notable here are 5 Drawing xcolor [1], which allows user-friendly mixing of colors, Whilst the picture environment of the LATEX kernel and TikZ/pgf [6], an extremely rich and versatile does provide a way to create simple graphical ele- system for the programmatic creation of graphics. ments, today perhaps the most powerful tool for this Here, I will look at recent efforts to begin provid- task is TikZ/pgf. Reimplementing all of the latter ing a similar level of overall functionality via expl3. may seem excessive, but there are several reasons Central to these efforts is the availability of a fast, to explore this. First, a core aim of expl3/LATEX3 expandable and accurate software floating-point unit work is to eventually provide a full set of features for (FPU) within expl3. This provides a base on which supporting document preparation, certainly provid- many graphics-related functions can build: calcula- ing code-level tools for all common tasks. Coupled tions are a core part of many image-related functions. to this, an expl3 implementation will have API con- sistency with the rest of the code: mixing TikZ and 2 The driver layer expl3 can be tricky. We are also able to use existing Unlike the LATEX 2ε situation, where the graphics and expl3 tools in the implementation and usage. Finally, color driver code is managed (somewhat) separately there is the potential offered by the LATEX3 FPU: from the kernel, the expl3 versions are part of the core this avoids using dimensions for floating point work, distribution. Development of the driver code in expl3 and so also avoids the Dimension too big issue that has been informed by recent efforts to standardise comes up from time-to-time using TikZ. the LATEX 2ε versions, and vice versa. Much like expl3, pgf is divided into different As new features are added to expl3 which require layers: these line up as show in Table 1. There is driver support, the driver layer is being adjusted good alignment, and thus in many ways it is simply to match. This means that unlike in LATEX 2ε, for a case of re-creating the macros with new names. Of expl3 there should be a single set of definitive driver course, there is more to do than that: for example, files, supported by the team and usable by (and the use of the LATEX3 FPU means that co-ordinate documented for) others. expressions are processed expandably by l3draw, with a knock-on effect in usage. However, as far as possible 3 Colo(u)r the interfaces in l3draw retain the same arguments as those in pgf. The LATEX 2ε (required) package color provides a base interface for using pre-defined colors. However, one of the most common ways to use a color is to 6 Examples describe it as a mix of base colors: red, green and At the time of writing, l3draw is very much a work blue, or cyan, magenta, yellow and black. The xcolor in progress. However, the core idea of constructing package provides a convenient ‘expression’ interface paths is fully implemented. For example, a simple for creating mixtures: \color{red!50!blue}. geometric shape including smoothing joins:

Supporting color and graphics in expl3 118 TUGboat, Volume 39 (2018), No. 2

Table 1: Comparison of TikZ/pgf and l3draw concepts Layer TikZ/pgf l3draw System \pgfsys@moveto \driver_draw_moveto:nn Base \pgfpathmoveto \draw_path_moveto:n Interface \draw —

Thus, l3draw is ready for application in expl3 contexts which require drawing. Over time, we ex- pect to cover essentially the entire API provided by pgf’s core, plus probably node handling (loaded by pgf but not technically part of the core of the \draw_begin: bundle). \draw_path_corner_arc:nn { 4pt } { 4pt } \draw_path_moveto:n References { \draw_point_polar:nn { 0 } { 1cm } } [1] U. Kern. Extending LATEX’s color facilities: the \int_step_inline:nnnn { 72 } { 72 } { 359 } xcolor package, 2016. ctan.org/pkg/xcolor { A \draw_path_lineto:n [2] LTEX Project. Color and graphics option files, ctan.org/pkg/graphics-def { 2018. \draw_point_polar:nn { #1 } { 1cm } [3] LATEX Project. Experimental LATEX3 concepts, } 2018. ctan.org/pkg/l3experimental } [4] LATEX Project. The expl3 package and LATEX3 \draw_path_close: programming, 2018. ctan.org/pkg/expl3 \draw_path_use_clear:n { stroke } [5] LATEX Project. The graphics bundle, 2018. \draw_end: ctan.org/pkg/graphics The new code also integrates with existing ideas [6] T. Tantau and C. Feuers¨anger. TikZ and pgf, such as coffins. Here, we draw a line to the center of 2015. ctan.org/pkg/pgf typeset text: Joseph Wright ⋄ LATEX Project This is text. joseph dot wright (at) \draw_begin: morningstar2.co.uk \draw_path_moveto:n { 0cm , 0cm } \draw_path_lineto:n { 0cm , 1cm } \draw_path_use_clear:n { stroke } \hcoffin_set:Nn \l_tmpa_coffin { This~is~text. } \draw_coffin_use:Nnn \l_tmpa_coffin { hc } { vc } \draw_end: We can also exploit the expandable nature of the FPU: 22.72949518869545pt,-17.11517943480897pt \tl_set:Nx \l_tmpa_tl { \draw_point_intersect_circles:nnnnn { (0,0) } { 1cm } { (sqrt(2),sqrt(3)) } { 1cm } { 1 } } \tl_to_str:N \l_tmpa_tl

Joseph Wright TUGboat, Volume 39 (2018), No. 2 119

siunitx: Past, present and future hopefully it will appear within a day or two. Joseph Wright It has been suggested by the Abstract maintainer of the SIstyle package that integration of the two be would siunitx The package provides a powerful toolkit for worth considering. Other suggestions A typesetting numbers and units in LTEX. By incor- have also been made in the newsgroup porating detail about the agreed rules for presenting and by private mail. I am therefore siunitx scientific data, enables authors to concentrate planning to review the existing on the meaning of their input and leave the package situation and see what improvements to deal with the formatting. Here, I look at the are needed/desirable. As well as background to the package, what led me from ver- SIunits and SIstyle, I am going to sion 1 to version 2, and why version 3 is now under look at numprint, units, unitsdef and development. hepunits for inspiration/points to consider/etc. 1 Introduction So far, I have some outline ideas, Typesetting units naturally lends itself, in TEX, to for example: ... using macro support. The formal rules for SI units [1] I soon had quite a list, and work on the new link unit names with unit symbols, and it’s not sur- package began in earnest, and by February 2008 the prising that several authors have created packages first testing release was out. After a little more work, that tackle some or all of the subtleties involved. I’ve and a rename, the first official version of siunitx hit detailed some of these issues and packages before, CTAN on the 16th of April 2008 [7]. when I last looked at siunitx for TUGboat [6]. Here, I’ll briefly recap some of those key points, then ex- 3 Key features plore what is driving efforts toward a third version The core features of siunitx have been present from of the package. that first version, and are pretty well-known. I’d 2 Early days summarise them as • Automatic, semantic formatting of quantities Before siunitx, there were a variety of units-related (numbers with units) packages, including one called SIunits [3], which deals with providing semantic macros for units. My in- • Parsing and manipulation of numbers volvement started when I followed up an apparently- • Control of printing of numbers, units and innocuous post to comp.text.tex from Stefan Pin- quantities now in November 2007, reporting a straightforward • Alignment of numbers in tables bug • Unified key–value interface for controlling I want to report that \reciprocal, options \rpsquare, \rpcubic, etc. output is For me, the package has always been about units, written as "-1" instead of a $-1$, when and the fundamental idea that input such as the package option "textstyle" is used. \joule\per\mole\per\kelvin I tried to contact Mr. Heldoorn, but he can give J mol−1 K−1 or J or J/(mol K), depend- didn’t answer until now. Does anyone mol K ing on the settings in force. This idea has been there have an idea what to do? since day one, and the code has carried through Being young(ish) and foolish, after looking at more-or-less unchanged. the bug itself and finding that SIunits was no longer maintained, I volunteered to pick up the package. 4 From version one to version two Even more foolishly, I then followed up with the Version one of siunitx worked well for delivering on following in November 2007: those key features. Releases progressed rapidly, cul- As some of you may have noticed, minating in version 1.4c in February 2010. However, following a recent bug report adding new features was a problem: internally it was concerning the SIunits package, a bit of a mess. For example, if you look at the old I have taken over as the package code you’ll see: maintainer. I have uploaded a bug fix • Internals other than unit parsing taken from for the specific issue to CTAN, and so existing packages and somewhat haphazard

siunitx: Past, present and future 120 TUGboat, Volume 39 (2018), No. 2

• Sub-optimal key–value choices 4. Perhaps apply \text again (for text mode • Essentially no internal API output) • Poor self-coded loops 5. Force the font with e.g. \mathrm or \rmfamily • ... That requires a lot of work, and more import- antly is unreliable: it’s not always easy to get the Around this time, Will Robertson contacted right font ‘inside’ the output section. It also fails me to ask what I thought of the LAT X3 language E very badly with OpenType math mode fonts, where expl3 [4]. This was before I joined the LAT X team, E the ideas in classical T X about math families simply and expl3 looked a bit different than today, but the E don’t apply. So there is a new approach: for version central ideas were all there. I liked the ideas, but at three the time was a bit wary of loading an external library (and thus a dependency). So I started by picking 1. Detect current font type using LATEX internal out the ideas and re-coding them in my development data setup for version two. It soon became clear that I 2. Set any aspects that are needed needed a lot of the ideas, and I realised that I’d be 3. Only use an \mbox if math version has to be much better off just requiring expl3. altered Work on the second version of siunitx took me This ‘minimal change’ approach is much faster into expl3 programming, and asking the team for lots than the current one, and is much better at respecting of features. In particular, I wanted to have key–value font changes. I’m still finalising compatibility for support built-in, rather than needing to use another current edge-case setups, but I believe the new code package to do that. So I wrote some code, which is much preferable overall. I called keys3, to solve the problem. It turned out that was my application to join the team: it’s today 5.2 The code API and testing l3keys in expl3 itself! The development of siunitx version two very much The rewrite gave me a chance to significantly parallels that of expl3 as a truly usable language: in revise internal API aspects, and to significantly im- the time I’ve been using it, expl3 has gone from a set prove performance. It also came of course with new of clever experiments to a well-established approach features for users, and completely new names for to coding in TEX. But keeping all of siunitx up-to- the key–value interface. In the v2.0 release, I didn’t date with ideas has been tricky. include backward-compatibility: I soon learned, and The biggest issue is that when I wrote the cur- that’s been there since a few days after the second rent release code, there were just user commands generation release. such as \num and internal implementation. However, it’s now clear that each user command should have 5 From version two to version three a documented code-level interface. Moreover, these Version two retains most of the features that version interfaces should all be properly tested: the team one had, but as well as the good ones, it turns out it have created l3build precisely for that [5]. Combining keeps some of the bad ones too! In particular these ideas, the new code will take the input • Assumptions about fonts: OpenType, etc. \siunitx_unit_format:nN • No code-level API expl3 { \joule \per \mole } • Internals still too messy \l_tmpa_tl \tl_show:N \l_tmpa_tl • Testing the PDF documentation only and create as output • Monolithic source > \l_tmpa_tl= • Still too slow \mathrm {J}\,\mathrm {mol}^{-1} 5.1 Font control Notice that this is easy to test, and highlights another The font assumptions carry all the way through from new idea: the parsing step should produce the same SIstyle [2], and which I adjusted only slightly. The results as a user typing in the formatting ‘by hand’. approach currently used is 5.3 First alpha release 1. Detect current font type using LAT X internal E At the time of writing, the development of version data three has reached the first alpha stage: the code is 2. Insert everything inside \text usable but there are real gaps. Currently, all of the 3. Apply \ensuremath inside the box following are working:

Joseph Wright TUGboat, Volume 39 (2018), No. 2 121

• Core functionality: Appendix: demos – Unit parsing and formatting Simple number formatting: – Real number formatting 123 \num{123} \\ – Tabular columns 1234 \num{1234} \\ \num{12345} \\ • Existing API: \num, \SI, \si, S-column 12 345 0.123 \num{0.123} \\ • New (experimental) document API: \unit, \qty 0.1234 \num{0,1234} \\ There are some big areas left to do, such as 0.123 45 \num{.12345} \\ multi-part numbers, ranges, lists and most import- 3.45 × 10−4 \num{3.45d-4} \\ antly the compatibility layer for dealing with existing −1010 \num{-e10} documents. However, that is all relatively manage- able, and I expect to be done around the end of the Angles: year. So 2019 should see siunitx reach version 3.0.0, 10◦ \ang{10} \\ and I hope retain its place as the units package for 12.3◦ \ang{12.3} \\ ◦ LATEX. 4.5 \ang{4,5} \\ 1◦2′3′′ \ang{1;2;3} \\ References ′′ 1 \ang{;;1} \\ [1] Bureau International des Poids et Mesures. 10◦ \ang{+10;;} \\ The international system of units (SI), 2010. −0◦1′ \ang{-0;1;} bipm.org/en/measurement-units/ Units as macros: [2] D. Els. The SIstyle package, 2008. − kg m s 2 ctan.org/pkg/sistyle − g cm 3 [3] M. Heldoorn and J. Wright. The SIunits V2 lm3 F−1 package: Consistent application of SI units, m2 Gy−1 lx3 2007. ctan.org/pkg/siunits H s [4] LATEX Project. The expl3 package and LATEX3 \si{\kilo\gram\metre\per\square\second} \\ programming, 2018. ctan.org/pkg/expl3 \si{\gram\per\cubic\centi\metre} \\ \si{\square\volt\cubic\lumen\per\farad} \\ [5] LATEX Project. l3build: Checking and building packages, 2018. ctan.org/pkg/l3build \si{\metre\squared\per\gray\cubic\lux} \\ \si{\henry\second} [6] J. Wright. siunitx: A comprehensive (SI) units package. TUGboat 32(1):95–98, 2011. tug.org/ Quantities: TUGboat/tb32-1/tb100wright-siunitx.pdf 1.23 J mol−1 K−1 [7] J. Wright. siunitx —a comprehensive (SI) units 0.23 × 107 cd package, 2018. ctan.org/pkg/siunitx 1.99/kg C 1.345 mol Joseph Wright ⋄ \SI[mode = text]{1.23}{J.mol^{-1}.K^{-1}} \\ Morning Star \SI{.23e7}{\candela} \\ 2, Dowthorpe End \SI[per-mode = symbol] Earls Barton {1.99}{\per\kilogram} \\ Northampton NN6 0NH United Kingdom \SI[per-mode = fraction] joseph dot wright (at) {1,345}{\coulomb\per\mole} morningstar2.co.uk

siunitx: Past, present and future 122 TUGboat, Volume 39 (2018), No. 2

Arara — TEX automation made easy dated April 2012. Nothing much was there, besides the core concepts that still exist today: Paulo Roberto Massa Cereda • Rules: a rule is a formal description of how arara Abstract handles a certain task. It tells the tool how to This article covers a bit of history behind arara, the do something. cool TEX automation tool, from the earlier stages of • Directives: A directive is a special comment development to the new 4.0 series. We also highlight inserted in the source file in which you indicate some noteworthy features of our tool. how arara should behave. Back then, we could write directives in our doc- 1 Introduction ument and have the tool process them as expected, Writing software is easy. Writing good software is like the following example: extremely difficult. I was working on a Catholic % arara: pdftex songbook with 1200+ songs and several indices and Hello world! cross-references. The compilation steps required to \bye achieve the final result were getting out of hand. Amusingly, the first version offered only a log knew At some point, I realized I all the steps I output as an additional feature. There was no ver- had to reproduce beforehand, I only had to find a way bose mode. The log file was a gathering of streams to automate them! Inspired by the way compilers (error and output) from the sequence of commands work (i.e., read a source file, ignore all comments specified through directives. And that was it. and process the rest), I could exploit TEX comments to include special indications on what to do on the 2.2 The second version document. Since engines do ignore comments, no The first version had a serious drawback: compilation side effects would arise, at least document-wise. feedback was not in real time and, consequently, no It was a cold afternoon. I sat in front of my user input was allowed. For the second version, real computer and decided to work on this new tool. time feedback was introduced when the tool was It was a matter of time to reach preliminary yet executed in verbose mode. promising results. I mentioned this effort in the chat $ arara -v mydoc.tex room of the T X community at StackExchange and E ... [real time feedback] ... some friends asked me to make a public release out of it, as other users could benefit from this new tool. Two other features were included in this version: However, a name was needed for the tool. In a flag to set an overall execution timeout, in millisec- the chat room, we used to have a lot of fun with onds, as a means to prevent a potentially infinite palindromes (especially palindromic reputations in execution, and a special variable in the rule context arbitrary bases), so I took that aspect as inspiration. for handling cross-platform operations. Then I thought of a very beautiful, colourful bird of 2.3 The third version the Brazilian fauna: the macaw, or as we like to call it, the arara. The name was immediately adopted! So far, arara was only a tiny project with a very Once the name was chosen, I needed a logo. restricted user base. However, for version 3.0, a Since I am a Fedora Linux user, I was always a fan qualitative goal was reached: the tool became inter- of their default typeface, which is quite round! The national, with localised messages in English, Brazil- choice was made: the humble arara tool became ian Portuguese, German, Italian, Spanish, French, arara! (But we’ll use the more subdued arara in Turkish and Russian. Further, new features such as regular text.) My life was about to change. configuration file support and rule methods brought arara to new heights. As a direct consequence, the 2 A bit of history lines of code virtually doubled from previous releases. A lot of things have happened since version 1.0, re- $ arara --help -L es leased in 2012, to the new version 4.0, released in ... 2018. This section presents a bit of history of arara, -h,--help imprime el mensaje de ayuda including challenges in each version. -l,--log genera el registro de la salida ... 2.1 The first version When the counter stopped at version 3.0, Brent There is a famous quote along the lines of “If at Longborough, Marco Daniel and I decided it was first you do not succeed, call it version 1.0.” The time for arara to graduate and finally be released in first version of arara was also the first public release, TEX Live. Then things really changed in my life. The

Paulo Roberto Massa Cereda TUGboat, Volume 39 (2018), No. 2 123

tool was a success! Given the worldwide coverage of time and effort to document a great yet complex tool that TEX distribution, arara silently became part of in all details, from user to developer perspectives. the daily typographic tool belt of many users. But It took me a lot of dedication to write the user then, the inevitable happened: a lot of bugs emerged manual and try to cover as much detail as possible from the dark depths of my humble code. for every feature, old and new, and the tool itself. Some of the internals had to be changed, so more 2.4 Critical and blocker bugs explanations were needed. Documenting a tool is Suddenly, several questions about arara were posted almost as difficult as writing code for it! in the TEX community at StackExchange and I was not able to provide a consistent, definitive answer 3 New features for many of them! It was very tricky to track the This section highlights some noteworthy features bugs to their sources, and some of them were really found in the new version 4.0 of arara. For additional nasty. For instance, a simple scenario of a file with information, please refer to our user manual. spaces in the name was more than enough to make the poor tool cry for help for apparently no reason: 3.1 REPL work flow $ arara "My PhD thesis.tex" In version 4.0, arara employs a REPL (read-evaluate- Likewise, the issues page of the project repos- print loop) work flow for rules and directives. In itory hosted at GitHub had a plethora of reports, previous versions, directives were extracted, their and little could I do about them. I delved into the corresponding rules were analyzed, commands were code of third party libraries, but the root of all evil built and added to a queue before any proper exe- seemed to lie in my own sources. cution or evaluation. I decided to change this work flow, so now arara evaluates each rule on demand, 2.5 Nightingale i.e., there is no a priori checking. A rule will al- In all seriousness, I was about to give up. My code ways reflect the current state, including potential was not awful, but there were a couple of critical side effects from previously executed rules. and blocking bugs. Something very drastic had to be done in order to put arara back on track. Then, 3.2 Multiline directives proceeding on faith, I decided to rewrite the tool Sometimes, directives can span several source lines, entirely from scratch. In order to achieve this goal, particularly those with several parameters. From I created a sandbox and started working on the arara 4.0 on, we can split a directive into multiple new code. And this new project got a proper name: lines by using the arara: --> mark on each line nightingale. which should comprise the directive. We call it a It was the right thing to do. Nicola Talbot multiline directive. Let us see an example: helped me with the new version, writing code, fixing bugs and suggesting new features. She was writing % arara: pdflatex: { % arara: --> shell: yes, a book about LAT X for administrative work at the E % arara: --> synctex: yes arara time and was extensively using in the code % arara: --> } examples. Her writing indirectly became my writing as well, as I progressively improved the code and It is important to observe that there is no need added new features to match her suggestions. for them to be on contiguous lines in the source file, i.e., provided that the syntax for parameterized 2.6 The fourth version directives holds for the line composition, lines can At some point, nightingale had to say farewell and be distributed all over the code. The log file (when gave most of its features to the bigger, older bird enabled) will contain a list of all line numbers that in the nest. It is worth mentioning that nightingale made up a directive. still lives in my repository at GitHub for those who are bold enough to try it. From 1500+ lines of 3.3 Directive conditionals code in version 3.0, arara 4.0 tripled that number: a arara 4.0 provides logical expressions, written in the whopping 4500+ lines of code! And, most important: MVEL language, and special operators processed at all critical and blocking bugs were completely fixed. runtime in order to determine whether and how a However, although the code was ready for pro- directive should be processed. This feature is named duction, the user manual was far from being finished. directive conditional, or simply conditional for short. In fact, the documentation had to be written entirely The following list describes all conditional operators from scratch. Then another saga started: find proper available in the directive context.

Arara — TEX automation made easy 124 TUGboat, Volume 39 (2018), No. 2

• if: The associated MVEL expression is evalu- 3.5 Dry-run execution ated beforehand, and the directive is interpreted The --dry-run command line option makes arara if, and only if, the result of such evaluation is go through all the motions of running tasks and true. This directive, when the conditional holds subtasks, but with no actual calls. This is useful for true, is executed at most once. testing the sequence of underlying system commands % arara: pdflatex if missing(’pdf’) to be performed on a file. % arara: --> || changed(’tex’) [DR] (PDFLaTeX) PDFLaTeX engine • unless: Same as if but the condition test is ------inverted. Authors: Marco Daniel, Paulo Cereda About to run: [ pdflatex, hello.tex ] % arara: pdflatex unless unchanged(’tex’) Note that by the rule, authors are displayed (so % arara: --> && exists(’pdf’) they can be blamed in case anything goes wrong), • until: The directive is interpreted the first time, as well as the system command to be executed. It is then the associated MVEL expression evaluation an interesting approach to see everything that will is done. As long as the result holds false, the happen to your document and in which order. It is directive is reinterpreted. There is no guarantee important to observe, though, that conditionals are of halting. not evaluated in this mode. % arara: pdflatex until !found(’log’, 3.6 Local configuration files % arara: --> ’undefined references’) From version 4.0 on, arara provides support for local • while: Same as until but the condition test is configuration files. In this approach, a configuration inverted. file can be located in the working directory associated % arara: pdflatex while missing(’pdf’) with the current execution. This directory can also % arara: --> || found(’log’, ’undefined be interpreted as the one relative to the processed % arara: --> references’) file. This approach offers a project-based solution Although there is no conceptual guarantee for for complex work flows, e.g., a thesis or a book. proper halting of unbounded loops, we have provided However, arara must be executed within the working a practical solution to potentially infinite iterations: directory, or the local configuration file lookup will arara has a predefined maximum number of loops. fail. Observe that this approach has the highest The default value is 10, but it can be overridden lookup priority, which means that it will always either in the configuration file or on the command supersede a global configuration. line. 3.7 File hashing 3.4 Directive extraction only in the header arara 4.0 features four methods for file hashing in the rule and directive scopes, presented as follows. The The --header command line option changes the file base name refers to the file name without the mechanics of how arara extracts the directives from associated extension. the code. The tool always reads the entire file and extracts every single directive found throughout the • changed(extension): checks if the file base code. However, by activating this switch, arara will name concatenated with the provided extension extract all directives from the beginning of the file has changed its checksum from last verification. until it reaches a line that is not empty and is not • changed(file): the very same idea as the previ- a comment (hence the option name). Consider the ous method, but with a proper Java File object following example: instead. % arara: pdftex • unchanged(extension): checks if the file base Hello world. name concatenated with the provided extension \bye is unchanged from last verification. It is the % arara: pdftex opposite of the changed(...) method. When running arara without the --header op- • unchanged(file): the very same idea as the tion, two directives will be extracted (on lines 1 previous method, but with a proper Java File and 4). However, if executed with this switch, the object instead. tool will only extract one directive (from line 1), as it The value is stored in a database file named will stop the extraction process as soon as it reaches arara. as a pair containing the full path of the line 2. provided file and its corresponding CRC-32 hash (the

Paulo Roberto Massa Cereda TUGboat, Volume 39 (2018), No. 2 125

database is created as needed). If the entry already (PDFLaTeX) PDFLaTeX engine ...... SUCCESS exists, the value is updated, or created otherwise. (PDFLaTeX) PDFLaTeX engine ...... SUCCESS If a task fails, arara will halt the entire execution 3.8 Dialog boxes at once and immediately report back to the user. A dialog box is a graphical control element, typically This is an example of what a failed task looks like: a small window, that communicates information to (PDFLaTeX) PDFLaTeX engine ...... FAILURE the user and prompts them for a response. arara 4.0 Also, observe that our tool displays the execu- provides UI methods related to such interactions. tion time before terminating, in seconds. The execu- As good practice, make sure to provide descriptive tion time has a very simple precision, as it is meant messages to be placed in dialog boxes in order to ease and enhance the user experience. to be easily readable, and should not be considered for command profiling. 3.9 Session Total: 1.45 seconds Rules are designed under the encapsulation notion, The tool has two execution modes: silent, which such that direct access to the internal workings of is the default, and verbose, which prints as much such structures is restricted. However, as a means information about tasks as possible: of supporting framework awareness, arara provides • When in silent mode, arara will simply display a mechanism for data sharing across rule contexts, the task and subtask names, as well as the ex- implemented as a Session object. In practical terms, ecution result. Nothing more is added to the this particular object is a global, persistent map output. composed of keys and values available throughout • When executed in verbose mode, arara will dis- the entire execution. play the underlying system command output 3.10 Redesigned user interface as well, when applied. In version 4.0 of our tool, this mode was also entirely redesigned in For arara 4.0, we redesigned the interface in order order to avoid unnecessary clutter, so it would to look more pleasant to the eye; after all, we work be easier to spot each task. with TEX and friends. Please note that the output here is truncated to respect the column width. It is important to observe that, in verbose mode, arara can offer proper interaction if the system com- ______mand requires user intervention. However, in silent / _‘ | ’__/ _‘ | ’__/ _‘ | | (_| | | | (_| | | | (_| | mode the tool will simply discard this requirement \__,_|_| \__,_|_| \__,_| and the command will almost surely fail. 4 The future Processing ’doc.tex’ (size: 307 bytes, last modified: 05/29/2018 08:57:30), please wait. Now that arara 4.0 is officially released and already available in CTAN and TEX Live, it is time to plan (PDFLaTeX) PDFLaTeX engine ...... SUCCESS the future. Our repository already has suggestions (PDFLaTeX) PDFLaTeX engine ...... SUCCESS for new features and improvements. The work on arara 5.0 has begun! If you have any feedback about Total: 1.45 seconds our tool, please drop us a note. First of all, we have the nice application logo, Also, if you believe your custom rule is com- displayed using ASCII art. The entire layout is based prehensive enough and deserves to be in the official on monospaced font spacing, usually used in terminal pack, please contact us. We will be more than happy prompts. Hopefully you follow the conventional use to discuss the inclusion of your rule in forthcoming of a monospaced font in your terminal, otherwise updates. Happy TEXing with arara! the visual effect will not be so pleasant. First and foremost, arara displays details about the file being Paulo Roberto Massa Cereda ⋄ processed, including size and modification status: Analˆandia, S˜ao Paulo, Brazil Processing ’doc.tex’ (size: 307 bytes, last cereda dot paulo (at) gmail dot com modified: 05/29/2018 08:57:30), please wait. github.com/cereda/arara The list of tasks was also redesigned to be fully justified, and each entry displays both task and sub- task names (the former being displayed enclosed in parentheses), besides the usual execution result:

Arara — TEX automation made easy 126 TUGboat, Volume 39 (2018), No. 2

The Canvas learning management system this comprehensive document fell out of sync with and LATEXML the live content and had to be dropped. However, the single reference document had specific utility in being Will Robertson able to be easily distributed, and being searchable; 1 Introduction its loss was not disastrous but not ideal. The new LMS provided the opportunity to re- In 2017 The University of Adelaide adopted Canvas think the means by which the information needed (Instructure, Utah, USA) for its learning management in this course was documented and communicated system (LMS). Unlike our previous LMS, Canvas to students and supervisors. This project was moti- provides a programming interface to get data from vated by two main requirements: (1) improving the and send data to its servers. In this paper I will care and maintenance of the (somewhat extensive, discuss the system I have started developing to pre- and growing, amount of) content, and (2) to allow pare coursework material using LAT X, processed via E the generation of a comprehensive PDF reference LAT XML, and uploaded into Canvas in both HTML E document for the entire course. and PDF formats. When I started this work, I didn’t know exactly what I wanted except that I knew I needed at least 1.1 What is a learning management a good combination of the following: system? One source, multiple outputs. My need for a An LMS is an online system that organises students better system arose from wanting to be able to keep into classes and allows them to access course notes, online content up-to-date, while also having this assignments, lecture recordings, discussion boards, content collected in a single offline location. And it and so on. They usually also include collaborative soon became clear in my thinking that it would also features to help teamwork activities. The LMS is need to be compilable into a single PDF document also how the lecturer or coordinator for the course for distribution via alternate means. communicates with the students, posts grades, and otherwise does their job of running the course. Macros. I knew there would be a fair amount of Each course tends to have a fairly typical struc- information that I would want to re-use and keep ture, with links to the syllabus, assignment submis- consistent through the document (e.g., the names of sions, grades, etc. Actual course content in Canvas academic and professional staff members; due dates is organised into modules with individual pages writ- for assessment). This precluded writing in HTML or ten in HTML via a rich text editor. The amount of a ‘plain text’ format like Markdown. technical content in each course will depend on the Reliable and easy to set up. As much as I might coordinator; most academics I know still rely largely like to program my own document preparation sys- on printed lecture notes. tem, using this was to be part of my day job and I don’t want to have to dive into the weeds if code rot 1.2 Requirements for the project occurs and the system breaks down. As the coordinator for the mechanical engineering LATEX syntax. I admit, I stick with what I know. honours project course, I maintain a large collection Although I could have jumped into any number of of course content that is provided as reference mate- competing technologies here, I knew I would be most rial. After many years as a LATEX user, I am most comfortable if I was writing in the system with which comfortable with the idea of a source document that I was most accustomed. More objectively, LATEX is a is portable, version controllable, and easy to edit. mature format with a variety of possibilities among For me, using any web interface to fix typos or make third party support tools for creating HTML. small changes requires a non-negligible mental effort due to having to log in, navigate to an appropriate 2 The authoring interface page, and click through to an editing mode. This After some quick trials to establish that I could project was motivated by my desire for a more ef- programmatically send HTML content to Canvas, it ficient and effective means to keep course material was time to decide how to generate the HTML in the up-to-date. first place. In the past, our honours project course docu- mentation was a single monolithic Word document, 2.1 Which HTML converter to choose? which was difficult to maintain and awkward to ex- As discussed above, I didn’t want to do anything tract information from. With a slow move to online home-grown (and hence fragile), nor inflexible such as documentation and incremental changes over time, Markdown or raw HTML. I was aware of a number of

Will Robertson TUGboat, Volume 39 (2018), No. 2 127

‘competing’ technologies to write in LATEX or LATEX- is created, which is the starting point for getting my like syntaxes which could be converted to XML and content into Canvas. hence to HTML. The most actively developed of these Using a degree of consistency in the naming and tools, and their implementation language, appear to structure of my document, each of my source LATEX be: files with an \input for each chapter is therefore • lwarp [1] — Lua converted into a similarly-named HTML file. The • LATEXML [2, 3] — structure of the source document is as follows: • HeVeA [8] — OCaml \documentclass{report} • Tralics [4] — C++ ... • TEX4ht [5] — C and TEX \begin{document} • GELLMU [6, 7] — Emacs Lisp \title{...}\author{...}\date{...} \maketitle\tableofcontents (Not an exhaustive list; apologies for any oversights.) \input{../texdata/course-data.tex} To be honest I didn’t thoroughly evaluate each on \part{Introduction}\label{part-intro} their pragmatic merits; I was passingly familiar with \input{../pages/introduction} LATEXML’s philosophy, had heard it was robust, and \input{../pages/course-schedule} wanted to see if it fit the bill. It did, largely speaking. \input{../pages/week-planner} Of the tools listed above, only TEX4ht and lwarp ... are included in TEX Live. While LATEXML required The file course-data.tex is the source for various ‘manual’ installation, I had no troubles doing so. data (such as names of staff members, weightings A A of assessment, due dates, etc.) in basic LTEX data 2.2 LTEXML overview structures. The LATEXML program would be better explained by Each .tex file contains one chapter, with a con- someone who knows a lot more than I do about Perl, vention that the \label of each chapter matches its XML, and friends. My user-level understanding is file name: that LATEXML reimplements an extensive subset of % file: pages/introduction.tex TEX in Perl, so that input documents are literally \chapter{Introduction} processed as LATEX syntax, but not by the LATEX \label{introduction} program. The LATEXML parser then intercepts pack- ... age loading and inserts its own understanding of the This is because LATEXML does not convert file by various syntaxes introduced by different packages. If file; rather, with the --splitat=chapter option, the needed, it is possible to write custom support for output HTML is split by chapter. packages that it doesn’t cover out of the box. LATEXML does an excellent job emulating TEX, 3 The Canvas programming interface and it covers an impressive array of both TEX and Canvas has a so-called ‘REST API’2 that was easy 1 LATEX programming constructs. Therefore, includ- enough for me to get started with, with a little trial ing in my preamble a construct like and error. Initially, I used curl commands wrapped \newcommand\honourscoord{Will Robertson} into Bash scripts like this: simply worked out of the box with LATEXML; indeed, curl -X GET -H "$CANVASAUTH" $CANVASCOURSE/$1 simple LATEX 2ε programming using counters and so where $CANVASAUTH is set up in my .bash_profile on worked without a hitch. as a secret ‘token’ to avoid needing a manually-input To run LATEXML on my document involves the password, and $CANVASCOURSE is defined essentially somewhat complex command: as the institution-specific URL to the Canvas course. tex/$FILENAME.tex | latexmlpost - \ Finally, $1 is the parameter to send through to the --xsltparameter=SIMPLIFY_HTML:true \ Canvas API, such as assignments or rubrics or --sourcedirectory=tex \ users, etc. The parameters passed in the curl ar- --format=html5 \ gument $1 can include additional options, such as --destination=html/$FILENAME.html \ --splitat=chapter \ assignments?search_term=charter --splitnaming=label would return just the one assignment for my honours This setup ensures that for each ‘chapter’ of my project students called their ‘Project Charter’. LATEX document a separate self-contained HTML file The Canvas API can also be used to send or upload data to a course using PUT and POST. This 1 Even David Carlisle’s xii.tex can be successfully run through LATEXML. 2 https://canvas.instructure.com/doc/api/

The Canvas learning management system and LATEXML 128 TUGboat, Volume 39 (2018), No. 2

can range from relatively small and simple pieces of HTML is that this isn’t really a problem, since any information, to entire ‘content pages’ in HTML, to additional markup in the HTML is silently ignored. linked files that students can access and download LATEXML runs a two-stage process, where the (see Section A). latexml program itself generates generic XML from The results from any communication are sent the LATEX input, and then latexmlpost converts this back from the Canvas API in JSON format, for which generic XML into one of several output formats. In there are a number of useful standard tools. For theory I could write my own XSL stylesheet to format Bash scripts I use jq, a nice tool which is designed the information in the generic XML document in a in the philosophy of Unix tools such as awk and sed. customised way. Instead, I simply postprocess the After getting comfortable with this Bash script HTML output from latexmlpost; because LATEXML approach of sending and receiving data using curl creates highly structured and machine friendly HTML, and friends, I more recently started programming the output from latexmlpost makes this an easy pro- small Lua interfaces for more advanced operations. cess with some ad hoc tools (with plans for more The main impetus for this switch was that the Can- robust Lua processing in the future). vas API will not send arbitrarily large amounts of According to the options passed to latexmlpost, information in one request. For example, if I request each chapter is converted into its own HTML file; this a list of students, it will send me just ten and expect means I have a one-for-one correspondence between me to ask again with page=2 as an option. Then re- files \included as chapters in the main document. peat until no data is returned. This level of iteration Each of these chapters has a standard structure, with was beyond what I wanted to invest in a Bash script. ‘top matter’ that is not needed:3 To write the Lua scripts I needed a number of third-party utilities. For Lua there are in fact very many tools to convert JSON data into Lua’s ‘table’ data structure. I have been using the library Title of chapter h i json-lua (installed via luarocks) and it has been fine. After installing an SSL library (namely luasec, since convert the curl command above into an equivalent statement in Lua: [...] local http = require("ssl.https") local ltn12 = require("ltn12") local body, code, hdrs, status = http.request{ The chapters end with ‘bottom matter’ which is also method = "GET", not needed in my application: url = canvas_url .. req .. "?" .. opt,

headers = { [...] ["authorization"] = "Bearer "..canvas_token,
["content-type"] = "application/json"