Emacs/GDB: всегда отображать источник в определенном окне с помощью gdb-many-windows

Я использую GDB в Emacs 24 с gdb-many-windows установлен в t, как правило, в своем собственном кадре. Мне нравится иметь отдельную рамку для редактирования. Это выглядит так (извиняюсь за мою грубую диаграмму ASCII):

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

Это работает довольно хорошо, за исключением одной большой проблемы. Всякий раз, когда GDB необходимо отобразить другой исходный буфер, например, после up / down / step, он не всегда показывает его в окне "source". Например, если у меня один и тот же буфер открыт в окне в другом кадре, он будет поднимать этот кадр, сохраняя фокус клавиатуры в кадре GDB. Это действительно раздражает при настройке одного монитора, когда кадры закрывают друг друга.

Я бы хотел, чтобы gdb всегда использовал исходное окно в настройке gdb-many-windows для отображения источника, независимо от того, отображается ли в другом месте тот же самый буфер источника. Как я могу это сделать?


РЕДАКТИРОВАТЬ: более подробные инструкции по воспроизведению. Я использую Emacs 24.2.1 с GDB 7.5-Ubuntu. Я видел эту проблему в Ubuntu 10.04 и Linux Mint Nadia с Cinnamon.

  • Оцените это выражение: (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, В этом кадре начните GDB с M-x gdb, В этом кадре должно быть шесть окон, как показано выше. Поместите кадр GDB поверх исходного кадра.
  • Установить точку останова в main и шаг за шагом foo а также bar, когда bar называется, основной кадр будет поднят над кадром GDB, так как там уже виден bar.c, но фокус клавиатуры останется в кадре GDB.

Я думаю, что проблема функции gdb-display-source-buffer в gud.el.gz. Я планирую переопределить это с defadvice, но я не очень знаком с советами. Если я это выясню, я отправлю ответ здесь.

3 ответа

Решение

У меня 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.

Функция, вызывающая эту проблему на самом деле 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))))
  ...)

Очевидно, не самое элегантное решение. Это также не помогает при переключении кадров (с помощью up/down/frame), поэтому я отредактирую это, когда выясню это.

Я использую 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 вверху слева, буфер ввода-вывода внизу слева и устанавливает исходный буфер справа. GUD и буфер ввода-вывода установлены на выделенные.

Другие вопросы по тегам