2025-12-13

Edebugチートシート

デバッグの準備

  • 関数内で C-u C-M-x
  • M-x edebug-all-defs を実行した上で eval-buffer, eval-region, eval-defun
  • M-x edebug-all-forms を実行した上で eval-buffer, eval-region を使うと(範囲内にある)定義以外のフォームもデバッグする
  • M-x edebug-eval-top-level-form を使うとポイントがある場所(直後またはフォーム内であればそのトップレベル)のフォームをデバッグする

(参考: Instrumenting)

ストップポイント

(defun fun (a b)
  .(if .(< a. b.).
      .(insert .(format "%s %s %s" '(1 2 3) [1 2 3] .`(1 2 ,.(+ a. b.).).).).
    .(fun b. a.).).)

要するにリストの前後と変数参照の後。リテラル的な物は除く。

(参考:Using Edebug)

コマンド一覧

分類 キー コマンド 説明
ポイントの移動 w edebug-where 現在のストップポイントへポイントを移動する
  B edebug-next-breakpoint 次のブレークポイントがある位置へポイントを移動する(関数内で循環移動)
実行モード S edebug-stop どこかのストップポイントで止める
  SPC edebug-step-mode 次のストップポイントまで進んで止める
  n edebug-next-mode 式の後にあるストップポイントまで進んで止める(式の前にあるストップポイントでは止まらない)
  g edebug-go-mode 次のブレークポイントまで進んで止める
  G edebug-Go-nonstop-mode ブレークポイントを無視して進む
  t edebug-trace-mode ストップポイント毎に1秒停止しながら進む
  T edebug-Trace-fast-mode ストップポイント毎に表示を更新しながら進む
  c edebug-continue-mode ブレークポイント毎に1秒停止しながら進む
  C edebug-Continue-fast-mode ブレークポイント毎に表示を更新しながら進む
  C-x C-a RET edebug-set-initial-mode 最初の実行モードを設定する
指定位置まで実行 h edebug-goto-here ポイントがある場所まで進む
  f edebug-forward-sexp ポイントから 式一つ分(もしくはprefix指定数)先まで進む (現在のストップポイントからではない)
  o edebug-step-out ポイントを包む フォームの直後まで進む
  i edebug-step-in ポイントの直後 の式が関数またはマクロ呼び出しの場合、その呼び出し先に入る(引数の評価は飛ばす)
デバッグの準備 I edebug-instrument-callee ポイントの直後の式が関数またはマクロ呼び出しの場合、その呼び出し先をデバッグ可能にする
脱出 q top-level quitする。途中ハンドラでデバッグに入る
  Q edebug-top-level-nonstop quitする。ハンドラがあってもデバッグに入らない
  a / C-] abort-recursive-edit 再帰編集を1段階戻る
ブレークポイント b edebug-set-breakpoint ポイントの場所にブレークポイントを設定する(prefix付きで一時的)
  C-c C-t (edebug-set-breakpoint t) ポイントの場所にブレークポイントを一時的に設定する
  u edebug-unset-breakpoint ポイントの場所のブレークポイントを解除する
  U edebug-unset-breakpoints 現在のフォーム内の全てのブレークポイントを解除する
  x edebug-set-conditional-breakpoint 条件付きブレークポイントを設定する
  D edebug-toggle-disable-breakpoint ブレークポイントの無効化状態をトグルする
ブレーク条件 X edebug-set-global-break-condition 場所に関係なく成立したら止まる条件を設定する
情報の表示 r edebug-previous-result 直前の式の評価結果を表示する
  d edebug-pop-to-backtrace バックトレースを表示する
  \= edebug-temp-display-freq-count 通過回数を一時的に表示する
  \= edebug-display-freq-count 通過回数を表示(挿入)する
  ? edebug-help ヘルプを表示する
  p edebug-bounce-point 一時的(1秒間)に実行中のカレントバッファのポイント位置を表示する
評価 e edebug-eval-expression ミニバッファから式を入力して評価する
  C-x C-e edebug-eval-last-sexp ポイントの直前の式を評価する
  E edebug-visit-eval-list 評価リストバッファを開く
画面構成 v edebug-view-outside edebugではないウィンドウ構成に切り替える(C-x X wで戻る)
  P edebug-view-outside  
  W edebug-toggle-save-windows  

Tips:

  • iを使うと引数の評価を飛ばしてしまう。それが嫌ならばIを押してからステップ実行する。一度関数をデバッグ対象にしてしまえば次からは何もしなくても中に入る。中に入りたくない場合はf、o、hを使う。nではダメ。hがあれば他要らなくね?

練習

前進:

;; (scratchバッファ上を想定)
(defun my-callee-function (a b)
  (message "a=%s b=%s" a b))

;; ↓ここで C-u C-M-x または M-x edebug-eval-top-level-form
(let (a b c d)
  ;; ■ここにいた場合
  (my-callee-function ;; ←i(関数の中)
   ;; ↓SPC (最初のストップポイント)
   (cons a ;; ←n(最初の後方ストップポイント)
         b)
   (cons c d) ) ;; ←f(my-callee-functionを呼び出す式の直後)
  (list a b c d) ) ;; ←o(let式の直後)

無限ループ:

(defun my-edebug-practice-infinite-loop ()
  (let ((count 0)
        (end nil)) ;; この変数を書き替えられれば無限ループを脱出できるのだが……
    (unwind-protect
        ;; 無限ループはt、T、c、C、g、Gの効果を試すのにうってつけ。
        ;; Sで停止。b、C-u b、u、U、x、Dでブレークポイント操作。
        (while (not end)
          ;; 1行進む。進めなかったらバッファの先頭に移動。
          (unless (zerop (forward-line))
            (goto-char (point-min)))
          ;; pを押すと今ポイントがどこに進んだかが分かる(1秒間)。
          (cl-incf count))
      ;; ループ中qを押すとここに来る。Qでは来ない。
      (message "count=%s" count)))) ;;←ここでC-u C-M-x

;; (my-edebug-practice-infinite-loop) ;;←ここでC-x C-e