As wasamasa already pointed out word-wrapping only a part of the buffer requires most probably some re-plumping.
The following demonstrates an idea. It works with truncated lines and puts a newline with indent before the word reaching
I am aware that this is not perfect. Some things that are not handled:
- word wrapping does not adapt to
- it does also not adapt to changes of
fill-column; one could advice
- no special point motion (e.g.
forward-line jumps over the visual lines)
jit-lock handlers might interfere with
If you want to try this stuff load it. There is an
org-visline-mode function at the end of this code which installs the filter for org headlines and switches on
(defvar-local visline-predicate-functions nil
"List of predicate functions that are run at the beginning of each line which is visually word-wrapped by `visline-mode'.
You should add your handlers before running `visline-mode'.
The predicate functions are called without arguments.")
(defmacro visline-expand-region (start end)
"Expand region between START and END such that START is at the beginning of a line and END at the end of a line."
(declare (debug (sexp sexp)))
(setq ,start (save-excursion (goto-char ,start) (beginning-of-line) (point)))
(setq ,end (save-excursion (goto-char ,end) (end-of-line) (point)))))
(defun visline-clear (start end)
"Remove visual linebreaks in the region from START to END."
(while (setq start (text-property-any start end 'visline t))
(remove-text-properties start (1+ start) '(visline t display "\n")))))
(defsubst visline-put (pos indent)
"Put a visual linebreak at the character following position POS."
(add-text-properties pos (1+ pos) (list 'visline t 'display (concat "\n" (make-string indent ?\ )))))
(defun visline-fill-line ()
"Word-wrap current line with the help of visual linebreaks."
(let* ((indent (current-column))
(while (null (eolp))
(setq last-col (current-column))
(setq last-posn (point))
(when (and (> (- (current-column) last-virtual-newline) fill-column)
(> last-col indent))
(visline-put last-posn indent)
(setq last-virtual-newline (+ last-col indent))))))
(defun visline-handler (start end)
"Visually word-wrap region between START and END."
(visline-expand-region start end)
(visline-clear start end)
(while (< (point) end)
(when (run-hook-with-args-until-failure 'visline-predicate-functions)
"Word-wrap via text-properties"
(jit-lock-register 'visline-handler) ;; `jit-lock-register' also re-fontifies
(visline-clear (point-min) (point-max)))))
(defun org-visline-dont-wrap-headlines ()
"Return only t if we are not on a headline."
(null (eq (char-after) ?*)))
(defun org-visline-mode ()
"Switches `visline-mode' on in `org-mode'.
(add-hook 'org-mode-hook 'org-visline-mode)"
(add-hook 'visline-predicate-functions 'org-visline-dont-wrap-headlines)
(add-hook 'org-mode-hook 'org-visline-mode)