Skip to content

Instantly share code, notes, and snippets.

@arrdem
Created January 20, 2017 02:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arrdem/20cd8925846f76b8a55bd80c4b189990 to your computer and use it in GitHub Desktop.
Save arrdem/20cd8925846f76b8a55bd80c4b189990 to your computer and use it in GitHub Desktop.
My markdown support
;; 20-markdown.el
(require 'markdown-mode)
;; One space per line implementation
(defun arrdem:markdown-nobreak-p ()
"Return nil if it is acceptable to break the current line at the point.
Supports Markdown links, liquid tags."
;; inside in square brackets (e.g., link anchor text)
(or (looking-back "\\[[^]]*")
(looking-back "^\s?[-*]")
(looking-back "{%[^%]*")))
(defun arrdem:token-inbetween (start close)
"Scans forwards from the start of the buffer, returning 't if the mark
is in-between the start and end pattern, or the point is on either
the open or the close pattern.
Ex. is the point in a Markdown code block."
(or (looking-at start)
(looking-back close)
(let ((m (point))
(flag nil)
(break nil))
;; Jump back to the start of the buffer
(save-mark-and-excursion
(goto-char (point-min))
(while (not break)
(if (and
;; If there is a ``` open or close ahead of the point (and move there)
(re-search-forward
(if flag
close
start)
nil t)
;; We have not scanned forwards past the point in question
(<= (point) m))
;; Flip the flag (initially nil, t after an open, nil after matching close etc.)
(setq flag (not flag))
;; We've scanned far enough, break
(setq break t))))
;; Yield the flag
flag)))
(defun arrdem:markdown-in-code-block-p ()
"Returns 't if the point is in a code block"
(arrdem:token-inbetween
markdown-regex-gfm-code-block-open
markdown-regex-gfm-code-block-close))
(defun arrdem:markdown-in-yaml-header-p ()
"Returns 't if the point is in a Jekyll YAML header"
(arrdem:token-inbetween
"---"
"---"))
(defun arrdem:unfill-region (beg end)
"Unfill the region, joining text paragraphs into a
single logical line. This is useful, e.g., for use
with 'visual-line-mode'."
(interactive "*r")
(let ((fill-column (point-max)))
(fill-region beg end)))
(defun arrdem:fill-sentences-in-region (start end)
"Put a newline at the end of each sentence in region."
(interactive "*r")
(call-interactively 'arrdem:unfill-region)
(save-mark-and-excursion
(goto-char start)
(while (re-search-forward "[:;.?!][]\"')}]*\\( \\)" end t)
(call-interactively (key-binding (kbd "M-j"))))))
(defun arrdem:fill-sentences-in-paragraph ()
"Put a newline at the end of each sentence in paragraph."
(interactive)
(when (not (or (arrdem:markdown-in-code-block-p)
(arrdem:markdown-in-yaml-header-p)))
(save-mark-and-excursion
(mark-paragraph)
(call-interactively 'arrdem:fill-sentences-in-region))))
(defun arrdem:activate-ospl ()
"Installs a bunch of buffer-local customizations to `fill.el'"
(interactive)
(setq-local fill-paragraph-function 'arrdem:fill-sentences-in-paragraph)
(setq-local fill-nobreak-predicate arrdem:markdown-nobreak-p)
(local-set-key (kbd "M-q") 'arrdem:fill-sentences-in-paragraph))
(add-hook 'markdown-mode-hook 'arrdem:activate-ospl)
;; Smartparens for liquid markup & Markdown links
(require 'smartparens)
(add-hook 'markdown-mode-hook 'smartparens-mode)
(sp-with-modes '(markdown-mode)
(sp-local-pair "{%" "%}")
(sp-local-pair "[" "]()"))
;; Flycheck prose checker
(require 'flycheck)
(flycheck-define-checker proselint
"A linter for prose."
:command ("proselint" source-inplace)
:error-patterns ((warning line-start (file-name) ":" line ":" column ": "
(id (one-or-more (not (any " "))))
(message) line-end))
:modes (text-mode markdown-mode gfm-mode))
(add-to-list 'flycheck-checkers 'proselint)
(add-hook 'markdown-mode-hook 'flycheck-mode)
;; Flyspell
(require 'flyspell)
(add-hook 'markdown-mode-hook 'flyspell-mode)
;; Aggressive fill paragraph
(require 'aggressive-fill-paragraph)
(add-hook 'markdown-mode-hook 'aggressive-fill-paragraph-mode)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment