8

我在 Emacs 24 中使用 GDB 并gdb-many-windows设置为t,通常在它自己的框架中。我喜欢有一个单独的编辑框。它看起来像这样(为我粗略的 ASCII 图道歉):

+-------------+-------------+
| gdb         | locals      |
+-------------+-------------+
| source      | I/O         |
|             |             |
+-------------+-------------+
| stack       | breakpoints |
+-------------+-------------+

这工作得很好,除了一个大问题。每当 gdb 需要显示不同的源缓冲区时,例如,在 up/down/step 之后,它并不总是在“源”窗口中显示它。例如,如果我在不同框架的窗口中打开了相同的缓冲区,它将提升该框架,同时将键盘焦点保持在 gdb 框架中。当框架相互覆盖时,这在单显示器设置中真的很烦人。

我希望 gdb 始终使用 gdb-many-windows 设置中的源窗口来显示源,无论是否在其他地方显示相同的源缓冲区。我怎样才能做到这一点?


编辑:更详细的复制说明。我将 Emacs 24.2.1 与 GDB 7.5-ubuntu 一起使用。我在 Ubuntu 10.04 和带有 Cinnamon 的 Linux Mint Nadia 上看到了这个问题。

  • 评估这个表达式:(setq gdb-many-windows t)
  • 用至少两个文件编译一个 C 程序。

例如:

// foo.c
void bar(int);
void foo(int c) {
  if (c > 0)
    bar(c - 1);
}
int main(void) {
  foo(100);
  return 0;
}

// bar.c
void foo(int c);
void bar(int c) {
  if (c > 0)
    foo(c - 2);
}

// compile with gcc -g -O0 foo.c bar.c -o test
  • 让 bar.c 显示在主框架中。用 . 打开一个新框架M-x 5 2。在该框架中,使用M-x gdb. 如上所示,该框架中应该有六个窗口。将 gdb 框架放在源框架的顶部。
  • 设置断点main并逐步调用foobar。当bar被调用时,主框架将被提升到 gdb 框架上,因为 bar.c 已经在那里可见,但键盘焦点将保留在 gdb 框架中。

我认为问题函数gdb-display-source-buffer在 gud.el.gz 中。我打算尝试用 覆盖它defadvice,但我不太熟悉建议。如果我弄明白了,我会在这里发布答案。

4

3 回答 3

2

导致这个问题的函数实际上gud-display-line在 gud.el.gz 中。该函数负责将源窗口中的叠加箭头定位在当前行上,并确保其可见。这是逻辑:

(let* ...
 (window (and buffer
          (or (get-buffer-window buffer)
          (if (eq gud-minor-mode 'gdbmi)
              (or (if (get-buffer-window buffer 'visible)
                  (display-buffer buffer nil 'visible))
              (unless (gdb-display-source-buffer buffer)
                (gdb-display-buffer buffer nil 'visible))))
          (display-buffer buffer))))

我曾经defadvice覆盖整个功能;基本上,我复制了源代码并更改了窗口选择逻辑。

(defadvice gud-display-line (around do-it-better activate)
  (let* ...
     (window (and buffer
                  (or (if (eq gud-minor-mode 'gdbmi)
                          (unless (gdb-display-source-buffer buffer)
                            (gdb-display-buffer buffer nil 'visible)))
                      (get-buffer-window buffer)
                      (display-buffer buffer))))
  ...)

显然不是最优雅的解决方案。切换帧(向上/向下/帧)时它也无济于事,所以当我弄清楚时我会编辑它。

于 2013-12-04T22:15:07.893 回答
1

我有24.3。而且我无法重现此版本的问题。看起来gud-display-line如下:

(defun gud-display-line (true-file line)
  (let* ((last-nonmenu-event t)  ; Prevent use of dialog box for questions.
     (buffer
      (with-current-buffer gud-comint-buffer
        (gud-find-file true-file)))
     (window (and buffer
              (or (get-buffer-window buffer)
              (display-buffer buffer))))
     (pos))
    (when buffer
      (with-current-buffer buffer
    (unless (or (verify-visited-file-modtime buffer) gud-keep-buffer)
      (if (yes-or-no-p
           (format "File %s changed on disk.  Reread from disk? "
               (buffer-name)))
          (revert-buffer t t)
        (setq gud-keep-buffer t)))
    (save-restriction
      (widen)
      (goto-char (point-min))
      (forward-line (1- line))
      (setq pos (point))
      (or gud-overlay-arrow-position
          (setq gud-overlay-arrow-position (make-marker)))
      (set-marker gud-overlay-arrow-position (point) (current-buffer))
      ;; If they turned on hl-line, move the hl-line highlight to
      ;; the arrow's line.
      (when (featurep 'hl-line)
        (cond
         (global-hl-line-mode
          (global-hl-line-highlight))
         ((and hl-line-mode hl-line-sticky-flag)
          (hl-line-highlight)))))
    (cond ((or (< pos (point-min)) (> pos (point-max)))
           (widen)
           (goto-char pos))))
      (when window
    (set-window-point window gud-overlay-arrow-position)
    (if (eq gud-minor-mode 'gdbmi)
        (setq gdb-source-window window))))))

设置和你的window完全不同。也许,上面的代码很有帮助,或者你应该升级到新的 gud/gdb 东西。

于 2013-12-04T22:31:09.240 回答
-1

我运行 Emacs 24.5,对我来说这仍然是一个问题。我现在使用专用窗口手动管理我的窗口,主要具有以下功能:

(defun gdb-restore-windows-gud-io-and-source ()
  "Restore GUD buffer, IO buffer and source buffer next to each other."
  (interactive)
  ;; Select dedicated GUD buffer.
  (switch-to-buffer gud-comint-buffer)
  (delete-other-windows)
  (set-window-dedicated-p (get-buffer-window) t)
  (when (or gud-last-last-frame gdb-show-main)
    (let ((side-win (split-window nil nil t))
          (bottom-win (split-window)))
      ;; Put source to the right.
      (set-window-buffer
       side-win
       (if gud-last-last-frame
           (gud-find-file (car gud-last-last-frame))
         (gud-find-file gdb-main-file)))
      (setq gdb-source-window side-win)
      ;; Show dedicated IO buffer at the bottom.
      (set-window-buffer
       bottom-win
       (gdb-get-buffer-create 'gdb-inferior-io))
      (set-window-dedicated-p bottom-win t))))

这会在左上角显示 GUD 窗口,在左下角显示 IO 缓冲区,并将源缓冲区设置在右侧。GUD 和 IO 缓冲区设置为专用。

于 2015-06-01T11:15:11.660 回答