markdown-mode is a major mode for GNU Emacs which provides syntax highlighting and supporting commands for editing Markdown files. It provides keybindings and commands for inserting Markdown elements and to assist in calling Markdown to parse the source code or preview the document in a browser. It also, optionally, provides syntax highlighting for wiki links and embedded itex mathematical expressions.
http://jblevins.org/projects/markdown-mode/
markdown-mode version 2.1 was released on January 9, 2016. Release notes can be found here:
http://jblevins.org/projects/markdown-mode/rev-2-1
Debian have ‘elpa-markdown-mode’ package.
It can be useful to enforce certain static constraints on Markdown files; for example, the heavy use of brackets and parentheses in link syntax mean it is easy to omit a closing parentheses, especially if one is linking something inside a natural language digression (where one will have 2 or more closing parentheses). Balance can be checked with 'check-parens', and it can be automatically invoked after file saves with the usual hooks, eg.
(add-hook 'markdown-mode-hook
(lambda ()
(when buffer-file-name
(add-hook 'after-save-hook
'check-parens
nil t))))A similar logic applies to double-quotes, especially if one is frequently adding tooltips to links. ‘check-parens’ works off the buffer syntax table, and double-quotes are not special to markdown-mode, so one must do a more invasive hook:
; warning, may yield wrong results in edge-cases like single double-quotes in code block. ; Use only if your files usually are balanced w/r/t double-quotes ; <http://stackoverflow.com/questions/9527593/> (add-hook 'markdown-mode-hook (lambda () (modify-syntax-entry ?\" "\"" markdown-mode-syntax-table)))
Useful markdown-specific editing features:
‘C-c C--’ or `C-c C-=’ or by re-issuing a heading insertion command when the point is at a heading (e.g., ‘C-c C-t 4’ will replace the current heading with a level-four heading).‘C-c C-f’, ‘C-c C-b’, ‘C-c C-u’, ‘C-c C-p’, and ‘C-c C-n’).Assuming you are using the Perl script `markdown` which is called without a filename, and assuming you write all your files using UTF-8, then this is for you:
(eval-after-load "markdown-mode" '(defalias 'markdown-add-xhtml-header-and-footer 'as/markdown-add-xhtml-header-and-footer)) (defun as/markdown-add-xhtml-header-and-footer (title) "Wrap XHTML header and footer with given TITLE around current buffer." (goto-char (point-min)) (insert "<!DOCTYPE html5>\n" "<html>\n" "<head>\n<title>") (insert title) (insert "</title>\n") (insert "<meta charset=\"utf-8\" />\n") (when (> (length markdown-css-paths) 0) (insert (mapconcat 'markdown-stylesheet-link-string markdown-css-paths "\n"))) (insert "\n</head>\n\n" "<body>\n\n") (goto-char (point-max)) (insert "\n" "</body>\n" "</html>\n"))
This does the following:
markdown-content-type and markdown-coding-systemmarkdown-xhtml-header-content is also ignoredThis other app I’m using treats single newlines as paragraph breaks. In order for Emacs to work well with it, I use the following:
;; The Markdown files I write using IA Writer use newlines to separate ;; paragraphs. That's why I need Visual Line Mode. I also need to ;; disable M-q. If I fill paragraphs, that introduces unwanted ;; newlines. (add-hook 'markdown-mode-hook 'visual-line-mode) (add-hook 'markdown-mode-hook 'as/markdown-config) (defun as/markdown-config () (local-set-key (kbd "M-q") 'ignore))
Sometimes I want to post a fragment I wrote on Google+ and need a quick way to convert Markdown to Google+ markup.
;; I write a lot of Markdown but then I want to post the text on ;; Google+ so here's a quick export. (defun as/markdown-region-to-google (start end) (interactive "r") (goto-char start) (while (search-forward "*" end t) (goto-char (match-beginning 0)) (cond ((looking-at "\\b\\*\\*\\|\\*\\*\\b") (delete-char 1) (forward-char 1)) ((looking-at "\\b\\*\\|\\*\\b") (delete-char 1) (insert "_")))))
When I’m done writing a chapter, the text gets copied over to a LaTeX document. Here’s a quick way to convert my text.
;; Often Markdown gets added to a LaTeX project, too. So I eventually ;; need a LaTeX export. (defun as/markdown-region-to-latex (start end) (interactive "r") (goto-char start) (save-restriction (let (in-list skip-to) (narrow-to-region start end) (while (re-search-forward "\\*\\|\n\\|\\`" nil t) (goto-char (match-beginning 0)) (if (= (point) (match-end 0)) (setq skip-to (1+ (point))) (setq skip-to (match-end 0))) (cond ((looking-at "\\*\\*\\b\\([^*]*?\\)\\b\\*\\*") (replace-match "\\\\textbf{\\1}")) ((looking-at "\\*\\b\\([^*]*?\\)\\b\\*") (replace-match "\\\\textit{\\1}")) ((looking-at "^# \\(.*\\)") (replace-match "\\\\section{\\1}")) ((looking-at "^## \\(.*\\)") (replace-match "\\\\subsection{\\1}")) ((looking-at "^### \\(.*\\)") (replace-match "\\\\subsubsection{\\1}")) ((looking-at "^\\* ") (replace-match (if in-list "\\\\item " "\\\\begin{itemize}\n\\\\item ")) (setq in-list "itemize")) ((looking-at "^[0-9]+\\. ") (replace-match (if in-list "\\\\item " "\\\\begin{enumerate}\n\\\\item ")) (setq in-list "enumerate")) ((and in-list (looking-at "^")) (replace-match (format "\\\\end{%s}\n" in-list)) (setq in-list nil)) (t (goto-char skip-to)))))))