跳转到内容
来自 Arch Linux 中文维基

本文主要讲解了 Emacs 的使用技巧和高效方法,包括各方面的实用提示。

TRAMP

TRAMP(Transparent Remote Access, Multiple Protocols)是一个扩展名,顾名思义,它可以通过多种协议对远程文件进行透明访问。当提示输入文件名时,输入一个特定的表单就会调用 TRAMP。举几个例子:

以根权限打开 /etc/hosts 前提示输入根密码:

C-x C-f /sudo::/etc/hosts

以“你”的身份通过 SSH 连接到 “remotehost”,并打开文件 ~/example.txt

C-x C-f /ssh:you@remotehost:~/example.txt

TRAMP 的路径形式通常为"/[协议]:[[用户@]主机]:<文件>"。

以“你”的身份连接“myhost”,并使用 sudo 编辑 /etc/hosts


/ssh:you@remotehost|sudo:remotehost:/etc/hosts

TRAMP 支持的功能远不止上面的例子。欲了解更多信息,请参阅随 Emacs 一起发布的 TRAMP info 手册。

将 Emacs 用作 git 合并工具

Git 默认支持使用 Emacs 的 Emerge 模式作为合并工具。不过,你可能更喜欢 Ediff 模式。遗憾的是,由于技术原因,git 并不支持这种模式。但还是有办法在调用 emacs 时评估一些 elisp 代码来使用它。

.gitconfig
[mergetool.ediff]
    cmd = emacs --eval \" (progn (defun ediff-write-merge-buffer () (let ((file ediff-merge-store-file)) (set-buffer ediff-buffer-C) (write-region (point-min) (point-max) file) (message \\\"Merge buffer saved in: %s\\\" file) (set-buffer-modified-p nil) (sit-for 1))) (setq ediff-quit-hook 'kill-emacs ediff-quit-merge-hook 'ediff-write-merge-buffer) (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\" \\\"$BASE\\\" nil \\\"$MERGED\\\"))\" 

[merge]
	tool = ediff

注意,命令必须在一行中。 在上例中,我们启动了一个新的 Emacs 实例。你可能想使用 emacsclient 更快地启动 Emacs,但不建议这样做,因为 Ediff 调用并不干净:它可能会扰乱你当前的 Emacs 会话。

如果想立即启动,可以使用 -q 参数。如果想快速启动 Emacs,同时至少保留部分配置,可以使用:

emacs -q -l ~/.emacs-light

其中的轻量配置文件只加载 Ediff 所需的内容。

有关此技巧和 Ediff 问题的更多详情,请参阅 kerneltrap.orgstackoverflow

将大写锁定键用作 Control 键

有些用户喜欢这种行为,以避免出现所谓的 “emacs 小指”。 在图形用户界面桌面(XorgWayland)、终端甚至控制台中实现这一功能的好方法是使用 keyd安装此软件包并创建此配置文件:

/etc/keyd/main.conf
[ids]	
*

[main]
capslock = overload(control, noop)

然后启用/启动 keyd 服务。

这样大写锁定键就会启 Control 键之作用。

复用 emacs 和 emacsclient

在同一个 emacs-session 中打开新文件,需要使用 emacsclient。如果会话存在,emacs 命令本身也可以进行封装,以更智能地打开文件。

要启动会话,需要使用 start-server。该代码段将在 emacs 的第一个会话中创建服务器。将其添加到 emacs 配置文件中。

.emacs or .emacs.d/init.el
(require 'server)
(unless (server-running-p)
  (server-start))

Shell 别名方法并不能满足要求,因为你还需要传递变量或启动自己的独立会话。在 shell 的 .bashrc 或任何 rc 文件中添加此选项。这样,如果参数被传递,emacs 命令就会像 emacsclient 一样运行。

function emacs {
    if [[ $# -eq 0 ]]; then
        /usr/bin/emacs # "emacs" is function, will cause recursion
        return
    fi
    args=($*)
    for ((i=0; i <= ${#args}; i++)); do
        local a=${args[i]}
        # NOTE: -c for creating new frame
        if [[ ${a:0:1} == '-' && ${a} != '-c' && ${a} != '--' ]]; then
            /usr/bin/emacs ${args[*]}
            return
        fi
    done
    setsid emacsclient -n -a /usr/bin/emacs ${args[*]}
}

如果要在新会话中运行,只需执行 emacs file -

多种配置

您可以使用多种配置,并告诉 Emacs 加载其中一种或另一种。

例如,让我们定义两种配置文件。

.emacs
(load "~/.emacs.d/main" nil t)
(load "~/.emacs.d/functions" nil t)
(load "~/.emacs.d/modes" nil t)
(load "~/.emacs.d/plugins" nil t)
(load "~/.emacs.d/theme" nil t)

这是我们针对守护进程加载的全部配置。但 plugins 文件很大,加载速度也很慢。如果我们想生成一个不需要 plugins 功能的新 Emacs 实例,那么从长远来看,每次加载都会很麻烦。

.emacs-light
(load "~/.emacs.d/main" nil t)
(load "~/.emacs.d/functions" nil t)
(load "~/.emacs.d/modes" nil t)
(load "~/.emacs.d/theme" nil t)

现在我们用:

emacs -q -l ~/.emacs-light

您可以创建一个别名(如 emacs-light),以便调用。

局部变量和自定义变量

您可以在配置文件中定义变量,以后可以在本地对文件进行修改。

(defcustom my-compiler "gcc" "Some documentation")

现在,在任何文件中都可以通过两种方式定义局部变量,详见手册

  • 使用 M-x add-file-local-variable-prop-line 可以在开头添加一行注释,类似于:
// -*- my-compiler:g++; mode:c++ -*-
  • 或者使用 M-x add-file-local-variable 在文件末尾添加行:
// Local Variables:
// my-compiler: g++
// mode: c++
// End:

请注意,要使这些值生效,您需要调用 M-x revert-buffer

默认情况下,自定义变量被认为是不安全的。如果你试图打开一个包含重新定义自定义变量的局部变量的文件,Emacs 会要求你确认。

您可以将变量声明为安全变量,从而消除 Emacs 的确认提示。您需要指定一个谓词,任何新值都必须经过该谓词的验证,这样才能被认为是安全的。

(defcustom my-compiler "gcc" "Some documentation" :safe 'stringp)

在上例中,如果您试图设置字符串以外的内容,Emacs 会认为这是不安全的。

自定义色彩和主题

可以使用 face 工具轻松定制颜色。


(set-face-background  'region                 "color-17")
(set-face-foreground  'region                 "white")
(set-face-bold-p      'font-lock-builtin-face t ) 

您可以让 Emacs 告诉您点所在的 face 的名称。为此,请使用 customize-face 功能。该功能会告诉你如何设置颜色、粗体、下划线等。

控制台中的 Emacs 可以处理 256 种颜色,但必须使用合适的终端。例如,URxvt 支持 256 种颜色。你可以使用 list-colors-display 查看支持颜色的完整列表。这在很大程度上取决于终端。

参见:

SyncTeX 支持

Emacs 是一款功能强大的 LaTeX 编辑器。这主要是因为你可以调整或创建最适合自己需要的 LaTeX 模式。

不过,也可能会遇到一些挑战,比如 SyncTeX 支持。首先,你需要确保你的 TeX 发行版支持 SyncTeX。如果你手动安装了 TeX Live,可能需要安装 synctex 软件包。

# umask 022 && tlmgr install synctex

SyncTeX 支持与阅读器有关。在此,我们将以 Zathura 为例,因此如果您想使用其他 PDF 阅读器,则需要对代码进行调整。

(defcustom tex-my-viewer "zathura --fork -s -x \"emacsclient --eval '(progn (switch-to-buffer  (file-name-nondirectory \"'\"'\"%{input}\"'\"'\")) (goto-line %{line}))'\"" 
  "PDF Viewer for TeX documents. You may want to fork the viewer
so that it detects when the same document is launched twice, and
persists when Emacs gets closed.

Simple command:

  zathura --fork

We can use

  emacsclient --eval '(progn (switch-to-buffer  (file-name-nondirectory \"%{input}\")) (goto-line %{line}))'

to reverse-search a pdf using SyncTeX. Note that the quotes and double-quotes matter and must be escaped appropriately."
:safe 'stringp)

在这里,我们定义了自定义变量。如果您使用的是 AucTeX 或 Emacs 默认的 LaTeX 模式,则必须相应地设置查看器。

现在用 Emacs 打开一个 LaTeX 源文件,编译文档,然后启动查看器。Zathura 进程会自动创建。如果按下 Ctrl+Left click 键,Emacs 就会将点放在相应的位置。

systemd 文件的语法高亮显示

您可以使用 systemd-mode

或者,你也可以在 init 文件中添加以下内容,让 emacs 为 systemd 文件(服务、定时器等)着色:


 (add-to-list 'auto-mode-alist '("\\.service\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.timer\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.target\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.mount\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.automount\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.slice\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.socket\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.path\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.netdev\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.network\\'" . conf-unix-mode))
 (add-to-list 'auto-mode-alist '("\\.link\\'" . conf-unix-mode))

为 emacs-nox 提供剪贴板支持

要在 emacs-nox 中使用 Xorg 剪贴板,请安装xclip 并在 ~/.emacs 中添加以下函数[1]

;; use xclip to copy/paste in emacs-nox
(unless window-system
  (when (getenv "DISPLAY")
    (defun xclip-cut-function (text &optional push)
      (with-temp-buffer
	(insert text)
	(call-process-region (point-min) (point-max) "xclip" nil 0 nil "-i" "-selection" "clipboard")))
    (defun xclip-paste-function()
      (let ((xclip-output (shell-command-to-string "xclip -o -selection clipboard")))
	(unless (string= (car kill-ring) xclip-output)
	  xclip-output )))
    (setq interprogram-cut-function 'xclip-cut-function)
    (setq interprogram-paste-function 'xclip-paste-function)
    ))
提示:您还可以通过添加以下内容来启用终端鼠标支持:
;; xterm mouse support
(require 'mouse)
(xterm-mouse-mode t)

参见 mwheel.el[失效链接 2024-11-05 ⓘ]