Skip to content

Commit b5d7b4d

Browse files
committed
Add ghostel-debug-info and resize/redraw logging
ghostel-debug-info: interactive command that dumps Emacs version, system info, native module version (with mismatch warning), terminal state (DEC 2026, pending output, window-start), and settings into *ghostel-debug* for pasting into bug reports. ghostel-debug-start/stop: now also logs resize events (old/new dimensions, timing) and redraw decisions (skip vs execute, DEC 2026 state, force flag, buffer size delta, window-start before/after).
1 parent e1e1896 commit b5d7b4d

1 file changed

Lines changed: 198 additions & 1 deletion

File tree

ghostel-debug.el

Lines changed: 198 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,33 @@
3131
;;; Code:
3232

3333
(require 'cl-lib)
34+
(require 'lisp-mnt)
35+
(require 'ghostel)
36+
37+
(declare-function ghostel--module-version "ghostel-module")
38+
(declare-function ghostel--mode-enabled "ghostel-module")
3439

3540
(defvar ghostel-debug--log-buffer nil
3641
"Buffer used for ghostel debug logging.")
3742

43+
;;;###autoload
3844
(defun ghostel-debug-start ()
39-
"Start logging ghostel filter calls to *ghostel-debug* buffer."
45+
"Start logging ghostel events to *ghostel-debug* buffer.
46+
Logs filter calls, key sends, resize events, redraw decisions
47+
\(including DEC 2026 skip/force), and `window-start' anchoring."
4048
(interactive)
4149
(setq ghostel-debug--log-buffer (get-buffer-create "*ghostel-debug*"))
4250
(with-current-buffer ghostel-debug--log-buffer
4351
(erase-buffer)
4452
(insert "=== Ghostel Debug Log ===\n\n"))
53+
;; Data path
4554
(advice-add 'ghostel--filter :before #'ghostel-debug--log-filter)
4655
(advice-add 'ghostel--send-key :before #'ghostel-debug--log-send)
4756
(advice-add 'ghostel--send-encoded :before #'ghostel-debug--log-encoded)
57+
;; Render path
58+
(advice-add 'ghostel--delayed-redraw :around #'ghostel-debug--log-redraw)
59+
(advice-add 'ghostel--window-adjust-process-window-size
60+
:around #'ghostel-debug--log-resize)
4861
(when (fboundp 'ghostel--enable-vt-log)
4962
(ghostel--enable-vt-log))
5063
(message "ghostel-debug: logging started, check *ghostel-debug* buffer"))
@@ -55,6 +68,9 @@
5568
(advice-remove 'ghostel--filter #'ghostel-debug--log-filter)
5669
(advice-remove 'ghostel--send-key #'ghostel-debug--log-send)
5770
(advice-remove 'ghostel--send-encoded #'ghostel-debug--log-encoded)
71+
(advice-remove 'ghostel--delayed-redraw #'ghostel-debug--log-redraw)
72+
(advice-remove 'ghostel--window-adjust-process-window-size
73+
#'ghostel-debug--log-resize)
5874
(when (fboundp 'ghostel--disable-vt-log)
5975
(ghostel--disable-vt-log))
6076
(message "ghostel-debug: logging stopped"))
@@ -103,6 +119,63 @@ _PROC is ignored."
103119
(format-time-string "%T.%3N")
104120
key-name mods utf8)))))
105121

122+
(defun ghostel-debug--log-redraw (orig-fn buffer)
123+
"Log redraw decisions: skip vs execute, DEC 2026 state, timing.
124+
ORIG-FN is `ghostel--delayed-redraw', BUFFER is the target buffer."
125+
(when ghostel-debug--log-buffer
126+
(let (sync force win-start pt buf-size)
127+
(when (buffer-live-p buffer)
128+
(with-current-buffer buffer
129+
(setq sync (and ghostel--term
130+
(ghostel--mode-enabled ghostel--term 2026)))
131+
(setq force ghostel--force-next-redraw)
132+
(setq buf-size (buffer-size))
133+
(setq pt (point))
134+
(let ((win (get-buffer-window buffer)))
135+
(when win
136+
(setq win-start (window-start win))))))
137+
(let ((t0 (current-time)))
138+
(funcall orig-fn buffer)
139+
(let ((elapsed (* 1000 (float-time (time-subtract (current-time) t0))))
140+
pt-after win-start-after buf-size-after)
141+
(when (buffer-live-p buffer)
142+
(with-current-buffer buffer
143+
(setq pt-after (point))
144+
(setq buf-size-after (buffer-size))
145+
(let ((win (get-buffer-window buffer)))
146+
(when win
147+
(setq win-start-after (window-start win))))))
148+
(with-current-buffer ghostel-debug--log-buffer
149+
(goto-char (point-max))
150+
(if (and sync (not force))
151+
(insert (format "[%s] REDRAW: SKIPPED (DEC2026 active, force=nil)\n"
152+
(format-time-string "%T.%3N")))
153+
(insert (format "[%s] REDRAW: %.1fms force=%s dec2026=%s buf=%d%d pt=%d%d wstart=%s%s\n"
154+
(format-time-string "%T.%3N")
155+
elapsed force sync
156+
buf-size buf-size-after
157+
pt pt-after
158+
win-start win-start-after)))))))))
159+
160+
(defun ghostel-debug--log-resize (orig-fn process windows)
161+
"Log resize events with old/new dimensions and timing.
162+
ORIG-FN is `ghostel--window-adjust-process-window-size'.
163+
PROCESS and WINDOWS are passed through."
164+
(let* ((old-rows (when (buffer-live-p (process-buffer process))
165+
(buffer-local-value 'ghostel--term-rows (process-buffer process))))
166+
(t0 (current-time))
167+
(size (funcall orig-fn process windows))
168+
(elapsed (* 1000 (float-time (time-subtract (current-time) t0)))))
169+
(when ghostel-debug--log-buffer
170+
(with-current-buffer ghostel-debug--log-buffer
171+
(goto-char (point-max))
172+
(insert (format "[%s] RESIZE: %sx%s%sx%s (%.1fms)\n"
173+
(format-time-string "%T.%3N")
174+
(and old-rows (cdr size)) old-rows
175+
(car size) (cdr size)
176+
elapsed))))
177+
size))
178+
106179

107180
;;; Typing latency measurement
108181

@@ -221,5 +294,129 @@ The latency breakdown shows:
221294
(insert "\n")))
222295
(message "ghostel-debug: latency report ready in *ghostel-debug*")))
223296

297+
298+
;;; Environment diagnostics
299+
300+
;;;###autoload
301+
(defun ghostel-debug-info ()
302+
"Display diagnostic info about the ghostel environment.
303+
Collects Emacs version, system info, native module state, terminal
304+
state, and settings into *ghostel-debug* for pasting into bug reports."
305+
(interactive)
306+
(let ((out (get-buffer-create "*ghostel-debug*"))
307+
(ghostel-buf (when (derived-mode-p 'ghostel-mode) (current-buffer))))
308+
(with-current-buffer out
309+
(let ((inhibit-read-only t))
310+
(erase-buffer)
311+
(insert "=== ghostel-debug-info ===\n\n")
312+
;; System
313+
(insert "--- System ---\n")
314+
(insert (format "Emacs version: %s\n" emacs-version))
315+
(insert (format "System type: %s\n" system-type))
316+
(insert (format "System config: %s\n" system-configuration))
317+
(insert (format "Window system: %s\n" (or window-system "terminal")))
318+
(when (display-graphic-p)
319+
(insert (format "Display pixel size: %sx%s\n"
320+
(display-pixel-width) (display-pixel-height)))
321+
(insert (format "Char size: %dx%d px\n"
322+
(frame-char-width) (frame-char-height))))
323+
(insert (format "Native comp: %s\n"
324+
(if (and (fboundp 'native-comp-available-p)
325+
(native-comp-available-p))
326+
"yes" "no")))
327+
;; Ghostel versions
328+
(insert "\n--- Ghostel ---\n")
329+
(let* ((lib (locate-library "ghostel"))
330+
(dir (and lib (file-name-directory lib))))
331+
(insert (format "Package version: %s\n"
332+
(condition-case nil
333+
(lm-version (locate-library "ghostel.el" t))
334+
(error "Unknown"))))
335+
(insert (format "Min module version: %s\n" ghostel--minimum-module-version))
336+
(insert (format "Library path: %s\n" (or lib "not found")))
337+
;; Native module
338+
(let ((mod-loaded (fboundp 'ghostel--module-version)))
339+
(insert (format "Module loaded: %s\n" (if mod-loaded "yes" "no")))
340+
(when mod-loaded
341+
(let ((mod-ver (ghostel--module-version)))
342+
(insert (format "Module version: %s\n" mod-ver))
343+
(unless (string= mod-ver ghostel--minimum-module-version)
344+
(insert (format " *** VERSION MISMATCH: elisp expects >= %s, module is %s ***\n"
345+
ghostel--minimum-module-version mod-ver)))))
346+
(when dir
347+
(let ((mod-file (expand-file-name
348+
(concat "ghostel-module" module-file-suffix) dir)))
349+
(if (file-exists-p mod-file)
350+
(let ((attrs (file-attributes mod-file)))
351+
(insert (format "Module file: %s\n" mod-file))
352+
(insert (format "Module size: %s bytes\n"
353+
(file-attribute-size attrs)))
354+
(insert (format "Module modified: %s\n"
355+
(format-time-string
356+
"%Y-%m-%d %H:%M:%S"
357+
(file-attribute-modification-time attrs)))))
358+
(insert (format "Module file: NOT FOUND in %s\n" dir)))))))
359+
;; Terminal state
360+
(insert "\n--- Terminal State ---\n")
361+
(if ghostel-buf
362+
(let (info)
363+
(with-current-buffer ghostel-buf
364+
(setq info
365+
(list :buffer (buffer-name)
366+
:rows ghostel--term-rows
367+
:buf-size (buffer-size)
368+
:buf-lines (count-lines (point-min) (point-max))
369+
:point (point)
370+
:term ghostel--term
371+
:force ghostel--force-next-redraw
372+
:pending (length ghostel--pending-output)
373+
:timer (and ghostel--redraw-timer t)
374+
:copy ghostel--copy-mode-active
375+
:dec2026 (and ghostel--term
376+
(ghostel--mode-enabled ghostel--term 2026))))
377+
(let ((win (get-buffer-window ghostel-buf)))
378+
(when win
379+
(setq info (plist-put info :win-w (window-body-width win)))
380+
(setq info (plist-put info :win-h (window-body-height win)))
381+
(setq info (plist-put info :win-start (window-start win)))
382+
(setq info (plist-put info :win-end (window-end win t))))))
383+
(insert (format "Buffer: %s\n" (plist-get info :buffer)))
384+
(insert (format "Term rows: %s\n" (plist-get info :rows)))
385+
(insert (format "Buffer size: %d chars, %d lines\n"
386+
(plist-get info :buf-size) (plist-get info :buf-lines)))
387+
(insert (format "Point: %d\n" (plist-get info :point)))
388+
(if (plist-get info :win-w)
389+
(progn
390+
(insert (format "Window body: %dx%d (cols x rows)\n"
391+
(plist-get info :win-w) (plist-get info :win-h)))
392+
(insert (format "Window start: %d\n" (plist-get info :win-start)))
393+
(insert (format "Window end: %d\n" (plist-get info :win-end))))
394+
(insert "Window: not displayed\n"))
395+
(if (plist-get info :term)
396+
(progn
397+
(insert (format "DEC 2026 (sync): %s\n"
398+
(if (plist-get info :dec2026) "ACTIVE" "off")))
399+
(insert (format "Force next redraw: %s\n" (plist-get info :force)))
400+
(insert (format "Pending output: %s chunks\n" (plist-get info :pending)))
401+
(insert (format "Redraw timer: %s\n"
402+
(if (plist-get info :timer) "pending" "none")))
403+
(insert (format "Copy mode: %s\n"
404+
(if (plist-get info :copy) "active" "off"))))
405+
(insert "Term handle: nil (no terminal)\n")))
406+
(insert "(not in a ghostel buffer)\n"))
407+
;; Settings
408+
(insert "\n--- Settings ---\n")
409+
(insert (format "timer-delay: %s\n" ghostel-timer-delay))
410+
(insert (format "full-redraw: %s\n" ghostel-full-redraw))
411+
(insert (format "adaptive-fps: %s\n" ghostel-adaptive-fps))
412+
(insert (format "immediate-threshold: %s\n" ghostel-immediate-redraw-threshold))
413+
(insert (format "immediate-interval: %s\n" ghostel-immediate-redraw-interval))
414+
(insert (format "scroll-conservatively: %s\n"
415+
(if ghostel-buf
416+
(buffer-local-value 'scroll-conservatively ghostel-buf)
417+
scroll-conservatively)))))
418+
(display-buffer out)
419+
(message "Debug info written to *ghostel-debug*")))
420+
224421
(provide 'ghostel-debug)
225422
;;; ghostel-debug.el ends here

0 commit comments

Comments
 (0)