Spacemacs入門

# 背景
Spacemacsの導入や入門の記事はいくつかありますが、情報が古かったりするので、なるべく最新の状態を意識して記事を作成しました。
定期的にメンテナンスをして、最新の状態を保ちたいと思っています。

# 対象
- Emacs初心者、Emacs盆栽に時間をかけられない人
- VimユーザーでEmacsに興味がある人

# インストール
[Spacemacs (Github)](https://github.com/syl20bnr/spacemacs)を参考にします。

## Emacsのインストール

### Linux

各ディストリビューションのパッケージマネージャからインストールします。
ubuntuの場合は下記コマンドを入力します。

```
$ sudo apt install emacs
```

### Mac

下記のコマンドの中でお好みのバージョンをインストールします。

```
$ brew tap d12frosted/emacs-plus
# to install Emacs 26
$ brew install emacs-plus
# or to install Emacs 27
$ brew install emacs-plus@27 --with-spacemacs-icon
# or to install Emacs 28
$ brew install emacs-plus@28 --with-spacemacs-icon
$ brew link emacs-plus
```

### Windows

[GNU FTP](https://ftp.gnu.org/gnu/emacs/windows/)からダウンロードします。
[こちら](https://www.kkaneko.jp/tools/win/emacs.html)の記事が参考になります。

## Spacemacsのインストール

下記のコマンドを実行して、ホームディレクトリにSpacemacsの`.emacs.d`を配置します。

### Mac、Linux

```
$ git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d
```

### Windows

```
$ git clone -b develop https://github.com/syl20bnr/spacemacs %appdata%/.emacs.d
```

# 初回起動

`.emacs.d`の導入が完了後に、emacsを起動します。

```
$ emacs
```
Spacemacsの起動画面が表示され、キーバインドの選択ができます。
※キーバインドは後述の`dotspacemacs-editing-style`で変更できます。
![スクリーンショット_2021-12-06_21-46-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696232/194f9287-86f2-231c-6bc4-7676464a1e96.png)
キーバインドを選択すると標準のSpacemacsか、最小構成のSpacemacsかを選択できます。
ここでは`The standard distribution`を選択します。
![スクリーンショット_2021-12-06_21-59-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696232/9c8930b5-3bbc-934f-b960-0f6582eb6b9b.png)

必要なパッケージのインストール設定が完了すると、Spacemacsのホーム画面が表示されます。
![スクリーンショット_2021-12-06_22-04-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696232/39168098-44c0-6d40-fc2a-657b0cc6d2c4.png)

# Spacemacsのアップデート

Spacemacs本体をアップデートするには`.emacs.d`上で下記のコマンドを実行します。

```
$ git pull --rebase
```

# パッケージのアップデート

Spacemacsホーム画面上の`[Update Package]`を押下するとパッケージのアップデートが出来ます。
他の方法でのパッケージのアップデートは推奨されていません。
ホーム画面は`SPC b h`で表示する事が出来ます。

# パッケージのロールバック

たまにパッケージのアップデートを行うと動作しなくなる場合があります。
その場合`[Rollback Package Update]`を押下するとアップデート前の状態に戻す事が出来ます。
ロールバックで戻れる回数は`.spacemacs`上の`dotspacemacs-max-rollback-slots`で定義しています。

# Spacemacsの設定

Spacemacsの設定は`.spacemacs`に記述していきます。
`.spacemacs`は`SPC f e d`を入力すると開くことができます。

`SPC q r`や`SPC q R`でSpacemacsを再起動すると設定内容が反映されます。

この記事に載っていない設定は[Spacemacs documentation](https://develop.spacemacs.org/doc/DOCUMENTATION.html)を参照してください。

下記に`.spacemacs`の大まかな設定を紹介します。

## dotspacemacs-configuration-layers

[Spacemacs layers list](https://develop.spacemacs.org/layers/LAYERS.html)に記載されているレイヤーを追加するとパッケージのダウンロードと設定をしてくれます。
dotspacemacs-configuration-layersへ記述後、Spacemacsの再起動または`SPC f e R (dotspacemacs/sync-configuration-layers)`を実行すると反映されます。

```lisp:.spacemacs
   ;; List of configuration layers to load.
   dotspacemacs-configuration-layers
   '((python :variables
             python-formatter 'black
             python-format-on-save t)
     java
     (html :variables
           css-enable-lsp t
           less-enable-lsp t
           scss-enable-lsp t
           html-enable-lsp t)
     (rust :variables
           rust-format-on-save t)
     unicode-fonts
     emoji
     themes-megapack
     (colors :variables
             colors-enable-nyan-cat-progress-bar t)
     ;; ----------------------------------------------------------------
     ;; Example of useful layers you may want to use right away.
     ;; Uncomment some layer names and press `SPC f e R' (Vim style) or
     ;; `M-m f e R' (Emacs style) to install them.
     ;; ----------------------------------------------------------------
     (auto-completion :variables
                      auto-completion-tab-key-behavior 'complete
                      auto-completion-return-key-behavior nil
                      auto-completion-minimum-prefix-length 1
                      auto-completion-idle-delay 0
                      auto-completion-enable-snippets-in-popup t
                      auto-completion-use-company-box t
                      auto-completion-enable-help-tooltip t)
     better-defaults
     emacs-lisp
     git
     (helm :variables
           helm-use-fuzzy 'source)
     lsp
     markdown
     multiple-cursors
     org
     (shell :variables
            shell-default-height 30
            shell-default-position 'bottom)
     ;; パフォーマンスに影響するため外しています
     ;; spell-checking
     syntax-checking
     version-control
     treemacs)
```

## dotspacemacs-additional-packages

[Spacemacs layers list](https://develop.spacemacs.org/layers/LAYERS.html)に記載されていないパッケージは、こちらに記述することでダウンロードできます。
`(xxx :location (recipe :fetcher github :repo "user-name/xxx")`のように記述すればGithubから直接ダウンロードもできます。([Spacemacs FAQ](https://github.com/mbertheau/spacemacs-faq/wiki#how-do-i-install-an-emacs-package-from-github))
※パッケージによってはうまくダウンロードできない場合があります。調査中。
パッケージの設定は後述の`dotspacemacs/user-config`へ記述します。

```lisp:.spacemacs
   dotspacemacs-additional-packages '(rg
                                      tr-ime
                                      mozc
                                      orderless
                                      company-prescient)
```

## dotspacemacs-editing-style

インストール時に指定した編集スタイルを変更することができます。
編集スタイルは`vim`、`emacs`、`hybrid`があります。

```lisp:.spacemacs
   ;; One of `vim', `emacs' or `hybrid'.
   ;; `hybrid' is like `vim' except that `insert state' is replaced by the
   ;; `hybrid state' with `emacs' key bindings. The value can also be a list
   ;; with `:variables' keyword (similar to layers). Check the editing styles
   ;; section of the documentation for details on available variables.
   ;; (default 'vim)
   dotspacemacs-editing-style 'vim
```

## dotspacemacs-themes

`SPC T n`で指定しているテーマの切り替え、`SPC T s`でテーマ一覧から選択できます。

```lisp:.spacemacs
   ;; List of themes, the first of the list is loaded when spacemacs starts.
   ;; Press `SPC T n' to cycle to the next theme in the list (works great
   ;; with 2 themes variants, one dark and one light)
   dotspacemacs-themes '(spacemacs-dark
                         spacemacs-light)
```

## dotspacemacs-mode-line-theme

モードラインの種類をここで変更することができます。
下記の中から選択できます。

- (default '(spacemacs :separator wave :separator-scale 1.5)) 【標準】
- 'doom
- 'all-the-icons
- 'custom
- 'vim-powerline
- 'vanilla

```lisp:.spacemacs
   ;; Set the theme for the Spaceline. Supported themes are `spacemacs',
   ;; `all-the-icons', `custom', `doom', `vim-powerline' and `vanilla'. The
   ;; first three are spaceline themes. `doom' is the doom-emacs mode-line.
   ;; `vanilla' is default Emacs mode-line. `custom' is a user defined themes,
   ;; refer to the DOCUMENTATION.org for more info on how to create your own
   ;; spaceline theme. Value can be a symbol or list with additional properties.
   ;; (default '(spacemacs :separator wave :separator-scale 1.5))
   dotspacemacs-mode-line-theme '(spacemacs :separator wave :separator-scale 1.5)
```

## dotspacemacs-default-font

こちらでフォントの指定ができます。
デフォルトは`Source Code Pro`ですが、日本語対応フォントに変更しています。

```lisp:.spacemacs
   ;; Default font or prioritized list of fonts. The `:size' can be specified as
   ;; a non-negative integer (pixel size), or a floating-point (point size).
   ;; Point size is recommended, because it's device independent. (default 10.0)
   dotspacemacs-default-font '("Source Code Pro"
                               :size 10.0
                               :weight normal
                               :width normal)
```

## dotspacemacs-maximized-at-startup

起動時に画面サイズを最大にすることができます。

```lisp:.spacemacs
   ;; If non-nil the frame is maximized when Emacs starts up.
   ;; Takes effect only if `dotspacemacs-fullscreen-at-startup' is nil.
   ;; (default nil) (Emacs 24.4+ only)
   dotspacemacs-maximized-at-startup t
```

## dotspacemacs-smooth-scrolling

smooth-scrollingの設定ができます。
smooth-scrollingが好きではないので、無効にしています。

```lisp:.spacemacs
   ;; If non-nil smooth scrolling (native-scrolling) is enabled. Smooth
   ;; scrolling overrides the default behavior of Emacs which recenters point
   ;; when it reaches the top or bottom of the screen. (default t)
   dotspacemacs-smooth-scrolling nil
```

## dotspacemacs-line-numbers

`t`にすると行番号を表示することできます。
行番号の相対表示や特定のモードでdisabledにすることもできます。

```lisp:.spacemacs
   ;; Control line numbers activation.
   ;; If set to `t', `relative' or `visual' then line numbers are enabled in all
   ;; `prog-mode' and `text-mode' derivatives. If set to `relative', line
   ;; numbers are relative. If set to `visual', line numbers are also relative,
   ;; but only visual lines are counted. For example, folded lines will not be
   ;; counted and wrapped lines are counted as multiple lines.
   ;; This variable can also be set to a property list for finer control:
   ;; '(:relative nil
   ;;   :visual nil
   ;;   :disabled-for-modes dired-mode
   ;;                       doc-view-mode
   ;;                       markdown-mode
   ;;                       org-mode
   ;;                       pdf-view-mode
   ;;                       text-mode
   ;;   :size-limit-kb 1000)
   ;; When used in a plist, `visual' takes precedence over `relative'.
   ;; (default nil)
   dotspacemacs-line-numbers nil
```

## dotspacemacs-enable-server

Spacemacsは起動に時間がかかるので、Daemon起動を利用します。
`emacsclient`コマンドを使用することで、ファイルを開くことができます。
起動が上手く行かない場合、`M-x server-mode`を実行するか、`~/.emacs.d/.cache/`配下の`server`ディレクトリを削除して再起動してください。

```lisp:.spacemacs
   ;; If non-nil, start an Emacs server if one is not already running.
   ;; (default nil)
   dotspacemacs-enable-server t
```

## dotspacemacs/user-init

Layerが読み込まれる前に呼ばれる関数です。
変数などパッケージが読み込まれる前に設定しておきたいものはこちらに記述します。

```lisp:.spacemacs
(defun dotspacemacs/user-init ()
  "Initialization for user code:
This function is called immediately after `dotspacemacs/init', before layer
configuration.
It is mostly for variables that should be set before packages are loaded.
If you are unsure, try setting them in `dotspacemacs/user-config' first."
  )
```

## dotspacemacs/user-config

Spacemacs起動後に呼ばれる関数です。
Layerで設定できないパッケージの設定はここへ記述します。

### Emacs標準機能に関する設定
補完スタイルの設定と文字コードに関する設定をしています。

```lisp:.spacemacs
  (use-package emacs
    :custom (completion-ignore-case t) ;; 小文字と大文字を区別しない
    :hook ((java-mode . (lambda ()
                          (setq-local indent-tabs-mode t))))
    :config
    (which-function-mode +1) ;; 現在の機能（関数名等）をモードライン上に表示します

    ;; 日本語の文字コード設定
    (set-language-environment "Japanese")
    (prefer-coding-system 'utf-8)
    (when (eq system-type 'windows-nt)
      (set-file-name-coding-system 'cp932)
      (set-keyboard-coding-system 'cp932)
      (set-terminal-coding-system 'cp932))

    (set-charset-priority 'ascii
                          'japanese-jisx0208
                          'latin-jisx0201
                          'katakana-jisx0201
                          'iso-8859-1
                          'cp1252
                          'unicode)
    (set-coding-system-priority 'utf-8
                                'euc-jp
                                'iso-2022-jp
                                'cp932))
```

### IMEの設定
IMEに関する設定をしています。`C-\`で切り替えます。

```lisp:.spacemacs
  (use-package tr-ime
    :if (eq system-type 'windows-nt)
    :custom (default-input-method "W32-IME")
    :config
    (tr-ime-standard-install)
    (w32-ime-initialize))

  (use-package mozc
    :if (eq system-type 'gnu/linux)
    :custom (default-input-method "japanese-mozc"))
```

### CompanyとSelectrumの設定

```lisp:.spacemacs
  (use-package company-box
    :custom (company-box-icons-alist 'company-box-icons-images)) ;; そのままだと高さがズレるので変更

  ;; 補完候補の並び替え（使用履歴、候補の長さ）
  (use-package company-prescient
    :hook (lsp-mode . (lambda ()
                        ;; language serverが並び替えをしているので、長さによる並び替えを無効
                        (setq-local company-prescient-sort-length-enable nil)))
    :config
    (company-prescient-mode +1))

  ;; 使用履歴の永続化
  (use-package prescient
    :config
    (prescient-persist-mode +1))

  ;; companyでfuzzyに絞り込み
  (use-package orderless
    :custom ((completion-styles '(basic orderless))
             (completion-category-defaults nil)
             (completion-category-overrides nil)
             (orderless-matching-styles '(orderless-flex))
             (orderless-style-dispatchers '(orderless-dispatch-flex-first)))
    :init
    (defun orderless-dispatch-flex-first (_pattern index _total)
      (and (eq index 0) 'orderless-flex))

    (defun just-one-face (fn &rest args)
      (let ((orderless-match-faces [completions-common-part]))
        (apply fn args)))

    (with-eval-after-load 'company
      (advice-add 'company-capf--candidates :around #'just-one-face)))
```

### Pythonの設定
Spacemacsではデフォルトで`python3`コマンドを利用するように設定されています。
`python`コマンドを利用したい場合は下記のように値を変更します。

```lisp:.spacemacs
  (when (eq system-type 'windows-nt)
    (setq flycheck-python-flake8-executable "python"
          flycheck-python-pycompile-executable "python"
          flycheck-python-pylint-executable "python"))
```

### モードラインの設定

```lisp:.spacemacs
  (use-package spaceline
    :config
    ;; 不要な情報を非表示
    (spaceline-toggle-buffer-size-off)
    (spaceline-toggle-minor-modes-off)
    (spaceline-toggle-purpose-off)
    (spaceline-toggle-buffer-position-off)
    (spaceline-toggle-hud-off))

  (use-package nyan-mode
    :custom (nyan-bar-length 24))
```

# 所感

Spacemacs以外にも`Doom emacs`や`Vanilla Emacs + Evil`などがありますが、それぞれ一長一短があります。
最近は`Doom Emacs`が人気ですが、日本語入力の不具合が解消できず、Spacemacsに落ち着きました。
高い拡張性と操作性を手軽に実現できるSpacemacsは、`init.el`にあまり時間をかけられない方やVimユーザーの方にとてもオススメです！