- Questo topic ha 10 risposte, 4 partecipanti ed è stato aggiornato l'ultima volta 3 anni, 6 mesi fa da
MatteoF.
-
CreatoreTopic
-
17 Febbraio 2023 alle 8:14 #121444::
Buongiorno a tutti,
avrei due esigenze, riguardanti l’analisi / manipolazione di una stringa di testo.1) vorrei sapere se esiste un condizionale (kernel [tt]LaTeX[/tt] o pacchetto esterno) che verifichi se l’argomento di una macro inizi o meno con una lettera maiuscola.
2) inoltre, ho la necessità di rimuovere l’ultimo carattere dell’argomento di una macro, in modo tale che [tt]\foo{Hello World}[/tt] diventi [tt]Hello Worl[/tt].
Grazie mille,
Matteo
-
CreatoreTopic
-
AutoreRisposte
-
-
18 Febbraio 2023 alle 16:43 #121445::
MatteoF” post=122011Buongiorno a tutti,
avrei due esigenze, riguardanti l’analisi / manipolazione di una stringa di testo.1) vorrei sapere se esiste un condizionale (kernel [tt]LaTeX[/tt] o pacchetto esterno) che verifichi se l’argomento di una macro inizi o meno con una lettera maiuscola (TitleCase).
2) inoltre, ho la necessità di rimuovere l’ultimo carattere dell’argomento di una macro, in modo tale che [tt]\foo{Hello World}[/tt] diventi [tt]Hello Worl[/tt].
Grazie mille,
MatteoCiao Matteo.
Sicuramente si può fare con LaTeX. Sono comandi che puoi ottenere studiando la guida alla programmazione di Enrico. La trovi facilmente.
Ti vorrei proporre la soluzione in Lua (e quindi dovrai passare a compilare con LuaLaTeX). Penso infatti che con questo genere di necessità alla fine Lua è preferibile perché certamente nasce sempre qualche nuova esigenza più facilmente implementabile.Per esempio: controllo se il primo carattere è maiuscolo:
`% !TeX program = LuaLaTeX\documentclass{article}
\directlua{
myLib = {}
function myLib.checkUppercase(s)
assert(type(s)==[[string]])
local code = string.byte(s, 1)
if code > 64 and code < 91 then return true else return false end end } \newcommand{\isUpper}[1]{\directlua{ local s = [==[#1]==] if myLib.checkUppercase(s) then tex.sprint[[yes]] else tex.sprint[[no]] end }} \begin{document} \isUpper{rrr} \isUpper{L} \end{document}` Ciao. R. -
21 Febbraio 2023 alle 6:24 #121446::
Ciao Roberto,
grazie mille per la tua proposta in linguaggio [tt]Lua[/tt]. Pur non conoscendo la programmazione, sono riuscito ad adattare il codice al mio caso d’uso:
`
\directlua{
myLib = {}
function myLib.checkUppercase(s)
assert(type(s)==[[string]])
local code = string.byte(s, 1)
if code > 64 and code < 91 then return false else return true end end } \newcommand{\checkuppercase}[1]{% \directlua{ local s = [==[#1]==] if myLib.checkUppercase(s) then tex.sprint[==[\noindent]==] end} } ` Il tutto funziona, però la tua funzione [tt]myLib.checkUppercase(s)[/tt] ha dei limiti abbastanza importanti. Ovvero: funziona solamente con caratteri ASCII. Quindi fallisce con accenti e segni diacritici :( ` % !TeX program = LuaLaTeX \documentclass{article} \directlua{ myLib = {} function myLib.checkUppercase(s) assert(type(s)==[[string]]) local code = string.byte(s, 1) if code > 64 and code < 91 then return true else return false end end } \newcommand{\isUpper}[1]{\directlua{ local s = [==[#1]==] if myLib.checkUppercase(s) then tex.sprint[[yes]] else tex.sprint[[no]] end }} \begin{document} \isUpper{è} \isUpper{È} \end{document} ` Matteo -
21 Febbraio 2023 alle 7:09 #121447::
Matteo, non sono abbastanza competente per esprimere pareri validi né sul codice Lua ti ti ha mandato Roberto né sulle funzioni per la manipolazione delle token list del linguaggio LaTeX; trovi le istruzioni nel capitolo 15 del manuale interface2 che puoi leggere con texdoc interface3.
In questo capitolo ci sono “funzioni” sia per esamirare il primo token sia per capovolgere la lisa in modo da poter esaminare l’ultimo token della lista originale che è diventato il primo della lista capovolta;
Nel capitolo 16 si parla delle strings, ma queste sono token list che NON contengono lettere ma solo caratteri analfabetici e spazi, mentre le token list possono contenere qualsiasi token, comprese le lettere.
Se non vado errato Enrico scrisse un articolo sulle manipolazioni delle token list e delle cose incredibili che si possono fare con queste cose; di dovrebbe trovare su Ars di qualche anno fa. Lo puoi tovare esaminando la sezione ArsTeXnica di questo forum. Non sono sicuro se mostrasse come si esamina lo stato uppercase rispetto allo stato lower case. Comunque LaTeX3 è capce di manipolare tutti i caratteri, anche quelli non ASCII,Se ti immergi in LATeX3, scopri un mondo incredibilmente diverso da quanto siamo abituati a fare con LaTeX2e.
Per me, visto che i miei neuroni cominciano a fare cilecca, LaTeX3 rimane un sogno, sebbene ne abbia usato molto, o meglio, molte inerfacce fal LaTeX2e e LaTeX3 che permettono di mantenere più o meno lo stesso approccio grammaticale al linguaggio interpretabile dall sottostante interprete.
-
21 Febbraio 2023 alle 7:43 #121448::
MatteoF” post=122019Ciao Roberto,
grazie mille per la tua proposta in linguaggio [tt]Lua[/tt]. Pur non conoscendo la programmazione, sono riuscito ad adattare il codice al mio caso d’uso:
`
\directlua{
myLib = {}
function myLib.checkUppercase(s)
assert(type(s)==[[string]])
local code = string.byte(s, 1)
if code > 64 and code < 91 then return false else return true end end } \newcommand{\checkuppercase}[1]{% \directlua{ local s = [==[#1]==] if myLib.checkUppercase(s) then tex.sprint[==[\noindent]==] end} } ` Il tutto funziona, però la tua funzione [tt]myLib.checkUppercase(s)[/tt] ha dei limiti abbastanza importanti. Ovvero: funziona solamente con caratteri ASCII. Quindi fallisce con accenti e segni diacritici :( ` % !TeX program = LuaLaTeX \documentclass{article} \directlua{ myLib = {} function myLib.checkUppercase(s) assert(type(s)==[[string]]) local code = string.byte(s, 1) if code > 64 and code < 91 then return true else return false end end } \newcommand{\isUpper}[1]{\directlua{ local s = [==[#1]==] if myLib.checkUppercase(s) then tex.sprint[[yes]] else tex.sprint[[no]] end }} \begin{document} \isUpper{è} \isUpper{È} \end{document} ` MatteoCiao Matteo.
Infatti è proprio così. Volevo solo darti uno spunto. Non mi intendo di Unicode così da poterti dare la soluzione. So che all’interno di LuaTeX ci si può avvalere di libreria utf8 con cui puoi manipolare anche stringhe unicode (pagina 63 del manuale “Multibyte string functions”).
Penso anch’io che LaTeX3 possa risolvere i tuoi problemi di elaborazione stringhe come giustamente ha ricordato Claudio.
Tuttavia nella mia esperienza capita che prima o poi il codice vada potenziato per nuove esigenze e che con Lua lo puoi fare con meno limitazioni.
R.
-
22 Febbraio 2023 alle 1:01 #121449::
OldClaudio” post=122021Se ti immergi in LATeX3, scopri un mondo incredibilmente diverso da quanto siamo abituati a fare con LaTeX2e.
È da qualche settimana che ho iniziato a “giocherellare” con LaTeX3/expl3. Ho sempre seguito con interesse l’evoluzione di LaTeX (da ultimo il progetto Tagged PDF), cercando sempre di sfruttarne le potenzialità (al limite, ovviamente, delle mie capacità TeXniche e delle mie necessità pratiche).
Riguardo l’esigenza di una funzione che verifichi il case della prima lettera di un testo, ho trovato qualcosa di simile su tex.stackexchange. Modificando opportunamente la macro, ecco pronto il mio bel condizionale:
`
\prg_new_protected_conditional:Npnn \my_if_first_uppercase:n #1 { T , F , TF }
{
\tl_set:Nx \l_my_testa_tl { \tl_item:nn { #1 } { 1 } }
\tl_set:Nx \l_my_testb_tl { \exp_args:NV \text_uppercase:n \l_my_testa_tl }
\tl_if_eq:NNTF \l_my_testa_tl \l_my_testb_tl
{ \prg_return_true: }
{ \prg_return_false: }
}
`
La logica è la seguente: confrontare la variabile che memorizza la prima lettera di una stringa con la variabile che memorizza la stessa lettera in maiuscolo. Se le due variabili coincidono significa che la prima lettera della stringa è essa stessa una lettera maiuscola ([tt]true[/tt]), diversamente significa che la stringa inizia con una lettera minuscola ([tt]false[/tt]).Di seguito un banale esempio del suo utilizzo:
`
\documentclass{minimal}\ExplSyntaxOn
\prg_new_protected_conditional:Npnn \my_if_first_uppercase:n #1 { T , F , TF }
{
\tl_set:Nx \l_my_testa_tl { \tl_item:nn { #1 } { 1 } }
\tl_set:Nx \l_my_testb_tl { \exp_args:NV \text_uppercase:n \l_my_testa_tl }
\tl_if_eq:NNTF \l_my_testa_tl \l_my_testb_tl
{ \prg_return_true: }
{ \prg_return_false: }
}
\NewDocumentCommand { \mytest } { m }
{
\my_if_first_uppercase:nTF {#1}
{ La~parola~ \emph{#1} ~inizia~con~una~lettera~ \text_uppercase:n {maiuscola}. }
{ La~parola~ \emph{#1} ~inizia~con~una~lettera~minuscola. }
}
\ExplSyntaxOff\begin{document}
\mytest{übersetzung}\mytest{Übersetzung}
\end{document}
`
Per quanto riguarda la mia seconda esigenza (eliminazione dell’ultimo carattere di una stringa) avevo già letto gli «Appunti di programmazione in LaTeX e TeX» di Enrico Gregorio. Effettivamente sono presenti alcuni esempi sul genere (§ 7.2 Trattamento di liste di token in ε-TeX). Come potete immaginare: puro e crudo (e oscuro) linguaggio TeX.
Poco male: in [tt]interface3[/tt] (cap 15) ho già individuato le funzioni opportune… Stay tuned…Matteo
-
25 Febbraio 2023 alle 3:35 #121450::
Riguardo l’eliminazione dell’ultimo carattere di una stringa, a partire da questo post sono riuscito a creare la seguente macro:
`
\cs_new_protected:Npn \my_remove_last:n #1
{
\tl_set:Nx \l_my_remove_last_tl { #1 }
\cs_generate_variant:Nn \tl_reverse:n {f}
\tl_set:Nx \l_my_remove_last_tl { \tl_reverse:f { \tl_tail:f { \tl_reverse:V \l_my_remove_last_tl } } }
\tl_use:N \l_my_remove_last_tl
}
`
Il comando [tt]\tl_tail[/tt] «discards all leading explicit space characters (explicit tokens with character code 32 and category code 10) and the first ⟨item⟩ in the ⟨token list⟩, and leaves the remaining tokens in the input stream» ([tt]interface3[/tt], p. 114). Poco male, nel mio caso d’uso la stringa di testo è una singola parola:
`
\documentclass{minimal}\ExplSyntaxOn
\cs_new_protected:Npn \my_remove_last:n #1
{
\tl_set:Nx \l_my_remove_last_tl { #1 }
\cs_generate_variant:Nn \tl_reverse:n {f}
\tl_set:Nx \l_my_remove_last_tl { \tl_reverse:f { \tl_tail:f { \tl_reverse:V \l_my_remove_last_tl } } }
\tl_use:N \l_my_remove_last_tl
}
\NewDocumentCommand { \mytest } { m }
{
\my_remove_last:n {#1}
}
\ExplSyntaxOff\begin{document}
\mytest{ciao}
\end{document}
`
Matteo
-
25 Febbraio 2023 alle 7:48 #121451
-
28 Febbraio 2023 alle 11:39 #121452::
MatteoF” post=122011Buongiorno a tutti,
avrei due esigenze, riguardanti l’analisi / manipolazione di una stringa di testo.1) vorrei sapere se esiste un condizionale (kernel [tt]LaTeX[/tt] o pacchetto esterno) che verifichi se l’argomento di una macro inizi o meno con una lettera maiuscola.
2) inoltre, ho la necessità di rimuovere l’ultimo carattere dell’argomento di una macro, in modo tale che [tt]\foo{Hello World}[/tt] diventi [tt]Hello Worl[/tt].
Grazie mille,
MatteoDipende molto da che cosa si intende passare. Se è testo arbitrario in UTF-8 in pdflatex, è piuttosto complesso, ma fattibile. Se assumiamo XeLaTeX o LuaLaTeX, è molto più semplice.
`
\prg_new_conditional:Nnn \matteo_if_firstchar_uc:n { p,T,F,TF }
{
\str_if_eq:eeTF { \str_head:e { \str_uppercase:n { #1 } } } { \str_head:n { #1 } } { \prg_return_true: } { \prg_return_false: }
}
\cs_generate_variant:Nn \str_head:n { e }\cs_new:Nn \matteo_remove_last_char:n
{
\tl_range:nnn { #1 } { 1 } { -2 }
}
`Differenze con il tuo codice? Che il condizionale è espandibile, così come la rimozione dell’ultimo carattere.
Esempio completo:
`
\documentclass{article}\ExplSyntaxOn
\prg_new_conditional:Nnn \matteo_if_firstchar_uc:n { p,T,F,TF }
{
\str_if_eq:eeTF
{ \str_head:e { \str_uppercase:n { #1 } } }
{ \str_head:n { #1 } }
{ \prg_return_true: }
{ \prg_return_false: }
}
\cs_generate_variant:Nn \str_head:n { e }\cs_new:Nn \matteo_remove_last_char:n
{
\tl_range:nnn { #1 } { 1 } { -2 }
}\NewDocumentCommand{\testUC}{mmm}
{
\matteo_if_firstchar_uc:nTF { #1 } { #2 } { #3 }
}\NewExpandableDocumentCommand{\testremove}{m}
{
\matteo_remove_last_char:n { #1 }
}\ExplSyntaxOff
\begin{document}
\testUC{Hello World}{VERO}{FALSO}
\testUC{hello world}{VERO}{FALSO}
\testremove{Hello World}
\end{document}
`Ciao
Enrico
-
28 Febbraio 2023 alle 11:41 #121453
-
2 Marzo 2023 alle 22:34 #121454
-
-
AutoreRisposte
- Devi essere connesso per rispondere a questo topic.