Elisp è un linguaggio interpretato. Puoi inserire codice specifico della versione nel tuo .emacs
, ma proteggerlo testando al momento del caricamento che sta funzionando con la versione corretta.
(if (is-new-feature-available)
(shiny-new-feature)
(old-less-nifty-feature))
Questo codice funzionerà in tutte le versioni perché (shiny-new-feature)
viene valutato solo quando (is-new-feature-available)
restituisce true. Gran parte di questa risposta è dedicata a come implementare (is-new-feature-available)
.
Affrontare diversi set di funzionalità
È meglio verificare se una funzionalità è disponibile piuttosto che testare la versione di Emacs. A volte la funzione potrebbe essere disponibile come pacchetto opzionale. Se vuoi eseguire il codice in XEmacs o altra variante di Emacs, potrebbe aver acquisito le stesse funzionalità in versioni diverse. Utilizzare la funzione boundp
per verificare se è disponibile una variabile e fboundp
per verificare se è disponibile una funzione.
Ad esempio, il frammento seguente associa una chiave per attivare visual-line-mode
o disattivare la disponibilità, e in caso longlines-mode
contrario.
(global-set-key "\eml" (if (fboundp 'visual-line-mode)
'visual-line-mode
'longlines-mode))
A volte, piuttosto che testare la funzionalità, è più semplice eseguire un piccolo pezzo di codice e ignorare eventuali errori dovuti a funzioni indefinite, argomenti non validi, ecc. Non farlo per grandi quantità di codice, poiché ciò renderà il codice molto difficile da eseguire il debug.
Ad esempio, non voglio vedere una barra degli strumenti. Le versioni precedenti di Emacs non li avevano affatto. GNU Emacs e XEmacs hanno aggiunto quella caratteristica in diversi modi e lo hanno reso predefinito. Ecco come li spengo. La set-specifier
funzione è specifica per XEmacs ed default-toolbar-visible-p
è specifica per le versioni abbastanza recenti di Emacs; l'utilizzo condition-case
soddisfa entrambi i requisiti. GNU Emacs fornisce una funzione dedicata, quindi ho semplicemente testato se quella funzione è disponibile.
;; For XEmacs
(condition-case nil
(set-specifier default-toolbar-visible-p nil)
(error nil))
;; For GNU Emacs
(if (fboundp 'tool-bar-mode)
(tool-bar-mode 0))
Alcuni nomi di volti cambiano rispetto alle versioni. Utilizzare facep
per testare la disponibilità di un nome volto.
(let ((face (if (facep 'mode-line) 'mode-line 'modeline)))
(set-face-background face …))
A volte potresti voler caricare un bel pacchetto se presente e non fare nulla se il pacchetto non è disponibile. require
ha un argomento opzionale per questo.
(require 'tex-site nil t) ;; Load AUCTeX if available
Questo argomento è stato introdotto in GNU Emacs 20.4 e non è disponibile in XEmacs, quindi se vuoi andare così indietro, dovrai avvolgerlo condition-case
o usarlo load
(che non controlla le librerie già caricate) .
Limitare le dipendenze della versione alle funzionalità a livello di utente. Non utilizzare le funzioni di programmazione più recenti che non sono disponibili in tutte le versioni che desideri supportare: dovrai fornire una versione di compatibilità per le versioni precedenti ed è più facile mantenere una singola versione.
A volte hai bisogno di una funzionalità in molti luoghi ed è disponibile su tutte le implementazioni che ti interessano, ma in modo diverso. Questo è principalmente il caso se si desidera supportare sia XEmacs che GNU Emacs: avevano una tendenza frustrante a copiare le reciproche funzionalità ma non la loro interfaccia. In questo caso, la definizione di una funzione di compatibilità è più conveniente del test nel punto di utilizzo.
Ad esempio, il codice seguente definisce una funzione che restituisce il sistema di finestre del frame corrente, il modo GNU moderno, il modo XEmac moderno e il modo vecchio stile quando non è possibile combinare i frame terminale e GUI nella stessa istanza.
(defalias 'compat-window-system
(cond
((fboundp 'window-system) #'window-system)
((fboundp 'device-type)
(lambda (&optional frame)
(device-type (frame-device frame))))
(t
(lambda (&optional frame) window-system))))
Dipendenze dall'ambiente
Non c'è molto codice che deve essere dipendente dalla piattaforma. La variabile system-type
indica il sistema operativo. Lo uso esclusivamente per attivare alcuni hack per ms-dos
(sì, i miei file sono così vecchi) e windows-nt
.
Potresti voler aggiungere directory al tuo percorso di ricerca eseguibile ( PATH
), ma di solito è meglio farlo al di fuori di Emacs, nel tuo .profile
sistema per Unix e attraverso il pannello di controllo in Windows. Per verificare se è disponibile un programma esterno, chiamare executable-find
.
Per il codice che deve agire in modo diverso a seconda del tipo di GUI, se presente, controlla window-type
o i suoi successori (vedi sopra).
File di inizializzazione
Per la massima compatibilità, inserisci il tuo codice ~/.emacs
. GNU Emacs ha iniziato a cercare nella ~/emacs.d
versione 22. XEmacs ha iniziato a cercare ~/.xemacs
nella versione 21.4. Un approccio alternativo è inserire ~/.emacs
e completare il codice di compatibilità caricando il file principale. Metti (setq load-home-init-file t)
da qualche parte per evitare che le recenti versioni¹ di XEmac ti chiedano se vuoi spostarti .emacs
nella posizione solo per XEmacs.
Versioni diverse di Emacs possono presentare espansioni diverse e incompatibili per alcune macro. Quindi non condividere i file compilati in byte tra le versioni, compilare i file su ogni macchina.
A volte una funzione è obsoleta, ma vuoi comunque usarla perché è tutto ciò che c'è in qualche altra versione che vuoi supportare. Gli avvisi del compilatore di byte provengono dalla byte-obsolete-variable
proprietà.
(cond
((not (boundp 'desktop-enable))
(defvaralias 'desktop-enable 'desktop-save-mode))
((get 'desktop-enable 'byte-obsolete-variable)
(put 'desktop-enable 'byte-obsolete-variable nil)))
¹ Relativamente parlando, rispetto agli XEmac più vecchi.
window-system
, ecc. Possono essere ragionevolmente risolti qui.