git.iko.soy/typeable/pandoc
on master help sign in
Groff escaping changes.

- `--ascii` is now turned on automatically for man output, for portability. All man output will be escaped to ASCII. - In T.P.Writers.Groff, `escapeChar`, `escapeString`, and `escapeCode` now take a boolean parameter that selects ascii-only output. This is used by the Ms writer for `--ascii`, instead of doing an extra pass after writing the document. - In ms output without `--ascii`, unicode is used whenever possible (e.g. for double quotes). - A few escapes are changed: e.g. `\[rs]` instead of `\\` for backslash, and `\ga]` instead of `` \` `` for backtick.

commitefbb329f1a81a778fd853bffee0414c87a1133b3 authorJohn MacFarlane <jgm@berkeley.edu> dateThu 18 Oct 2018, 10:21 (8 years ago) parentbbd94ea
10 files changed+118−110
MANUAL.txt+4−3 src/Text/Pandoc/GroffChar.hs+16−15 src/Text/Pandoc/Writers/Groff.hs+20−18 src/Text/Pandoc/Writers/Man.hs+6−6 src/Text/Pandoc/Writers/Ms.hs+28−24 test/command/4550.md+1−1 test/command/ascii.md+2−2 test/tables.ms+4−4 test/writer.man+14−14 test/writer.ms+23−23
MANUAL.txt+4−3
@@ -860,10 +860,11 @@ Options affecting specific writers {.options}
860860
861861: Use only ASCII characters in output. Currently supported for
862862 XML and HTML formats (which use numerical entities instead of
863− UTF-8 when this option is selected), groff ms and man
863+ UTF-8 when this option is selected), groff ms
864864 (which use hexadecimal escapes), and to a limited degree
865− for LaTeX (which uses standard commands for accented
866− characters when possible).
865+ LaTeX (which uses standard commands for accented
866+ characters when possible). Groff man output uses ASCII
867+ by default.
867868
868869`--reference-links`
869870
src/Text/Pandoc/GroffChar.hs+16−15
@@ -1,4 +1,5 @@
11{-# LANGUAGE NoImplicitPrelude #-}
2+{-# LANGUAGE OverloadedStrings #-}
23{-
34Copyright (C) 2018 John MacFarlane <jgm@berkeley.edu>
45
@@ -400,19 +401,19 @@ characterCodes =
400401-- use like: \\[E a^ aa]
401402combiningAccents :: [(Char, String)]
402403combiningAccents =
403− [ ('˝' , "\\[a\"]")
404− , ('¯', "\\[a-]")
405− , ('˙', "\\[a.]")
406− , ('^', "\\[a^]")
407− , ('´', "\\[aa]")
408− , ('`', "\\[ga]")
409− , ('˘', "\\[ab]")
410− , ('¸', "\\[ac]")
411− , ('¨', "\\[ad]")
412− , ('ˇ', "\\[ah]")
413− , ('˚', "\\[ao]")
414− , ('~', "\\[a~]")
415− , ('˛', "\\[ho]")
416− , ('^', "\\[ha]")
417− , ('~', "\\[ti]")
404+ [ ('˝' , "a\"")
405+ , ('¯', "a-")
406+ , ('˙', "a.")
407+ , ('^', "a^")
408+ , ('´', "aa")
409+ , ('`', "ga")
410+ , ('˘', "ab")
411+ , ('¸', "ac")
412+ , ('¨', "ad")
413+ , ('ˇ', "ah")
414+ , ('˚', "ao")
415+ , ('~', "a~")
416+ , ('˛', "ho")
417+ , ('^', "ha")
418+ , ('~', "ti")
418419 ]
src/Text/Pandoc/Writers/Groff.hs+20−18
@@ -37,12 +37,10 @@ module Text.Pandoc.Writers.Groff (
3737 , escapeChar
3838 , escapeString
3939 , escapeCode
40− , groffEscape
4140 , withFontFeature
4241 ) where
4342import Prelude
44−import qualified Data.Text as T
45−import Data.Char (isAscii, ord)
43+import Data.Char (ord, isAscii)
4644import Control.Monad.State.Strict
4745import Data.List (intercalate)
4846import qualified Data.Map as Map
@@ -51,7 +49,7 @@ import Text.Pandoc.Class (PandocMonad)
5149import Text.Pandoc.Definition
5250import Text.Pandoc.Pretty
5351import Text.Printf (printf)
54−import Text.Pandoc.GroffChar (essentialEscapes)
52+import Text.Pandoc.GroffChar (essentialEscapes, characterCodes)
5553
5654data WriterState = WriterState { stHasInlineMath :: Bool
5755 , stFirstPara :: Bool
@@ -82,31 +80,35 @@ type Note = [Block]
8280
8381type MS = StateT WriterState
8482
85−
86−escapeChar :: Char -> String
87−escapeChar c = fromMaybe [c] (Map.lookup c essentialEscapes)
83+escapeChar :: Bool -> Char -> String
84+escapeChar useAscii c =
85+ case Map.lookup c essentialEscapes of
86+ Just s -> s
87+ Nothing
88+ | useAscii
89+ , not (isAscii c) ->
90+ case Map.lookup c characterCodeMap of
91+ Just t -> "\\[" <> t <> "]"
92+ Nothing -> printf "\\[u%04X]" (ord c)
93+ | otherwise -> [c]
8894
8995-- | Escape special characters for groff.
90−escapeString :: String -> String
91−escapeString = concatMap escapeChar
96+escapeString :: Bool -> String -> String
97+escapeString useAscii = concatMap (escapeChar useAscii)
9298
9399-- | Escape a literal (code) section for groff.
94−escapeCode :: String -> String
95−escapeCode = intercalate "\n" . map escapeLine . lines
100+escapeCode :: Bool -> String -> String
101+escapeCode useAScii = intercalate "\n" . map escapeLine . lines
96102 where escapeCodeChar ' ' = "\\ "
97103 escapeCodeChar '\t' = "\\\t"
98− escapeCodeChar c = escapeChar c
104+ escapeCodeChar c = escapeChar useAScii c
99105 escapeLine codeline =
100106 case concatMap escapeCodeChar codeline of
101107 a@('.':_) -> "\\&" ++ a
102108 b -> b
103109
104−-- | Escape non-ASCII characters using groff \u[..] sequences.
105−groffEscape :: T.Text -> T.Text
106−groffEscape = T.concatMap toUchar
107− where toUchar c
108− | isAscii c = T.singleton c
109− | otherwise = T.pack $ printf "\\[u%04X]" (ord c)
110+characterCodeMap :: Map.Map Char String
111+characterCodeMap = Map.fromList characterCodes
110112
111113fontChange :: PandocMonad m => MS m Doc
112114fontChange = do
src/Text/Pandoc/Writers/Man.hs+6−6
@@ -33,6 +33,7 @@ Conversion of 'Pandoc' documents to groff man page format.
3333module Text.Pandoc.Writers.Man ( writeMan) where
3434import Prelude
3535import Control.Monad.State.Strict
36+import Data.Char (isAscii)
3637import Data.List (intersperse, stripPrefix)
3738import Data.Maybe (fromMaybe)
3839import Data.Text (Text)
@@ -93,8 +94,7 @@ pandocToMan opts (Pandoc meta blocks) = do
9394 $ defField "has-tables" hasTables
9495 $ defField "hyphenate" True
9596 $ defField "pandoc-version" pandocVersion metadata
96− (if writerPreferAscii opts then groffEscape else id) <$>
97− case writerTemplate opts of
97+ case writerTemplate opts of
9898 Nothing -> return main
9999 Just tpl -> renderTemplate' tpl context
100100
@@ -148,7 +148,7 @@ blockToMan _ (CodeBlock _ str) = return $
148148 text ".IP" $$
149149 text ".nf" $$
150150 text "\\f[C]" $$
151− text (escapeCode str) $$
151+ text (escapeCode True str) $$
152152 text "\\f[R]" $$
153153 text ".fi"
154154blockToMan opts (BlockQuote blocks) = do
@@ -296,10 +296,10 @@ inlineToMan opts (Quoted DoubleQuote lst) = do
296296inlineToMan opts (Cite _ lst) =
297297 inlineListToMan opts lst
298298inlineToMan _ (Code _ str) =
299− withFontFeature 'C' (return (text $ escapeCode str))
299+ withFontFeature 'C' (return (text $ escapeCode True str))
300300inlineToMan _ (Str str@('.':_)) =
301− return $ afterBreak "\\&" <> text (escapeString str)
302−inlineToMan _ (Str str) = return $ text $ escapeString str
301+ return $ afterBreak "\\&" <> text (escapeString True str)
302+inlineToMan _ (Str str) = return $ text $ escapeString True str
303303inlineToMan opts (Math InlineMath str) =
304304 lift (texMathToInlines InlineMath str) >>= inlineListToMan opts
305305inlineToMan opts (Math DisplayMath str) = do
src/Text/Pandoc/Writers/Ms.hs+28−24
@@ -69,6 +69,9 @@ writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m Text
6969writeMs opts document =
7070 evalStateT (pandocToMs opts document) defaultWriterState
7171
72+escString :: WriterOptions -> String -> String
73+escString opts = escapeString (writerPreferAscii opts)
74+
7275-- | Return groff ms representation of document.
7376pandocToMs :: PandocMonad m => WriterOptions -> Pandoc -> MS m Text
7477pandocToMs opts (Pandoc meta blocks) = do
@@ -84,8 +87,8 @@ pandocToMs opts (Pandoc meta blocks) = do
8487 body <- blockListToMs opts blocks
8588 let main = render' body
8689 hasInlineMath <- gets stHasInlineMath
87− let titleMeta = (escapeString . stringify) $ docTitle meta
88− let authorsMeta = map (escapeString . stringify) $ docAuthors meta
90+ let titleMeta = (escString opts . stringify) $ docTitle meta
91+ let authorsMeta = map (escString opts . stringify) $ docAuthors meta
8992 hasHighlighting <- gets stHighlighting
9093 let highlightingMacros = if hasHighlighting
9194 then case writerHighlightStyle opts of
@@ -101,8 +104,7 @@ pandocToMs opts (Pandoc meta blocks) = do
101104 $ defField "title-meta" titleMeta
102105 $ defField "author-meta" (intercalate "; " authorsMeta)
103106 $ defField "highlighting-macros" highlightingMacros metadata
104− (if writerPreferAscii opts then groffEscape else id) <$>
105− case writerTemplate opts of
107+ case writerTemplate opts of
106108 Nothing -> return main
107109 Just tpl -> renderTemplate' tpl context
108110
@@ -112,18 +114,18 @@ escapeUri = escapeURIString (\c -> c /= '@' && isAllowedInURI c)
112114-- | Escape | character, used to mark inline math, inside math.
113115escapeBar :: String -> String
114116escapeBar = concatMap go
115− where go '|' = "\\[u007C]"
117+ where go '|' = "\\[ba]"
116118 go c = [c]
117119
118−toSmallCaps :: String -> String
119−toSmallCaps [] = []
120−toSmallCaps (c:cs)
120+toSmallCaps :: WriterOptions -> String -> String
121+toSmallCaps _ [] = []
122+toSmallCaps opts (c:cs)
121123 | isLower c = let (lowers,rest) = span isLower (c:cs)
122− in "\\s-2" ++ escapeString (map toUpper lowers) ++
123− "\\s0" ++ toSmallCaps rest
124+ in "\\s-2" ++ escString opts (map toUpper lowers) ++
125+ "\\s0" ++ toSmallCaps opts rest
124126 | isUpper c = let (uppers,rest) = span isUpper (c:cs)
125− in escapeString uppers ++ toSmallCaps rest
126− | otherwise = escapeChar c ++ toSmallCaps cs
127+ in escString opts uppers ++ toSmallCaps opts rest
128+ | otherwise = escapeChar (writerPreferAscii opts) c ++ toSmallCaps opts cs
127129
128130-- We split inline lists into sentences, and print one sentence per
129131-- line. groff/troff treats the line-ending period differently.
@@ -160,7 +162,7 @@ blockToMs opts (Para [Image attr alt (src,_tit)])
160162 _ -> empty
161163 capt <- inlineListToMs' opts alt
162164 return $ nowrap (text ".PSPIC -C " <>
163− doubleQuotes (text (escapeString src)) <>
165+ doubleQuotes (text (escString opts src)) <>
164166 sizeAttrs) $$
165167 text ".ce 1000" $$
166168 capt $$
@@ -198,7 +200,7 @@ blockToMs opts (Header level (ident,classes,_) inlines) = do
198200 (if null secnum
199201 then ""
200202 else " ") ++
201− escapeString (stringify inlines))
203+ escString opts (stringify inlines))
202204 let backlink = nowrap (text ".pdfhref L -D " <>
203205 doubleQuotes (text (toAscii ident)) <> space <> text "\\") <> cr <>
204206 text " -- "
@@ -400,14 +402,14 @@ inlineToMs opts (Cite _ lst) =
400402inlineToMs opts (Code attr str) = do
401403 hlCode <- highlightCode opts attr str
402404 withFontFeature 'C' (return hlCode)
403−inlineToMs _ (Str str) = do
405+inlineToMs opts (Str str) = do
404406 let shim = case str of
405407 '.':_ -> afterBreak "\\&"
406408 _ -> empty
407409 smallcaps <- gets stSmallCaps
408410 if smallcaps
409− then return $ shim <> text (toSmallCaps str)
410− else return $ shim <> text (escapeString str)
411+ then return $ shim <> text (toSmallCaps opts str)
412+ else return $ shim <> text (escString opts str)
411413inlineToMs opts (Math InlineMath str) = do
412414 modify $ \st -> st{ stHasInlineMath = True }
413415 res <- convertMath writeEqn InlineMath str
@@ -449,9 +451,10 @@ inlineToMs opts (Link _ txt (src, _)) = do
449451 doubleQuotes (text (escapeUri src)) <> text " -A " <>
450452 doubleQuotes (text "\\c") <> space <> text "\\") <> cr <>
451453 text " -- " <> doubleQuotes (nowrap contents) <> cr <> text "\\&"
452−inlineToMs _ (Image _ alternate (_, _)) =
454+inlineToMs opts (Image _ alternate (_, _)) =
453455 return $ char '[' <> text "IMAGE: " <>
454− text (escapeString (stringify alternate)) <> char ']'
456+ text (escString opts (stringify alternate))
457+ <> char ']'
455458inlineToMs _ (Note contents) = do
456459 modify $ \st -> st{ stNotes = contents : stNotes st }
457460 return $ text "\\**"
@@ -531,20 +534,21 @@ toMacro sty toktype =
531534 -- lnColor = lineNumberColor sty
532535 -- lnBkgColor = lineNumberBackgroundColor sty
533536
534−msFormatter :: FormatOptions -> [SourceLine] -> Doc
535−msFormatter _fmtopts =
537+msFormatter :: WriterOptions -> FormatOptions -> [SourceLine] -> Doc
538+msFormatter opts _fmtopts =
536539 vcat . map fmtLine
537540 where fmtLine = hcat . map fmtToken
538541 fmtToken (toktype, tok) = text "\\*" <>
539542 brackets (text (show toktype) <> text " \""
540− <> text (escapeCode (T.unpack tok)) <> text "\"")
543+ <> text (escapeCode (writerPreferAscii opts)
544+ (T.unpack tok)) <> text "\"")
541545
542546highlightCode :: PandocMonad m => WriterOptions -> Attr -> String -> MS m Doc
543547highlightCode opts attr str =
544− case highlight (writerSyntaxMap opts) msFormatter attr str of
548+ case highlight (writerSyntaxMap opts) (msFormatter opts) attr str of
545549 Left msg -> do
546550 unless (null msg) $ report $ CouldNotHighlight msg
547− return $ text (escapeCode str)
551+ return $ text (escapeCode (writerPreferAscii opts) str)
548552 Right h -> do
549553 modify (\st -> st{ stHighlighting = True })
550554 return h
test/command/4550.md+1−1
@@ -3,5 +3,5 @@
33A ‘simple’ example
44^D
55.LP
6−A \[oq]simple\[cq] example
6+A ‘simple’ example
77```
test/command/ascii.md+2−2
@@ -17,7 +17,7 @@ pandoc -t man --ascii
1717äéıå
1818^D
1919.PP
20−\[u00E4]\[u00E9]\[u0131]\[u00E5]
20+\[:a]\['e]\[.i]\[oa]
2121```
2222
2323```
@@ -25,7 +25,7 @@ pandoc -t ms --ascii
2525äéıå
2626^D
2727.LP
28−\[u00E4]\[u00E9]\[u0131]\[u00E5]
28+\[:a]\['e]\[.i]\[oa]
2929```
3030
3131```
test/tables.ms+4−4
@@ -135,7 +135,7 @@ T}
135135.LP
136136Multiline table with caption:
137137.PP
138−Here\[cq]s the caption. It may span multiple lines.
138+Here’s the caption. It may span multiple lines.
139139.TS
140140delim(@@) tab( );
141141cw(10.5n) lw(9.6n) rw(11.4n) lw(24.5n).
@@ -165,7 +165,7 @@ row
165165T} T{
1661665.0
167167T} T{
168−Here\[cq]s another one.
168+Here’s another one.
169169Note the blank line between rows.
170170T}
171171.TE
@@ -201,7 +201,7 @@ row
201201T} T{
2022025.0
203203T} T{
204−Here\[cq]s another one.
204+Here’s another one.
205205Note the blank line between rows.
206206T}
207207.TE
@@ -261,7 +261,7 @@ row
261261T} T{
2622625.0
263263T} T{
264−Here\[cq]s another one.
264+Here’s another one.
265265Note the blank line between rows.
266266T}
267267.TE
test/writer.man+14−14
@@ -104,7 +104,7 @@ And:
104104\f[C]
105105\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
106106
107−These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{
107+These\ should\ not\ be\ escaped:\ \ \[rs]$\ \[rs]\[rs]\ \[rs]>\ \[rs][\ \[rs]{
108108\f[R]
109109.fi
110110.PP
@@ -525,7 +525,7 @@ So is \f[B]\f[BI]this\f[B]\f[R] word.
525525.PP
526526So is \f[B]\f[BI]this\f[B]\f[R] word.
527527.PP
528−This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\\\f[R], \f[C]\\$\f[R],
528+This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\[rs]\f[R], \f[C]\[rs]$\f[R],
529529\f[C]<html>\f[R].
530530.PP
531531[STRIKEOUT:This is \f[I]strikeout\f[R].]
@@ -563,11 +563,11 @@ Ellipses\&...and\&...and\&....
563563.SH LaTeX
564564.IP \[bu] 2
565565.IP \[bu] 2
566−2 + 2 = 4
566+2\[u2005]+\[u2005]2\[u2004]=\[u2004]4
567567.IP \[bu] 2
568−\f[I]x\f[R] ∈ \f[I]y\f[R]
568+\f[I]x\f[R]\[u2004]\[mo]\[u2004]\f[I]y\f[R]
569569.IP \[bu] 2
570−\f[I]α\f[R] ∧ \f[I]ω\f[R]
570+\f[I]\[*a]\f[R]\[u2005]\[AN]\[u2005]\f[I]\[*w]\f[R]
571571.IP \[bu] 2
572572223
573573.IP \[bu] 2
@@ -575,11 +575,11 @@ Ellipses\&...and\&...and\&....
575575.IP \[bu] 2
576576Here\[cq]s some display math:
577577.RS
578−$$\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}$$
578+$$\[rs]frac{d}{dx}f(x)=\[rs]lim_{h\[rs]to 0}\[rs]frac{f(x+h)-f(x)}{h}$$
579579.RE
580580.IP \[bu] 2
581581Here\[cq]s one that has a line break in it:
582−\f[I]α\f[R] + \f[I]ω\f[R] × \f[I]x\f[R]^2^.
582+\f[I]\[*a]\f[R]\[u2005]+\[u2005]\f[I]\[*w]\f[R]\[u2005]\[tmu]\[u2005]\f[I]x\f[R]^2^.
583583.PP
584584These shouldn\[cq]t be math:
585585.IP \[bu] 2
@@ -600,15 +600,15 @@ Here\[cq]s a LaTeX table:
600600.PP
601601Here is some unicode:
602602.IP \[bu] 2
603−I hat: Î
603+I hat: \[^I]
604604.IP \[bu] 2
605−o umlaut: ö
605+o umlaut: \[:o]
606606.IP \[bu] 2
607−section: §
607+section: \[sc]
608608.IP \[bu] 2
609−set membership: ∈
609+set membership: \[mo]
610610.IP \[bu] 2
611−copyright: ©
611+copyright: \[co]
612612.PP
613613AT&T has an ampersand in their name.
614614.PP
@@ -620,9 +620,9 @@ This & that.
620620.PP
6216216 > 5.
622622.PP
623−Backslash: \\
623+Backslash: \[rs]
624624.PP
625−Backtick: \`
625+Backtick: \[ga]
626626.PP
627627Asterisk: *
628628.PP
test/writer.ms+23−23
@@ -75,7 +75,7 @@ July 17, 2006
7575.1C
7676.LP
7777This is a set of tests for pandoc.
78−Most of them are adapted from John Gruber\[cq]s markdown test suite.
78+Most of them are adapted from John Gruber’s markdown test suite.
7979.HLINE
8080.SH 1
8181Headers
@@ -126,7 +126,7 @@ Paragraphs
126126.pdfhref O 1 "Paragraphs"
127127.pdfhref M "paragraphs"
128128.LP
129−Here\[cq]s a regular paragraph.
129+Here’s a regular paragraph.
130130.PP
131131In Markdown 1.0.0 and earlier.
132132Version 8.
@@ -134,7 +134,7 @@ This line turns into a list item.
134134Because a hard-wrapped line in the middle of a paragraph looked like a list
135135item.
136136.PP
137−Here\[cq]s one with a bullet.
137+Here’s one with a bullet.
138138* criminey.
139139.PP
140140There should be a hard line break
@@ -210,7 +210,7 @@ And:
210210\f[C]
211211\ \ \ \ this\ code\ block\ is\ indented\ by\ two\ tabs
212212
213−These\ should\ not\ be\ escaped:\ \ \\$\ \\\\\ \\>\ \\[\ \\{
213+These\ should\ not\ be\ escaped:\ \ \[rs]$\ \[rs]\[rs]\ \[rs]>\ \[rs][\ \[rs]{
214214\f[]
215215.fi
216216.HLINE
@@ -314,7 +314,7 @@ Item 1, graf one.
314314.PP
315315Item 1.
316316graf two.
317−The quick brown fox jumped over the lazy dog\[cq]s back.
317+The quick brown fox jumped over the lazy dog’s back.
318318.RE
319319.IP " 2." 4
320320Item 2.
@@ -335,7 +335,7 @@ Tab
335335.RE
336336.RE
337337.LP
338−Here\[cq]s another:
338+Here’s another:
339339.IP " 1." 4
340340First
341341.IP " 2." 4
@@ -570,7 +570,7 @@ Interpreted markdown in a table:
570570This is \f[I]emphasized\f[R]
571571And this is \f[B]strong\f[R]
572572.PP
573−Here\[cq]s a simple block:
573+Here’s a simple block:
574574.LP
575575foo
576576.LP
@@ -617,7 +617,7 @@ Code:
617617\f[]
618618.fi
619619.LP
620−Hr\[cq]s:
620+Hr’s:
621621.HLINE
622622.SH 1
623623Inline Markup
@@ -641,7 +641,7 @@ So is \f[B]\f[BI]this\f[B]\f[R] word.
641641.PP
642642So is \f[B]\f[BI]this\f[B]\f[R] word.
643643.PP
644−This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\\\f[R], \f[C]\\$\f[R],
644+This is code: \f[C]>\f[R], \f[C]$\f[R], \f[C]\[rs]\f[R], \f[C]\[rs]$\f[R],
645645\f[C]<html>\f[R].
646646.PP
647647\m[strikecolor]This is \f[I]strikeout\f[R].\m[]
@@ -666,16 +666,16 @@ Smart quotes, ellipses, dashes
666666`Oak,' `elm,' and `beech' are names of trees.
667667So is `pine.'
668668.PP
669−`He said, \[lq]I want to go.\[rq]' Were you alive in the 70\[cq]s?
669+`He said, \[lq]I want to go.\[rq]' Were you alive in the 70’s?
670670.PP
671671Here is some quoted `\f[C]code\f[R]' and a \[lq]\c
672672.pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
673673 -- "quoted link"
674674\&\[rq].
675675.PP
676−Some dashes: one\[em]two \[em] three\[em]four \[em] five.
676+Some dashes: one—two — three—four — five.
677677.PP
678−Dashes between numbers: 5\[en]7, 255\[en]66, 1987\[en]1999.
678+Dashes between numbers: 5–7, 255–66, 1987–1999.
679679.PP
680680Ellipses\&...and\&...and\&....
681681.HLINE
@@ -695,14 +695,14 @@ LaTeX
695695.IP \[bu] 3
696696@p@-Tree
697697.IP \[bu] 3
698−Here\[cq]s some display math:
698+Here’s some display math:
699699.EQ
700700d over {d x} f ( x ) = lim sub {h -> 0} {f ( x + h ) \[u2212] f ( x )} over h
701701.EN
702702.IP \[bu] 3
703−Here\[cq]s one that has a line break in it: @alpha + omega times x sup 2@.
703+Here’s one that has a line break in it: @alpha + omega times x sup 2@.
704704.LP
705−These shouldn\[cq]t be math:
705+These shouldn’t be math:
706706.IP \[bu] 3
707707To get the famous equation, write \f[C]$e\ =\ mc\[ha]2$\f[R].
708708.IP \[bu] 3
@@ -714,7 +714,7 @@ Shoes ($20) and socks ($5).
714714.IP \[bu] 3
715715Escaped \f[C]$\f[R]: $73 \f[I]this should be emphasized\f[R] 23$.
716716.LP
717−Here\[cq]s a LaTeX table:
717+Here’s a LaTeX table:
718718.HLINE
719719.SH 1
720720Special Characters
@@ -743,9 +743,9 @@ This & that.
743743.PP
7447446 > 5.
745745.PP
746−Backslash: \\
746+Backslash: \[rs]
747747.PP
748−Backtick: \`
748+Backtick: \[ga]
749749.PP
750750Asterisk: *
751751.PP
@@ -885,22 +885,22 @@ With ampersands
885885.pdfhref O 2 "With ampersands"
886886.pdfhref M "with-ampersands"
887887.LP
888−Here\[cq]s a \c
888+Here’s a \c
889889.pdfhref W -D "http://example.com/?foo=1&bar=2" -A "\c" \
890890 -- "link with an ampersand in the URL"
891891\&.
892892.PP
893−Here\[cq]s a link with an amersand in the link text: \c
893+Here’s a link with an amersand in the link text: \c
894894.pdfhref W -D "http://att.com/" -A "\c" \
895895 -- "AT&T"
896896\&.
897897.PP
898−Here\[cq]s an \c
898+Here’s an \c
899899.pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
900900 -- "inline link"
901901\&.
902902.PP
903−Here\[cq]s an \c
903+Here’s an \c
904904.pdfhref W -D "/script?foo=1&bar=2" -A "\c" \
905905 -- "inline link in pointy braces"
906906\&.
@@ -967,7 +967,7 @@ It need not be placed at the end of the document.
967967.FE
968968and another.\**
969969.FS
970−Here\[cq]s the long note.
970+Here’s the long note.
971971This one contains multiple blocks.
972972.PP
973973Subsequent blocks are indented to show that they belong to the footnote (as