convert markdown to html in new tab

131 views
Skip to first unread message

Rick Dooling

unread,
Jan 9, 2014, 11:42:47 AM1/9/14
to vim...@googlegroups.com
Dear Vim Scripters:

I know how to run external commands and send the output to new files and such, but I'm wondering if a Vim scripter can help me do something that has to be a common task.

Assume I have a buffer open in Vim called file.markdown

I want to run my external markdown processor of choice, say pandoc, on the contents of that buffer and have it appear in a new tab called file.html.

In other words I don't want a filter to replace the markdown. I want to run the external command and have the output placed in a new appropriately named buffer in a new tab.

THANK YOU

Rick

Message has been deleted

Rick Dooling

unread,
Jan 9, 2014, 12:14:02 PM1/9/14
to vim...@googlegroups.com
I have tried this:

!pandoc % -o %<.html | tabe %<.html

But I get this error

/bin/bash: tabe: command not found

shell returned 127

Looking for a bash command not a vim command, it seems.

Nikolay Pavlov

unread,
Jan 9, 2014, 12:22:52 PM1/9/14
to vim...@googlegroups.com


On Jan 9, 2014 9:13 PM, "Rick Dooling" <rpdo...@gmail.com> wrote:
>
> On Thursday, January 9, 2014 10:42:47 AM UTC-6, Rick Dooling wrote:

> > Dear Vim Scripters:
> >
> > I know how to run external commands and send the output to new files and such, but I'm wondering if a Vim scripter can help me do something that has to be a common task.

> I have tried this:
>
> !pandoc % -o %<.html | tabe %<.html
>
> But I get this error
>
> /bin/bash: tabe: command not found
>
> shell returned 127
>
> Looking for a bash command not a vim command, it seems.

Not exactly. :! takes pipe symbol as its argument. Vim is not ever looking for any shell commands (except for the case when you use executable()), it is just passing everything to shell. As pipe and following characters were assumed to be :! argument bash got tabe. You need to use :execute to avoid such problems.

>
> >
> > Assume I have a buffer open in Vim called file.markdown
> >
> > I want to run my external markdown processor of choice, say pandoc, on the contents of that buffer and have it appear in a new tab called file.html.
> >
> > In other words I don't want a filter to replace the markdown. I want to run the external command and have the output placed in a new appropriately named buffer in a new tab.
> >
> > THANK YOU
> >
> > Rick
>

> --
> --
> You received this message from the "vim_use" maillist.
> Do not top-post! Type your reply below the text you are replying to.
> For more information, visit http://www.vim.org/maillist.php
>
> ---
> You received this message because you are subscribed to the Google Groups "vim_use" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Rick Dooling

unread,
Jan 9, 2014, 12:26:15 PM1/9/14
to vim...@googlegroups.com
On Thursday, January 9, 2014 10:42:47 AM UTC-6, Rick Dooling wrote:

Thank you,

I shall investigate execute!

Rick Dooling

unread,
Jan 9, 2014, 2:50:35 PM1/9/14
to vim...@googlegroups.com

Quite an education! Still learning Vim. I mainly just write in it. Very little vim scripting.

This works inside Vim on the command line

:execute "!pandoc % -o html" | :tabe %:t:r.html

But I could not map it. I would get weird errors about using :p:h.

So I did this instead.


function! MD()
exe "!pandoc % -o html"
exe ":tabe %:t:r.html"
endfunction

Nikolay Pavlov

unread,
Jan 9, 2014, 3:29:41 PM1/9/14
to vim...@googlegroups.com

You do not need any :exe here in the current state. But you need :exe in the first statement: do not ever use % in shell commands as it is not doing any escaping. E.g. if name of currently edited file contains space first line of function MD will not do its job.

You should use

    execute '!pandoc" shellescape(@%, 1) '-o ' shellescape(expand('%:t:r')) '.html'

instead. This does not apply to vim commands: :tabe %:t:r.html is fine.

Rick Dooling

unread,
Jan 9, 2014, 4:07:06 PM1/9/14
to vim...@googlegroups.com
THANK YOU!

I probably would never have noticed the shellescape because I never use spaces in filenames. But always nice to be ready for cross platform.

I'll leave this here for any other neophyte.

function! MD()
exe '!pandoc' shellescape(@%, 1) ' -o ' shellescape(expand('%:t:r')).'.html'

Nikolay Pavlov

unread,
Jan 9, 2014, 4:16:34 PM1/9/14
to vim...@googlegroups.com

Sorry, but I had a typo: both shellescape() calls should have second argument.

By the way, colon before tabe is optional. In mapping it is used to enter command mode, here it is just ignored (I usually use it to mark start of the body of :autocmd and :command: command -nargs=1 Foo :echo 'foo'). It does not harm in any case.

Jacobo de Vera

unread,
Jan 10, 2014, 7:16:31 AM1/10/14
to vim_use
This is a very cool user case, I hadn't even thought of this but it does come quite handy.

I wonder, though, if there would be a way to do this without involving files at all, that is, passing whatever is in the buffer to pandoc as STDIN and then getting pandoc's STDOUT into a new buffer, in a split window or a new tab.

If I run pandoc as a filter with :%!pandoc ... it will replace the current buffer contents.

Regards,

-- 
Jacobo de Vera
http://www.jacobodevera.com
@jovianjake

Rick Dooling

unread,
Jan 10, 2014, 1:14:42 PM1/10/14
to vim...@googlegroups.com
This one grabs the buffer contents, converts it to HTML, and sends it to the clipboard for pasting into WordPress or whatever.

" Send Text Through Filter To Clipboard:
" http://vim.wikia.com/wiki/Use_filter_commands_to_process_text
function! MDC()
:redir @+
" No output file specified so it goes to STDOUT
exe '!pandoc %'
:redir END
endfunction

This morning I was monkeying with using Python in Vim to do this. That also works. Then you can use Python's Markdown module.

ZyX

unread,
Jan 10, 2014, 1:18:43 PM1/10/14
to vim...@googlegroups.com
> This one grabs the buffer contents, converts it to HTML, and sends it to the clipboard for pasting into WordPress or whatever.

It does not. Just run in *terminal* vim.

Rick Dooling

unread,
Jan 10, 2014, 1:22:41 PM1/10/14
to vim...@googlegroups.com
On Friday, January 10, 2014 12:18:43 PM UTC-6, ZyX wrote:
> > This one grabs the buffer contents, converts it to HTML, and sends it to the clipboard for pasting into WordPress or whatever.
>
> It does not. Just run in *terminal* vim.

Mmm. I'm on a MacBook Pro using MacVim?

Don't know if that would do it.

Just tried it again to be sure.

Jacobo de Vera

unread,
Jan 10, 2014, 1:56:37 PM1/10/14
to vim_use
On Fri, Jan 10, 2014 at 6:14 PM, Rick Dooling <rpdo...@gmail.com> wrote:
>
>
> This one grabs the buffer contents, converts it to HTML, and sends it to the clipboard for pasting into WordPress or whatever.
>
> " Send Text Through Filter To Clipboard:
> " http://vim.wikia.com/wiki/Use_filter_commands_to_process_text
> function! MDC()
> :redir @+
> " No output file specified so it goes to STDOUT
> exe '!pandoc %'
> :redir END
> endfunction
>
> This morning I was monkeying with using Python in Vim to do this. That also works. Then you can use Python's Markdown module.
>


But does it though? From what I see the line:

exe '!pandoc %'

Is running pandoc with the *file* open in the current buffer as input,
which means you have to have a file and you have to save it in order
for it to work. This is similar to what was shown in previous emails,
but what I was wondering is whether one can use something similar that
uses buffer contents, not file contents.

Rick Dooling

unread,
Jan 10, 2014, 2:03:37 PM1/10/14
to vim...@googlegroups.com

if no file is specified with -o in pandoc it goes to STDOUT, and you are using redir to redirect STOUT to the clipboard. At least that's how I understand it.

Another scripting angle, esp. using Python or Ruby is just run the commands, save the file, and tell vim to open the file in a new buffer.

Now that I've been playing, the redirect to the clipboard is actually even more useful, because you can use Marked2 or some other html converter/viewer to check things before loading your html up to go paste.

Rick

Jacobo de Vera

unread,
Jan 10, 2014, 4:06:44 PM1/10/14
to vim_use
On Fri, Jan 10, 2014 at 7:03 PM, Rick Dooling <rpdo...@gmail.com> wrote:
>
>> > This one grabs the buffer contents, converts it to HTML, and sends it to the clipboard for pasting into WordPress or whatever.
>>
>> > " Send Text Through Filter To Clipboard:
>> > " http://vim.wikia.com/wiki/Use_filter_commands_to_process_text
>> > function! MDC()
>> > :redir @+
>> > " No output file specified so it goes to STDOUT
>> > exe '!pandoc %'
>> > :redir END
>> > endfunction
>>
>> > This morning I was monkeying with using Python in Vim to do this. That also works. Then you can use Python's Markdown module.
>>
>> But does it though? From what I see the line:
>>
>> exe '!pandoc %'
>>
>> Is running pandoc with the *file* open in the current buffer as input,
>> which means you have to have a file and you have to save it in order
>> for it to work. This is similar to what was shown in previous emails,
>> but what I was wondering is whether one can use something similar that
>> uses buffer contents, not file contents.
>>

>
> if no file is specified with -o in pandoc it goes to STDOUT, and you are using redir to redirect STOUT to the clipboard. At least that's how I understand it.
>
> Another scripting angle, esp. using Python or Ruby is just run the commands, save the file, and tell vim to open the file in a new buffer.
>
> Now that I've been playing, the redirect to the clipboard is actually even more useful, because you can use Marked2 or some other html converter/viewer to check things before loading your html up to go paste.
>
> Rick
>

Rick, I think you and I are talking about two different things here. I
am talking about the input and you are talking about the output. So
yes, pandoc sends its output to stdout, which is captured by Vim. But
the input, it takes from a file name, which is the value after
replacing '%' on that exe line.

Say you create a new file, then write some markdown, and, before
saving, you run that function. You'd get nothing, because pandoc
receives, as input, an empty file. Pandoc, and many other programs,
however, support getting their input from stdin. In vim you can send
the contents of the current buffer to a process' stdin, and then the
process' stdout replaces those contents, just like when one does:

:%!sort

What I was trying to ask is. How does one send those unsaved contents
to a program without getting them replaced with the output of such
program, but instead get the output in a separate tab? The function
you sent provides a solution for the second part, since it will
redirect output to a variable or a register. Now we are only missing
the first part, which we nearly have, but it uses files, rather than
buffer contents.

Hope that clarifies my question a little.

Nikolay Pavlov

unread,
Jan 10, 2014, 4:21:53 PM1/10/14
to vim...@googlegroups.com

If it is terminal vim output is not captured. In fact command executed with :! gets direct access to the terminal. For capturing output there is system().

>
> Say you create a new file, then write some markdown, and, before
> saving, you run that function. You'd get nothing, because pandoc
> receives, as input, an empty file. Pandoc, and many other programs,
> however, support getting their input from stdin. In vim you can send
> the contents of the current buffer to a process' stdin, and then the
> process' stdout replaces those contents, just like when one does:
>
> :%!sort
>
> What I was trying to ask is. How does one send those unsaved contents
> to a program without getting them replaced with the output of such
> program, but instead get the output in a separate tab? The function
> you sent provides a solution for the second part, since it will
> redirect output to a variable or a register. Now we are only missing
> the first part, which we nearly have, but it uses files, rather than
> buffer contents.
>
> Hope that clarifies my question a little.
>
> Regards,
>
> --
> Jacobo de Vera
> http://www.jacobodevera.com
> @jovianjake
>

Rick Dooling

unread,
Jan 10, 2014, 5:19:18 PM1/10/14
to vim...@googlegroups.com
On Friday, January 10, 2014 3:06:44 PM UTC-6, Jacobo de Vera wrote:

I think I am not the person to answer. I have never tried to do anything with buffer contents before saving them as a file. In fact, my maps often begin with :w<CR> to make sure that the save happens first, or I guess :up<CR>. I think it would be a bad idea to attempt anything with a filter or external program on an unsaved file. One error and poof.

David Sanson

unread,
Feb 1, 2014, 10:21:33 PM2/1/14
to vim...@googlegroups.com
Something like this is close to perfect:

:tabnew | read !pandoc #

But, just as '%' runs into trouble with escapes, so does '#'. So this is better:

:tabnew | exe "read !pandoc " . shellescape(@#, 1)

And if you want to map it, you'll need to escape the '|', so:

nmap <leader>h :tabnew \| exe "read !pandoc " . shellescape{@#, 1)

(see http://stackoverflow.com/a/8292838/1342986 and the surrounding comments.)

Richard Dooling

unread,
Feb 4, 2014, 10:56:53 PM2/4/14
to vim...@googlegroups.com
Nice!

Thanks, David!


--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to a topic in the Google Groups "vim_use" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vim_use/i1mOvKCPuD4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vim_use+u...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.



--

rd

Reply all
Reply to author
Forward
0 new messages