[precedente] Data e ora - Copertina - Ricomp. Kernel [successivo]

Articoli


Usare emacs per editare file tar o zip

Vi è mai capitato di passare un pomeriggio a scompattare file .tar o .zip solo per poter vedere cosa c'è dentro o per cambiare una virgola in un README ? Se normalmente utilizzate emacs potete fare tutto questo molto più velocemente e con meno fatica utilizzando questa piccola estensione, archive-mode.el, scritta in emacs-lisp, il linguaggio di programmazione di emacs. Se invece siete dei fan di vi o di mc allora questo articolo non è roba per voi. Ho scritto questo codice molti anni fa e da allora lo uso praticamente tutti i giorni, spero quindi che possa essere utile anche ad altri.

L'idea

L'idea è quella di definire un major-mode particolare associato ai files di tipo "archivio", cioè .tar, .zip, eccetera, e di programmare emacs in modo che quando cerco di editare uno di questi files venga eseguito un programma esterno in grado di effettuare alcune di operazioni su di esso, tipicamente listarne il contenuto, estrarre un file e, se possibile, memorizzarlo o cancellarlo nell'archivio stesso. In questo modo è possibile gestire qualsiasi tipo di archivio semplicemente definendo un handler in grado di eseguire le funzioni di base sull'archivio stesso. Emacs non conosce nulla del formato interno degli archivi ma si limita semplicemente a lanciare i programmi esterni quando serve. Una soluzione semplice e modulare secondo la vecchia filosofia di UNIX: "quello che non sai o non vuoi fare nel tuo programma fallo chiamando un programma esterno".

Il file archive-mode.el si compone logicamente di sei parti:

Ciascun handler definisce per ogni tipo di archivio le seguenti informazioni: Per esempio per gestire un file tar non compresso posso definire il seguente handler:
(archive-define-handler
 "tar"				  ; file extension(s), in lowercase
 "tar -tv --force-local -f"	  ; list command
 "tar -x --force-local -f"	  ; extract command
 "tar -r --force-local -f"	  ; store command
 "tar --delete --force-local -f"  ; delete command
 ":[0-9][0-9] [0-9]+ "		  ; regexp preceeding filenames
 'tar-mode)			  ; major-mode function
Con questo sistema è possibile definire facilmente nuovi handler senza dover scrivere altro codice in lisp. I tipi di archivi che vengono gestiti attualmente sono: ma questa è la configurazione del mio file, voi dovete ovviamente definire quelli che servono a voi.

Come funziona ?

La funzione archive-define-handler associa a ciascuna estensione del file la funzione che stabilisce il major-mode, utilizzando il meccanismo standard fornito da emacs. Quando cerco di editare un file emacs si accorge di questo e chiama automaticamente tale funzione dopo che il file è stato caricato nel buffer. A questo punto la archive-mode ricerca l'handler associato all'estensione e setta una serie di variabili locali nel buffer, fra cui i comandi in grado di effettuare le funzioni fondamentali sull'archivio. Alla fine viene cancellato il contenuto del buffer e sostituito con la lista dei files dell'archivio ottenuta tramite il comando list-cmd fornito dall'handler. Inoltre viene associata al buffer una particolare keymap, una tabella che associa i tasti ed il mouse ai comandi da eseguire, in modo che quando sposto il cursore su uno dei nomi e premo il tasto "e" o clicco due volte col mouse viene eseguito un comando che estrae il nome del file e richiama il comando extract-cmd per estrarne il contenuto in un nuovo buffer. In modo analogo è possibile gestire i comandi per copiare, salvare o cancellare il file nell'archivio. Siccome tipicamente i vari comandi esterni sono previsti per lavorare su dei files il modulo utilizza una directory di lavoro in cui vengono creati e poi cancellati immediatamente i vari files temporanei.

Una cosa interessante di tutto l'accrocchio è che si possono editare, ma non modificare, anche gli archivi contenuti ricorsivamente in altri archivi, per esempio un file readme.doc in un archivio pippo.zip contenuto nel file pluto.tar.gz. Siccome la gestione ricorsiva delle modifiche sarebbe stata piuttosto complicata ho disabilitato le operazioni di modifica all'interno di archivi ricorsivi. È comunque da tenere presente che non tutti i progammi per gestire i vari tipi di archivi consentono di modificare il contenuto dell'archivio stesso, per esempio non è possibile cancellare o aggiungere files ad archivi compressi. Siccome però questo mi dava molto fastidio ho aggirato il limite scrivendo un piccolo script, tgz, che fa da wrapper al tar standard (dove per standard si intende la versione GNU) in modo da decomprimere il .tgz al volo e ricomprimerlo dopo che il tar ha effettuato le modifiche sul file temporaneo non compresso. Mi sembra superfluo ricordare che il tutto gestisce ovviamente anche i files .tar.bz2, compressi col bzip2. Sempre utilizzando dei piccoli script, debarc e rpmarc, ho fatto in modo di poter gestire in sola lettura anche i pacchetti .deb della Debian e .rpm della RedHat. Purtroppo non vi mostra i files di controllo del pacchetto, ma in compenso potete curiosare all'interno e guardare cosa c'è nei vari files senza dover lanciare a mano i relativi strumenti per la gestione dei pacchetti.


Il codice

Qui potete tovare i sorgenti completi di tutto quello che vi ho raccontato.

Per caricare il modulo in emacs dovete fare a mano il seguente comando:
M-x load-file archive-mode.el
oppure inserire la seguente istruzione nel vostro file ~/.emacs:
(load-file "archive-mode.el")
Gli altri script invece basta salvarli in una directory presente nel vostro PATH e il modulo se li trova da solo (ricordatevi di renderli esguibili). Tutto il codice è ovviamente infettato dal GNU virus (GPL versione 2).

di Massimo Dal Zotto


[precedente] Data e ora - Copertina - Ricomp. Kernel [successivo]