現在お買い物カゴには何も入っていません。
タグ: emacs lisp
Emacs入門
Emacsの基本と開発
チュートリアルの起動
Emacsを起動後、以下のコマンドでチュートリアルを開始できます:
C-h t
日本語版を起動するには:
C-h t japanese
これを練習しないと、例えばマニュアルでのキーバインドの特殊な記法の意味すら理解できません。上記のキーバインドの意味が分からない方は、プルダウンのHelpメニューから辿って下さい。時間はかかりません。すぐに終わります。
基本的な使い方
- 起動と終了:
- 起動:ターミナルで
emacs
と入力 - コマンドラインでの使用:
emacs -nw
と入力 - 終了:
C-x C-c
- 起動:ターミナルで
- 基本的なカーソル移動:
- 前後左右:
C-p
,C-n
,C-b
,C-f
- 行頭/行末:
C-a
,C-e
- 前後左右:
- ファイル操作:
- 開く:
C-x C-f
- 保存:
C-x C-s
- 開く:
- 編集:
- コピー:
M-w
- カット:
C-w
- ペースト:
C-y
- コピー:
- バッファ操作:
- バッファ切り替え:
C-x b
- バッファ一覧:
C-x C-b
- バッファ切り替え:
Elispでの開発方法
- Elispファイルの作成:
.el
拡張子のファイルを作成 - 基本的な構文:
(defun my-function (arg) "Documentation string." (interactive "p") (message "Hello, %s" arg))
- 評価:
- 関数全体:カーソルを関数定義の末尾に置き
C-x C-e
- バッファ全体:
M-x eval-buffer
- 関数全体:カーソルを関数定義の末尾に置き
- デバッグ:
- デバッガの有効化:
(setq debug-on-error t)
- ブレークポイントの設定:
(debug)
- Flycheckによるsyntaxチェック
- デバッガの有効化:
- パッケージ開発:
provide
を使用してパッケージ名を定義- 依存関係は
require
で指定
極端な話、M-x load-file RETとC-h fとC-h vを知っていれば、ある程度までは試行錯誤で出来ます。まずは Programming in Emacs Lisp を読みましょう。
load-path
とload
の違いload-path
は、Emacsがライブラリを検索するディレクトリのリストです。新しいディレクトリを追加するには、add-to-list
関数を使います。;; ~/.emacs.d/init.el に記述 (add-to-list 'load-path "~/.emacs.d/site-lisp/")
これにより、
~/.emacs.d/site-lisp/
ディレクトリ内のファイルがEmacsの検索対象に追加されます。load
関数は指定したファイルをロードします。ファイルの拡張子(通常は.el
)は省略可能です。;; ~/.emacs.d/init.el に上記設定に続いて記述 ;; ~/.emacs.d/site-lisp/my-settings.el (load "my-settings")
これにより、
~/.emacs.d/site-lisp/my-settings.el
がロードされます。require
関数は指定したライブラリがロードされていなければロードします。provide
関数とセットで使用されることが多いです。flycheckを有効にしていると、elispファイルの末尾で
provide
を書けと注意されるので、flycheck-copy-errors-as-kill
でコピーすると便利です。;; ~/.emacs.d/site-lisp/my-settings.el に記述 (provide 'my-settings) ;;; my-settings.el ends here ;; ~/.emacs.d/init.el に記述 ;; load-pathが通っていることが前提 (require 'my-settings)
設定ファイルを幾つも書いていて、まとめて
load
する必要がある場合、EmacsWikiに投稿されているload-directoryを利用すると便利です。但し、load-directory.elは別のディレクトリに置いた方が良いかも知れません。以下の設定で、そのファイルを2度load
するからです。;; load-pathが通っていることが前提 (load "load-directory") ;; 或いは (load "~/.emacs.d/site-lisp/load-directory") ;; provideが書かれていれば (require 'load-directory) (load-directory "~/.emacs.d/site-lisp")
以下の関数はload-directoryを元にChatGPTが書いてくれました。
load
ではなく、require
を再帰的に実行します。(defun require-directory (directory)
"Require recursively all `.el' files in DIRECTORY."
(dolist (element (directory-files-and-attributes directory nil nil nil))
(let* ((path (car element))
(fullpath (concat directory "/" path))
(isdir (car (cdr element)))
(ignore-dir (or (string= path ".") (string= path ".."))))
(cond
((and (eq isdir t) (not ignore-dir))
(require-directory fullpath))
((and (eq isdir nil) (string= (substring path -3) ".el"))
(require (intern (file-name-sans-extension path))))))))以下は~/.emacs.d/init.elの設定です。
;; load-pathが通っていることが前提 ;; load-directoryと同じファイル名と仮定 ;; ~/.emacs.d/site-lisp/load-directory.el (load "load-directory") ;; provideが書かれていれば (require 'load-directory) (require-directory "~/.emacs.d/site-lisp")
MELPA (Milkypostman’s Emacs Lisp Package Archive)
MELPAは、Emacsの人気のあるパッケージリポジトリです。開発したパッケージを登録することも出来ます。プルリクエストとしてRecipeを提出する方法はREADMEを御覧ください。Pull requestsタブをクリックして書き方の参考にすると良いでしょう。
- MELPAの設定:
(require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize)
- パッケージのインストール:
M-x package-install RET package-name RET
- パッケージの更新:
M-x package-list-packages RET U x
keyword-searchプロジェクト
keyword-searchは、Emacsでブラウザスタイルのキーワード検索を可能にするパッケージです。
- インストール:
M-x package-install RET keyword-search RET
- 基本的な使用方法:
M-x keyword-search RET
- 検索エンジンを選択(TABで補完可能)
- 検索クエリを入力
- カスタマイズ:
- デフォルト検索エンジンの設定:
M-x customize-variable RET keyword-search-default RET
- 検索エンジンの追加:
M-x customize-variable RET keyword-search-alist RET
- デフォルト検索エンジンの設定:
- 拡張モード:
- 追加の言語サービス:
keyword-search-extra-mode
- マニア向けウェブサイト:
keyword-search-mad-mode
- 追加の言語サービス:
keyword-searchは、Emacsユーザーが効率的にウェブ検索を行えるようにする便利なツールです。MELPAを通じて簡単にインストールでき、カスタマイズも容易です。
browse-apropos-urlを元にMr. Jens Petersenが開発しました。私が書いたコードよりずっと素晴らしいです。私はプルリクエストを提出したことがきっかけで開発に参加しました。2024年現在、最後のコミットが6年前なので、動作しないURLや機能があるでしょうが、検索に役立つので是非試してください。
プログラミングの作業の大半は調べものなのですから。
Emacsでの定義元ジャンプと自動補完の設定
定義元ジャンプ
定義元ジャンプには、主に以下のパッケージが使用されます:
xref
: Emacsに標準搭載されているパッケージdumb-jump
: 外部ツールに依存しない汎用的なジャンプツール
xrefの設定
M-.
がxref-find-definitions
に、M-,
がxref-go-back
に割り当てられています。xref-pop-marker-stack
はEmacs 29.1で廃止されました。C-h k M-.
でキーバインドを確認できます。設定されていなければ、以下のように設定し直すことが出来ます。(global-set-key (kbd "M-.") 'xref-find-definitions) (global-set-key (kbd "M-,") 'xref-go-back)
xref
を使う前に、TAGS
ファイルを作成する必要があります。以下のコマンドを使用してTAGS
ファイルを生成します。Pythonでの例:
etags --help --lang=python In Python code, 'def' or 'class' at the beginning of a line generate a tag. find . -type f -name "*.py" -exec etags -a {} + find /usr/lib/python3/dist-packages/ -type f -name "*.py" -exec etags -a {} +
ctagsやetagsの拡張がaptでインストール出来ます。例えば:
sudo apt install universal-ctags ls -l /usr/bin/etags lrwxrwxrwx 1 root root 23 3月 16 2023 /usr/bin/etags -> /etc/alternatives/etags* ls -l /etc/alternatives/etags lrwxrwxrwx 1 root root 24 7月 16 22:10 /etc/alternatives/etags -> /usr/bin/ctags-universal*
dumb-jumpの設定
MELPAからインストール:
M-x package-install RET dumb-jump RET
設定。xrefの上書き:
(require 'dumb-jump) (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
自動補完
自動補完には、
company-mode
を使用します。MELPAからインストール:
M-x package-install RET company RET
設定:
(add-hook 'after-init-hook 'global-company-mode)
MELPAでインストールすべき便利なパッケージ
選択候補を表示した方が早いこともあります。例えば、yank-popを視覚化したcounsel-yank-popの方が使いやすいと多くの人が感じるでしょう。私も思います。
ivy
1: 補完フレームワークM-x package-install RET ivy RET
counsel
2: ivyを使用した各種コマンドの強化版M-x package-install RET counsel RET
swiper
: ivyを使用した検索機能M-x package-install RET swiper RET
projectile
: プロジェクト管理ツールM-x package-install RET projectile RET
magit
: GitクライアントM-x package-install RET magit RET
flycheck
: シンタックスチェッカーM-x package-install RET flycheck RET
flycheckの説明と設定
flycheckは、コードの文法チェックをリアルタイムで行うツールです。多くのプログラミング言語に対応しています。
お薦めの関数は
flycheck-copy-errors-as-kill
です。その場のエラーをkill ringにコピーできるので、そのままyank出来ます。因みに、この記事ではbuilt-inのFlymakeやEglotの説明をしません。
設定:
(add-hook 'after-init-hook #'global-flycheck-mode)
global-flycheck-mode
はあらゆる場面で起動するため、特定のメジャーモードでのみ起動する設定を推奨します。(add-hook 'emacs-lisp-mode-hook 'flycheck-mode) (add-hook 'python-mode-hook 'flycheck-mode)
Pythonの場合、Flycheck は python-flake8 または python-pylint を使用して Python をチェックし、どちらも使用できない場合は python-pycompile を使用します(fall back)。
Supported Languagespip install pylint
lsp-modeの設定とlanguage serverのインストール
lsp-modeのインストールと設定
MELPAからインストール:
M-x package-install RET lsp-mode RET
設定例:
(require 'lsp-mode) (add-hook 'python-mode-hook #'lsp) (add-hook 'c-mode-hook #'lsp) (add-hook 'javascript-mode-hook #'lsp) (add-hook 'prog-mode-hook #'lsp) ;; あらゆるprogramming modesで起動
後者の設定は
prog-mode
3より派生するmajor modesに対応できるので便利です。Language Serverのインストール方法
一つのプログラミング言語に対応する複数のlanguage serverがあります。
- Python (pyright)
npm install -g pyright which pyright /home/foo/.npm-global/bin/pyright
- Python(jedi-language-server)
pip install -U jedi-language-server
- C/C++ (clangd)
sudo apt install clangd
- JavaScript (typescript-language-server)
npm install -g typescript-language-server
- Objective-C (clangd)
sudo apt install clangd
lsp
の切り替えC-u M-x lsp
つまり数引数を先に与えてlsp
を実行すると、language serverを切り替えることが出来ます。例えばPythonで複数のlanguage serverをインストールしている場合に便利です。lsp-pyrightのインストールと設定はREADMEに書かれています。
使用しているvenvを指定するには
C-h lsp-pyright-venv-path
でcustomize this variableのリンクに入ります:/home/foo/.venv3.12 ;; 初期値はnil
lsp-jediのインストールと設定もREADMEに書かれています。venvのpipでjedi-language-serverをインストールすると、lspが呼び出せませんので以下の作業が必要になります。また、Emacsで使用する前に毎回activateする必要があります。
まず、コマンドのパスを調べます:
source ~/.venv3.12/bin/activate # venvの例 which jedi-language-server
C-h v lsp-jedi-executable-commandでcustomize this variableのリンクに入ります:
jedi-language-server ;; 変更前の初期値 /home/foo/.venv3.12/bin/jedi-language-server ;; 変更例
Jediを使った他の補完方法
lsp-jediを使わずcompany-jediを使う方法もあります。
MELPAからインストール:
M-x package-install RET company-jedi RET
設定:
(defun my/python-mode-hook () (add-to-list 'company-backends 'company-jedi)) (add-hook 'python-mode-hook 'my/python-mode-hook)
auto-completeとjedi.el(MELPAパッケージ名はjedi)を使う方法もあります。但し、virtualenvに依存します。aptやpipでのインストールが必要です。現在はvenvが主流ですので勘違いしないで下さい。両者は別物です。詳しくはマニュアルを参照して下さい。
以下の作業も必要になるでしょう:
M-x jedi:install-server RET M-x jedi:reinstall-server RET ;; 2回目から
~/.emacs.d/.python-environments/default/
に仮想環境が作られます。デバッグの設定と使い方
デバッグの設定と使い方についても簡単に説明します。
- Emacs標準のgud-modeを使用する場合:
M-x gdb M-x pdb ;; Pythonの場合
pdbの場合、ミニバッファに以下のように表示されるのでファイルを指定します:
Run pdb (like this): python -m pdb myscript.py
キー割り当て
キーボードに右Altが無いと、Emacsユーザーには不便です。以下のように設定すると、変換キーをEscのように使うことが出来ます。
;; 「無変換」キーで定義の先頭に移動 (global-set-key [muhenkan] 'beginning-of-defun) ;; MetaつまりAltを押しながら「無変換」で定義の末尾に移動 (global-set-key (kbd "M-<muhenkan>") 'end-of-defun) ;; 「変換」キーをEscのようにする (global-set-key (kbd "<henkan>") esc-map) ;; 「カタカナひらがな」キーをM-xにする (global-set-key [hiragana-katakana] 'execute-extended-command)
まとめ
設定したりパッケージを導入することで、Emacsの機能を大幅に拡張し、より効率的な開発環境を構築することができます。定義元ジャンプや自動補完、シンタックスチェックなどの機能は、コーディングの生産性を大きく向上させます。
Emacsのパッケージとは別に、aptやpipやnpmでインストールしてEmacsから呼び出すものがあるので混乱するかも知れませんが、そのソフトウェアの開発言語が何かを知っていれば、何故そのpackage managerでインストールするのか理解できるでしょう。
Citations:
[1] keyword-search.el
[2] Emacsの特徴や活用方法を徹底解説!
[3] Emacsチュートリアル 日本語訳
[4] emacs の使い方
[5] Emacs の簡単な使い方
[6] #17 “手遅れ”を防ぐ Emacsのセーフガードシステム (Software Design 2015年9月号掲載記事) Emacs undo redo 使い方
[7] 突然だがEmacs を始めよう
[8] Programming in Emacs Lisp
[9] EmacsでFlycheckのウィンドウをトグルできるようにした
[10] ctagとetagについて #8
[11] exuberant-ctagsとuniversal-ctagsの違い
[12] Flycheck を Python で使うためにしたことメモ
[13] Flycheck — Syntax checking for GNU Emacs- 起動と終了: