Uruchamianie spacemaców wraz ze zwykłymi emacami: jak zachować osobny .emacs.d

32

Chciałbym wypróbować kosmiczne. Ale nie chcę jeszcze przełączać się z mojej zwykłej konfiguracji emacsa, więc chciałbym, aby konfiguracja, która jest obecnie w moim, .emacs.dznajdowała się w jednym katalogu, a równoważna konfiguracja dla spacemaców była w innym katalogu. Nie mam nic przeciwko, jaką nazwę ma każdy katalog.

Czy to możliwe, brakuje chrootów / LD_PRELOAD / innych takich sztuczek? Jak mogę to zrobić?

Croad Langshan
źródło
2
Zobacz także odpowiedź Dana na podobne pytanie dotyczące konfigurowania timera z opcjami, kiedy Emacs się uruchamia: emacs.stackexchange.com/questions/3588/ ... Od tego czasu używam niewielkiej odmiany tej odpowiedzi.
prawnik
1
Być może w kategorii „innych sztuczek” można utworzyć dowiązanie symboliczne spacemacswskazujące na plik wykonywalny emacsa i użyć wartości, (car command-line-args)aby zdecydować, który plik init ma zostać uruchomiony. Zakłada się oczywiście, że korzystasz z systemu uniksowego innego niż OS X. (Sposób, w jaki pakiety aplikacji działają w systemie OS X, utrudnia tę sztuczkę.)
Harald Hanche-Olsen
1
Zobacz inne podejście tutaj: emacs.stackexchange.com/q/4253/780
glucas
2
Właśnie wróciłem, by powiedzieć, że około 18 miesięcy później wciąż jest to powód, dla którego nie nauczyłem się kosmicznych znaków kosmicznych. Miałem kilka drobnych problemów z zaakceptowaną odpowiedzią, po prostu spróbowałem jeszcze raz, nadal prawdziwe. Po dodaniu warstwy org otrzymałem „Definicja funkcji symbolu jest teraz nieważna: pętla”. Nie WIEM, że to część przyczyny, ale to jest właśnie problem: w przypadku dopracowanego projektu „dołączone baterie” wydaje się dziwne, że trzeba coś połączyć, aby go uruchomić, a potem zastanawiać się, czy moja konfiguracja jest obsługiwana? Być może niesprawiedliwe, ale to sprawia, że ​​tracę zaufanie. Może za kolejne 18 miesięcy zostanie to naprawione ...
Croad Langshan

Odpowiedzi:

20

Jedną z opcji jest określenie, którą konfigurację chcesz załadować do ~/.emacspliku. Kiedy Emacs uruchomi się, poszuka takiego pliku, zanim przejrzy ~/.emacs.d/. Aby uzyskać więcej informacji, możesz przeczytać o pliku początkowym w podręczniku Emacsa.

Na przykład możesz utworzyć ~/.spacemacs.di zachować istniejącą wersję ~/.emacs.dtaką, jaka jest. Następnie utwórz, ~/.emacsaby załadować dowolny, który masz ochotę użyć:

(setq use-spacemacs t)   ; or nil 

(when use-spacemacs
  (setq user-emacs-directory "~/.spacemacs.d/"))   ; defaults to ~/.emacs.d/

(load (expand-file-name "init.el" user-emacs-directory))

Jeśli chcesz, możesz wymyślić sposoby przełączania konfiguracji bez modyfikowania pliku .emacs. Na przykład poproś, aby .emacs sprawdził zmienną środowiskową ustawioną w powłoce lub w skrypcie używanym do uruchamiania spacemac:

(setq use-spacemacs (getenv "USE_SPACEMACS"))
glucas
źródło
1
Z pewnością musi istnieć sposób z wnętrza elisp, aby stwierdzić, czy korzystasz z kosmicznych znaków, czy nie? Na przykład, sprawdzając (za pomocą fboundp) funkcji lub polecenia, które jest unikalne dla znaków spacji?
Harald Hanche-Olsen
2
Jasne, ale to nie było pytanie, jak je rozumiałem. Spacemacs to tylko konfiguracja emacs, a OP chce wiedzieć, jak zachować więcej niż jeden niezależny katalog emacs config.
glucas
1
@ HaraldHanche-Olsen, który również mnie zaskoczył, gdy go pobrałem, ale kiedy o nim pomyślałem, miało to sens. Wydaje mi się, że powodem, dla którego się spodziewamy, jest to, że w przypadku większości systemów, aby stworzyć dopracowany „produkt”, taki jak spacemacs, konieczne jest wypróbowanie jakiegoś języka systemów niższego poziomu - ale w emacs jest tak duża rozszerzalność (dzięki elisp) to nie jest konieczne.
Croad Langshan
1
Zaakceptowałem to, ale tak naprawdę nie próbowałem. Teraz, gdy go mam, nie działa tak jak jest: Błąd pliku: Nie można otworzyć pliku ładowania, /home/me/.emacs.d/core/core-load-paths.el - musiałem (setq user-emacs-directory "~/.spacemacs.d/")to zrobić praca (w progngałęzi spacemacs twojej warunkowej). Czy możesz dodać to do swojej odpowiedzi, abym mógł ją ponownie zaakceptować?
Croad Langshan
2
@glucas Jestem na win10, z jakiegoś powodu HOME został przypisany do c: / users / nate. Usunięto zmienną środowiskową i wszystko działało dobrze.
Nathaniel Saxe,
12

Ponieważ przy inicjowaniu jest coś więcej niż tylko ładowanie pliku, a z drugiej strony symlinkowanie .emacs.dlub zmiana HOMEzmian w moim środowisku wykonawczym, zdecydowałem się na wariant zaproponowany przez @glucas. Użyłem kodu z startup.eli dodałem łatkę z # 15539, aby użyć zmiennej środowiskowej do przełączania między różnymi katalogami init. Jeśli nie podano żadnej, używana jest wartość domyślna.

Wystąpił jeden problem z spacemacs: asyncnie wie o zmienionym katalogu init, więc nie może znaleźć potrzebnych plików. Ale problem został ostatnio rozwiązany w metodzie spacemacs: Błąd podczas korzystania z katalogu konfiguracji innego niż .emacs.d · Problem # 3390

Oto moje, ~/.emacsktóre powinny zachowywać się jak oryginalny kod init, ale z konfigurowalnym katalogiem init:

;;; .emacs --- let the user choose the emacs environment to use

;;; Commentary:
;;; This code mimics the behaviour of `startup.el' to let the
;;; usage of the custom init directory behave just like the
;;; one and only "~/.emacs.d".
;;;
;;; By setting the environment variable `EMACS_USER_DIRECTORY'
;;; the user-emacs-directory can be chosen and if there is an
;;; `init.el' the configuration from that directory will be used.
;;; If the environment variable is not set or there is no `init.el'
;;; the default configuration directory `~/.emacs.d/' will be used.
;;;
;;; The variable `server-name' will be set to the name of the directory
;;; chosen as start path.  So if the server will be started, it can be
;;; reached with 'emacsclient -s servername'.
;;;
;;; This now works with a current version of spacemacs but does not
;;; work with `async-start' in general, if the code executed with `async'
;;; uses `user-init-dir' or makes other assumptions about the emacs
;;; start-directory.

;;; Code:
(let* ((user-init-dir-default
    (file-name-as-directory (concat "~" init-file-user "/.emacs.d")))
       (user-init-dir
    (file-name-as-directory (or (getenv "EMACS_USER_DIRECTORY")
                    user-init-dir-default)))
       (user-init-file-1
    (expand-file-name "init" user-init-dir)))
  (setq user-emacs-directory user-init-dir)
  (with-eval-after-load "server"
    (setq server-name
      (let ((server--name (file-name-nondirectory
                   (directory-file-name user-emacs-directory))))
        (if (equal server--name ".emacs.d")
        "server"
          server--name))))
  (setq user-init-file t)
  (load user-init-file-1 t t)
  (when (eq user-init-file t)
    (setq user-emacs-directory user-init-dir-default)
    (load (expand-file-name "init" user-init-dir-default) t t)))

(provide '.emacs)
;;; .emacs ends here

Jest też miły dodatek, który sprawia, że ​​działa on jako demon bez dodatkowego wysiłku: nazwa-serwera zostanie ustawiona na nazwę katalogu init. Teraz możesz uruchomić drugiego demona emacs z waniliowymi znakami kosmicznymi

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs --daemon

i nadal używamy emacsclient

emacsclient -s spacemacs -c -e '(message "Hello spacemacs")'

Mój przypadek użycia jest bardzo prosty i jestem zdumiony, że jestem jedyny: mam zawsze działającego demona emacs i używam go z GUI i na konsoli (na przykład z ssh). W tym emacsie przygotowuję całą moją dokumentację i dziennik pracy, więc musi być tam cały czas. Ale potem chcę wypróbować kosmiczne lub jeden z innych pakietów dystrybucyjnych, a nawet je skonfigurować, dopóki nie mogę wycofać mojej obecnej konfiguracji lub skorzystać z niektórych sprytnych pomysłów. I podobnie jak inni, chciałem stworzyć prostą konfigurację podstawową dla moich współpracowników - i udokumentować ją w trybie org w uruchomionej instancji.

Ponieważ jedynym znanym mi problemem jest asyncto, że nie wie on o zmienionym katalogu init, myślę o najlepszym sposobie dodania konfiguracji, asyncktóra zawiera zmienne, które powinny być wstrzykiwane domyślnie, aby nie było potrzeby łatania wszystkich inwokacje async-starttak, jak zrobiły to kosmiczne maszyny.

Uwe Koloska
źródło
To jest naprawdę piękne i działało pięknie ... dopóki nie musiałem używać async. :-( Ponieważ minęło kilka miesięcy od opublikowania, czy masz obejście?
Trey
Niestety nie - ale dla kosmicznych znaków jest to naprawione i dla ogólnego asynchronizacji nie jestem do końca pewien, czy musi to być jakakolwiek zmiana, ponieważ async-starturuchamia emac bez niczego, a jeśli chcesz użyć jakiejś zmiennej, musisz ją przekazać. bądź miły i wygodny, jeśli asynchronię można skonfigurować z listą zmiennych, które będą używane przy każdym wywołaniu async-start.
Uwe Koloska
1
Przy takim podejściu mogą istnieć inne zmienne inicjowane z domyślnego katalogu emacs użytkownika przed załadowaniem pliku .emacs. Na przykład musiałem dodać (setq custom-theme-directory user-emacs-directory)tutaj.
glucas
1
Nie wiem, gdzie ta zmienna jest ustawiona, ponieważ kiedy badam ją wewnątrz minimalnego testenv, otrzymuję: Jej wartość to „~ / .emacs.d /”. Oryginalna wartość to „~ / .emacsenv.d / init-test /” Więc ma prawidłową wartość, ale została nadpisana.
Uwe Koloska
1
Właściwie skończyłem z użyciem tej odpowiedzi, długo po tym, jak zadałem pytanie. Nie zmieniłem przyjętej odpowiedzi, ponieważ jest ona tak długa i ponieważ tak naprawdę nie przywiązywałem dużej uwagi do implementacji! Ta odpowiedź była jednak dla mnie bardzo przydatna.
Croad Langshan,
5

Wyjaśniono to tutaj i istnieje ciągły PR, aby dodać go do dokumentacji:

mkdir ~/spacemacs
git clone [email protected]:syl20bnr/spacemacs.git ~/spacemacs/.emacs.d
HOME=~/spacemacs emacs```
StreakyCobra
źródło
6
Tak, czasami zmieniam HOME, aby wypróbować alternatywną konfigurację. Minusem jest to, że HOME jest używany do innych rzeczy, na które wolisz nie wpływać.
glucas
3

Odpowiedź została już zaakceptowana i zaakceptowana, ale jeśli masz ochotę wypróbować nowe sposoby robienia rzeczy w sposób odwracalny (poza konfiguracjami emacs), polecam spędzić pół godziny na zapoznaniu się z GNU Stow. To coś w rodzaju ln -ssterydów i może istnieć kilka podejść do jego użycia. Możesz mieć całą konfigurację w jednym podkatalogu (włączając konfiguracje offlineimap, emacs config itp.) - to podejście oparte na środowisku - lub mieć osobny podkatalog dla każdej aplikacji. Słodka schizofrenia.

Np. Lista związana z emacsem z mojego ~ / Stow:

-> % ls ~/Stow | grep emacs
emacs 
emacs_from_scratch
spacemacs
hoodoo@T450s 2:46 [~]

Jest jedna konfiguracja początkowa, którą udało mi się wykorzystać, jedna konfiguracja „Trzymam się przy ustawieniach domyślnych” i jedna „Zmienię własną”. Mogę tylko włączyć i wyłączyć każdy z nich i zawsze mieć je wszystkie dostępne. Każdy podkatalog może mieć całe drzewo względem mojego ~ / i bardzo przydatne jest mieszanie i dopasowywanie.

Roman Grazhdan
źródło
Używam już stow, jak to się dzieje. Ale jak tego używasz? Po prostu „dynamicznie scopujesz” swój .emacs.d poprzez symlinkowanie wejścia / wyjścia z tym, którego chcesz użyć, używając stow? Czy prowadzisz kiedyś oba jednocześnie? Jeśli tak, to myślę, że oba emacace uważają, że są „właścicielami” .emacs.d. Zastanawiam się, czy to może powodować pewne dziwactwa związane z rzeczami, które zapisują stan w tym miejscu, tak jak nie wiem, że ostatnie, savehist, automatyczne zapisywanie itp., Zwłaszcza gdy dwie kopie emacsa działają z radykalnie różnymi konfiguracjami?
Croad Langshan,
Nie, zmieniam konfiguracje według potrzeb.
Roman Grazhdan
2

Sprawdziłem łatkę używaną przez @Uwe Koloska. Nie został uwzględniony w głównej gałęzi. W pewnym sensie zgadzam się, myślę, że problem powinien zostać rozwiązany poza emacsem za pomocą powłoki i pozostawienie emacsa nic o tym nie wiedząc.

Może ta funkcja byłaby bardziej logiczna z perspektywy użytkownika, użycie flagi byłoby mniej skomplikowane dla niektórych użytkowników.

W moim przypadku użytkowania chcę zachować instalację Emacsa i Spacemaców, więc moja odmiana dwóch powyższych rozwiązań działa w ten sposób.

Skrypt powłoki

Przede wszystkim skrypt do uruchamiania znaków kosmicznych:

#!/bin/sh

export EMACS_USER_DIR=~/spacemacs/emacs.d

exec emacs "$@"

Ten skrypt jest wywoływany spacemacsi jest instalowany w /usr/local/binfolderze.

plik .emacs

Następnie potrzebuję .emacspliku w moim folderze domowym, który poprawnie traktowałby zmienną środowiskową EMACS_USER_DIR.

(defvar user-custom-dir (getenv "EMACS_USER_DIR"))

(when (/= (length user-custom-dir) 0)
  (setq user-emacs-directory (file-name-as-directory user-custom-dir)))

(load (expand-file-name "init.el" user-emacs-directory))

W ogóle nie mam doświadczenia z elisp, więc wymyśliłem to, bardziej doświadczeni ludzie prawdopodobnie mogliby wymyślić coś lepszego. Ale hej, to działa.

Eye-Candy

Dlaczego więc nie dodać ikony:

Ikona

[Desktop Entry]
Name=Spacemacs
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=spacemacs %F
Icon=/home/marcs/.icons/spacemacs.svg
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupWMClass=Emacs
Keywords=Text;Editor;
Marcs
źródło
3
Twój skrypt powłoki powinien użyć exec emacs "$@".
Uwe Koloska
Tak, dziękuję za napiwek, właśnie naprawione.
Marcs,