자동화된 아래 첨자 및 위 첨자

자동화된 아래 첨자 및 위 첨자

인수의 첫 글자를 위 첨자로 인쇄하고 마지막 두 글자를 아래 첨자로 인쇄하는 명령을 정의하고 싶습니다. 따라서 다음을 입력하면:

\mynewcommand{abcde}

그것은 같은 일을해야

\textsuperscript{a}bc\textsubscript{de}

이러한 명령을 사용하면 몇 시간의 시간을 절약할 수 있지만 어떻게 해야 할지 모르겠습니다.

편집: 죄송합니다. 명확하지 않았을 것 같습니다. 중간 부분이 모든 것이 될 수 있습니다. 따라서 첫 글자만 위 첨자로, 마지막 두 글자는 아래 첨자로 써야 합니다.

나에게 필요한 것은:

\anothernewcommand{a some text that can contain \textit{other commands} cd}

다음과 동일하게 수행해야 하는 것

\textsuperscript{a} some text that can contain \textit{other commands} \textsubscript{cd}

답변1

나는 다음과 같은 구문이 더 명확할 것이라고 믿습니다 \mynewcommand{a}{bc}{de}. 어쨌든 위 첨자 뒤와 아래 첨자 앞의 공백 처리가 다른 두 가지 구현을 제공할 수 있습니다. 골라보세요.

\documentclass{article}

%\usepackage{xparse} % not needed for LaTeX 2020-10-01

\ExplSyntaxOn
\NewDocumentCommand{\mynewcommandA}{m}
 {
  \textsuperscript{\tl_range:nnn { #1 } { 1 } { 1 } }
  \tl_range:nnn { #1 } { 2 } { -3 }
  \textsubscript{\tl_range:nnn { #1 } { -2 } { -1 } }
 }

\NewDocumentCommand{\mynewcommandB}{m}
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_replace_all:Nnn \l_tmpa_tl { ~ } { \c_space_tl }
  \textsuperscript{\tl_range:Nnn \l_tmpa_tl { 1 } { 1 } }
  \tl_range:Nnn \l_tmpa_tl { 2 } { -3 }
  \textsubscript{\tl_range:Nnn \l_tmpa_tl { -2 } { -1 } }
}
\ExplSyntaxOff

\begin{document}

\textbf{Leading and trailing spaces are not kept}

\mynewcommandA{abcde}

\mynewcommandA{a some text that can contain \textit{other commands} cd}

\bigskip

\textbf{Leading and trailing spaces are kept}

\mynewcommandB{abcde}

\mynewcommandB{a some text that can contain \textit{other commands} cd}

\end{document}

여기에 이미지 설명을 입력하세요

추가 정보. 이 함수는 \tl_range:nnn세 개의 인수를 사용합니다. 첫 번째 인수는 텍스트이고, 두 번째와 세 번째 인수는 추출할 범위를 지정하는 정수입니다. 그래서 {1}{1}첫 번째 항목을 추출합니다(일 수도 있지만 \tl_head:n균일성을 위해 더 복잡한 함수를 사용했습니다). 반면 {-2}{-1}마지막 두 항목을 지정합니다(음수 인덱스를 사용하여 추출이 끝에서 시작됩니다). {2}{-3}두 번째 항목부터 오른쪽부터 세 번째 항목까지의 범위를 지정합니다.

그러나 추출된 부분의 경계에 있는 공백을 유지하기 위해서는 먼저 공백을 로 대체해야 하며 \c_space_tl, 이는 공백으로 확장되지만 추출 기능에 의해 잘리지는 않습니다. 구문은 \tl_set:Nnn동일하며 첫 번째 인수만 tl 변수여야 합니다.

답변2

복잡성을 위해 TeX 기본 수준에서 이 문제를 해결하는 방법을 보여줍니다.

\newcount\bufflen

\def\splitbuff #1#2{% #1: number of tokens from end, #2 data
                    % result: \buff, \restbuff
    \edef\buff{\detokenize{#2} }%
    \edef\buff{\expandafter}\expandafter\protectspaces \buff \\
    \bufflen=0 \expandafter\setbufflen\buff\end
    \advance\bufflen by-#1\relax
    \ifnum\bufflen<0 \errmessage{#1>buffer length}\fi
    \ifnum\bufflen>0 \edef\buff{\expandafter}\expandafter\splitbuffA \buff\end
    \else \let\restbuff=\buff \def\buff{}\fi
    \edef\tmp{\gdef\noexpand\buff{\buff}\gdef\noexpand\restbuff{\restbuff}}%
    {\endlinechar=-1 \scantokens\expandafter{\tmp}}%
}

\def\protectspaces #1 #2 {\addto\buff{#1}%
    \ifx\\#2\else \addto\buff{{ }}\afterfi \protectspaces #2 \fi}  
\def\afterfi #1\fi{\fi#1}
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}

\def\setbufflen #1{%
    \ifx\end#1\else \advance\bufflen by1 \expandafter\setbufflen\fi}

\def\splitbuffA #1{\addto\buff{#1}\advance\bufflen by-1
    \ifnum\bufflen>0 \expandafter\splitbuffA
    \else \expandafter\splitbuffB \fi
}
\def\splitbuffB #1\end{\def\restbuff{#1}}

% --------------- \mynewcommand implementation:

\def\textup#1{$^{\rm #1}$}  \def\textdown#1{$_{\rm #1}$}
\def\mynewcommand#1{\mynewcommandA#1\end}
\def\mynewcommandA#1#2\end{%
   \textup{#1}\splitbuff 2{#2}\buff \textdown{\restbuff}}

% --------------- test:

\mynewcommand{abcde}

\mynewcommand{a some text that can contain {\it other commands} cd}

\bye

답변3

다양성을 위해 LuaLaTeX 기반 솔루션이 있습니다. 이는 Lua의 문자열 함수를 활용 string.sub하고 string.len해당 작업을 수행하는 Lua 함수를 설정합니다. 또한 \mynewcommandLua 함수에 전달하기 전에 인수를 한 번 확장하는 LaTeX "래퍼" 매크로를 설정합니다 .

솔루션은 실제로 Lua 문자열 함수의 변형을 사용 하며 unicode.utf8.sub,unicode.utf8.len\mynewcommand utf8로 인코딩된 문자의 유효한 문자열이 되도록 허용합니다. (물론 그러기 위해서는인쇄문자열의 문자에 적합한 글꼴을 로드해야 합니다.) 인수에는 \mynewcommand기본 형식과 매크로가 포함될 수 있습니다.

여기에 이미지 설명을 입력하세요

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for "\luaexec" and "\luastringO" macros
\luaexec{
% Define a Lua function called "mycommand"
function mycommand ( s )
   local s1,s2,s3
   s1  = unicode.utf8.sub ( s, 1, 1 )
   s2  = unicode.utf8.sub ( s, 2, unicode.utf8.len(s)-2 )
   s3  = unicode.utf8.sub ( s, -2 )
   return ( "\\textsuperscript{" ..s1.. "}" ..s2.. "\\textsubscript{" ..s3.. "}" )
end
}
% Create a wrapper macro for the Lua function
\newcommand\mynewcommand[1]{\directlua{tex.sprint(mycommand(\luastringO{#1}))}}
    
\begin{document}
abcde $\to$ \mynewcommand{abcde}

öçäßüéà $\to$ \mynewcommand{öçäßüéà}

\mynewcommand{a some text that can contain \textit{\textbf{other commands}} cd}
\end{document}

관련 정보