L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Towards L
A
T
E
X Coding Standards
Didier Verna
didier@lrde.epita.fr
http://www.lrde.epita.fr/˜didier
TUG 2011 – Thursday, October 20
1/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Table of contents
1 Introduction
2 Level 1: layout
3 Level 2: design
4 Level 3: behavior
5 Level 4: social
6 Conclusion
7 Perspectives
2/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
History
1918 The Elements of Style, William Strunk, Jr. and E.B.
White (4th edition 1999). Style guide for writing
American English.
1974 The Elements of Programming Style, B.W. Kernighan
and P.J. Plauger, McGraw Hill (2nd Edition 1978). Style
guide for programming.
. . . The Elements of whatnot Style.
4/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Purpose
help programmers to read and understand source code
not only their own but that of others
From the GNU Coding Standards:
Their purpose is to make the GNU system
clean, consistent, and easy to install. This
document can also be read as a guide to writing
portable, robust and reliable programs.
5/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
The coding standards many-festos
\relax
\keepcool
\takeiteasy
- Readability
- Maintainability
- Robustness
- Reliability
- Portability
- Extensibility
- Intercession
Consistency: the exact coding style is less important
than actually sticking to it!
6/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
30 years and no style?
. . . makes L
A
T
E
X a dull toy. . .
Legacy
Learning by example (learn the good and the bad)
Lack of help
Liberal language (macro-expansion)
Editor support (complicated)
Lack of need
A world of dwarfs
(T
E
XLive 2009: average 327 LoC, median 134 LoC)
Antisocial development
(most packages single-authored)
7/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
30 years and almost no style?
. . . makes L
A
T
E
X an almost dull toy. . .
Tools
Blank lines, comment syntax
calc, ifthen, doc, ltxdoc etc.
Conventions
\usepackage vs. \RequirePackage,
@ character etc.
L
A
T
E
X itself not even conformant (e.g. \hbox, \m@ne)
Companion
Section 2.1 (Structuring of source files)
Section A.4 (Structuring of package files)
Less than 1% of the book. . .
8/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
The need for coding standards is real
Why?
Learning by good example
Facilitate interaction
Clean up the current intercession mess
How?
Level 1 (low): layout – formatting, indentation, naming
schemes etc.
Level 2 (mid): design – modularity, encapsulation, other
paradigms etc.
Level 3 (high): behavior – user interfaces, package
interaction / conflict management etc.
Level 4 (meta): social
9/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Blanks
Be spacey
1 Stay WYSIWYGly coherent
\\, \par
Tabular-like environments (&, \\)
2 Put only one “logical” instruction per line
environment calls
\expandafter\foo\bar
\raggedleft\foo\bar baz
3 Be as spacey as you like in math mode
blanks ignored
4 Grouping (any kind) = indentation
{}, \b[egin]group \e[nd]group,
\makeatletter, \makeatother etc.
5 The % character is your friend!
11/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Example
Choose your preferred style. . .
\ def \ @docinclude#1 { \ clearpage
\ i f@ fil es w \ immediate \ w rit e \ @mainaux { \ s tri ng \ @input { #1 . aux } } \ f i
\ @tempswatrue \ if @part sw \ @tempswafalse \ edef \@tempb{ # 1} \ @for
\ @tempa: = \ @ pa rt l is t \ do { \ if x \ @tempa\ @tempb\ @tempswatrue \ fi } \ f i
\ if@tempswa \ l e t \ @auxout \ @partaux \ i f@ fi l es w
\ immediate \ openout \ @partaux #1. aux
\ immediate \ w rit e \ @partaux { \ r el ax } \ f i
% . . . \ f i : (
\ def \ @docinclude #1{
\ clearpage
\ i f@ fi l es w \ immediate \ wr ite \ @mainaux { \ st ri ng \ @input {#1 .aux } } \ f i
\ @tempswatrue
\ if@par ts w
\ @tempswafalse
\ edef \@tempb {#1 }
\ @for \ @tempa: = \ @ pa rtl is t \ do { \ if x \ @tempa\ @tempb\ @tempswatrue \ f i }
\ f i
\ if@tempswa
\ l e t \ @auxout \ @partaux
\ i f@ fi l es w
\ immediate \ openout \ @partaux #1. aux
\ immediate \ w rit e \ @partaux { \ r el ax }
\ f i
% . . . \ f i : )
12/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Braces for impact!
Where do you put them?
Hmmm
\ newenvironment { env } [ 1 ]
{%
\ opening \ code
\ opening \ code
}
{%
\ c lo si ng \ code
\ c lo si ng \ code
}
ok
\ newenvironment { env } [ 1 ]
{%
\ opening \ code
\ opening \ code
} {%
\ c lo si ng \ code
\ c lo si ng \ code
}
Ouch!
\ newenvironment { env } [ 1 ] {%
\ opening \ code
\ opening \ code } {%
\ c lo si ng \ code
\ c lo si ng \ code }
ok
\ newenvironment { env } [ 1 ] {%
%% \ begin { env } { o pt }
\ opening \ code
\ opening \ code } {%
%% \ end { env }
\ c lo si ng \ code
\ c lo si ng \ code }
Note: brace position may require eol % char
13/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Exceptional situations / oddities
No rule without exception
Forced indentation
\ @i fn extc har [%] syn tax screwup !
{ \ @fxbeginsenv { # 2 } } { \ @@fxbeginsenv { # 2} } }
\ @i fn extc har [%] syn tax screwup !
{ \ @fxbeginsenv { #2 } }
{ \ @@fxbeginsenv { #2 } } }
Empty body-like macro arguments
\ @if un defi ne d {#1 no te } { } {%
\ @fxpkge rro r {command pr e f ix #1 ’ al read y i n use } {%
You have c al le d \ st rin g \ FX Re gi st er Au th or \ space w it h a command p r e fi x
alr eady in use . \ MessageBreak
Please choose an ot her one . } }
14/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
How maniac can you be?
Inter-macro indentation
\newcommand\ t e xt {%
\ @n extentr y
\ noalign \ bgroup
\ gdef \ @beforespace { \ s ubr ubr icb efo res pac e }%
\ @ if sta r { \ @stext } { \ @text } }
\newcommand\ @text [ 1 ] {%
\ gdef \ @nextentry { }%
\ egroup% end of \ no ali gn opened in \ t e xt .
\ multico lumn { 3 } {@{ } p { \ l ine wi dth }@{ } } { \ @ ru bri ct ex tf on t # 1 } \\ }
\newcommand\ @stext {%
\ gdef \ @nextentry { \ egroup \ \ \ par }%
\ egroup% end of \ no ali gn opened in \ t e xt .
\ multico lumn { 3 } {@{ } p { \ l ine wi dth }@{ } } \ bgroup \ @ ru br ic tex tf on t }
15/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Names
You get one for life, so beware. . .
1 Use prefixes
Avoid name clashes (e.g. \text in C
u
rV
e
and siunitx)
Mandatory for styles, arguable for classes
Use one and stick to it!
(\finkdir vs. \fnk@maindir)
2 Use postfixes (beware the \new
*
commands!)
\newsavebox\myitemsBOX
vs. \newcounter{myitems}
3 From the Companion
Lowercase for API
Mixed case for extension API
@ character for internals (several levels)
4 But stop the m@dness!
\@latexerr, \@latex@error
\@input, \@@input, \@input@, \@filef@und
\sixt@@n, \g@addto@macro
16/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Examples
API
\ f xnote
\ f xu se lay ou t
\ FXL ayo utIn line
\ FXR eg is te rA ut ho r
Internals
\ @fxnote
\ @fxuselay out
\ @FXLayoutInline
\ @FXRegisterAuthor
Nesting levels
\ DeclareRobustCommand \ f xno te {%
%% . . .
\ @ if sta r {%
%% \ fxno te
\ @i fn extc har [%]
{ \ @fxsnote { # 2 } } { \ @@fxsnote { # 2 } } }{%
%% \ fxno te
\ @i fn extc har [%]
{ \ @fxnote { # 2 } } { \ @@fxnote { #2} } } }
\ long \ def \ @fxsnote #1[# 2]#3 #4{%
%% . . .
\ @@fxsnote { #1 } {# 3 }{ # 4} }
\ long \ def \ @@fxsnote#1#2#3{%
\ implement \me}
Polymorphic macros
\ def \ @@@fxnote@early@draft { \ f o r \ d r a ft \mode }
\ def \ @@@fxnote@early@final { \ fo r \ f i n a l \ mode}
%% . . .
\ l e t \ @@@fxnote@early \ @@@fxnote@early@final
17/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Exceptional situations / oddities
No exception without rule
Conforming to de facto standards
\ifmycondition
\listoffixmes, \listfixmename
But \fixmeindexname or \fxindexname ?
Forced exceptions
Manual: \l@fixme
Auto: \c@mycounter, \myenv, \endmyenv
Commands vs. environments
\fxnote but \begin{anfxnote}\end{anfxnote}
18/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
General design rules
1 Don’t reinvent the wheel / Use existing tools
calc, ifthen, record (!) etc.
Higher abstraction = better readability
2 Duplication is evil / Copy-paste is evil
Use wrappers
Use abstractions
3 Conditionals are evil
Centralize the logic
Be polymorphic
4 Be modular
Use docstrip
Write small macros
20/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Duplication is evil / Copy-paste is evil
Use wrappers and abstractions
Bad
\ define@key [ f x ] { l ay ou t } { mor elayout } {%
. . . }
\ define@cmdkey [ f x ] { l ay ou t } { i n ne rl ay o ut } {%
. . . }
\ define@key [ f x ] { e nvl ayo ut } { en vla you t } {%
. . . }
Good
\newcommand\ @fxdef inek ey {
\ define@key [ f x ] }
\newcommand\ @fxdefinecmdkey {
\ define@cmdkey [ f x ] }
%% . . .
\ @fxdefine key { la yo ut } { mo relayou t } {%
. . . }
\ @fxdefinecmdkey { l ay ou t } { i nn er la y ou t } {%
. . . }
\ @fxdefine key { e nvl ayo ut } { en vla you t } {%
. . . }
Bad
\ define@boolkey [ f x ] { l an g } { l an gt ra ck }
[ t ru e ] { }
\ @fx defi ne vo id ke y { l an g } { n olan gt rac k } {%
\ @nameuse{ fx@lang@langtrack } { f a ls e } }
\ define@boolkey [ f x ] { l og } { si l e n t }
[ t ru e ] { }
\ @fx defi ne vo id ke y { l og } { n o si l en t } {%
\ @nameuse{ fx@l og @slie nt } { f a ls e } }
Good
\newcommand \ @f xd ef in eb oo lkey [ 3 ] [ ] {%
\ define@boolkey [ f x ] {# 2 }{ # 3}
[ t ru e ] {# 1 }
\ @fx defi ne vo id ke y { #2 } {no #3 }{%
\ @nameuse{ fx@#2@#3} { f a ls e } } }
%% . . .
\ @fx de fineboolk ey { l an g } { l an gt ra ck }
\ @fx de fineboolk ey { lo g } { s i l e n t }
21/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Conditionals are evil
Centralize the logic, be polymorphic
Bad
\ newif \ i f d r a f t
\ def \ do@everything {%
\ i f d r a f t
\ @dothis \ t h is \ way
\ else
\ @dothis \ t h is \ ot her \ way
\ f i
%% . . .
\ i f d r a f t
\ @dothat \ t ha t \ way
\ else
\ @dothat \ t ha t \ o the r \ way
\ f i }
\ Dec lare Op tion { d r aft } {
\ i f d r a f t t r u e }
\ Dec lare Op tion { f i n a l } {
\ i f d r a f t f a l s e }
\ ExecuteOptions { f i n a l }
\ ProcessOptions
Good
\ def \ @dothis@draft { \ t hi s \ way }
\ def \ @d oth is@ final { \ t his \ o the r \ way }
\ def \ @dothat@draft { \ t h at \ way }
\ def \ @dothat@final { \ t h at \ o th er \ way}
\ def \ do@everything {%
\ @dothis
%% . . .
\ @dothat }
\ Dec lare Op tion { d r aft } {
\ l e t \ @dothis \ @d othis@draft
\ l e t \ @dothat \ @dothat@draft }
\ Dec lare Op tion { f i n a l } {
\ l e t \ @dothis \ @dot his @fi nal
\ l e t \ @dothat \ @doth at@final }
\ ExecuteOptions { f i n a l }
\ ProcessOptions
23/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Be modular
Write small macros
Veeeeeeeeeeery bad, splitbib, veeeeeeeeeeery bad!!
\ def \NM SB@w rite entr y# #1 ##2 ##3 ##4 ##5 ,{\ i f x \r ela x ## 5\ re l ax
\ el se
\ def \NMSB@c urrcat{## 1## 2# #3# #4}%
\ def \N MSB @cu rrc atl eve lon e{ ##1 ## 2}%
\ i f x \NM SB@ cur rca tle vel one \ NMSB@pr evca tle velo ne \ els e
\ expan da fte r \ i f x \csname NMSB titl e@ \ NMS B@c urr cat lev elo ne
\ endcsname \ r el ax
\ el se
\ i f@f il es w
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentry
\ csname NMSBtitl e@ \ NMS B@c urr cat lev elo ne \endcsname
\ ede f \ NMSB@tempentry { \ @ba cks las hchar s ub rub ri c { \ NMSB@tempentry }}
\ expan da fte r \ NMS B@write catbib \ exp an daf te r { \ NMSB@tempentry }
\ expan da fte r \ i f x \csname
NMSBcomment@\ NMS B@c urr cat lev elo ne \ endcsname \ r el ax
\ el se
\ immediate \w ri t e \ NMSB@catbib { \ str in g \vs ki p2ex^^ J%
\ str in g \hspace { \ le ft m ar gi n } \ s tr i ng \re la x ^^ J%
\ str in g \be gin { mi ni pag e } { \ tex tw id th }^^ J%
\ str in g \ad dt ole ng th \ s tr i ng \p ar in de nt {2 0pt } ^^ J%
\ str in g \no ind ent }
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentry
\ csname NMSBcomment@ \ NMS B@c urr cat lev elo ne \ endcsname
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ NMSB@tempentry^^ J }%
\ immediate \w ri t e \ NMSB@catbib { \ str in g \end{ minip age } ^^ J%
\ str in g \pa r \ st r in g \ addp ena lty {\ NMSB@penalty }
\ str in g \vs ki p2ex }
\ f i
\ f i
\ f i
\ xde f \ NMSB @pr evca tlevelo ne {# #1##2 }%
\ ifnum \ the SBr ese tde pth > 0\ re la x
\ se tco un te r { \ @ li stc t r } { 0 }%
\ f i
\ expan da fte r \ i f x \csname NMSBprefix@\ NMSB @pr evca tlevelo ne
\ endcsname \ r el ax
\ NM SB @c ur rp re fi xl eveloneto k { \ re l a x }%
\ el se
\ expan da fte r \ ex pa nda ft er \ expa nd aft er \N MS B@ currprefi xle vel one tok
\ expan da fte r \ ex pa nda ft er \ expa nd aft er {%
\ csname NMSBprefix@ \ NMSB @prevca tlev elo ne \endcsname}%
\ f i
\ f i
\ i f x \NMSB@currcat \ NMSB@prevcat \ els e
\ ifnum \ NMSB@currc at=999 9\ els e
\ expan da fte r \ i f x \csname NMSB titl e@ \NMSB@currca t\endcsname
\ re l ax
\ el se
\ i f@f il es w
\ immediate \w ri t e \ NMSB@catbib{%
\ str in g \pa r \ st r in g \ addp ena lty { \ NMSB @halfpe nalt y }%
\ str in g \r el a x ^^ J%
\ str in g \it em []%
\ str in g \S Bs ub ti tl e }%
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentrya
\ csname NMSBtitl e@ \ NMS B@c urr cat lev elo ne \endcsname
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentryb
\ csname NMSBtitl e@ \NMSB@currcat\ endcsname
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ expan da fte r { \ NMSB@tempentrya }}
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ expan da fte r { \ NMSB@tempentryb }}
\ immediate \w ri t e \ NMSB@catbib { \ str in g \r el a x ^^ J%
\ str in g \pa r \ st r in g \ addp ena lty {\ NMSB@penalty }%
\ str in g \r el a x }%
\ expan da fte r \ i f x \csname
NMSBcomment@\ NMSB@currc at \endcsname \ re lax
\ el se
\ immediate \w ri t e \ NMSB@catbib { \ str in g \vs ki p2ex^^ J%
\ str in g \hspace { \ le ft m ar gi n } \ s tr i ng \re la x ^^ J%
\ str in g \be gin { mi ni pag e } { \ tex tw id th }^^ J%
\ str in g \ad dt ole ng th \ s tr i ng \p ar in de nt {2 0pt } ^^ J%
\ str in g \no ind ent }
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentry
\ csname NMSBcomment@ \NMSB@currca t\endcsname
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ NMSB@tempentry^^ J }%
\ immediate \w ri t e \ NMSB@catbib { \ str in g \end{ minip age } ^^ J%
\ str in g \pa r \ st r in g \ addp ena lty {\ NMSB@penalty }%
\ str in g \vs ki p2ex }
\ f i
\ f i
\ f i
\ f i
\ xde f \ NMSB@prevcat{# #1# #2# #3## 4}%
\ ifnum \ the SBr ese tde pth > 1\ re la x
\ se tco un te r { \ @ li stc t r } { 0 }%
\ f i
\ expan da fte r \ i f x \csname NMSBprefix@\NMSB@currcat\ endcsname\ r el ax
\ expan da fte r \ NM SB@ currpr efi xto k \ exp an da f te r {%
\ the \N MSB @cu rrp ref ix le ve lo ne to k }%
\ el se
\ expan da fte r \ ex pa nda ft er \ expa nd aft er \NM SB@cur rpr efi xto k
\ expan da fte r \ ex pa nda ft er \ expa nd aft er {%
\ csname NMSBprefix@ \ NMSB@currcat \ endcsname }
\ f i
\ f i
\ expan da fte r \ i f x \csname NMSBlabel@ ## 5\ endcsname \ r el a x
\ i f@f il es w
\ ste pc oun te r \ @ li stc t r
\ expan da fte r \ i f x \e xpand af ter \r e la x \ th e \ NM SB@ cu rrp refix tok
\ def \NMSB@tempentry { }%
\ el se
\ expan da fte r \ ex pa nda ft er \ expa nd aft er \de f
\ expan da fte r \ ex pa nda ft er \ expa nd aft er \NMSB@tempentry
\ expan da fte r \ ex pa nda ft er \ expa nd aft er {%
\ expan da fte r \ th e \ ex pan da fte r \ NM SB@ cur rpr efixt ok
\ the \v alu e { \ @ lis t ct r } }%
\ ede f \ NMSB@tempentry { [ \ NMSB@tempentry ]}
\ f i
\ ede f \ NMSB@tempentry{%
\ @ba cks las hcha r bi bi te m%
\ NMSB@tempentry { \ csname NMSBkey@## 5\ endcsname } }%
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ NMSB@tempentry }
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentry
\ csname NMSBentry@# #5 \endcsname%
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ NMSB@tempentry }
\ f i
\ setb ox \ @tempboxa= \hbox { \ th e \ NMSB@ cur rpr efi xtok \ the \va lu e { \ @ li stc t r } }%
\ if di m \ NM SB@ real lyl ong est < \wd \ @tempboxa
\ s et le ng th {\ N MSB @re allyl ong est } { \wd \ @tempboxa}%
\ xde f \ NM SB @r ea ll yl on gestlab el {%
\ expan da fte r \ i f x \e xpand af ter \r e la x \ th e \ NM SB@ cu rrp refix tok
\ el se \the \ NM SB@cu rrp refixt ok \ f i \ th e \ val ue {\ @ l is t c tr }} %
\ f i
\ el se
\ i f@f il es w
\ immediate \w ri t e \ NMSB@catbib{%
\ str in g \bibi te m }
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentry
\ csname NMSBlabel@ ## 5\ endcsname
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ expan da fte r [ \ NMSB@tempentry ] }%
\ immediate \w ri t e \ NMSB@catbib{%
{ \csname NMSBkey@##5\endcsname } }%
\ expan da fte r \ l e t \e xpand af ter \NMSB@tempentry
\ csname NMSBentry@# #5 \endcsname%
\ expan da fte r \ NMS B@write catbib \ exp an daf te r {%
\ NMSB@tempentry^^ J^ ^J }
\ f i
\ setb ox \ @tempboxa= \hbox { \ csname NMSBlabel@ ##5 \endcsname}%
\ if di m \ NM SB@ real lyl ong est < \wd \ @tempboxa
\ s et le ng th {\ N MSB @re allyl ong est } { \wd \ @tempboxa}%
\ expan da fte r \ l e t \e xpand af ter \N MS B@ re al ly lo ngestla bel \ csname
NMSBlabel@# #5 \endcsname
\ f i
\ f i
\ f i
}
Originally 203 LoC. 156 after dead branches removal.
Only interested in the “green” lines. . .
25/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Behavior
1 Be nice to your users (incl. yourself)
Document your packages properly
Be backward-compatible
Use key/value interfaces
2 Be nice to your hackers (incl. yourself)
Be bottom-up
Organize your code by feature
3 Intercession management
Localize behavior
filehook is crucial
27/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Key/Value interfaces
How do I choose one? Yeah, I know. . .
Package level
\mysetup macro
Macro level
xkeyval example
\ ExecuteOptionsX [my] <fam 1 ,fam 2 , . .. > { op t1= de f 1 , op t2= de f 2 , . . . }
\ ProcessOptionsX [my] <fam 1 ,fam 2 , .. . >
\newcommand \ mysetup [ 1 ] { \ se tkey s [ my] { fam1 , fam 2 , . . . } { # 1 } }
\newcommand\ mymacro [ 2 ] [ ] {%
\ setk ey s [my] { fam1 , fam 2 , . . . } { # 1 }
. . . }
28/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Behavior
1 Be nice to your users (incl. yourself)
Document your packages properly
Be backward-compatible
Use key/value interfaces
2 Be nice to your hackers (incl. yourself)
Be bottom-up
Organize your code by feature
3 Intercession management
Localize behavior
filehook is crucial
29/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Standard interface too limited
The L
A
T
E
X developer’s worst nightmare
\@ifpackageloaded, \@ifclassloaded
Curative (a posteriori) code only
What about precautionary code?
\AtBeginDocument
Massively defer code execution
What about the order?
Example:
Style S calls \AtBeginDocument{\things}
Class C loads style S
How does C intercede on \things?
30/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
filehook is crucial
Before and after hooks
Start with your default behavior
Rewrite on demand and locally
Example: how C
u
rV
e
handles bibliography
31/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Collaboration and Reactivity
One year and 38 weeks later. . .
1 Propose collaboration
Don’t keep it for yourself
Don’t reinvent the wheel
2 Accept collaboration
Be reactive
Review and accept patches
Examine and implement ideas
Open development
Use collaborative tools
Trust people
33/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Conclusion
The golden rules of (L
A
T
E
X) programming
1 Coding style is important
2 Sticking to it is more important
3 Keep it in mind permanently
4 Let it evolve
5 No rule without exception
35/37
L
A
T
E
X Style
Didier Verna
Introduction
Coding Standards?
Not L
A
T
E
X ones?
What can we do?
Layout
Blanks
Names
Design
Duplication
Conditionals
Modularity
Behavior
Key/Value interfaces
Intercession
Social
Conclusion
Perspectives
Perspectives
Where is this book?
37/37