Improved integration between Vim and its environment (full-screen, open URL, background execute())

149 views
Skip to first unread message

Peter Odding

unread,
Jun 13, 2010, 11:42:58 AM6/13/10
to vim_dev
Hi list!

I wrote a plug-in that aims to improve the integration between Vim and
its environment by providing functions to switch to full-screen, open
URLs in the user's default web browser and execute external commands in
the background without opening a command prompt window. A DLL is
included to perform these things on Windows, while on UNIX external
commands are used (such as wmctrl, gnome-open, kde-open, etc.)

I'm not sure yet how portable the included DLL file is between different
types of Windows installations. You can find a first ZIP release of the
plug-in on its Vim scripts page at
http://www.vim.org/scripts/script.php?script_id=3123

I'd be very grateful if some of you can test the plug-in by unpacking
the ZIP release in your %USERPROFILE%\vimfiles or ~/.vim/ directory,
restarting Vim and testing the three functions as follows:

1. Execute :call xolox#shell#openurl('http://www.vim.org/')

Does this open your preferred (or best available) web browser? On UNIX
if $DISPLAY is empty the plug-in will switch to a command-line browser.

2. (Windows only) Execute :call xolox#shell#execute('notepad')

Does this start Notepad without blocking Vim's window and without
opening a command prompt window to run the command?

3. In graphical Vim execute :call xolox#shell#fullscreen()

Is Vim's GUI window properly switched to full-screen mode? If so you can
return to normal mode by calling the function again. If you're stuck in
full-screen Vim, save your existing buffers and press `Alt-F4`, that
should always work.

One last thing: I run Windows in a virtual machine which isn't exposed
to the outside world much, however I don't have a virus scanner
available and didn't check the freshly compiled DLL, so if you don't
trust me feel free to scan it yourself before trying the plug-in :-)

Thanks for your time,

- Peter Odding

* http://www.vim.org/scripts/script.php?script_id=3114

Sergey Khorev

unread,
Jun 13, 2010, 2:17:46 PM6/13/10
to vim...@googlegroups.com
> I wrote a plug-in that aims to improve integration between Vim and its

> environment by providing functions to switch to full-screen, open URLs in
> the user's default web browser and execute external commands in the
> background without opening a command prompt window.

Re execution background processes, what's wrong with :call system("cmd
/c start notepad")?
And URLs could be opened in the same way too: :call system("cmd /c
start http://www.vim.org")

--
Sergey Khorev
http://sites.google.com/site/khorser
Can anybody think of a good tagline I can steal?

Lech Lorens

unread,
Jun 13, 2010, 3:27:29 PM6/13/10
to Sergey Khorev, vim...@googlegroups.com
On 13-Jun-2010 Sergey Khorev <sergey...@gmail.com> wrote:
> > I wrote a plug-in that aims to improve integration between Vim and its
> > environment by providing functions to switch to full-screen, open URLs in
> > the user's default web browser and execute external commands in the
> > background without opening a command prompt window.
>
> Re execution background processes, what's wrong with :call system("cmd
> /c start notepad")?
> And URLs could be opened in the same way too: :call system("cmd /c
> start http://www.vim.org")

llorens@neo ~ $ which cmd
llorens@neo ~ $ type cmd
-bash: type: cmd: not found

This seems to answer the question of portability of using cmd ;-)

Unless you mean why it is necessary to have a DLL to perform these
operations on Windows.

--
Cheers,
Lech

Peter Odding

unread,
Jun 13, 2010, 8:50:24 PM6/13/10
to vim...@googlegroups.com
Hi Sergey,

> Re execution background processes, what's wrong with :call system("cmd
> /c start notepad")?

On Windows when you create a child process running a command-line
program (such as Exuberant Ctags) a command prompt window automatically
pops up. If you don't want this you have to explicitly request it using
the CREATE_NO_WINDOW flag to CreateProcess() and Vim doesn't do this.
Additionally because Vim uses the command-line program vimrun.exe* to
wrap child processes created using the system() function, it will always
(at least temporarily) show a command prompt window that (again
temporarily) steals focus from Vim.

The reason those command prompts windows bother me is that my
easytags.vim** plug-in runs Exuberant Ctags every time the CursorHold
autocmd fires and the current buffer is newer (on disk) than the tags
file. On UNIX this works great but on Windows it is horrible because
command prompts keep popping up while you're typing. I noticed this
myself when testing the easytags plug-in on Windows and also got
feedback about this from users.

> And URLs could be opened in the same way too: :call system("cmd /c
> start http://www.vim.org")

I knew this was possible, which is why the plug-in contains code to do
this when the DLL isn't available. The reason I wrote openurl() was
because your technique still opens a command-prompt window and I seem to
remember that it would sometimes stay open for as long as my web browser
was running. However I just checked in my Windows XP SP3 VM and the
command prompt disappears in an instant both with Internet Explorer 8 as
well as Mozilla Firefox 3.6 as the default web browser. I guess that
makes the openurl() function inside the DLL moot :-)

- Peter Odding

* http://vimdoc.sourceforge.net/htmldoc/gui_w32.html#win32-vimrun
** http://www.vim.org/scripts/script.php?script_id=3114

Peter Odding

unread,
Jun 13, 2010, 8:59:35 PM6/13/10
to vim...@googlegroups.com
Hi again.

Before I published the shell.vim plug-in I tested my execute()
implementation by comparing the results of executing the interactive,
graphical program Notepad using Vim's system() function and my execute()
implementation, simply as a demonstration of a child process blocking
further input in Vim until the child process dies.

In the test above my execute() implementation works great, but my actual
goal with the execute() function is to run programs such as Exuberant
Ctags without waiting for them to finish AND without creating a command
prompt window. And of course I was stupid enough not to test my actual
use-case first... Turns out the code as it was would still create a
command prompt window to run command-line programs, it just appeared to
not show command prompt windows simply because Notepad is a GUI program!

I've uploaded a new release to www.vim.org that corrects this problem
and I've also changed the test instructions to more accurately reflect
the goals of the execute() implementation, you can find both at:

http://www.vim.org/scripts/script.php?script_id=3123

- Peter Odding

Sergey Khorev

unread,
Jun 14, 2010, 2:19:28 AM6/14/10
to vim...@googlegroups.com
>> Re execution background processes, what's wrong with :call system("cmd
>> /c start notepad")?
>
> On Windows when you create a child process running a command-line program
> (such as Exuberant Ctags) a command prompt window automatically pops up. If

One question, have you _actually_ seen console window when system()
function is used?

Sergey Khorev

unread,
Jun 14, 2010, 2:20:23 AM6/14/10
to vim...@googlegroups.com
> Unless you mean why it is necessary to have a DLL to perform these
> operations on Windows.

Exactly

Peter Odding

unread,
Jun 14, 2010, 7:30:31 AM6/14/10
to vim...@googlegroups.com
Sergey Khorev wrote:
> One question, have you _actually_ seen console window when system()
> function is used?

Yes I did, which is why I said as much:

> The reason those command prompts windows bother me is that my easytags.vim** plug-in runs Exuberant Ctags every time the CursorHold autocmd fires and the current buffer is newer (on disk) than the tags file. On UNIX this works great but on Windows it is horrible because command prompts keep popping up while you're typing. *I noticed this myself when testing the easytags plug-in on Windows* and also got feedback about this from users.

See also the attached screenshot of me executing Ctags from inside Vim
using the system() function, where a command prompt window is clearly
visible while ctags is executing.

- Peter Odding

screenshot.png

Tom Link

unread,
Jun 14, 2010, 2:08:45 PM6/14/10
to vim_dev
> llorens@neo ~ $ which cmd
> llorens@neo ~ $ type cmd
> -bash: type: cmd: not found
>
> This seems to answer the question of portability of using cmd ;-)

Which executable do you intend to execute in a cross-plattform
portable way?

Lech Lorens

unread,
Jun 14, 2010, 6:27:53 PM6/14/10
to Tom Link, vim_dev

What's the difference?

I used to get annoyed by the console window when running wish from Vim.

--
Cheers,
Lech

Ernie Rael

unread,
Jun 15, 2010, 1:07:33 AM6/15/10
to vim...@googlegroups.com
On 6/13/2010 5:59 PM, Peter Odding wrote:
> [...] goal with the execute() function is to run programs such as
> Exuberant Ctags without waiting for them to finish AND without
> creating a command prompt window [...]
>
I wonder what the chances are of getting a new command in vim that does
what you want (or perhaps some options for no-window and no-wait). Then
the DLL on windows would not be needed.

-ernie

Peter Odding

unread,
Jun 15, 2010, 1:24:00 AM6/15/10
to vim...@googlegroups.com
Ernie Rael wrote:
> I wonder what the chances are of getting a new command in vim that does
> what you want (or perhaps some options for no-window and no-wait). Then
> the DLL on windows would not be needed.

I've asked myself why Vim's system() function on Windows uses vimrun.exe
and shows a command prompt window. The only reason I can think of is so
that the user has a chance to quit the external command using Ctrl-C.
But strange enough the documentation only guarantees this on UNIX:

The command will be executed in "cooked" mode, so that a
CTRL-C will interrupt the command (on Unix at least).

While on UNIX it's dead easy to make system() calls asynchronous,
circumventing the "cooked" mode: you can just wrap the external command
in ( ... ) & . For what it's worth, I've never been bothered by the fact
that I have to kill runaway background processes using a process monitor
on UNIX.

- Peter Odding

John Beckett

unread,
Jun 15, 2010, 6:44:29 AM6/15/10
to vim...@googlegroups.com
Peter Odding wrote:
> I've asked myself why Vim's system() function on Windows uses
> vimrun.exe and shows a command prompt window. The only reason
> I can think of is so that the user has a chance to quit the
> external command using Ctrl-C.

Sorry if the following is not relevant (I have not followed
this thread). If you do not have to use system() to get results,
you can use :!start which is different from :! on Windows.
I believe that :!start does not use vimrun.exe.

There is some info in the following:
http://vim.wikia.com/wiki/Execute_external_programs_asynchronously_under_Windows

John

Luc Hermitte

unread,
Jun 15, 2010, 8:58:50 AM6/15/10
to vim dev
Hello,

"Tom Link" wrote :

> Which executable do you intend to execute in a cross-plattform
> portable way?

(c)make/(b)jam/aap, gcc, doxygen, ctags, latex, ...

As far as I'm concerned, the need exists. I'd rather not require an external executable/DLL though.

--
Luc Hermitte
http://lh-vim.googlecode.com/
http://hermitte.free.fr/vim/

Ernie Rael

unread,
Jun 15, 2010, 10:26:39 AM6/15/10
to vim...@googlegroups.com
On 6/14/2010 10:24 PM, Peter Odding wrote:
> Ernie Rael wrote:
>> I wonder what the chances are of getting a new command in vim that
>> does what you want (or perhaps some options for no-window and
>> no-wait). Then the DLL on windows would not be needed.
>
> [...] on UNIX it's dead easy to make system() calls asynchronous,
> circumventing the "cooked" mode: you can just wrap the external
> command in ( ... ) & [...]
Though it is possible, if the behavior could be abstracted into vim
options/commands (rather than OS specific code in scripts) then there
could be general benefit. It looks like the ":!start" is only available
on windows.

-ernie

Tom Link

unread,
Jun 16, 2010, 12:55:13 AM6/16/10
to vim_dev
> > Which executable do you intend to execute in a cross-plattform
> > portable way?
>
> (c)make/(b)jam/aap, gcc, doxygen, ctags, latex, ...

In my experience the major problem with running external apps like
those listed above is filenames -- e.g. when I use cygwin tools from
windows gvim or when I want to use the same code to run an executable
on linux and windows etc. I don't consider the cmd window a major
problem since it's often minimized anyway.

IMHO a "portable way" would have to include a way to filter filenames
(e.g. when using cygwin, I'd like to pass them to cygpath -u before
running the command). Such a function call could then look like:
call foo#fexecute('%x -9 %f', 'gzip', expand('%')), where %f expands
to a filename,

Peter Odding

unread,
Jun 16, 2010, 4:41:27 AM6/16/10
to vim...@googlegroups.com
Tom Link wrote:
> In my experience the major problem with running external apps like
> those listed above is filenames -- e.g. when I use cygwin tools from
> windows gvim or when I want to use the same code to run an executable
> on linux and windows etc. I don't consider the cmd window a major
> problem since it's often minimized anyway.
>
> IMHO a "portable way" would have to include a way to filter filenames
> (e.g. when using cygwin, I'd like to pass them to cygpath -u before
> running the command). Such a function call could then look like:
> call foo#fexecute('%x -9 %f', 'gzip', expand('%')), where %f expands
> to a filename,

I haven't had much trouble with filenames personally, as long as I stick
to forward slashes (which work on Windows) instead of backslashes (which
don't work on anything but Windows) and don't mangle user-provided
pathnames starting with drive letters on Windows. Could you be more
specific in what can go wrong?!

- Peter Odding

Tom Link

unread,
Jun 16, 2010, 1:56:51 PM6/16/10
to vim_dev
> I haven't had much trouble with filenames personally, as long as I stick
> to forward slashes (which work on Windows) instead of backslashes (which
> don't work on anything but Windows) and don't mangle user-provided
> pathnames starting with drive letters on Windows. Could you be more
> specific in what can go wrong?!

The problem occurs when using full/absolute filenames or when e.g. (on
windows) the current working directory is on a different drive than
the current buffer so that expand('%') expands to an absolute
filename. You could circumvent this problem by temporarily chdir'ing
into the buffer's directory but this could cause problems when the
executable expects the cwd to be, e.g., a project's root directory
etc.

Quite a few plugins don't work properly when you use e.g. windows gvim
with cygwin tools. Since hardly anybody mentions similar problems on
this list, I'd assume though that only very few people are affected by
this problem.

Ben Fritz

unread,
Jun 16, 2010, 4:31:02 PM6/16/10
to vim_dev


On Jun 16, 3:41 am, Peter Odding <pe...@peterodding.com> wrote:
>
> I haven't had much trouble with filenames personally, as long as I stick
> to forward slashes (which work on Windows) instead of backslashes (which
> don't work on anything but Windows) and don't mangle user-provided
> pathnames starting with drive letters on Windows. Could you be more
> specific in what can go wrong?!
>

In general, I don't have problems with forward/backward slashes on
Windows. Purely within Vim, there are no problems. But, some Windows
commands, built-in or otherwise, only know about backward slashes. Two
notable examples of such commands are "dir" to list directory
contents, and cscope. Cscope on Windows also does not like spaces in
the file name, I've found. My scripts for working with Cscope all use
the 8.3-style file paths (C:\Progra~1\Vim instead of "C:\Program Files
\Vim") to eliminate spaces, and temporarily disable 'shellslash',
among other things.

Peter Odding

unread,
Jul 14, 2010, 7:09:42 AM7/14/10
to vim...@googlegroups.com

Thanks for your suggestion John. When I initially followed the link
above I didn't realize that :!start ... is a special case on Vim for
Windows so I assumed that :!start ... was just a shorthand for :!cmd /c
start ... and because that doesn't DWIM I didn't respond to your reply.

Since then I've realized that :!start is almost what I need, because it
does run external programs asynchronously without blocking Vim. However
if you execute a command-line program (like Exuberant Ctags) the :!start
... command still opens a command prompt window, and contrary to :call
system('...') the command prompt window is now actually positioned in
front and above of Vim's main window, thereby undermining the whole
point of not blocking Vim :-( (tested on Windows XP SP3, Vim 7.2).

- Peter Odding

Ben Fritz

unread,
Jul 14, 2010, 11:00:28 PM7/14/10
to vim_dev


On Jul 14, 6:09 am, Peter Odding <pe...@peterodding.com> wrote:
>
> > There is some info in the following:
> >http://vim.wikia.com/wiki/Execute_external_programs_asynchronously_un...
>
> Thanks for your suggestion John. When I initially followed the link
> above I didn't realize that :!start ... is a special case on Vim for
> Windows so I assumed that :!start ... was just a shorthand for :!cmd /c
> start ... and because that doesn't DWIM I didn't respond to your reply.
>
> Since then I've realized that :!start is almost what I need, because it
> does run external programs asynchronously without blocking Vim. However
> if you execute a command-line program (like Exuberant Ctags) the :!start
> ... command still opens a command prompt window, and contrary to :call
> system('...') the command prompt window is now actually positioned in
> front and above of Vim's main window, thereby undermining the whole
> point of not blocking Vim :-( (tested on Windows XP SP3, Vim 7.2).
>

Hence, the use of z':!start /min" in the tip John linked you to :-)

Ben Fritz

unread,
Jul 14, 2010, 11:01:14 PM7/14/10
to vim_dev


On Jul 14, 10:00 pm, Ben Fritz <fritzophre...@gmail.com> wrote:
>
> Hence, the use of z':!start /min" in the tip John linked you to :-)

Not sure how that happened...

Hence, the use of ":!start /min" in the tip John linked you to :-)

Peter Odding

unread,
Jul 14, 2010, 11:51:10 PM7/14/10
to vim...@googlegroups.com
Ben Fritz wrote:
> Hence, the use of ":!start /min" in the tip John linked you to :-)

It appears I didn't read the linked web page carefully enough, thanks
for correcting me Ben. After receiving your message I was still
concerned that the /min option would open a minimized command prompt
window in the foreground, thereby stealing Vim's input focus anyway. I
just checked it though and it works perfectly, well almost anyway, the
command prompt window is of course still listed in the task bar.

- Peter Odding

Reply all
Reply to author
Forward
0 new messages