I tre vocabolari di NVDA.

Di Adriano Barbieri.

Gli sviluppatori dello ormai diffuso screen reader opensource NVDA, in continua evoluzione, hanno di recente implementato nel codice anche un modulo dizionario,
molto importante per uno screen-reader.

A dire il vero, se ne sentiva la mancanza fin dall'inizio e finalmente ne possiamo fare buon uso. Inoltre, non si tratta di un solo dizionario, ma ve ne
sono ben 3.

Volendo, gli smanettoni possono editarli dal notissimo Blocco note di Windows, semplicemente inserendo su un'unica riga la parola da ricercare, uno spazio
di tabulazione creato con la pressione del tasto tab e, infine, la parola in sostituzione.

Ecco una breve descrizione dei tre file vocabolario di NVDA:

elenco di 3 elementi
1. Dizionario di default: ha priorit su tutti, in pratica ogni vocabolo al suo interno viene elaborato in ugual modo a prescindere dalla sintesi vocale
correntemente in uso. 
2. Dizionario specifico per la voce: viene creato automaticamente all'inserimento del primo vocabolo da parte dell'utente, il nome del file dizionario corrisponder
al nome della sintesi vocale correntemente in uso. Tutti i vocaboli inseriti avranno effetto solo sulla sintesi omonima in uso al momento, la sua priorit
 secondaria, in supporto al dizionario di default. 
3. Dizionario temporaneo: Molto utile per testare gli effetti sui vocaboli che mammano andremo ad inserire poi definitivamente in uno dei permanenti messi
a nostra disposizione. 
fine elenco

I primi due dizionari risiedono nella cartella di installazione di NVDA e precisamente nella cartella userdicts.

Il terzo, invece, ha la particolarit di allocarsi in memoria ram e di non scrivere niente sul nostro hard-disk. In caso di errori e di risultati indesiderati
che in certi casi, soprattutto nell'uso di Regex mal strutturate, rendono incomprensibile l'ascolto della sintesi da non riuscire pi agestirla, sar sufficiente
chiudere NVDA e riavviarlo, per eliminare il dizionario temporaneo dalla memoria e riprovare.

La struttura dei vocabolari di NVDA  alquanto semplice perch il modulo dizionario implementa l'uso delle Regex.

Niente di trascendentale. Le Regex sono espressioni regolari e non sono altro che un linguaggio per descrivere la forma o la sintassi di una stringa. Una
stringa, a sua volta  un testo qualunque, di qualunque lunghezza, una sequenza di caratteri) e null'altro.

Con il vocabolario  possibile effettuare ricerche e, quindi, sostituzioni talvolta molto complesse. Si pu verificare che un testo sia conforme ad alcune
caratteristiche e rispetta una determinata sintassi, come, per esempio, verificare se un testo  un indirizzo email o una URL valida.

In svariati ambienti di programmazione, il motore di ricerca delle Regex usato dal vocabolario di NVDA  una manna dal cielo. Infatti, nel nostro caso,
per trovare delle parole o parti di esse e modificarne la dizione, si rivela uno strumento molto potente.

Sulla rete Internet si possono trovare migliaia di siti dedicati alle Espressioni Regolari. Ecco, ad esempio, un paio di siti che personalmente ho trovato
molto esaustivi:

elenco di 2 elementi
 Il primo  sul sito dedicato al linguaggio di programmazione Python: 
http://www.python.it/doc/articoli/re-0.html 
 Il secondo, sempre riferito al linguaggio Python,  ospitato da Altervista: 
http://fido.altervista.org/RegExp/regex.html 
fine elenco

NOTAbene: talvolta le regex hanno piccole differenze tra un programma e l'altro o tra un linguaggio di programmazione ed un altro ma il loro concetto ed
utilizzo resta sempre lo stesso.

Se provate ad accedere al dizionario di default potrete notare un piccolo gruppo di regex preimpostate, ognuna corredata da una nota descrittiva che aiuta
a capire ulteriormente il loro utilizzo.

Non  mia intenzione dilungarmi in un corso approfondito delle Regex, ma se si desiderasse sfruttare appieno le potenzialit messe a nostra disposizione
dai dizionari di NVDA, sarebbe bene capirne almeno le basi di utilizzo. Il mio consiglio  quello di seguire le spiegazioni che vengono fornite sui due
siti indicati sopra.

Facciamo qualche prova pratica, in modo da rendere bene l'idea.

elenco di 17 elementi
 Apriamo il blocco note di Windows. 
 Scriviamo una parola, ad esempio il nome "sophia". Per questo esempio, la scriviamo tutta in minuscolo. 
 Portiamo il pannello di NVDA in primo piano con la combinazione di tasti: insert+n. 
 Dal men NVDA, scendiamo fino al sottomen: Dizionari, e facciamo invio sulla terza voce, dizionario temporaneo. 
 La finestra che si aprir  del tutto identica a quella deglialtri dizionari, e presenta la lista di tutti i vocaboli inseriti al suo interno. La si pu
scorrere con le frecce verticali, ma, al momento, nel nostro caso sar vuota. 
 Premendo ripetutamente tab ci porteremo sui pulsanti che possiamo usare e che sono: Aggiungi, Modifica, Rimuovi, ok e Cancel. Con esc, si annulla tutto.

 Se facciamo invio su Aggiungi, verranno resi disponibili 3 campi editazione. La sintesi dir voce e il focus sar gi posizionato sul primo campo, quello
giusto per inserire la nostra parola da testare. 
 Inseriamo la parola, cos come l'abbiamo scritta nel blocco note. 
 Premiamo tab per spostarci nel campo Voce in sostituzione. Qui scriviamo la parola corretta, "sopha", usando la i accentata al posto di quella normale.
In questo campo editazione suggerisco di usare sempre parole in minuscolo. 
 Ancora tab e saremo nel terzo campo di editazione, che ci permetter di inserire un commento. Non  obbligatorio, ma quest'ultimo campo  molto utile
perch viene letto per primo durante lo scorrimento nella lista dei vocaboli inseriti e ne sveltisce l'identificazione. Se lo si omette verr letto subito
il campo della parola da correggere, che nella maggior parte dei casi essendo una stringa con caratteri misti verr letta in sillabe rallentandone il riconoscimento
immediato. Quindi, nel campo del commento, sar utile inserire la copia della voce in sostituzione. Questa cosa  facilitata con un copia ed incolla. 
 Facendo un passo indietro con shift pi tab ci troveremo sul campo voce in sostituzione che, nel frattempo, sar stato selezionato in modo automatico.

 Non ci resta che premere control pi C. 
 Premiamo Tab per tornare nel campo del commento. 
 Incollare con control+v. 
 Premere invio su ok o semplicemente invio, e il nostro primo vocabolo sar stato integrato nella lista del vocabolario provvisorio. 
 Ancora invio su ok per confermare e chiudere il dizionario che NVDA inizier subito a sfruttare. 
 Con Alt pi tab portiamo in primo piano il nostro Blocco note e verifichiamo se la nostra parola ora viene vocalizzata correttamente. Vi ricordo che Per
ripetere la lettura della riga corrente basta premere insert+freccia s, ma essendo l'unica riga,come nel nostro caso, anche solo freccia s. 
fine elenco

Se tutto  stato fatto correttamente, saremo sicuramente soddisfatti del risultato.

Adesso proviamo a cambiare la lettera iniziale della nostra parola, mettendo la maiuscola iniziale ed ora il nome Sophia  scritto in modo corretto. Ecco!
il nome non viene pi riconosciuto, perch?

Il motivo  che le Regex sono per default case sensitive, cio, fanno distinzione tra minuscole e maiuscole. Se il testo contenuto nel campo "voce"  testo
semplice, verr ricercata esattamente quella sequenza di caratteri, distinguendo tra maiuscole e minuscole.

elenco di 1 elementi
 Esistono alcuni caratteri particolari che se inseriti all'interno della regex hanno un significato diverso dal loro simbolo e ne vedremo solo alcuni:

fine elenco

"[]", Parentesi quadre, tutti i caratteri all'interno di esse sono accettati in alternativa e le due parentesi si comportano come un singolo carattere.
Possono esserci utili nel nostro esempio.

Torniamo nel dizionario temporaneo, selezioniamo dalla lista la parola inserita in precedenza, e facciamo invio su Modifica. Ci troveremo gi nel campo
"voce".

Modifichiamo la parola racchiudendo l'iniziale fra parentesi quadre. Facciamo in modo che all'interno vi sia lo stesso carattere sia in minuscolo che in
maiuscolo, lasciando fuori il resto, cos: [sS]ophia

Non importa l'ordine dei caratteri dentro le parentesi quadre, a meno che non si metta un trattino, il trattino infatti se usato nel mezzo di numeri o lettere
si comporta da carattere speciale (range), definendo un gruppo ben delimitato di caratteri o numeri, ad esempio, [a-z]

IN questo caso, sono ammessi caratteri minuscoli dalla "a" alla "z".

[A-Z], come sopra, ma saranno accettati solo caratteri maiuscoli.

[1-6], sono ammessi solo i numeri compresi nel range, in questo esempio, solo da uno a sei.

Sono ammesse combinazioni:

[A-F0-9], lettere dalla "A" alla "F" maiuscole e i numeri dallo zero al nove compresi.

Quindi se si vuole che il "-" trattino si comporti come un normale carattere bisogner metterlo subito a sinistra o a destra del gruppo di caratteri compresi
nelle 2 parentesi quadre, o convertito in un carattere normale tramite la barra diagonale rovesciata che vedremo pi tardi.

Chiarito ci, torniamo alla nostra Sophia. In questo modo, la nostra parola specificata nella Regex, sar trovata ed elaborata indipendentemente se ha l'iniziale
minuscola o maiuscola.

Se andiamo nel blocco note lo possiamo verificare, scrivendo sia con la minuscola che con la maiuscola. Funziona!

Non va male, ma se si incontrasse la stessa parola, tutta in maiuscolo non verrebbe trovata. Provate, ve ne rendete subito conto!

Niente paura, abbiamo un altro carattere speciale che ci pu venire in aiuto. "|", la barra verticale, si comporta come un operatore logico "or" che significa
oppure. Permette infatti di aggiungere un'alternativa nella nostra Regex, nel nostro caso in questo modo: SOPHIA|[sS]ophia

La barra verticale si digita con shift pi la controbarra, che si trova proprio sopra il tab, a sinistra del numero 1. Si deve usare shift, perch altrimenti
si otterr la barra diagonale rovesciata, l'altro carattere speciale di cui parler fra poco.

Adesso la nostra prima Regex ha triplicato la sua efficacia. Infatti, ora trover la nostra parola sia tutta in maiuscolo, sia in minuscolo, e indipendentemente
dall'avere l'iniziale minuscola o maiuscola. Vi ricordo che se si chiude NVDA tutto ci che  stato inserito nel dizionario temporaneo andr perduto, ma
una volta ottenuto quello che desideriamo non sar difficile esportarlo in uno dei dizionari permanenti messi a nostra disposizione dallo Screen-reader
con un semplice copia ed incolla.

Vediamo ora il carattere speciale: "\", barra diagonale rovesciata, quella che generalmente chiamiamo controbarra.

Questo carattere ci permette di definire un carattere speciale alla stregua di un qualsiasi carattere normale, ma se usato con alcuni caratteri normali
gli assegna le propriet di un carattere speciale. Mi spiego meglio con qualche esempio del suo utilizzo:

elenco di 14 elementi
 \a minuscola, un carattere di allarme, il carattere ASCII "BEL". 
 \b minuscola, un carattere word boundary, limitatore di parola, oppure backspace se "\b"  dentro una classe di caratteri tra parentesi quadre. 
 \B Maiuscola, un carattere non word boundary. 
 \d Minuscola, un qualunque carattere che sia una cifra. E' equivalente a [0-9] . 
 \D Maiuscola, tutto ci che non  \d. E' equivalente a [^0-9] oppure a [^\d]. 
 \e Minuscola, un carattere di escape, il carattere ASCII "ESC". 
 \f Minuscola, un carattere di form feed, il carattere ASCII "FF". 
 \n Minuscola, un carattere di nuova linea, il carattere ASCII "NL". 
 \r Minuscola, un carattere di carriage return, il carattere ASCII "CR". 
 \s Minuscola, un qualunque carattere che crea spazi, come tabulazione, spazio, nuova linea,eccetera. E' equivalente a [ \f\n\r\t]. 
 \S Maiuscola, tutto ci che non  \s. 
 \t Minuscola, un carattere di tabulazione, il carattere ASCII "HT". 
 \w Minuscola, un qualunque carattere alfanumerico, compreso il carattere sottolineato. E' equivalente a [a-zA-Z0-9_] . 
 \W Maiuscola, tutto ci che non  w;  equivalente a [^a-zA-Z0-9_] o a [^\w]. 
fine elenco

Avete notato l'accento circonflesso "^" in alcune righe?

^ "apice" ha due significati:

elenco di 2 elementi
 se messo all'inizio della regex impone che la parola tra virgolette sia ad inizio linea, cio cominci con quello che segue apice. 
 Se usato con le parentesi quadre e messo prima di un carattere significa tranne il carattere che segue,  una negazione. 
fine elenco

Ecco ulteriori caratteri speciali:

elenco di 6 elementi
 . "punto" qualunque carattere. 
 * "asterisco" accetta zero o pi ripetizioni del carattere precedente. 
 + "pi" accetta una o pi ripetizioni del carattere precedente. 
 [ ] "parentesi quadre" tutti i caratteri all'interno delle [ ] "parentesi quadre" sono accettati. Le due parentesi si comportano come un singolo carattere.

 [^ ] "parentesi quadre con apice" tutti i caratteri tranne quelli all'interno delle [ ] "parentesi quadre" sono accettati. 
 \ "barra rovesciata" tratta il carattere speciale che segue come un normale carattere testuale o viceversa tratta un normale carattere come un carattere
speciale. 
fine elenco

Vediamo allora come sfruttare quest'ultimo carattere. Sicuramente avrete notato che, durante la lettura, ad esempio in Outlook Express, ma anche in altre
applicazioni, vengono vocalizzati caratteri che a lungo andare diventano molto fastidiosi come le parentesi quadre, i trattini, la tilde, il sottolineato,
barre diagonali, e chi pi ne ha pi ne metta. Tra questi caratteri, ce ne sono anche di speciali.

Il carattere "\" barra diagonale rovesciata ci pu venire in aiuto indicando che dovranno essere visti nel loro significato letterale,altrimenti, se usati
da soli nel campo "voce" genererebbero un errore, evidenziato dal tipico suono a due toni.

Dimenticare la chiusura delle parentesi, invece, genererebbe un errore nella sintassi della Regex. Ad esempio, volendo zittire paradossalmente proprio la
barra diagonale inversa, baster anteporre la stessa con se stessa, cos: \\

Nel campo della voce in sostituzione si pu mettere uno spazio se si desidera una piccola pausa, ed  consentito anche niente. Ecco qualche esempio:

elenco di 4 elementi
 \| La barra verticale. 
 \~ La tilde. 
 \- Il trattino. 
 \[\] Le parentesi quadre, notare che  possibile affiancare gli elementi. 
fine elenco

E cos per tutti i caratteri speciali.

Usando le parentesi quadre invece  possibile raggruppare tutta una classe di caratteri, come nell'esempio sotto riportato:

[-_[]\~]

Comodo, vero? Se poi, per un qualche motivo, si volesse ripristinare i caratteri zittiti in precedenza, sempre che la nostra Regex non sia troppo lunga,
baster anteporre il carattere cancelletto. Il "#" indica che tutto quello che lo segue  una semplice nota di commento, quindi, se lo anteporremo alla
Regex precedente, essa sar neutralizzata senza necessariamente doverla rimuovere dal nostro dizionario, alla bisogna, baster modificarla eliminando il
cancelletto per renderla nuovamente operativa.

Ecco un altro uso della barra diagonale rovesciata:

Avendo raggruppato parti di regex in sotto-espressioni con le parentesi tonde, possiamo riferirci ai loro rispettivi risultati, nell'ordine, da sinistra
verso destra, con \1, \2, \3, eccetera.

Esempi di questo tipo di Regex li troviamo anche nel dizionario di default di NVDA, quindi, se andate a leggerlo, vi rendete conto meglio di cosa si tratta.

Ho cercato di essere il pi chiaro possibile, ma non  facile essere sintetico e allo stesso tempo chiaro. Se siete giunti sin qui nella lettura, vuol dire
che siete veramente interessati e penso che piano piano diventerete bravi ad usare i vocabolari di NVDA.

Ovviamente ci sarebbero altri caratteri speciali da esplorare, per questo motivo vi suggerisco caldamente di visitare almeno una volta i link che vi ho
indicato all'inizio di questo articolo.

Quello che segue, invece,  una serie di Regex, che si potrebbero rivelare utili ai fini di correggere alcune vocalizzazioni non desiderate, generate da
alcune sintesi vocali SAPI5. Spero di fare una cosa gradita e, allo stesso tempo,  anche un modo per premiare la vostra pazienza.

Da questo momento in avanti, per semplificare, user come indicazione anteposta alle stringhe:

elenco di 3 elementi
 "v =", senza virgolette, per indicare la voce da ricercare. 
 "vs =", senza virgolette, per indicare la voce in sostituzione. 
 "# ", senza le virgolette, per indicare il commento relativo. 
fine elenco

Le stringhe che seguono "V =" e "vs =" le racchiuder tra virgolette, per comprendere eventuali spazi, ma non devono essere usate nelle regex.

***

Ecco le Regex che possono essere usate in uno dei vocabolari descritti ad inizio articolo:

# correzione pronuncia karati:

- v = "\b[kK]\d?\W".

- vs = " kappa ".

# Correzione pronuncia karati, parte 2:

- v = "((\d)+)[kK]+".

- vs = "\1 kappa ".

elenco di 2 elementi
 Queste 2 regex sono complementari, occorrono entrambe. Inoltre, possono essere sfruttate anche per correggere la pronuncia di grammi, volt, eccetera,
ma occorre cambiare le [kK] con i caratteri [gG], [vV], eccetera. 
 Ovviamente anche i campi "voce in sostituzione", cambiare " kappa " con " gi ", " vi ", eccetera. 
fine elenco

***

# Correzione pronuncia millisecondi:

- v = "MS|[mM]s[- ]?\b".

- vs = "m s ".

***

# Correzione pronuncia ettari:

- v = "[hH]a[ ]?\b".

- vs = "A".

***

# Correzione pronuncia centimetri cubici:

- v = "[ ][cC]{2}|^[cC]{2}".

- vs = "c c".

***

# Correzione vocali accentate:

- v = "a'".

- vs = "".

elenco di 2 elementi
 Ovviamente ripetere con le altre vocali. 
 Potete raggruppare alcuni tipi di vocali accentate simili che potrebbero distorcere la pronuncia, fra parentesi quadre, aggiungendo l'alternativa della
vocale apostrofata che  composta da 2 caratteri, tramite la barra verticale: 
fine elenco

- v = "[]|e'".

- vs = "".

elenco di 1 elementi
 Infatti potreste incontrare vocali accentate con caratteri ascii differenti anche se in apparenza uguali. 
fine elenco

***

# Eccezioni parole brevi con vocale accentata:

- v = "[bB]".

- vs = "be'".

- v = "[pP]".

- v = "po'".

elenco di 1 elementi
 Se avete aggiunto la correzione delle vocali apostrofate per. Quando sono cos brevi  meglio con l'apostrofo. 
fine elenco

***

# Correzione numeri romani:

elenco di 1 elementi
 La "C", la "D", la "L", la "V" e la "X" in maiuscolo, anche in gruppi vengono lette da alcune sintesi vocali come numeri romani. In questo caso  sufficiente
mettere il carattere in minuscolo nel campo in sostituzione, ma occorre racchiudere tra parentesi quadre le lettere nel campo "voce". 
fine elenco

- v = "[X]".

- vs = " x ".

elenco di 1 elementi
 Soprattutto la x e la v maiuscole sono particolarmente ostiche nei men di modifica. 
fine elenco

***

# Lettura del punto fermo:

elenco di 1 elementi
 Se volete sentire la lettura del punto nelle URL o negli indirizzi di posta: 
fine elenco

- v = "(\w)\.(\w)".

- vs = "\1 punto ".

***

# Lettura delle doppie barre nelle URL:

- v = "(\w)\:/{2}(\w)".

- vs = "\1 barra barra \2".

****

Non  stato facile, ma ho provato a creare qualche Regex per vocalizzare alcune faccine espressive solitamente usate nelle chat. Sono alquanto complicate,
ma se qualcuno pi esperto conosce il modo di semplificarle sarebbe meglio. Eccole:

# Faccina che fa l'occhiolino " ;-)":

- v = "[ ]+[;]+[)]| [;][^aA-zZ0-9][)]".

# Faccina disperata " :-((":

- v = "[ ]+[:]+[(]+[(]| [:][^*0-9aA-zZ_.,?!<>\/&%$":()\\][(]{2}[^aA-zZ0-9]".

# Faccina delusa " :-(":

- v = "[ ]+[:]+[(]| [:][^*0-9aA-zZ_.,?!<>\/&%$":()\\][(]{1}[^aA-zZ0-9]".

# Faccina che ride di gusto " :-))":

- v = "[ ]+[:]+[)]+[)]| [:][^*0-9aA-zZ_.,?!<>\/&%$":()\\][)]{2}[^aA-zZ0-9]".

# Faccina sorridente " :-)":

- v = "[ ]+[:]+[)]| [:][^*0-9aA-zZ_.,?!<>\/&%$":()\\][)]{1}[^aA-zZ0-9]".

# Faccina sorpresa " :-O":

- v = "[ ]+[:]+[oO]| [:][^*0-9aA-zZ_.,?!<>\/&%$":()\\][oO]{1}[^aA-zZ0-9]".

# Faccina che pernacchia " :-P":

- v = "[ ]+[:]+[pP]| [:][^*0-9aA-zZ_.,?!<>\/&%$":()\\][pP]{1}[^aA-zZ0-9]".

Tutte queste faccine richiedono che vi sia uno spazio alla loro sinistra. Funzionano anche senza il nasino " :)".

Importante! per funzionare bene devono essere immesse nello stesso ordine, magari nel dizionario di default, in modo da funzionare con qualsiasi sintesi
vocale in uso.

A dimostrazione delle difficolt che si incontrano a gestire la punteggiatura, come gi detto, non  stato facile fare in modo che una frase che finisse
con tali punteggiature e in pi caratteri speciali venissero fraintese come faccine.

Adriano Barbieri.

