Il pre-tutorial di Emacs

Questo documento è inteso come completamento del tutorial di Emacs.

Ad un certo punto vi verrà indicato di leggere il tutorial di Emacs, fatelo prima di continuare nella lettura di questo documento.

La prima cosa che si nota usando Emacs è che usa la tastiera in modo strano. In realtà Emacs è un programma che si avvicina ai 30 anni di età ed è stato scritto ben prima che venisse pensato il famigerato standard CUA.

Da quando è stato integrato con X11 (primi anni '90) il programma è stato dotato di un menù (anche questo non molto standard) che può essere utile come promemoria in quanto presenta la corrispondente combinazione di tasti qualora questa sia definita.

Ultimamente è stata aggiunta una toolbar che non tutti trovano utile ed anzi fanno scomparire per guadagnare spazio sullo schermo. Anche il menu e le scrollbar possono essere nascoste!

(Nota: con la versione 22 un comportamento conforme al CUA è facilmente ottenibile con una voce del menu 'Options').

Il programma, tra le varie voci del menu 'Help' presenta la possibilità di accedere ad un tutorial che permette di familiarizzare con i comandi di Emacs.

Il tutorial è molto chiaro sui comandi, cita i riferimenti mnemonici (mnemonici in inglese, ovviamente) da dare per muoversi dentro Emacs ma dimentica di dire esplicitamente come i comandi sono organizzati.

Emacs è stato uno dei primi editor in tempo reale, nei quali si vedono le modifiche al testo nel momento in cui le si applicano durante l'inserimento del testo: vi ad esempio (per citare un altro grande editor) mantiene la suddivisione in uno stato di inserimento del testo ed uno di input dei comandi di editing.

Il modo che ha Emacs per distinguere tra pressioni di tasti che determinano l'inserimento e quelle che sono comandi di editing Emacs usa due shift particolari, il tasto Control ed il tasto Meta, che sui PC odierni viene mappato sul tasto Alt o su uno dei tasti bandierina.

E su questo punto il tutorial è molto molto chiaro.

Quello che invece non dice chiaramente è che in 30 anni di sviluppo i comandi sono stati associati alla tastiera in modo che quelli più comuni siano i più rapidamente raggiungibili, e man mano che il comando diventa di uso più raro aumentano le operazioni da fare per attivarlo. Avremo quindi:

Bene, fatta questa premessa, che permette di mettere in ordine i comandi, passiamo al tutorial.

Il metodo brutale è usare il menu 'Help' e scegliere il Tutorial (in inglese o nel linguaggio preferito).

Un'altro metodo per avviare il tutorial con il linguaggio preferito è premere Meta X e poi scrivere "help-with-tutorial-spec-language" (premendo spazio si attiverà sia il completamento che l'inserimento del carattere -). Vi verrà chiesto il linguaggio nel quale volete il tutorial.

E' ora di leggersi il tutorial!. Non è obbligatorio fare tutte le prove che vi dicono di fare nel tutorial, l'importante è che impariate i comandi!

B-)

Bene, avete letto il tutorial, avete visto i comandi dati per nome e sopratutto avete visto i comandi C-h k, C-h f e C-h v che permettono di accedere alla documentazione dell'assegnazione di una sequenza di tasti, di un comando dato per nome o di una variabile.

VARIABILE ????? Variabile! Non ho detto che i comandi di Emacs sono funzioni LISP? LISP è un linguaggio di programmazione ed ovviamente ha le variabili :) .

No, non occorre sapere il LISP per usare Emacs. Può però essere utile imparare a balbettare il LISP per comprendere meglio il file di configurazione e imparare a far fare a Emacs le cose ripetitive.

Primo passo, le macro.

Date questa sequenza di comandi:

C-x 2
C-x o
C-x b  

scrivete "*scratch*" al prompt (senza doppi apici)

Ora giocate un po' con le macro. Quando vi siete stancati date i comandi

C-x o
C-x 1  

Provate ora a dare il comando

C-h k
C-x e  

e leggete la documentazione che verrà visualizzata. Scoprirete che potrete dare un nome alle macro per averne più di una definita. Potrebbe essere utile leggervi la documentazione anche di altri comandi, ma per il nostro esempio ci limiteremo a quella di C-x e. Prendiamo le prime 4 righe:

C-x e
runs the command kmacro-end-and-call-macro which  is an interactive compiled Lisp function in `kmacro.el'.
It is bound to C-x e.
(kmacro-end-and-call-macro ARG &optional NO-REPEAT)  

La prima cosa che ci viene detta è che C-x e esegue un comando. A questo punto devo confessarvi una cosa: OGNI pressione di un tasto in Emacs esegue un comando, alla peggio self-insert-command che inserisce nel testo il tasto appena premuto; ebbene sì, Emacs in pratica è sempre e solo in modo comandi :) :) :) :) :)

Lasciando da parte gli scherzi, ci viene detto che il comando è una funzione LISP, ci viene detto in che file è definita (se i sorgenti LISP sono al loro posto potete andarli a vedere seguendo il link) a che tasto è legata e quale è la sua sintassi.

BINGO!

Se la pressione di ogni tasto esegue una funzione LISP allora è possibile tradurre una sequenza di tasti in una funzione e richiamare quella ogni volta che lo vogliamo, salvare la funzione in un file e conservarla...

Un'altra cosa che si può fare è questa. Avete una montagna di file su cui dovete fare la stessa modifica, ad esempio sostituire PINCO con PANCO.

A parole, le operazioni per modificare un file sono:

In sequenze di tasti

C-x f nomefile
M-x replace-string PINCO PANCO (emacs chiede prima cosa rimpiazzare e poi il sostituto)
C-x s
C-x k RETURN (va bene il buffer suggerito da Emacs, quello corrente) 

E andando a guardare i vari comandi e leggendoci le documentazioni fornite abbiamo questa traduzione in invocazioni di funzioni LISP:

(find-file "nomefile")
;; Questo lo insegnano nella documentazione di replace-string
(while (search-forward "PINCO" nil t)
(replace-match "PANCO"))
(save-buffer) 

Rimane l'ultimo. La funzione che ci serve, kill-buffer, si aspetta un buffer come parametro, richiamata interattivamente dall'utente permette di selezionare uno dei buffer presenti. Ma per i nostri usi sarebbe meglio usare un qualcosa che non richieda l'intervento dell'utente, se troviamo il modo di passare a kill-buffer il buffer corrente come oggetto LISP siamo a cavallo.

Facendo una ricerca con l'apropos interno (C-h a) e indicando richiedendo current buffer (buffer corrente) Emacs risponde con una sbrodolata di funzioni e cercando con pazienza si trova la funzione current-buffer che ritorna il buffer corrente come oggetto LISP, quello che ci serve: (kill-buffer (current-buffer))

Nota: non tutti sono avvezzi alla sintassi del LISP, questo sito può aiutarvi: http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-1.html.

Riscriviamo ora le invocazioni delle funzioni insieme a ciò che serve a trasformare il tutto in una funzione

(defun da-pinco-a-panco (file)
;; Vogliamo poterla richiamare dall'interno di emacs
;; Portatevi sulla parola interactive e premete C-h f per
;; vedere a cosa serve e come funziona
(interactive "fFile da correggere:")
;; file non è più una costante, ma un parametro che passiamo
;; alla funzione
(find-file file)
;; Questo lo insegnano nella documentazione di replace-string
(while (search-forward "PINCO" nil t)
(replace-match "PANCO"))
(save-buffer)
(kill-buffer (current-buffer)))

Possiamo usarla interattivamente con

M-x da-pinco-a-panco 

oppure da programma con

(da-pinco-a-panco "nomefile") 

Bene, ora abbiamo una funzione che fa il nostro lavoro per UN SOLO FILE. A che ci serve ? Beh, Emacs è grande e grosso, ed è anche un server. :)

C'è un programma chiamato emacsclient (per versioni di Emacs anteriori alla 22 occorre procurarsi gnuclient e gnudoit) che serve ad usare Emacs come server di editing, carica temporaneamente un file, ve lo fa editare e poi quando date il comando C-x # (ovvero server-edit) lo fa sparire dopo avervi eventualmente chiesto di salvare le modifiche.

E che c'entra ?

Il programma ha una opzione che si chiama --eval e che richiede a Emacs di interpretare una espressione LISP (oppure lo fa il programma gnudoit). Date il comando M-x server-start (gnuserver-start con gnuclient) e provate a dare da shell

$ emacsclient --eval '( + 1 1 )' 

oppure

$ gnudoit '( + 1 1)'

vi verrà risposto 2. Che c'entra col nostro problema di correggere tutti i file che contengono PINCO e sostituendo la parola con PANCO? Beh, ad esempio lo shell script

$ find $PWD -exec grep -q PINCO {} \; \
> -exec emacsclient --eval '( da-pinco-a-panco "{}")' \;

cerca tutti i file che contengono la parola PINCO e chiama la nostra funzione per ognuno di essi... Emacs e la shell hanno fatto da soli il lavoro meccanico e noioso ;-) .

Gianozia Orientale: DEIEmacsTutorial (last edited 2010-03-24 10:24:18 by chiara)