The following code leverages visual-line-mode, font-lock-mode and filladapt to provide a soft indent feature. I’ve only been using it for a while, so it may have some rough edges yet that need to be smoothed out; comments or suggestions would be very welcome. – JamesWright

    (defvar adaptive-soft-wrap-font-keywords
      '((find-next-fillable-line 0 (list 'face nil 'wrap-prefix fill-prefix) append))
      "Add this to a mode's keywords to enable adaptive soft-wrapping.")
    (define-minor-mode adaptive-soft-wrap-mode
        "Use font-lock machinery to automatically set `wrap-prefix' properties on each line based on its filladapt fill-prefix."
      nil nil nil
      (require 'filladapt)
      (require 'font-lock)
      (if adaptive-soft-wrap-mode
          (font-lock-add-keywords nil adaptive-soft-wrap-font-keywords t)
          (unless (memq 'wrap-prefix font-lock-extra-managed-props)
            (setq font-lock-extra-managed-props
                  (cons 'wrap-prefix font-lock-extra-managed-props))))
          (font-lock-remove-keywords nil adaptive-soft-wrap-font-keywords)
    (defun find-next-fillable-line (bound)
      (let ((prefix nil)
            (nleft 0)
            (bolp nil))
          (setq bolp (bolp))
          (narrow-to-region (point) bound)
          (if (and (not bolp)
                   (zerop (setq nleft (forward-line 1))))
            (goto-char (point-at-bol)))
          ;; From this point onward, point is either at bol or we are done
          (while (and (zerop nleft)
                      (not (setq prefix (fillable-line-prefix)))
                      (zerop (setq nleft (forward-line 1)))))
          (if prefix
            (let ((s (point-marker))
                  (e (save-excursion (goto-char (point-at-eol)) (point-marker))))
              (set-match-data (list s e) t)
              (setq fill-prefix prefix)
              (goto-char (point-min))
    (defun fillable-line-prefix ()
      "Return a prefix for the current line if at the beginning of a fillable line, or NIL otherwise."
      (let* ((tokens (filladapt-parse-prefixes))
             (prefix (when tokens
                       (filladapt-make-fill-prefix tokens))))
        (if (> (length prefix) 0)