我在不同的地方使用emacs,并且希望在各处安装类似的设置和软件包。我想可以将版本控制存储库用于安装文件。由于我使用的是Prelude,那就是~/.emacs.d/personal/
。
我不知道如何处理包裹。在.emacs.d/
安装的软件包列表中是否有文件可用于在其他计算机上制作emacs并安装其中列出的软件包?
我在不同的地方使用emacs,并且希望在各处安装类似的设置和软件包。我想可以将版本控制存储库用于安装文件。由于我使用的是Prelude,那就是~/.emacs.d/personal/
。
我不知道如何处理包裹。在.emacs.d/
安装的软件包列表中是否有文件可用于在其他计算机上制作emacs并安装其中列出的软件包?
Answers:
没有自动生成的清单文件可以同步以达到所需的效果。
也就是说,您可以做的就是package-install
在emacs配置本身中添加对的调用。
(package-install 'auctex)
这个想法是package-install
幂等的,因此,如果该软件包已经存在,则实际上什么也不会发生。假设您对使用的每个程序包(或至少是依赖关系图中的叶子)都进行了调用,那么它将有效地跨计算机同步程序包。
对于多个软件包,可以使用以下命令:
(setq my-package-list '(package1 package2 packageN))
(mapc #'package-install my-package-list)
package-install
。
package.el
自从链接答案以来,已经发生了变化。当时有可能package-install
对现有软件包进行操作,而不仅仅是已卸载的软件包。
我将.emacs.d目录保留在版本控制中。然后,在我的init.el及后续文件中,我使用use-package定义软件包设置。use-package不仅会延迟加载您的软件包,而且如果您设置的任何软件包存储库中不存在它们,它也会按需下载它们。
例如,我使用go-mode,但不是在每台机器上都使用。在我的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。任何新软件包都将下载并安装。
:ensure go-mode
指定重复的软件包名称,而是只需指定:ensure t
:hook
关键字来简化代码。
一种替代方法如下:由于我不仅要同步我的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
目录放置在与OwnCloud,DropBox或任何其他文件同步服务同步的目录中,然后从~/.emacs.d
该目录创建指向该共享目录的符号链接。
虽然这package.el
是安装软件包的标准方法,但您可能还想尝试一下el-get
这对于安装不在elpa上(或不能在elpa上)的软件包非常有用。该答案涉及同步此类软件包。
确保使用el-get时已安装给定软件包的方法是在init文件中添加以下内容
(el-get 'sync '(packages))
其中,packages是要安装的软件包的列表。此功能类似于package-install
仅在尚未安装软件包的情况下才安装软件包,否则仅初始化软件包。
我使用emacs-starter-kit中的一个小技巧“偷了”(我认为):
(defun maybe-install-and-require (p)
(when (not (package-installed-p p))
(package-install p))
(require p))
因此,当我需要包装时,我只需使用:
(maybe-install-and-require 'magit)
在emacs初创公司上,评估我的配置package.el
将提供安装magit(如果未安装的话)。
您可以在这里找到我的配置:
我有〜/ emacs目录,该目录是由软件版本控制的,包含我的emacs设置包括的所有内容(〜/ emacs / site-lisp用于手动下载的库,〜/ emacs / elpa用于elpa安装的库,〜/ emacs / etc /对于分割的.emacs,〜/ emacs / dot-emacs.el,我将其链接为〜/ .emacs)。它需要对某些软件包进行一些调整,以使所有重要文件都包含在该树中,但是效果很好。我通过系统名称的条件实现了那些机器专用的几位。
因此,在我安装/重新配置/更改任何内容之后,我只需提交/拉动我使用的所有计算机之间的所有更改。
额外的好处是,我具有完整的配置历史记录,可以在发生任何错误的情况下返回/平分/还原。
PS mercurial似乎特别适合,因为它具有自然的两侧拉/推功能,但是使用git或任何其他dvc很难实现类似的设置。
setup-packages.el
我的emacs设置中包含此代码,它是Prelude和Tomorokoshi的Package Management博客中代码的混合体。
setup-packages.el
执行以下操作:
elpa
如果不存在,请为软件包创建目录,并将其及其子目录添加到中load-path
。package-archives
用Melpa 更新清单。my-packages
安装列表中列出的所有软件包。如果未安装软件包,请安装它。setup-packages.el
以下内容保存到您的~/.emacs.d/
目录中。user-emacs-directory
,setup-packages-file
以及my-packages
变量在你init.el
做(load setup-packages-file)
。当您第一次在没有安装这些软件包的机器上启动emacs时,其中列出的所有功能my-packages
都会自动安装。
;; 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
:
(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
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!"))))))
https://github.com/redguardtoo/elpa-mirror创建所有已安装软件包的本地存储库。
用法很简单,只需运行即可M-x elpamr-create-mirror-for-installed
。
在其他机器上,插入(setq package-archives '(("myelpa" . "~/myelpa/")))
您的.emacs
Emacs并重新启动。
现在,在所有计算机上,您将获得完全相同版本的软件包。