Respectable-abbreviations macro
up vote
7
down vote
favorite
How might one write a macro that makes slovenly abbreviations respectable?
documentclass{article}
% newcommandabr{...}
begin{document}
I've seen it in the abr{OED}.
end{document}
What I mean is that OED
should be rendered as O.,E.,D.
.
As Mico points out, there should never be two contiguous points. I
suppose one might use @ifnextchar.
to prevent that.
macros
add a comment |
up vote
7
down vote
favorite
How might one write a macro that makes slovenly abbreviations respectable?
documentclass{article}
% newcommandabr{...}
begin{document}
I've seen it in the abr{OED}.
end{document}
What I mean is that OED
should be rendered as O.,E.,D.
.
As Mico points out, there should never be two contiguous points. I
suppose one might use @ifnextchar.
to prevent that.
macros
Are you sure that you want two.
punctuation marks after the (non-slovenly) version ofOED
?
– Mico
Nov 8 at 16:41
1
@Mico, I'm sure I don't; edited.
– Toothrot
Nov 8 at 19:42
1
Note however that the norm is that abbreviations should be typeset without any dots. I don't have the reference to the norm right now, but I'll post it later on.
– Massimo Ortolano
Nov 9 at 7:44
add a comment |
up vote
7
down vote
favorite
up vote
7
down vote
favorite
How might one write a macro that makes slovenly abbreviations respectable?
documentclass{article}
% newcommandabr{...}
begin{document}
I've seen it in the abr{OED}.
end{document}
What I mean is that OED
should be rendered as O.,E.,D.
.
As Mico points out, there should never be two contiguous points. I
suppose one might use @ifnextchar.
to prevent that.
macros
How might one write a macro that makes slovenly abbreviations respectable?
documentclass{article}
% newcommandabr{...}
begin{document}
I've seen it in the abr{OED}.
end{document}
What I mean is that OED
should be rendered as O.,E.,D.
.
As Mico points out, there should never be two contiguous points. I
suppose one might use @ifnextchar.
to prevent that.
macros
macros
edited Nov 8 at 19:48
asked Nov 8 at 12:36
Toothrot
1,359417
1,359417
Are you sure that you want two.
punctuation marks after the (non-slovenly) version ofOED
?
– Mico
Nov 8 at 16:41
1
@Mico, I'm sure I don't; edited.
– Toothrot
Nov 8 at 19:42
1
Note however that the norm is that abbreviations should be typeset without any dots. I don't have the reference to the norm right now, but I'll post it later on.
– Massimo Ortolano
Nov 9 at 7:44
add a comment |
Are you sure that you want two.
punctuation marks after the (non-slovenly) version ofOED
?
– Mico
Nov 8 at 16:41
1
@Mico, I'm sure I don't; edited.
– Toothrot
Nov 8 at 19:42
1
Note however that the norm is that abbreviations should be typeset without any dots. I don't have the reference to the norm right now, but I'll post it later on.
– Massimo Ortolano
Nov 9 at 7:44
Are you sure that you want two
.
punctuation marks after the (non-slovenly) version of OED
?– Mico
Nov 8 at 16:41
Are you sure that you want two
.
punctuation marks after the (non-slovenly) version of OED
?– Mico
Nov 8 at 16:41
1
1
@Mico, I'm sure I don't; edited.
– Toothrot
Nov 8 at 19:42
@Mico, I'm sure I don't; edited.
– Toothrot
Nov 8 at 19:42
1
1
Note however that the norm is that abbreviations should be typeset without any dots. I don't have the reference to the norm right now, but I'll post it later on.
– Massimo Ortolano
Nov 9 at 7:44
Note however that the norm is that abbreviations should be typeset without any dots. I don't have the reference to the norm right now, but I'll post it later on.
– Massimo Ortolano
Nov 9 at 7:44
add a comment |
6 Answers
6
active
oldest
votes
up vote
7
down vote
All in all the same as the answer by Steven B. Segletes, but expandable. Also almost everything as contents should be fine (except the really unlikely endabr@
).
documentclass{article}
makeatletter
newcommandabr[1]
{%
abr@#1endabr@
}
defabr@#1#2endabr@
{%
#1.%
ifrelaxdetokenize{#2}relax
@%
expandafter@gobble
else
,%
expandafter@firstofone
fi
{abr@#2endabr@}%
}
makeatother
begin{document}
Single letter:
abr{eg}
Multi letter:
abr{{th}e}
end{document}
1
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
@StevenB.Segletesdef
is not expandable.
– Skillmon
Nov 8 at 13:00
Got it. I meant to say, mine can be placed in anedef
. But you are right, the contents of theedef
are not the final expansion.
– Steven B. Segletes
Nov 8 at 13:01
@StevenB.Segletes It can't be placed inside anedef
as theedef
would try to expandnext
before it gets defined.
– Skillmon
Nov 8 at 13:02
1
@StevenB.Segletes no. Just tryedeftmp{abr{OED}}
right after the definition ofabr
andabraux
in your MWE. It'll throw an error.
– Skillmon
Nov 8 at 13:05
|
show 2 more comments
up vote
6
down vote
Here is the simplest form of my original approach. It can be placed in an edef
. Its only drawback is that it can blow the stack if the argument is too long (maybe 256 characters??)
documentclass{article}
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{#1.ifxrelax#2relax@else,abraux#2relaxfi}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
end{document}
If that really were an issue, here is an alternative that doesn't have that problem.
There seems to be a misunderstanding that this definition of abr
cannot be placed into an edef
. It can. Naturally, the expansion is not necessarily pretty, but it will yield the proper typesetting. The only proviso is that @MyOwnMacro
is not used elsewhere in your document.
documentclass{article}
usepackage[T1]{fontenc}
makeatletter
let@MyOwnMacrorelax
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{%
#1.ifxrelax#2relaxdef@MyOwnMacro{@}elsedef@MyOwnMacro{,abraux#2relax}fi%
@MyOwnMacro%
}
makeatother
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Can be edef'ed:
edeftmp{abr{OED}} detokenizeexpandafter{tmp}
expands to tmp
end{document}
1
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
1
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
It can't beedef
ed if it is used for the first time! It'll throw an error.
– Skillmon
Nov 8 at 13:55
@Skillmon OK,letnextrelax
fixes that.
– Steven B. Segletes
Nov 8 at 14:16
2
@StevenB.Segletes as soon as anything else usesnext
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.
– Skillmon
Nov 8 at 14:21
|
show 3 more comments
up vote
6
down vote
Here's a LuaLaTeX-based solution.
Cases such as
abr{OED}
orabr{IMF}
work just as expected. If the acronym contains both uppercase and lowercase letters, dots are inserted only before the uppercase letters in the interior of the acronym. E.g.,abr{MSc}
generatesM.,Sc.
, andabr{PhD}
generatesPh.,D.
.It can handle mixed-case acronyms such as "PhD" directly -- no need to write
abr{{Ph}D}
.If a "slovenly abbreviation" ends a sentence, one should place the "." punctuation mark inside the argument of
abr
. The code takes care to insert a@
"space factor* directive before the final.
character. This, in turn, informs LaTeX that that.
character should be treated as ending a sentence.The code returns nothing if the argument of
abr
is either empty or expands to return nothing. E.g.,defttt{} /abr{ttt}/
returns//
. If the code encounters non-letter characters -- say,(
and)
-- no periods are inserted before or after them.The code is expandable in the sense that
abr
can be included in the argument of anedef
directive.
documentclass{article}
usepackage{luacode} % for 'luacode' environment
%% Lua-side code:
begin{luacode}
function abr ( s )
n = string.len ( s )
-- Do nothing unless "s" is non-empty.
if n>0 then
s_mod = "" -- initialize the string
-- Process the first n-1 characters in "s"
for i=1, n-1 do
s12 = string.sub ( s , i, i+1 )
s1 = string.sub ( s12, 1, 1 )
if string.match ( s12 , "%a%u" ) then
s_mod = s_mod .. s1 .. ".\,"
else
s_mod = s_mod .. s1
end
end
-- Process the final character in "s"
s_n = string.sub ( s , n)
if string.match (s_n, "%.") then -- "." char.
s_mod = s_mod .. "\@."
elseif string.match (s_n, "%l") then -- lowercase letter
s_mod = s_mod .. s_n .. ".\hbox{}"
elseif string.match (s_n, "%u") then -- uppercase letter
s_mod = s_mod .. s_n .. "."
else -- Any other character:
s_mod = s_mod .. s_n -- don't add anything after 's_n'
end
-- Print the modified string
tex.sprint ( s_mod )
end
end
end{luacode}
%% LaTeX-side code: macro that calls the Lua function
newcommandabr[2]{directlua{abr("#1")}}
begin{document}
abr{OED}, abr{PhD}, abr{DPhil}, abr{MSc}, abr{()}
smallskip
% Two calls to "abr" with an empty argument (upon expansion):
.abr{}. quad
defttt{} .abr{ttt}.
bigskip
edeftmp{abr{MA}} detokenizeexpandafter{tmp}
edeftmp{abr{MA.}} detokenizeexpandafter{tmp}
expands to: tmp
smallskip
edeftmp{abr{MSc}} detokenizeexpandafter{tmp}
edeftmp{abr{MSc.}} detokenizeexpandafter{tmp}
expands to: tmp
bigskip
Some tests of spacing after punctuation marks:
smallskip
a abr{PhD} candidate --- good
a Ph.,D. candidate --- just to verify
smallskip
an abr{MSc} candidate --- good
an M.,Sc. candidate --- just to verify
smallskip
She has a abr{PhD.} So do I. --- good
She has a Ph.,D@. So do I. --- just to verify
smallskip
He has an abr{MSc.} So do I. --- good
He has an M.,Sc. So do I. --- just to verify
smallskip
Does he have an abr{MSc.}? Really?! --- good
Does he have an M.,Sc.? Really?! --- just to verify
end{document}
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writesI like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after someabr{...}
directive is to include the period in the argument ofabr
. I've come up with an update to the code that allowsabbr{MSc}
andabr{MSc.}
to be typeset differently. I'll post the updated code shortly.
– Mico
Nov 8 at 22:49
How about@ifnextchar.{spacefactor3000@gobble}
or something like that?
– Toothrot
Nov 8 at 22:55
@Toothrot - Using@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...
– Mico
Nov 9 at 6:11
add a comment |
up vote
5
down vote
Let TeX do the recursion:
documentclass{article}
usepackage{xparse}
usepackage{etoolbox}
robustify{,} % just in order it doesn't expand in edef
ExplSyntaxOn
NewExpandableDocumentCommand{abr}{m}
{
tl_map_function:fN { tl_range:nnn { #1 } { 1 } { -2 } } __toothrot_abr:n
tl_range:nnn { #1 } { -1 } { -1 } .
}
cs_generate_variant:Nn tl_map_function:nN { f }
cs_new:Nn __toothrot_abr:n { #1., }
ExplSyntaxOff
begin{document}
abr{OED}
abr{{Ph}D}
edeftest{abr{OED}}
texttt{meaningtest}
edeftest{abr{}}
texttt{meaningtest}
end{document}
If a part of the argument is braced, it is considered as a single item.
One might check whether the argument is empty in order to print nothing at all, but it doesn't seem so important a feature.
With tl_range:nnn { #1 } { 1 } { -2 }
we extract all items but the last; tl_range:nnn { #1 } { -1 } { -1 }
extracts the last item.
add a comment |
up vote
5
down vote
documentclass{article}
usepackage{xinttools}
newcommandabr[1]{xintListWithSep{.,}{#1}.}
begin{document}
I've seen it in the abr{OED}.
I got my abr{{Ph}D}.
end{document}
Updated (à la Mico, but without LuaLaTeX)
The syntax here is to use abr{PhD.}
for example at end of a sentence, and abr{PhD}
if not at end of a sentence.
documentclass{article}
usepackage{xinttools}
makeatletter
newcommandabr[1]
{expandafter@gobbletworomannumeral0xintapplyunbracedabr@aux{#1}.@}
defabr@sep{.,}
defabr@aux#1{if.#1expandafterabr@end
else
if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterexpandafterexpandafterabr@sep
fi
fi#1}%
defabr@end.{ abr@@end}
defabr@@end.@{@.}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
just insert a dot in the verb|abr| argument: abr{OED.} It ended a
sentence and in non-French spacing mode, TeX inserted the extra
space.
texttt{We can see it better with monospace font: abr{OED.} See?}
I got my abr{PhD} and even my abr{PhilD}, leniency ruled
in those days.
texttt{The dots are added in a smart way: abr{AaaaBbbbCccc.} But it is
assumed that the first letter is abr{Uppercased.} That's it.}
texttt{Notice that neitger abr{Aaaa} nor abr{AaA} trigger an end of
sentence spacing after the dot, which is abr{Good.} Isn't it?}
end{document}
Again updated, for automatic end of sentence dot detection after abbreviation
Here an end of sentence dot will be detected automatically.
Of course we can't use @ifnextchar
for that, as it swallows spaces.
I added some comments about expandability, which seems to have drawn great attention in other answers :)
.
documentclass{article}
usepackage{shortvrb}MakeShortVerb{|}
usepackage{xinttools}
makeatletter
protecteddefabrsep{.,}% maybe redefined even after edeffoo{abr{DPhil}}...
protecteddefabrend{futurelet@let@tokenabr@end}
defabr@end{ifx.@let@token@else.@fi}
newcommandabr[1]
{expandafter@gobbleromannumeral0xintapplyunbracedabr@aux{#1}abrend}
defabr@aux#1{if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterabr@sep
fi#1}%
defabr@sep{ abrsep}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
it will detect it automatically: abr{OED}. There was no double dot.
Besides, TeX applied its end of sentence extra space.
texttt{We can see it better with monospace font: abr{OED}. See?}
texttt{We can see it better with monospace font: abr{OED}, See?}
I got a abr{MSc}, a abr{PhD} and even a abr{DPhil}. Leniency ruled
in those days.
{The abbreviation dots are added in a smart way, after the last
lowercase letter following an uppercase letter:
abr{AaaaBbbbCccc}. But it is emph{assumed} that the first letter is
abr{Uppercased}. That's it.}
texttt{Notice that neither abr{DPhil} nor abr{PhilD} get TeX to
consider the inserted final dot as signaling an end of
sentence spacing after the dot, which is abr{Good}. Isn't it?}
About expandability, the correct way for LaTeX2e's users would be to use
|protected@edef|, not a naked |edef|; although nowadays some
LaTeX2e users have heard about |edef|, they might not know
about |protected@edef|, which requires a cumbersome extra
|makeatletter| for its usage. Anyway, none of that is described in
textsc{Lamport} book, so I wonder if LaTeX2e users are really
emph{allowed} into using |edef| to start with.
But as it seems they know about |edef|, we as macro programmers need
better to use the e-TeX's |protected| prefix and not the LaTeX2e
|DeclareRobustCommand|, because users will not do |protected@edef|.
This is what I have done here for a macro |abrsep| (why haven't we all
used |abbr| by the way?) which is deliberately |protected|,
allowing it to be redefined at location of use, long after some macro
will have been defined via |edeffoo{abr{ABCDEFGH}}|.
edeffoo{abr{ABCDEFGH}}texttt{stringfoo is meaningfoo}
edeffoo{abr{AaaBccCcc}}texttt{stringfoo is meaningfoo}
The |abrend| is also |protected|, anyway as its expansion will be
context dependent (it detects if a dot follows), it had to not expand
in the |edef|.
end{document}
Notice that my proposals v2 and v3 will work only with ascii uppercase letters, no diacritics.
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
1
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX@ifnextchar
which swallows spaces.
– jfbu
Nov 9 at 8:21
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for anedef
and anyhow the tokens of the input are subjected to full-first expansion viaifnum
test etc...
– jfbu
Nov 9 at 9:47
add a comment |
up vote
4
down vote
documentclass{article}
newcommandabr[1]{abraux#1..}
defabraux#1#2#3{%
#1%
ifnum`#2>91relax% we have a lowercase letter following
defnext{abraux#2#3}%
else
.ifx.#2defnext{@}else,defnext{abraux#2#3}fi
fi
next
}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Here is abr{XOOED} abbreviation.
abr{MSc}
abr{DPhil}
end{document}
Can your code be extended to handle the lazy/slovenly punctuation ofMSc
(correct:M.,Sc.
) andDPhil
(correct:D.,Phil.
)?
– Mico
Nov 9 at 6:20
1
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
add a comment |
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
7
down vote
All in all the same as the answer by Steven B. Segletes, but expandable. Also almost everything as contents should be fine (except the really unlikely endabr@
).
documentclass{article}
makeatletter
newcommandabr[1]
{%
abr@#1endabr@
}
defabr@#1#2endabr@
{%
#1.%
ifrelaxdetokenize{#2}relax
@%
expandafter@gobble
else
,%
expandafter@firstofone
fi
{abr@#2endabr@}%
}
makeatother
begin{document}
Single letter:
abr{eg}
Multi letter:
abr{{th}e}
end{document}
1
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
@StevenB.Segletesdef
is not expandable.
– Skillmon
Nov 8 at 13:00
Got it. I meant to say, mine can be placed in anedef
. But you are right, the contents of theedef
are not the final expansion.
– Steven B. Segletes
Nov 8 at 13:01
@StevenB.Segletes It can't be placed inside anedef
as theedef
would try to expandnext
before it gets defined.
– Skillmon
Nov 8 at 13:02
1
@StevenB.Segletes no. Just tryedeftmp{abr{OED}}
right after the definition ofabr
andabraux
in your MWE. It'll throw an error.
– Skillmon
Nov 8 at 13:05
|
show 2 more comments
up vote
7
down vote
All in all the same as the answer by Steven B. Segletes, but expandable. Also almost everything as contents should be fine (except the really unlikely endabr@
).
documentclass{article}
makeatletter
newcommandabr[1]
{%
abr@#1endabr@
}
defabr@#1#2endabr@
{%
#1.%
ifrelaxdetokenize{#2}relax
@%
expandafter@gobble
else
,%
expandafter@firstofone
fi
{abr@#2endabr@}%
}
makeatother
begin{document}
Single letter:
abr{eg}
Multi letter:
abr{{th}e}
end{document}
1
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
@StevenB.Segletesdef
is not expandable.
– Skillmon
Nov 8 at 13:00
Got it. I meant to say, mine can be placed in anedef
. But you are right, the contents of theedef
are not the final expansion.
– Steven B. Segletes
Nov 8 at 13:01
@StevenB.Segletes It can't be placed inside anedef
as theedef
would try to expandnext
before it gets defined.
– Skillmon
Nov 8 at 13:02
1
@StevenB.Segletes no. Just tryedeftmp{abr{OED}}
right after the definition ofabr
andabraux
in your MWE. It'll throw an error.
– Skillmon
Nov 8 at 13:05
|
show 2 more comments
up vote
7
down vote
up vote
7
down vote
All in all the same as the answer by Steven B. Segletes, but expandable. Also almost everything as contents should be fine (except the really unlikely endabr@
).
documentclass{article}
makeatletter
newcommandabr[1]
{%
abr@#1endabr@
}
defabr@#1#2endabr@
{%
#1.%
ifrelaxdetokenize{#2}relax
@%
expandafter@gobble
else
,%
expandafter@firstofone
fi
{abr@#2endabr@}%
}
makeatother
begin{document}
Single letter:
abr{eg}
Multi letter:
abr{{th}e}
end{document}
All in all the same as the answer by Steven B. Segletes, but expandable. Also almost everything as contents should be fine (except the really unlikely endabr@
).
documentclass{article}
makeatletter
newcommandabr[1]
{%
abr@#1endabr@
}
defabr@#1#2endabr@
{%
#1.%
ifrelaxdetokenize{#2}relax
@%
expandafter@gobble
else
,%
expandafter@firstofone
fi
{abr@#2endabr@}%
}
makeatother
begin{document}
Single letter:
abr{eg}
Multi letter:
abr{{th}e}
end{document}
answered Nov 8 at 12:57
Skillmon
20.2k11840
20.2k11840
1
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
@StevenB.Segletesdef
is not expandable.
– Skillmon
Nov 8 at 13:00
Got it. I meant to say, mine can be placed in anedef
. But you are right, the contents of theedef
are not the final expansion.
– Steven B. Segletes
Nov 8 at 13:01
@StevenB.Segletes It can't be placed inside anedef
as theedef
would try to expandnext
before it gets defined.
– Skillmon
Nov 8 at 13:02
1
@StevenB.Segletes no. Just tryedeftmp{abr{OED}}
right after the definition ofabr
andabraux
in your MWE. It'll throw an error.
– Skillmon
Nov 8 at 13:05
|
show 2 more comments
1
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
@StevenB.Segletesdef
is not expandable.
– Skillmon
Nov 8 at 13:00
Got it. I meant to say, mine can be placed in anedef
. But you are right, the contents of theedef
are not the final expansion.
– Steven B. Segletes
Nov 8 at 13:01
@StevenB.Segletes It can't be placed inside anedef
as theedef
would try to expandnext
before it gets defined.
– Skillmon
Nov 8 at 13:02
1
@StevenB.Segletes no. Just tryedeftmp{abr{OED}}
right after the definition ofabr
andabraux
in your MWE. It'll throw an error.
– Skillmon
Nov 8 at 13:05
1
1
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
I believe mine is fully expandable, as well.
– Steven B. Segletes
Nov 8 at 12:59
@StevenB.Segletes
def
is not expandable.– Skillmon
Nov 8 at 13:00
@StevenB.Segletes
def
is not expandable.– Skillmon
Nov 8 at 13:00
Got it. I meant to say, mine can be placed in an
edef
. But you are right, the contents of the edef
are not the final expansion.– Steven B. Segletes
Nov 8 at 13:01
Got it. I meant to say, mine can be placed in an
edef
. But you are right, the contents of the edef
are not the final expansion.– Steven B. Segletes
Nov 8 at 13:01
@StevenB.Segletes It can't be placed inside an
edef
as the edef
would try to expand next
before it gets defined.– Skillmon
Nov 8 at 13:02
@StevenB.Segletes It can't be placed inside an
edef
as the edef
would try to expand next
before it gets defined.– Skillmon
Nov 8 at 13:02
1
1
@StevenB.Segletes no. Just try
edeftmp{abr{OED}}
right after the definition of abr
and abraux
in your MWE. It'll throw an error.– Skillmon
Nov 8 at 13:05
@StevenB.Segletes no. Just try
edeftmp{abr{OED}}
right after the definition of abr
and abraux
in your MWE. It'll throw an error.– Skillmon
Nov 8 at 13:05
|
show 2 more comments
up vote
6
down vote
Here is the simplest form of my original approach. It can be placed in an edef
. Its only drawback is that it can blow the stack if the argument is too long (maybe 256 characters??)
documentclass{article}
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{#1.ifxrelax#2relax@else,abraux#2relaxfi}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
end{document}
If that really were an issue, here is an alternative that doesn't have that problem.
There seems to be a misunderstanding that this definition of abr
cannot be placed into an edef
. It can. Naturally, the expansion is not necessarily pretty, but it will yield the proper typesetting. The only proviso is that @MyOwnMacro
is not used elsewhere in your document.
documentclass{article}
usepackage[T1]{fontenc}
makeatletter
let@MyOwnMacrorelax
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{%
#1.ifxrelax#2relaxdef@MyOwnMacro{@}elsedef@MyOwnMacro{,abraux#2relax}fi%
@MyOwnMacro%
}
makeatother
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Can be edef'ed:
edeftmp{abr{OED}} detokenizeexpandafter{tmp}
expands to tmp
end{document}
1
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
1
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
It can't beedef
ed if it is used for the first time! It'll throw an error.
– Skillmon
Nov 8 at 13:55
@Skillmon OK,letnextrelax
fixes that.
– Steven B. Segletes
Nov 8 at 14:16
2
@StevenB.Segletes as soon as anything else usesnext
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.
– Skillmon
Nov 8 at 14:21
|
show 3 more comments
up vote
6
down vote
Here is the simplest form of my original approach. It can be placed in an edef
. Its only drawback is that it can blow the stack if the argument is too long (maybe 256 characters??)
documentclass{article}
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{#1.ifxrelax#2relax@else,abraux#2relaxfi}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
end{document}
If that really were an issue, here is an alternative that doesn't have that problem.
There seems to be a misunderstanding that this definition of abr
cannot be placed into an edef
. It can. Naturally, the expansion is not necessarily pretty, but it will yield the proper typesetting. The only proviso is that @MyOwnMacro
is not used elsewhere in your document.
documentclass{article}
usepackage[T1]{fontenc}
makeatletter
let@MyOwnMacrorelax
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{%
#1.ifxrelax#2relaxdef@MyOwnMacro{@}elsedef@MyOwnMacro{,abraux#2relax}fi%
@MyOwnMacro%
}
makeatother
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Can be edef'ed:
edeftmp{abr{OED}} detokenizeexpandafter{tmp}
expands to tmp
end{document}
1
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
1
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
It can't beedef
ed if it is used for the first time! It'll throw an error.
– Skillmon
Nov 8 at 13:55
@Skillmon OK,letnextrelax
fixes that.
– Steven B. Segletes
Nov 8 at 14:16
2
@StevenB.Segletes as soon as anything else usesnext
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.
– Skillmon
Nov 8 at 14:21
|
show 3 more comments
up vote
6
down vote
up vote
6
down vote
Here is the simplest form of my original approach. It can be placed in an edef
. Its only drawback is that it can blow the stack if the argument is too long (maybe 256 characters??)
documentclass{article}
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{#1.ifxrelax#2relax@else,abraux#2relaxfi}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
end{document}
If that really were an issue, here is an alternative that doesn't have that problem.
There seems to be a misunderstanding that this definition of abr
cannot be placed into an edef
. It can. Naturally, the expansion is not necessarily pretty, but it will yield the proper typesetting. The only proviso is that @MyOwnMacro
is not used elsewhere in your document.
documentclass{article}
usepackage[T1]{fontenc}
makeatletter
let@MyOwnMacrorelax
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{%
#1.ifxrelax#2relaxdef@MyOwnMacro{@}elsedef@MyOwnMacro{,abraux#2relax}fi%
@MyOwnMacro%
}
makeatother
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Can be edef'ed:
edeftmp{abr{OED}} detokenizeexpandafter{tmp}
expands to tmp
end{document}
Here is the simplest form of my original approach. It can be placed in an edef
. Its only drawback is that it can blow the stack if the argument is too long (maybe 256 characters??)
documentclass{article}
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{#1.ifxrelax#2relax@else,abraux#2relaxfi}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
end{document}
If that really were an issue, here is an alternative that doesn't have that problem.
There seems to be a misunderstanding that this definition of abr
cannot be placed into an edef
. It can. Naturally, the expansion is not necessarily pretty, but it will yield the proper typesetting. The only proviso is that @MyOwnMacro
is not used elsewhere in your document.
documentclass{article}
usepackage[T1]{fontenc}
makeatletter
let@MyOwnMacrorelax
newcommandabr[1]{abraux#1relaxrelax}
defabraux#1#2relax{%
#1.ifxrelax#2relaxdef@MyOwnMacro{@}elsedef@MyOwnMacro{,abraux#2relax}fi%
@MyOwnMacro%
}
makeatother
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Can be edef'ed:
edeftmp{abr{OED}} detokenizeexpandafter{tmp}
expands to tmp
end{document}
edited Nov 8 at 15:31
answered Nov 8 at 12:50
Steven B. Segletes
151k9189397
151k9189397
1
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
1
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
It can't beedef
ed if it is used for the first time! It'll throw an error.
– Skillmon
Nov 8 at 13:55
@Skillmon OK,letnextrelax
fixes that.
– Steven B. Segletes
Nov 8 at 14:16
2
@StevenB.Segletes as soon as anything else usesnext
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.
– Skillmon
Nov 8 at 14:21
|
show 3 more comments
1
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
1
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
It can't beedef
ed if it is used for the first time! It'll throw an error.
– Skillmon
Nov 8 at 13:55
@Skillmon OK,letnextrelax
fixes that.
– Steven B. Segletes
Nov 8 at 14:16
2
@StevenB.Segletes as soon as anything else usesnext
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.
– Skillmon
Nov 8 at 14:21
1
1
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
Cheers to you :-) for your good solution. I have removed my comment. Is it correct in English language?
– Sebastiano
Nov 8 at 12:51
1
1
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
@Sebastiano 5:5 (loud and clear). Excellent English. Saluti!
– Steven B. Segletes
Nov 8 at 12:58
It can't be
edef
ed if it is used for the first time! It'll throw an error.– Skillmon
Nov 8 at 13:55
It can't be
edef
ed if it is used for the first time! It'll throw an error.– Skillmon
Nov 8 at 13:55
@Skillmon OK,
letnextrelax
fixes that.– Steven B. Segletes
Nov 8 at 14:16
@Skillmon OK,
letnextrelax
fixes that.– Steven B. Segletes
Nov 8 at 14:16
2
2
@StevenB.Segletes as soon as anything else uses
next
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.– Skillmon
Nov 8 at 14:21
@StevenB.Segletes as soon as anything else uses
next
you'll get problems. In general your macro can't be fully expandable as long as it contains anything changing the definition of anything.– Skillmon
Nov 8 at 14:21
|
show 3 more comments
up vote
6
down vote
Here's a LuaLaTeX-based solution.
Cases such as
abr{OED}
orabr{IMF}
work just as expected. If the acronym contains both uppercase and lowercase letters, dots are inserted only before the uppercase letters in the interior of the acronym. E.g.,abr{MSc}
generatesM.,Sc.
, andabr{PhD}
generatesPh.,D.
.It can handle mixed-case acronyms such as "PhD" directly -- no need to write
abr{{Ph}D}
.If a "slovenly abbreviation" ends a sentence, one should place the "." punctuation mark inside the argument of
abr
. The code takes care to insert a@
"space factor* directive before the final.
character. This, in turn, informs LaTeX that that.
character should be treated as ending a sentence.The code returns nothing if the argument of
abr
is either empty or expands to return nothing. E.g.,defttt{} /abr{ttt}/
returns//
. If the code encounters non-letter characters -- say,(
and)
-- no periods are inserted before or after them.The code is expandable in the sense that
abr
can be included in the argument of anedef
directive.
documentclass{article}
usepackage{luacode} % for 'luacode' environment
%% Lua-side code:
begin{luacode}
function abr ( s )
n = string.len ( s )
-- Do nothing unless "s" is non-empty.
if n>0 then
s_mod = "" -- initialize the string
-- Process the first n-1 characters in "s"
for i=1, n-1 do
s12 = string.sub ( s , i, i+1 )
s1 = string.sub ( s12, 1, 1 )
if string.match ( s12 , "%a%u" ) then
s_mod = s_mod .. s1 .. ".\,"
else
s_mod = s_mod .. s1
end
end
-- Process the final character in "s"
s_n = string.sub ( s , n)
if string.match (s_n, "%.") then -- "." char.
s_mod = s_mod .. "\@."
elseif string.match (s_n, "%l") then -- lowercase letter
s_mod = s_mod .. s_n .. ".\hbox{}"
elseif string.match (s_n, "%u") then -- uppercase letter
s_mod = s_mod .. s_n .. "."
else -- Any other character:
s_mod = s_mod .. s_n -- don't add anything after 's_n'
end
-- Print the modified string
tex.sprint ( s_mod )
end
end
end{luacode}
%% LaTeX-side code: macro that calls the Lua function
newcommandabr[2]{directlua{abr("#1")}}
begin{document}
abr{OED}, abr{PhD}, abr{DPhil}, abr{MSc}, abr{()}
smallskip
% Two calls to "abr" with an empty argument (upon expansion):
.abr{}. quad
defttt{} .abr{ttt}.
bigskip
edeftmp{abr{MA}} detokenizeexpandafter{tmp}
edeftmp{abr{MA.}} detokenizeexpandafter{tmp}
expands to: tmp
smallskip
edeftmp{abr{MSc}} detokenizeexpandafter{tmp}
edeftmp{abr{MSc.}} detokenizeexpandafter{tmp}
expands to: tmp
bigskip
Some tests of spacing after punctuation marks:
smallskip
a abr{PhD} candidate --- good
a Ph.,D. candidate --- just to verify
smallskip
an abr{MSc} candidate --- good
an M.,Sc. candidate --- just to verify
smallskip
She has a abr{PhD.} So do I. --- good
She has a Ph.,D@. So do I. --- just to verify
smallskip
He has an abr{MSc.} So do I. --- good
He has an M.,Sc. So do I. --- just to verify
smallskip
Does he have an abr{MSc.}? Really?! --- good
Does he have an M.,Sc.? Really?! --- just to verify
end{document}
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writesI like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after someabr{...}
directive is to include the period in the argument ofabr
. I've come up with an update to the code that allowsabbr{MSc}
andabr{MSc.}
to be typeset differently. I'll post the updated code shortly.
– Mico
Nov 8 at 22:49
How about@ifnextchar.{spacefactor3000@gobble}
or something like that?
– Toothrot
Nov 8 at 22:55
@Toothrot - Using@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...
– Mico
Nov 9 at 6:11
add a comment |
up vote
6
down vote
Here's a LuaLaTeX-based solution.
Cases such as
abr{OED}
orabr{IMF}
work just as expected. If the acronym contains both uppercase and lowercase letters, dots are inserted only before the uppercase letters in the interior of the acronym. E.g.,abr{MSc}
generatesM.,Sc.
, andabr{PhD}
generatesPh.,D.
.It can handle mixed-case acronyms such as "PhD" directly -- no need to write
abr{{Ph}D}
.If a "slovenly abbreviation" ends a sentence, one should place the "." punctuation mark inside the argument of
abr
. The code takes care to insert a@
"space factor* directive before the final.
character. This, in turn, informs LaTeX that that.
character should be treated as ending a sentence.The code returns nothing if the argument of
abr
is either empty or expands to return nothing. E.g.,defttt{} /abr{ttt}/
returns//
. If the code encounters non-letter characters -- say,(
and)
-- no periods are inserted before or after them.The code is expandable in the sense that
abr
can be included in the argument of anedef
directive.
documentclass{article}
usepackage{luacode} % for 'luacode' environment
%% Lua-side code:
begin{luacode}
function abr ( s )
n = string.len ( s )
-- Do nothing unless "s" is non-empty.
if n>0 then
s_mod = "" -- initialize the string
-- Process the first n-1 characters in "s"
for i=1, n-1 do
s12 = string.sub ( s , i, i+1 )
s1 = string.sub ( s12, 1, 1 )
if string.match ( s12 , "%a%u" ) then
s_mod = s_mod .. s1 .. ".\,"
else
s_mod = s_mod .. s1
end
end
-- Process the final character in "s"
s_n = string.sub ( s , n)
if string.match (s_n, "%.") then -- "." char.
s_mod = s_mod .. "\@."
elseif string.match (s_n, "%l") then -- lowercase letter
s_mod = s_mod .. s_n .. ".\hbox{}"
elseif string.match (s_n, "%u") then -- uppercase letter
s_mod = s_mod .. s_n .. "."
else -- Any other character:
s_mod = s_mod .. s_n -- don't add anything after 's_n'
end
-- Print the modified string
tex.sprint ( s_mod )
end
end
end{luacode}
%% LaTeX-side code: macro that calls the Lua function
newcommandabr[2]{directlua{abr("#1")}}
begin{document}
abr{OED}, abr{PhD}, abr{DPhil}, abr{MSc}, abr{()}
smallskip
% Two calls to "abr" with an empty argument (upon expansion):
.abr{}. quad
defttt{} .abr{ttt}.
bigskip
edeftmp{abr{MA}} detokenizeexpandafter{tmp}
edeftmp{abr{MA.}} detokenizeexpandafter{tmp}
expands to: tmp
smallskip
edeftmp{abr{MSc}} detokenizeexpandafter{tmp}
edeftmp{abr{MSc.}} detokenizeexpandafter{tmp}
expands to: tmp
bigskip
Some tests of spacing after punctuation marks:
smallskip
a abr{PhD} candidate --- good
a Ph.,D. candidate --- just to verify
smallskip
an abr{MSc} candidate --- good
an M.,Sc. candidate --- just to verify
smallskip
She has a abr{PhD.} So do I. --- good
She has a Ph.,D@. So do I. --- just to verify
smallskip
He has an abr{MSc.} So do I. --- good
He has an M.,Sc. So do I. --- just to verify
smallskip
Does he have an abr{MSc.}? Really?! --- good
Does he have an M.,Sc.? Really?! --- just to verify
end{document}
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writesI like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after someabr{...}
directive is to include the period in the argument ofabr
. I've come up with an update to the code that allowsabbr{MSc}
andabr{MSc.}
to be typeset differently. I'll post the updated code shortly.
– Mico
Nov 8 at 22:49
How about@ifnextchar.{spacefactor3000@gobble}
or something like that?
– Toothrot
Nov 8 at 22:55
@Toothrot - Using@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...
– Mico
Nov 9 at 6:11
add a comment |
up vote
6
down vote
up vote
6
down vote
Here's a LuaLaTeX-based solution.
Cases such as
abr{OED}
orabr{IMF}
work just as expected. If the acronym contains both uppercase and lowercase letters, dots are inserted only before the uppercase letters in the interior of the acronym. E.g.,abr{MSc}
generatesM.,Sc.
, andabr{PhD}
generatesPh.,D.
.It can handle mixed-case acronyms such as "PhD" directly -- no need to write
abr{{Ph}D}
.If a "slovenly abbreviation" ends a sentence, one should place the "." punctuation mark inside the argument of
abr
. The code takes care to insert a@
"space factor* directive before the final.
character. This, in turn, informs LaTeX that that.
character should be treated as ending a sentence.The code returns nothing if the argument of
abr
is either empty or expands to return nothing. E.g.,defttt{} /abr{ttt}/
returns//
. If the code encounters non-letter characters -- say,(
and)
-- no periods are inserted before or after them.The code is expandable in the sense that
abr
can be included in the argument of anedef
directive.
documentclass{article}
usepackage{luacode} % for 'luacode' environment
%% Lua-side code:
begin{luacode}
function abr ( s )
n = string.len ( s )
-- Do nothing unless "s" is non-empty.
if n>0 then
s_mod = "" -- initialize the string
-- Process the first n-1 characters in "s"
for i=1, n-1 do
s12 = string.sub ( s , i, i+1 )
s1 = string.sub ( s12, 1, 1 )
if string.match ( s12 , "%a%u" ) then
s_mod = s_mod .. s1 .. ".\,"
else
s_mod = s_mod .. s1
end
end
-- Process the final character in "s"
s_n = string.sub ( s , n)
if string.match (s_n, "%.") then -- "." char.
s_mod = s_mod .. "\@."
elseif string.match (s_n, "%l") then -- lowercase letter
s_mod = s_mod .. s_n .. ".\hbox{}"
elseif string.match (s_n, "%u") then -- uppercase letter
s_mod = s_mod .. s_n .. "."
else -- Any other character:
s_mod = s_mod .. s_n -- don't add anything after 's_n'
end
-- Print the modified string
tex.sprint ( s_mod )
end
end
end{luacode}
%% LaTeX-side code: macro that calls the Lua function
newcommandabr[2]{directlua{abr("#1")}}
begin{document}
abr{OED}, abr{PhD}, abr{DPhil}, abr{MSc}, abr{()}
smallskip
% Two calls to "abr" with an empty argument (upon expansion):
.abr{}. quad
defttt{} .abr{ttt}.
bigskip
edeftmp{abr{MA}} detokenizeexpandafter{tmp}
edeftmp{abr{MA.}} detokenizeexpandafter{tmp}
expands to: tmp
smallskip
edeftmp{abr{MSc}} detokenizeexpandafter{tmp}
edeftmp{abr{MSc.}} detokenizeexpandafter{tmp}
expands to: tmp
bigskip
Some tests of spacing after punctuation marks:
smallskip
a abr{PhD} candidate --- good
a Ph.,D. candidate --- just to verify
smallskip
an abr{MSc} candidate --- good
an M.,Sc. candidate --- just to verify
smallskip
She has a abr{PhD.} So do I. --- good
She has a Ph.,D@. So do I. --- just to verify
smallskip
He has an abr{MSc.} So do I. --- good
He has an M.,Sc. So do I. --- just to verify
smallskip
Does he have an abr{MSc.}? Really?! --- good
Does he have an M.,Sc.? Really?! --- just to verify
end{document}
Here's a LuaLaTeX-based solution.
Cases such as
abr{OED}
orabr{IMF}
work just as expected. If the acronym contains both uppercase and lowercase letters, dots are inserted only before the uppercase letters in the interior of the acronym. E.g.,abr{MSc}
generatesM.,Sc.
, andabr{PhD}
generatesPh.,D.
.It can handle mixed-case acronyms such as "PhD" directly -- no need to write
abr{{Ph}D}
.If a "slovenly abbreviation" ends a sentence, one should place the "." punctuation mark inside the argument of
abr
. The code takes care to insert a@
"space factor* directive before the final.
character. This, in turn, informs LaTeX that that.
character should be treated as ending a sentence.The code returns nothing if the argument of
abr
is either empty or expands to return nothing. E.g.,defttt{} /abr{ttt}/
returns//
. If the code encounters non-letter characters -- say,(
and)
-- no periods are inserted before or after them.The code is expandable in the sense that
abr
can be included in the argument of anedef
directive.
documentclass{article}
usepackage{luacode} % for 'luacode' environment
%% Lua-side code:
begin{luacode}
function abr ( s )
n = string.len ( s )
-- Do nothing unless "s" is non-empty.
if n>0 then
s_mod = "" -- initialize the string
-- Process the first n-1 characters in "s"
for i=1, n-1 do
s12 = string.sub ( s , i, i+1 )
s1 = string.sub ( s12, 1, 1 )
if string.match ( s12 , "%a%u" ) then
s_mod = s_mod .. s1 .. ".\,"
else
s_mod = s_mod .. s1
end
end
-- Process the final character in "s"
s_n = string.sub ( s , n)
if string.match (s_n, "%.") then -- "." char.
s_mod = s_mod .. "\@."
elseif string.match (s_n, "%l") then -- lowercase letter
s_mod = s_mod .. s_n .. ".\hbox{}"
elseif string.match (s_n, "%u") then -- uppercase letter
s_mod = s_mod .. s_n .. "."
else -- Any other character:
s_mod = s_mod .. s_n -- don't add anything after 's_n'
end
-- Print the modified string
tex.sprint ( s_mod )
end
end
end{luacode}
%% LaTeX-side code: macro that calls the Lua function
newcommandabr[2]{directlua{abr("#1")}}
begin{document}
abr{OED}, abr{PhD}, abr{DPhil}, abr{MSc}, abr{()}
smallskip
% Two calls to "abr" with an empty argument (upon expansion):
.abr{}. quad
defttt{} .abr{ttt}.
bigskip
edeftmp{abr{MA}} detokenizeexpandafter{tmp}
edeftmp{abr{MA.}} detokenizeexpandafter{tmp}
expands to: tmp
smallskip
edeftmp{abr{MSc}} detokenizeexpandafter{tmp}
edeftmp{abr{MSc.}} detokenizeexpandafter{tmp}
expands to: tmp
bigskip
Some tests of spacing after punctuation marks:
smallskip
a abr{PhD} candidate --- good
a Ph.,D. candidate --- just to verify
smallskip
an abr{MSc} candidate --- good
an M.,Sc. candidate --- just to verify
smallskip
She has a abr{PhD.} So do I. --- good
She has a Ph.,D@. So do I. --- just to verify
smallskip
He has an abr{MSc.} So do I. --- good
He has an M.,Sc. So do I. --- just to verify
smallskip
Does he have an abr{MSc.}? Really?! --- good
Does he have an M.,Sc.? Really?! --- just to verify
end{document}
edited Nov 9 at 6:12
answered Nov 8 at 15:05
Mico
269k30364749
269k30364749
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writesI like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after someabr{...}
directive is to include the period in the argument ofabr
. I've come up with an update to the code that allowsabbr{MSc}
andabr{MSc.}
to be typeset differently. I'll post the updated code shortly.
– Mico
Nov 8 at 22:49
How about@ifnextchar.{spacefactor3000@gobble}
or something like that?
– Toothrot
Nov 8 at 22:55
@Toothrot - Using@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...
– Mico
Nov 9 at 6:11
add a comment |
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writesI like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after someabr{...}
directive is to include the period in the argument ofabr
. I've come up with an update to the code that allowsabbr{MSc}
andabr{MSc.}
to be typeset differently. I'll post the updated code shortly.
– Mico
Nov 8 at 22:49
How about@ifnextchar.{spacefactor3000@gobble}
or something like that?
– Toothrot
Nov 8 at 22:55
@Toothrot - Using@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...
– Mico
Nov 9 at 6:11
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
I wonder if it weren't more correct to put a sentence-ending point after the macro rather than into the argument, seeing as the full-stop is not part of the abbreviation.
– Toothrot
Nov 8 at 22:16
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writes
I like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after some abr{...}
directive is to include the period in the argument of abr
. I've come up with an update to the code that allows abbr{MSc}
and abr{MSc.}
to be typeset differently. I'll post the updated code shortly.– Mico
Nov 8 at 22:49
@Toothrot - A major issue is: How does one inform LaTeX whether a sentence ends with a slovenly abbreviation? If one writes
I like the abr{OED}.
, one ends up with two "dots" -- not good. The only way I can think of indicating reliably to LaTeX that a sentence ends right after some abr{...}
directive is to include the period in the argument of abr
. I've come up with an update to the code that allows abbr{MSc}
and abr{MSc.}
to be typeset differently. I'll post the updated code shortly.– Mico
Nov 8 at 22:49
How about
@ifnextchar.{spacefactor3000@gobble}
or something like that?– Toothrot
Nov 8 at 22:55
How about
@ifnextchar.{spacefactor3000@gobble}
or something like that?– Toothrot
Nov 8 at 22:55
@Toothrot - Using
@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...– Mico
Nov 9 at 6:11
@Toothrot - Using
@ifnextchar
is a potentially interesting idea. I'll have to think about some more; unfortunately, I won't be able to get to work on it until this evening at the earliest. Maybe somebody else will come up with a good solution in the meantime...– Mico
Nov 9 at 6:11
add a comment |
up vote
5
down vote
Let TeX do the recursion:
documentclass{article}
usepackage{xparse}
usepackage{etoolbox}
robustify{,} % just in order it doesn't expand in edef
ExplSyntaxOn
NewExpandableDocumentCommand{abr}{m}
{
tl_map_function:fN { tl_range:nnn { #1 } { 1 } { -2 } } __toothrot_abr:n
tl_range:nnn { #1 } { -1 } { -1 } .
}
cs_generate_variant:Nn tl_map_function:nN { f }
cs_new:Nn __toothrot_abr:n { #1., }
ExplSyntaxOff
begin{document}
abr{OED}
abr{{Ph}D}
edeftest{abr{OED}}
texttt{meaningtest}
edeftest{abr{}}
texttt{meaningtest}
end{document}
If a part of the argument is braced, it is considered as a single item.
One might check whether the argument is empty in order to print nothing at all, but it doesn't seem so important a feature.
With tl_range:nnn { #1 } { 1 } { -2 }
we extract all items but the last; tl_range:nnn { #1 } { -1 } { -1 }
extracts the last item.
add a comment |
up vote
5
down vote
Let TeX do the recursion:
documentclass{article}
usepackage{xparse}
usepackage{etoolbox}
robustify{,} % just in order it doesn't expand in edef
ExplSyntaxOn
NewExpandableDocumentCommand{abr}{m}
{
tl_map_function:fN { tl_range:nnn { #1 } { 1 } { -2 } } __toothrot_abr:n
tl_range:nnn { #1 } { -1 } { -1 } .
}
cs_generate_variant:Nn tl_map_function:nN { f }
cs_new:Nn __toothrot_abr:n { #1., }
ExplSyntaxOff
begin{document}
abr{OED}
abr{{Ph}D}
edeftest{abr{OED}}
texttt{meaningtest}
edeftest{abr{}}
texttt{meaningtest}
end{document}
If a part of the argument is braced, it is considered as a single item.
One might check whether the argument is empty in order to print nothing at all, but it doesn't seem so important a feature.
With tl_range:nnn { #1 } { 1 } { -2 }
we extract all items but the last; tl_range:nnn { #1 } { -1 } { -1 }
extracts the last item.
add a comment |
up vote
5
down vote
up vote
5
down vote
Let TeX do the recursion:
documentclass{article}
usepackage{xparse}
usepackage{etoolbox}
robustify{,} % just in order it doesn't expand in edef
ExplSyntaxOn
NewExpandableDocumentCommand{abr}{m}
{
tl_map_function:fN { tl_range:nnn { #1 } { 1 } { -2 } } __toothrot_abr:n
tl_range:nnn { #1 } { -1 } { -1 } .
}
cs_generate_variant:Nn tl_map_function:nN { f }
cs_new:Nn __toothrot_abr:n { #1., }
ExplSyntaxOff
begin{document}
abr{OED}
abr{{Ph}D}
edeftest{abr{OED}}
texttt{meaningtest}
edeftest{abr{}}
texttt{meaningtest}
end{document}
If a part of the argument is braced, it is considered as a single item.
One might check whether the argument is empty in order to print nothing at all, but it doesn't seem so important a feature.
With tl_range:nnn { #1 } { 1 } { -2 }
we extract all items but the last; tl_range:nnn { #1 } { -1 } { -1 }
extracts the last item.
Let TeX do the recursion:
documentclass{article}
usepackage{xparse}
usepackage{etoolbox}
robustify{,} % just in order it doesn't expand in edef
ExplSyntaxOn
NewExpandableDocumentCommand{abr}{m}
{
tl_map_function:fN { tl_range:nnn { #1 } { 1 } { -2 } } __toothrot_abr:n
tl_range:nnn { #1 } { -1 } { -1 } .
}
cs_generate_variant:Nn tl_map_function:nN { f }
cs_new:Nn __toothrot_abr:n { #1., }
ExplSyntaxOff
begin{document}
abr{OED}
abr{{Ph}D}
edeftest{abr{OED}}
texttt{meaningtest}
edeftest{abr{}}
texttt{meaningtest}
end{document}
If a part of the argument is braced, it is considered as a single item.
One might check whether the argument is empty in order to print nothing at all, but it doesn't seem so important a feature.
With tl_range:nnn { #1 } { 1 } { -2 }
we extract all items but the last; tl_range:nnn { #1 } { -1 } { -1 }
extracts the last item.
answered Nov 8 at 13:25
egreg
698k8518553123
698k8518553123
add a comment |
add a comment |
up vote
5
down vote
documentclass{article}
usepackage{xinttools}
newcommandabr[1]{xintListWithSep{.,}{#1}.}
begin{document}
I've seen it in the abr{OED}.
I got my abr{{Ph}D}.
end{document}
Updated (à la Mico, but without LuaLaTeX)
The syntax here is to use abr{PhD.}
for example at end of a sentence, and abr{PhD}
if not at end of a sentence.
documentclass{article}
usepackage{xinttools}
makeatletter
newcommandabr[1]
{expandafter@gobbletworomannumeral0xintapplyunbracedabr@aux{#1}.@}
defabr@sep{.,}
defabr@aux#1{if.#1expandafterabr@end
else
if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterexpandafterexpandafterabr@sep
fi
fi#1}%
defabr@end.{ abr@@end}
defabr@@end.@{@.}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
just insert a dot in the verb|abr| argument: abr{OED.} It ended a
sentence and in non-French spacing mode, TeX inserted the extra
space.
texttt{We can see it better with monospace font: abr{OED.} See?}
I got my abr{PhD} and even my abr{PhilD}, leniency ruled
in those days.
texttt{The dots are added in a smart way: abr{AaaaBbbbCccc.} But it is
assumed that the first letter is abr{Uppercased.} That's it.}
texttt{Notice that neitger abr{Aaaa} nor abr{AaA} trigger an end of
sentence spacing after the dot, which is abr{Good.} Isn't it?}
end{document}
Again updated, for automatic end of sentence dot detection after abbreviation
Here an end of sentence dot will be detected automatically.
Of course we can't use @ifnextchar
for that, as it swallows spaces.
I added some comments about expandability, which seems to have drawn great attention in other answers :)
.
documentclass{article}
usepackage{shortvrb}MakeShortVerb{|}
usepackage{xinttools}
makeatletter
protecteddefabrsep{.,}% maybe redefined even after edeffoo{abr{DPhil}}...
protecteddefabrend{futurelet@let@tokenabr@end}
defabr@end{ifx.@let@token@else.@fi}
newcommandabr[1]
{expandafter@gobbleromannumeral0xintapplyunbracedabr@aux{#1}abrend}
defabr@aux#1{if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterabr@sep
fi#1}%
defabr@sep{ abrsep}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
it will detect it automatically: abr{OED}. There was no double dot.
Besides, TeX applied its end of sentence extra space.
texttt{We can see it better with monospace font: abr{OED}. See?}
texttt{We can see it better with monospace font: abr{OED}, See?}
I got a abr{MSc}, a abr{PhD} and even a abr{DPhil}. Leniency ruled
in those days.
{The abbreviation dots are added in a smart way, after the last
lowercase letter following an uppercase letter:
abr{AaaaBbbbCccc}. But it is emph{assumed} that the first letter is
abr{Uppercased}. That's it.}
texttt{Notice that neither abr{DPhil} nor abr{PhilD} get TeX to
consider the inserted final dot as signaling an end of
sentence spacing after the dot, which is abr{Good}. Isn't it?}
About expandability, the correct way for LaTeX2e's users would be to use
|protected@edef|, not a naked |edef|; although nowadays some
LaTeX2e users have heard about |edef|, they might not know
about |protected@edef|, which requires a cumbersome extra
|makeatletter| for its usage. Anyway, none of that is described in
textsc{Lamport} book, so I wonder if LaTeX2e users are really
emph{allowed} into using |edef| to start with.
But as it seems they know about |edef|, we as macro programmers need
better to use the e-TeX's |protected| prefix and not the LaTeX2e
|DeclareRobustCommand|, because users will not do |protected@edef|.
This is what I have done here for a macro |abrsep| (why haven't we all
used |abbr| by the way?) which is deliberately |protected|,
allowing it to be redefined at location of use, long after some macro
will have been defined via |edeffoo{abr{ABCDEFGH}}|.
edeffoo{abr{ABCDEFGH}}texttt{stringfoo is meaningfoo}
edeffoo{abr{AaaBccCcc}}texttt{stringfoo is meaningfoo}
The |abrend| is also |protected|, anyway as its expansion will be
context dependent (it detects if a dot follows), it had to not expand
in the |edef|.
end{document}
Notice that my proposals v2 and v3 will work only with ascii uppercase letters, no diacritics.
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
1
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX@ifnextchar
which swallows spaces.
– jfbu
Nov 9 at 8:21
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for anedef
and anyhow the tokens of the input are subjected to full-first expansion viaifnum
test etc...
– jfbu
Nov 9 at 9:47
add a comment |
up vote
5
down vote
documentclass{article}
usepackage{xinttools}
newcommandabr[1]{xintListWithSep{.,}{#1}.}
begin{document}
I've seen it in the abr{OED}.
I got my abr{{Ph}D}.
end{document}
Updated (à la Mico, but without LuaLaTeX)
The syntax here is to use abr{PhD.}
for example at end of a sentence, and abr{PhD}
if not at end of a sentence.
documentclass{article}
usepackage{xinttools}
makeatletter
newcommandabr[1]
{expandafter@gobbletworomannumeral0xintapplyunbracedabr@aux{#1}.@}
defabr@sep{.,}
defabr@aux#1{if.#1expandafterabr@end
else
if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterexpandafterexpandafterabr@sep
fi
fi#1}%
defabr@end.{ abr@@end}
defabr@@end.@{@.}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
just insert a dot in the verb|abr| argument: abr{OED.} It ended a
sentence and in non-French spacing mode, TeX inserted the extra
space.
texttt{We can see it better with monospace font: abr{OED.} See?}
I got my abr{PhD} and even my abr{PhilD}, leniency ruled
in those days.
texttt{The dots are added in a smart way: abr{AaaaBbbbCccc.} But it is
assumed that the first letter is abr{Uppercased.} That's it.}
texttt{Notice that neitger abr{Aaaa} nor abr{AaA} trigger an end of
sentence spacing after the dot, which is abr{Good.} Isn't it?}
end{document}
Again updated, for automatic end of sentence dot detection after abbreviation
Here an end of sentence dot will be detected automatically.
Of course we can't use @ifnextchar
for that, as it swallows spaces.
I added some comments about expandability, which seems to have drawn great attention in other answers :)
.
documentclass{article}
usepackage{shortvrb}MakeShortVerb{|}
usepackage{xinttools}
makeatletter
protecteddefabrsep{.,}% maybe redefined even after edeffoo{abr{DPhil}}...
protecteddefabrend{futurelet@let@tokenabr@end}
defabr@end{ifx.@let@token@else.@fi}
newcommandabr[1]
{expandafter@gobbleromannumeral0xintapplyunbracedabr@aux{#1}abrend}
defabr@aux#1{if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterabr@sep
fi#1}%
defabr@sep{ abrsep}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
it will detect it automatically: abr{OED}. There was no double dot.
Besides, TeX applied its end of sentence extra space.
texttt{We can see it better with monospace font: abr{OED}. See?}
texttt{We can see it better with monospace font: abr{OED}, See?}
I got a abr{MSc}, a abr{PhD} and even a abr{DPhil}. Leniency ruled
in those days.
{The abbreviation dots are added in a smart way, after the last
lowercase letter following an uppercase letter:
abr{AaaaBbbbCccc}. But it is emph{assumed} that the first letter is
abr{Uppercased}. That's it.}
texttt{Notice that neither abr{DPhil} nor abr{PhilD} get TeX to
consider the inserted final dot as signaling an end of
sentence spacing after the dot, which is abr{Good}. Isn't it?}
About expandability, the correct way for LaTeX2e's users would be to use
|protected@edef|, not a naked |edef|; although nowadays some
LaTeX2e users have heard about |edef|, they might not know
about |protected@edef|, which requires a cumbersome extra
|makeatletter| for its usage. Anyway, none of that is described in
textsc{Lamport} book, so I wonder if LaTeX2e users are really
emph{allowed} into using |edef| to start with.
But as it seems they know about |edef|, we as macro programmers need
better to use the e-TeX's |protected| prefix and not the LaTeX2e
|DeclareRobustCommand|, because users will not do |protected@edef|.
This is what I have done here for a macro |abrsep| (why haven't we all
used |abbr| by the way?) which is deliberately |protected|,
allowing it to be redefined at location of use, long after some macro
will have been defined via |edeffoo{abr{ABCDEFGH}}|.
edeffoo{abr{ABCDEFGH}}texttt{stringfoo is meaningfoo}
edeffoo{abr{AaaBccCcc}}texttt{stringfoo is meaningfoo}
The |abrend| is also |protected|, anyway as its expansion will be
context dependent (it detects if a dot follows), it had to not expand
in the |edef|.
end{document}
Notice that my proposals v2 and v3 will work only with ascii uppercase letters, no diacritics.
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
1
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX@ifnextchar
which swallows spaces.
– jfbu
Nov 9 at 8:21
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for anedef
and anyhow the tokens of the input are subjected to full-first expansion viaifnum
test etc...
– jfbu
Nov 9 at 9:47
add a comment |
up vote
5
down vote
up vote
5
down vote
documentclass{article}
usepackage{xinttools}
newcommandabr[1]{xintListWithSep{.,}{#1}.}
begin{document}
I've seen it in the abr{OED}.
I got my abr{{Ph}D}.
end{document}
Updated (à la Mico, but without LuaLaTeX)
The syntax here is to use abr{PhD.}
for example at end of a sentence, and abr{PhD}
if not at end of a sentence.
documentclass{article}
usepackage{xinttools}
makeatletter
newcommandabr[1]
{expandafter@gobbletworomannumeral0xintapplyunbracedabr@aux{#1}.@}
defabr@sep{.,}
defabr@aux#1{if.#1expandafterabr@end
else
if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterexpandafterexpandafterabr@sep
fi
fi#1}%
defabr@end.{ abr@@end}
defabr@@end.@{@.}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
just insert a dot in the verb|abr| argument: abr{OED.} It ended a
sentence and in non-French spacing mode, TeX inserted the extra
space.
texttt{We can see it better with monospace font: abr{OED.} See?}
I got my abr{PhD} and even my abr{PhilD}, leniency ruled
in those days.
texttt{The dots are added in a smart way: abr{AaaaBbbbCccc.} But it is
assumed that the first letter is abr{Uppercased.} That's it.}
texttt{Notice that neitger abr{Aaaa} nor abr{AaA} trigger an end of
sentence spacing after the dot, which is abr{Good.} Isn't it?}
end{document}
Again updated, for automatic end of sentence dot detection after abbreviation
Here an end of sentence dot will be detected automatically.
Of course we can't use @ifnextchar
for that, as it swallows spaces.
I added some comments about expandability, which seems to have drawn great attention in other answers :)
.
documentclass{article}
usepackage{shortvrb}MakeShortVerb{|}
usepackage{xinttools}
makeatletter
protecteddefabrsep{.,}% maybe redefined even after edeffoo{abr{DPhil}}...
protecteddefabrend{futurelet@let@tokenabr@end}
defabr@end{ifx.@let@token@else.@fi}
newcommandabr[1]
{expandafter@gobbleromannumeral0xintapplyunbracedabr@aux{#1}abrend}
defabr@aux#1{if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterabr@sep
fi#1}%
defabr@sep{ abrsep}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
it will detect it automatically: abr{OED}. There was no double dot.
Besides, TeX applied its end of sentence extra space.
texttt{We can see it better with monospace font: abr{OED}. See?}
texttt{We can see it better with monospace font: abr{OED}, See?}
I got a abr{MSc}, a abr{PhD} and even a abr{DPhil}. Leniency ruled
in those days.
{The abbreviation dots are added in a smart way, after the last
lowercase letter following an uppercase letter:
abr{AaaaBbbbCccc}. But it is emph{assumed} that the first letter is
abr{Uppercased}. That's it.}
texttt{Notice that neither abr{DPhil} nor abr{PhilD} get TeX to
consider the inserted final dot as signaling an end of
sentence spacing after the dot, which is abr{Good}. Isn't it?}
About expandability, the correct way for LaTeX2e's users would be to use
|protected@edef|, not a naked |edef|; although nowadays some
LaTeX2e users have heard about |edef|, they might not know
about |protected@edef|, which requires a cumbersome extra
|makeatletter| for its usage. Anyway, none of that is described in
textsc{Lamport} book, so I wonder if LaTeX2e users are really
emph{allowed} into using |edef| to start with.
But as it seems they know about |edef|, we as macro programmers need
better to use the e-TeX's |protected| prefix and not the LaTeX2e
|DeclareRobustCommand|, because users will not do |protected@edef|.
This is what I have done here for a macro |abrsep| (why haven't we all
used |abbr| by the way?) which is deliberately |protected|,
allowing it to be redefined at location of use, long after some macro
will have been defined via |edeffoo{abr{ABCDEFGH}}|.
edeffoo{abr{ABCDEFGH}}texttt{stringfoo is meaningfoo}
edeffoo{abr{AaaBccCcc}}texttt{stringfoo is meaningfoo}
The |abrend| is also |protected|, anyway as its expansion will be
context dependent (it detects if a dot follows), it had to not expand
in the |edef|.
end{document}
Notice that my proposals v2 and v3 will work only with ascii uppercase letters, no diacritics.
documentclass{article}
usepackage{xinttools}
newcommandabr[1]{xintListWithSep{.,}{#1}.}
begin{document}
I've seen it in the abr{OED}.
I got my abr{{Ph}D}.
end{document}
Updated (à la Mico, but without LuaLaTeX)
The syntax here is to use abr{PhD.}
for example at end of a sentence, and abr{PhD}
if not at end of a sentence.
documentclass{article}
usepackage{xinttools}
makeatletter
newcommandabr[1]
{expandafter@gobbletworomannumeral0xintapplyunbracedabr@aux{#1}.@}
defabr@sep{.,}
defabr@aux#1{if.#1expandafterabr@end
else
if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterexpandafterexpandafterabr@sep
fi
fi#1}%
defabr@end.{ abr@@end}
defabr@@end.@{@.}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
just insert a dot in the verb|abr| argument: abr{OED.} It ended a
sentence and in non-French spacing mode, TeX inserted the extra
space.
texttt{We can see it better with monospace font: abr{OED.} See?}
I got my abr{PhD} and even my abr{PhilD}, leniency ruled
in those days.
texttt{The dots are added in a smart way: abr{AaaaBbbbCccc.} But it is
assumed that the first letter is abr{Uppercased.} That's it.}
texttt{Notice that neitger abr{Aaaa} nor abr{AaA} trigger an end of
sentence spacing after the dot, which is abr{Good.} Isn't it?}
end{document}
Again updated, for automatic end of sentence dot detection after abbreviation
Here an end of sentence dot will be detected automatically.
Of course we can't use @ifnextchar
for that, as it swallows spaces.
I added some comments about expandability, which seems to have drawn great attention in other answers :)
.
documentclass{article}
usepackage{shortvrb}MakeShortVerb{|}
usepackage{xinttools}
makeatletter
protecteddefabrsep{.,}% maybe redefined even after edeffoo{abr{DPhil}}...
protecteddefabrend{futurelet@let@tokenabr@end}
defabr@end{ifx.@let@token@else.@fi}
newcommandabr[1]
{expandafter@gobbleromannumeral0xintapplyunbracedabr@aux{#1}abrend}
defabr@aux#1{if1ifnum`#1<`A 0fiifnum`#1>`Z 0fi1%
expandafterabr@sep
fi#1}%
defabr@sep{ abrsep}
makeatother
begin{document}%ttfamily
I've seen it in the abr{OED}, and if located at end of a sentence
it will detect it automatically: abr{OED}. There was no double dot.
Besides, TeX applied its end of sentence extra space.
texttt{We can see it better with monospace font: abr{OED}. See?}
texttt{We can see it better with monospace font: abr{OED}, See?}
I got a abr{MSc}, a abr{PhD} and even a abr{DPhil}. Leniency ruled
in those days.
{The abbreviation dots are added in a smart way, after the last
lowercase letter following an uppercase letter:
abr{AaaaBbbbCccc}. But it is emph{assumed} that the first letter is
abr{Uppercased}. That's it.}
texttt{Notice that neither abr{DPhil} nor abr{PhilD} get TeX to
consider the inserted final dot as signaling an end of
sentence spacing after the dot, which is abr{Good}. Isn't it?}
About expandability, the correct way for LaTeX2e's users would be to use
|protected@edef|, not a naked |edef|; although nowadays some
LaTeX2e users have heard about |edef|, they might not know
about |protected@edef|, which requires a cumbersome extra
|makeatletter| for its usage. Anyway, none of that is described in
textsc{Lamport} book, so I wonder if LaTeX2e users are really
emph{allowed} into using |edef| to start with.
But as it seems they know about |edef|, we as macro programmers need
better to use the e-TeX's |protected| prefix and not the LaTeX2e
|DeclareRobustCommand|, because users will not do |protected@edef|.
This is what I have done here for a macro |abrsep| (why haven't we all
used |abbr| by the way?) which is deliberately |protected|,
allowing it to be redefined at location of use, long after some macro
will have been defined via |edeffoo{abr{ABCDEFGH}}|.
edeffoo{abr{ABCDEFGH}}texttt{stringfoo is meaningfoo}
edeffoo{abr{AaaBccCcc}}texttt{stringfoo is meaningfoo}
The |abrend| is also |protected|, anyway as its expansion will be
context dependent (it detects if a dot follows), it had to not expand
in the |edef|.
end{document}
Notice that my proposals v2 and v3 will work only with ascii uppercase letters, no diacritics.
edited Nov 9 at 8:16
answered Nov 8 at 13:35
jfbu
44.5k65143
44.5k65143
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
1
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX@ifnextchar
which swallows spaces.
– jfbu
Nov 9 at 8:21
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for anedef
and anyhow the tokens of the input are subjected to full-first expansion viaifnum
test etc...
– jfbu
Nov 9 at 9:47
add a comment |
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
1
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX@ifnextchar
which swallows spaces.
– jfbu
Nov 9 at 8:21
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for anedef
and anyhow the tokens of the input are subjected to full-first expansion viaifnum
test etc...
– jfbu
Nov 9 at 9:47
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
@Mico I plagiarized your input syntax for end of sentence...
– jfbu
Nov 8 at 17:07
1
1
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX
@ifnextchar
which swallows spaces.– jfbu
Nov 9 at 8:21
@Mico I have again updated as I read OP is pushing towards automatic dot detection. One can not use LaTeX
@ifnextchar
which swallows spaces.– jfbu
Nov 9 at 8:21
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
Outstanding! :-) Incidentally, I've gone ahead and deleted my earlier comments are they're no longer relevant, or even understandable, for readers of the current version of your answer.
– Mico
Nov 9 at 8:39
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for an
edef
and anyhow the tokens of the input are subjected to full-first expansion via ifnum
test etc...– jfbu
Nov 9 at 9:47
(not to be told publicly: of course I could remove all usage of xinttools but where is the fun without it?) well, in fact usage of a an xinttools macro facilitates a fixed number of expansion steps to get final result, here 3 steps, I could reduce to 2 steps. But doesn't matter for an
edef
and anyhow the tokens of the input are subjected to full-first expansion via ifnum
test etc...– jfbu
Nov 9 at 9:47
add a comment |
up vote
4
down vote
documentclass{article}
newcommandabr[1]{abraux#1..}
defabraux#1#2#3{%
#1%
ifnum`#2>91relax% we have a lowercase letter following
defnext{abraux#2#3}%
else
.ifx.#2defnext{@}else,defnext{abraux#2#3}fi
fi
next
}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Here is abr{XOOED} abbreviation.
abr{MSc}
abr{DPhil}
end{document}
Can your code be extended to handle the lazy/slovenly punctuation ofMSc
(correct:M.,Sc.
) andDPhil
(correct:D.,Phil.
)?
– Mico
Nov 9 at 6:20
1
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
add a comment |
up vote
4
down vote
documentclass{article}
newcommandabr[1]{abraux#1..}
defabraux#1#2#3{%
#1%
ifnum`#2>91relax% we have a lowercase letter following
defnext{abraux#2#3}%
else
.ifx.#2defnext{@}else,defnext{abraux#2#3}fi
fi
next
}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Here is abr{XOOED} abbreviation.
abr{MSc}
abr{DPhil}
end{document}
Can your code be extended to handle the lazy/slovenly punctuation ofMSc
(correct:M.,Sc.
) andDPhil
(correct:D.,Phil.
)?
– Mico
Nov 9 at 6:20
1
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
add a comment |
up vote
4
down vote
up vote
4
down vote
documentclass{article}
newcommandabr[1]{abraux#1..}
defabraux#1#2#3{%
#1%
ifnum`#2>91relax% we have a lowercase letter following
defnext{abraux#2#3}%
else
.ifx.#2defnext{@}else,defnext{abraux#2#3}fi
fi
next
}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Here is abr{XOOED} abbreviation.
abr{MSc}
abr{DPhil}
end{document}
documentclass{article}
newcommandabr[1]{abraux#1..}
defabraux#1#2#3{%
#1%
ifnum`#2>91relax% we have a lowercase letter following
defnext{abraux#2#3}%
else
.ifx.#2defnext{@}else,defnext{abraux#2#3}fi
fi
next
}
begin{document}
Here is abr{OED} abbreviation.
Here is abr{XO} abbreviation.
Here is abr{XOOED} abbreviation.
abr{MSc}
abr{DPhil}
end{document}
edited Nov 10 at 8:32
answered Nov 8 at 12:58
Herbert
265k23401712
265k23401712
Can your code be extended to handle the lazy/slovenly punctuation ofMSc
(correct:M.,Sc.
) andDPhil
(correct:D.,Phil.
)?
– Mico
Nov 9 at 6:20
1
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
add a comment |
Can your code be extended to handle the lazy/slovenly punctuation ofMSc
(correct:M.,Sc.
) andDPhil
(correct:D.,Phil.
)?
– Mico
Nov 9 at 6:20
1
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
Can your code be extended to handle the lazy/slovenly punctuation of
MSc
(correct: M.,Sc.
) and DPhil
(correct: D.,Phil.
)?– Mico
Nov 9 at 6:20
Can your code be extended to handle the lazy/slovenly punctuation of
MSc
(correct: M.,Sc.
) and DPhil
(correct: D.,Phil.
)?– Mico
Nov 9 at 6:20
1
1
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
Sure, if it is not an uppercase letter then go the next char.
– Herbert
Nov 9 at 19:02
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f458975%2frespectable-abbreviations-macro%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Are you sure that you want two
.
punctuation marks after the (non-slovenly) version ofOED
?– Mico
Nov 8 at 16:41
1
@Mico, I'm sure I don't; edited.
– Toothrot
Nov 8 at 19:42
1
Note however that the norm is that abbreviations should be typeset without any dots. I don't have the reference to the norm right now, but I'll post it later on.
– Massimo Ortolano
Nov 9 at 7:44