Vai al contenuto del sito Vai alla maschera di ricerca

Accessibilità

Colore Dimensione carattere
Home page

I Dizionari di NVDA.\2

di Adriano Barbieri
su uiciechi.it, 2008\03

Seconda parte.

********

Nel precedente articolo dedicato all'argomento abbiamo visto come far matchare, cioè riconoscere, una determinata parola, "vocabolo", inserito in uno dei
tre dizionari messi a nostra disposizione dallo Screen-reader NVDA.

Abbiamo verificato tramite esempi pratici come far matchare un vocabolo interamente in maiuscolo, minuscolo, e a prescindere dall'avere l'iniziale maiuscola.

Questo grazie all'uso delle Regular Expressions o comunemente chiamate Regex.

Per ottenere questo risultato abbiamo utilizzato solamente due caratteri speciali:

• "|", La barra verticale, operatore logico "or", che ci permette una alternativa ed è come dire letteralmente: "oppure".
• "[]", le parentesi quadre, che ci permettono di definire una classe di caratteri a nostra discrezione, dandoci anche modo di delimitare un "Range" (serie),
grazie all'uso del carattere speciale "-" (Trattino).

L'esempio dell'articolo precedente, tanto per rinfrescarci la memoria era un semplice nome di persona: "Sophia".

La Regex usata era: "SOPHIA|[sS]ophia", attenzione che le virgolette servono solo a racchiudere gli esempi.

Tradotta in parole è come aver detto al modulo dizionario: se SOPHIA è in maiuscolo oppure una iniziale che ho racchiuso fra parentesi quadre corrisponde
nonché il resto in minuscolo della parola corrispondono, allora il confronto è "true" (cioè vero), quindi, sostituisci il matching con la parola che trovi
nel campo voce in sostituzione: "sophìa".

La sintassi è valida nella maggior parte dei vocaboli in cui ci imbatteremo durante la lettura di qualsiasi testo e può essere applicata indipendentemente
dalla sintesi vocale in uso.

Nell'articolo precedente v'è anche stilata una lista dei caratteri speciali che possono essere applicati a seconda del risultato che si desidera raggiungere,
alcuni sono composti da semplici lettere in maiuscolo o in minuscolo ma sono sempre preceduti dal carattere: "\" (barra diagonale rovesciata, detta anche
controbarra).

Opportunamente combinati, questi caratteri speciali ci consentono di ottenere risultati di gran lunga superiori rispetto ai diversi sistemi comunemente
adottati da altri Screen-reader.

Alcuni di questi, ci mettono a disposizione un carattere speciale "*", asterisco, che, se posto a destra di un vocabolo, permette di matcharlo anche se
composto da caratteri misti attigui, però, senza possibilità di scelta, e soprattutto non bilateralmente.

La domanda che sorge spontanea a questo punto è: "Con NVDA posso fare altrettanto?".

La risposta è: "Anche di meglio!".

Infatti, possiamo crearci il nostro "asterisco" personale; Grazie all'uso delle parentesi tonde, di un carattere speciale, e vedremo un altra utile funzione
del carattere speciale "\" (barra diagonale rovesciata, detta anche controbarra).

Abbiamo già appurato nell'articolo precedente, come quest'ultimo carattere messo a sinistra di un altro possa assegnare o togliere proprietà di carattere
speciale o ridurlo al suo semplice significato letterale.

Ora vedremo un'altra peculiarità ad esso abbinata, e cioè quella di poter richiamare e conseguentemente far vocalizzare alla nostra sintesi una o più parti
dei risultati elaborati e memorizzati nelle rispettive espressioni racchiuse fra parentesi tonde che possono essere presenti in una stringa Regex.

Ogni gruppo di queste espressioni ha un numero logico abbinato, il numero assegnato va' in ordine crescente. Ad esempio, "1", "2","3", eccetera, eccetera,
da sinistra verso destra.

Quando si desidera far vocalizzare il risultato memorizzato di una o più di queste espressioni, basterà usare il numero logico abbinato preceduto dalla:
"\", (barra diagonale rovesciata), ad esempio, nel campo voce in sostituzione scriveremo "\1", "\2", "\3", e così via; E' anche possibile inserire del
testo fra di essi. Di esempi pratici, ce ne sono a iosa nel dizionario che è stato allegato al giornale, inserito nel file completo della rivista.

Prendiamo ad esempio la parola "papera". Sappiamo tutti che la parola "papera" può comprendere: "papere", "paperi", "papero", eccetera.

Un'altro screen reader grazie al suo asterisco ci risolverebbe il problema così: "paper*" e la parola verrebbe correttamente matchata con ogni sua lettera
finale.

Però, se la parola è "paperino", o "paperella", oppure "paperone", eccetera, eccetera,non si avranno i risultati desiderati, ma si avranno solo errori
di
lettura e purtroppo senza la possibilità di metterci una toppa.

NVDA, invece, grazie a una sola Regex fa' questo e altro, in questo modo: "(PAPER|[pP]aper)([aAeEiIoO]\W)".

Tradotto in parole povere, con questa espressione diciamo a NVDA: se trovi la parola "PAPER" in maiuscolo, o in alternativa la stessa parola, ma in minuscolo,
anche se l'iniziale è in maiuscolo, ti ho messo tra parentesi anche due cose che voglio, la prima è un elenco delle lettere accettabili e te le ho definite
in una classe fra parentesi quadre, la seconda è che non vi sia dell'altro attaccato e te l'ho indicato con "\W" (barra diagonale rovesciata, doppiavu
maiuscola), sono tra parentesi tonde perché voglio che ne memorizzi il risultato per me.

Nel campo della voce in sostituzione basta fare così: "pàper\2", in pratica, si mette la parola corretta, in questo caso: "pàper" con la "a" accentata,
mentre se ci si chiede cos'è quel: "\2", barra rovesciata due, la risposta è presto detta.

Quello è il nostro asterisco personalizzato, al modulo avevamo detto di memorizzare qualcosa, no? Questo sistema si usa quando non si sa esattamente di
quale parola si tratterà, cioè lo si sa in parte. Infatti, noi non sappiamo se la parola matchata sarà tutta in maiuscolo, tutta in minuscolo, e con quale
vocale terminerà. Ecco perché gli abbiamo detto di memorizzarselo.

La nostra vocale è stata memorizzata grazie all'uso delle parentesi tonde e, nel nostro caso, inserita nel secondo gruppo. Per mettere la giusta vocale
affiancata alla nostra parola in sostituzione "pàper" abbiamo semplicemente detto di aggiungere ciò che gli è stato imposto di ricordare, (memorizzare),
nel nostro caso ci interessava il risultato dell'espressione racchiusa fra parentesi tonde del secondo gruppo, partendo da sinistra. Ecco il significato
di quel "\2", (barra diagonale rovesciata 2).

La "\W" (barra rovesciata doppiavu maiuscola) serve a impedire che la parola: "paper" abbia appiccicato qualcos'altro oltre a ciò che abbiamo indicato
nella
classe fra parentesi quadre. Questo carattere speciale "\W" accetta solo tutto ciò che non è una parola, a parte i caratteri di spaziatura e tabulazione.
Nel nostro caso tutte le vocali in minuscolo o in maiuscolo sono ammesse, discriminando però la u o qualsiasi altro carattere, o parola, ma non la punteggiatura.

Se ad esempio la parola fosse stata "paperoga", "paperinik", o qualsiasi altra simile, l'ultimo carattere speciale che abbiamo appena visto renderebbe
"false"
(non vera) la condizione, quindi, verrebbe ignorata.

L'esempio precedente potrebbe funzionare anche così: "(PAPER|[pP]aper)(.\W)".

Stessa sintassi, ma al posto della classe fra parentesi quadre abbiamo messo un semplice punto fermo.

Il punto fermo è un carattere speciale, equivalente all'asterisco usato ad esempio in Jaws. Esso infatti accetta un qualsiasi carattere, manon un numero.

Ecco un esempio: "zodiaca". Anche questo vocabolo può variare cambiando la vocale finale "zodiaci", "zodiaco", ma può anche essere "zodiache". E qui c'è
un'acca di troppo; Mentre la parola: "zodiacale" o qualsiasi altra la vorremmo escludere, ecco unapossibile soluzione: "(ZODIAC|[zZ]odiac)(.{1,2}\W)".

Ormai conoscete la sintassi per far matchare parole maiuscole e minuscole con anche l'iniziale. E' sempre quella! La cosa che invece voglio farvi notare
è racchiusa nel secondo gruppo di parentesi tonde, il nostro asterisco personalizzato.

Ormai credo sia chiaro che racchiudere qualcosa fra parentesi tonde, vuol dire al nostro modulo dizionario di memorizzare ilcontenuto per rendercelo disponibile
semplicemente richiamando il numero corrispondente del gruppo, precedendolo con il carattere speciale "\" (barra diagonale rovesciata), ma questa volta
non ho usato un solo punto, ma grazie alle "{}", parentesi graffe, ho indicato un minimo e un massimo di caratteri ignoti, rappresentati dal ".", punto
fermo, nel nostro caso, almeno uno e massimo due.

Attenzione! Usare nel secondo parametro un valore inferiore al primo, non è ammesso. Se si omette il secondo parametro, lasciando la virgola, è come dire
"illimitatamente". Mettere solo un parametro con valore maggiore di zero, vuol dire allo stesso tempo minimo e massimo. Mettere un solo parametro e con
valore zero?, o negativo....?

Se volete divertirvi un pochino, ecco un giochino che potete provare afare tramite il dizionario temporaneo di NVDA.

Apritelo e aggiungete questa voce: "falso([aeiou]{2,4}\W)".

Mettete nel campo voce in sostituzione la seguente stringa: "vero, \1".

Come più volte detto, vi raccomando di non usare anche le virgolette!

aprite il Blocco note e scrivete: "falso".

Se avete fatto caso alla Regex appena immessa nel dizionario temporaneo, certamente avrete notato che cosa si deve aspettare da noi il modulo.

Per far sì che la condizione diventi "vera" occorre che si immetta uno qualsiasi dei caratteri elencati fra le parentesi quadre, ok?

Ma, un minimo di due, fino a un massimo di quattro, giusto?

Quindi è vero se digito almeno due qualsiasi, dei caratteri consentiti nella classe. Ma è altresì vero se ne digito in totale quattro, basta che siano
quelli
consentiti.

E' altresì vero se digito ogni singolo carattere da 2 a quattro volte, uno qualsiasi di quelli consentiti. Oppure almeno quattro dei caratteri consentiti,
ma sempre un minimo di due.

Ora, provate invece a inserire un carattere non compreso nella classe consentita e vedrete che la condizione non sarà più vera, ma falsa e la sintesi ve
lo dirà!

Provate anche a cambiare i valori dei parametri per vedere che succede, e vedrete che non è poi così difficile apprenderne il meccanismo.

Le parentesi graffe si possono ottenere facilmente premendo la combinazione "alt sinistro+123" dal tastierino numerico per la parentesi graffa aperta e
"alt sinistro+125" per la parentesi graffa chiusa.

In pratica il carattere che precede la parentesi graffa aperta subirà l'effetto conteggiato nelle parentesi graffe, nel nostro caso, il carattere speciale
".", punto fermo. Questo sarebbe valido anche se al posto del punto fermo ci fosse un qualsiasi carattere alfabetico o una classe di caratteri racchiusa
fra parentesi quadre. In pratica, verrebbero accettati un numero minimo ed un numero massimo di caratteri della classe definita come indicato dai due numeri
nelle parentesi graffe separati da una virgola.

Attenzione, i numeri non verranno accettati!

Ma torniamo all'esempio "zodiac". Ecco cosa metteremo nel campo della voce in sostituzione: "zodìac\2".

La parola "zodìac" con la "i" accentata, seguita dal richiamo del risultato memorizzato nel secondo gruppo di parentesi tonde.

Anche qui il carattere speciale ci viene in aiuto limitando il matching solo a ciò che abbiamo impostato noi, cioè uno o 2 caratteri qualsiasi in più e
nient'altro. Quindi verrà anche matchata: "zodiache", ma non qualsiasi altra parola più lunga. Ovviamente "zodiacale", "zodiacali", eccetera verranno escluse
e non subiranno alterazioni di sorta. Ciò non impedirà però di matchare: "zodiac" seguita da un massimo di caratteri da noi definiti nella Regex d'esempio
anche se in un ordine invertito, ad esempio con l'acca alla fine.

Ricordate che il punto fermo in se indica "qualsiasi carattere", ma non un numero. Altrimenti, occorre usare una classe che indichi quali caratteri accettare,
e potrebbe essere così: "(ZODIAC|[zZ]odiac)((HE|he)|[aAiIoO]\W)".

In questo caso abbiamo aggiunto: "HE|he", per dire che è consentita la parola: "zodiac" seguita da: "HE" in maiuscolo o "he" in minuscolo, in aggiunta
anche
una lista di vocali minuscole e maiuscole consentite che abbiamo racchiuso nella classe fra parentesi quadre. Affinché l'ultimo carattere speciale "barra
diagonale rovesciata doppiavu maiuscola abbia effetto su tutto il gruppo di caratteri consentiti e da noi definiti, è stato neccessario racchiuderli fra
ulteriori parentesi tonde, altrimenti l'effetto della doppiavu maiuscola avrebbe agito solo sulla classe fra parentesi quadre. avrete notato, infatti,
che ho usato un operatore "| or" per definire due alternative, contenenti rispettivamente il frammento di parola "HE", e "he", in maiuscolo e in minuscolo.
Ecco perché le ho dovute raggruppare fra parentesi tonde nidificate.

Quindi, le parentesi tonde sono molto utili anche per raggruppare qualcosa come del testo, che verrà interpretato nell'ordine da noi digitato, a differenza
di una classe che indica un carattere fra i caratteri.

La voce da mettere nel campo in sostituzione è sempre quella vista in precedenza, ossia: "zodìac\2".

Il nostro asterisco virtuale lo si può usare anche a sinistra del vocabolo, cosa che, vi assicuro, Jaws non fa, a dimostrazione della potenzialità delle
Regex.

Vediamo un po', per esempio, alcune sintesi vocali non leggono bene un nome straniero tipo: "Ross", o "Gibb".

Nella maggior parte dei casi viene letta sillabata "ro s s", o "gi b b".

In lingua italiana, però, la parola: "Ros" può essere contenuta in: "Rosso", "Rossiccio", "Rossano", eccetera eccetera,e la parola: "Gibb" può essere contenuta
in: "Gibbone", giusto?

Allora come facciamo a escludere dal matching quelle parole e specificare che la correzione deve essere fatta solo al nome: "Ross", o "Gibb"?

Un modo è questo: "(\W|^)(ROSS|[rR]oss)(\W)".

il primo gruppo di parentesi tonde, a sinistra del vero vocabolo da matchare serve ad indicare che a sinistra del vocabolo non vi sia nulla a parte spaziature,
o punteggiatura, nessun carattere alfanumerico. Ricordatelo, perché: "(\W|^)" vi verrà in soccorso in quei casi di conflittualità di alcune parole,come
ad esempio, "girasole", se nel vostro dizionario aveste in precedenza aggiunto un vocabolo come questo: "asole". La parola, infatti, è contenuta in: "girasole",
potrebbe verificarsi appunto il caso di conflittualità che vi dicevo, e avrebbe priorità la parola più a monte, sì, perché i vocaboli vengono memorizzati
nell'ordine da noi imposto, e in cascata, ecco perché ritengo necessario cercare di mantenere nel nostro dizionario un ordine alfabetico il più approssimato
possibile, ciò ci aiuterà non poco nel "de-bug", (snidare dei conflitti, e vi garantisco che con le Regex capita!

Quindi, quando si inserisce un nuovo vocabolo e sembra non avere effetto, occorre armarsi di un po' di pazienza e usando magari il "blocco note" cercare
la parola che genera il conflitto, e una volta trovata, anteponendole poi: "(W|^)", in modo da indicare che deve essere una parola a se, e non nidificata
in un'altra, fare poi la modifica del caso anche alla voce in sostituzione che si trova dopo la tabulazione, se essa dovesse contenere dei richiami a dei
gruppi di espressioni, occorrerà ovviamente aggiornarli perché ne abbiamo aggiunta una nuova e i numeri logici di riferimento non hanno più ragione di
essere, ad esempio la riga: "(ASOL|[aA]sol)(.\W)        àsol\2".

Se la andassimo a modificare aggiungendo l'espressioncina che avevo descritto, la riga diventerebbe così: "(\W|^)(ASOL|[aA]sol)(.\W)  àsol\3".

Torniamo a noi, come vedete la nostra "\W", (barra diagonale rovesciata doppiavu maiuscola) ci viene in aiuto anche se messa a sinistra.

Subito dopo abbiamo posto un'alternativa tramite il consueto carattere speciale "|" (or), seguito dall'accento circonflesso, l'apice in questo caso indica
che il matching è valido anche se il vocabolo è a inizio linea.

Quindi, abbiamo già scartato che la parola si trovi inserita ad esempio in: "grosso", "infrarossi", "prossimo", eccetera eccetera.

Alla destra del vocabolo invece ancora il nostro carattere magico "\W" (barra diagonale rovesciata doppiavu maiuscola) racchiuso fra parentesi tonde anch'esso.

In totale abbiamo tre gruppi racchiusi fra parentesi tonde, ma a noi servono solo il primo ed il terzo. In essi, sono memorizzati i caratteri separatori
che ci servono. Allora, la nostra voce in sostituzione potrebbe essere: "\1ros\3".

Provate a verificare e vedrete che: "rosso", "grosso", infrarosso", eccetera non subiranno alterazioni.

Ma non abbiamo ancora finito! Infatti, è anche possibile creare il nostro asterisco virtuale nel bel mezzo di un vocabolo; Poniamo il caso di voler matchare
una parola che al suo interno abbia uno spazio, come ad esempio, "juke box", e, ovviamente, vorremmo applicare le nostre solite regole di maiuscolo/minuscolo,
eccetera, eccetera, che ormai abbiamo consolidato. Ecco come è possibile farlo: "((JUKE|[jJ]uke)(\W|)(BOX|[bB]ox))".

Se fra le due parole c'è uno spazio o un carattere di separazione come il trattino o il sottolineato, o addirittura niente, cioè le due parole sono attaccate,
il matching sarà "true", cioè vero ugualmente.

In parole povere, con il nostro asterisco personalizzato che abbiamo posto al centro delle due parole, abbiamo detto che è ammesso un solo carattere separatore
come: (spazio, il trattino, o il sottolineato o la tabulazione, badate bene, uno solo di essi). Infine, notate la barra verticale, (l'operatore or) solo
soletto con niente alla sua destra, appunto, vuol proprio dire letteralmente "oppure niente" e questo permette di matchare le due parole anche se appiccicate.

Faccio notare che se però si volesse fare accettare più di un solo carattere separatore come nell'esempio citato è sempre possibile ricorrere al trucchetto
delle parentesi graffe che abbiamo visto in precedenza; Ripeto, esse ci consentono di definire il numero di ripetizioni consentite del carattere che le
precede, quindi, se si volesse nessun limite si potrebbe fare una piccola modifica alla nostra Regex, ovviamente nel gruppo ove risiede il nostro asterisco
centrale virtuale personalizzato, così: "((JUKE|[jJ]uke)(\W|){1,}(BOX|[bB]ox))".

Una assurdità insomma, ad ogni modo l'incantesimo avrebbe fine nonappena la seconda parola dovesse andare a capo in una nuova linea). Ah!Dimenticavo...
la parola da mettere nel campo in sostituzione in questo caso è: "giubox" e senza tanti fronzoli.

Se invece la "w", è usata in minuscolo, il carattere speciale: "\w", (barra diagonale rovesciata doppia vu) ci permette ovviamente tutto l'opposto.

Essa infatti permette di matchare del testo appiccicato o inserito in una riga di altro testo, ad esempio, volendo matchare il punto fermo presente fra
due parole come: "Tizio@provider.com", si potrebbe fare così: "(\w)\.(\w)".

Come voce in sostituzione mettere: "\1 punto \2".

In parole povere abbiamo detto, se in una riga di testo, nel bel mezzo di questa, trovi il carattere "punto", (notate che il punto è preceduto dalla "\"
barra diagonale rovesciata proprio per rendere il ".", punto fermo, che normalmente è di per sè un carattere speciale, questa volta è un normale carattere
con il suo significato letterale), e voglio che subito dopo del punto vi sia attaccato altro testo.

Se si omettesse la seconda espressione verrebbero anche letti tutti i punti di a capo e di fine paragrafo.

Come avete visto le combinazioni sono infinite e tutto dipende dalla nostra fantasia, e se si rispettano le sintassi si possono ottenere molti risultati
soddisfacenti, e non abbiamo ancora visto tutto! E' poco che ho a che fare con le Regex, ma più ci lavoro su e più mi affeziono, a tal punto che ora mi
ci sono talmente abituato e ora non saprei come farne ameno, senza contare che ho ritrovato un po' il gusto ormai sopito della programmazione, perché in
fin dei conti anche le Regex hanno una sintassi e unaloro logica come in tutti i linguaggi di programmazione.

Adriano Barbieri.

Categorie:
Articolo precedenteArticolo successivoTorna all'indice