So starten Sie emacs mit einem benutzerdefinierten Benutzer-emacs-Verzeichnis

58

Ich arbeite an einer benutzerdefinierten und kleinen Emacs-Konfiguration, die ich als Git-Repository für einige Freunde freigeben möchte, damit diese sie als Basis für ihre eigenen zukünftigen Konfigurationen verwenden können.

Dafür brauche ich eine Möglichkeit, meine Konfiguration zu testen. Die einfachste Lösung, die ich finden kann, ist etwa:

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

Aber ich kann es scheinbar nicht zum Laufen bringen.

Jede Hilfe sehr geschätzt.

Mattias Bengtsson
quelle
3
Ich habe Anhang C Befehlszeilenargumente für den Aufruf von Emacs durchgelesen, aber ich habe keine einfache Befehlszeilenoption zum Starten von Emacs mit einem benutzerdefinierten .emacs.dVerzeichnis gefunden, es sei denn, Sie ändern HOME, was mir problematisch erscheint. Die Leute haben im Folgenden Problemumgehungen bereitgestellt, aber für mich klingt dies nach einer sehr vernünftigen Feature-Anfrage für Emacs.
David J.
5
@DavidJames Sie haben Recht: In Emacs 'Bug-Tracker gibt es tatsächlich einen Artikel in der Wunschliste dazu .
ffevotte
2
Update: Es sieht so aus, als würde diese Funktion Emacs-Entwickler nicht so sehr interessieren: Die Anfrage wurde markiert wontfixund im Bug-Tracker geschlossen.
ffevotte
@Francesco: Ich versuche einen dynamischen Ansatz, der es erlaubt, das Emacs-Benutzerverzeichnis außerhalb von "~" zu platzieren. Vielleicht werden Sie es versuchen.
Antonio

Antworten:

39

Der grundlegende Ansatz, den ich dafür verwende, besteht darin, Folgendes zu ändern $HOME:

env HOME=/path/to/dir emacs

Sie verwenden dann /path/to/dir/.emacs.d

Möglicherweise möchten Sie auch alle Dateien oder Verzeichnisse, die in diesem falschen Verzeichnis von Bedeutung sind, mit den echten verknüpfen, damit Emacs sie sehen kann.

Phils
quelle
2
Das funktioniert perfekt!
Mattias Bengtsson
8
Laut Emac Manual - Anhang C, Befehlszeilenargumente für Emacs-Aufruf - Umgebungsvariablen - Allgemeine Variablen , setzt HOME "Die Position Ihrer Dateien im Verzeichnisbaum; wird für die Erweiterung von Dateinamen verwendet, die mit einer Tilde (~) beginnen." Das Ändern von HOME klingt später wie ein Rezept für Probleme, wenn Sie schnell in Ihrem echten Home-Ordner navigieren oder nach Dateien suchen möchten .
David J.
2
David James: Ja, das ist ein kleiner Ärger mit diesem Ansatz. Wie bereits erwähnt, sollten Sie oder Symlink Dinge kopieren , die Sie brauchen Emacs unter HOME , um zu sehen, und wenn Sie Ihr echten Home - Verzeichnis besuchen wollen , dann müssen Sie den absoluten Pfad verwenden (oder Sie können einen Symlink zu , dass auch hinzufügen ).
Phils
3
Sie können auch experimentieren, um während der Initialisierung das ursprüngliche HOME in Emacs wiederherzustellen. Ich habe das nicht ausprobiert, aber es scheint einen Blick wert zu sein.
Phils
1
@phils: Ich habe versucht, was Sie vorschlagen.
Antonio
39

Die Art und Weise, wie ich mehrere .emacs.dVerzeichnisse parallel pflege, ist die folgende.

  1. emacs wird so gestartet:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Jede init.elDatei beginnt wie folgt, um die Variablen user-init-fileund korrekt einzurichten user-emacs-directory:

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

Ich habe festgestellt, dass dies in den letzten Monaten sehr zuverlässig funktioniert. Hier einige Anmerkungen:

  • Es bricht ab emacs-init-timeund gibt nur die Zeit an, die zum Laden der Standardsystemkonfiguration benötigt wird, nicht jedoch Ihre eigene Init-Datei. Wenn Sie daran interessiert sind, Ihre Init-Zeit zu messen , müssen Sie dies auf eine andere Weise tun (siehe zum Beispiel Wie messe ich die Leistung von Elisp-Code? ).

  • Es ist nicht gleichbedeutend mit einem normalen Start und Sie müssen sich um einige bestimmte Punkte kümmern. Speziell:

    • after-init-hookwird ausgeführt, bevor die Init-Datei geladen wird.
    • Der *scratch*Puffer wird erstellt, bevor die Init-Datei geladen wird. Sie müssen den Modus explizit ändern (anstatt zu verwenden initial-major-mode).
    • Sie müssen explizit anrufen package-initialize; es wird nicht automatisch gemacht
  • der Weg zu init.elkann beliebig gewählt werden; Insbesondere muss das Verzeichnis, in dem sich init.elbefindet, nicht benannt werden .emacs.d. Ich benutze dies zum Beispiel habe .emacs.d.23neben .emacs.d.24um zwischen verschiedenen Versionen von Emacs umschalten zu können (das System mir bei der Arbeit ist leidlich veraltet, und ich kann nicht Emacs 24 auf allen Rechnern installiere ich verwende).

  • Dieser Workflow erfordert keine Änderung der Umgebung (und insbesondere der HOMEenvvar). Dies kann wünschenswert sein, wenn Sie Programme in Emacs ausführen, die von der geänderten Umgebung betroffen sein könnten.

ffevotte
quelle
1
Dies ändert (in der Tat) die normale Ausführungsreihenfolge, wenn Sie die --loaded-Datei als Init-Datei betrachten. Für den Anfang sieht es für mich so aus, als würde keine normale (Standard-) Paketinitialisierung stattfinden, und sie after-init-hookwird ausgeführt, bevor die (gefälschte) Init-Datei ausgewertet wird. Dies sind Dinge, die Sie sicherlich umgehen können, aber beachten Sie, dass es nicht genau dasselbe ist wie Emacs, das den angegebenen Pfad als Init-Datei verwendet.
Phils
2
@phils ja du hast recht Dies ändert in der Tat die normale Ausführungsreihenfolge und entspricht nicht der Verwendung einer regulären Init-Datei. Ich habe meine Antwort so bearbeitet, dass sie Ihren Standpunkt widerspiegelt after-init-hook. Aber ich muss sagen, dass ich, obwohl ich diese Technik die ganze Zeit benutze, nie auf Probleme gestoßen bin after-init-hook(aber ich benutze sie nicht explizit und vielleicht bin ich nur glücklich, dass die Pakete, die ich benutze, nicht darauf angewiesen sind). . Was meinen Sie mit "normale (Standard-) Paketinitialisierung wird nicht stattfinden"?
ffevotte
1
Ich meine, das command-linewird package-initializein dieser Situation nicht klappen . Sie müssten es manuell in der Fake-Init-Datei aufrufen.
Phils
1
@phils danke. Ich fügte dies der Antwort hinzu, zusammen mit der Erwähnung, dass der anfängliche Hauptmodus ebenfalls speziell berücksichtigt werden muss.
ffevotte
Das hat einwandfrei funktioniert .. Danke !!!
Stryker
15

Du kannst symlinken ~/.emacs.d , das ist was ich tue

  1. Versuchen Sie, meine emacs-Konfiguration so zu gestalten, dass ~/.emacs.dsich alle emacs-bezogenen Konfigurationsdateien in diesem Ordner befinden

  2. Dann habe ich einen ~/.emacs_configsOrdner, in dem alle Konfigurationsordner (im Grunde genommen ein Ordner mit einer init.elund der restlichen Konfiguration) liegen, so dass sich mein persönlicher Konfigurationsordner befindet ~/emacs_configs/iqbal, in dem sich eine Präludiumsdistribution befindet~/emacs_configs/prelude

  3. Sehr früh in meiner persönlichen Emacs-Konfiguration habe ich user-emacs-directoryden vollständigen Pfad zu meiner Konfiguration wie folgt festgelegt

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Dann symlinke ich schließlich ~/.emacs.dzu der Konfiguration, die ich tatsächlich verwenden möchte, z. Um meine Konfiguration zu verwenden, werde ich tun ln -s ~/emacs_configs/iqbal .emacs.d. Wenn Sie eine Konfiguration ausprobieren möchten, kopieren Sie den Konfigurationsordner in ~/emacs_configs/whatever_nameund ändern Sie den Symlink

Der Vorteil des dritten Schritts ist, dass Emacs, die mit meiner persönlichen Konfiguration gestartet wurden, unbeeinträchtigt ausgeführt werden können, auch wenn ich den .emacs.dSymlink ändere, während Emacs ausgeführt wird.

Ein weiterer Vorteil ist, dass die HOMEnicht geänderten externen Programme, mit denen Emacs möglicherweise interagieren müssen, nicht betroffen sind

Iqbal Ansari
quelle
1
Bedeutet dies, dass wir alle separaten Emacs-Konfigurationen (setq user-emacs-directory (file-truename "~/.emacs.d/"))so anpassen können, dass sie alle gleichzeitig ohne Auswirkungen ausgeführt werden können?
user1011471
1
Theoretisch ja, aber in der Praxis gibt es möglicherweise einige Bibliotheken, die den Pfad fest codieren, ~/.emacs.danstatt ihn zu verwenden user-emacs-directory. Ich bin mindestens einer solchen Bibliothek begegnet, kann mich aber leider nicht an den Namen erinnern.
Iqbal Ansari
7

Eine Konfiguration, die sich nicht ändert HOMEoder mit Symlinks funktioniert, finden Sie in meiner Antwort https://emacs.stackexchange.com/a/20508/934 . Mit dieser Konfiguration können Sie Folgendes ändern, user-emacs-directoryindem Sie eine Umgebungsvariable festlegen:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

und das funktioniert sogar mit dem daemon.

Uwe Koloska
quelle
5

Ich habe diese saubere Lösung von EmacsWiki gefunden :

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

(Nicht unbedingt ein benutzerdefiniertes Verzeichnis verwenden, funktioniert aber gut, da Sie wahrscheinlich sowieso nur eine einzige Eintragsdatei haben.)

phunehehe
quelle
Zu Ihrer Information, dies ist überflüssig mit einem Kommentar von @Francesco von vor 2 Jahren.
Bryce
4

Der Patch, mit dem Sie den Speicherort von .emacs.d über die Umgebungsvariable EMACS_USER_DIRECTORY angeben können, ist unter https://debbugs.gnu.org/cgi/bugreport.cgi?bug=15539 verfügbar, wurde jedoch noch nicht zusammengeführt.

Gott
quelle
3

Stellen Sie Ihre Variable ein, bevor Sie Ihre Init-Datei laden:

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

Dann, in Ihrer Init-Datei (in diesem Fall ~/.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"))
yPhil
quelle
Sehr elegant, mein Lieblingssystem, da alles in der Domäne von Emacs bleibt, wie es sollte. Danke.
gsl
1

Um die Antwort von @phils zu erweitern, habe ich dieses kleine Shell-Skript (genannt testrun.sh) erstellt, um meine neue emacs-Konfiguration zu testen. Dies kann auch in anderen Fällen sinnvoll sein (zum Beispiel beim Testen von Änderungen an Ihrem init.el, die Emacs beschädigen könnten).

#!/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
Mattias Bengtsson
quelle
1

Hier ist ein kleines Skript, das auf der Antwort und dem Kommentar von @ Phil zum Ändern der HOMEUmgebungsvariablen und zum anschließenden Wiederherstellen in Emacs basiert .

#!/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 "$@"
ffevotte
quelle
1

Wenn der Anwendungsfall einzelne Emacs - Konfiguration „.emacs.d“ Verzeichnis für alle Benutzer eines Linux - Rechner teilen dann diese Lösung https://emacs.stackexchange.com/a/4258/5488 würde in den meisten Fällen funktionieren, aber in einigen In einigen Fällen versucht emacs, temporäre Dateien in das user-emacs-Verzeichnis zu schreiben (z. B. die Datei .ido.last). In solchen Fällen funktioniert das freigegebene Konfigurationsverzeichnis mit Schreibberechtigung für alle Benutzer, ist jedoch möglicherweise nicht die gewünschte Lösung, da möglicherweise nicht jeder Systembenutzer dasselbe Verzeichnis zum Speichern von temporären Dateien verwenden möchte. In diesem Fall ist die folgende Lösung die bessere Option.

Die gemeinsame Konfigurationsdatei .emacs.d / init.el sollte mit beginnen

;; 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)

Stellen Sie sicher, dass die freigegebene Konfigurationsdatei .emacs.d Leseberechtigung für alle Benutzer hat (Schreibberechtigungen sind nicht erforderlich).

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

Jeder Benutzer hat sein eigenes "~ / .emacs.d /" - Verzeichnis, das jedoch nur zum Speichern der temporären Dateien verwendet wird. Die Pakete und andere Konfigurationsdateien werden jedoch aus dem freigegebenen Konfigurationsverzeichnis geladen.

Talespin_Kit
quelle