Changing margin for emacs text-mode

2019-04-10 09:11发布

问题:

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?

回答1:

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)


回答2:

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)


回答3:

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) ))


回答4:

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.