Cerchiamo di chiarire in breve come funziona la tastiera in Linux.
A questo scopo è molto utile il programma showkey(1), che permette di controllare il buon funzionamento della tastiera. Si può trovare in ``Il pacchetto kbd'' , assieme ai programmi per la gestione della tabella dei caratteri, loadkeys(1), dumpkeys(1) e una bellissima FAQ che consiglio di leggere. Viene comunque installata di default dalla maggior parte delle distribuzioni, slackware inclusa.
Quando premete un tasto sulla vostra tastiera, il controller interno della stessa spedisce una serie di valori (ScanCodes) al kernel. Esistono in commercio delle tastiere programmabili, ovvero delle tastiere con cui è possibile modificare gli scancodes generati.
Vedremo anche che ci sono molti altri modi meno dispendiosi, oltre che cambiare tastiera, per poter associare effetti diversi ai tasti.
Quando il kernel viene posto in questa modalità da un programma, non fa altro che passare, tali e quali, gli scancodes al programma che ne ha fatto richiesta.
Programmi che hanno questo comportamento sono, per esempio, X e DOOM.
Potete vedere gli scancode della vostra tastiera semplicemente facendo
un showkey -s
.
Altrimenti il kernel converte gli scancode in eventi detti KeyCode composti da un flag, che indica se è un evento di tasto premuto o di tasto rilasciato, e da un numero identificativo del tasto stesso, tra l'altro seguendo l'ordine logico della tastiera, ovvero [ESC]=1, [F1]=2, ... Non esistono combinazioni. Anche il premere il tasto [ALT] o [CTRL] genera un KeyCode, mentre premere in contemporanea più tasti genera semplicemente più KeyCode di pressione corrispondenti.
Questi caratteri possono essere passati direttamente all'applicazione
che ne fa richiesta in KeyCode mode. Non è molto usuale, infatti
l'unica applicazione a me nota è showkey(1) che senza
l'opzione -s
serve proprio a fare vedere i KeyCode.
I KeyCode vengono filtrati dal kernel attraverso la KeyMap, ovvero una tabella di conversione. Non è un eufemismo, si tratta di una particolare tabella, un file di testo, che contiene tutte le conversioni KeyCode->KeySim. Questa conversione genera in uscita caratteri o stringhe (dette sequenze di escape) seguendo lo standard VT100, ovvero lo standard di terminale testo che Linux adotta per i suoi terminali virtuali, o virtual consoles.
Fanno parte di questa categoria la stragrande maggioranza degli applicativi, a partire da shells, editors e programmi vari.
Come abbiamo visto, possiamo agire al livello 3, modificando la KeyMap, per poter ottenere tutto quello che vogliamo.
E' sufficiente impartire il comando loadkeys /usr/lib/kbd/keytables/it.map
per riconfigurare la tastiera. Il file it.map
è ormai presente in
tutte le distribuzioni, correttamente installato e configurato.
Inoltre supporta alcune aggiunte molto comode per i programmatori, come le
parentesi graffe e il carattere tilde ottenuti premendo [AltGr+8],
[AltGr+9] e [AltGr+0] rispettivamente.
Ovviamente la modifica della tabella interessa tutto il sistema, anche se solitamente anche un utente comune può compiere questa operazione. Si consiglia quindi, quando comporti problemi di sicurezza, di impedire l'esecuzione dei programmi citati a utenti diversi da root, agendo sui permessi di esecuzione dei file.
Di solito conviene aggiungere questo comando nel file
/etc/rc.d/rc.local
, in modo che venga eseguito ad ogni avvio del SO.
Altro programma utile oltre al già citato showkey(1) è dumpkey(1) che produce in output la tabella di conversione corrente. Si considerano utili letture le manpages di questi programmi.
Fano parte di questa categoria tutti quei programmi che lavorano con i KeySim generati dal kernel nella maniera descritta prima.
Il problema maggiore, in questi casi, è quello di completare la dotazione di comandi del programma, di modo che il suo uso ne sia semplificato.
tcsh(1) è dotata di un comando che serve ad assegnare delle macro a
dei KeySym, ovvero bindkey
.
Ad esempio, aggiungendo questo nel proprio $(HOME)/.cshrc
(oppure per rendere valida la modifica per tutti gli utenti in
/etc/csh.cshrc
come root) si ottiene la possibilita' di usare i
tasti [Home],[End] e [Canc] con i loro corretti
siglificati:
if ($term == "xterm" || $term == "vt100" \ || $term == "vt102" || $term !~ "con*") then # bind keypad keys for console, vt100, vt102, xterm bindkey "\e[1~" beginning-of-line # Home bindkey "\e[2~" overwrite-mode # Ins bindkey "\e[3~" delete-char # Delete bindkey "\e[4~" end-of-line # End endif
Comunque sempre meglio riguardarsi la man page di tcsh(1) per ulteriori chiarimenti e approfondimenti.
Similmente a quanto fatto per tcsh, aggiungendo nel file
$(HOME)/.inputrc
le seguenti righe:
"\e[1~": beginning-of-line "\e[3~": delete-char "\e[4~": end-of-line
ci si ritrova con i tasti [Home], [Canc], e [Fine] correttamente rispondenti alle funzioni che uno si aspetta.
Anche qui la man page di bash(1) è lettura caldamente consigliata.
Emacs soffre di una grossa problematica. Il tasto [BackSpace] genera in linux il carattere ascii Ctrl-H (o 0x08), che sfortunatamente, da quando esiste emacs sulla terra, è anche il caratere con il quale viene richiamato l'help, e che, per rendere le cose ancora piu' semplici, e' lo stesso che viene generato comunque premendo [Ctrl+H].
Insomma, le scelte sono due. O si rimappa BS su qualche altro tasto, o su qualche combianzione di tasti, oppure si sposta il tasto di help da qualche altra parte.
Ho scelto di seguire la seconda via. I cultori di Emacs non se l'abbiano a a male, questo non vuole essere un golpe...
Emacs 19 ha una funzione del linguaggio interno elisp define-key
che serve proprio ad assegnare i tasti.
In questo modo vedremo di sistemate le cose, ovvero assegnamo al tasto BS il suo vero significato, spostando il tasto per richiamare l'help su qualche altro tasto
Piazzando questo nel proprio $(HOME)/.emacs
:
;; map function keys on PC keyboard (setq term (getenv "TERM")) (if (or (string= "xterm" term) (string= "con" (substring term 0 3)) ; linux consoles (string= "vt100" term) (string= "vt102" term)) (progn (defun my-setkey-hook () (define-key function-key-map "\e[1~" [home]) (define-key function-key-map "\e[2~" [insert]) (define-key function-key-map "\e[3~" [delete]) (define-key function-key-map "\e[4~" [end]) ;; these are just my own sequences ;; so I can use the keys under Emacs (define-key function-key-map "\e[40~" [C-prior]) (define-key function-key-map "\e[41~" [C-next]) ;; function keys: use same mapping as xterm (define-key function-key-map "\e[11~" [f1]) (define-key function-key-map "\e[12~" [f2]) ;; ... (define-key function-key-map "\e[24~" [f12]) (define-key function-key-map "\e[25~" [S-f1]) (define-key function-key-map "\e[26~" [S-f2]) ;; ... (define-key function-key-map "\e[39~" [S-f12]) ) (add-hook 'term-setup-hook 'my-setkey-hook) ) () )
Ovviamente tutto deve essere così com'è, ovvero emacs fa molta differenza tra maiuscolo e minuscolo.
Ora che abbiamo assegnato dei codici ai tasti, dobbiamo assegnare delle
funziondi da eseguire!
Anche qui emacs ci viene in aiuto con il comando interno global-set-key
.
Al solito, aggiungendo questo nel file $(HOME)/.emacs
:
(global-set-key [delete] 'delete-char) (global-set-key [home] 'beginning-of-line) ; you might not want this (global-set-key [end] 'end-of-line) ; nor this (global-set-key [C-prior] 'beginning-of-buffer) (global-set-key [C-next] 'end-of-buffer) (global-set-key [f1] 'help-for-help) ;; ... (global-set-key [S-f12] 'info)
Le cose dovrebbero andare a posto.
Come sempre la lettura della man page di emacs, o meglio del suo help
ipertestuale in formato info e' consigliata per saperne di piu'.
Si ottiene con emacs -f info
.
Il comando lesskey(1) premette di rimappare i tasti per less(1),
che è il pager, ovvero il visualizzatore di file testo che viene
implicitamente usato da man (e da qualche altro centinaio di programmi...).
Aggiungendo le seguenti cose nel proprio $(HOME)/.lessrc
:
# aggiunge la gestione dei tasti cursore a less \e[A back-line \e[B forw-line \e[C next-file \e[D prev-file \eOA back-line \eOB forw-line \eOC next-file \eOD prev-file \e[6~ forw-scroll \e[5~ back-scroll \e[1~ goto-line \e[4~ goto-end
Eseguendo lesskey
il file genererà automaticamente il file .less
con le impostazioni corrette.
Come sempre, la lettura delle man pages di less(1) e lesskey(1) sono letture consigliate.
Come abbiamo già accennato in precedenza, X(1) si riporta in modalità ScanCode, ovvero và ad interagire direttamente con l'hardware, il controller della tastiera.
X inoltre utilizza le sue convenzioni per la gestione dei tasti, ovviamente diversa da quella di Linux.
X associa ad ogni tasto un codice (e fin qui niente di diverso), assieme a dei Modifiers, ovvero dei modificatori, ovvero dei flags che indicano la contemporanea pressione dei tasti CTRL, ALT, SHIFT, META, SUPER, HYPER.
Tutti i codici associati ai tasti possono essere visti nel file /usr/lib/X11/XKeysymDB. Occhio che non è un file di gestione della tastiera, ma solo un database di nomi di tasti!!! Insomma, non picchignate...
Tutte quese cose possono essere anche viste utilizzando il programma xev, che monitorizza e visualizza tutti gli eventi di X.
Ovviamente X fa il possibile per rendere indolore il passaggio dalla console al modo grafico. Cerca di ricavare da linux tutto quello che gli serve per inizializzare il suo driver di tastiera.
Il problema è che sbaglia miseramente, ovviamente sul solito, sfortunato, tasto di [BackSpace].
Bisogna aggiustare le cose a mano, con il programma xmodmap(1), ma vedremo che questo di solito non basta.
Come prima cosa bisogna avvisare X che abbiamo intenzione di usare [AltGr] come modificatore META. (Non vi ricordate? era una di quelle imbarazzanti domande che vi ha posto xf86config(1)...)
A tal fine è bene che ci sia una riga come questa nel vostro XF86Config(1)
Section "Keyboard" [...] LeftAlt Meta RightAlt ModeShift EndSection
Ora non resta che modificare i KeySym associati a BS e DEL.
Ovviamente xmodmap(1) non fa altro che associare KeySym a X KeyCodes, come il buon vecchio loadkeys.
Qui, a meno di volersi lanciare in una completa personalizzazione della tastiera, basta correggere la scorretta impostazione dei tasti BS e DEL.
I metodi sono 2:
O si crea un file $(HOME)/.Xmodmap
così fatto:
keycode 22 = BackSpace keycode 107 = Delete
e si fa in modo che il proprio $(HOME)/.xinitrc
o il generale
/var/X11R6/lib/xinit/xinitrc
abbia una riga del tipo
usermodmap=$HOME/.Xmodmap if [ -f $usermodmap ]; then xmodmap $usermodmap fi
Oppure inserire direttamente in $(HOME)/.xinitrc
o
/var/X11R6/lib/xinit/xinitrc
le righe:
# map the <BackSpace> key to the [BackSpace] keysym. xmodmap -e "keycode 22 = BackSpace" # map the <Delete> key to the [Delete] keysym. xmodmap -e "keycode 107 = Delete"
che eseguono direttamente la reinizializzazione.
ATTENZIONE che /var/X11R6/lib/xinit/xinitrc
o
$(HOME)/.xinitrc
devono avere sempre come ultima riga
eseguibile il nome del window manager, di solito fvwm(1), altrimenti
X esce appena eseguito la lista di elementi nei suddetti file.
Consiglio caldamente, se si vuole fare il proprio
$(HOME)/.xinitrc
, di copiarlo da quello generale e fare
SOLO AGGIUNTE!!!
Le X applications di solito vengono configurate via risorse. Le risorse
sono dei file che vengono caricati da X
(/var/X11R6/lib/xinit/.Xresources
, e poi
$HOME/.Xresources
) nel momento dell'avvio, e poi dei file,
che hanno però la stessa sitassi, che vengono caricati da ogni applicazione
e che si trovano tutti in /var/X11R6/lib/app-defaults
.
Queste impostazioni vengono gestite da un resource manager, ovvero un programma che si accolla la responsabilità di inserire, modificare, aggiornare dei valori in un database.
Questo accade nel solito /var/X11R6/lib/xinit/xinitrc
o
$(HOME)/.xinitrc
, precisamente alle righe:
userresources=$HOME/.Xresources sysresources=/var/X11R6/lib/xinit/.Xresources if [ -f $sysresources ]; then xrdb -load $sysresources fi if [ -f $userresources ]; then xrdb -load $userresources fi
Anche qui una lettura delle man page di X(1) e xrdb sono consigliate per chiarirsi le idee.
In questo caso dobbiamo cercare di convertire la pressione dei tasti in X in codici VT100 compatibili, che ormai sappiamo essere lo standard di Linux, da mandare attraverso il programma di emulazione terminale.
Tutto questo NON si applica a rxvt(1), che per adesso resta un caso patologico a parte.
Aggiungendo queste righe nel proprio $(HOME)/.Xresources
:
*VT100.Translations: #override <Key>BackSpace: string(0x7F)\n\ <Key>Delete: string(0x1b) string("[3~")\n\ <Key>Home: string(0x1b) string("[1~")\n\ <Key>End: string(0x1b) string("[4~")\n\ Ctrl<Key>Prior: string(0x1b) string("[40~")\n\ Ctrl<Key>Next: string(0x1b) string("[41~")
tutti i programmi, shell e cose varie che girano nell'xterm si dovrebbero comportare tali quali che in console.
Ma a me non funge niente. Funziona solo la shell (che mi fa end, home e cose varie, ma gli editor non fungono una tega...)
In teoria le cose dovrebbero essere già a posto.
Il problema è che emacs è un programma tasto-dipendente, ovvero fa un uso smodato di combinazioni di tasti.
Il consiglio che vi do è che, se vi trovate con combinazioni di tasti non
mappati o con comportamenti stani, provate a vedere, in un buffer vuoto, che
cosa genera la pressione del tasto usando il comando view-lossage
(di
solito [Ctrl+h] [l]) per vedere che cosa e' stato generato.
Poi non vi resta che aggiungere una riga al vostro file
$HOME/.emacs
visto sopra.
Non funge assolutamente niente. Provare con TextEdit, se ne strafrega delle impostazioni. Continua a generare BS quando si preme DEL.
Mi viene da piangere...
Anche in Motif il tasto [Delete] da molti problemi. Un esempio di queste applicazioni è Mosaic o Netscape. Su consiglio di Ted Stern , basta aggiungere queste righe nel proprio $HOME/.Xdefaults:
! ! To make Backspace delete-previous-character and Delete ! delete-next-character in Motif applications generally ... ! *XmText.translations: #override \n\ ~a <Key>osfBackSpace: delete-previous-character() \n\ ~a <Key>osfDelete: delete-next-character() \n\ a <Key>osfDelete: delete-previous-word() \n\ c <Key>d: delete-next-character() \n\ a <Key>d: delete-next-word() \n\ c <Key>a: beginning-of-line() \n\ c <Key>e: end-of-line() \n\ c <Key>k: delete-to-end-of-line() \n\ a <Key>Left: backward-word() \n\ a <Key>Right: forward-word() *XmTextField.translations: #override \n\ ~a <Key>osfBackSpace: delete-previous-character() \n\ ~a <Key>osfDelete: delete-next-character() \n\ a <Key>osfDelete: delete-previous-word() \n\ c <Key>d: delete-next-character() \n\ a <Key>d: delete-next-word() \n\ c <Key>a: beginning-of-line() \n\ c <Key>e: end-of-line() \n\ c <Key>k: delete-to-end-of-line() \n\ a <Key>Left: backward-word() \n\ a <Key>Right: forward-word()
Ovviamente questo richiede comunque che i tasti [BackSpace] e [Delete] generino i corretti KeySyms.
Capitolo Successivo, Capitolo Precedente
Indice di questo capitolo, Indice generale
Inizio del documento, Inizio di questo Capitolo