[emacs] [gdb customization]如何在一个窗口中显示源缓冲区?

时间:2016-09-29 06:23:17

标签: debugging emacs gdb customization

我在emacs中定制了gdb窗口。在调试之后,新的源代码在不同的窗口中打开。我想在一个窗口中看到源代码。我的gdb自定义是:

;     _____________________________________________________________________________________
;    |                                          |                                          |
;    |              BREAKPOINTS                 |                                          |
;    |__________________________________________|                                          |
;    |                                          |                                          |
;    |                 STACK                    |                                          |
;    |__________________________________________|                                          |
;    |                                          |                                          |
;    |                                          |                                          |
;    |                 LOCALS                   |                                          |
;    |                                          |                SOURCE CODE               |
;    |__________________________________________|                                          |
;    |                                          |                                          |
;    |                                          |                                          |
;    |                                          |                                          |
;    |                                          |                                          |
;    |                                          |                                          |
;    |                                          |                                          |
;    |                  GDB                     |                                          |
;    |                                          |__________________________________________|
;    |                                          |                                          |
;    |                                          |                                          |
;    |                                          |                    I/O                   |
;    |                                          |                                          |
;    |__________________________________________|__________________________________________|

(require 'gud)

; invoke
(global-set-key [f8] 'gdb)

; GDB layout
(defadvice gdb-setup-windows (after activate)
  (gdb-setup-my-windows)
)

(defun gdb-setup-my-windows ()
  (set-window-dedicated-p (selected-window) nil)
  (switch-to-buffer gud-comint-buffer)
  (delete-other-windows)
  (let
    ((win0 (selected-window))             ; breakpoints
     (win1 (split-window-horizontally
         (floor (* 0.5 (window-width)))))   ; source + i/o
     (win2 (split-window-vertically
         (floor (* 0.5 (window-body-height))))) ; gdb
     (win3 (split-window-vertically
        (floor (* 0.5 (window-body-height))))) ; locals
     (win4 (split-window-vertically
         (floor (* 0.6 (window-body-height))))) ; stack
    )
    (select-window win1)
    ; configurating right window
    (let
    ((winSrc (selected-window)) ; source
     (winIO (split-window-vertically (floor (* 0.9 (window-body-height))))) ; I/O
     )
      (set-window-buffer winIO (gdb-get-buffer-create 'gdb-inferior-io))
      (set-window-buffer
    winSrc
    (if gud-last-last-frame
     (gud-find-file (car gud-last-last-frame))
      (if gdb-main-file
       (gud-find-file gdb-main-file)
     (list-buffers-noselect))))
      (setq gdb-source-window winSrc)
      (set-window-dedicated-p winIO t)
   )

    (set-window-buffer win0 (gdb-get-buffer-create 'gdb-breakpoints-buffer))
    (set-window-buffer win3 (gdb-get-buffer-create 'gdb-locals-buffer))
    (set-window-buffer win4 (gdb-get-buffer-create 'gdb-stack-buffer))
    (select-window win2)
  )
)

; GDB variables
(setq gdb-many-windows t)
(setq gdb-show-main t)
(setq gdb-show-changed-values t)
(setq gdb-use-colon-colon-notation t)
(setq gdb-use-separate-io-buffer nil)
(setq gdb-delete-out-of-scope t)
(setq gdb-speedbar-auto-raise t)

主屏幕是: gdb screen after start

但是当我开始调试时,下一个源文件会在另一个窗口中打开。见下面的例子: New source code in gdb window

复制的应用示例是:

的main.cpp

#include "classB.h"

int main()
{
  B *b = 0;
  b = new B();
  return 0;
}

classA.h

#ifndef CLASS_A_H
#define CLASS_A_H

class A
{
public:
  A();
};

#endif

classA.cpp

#include "classA.h"
#include <iostream>

A::A()
{
  std::cout << "Constructor A" << std::endl;
}

classB.h

#ifndef CLASS_B_H
#define CLASS_B_H

#include "classA.h"

class B : public A
{
public:
  B();
};

#endif

classB.cpp

#include "classB.h"
#include <iostream>

B::B() : A()
{
  std::cout << "Constructor B" << std::endl;
}

生成文件

SOURCES=main.cpp classA.cpp classB.cpp
TARGET=test
CXX_FLAGS=-g

.PHONY: all

all: $(TARGET)

$(TARGET): $(SOURCES)
    $(CXX) $(CXX_FLAGS) $^ -o $@

.PHONY: clean

clean:
    rm -vf $(TARGET)

重现步骤:

  1. 运行emacs

  2. M-x gdb

  3. gdb -i = mi test

  4. 在gdb命令窗口中运行:start

  5. 运行:下一步

  6. 运行:步骤

  7. 我的环境是:Ubuntu14.04,gdb - 7.7.1,emacs - 25.1.1。

    我尝试使用 set-window-dedicated-p 。但这不是我的问题的解决方案。 我是emacs的新手,请帮帮我,我的配置有什么问题?

2 个答案:

答案 0 :(得分:0)

display-buffer-alist可让您控制在哪些窗口中显示新缓冲区。首先在其中注册一个函数指针

(add-to-list 'display-buffer-alist
         (cons 'cdb-source-code-buffer-p
           (cons 'display-source-code-buffer nil)))

然后实现选择窗口的功能,例如

(defun cdb-source-code-buffer-p (bufName action)
  "Return whether BUFNAME is a source code buffer."
  (let ((buf (get-buffer bufName)))
    (and buf
     (with-current-buffer buf
       (derived-mode-p buf 'c++-mode 'c-mode 'csharp-mode 'nxml-mode)))))

(defun display-source-code-buffer (sourceBuf alist)
  "Find a window with source code and set sourceBuf inside it."
  (let* ((curbuf (current-buffer))
     (wincurbuf (get-buffer-window curbuf))
     (win (if (and wincurbuf
               (derived-mode-p sourceBuf 'c++-mode 'c-mode 'nxml-mode)
               (derived-mode-p (current-buffer) 'c++-mode 'c-mode 'nxml-mode))
          wincurbuf
        (get-window-with-predicate
         (lambda (window)
           (let ((bufName (buffer-name (window-buffer window))))
             (or (cdb-source-code-buffer-p bufName nil)
             (assoc bufName display-buffer-alist)
             ))))))) ;; derived-mode-p doesn't work inside this, don't know why...
    (set-window-buffer win sourceBuf)
    win))

cdb-source-code-buffer-p选择调用display-source-code-buffer的源代码缓冲区,返回所需的窗口。

答案 1 :(得分:0)

这是一个对我有用的简单版本。它利用了默认情况下专用于GUD窗口和IO窗口的事实。因此,只需向现有窗口请求显示缓冲区就足够了(因为只有一个选择可用)。

;; Ensure that all source files are opened in the same window when gdb                                                                                                  
;; is running.                                                                                                                                                          
(add-to-list 'display-buffer-alist
         (cons 'gdb-source-code-buffer-p
           (cons 'display-buffer-use-some-window nil)))

(defun gdb-source-code-buffer-p (bufName action)
  "Return whether BUFNAME is a source code buffer and gdb is running."
  (let ((buf (get-buffer bufName)))
    (and buf
         (eq gud-minor-mode 'gdbmi)
         (with-current-buffer buf
           (derived-mode-p buf 'c++-mode 'c-mode)))))