從 Vim 遷移到 spacemacs

jopen 8年前發布 | 15K 次閱讀 Vim

從 Vim 遷移到 spacemacs

  • 從 vim 遷移到 spacemacs

  • 本文檔的目的

  • 哲學

  • 基本使用

    • 緩沖區

    • 窗戶

    • 模式和狀態

    • 微觀狀態

    • 條款

    • 方便快捷的按鍵綁定

    • 執行命令

    • 緩沖區和窗口管理

    • 文件

    • 幫助系統

    • 探索

  • 定制

    • 改變 escape 鍵

    • 改變代碼高亮主題

    • 非高亮查找

    • 會話

    • 使用虛線作為導航

    • 變量

    • 快捷鍵

    • 函數

    • .spacemacs 配置文件

    • Emacs Lisp

    • 激活一層

    • 創建一個層

    • 安裝一個包

    • 加載一個包

    • 卸載一個包

    • 常見的調整

  • 其他有用的鏈接

本文檔的目的

本文旨在通過跨越 vim 和 Spacemacs 之間的差距,以補充 Spacemacs 文檔。雖然有些信息可能被復制,但這并不能代替 Spacemacs 文檔。建議您閱讀這兩個文件,充分認識 Spacemacs

哲學

很多 vim 都有的誤解是,Spacemacs 是 vim 的 Emacs 克隆。Spacemacs 沒有完全模仿 vim 的行為,它只有在編輯的時候才這樣。你不能指望每個 vim 指令都可用,盡管很多都是可用的。你不能用 Vimscript 配置 Spacemacs,反正沒人喜歡 Vimscript。重要的是,Spacemacs 旨在使用 vim 高級編輯模式以及 Emacs 更好的配置語言來改善 vim 和 Emacs 兩者。

基本介紹

術語

Spacemacs 使用與 vim 不同的術語,可能會使新用戶感到困惑。本節試圖厘清這些困惑。

模式和狀態

在 vim 中,你具有多種編輯模式如插入模式和可視模式來處理文本。在 Emacs 中,我們使用的是狀態。它們等同于 vim 的模式。例如 evil-insert-state 與 vim中的insert-mode相同。

Emacs 中的 minor-mode 就像是激活一項功能。例如:aggressive-indent-mode 就是一個 minor-mode,它可以在你輸入的同時自動縮進代碼。需要知道的是,在一個緩沖區中可以激活多個 minor-modes。許多 Emacs 包通過提供一個 minor-mode 進行工作。Major-mode 確定 Emacs 在當前緩沖區的行為。通常每個文件類型對應一個 major-mode。一個 major-mode 的例子如 python-mode,它對 python 文件提供針對 python 的設置。每個緩沖區只有一個 major-mode。

Spacemacs 具有層的概念。層類似于 vim 中的插件。它們提供可以在 Spacemacs 中使用的新功能。但是層通常是由數個相互整合良好的包組成。例如,python 層包括自動補齊支持,文檔查找,測試和其它由不同的包提供的功能。這使你不需要考慮安裝什么包,只需要考慮你想要什么功能。關于層的更多內容可以參考自定義章節和官方文檔。同時還有一個關于編寫層的更深入的指南

微狀態

Spacemacs 提供一個稱為微狀態的特殊功能。微狀態允許相似的命令連續執行,不需要重復按鍵。微狀態通常由使用如下模式的鍵位綁定觸發:<Leader> <group>這里的 group 是微狀態從屬的目錄。當處于一個微狀態時,你將會在窗口的底部看到說明文檔。要退出微狀態,按 q 鍵。

從 Vim 遷移到 spacemacs

鍵位綁定約定

Spacemacs 使用 SPC 作為它的 <Leader> 鍵。本文檔也使用 SPC 作為 <Leader> 鍵。所有的鍵位綁定都采用助記方式,并由 <Leader> 鍵組織。例如,語言指定命令的鍵位綁定通常使用 SPC m前綴。Spacemacs 使用的約定如下 . 注意所有的鍵位綁定都可以更改。

Spacemacs 在一個延遲之后使用 which-key 來顯示可用的鍵位綁定:

從 Vim 遷移到 spacemacs

運行命令

可以使用 SPC:運行 Emacs 命令。這將會彈出一個使用 Helm 的緩沖區。這個緩沖區中可以運行任意的 Emacs 命令。你同樣可以使用:運行許多外部命令,就跟 vim 中一樣。

注意:你可以使用: 運行 Emacs 交互命令,但是不能使用 SPC : 運行外部命令。

緩沖區和窗口管理

緩沖區

在 Emacs 和 vim 中緩沖區本質上是相同的。緩沖區的快捷鍵都具有 SPC b 前綴。

 快捷鍵  功能
    SPC b b <buffer-name>    創建一個名為<buffer-name>的緩沖區。
    SPC b b    通過打開緩沖區和最近的文件搜索。
    SPC b n 或 :bnext    切換到下一個緩沖區。(參見特殊緩沖區)
    SPC b p 或 :bprevious    切換到前一個緩沖區。 (參見特殊緩沖區)
    SPC b d 或 :bdelete    結束當前緩沖區。
    SPC b k    查找并結束一個緩沖區。
    SPC b K    結束除當前緩沖區的所有其他緩沖區。
    SPC b .    緩沖區微狀態。

特殊緩沖區

Emacs 默認會創建大量緩沖區,這些緩沖區很多人從來都不會使用到,就像 *Messages*。Spacemacs 會在使用這些快捷鍵時自動忽略這些緩沖區。可以在這里找到更多相關信息。

窗口

窗口就像 vim 中的分割。它們在一次編輯多個文件時相當有用。所有的快捷鍵都有 SPC w 前綴。

 快捷鍵  功能
    SPC w v 或 :vsplit     在右側打開一個垂直分割。
    SPC w s 或 :split     在下部打開一個水平分割。
    SPC w h/j/k/l     在窗口間導航。
    SPC w H/J/K/L     移動當前窗口。
    SPC w .     窗口微狀態。

文件

Spacemacs 中所有文件命令都有 SPC f 前綴。

 快捷鍵  功能
    SPC f f     打開一個緩沖區搜索當前目錄中的文件。
    SPC f r     打開一個緩沖區在最近打開的文件中搜索。
    SPC f s 或 :w     保存當前文件。
    :x     保存當前文件并退出。
    :e <file>     打開<file>

幫助系統

Emacs 具有一個可擴展的幫助系統。所有的快捷鍵都有SPC h d 前綴,以允許便捷地訪問幫助系統。最重要的快捷鍵是 SPC h d f, SPC h d k, 和 SPC h d v。同樣還有 SPC <f1> 允許用戶搜索文檔。

 快捷鍵  功能
    SPC h d f     對一個功能提示并顯示其文檔。
    SPC h d k     對一個快捷鍵提示并顯示其綁定的內容。
    SPC h d v     對一個變量提示并顯示其文檔和當前值。
    SPC <f1>     搜索一個命令,功能,變量或接口,并顯示其文檔

不論何時,你遇到怪異的行為或想知道是什么東西做的,這些功能是你應該首先查閱的。

探索

有幾種方式可以探索 Spacemacs 的功能。一個是閱讀 Github 上的源代碼。你可以開始了解 Emacs Lisp,并能知道 Spacemacs 是怎樣工作的。你還能通過如下快捷鍵來探索:

 快捷鍵  功能
    SPC f e h     列出所有層并允許你瀏覽層上的文件。
    SPC ?     列出所有快捷鍵。

自定義

.spacemacs  文件

首次啟動 spacemacs 時,會提示你選擇編輯樣式。如果你現在正讀到這里,你可能會選擇 vim 樣式。這樣將會使用選擇的相應樣式創建一個  .spacemacs   文件。大多數瑣碎的配置都在這個文件中。

在這個文件中有四個頂級函數:dotspacemacs/layers,  dotspacemacs/init,dotspacemacs/user-init 和 dotspacemacs/user-config。

Dotspacemacs/layers 函數僅用于啟用和禁用層和包。Dotspacemacs/init  函數是在啟動過程中,在其他東西運行前運行,并且包含  Spacemacs  設置。 除非你需要更改默認 Spacemacs 設置,否則你不用動這個函數。Dotspacemacs/user-init 函數也是在其他程序運行前運行,并包含用戶特定配置。Dotspacemacs/user-config 函數是你用到最多的函數。 在這里,你可以定義任何用戶配置。


快捷鍵
                功能
                SPC f e d                 打開你的 .spacemacs
                SPC f e D                 使用diff 通過默認模版手動更新你的 .spacemacs 

Emacs Lisp

這個部分介紹幾個 配置 Spacemacs 需要的 Emacs Lisp 函數。如需詳細了解這個語言,請查看次鏈接。如果你很想了解 emacs lisp 的一切,請使用 SPC h i elisp RET 上的信息頁面

變量

設置變量是定制 Spacemacs 行為最常見的方式。語法很簡單:

(setq variable value) ; Syntax
;; Setting variables example
(setq variable1 t ; True
      variable2 nil ; False
      variable3 '("A" "list" "of" "things"))

快捷鍵

定義快捷鍵是幾乎每個人都想做的事情,最好的方式就是使用內置的 define-key 函數。

(define-key map new-keybinding function) ; Syntax
;; Map H to go to the previous buffer in normal mode
(define-key evil-normal-state-map (kbd "H") 'spacemacs/previous-useful-buffer)
;; Mapping keybinding to another keybinding
(define-key evil-normal-state-map (kbd "H") (kbd "^")) ; H goes to beginning of the line

map 是你想要綁定鍵位到的 keymap。大多數情況下你會使用 evil-<state-name>-state-map。其對應不同的 evil-mode 狀態。例如,使用 evil-insert-state-map 映射用于插入模式的快捷鍵。

使用 evil-leader/set-key 函數來映射 <Leader> 快捷鍵。

(evil-leader/set-key key function) ; Syntax
;; Map killing a buffer to <Leader> b c
(evil-leader/set-key "bc" 'kill-this-buffer)
;; Map opening a link to <Leader> o l only in org-mode
(evil-leader/set-key-for-mode 'org-mode
  "ol" 'org-open-at-point)

函數

你可能偶爾想要定義一個函數做更復雜的定制,語法很簡單:

(defun func-name (arg1 arg2)
  "docstring"
  ;; Body
  )
;; Calling a function
(func-name arg1 arg1)

這里有個現實可用的示例函數:

;; This snippet allows you to run clang-format before saving
;; given the current file as the correct filetype.
;; This relies on the c-c++ layer being enabled.
(defun clang-format-for-filetype ()
  "Run clang-format if the current file has a file extensions
in the filetypes list."
  (let ((filetypes '("c" "cpp")))
    (when (member (file-name-extension (buffer-file-name)) filetypes)
      (clang-format-buffer))))
;; See http://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html for
;; what this line means
(add-hook 'before-save-hook 'clang-format-for-filetype)

激活一個層

正如上文術語那段所說,層提供一個簡單的方式來添加特性。可在 .spacemacs 文件中激活一個層。在文件中找到 dotspacemacs-configuration-layers 變量,默認情況下,它看起來應該是這樣的:

(defun dotspacemacs/layers ()
  (setq-default
   ;; ...
   dotspacemacs-configuration-layers '(;; auto-completion
                                       ;; better-defaults
                                       emacs-lisp
                                       ;; (git :variables
                                       ;;      git-gutter-use-fringe t)
                                       ;; markdown
                                       ;; org
                                       ;; syntax-checking
                                       )))

你可以通過刪除分號來取消注釋這些建議的層,開箱即用。要添加一個層,就把它的名字添加到列表中并重啟 Emacs 或按 SPC f e R。使用 SPC f e h 來顯示所有的層和他們的文檔。

創建一個層

為了將配置分組或當配置與你的 .spacemacs 文件之間不匹配時,你可以創建一個配置層。Spacemacs 提供了一個內建命令用于生成層的樣板文件:SPC :configuration-layer/create-layer。這條命令將會生成一個如下的文件夾:

[layer-name]
  |__ [local]*
  | |__ [example-mode-1]
  | |     ...
  | |__ [example-mode-n]
  |__ config.el*
  |__ funcs.el*
  |__ keybindings.el*
  |__ packages.el

[] = 文件夾
* = 不是命令生成的文件

Packages.el 文件包含你可以在 <layer-name>-packages 變量中安裝的包的列表。所有 MELPA 倉庫中的包都可以添加到這個列表中。還可以使用 :excludedt 特性將包包含在列表中。每個包都需要一個函數來初始化。這個函數必須以這種模式命名:<layer-name>/init-<package-name>。這個函數包含了包的配置。同時還有一個 pre/post-init 函數來在包加載之前或之后運行代碼。它看起來想這個樣子:

(setq layer-name-packages '(example-package
                            ;;這個層通過設置:excluded 屬性
                            ;;為真(t)來卸載example-package-2
                            (example-package-2 :excluded t)))
(defun layer-name/post-init-package ()
  ;;在這里添加另一個層的包的配置
  )
(defun layer-name/init-example-package ()
  ;;在這里配置example-package
  )

**注意**:只有一個層可以具有一個對于包的 init 函數。如果你想覆蓋另一個層對一個包的配置,請使用 use-package hooks 中的 <layer-name>/pre-init 函數。

如果 MELPA 中沒有你想要的包,你必須是由一個本地包或一個包源。關于此的更多信息可以從層的剖析處獲得。

確保你添加了你的層到你的 .spacemacs 文件中,并重啟 spacemacs 以激活。

關于層的加載過程和層的工作原理的詳細描述可以參考LAYERS.org

安裝一個單獨的包

有時創建一個層會有點大材小用了,也許你僅僅想要一個包而不想維持整個層。Spacemacs 在 .spacemacs 文件中的 dotspacemacs/layers 函數里提供了一個叫做 dotspacemacs-additional-packages 的變量,只要在列表中添加一個包名,它就會在你重啟的時候被安裝。下一段來說明如何加載這個包。

加載包

有沒有想過 Spacemacs 如何可以在僅僅幾秒鐘之內加載超過 100 個包呢?如此低的加載時間必須需要某種難以理解的黑魔法吧。還好這不是真的,多虧有了 use-package。它是一個可以輕松實現對包進行延遲加載和配置的包。以下是它的基礎用法:

;; Basic form of use-package declaration. The :defer t tells use-package to
;; try to lazy load the package.
(use-package package-name
  :defer t)
;; The :init section is run before the package loads The :config section is
;; run after the package loads
(use-package package-name
  :defer t
  :init
  (progn
    ;; Change some variables
    (setq variable1 t variable2 nil)
    ;; Define a function
    (defun foo ()
      (message "%s" "Hello, World!")))
  :config
  (progn
    ;; Calling a function that is defined when the package loads
    (function-defined-when-package-loads)))

這只是 use-package 的一個非常基本的概述。它還有許多其他的方式來控制包的加載,就不在這里介紹了。

卸載一個包

Spacemacs 在 .spacemacs 文件中的 dotspacemacs/init 函數里提供了一個叫做 dotspacemacs-excluded-packages 的變量。只要在列表中添加一個包名,它就會在你重啟的時候被卸載。

常見調整

本段是為了想要做更多調整的人所寫的。除非另有說明,所有這些設置都去你的 .spacemacs 文件中的 dotspacemacs/user-config 函數里完成。

變更 escape 鍵

 Spacemacs 使用 [[https://github.com/syl20bnr/evil-escape][evil-escape]] 來允許從許多擁有一個快捷鍵的 major-modes 中跳出。你可以在你的 dotspacemacs/user-config 函數中像這樣定制變量:

(defun dotspacemacs/user-config ()
  ;; ...
  ;; Set escape keybinding to "jk"
  (setq-default evil-escape-key-sequence "jk"))

更多的文檔可以在 evil-escape README 中找到。

變更配色方案

.spacemacs 文件的 dotspacemacs/init 函數中有一個 dotspacemacs-themes 變量。這是一個可以用 SPC T n 鍵循環的主題的列表。列表中的第一個主題是在啟動時加載的主題。以下為示例:

(defun dotspacemacs/init
    ;; Darktooth theme is the default theme
    ;; Each theme is automatically installed.
    ;; Note that we drop the -theme from the package name.
    ;; Ex. darktooth-theme -> darktooth
    (setq-default dotspacemacs-themes '(darktooth
                                        soothe
                                        gotham)))

可以使用 SPC T h 鍵列出和選擇所有已安裝的主題。

非高亮搜索

Spacemacs 模仿了默認的 vim 行為,會高亮顯示搜索結果,盡管你不在它們之間進行導航。你可以使用 SPC s c 或 :nohlsearch 來關閉搜索結果高亮。

若再也不需要自動高亮結果,你可以卸載 evil-search-highlight-persist 包。

會話

當你打開 Spacemacs 時,它不會自動恢復窗口和緩沖區。如果你常使用 vim 會話,你可能要在你的 .spacemacs 文件中的 dotspacemacs/user-config 里添加 (desktop-save-mode t),然后你就可以使用 SPC : desktop-read 加載已被保存的會話。桌面文件的位置可以使用 desktop-dirname 變量設置。要自動加載一個會話,就在你的 .spacemacs 文件中添加 (desktop-read)。

使用 visual lines 導航

Spacemacs 使用 vim 默認 actual lines 導航,即使它們被包裝了。如果你想要讓 j 和 k 的行為如 g j 和 g k 一般,將一下代碼添加到你的 .spacemacs 文件:

(define-key evil-normal-state-map (kbd "j") 'evil-next-visual-line)
(define-key evil-normal-state-map (kbd "k") 'evil-previous-visual-line)

其他有用的連接

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!