Як запустити emacs зі спеціального каталогу user-emacs


58

Я працюю над власною та невеликою конфігурацією Emacs, якою хочу поділитися з деякими друзями як сховище git, яке вони використовують як базову лінію для їхніх майбутніх конфігурацій.

Для цього мені потрібен спосіб перевірити свою конфігурацію, і найпростіше рішення, яке я можу придумати, - це щось на зразок:

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

Але я не можу, здається, змусити його працювати.

Будь-яка допомога дуже цінується.


3
Я прочитав Додаток C Аргументи командного рядка для виклику Emacs, але не знайшов простого параметра командного рядка, щоб запустити Emacs зі спеціального .emacs.dкаталогу, якщо ви не зміните HOME, що мені здається проблематичним. Люди надали способи вирішення нижче, але, на мій погляд, це звучить як дуже розумний запит на функції для самого Emacs.
Девід Дж.


5
@DavidJames Ви маєте рацію: насправді в списку помилок Emacs про це є список бажань .
ffevotte

2
Оновлення: схоже, ця функція не так зацікавила розробників Emacs: запит позначено тегами wontfixта закрито в трекер помилок.
ffevotte

@Francesco: Я намагаюся динамічний підхід, який дозволяє виводити каталог Emacs користувача за межі "~". Можливо, ви спробуєте.
Антоніо

Відповіді:


39

Основний підхід, який я використовую для цього, - це змінити $HOME, запустивши:

env HOME=/path/to/dir emacs

Потім ви використовуєте /path/to/dir/.emacs.d

Ви можете також позначити будь-які важливі файли чи каталоги в цьому підробленому домашньому режимі до справжніх, щоб Emacs їх бачив.


2
Це прекрасно працює!
Маттіас Бенгтссон

8
Відповідно до посібника Emac - Додаток C Аргументи командного рядка для виклику Emacs - Змінні середовища - Загальні змінні , HOME встановлює "Розташування ваших файлів у дереві каталогів; використовується для розширення імен файлів, починаючи з тильди (~)." Зміна HOME звучить як рецепт неприємностей пізніше, коли ви хочете швидко перейти або знайти файли з вашої реальної домашньої папки.
Девід Дж.

2
Девід Джеймс: Так, це незначне роздратування при такому підході. Як уже згадувалося, ви хочете скопіювати або символізувати посилання на те, що вам потрібно Emacs бачити в ГОЛОВНІЙ, і якщо ви хочете відвідати свій справжній домашній каталог, тоді вам потрібно використовувати абсолютний шлях (або ви можете додати також посилання на це також ).
філ

3
Ви також можете експериментувати зі відновленням оригіналу HOME в Emacs під час ініціалізації. Я цього не пробував, але, здається, варто заглянути.
філ

1
@phils: Я спробував те, що ти пропонуєш.
Антоніо

39

Я використовую для .emacs.dпаралельного обслуговування декількох каталогів наступним чином.

  1. emacs запускається так:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Кожен init.elфайл починається так, щоб правильно налаштувати user-init-fileі user-emacs-directoryзмінні:

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

Я виявив, що це працює дуже надійно за останні місяці. Ось кілька зауважень:

  • вона порушується emacs-init-time, що повідомляє лише про час, необхідний для завантаження конфігурації системи за замовчуванням, але не власний файл init. Якщо вас зацікавило тестування часу на init, вам доведеться це зробити іншим способом (див. Наприклад, як я вимірюю ефективність коду elisp? ).

  • це не еквівалентно звичайному запуску, і вам потрібно буде подбати про кілька конкретних моментів. Зокрема:

    • after-init-hookзапускається до завантаження файлу init.
    • *scratch*Буфер створюється , перш ніж буде завантажений файл ініціалізації. Вам доведеться явно (замість використання initial-major-mode) змінити його режим .
    • Вам потрібно буде чітко зателефонувати package-initialize; це не буде зроблено автоматично
  • шлях до init.elможе бути обраний довільно; зокрема, каталог, у якому init.elзнаходиться, не повинен бути названий .emacs.d. Я використовую це , щоб мати, наприклад , .emacs.d.23поряд .emacs.d.24з тим , щоб мати можливість перемикатися між різними версіями Emacs (система , я використовую на роботі проходимо застаріли, і я не можу встановити Emacs 24 на всіх машинах , які я використовую).

  • цей робочий процес не вимагає зміни середовища (і особливо HOMEenvvar), що може бути бажано, якщо ви запускаєте програми зсередини emacs, на які може впливати змінене середовище).


1
Це (фактично) змінює звичайний порядок виконання, якщо ви розглядаєте --loadфайл ed як файл init. Для початку, мені здається, ніби нормальна (за замовчуванням) ініціалізація пакету не відбудеться, і after-init-hookзапуститься до того, як (підроблений) файл init буде оцінено. Це, напевно, можна обійти, але пам’ятайте, що це не те саме, що Emacs, використовуючи вказаний шлях, як файл init.
філс

2
@phils так, ти маєш рацію. Це дійсно змінює звичайний порядок виконання і не еквівалентно використанню звичайного файлу init. Я відредагував свою відповідь, щоб відобразити вашу думку after-init-hook. Але я мушу сказати, що, хоча я весь час використовую цю техніку, я ніколи не стикався з жодною проблемою after-init-hook(але я не використовую її явно, і, можливо, мені пощастило, що пакунки, якими я користуюся, не покладаються на неї) . Що ви маєте на увазі під "звичайною (за замовчуванням) ініціалізацією пакета не буде"?
ffevotte

1
Я маю на увазі, що в цій ситуації command-lineне зателефонують package-initialize. Вам потрібно буде викликати його вручну у підробленому файлі init.
філс

1
@phils дякую. Я додав це до відповіді, разом із зазначенням, що для початкового основного режиму потрібно також ретельно піклуватися.
ffevotte

Це спрацювало чудово .. Дякую !!!
Стрикер

15

Ви можете зв'язати посилання ~/.emacs.d , це я і роблю

  1. Постарайтеся, щоб конфігурація моєї emacs була ~/.emacs.dорієнтована, тобто всі файли конфігурації, пов'язані з emacs, повинні жити у цій папці

  2. Тоді у мене є ~/.emacs_configsпапка, в якій init.elживуть усі конфігураційні папки (в основному це папка з конфігурацією a і решта), тож моя особиста папка config буде ~/emacs_configs/iqbalв розповсюдженні прелюдії.~/emacs_configs/prelude

  3. Дуже рано в моїй персональній конфігурації emacs я встановив user-emacs-directoryповний шлях до моєї конфігурації, використовуючи наступне

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Потім, нарешті, я посилаюсь ~/.emacs.dна конфігурацію, яку я фактично хочу використовувати, наприклад. використовувати мою конфігурацію, яку я буду робити ln -s ~/emacs_configs/iqbal .emacs.d. Якщо ви хочете спробувати деяку конфігурацію, просто скопіюйте папку конфігурації ~/emacs_configs/whatever_nameта змініть симпосилання

Перевага третього кроку полягає в тому, що emacs, розпочатий з моєї особистої конфігурації, може працювати без змін, навіть якщо я .emacs.dзмінюю симпосилання під час роботи emacs.

Ще одна перевага полягає в тому, що HOMEзовнішні програми, які не змінюються, можливо, для взаємодії з електронними програмами не впливають


1
Чи означає це, що ми можемо налаштувати всі окремі конфігурації emacs, щоб (setq user-emacs-directory (file-truename "~/.emacs.d/"))вони могли працювати одночасно без змін?
користувач1011471

1
Теоретично так, але на практиці можуть бути деякі бібліотеки, які важко кодують шлях, ~/.emacs.dа не використовують user-emacs-directory. Я натрапив на принаймні одну таку бібліотеку, але, на жаль, не можу згадати її ім'я.
Ікбал Ансарі

7

Конфігурація, яка не змінюється HOMEабо працює із символьними посиланнями, можна знайти у моїй відповіді https://emacs.stackexchange.com/a/20508/934 . За допомогою цієї конфігурації ви можете змінити user-emacs-directory, встановивши змінну середовища:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

і це навіть працює з демоном.


5

Я знайшов це акуратне рішення від EmacsWiki :

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

(не зовсім за допомогою спеціального каталогу, але добре працює, тому що ви, швидше за все, маєте єдиний файл входу)


FYI, це зайве з коментарем @Francesco від 2 років тому.
Брайс


3

Встановіть var перед завантаженням файлу init:

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

Потім у своєму init-файлі (у цьому випадку ~/.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"))

Дуже елегантна моя улюблена система, оскільки все залишається у домені Emacs, як слід. Дякую.
gsl

1

Розширюючи відповідь від @phils, я створив цей маленький скрипт оболонки (званий testrun.sh) для тестування мого нового конфігурації emacs. Це може мати сенс робити і в інших випадках (наприклад, при тестуванні змін у вашому init.el, які можуть порушити 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

Ось невеликий сценарій, заснований на відповіді @ коментаря @ Phil про зміну HOMEзмінної середовища, а потім відновлення її в 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

Якщо випадком використання є спільний каталог конфігурації emacs ".emacs.d" для всіх користувачів машини Linux, це рішення https://emacs.stackexchange.com/a/4258/5488 буде працювати в більшості випадків, але в деяких case emacs намагається записати тимчасові файли в каталог user-emacs (наприклад, .ido.last файл). У таких випадках, якщо спільний конфігураційний каталог має дозвіл на запис для всіх користувачів, він буде працювати, але це може бути не бажаним рішенням, оскільки кожен користувач системи може не захотіти спільно використовувати один і той же каталог для зберігання тимчасових файлів. У такому випадку наступне рішення буде кращим варіантом.

Спільний файл конфігурації .emacs.d / init.el повинен починатися з

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

Зробіть загальний config .emacs.d мати дозвіл на читання для всіх користувачів (не потрібно мати дозвіл на запис)

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

Кожен користувач матиме власну "~ / .emacs.d /" каталог, але використовується лише для збереження тимчасових файлів, але пакунки та інша конфігурація завантажуються із спільного каталогу конфігурацій.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.