Improve +word-wrap in non-code buffers

Adds `+word-wrap-text-modes`, a list of modes which shouldn't get any
extra indentation. This is used for text and markdown modes, which
should just indent to the parent depth.

Adds `+word-wrap-visual-modes`, a list of modes which shouldn't enable
`adaptive-wrap-prefix-mode`. This is used to fix the prefix indentation
in `org-mode`, which provides its own implementation.

Tweaks the indent behaviour to treat strings the same as comments so
they don't receive additional indentation.
This commit is contained in:
Andrew Whatson 2019-10-15 00:51:28 +10:00
parent 24b336322c
commit 930d0d134a
3 changed files with 62 additions and 29 deletions

View file

@ -12,10 +12,10 @@
This module adds a minor-mode ~+word-wrap-mode~, which intelligently wraps long This module adds a minor-mode ~+word-wrap-mode~, which intelligently wraps long
lines in the buffer without modifying the buffer content. lines in the buffer without modifying the buffer content.
Wrapped lines will be indented to match the preceding line. Lines which are not Wrapped lines will be indented to match the preceding line. In code buffers,
inside a comment will have extra indentation as determined by lines which are not inside a string or comment will have extra indentation as
~+word-wrap-extra-indent~. The default is to increase the indent by twice the determined by ~+word-wrap-extra-indent~. The default is to increase the indent
major-mode indent. by twice the major-mode indent.
The ~+word-wrap-extra-indent~ variable supports the following values: The ~+word-wrap-extra-indent~ variable supports the following values:
- ~double~: indent by twice the major-mode indentation - ~double~: indent by twice the major-mode indentation
@ -29,6 +29,14 @@ 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
~+word-wrap-disabled-modes~. ~+word-wrap-disabled-modes~.
The ~+word-wrap-text-modes~ variable lists modes which shouldn't have any extra
indentation, regardless of the ~+word-wrap-extra-indent~ setting. This is useful
for modes which are primarily text, such as ~text-mode~ and ~markdown-mode~.
The ~+word-wrap-visual-modes~ variable lists modes which should only enable
~visual-line-mode~ and not provide any prefix indentation. This is useful for
modes like ~org-mode~ which handle prefix indentation themselves.
** Module Flags ** Module Flags
This module provides no flags. This module provides no flags.
@ -49,12 +57,12 @@ To enable wrapping in a specific mode, add it to the appropriate hook in your
(add-hook 'c-mode-common-hook #'+word-wrap-mode) (add-hook 'c-mode-common-hook #'+word-wrap-mode)
#+END_SRC #+END_SRC
To customize the extra indent for a specific mode: To customize the behaviour in a specific mode:
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
;; enable word-wrap with fixed extra 2 spaces in org-mode ;; use a single indent in json-mode
(add-hook! 'org-mode-hook (add-hook! 'json-mode-hook
(setq-local +word-wrap-extra-indent 2) (setq-local +word-wrap-extra-indent 'single)
(+word-wrap-mode +1)) (+word-wrap-mode +1))
#+END_SRC #+END_SRC

View file

@ -1,7 +1,9 @@
;;; editor/word-wrap/autoload.el -*- lexical-binding: t; -*- ;;; editor/word-wrap/autoload.el -*- lexical-binding: t; -*-
(defvar +word-wrap--prev-adaptive-wrap-mode nil) (defvar +word-wrap--major-mode-is-visual nil)
(defvar +word-wrap--prev-visual-line-mode nil) (defvar +word-wrap--major-mode-is-text nil)
(defvar +word-wrap--enable-adaptive-wrap-mode nil)
(defvar +word-wrap--enable-visual-line-mode nil)
(defvar +word-wrap--major-mode-indent-var nil) (defvar +word-wrap--major-mode-indent-var nil)
(defun +word-wrap--adjust-extra-indent-a (orig-fn beg end) (defun +word-wrap--adjust-extra-indent-a (orig-fn beg end)
@ -11,7 +13,8 @@
(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 (sp-point-in-comment p)) (if (not (or +word-wrap--major-mode-is-text
(sp-point-in-string-or-comment 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)))
@ -31,34 +34,45 @@ without modifying the buffer content. This is useful when dealing with legacy
code which contains gratuitously long lines, or running emacs on your code which contains gratuitously long lines, or running emacs on your
wrist-phone. wrist-phone.
Wrapped lines will be indented to match the preceding line. Lines which are not Wrapped lines will be indented to match the preceding line. In code buffers,
inside a comment will have additional indentation according to the configuration lines which are not inside a string or comment will have additional indentation
of `+word-wrap-extra-indent'." according to the configuration of `+word-wrap-extra-indent'."
:init-value nil :init-value nil
(if +word-wrap-mode (if +word-wrap-mode
(progn (progn
(require 'adaptive-wrap) (setq-local +word-wrap--major-mode-is-visual
(require 'dtrt-indent) ; for dtrt-indent--search-hook-mapping (memq major-mode +word-wrap-visual-modes))
(require 'smartparens) ; for sp-point-in-string-or-comment (setq-local +word-wrap--major-mode-is-text
(memq major-mode +word-wrap-text-modes))
(setq-local +word-wrap--prev-adaptive-wrap-mode adaptive-wrap-prefix-mode) (setq-local +word-wrap--enable-adaptive-wrap-mode
(setq-local +word-wrap--prev-visual-line-mode visual-line-mode) (and (not (bound-and-true-p adaptive-wrap-prefix-mode))
(setq-local +word-wrap--major-mode-indent-var (not +word-wrap--major-mode-is-visual)))
(caddr (dtrt-indent--search-hook-mapping major-mode)))
(advice-add #'adaptive-wrap-fill-context-prefix :around #'+word-wrap--adjust-extra-indent-a) (setq-local +word-wrap--enable-visual-line-mode
(not (bound-and-true-p visual-line-mode)))
(unless +word-wrap--prev-adaptive-wrap-mode (unless +word-wrap--major-mode-is-visual
(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
(caddr (dtrt-indent--search-hook-mapping major-mode)))
(advice-add #'adaptive-wrap-fill-context-prefix :around #'+word-wrap--adjust-extra-indent-a))
(when +word-wrap--enable-adaptive-wrap-mode
(adaptive-wrap-prefix-mode +1)) (adaptive-wrap-prefix-mode +1))
(unless +word-wrap--prev-visual-line-mode (when +word-wrap--enable-visual-line-mode
(visual-line-mode +1))) (visual-line-mode +1)))
;; disable +word-wrap-mode ;; disable +word-wrap-mode
(advice-remove #'adaptive-wrap-fill-context-prefix #'+word-wrap--adjust-extra-indent-a) (unless +word-wrap--major-mode-is-visual
(advice-remove #'adaptive-wrap-fill-context-prefix #'+word-wrap--adjust-extra-indent-a))
(unless +word-wrap--prev-adaptive-wrap-mode (when +word-wrap--enable-adaptive-wrap-mode
(adaptive-wrap-prefix-mode -1)) (adaptive-wrap-prefix-mode -1))
(unless +word-wrap--prev-visual-line-mode (when +word-wrap--enable-visual-line-mode
(visual-line-mode -1)))) (visual-line-mode -1))))
(defun +word-wrap--enable-global-mode () (defun +word-wrap--enable-global-mode ()

View file

@ -1,15 +1,26 @@
;;; editor/word-wrap/config.el -*- lexical-binding: t; -*- ;;; editor/word-wrap/config.el -*- lexical-binding: t; -*-
(defvar +word-wrap-extra-indent 'double (defvar +word-wrap-extra-indent 'double
"The amount of extra indentation for wrapped non-comment lines. "The amount of extra indentation for wrapped code lines.
When 'double, indent by twice the major-mode indentation. When 'double, indent by twice the major-mode indentation.
When 'single, indent by the major-mode indentation. When 'single, indent by the major-mode indentation.
When a positive integer, indent by this fixed amount. When a positive integer, indent by this fixed amount.
When a negative integer, dedent by this fixed amount. 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-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
`+word-wrap-mode'.") `+word-wrap-mode'.")
(defvar +word-wrap-visual-modes
'(org-mode)
"Major-modes where `+word-wrap-mode' should not use
`adaptive-wrap-prefix-mode'.")
(defvar +word-wrap-text-modes
'(text-mode markdown-mode markdown-view-mode gfm-mode gfm-view-mode rst-mode
latex-mode LaTeX-mode)
"Major-modes where `+word-wrap-mode' should not provide extra indentation.")