5

I'm attempting to automate Werner's answer to my question here.


In short, in order to sort the Norwegian letters Æ Ø Å (they come at the end of the regular Latin alphabet) correctly dtlsort needs some help. This means replacing æ with za, ø with zb, etc.

I tried doing this with xstring's \StrSubstitute command, but it can only replace one string at a time, and doesn't seem to like being nested.

One single pass works in PDFLaTeX.


This MWE should output zbzazc.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{datatool,xparse}
\usepackage{xstring}

\NewDocumentCommand{\norskletterssub}{m}{%
    \def\strA{\StrSubstitute{#1}{æ}{za}}
    \def\strB{\StrSubstitute{\strA}{ø}{zb}}
    \def\strC{\StrSubstitute{\strB}{å}{zc}}
    \strC
    }

\begin{document}

    \norskletterssub{øæå}

\end{document}

I need to run multiple passes because there's obviously no guarantee there's only one of each letter.

Additionally, there aren't any capital letters that need to be checked for.

What's the best way to do this?

6

While I fully endorse using an expl3 based method, here's how you can do the same with xstring.

  1. You should use the trailing optional argument, not doing \def\strA{\StrSubstitute{...}{...}{...}}

  2. You have to care about not doing unwanted expansion: with the utf8 option, the non ASCII characters are essentially macros, hence \noexpandarg is in order.

Here's the code.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{datatool,xparse}
\usepackage{xstring}

\NewDocumentCommand{\norskletterssub}{m}{%
  \saveexpandmode\noexpandarg
  \def\tempstring{#1}%
  \xStrSubstitute{\tempstring}{æ}{za}[\tempstring]%
  \xStrSubstitute{\tempstring}{ø}{zb}[\tempstring]%
  \xStrSubstitute{\tempstring}{å}{zc}[\tempstring]%
  \tempstring
  \restoreexpandmode
}
\newcommand*{\xStrSubstitute}{%
  \expandafter\StrSubstitute\expandafter
}

\begin{document}

\norskletterssub{øæå}

\end{document}

enter image description here

If your aim is to do the substitution for a check such as with \IfStrEq, you can do

\NewDocumentCommand{\IfNorskStrEq}{mmmm}{%
  \saveexpandmode\noexpandarg
  \def\tempstring{#1}%
  \xStrSubstitute{\tempstring}{æ}{za}[\tempstring]%
  \xStrSubstitute{\tempstring}{ø}{zb}[\tempstring]%
  \xStrSubstitute{\tempstring}{å}{zc}[\tempstring]%
  \restoreexpandmode
  \IfStrEq{\tempstring}{#2}{#3}{#4}%
}
\newcommand*{\xStrSubstitute}{%
  \expandafter\StrSubstitute\expandafter
}

Now something like

\IfNorskStrEq{våkne}}{vzckne}{true}{false}

should evaluate to true.

8
  • While this works for my question as asked, it has problems with my overarching question, which is how sort Norwegian words. For some reason, this is fails with \dtlsort. Do you have any idea why? (I thought I'd ask, in case it's an encoding issue I'm not familiar with, before posting a third question about my same problem.) – Azor Ahai -him- Jan 8 '16 at 20:35
  • @Azor-Ahai Not without seeing the real thing, I'm afraid. – egreg Jan 8 '16 at 21:21
  • Would it help to know \IfStrEq{\norskletterssub{våkne}}{vzckne}{true}{false} evaluates to false? – Azor Ahai -him- Jan 8 '16 at 21:36
  • @Azor-Ahai Yes, of course it evaluates to false. You have to do \norskletterssub{våkne}\IfStrEq{\tempstring}{vzckne}{true}{false}; but remove the last call of \tempstring in the definition of \norskletterssub. – egreg Jan 8 '16 at 21:51
  • Ah, I assumed \tempstring was local to \norskletterssub. But doesn't the command \tempstring within the command definition output the new string, like in your example? – Azor Ahai -him- Jan 8 '16 at 21:58
7

The programming layer expl3 of the upcoming LaTeX3 offers a lot of handy functions for such tasks. In expl3 the underscore _ character can be used in macro names. We first allocate a new token list variable

\tl_new:N \l_azor_string_tl

Then we define a code level function, which sets the token list variable to the input string and then replaces the desired substrings.

\cs_new_protected:Npn \azor_replace_norsk:n #1
 {
  \tl_set:Nn \l_azor_string_tl { #1 }
  \tl_replace_all:Nnn \l_azor_string_tl { æ } { za }
  \tl_replace_all:Nnn \l_azor_string_tl { ø } { zb }
  \tl_replace_all:Nnn \l_azor_string_tl { å } { zc }
  \tl_use:N \l_azor_string_tl
 }

In the end we defined a document level function (i.e. the one which is to be used by you in when typing the document), which simply calls the code level function with the appropriate argument.

\NewDocumentCommand \norskletterssub { m }
 {
  \azor_replace_norsk:n { #1 }
 }

(Unfortunately the whole thing is not expandable, i.e. when doing \edef\temp{\norskletterssub{øæå}} the macro \temp will not contain zbzazc, but still \norskletterssub {øæå})

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{xparse}

\ExplSyntaxOn

\tl_new:N \l_azor_string_tl

\cs_new_protected:Npn \azor_replace_norsk:n #1
 {
  \tl_set:Nn \l_azor_string_tl { #1 }
  \tl_replace_all:Nnn \l_azor_string_tl { æ } { za }
  \tl_replace_all:Nnn \l_azor_string_tl { ø } { zb }
  \tl_replace_all:Nnn \l_azor_string_tl { å } { zc }
  \tl_use:N \l_azor_string_tl
 }

\NewDocumentCommand \norskletterssub { m }
 {
  \azor_replace_norsk:n { #1 }
 }

\ExplSyntaxOff

\begin{document}

øæå \norskletterssub{øæå}

\end{document}

enter image description here

2
  • Can you maybe explain your code a little? I haven't used expl3 before. – Azor Ahai -him- Jan 3 '16 at 21:30
  • @Azor-Ahai See updated answer. – Henri Menke Jan 3 '16 at 21:38

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.