TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
up vote 4 down vote accepted

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.

share|improve this answer
    
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 Jan 8 at 20:35
    
@Azor-Ahai Not without seeing the real thing, I'm afraid. – egreg Jan 8 at 21:21
    
Would it help to know \IfStrEq{\norskletterssub{våkne}}{vzckne}{true}{false} evaluates to false? – Azor-Ahai Jan 8 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 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 Jan 8 at 21:58

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

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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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