From: Stefan R. <lis...@st...> - 2008-10-23 07:33:20
|
Hi Günter, [your reply to me did not go to the list I think, so I added and commented it inline below] on 22.10.2008 16:36 G. Milde said the following: > On 21.10.08, Stefan Rank wrote: >> on 21.10.2008 18:02 Guenter Milde said the following: > > >>> Currently, an inline node with a class unknown to the latex writer > ... >>> leads to an error if the document is translated to PDF without a >>> special stylesheet. > >>> The missing feature is a "failsave" handling of class information: > >> I very much like the failsafe nature of this patch (compared to the >> status quo), but I would like to propose a different approach that >> should be backwards-compatible and easier to extend: > >> Change the standard definition of inlinenode so that it checks for the >> existence of a \docutilsroleXYZ definition. I am sorry I am not fluent >> enough in latex/tex, but I am pretty sure that is possible: > >> What do you think? > > Thanks for this idea and the sample implementation in your followup post. Thank you for the effort!! > The only missing feature was support for multiple classes. Attached > are the updated patch and a sample document. Ah, very nice. I have two more comments below. > Günter > > Styling LaTeX with classes > ************************** > > With the proposed patch to the latex2e writer will define a new LaTeX macro:: > > \makeatletter > \providecommand{\inlinenode}[2]{% > {% use a group ("span") to limit scope of styling commands > \@for\class@name:=#1\do{% > \ifcsname docutilsrole\class@name\endcsname% > \@nameuse{docutilsrole\class@name}% > \fi% > }% > {#2}% node content as argument to last \docutilsrole... command > }% close "span" > } > \makeatother > > Inline nodes with class arguments are translated to an ``\inlinenode`` > command which is typeset without error, ignoring the class arguments if no > special `class-command` definitions (e.g. in a style sheet) are provided. > > Example > ======= > > .. role:: boldsans > > The custom role `boldsans` translates to:: > > \inlinenode{boldsans}{bold italic inline-text} > > If a command named `docutilsroleboldsans` exists, its > definition is used to style the content. > > .. The following definition is the LaTeX equivalent of a CSS rule for the > `boldsans` class. > > .. raw:: latex > > \newcommand{\docutilsroleboldsans}{\sffamily\bfseries} > > Test: > > This should be :boldsans:`bold sans-serif text` in a normal > paragraph. > > Non-alphabetic characters in the class name > =========================================== > > LaTeX normally does not allow non-alphabetic characters in commands. > There is, however a workaround to allow e.g. class names with hyphens: > > .. role:: bold-italic > > The custom role `bold-italic` translates to:: > > \inlinenode{bold-italic}{bold italic inline-text} > > The special TeX macro ``\@namedef`` must be used to define > `docutilsrolebold-italic`. > > .. raw:: latex > > \makeatletter > \@namedef{docutilsrolebold-italic}{\bfseries\itshape} > \makeatother > > Test: > > This should be :bold-italic:`bold italic text` in a normal paragraph. > > Multiple classes > ================ > > A list of class names is passed on to the LaTeX source, e.g. as:: > > \inlinenode{small,boldsans}{small bold sans-serif inline-text} > > With a definition of `docutilsrolesmall`, this will be rendered > correctly. > > .. raw:: latex > > \newcommand{\docutilsrolesmall}{\footnotesize} > > Test: (TODO: How do I generate an inline doctree node with two class > arguments from reStructuredText?) > > .. raw:: latex > > This should be \inlinenode{small,boldsans}{small bold sans serif > inline-text} in a normal paragraph. > > Caveats > ======= > > With the proposed latex2e patch, the expansion of:: > > \inlinenode{small,boldsans}{small bold sans-serif} > > is:: > > {\docutilsrolesmall\docutilsroleboldsans{small bold sans-serif}} > > (while the unpatched writer writes:: > > \docutilsrolesmall{\docutilsroleboldsans{small bold sans-serif}} > > dirctly in the LaTeX source). > > This results in some restrictions to the class-commands: > > 1. All (but the last) class-command should be defined without argument. > > Use ``\itshape`` instead of ``\textit{#1}`` etc. > > 2. As the order of class names should not matter, definitions should be > "orthogonal" (if possible). Mmmh, do you think we could change that so the original behaviour is reproduced? Commands that take one argument:: \docutilsroleXYZ{...} are much more flexible (and more 'latex-ish' and backwards-compatible) than spans:: { \docutilsroleXYZ ...} I think that using \begingroup (which is another way to say '{' in latex) and then generating a corresponding number of \endgroup's might do the trick? > Naming > ====== > > * The ``\inlinenode`` name for the dispatcher command is open for discussion. > Alternatives are e.g. ``\reSTspan``, ``\SPAN``, ``\reSTinline``. > > Generally, it should be considered to provide a "namespace prefix" to all > macros defined by a reStructuredText to LaTeX converter. Proposals are > ``\RST``, ``\reST``, or a suitable acronym for Docutils. > > * The ``\docutilsrole`` prefix for class-styling macros is used for > backwards compatibility. It is sub-optimal because there is no visible > separation of prefix and class-name. > > Alternatives are ``\reSTclass``, ``\RSTclass``, ``\reSTclass@``, > ``\class@``. (The last two alternatives would require the > ``\makeatletter`` ``\makeatother`` wrapper around command definitions.) Why not use 'docutils' as the namespace prefix? After all this is about the docutils document tree and not about the rst parser input format. Then \docutilsroleXYZ stays the same and \inlinenode would be \docutilsinlinenode. Also, a longer prefix reduces namespace-clash-probability :-) cheers, stefan > > > Exec: svn 'diff' '__init__.py' 2>&1 > Dir: /home/milde/Code/Python/docutils-svn/docutils/docutils/writers/latex2e/ > > Index: __init__.py > =================================================================== > --- __init__.py (Revision 5680) > +++ __init__.py (Arbeitskopie) > @@ -366,6 +366,22 @@ > ] > } > > +latex_headings['inlinenode'] = > +[r"""\makeatletter > +\providecommand{\inlinenode}[2]{% > + {% use a group (i.e. "span") to limit the scope of styling commands > + \@for\class@name:=#1\do{% > + \ifcsname docutilsrole\class@name\endcsname% > + \@nameuse{docutilsrole\class@name}% > + \fi% > + }% > + {#2}% node content as argument to last \docutilsrole... command > + }% close "span" > +} > +\makeatother > +"""] > + > + > class DocumentClass: > """Details of a LaTeX document class.""" > > @@ -750,6 +766,7 @@ > self.head_prefix.extend( latex_headings['optionlist_environment'] ) > self.head_prefix.extend( latex_headings['lineblock_environment'] ) > self.head_prefix.extend( latex_headings['footnote_floats'] ) > + self.head_prefix.extend( latex_headings['inlinenode'] ) > self.head_prefix.extend( latex_headings['some_commands'] ) > ## stylesheet is last: so it might be possible to overwrite defaults. > stylesheet = utils.get_stylesheet_reference(settings) > @@ -2207,14 +2224,12 @@ > self.body.append('\n') > > def visit_inline(self, node): # titlereference > - classes = node.get('classes', ['Unknown', ]) > - for cls in classes: > - self.body.append( '\\docutilsrole%s{' % cls) > - self.context.append('}'*len(classes)) > - > + classes = node.get('classes', []) > + self.body.append(r'\inlinenode{%s}{' %','.join(classes)) > + > def depart_inline(self, node): > - self.body.append(self.context.pop()) > - > + self.body.append('}') > + > def visit_rubric(self, node): > self.body.append('\\rubric{') > self.context.append('}\n') |