LoginSignup
21
27

Emacs備忘録(2024年版)

Last updated at Posted at 2024-03-19

背景

こちらの記事を書いてから1年半ほど経過しましたが、設定やパッケージが大きく変わってきたので、振り返りも兼ねて備忘録を投稿します。

設定の管理はorgファイルでorb-babel-load-fileコマンドを使用してelファイルを生成・ロードするようにしています。
パッケージの選定基準はシンプルでemacs組み込み機能を活用しているものをなるべく選んでいます。

最終的な見た目は下記のような感じです。

  • org-modern + perfect-margin + spacious-padding

image.png
image.png

  • vertico (vertico-buffer)

image.png
image.png

  • corfu

image.png
image.png

  • vundo

image.png
image.png

  • imenu-list

image.png
image.png

  • magit

image.png
image.png

  • difftastic

image.png
image.png

下記はorgファイルの設定をmarkdownに変換してそのまま貼り付けてます。
Emacs29以上が対象です。

追記

注意点

builtinパッケージはそのままではアップデートされないので、
list-packagesUxを入力してアップデートを行います。

aggresive-indentの影響でパッケージのインストールで上手くいかない場合があります。
#+begin_src emacs-lisp:tangle noを追加し、設定ファイルから除外することで解消されます。

early-init.el

header

;;; package --- Summary
;;; Commentary:
;;; Code:

custom変数の保存先を変更

(setq custom-file (locate-user-emacs-file "custom.el"))
(when (file-exists-p (expand-file-name custom-file))
  (load-file (expand-file-name custom-file)))

protesilaosを参考

ファイル選択ウィンドウを使用しない

(setq use-file-dialog nil)

Xリソースを使用しない

(setq inhibit-x-resources t)

バッファメニューの使用を抑制

(setq inhibit-startup-buffer-menu t)

画面最大化

(push '(fullscreen . maximized) default-frame-alist)

スクロール非表示

(scroll-bar-mode -1)

メニューバー非表示

(menu-bar-mode -1)

ツールバー非表示

(tool-bar-mode -1)

footer

(provide 'early-init)
;;; early-init.el ends here

init.el

header

;;; package --- Summary
;;; Commentary:
;;; Code:

OS判定用定数

(defconst IS-MAC (eq system-type 'darwin))
(defconst IS-LINUX (memq system-type '(gnu gnu/linux gnu/kfreebsd berkeley-unix)))
(defconst IS-WINDOWS (memq system-type '(cygwin windows-nt ms-dos)))

文字コード

slack emacs-jpのwindowsチャンネルを参考にしています。default-process-coding-system が重要。

(when IS-WINDOWS
  ;; shift-jisよりcp932を優先させる
  (set-coding-system-priority 'utf-8
                              'euc-jp
                              'iso-2022-jp
                              'cp932)
  (setq-default default-process-coding-system '(utf-8-unix . japanese-cp932-dos)))

package.el

modus-themesの作者 Protesilaos Stavrouのブログ を参考にしています。

(require 'package)

(add-to-list 'package-archives '("gnu-elpa-devel" . "https://elpa.gnu.org/devel/"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))

;; インストールする優先順位を指定
(setq package-archive-priorities
      '(("gnu-elpa-devel" . 3)
        ("melpa" . 2)
        ("nongnu" . 1)))

(setq package-install-upgrade-built-in t ; built-inパッケージも更新対象にする
      package-native-compile t           ; インストール時にnative compileする
      )

use-package

Emacsパッケージの設定や管理を簡単にしてくれます。Emacs29からbuiltinされました。

(use-package use-package
  :config
  (setq use-package-always-ensure t))
  1. vc-use-package

    use-packageとvcを統合します。Windows版Emacsではbuiltinされていないのでインストールします。

    (unless (package-installed-p 'vc-use-package)
      (package-vc-install "https://github.com/slotThe/vc-use-package"))
    (require 'vc-use-package)
    

auto-package-update

パッケージを自動的に更新してくれます。最新のEmacsでは package-upgrade-all 機能が搭載されていますが、高頻度でエラーが発生するためこちらのパッケージで更新します。

(use-package auto-package-update
  :config
  (setq auto-package-update-interval 1)
  (auto-package-update-maybe))

auto-compile

古いバイトコードをロードしないように再コンパイルしてくれるパッケージです。

(use-package auto-compile
  :config
  (setq load-prefer-newer t)
  (auto-compile-on-load-mode +1)
  (auto-compile-on-save-mode +1))

keymap

後述のmeowで設定するキーマップを作成します。こちらによく使うコマンドを登録し、利便性を向上させます。

(defvar my-toggle-map (make-keymap))
(defvar my-quit-map (make-keymap))
(defvar my-error-map (make-keymap))

Emacs標準機能の設定

yes-or-noをy-or-nに変更

(setq use-short-answers t)

バックアップファイルを作成しない

(setq make-backup-files nil)
(setq backup-inhibited nil)
(setq create-lockfiles nil)

ビープ音を無効化

(setq ring-bell-function 'ignore)

auto-save-visited

一定時間経過しても操作がない場合、バッファを自動保存します。

(use-package files
  :ensure nil
  :config
  (setq auto-save-visited-interval 30)
  (auto-save-visited-mode +1))

フォーカスアウト時に全バッファを保存

(defun my/save-all-buffers ()
  (save-some-buffers "!"))

(add-hook 'focus-out-hook #'my/save-all-buffers)

デーモン起動

emacsclient コマンドで高速にファイルが開けます。

(use-package server
  :config
  (unless (server-running-p)
    (server-start)))

最後のカーソル位置を保存する

(use-package saveplace
  :init
  (save-place-mode +1))

ファイルの閲覧履歴を保存する

(use-package recentf
  :init
  (setq recentf-max-saved-items 100)
  (recentf-mode +1))

コマンドの履歴を保存

(use-package savehist
  :init
  (savehist-mode +1))

対応括弧を強調表示

(use-package paren
  :init
  (show-paren-mode +1))

対応括弧を自動補完

(use-package elec-pair
  :config
  (electric-pair-mode +1))

現在行を強調表示

(use-package hl-line
  :init
  (global-hl-line-mode +1))

他プロセスの編集をバッファに反映

(use-package autorevert
  :init
  (global-auto-revert-mode +1))

camelCase単位で移動する

(use-package subword
  :init
  (global-subword-mode +1))

削除したファイルをゴミ箱に移動させる

(setq delete-by-moving-to-trash t)

native-compの警告を表示しない

(setq native-comp-async-report-warnings-errors 'silent)

build時にnative-compファイルを削除する

(setq native-compile-prune-cache t)

終了コマンドをキーマップに設定

(use-package files
  :ensure nil
  :bind ( :map my-quit-map
          ("q" . save-buffers-kill-terminal)))

インデントの基本をスペースに変更

(use-package simple
  :ensure nil
  :init
  (setq-default indent-tabs-mode nil))

ガベージコレクション

デフォルトの設定ではガベージコレクションが頻発する為調整しています。前はgcmhを使用していましたがタイマーによるごみが多く生成されてしまうようで、こちらの記事で推奨されているようにgc-cons-percentage を0.2にするように変更しました。

(setq gc-cons-percentage 0.2)
(add-hook 'focus-out-hook #'garbage-collect)
  1. ガベージコレクションのメッセージを表示

    (setq garbage-collection-messages t)
    

長い行を含むファイルの最適化

(use-package so-long
  :init
  (global-so-long-mode +1))

flymake

Emacs標準に組み込まれているシンタックスチェック用のパッケージです。他の有名なパッケージにflycheckがあります。

(use-package flymake
  :hook ((prog-mode
          conf-mode) . flymake-mode)
  :bind ( :map my-error-map
          ("l" . flymake-show-buffer-diagnostics)
          ("L" . flymake-show-project-diagnostics)
          ("n" . flymake-goto-next-error)
          ("p" . flymake-goto-prev-error))
  :init
  (setq-default flymake-no-changes-timeout 1.0)

  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     `("e" . ("error" . ,my-error-map)))))
  1. flymake-collection

    flymake-collectionはflymakeの各言語の設定を簡単にしてくれるパッケージです。typescriptでeglotと併用する際に、そのままだとeslintの設定が上書きされてしまうので、eglotのflymake設定を後から追加するようにしています。

    (use-package flymake-collection
      :hook ((after-init . flymake-collection-hook-setup)
             ((tsx-ts-mode
               jsx-ts-mode
               jtsx-jsx-mode
               jtsx-tsx-mode
               jtsx-typescript-mode) . (lambda () (add-to-list 'flymake-diagnostic-functions #'flymake-collection-eslint)))
             (eglot-managed-mode . (lambda () (add-to-list 'flymake-diagnostic-functions #'eglot-flymake-backend)))))
    

末尾のスペースやタブを可視化

(setq-default show-trailing-whitespace t)

delsel

選択している状態で入力したときに、regionを削除して挿入するようにします。

(use-package delsel
  :config
  (delete-selection-mode +1))

パフォーマンスの向上

https://ayatakesi.github.io/lispref/25.2/html/Output-from-Processes.html

(setq process-adaptive-read-buffering t)
  1. protesilaos

    1. 閉じ括弧を入力しても点滅させない

      (setq blink-matching-paren nil)
      
    2. vcのバックエンドをGitのみに変更

      (setq vc-handled-backends '(Git))
      
  2. doomemacs

    1. ファイル検索を2回行わないようにする

      (setq auto-mode-case-fold nil)
      
    2. 双方向の並び替えを抑制する

      (setq-default bidi-display-reordering 'left-to-right)
      
    3. 長い行の双方向スキャン

      (setq bidi-inhibit-bpa t)
      
    4. フォーカスされていないウィンドウのカーソルを削除

      (setq-default cursor-in-non-selected-windows nil)
      (setq highlight-nonselected-windows nil)
      
    5. 高速なスクロール

      (setq fast-but-imprecise-scrolling t)
      
    6. ドメインにpingを送信しない

      (setq ffap-machine-p-known 'reject)
      
    7. UIの更新頻度を下げる

      (setq idle-update-delay 1.0)
      
    8. 不要なフォント表示化を抑制

      (setq redisplay-skip-fontification-on-input t)
      
    9. Windowsの最適化

      (when IS-WINDOWS
        (setq w32-get-true-file-attributes nil
              w32-pipe-read-delay 0
              w32-pipe-buffer-size (* 64 1024)))
      
  3. Centaur Emacs

    1. 各OSの最適化

      (when IS-WINDOWS
        (setq w32-use-native-image-API t))
      
      (unless IS-MAC
        (setq command-line-ns-option-alist nil))
      
      (unless IS-LINUX
        (setq command-line-x-option-alist nil))
      

meow

meow は vi/vim に代表される modal editing を提供するパッケージで、Normal ModeやInsert Modeのような移動や編集に特化したモードを提供します。Emacsで最も有名なものはevilですが、シンプルでEmacsによく統合されているmeowに乗り換えてみました。デフォルトのQWERTYキーバインドではVimの操作と乖離が大きいので、近づけるようにキーバインドを変更しています。

また、meowではEmacsのショートカットを下記のような入力で実行できます。

  • M-x → SPC m x
  • C-x C-f → SPC x f
  • C-x b → SPC x SPC b
  • C-c C-c → SPC c c

※ 上のコマンドは evil + god-mode でも同様のことができるみたいです。

(use-package meow
  :config
  (setq meow-use-clipboard t
        meow-expand-hint-counts nil)

  (defun meow-setup ()
    (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
    (meow-motion-overwrite-define-key
     '("j" . meow-next)
     '("k" . meow-prev)
     '("<escape>" . ignore))
    (meow-leader-define-key
     ;; SPC j/k will run the original command in MOTION state.
     '("j" . "H-j")
     '("k" . "H-k")
     ;; Use SPC (0-9) for digit arguments.
     '("0" . delete-window)
     '("1" . delete-other-windows)
     '("2" . split-window-below)
     '("3" . split-window-right)
     '("4" . switch-to-buffer-other-frame)
     '("5" . meow-digit-argument)
     '("6" . meow-digit-argument)
     '("7" . meow-digit-argument)
     '("8" . meow-digit-argument)
     '("9" . meow-digit-argument)
     '("/" . meow-keypad-describe-key)
     '("?" . meow-cheatsheet)
     '("w" . other-window)
     `("s" . ("search" . ,search-map))
     `("p" . ("project" . ,project-prefix-map))
     `("t" . ("toggle" . ,my-toggle-map))
     `("q" . ("quit" . ,my-quit-map)))
    (meow-normal-define-key
     '("$" . move-end-of-line)
     '("0" . move-beginning-of-line)
     '("^" . back-to-indentation)
     '("9" . meow-expand-9)
     '("8" . meow-expand-8)
     '("7" . meow-expand-7)
     '("6" . meow-expand-6)
     '("5" . meow-expand-5)
     '("4" . meow-expand-4)
     '("3" . meow-expand-3)
     '("2" . meow-expand-2)
     '("1" . meow-expand-1)
     '("-" . negative-argument)
     '(";" . repeat)
     '(":" . meow-reverse)
     '("," . meow-inner-of-thing)
     '("." . meow-bounds-of-thing)
     '("<" . meow-beginning-of-thing)
     '(">" . meow-end-of-thing)
     '("[" . scroll-down-command)
     '("]" . scroll-up-command)
     '("{" . backward-paragraph)
     '("}" . forward-paragraph)
     '("a" . meow-append)
     '("A" . meow-open-below)
     '("b" . meow-back-word)
     '("B" . meow-back-symbol)
     '("c" . meow-change)
     '("d" . meow-kill)
     '("D" . meow-kill-whole-line)
     '("e" . meow-next-word)
     '("E" . meow-next-symbol)
     '("f" . meow-find)
     '("g" . meow-cancel-selection)
     '("G" . meow-grab)
     '("h" . meow-left)
     '("H" . meow-left-expand)
     '("i" . meow-insert)
     '("I" . meow-open-above)
     '("j" . meow-next)
     '("J" . meow-next-expand)
     '("k" . meow-prev)
     '("K" . meow-prev-expand)
     '("l" . meow-right)
     '("L" . meow-right-expand)
     '("m" . meow-join)
     '("o" . meow-block)
     '("O" . meow-to-block)
     '("p" . yank)
     '("q" . meow-quit)
     '("Q" . meow-goto-line)
     '("r" . meow-replace)
     '("R" . meow-swap-grab)
     '("s" . meow-change)
     '("t" . meow-till)
     '("u" . meow-undo)
     '("U" . meow-undo-in-selection)
     '("v" . set-mark-command)
     '("V" . meow-line)
     '("w" . meow-mark-word)
     '("W" . meow-mark-symbol)
     '("x" . meow-delete)
     '("y" . meow-save)
     '("Y" . meow-sync-grab)
     '("z" . meow-pop-selection)
     '("'" . meow-reverse)
     '("/" . isearch-forward)
     '("n" . isearch-repeat-forward)
     '("N" . isearch-repeat-backward)
     '("*" . isearch-forward-symbol-at-point)
     '("=" . indent-region)
     '("<escape>" . ignore)))

  (meow-setup)
  (meow-global-mode +1)

  ;; ノーマルモードに戻る際、日本語入力を解除する
  (add-hook 'meow-normal-mode-hook #'deactivate-input-method))

org

org-mode に関する基本的な設定をしています。

(use-package org
  :init
  (setq org-return-follows-link t  ; Returnキーでリンク先を開く
        org-mouse-1-follows-link t ; マウスクリックでリンク先を開く
        ))

アンダースコアを入力しても下付き文字にならないようにする

(setq org-use-sub-superscripts '{}
      org-export-with-sub-superscripts nil)

org-agenda

org-agenda のディレクトリを指定しています。

(use-package org-agenda
  :ensure nil
  :after org
  :config
  (setq org-agenda-files (file-expand-wildcards (concat org-directory "/*.org"))))

org-indent-mode

インデント機能を有効にしています。

(use-package org-indent
  :ensure nil
  :hook (org-mode . org-indent-mode))

org-pomodoro

カーソル上のタスクでポモドーロタイマーを設定してくれます。

(use-package org-pomodoro
  :after org)

ox-qmd (qiita投稿用)

orgファイルをmarkdownファイルに変換してくれます。

(use-package ox-qmd
  :defer t)

denote

org用のシンプルなメモ取りツールとして愛用しています。

(use-package denote
  :init
  (with-eval-after-load 'org
    (setq denote-directory org-directory))

  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("d" . denote-open-or-create)))

  (add-hook 'find-file-hook #'denote-link-buttonize-buffer)
  (add-hook 'dired-mode-hook #'denote-dired-mode-in-directories)
  (add-hook 'context-menu-functions #'denote-context-menu)

  (denote-rename-buffer-mode +1))

org-modern

org-modeの見た目をリッチなものにしてくれます。

(use-package org-modern
  :after org
  :init
  (setq
   ;; Edit settings
   org-auto-align-tags nil
   org-tags-column 0
   org-fold-catch-invisible-edits 'show-and-error
   org-special-ctrl-a/e t
   org-insert-heading-respect-content t

   ;; Org styling, hide markup etc.
   org-hide-emphasis-markers t
   org-pretty-entities t
   org-ellipsis "…"

   ;; Agenda styling
   org-agenda-tags-column 0
   org-agenda-block-separator ?
   org-agenda-time-grid
   '((daily today require-timed)
     (800 1000 1200 1400 1600 1800 2000)
     " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
   org-agenda-current-time-string
   "⭠ now ─────────────────────────────────────────────────")

  :config
  (global-org-modern-mode +1))
  1. org-modern-indent

    org-indent + org-modern を有効にするとsrcブロックの「bracket」と呼ばれる表示が無効になります。このパッケージは org-indent + org-modern でも「bracket」を再現します。

    (use-package org-modern-indent
      :vc ( :fetcher github :repo "jdtsmith/org-modern-indent")
      :config
      (add-hook 'org-mode-hook #'org-modern-indent-mode 90))
    

IME

Emacsは~C-\~で日本語入力を切り替えることができますが、デフォルトだとあまり補完が賢くないのでOSに合わせて導入します。

tr-ime

(use-package tr-ime
  :if IS-WINDOWS
  :config
  (setq default-input-method "W32-IME")
  (tr-ime-standard-install)
  (w32-ime-initialize))

mozc

日本語変換 Mozc の設定,emacs 用の Mozc の設定(Ubuntu 上) を参考にしています。

  1. 必要なパッケージを導入

    sudo apt install fcitx-libs-dev
    sudo apt install emacs-mozc
    fcitx-config-gtk
    
  2. Emacs側の設定

    (use-package mozc
      :unless IS-WINDOWS
      :init
      (setq default-input-method "japanese-mozc"))
    

フォントの設定

私は fontaine を使用してフォントを設定しています。

(use-package fontaine
  :config
  (cond (IS-LINUX
         (setq fontaine-presets
               '((regular
                  :default-family "PlemolJP HS"
                  :fixed-pitch-family "PlemolJP HS"
                  :variable-pitch-family "IBM Plex Sans JP"
                  :italic-family "PlemolJP HS")
                 (large
                  :default-family "PlemolJP HS"
                  :variable-pitch-family "IBM Plex Sans JP"))))

        (IS-WINDOWS
         (setq fontaine-presets
               '((regular
                  :default-family "PlemolJP Console NF"
                  :fixed-pitch-family "PlemolJP Console NF"
                  :variable-pitch-family "IBM Plex Sans JP"
                  :italic-family "PlemolJP Console NF")
                 (large
                  :default-family "PlemolJP Console NF"
                  :variable-pitch-family "IBM Plex Sans JP")))))

  (fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular))
  (add-hook 'kill-emacs-hook #'fontaine-store-latest-preset))

アイコン

nerd-icons

アイコンにはnerd-iconsを使用しています。他にall-the-iconsというパッケージもあります。

(use-package nerd-icons)
  1. nerd-icons-completion

    vertico等の補完パッケージでアイコンが表示されるようにします。

    (use-package nerd-icons-completion
      :hook (after-init . nerd-icons-completion-mode))
    
  2. nerd-icons-dired

    diredでアイコンが表示されるようにします。

    (use-package nerd-icons-dired
      :hook (dired-mode . nerd-icons-dired-mode))
    
  3. nerd-icons-corfu

    corfuでアイコンが表示されるようになります。

    (use-package nerd-icons-corfu
      :vc ( :fetcher github :repo "LuigiPiucco/nerd-icons-corfu")
      :after corfu nerd-icons
      :config
      (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
    

modeline

nyan-mode

バッファー上での位置をニャンキャットが教えてくれるパッケージです。マウスでクリックすると大体の位置にジャンプもできます。

(use-package nyan-mode
  :init
  (setq nyan-bar-length 24)
  (nyan-mode +1))

minions

デフォルトのモードラインでは各言語のメジャーモードやマイナーモードが全て表示されますが、こちらのパッケージを導入することで、マイナーモードがハンバーガーメニューで表示され、マウスクリックで表示されるようになります。

(use-package minions
  :init
  (minions-mode +1))

corfu

corfuはEmacsの補完パッケージです。他に有名な補完パッケージにcompanyauto-completeがありますが、corfuが最もEmacsの組み込み機能と統合されています。

(use-package corfu
  :demand t
  :bind ( :map corfu-map
          ("TAB" . corfu-insert)
          ([tab] . corfu-insert)
          ("RET" . nil)
          ([return] . nil))
  :hook (prog-mode . (lambda ()
                       (global-set-key [remap c-indent-line-or-region] #'indent-for-tab-command)))
  :config
  (setq corfu-cycle t
        corfu-count 16
        corfu-auto t
        corfu-auto-prefix 1
        corfu-auto-delay 0
        corfu-on-exact-match nil)

  (global-corfu-mode +1)

  (defun corfu-enable-always-in-minibuffer ()
    "Enable Corfu in the minibuffer if Vertico/Mct are not active."
    (unless (or (bound-and-true-p mct--active)
                (bound-and-true-p vertico--input))
      ;; (setq-local corfu-auto nil) ;; Enable/disable auto completion
      (setq-local corfu-echo-delay nil ;; Disable automatic echo and popup
                  corfu-popupinfo-delay nil)
      (corfu-mode 1)))
  (add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1)

  (with-eval-after-load 'meow
    (define-key corfu-map (kbd "<escape>")
                (lambda ()
                  (interactive)
                  (corfu-quit)
                  (meow-normal-mode))))

  (with-eval-after-load 'lsp-mode
    (setq lsp-completion-provider :none)))

corfu-popupinfo

補完候補の横に説明用のポップアップが表示されるようになります。

(use-package corfu-popupinfo
  :ensure nil
  :hook (corfu-mode . corfu-popupinfo-mode))

corfu-magic

evil-collectionの設定を元にキーバインドを設定しています。補完候補未選択時にRETを押下すると改行が挿入され、補完候補選択時にRETを押下すると補完候補を選択します。

(with-eval-after-load 'corfu
  (setq corfu-preselect 'prompt)

  (define-key corfu-map (kbd "TAB") 'corfu-next)
  (define-key corfu-map (kbd "<tab>") 'corfu-next)
  (define-key corfu-map (kbd "S-TAB") 'corfu-previous)
  (define-key corfu-map (kbd "<backtab>") 'corfu-previous)

  (defvar corfu--index)
  (defvar corfu-magic-insert-or-next-line
    `(menu-item "" nil :filter ,(lambda (&optional _)
                                  (when (>= corfu--index 0)
                                    'corfu-insert)))
    "If we made a selection during `corfu' completion, select it.")
  (define-key corfu-map (kbd "RET") corfu-magic-insert-or-next-line)

  (defvar corfu-magic-cancel-or-backspace
    `(menu-item "" nil :filter ,(lambda (&optional _)
                                  (when (>= corfu--index 0)
                                    'corfu-reset)))
    "If we made a selection during `corfu' completion, cancel it.")
  (define-key corfu-map (kbd "DEL") corfu-magic-cancel-or-backspace)
  (define-key corfu-map (kbd "<backspace") corfu-magic-cancel-or-backspace)
  )

cape

capeは completion-at-point(capf) と呼ばれるEmacsの組み込み補完機能を拡張するパッケージです。capfはcorfuやcompanyで使用されており、補完候補の候補をカスタマイズできます。

(use-package tabnine
  :demand t
  :hook (kill-emacs . tabnine-kill-process)
  :bind ( :map tabnine-completion-map
          ("TAB" . nil)
          ("<tab>" . nil))
  :config
  (tabnine-start-process)
  (global-tabnine-mode +1))

(use-package cape
  :hook (((prog-mode
           text-mode
           conf-mode
           eglot-managed-mode
           lsp-completion-mode) . my/set-super-capf))
  :config
  (defun my/set-super-capf (&optional arg)
    (setq-local completion-at-point-functions
                (list (cape-capf-properties
                       (cape-capf-super
                        (cape-capf-noninterruptible
                         (cape-capf-buster
                          (if arg
                              arg
                            (car completion-at-point-functions))))
                        #'tempel-complete
                        #'tabnine-completion-at-point
                        #'cape-dabbrev
                        #'cape-file)
                       :sort t)))))
  1. dabbrevのサイズを制限

    (setq dabbrev-friend-buffer-function (lambda (other-buffer)
                                           (< (buffer-size other-buffer) (* 1024 1024))))
    

corfu-terminal

corfuはデフォルトではターミナルに対応していません。こちらのパッケージを導入することでターミナルでもcorfuが使用できるようになります。

(use-package corfu-terminal
  :unless (display-graphic-p)
  :config
  (corfu-terminal-mode +1))

TABで補完を表示する

(setq tab-always-indent 'complete)

vertico

helmivy よりも補完インタフェース新しくシンプルな補完パッケージです。

(use-package vertico
  :init
  (setq vertico-cycle t)
  (vertico-mode +1))

vertico-repeat

verito の拡張機能の一つで直前のコマンドを再度表示します。

(use-package vertico-repeat
  :ensure nil
  :after vertico
  :hook (minibuffer-setup . vertico-repeat-save)
  :init
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("z" . vertico-repeat))))

vertico-directory

verito の拡張機能の一つで find-file のファイル・ディレクトリ操作時の操作性を向上させる拡張機能です。

(use-package vertico-directory
  :ensure nil
  :after vertico
  :bind ( :map vertico-map
          ("<backspace>" . vertico-directory-delete-char)))

vertico-buffer

verticoはデフォルトではミニバッファを使用して表示しますが、縦長のディスプレイを使用した際に視線の移動が大きいため、helmのようにバッファを使用するようにしています。

(use-package vertico-buffer
  :ensure nil
  :config
  (setq vertico-buffer-display-action '(display-buffer-at-bottom))
  (vertico-buffer-mode +1))

Prefix current candidate with arrow

verticoの選択行のアイコンを追加します。vertico wikiで紹介されています。

(defvar +vertico-current-arrow t)

(cl-defmethod vertico--format-candidate :around
  (cand prefix suffix index start &context ((and +vertico-current-arrow
                                                 (not (bound-and-true-p vertico-flat-mode)))
                                            (eql t)))
  (setq cand (cl-call-next-method cand prefix suffix index start))
  (let ((arrow (nerd-icons-faicon "nf-fa-hand_o_right")))
    (if (bound-and-true-p vertico-grid-mode)
        (if (= vertico--index index)
            (concat arrow " " cand)
          (concat #("_" 0 1 (display " ")) cand))
      (if (= vertico--index index)
          (concat " " arrow " " cand)
        (concat "    " cand)))))

vertico-truncate

補完候補に非常に長い候補が存在するとパフォーマンス上の問題があるそうで、こちらのパッケージがそれを解消してくれます。

(use-package vertico-truncate
  :vc ( :fetcher github :repo "jdtsmith/vertico-truncate")
  :config
  (vertico-truncate-mode +1))

orderless

orderlessは柔軟な補完スタイルを提供するパッケージです。パフォーマンスも良く、高度にカスタマイズ可能です。

(use-package orderless
  :config
  (setq completion-styles '(orderless basic)
        completion-category-defaults nil
        completion-category-overrides nil)

  (with-eval-after-load 'migemo
    ;; orderlessをmigemo対応
    (defun orderless-migemo (component)
      (let ((pattern (downcase (migemo-get-pattern component))))
        (condition-case nil
            (progn (string-match-p pattern "") pattern)
          (invalid-regexp nil))))
    (add-to-list 'orderless-matching-styles 'orderless-migemo))

  (with-eval-after-load 'corfu
    (defun orderless-fast-dispatch (word index total)
      (and (= index 0) (= total 1) (length< word 4)
           'orderless-literal-prefix))

    (orderless-define-completion-style orderless-fast
      (orderless-style-dispatchers '(orderless-fast-dispatch))
      (orderless-matching-styles '(orderless-flex)))

    (defun my/setup-corfu-for-orderless ()
      (setq-local corfu-auto-delay 0
                  corfu-auto-prefix 1
                  completion-styles '(orderless-fast)))

    (add-hook 'corfu-mode-hook #'my/setup-corfu-for-orderless)))

prescient

prescientは補完候補の並び替えやフィルター機能を提供します。フィルター機能はorderlessの方が優れているので、並び替えのみを使用します。

(use-package prescient
  :config
  (setq prescient-aggressive-file-save t)
  (prescient-persist-mode +1))

vertico-prescient

prescientをverticoに適用します。

(use-package vertico-prescient
  :config
  (setq vertico-prescient-enable-filtering nil)
  (vertico-prescient-mode +1))

corfu-prescient

prescientをcorfuに適用します。

(use-package corfu-prescient
  :config
  (setq corfu-prescient-enable-filtering nil)
  (corfu-prescient-mode +1))

flx

flxは補完候補にスコアリングを適用するパッケージです。prescientのtiebreakerに利用しています。

(use-package flx
  :config
  (with-eval-after-load 'prescient
    ;; 入力文字を抽出
    (defvar-local my/input-query nil)
    (defun my/store-input-query (string &rest _args)
      "store the current completion query in `my/input-query'."
      (setq my/input-query (replace-regexp-in-string " " "" string)))
    (advice-add 'completion-all-completions :before #'my/store-input-query)

    ;; ローカル変数を使用できるように再定義
    (defvar vertico--total nil)
    (defvar corfu--total nil)

    (defun my/flx-tiebreaker (c1 c2)
      (if (and (and (< vertico--total 3000)
                    (< corfu--total 3000))
               (> (length my/input-query) 0)
               (< (length c1) 100)
               (< (length c2) 100))
          (let ((query my/input-query))
            (let ((score1 (car (flx-score c1 query flx-file-cache)))
                  (score2 (car (flx-score c2 query flx-file-cache))))
              (if (and (integerp score1) (integerp score2))
                  (cond ((> score1 score2) -1)
                        ((< score1 score2) 1)
                        (t (- (length c1) (length c2))))
                0)))
        (- (length c1) (length c2))))

    (setq prescient-tiebreaker #'my/flx-tiebreaker)))

consult

verticoselectrum で利用できる便利なコマンドを提供してくれます。

;; Example configuration for Consult
(use-package consult
  ;; Replace bindings. Lazily loaded due by `use-package'.
  :bind (;; C-c bindings (mode-specific-map)
         ("C-c h" . consult-history)
         ("C-c m" . consult-mode-command)
         ("C-c k" . consult-kmacro)
         ;; C-x bindings (ctl-x-map)
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ([remap switch-to-buffer] . consult-buffer)                ;; orig. switch-to-buffer
         ([remap switch-to-buffer-other-window] . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ([remap switch-to-buffer-other-frame] . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ([remap bookmark-jump] . consult-bookmark)            ;; orig. bookmark-jump
         ([remap project-switch-to-buffer] . consult-project-buffer)      ;; orig. project-switch-to-buffer
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ("<help> a" . consult-apropos)            ;; orig. apropos-command
         :map goto-map
         ("e" . consult-compile-error)
         ("f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("g" . consult-goto-line)             ;; orig. goto-line
         ("M-g" . consult-goto-line)           ;; orig. goto-line
         ("o" . consult-outline)               ;; Alternative: consult-org-heading
         ("m" . consult-mark)
         ("k" . consult-global-mark)
         ("i" . consult-imenu)
         ("I" . consult-imenu-multi)
         :map search-map
         ("d" . consult-fd)
         ("D" . consult-locate)
         ("g" . consult-grep)
         ("G" . consult-git-grep)
         ("r" . consult-ripgrep)
         ("l" . consult-line)
         ("L" . consult-line-multi)
         ("m" . consult-multi-occsur)
         ("k" . consult-keep-lines)
         ("u" . consult-focus-lines)
         ("e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-hisstory)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
         ;; Minibuffer history
         :map minibuffer-local-map
         ("M-s" . consult-history)                 ;; orig. next-matching-history-element
         ("M-r" . consult-history)
         :map my-error-map
         ("e" . consult-flymake))                ;; orig. previous-matching-history-element

  ;; Enable automatic preview at point in the *Completions* buffer. This is
  ;; relevant when you use the default completion UI.
  :hook (completion-list-mode . consult-preview-at-point-mode)

  ;; The :init configuration is always executed (Not lazy)
  :init

  ;; Optionally configure the register formatting. This improves the register
  ;; preview for `consult-register', `consult-register-load',
  ;; `consult-register-store' and the Emacs built-ins.
  (setq register-preview-delay 0.5
        register-preview-function #'consult-register-format)

  ;; Optionally tweak the register preview window.
  ;; This adds thin lines, sorting and hides the mode line of the window.
  (advice-add #'register-preview :override #'consult-register-window)

  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)

  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("b" . consult-buffer)))

  ;; Configure other variables and modes in the :config section,
  ;; after lazily loading the package.
  :config

  ;; Optionally configure preview. The default value
  ;; is 'any, such that any key triggers the preview.
  ;; (setq consult-preview-key 'any)
  ;; (setq consult-preview-key (kbd "M-."))
  ;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
  ;; For some commands and buffer sources it is useful to configure the
  ;; :preview-key on a per-command basis using the `consult-customize' macro.
  (consult-customize
   consult-theme :preview-key '(:debounce 1.0 any)
   consult-ripgrep consult-git-grep consult-grep
   consult-bookmark consult-recent-file consult-xref
   consult--source-bookmark consult--source-file-register
   consult--source-recent-file consult--source-project-recent-file
   ;; :preview-key "M-."
   :preview-key '(:debounce 0.4 any))

  ;; Optionally configure the narrowing key.
  ;; Both < and C-+ work reasonably well.
  (setq consult-narrow-key "<") ;; (kbd "C-+")

  ;; Optionally make narrowing help available in the minibuffer.
  ;; You may want to use `embark-prefix-help-command' or which-key instead.
  (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)

  ;; By default `consult-project-function' uses `project-root' from project.el.
  ;; Optionally configure a different project root function.
  ;; There are multiple reasonable alternatives to chose from.
    ;;;; 1. project.el (the default)
  ;; (setq consult-project-function #'consult--default-project--function)
    ;;;; 2. projectile.el (projectile-project-root)
  ;; (autoload 'projectile-project-root "projectile")
  ;; (setq consult-project-function (lambda (_) (projectile-project-root)))
    ;;;; 3. vc.el (vc-root-dir)
  ;; (setq consult-project-function (lambda (_) (vc-root-dir)))
    ;;;; 4. locate-dominating-file
  ;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
  )

その他

現在のディレクトリのみripgrepで検索するコマンドを定義しています。

(defun consult-ripgrep-current-directory ()
  (interactive)
  (consult-ripgrep default-directory))

(define-key search-map (kbd "R") #'consult-ripgrep-current-directory)

marginalia

vertico の候補に情報を追加してくれます。

(use-package marginalia
  :init
  (marginalia-mode +1))

embark

vertico の候補等に様々なアクションを提供してくれます。

(use-package embark
  :bind (("C-." . embark-act)         ;; pick some comfortable binding
         ("C-;" . embark-dwim)        ;; good alternative: M-.
         ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
  :init
  (setq prefix-help-command #'embark-prefix-help-command)

  :config
  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none)))))

embark-consult

embarkconsult を連動させます。

(use-package embark-consult
  :hook (embark-collect-mode . consult-preview-at-point-mode))

tempel

tempelはEmacs用のテンプレートパッケージです。有名なものにyasnippetがありますが、こちらの方がシンプルな実装になっています。

(use-package tempel
  :demand t
  :bind (("M-+" . tempel-complete) ;; Alternative tempel-expand
         ("M-*" . tempel-insert)))

tempel-collection

tempel用のテンプレートを集めているパッケージです。

(use-package tempel-collection
  :after tempel)

git

magit

Emacs上でGitを快適に操作できるようにしてくれます。

(use-package magit
  :config
  (when IS-WINDOWS
    (setq magit-refresh-status-buffer nil)
    (setq auto-revert-buffer-list-filter
          'magit-auto-revert-repository-buffer-p)
    (remove-hook 'magit-refs-sections-hook 'magit-insert-tags)
    (remove-hook 'server-switch-hook 'magit-commit-diff)
    (remove-hook 'with-editor-filter-visit-hook 'magit-commit-diff)))

diff-hl

ウィンドウの左側にコミットされていない箇所を強調表示してくれます。

(use-package diff-hl
  :hook ((magit-pre-refresh . diff-hl-magit-pre-refresh)
         (magit-post-refresh . diff-hl-magit-post-refresh)
         (dired-mode . diff-hl-dired-mode))
  :init
  (global-diff-hl-mode +1)
  (global-diff-hl-show-hunk-mouse-mode +1))

difftastic.el

Emacsでdifftasticを使用できるようにします。通常のコマンドとしても使用でき、magitにも統合させています。

(use-package difftastic
  :demand t
  :bind (:map magit-blame-read-only-mode-map
              ("D" . difftastic-magit-show)
              ("S" . difftastic-magit-show))
  :config
  (eval-after-load 'magit-diff
    '(transient-append-suffix 'magit-diff '(-1 -1)
       [("D" "Difftastic diff (dwim)" difftastic-magit-diff)
        ("S" "Difftastic show" difftastic-magit-show)])))

which-key

キーバインドを可視化してくれます。

(use-package which-key
  :config
  (which-key-mode +1))

undo

undo-fu

Emacsのundoとredoを強化するパッケージです

(use-package undo-fu
  :config
  (with-eval-after-load 'evil
    (setq evil-undo-system 'undo-fu)))

undo-fu-session

undo情報をEmacs終了後も保持してくれるようになります。

(use-package undo-fu-session
  :config
  (undo-fu-session-global-mode +1))

vundo

undo履歴を視覚的に分かりやすく表示してくれます。代表的なものにundo-treeがありますが、vundoはundo-treeよりもシンプルな実装になっています。

(use-package vundo
  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("u" . vundo))))

rg

ripgrep を利用してGrep検索してくれます。

(use-package rg
  :defer t)

apheleia

フォーマットを実行してくれるパッケージです。そのままではWindows環境でprettierが実行できなかったので、修正しています。

(use-package apheleia
  :config
  (when IS-WINDOWS
    (add-to-list 'apheleia-formatters
                 '(prettier-css
                   . (npx "prettier" "--stdin-filepath" filepath "--parser=css"
                          (apheleia-formatters-js-indent "--use-tabs" "--tab-width"))))
    (add-to-list 'apheleia-formatters
                 '(prettier-html
                   . (npx "prettier" "--stdin-filepath" filepath "--parser=html"
                          (apheleia-formatters-js-indent "--use-tabs" "--tab-width"))))
    (add-to-list 'apheleia-formatters
                 '(prettier-json
                   . (npx "prettier" "--stdin-filepath" filepath "--parser=json"
                          (apheleia-formatters-js-indent "--use-tabs" "--tab-width"))))
    (add-to-list 'apheleia-formatters
                 '(prettier-typescript
                   . (npx "prettier" "--stdin-filepath" filepath "--parser=typescript"
                          (apheleia-formatters-js-indent "--use-tabs" "--tab-width")))))

  (apheleia-global-mode +1))

theme

ef-themes

(use-package ef-themes
  :config
  (setq ef-themes-mixed-fonts t
        ef-themes-variable-pitch-ui t)
  (load-theme 'ef-melissa-light t))

modus-themes

(use-package modus-themes
  :config
  (setq modus-themes-italic-constructs t
        modus-themes-bold-constructs nil
        modus-themes-mixed-fonts t
        modus-themes-variable-pitch-ui t
        modus-themes-disable-other-themes t)

  (setq modus-themes-completions
        '((t . (underline))))

  (setq modus-themes-common-palette-overrides
        '((fg-completion-match-0 blue)
          (fg-completion-match-1 magenta-warmer)
          (fg-completion-match-2 cyan)
          (fg-completion-match-3 red)
          (bg-completion-match-0 bg-blue-nuanced)
          (bg-completion-match-1 bg-magenta-nuanced)
          (bg-completion-match-2 bg-cyan-nuanced)
          (bg-completion-match-3 bg-red-nuanced)))

  ;; (load-theme 'modus-operandi-tinted t)
  )

restart-emacs

Emacsを再起動してくれます。

(use-package restart-emacs
  :ensure nil
  :bind ( :map my-quit-map
          ("r" . restart-emacs)))

expreg

選択範囲を拡張するパッケージです。有名なものにexpand-regionがありますが、expregの方がシンプルな実装になっています。

(use-package expreg
  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("v" . expreg-expand))))

puni

括弧等の構造を操作するパッケージです。こちらの記事でも紹介されています。他に有名なパッケージとしてsmartparensがあります。

(use-package puni
  :config
  (puni-global-mode +1))

alert

通知機能を利用できるようにします。主に org-pomodoro で使用します。

(use-package alert
  :init
  (setq alert-default-style 'libnotify))

alert-toast

Windows用の設定です。

(use-package alert-toast
  :if IS-WINDOWS
  :init
  (setq alert-default-style 'toast))

treesit

tree-sitter をEmacsで利用できるようにします。

treesit-auto

treesiterの自動インストールやセットアップをしてくれます。

(use-package treesit-auto
  :config
  (setq treesit-auto-install 'prompt)
  (treesit-auto-add-to-auto-mode-alist 'all)
  (global-treesit-auto-mode +1))

string-inflection

こちらのパッケージはカーソル直下の単語をunderscore -> UPCASE -> CamelCase に変換してくれます。

(use-package string-inflection
  :bind ( :map my-string-inflection-map
          ("a" . string-inflection-all-cycle)
          ("_" . string-inflection-underscore)
          ("p" . string-inflection-pascal-case)
          ("c" . string-inflection-camelcase)
          ("u" . string-inflection-upcase)
          ("k" . string-inflection-kebab-case)
          ("C" . string-inflection-capital-underscore))
  :init
  (defvar my-string-inflection-map (make-keymap))
  (with-eval-after-load 'meow
    (meow-leader-define-key
     `("i" . ("inflection" . ,my-string-inflection-map)))))

go-translate

Emacs内で翻訳してくれるようになります。

(use-package go-translate
  :init
  (setq gts-translate-list '(("en" "ja")))
  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("T" . gts-do-translate))))

avy

画面上の文字にジャンプできるようになります。別ウィンドウにもジャンプできるので重宝しています。

(use-package avy
  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("a" . avy-goto-char))))

ace-window

Emacsモダン化計画 -かわEmacs編-を参考に設定しています。ウィンドウの移動が楽になります。

(use-package ace-window
  :config
  (with-eval-after-load 'meow
    (meow-leader-define-key
     '("w" . ace-window)))
  (custom-set-faces
   '(aw-leading-char-face ((t (:foreground "red" :height 4.0))))))

migemo

ローマ字で日本語を検索できるようにしてくれます。WindowsではScoopを使用してcmigemoをダウンロードしています。

(use-package migemo
  :init
  ;; cmigemo(default)
  (setq migemo-command "cmigemo")
  (setq migemo-options '("-q" "--emacs"))

  ;; Set your installed path
  (when IS-WINDOWS
    (setq migemo-dictionary
          "C:/Users/u396/scoop/apps/cmigemo/current/cmigemo-mingw64/share/migemo/utf-8/migemo-dict"))

  (setq migemo-user-dictionary nil)
  (setq migemo-regex-dictionary nil)
  (setq migemo-coding-system 'utf-8-unix)

  :config
  (migemo-init))

lin

hl-line-mode を強化するパッケージです。

(use-package lin
  :init
  (setq lin-face 'lin-red)
  (lin-global-mode +1))

pulsar

カーソルの移動を視覚的に分かりやすくしてくれます。beaconよりもシンプルな実装になっています。

(use-package pulsar
  :config
  (pulsar-global-mode +1))

goggles

(use-package goggles
  :hook ((prog-mode text-mode) . goggles-mode)
  :config
  (setq-default goggles-pulse t)) ;; set to nil to disable pulsing

spacious-padding

画面の余白を付けてくれます。カスタマイズ変数を調整することでモードラインも良い感じにしてくれます。

(use-package spacious-padding
  :config
  (setq spacious-padding-widths
        '( :internal-border-width 15
           :header-line-width 4
           :mode-line-width 6
           :tab-width 4
           :right-divider-width 30
           :scroll-bar-width 8))

  ;; Read the doc string of `spacious-padding-subtle-mode-line' as it
  ;; is very flexible and provides several examples.
  (setq spacious-padding-subtle-mode-line
        `( :mode-line-active 'default
           :mode-line-inactive vertical-border))

  (spacious-padding-mode +1))

beframe

あまり使い方を理解していませんが、consult-bufferに適用しています。

(use-package beframe
  :config
  (defvar consult-buffer-sources)
  (declare-function consult--buffer-state "consult")

  (with-eval-after-load 'consult
    (defface beframe-buffer
      '((t :inherit font-lock-string-face))
      "Face for `consult' framed buffers.")

    (defvar beframe-consult-source
      `( :name     "Frame-specific buffers (current frame)"
         :narrow   ?F
         :category buffer
         :face     beframe-buffer
         :history  beframe-history
         :items    ,#'beframe-buffer-names
         :action   ,#'switch-to-buffer
         :state    ,#'consult--buffer-state))

    (add-to-list 'consult-buffer-sources 'beframe-consult-source))

  (beframe-mode +1))

aggressive-indent

インデントを自動的に整えてくれるパッケージです。elispを書いているときに重宝します。

(use-package aggressive-indent
  :hook (emacs-lisp-mode . aggressive-indent-mode))

perfect-mergin

バッファが1つの時に中央寄せしてくれます。同様のパッケージにsublimityがあります。

(use-package perfect-margin
  :config
  (setq perfect-margin-ignore-filters nil)
  (perfect-margin-mode +1))

dashboard

起動画面を良い感じにしてくれます。

(use-package dashboard
  :config
  (setq dashboard-center-content t)
  (dashboard-setup-startup-hook))

page-break-lines

^Lの改ページ文字の表示を良くします。

(use-package page-break-lines
  :config
  (page-break-lines-mode +1))

breadcrumb

バッファ上部にパンくずリストを表示してくれます。

(use-package breadcrumb
  :vc ( :fetcher github :repo "joaotavora/breadcrumb")
  :config
  (breadcrumb-mode +1))

rainbow-delimiters

括弧の深さに応じて色付けをしてくれます。

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

imenu-list

imenuを一覧表示してくれます。

(use-package imenu-list
  :bind ( :map my-toggle-map
          ("i" . imenu-list-smart-toggle))
  :init
  (setq imenu-list-position 'left))

eglot

emacsに標準で組み込まれているlspクライアントです。lsp-modeよりもEmacsの標準機能と良く統合されています。lsp-modeにはlanguage serverのインストール機能が備わっていますので、lsp-modeでインストールしたlanguage serverを利用できるようにパスを通しています。

(use-package eglot
  :bind ( :map eglot-mode-map
          ("C-c r" . eglot-rename)
          ("C-c o" . eglot-code-action-organize-imports)
          ("C-c a" . eglot-code-actions)
          ("C-c h" . eldoc)
          ("<f6>" . xref-find-definitions))
  :init
  (setq eglot-events-buffer-config '(:size 0  :format short)
        eglot-ignored-server-capabilities '(:documentHighlightProvider)
        eglot-stay-out-of '(flymake)
        eglot-send-changes-idle-time 1.0)

  (defun my/add-directory-to-exec-path-recursively (dir)
    "Recursively add directories and their subdirectories to `exec-path`."
    (add-to-list 'exec-path dir)
    (dolist (entry (directory-files dir t "^[^.]" t))
      (when (file-directory-p entry)
        (my/add-directory-to-exec-path-recursively entry))))

  (defun my/load-lsp-exec-path ()
    (interactive)
    (my/add-directory-to-exec-path-recursively "~/.emacs.d/.cache/"))

  (my/load-lsp-exec-path))

eglot-tempel

スニペットパッケージのtempelとeglotと統合するパッケージです。

(use-package eglot-tempel
  :after (eglot tempel)
  :hook (eglot-managed-mode . eglot-tempel-mode))

consult-eglot

consultとeglotを統合するパッケージです。シンボルの検索が行えるようになります。

(use-package consult-eglot
  :after eglot
  :bind ( :map eglot-mode-map
          ("C-c s" . consult-eglot-symbols)))

jsonrpc

jsonrpcはjsonを扱うEmacsの標準パッケージです。デフォルトのタイムアウト時間が短いため、タイムアウトしないように時間を延ばしています。また、ログを無視するように設定することでパフォーマンスを向上させています。

(use-package jsonrpc
  :defer t
  :config
  (setq jsonrpc-default-request-timeout 3000)
  (fset #'jsonrpc--log-event #'ignore))

eglot-booster

lsp-boosterはlspのパフォーマンスを向上させるパッケージです。Windowsでは上手く動作が確認できませんでした…

(use-package eglot-booster
  :after eglot
  :vc ( :fetcher github :repo "jdtsmith/eglot-booster")
  :config
  (eglot-booster-mode +1))

eglot-x

eglotは標準的な機能しかサポートしていませんが、こちらのパッケージを導入することでサポートされる機能が増えます。

(use-package eglot-x
  :vc ( :fetcher github :repo "nemethf/eglot-x")
  :after eglot
  :config
  (eglot-x-setup))

eldoc-box

ミニバッファのeldocをposframeで表示してくれます。

(use-package eldoc-box
  :hook (eglot-managed-mode . eldoc-box-hover-mode))

eglot-signature-eldoc-talkative

eldocの情報を追加します。

(use-package eglot-signature-eldoc-talkative
  :after eldoc-box
  :config
  (advice-add #'eglot-signature-eldoc-function
              :override #'eglot-signature-eldoc-talkative))

lsp-mode

lsp-modeはeglotよりも多機能で開発が活発です。全ての機能を有効にすると、パフォーマンスが悪くなる可能性があるので、必要のない機能は無効にします。

(use-package lsp-mode
  ;; :hook (((typescript-ts-mode
  ;;          tsx-ts-mode
  ;;          html-ts-mode
  ;;          css-ts-mode
  ;;          json-ts-mode) . lsp))
  :init
  (setq read-process-output-max (* 1024 1024)) ;; 1mb
  (setq lsp-keymap-prefix "M-l")
  (setq lsp-headerline-breadcrumb-enable nil
        lsp-enable-file-watchers nil
        lsp-enable-folding nil
        lsp-enable-symbol-highlighting nil
        lsp-enable-text-document-color nil
        lsp-enable-indentation nil
        lsp-enable-on-type-formatting nil
        lsp-auto-execute-action nil
        lsp-before-save-edits nil))

lsp-java

JavaのLSは特殊なため、専用の拡張パッケージをインストールします。

最新のバージョンはここを参照します。※1.13以降はJava17が必要

(use-package lsp-java
  :after (lsp-mode java-mode))

lsp-pyright

pyright を利用したい場合、こちらのパッケージをインストールします。

(use-package lsp-pyright
  :after (lsp-mode python-mode))

symbol-overlay

emacsの組み込み関数を利用してシンボルをハイライトしてくれます。

(use-package symbol-overlay
  :hook (prog-mode . symbol-overlay-mode))

lsp-snippet

tempelとlsp-modeを統合するパッケージです。

(use-package lsp-snippet
  :vc ( :fetcher github :repo "svaante/lsp-snippet")
  :config
  (when (featurep 'lsp)
    (lsp-snippet-tempel-lsp-mode-init)))

emacs-lsp-booster

lsp-boosterはlspのパフォーマンスを向上させるパッケージです。Windowsでは上手く動作が確認できませんでした…

(progn
  (defun lsp-booster--advice-json-parse (old-fn &rest args)
    "Try to parse bytecode instead of json."
    (or
     (when (equal (following-char) ?#)
       (let ((bytecode (read (current-buffer))))
         (when (byte-code-function-p bytecode)
           (funcall bytecode))))
     (apply old-fn args)))
  (advice-add (if (progn (require 'json)
                         (fboundp 'json-parse-buffer))
                  'json-parse-buffer
                'json-read)
              :around
              #'lsp-booster--advice-json-parse)

  (defun lsp-booster--advice-final-command (old-fn cmd &optional test?)
    "Prepend emacs-lsp-booster command to lsp CMD."
    (let ((orig-result (funcall old-fn cmd test?)))
      (if (and (not test?)                             ;; for check lsp-server-present?
               (not (file-remote-p default-directory)) ;; see lsp-resolve-final-command, it would add extra shell wrapper
               lsp-use-plists
               (not (functionp 'json-rpc-connection))  ;; native json-rpc
               (executable-find "emacs-lsp-booster"))
          (progn
            (message "Using emacs-lsp-booster for %s!" orig-result)
            (cons "emacs-lsp-booster" orig-result))
        orig-result)))
  (advice-add 'lsp-resolve-final-command :around #'lsp-booster--advice-final-command))

language

各言語のインデントの設定や専用のパッケージを設定しています。

elisp

  1. highlight-defined

    既知のシンボルに色を付けてくれます。

    (use-package highlight-defined
      :hook (emacs-lisp-mode . highlight-defined-mode))
    
  2. highlight-quoted

    引用符と引用記号を色付けしてくれます。

    (use-package highlight-quoted
      :hook (emacs-lisp-mode . highlight-quoted-mode))
    

web

  1. typescript-mode

    (use-package typescript-mode)
    
  2. jtsx

    tsxやjsxファイルの編集を強化してくれます。

    (use-package jtsx
      :ensure t
      :mode (("\\.jsx?\\'" . jtsx-jsx-mode)
             ("\\.tsx\\'" . jtsx-tsx-mode)
             ("\\.ts\\'" . jtsx-typescript-mode))
      :commands jtsx-install-treesit-language
      :hook ((jtsx-jsx-mode . hs-minor-mode)
             (jtsx-tsx-mode . hs-minor-mode)
             (jtsx-typescript-mode . hs-minor-mode))
      :custom
      ;; Optional customizations
      ;; (js-indent-level 2)
      ;; (typescript-ts-mode-indent-offset 2)
      ;; (jtsx-switch-indent-offset 0)
      (jtsx-indent-statement-block-regarding-standalone-parent nil)
      (jtsx-jsx-element-move-allow-step-out t)
      (jtsx-enable-jsx-electric-closing-element t)
      (jtsx-enable-electric-open-newline-between-jsx-element-tags t)
      (jtsx-enable-jsx-element-tags-auto-sync t)
      (jtsx-enable-all-syntax-highlighting-features t)
      :config
      (defun jtsx-bind-keys-to-mode-map (mode-map)
        "Bind keys to MODE-MAP."
        (define-key mode-map (kbd "C-c C-j") 'jtsx-jump-jsx-element-tag-dwim)
        (define-key mode-map (kbd "C-c j o") 'jtsx-jump-jsx-opening-tag)
        (define-key mode-map (kbd "C-c j c") 'jtsx-jump-jsx-closing-tag)
        (define-key mode-map (kbd "C-c j r") 'jtsx-rename-jsx-element)
        (define-key mode-map (kbd "C-c <down>") 'jtsx-move-jsx-element-tag-forward)
        (define-key mode-map (kbd "C-c <up>") 'jtsx-move-jsx-element-tag-backward)
        (define-key mode-map (kbd "C-c C-<down>") 'jtsx-move-jsx-element-forward)
        (define-key mode-map (kbd "C-c C-<up>") 'jtsx-move-jsx-element-backward)
        (define-key mode-map (kbd "C-c C-S-<down>") 'jtsx-move-jsx-element-step-in-forward)
        (define-key mode-map (kbd "C-c C-S-<up>") 'jtsx-move-jsx-element-step-in-backward)
        (define-key mode-map (kbd "C-c j w") 'jtsx-wrap-in-jsx-element)
        (define-key mode-map (kbd "C-c j u") 'jtsx-unwrap-jsx)
        (define-key mode-map (kbd "C-c j d") 'jtsx-delete-jsx-node))
    
      (defun jtsx-bind-keys-to-jtsx-jsx-mode-map ()
        (jtsx-bind-keys-to-mode-map jtsx-jsx-mode-map))
    
      (defun jtsx-bind-keys-to-jtsx-tsx-mode-map ()
        (jtsx-bind-keys-to-mode-map jtsx-tsx-mode-map))
    
      (add-hook 'jtsx-jsx-mode-hook 'jtsx-bind-keys-to-jtsx-jsx-mode-map)
      (add-hook 'jtsx-tsx-mode-hook 'jtsx-bind-keys-to-jtsx-tsx-mode-map))
    
  3. emmet-mode

    Emmet を導入します。

    (use-package emmet-mode
      :hook ((html-mode
              css-mode
              js-mode
              typescript-mode) . emmet-mode))
    
  4. web-beautify

    web-beautify を導入します。

    (use-package web-beautify
      :defer t)
    

rust-mode

(use-package rust-mode
  :hook (rust-mode . (lambda ()
                       (setq-local tab-width 4))))
  1. cargo

    (use-package cargo
      :hook (rust-mode . cargo-minor-mode))
    

python

  1. pyvenv

    (use-package pyvenv
      :defer t)
    

common lisp

  1. slime

    (use-package slime
      :defer t
      :init
      (setq inferior-lisp-program "sbcl"))
    
  2. slime-company

    (use-package slime-company
      :after (slime company)
      :config
      (setq slime-company-completion 'fuzzy
            slime-company-after-completion 'slime-company-just-one-space))
    

sql

  1. sql-indent

    (use-package sql-indent
      :hook (sql-mode . sqlind-minor-mode))
    
  2. sql-format

    (use-package sqlformat
      :init
      (setq sqlformat-command "sqlfluff"))
    

footer

(provide 'init)
;;; init.el ends here
21
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
27