改造Emacs GDB除錯的多視窗布局

2021-06-22 15:43:42 字數 4027 閱讀 5254

**:

emacs支援多視窗的gdb除錯,要開啟gdb的多視窗模式只需要設定emacs全域性變數gdb-many-windows 為true。

但預設的多視窗感覺並不夠用,沒有彙編視窗,在學習一些語言底層實現的時候有時還需要看看彙編和暫存器內容。

研究emacs的gbd ui指令碼發現emacs的gdb多視窗布局不是定義在配置檔案,而是固化在程式中實現的。

這裡寫了個函式改造了一下視窗布局,下面**在linux下應該放入.emacs檔案,如果window下則放入_emacs檔案。

該函式註冊成乙個切面函式,會在emacs構建gdb的多視窗結束時被呼叫,額外再建立出幾個視窗,用來顯示彙編、記憶體和暫存器。

lisp**  

;;啟動gdb-many-windows時載入的鉤子函式,改變many-windows的預設布局,這個鉤子函式不能勾在gdb-setup-windows,因為此時assamble-buffer還沒完成初始化,不能set到window  

(defadvice gdb-frame-handler-1 (after activate)  

(if gdb-use-separate-io-buffer  

(advice_separate_io)  

(advice_no_separate_io)))  

;;生成沒有單獨io視窗的gdb布局  

(defun advice_no_separate_io()  

;;預設的生成gdb-assembler-buffer的函式本身也會設計呼叫gdb-frame-handler-1,加入此條件發生避免無限遞迴呼叫  

(if (not (gdb-get-buffer 'gdb-assembler-buffer))  

(progn  

(shrink-window-horizontally ( / (window-width) 3))  

(other-window 1)  

(split-window-horizontally)  

(other-window 1)  

(gdb-set-window-buffer (gdb-stack-buffer-name))  

(other-window 1)  

(split-window-horizontally)  

(other-window 1)  

(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-assembler-buffer))  

(split-window-horizontally  (/ ( * (window-width) 2) 3))  

(other-window 1)  

(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-registers-buffer))  

(other-window 1)  

(toggle-current-window-dedication)  

(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-memory-buffer))  

(toggle-current-window-dedication)  

(other-window 2)  

)))  

;;生成有單獨io視窗的gdb布局  

(defun advice_separate_io()  

;;預設的生成gdb-assembler-buffer的函式本身也會設計呼叫gdb-frame-handler-1,加入此條件發生避免無限遞迴呼叫  

(if (not (gdb-get-buffer 'gdb-assembler-buffer))  

(progn  

(split-window-horizontally)  

(enlarge-window-horizontally ( / (window-width) 3))  

(other-window 1)  

;;此處不能使用(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-inferior-io))代替,  

;;因為在開啟gdb-use-separate-io-buffer的狀態時,它還會額外呼叫一些函式將gdb的input,output定位到該buffer  

(gdb-set-window-buffer (gdb-inferior-io-name))  

(other-window 1)  

(split-window-horizontally)  

(other-window 1)  

(gdb-set-window-buffer (gdb-stack-buffer-name))  

(other-window 1)  

(other-window 1)  

(toggle-current-window-dedication)  

(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-assembler-buffer))  

(toggle-current-window-dedication)  

(split-window-horizontally  (/ ( * (window-width) 2) 3))  

(other-window 1)  

(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-registers-buffer))  

(other-window 1)  

(toggle-current-window-dedication)  

(gdb-set-window-buffer (gdb-get-buffer-create 'gdb-memory-buffer))  

(toggle-current-window-dedication)  

(other-window 2)  

)))  

語句defadvice gdb-frame-handler-1 (after activate) 這裡定義了乙個切面函式,和spring中切面函式一樣,lisp中的切面函式也可以在pre,post,around三種模式下被呼叫,這裡after activate相當於是post,即該函式會在函式gdb-frame-handler-1被呼叫完畢後才被呼叫。

gdb的多視窗有兩種模式,一種是程式的標準輸入輸出和gdb自身命令的輸入輸出會在分離的兩個視窗顯示,另一種則是程式輸入輸出都會在gdb命令列中一起輸出,具體區別看圖就知道了。

下面是分離出程式io的多視窗模式:

下面是沒有分離io的多視窗模式:

啟用分離io模式的多視窗除錯可以通過在.emacs/_emacs檔案中新增:

(setq gdb-use-separate-io-buffer 1)

該語句作用是定義變數gdb-use-separate-io-buffer為非空。

如果要不單獨分離出程式io的視窗模式,則可以注釋掉上面的語句,或者設定成:

(setq gdb-use-separate-io-buffer nil)

已知的問題:

如果該函式是在ecb已經被activate的情況下被呼叫(即在ecb環境下啟動gdb)會出錯。

原因應該是ecb預設的起始視窗不同,導致我**中的(other-window 1)焦點會移動到錯位的視窗上從而引發錯誤。可以通過在這段**啟動階段增加重定位視窗焦點來解決,不過因為暫時還用不著ecb並且視窗函式也不熟,先不花力氣了,有興趣的人可以自己嘗試。

下面也是要注意的問題,但是來自emacs

1.input/output視窗需要在程式執行後用滑鼠滾動一下,或者按up鍵,才能顯示出程式輸出的內容,不過這應該是emacs實現的問題,預設emacs也是這種情況(似乎和字型大小和解析度都相關,在我筆記本上11號consolas字型就正常,而同樣配置在台式電腦會出現這個問題)

2.emacs視窗在反覆最大化和視窗化過程中,視窗大小的相對比例會逐漸改變,每個水平、豎直方向的視窗大小都會慢慢變一致,水平分割的視窗平分寬度,垂直劃分的視窗平分高度。不過同樣這也是emacs的問題。

多視窗的顯示

在進銷存軟體中經常會用到輸入貨品資訊,查詢相關報表等資料.按以往的程式,我全部是採用的showmodal模式,這樣就極不方便,必須關閉了這個視窗後,才可以開啟另乙個視窗。於是想使用多個視窗同時顯示在螢幕上,可以點選視窗切換。按常規換成了show模式,結果一測試,發現乙個視窗出現了,另乙個視窗就沒有了...

vim多視窗操作 建立新的視窗

vim中,預設的多視窗開啟,是橫向分割視窗。1 new 命令 new 新建乙個未命名視窗 new name 新建乙個名為name的視窗 2 split命令 橫向分割視窗 split name 在當前位置開啟name視窗 將原來檔案向下移動 sp name 是split的縮寫 與split功能相同 如...

vim改變多視窗的大小

vim改變視窗大小 window resize ctrl w ctrl w 使得所有視窗 幾乎 等寬 等高,但當前視窗使用 winheight 和 winwidth res ize n res resize ctrl w ctrl w 使得當前視窗高度減 n 預設值是 1 如果在 vertical ...