विभिन्न मशीनों के बीच संकुल को सिंक्रनाइज़ करें


57

मैं विभिन्न स्थानों में emacs का उपयोग करता हूं और मैं एक समान सेटअप और पैकेज हर जगह स्थापित करना चाहता हूं। मुझे लगता है कि मैं सेटअप फ़ाइलों के लिए एक संस्करण नियंत्रण भंडार का उपयोग कर सकता हूं। चूंकि मैं प्रस्तावना का उपयोग करता हूं , इसलिए यह होगा ~/.emacs.d/personal/

मुझे नहीं पता कि पैकेज के साथ क्या करना है। क्या .emacs.d/स्थापित पैकेजों की सूची के साथ कहीं एक फ़ाइल है जिसे मैं अन्य मशीनों में emac बनाने के लिए उपयोग कर सकता हूं जो वहां सूचीबद्ध हैं?


2
मेरे लिए स्थापित पैकेज मेरे Emacs संस्करण नियंत्रण रिपॉजिटरी का सिर्फ एक हिस्सा हैं। मैं बोट्स को ईमैक्स के सबसे पुराने संस्करण के साथ संकुल को संकलित करता हूं, जिसे मैं उपयोग करना चाहता / चाहती हूं और .elc फाइलों को रिपॉजिटरी में भी डालती हूं। यह अधिकतम नियंत्रण और स्थिरता प्रदान करता है। व्यापार बंद भंडार का (अपेक्षाकृत) बड़ा आकार है। मेरे 6 साल पुराने गिट रिपॉजिटरी का आकार 120 एमबी है। हालांकि मैं शायद 1/10 के साथ दूर हो सकता हूं अगर मैं पैकेज शामिल नहीं करूंगा, तो कुछ "बर्बाद" मेगाबाइट वास्तव में मुझे चिंता नहीं करते हैं।
पपरिका

1
मुझे उस समय जोड़ना चाहिए जब ELPA / MELPA / ... आजकल बहुत लोकप्रिय हैं, फिर भी सभी पैकेज उनके माध्यम से उपलब्ध नहीं हैं। इसलिए यदि आप एक ऐसे पैकेज का उपयोग करते हैं, जिसके लिए आपको मैन्युअल इंस्टॉलेशन की आवश्यकता होती है, तो आप अपने द्वारा उपयोग की जाने वाली प्रत्येक नई मशीन पर प्रयास को दोहराना नहीं चाहते हैं (साथ ही प्रत्येक पैकेज अपग्रेड के लिए)। फिर से, एक आसान उपाय पैकेज को अपने Emacs संस्करण नियंत्रण भंडार में जोड़ना है।
पेपरिका

क्या आप साइट पर केवल बाइट नहीं कर सकते और git में अनदेखी .elc फाइलों के साथ भाग सकते हैं?
वम्सी

@Vamsi: मैंने बाइट-संकलित फ़ाइलों को रिपॉजिटरी में डाल दिया क्योंकि कुछ (गैर-ईएलपीए) पैकेज उनकी निर्भरता के कारण संकलित करने के लिए थोड़ा बारीक हैं। इन के लिए मैं इस प्रक्रिया को दोहराना पसंद नहीं करता यदि आवश्यक नहीं है।
पेपरिका

@paprika क्या आप कुछ विवरण प्रदान कर सकते हैं कि अपना सेटअप कैसे प्राप्त करें? क्या आप .emacs.d plus .emacs में हर चीज को रिपॉजिटरी में जोड़ते हैं और यही है?
शुरुआत

जवाबों:


50

वांछित प्रभाव प्राप्त करने के लिए सिंक्रनाइज़ की गई कोई स्वचालित रूप से उत्पन्न हुई फ़ाइल नहीं है।

उस ने कहा, कुछ तुम कर सकते हो package-installअपने emacs विन्यास में ही कॉल जोड़ें ।

(package-install 'auctex)

विचार यह है कि package-installबेरोजगार है, इसलिए यदि पैकेज पहले से मौजूद है, तो वास्तव में कुछ भी नहीं होगा। यह मानकर कि आपके द्वारा उपयोग किए जाने वाले प्रत्येक पैकेज के लिए आपके पास ऐसी कॉल है (या कम से कम पत्तियों पर निर्भरता ग्राफ में), जो आपके पैकेज को पूरी तरह से मशीनों में सिंक्रनाइज़ कर देगा।


कई पैकेजों के लिए आप निम्नलिखित का उपयोग कर सकते हैं:

(setq my-package-list '(package1 package2 packageN))
(mapc #'package-install my-package-list)

2
मैं आश्चर्यचकित हूं कि यह दृष्टिकोण यहां सुझाए गए समाधान की तुलना में कितना सरल है । क्या कोई अंतर है? स्निपेट का भी उपयोग करता है package-install
स्टेंसकेजर

1
package.elउस जुड़े हुए उत्तर के बाद से परिवर्तन हुए हैं । यह संभव है कि उस समय package-installमौजूदा संकुल पर परिचालन हो, न कि केवल अनइंस्टॉल किए गए।
जोनाथन लीच-पेपिन

3
यह तकनीक दुर्भाग्य से समस्याग्रस्त है - भले ही पैकेज-अभिलेख भंडार मशीनों के बीच समान हो और एससीएम में निर्दिष्ट हो। यह आश्वासन नहीं देता कि पैकेज संस्करण मशीनों के बीच समान हैं। मुद्दा यह है कि पैकेज संस्करण निर्दिष्ट नहीं हैं; ये अलग-अलग पैकेज समय के साथ समाप्त हो सकते हैं और उनकी निर्भरता असंगत हो सकती है। यह मेलपा जैसे सक्रिय पैकेज अभिलेखागार पर काफी आसानी से हो सकता है।
ctpenrose

@ctpenrose: क्या आपके पास इस समस्या से बचने का सुझाव है?
छात्र

@ अक्सर मैंने मेलपा-स्टेबल का उपयोग करके और कम बार पैकेज को अपडेट करके समस्या को कम कर दिया है।
ctpenrose

34

मैं संस्करण नियंत्रण में अपनी .emacs.d निर्देशिका रखता हूं। फिर, मेरे init.el और बाद की फ़ाइलों में मैं पैकेज सेटअप को परिभाषित करने के लिए उपयोग-पैकेज का उपयोग करता हूं । न केवल उपयोग-पैकेज lazily आपके पैकेजों को लोड करता है, यह उन्हें मांग पर डाउनलोड करेगा यदि वे आपके द्वारा सेट किए गए किसी भी पैकेज प्रतिनिधि से मौजूद नहीं हैं।

उदाहरण के लिए, मैं गो-मोड का उपयोग करता हूं, लेकिन हर मशीन पर नहीं। मेरे init.el में मेरे पास निम्नलिखित हैं:

(use-package go-mode
  :ensure t
  :config
  (progn
    (defun my-go-mode-hook ()
      (linum-mode t)
      (setq tab-width 4)
      (add-hook 'before-save-hook 'gofmt-before-save))
    (add-hook 'go-mode-hook 'my-go-mode-hook)))

यह एक मोड हुक जोड़ता है, लेकिन इससे भी महत्वपूर्ण बात, :ensure tयह निर्दिष्ट करके कि यह मांग पर पैकेज डाउनलोड करेगा।

एक मशीन को सिंक में रखने के लिए, आप केवल चेकआउट कर सकते हैं या रेपो से खींच सकते हैं और Emacs शुरू कर सकते हैं। कोई भी नया पैकेज डाउनलोड और इंस्टॉल किया जाएगा।


यह वह समाधान है जो मैं अब कास्क के बजाय भी उपयोग करता हूं, मुख्य रूप से क्योंकि (जैसा कि टी। वेरॉन ने उल्लेख किया है) कास्केट विंडोज पर (अच्छी तरह से) काम नहीं करता है, और अभी तक एक और निर्भरता है।
एंडी

1
यह वह तरीका है जो मैं भी उपयोग करता हूं, लेकिन ऐसा करने के बजाय :ensure go-modeआप पैकेज का नाम दोहरा रहे हैं , आप बस निर्दिष्ट कर सकते हैं:ensure t
पेड्रो लूज

अच्छी बात! यह एक पुराना उत्तर है। मैं इसे अपडेट करूंगा।
एलारसन

आप :hookअपने कोड को सरल बनाने के लिए भी कीवर्ड का उपयोग कर सकते हैं ।
गुइलहर्मे सालोमे

17

Emacs-25 में, चर है package-selected-packages, इसलिए आप इस चर को अनुकूलित कर सकते हैं और package-install-selected-packagesयह सुनिश्चित करने के लिए उपयोग कर सकते हैं कि वे स्थापित हैं।


ध्यान दें कि मैं इसे देखता हूं, उस कमांड का नाम थोड़ा भ्रमित है। क्या मैं इसे पैकेज-इंस्टॉल-चयनित-पैकेज में बदल सकता हूं?
मालाबार

मान लें कि "नोट" के बजाय "नाऊ" का मतलब है, हां।
स्टीफन

9

जो आप उपयोग करना चाहते हैं , वह है Cask , जो आपको एक Cask फ़ाइल बनाने की अनुमति देता है जो यह बताती है कि कौन से संकुल को संस्थापित करना है cask install। इसका उपयोग पैकेज की निर्भरता को प्रबंधित करने के लिए किया जा सकता है, और आसानी से आपके एमएसीएस कॉन्फ़िगरेशन की "निर्भरता"। अपनी Cask फ़ाइल को संस्करण नियंत्रण में रखें, और प्रति-मशीन के आधार पर संकुल को अद्यतन / स्थापित करें।


4
यह ध्यान देने योग्य है कि (आज के अनुसार) यह समाधान विंडोज़ मशीनों के लिए काम नहीं करता है।
टी। वेरॉन

1
मैं अब इस समाधान का उपयोग नहीं करता, आपके बहुत कारण के लिए (और यह कि कास्क अभी तक एक और निर्भरता है)। पैकेज बनाने के लिए महान; कॉन्फ़िगरेशन प्रबंधन के लिए भयानक।
एंडी

6

एक वैकल्पिक दृष्टिकोण निम्नलिखित होगा: के बाद से मैं नहीं है सिर्फ अपने Emacs संकुल सिंक्रनाइज़ करना चाहते हैं, लेकिन यह भी अन्य फ़ाइलों (जैसे .emacs, .bashrc, लेकिन यह भी अन्य निर्देशिकाओं) अपने सर्वर और अपने लैपटॉप के बीच, मैं उपयोग करने के लिए शुरू कर दिया unison, फ़ाइलों को समन्वयित करने और निर्देशिका। इसलिए जब मैं अपने लैपटॉप पर काम कर रहा हूं तो मैं unison laptopकिसी भी चीज से पहले साधारण रन कर सकता हूं । मेरी ~/.unison/laptop.prfफ़ाइल में Emacs संबंधित फ़ाइलों के लिए निम्न अनुभाग है:

path = .emacs
path = .emacs.d
ignore = Path {.emacs.d/semanticdb}

चूंकि मेरे Emacs के पैकेज (और मेरे Emacs बैकअप और बुकमार्क भी) संग्रहीत हैं, इसलिए ~/.emacs.dयह सुनिश्चित करता है कि मुझे मेरी सभी मशीनों पर सब कुछ मिल गया है।

एक वैकल्पिक दृष्टिकोण को .emacs.dडायरेक्टरी में डायरेक्ट्री में रखा जाएगा जो कि खुद को क्लॉक, ड्रॉपबॉक्स या किसी अन्य फाइल सिंकिंग सर्विस के साथ सिंक किया गया है और फिर ~/.emacs.dउस साझा डायरेक्टरी से सिमिलिंक बना सकते हैं ।


5

जबकि package.elपैकेजों को स्थापित करने का मानक तरीका है, आप यह भी आज़माना चाह सकते हैं कि el-getपैकेजों को स्थापित करने के लिए बहुत उपयोगी है जो कि कल्प के लिए (या नहीं हो सकता)। यह जवाब ऐसे पैकेजों को सिंक्रोनाइज़ करने से संबंधित है।

जिस तरह से आप सुनिश्चित करते हैं कि एल-गेट का उपयोग करते समय दिए गए पैकेज स्थापित किए गए हैं, आपके लिए इनिट फ़ाइल में कुछ ऐसा जोड़ना है

(el-get 'sync '(packages))

जहाँ संकुल उन संकुल की सूची है जिन्हें आप स्थापित करना चाहते हैं। यह फ़ंक्शन समान है package-installक्योंकि यह पैकेजों को केवल तभी इंस्टॉल करता है जब वे पहले से इंस्टॉल नहीं होते हैं, अन्यथा यह केवल पैकेज को इनिशियलाइज़ करता है।


5

मैं emacs- स्टार्टर-किट से एक छोटी सी चाल "चोरी" का उपयोग करता हूं (मुझे लगता है):

(defun maybe-install-and-require (p)
  (when (not (package-installed-p p))
   (package-install p))
  (require p))

इसलिए जब मुझे पैकेज की आवश्यकता होती है, तो मैं बस उपयोग करता हूं:

(maybe-install-and-require 'magit)

Emacs startups पर, मेरे कॉन्फिग का मूल्यांकन package.elकरते हुए , यदि यह इंस्टॉल नहीं हुआ है तो मैगिट इंस्टॉल करने के लिए प्रदान करेगा।

आप यहाँ मेरा विन्यास पा सकते हैं:

https://github.com/mdallastella/emacs-config/


1
एक ही दर्शन के बाद, आप इस्तेमाल कर सकते हैं 'विरोधाभास-की आवश्यकता होती है' से विरोधाभास
csantosb

3

मेरे पास ~ / emacs डायरेक्टरी है जो मर्क्यूरियल-वर्जन नियंत्रित है और इसमें मेरी एमएसीएस सेटअप सब कुछ शामिल है (~ / emacs / site-lisp मैन्युअल रूप से डाउनलोड की गई लाइब्रेरियों के लिए, ~ / emacs / elpa elpa- इनवॉइस लाइब्रेरी के लिए, ~ / emacs / etc /) splitted के लिए .emacs, ~ / emacs / dot-emacs.el जिसे मैं ~ / .emacs के रूप में सिमिल करता हूं)। इस पेड़ के अंदर सभी महत्वपूर्ण फाइलों को रखने के लिए कुछ पैकेजों की आवश्यकता होती है, लेकिन यह अच्छी तरह से काम करता है। उन कुछ बिट्स जो मशीन-विशिष्ट हैं जिन्हें मैंने सिस्टम नाम पर सशर्त रूप से लागू किया है।

इसलिए मैं कुछ भी स्थापित / पुन: कॉन्फ़िगर / परिवर्तित करने के बाद, मैं केवल उन सभी मशीनों के बीच सभी परिवर्तनों को खींच / धक्का देता हूं, जिनका मैं उपयोग करता हूं।

अतिरिक्त लाभ यह है कि मेरे पास मेरे कॉन्फ़िगरेशन का पूरा इतिहास है और कुछ भी गलत होने पर वापस / बिसेक्ट / रिवर्ट जा सकता है।

पीएस मर्क्यूरियल विशेष रूप से उपयुक्त लगता है क्योंकि इसमें प्राकृतिक दो-साइड पुल / पुश हैं, लेकिन समान सेटअप को गिट या किसी अन्य डीवीसी के साथ प्राप्त करना कठिन नहीं होना चाहिए।


3

मैं इस राशि setup-packages.elमेरी Emacs सेटअप है जहाँ से कोड की एक संकर है में प्रस्तावना और पैकेज प्रबंधन पर Tomorokoshi के ब्लॉग

setup-packages.el निम्नलिखित कार्य करता है:

  • elpaयदि कोई मौजूद नहीं है, तो पैकेज के लिए एक निर्देशिका बनाएं और इसे और इसके उप-निर्देशिकाओं को इसमें जोड़ें load-path
  • package-archivesमेलपा के साथ अद्यतन सूची।
  • जांचें कि क्या आपके पास my-packagesसूची में सूचीबद्ध सभी पैकेज स्थापित हैं। यदि कोई पैकेज स्थापित नहीं है, तो इसे स्थापित करें।

कैसे लागू करें?

  • setup-packages.elनीचे अपनी ~/.emacs.d/निर्देशिका में सहेजें ।
  • सेट user-emacs-directory, setup-packages-fileऔर my-packagesअपने init.elऔर चर में (load setup-packages-file)

जब आप पहली बार किसी ऐसी मशीन पर emacs शुरू करते हैं जिसमें ये पैकेज स्थापित नहीं होते हैं, तो सूचीबद्ध सभी pacakges my-packagesऑटो-इंस्टॉल हो जाएंगे।

सेटअप-packages.el

;; setup-packages.el - Package management

(require 'cl)
(require 'package)

;; Set the directory where you want to install the packages
(setq package-user-dir (concat user-emacs-directory "elpa/"))

;; Add melpa package source when using package list
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)

;; Load emacs packages and activate them
;; This must come before configurations of installed packages.
;; Don't delete this line.
(package-initialize)
;; `package-initialize' call is required before any of the below
;; can happen

;; Auto install the required packages
;; Method to check if all packages are installed
(defun packages-installed-p ()
  (loop for p in my-packages
        when (not (package-installed-p p)) do (return nil)
        finally (return t)))

;; if not all packages are installed, check one by one and install the missing ones.
(unless (packages-installed-p)
  ;; check for new packages (package versions)
  (message "%s" "Emacs is now refreshing its package database...")
  (package-refresh-contents)
  (message "%s" " done.")
  ;; install the missing packages
  (dolist (p my-packages)
    (when (not (package-installed-p p))
      (package-install p))))

(provide 'setup-packages)

init.el

आपको अपने में निम्नलिखित की आवश्यकता होगी init.el:

(setq user-home-directory  (getenv "HOME"))
(setq user-emacs-directory (concat user-home-directory ".emacs.d/"))
(setq setup-packages-file  (expand-file-name "setup-packages.el" user-emacs-directory))

;; A list of packages to ensure are installed at launch
(setq my-packages
      '(
        ;; package1
        ;; package2
       ))

(load setup-packages-file nil :nomessage) ; Load the packages

2

अपने कॉन्फिगरेशन को मिरर करने के लिए मैंने Syncthing का उपयोग करते हुए एक अलग दृष्टिकोण के लिए जाने का फैसला किया ; मेरी किसी भी कॉन्फिग फाइल में हर बदलाव मेरे पीसी के किसी अन्य हिस्से को उसकी परवाह किए बिना प्रचारित करता है, इसलिए जब मैं पैकेजों को अपग्रेड करता हूं तो मुझे इसे केवल एक पीसी में करना होता है।


2

RSYNC : rsyncकिसी होम नेटवर्क पर या sshरिमोट सर्वर के माध्यम से या तो चुनिंदा फ़ोल्डर्स / फाइलों को सिंक्रनाइज़ करें ।

rsyncएक तरह से सिंक्रनाइज़ेशन उपयोगिता है जो लक्ष्य पर फ़ाइलों को हटाने में सक्षम है , इसलिए कृपया अपने डेटा को स्रोत और लक्ष्य दोनों स्थानों पर बैक-अप करना सुनिश्चित करें , और वास्तविक चीज़ करने से पहले--dry-run विकल्प का उपयोग करके अच्छी तरह से परीक्षण करें ।

.authinfoफ़ाइल को ठीक से कॉन्फ़िगर करने के तरीके के बारे में पढ़ने के लिए , https://www.gnu.org/software/emacs/manual/auth.html एक उदाहरण .authinfoफ़ाइल सामग्री (जिसमें कई अलग-अलग प्रविष्टियाँ हो सकती हैं) देखें निम्नानुसार है:

machine mymachine login myloginname password mypassword port myport

दूरस्थ सर्वर rsync-remoteपर सिंक्रनाइज़ करने के लिए फ़ंक्शन को कॉन्फ़िगर करें और उपयोग sshकरें। या, rsync-localएक ही कंप्यूटर या एक विश्वसनीय होम नेटवर्क पर सिंक्रनाइज़ करने के लिए फ़ंक्शन का उपयोग करें ।

(require 'auth-source)

;;; EXAMPLE:
;;;   (get-auth-info "12.34.567.89" "username")
;;;   (get-auth-info "localhost" "root")
(defun get-auth-info (host user &optional port)
  (let ((info (nth 0 (auth-source-search
                      :host host
                      :user user
                      :port port
                      :require '(:user :secret)
                      :create t))))
    (if info
      (let* ((port (plist-get info :port))
             (secret-maybe (plist-get info :secret))
             (secret
               (if (functionp secret-maybe)
                 (funcall secret-maybe)
                 secret-maybe)))
          (list port secret))
    nil)))

(defun rsync-filter (proc string)
  (cond
    ((string-match
       "^\\([a-zA-Z0-9_\\-\\.]+\\)@\\([a-zA-Z0-9_\\-\\.]+\\)'s password: "
       string)
      (let* ((user (substring string (match-beginning 1) (match-end 1)))
             (host (substring string (match-beginning 2) (match-end 2)))
             (password (car (cdr (get-auth-info host user)))))
        (process-send-string proc (concat password "\n"))))
    ((not (or (string-match "files\\.\\.\\.\r" string)
              (string-match "files to consider\n" string)))
      (with-current-buffer (messages-buffer)
        (let ((inhibit-read-only t))
          (goto-char (point-max))
          (when (not (bolp))
            (insert "\n"))
          (insert string)
          (when (not (bolp))
            (insert "\n")))))))

(defun rsync-remote ()
"Use rsync to a remote server via ssh.  Back-up your data first!!!"
(interactive)
  (let* (
      (host "localhost")
      (username "root")
      (port (or (car (get-auth-info host username))
                (number-to-string (read-number "Port:  "))))
      (source
        (let ((dir (expand-file-name (locate-user-emacs-file "elpa/"))))
          (if (file-directory-p dir)
            dir
            (let ((debug-on-quit nil)
                  (msg (format "`%s` is not a valid directory." dir)))
              (signal 'quit `(,msg))))))
      (target "/private/var/mobile/elpa/")
      (ssh "/usr/bin/ssh")
      (rsync "/usr/bin/rsync")
      (rsync-include-file "/path/to/include-file.txt")
      (rsync-exclude-file "/path/to/exclude-file.txt")
      (rsh (concat "--rsh=ssh -p " port " -l " username))
      (host+target (concat host ":" target)))
    (start-process
        "rsync-process"
        nil
        rsync
        "-avr" ;; must specify the `-r` argument when using `--files-from`
        "--delete"
        ;; The paths inside the exclusion file must be relative, NOT absolute.
        ;;; (concat "--files-from=" rsync-include-file)
        ;;; (concat "--exclude-from=" rsync-exclude-file)
        rsh
        source
        host+target)
    (set-process-filter (get-process "rsync-process") 'rsync-filter)
    (set-process-sentinel
      (get-process "rsync-process")
      (lambda (p e) (when (= 0 (process-exit-status p))
        (message "rsync-remote:  synchronizing ... done."))))))

(defun rsync-local ()
"Use rsync locally -- e.g., over a trusted home network.
 Back-up your data first!!!"
  (interactive)
  (let (
      (rsync-program "/usr/bin/rsync")
      (source
        (let ((dir (expand-file-name
                     (file-name-as-directory
                       (read-directory-name "Source Directory: " nil nil nil nil)))))
          (if (file-directory-p dir)
            dir
            (let ((debug-on-quit nil)
                  (msg (format "`%s` is not a valid directory." dir)))
              (signal 'quit `(,msg))))))
      (target (expand-file-name
                (file-name-as-directory
                  (read-directory-name "Target Directory: " nil nil nil nil)))))
    (unless (y-or-n-p (format "SOURCE:  %s | TARGET:  %s" source target))
      (let ((debug-on-quit nil))
        (signal 'quit `("You have exited the function."))))
    (start-process "rsync-process"
      nil
      rsync-program
      "--delete"
      "-arzhv"
      source
      target)
    (set-process-filter (get-process "rsync-process") #'rsync-process-filter)
    (set-process-sentinel
      (get-process "rsync-process")
      (lambda (p e)
        (when (= 0 (process-exit-status p))
        (message "Done!"))))))

0

https://github.com/redguardtoo/elpa-mirror सभी स्थापित पैकेजों का एक स्थानीय भंडार बनाता है।

उपयोग सरल है, बस चलाएं M-x elpamr-create-mirror-for-installed

अन्य मशीनों पर, (setq package-archives '(("myelpa" . "~/myelpa/")))अपने में डालें .emacsऔर Emacs को पुनरारंभ करें।

अब सभी मशीनों पर, आपको पैकेज का एक ही संस्करण मिलता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.