Take the 2-minute tour ×
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.

In my thesis I will include a fair number of tags (morphological tags, in case it matters) that are fixed-width character strings like this: ab-c--d, where dashes denote NULL fields. I'd like to define a macro \msd that takes such a tag and outputs it with en-dashes for the NULL fields.

As far as I can make out, this macro needs to do two things:

  1. Disable the double-hyphen and triple-hyphen ligatures (to avoid weirdness when two NULL fields are adjacent)
  2. The actual TeXnical jiggery-pokery required to render hyphens as en-dashes

The details of how I'd do this elude me, unfortunately. Could someone help me out with this, or point me in the right direction?

share|improve this question
    
Is it practiable to find and replace on the tags before inclusion and just replace the hypen character with a macro \null say, which then is defined as an en-dash? This would certainly be a simple and safe solution, if practical... –  Seamus Jan 26 '11 at 13:10
    
Another option might be to typeset using typewriter font: \newcommand*\msd{}\let\msd\texttt. –  Bruno Le Floch Jan 26 '11 at 18:44
add comment

4 Answers 4

up vote 3 down vote accepted

Here is a straightforward latex solution. It may behave oddly, though, if you feed unexpected stuff to it, such as brace delimited material (such as, say, \msd{ab{-b-c}d}).

\documentclass{minimal}
\newcommand{\msd}[1]{\msdhelper#1\relax}
\newcommand{\msdhelper}[1]
  {\ifx\relax#1\else
    \ifx-#1--{}\else#1\fi
    \expandafter\msdhelper\fi}
\begin{document}
\msd{ab-c--d}
\end{document}
share|improve this answer
    
In the end, I went with a variant on this. As Alan Munn pointed out, there's no space around the en-dashes, so explicit space is needed. I went with 1pt of space, and an mbox around the whole ting, so that it won't be broken up. –  arnsholt Mar 26 '11 at 16:50
add comment

There's a simple solution to your problem: just encode your source file as UTF-8 and change all the null field markers to the actual en-dash in your source.

However, I don't think this will achieve the formatting you actually want, since when you put two en-dashes together, they will not have any space between them (unlike the hyphen characters.) So probably what you need is a bit more complicated, since you need to add some space after each en-dash to show the null fields as individual elements.

So here's another solution using XeLaTeX: create a custom map file which maps the hyphen into an en-dash with a non-breaking space. The following instructions work on a Mac or Linux machine; the same thing can be done in Windows but I don't know how, although you can get directions in the link below.

First, dowload and install the TECkit software from SIL:

Next, make the following map file (plain text file, named hyphen-dash.map). This file maps '-' into an en-dash+non-breaking space.

; Hyphen to emdash mapping file for XeTeX
; hyphen-dash.map
;
LHSName "hyphen-dash"
RHSName "UNICODE"
pass(Unicode)

U+002D  <>  U+2013 U+00A0   ; "-" -> "– "

Next, compile this file using the following command from the command line:

teckit_compile hyphen-dash.map -o hyphen-dash.tec

Copy the hyphen-dash.tec file to your local texmf folder in fonts/misc/xetex

Now you can compile the following xelatex document:

% !TEX TS-program = XeLaTeX
\documentclass{article}
\usepackage{fontspec}
\pagestyle{empty}
\setmainfont[Mapping=tex-text]{Charis SIL}
\newfontfamily\glossfont[Mapping=hyphen-dash]{Charis SIL}
\newcommand{\formatgloss}[1]{{\glossfont#1}}
\begin{document}
Without the hyphen mapping: regular hyphens and dashes:

a-b--c---d

What happens when you put two en-dashes directly together:

a––

Now with the mapping file enabled:

\formatgloss{a-b--c----d}

This solution can be used inside other macros:

\textit{\formatgloss{a-b--c----d}}
\end{document}

Output here:

enter image description here

share|improve this answer
add comment

The following TeXnical jiggery-pokery seems to work:

\documentclass{article}
\begingroup
\catcode`-=\active
\aftergroup\newcommand
\aftergroup-
\endgroup
{--\relax}
\newcommand\msd{\begingroup\catcode`-=\active\msdhelper}
\newcommand\msdhelper[1]{#1\endgroup}
\begin{document}
test \msd{ab-c--d} test-case
\end{document}

Inside the \msd macro, the - is made active (and produces the en-dash), but the usual - is restored afterwards. This solution can cause trouble if other packages try similar trickery with making - active.

share|improve this answer
1  
This will work fine when \msd{ab-c--d} is encountered at top-level, but not if this is encountered as an argument to some other macro (since the catcodes will be fixed and cannot be changed, except perhaps by some etex hackery). –  Harald Hanche-Olsen Jan 26 '11 at 15:36
add comment

And a LaTeX3 answer as well: we go through the argument token by token using \tl_map_function:nN, and we replace every character - by the token list --\relax. Note that this implementation gets confused by braced things, e.g. \msd{a{bc}d} will fail.

\documentclass{minimal}
\usepackage{expl3}
\usepackage{xparse}
\begin{document}
\ExplSyntaxOn
\cs_new:Npn \msd #1 {
  \tl_map_function:nN {#1} \msd_convert_dash:n
}
\cs_new:Npn \msd_convert_dash:n #1 {
  \token_if_eq_charcode:NNTF - #1 {\texttt{-}} {#1}
}
\ExplSyntaxOff

% Tests
\msd{a--b-c}
\msd{a-bc}
% It is expandable:
\edef\foo{\msd{a-b---c}}
\foo

\end{document}

EDIT: Alan Munn is right about two dashes together looking ugly. I replaced by a \texttt{-} in my solution.

share|improve this answer
    
There is a \tl_replace_all_in:Nnn function that probably makes this a bit easier. –  Will Robertson Jan 27 '11 at 5:11
    
@Will: \tl_replace_all_in:Nnn seems to require the argument to already be inside a token list. Putting it there would be unexpandable. –  Bruno Le Floch Jan 27 '11 at 6:30
add comment

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.