Jak uruchomić emacsa za pomocą niestandardowego katalogu emacs użytkownika


58

Pracuję nad niestandardową i małą konfiguracją Emacsa, którą chcę udostępnić niektórym znajomym jako repozytorium git, aby mogli oni używać ich jako podstawy dla własnych przyszłych konfiguracji.

W tym celu potrzebuję sposobu na przetestowanie mojej konfiguracji, a najprostszym rozwiązaniem, jakie mogę wymyślić, jest:

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

Ale nie mogę sprawić, żeby działało.

Każda pomoc bardzo doceniana.


3
Przeczytałem powyżej Dodatek C Argumenty wiersza poleceń dla wywoływania Emacsa, ale nie znalazłem prostej opcji wiersza poleceń, aby uruchomić Emacsa z niestandardowym .emacs.dkatalogiem, chyba że zmienisz HOME, co wydaje mi się problematyczne. Ludzie przedstawili poniższe obejścia, ale dla mnie to brzmi jak bardzo rozsądna prośba o funkcje dla samego Emacsa.
David J.


5
@DavidJames Masz rację: w trackerze błędów Emacsa znajduje się pozycja na liście życzeń .
ffevotte

2
Aktualizacja: wygląda na to, że ta funkcja tak bardzo nie interesuje programistów Emacsa: żądanie zostało oznaczone wontfixi zamknięte w module do śledzenia błędów.
ffevotte

@Francesco: Próbuję dynamicznego podejścia, które pozwala umieścić katalog użytkownika Emacsa poza „~”. Być może spróbujesz.
Antonio

Odpowiedzi:


39

Podstawowym podejściem, którego używam do tego jest modyfikacja $HOME, uruchamiając:

env HOME=/path/to/dir emacs

Następnie użyj /path/to/dir/.emacs.d

Możesz również dowiązać dowolne pliki lub katalogi ważne w tym fałszywym katalogu domowym z powrotem do prawdziwych, aby Emacs je zobaczył.


2
To działa idealnie!
Mattias Bengtsson,

8
Zgodnie z Podręcznikiem Emac - Dodatek C Argumenty wiersza poleceń dla wywoływania Emacsa - Zmienne środowiskowe - Zmienne ogólne , HOME ustawia „Lokalizacja twoich plików w drzewie katalogów; służy do rozwijania nazw plików zaczynających się od tyldy (~).” Zmiana HOME brzmi jak przepis na kłopoty, gdy chcesz szybko nawigować lub znajdować pliki z prawdziwego folderu domowego.
David J.

2
David James: Tak, to niewielkie rozdrażnienie przy takim podejściu. Jak wspomniano, będziesz chciał skopiować lub dowiązać symbolicznie rzeczy, które potrzebujesz Emacsa, aby zobaczyć w HOME, a jeśli chcesz odwiedzić swój prawdziwy katalog domowy, musisz użyć ścieżki bezwzględnej (lub możesz również dodać do niego dowiązanie symboliczne ).
phils

3
Możesz także eksperymentować z przywracaniem oryginalnego HOME w Emacsie podczas inicjalizacji. Nie próbowałem tego, ale warto się temu przyjrzeć.
phils

1
@phils: Próbowałem tego, co sugerujesz.
Antonio

39

Sposób, w jaki używam do obsługi kilku .emacs.dkatalogów równolegle, jest następujący.

  1. emacs jest uruchamiany w następujący sposób:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Każdy init.elplik zaczyna się w ten sposób, aby poprawnie skonfigurować zmienne user-init-filei user-emacs-directory:

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

Przekonałem się, że działa to bardzo niezawodnie w ciągu ostatnich miesięcy. Oto kilka uwag:

  • psuje się emacs-init-time, co zgłasza tylko czas potrzebny do załadowania domyślnej konfiguracji systemu, ale nie twój własny plik init. Jeśli chcesz sprawdzić czas inicjalizacji, musisz to zrobić w inny sposób (zobacz na przykład Jak zmierzyć wydajność kodu elisp? ).

  • nie jest to odpowiednik normalnego startu i musisz zadbać o kilka konkretnych punktów. W szczególności:

    • after-init-hookjest uruchamiany przed załadowaniem pliku init.
    • *scratch*Bufor jest tworzony przed plik init załadowany. Musisz jawnie zmienić jego tryb (zamiast używać initial-major-mode).
    • Musisz wyraźnie zadzwonić package-initialize; nie będzie to zrobione automatycznie
  • ścieżka, którą init.elmożna dowolnie wybrać; w szczególności katalog, w którym się init.elznajduje, nie musi być nazwany .emacs.d. Używam tego, aby mieć na przykład .emacs.d.23obok .emacs.d.24, aby móc przełączać się między różnymi wersjami emacsa (system, którego używam w pracy, jest dość przestarzały i nie mogę zainstalować emacsa 24 na wszystkich komputerach, których używam).

  • ten przepływ pracy nie wymaga modyfikowania środowiska (a zwłaszcza środowiska HOMEenvvar), co może być pożądane, jeśli uruchamiasz programy z poziomu emacsa, na które zmodyfikowane środowisko może mieć wpływ).


1
To (w efekcie) zmienia normalną kolejność wykonywania, jeśli rozważasz --loadplik ed jako plik init. Na początek wydaje mi się, że normalna (domyślna) inicjalizacja pakietu nie nastąpi i after-init-hookbędzie działać przed oceną (fałszywego) pliku inicjującego. Są to rzeczy, które możesz obejść, z pewnością, ale pamiętaj, że nie jest to dokładnie to samo, co Emacs używający określonej ścieżki jako pliku init.
phils

2
@phils tak, masz rację. To rzeczywiście zmienia normalną kolejność wykonywania i nie jest równoważne z używaniem zwykłego pliku init. Zredagowałem moją odpowiedź, aby odzwierciedlić twój punkt widzenia after-init-hook. Ale muszę powiedzieć, że chociaż używam tej techniki przez cały czas, nigdy nie spotkałem się z żadnym problemem after-init-hook(ale nie używam jej jawnie i być może mam szczęście, że pakiety, których używam, nie polegają na niej) . Co rozumiesz przez „normalną (domyślną) inicjalizację pakietu nie nastąpi”?
ffevotte,

1
Mam na myśli, że command-linenie zadzwoni package-initializew tej sytuacji. Będziesz musiał wywołać go ręcznie w fałszywym pliku inicjującym.
phils,

1
@phils dzięki. Dodałem to do odpowiedzi wraz ze wzmianką o tym, że należy szczególnie zadbać o początkowy tryb główny.
ffevotte,

To działało idealnie .. Dziękuję !!!
Stryker,

15

Możesz linkować ~/.emacs.d , to właśnie robię

  1. Staraj się, aby moja konfiguracja emacsa była ~/.emacs.dzorientowana, tzn. Wszystkie pliki konfiguracyjne związane z emacsem powinny znajdować się w tym folderze

  2. Następnie mam ~/.emacs_configsfolder, w którym wszystkie foldery konfiguracji (w zasadzie folder z init.elresztą konfiguracji) są aktywne, więc mój osobisty folder konfiguracji będzie ~/emacs_configs/iqbal, dystrybucja preludium będzie w~/emacs_configs/prelude

  3. Bardzo wcześnie w mojej osobistej konfiguracji emacsa ustawiłem user-emacs-directorypełną ścieżkę do mojej konfiguracji, używając następujących poleceń

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Następnie w końcu dowiązuję symbolicznie ~/.emacs.ddo konfiguracji, której faktycznie chcę użyć, np. aby użyć mojej konfiguracji zrobię ln -s ~/emacs_configs/iqbal .emacs.d. Jeśli chcesz wypróbować jakąś konfigurację, po prostu skopiuj folder konfiguracji ~/emacs_configs/whatever_namei zmień dowiązanie symboliczne

Zaletą trzeciego kroku jest to, że emacs rozpoczęty w mojej osobistej konfiguracji może działać bez zmian, nawet jeśli zmienię .emacs.ddowiązanie symboliczne podczas działania emacsa.

Kolejną zaletą jest to, że HOMEnie ulegają zmianie programy zewnętrzne, z którymi emacs może potrzebować interakcji, pozostają niezmienione


1
Czy to oznacza, że ​​możemy dostosować wszystkie osobne konfiguracje emacsa, aby (setq user-emacs-directory (file-truename "~/.emacs.d/"))wszystkie mogły działać jednocześnie bez zmian?
user1011471

1
Teoretycznie tak, ale w praktyce mogą istnieć pewne biblioteki, które ~/.emacs.draczej kodują ścieżkę niż używają user-emacs-directory. Natrafiłem na przynajmniej jedną taką bibliotekę, ale niestety nie pamiętam nazwy.
Iqbal Ansari

7

Konfiguracja, która się nie zmienia HOMElub działa z dowiązaniami symbolicznymi, można znaleźć w mojej odpowiedzi https://emacs.stackexchange.com/a/20508/934 . W tej konfiguracji możesz zmienić user-emacs-directory, ustawiając zmienną środowiskową:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

i to nawet działa z demonem.


5

Znalazłem to fajne rozwiązanie od EmacsWiki :

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

(nie do końca używasz niestandardowego katalogu, ale działa dobrze, ponieważ najprawdopodobniej i tak masz plik pojedynczego wpisu)


Do Twojej wiadomości jest to zbędne z komentarzem @Francesco sprzed 2 lat.
Bryce,


3

Ustaw swój var przed załadowaniem pliku init:

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

Następnie w pliku inicjującym (w tym przypadku ~/.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"))

Bardzo elegancki, mój ulubiony system, ponieważ wszystko pozostaje w domenie Emacsa, tak jak powinno. Dziękuję Ci.
gsl

1

Rozwijając odpowiedź z @phils, stworzyłem ten mały skrypt powłoki (wywoływany testrun.sh) do testowania mojej nowej konfiguracji emacsa. Może to mieć sens również w innych przypadkach (na przykład podczas testowania zmian w pliku init.el, które mogą uszkodzić emacsa).

#!/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

Oto mały skrypt oparty na odpowiedzi i komentarzu @ Phila na temat zmiany HOMEzmiennej środowiskowej, a następnie przywrócenia jej w Emacsie.

#!/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

Jeśli przypadek użycia polega na współużytkowaniu katalogu pojedynczego emacsa „.emacs.d” dla wszystkich użytkowników komputera z systemem Linux, to rozwiązanie https://emacs.stackexchange.com/a/4258/5488 działałoby w większości przypadków, ale w niektórych przypadki emacs próbuje zapisać pliki tymczasowe w katalogu emacs użytkownika (np. plik .ido.last). W takich przypadkach, jeśli udostępniony katalog konfiguracji ma uprawnienia do zapisu dla wszystkich użytkowników, będzie działać, ale może nie być pożądanym rozwiązaniem, ponieważ każdy użytkownik systemu może nie chcieć udostępniać tego samego katalogu do przechowywania plików tymczasowych. W takim przypadku lepszym rozwiązaniem będzie poniższe rozwiązanie.

Wspólny udostępniony plik konfiguracyjny .emacs.d / init.el powinien zaczynać się od

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

Upewnij się, że udostępniona konfiguracja .emacs.d ma uprawnienia do odczytu dla wszystkich użytkowników (nie muszą mieć uprawnień do zapisu)

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

Każdy użytkownik będzie miał swój własny katalog „~ / .emacs.d /”, ale służy tylko do zapisywania plików tymczasowych, ale pakiety i inna konfiguracja są ładowane z udostępnionego katalogu konfiguracji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.