The only way I found to change margins in emacs to my liking without things acting funny is this:
(add-hook 'window-configuration-change-hook
(lambda ()
(set-window-margins (car (get-buffer-window-list (current-buffer) nil t)) 24 24)))
I would like for this setting to be invoked only in text-mode and change back when I change to other modes. Somewhat naively I tried this:
(add-hook 'text-mode-hook
(lambda ()
(set-window-margins (car (get-buffer-window-list (current-buffer) nil t)) 24 24)))
But it's not working. What would be the right code to have the margins only change for buffers in text-mode?
Even though you can set the margins using set-window-margins
, they are lost as soon as you change the window in any way. A better solution is to set the variables left-margin-width
and right-margin-width
. For example:
(defun my-set-margins ()
"Set margins in current buffer."
(setq left-margin-width 24)
(setq right-margin-width 24))
(add-hook 'text-mode-hook 'my-set-margins)
Here's some code to center your markdown and text files within 80 characters. This adjusts the margins for all your frames automatically.
;; Add left and right margins, when file is markdown or text.
(defun center-window (window) ""
(let* ((current-extension (file-name-extension (or (buffer-file-name) "foo.unknown")))
(max-text-width 80)
(margin (max 0 (/ (- (window-width window) max-text-width) 2))))
(if (and (not (string= current-extension "md"))
(not (string= current-extension "txt")))
;; Do nothing if this isn't an .md or .txt file.
()
(set-window-margins window margin margin))))
;; Adjust margins of all windows.
(defun center-windows () ""
(walk-windows (lambda (window) (center-window window)) nil 1))
;; Listen to window changes.
(add-hook 'window-configuration-change-hook 'center-windows)
How about something like this? Your problem likely stems from the fact that many major modes inherit text-mode
. You can either eliminate your window-configuration-change-hook
, or you can use your new function major-briggs
with it -- personally I'd just use the text-mode-hook
with the major-briggs
function.
(add-hook 'text-mode-hook (lambda ()
(major-briggs)
;; insert additional stuff if so desired
))
(defun major-briggs ()
(when (eq major-mode 'text-mode)
(set-window-margins
(car (get-buffer-window-list (current-buffer) nil t)) 24 24) ))
With the following code:
(defvar-local my-text-width nil
"Text area width for current buffer, or nil if no attention needed.")
(put 'my-text-width 'safe-local-variable #'integerp)
(defun my--margin-setup ()
"Handle settings of `my-text-width'."
(walk-windows
(lambda (window)
(with-current-buffer (window-buffer window)
(let ((margin (and my-text-width
(/ (max 0 (- (window-total-width)
my-text-width))
2))))
(when (or (not (equal margin left-margin-width))
(not (equal margin right-margin-width)))
(setq left-margin-width margin)
(setq right-margin-width margin)
(set-window-buffer window (current-buffer))))))))
(add-hook 'window-configuration-change-hook #'my--margin-setup)
You can set my-text-width
in a file-local or directory-local variable, and Emacs will automatically set the margins accordingly to get that text width. It works even when you resize the frame or introduce splits.