5

There are a number of times when I'm writing LaTeX documents when I need to write a character with an accent or diacritic in it. For instance, the "ô" needed to write "L'Hôpital" (in reference to his titular rule) came up quite frequently in writing notes for my calculus class.

Of course, this extends to other accented characters and the like, often for names (e.g. Paul Erdős, René Descartes, Otto Hölder). Some can be seen here.

Writing these out in LaTeX has become a bit of a chore for me, mainly because I struggle to remember the actual codes to use them or often mix them up. I'm writing on a standard English keyboard as well, so "just type the character into the document" results in me having to copy-and-paste it from elsewhere. So either way I have to look something up - the list of codes, or something with the character in it.

It would be easier for me if I could have some sort of piece of code that automatically detects a relevant string, and replaces it with one with the corrected accent. So for instance, something that would see that I'd typed L'Hopital, and replace it with L'Hôpital instead, in the resulting PDF.

Of course, it would be trivial to define a macro that does it, something like

    \newcommand{\lhopital}{L'Hôpital}

but using this feels clunky and unnatural, especially for something that is almost surely going to be rendered outside of math mode.

I feel like something like this may be possible based on some searching I've done in the past. For instance, this post changes it so that := generates what you would expect, but with better vertical alignment of the colon with respect to the equal sign. Granted, I have a hard time parsing what exactly the snippet of code is doing... But regardless, that code works exactly like I'd envision: zero extra effort on my part aside from putting in the code.

So in short, what I'd ideally like is something which can automatically replace a text string I type in the document, with a particular text string I want to replace it with. Hence whenever I type L'Hopital I get L'Hôpital, Erdos I get Erdős, and so on and so forth - in general, I type stringA and obtain stringB in the output.

Thanks for any help you can give!

5
  • For understanding maybe see tex.stackexchange.com/questions/12668/…
    – user202729
    Nov 6, 2021 at 6:37
  • Are you willing and able to use LuaLaTeX?
    – Mico
    Nov 6, 2021 at 8:07
  • 3
    you can always use L'H\^opital which is a lot easier to type on a UK keyboard. As Don says you can use your editor or if you are using lualatex you could use an input filter for this Nov 6, 2021 at 8:08
  • Able to? Maybe. And maybe others might appreciate a solution in that vein. Personally I'd rather avoid LuaLaTeX if possible. Nov 6, 2021 at 8:08
  • 1
    It depends on many factors. For instance, there are editors that have autocompletion suggestions for ordinary text in a document, so you would only have to type it out once and could use autocompletion from there on.
    – TeXnician
    Nov 6, 2021 at 8:11

4 Answers 4

7

If you're willing and able to use LuaLaTeX, you could make use of its process_input_buffer callback, which can be made to perform as a pre-processor on the input stream, before TeX even starts its usual work. Users will just need to populate the name_table Lua table with suitable search and replacement strings.

enter image description here

\documentclass{article}

\directlua{ 
% -- Set up a Lua table with search and replacement strings:
  name_table = {
     { "L'?Hopital" , "L'Hôpital" },
     { "Erdos"      , "Erdős"     },
     { "Holder"     , "Hölder"    }, 
     { "Godel"      , "Gödel"     },
     { "Rene"       , "René"      },
  }
% -- Next, define the Lua function that does the actual work:
  function change_table_vals ( s )
    for _,j in pairs ( name_table ) do 
      s = s:gsub ( j[1] , j[2] ) 
    end
    return s
  end
}
%% assign the Lua function to the 'process_input_buffer' callback
\AtBeginDocument{\directlua{luatexbase.add_to_callback ( 
   "process_input_buffer" , change_table_vals , "change" )}}

\begin{document}
L'Hopital LHopital Erdos Holder Rene Godel
\end{document}
4

Since TeX is an expandable macro language, Expl3's regex functionality can handle replacements, more powerfully than just replacing strings, as it works at token-list level and can see inside control sequences.

All sorts of typing shortcuts become available, and for typing convenience the entire document environment can be fed to the regex as a token list:

regex usage

The hard work is keeping the lookup (stringA) elements unique (from each other, and from (parts of) ordinary words in the text).

MWE

\documentclass{article}
\usepackage{xcolor}
\pagecolor{green!3}
\usepackage{etoolbox}
\usepackage{xparse}
\usepackage{fontspec}

\DeclareTextFontCommand{\textjp}{\fnippon}
\AtBeginEnvironment{document}{\myauto}
\AtEndEnvironment{document}{\endmyauto}

\setmainfont{Noto Serif}
\newfontfamily{\fnippon}{NotoSerifCJKjp}[
Extension=.otf,
UprightFont=*-Regular,
%BoldFont=NotoSerifCJKjp-Bold.otf,
]
%==============================


%^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
\ExplSyntaxOn

\tl_new:N \l_myab_tl

\NewDocumentEnvironment { myauto } { +b }
{
    \tl_set:Nn \l_myab_tl { #1 } 
    \domyauto 
    \tl_use:N \l_myab_tl 
}
{}

\newcommand\dmr[2]{
\regex_replace_all:nnN { #1 } { #2 } \l_myab_tl
%   \tl_replace_all:Nnn 
%                   \l_myab_tl 
%                   { #1 } 
%                   { #2 }

}

\newcommand{\domyauto}{
\dmr{lhopital} {L'Hôpital}
\dmr{hoelder}{Hölder}
\dmr{goedel}{Gödel}
\dmr{rened}{René}
\dmr{erdos}{Erdős}
\dmr{kazkur}{Kazimierz\ Kuratowski}
\dmr{waclaw}{Wacław\ Sierpiński}
\dmr{zyg}{Zygmunt\ Janiszewski}
\dmr{jerzy}{Jerzy\ Różycki}
\dmr{golab}{Stanisław\ Gołąb}
\dmr{ariege}{Ariège}
\dmr{bdrhone}{Bouches-du-Rhône}
\dmr{cotedor}{Côte-d'Or}
\dmr{isere}{Isère}
\dmr{upperaustria}{Oberösterreich}
\dmr{Carinthia}{Kärnten}
\dmr{kanagawa}{\c{textcolor}\cB\{blue\cE\}\cB\{\c{textjp}\cB\{神奈川県\cE\}\cE\}}
\dmr{toyama}{\c{textcolor}\cB\{blue\cE\}\cB\{\c{textjp}\cB\{富山県\cE\}\cE\}}
\dmr{hironaka}{\c{textjp}\cB\{広中\ 平祐\cE\}}
\dmr{yoneda}{\c{textjp}\cB\{米田\ 信夫\cE\}}
%\dmr{}{}
}

\ExplSyntaxOff


\begin{document}
%\begin{myauto}
\section{lhopital}
The cat sat on the lhopital rule.

erdos hoelder goedel rened fullerene

golab, jerzy, zyg, waclaw, kazkur.

ariege, bdrhone, cotedor, isere, upperaustria, Carinthia

\section{kanagawa, toyama}

Heisuke Hironaka (hironaka), Nobuo Yoneda (yoneda).


%\end{myauto}
\end{document}
5
  • 1
    It's relatively clear that with this method anything that involves catcode (for example verbatim) will break.
    – user202729
    Nov 6, 2021 at 16:32
  • For the unique part... you can match word boundary in expl3, and also sort There placements by decreasing length.
    – user202729
    Nov 6, 2021 at 16:34
  • Also note that \ ​ is different from a normal space, normal space is usually ~ in LaTeX3 mode
    – user202729
    Nov 6, 2021 at 16:38
  • @user202729 The interface3 manual describes controlling category codes under regex; alternatively, for non-catcode runs of text, a local transliteration environment (or command) could be used instead of a document-wide one. The effort involved in setting up the stringB side of the lookup (and where: editor, regex, OS, input method, keyboard overlay, etc) will be input into the transliteration use-case. For example, typing French is trivial (OS: swap keyboards); typing Ugaritic, I could build a custom keyboard overlay (OS), or use a regex with appropriate font. Typing 12 ancient scripts....
    – Cicada
    Nov 7, 2021 at 1:41
  • 2
    Yes, wrapping individual segments are okay. // I just point it out so people who also use something like \verb|%| in the document will understand why it gives "mysterious" error.
    – user202729
    Nov 7, 2021 at 1:51
1

This is generally going to be a feature of your text editor or even your OS. For example, on MacOS, you can go to Settings|Keyboard|Text and set it up so if you type lhopital it will automatically change that to L'Hôpital wherever you're typing.

0

The easy alternative would be using AutoHotKey or something else (vim abbrev command, etc.) to do the replacement, as mentioned in other answers.


Remember that TeX is just a programming language.

Think how you would do it for a "normal" programming language such as Python...

​  • You run another script to replace all sequence of characters in the old script by the new sequence you desire, then
​  • you execute the new script.

This is (should be?) also possible in LaTeX by

​  • Reading the content of the file (either literally as in \ior_str_get:NN or by technique similar to verbatim scan-forward)
​  • Use something like \str_replace_all:Nnn to replace the old string with the new string
​  • Use \scantokens to re-interpret (exec in Python) as TeX source code.

For engines such as LuaTeX it's already possible to preprocess the source code through Lua without a separate step, see the other answer.

Needless to say programming in TeX is not very comfortable, and making a Python/Lua/something else script to find-and-replace in the source is preferred by most people.

To be more precise for languages such as Python you can use ast to parse the source code into a parse tree then only replace parts in strings etc., but as far as I know TeX does not output any parse tree (most of the time the concept of a parse tree doesn't even make sense in TeX.)


In TeX however, you can redefine a character in normal (text) mode to scan the characters forward. Which means you can define L to scan forward (see \peek_N_type:TF and similar) to determine if the next characters is 'Hopital and do the replacement appropriately; but now that L is an active character it may break various other things (such as you can't use it in a control sequence name)

The alternative is to define some character such as to do the forward scan, but if you want to type ◇L'Hopital you might as well just type \LHopital.


Yet another method is to use ligature in font file...

European languages can also be accommodated effectively with only a limited character set. For example, let’s consider Norwegian again, but suppose that you want to use a keyboard without an æ character. You can arrange the font metric file so that TEX will interpret ae, o/, aa, AE, O/, and AA as ligatures that produce æ, ø, ˚a, Æ, Ø, and ˚A, respectively; and you could put the characters ˚a and ˚A into positions 128 and 129 of the font.

(The TeXBook, page 45, chapter 8 "The Characters You Type")

I'm not sure if this method works for the new engines (which use new font formats), and I definitely don't know how to create such a font (and even if you do this I think you still need to type L'Ho"pital or similar? Not much of an improvement I guess).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.