Recuerda que en la informática un error casi siempre tiene diversas resoluciones, así que enseñaremos lo más óptimo y eficiente.
Solución:
Creo que una sintaxis como mynewcommandabcde
sería más claro. De todos modos, puedo ofrecer dos implementaciones que difieren en el tratamiento de los espacios después del superíndice y antes del subíndice. Elige tu opción.
documentclassarticle
%usepackagexparse % not needed for LaTeX 2020-10-01
ExplSyntaxOn
NewDocumentCommandmynewcommandAm
textsuperscripttl_range:nnn #1 1 1
tl_range:nnn #1 2 -3
textsubscripttl_range:nnn #1 -2 -1
NewDocumentCommandmynewcommandBm
tl_set:Nn l_tmpa_tl #1
tl_replace_all:Nnn l_tmpa_tl ~ c_space_tl
textsuperscripttl_range:Nnn l_tmpa_tl 1 1
tl_range:Nnn l_tmpa_tl 2 -3
textsubscripttl_range:Nnn l_tmpa_tl -2 -1
ExplSyntaxOff
begindocument
textbfLeading and trailing spaces are not kept
mynewcommandAabcde
mynewcommandAa some text that can contain textitother commands cd
bigskip
textbfLeading and trailing spaces are kept
mynewcommandBabcde
mynewcommandBa some text that can contain textitother commands cd
enddocument
Más información. La función tl_range:nnn
toma tres argumentos donde el primero es un texto, el segundo y el tercero son números enteros que especifican el rango a extraer; asi que 11
extrae el primer elemento (también puede ser tl_head:n
pero usé la función más compleja para la uniformidad), mientras que -2-1
especifica los dos últimos elementos (con índices negativos, la extracción comienza desde el final); 2-3
especifica el rango desde el segundo elemento hasta el tercero comenzando desde la derecha.
Sin embargo, para mantener los espacios en los límites de las partes extraídas, primero debemos reemplazar los espacios con c_space_tl
, que se expandirá a un espacio, pero no está recortado por las funciones de extracción. la sintaxis de tl_set:Nnn
es lo mismo, solo que el primer argumento tiene que ser una variable tl.
En aras de la variedad, aquí hay una solución basada en LuaLaTeX. Establece una función de Lua que, a su vez, hace uso de la función de Lua string funciones string.sub
y string.len
para cumplir su cometido. También configura un “envoltorio” de LaTeX macro llamado mynewcommand
que expande su argumento una vez antes de pasarlo a la función Lua.
La solución en realidad emplea variantes del Lua. string funciones, unicode.utf8.sub
y unicode.utf8.len
para permitir el argumento de mynewcommand
para ser cualquier válido string de caracteres codificados en utf8. (Por supuesto, para imprimir los personajes en el stringse debe cargar una fuente adecuada.) El argumento de mynewcommand
puede contener primitivas y macros.
% !TEX TS-program = lualatex
documentclassarticle
usepackageluacode % 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
newcommandmynewcommand[1]directluatex.sprint(mycommand(luastringO#1))
begindocument
abcde $to$ mynewcommandabcde
öçäßüéà $to$ mynewcommandöçäßüéà
mynewcommanda some text that can contain textittextbfother commands cd
enddocument
En aras de la complejidad, muestro cómo resolver este problema en el nivel primitivo de TeX:
newcountbufflen
defsplitbuff #1#2% #1: number of tokens from end, #2 data
% result: buff, restbuff
edefbuffdetokenize#2 %
edefbuffexpandafterexpandafterprotectspaces buff \
bufflen=0 expandaftersetbufflenbuffend
advancebufflen by-#1relax
ifnumbufflen<0 errmessage#1>buffer lengthfi
ifnumbufflen>0 edefbuffexpandafterexpandaftersplitbuffA buffend
else letrestbuff=buff defbufffi
edeftmpgdefnoexpandbuffbuffgdefnoexpandrestbuffrestbuff%
endlinechar=-1 scantokensexpandaftertmp%
defprotectspaces #1 #2 addtobuff#1%
ifx\#2else addtobuff afterfi protectspaces #2 fi
defafterfi #1fifi#1
longdefaddto#1#2expandafterdefexpandafter#1expandafter#1#2
defsetbufflen #1%
ifxend#1else advancebufflen by1 expandaftersetbufflenfi
defsplitbuffA #1addtobuff#1advancebufflen by-1
ifnumbufflen>0 expandaftersplitbuffA
else expandaftersplitbuffB fi
defsplitbuffB #1enddefrestbuff#1
% --------------- mynewcommand implementation:
deftextup#1$^rm #1$ deftextdown#1$_rm #1$
defmynewcommand#1mynewcommandA#1end
defmynewcommandA#1#2end%
textup#1splitbuff 2#2buff textdownrestbuff
% --------------- test:
mynewcommandabcde
mynewcommanda some text that can contain it other commands cd
bye
Te mostramos las reseñas y valoraciones de los lectores
Recuerda algo, que tienes la capacidad de aclarar tu experiencia si te fue de ayuda.