11

Let's say I have the following buffer.

1. lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum

Hitting M-q here while in text-mode leads to the following.

1. lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem
ipsum lorem ipsum lorem ipsum lorem ipsum

On the other hand, if I activate markdown-mode, I get the following (Markdown is just an example, you see similar behavior in various modes).

1. lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem
   ipsum lorem ipsum lorem ipsum lorem ipsum

How do I configure text-mode to do that?

I imagine this can be achieved by writting a special fill-paragraph-function, but this variable is just set to nil in markdown-mode, so there's probably an easier way.

6

I've been a happy user of filladapt-mode for a long time, which handles this sort of thing really nicely. For info, see

http://emacswiki.org/emacs/FillAdapt

From that page:

Filladapt by KyleJones enhances Emacs’ fill functions by guessing a fill prefix, such as a comment sequence in program code, and handling bullet points like “1.” or “*”.

For example, it could turn this

* Pretend I'm a really super long line.
* And the window's narrow.

into

* Pretend I'm a really super
  long line.
* And the window's narrow.
  • Ok, edited to address that. – Chris Oct 1 '15 at 1:29
  • to enable this mode in conjunction w/ another mode, add something like (add-hook 'org-mode-hook 'turn-on-filladapt-mode) to your config file (this info isn't directly available on the linked wiki page). – Mark Feb 1 '16 at 18:14
  • Works beautifully to make fill-paragraph behave properly within blockquotes in markdown-mode. – Radon Rosborough Mar 14 '17 at 17:55
  • 2 years has passed since the answer. Download link wonderworks.com/download/filladapt.el is no longer available. – Tankman六四 Jul 26 '17 at 12:01
  • The link works for me right now. Maybe there was a temporary problem with the site. – Chris Jul 28 '17 at 18:48
3
(fill-paragraph &optional JUSTIFY REGION)

[...]

If `fill-paragraph-function' is non-nil, we call it (passing our
argument to it), and if it returns non-nil, we simply return its value.

If `fill-paragraph-function' is nil, return the `fill-prefix' used for filling.

[...]

markdown-mode presumably sets fill-paragraph-function to nil so that the function uses fill-prefix to do the filling.

(let ((fill-prefix (make-string (length "1. ") ? ))
  (fill-paragraph))

Full example:

(let* ((num 15)
       (numstr (format "%d. " num))
       (fill-prefix (make-string (length numstr) ? )))
  (with-temp-buffer
    (loop for i from 1 to 15 do
          (insert (format "lorem ipsum (%d) doler sit amet " i)))
    (beginning-of-line)
    (insert numstr)
    (fill-paragraph)
    (buffer-string)))

;; =>

"\
15. lorem ipsum (1) doler sit amet lorem ipsum (2) doler sit amet
    lorem ipsum (3) doler sit amet lorem ipsum (4) doler sit amet
    lorem ipsum (5) doler sit amet lorem ipsum (6) doler sit amet
    lorem ipsum (7) doler sit amet lorem ipsum (8) doler sit amet
    lorem ipsum (9) doler sit amet lorem ipsum (10) doler sit amet
    lorem ipsum (11) doler sit amet lorem ipsum (12) doler sit amet
    lorem ipsum (13) doler sit amet lorem ipsum (14) doler sit amet
    lorem ipsum (15) doler sit amet "
  • 1
    "markdown-mode presumably sets fill-paragraph-function to nil so that the function uses fill-prefix to do the filling." That can't be the whole story. When I hit M-q, fill-paragraph is invoked directly (there's no let-bind around it). While it's possible that fill-prefix is ultimately used for this purpose, there has to be some configuration variable that allows it to be auto-detected. – Malabarba Feb 14 '15 at 17:14
  • 1
    @Malabarba Looks like markdown-mode actually does this via paragraph definitions: gist.github.com/vermiculus/88759fd9f8368adbf663 – Sean Allred Feb 14 '15 at 17:24
  • Yes, that looks more like it. – Malabarba Feb 14 '15 at 17:42
2

Sean's gist pointed me in the right direction, and here's the snippet that solved it.

(defun my-adaptive-fill-function ()
  "Return prefix for filling paragraph or nil if not determined."
  (cond
   ;; List item inside blockquote
   ((looking-at "^[ \t]*>[ \t]*\\([0-9]+\\.\\|[*+-]\\)[ \t]+")
    (replace-regexp-in-string
     "[0-9\\.*+-]" " " (match-string-no-properties 0)))
   ;; Blockquote
   ((looking-at "^[ \t]*>[ \t]*")
    (match-string-no-properties 0))
   ;; List items
   ((looking-at "^\\([ \t]*\\)\\([0-9]+\\.\\|[\\*\\+-]\\)\\([ \t]+\\)")
    (match-string-no-properties 0))
   ;; No match
   (t nil)))

;; Paragraph filling in text-mode.
(add-hook 'text-mode-hook
  (lambda ()
    (set (make-local-variable 'paragraph-start)
         "\f\\|[ \t]*$\\|[ \t]*[*+-] \\|[ \t]*[0-9]+\\.[ \t]\\|[ \t]*: ")
    (set (make-local-variable 'paragraph-separate)
         "\\(?:[ \t\f]*\\|.*  \\)$")
    (set (make-local-variable 'adaptive-fill-first-line-regexp)
         "\\`[ \t]*>[ \t]*?\\'")
    (set (make-local-variable 'adaptive-fill-function)
         'my-adaptive-fill-function)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.