Skip to content

Instantly share code, notes, and snippets.

@natesilva
Created May 6, 2011 23:44
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save natesilva/960015 to your computer and use it in GitHub Desktop.
Save natesilva/960015 to your computer and use it in GitHub Desktop.
Vim: Preview a Markdown document in the default browser on Windows or Mac OS X
"
" While editing a Markdown document in Vim, preview it in the
" default browser.
"
" Author: Nate Silva
"
" To install: Place markdown.vim in ~/.vim/ftplugin or
" %USERPROFILE%\vimfiles\ftplugin.
"
" To use: While editing a Markdown file, press ',p' (comma p)
"
" Tested on Windows and Mac OS X. Should work on Linux if you set
" BROWSER_COMMAND properly.
"
" Requires the `markdown` command to be on the system path. If you
" do not have the `markdown` command, install one of the following:
"
" http://www.pell.portland.or.us/~orc/Code/discount/
" http://www.freewisdom.org/projects/python-markdown/
"
function!PreviewMarkdown()
" **************************************************************
" Configurable settings
let MARKDOWN_COMMAND = 'markdown'
if has('win32')
" note important extra pair of double-quotes
let BROWSER_COMMAND = 'cmd.exe /c start ""'
else
let BROWSER_COMMAND = 'open'
endif
" End of configurable settings
" **************************************************************
silent update
let output_name = tempname() . '.html'
" Some Markdown implementations, especially the Python one,
" work best with UTF-8. If our buffer is not in UTF-8, convert
" it before running Markdown, then convert it back.
let original_encoding = &fileencoding
let original_bomb = &bomb
if original_encoding != 'utf-8' || original_bomb == 1
set nobomb
set fileencoding=utf-8
silent update
endif
" Write the HTML header. Do a CSS reset, followed by setting up
" some basic styles from YUI, so the output looks nice.
let file_header = ['<html>', '<head>',
\ '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">',
\ '<title>Markdown Preview</title>',
\ '<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssreset/reset-min.css">',
\ '<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssbase/base-min.css">',
\ '<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.3.0/build/cssfonts/fonts-min.css">',
\ '<style>body{padding:20px;}div#container{background-color:#F2F2F2;padding:0 20px;margin:0px;border:solid #D0D0D0 1px;}</style>',
\ '</head>', '<body>', '<div id="container">']
call writefile(file_header, output_name)
let md_command = '!' . MARKDOWN_COMMAND . ' "' . expand('%:p') . '" >> "' .
\ output_name . '"'
silent exec md_command
if has('win32')
let footer_name = tempname()
call writefile(['</div></body></html>'], footer_name)
silent exec '!type "' . footer_name . '" >> "' . output_name . '"'
exec delete(footer_name)
else
silent exec '!echo "</div></body></html>" >> "' .
\ output_name . '"'
endif
" If we changed the encoding, change it back.
if original_encoding != 'utf-8' || original_bomb == 1
if original_bomb == 1
set bomb
endif
silent exec 'set fileencoding=' . original_encoding
silent update
endif
silent exec '!' . BROWSER_COMMAND . ' "' . output_name . '"'
exec input('Press ENTER to continue...')
echo
exec delete(output_name)
endfunction
" Map this feature to the key sequence ',p' (comma lowercase-p)
map ,p :call PreviewMarkdown()<CR>
@caseywatts
Copy link

Beautiful!
I love how simple this is :)

@cykerway
Copy link

cykerway commented Sep 8, 2012

Great script!

Tested on Linux:

  1. I don't know whether Linux has an 'open' command, but 'xdg-open' generally works.
  2. Some terminals won't redraw after the script exits. I don't know whose problem it is. But add a 'redraw!' command in the end fix it.

@pacoqueen
Copy link

xdg-open doesn't work for me.

I added this function:

    function! OpenDocument(document)
        if has("win32") || has("win64")
            " It's often recommended to use the build-in 'start' command of the cmd
            " shell, but that didn't seem to work on my Windows 7 machine. Invoking
            " Explorer opens the document correctly
            call system("explorer \"" . a:document . "\"")
        elseif has("unix")
            " OS X or Linux? Note that we can't rely on has("mac") here as this
            " isn't set for the console Vim shipping with OS X
            let s:uname = system("uname")
            if s:uname == "Darwin\n"
                " Use 'open' command on OS X
                call system("open '" . a:document . "'")
            else
                " Assume we're on Linux, use 'xdg-open'
                call system("xdg-open '" . a:document . "'")
            endif
        endif
    endfunc

And changed this:

    silent exec '!' . BROWSER_COMMAND . ' "' . output_name . '"'

for this:

    call OpenDocument(output_name)

@josericardo
Copy link

Hi, thanks for contributing. It works just great.

By the way, have you considered making a pull request to https://github.com/tpope/vim-markdown ?

Best regards :)

@mmtung
Copy link

mmtung commented Jun 19, 2018

Nowadays probably the best command tool for conversion is pandoc. The changes in the config section of markdown.vim are minimal (I am using Linux):

" **************************************************************
" Configurable settings

let MARKDOWN_COMMAND = 'pandoc -s --filter pandoc-citeproc'

if has('win32')
    " note important extra pair of double-quotes
    let BROWSER_COMMAND = 'cmd.exe /c start ""'
else
    let BROWSER_COMMAND = 'firefox'
endif

" End of configurable settings
" **************************************************************

Best!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment