Saltar al contenido

Subíndices y superíndices automatizados

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

ingrese la descripción de la imagen aquí

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:npero 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 mynewcommandque 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.lenpara 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.

ingrese la descripción de la imagen aquí

% !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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *