【2024年版】c-quick: Lisp系のソースコードを効率的に編集するためのEmacs Lispパッケージ

https://qiita.com/javacommons/items/40cc831b1a6315387a63

最新版の c-quick.el は以下のGitHubリポジトリからダウンロードできます。

> [https://github.com/emacs-pkg/c-quick/releases/latest](https://github.com/emacs-pkg/c-quick/releases/latest)

# インストール方法 (c-quick.el)

とりあえず使ってみたい(または最新の変更に追随したい)方は、.emacs または init.el に以下を追加しておくと自動的にロードされます。更新があれば自動的に更新されます。

```elisp:~/.emacs or ~/.emacs.d/init.el
(unless (featurep 'get-feature)
  (defun get-feature (feature-name &optional url file-name)
    (if (featurep feature-name) t
      (unless url (setq url (format "https://github.com/emacs-pkg/%s/raw/main/%s.el"
                                    feature-name feature-name)))
      (unless file-name (setq file-name (format "%s.el" feature-name)))
      (let ((make-backup-files nil)
            (file-path (expand-file-name file-name user-emacs-directory)))
        (ignore-errors
          (url-copy-file url file-path 'ok-if-already-exists))
        (ignore-errors
          (load file-path nil 'nomessage))
        (featurep feature-name))))
  (get-feature 'get-feature))

(get-feature 'c-quick)
```

straight.el でロードしたい場合は以下を .emacs または init.el に入れてください(但し git のインストールが必要です)：

```elisp:~/.emacs or ~/.emacs.d/init.el
(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 6))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

(straight-use-package '(c-quick :type git :host github :repo "emacs-pkg/c-quick"))
(require 'c-quick)
```

----

尚、straight.el ではパッケージを最新化するのに手動で操作をする必要があります。以下の記事をご覧ください：

https://qiita.com/javacommons/items/4dd0f1b74213437c04ec

----

# 1. Lisperのためのカーソル移動ライブラリの側面(入門者向けモード)

## 1.1 S式の幅での移動

次の例でカーソルが㊀にあるときに、Ctrl-right を1回押すと㊁に移動します。
また、カーソルが㊁にあるときに、Ctrl-left を1回押すと㊀に移動します。
(※括弧の中に入れません)

```text:例1.1A
㊀(defun add2 (a b) (+ a b))㊁
```

今度は、トップレベルの括弧の中に入って㊀の場所にカーソルがある際に、Ctrl-right を順に押すと、㊀⇒㊁⇒・・・⇒㊇と移動し、㊇まで来るとそれ以上右に移動しません。
逆に、㊇にカーソルがある際に、Ctrl-left を押すと、㊇⇒㊆⇒・・・⇒㊀と移動し、㊀まで来るとそれ以上左に移動しません。
(※括弧の中から出れません)

```text:例1.1B
(㊀defun㊁ ㊂add2㊃ ㊄(a b)㊅ ㊆(+ a b)㊇)
```

## 1.2 トップレベルのS式の位置づけ

Ctrl-down を押すと、(コメント等はすっ飛ばして) ㊀㊁㊂・・・㊆というように移動します。これは単に左端(行頭)の括弧を位置づけるだけですが、複数行ある定義においても有効です。
逆に、Ctrl-up を押すと㊆㊅㊄・・・㊀と移動します。

```
㊀(require 'find-func)

㊁(global-set-key (kbd "<down>")     'c-quick-down-key)
㊂(global-set-key (kbd "<up>")       'c-quick-up-key)
㊃(global-set-key (kbd "<right>")    'c-quick-right-key)
㊄(global-set-key (kbd "<left>")     'c-quick-left-key)
㊅(global-set-key (kbd "C-z")        'undo)
㊆(global-set-key (kbd "M-w")        'c-quick-copy-region)
  ・
  ・
  ・
```

# 2. Lisperのためのカーソル移動ライブラリの側面(エキスパートモード)

片手で Lisp/Scheme のソースレビューをするためのモード(c-quick mode)をご紹介します。
c-quick.el をロードした状態で F9 を押すと、ミニバッファに「c-quick-mode is ON」と表示されます(もう一回 F9 を押すと解除されます)。(※c-quick mode は、バッファー毎に独立して設定されます)
c-quick mode では、以下に説明するようなカーソルの動きとなります。

## 2.1 左右キーは、1章の Ctrl-left, Ctrl-right と同じ動作になります

Ctrl を押す必要がなくなるため、片手(右手)をカーソルキー(矢印キー)に置くだけでS式の幅でカーソル移動ができます。

## 2.2 上下キーは(原則)、左右一文字の移動となります

「原則」と書いたのは、カーソルが行頭にある場合は、上下キーは「上下に移動します」。

## 2.3 実際的な使い方

c-quick mode において、㊀にカーソルがある場合に、右矢印を押すと㊁に移動してしまい。`+ a b` の部分に入ることができません。
そこで、上下キーの「横スライド」が役に立つのです。

```text:例2.3A
(defun add2 (a b) ㊀(+ a b)㊁)
```

上図において、㊀にカーソルがある場合には、下矢印を押すと㊂に移動します。
㊁にカーソルがある場合には、上矢印を押すと㊃に移動します。
㊂または㊃に入ったら、今度は左右矢印で`+ a b`のレベルのナビゲートができます。

```text:例2.3B
(defun add2 (a b) (㊂+ a b㊃))
```

では、下図の㊀にカーソルがある場合に㊂に移動するには、どうしたらいいでしょう？
行頭では、上下キーはまさに上下に移動してしまいます。
この場合には、一回右矢印を押して㊁に移動した後上キー(の横スライド)で㊃に入った後、左キーを押しっぱなし(キーリピート)で㊂までかっ飛ばします。
(※ これがトップレベルの括弧の中に入る定石ですのでマスターしてくださいね)

```:例2.3C
㊀(㊂defun add2 (a b) (+ a b)㊃)㊁
```

左端の括弧の場合、「中に入る」操作が少しトリッキーですが、以下のようなソースになっている(ことが多い)場合には、やはり下矢印で「中(㊁)に入る」ことができます。
下矢印で一段下の「中に入る」ことができますので、後は、左矢印で㊂までかっ飛ばします。
この場合も、右矢印で㊀から㊃にとんだ後、上キー(の横スライド)で中に入り、左キーでかっ飛ばすという戦略(上記の定石)もまた有効です。

```:例2.3D
㊀(㊂defun add2 (a b)
㊁  (+ a b))㊃
```

## 2.4 上下キーの使い道

### 2.4.1

c-quick mode において、㊀から㊁に移動するにはどうしたらいいのか？
* まず、HOMEキーで㊂に移動します。(M-x move-beginning-of-line)
* 行頭では(横スライドでなく)上下キーが正常に動作しますから上キーで㊃まで移動します。
* 次に、右キーで行頭の空白をスキップして、
* 下キーの横スライドで㊁に入ります。

但し、S式の幅で位置づけるのではなければ F9 をいったん押して、non-c-quick mode に戻すのもありです。

```
(defun c-quick-forward-sexp ()
  (interactive)
  (cond
㊃ (㊁(eobp) (c-quick-ding))
   ((c-quick-within-string (point)) (c-quick-forward-within-string))
   ((looking-at "\\s)") (c-quick-ding))
   ((looking-at "\\s.")
    (forward-char))
   ((looking-at "\\s-*\\s<")
    (let ((opoint (point)))
      (forward-line)
      (while (looking-at "\\s-*\\s<")
        (setq opoint (point))
        (forward-line))
㊂    (goto-char (max opoint (save-excursion ㊀(beginning-of-line) (point))))))
   ((looking-at "\\s-") (while (looking-at "\\s-") (forward-char)))
   ((looking-at "\n")
    (let ((bol? (bolp)))
      (forward-char)
      (when bol?
        (while (and (bolp) (looking-at "\n"))
          (forward-char)))))
   (t (ignore-errors (forward-sexp)))))
```

### 2.4.2

c-quick mode における上下キーで一段下に入る例は示しましたが、
㊀にある場合に上キーで括弧の外に出る、また㊁にある場合に下キーで括弧の外に出るということにも使えます。

```
(defun add2 (a b) (㊀+ a b㊁))
```

## 3. S式の幅でのコピー、切り取り、削除

c-quick.el がロードされている場合には、M-w、C-w、C-delete が以下のような動作となります。

* マークを設定してリージョンが有効な場合には、リージョンをコピー(M-w (Alt-w))、リージョンを切り取り(C-w)、リージョンを削除(C-delete)となります。
* リージョンが設定されてない場合には、現在位置にマークを設定し、Ctrl-right で移動した場所までをリージョンとし、リージョンをコピー(M-w (Alt-w))、リージョンを切り取り(C-w)、リージョンを削除(C-delete)となります。

下図で㊀にカーソルがあり、リージョンが設定されてない(マークが設定されてない)場合、㊀～㊁までが、コピー／切り取り／削除されます。

```
(defun add2 (a b) ㊀(+ a b)㊁)
```

下図で㊀にカーソルがあり、リージョンが設定されてない(マークが設定されてない)場合、M-w (Alt-w) を3回押すと㊀～㊁までが、コピーされます。(連続で使えます。切り取り・削除も同様です)

```
(defun add2 ㊀(a b) (+ a b)㊁)
```

## 4. カーソル下のLispの関数(名の)定義へのジャンプ

すでに、ロード済みの関数であれば F12 キーで別バッファに関数定義が(.elファイルが開かれて)位置づけられます。
これは結構便利です。もちろん自分が開発している関数に対しても有効です。
C言語で書かれたLispルーチンや、ネイティブコンパイルされたLispルーチンに対してはヘルプ画面が開かれます。

# 最後に

もうちょっと機能があるのですが、カーソル移動とあまり関係がない機能でもありますので別記事でご紹介したいと思います。

https://qiita.com/javacommons/items/87f7c1f12fac5eedb152

https://qiita.com/javacommons/items/c4e85585604d850370b6

----
何かお気づきの点がございましたら、コメント等で教えていただけると助かります。