Come avviare emacs con una directory utente-emacs personalizzata


58

Sto lavorando su una configurazione Emacs personalizzata e di piccole dimensioni che voglio condividere con alcuni amici come repository git da utilizzare come base per le loro future configurazioni.

Per questo ho bisogno di un modo per testare la mia configurazione e la soluzione più semplice che posso trovare è qualcosa di simile:

$ emacs --eval "(setq user-emacs-directory \"~/Code/my_custom_emacs.d/\")"

Ma non riesco a farlo funzionare.

Qualsiasi aiuto molto apprezzato.


3
Ho letto l' Appendice C Argomenti della riga di comando per l'invocazione di Emacs ma non ho trovato una semplice opzione della riga di comando per avviare Emacs con una .emacs.ddirectory personalizzata a meno che non cambi HOME, il che mi sembra problematico. Le persone hanno fornito soluzioni alternative di seguito, ma, per me, sembra una richiesta di funzionalità molto ragionevole per Emacs stesso.
David J.


5
@DavidJames Hai ragione: in realtà c'è un elemento della lista dei desideri a riguardo nel bug tracker di Emacs.
ffevotte,

2
Aggiornamento: sembra che questa funzionalità non interessi così tanto agli sviluppatori Emacs: la richiesta è stata taggata wontfixe chiusa nel bug tracker.
ffevotte,

@Francesco: provo un approccio dinamico che consente di mettere la directory Emacs dell'utente fuori da "~". Magari ci proverai.
antonio,

Risposte:


39

L'approccio di base che utilizzo per questo è quello di modificare $HOME, eseguendo:

env HOME=/path/to/dir emacs

Quindi usi /path/to/dir/.emacs.d

Potresti anche voler collegare in modo simbolico qualsiasi file o directory di importanza in questa finta home directory a quelli reali, in modo che Emacs li veda.


2
Funziona perfettamente!
Mattias Bengtsson,

8
Secondo il manuale Emac - Appendice C Argomenti della riga di comando per invocazione di Emacs - Variabili di ambiente - Variabili generali , HOME imposta "La posizione dei file nella struttura della directory; utilizzata per l'espansione dei nomi dei file che iniziano con una tilde (~)." La modifica di HOME sembra una ricetta per problemi in seguito, quando si desidera navigare rapidamente o trovare file dalla propria cartella principale.
David J.

2
David James: Sì, questo è un piccolo fastidio con questo approccio. Come già detto, ti consigliamo di copiare o cose link simbolici che servono Emacs di vedere sotto casa, e se si desidera visitare la vostra home directory vero allora avete bisogno di utilizzare il percorso assoluto (o si potrebbe aggiungere un link simbolico a quello pure ).
phils,

3
Durante l'inizializzazione potresti anche provare a ripristinare la HOME originale in Emacs. Non l'ho provato, ma sembra che valga la pena esaminarlo.
phils,

1
@phils: ho provato quello che mi hai suggerito.
antonio,

39

Il modo in cui uso per mantenere diverse .emacs.ddirectory in parallelo è il seguente.

  1. emacs è iniziato in questo modo:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Ogni init.elfile inizia così, per impostare correttamente le variabili user-init-filee user-emacs-directory:

    (setq user-init-file (or load-file-name (buffer-file-name)))
    (setq user-emacs-directory (file-name-directory user-init-file))
    

Ho scoperto che funziona in modo molto affidabile negli ultimi mesi. Ecco alcune osservazioni:

  • si interrompe emacs-init-time, che riporta solo il tempo necessario per caricare la configurazione di sistema predefinita, ma non il proprio file init. Se sei interessato a confrontare il tuo tempo di inizializzazione, dovrai farlo in un altro modo (vedi ad esempio Come misurare le prestazioni del codice elisp? ).

  • non equivale a una normale partenza e dovrai occuparti di alcuni punti specifici. In particolare:

    • after-init-hookviene eseguito prima del caricamento del file init.
    • Il *scratch*buffer viene creato prima del caricamento del file init. Dovrai cambiare esplicitamente la sua modalità (invece di usarla initial-major-mode).
    • Dovrai chiamare esplicitamente package-initialize; non sarà fatto automaticamente
  • il percorso init.elpuò essere scelto arbitrariamente; in particolare, init.elnon è necessario assegnare un nome alla directory in cui risiede .emacs.d. Lo uso ad esempio .emacs.d.23accanto .emacs.d.24per poter passare da una versione all'altra di emacs (il sistema che sto usando al lavoro è passabilmente obsoleto e non riesco a installare emacs 24 su tutte le macchine che utilizzo).

  • questo flusso di lavoro non richiede la modifica dell'ambiente (e in particolare di HOMEenvvar), che può essere desiderabile se si eseguono programmi dall'interno di emacs, che potrebbero essere influenzati dall'ambiente modificato).


1
Questo (in effetti) altera il normale ordine di esecuzione, se si considera il --loadfile ed come file init. Per i principianti, mi sembra che l'inizializzazione del pacchetto (predefinito) normale non avverrà e after-init-hookverrà eseguita prima che venga valutato il file init (falso). Queste sono cose su cui puoi ovviare, certamente, ma tieni presente che non è esattamente la stessa cosa di Emacs che usa il percorso specificato come file init.
phils,

2
@phils sì, hai ragione. Questo in effetti cambia il normale ordine di esecuzione e non equivale all'utilizzo di un normale file init. Ho modificato la mia risposta per riflettere sul tuo punto after-init-hook. Ma devo dire che sebbene io usi sempre questa tecnica, non ho mai riscontrato alcun problema after-init-hook(ma non lo uso esplicitamente e forse sono solo fortunato che i pacchetti che utilizzo non si basano su di esso) . Cosa intendi con "l'inizializzazione del pacchetto normale (predefinito) non avverrà"?
ffevotte,

1
Voglio dire che command-linenon chiamerà package-initializein quella situazione. Dovresti chiamarlo manualmente nel file init falso.
phils,

1
@phils grazie. Ho aggiunto questo alla risposta, insieme a una menzione che anche la modalità principale iniziale deve essere curata in modo specifico.
ffevotte,

Questo ha funzionato perfettamente .. Grazie !!!
Stryker,

15

Puoi link simbolico ~/.emacs.d , questo è quello che faccio

  1. Cerca di mantenere ~/.emacs.dorientata la mia configurazione di emacs, cioè tutti i file di configurazione relativi a emacs dovrebbero vivere in quella cartella

  2. Quindi ho una ~/.emacs_configscartella in cui vivono tutte le cartelle di configurazione (fondamentalmente una cartella con a init.ele il resto della configurazione), quindi la mia cartella di configurazione personale sarà ~/emacs_configs/iqbal, una distribuzione di preludio sarà in~/emacs_configs/prelude

  3. Molto presto nella mia configurazione personale di emacs ho impostato il user-emacs-directorypercorso completo per la mia configurazione usando quanto segue

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Quindi finalmente collegamento simbolico ~/.emacs.dalla configurazione che voglio effettivamente usare, ad es. per usare la mia configurazione lo farò ln -s ~/emacs_configs/iqbal .emacs.d. Se si desidera provare alcune configurazioni, è sufficiente copiare la cartella di configurazione ~/emacs_configs/whatever_namee modificare il collegamento simbolico

Il vantaggio del terzo passaggio è che emacs avviato con la mia configurazione personale può funzionare inalterato anche se cambio il .emacs.dlink simbolico mentre emacs è in esecuzione.

Un altro vantaggio è dato dal fatto che i HOMEprogrammi esterni non modificati potrebbero non essere interessati da emacs con cui interagire


1
Questo significa che possiamo modificare tutte le configurazioni separate di emacs in (setq user-emacs-directory (file-truename "~/.emacs.d/"))modo che possano funzionare tutte inalterate contemporaneamente?
user1011471

1
In teoria sì, ma in pratica potrebbero esserci alcune librerie che codificano il percorso ~/.emacs.dpiuttosto che utilizzarlo user-emacs-directory. Mi sono imbattuto in almeno una di queste biblioteche, ma sfortunatamente non riesco a ricordare il nome.
Iqbal Ansari,

7

Una configurazione che non cambia HOMEo funziona con i collegamenti simbolici è disponibile nella mia risposta https://emacs.stackexchange.com/a/20508/934 . Con questa configurazione è possibile modificare user-emacs-directoryimpostando una variabile di ambiente:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

e questo funziona anche con il demone.


5

Ho trovato questa soluzione pulita da EmacsWiki :

emacs -q -l ~/my-init-file.el

(non esattamente usando una directory personalizzata, ma funziona bene perché molto probabilmente hai comunque un singolo file di voce)


Cordiali saluti, questo è ridondante con un commento di @Francesco di 2 anni fa.
Bryce,


3

Imposta la tua var prima di caricare il tuo file init:

emacs -q --eval '(setq alt-conf t)' --load ~/.emacs

Quindi, nel tuo file init (in questo caso ~/.emacs):

(defvar alt-conf nil)

(if alt-conf
    (let ((default-directory "~/src/elisp-test/"))
      (normal-top-level-add-subdirs-to-load-path)
      (various-alt-config-stuff)
      (message "Alternate conf"))
  (message "Regular conf"))

Molto elegante, il mio sistema preferito, poiché tutto rimane nel dominio di Emacs, come dovrebbe. Grazie.
gsl

1

Espandendo la risposta di @phils ho creato questo piccolo script di shell (chiamato testrun.sh) per testare la mia nuova configurazione di emacs. Questo potrebbe avere senso farlo anche in altri casi (ad esempio durante il test delle modifiche a init.el che potrebbero interrompere emacs).

#!/bin/bash

cd $(dirname "${BASH_SOURCE[0]}")
[ -d .testrun ] || mkdir .testrun
cd .testrun
[ -h .emacs.d ] || ln -s .. .emacs.d

env HOME=`pwd` emacs

rm .emacs.d
cd ..
rm -rf .testrun

1

Ecco un piccolo script basato sulla risposta e sul commento di @ Phil su come modificare la HOMEvariabile d'ambiente e poi ripristinarla all'interno di Emacs.

#!/bin/bash

# Use it like this:
#   /path/to/this/script  EMACS_USER_DIRECTORY  [OTHER EMACS ARGS]

# You can never be too careful
set -e

# First arg = emacs user directory
#   (get a canonical, absolute path)
EMACS_USER_DIRECTORY=$(readlink -f "$1")
shift
if [ ! -d "${EMACS_USER_DIRECTORY}" ]; then
    echo "Non-existent directory: '${EMACS_USER_DIRECTORY}'"
    exit 1
fi

# Bootstrap directory
BOOTSTRAP=$(mktemp --directory --tmpdir .emacs-bootstrap.XXXXXX)
mkdir "${BOOTSTRAP}/.emacs.d"

# Bootstrap init file
cat >"${BOOTSTRAP}/.emacs.d/init.el" <<EOF
  ;; # Correctly set-up emacs-user-directory
  (setq user-emacs-directory "${EMACS_USER_DIRECTORY}/")
  (setq user-init-file (concat user-emacs-directory "init.el"))

  ;; # Reset the HOME environment variable
  (setenv "HOME" "${HOME}")

  ;; # Load the real init file and clean-up afterwards
  (unwind-protect (load user-init-file)
    (delete-directory "${BOOTSTRAP}" :recursive))
EOF

# Forward remaining arguments to emacs
exec env HOME="${BOOTSTRAP}" emacs "$@"

1

Se il caso d'uso condivide la directory ".emacs.d" della configurazione di single emacs tra tutti gli utenti di una macchina linux, questa soluzione https://emacs.stackexchange.com/a/4258/5488 funzionerebbe nella maggior parte dei casi, ma in alcuni casi emacs tenta di scrivere file temporanei nella directory user-emacs (come il file .ido.last). In questi casi, se la directory di configurazione condivisa ha l'autorizzazione di scrittura per tutti gli utenti, allora funzionerà ma potrebbe non essere la soluzione desiderata poiché ogni utente del sistema potrebbe non voler condividere la stessa directory per archiviare i file temporanei. In tal caso, la seguente soluzione sarà l'opzione migliore.

Il file di configurazione condiviso comune .emacs.d / init.el dovrebbe iniziare con

;; should come before calling package-initialize as it will populate
;; everything under common config "~/.emacs.d/elpa"
(setq user-init-file (or load-file-name (buffer-file-name)))
(setq package-user-dir (concat (file-name-directory user-init-file) "elpa"))

(package-initialize)

Rendere la configurazione condivisa .emacs.d abbia l'autorizzazione di lettura per tutti gli utenti (non è necessario disporre delle autorizzazioni di scrittura)

another_user $ emacs -q --load /path/to/shared/config/.emacs.d/init.el

Ogni utente avrà la propria directory "~ / .emacs.d /" ma verrà utilizzato solo per salvare i file temporanei, ma i pacchetti e le altre configurazioni vengono caricati dalla directory di configurazione condivisa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.