With amsmath
you can define
\newcommand{\heightphantom}[1]{\vphantom{\smash[b]{#1}}
\newcommand{\depthphantom}[1]{\vphantom{\smash[t]{#1}}
Not as efficient as Heiko's, but shorter to define.
An expl3
version, with a key-value interface. The *
-version of the command doesn't force horizontal mode, if one really needs it.
The keys specify what dimensions are to be kept; specifying none means keeping all three (height, depth and width). Thus \xphantom{g}
is mainly equivalent to \phantom{g}
(apart from the automatic \leavevmode
), while \xphantom[width]{g}
and \xphantom[totalheight]{g}
are equivalent to \hphantom
and \vphantom
respectively. Shorthands \xhphantom
and \xvphantom
are provided for these.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\xphantom}{som}
{% #2 is a list of key-value options, #3 is the text
\IfBooleanF{#1}{\leavevmode}
\IfNoValueTF{#2}
{
\manual_phantom:nn { totalheight , width } { #3 }
}
{
\manual_phantom:nn { #2 } { #3 }
}
}
\NewDocumentCommand{\xhphantom}{sm}
{
\IfBooleanTF{#1}
{
\xphantom*[width]{#2}
}
{
\xphantom[width]{#2}
}
}
\NewDocumentCommand{\xvphantom}{sm}
{
\IfBooleanTF{#1}
{
\xphantom*[totalheight]{#2}
}
{
\xphantom[totalheight]{#2}
}
}
\keys_define:nn { manual/xphantom }
{
height .bool_set:N = \l__manual_phantom_keepht_bool,
depth .bool_set:N = \l__manual_phantom_keepdp_bool,
width .bool_set:N = \l__manual_phantom_keepwd_bool,
totalheight .code:n =
\bool_set_true:N \l__manual_phantom_keepht_bool
\bool_set_true:N \l__manual_phantom_keepdp_bool,
height .default:n = true,
depth .default:n = true,
width .default:n = true,
totalheight .default:n = ,
}
\box_new:N \l__manual_phantom_input_box
\box_new:N \l__manual_phantom_box
\cs_new_protected:Npn \manual_phantom:nn #1 #2
{
\group_begin:
\keys_set:nn { manual/xphantom } { #1 }
\hbox_set:Nn \l__manual_phantom_input_box { #2 }
\hbox_set:Nn \l__manual_phantom_box {}
\bool_if:NT \l__manual_phantom_keepht_bool
{
\box_set_ht:Nn \l__manual_phantom_box { \box_ht:N \l__manual_phantom_input_box }
}
\bool_if:NT \l__manual_phantom_keepdp_bool
{
\box_set_dp:Nn \l__manual_phantom_box { \box_dp:N \l__manual_phantom_input_box }
}
\bool_if:NT \l__manual_phantom_keepwd_bool
{
\box_set_wd:Nn \l__manual_phantom_box { \box_wd:N \l__manual_phantom_input_box }
}
\box_use:N \l__manual_phantom_box
\group_end:
}
\ExplSyntaxOff
\begin{document}
\newcommand*{\test}[1]{%
\begingroup
\setlength{\fboxsep}{0pt}%
\fbox{#1}%
\endgroup
}
g
\test{\xphantom{g}}
\test{\xphantom[width]{g}}
\test{\xphantom[totalheight]{g}}
\test{\xphantom[height]{g}}
\test{\xphantom[depth]{g}}
g
\test{\xphantom[height,width]{g}}
\test{\xphantom[depth,width]{g}}
g
\test{\xhphantom{g}}
\test{\xvphantom{g}}
\end{document}
A version also implementing math mode:
\documentclass{article}
\usepackage{amsmath,xparse}
\ExplSyntaxOn
\NewDocumentCommand{\xphantom}{som}
{% #2 is a list of key-value options, #3 is the text
\IfBooleanF{#1}{ \mode_if_math:F { \leavevmode } }
\IfNoValueTF{#2}
{
\manual_phantom:nn { totalheight , width } { #3 }
}
{
\manual_phantom:nn { #2 } { #3 }
}
}
\NewDocumentCommand{\xhphantom}{sm}
{
\IfBooleanTF{#1}
{
\xphantom*[width]{#2}
}
{
\xphantom[width]{#2}
}
}
\NewDocumentCommand{\xvphantom}{sm}
{
\IfBooleanTF{#1}
{
\xphantom*[totalheight]{#2}
}
{
\xphantom[totalheight]{#2}
}
}
\keys_define:nn { manual/xphantom }
{
height .bool_set:N = \l__manual_phantom_keepht_bool,
depth .bool_set:N = \l__manual_phantom_keepdp_bool,
width .bool_set:N = \l__manual_phantom_keepwd_bool,
totalheight .code:n =
\bool_set_true:N \l__manual_phantom_keepht_bool
\bool_set_true:N \l__manual_phantom_keepdp_bool,
height .default:n = true,
depth .default:n = true,
width .default:n = true,
totalheight .default:n = ,
}
\box_new:N \l__manual_phantom_input_box
\box_new:N \l__manual_phantom_box
\cs_new_protected:Npn \manual_phantom:nn #1 #2
{
\group_begin:
\keys_set:nn { manual/xphantom } { #1 }
\hbox_set:Nn \l__manual_phantom_box {}
\mode_if_math:TF
{
\__manual_phantom_math:n { #2 }
}
{
\hbox_set:Nn \l__manual_phantom_input_box { #2 }
\__manual_phantom_set:
}
\group_end:
}
\cs_new_protected:Npn \__manual_phantom_set:
{
\bool_if:NT \l__manual_phantom_keepht_bool
{
\box_set_ht:Nn \l__manual_phantom_box { \box_ht:N \l__manual_phantom_input_box }
}
\bool_if:NT \l__manual_phantom_keepdp_bool
{
\box_set_dp:Nn \l__manual_phantom_box { \box_dp:N \l__manual_phantom_input_box }
}
\bool_if:NT \l__manual_phantom_keepwd_bool
{
\box_set_wd:Nn \l__manual_phantom_box { \box_wd:N \l__manual_phantom_input_box }
}
\box_use:N \l__manual_phantom_box
}
% Now math mode; there's currently no syntactic sugar for \mathpalette
\cs_new_protected:Npn \__manual_phantom_math:n #1
{
\mathpalette \__manual_make_phantom_math:nn { #1 }
}
\cs_new_protected:Npn \__manual_make_phantom_math:nn #1 #2
{
\hbox_set:Nn \l__manual_phantom_input_box { $ #1 {#2} \mathsurround=0pt $ }
\__manual_phantom_set:
}
\ExplSyntaxOff
\begin{document}
\newcommand*{\test}[1]{%
\begingroup
\setlength{\fboxsep}{0pt}%
\fbox{#1}%
\endgroup
}
g
\test{\xphantom{g}}
\test{\xphantom[width]{g}}
\test{\xphantom[totalheight]{g}}
\test{\xphantom[height]{g}}
\test{\xphantom[depth]{g}}
g
\test{\xphantom[height,width]{g}}
\test{\xphantom[depth,width]{g}}
g
\test{\xhphantom{g}}
\test{\xvphantom{g}}
$\displaystyle\sum$
\test{$\displaystyle\xphantom{\sum}$}
\test{$\displaystyle\xvphantom{\sum}$}
\test{$\displaystyle\xhphantom{\sum}$}
\test{$\displaystyle\xphantom[height]{\sum}$}
\test{$\displaystyle\xphantom[depth]{\sum}$}
\test{$\displaystyle\xphantom[height,width]{\sum}$}
\test{$\displaystyle\xphantom[depth,width]{\sum}$}
$\textstyle\sum$
\test{$\textstyle\xphantom{\sum}$}
\test{$\textstyle\xvphantom{\sum}$}
\test{$\textstyle\xhphantom{\sum}$}
$\scriptstyle\sum$
\test{$\scriptstyle\xphantom{\sum}$}
\test{$\scriptstyle\xvphantom{\sum}$}
\test{$\scriptstyle\xhphantom{\sum}$}
$\scriptscriptstyle\sum$
\test{$\scriptscriptstyle\xphantom{\sum}$}
\test{$\scriptscriptstyle\xvphantom{\sum}$}
\test{$\scriptscriptstyle\xhphantom{\sum}$}
\end{document}