วิธีเริ่มต้น emacs ด้วย user-emacs-directory ที่กำหนดเอง


58

ฉันกำลังทำงานกับการกำหนดค่า Emacs ที่กำหนดเองและขนาดเล็กที่ฉันต้องการแบ่งปันกับเพื่อน ๆ ในฐานะที่เก็บ git สำหรับพวกเขาเพื่อใช้เป็นพื้นฐานสำหรับการกำหนดค่าในอนาคตของพวกเขาเอง

สำหรับสิ่งนี้ฉันต้องการวิธีทดสอบการกำหนดค่าของฉันและวิธีที่ง่ายที่สุดที่ฉันสามารถหาได้คือ:

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

แต่ฉันไม่สามารถทำงานได้

ความช่วยเหลือใด ๆ ที่ชื่นชมมาก


3
ฉันอ่านภาคผนวก C อาร์กิวเมนต์บรรทัดคำสั่งสำหรับการเรียกใช้ Emacsแต่ฉันไม่พบตัวเลือกบรรทัดคำสั่งที่ง่ายในการเริ่มต้น Emacs ด้วย.emacs.dไดเรกทอรีที่กำหนดเองยกเว้นว่าคุณจะเปลี่ยน HOME ซึ่งดูเหมือนว่ามีปัญหากับฉัน ผู้คนต่างให้วิธีการแก้ปัญหาด้านล่าง แต่สำหรับฉันแล้วนี่ดูเหมือนจะเป็นการร้องขอคุณสมบัติที่สมเหตุสมผลสำหรับ Emacs เอง
David J.

ดูเพิ่มเติม49.4 ไฟล์ Emacs เริ่มต้นที่ชี้ไป49.4.4 วิธี Emacs พบไฟล์
David J.

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
มันใช้งานได้สมบูรณ์แบบ!
Mattias Bengtsson

8
อ้างอิงจากคู่มือ Emac - ภาคผนวก C อาร์กิวเมนต์บรรทัดคำสั่งสำหรับการเรียกใช้ Emacs - ตัวแปรสภาพแวดล้อม - ตัวแปรทั่วไป HOME ตั้งค่า "ตำแหน่งของไฟล์ของคุณในแผนผังไดเรกทอรีใช้สำหรับการขยายชื่อไฟล์ที่เริ่มต้นด้วยเครื่องหมายตัวหนอน (~)" การเปลี่ยนหน้าแรกจะดูเหมือนสูตรสำหรับปัญหาในภายหลังเมื่อคุณต้องการนำทางหรือค้นหาไฟล์จากโฟลเดอร์บ้านที่แท้จริงของคุณ
David J.

2
เดวิดเจมส์: ใช่มันเป็นเรื่องน่ารำคาญเล็กน้อยสำหรับแนวทางนี้ ดังที่กล่าวไว้คุณจะต้องคัดลอกหรือเชื่อมโยงสิ่งต่าง ๆ ที่คุณต้องการให้ Emacs ดูภายใต้หน้าแรกและถ้าคุณต้องการเยี่ยมชมโฮมไดเร็กตอรี่จริงของคุณคุณต้องใช้เส้นทางสัมบูรณ์ (หรือคุณสามารถเพิ่ม symlink ลงไปได้เช่นกัน) )
phils

3
คุณอาจทดลองกู้คืน HOME ดั้งเดิมภายใน Emacs ในระหว่างการเริ่มต้น ฉันไม่ได้ลองมัน แต่มันก็ดูคุ้มค่า
phils

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 ของคุณเอง หากคุณสนใจในการเปรียบเทียบเวลาเริ่มต้นของคุณคุณจะต้องทำอย่างอื่น (ดูตัวอย่างฉันจะวัดประสิทธิภาพของรหัส elisp ได้อย่างไร )

  • มันไม่เท่ากับการเริ่มต้นปกติและคุณจะต้องดูแลจุดเฉพาะบางอย่าง โดยเฉพาะอย่างยิ่ง:

    • after-init-hookจะรันก่อนที่จะโหลดไฟล์ init
    • *scratch*บัฟเฟอร์จะถูกสร้างขึ้นก่อนที่ไฟล์ init จะโหลด คุณจะต้องเปลี่ยนโหมดอย่างชัดเจน (แทนที่จะใช้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
phils

2
@phils ใช่คุณพูดถูก นี่เป็นการเปลี่ยนแปลงลำดับการดำเนินการตามปกติและไม่เทียบเท่ากับการใช้ไฟล์ init ปกติ after-init-hookฉันแก้ไขคำตอบของฉันที่จะสะท้อนให้เห็นถึงจุดของคุณบน แต่ฉันต้องบอกว่าถึงแม้ว่าฉันจะใช้เทคนิคนี้ตลอดเวลาฉันไม่เคยประสบปัญหาใด ๆ กับafter-init-hook(แต่ฉันไม่ได้ใช้มันอย่างชัดเจนและบางทีฉันโชคดีที่แพคเกจที่ฉันใช้ไม่พึ่งพา) . คุณหมายถึงอะไรโดย "การเริ่มต้นแพ็คเกจปกติ (ค่าเริ่มต้น) จะไม่เกิดขึ้น"?
ffevotte

1
ฉันหมายความว่าcommand-lineจะไม่โทรpackage-initializeในสถานการณ์นั้น คุณจะต้องเรียกมันด้วยตนเองในไฟล์ init ปลอม
phils

1
@phils ขอบคุณ ฉันเพิ่มสิ่งนี้ในคำตอบพร้อมกับพูดถึงว่าโหมดหลักเริ่มต้นจะต้องได้รับการดูแลเป็นพิเศษด้วย
ffevotte

มันทำงานได้อย่างสมบูรณ์แบบ .. ขอบคุณ !!!
สไตรเกอร์

15

คุณสามารถsymlink ~/.emacs.dนี่คือสิ่งที่ฉันทำ

  1. พยายามให้การกำหนดค่า emacs ของฉันถูก~/.emacs.dเน้นเช่นไฟล์การกำหนดค่าที่เกี่ยวข้องกับ emac ทั้งหมดควรอยู่ในโฟลเดอร์นั้น

  2. จากนั้นฉันก็มี~/.emacs_configsโฟลเดอร์ที่โฟลเดอร์การตั้งค่าทั้งหมด (โดยทั่วไปจะเป็นโฟลเดอร์ที่มีinit.elและส่วนที่เหลือของการกำหนดค่า) อยู่ดังนั้นโฟลเดอร์การตั้งค่าส่วนตัวของฉันจะเป็น~/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และเปลี่ยน symlink

ข้อดีของขั้นตอนที่ 3 คือ emacs ที่เริ่มต้นด้วยการกำหนดค่าส่วนบุคคลของฉันสามารถทำงานได้โดยไม่ได้รับผลกระทบแม้ว่าฉันจะเปลี่ยน.emacs.dsymlink ในขณะที่ emacs นั้นกำลังทำงานอยู่ก็ตาม

ข้อดีอีกอย่างคือเนื่องจากHOMEไม่มีการเปลี่ยนแปลงโปรแกรมภายนอก emacs อาจจำเป็นต้องมีปฏิสัมพันธ์กับไม่ได้รับผลกระทบ


1
นี่หมายความว่าเราสามารถปรับแต่ง emacs ที่แยกต่างหากทั้งหมดเพื่อ(setq user-emacs-directory (file-truename "~/.emacs.d/"))ให้พวกเขาสามารถทำงานได้โดยไม่ได้รับผลกระทบพร้อมกันหรือไม่?
user1011471

1
ในทางทฤษฎีใช่ แต่ในทางปฏิบัติอาจจะมีห้องสมุดบางอย่างที่ยากรหัสเส้นทางไปมากกว่าการใช้~/.emacs.d user-emacs-directoryฉันเจอห้องสมุดอย่างน้อยหนึ่งแห่ง แต่น่าเสียดายที่จำชื่อไม่ได้
อิกบาลอันซารี

7

การกำหนดค่าที่ไม่เปลี่ยนแปลงHOMEหรือทำงานร่วมกับ symlinks สามารถพบได้ในคำตอบของฉัน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.d" การกำหนดค่า emacs เดียวกับผู้ใช้เครื่องลินุกซ์ดังนั้นวิธีการแก้ปัญหานี้https://emacs.stackexchange.com/a/4258/5488จะทำงานในกรณีส่วนใหญ่ แต่ในบางกรณี เคส emacs พยายามเขียนไฟล์ชั่วคราวไปยังไดเร็กทอรี user-emacs-(เช่นไฟล์ .ido.last) ในกรณีเช่นนี้หากไดเรกทอรีการกำหนดค่าที่แชร์มีสิทธิ์ในการเขียนสำหรับผู้ใช้ทั้งหมดมันจะทำงานได้ แต่อาจไม่เป็นที่ต้องการเนื่องจากผู้ใช้ระบบแต่ละคนอาจไม่ต้องการแชร์ไดเรกทอรีเดียวกันเพื่อจัดเก็บไฟล์ชั่วคราว ในกรณีเช่นนี้การแก้ปัญหาต่อไปนี้จะเป็นทางเลือกที่ดีกว่า

ไฟล์ config ที่ใช้ร่วมกันทั่วไป. 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)

ทำให้การกำหนดค่าที่ใช้ร่วมกัน. emacs.d มีสิทธิ์อ่านสำหรับผู้ใช้ทั้งหมด (ไม่จำเป็นต้องมีสิทธิ์ในการเขียน)

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

ผู้ใช้ทุกคนจะมีไดเรกทอรี "~ / .emacs.d /" ของตนเอง แต่ใช้เพื่อบันทึกไฟล์ชั่วคราวเท่านั้น แต่แพ็คเกจและการกำหนดค่าอื่น ๆ จะถูกโหลดจากไดเรกทอรีการกำหนดค่าที่ใช้ร่วมกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.