Skip to content

Commit

Permalink
Hack forward-paragraph-func so fill-region skips code blocks
Browse files Browse the repository at this point in the history
Also Rename `markdown-fill-forward-paragraph-function` to
`markdown-fill-forward-paragraph`.

Includes three test cases.

Closes GH-192.

The trick here is to make `markdown-fill-forward-paragraph` move
asymmetrically when called with argument 1 and -1.  Consider this file
with important positions indicated by (n):

           <-- (0)
    par 1
           <-- (1)
    ```
    code
    ```
           <-- (2)
    par 2
           <-- (3)

Starting at `point-min` (0), calling `(markdown-fill-forward-paragraph
1)` repeatedly first moves to (1).  This identifies the first
paragraph that `fill-region` will fill.  With this patch, calling
`(markdown-fill-forward-paragraph 1)` again moves to (3), fully
skipping over (2).  Once at (3), calling
`(markdown-fill-forward-paragraph -1)` now moves back to (2).  Thus,
`fill-region` identifies the next paragraph as the paragraph between
(2) and (3) rather than the code block (1) and (2).
  • Loading branch information
jrblevin committed Jun 15, 2017
1 parent 7541ad0 commit 199975f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 10 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
Previously, `markdown-header-delimiter-face` was used.
- Markdown Mode is now distributed under the GNU GPL version 3
or later.
- Rename `markdown-fill-forward-paragraph-function` to
`markdown-fill-forward-paragraph`.

* New features:

Expand Down Expand Up @@ -118,6 +120,8 @@
- Reuse existing windows, when possible, rather than splitting
again in preferred direction. ([GH-129][])
- Update known languages in `markdown-gfm-recognized-languages`.
- Filling with `fill-region` now leaves code blocks unmodified.
([GH-192][])

* Bug fixes:

Expand All @@ -135,6 +139,7 @@
[gh-176]: https://github.com/jrblevin/markdown-mode/issues/176
[gh-185]: https://github.com/jrblevin/markdown-mode/issues/185
[gh-191]: https://github.com/jrblevin/markdown-mode/issues/191
[gh-192]: https://github.com/jrblevin/markdown-mode/issues/192
[gh-197]: https://github.com/jrblevin/markdown-mode/issues/197

# Markdown Mode 2.2
Expand Down
35 changes: 25 additions & 10 deletions markdown-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -7709,24 +7709,39 @@ handles filling itself, it always returns t so that
(fill-paragraph justify))
t)

(defun markdown-fill-forward-paragraph-function (&optional arg)
(make-obsolete 'markdown-fill-forward-paragraph-function
'markdown-fill-forward-paragraph "v2.3")

(defun markdown-fill-forward-paragraph (&optional arg)
"Function used by `fill-paragraph' to move over ARG paragraphs.
This is a `fill-forward-paragraph-function' for `markdown-mode'.
It is called with a single argument specifying the number of
paragraphs to move. Just like `forward-paragraph', it should
return the number of paragraphs left to move."
(let* ((arg (or arg 1))
(paragraphs-remaining (forward-paragraph arg))
(start (point)))
(when (< arg 0)
(or arg (setq arg 1))
(if (> arg 0)
;; With positive ARG, move across ARG non-code-block paragraphs,
;; one at a time. When passing a code block, don't decrement ARG.
(while (and (not (eobp))
(> arg 0)
(= (forward-paragraph 1) 0)
(or (markdown-code-block-at-pos (point-at-bol 0))
(setq arg (1- arg)))))
;; Move backward by one paragraph with negative ARG (always -1).
(let ((start (point)))
(setq arg (forward-paragraph arg))
(while (and (not (eobp))
(progn (move-to-left-margin) (not (eobp)))
(looking-at-p paragraph-separate))
(forward-line 1))
(if (looking-at markdown-regex-list)
(forward-char (length (match-string 0)))
(goto-char start)))
paragraphs-remaining))
(cond
;; Move point past whitespace following list marker.
((looking-at markdown-regex-list)
(goto-char (match-end 0)))
;; Return point if the paragraph passed was a code block.
((markdown-code-block-at-pos (point-at-bol 2))
(goto-char start)))))
arg)


;;; Extension Framework =======================================================
Expand Down Expand Up @@ -8210,7 +8225,7 @@ position."
(set (make-local-variable 'adaptive-fill-function)
'markdown-adaptive-fill-function)
(set (make-local-variable 'fill-forward-paragraph-function)
'markdown-fill-forward-paragraph-function)
#'markdown-fill-forward-paragraph)
;; Outline mode
(make-local-variable 'outline-regexp)
(setq outline-regexp markdown-regex-header)
Expand Down
54 changes: 54 additions & 0 deletions tests/markdown-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -4346,6 +4346,60 @@ this is not header line
(fill-paragraph)
(should (string-equal (buffer-string) text))))))

(ert-deftest test-markdown-filling/fill-region-skip-code-blocks ()
"Test `fill-region' on code blocks."
(let ((text "testing\n\n```\nhello\nworld\n```\n\n123"))
(markdown-test-string text
;; Fill entire buffer; buffer should not change.
(fill-region (point-min) (point-max))
(should (string-equal (buffer-string) text)))))

(ert-deftest test-markdown-filling/fill-region-skip-code-blocks-2 ()
"Test `fill-region' on a buffer with a code block with long paragraphs."
(markdown-test-string "long unwrapped paragraph 1

```
code
block

foo
bar
```

long unwrapped paragraph 2"
;; Test markdown-fill-forward-paragraph movement.
(should (= (markdown-fill-forward-paragraph 1) 0))
(should (= (point) 28)) ;; Point just after par. 1.
(should (= (markdown-fill-forward-paragraph 1) 0))
(should (= (point) 84)) ;; Point at end of par. 2.
;; Test filling the entire buffer with `fill-region'.
(let ((fill-column 12))
(fill-region (point-min) (point-max))
(should (string-equal (buffer-string)
"long
unwrapped
paragraph 1

```
code
block

foo
bar
```

long
unwrapped
paragraph 2")))))

(ert-deftest test-markdown-filling/fill-region-skip-code-blocks-3 ()
"Test `fill-region' on a lone code block with no surrounding text."
(let ((text "```\ncode\nblock\n```\n"))
(markdown-test-string text
;; Fill entire buffer; buffer should not change.
(fill-region (point-min) (point-max))
(should (string-equal (buffer-string) text)))))

(ert-deftest test-markdown-filling/long-paragraph-with-link ()
"Test `fill-paragraph' on a long paragraph with a long link."
(markdown-test-string
Expand Down

0 comments on commit 199975f

Please sign in to comment.