设置了 margin-width 后, 会导致company-posframe也出现margin

我希望给 org-mode 加上margin, 这样org的一行的内容就不至于太长. 但是不知道为什么, company弹出的posframe的样式被影响了, 两边出现了多余的margin, 如下图:

有大佬可以帮忙定位一下原因吗?

相关配置代码如下

    (defvar-local my-text-width nil)
    (add-hook 'org-mode-hook (lambda ()
                               (setq-local my-text-width 80) 
                               
                               (let ((margin (and my-text-width
                                                  (/ (max 0 (- (frame-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)))
                               (display-line-numbers-mode -1)
                               (set-face-attribute 'fringe nil
                                                   :background "#000000")))

我自己尝试定位了一下, 但是失败了, 下面是一下尝试, 希望对愿意帮忙的大佬有帮助:

  1. 尝试先进入别的mode(如随便打开一个 .el 文件), 然后再进入org-mode, 问题消失;
  2. 尝试在org-mode中手动创建pos-frame, 新建的posframe无多余margin, 如下图:

感觉可能是一个 x-y problem。

有一个包可以实现你想要的效果:visual-fill-columnwriteroom-mode 这个包内部也是调用的 visual-fill-column

效果如下:

1 个赞

非常非常感谢!我一会试一下

我用的是 olivetti ,推荐

1 个赞

我最后用这个方案解决了, 非常感谢! 说一下我仍然疑惑的地方, 我看 visual-fill-column 这个库也是通过设置 margin 来实现的, 但是他是通过调用 set-window-margins 设置的margin, 我自己尝试把我配置中的相关设置替换成 set-window-margins 后margin又不见了 :face_exhaling:

不过问题解决我已经很满意了, 再次感谢大佬的帮助!

试了一下, 确实也可以达到相同的效果, 感谢懒猫大神!

1 个赞

因为使用 set-window-margins 设置的margin不能持久保持,当window中的buffer改变时,margin就会被覆盖,原因可以看 set-window-margins 的文档里有这么一段:

The margins specified by calling this function may be later overridden
by invoking ‘set-window-buffer’ for the same WINDOW, with its
KEEP-MARGINS argument nil or omitted.

我自己写了一个简易的 margin-mode 可以实现 margin 的持久保持:

(defvar margin-width 2)

(defcustom margin-work-modes
  '(org-mode markdown-mode)
  "Major modes that would work.")

(defun margin-mode-work-p (&optional buffer)
  (seq-some (lambda (mode)
              (eq mode (buffer-major-mode buffer)))
            margin-work-modes))

(defun margin-preserve ()
  "Preserve pages' window margin."
  (dolist (window (window-list))
    (when (margin-mode-work-p (window-buffer window))
      (set-window-margins window margin-width margin-width))))

(defun margin-restore ()
  (dolist (window (window-list))
    (when (margin-mode-work-p (window-buffer window))
      (set-window-margins window 0 0))))

(defun margin-after-change-major-mode ()
  (unless (minibufferp)
    ;; 排除光标切换到 minibuffer 时也会触发这个 hook 的情况
    (if (margin-mode-work-p)
        (set-window-margins (selected-window) margin-width margin-width)
      (set-window-margins (selected-window) 0 0))))

(define-minor-mode margin-mode
  "Minor mode for preserving windows margins."
  :lighter " Margin"
  :init-value nil
  :keymap nil
  :global t
  (if margin-mode
      (progn
        (margin-preserve)
        (add-hook 'after-change-major-mode-hook
                  'margin-after-change-major-mode)
        (add-hook 'window-configuration-change-hook 'margin-preserve))
    (margin-restore)
    (remove-hook 'after-change-major-mode-hook
                 'margin-after-change-major-mode)
    (remove-hook 'window-configuration-change-hook 'margin-preserve)))

(provide 'margin-mode)