Cara memulai emacs dengan direktori user-emacs khusus

58

Saya sedang mengerjakan konfigurasi Emacs khusus dan kecil yang ingin saya bagikan dengan beberapa teman sebagai repositori git untuk mereka gunakan sebagai garis dasar untuk konfigurasi masa depan mereka sendiri.

Untuk ini saya perlu beberapa cara untuk menguji konfigurasi saya dan solusi paling sederhana yang dapat saya buat adalah sesuatu seperti:

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

Tapi sepertinya saya tidak bisa membuatnya bekerja.

Setiap bantuan sangat dihargai.

Mattias Bengtsson
sumber
3
Saya membaca Apendiks C Argumen Baris Perintah untuk Doa Emacs tetapi saya tidak menemukan opsi baris perintah sederhana untuk memulai Emacs dengan .emacs.ddirektori khusus kecuali jika Anda mengubah HOME, yang tampaknya bermasalah bagi saya. Orang-orang telah memberikan solusi di bawah ini, tetapi bagi saya, ini terdengar seperti permintaan fitur yang sangat masuk akal untuk Emacs sendiri.
David J.
5
@ DavidJames Anda benar: sebenarnya ada item wishlist tentang ini di pelacak bug Emacs.
ffevotte
2
Pembaruan: sepertinya fitur ini tidak terlalu menarik bagi pengembang Emacs: permintaan telah ditandai wontfixdan ditutup di pelacak bug.
ffevotte
@ Francesco: Saya mencoba pendekatan dinamis yang memungkinkan untuk menempatkan direktori pengguna Emacs di luar "~". Mungkin Anda akan mencobanya.
antonio

Jawaban:

39

Pendekatan dasar yang saya gunakan untuk ini adalah memodifikasi $HOME, dengan menjalankan:

env HOME=/path/to/dir emacs

Anda kemudian gunakan /path/to/dir/.emacs.d

Anda mungkin ingin juga menyambungkan semua file atau direktori yang penting dalam direktori home palsu ini kembali ke yang asli, sehingga Emacs akan melihatnya.

phils
sumber
2
Ini berfungsi sempurna!
Mattias Bengtsson
8
Menurut Manual Emac - Apendiks C Argumen Baris Perintah untuk Doa Emacs - Variabel Lingkungan - Variabel Umum , HOME menetapkan "Lokasi file Anda di pohon direktori; digunakan untuk ekspansi nama file yang dimulai dengan tilde (~)." Mengubah RUMAH terdengar seperti resep untuk masalah nanti ketika Anda ingin menavigasi dengan cepat atau menemukan file dari folder rumah Anda yang sebenarnya .
David J.
2
David James: Ya, itu gangguan kecil dengan pendekatan ini. Seperti yang disebutkan, Anda ingin menyalin atau menyinkronkan hal-hal yang Anda perlukan untuk dilihat oleh Emacs di HOME, dan jika Anda ingin mengunjungi direktori home asli Anda, maka Anda perlu menggunakan jalur absolut (atau Anda juga dapat menambahkan symlink ke situ ).
phils
3
Anda mungkin juga bereksperimen dengan mengembalikan HOME asli di dalam Emacs selama inisialisasi. Saya belum mencobanya, tetapi sepertinya layak untuk dicoba.
phils
1
@phils: Saya mencoba apa yang Anda sarankan.
antonio
39

Cara yang saya gunakan untuk memelihara beberapa .emacs.ddirektori secara paralel adalah sebagai berikut.

  1. emacs dimulai seperti ini:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. Setiap init.elfile dimulai seperti ini, untuk mengatur user-init-filedan user-emacs-directoryvariabel dengan benar:

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

Saya menemukan ini berfungsi dengan sangat andal selama beberapa bulan terakhir. Berikut ini beberapa komentar:

  • rusak emacs-init-time, yang hanya melaporkan waktu yang diperlukan untuk memuat konfigurasi sistem default, tetapi bukan file init Anda sendiri. Jika Anda tertarik untuk membuat tolok ukur waktu init Anda, Anda harus melakukannya dengan cara lain (lihat misalnya Bagaimana cara mengukur kinerja kode elisp? ).

  • itu tidak setara dengan startup normal dan Anda harus mengurus beberapa poin tertentu. Khususnya:

    • after-init-hookdijalankan sebelum file init dimuat.
    • The *scratch*buffer dibuat sebelum file init dimuat. Anda harus mengubah mode secara eksplisit (alih-alih menggunakan initial-major-mode).
    • Anda harus menelepon secara eksplisit package-initialize; itu tidak akan dilakukan secara otomatis
  • jalan menuju init.eldapat dipilih secara sewenang-wenang; khususnya, direktori tempat init.eltinggal tidak harus disebutkan namanya .emacs.d. Saya menggunakan ini untuk memiliki contoh di .emacs.d.23samping .emacs.d.24agar dapat beralih di antara versi emacs yang berbeda (sistem yang saya gunakan di tempat kerja sudah ketinggalan zaman, dan saya tidak dapat menginstal emacs 24 pada semua mesin yang saya gunakan).

  • alur kerja ini tidak memerlukan modifikasi lingkungan (dan terutama HOMEenvvar), yang dapat diinginkan jika Anda menjalankan program dari dalam emacs, yang dapat dipengaruhi oleh lingkungan yang dimodifikasi).

ffevotte
sumber
1
Ini memang (pada dasarnya) mengubah urutan eksekusi normal, jika Anda menganggap --loadfile ed sebagai file init. Sebagai permulaan, tampaknya bagi saya seolah-olah inisialisasi paket normal (default) tidak akan terjadi, dan after-init-hookakan berjalan sebelum file init (palsu) dievaluasi. Ini adalah hal-hal yang dapat Anda atasi, tentu saja, tetapi perlu diketahui bahwa itu bukan hal yang persis sama dengan Emacs menggunakan jalur yang ditentukan sebagai file init.
phils
2
@phils ya, Anda benar. Ini memang mengubah urutan eksekusi normal, dan tidak setara dengan menggunakan file init biasa. Saya mengedit jawaban saya untuk mencerminkan maksud Anda after-init-hook. Tetapi saya harus mengatakan bahwa walaupun saya menggunakan teknik ini sepanjang waktu, saya tidak pernah menemui masalah dengan after-init-hook(tapi saya tidak menggunakannya secara eksplisit, dan mungkin saya hanya beruntung bahwa paket yang saya gunakan tidak bergantung pada itu) . Apa yang Anda maksud dengan inisialisasi paket "normal (default) tidak akan terjadi"?
ffevotte
1
Maksud saya itu command-linetidak akan memanggil package-initializedalam situasi itu. Anda perlu menyebutnya secara manual di file init palsu.
phils
1
@phils terima kasih. Saya menambahkan ini ke jawabannya, bersama dengan menyebutkan bahwa mode utama awal juga harus dijaga secara khusus.
ffevotte
Ini bekerja dengan sempurna .. Terima kasih !!!
Stryker
15

Anda dapat symlink ~/.emacs.d , ini yang saya lakukan

  1. Cobalah untuk tetap ~/.emacs.dberorientasi konfigurasi emacs saya yaitu semua file konfigurasi emacs terkait harus hidup di folder itu

  2. Kemudian saya memiliki ~/.emacs_configsfolder tempat semua folder konfigurasi (pada dasarnya folder dengan init.eldan sisa konfigurasi) tinggal, jadi folder konfigurasi pribadi saya akan ~/emacs_configs/iqbal, distribusi pendahuluan akan berada di~/emacs_configs/prelude

  3. Sangat awal dalam konfigurasi emacs pribadi saya, saya mengatur user-emacs-directoryjalur penuh ke konfigurasi saya menggunakan yang berikut

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. Lalu akhirnya saya symlink ~/.emacs.dke konfigurasi yang sebenarnya ingin saya gunakan, misalnya. untuk menggunakan konfigurasi saya akan saya lakukan ln -s ~/emacs_configs/iqbal .emacs.d. Jika Anda ingin mencoba beberapa konfigurasi cukup salin folder konfigurasi ~/emacs_configs/whatever_namedan ubah symlink

Keuntungan dari langkah ke-3 adalah emacs yang dimulai dengan konfigurasi pribadi saya dapat berjalan tidak terpengaruh bahkan jika saya mengubah .emacs.dsymlink saat emacs sedang berjalan.

Keuntungan lain adalah karena HOMEprogram eksternal yang tidak diubah, emacs mungkin perlu berinteraksi dengan yang tidak terpengaruh

Iqbal Ansari
sumber
1
Apakah ini berarti kita dapat mengubah semua konfigurasi emacs yang terpisah (setq user-emacs-directory (file-truename "~/.emacs.d/"))sehingga mereka semua dapat berjalan tanpa terpengaruh secara bersamaan?
user1011471
1
Secara teori ya, tetapi dalam praktiknya mungkin ada beberapa perpustakaan yang menyulitkan jalur untuk ~/.emacs.dmenggunakan daripada menggunakan user-emacs-directory. Saya telah menemukan setidaknya satu perpustakaan seperti itu tetapi sayangnya tidak dapat mengingat namanya.
Iqbal Ansari
7

Konfigurasi yang tidak berubah HOMEatau berfungsi dengan symlink dapat ditemukan di jawaban saya https://emacs.stackexchange.com/a/20508/934 . Dengan konfigurasi ini Anda dapat mengubah user-emacs-directorydengan menyetel variabel lingkungan:

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs

dan ini bahkan bekerja dengan daemon.

Uwe Koloska
sumber
5

Saya menemukan solusi rapi ini dari EmacsWiki :

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

(tidak persis menggunakan direktori khusus, tetapi berfungsi dengan baik karena Anda kemungkinan besar memiliki file entri tunggal)

phhehehe
sumber
FYI, ini berlebihan dengan komentar dari @Francesco dari 2 tahun yang lalu.
Bryce
3

Setel var Anda sebelum memuat file init Anda:

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

Kemudian, dalam file init Anda (dalam hal ini ~/.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
sumber
Sangat elegan, sistem favorit saya, karena semuanya tetap dalam domain Emacs, sebagaimana mestinya. Terima kasih.
gsl
1

Memperluas jawaban dari @phils saya membuat skrip shell kecil ini (dipanggil testrun.sh) untuk menguji konfigurasi emacs baru saya. Ini mungkin masuk akal untuk dilakukan dalam kasus lain juga (misalnya saat menguji perubahan pada init.el Anda yang mungkin merusak 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
sumber
1

Berikut ini adalah skrip kecil berdasarkan jawaban dan komentar @ Phil tentang mengubah HOMEvariabel lingkungan, dan kemudian memulihkannya di dalam 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
sumber
1

Jika use case berbagi direktori konfigurasi emacs tunggal ".emacs.d" di semua pengguna mesin linux maka solusi ini https://emacs.stackexchange.com/a/4258/5488 akan berfungsi dalam banyak kasus, tetapi dalam beberapa kasus case emacs mencoba menulis file sementara ke direktori user-emacs (seperti file .ido.last). Dalam kasus seperti itu jika direktori konfigurasi bersama memiliki izin menulis untuk semua pengguna maka itu akan berfungsi tetapi mungkin bukan solusi yang diinginkan karena setiap pengguna sistem mungkin tidak ingin berbagi direktori yang sama untuk menyimpan file temp. Dalam hal demikian solusi berikut akan menjadi pilihan yang lebih baik.

File konfigurasi bersama yang umum .emacs.d / init.el harus dimulai dengan

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

Buat config bersama .emacs.d memiliki izin baca untuk semua pengguna (tidak perlu memiliki izin menulis)

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

Setiap pengguna akan memiliki direktori "~ / .emacs.d /" sendiri tetapi hanya digunakan untuk menyimpan file sementara tetapi paket dan konfigurasi lainnya dimuat dari direktori konfigurasi bersama.

Talespin_Kit
sumber