Re: Modificare una funzione.

Alberto Buffolino
 

Gabriele Battaglia via Groups.Io, il 15/01/2020 12.11, ha scritto:
Se io volessi che, premendo NVDA+F12, invece di dire 12:09, NVDA dicesse "Sono le 12:09".
Potrei semplicemente localizzare lo script datetime, salvato da qualche parte e modificare la stringa che viene passata alla sintesi, oppure le cose non funzionano esattamente così?
Alberto:
Ciao Gabry,
do per scontato tu intenda come esempio il creare un add-on che faccia quel che dicevi, sovrascrivendo lo script dateTime con una tua implementazione.
La risposta è, come accade spesso: dipende:
Innanzitutto, localizziamo lo script. Son sicuro che tu sai come fare, ma riassumo per tutti. Premiamo NVDA+1 per l'aiuto tastiera, quindi premiamo NVDA+F12, e di nuovo NVDA+1 per uscire dall'aiuto tastiera. Ora apriamo il log, e cercando fra le ultime righe troviamo qualcosa tipo:
***
INFO - inputCore.InputManager._handleInputHelp (14:50:36.507) - MainThread (35444):
Input help: gesture kb(laptop):NVDA+f12, bound to script dateTime on globalCommands.GlobalCommands
***
Dobbiamo cioè trovare il file globalCommands.py fra i sorgenti di NVDA, e studiarci il nostro bello script dateTime nella classe GlobalCommands. Che, al momento, recita così:
***
def script_dateTime(self,gesture):
if scriptHandler.getLastScriptRepeatCount()==0:
text=winKernel.GetTimeFormatEx(winKernel.LOCALE_NAME_USER_DEFAULT, winKernel.TIME_NOSECONDS, None, None)
else:
text=winKernel.GetDateFormatEx(winKernel.LOCALE_NAME_USER_DEFAULT, winKernel.DATE_LONGDATE, None, None)
ui.message(text)
***
A questo punto, si vede subito che le cose non son così ovvie, e bisogna fare alcune considerazioni:
1) potremmo copiare tal quale il codice di dateTime, e quindi ritoccarlo così:
***
def script_dateTime(self,gesture):
if scriptHandler.getLastScriptRepeatCount()==0:
text=winKernel.GetTimeFormatEx(winKernel.LOCALE_NAME_USER_DEFAULT, winKernel.TIME_NOSECONDS, None, None)
text = "Sono le "+text
etc
***
quasi certamente funzionerà. Il problema sarà mantenere la nostra copia di dateTime in linea con quella contenuta dentro NVDA (beninteso, dubito cambi spesso in questo caso, ma la considerazione è valida, più che mai con funzioni ben più complesse);
2) potremmo riscrivere, anziché lo script, la funzione evocata, ovvero winKernel.GetTimeFormatEx. Si può fare, ma bisogna fare attenzione a conservare sempre un riferimento certo alla funzione originale, anche in caso di ricaricamento dei plugin. Per capirsi, l'idea è questa:
***
import globalPluginHandler
import winKernel
from globalCommands import commands

# variabile da non ritoccare
backupFunc = winKernel.GetTimeFormatEx

def newFunc(*args):
text = backupFunc(*args)
text = "Sono le "+text
return text

class GlobalPlugin(globalPluginHandler.GlobalPlugin):

def script_dateTime(self,gesture):
winKernel.GetTimeFormatEx = newFunc
commands.script_dateTime(gesture)
winKernel.GetTimeFormatEx = backupFunc

def terminate(self):
# per quando si ricaricano i plugin
winKernel.GetTimeFormatEx = backupFunc

__gestures = {
"kb:NVDA+F12": "dateTime"
}
***
Il vantaggio di una simile soluzione, per quanto apparentemente più complessa, è che sia la funzione GetTimeFormatEx sia script_dateTime potrebbero cambiare in una parte dell'implementazione, e a noi importerebbe ben poco, a patto che l'output sia rispettato (e, ovviamente, venga usata ancora la funzione che abbiamo rimappato).
In realtà, qui, il metodo terminate non è necessario, in quanto ogni volta modifichiamo e ripristiniamo la funzione all'interno dello stesso script; sarebbe stato importante, invece, se avessimo fornito un comportamento del tipo abilita/disabilita, come in NumberProcessing.
Spero di non essere stato troppo criptico :)
Alberto

Join nvda-it@groups.io to automatically receive all group messages.