Function: markdown-mode

markdown-mode is an autoloaded, interactive and byte-compiled function defined in markdown-mode.el.

Signature

(markdown-mode)

Documentation

Major mode for editing Markdown files.

In addition to any hooks its parent mode text-mode might have run, this mode runs the hook markdown-mode-hook, as the final or penultimate step during initialization.

<backtab> markdown-shifttab
C-M-{ markdown-backward-block
C-M-} markdown-forward-block
C-a markdown-beginning-of-line
C-c ' markdown-edit-code-block
C-c - markdown-insert-hr
C-c < markdown-outdent-region
C-c <down> markdown-move-down
C-c <left> markdown-promote
C-c <right> markdown-demote
C-c <up> markdown-move-up
C-c > markdown-indent-region
C-c C-- markdown-promote
C-c C-= markdown-demote
C-c C-M-h markdown-mark-subtree
C-c C-] markdown-complete
C-c C-a L markdown-insert-link
C-c C-a f markdown-insert-footnote
C-c C-a l markdown-insert-link
C-c C-a r markdown-insert-link
C-c C-a u markdown-insert-uri
C-c C-a w markdown-insert-wiki-link
C-c C-b markdown-outline-previous-same-level
C-c C-c ] markdown-complete-buffer
C-c C-c ^ markdown-table-sort-lines
C-c C-c c markdown-check-refs
C-c C-c e markdown-export
C-c C-c l markdown-live-preview-mode(var)/markdown-live-preview-mode(fun)
C-c C-c m markdown-other-window
C-c C-c n markdown-cleanup-list-numbers
C-c C-c o markdown-open
C-c C-c p markdown-preview
C-c C-c t markdown-table-transpose
C-c C-c u markdown-unused-refs
C-c C-c v markdown-export-and-preview
C-c C-c w markdown-kill-ring-save
C-c C-c | markdown-table-convert-region
C-c C-d markdown-do
C-c C-f markdown-outline-next-same-level
C-c C-j markdown-insert-list-item
C-c C-k markdown-kill-thing-at-point
C-c C-l markdown-insert-link
C-c C-n markdown-outline-next
C-c C-o markdown-follow-thing-at-point
C-c C-p markdown-outline-previous
C-c C-s ! markdown-insert-header-setext-1
C-c C-s - markdown-insert-hr
C-c C-s 1 markdown-insert-header-atx-1
C-c C-s 2 markdown-insert-header-atx-2
C-c C-s 3 markdown-insert-header-atx-3
C-c C-s 4 markdown-insert-header-atx-4
C-c C-s 5 markdown-insert-header-atx-5
C-c C-s 6 markdown-insert-header-atx-6
C-c C-s @ markdown-insert-header-setext-2
C-c C-s C markdown-insert-gfm-code-block
C-c C-s F markdown-insert-foldable-block
C-c C-s H markdown-insert-header-setext-dwim
C-c C-s P markdown-pre-region
C-c C-s Q markdown-blockquote-region
C-c C-s [ markdown-insert-gfm-checkbox
C-c C-s b markdown-insert-bold
C-c C-s c markdown-insert-code
C-c C-s e markdown-insert-italic
C-c C-s f markdown-insert-footnote
C-c C-s h markdown-insert-header-dwim
C-c C-s i markdown-insert-italic
C-c C-s k markdown-insert-kbd
C-c C-s l markdown-insert-link
C-c C-s p markdown-insert-pre
C-c C-s q markdown-insert-blockquote
C-c C-s s markdown-insert-strike-through
C-c C-s t markdown-insert-table
C-c C-s w markdown-insert-wiki-link
C-c C-t ! markdown-insert-header-setext-1
C-c C-t 1 markdown-insert-header-atx-1
C-c C-t 2 markdown-insert-header-atx-2
C-c C-t 3 markdown-insert-header-atx-3
C-c C-t 4 markdown-insert-header-atx-4
C-c C-t 5 markdown-insert-header-atx-5
C-c C-t 6 markdown-insert-header-atx-6
C-c C-t @ markdown-insert-header-setext-2
C-c C-t H markdown-insert-header-setext-dwim
C-c C-t h markdown-insert-header-dwim
C-c C-t s markdown-insert-header-setext-2
C-c C-t t markdown-insert-header-setext-1
C-c C-u markdown-outline-up
C-c C-x C-e markdown-toggle-math
C-c C-x C-f markdown-toggle-fontify-code-blocks-natively
C-c C-x C-l markdown-toggle-url-hiding
C-c C-x C-x markdown-toggle-gfm-checkbox
C-c C-x RET markdown-toggle-markup-hiding
C-c C-x TAB markdown-toggle-inline-images
C-c C-x d markdown-move-down
C-c C-x l markdown-promote
C-c C-x m markdown-insert-list-item
C-c C-x r markdown-demote
C-c C-x u markdown-move-up
C-c M-h markdown-mark-block
C-c S-<down> markdown-table-insert-row
C-c S-<left> markdown-table-delete-column
C-c S-<right> markdown-table-insert-column
C-c S-<up> markdown-table-delete-row
C-c TAB markdown-insert-image
C-e markdown-end-of-line
C-x C-p RET markdown-mark-page
C-x [ markdown-backward-page
C-x ] markdown-forward-page
C-x n b markdown-narrow-to-block
C-x n p markdown-narrow-to-page
C-x n s markdown-narrow-to-subtree
DEL markdown-outdent-or-delete
M-RET markdown-insert-list-item
M-h markdown-mark-paragraph
M-n markdown-next-link
M-p markdown-previous-link
M-{ markdown-backward-paragraph
M-} markdown-forward-paragraph
RET markdown-enter-key
TAB markdown-cycle

Probably introduced at or before Emacs version 26.1.

Key Bindings

Source Code

;; Defined in ~/.emacs.d/elpa/markdown-mode-20260321.143/markdown-mode.el
;;;###autoload
(define-derived-mode markdown-mode text-mode "Markdown"
  "Major mode for editing Markdown files."
  (when buffer-read-only
    (when (or (not (buffer-file-name)) (file-writable-p (buffer-file-name)))
      (setq-local buffer-read-only nil)))
  ;; Natural Markdown tab width
  (setq tab-width 4)
  ;; Comments
  (setq-local comment-start "<!-- ")
  (setq-local comment-end " -->")
  (setq-local comment-start-skip "<!--[ \t]*")
  (setq-local comment-column 0)
  (setq-local comment-auto-fill-only-comments nil)
  (setq-local comment-use-syntax t)
  ;; Sentence
  (setq-local sentence-end-base "[.?!…‽][]\"'”’)}»›*_`~]*")
  ;; Syntax
  (add-hook 'syntax-propertize-extend-region-functions
            #'markdown-syntax-propertize-extend-region nil t)
  (add-hook 'jit-lock-after-change-extend-region-functions
            #'markdown-font-lock-extend-region-function t t)
  (setq-local syntax-propertize-function #'markdown-syntax-propertize)
  (syntax-propertize (point-max)) ;; Propertize before hooks run, etc.
  ;; Font lock.
  (setq font-lock-defaults
        '(markdown-mode-font-lock-keywords
          nil nil nil nil
          (font-lock-multiline . t)
          (font-lock-syntactic-face-function . markdown-syntactic-face)
          (font-lock-extra-managed-props
           . (composition display invisible rear-nonsticky
                          keymap help-echo mouse-face))))
  (if markdown-hide-markup
      (add-to-invisibility-spec 'markdown-markup)
    (remove-from-invisibility-spec 'markdown-markup))
  ;; Math mode
  (when markdown-enable-math (markdown-toggle-math t))
  ;; Add a buffer-local hook to reload after file-local variables are read
  (add-hook 'hack-local-variables-hook #'markdown-handle-local-variables nil t)
  ;; For imenu support
  (setq-local imenu-create-index-function (if markdown-nested-imenu-heading-index
                                              #'markdown-imenu-create-nested-index
                                            #'markdown-imenu-create-flat-index)
              imenu-submenus-on-top nil)

  ;; Defun movement
  (setq-local beginning-of-defun-function #'markdown-beginning-of-defun)
  (setq-local end-of-defun-function #'markdown-end-of-defun)
  ;; Paragraph filling
  (setq-local fill-paragraph-function #'markdown-fill-paragraph)
  (setq-local paragraph-start
              ;; Should match start of lines that start or separate paragraphs
              (mapconcat #'identity
                         '(
                           "\f" ; starts with a literal line-feed
                           "[ \t\f]*$" ; space-only line
                           "\\(?:[ \t]*>\\)+[ \t\f]*$"; empty line in blockquote
                           "[ \t]*[*+-][ \t]+" ; unordered list item
                           "[ \t]*\\(?:[0-9]+\\|#\\)\\.[ \t]+" ; ordered list item
                           "[ \t]*\\[\\S-*\\]:[ \t]+" ; link ref def
                           "[ \t]*:[ \t]+" ; definition
                           "^|" ; table or Pandoc line block
                           )
                         "\\|"))
  (setq-local paragraph-separate
              ;; Should match lines that separate paragraphs without being
              ;; part of any paragraph:
              (mapconcat #'identity
                         '("[ \t\f]*$" ; space-only line
                           "\\(?:[ \t]*>\\)+[ \t\f]*$"; empty line in blockquote
                           ;; The following is not ideal, but the Fill customization
                           ;; options really only handle paragraph-starting prefixes,
                           ;; not paragraph-ending suffixes:
                           ".*  $" ; line ending in two spaces
                           "^#+"
                           "^\\(?:   \\)?[-=]+[ \t]*$" ;; setext
                           "[ \t]*\\[\\^\\S-*\\]:[ \t]*$") ; just the start of a footnote def
                         "\\|"))
  (setq-local adaptive-fill-first-line-regexp "\\`[ \t]*[A-Z]?>[ \t]*?\\'")
  (setq-local adaptive-fill-regexp "\\s-*")
  (setq-local adaptive-fill-function #'markdown-adaptive-fill-function)
  (setq-local fill-forward-paragraph-function #'markdown-fill-forward-paragraph)
  ;; Outline mode
  (setq-local outline-regexp markdown-regex-header)
  (setq-local outline-level #'markdown-outline-level)
  ;; Cause use of ellipses for invisible text.
  (add-to-invisibility-spec '(outline . t))
  ;; ElDoc support
  (if (boundp 'eldoc-documentation-functions)
      (add-hook 'eldoc-documentation-functions #'markdown-eldoc-function nil t)
    (add-function :before-until (local 'eldoc-documentation-function)
                  #'markdown-eldoc-function))
  ;; Inhibiting line-breaking:
  ;; Separating out each condition into a separate function so that users can
  ;; override if desired (with remove-hook)
  (add-hook 'fill-nobreak-predicate
            #'markdown-line-is-reference-definition-p nil t)
  (add-hook 'fill-nobreak-predicate
            #'markdown-pipe-at-bol-p nil t)

  ;; Indentation
  (setq-local indent-line-function markdown-indent-function)
  (setq-local indent-region-function #'markdown--indent-region)

  ;; Flyspell
  (setq-local flyspell-generic-check-word-predicate
              #'markdown-flyspell-check-word-p)

  ;; Electric quoting
  (add-hook 'electric-quote-inhibit-functions
            #'markdown--inhibit-electric-quote nil :local)

  ;; drag and drop handler
  (let ((dnd-handler (if (>= emacs-major-version 30)
                         #'markdown--dnd-multi-local-file-handler
                       #'markdown--dnd-local-file-handler)))
    (setq-local dnd-protocol-alist (append
                                    (list (cons "^file:///" dnd-handler)
                                          (cons "^file:/[^/]" dnd-handler)
                                          (cons "^file:[^/]" dnd-handler))
                                    dnd-protocol-alist)))

  ;; media handler
  (when (version< "29" emacs-version)
    (yank-media-handler "image/.*" #'markdown--image-media-handler)
    ;; TODO support other than GNOME, like KDE etc
    (yank-media-handler "x-special/gnome-copied-files" #'markdown--file-media-handler))

  ;; Make checkboxes buttons
  (when markdown-make-gfm-checkboxes-buttons
    (markdown-make-gfm-checkboxes-buttons (point-min) (point-max))
    (add-hook 'after-change-functions #'markdown-gfm-checkbox-after-change-function t t)
    (add-hook 'change-major-mode-hook #'markdown-remove-gfm-checkbox-overlays t t))

  ;; edit-indirect
  (add-hook 'edit-indirect-after-commit-functions
            #'markdown--edit-indirect-after-commit-function
            nil 'local)

  ;; Marginalized headings
  (when markdown-marginalize-headers
    (add-hook 'window-configuration-change-hook
              #'markdown-marginalize-update-current nil t))

  ;; add live preview export hook
  (add-hook 'after-save-hook #'markdown-live-preview-if-markdown t t)
  (add-hook 'kill-buffer-hook #'markdown-live-preview-remove-on-kill t t)

  ;; Add a custom keymap for `visual-line-mode' so that activating
  ;; this minor mode does not override markdown-mode's keybindings.
  ;; FIXME: Probably `visual-line-mode' should take care of this.
  (let ((oldmap (cdr (assoc 'visual-line-mode minor-mode-map-alist)))
        (newmap (make-sparse-keymap)))
    (set-keymap-parent newmap oldmap)
    (define-key newmap [remap move-beginning-of-line] nil)
    (define-key newmap [remap move-end-of-line] nil)
    (make-local-variable 'minor-mode-overriding-map-alist)
    (push `(visual-line-mode . ,newmap) minor-mode-overriding-map-alist)))