Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add markdown-native-preview-mode to view previewed output within emacs #36

Merged
merged 18 commits into from
Nov 8, 2015
Merged
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,14 @@ keybindings by pressing <kbd>C-c C-h</kbd>.
and save the result in the file `basename.html`, where
`basename` is the name of the Markdown file with the extension
removed. *Export and View:* press <kbd>C-c C-c v</kbd> to export the
file and view it in a browser. **For both export commands, the
output file will be overwritten without notice.**
*Open:* <kbd>C-c C-c o</kbd> will open the Markdown source file directly
using `markdown-open-command`.
file and view it in a browser. *Open:* <kbd>C-c C-c o</kbd> will open
the Markdown source file directly using `markdown-open-command`.
*Live Export*: Press <kbd>C-c C-c l</kbd> to turn on
`markdown-live-preview-mode` to view the exported output
side-by-side with the source Markdown. **For all export commands,
the output file will be overwritten without notice.**
`markdown-live-preview-window-function` can be customized to open
in a browser other than `eww`.

To summarize:

Expand All @@ -221,6 +225,7 @@ keybindings by pressing <kbd>C-c C-h</kbd>.
- <kbd>C-c C-c v</kbd>: `markdown-command` > `basename.html` > browser.
- <kbd>C-c C-c w</kbd>: `markdown-command` > kill ring.
- <kbd>C-c C-c o</kbd>: `markdown-open-command`.
- <kbd>C-c C-c l</kbd>: `markdown-live-preview-mode` > `*eww*` buffer.

<kbd>C-c C-c c</kbd> will check for undefined references. If there are
any, a small buffer will open with a list of undefined
Expand Down
105 changes: 101 additions & 4 deletions markdown-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,14 @@
;; and save the result in the file `basename.html`, where
;; `basename` is the name of the Markdown file with the extension
;; removed. *Export and View:* press `C-c C-c v` to export the
;; file and view it in a browser. **For both export commands, the
;; output file will be overwritten without notice.**
;; *Open:* `C-c C-c o` will open the Markdown source file directly
;; using `markdown-open-command'.
;; file and view it in a browser. *Open:* `C-c C-c o` will open
;; the Markdown source file directly using `markdown-open-command'.
;; *Live Export*: Press `C-c C-c l` to turn on
;; `markdown-live-preview-mode' to view the exported output
;; side-by-side with the source Markdown. **For all export commands,
;; the output file will be overwritten without notice.**
;; `markdown-live-preview-window-function' can be customized to open
;; in a browser other than `eww'.
;;
;; To summarize:
;;
Expand All @@ -270,6 +274,7 @@
;; - `C-c C-c v`: `markdown-command' > `basename.html` > browser.
;; - `C-c C-c w`: `markdown-command' > kill ring.
;; - `C-c C-c o`: `markdown-open-command'.
;; - `C-c C-c l`: `markdown-live-preview-mode' > `*eww*` buffer.
;;
;; `C-c C-c c` will check for undefined references. If there are
;; any, a small buffer will open with a list of undefined
Expand Down Expand Up @@ -1003,6 +1008,18 @@ to `nil' instead. See `font-lock-support-mode' for more details."
:group 'markdown
:type 'boolean)

(defcustom markdown-live-preview-window-function 'markdown-live-preview-window-eww
"Function to display preview of Markdown output within Emacs. Function must
update the buffer containing the preview and return the buffer."
:group 'markdown
:type 'function)

(defcustom markdown-live-preview-delete-export t
"When non-nil, deleted exported html file when using
`markdown-live-preview-export'."
:group 'markdown
:type 'boolean)


;;; Font Lock =================================================================

Expand Down Expand Up @@ -3543,6 +3560,7 @@ Assumes match data is available for `markdown-regex-italic'."
(define-key map (kbd "C-c C-c e") 'markdown-export)
(define-key map (kbd "C-c C-c v") 'markdown-export-and-preview)
(define-key map (kbd "C-c C-c o") 'markdown-open)
(define-key map (kbd "C-c C-c l") 'markdown-live-preview-mode)
(define-key map (kbd "C-c C-c w") 'markdown-kill-ring-save)
(define-key map (kbd "C-c C-c c") 'markdown-check-refs)
(define-key map (kbd "C-c C-c n") 'markdown-cleanup-list-numbers)
Expand Down Expand Up @@ -3597,6 +3615,8 @@ See also `markdown-mode-map'.")
["Export" markdown-export]
["Export & View" markdown-export-and-preview]
["Open" markdown-open]
["Live Export" markdown-live-preview-mode
:style toggle :selected markdown-live-preview-mode]
["Kill ring save" markdown-kill-ring-save]
"---"
("Headings"
Expand Down Expand Up @@ -4655,6 +4675,71 @@ current filename, but with the extension removed and replaced with .html."
(interactive)
(browse-url-of-file (markdown-export)))

(defvar-local markdown-live-preview-buffer nil
"Buffer used to preview markdown output in `markdown-live-preview-export'.")

(defun markdown-live-preview-window-eww (file)
"A `markdown-live-preview-window-function' for previewing with eww."
(eww-open-file file)
(get-buffer "*eww*"))

(defun markdown-live-preview-window-serialize (buf)
"Get window point and scroll data for all windows displaying BUF if BUF is
non-nil."
(when buf
(mapcar (lambda (win) (list win (window-point win) (window-start win)))
(get-buffer-window-list buf))))

(defun markdown-live-preview-window-deserialize (window-posns)
"Apply window point and scroll data from WINDOW-POSNS, given by
`markdown-live-preview-window-serialize'."
(destructuring-bind (win pt start) window-posns
(when (window-live-p win)
(set-window-buffer win markdown-live-preview-buffer)
(set-window-point win pt)
(set-window-start win start))))

(defun markdown-live-preview-export ()
"Export to XHTML using `markdown-export' and browse the resulting file within
Emacs using `markdown-live-preview-window-function' Return the buffer displaying
the rendered output."
(interactive)
(let ((export-file (markdown-export))
;; get positions in all windows currently displaying output buffer
(window-data
(markdown-live-preview-window-serialize markdown-live-preview-buffer))
(cur-buf (current-buffer)))
(save-window-excursion
;; protect against `markdown-live-preview-window-function' changing
;; `current-buffer'
(let ((output-buffer
(funcall markdown-live-preview-window-function export-file)))
(with-current-buffer cur-buf
(setq markdown-live-preview-buffer output-buffer))))
;; reset all windows displaying output buffer to where they were, now with
;; the new output
(mapc #'markdown-live-preview-window-deserialize window-data)
(when (and markdown-live-preview-delete-export
export-file (file-exists-p export-file))
(delete-file export-file)
(let ((buf (get-file-buffer export-file))) (when buf (kill-buffer buf))))
markdown-live-preview-buffer))

(defun markdown-live-preview-remove ()
(when (buffer-live-p markdown-live-preview-buffer)
(kill-buffer markdown-live-preview-buffer))
(setq markdown-live-preview-buffer nil))

(defun markdown-live-preview-if-markdown ()
(when (and (derived-mode-p 'markdown-mode)
markdown-live-preview-mode)
(markdown-live-preview-export)))

(defun markdown-live-preview-remove-on-kill ()
(when (and (derived-mode-p 'markdown-mode)
markdown-live-preview-mode)
(markdown-live-preview-remove)))

(defun markdown-open ()
"Open file for the current buffer with `markdown-open-command'."
(interactive)
Expand Down Expand Up @@ -5221,6 +5306,18 @@ before regenerating font-lock rules for extensions."
;; do the initial link fontification
(markdown-fontify-buffer-wiki-links))


;;; Live Preview Mode ============================================
(define-minor-mode markdown-live-preview-mode
"Toggle native previewing on save for a specific markdown file."
:lighter " MD-Preview"
(cond (markdown-live-preview-mode
(switch-to-buffer-other-window (markdown-live-preview-export)))
(t (markdown-live-preview-remove))))

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


(provide 'markdown-mode)
;; Local Variables:
Expand Down
12 changes: 8 additions & 4 deletions tests/markdown-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
(expand-file-name (file-name-directory
(or load-file-name buffer-file-name))))

(defconst markdown-test-font-lock-function
(if (and noninteractive (fboundp 'font-lock-ensure))
#'font-lock-ensure #'font-lock-fontify-buffer))

(defmacro markdown-test-string-mode (mode string &rest body)
"Run BODY in a temporary buffer containing STRING in MODE."
`(let ((win (selected-window)))
Expand All @@ -49,7 +53,7 @@
(setq-default indent-tabs-mode nil)
(insert ,string)
(goto-char (point-min))
(font-lock-fontify-buffer)
(funcall markdown-test-font-lock-function)
(prog1 ,@body (kill-buffer))))))

(defmacro markdown-test-file-mode (mode file &rest body)
Expand All @@ -60,7 +64,7 @@
(insert-file-contents fn)
(funcall ,mode)
(goto-char (point-min))
(font-lock-fontify-buffer)
(funcall markdown-test-font-lock-function)
,@body))))

(defmacro markdown-test-string (string &rest body)
Expand Down Expand Up @@ -94,7 +98,7 @@ This file is not saved."
(insert-file-contents fn)
(markdown-mode)
(goto-char (point-min))
(font-lock-fontify-buffer)
(funcall markdown-test-font-lock-function)
,@body
(set-buffer-modified-p nil)
(kill-buffer buf)
Expand Down Expand Up @@ -2736,7 +2740,7 @@ indented the same amount."
"Test markdown math mode."
(markdown-test-file "math.text"
(markdown-enable-math t)
(font-lock-fontify-buffer)
(funcall markdown-test-font-lock-function)
(markdown-test-range-has-face 1 32 nil)
(markdown-test-range-has-face 33 33 markdown-markup-face)
(markdown-test-range-has-face 34 45 markdown-math-face)
Expand Down