简体   繁体   English

Emacs / GDB:始终使用gdb-many-windows在特定窗口中显示源

[英]Emacs/GDB: always display source in specific window with gdb-many-windows

I use GDB in Emacs 24 with gdb-many-windows set to t , usually in its own frame. 我在Emacs 24中使用GDB,并将gdb-many-windows设置为t ,通常在其自己的框架中。 I like to have a separate editing frame. 我喜欢有一个单独的编辑框。 It looks like this (apologies for my crude ASCII diagram): 看起来像这样(对我的原始ASCII图表示歉意):

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

This works pretty well except for one big problem. 除一个大问题外,这工作得很好。 Whenever gdb needs to display a different source buffer, eg, after up/down/step, it doesn't always show it in the "source" window. 每当gdb需要显示不同的源缓冲区时,例如,在上/下/步进之后,它并不总是在“源”窗口中显示。 For example, if I have the same buffer open in a window in a different frame, it will raise that frame while keeping keyboard focus in the gdb frame. 例如,如果我在不同框架的窗口中打开了相同的缓冲区,它将在抬起该框架的同时将键盘焦点保持在gdb框架中。 This is really annoying on a single-monitor setup when the frames cover each other. 当框架相互覆盖时,这在单显示器设置上确实很烦人

I'd like gdb to always use the source window in the gdb-many-windows setup to display source, no matter if the same source buffer is displayed elsewhere. 我希望gdb始终使用gdb-many-windows设置中的源窗口来显示源,而不管是否在其他地方显示了相同的源缓冲区。 How can I do that? 我怎样才能做到这一点?


EDIT: More detailed instructions to reproduce. 编辑:更详细的说明进行复制。 I'm using Emacs 24.2.1 with GDB 7.5-ubuntu. 我正在将Emacs 24.2.1与GDB 7.5-ubuntu一起使用。 I've seen this problem on Ubuntu 10.04 and Linux Mint Nadia with Cinnamon. 我已经在Ubuntu 10.04和Linux Mint Nadia和Cinnamon上看到了此问题。

  • Evaluate this expression: (setq gdb-many-windows t) 评估此表达式: (setq gdb-many-windows t)
  • Compile a C program with at least two files. 用至少两个文件编译一个C程序。

For example: 例如:

// 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
  • Let bar.c be displayed in the main frame. 让bar.c显示在主框架中。 Open a new frame with Mx 5 2 . Mx 5 2打开一个新框架。 In that frame, start gdb with Mx gdb . 在该帧中,以Mx gdb启动Mx gdb There should be six windows in that frame as shown above. 如上所示,该框架中应有六个窗口。 Position the gdb frame on top of the source frame. 将gdb框架放置在源框架的顶部。
  • Set a breakpoint in main and step through calls to foo and bar . main设置一个断点,并逐步执行对foobar调用。 When bar is called, the main frame will be raised over the gdb frame since bar.c is already visible there, but keyboard focus will stay in the gdb frame. 调用bar ,由于bar.c已在此处可见,所以主框架将在gdb框架上方升高,但键盘焦点将停留在gdb框架中。

I think the problem function is gdb-display-source-buffer in gud.el.gz. 我认为问题函数是gud.el.gz中的gdb-display-source-buffer I'm planning to try overriding this with defadvice , but I'm not really familiar with advice. 我打算尝试使用defadvice替代它,但是我对建议并不十分熟悉。 If I figure it out, I'll post an answer here. 如果我知道了,我会在这里发布答案。

The function causing this problem is actually gud-display-line in gud.el.gz. 导致此问题的函数实际上是gud.el.gz中的gud-display-line This function is responsible for positioning the overlay arrow in the source window on the current line and making sure it is visible. 此功能负责在当前行的源窗口中放置叠加箭头,并确保其可见。 Here's the logic: 这是逻辑:

(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))))

I used defadvice to override the whole function; 我使用defadvice覆盖了整个功能; basically, I copied the source and changed the window selection logic. 基本上,我复制了源代码并更改了窗口选择逻辑。

(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))))
  ...)

Obviously not the most elegant solution. 显然不是最优雅的解决方案。 It also doesn't help when switching frames (with up/down/frame), so I'll edit this when I figure that out. 当切换帧(带有上/下/帧)时,它也无济于事,所以我一弄清楚就将对其进行编辑。

I have 24.3. 我有24.3。 And I cannot reproduce the problem with this version. 我无法重现此版本的问题。 There gud-display-line looks as follows: 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))))))

The window setting is completely different from yours. window设置与您的完全不同。 Maybe, the above code is helpful or maybe you should upgrade to the new gud/gdb stuff. 也许上面的代码很有帮助,或者您应该升级到新的gud / gdb东西。

I run Emacs 24.5 and for me this is still an issue. 我运行Emacs 24.5,对我来说这仍然是一个问题。 I manage my windows manually with dedicated windows now, mainly with the following function: 我现在使用专用窗口手动管理窗口,主要使用以下功能:

(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))))

This shows the GUD window at the top left, the IO buffer at the bottom left and sets the source buffer to the right side. 这将在左上方显示GUD窗口,在左下方显示IO缓冲区,并将源缓冲区设置在右侧。 The GUD and the IO buffer are set to dedicated. GUD和IO缓冲区设置为专用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM