Comment démarrer emacs avec un répertoire utilisateur personnalisé-emacs

58

Je travaille sur une petite configuration personnalisée Emacs que je souhaite partager avec des amis en tant que référentiel git qu'ils pourront utiliser comme base de référence pour leurs propres configurations futures.

Pour cela, j'ai besoin d'un moyen de tester ma configuration et la solution la plus simple que je puisse trouver est quelque chose comme:

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

Mais je n'arrive pas à le faire fonctionner.

Toute aide très appréciée.

Mattias Bengtsson
la source
3
J'ai relu l' Annexe C Arguments en ligne de commande pour Emacs Invocation mais je n'ai pas trouvé une simple option en ligne de commande permettant de démarrer Emacs avec un .emacs.drépertoire personnalisé à moins que vous ne changiez HOME, ce qui me semble problématique. Les gens ont fourni des solutions de contournement ci-dessous, mais pour moi, cela ressemble à une demande de fonctionnalité très raisonnable pour Emacs lui-même.
David J.
5
@DavidJames Vous avez raison: il existe un élément de liste de souhaits à ce sujet dans le suivi des bogues d'Emacs.
ffevotte
2
Mise à jour: il semble que cette fonctionnalité n'intéresse pas tellement les développeurs Emacs: la demande a été marquée wontfixet fermée dans le suivi des bogues.
ffevotte
@Francesco: J'essaie une approche dynamique qui permet de placer le répertoire utilisateur Emacs en dehors de "~". Peut-être que vous allez essayer.
antonio

Réponses:

39

L’approche de base que j’utilise pour cela consiste à modifier $HOME, en exécutant:

env HOME=/path/to/dir emacs

Vous utilisez alors /path/to/dir/.emacs.d

Vous voudrez peut-être aussi créer un lien symbolique entre tous les fichiers ou répertoires d’importance de ce faux répertoire personnel, afin qu’Emacs puisse les voir.

phils
la source
2
Cela fonctionne parfaitement!
Mattias Bengtsson
8
Selon le manuel Emac - Annexe C Arguments en ligne de commande pour l'invocation Emacs - Variables d'environnement - Variables générales , HOME définit "L'emplacement de vos fichiers dans l'arborescence de répertoires; utilisé pour développer les noms de fichiers commençant par un tilde (~)". " Changer de HOME peut sembler une source de problèmes plus tard, lorsque vous souhaitez naviguer rapidement ou trouver des fichiers dans votre véritable dossier personnel.
David J.
2
David James: Oui, c'est une gêne mineure avec cette approche. Comme mentionné précédemment, vous voudrez peut-être copier ou créer des liens symboliques entre les éléments que vous devez voir Emacs sous ACCUEIL. Si vous souhaitez visiter votre répertoire personnel, vous devez utiliser le chemin absolu (ou vous pouvez également ajouter un lien symbolique à celui-ci). ).
phils
3
Vous pouvez également expérimenter avec la restauration du HOME d'origine dans Emacs lors de l'initialisation. Je n'ai pas essayé cela, mais cela semble valoir la peine d'être examiné.
phils
1
@phils: J'ai essayé ce que vous suggérez.
antonio
39

La façon dont j'utilise pour maintenir plusieurs .emacs.drépertoires en parallèle est la suivante.

  1. emacs est lancé comme ceci:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Chaque init.elfichier commence comme ceci, pour configurer correctement les variables user-init-fileet user-emacs-directory:

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

J'ai trouvé que cela fonctionnait de manière très fiable au cours des derniers mois. Voici quelques remarques:

  • ça casse emacs-init-time, ce qui ne rapporte que le temps nécessaire pour charger la configuration système par défaut, mais pas votre propre fichier init. Si vous souhaitez analyser votre temps d'initialisation, vous devrez le faire d'une autre manière (voir par exemple Comment mesurer les performances du code elisp? ).

  • ce n'est pas équivalent à un démarrage normal et vous devrez vous occuper de quelques points spécifiques. En particulier:

    • after-init-hookest exécuté avant le chargement du fichier init.
    • Le *scratch*tampon est créé avant le chargement du fichier init. Vous devrez changer son mode explicitement (au lieu d'utiliser initial-major-mode).
    • Vous aurez besoin d'appeler explicitement package-initialize; ça ne se fera pas automatiquement
  • le chemin à suivre init.elpeut être choisi arbitrairement; en particulier, le répertoire dans lequel init.elréside ne doit pas être nommé .emacs.d. J'utilise ceci pour avoir par exemple .emacs.d.23côte .emacs.d.24à côte afin de pouvoir basculer entre les différentes versions d’emacs (le système que j’utilise au travail est passablement obsolète et je ne peux pas installer emacs 24 sur toutes les machines que j’utilise).

  • ce flux de travail ne nécessite pas de modification de l'environnement (et en particulier de la HOMEvariable d'environnement, ce qui peut être souhaitable si vous exécutez des programmes à partir d'emacs, ce qui pourrait être affecté par l'environnement modifié).

ffevotte
la source
1
Cela modifie (en effet) l'ordre d'exécution normal, si vous considérez le --loadfichier ed comme étant le fichier init. Pour commencer, il me semble que l'initialisation normale du paquet (par défaut) ne se produira pas et after-init-hookqu'elle s'exécutera avant l'évaluation du fichier (factice) init. Ce sont des choses sur lesquelles vous pouvez travailler, certes, mais sachez que ce n'est pas exactement la même chose qu'Emacs utilisant le chemin spécifié comme fichier init.
phils
2
@phils oui, vous avez raison. Cela change effectivement l'ordre d'exécution normal, et n'équivaut pas à utiliser un fichier init ordinaire. J'ai modifié ma réponse pour refléter votre argument after-init-hook. Mais je dois dire que bien que j'utilise cette technique tout le temps, je n'ai jamais rencontré de problème avec after-init-hook(mais je ne l'utilise pas explicitement, et peut-être que je suis juste chanceux que les paquets que j'utilise ne dépendent pas d'elle) . Qu'entendez-vous par "l'initialisation normale du paquet (par défaut) ne se produira pas"?
ffevotte
1
Je veux dire que command-linecela n'appellera pas package-initializedans cette situation. Vous devrez l’appeler manuellement dans le faux fichier init.
phils
1
@phils merci. J'ai ajouté ceci à la réponse, avec une mention indiquant que le mode majeur initial doit également être pris en charge de manière spécifique.
ffevotte
Cela a fonctionné parfaitement .. Merci !!!
Stryker
15

Vous pouvez créer un lien symbolique ~/.emacs.d , c'est ce que je fais

  1. Essayez de garder ma configuration emacs ~/.emacs.dorientée, c’est-à-dire que tous les fichiers de configuration liés à emacs doivent vivre dans ce dossier.

  2. Ensuite, j'ai un ~/.emacs_configsdossier où tous les dossiers de configuration (essentiellement un dossier avec un init.elet le reste de la configuration) résident, donc mon dossier de configuration personnel sera ~/emacs_configs/iqbal, une distribution prélude sera dans~/emacs_configs/prelude

  3. Très tôt dans ma configuration personnelle emacs, j’ai défini le user-emacs-directorychemin complet de ma configuration en utilisant ce qui suit:

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Enfin, je crée un lien symbolique ~/.emacs.dvers la configuration que je souhaite utiliser, par exemple. pour utiliser ma configuration je vais faire ln -s ~/emacs_configs/iqbal .emacs.d. Si vous voulez essayer une configuration, copiez simplement le dossier de configuration ~/emacs_configs/whatever_nameet changez le lien symbolique

L’avantage de la troisième étape est que emacs démarré avec ma configuration personnelle peut fonctionner sans .emacs.daucune modification, même si je modifie le lien symbolique alors qu’emacs est en cours d’exécution.

Un autre avantage réside dans le HOMEfait que les programmes externes avec lesquels emacs pourrait avoir besoin d’interagir ne sont pas modifiés.

Iqbal Ansari
la source
1
Est-ce que cela signifie que nous pouvons modifier toutes les configurations d'Emac différentes (setq user-emacs-directory (file-truename "~/.emacs.d/"))afin qu'elles puissent toutes fonctionner sans être affectées simultanément?
user1011471
1
En théorie, oui, mais en pratique, certaines bibliothèques pourraient coder en dur le chemin d'accès ~/.emacs.dplutôt que de l'utiliser user-emacs-directory. J'ai rencontré au moins une de ces bibliothèques, mais malheureusement, je ne me souviens plus de son nom.
Iqbal Ansari
7

Une configuration qui ne change pas HOMEou ne fonctionne pas avec des liens symboliques se trouve dans ma réponse à l' adresse https://emacs.stackexchange.com/a/20508/934 . Avec cette configuration, vous pouvez changer le user-emacs-directoryen définissant une variable d’environnement:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

et cela fonctionne même avec le démon.

Uwe Koloska
la source
5

J'ai trouvé cette solution intéressante d' EmacsWiki :

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

(n'utilise pas exactement un répertoire personnalisé, mais fonctionne bien parce que vous avez de toute façon un seul fichier d'entrée)

phunehehe
la source
Pour info, c'est redondant avec un commentaire de @Francesco d'il y a 2 ans.
Bryce
3

Définissez votre var avant de charger votre fichier init:

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

Ensuite, dans votre fichier d'initialisation (dans ce cas ~/.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
la source
Très élégant, mon système préféré, car tout reste dans le domaine d'Emacs, comme il se doit. Je vous remercie.
GSL
1

En développant la réponse de @phils, j'ai créé ce petit script shell (appelé testrun.sh) pour tester ma nouvelle configuration emacs. Cela peut également être utile dans d’autres cas (par exemple, lors du test de modifications apportées à votre fichier init.el qui pourraient endommager 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
Mattias Bengtsson
la source
1

Voici un petit script basé sur la réponse et le commentaire de @ Phil sur la modification de la HOMEvariable d'environnement, puis sa restauration dans 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 "$@"
ffevotte
la source
1

Si le cas d'utilisation concerne le répertoire ".emacs.d" de configuration unique d'Emacs entre tous les utilisateurs d'une machine Linux, cette solution https://emacs.stackexchange.com/a/4258/5488 fonctionnerait dans la plupart des cas, mais dans certains cas. cases emacs essaie d'écrire des fichiers temporaires dans le répertoire user-emacs (tel que le fichier .ido.last). Dans ce cas, si le répertoire de configuration partagé est autorisé en écriture pour tous les utilisateurs, il fonctionnera mais ne constituera peut-être pas la solution souhaitée, car chaque utilisateur du système peut ne pas vouloir partager le même répertoire pour stocker les fichiers temporaires. Dans ce cas, la solution suivante sera la meilleure option.

Le fichier de configuration partagé commun .emacs.d / init.el devrait commencer par

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

Assurez-vous que le fichier de configuration partagé .emacs.d dispose d'une autorisation de lecture pour tous les utilisateurs (aucune autorisation d'écriture n'est nécessaire)

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

Chaque utilisateur aura son propre répertoire "~ / .emacs.d /" mais utilisé uniquement pour enregistrer les fichiers temporaires, mais les packages et autres configurations seront chargés à partir du répertoire de configuration partagé.

Talespin_Kit
la source