Soft-wrapping with hanging indent

Hi all,

I am new to emacs and configuring it for LaTeX. In VSCode I can set a “hanging” indent when I soft wrap:

This is an example sentence which flows past my
editor margin and ends here.

How can I achieve the same behavior in emacs? I would like it purely with soft-wrapping.

I enabled visual-line-mode and adaptive-wrap-prefix-mode and eval’d (setq adaptive-wrap-extra-indent 4) but my result looks like:

This is an example sentence which flows past my
editor margin and ends here.

Any insights how to config this correctly?

What do you get if you try:

(global-visual-line-mode 1)
(with-eval-after-load 'adaptive-wrap
  (setq adaptive-wrap-extra-indent 4)
  (add-hook 'visual-line-mode-hook #'adaptive-wrap-prefix-mode))

If you use Emacs 30 (or higher), then you can use visual-line-mode together with visual-wrap-prefix-mode, no need for any external package:

(defun enable-line-prefix-wrap (&optional indent)
  "Enable `visual-line-mode' and `visual-wrap-prefix-mode' in the
current buffer.

The optional setting INDENT is the amount of indentation."
  (interactive "P")
  (visual-line-mode 1)
  (setq-local visual-wrap-extra-indent (or indent 4))
  (visual-wrap-prefix-mode 1))

Use via M-x enable-line-prefix-wrap RET. Or add it to a hook.

Demonstration

This demonstration uses emacs -Q. Beside the aforementioned function, only the follwing Emacs Lisp code has been executed:

(setq frame-title-format “Demonstration”)
(column-numbers-mode)   ; see the cursor position in both screenshots

Before

After

2 Likes

Thank you! This seems to be what I’m after.

I would additionally like to add visual-fill-column-mode (joostkremers/visual-fill-column: Emacs mode for wrapping visual-line-mode buffers at fill-column. - Codeberg.org) but I am confused a little with the instructions:

visual-fill-column-mode wraps long lines at fill-column without adding newlines to the buffer. Its primary (though not exclusive) purpose is to soft-wrap text in buffers that use visual-line-mode. The most straightforward way to achieve this is to add the function visual-fill-column-for-vline to visual-line-mode-hook:

(add-hook 'visual-line-mode-hook #'visual-fill-column-for-vline)

This function ensures that visual-fill-column-mode is enabled and disabled in conjunction with visual-line-mode. Note that you should not add visual-fill-column-mode to visual-line-mode-hook, because then visual-fill-column-mode is not disabled when you disable visual-line-mode. This also means that if you use use-package, you should not use the :hook keyword, because it will add -hook to the name of the function. Instead, put the add-hook invocation under :config.

I wasn’t sure how or where I should add this add-hook This Is what I’ve attempted so far, but visual-fill-column-mode isn’t called when i load a tex file:

(use-package visual-fill-column
:ensure t
:defer t
:config
((add-hook 'visual-line-mode-hook #'visual-fill-column-for-vline)
(setq visual-fill-column-width 120))
)

(defun enable-line-prefix-wrap (&optional indent)
"Enable visual-line-mode' and visual-wrap-prefix-mode’ in the current buffer.

The optional setting INDENT is the amount of indentation."
(interactive “P”)
(visual-line-mode 1)
(setq-local visual-wrap-extra-indent (or indent 4))
(visual-wrap-prefix-mode 1))

(use-package tex
:ensure auctex
:mode (“\.tex\'” . LaTeX-mode)
:hook
((LaTeX-mode . visual-line-mode))
(LaTeX-mode . enable-line-prefix-wrap))

You’re mixing a bit of syntax there. Given that you always want to run visual-fill-column when you run visual-line-mode, I’d recommend to use the following use-package:

(use-package visual-fill-column
  :ensure t
  :hook 
  (visual-line-mode . visual-fill-column-for-vline)
  :config
  (setopt visual-fill-column-width 120))

Note that there is no :defer necessary if you use :hook.[1] But: :hook should only be used if the function that is called is defined by the package.[2]

So, next up, let’s customize visual-wrap-prefix-mode:

(use-package visual-wrap
  :ensure nil
  :config
  (setopt visual-wrap-extra-indent 4))

And last but not least, let’s customize tex:

(use-package tex
  :ensure auctex
  :mode (“\.tex\'” . LaTeX-mode)
  :config
  (add-hook 'LaTeX-mode-hook #'visual-line-mode)
  (add-hook 'LaTeX-mode-hook #'visual-wrap-prefix-mode))

Here, we have to use add-hook, because the called function is not provided by auctex. Now, if you always want to use visual-wrap-prefix-mode whenever you use visual-line-mode, then it gets a bit easier:

;; visual-fill-column's package definition stays as-is
(use-package visual-wrap
  :ensure nil
  :hook
  (visual-line-mode . visual-wrap-prefix-mode)   ; always use wrap-prefix
  :config
  (setopt visual-wrap-extra-indent 4))

(use-package tex
  :ensure auctex
  :mode (“\.tex\'” . LaTeX-mode)
  :config
  (add-hook 'LaTeX-mode-hook #'visual-line-mode)) ; second hook removed

Now, with all that said, I think that this is not quite correct. While visual-line-mode can work together with visual-wrap-prefix-mode, you can use the latter without the former and then get hints in the fringes about the continuation, which you may prefer. However, the authors of visual-fill-column have bound visual-fill-column-for-vline to visual-line-mode’s variable value, so you would have to do that yourself[3].


  1. That’s also the reason why I don’t like the maintainers comment about :hook: “This also means that if you use use-package, you should not use the :hook keyword, because it will add -hook to the name of the function. Instead, put the add-hook invocation under :config.” That is not necessary and will instead work against use-package’s autoloading features. ↩︎

  2. Again, use-package does some magic and defers loading your package if you specify :hook. It does so by providing autoloads; setting them on unrelated functions would be bad, hmkay? ↩︎

  3. see visual-fill-column-for-vline’s definition ↩︎

1 Like