feat(word-wrap): add soft-wrapping at fill-column

Using visual-fill-column.

Close: #1906
Co-authored-by: flatwhatson <flatwhatson@users.noreply.github.com>~
This commit is contained in:
Henrik Lissner 2022-11-02 16:27:46 +01:00
parent 4e3b94c602
commit 33db882ae6
No known key found for this signature in database
GPG key ID: B60957CA074D39A3
4 changed files with 63 additions and 25 deletions

View file

@ -17,6 +17,7 @@ lines in the buffer without modifying the buffer content.
** Packages ** Packages
- [[doom-package:adaptive-wrap]] - [[doom-package:adaptive-wrap]]
- [[doom-package:visual-fill-column]]
** Hacks ** Hacks
/No hacks documented for this module./ /No hacks documented for this module./
@ -46,8 +47,8 @@ Word wrapping is not enabled by default.
Wrapping can be toggled in the current buffer with ~M-x +word-wrap-mode~. The Wrapping can be toggled in the current buffer with ~M-x +word-wrap-mode~. The
default doom bindings bind this to [[kbd:][SPC t w]] for ~evil~ users. default doom bindings bind this to [[kbd:][SPC t w]] for ~evil~ users.
To enable wrapping in a specific mode, add it to the appropriate hook in your To enable wrapping in a specific mode, add it to the appropriate hook in
~config.el~: ~$DOOMDIR/config.el~:
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; enable word-wrap in C/C++/ObjC/Java ;; enable word-wrap in C/C++/ObjC/Java
(add-hook 'c-mode-common-hook #'+word-wrap-mode) (add-hook 'c-mode-common-hook #'+word-wrap-mode)
@ -55,9 +56,10 @@ To enable wrapping in a specific mode, add it to the appropriate hook in your
To customize the behaviour in a specific mode: To customize the behaviour in a specific mode:
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; use a single indent in json-mode ;; use a single indent and wrap at fill-column in json-mode
(add-hook! 'json-mode-hook (add-hook! 'json-mode-hook
(setq-local +word-wrap-extra-indent 'single) (setq-local +word-wrap-extra-indent 'single
+word-wrap-fill-style 'soft)
(+word-wrap-mode +1)) (+word-wrap-mode +1))
#+end_src #+end_src
@ -86,6 +88,13 @@ The ~+word-wrap-extra-indent~ variable supports the following values:
- a negative integer: dedent by this fixed amount - a negative integer: dedent by this fixed amount
- ~nil~: no extra indent - ~nil~: no extra indent
Long lines are wrapped at the window margin by default, however soft-wrapping at
~fill-column~ is supported by setting ~+word-wrap-fill-style~. When set to
~auto~, if ~auto-fill-mode~ is enabled in the buffer, its behavior will not be
affected. This allows hard and soft wrapping methods to co-exist, with
hard-wrapping for new lines and soft-wrapping for existing lines. To disable
hard-wrapping entirely, set ~+word-wrap-fill-style~ to ~soft~.
This module also includes a global minor-mode ~+global-word-wrap-mode~ to This module also includes a global minor-mode ~+global-word-wrap-mode~ to
automatically enable wrapping in most buffers. Wrapping will not be enabled in automatically enable wrapping in most buffers. Wrapping will not be enabled in
buffers whose major mode is marked "special", or are listed in buffers whose major mode is marked "special", or are listed in

View file

@ -4,6 +4,8 @@
(defvar +word-wrap--major-mode-is-text nil) (defvar +word-wrap--major-mode-is-text nil)
(defvar +word-wrap--enable-adaptive-wrap-mode nil) (defvar +word-wrap--enable-adaptive-wrap-mode nil)
(defvar +word-wrap--enable-visual-line-mode nil) (defvar +word-wrap--enable-visual-line-mode nil)
(defvar +word-wrap--enable-visual-fill-mode nil)
(defvar +word-wrap--disable-auto-fill-mode nil)
(defvar +word-wrap--major-mode-indent-var nil) (defvar +word-wrap--major-mode-indent-var nil)
(defvar adaptive-wrap-extra-indent) (defvar adaptive-wrap-extra-indent)
@ -15,7 +17,7 @@
(defun +word-wrap--calc-extra-indent (p) (defun +word-wrap--calc-extra-indent (p)
"Calculate extra word-wrap indentation at point." "Calculate extra word-wrap indentation at point."
(if (not (or +word-wrap--major-mode-is-text (if (not (or +word-wrap--major-mode-is-text
(sp-point-in-string-or-comment p))) (doom-point-in-string-or-comment-p p)))
(pcase +word-wrap-extra-indent (pcase +word-wrap-extra-indent
('double ('double
(* 2 (symbol-value +word-wrap--major-mode-indent-var))) (* 2 (symbol-value +word-wrap--major-mode-indent-var)))
@ -30,33 +32,39 @@
(define-minor-mode +word-wrap-mode (define-minor-mode +word-wrap-mode
"Wrap long lines in the buffer with language-aware indentation. "Wrap long lines in the buffer with language-aware indentation.
This mode configures `adaptive-wrap' and `visual-line-mode' to wrap long lines This mode configures `adaptive-wrap', `visual-line-mode' and
without modifying the buffer content. This is useful when dealing with legacy `visual-fill-column-mode' to wrap long lines without modifying the buffer
code which contains gratuitously long lines, or running emacs on your content. This is useful when dealing with legacy code which contains
wrist-phone. gratuitously long lines, or running emacs on your wrist-phone.
Wrapped lines will be indented to match the preceding line. In code buffers, Wrapped lines will be indented to match the preceding line. In code buffers,
lines which are not inside a string or comment will have additional indentation lines which are not inside a string or comment will have additional indentation
according to the configuration of `+word-wrap-extra-indent'." according to the configuration of `+word-wrap-extra-indent'.
Long lines will wrap at the window margin by default, or can optionally be
wrapped at `fill-column' by configuring `+word-wrap-fill-style'."
:init-value nil :init-value nil
(if +word-wrap-mode (if +word-wrap-mode
(progn (progn
(setq-local +word-wrap--major-mode-is-visual (setq-local
(memq major-mode +word-wrap-visual-modes)) +word-wrap--major-mode-is-visual
(setq-local +word-wrap--major-mode-is-text (memq major-mode +word-wrap-visual-modes)
(memq major-mode +word-wrap-text-modes)) +word-wrap--major-mode-is-text
(memq major-mode +word-wrap-text-modes)
(setq-local +word-wrap--enable-adaptive-wrap-mode +word-wrap--enable-adaptive-wrap-mode
(and (not (bound-and-true-p adaptive-wrap-prefix-mode)) (and (not (bound-and-true-p adaptive-wrap-prefix-mode))
(not +word-wrap--major-mode-is-visual))) (not +word-wrap--major-mode-is-visual))
+word-wrap--enable-visual-line-mode
(setq-local +word-wrap--enable-visual-line-mode (not (bound-and-true-p visual-line-mode))
(not (bound-and-true-p visual-line-mode))) +word-wrap--enable-visual-fill-mode
(and (not (bound-and-true-p visual-fill-column-mode))
(memq +word-wrap-fill-style '(auto soft)))
+word-wrap--disable-auto-fill-mode
(and (bound-and-true-p auto-fill-function)
(eq +word-wrap-fill-style 'soft)))
(unless +word-wrap--major-mode-is-visual (unless +word-wrap--major-mode-is-visual
(require 'dtrt-indent) ; for dtrt-indent--search-hook-mapping (require 'dtrt-indent) ; for dtrt-indent--search-hook-mapping
(require 'smartparens) ; for sp-point-in-string-or-comment
(setq-local +word-wrap--major-mode-indent-var (setq-local +word-wrap--major-mode-indent-var
(caddr (dtrt-indent--search-hook-mapping major-mode))) (caddr (dtrt-indent--search-hook-mapping major-mode)))
@ -65,7 +73,11 @@ according to the configuration of `+word-wrap-extra-indent'."
(when +word-wrap--enable-adaptive-wrap-mode (when +word-wrap--enable-adaptive-wrap-mode
(adaptive-wrap-prefix-mode +1)) (adaptive-wrap-prefix-mode +1))
(when +word-wrap--enable-visual-line-mode (when +word-wrap--enable-visual-line-mode
(visual-line-mode +1))) (visual-line-mode +1))
(when +word-wrap--enable-visual-fill-mode
(visual-fill-column-mode +1))
(when +word-wrap--disable-auto-fill-mode
(auto-fill-mode -1)))
;; disable +word-wrap-mode ;; disable +word-wrap-mode
(unless +word-wrap--major-mode-is-visual (unless +word-wrap--major-mode-is-visual
@ -74,7 +86,11 @@ according to the configuration of `+word-wrap-extra-indent'."
(when +word-wrap--enable-adaptive-wrap-mode (when +word-wrap--enable-adaptive-wrap-mode
(adaptive-wrap-prefix-mode -1)) (adaptive-wrap-prefix-mode -1))
(when +word-wrap--enable-visual-line-mode (when +word-wrap--enable-visual-line-mode
(visual-line-mode -1)))) (visual-line-mode -1))
(when +word-wrap--enable-visual-fill-mode
(visual-fill-column-mode -1))
(when +word-wrap--disable-auto-fill-mode
(auto-fill-mode +1))))
(defun +word-wrap--enable-global-mode () (defun +word-wrap--enable-global-mode ()
"Enable `+word-wrap-mode' for `+word-wrap-global-mode'. "Enable `+word-wrap-mode' for `+word-wrap-global-mode'.

View file

@ -10,6 +10,18 @@ When a negative integer, dedent by this fixed amount.
Otherwise no extra indentation will be used.") Otherwise no extra indentation will be used.")
(defvar +word-wrap-fill-style nil
"How to handle `fill-column' in `+word-wrap-mode'.
When 'auto, long lines will soft-wrap at `fill-column'. If `auto-fill-mode' is
enabled, its behaviour will not be affected.
When 'soft, long lines will soft-wrap at `fill-column' and `auto-fill-mode' will
be forcibly disabled.
Otherwise long lines will soft-wrap at the window margin and `auto-fill-mode'
will not be affected.")
(defvar +word-wrap-disabled-modes (defvar +word-wrap-disabled-modes
'(fundamental-mode so-long-mode) '(fundamental-mode so-long-mode)
"Major-modes where `+global-word-wrap-mode' should not enable "Major-modes where `+global-word-wrap-mode' should not enable

View file

@ -2,3 +2,4 @@
;;; editor/word-wrap/packages.el ;;; editor/word-wrap/packages.el
(package! adaptive-wrap :pin "0d5b4a07de76d87dd64333a566a8a0a845f2b9f0") (package! adaptive-wrap :pin "0d5b4a07de76d87dd64333a566a8a0a845f2b9f0")
(package! visual-fill-column :pin "453d698d7fc243a547665f8ba43c55eee574e0db")