├── .gitignore
├── INSTALL.md
├── README.md
├── TODO.md
├── addon-info.json
├── autoload
└── xolox
│ └── shell.vim
├── doc
└── shell.txt
├── misc
└── shell
│ ├── make.cmd
│ ├── shell-x64.dll
│ ├── shell-x86.dll
│ └── shell.c
└── plugin
└── shell.vim
/.gitignore:
--------------------------------------------------------------------------------
1 | doc/tags
2 |
--------------------------------------------------------------------------------
/INSTALL.md:
--------------------------------------------------------------------------------
1 | *Please note that the vim-shell plug-in requires my vim-misc plug-in which is separately distributed.*
2 |
3 | Unzip the most recent ZIP archives of the [vim-shell] [download-shell] and [vim-misc] [download-misc] plug-ins inside your Vim profile directory (usually this is `~/.vim` on UNIX and `%USERPROFILE%\vimfiles` on Windows), restart Vim and execute the command `:helptags ~/.vim/doc` (use `:helptags ~\vimfiles\doc` instead on Windows).
4 |
5 | If you prefer you can also use [Pathogen] [pathogen], [Vundle] [vundle] or a similar tool to install & update the [vim-shell] [github-shell] and [vim-misc] [github-misc] plug-ins using a local clone of the git repository.
6 |
7 |
8 | [download-misc]: http://peterodding.com/code/vim/downloads/misc.zip
9 | [download-shell]: http://peterodding.com/code/vim/downloads/shell.zip
10 | [github-misc]: http://github.com/xolox/vim-misc
11 | [github-shell]: http://github.com/xolox/vim-shell
12 | [pathogen]: http://www.vim.org/scripts/script.php?script_id=2332
13 | [vundle]: https://github.com/gmarik/vundle
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Improved integration between
Vim and its environment
2 |
3 | This plug-in aims to improve the integration between [Vim] [vim] and its environment (your operating system) by providing the following functionality:
4 |
5 | * The `:Fullscreen` command and `` mapping toggle Vim between normal and full-screen mode (see the [screenshots] [screenshots]). To invoke this functionality without using the `:Fullscreen` command see the `xolox#shell#fullscreen()` and `xolox#shell#is_fullscreen()` functions.
6 |
7 | * The `:Maximize` command and `` mapping toggle Vim between normal and maximized state: They show/hide Vim's menu bar, tool bar and/or tab line without hiding the operating system task bar.
8 |
9 | * The `:Open` command and `` mapping know how to open file and directory names, URLs and e-mail addresses in your favorite programs (file manager, web browser, e-mail client, etc).
10 |
11 | * The `xolox#misc#os#exec()` function enables other Vim plug-ins (like my [easytags.vim] [easytags] plug-in) to execute external commands in the background (i.e. asynchronously) *without opening a command prompt window on Windows*.
12 |
13 | Two [Windows DLL files] [dll] are included to perform these functions on Windows, while on UNIX external commands are used. MacVim supports full-screen out of the box (and vim-shell knows how to enable it) but is otherwise treated as UNIX.
14 |
15 | ## Installation
16 |
17 | *Please note that the vim-shell plug-in requires my vim-misc plug-in which is separately distributed.*
18 |
19 | Unzip the most recent ZIP archives of the [vim-shell] [download-shell] and [vim-misc] [download-misc] plug-ins inside your Vim profile directory (usually this is `~/.vim` on UNIX and `%USERPROFILE%\vimfiles` on Windows), restart Vim and execute the command `:helptags ~/.vim/doc` (use `:helptags ~\vimfiles\doc` instead on Windows).
20 |
21 | If you prefer you can also use [Pathogen] [pathogen], [Vundle] [vundle] or a similar tool to install & update the [vim-shell] [github-shell] and [vim-misc] [github-misc] plug-ins using a local clone of the git repository.
22 |
23 | After you've installed the plug-in and restarted Vim, the following commands will be available to you:
24 |
25 | ## Usage (commands & functions)
26 |
27 | ### The `:Maximize` command
28 |
29 | This command toggles the visibility of Vim's main menu, tool bar and/or tab line. It's mapped to `` by default, see `g:shell_mappings_enabled` if you don't like this. If you want to change which items are hidden see the `g:shell_fullscreen_items` option.
30 |
31 | ### The `:Fullscreen` command
32 |
33 | The `:Fullscreen` command toggles Vim between normal and [full-screen mode] [screenshots]. It's mapped to `` by default, see `g:shell_mappings_enabled` if you don't like this. This command first executes `:Maximize` and then (if possible) switches Vim's [GUI window] [gui] to real full-screen mode (hiding any [taskbars, panels or docks] [taskbars]). When you leave full-screen Vim's main menu, toolbar and tabline are restored and the [GUI window] [gui] is switched back to normal mode.
34 |
35 | Note that on UNIX this command even works inside of graphical terminal emulators like `gnome-terminal` or `xterm` (try it out!).
36 |
37 | ### The `:Open` command
38 |
39 | The `:Open` command knows how to open files, directories, URLs and e-mail addresses. It's mapped to `` by default, see `g:shell_mappings_enabled` if you don't like this. You can provide a filename, URL or e-mail address as argument to the command or if there's a filename, URL or e-mail address under the text cursor that will be used. If both of those fail, the directory containing the current file will be opened. You can use the command as follows:
40 |
41 | :Open http://www.vim.org/
42 |
43 | This will launch your preferred (or the best available) web browser. Likewise the following command will open your file manager in the directory of Vim's runtime files:
44 |
45 | :Open $VIMRUNTIME
46 |
47 | Note that on UNIX if the environment variable `$DISPLAY` is empty the plug-in will fall back to a command-line web browser. Because such web browsers are executed in front of Vim you have to quit the web browser to return to Vim.
48 |
49 | ### The `:MakeWithShell` command
50 |
51 | This command is a very simple replacement for the [:make] [] command that does not pop up a console window on Windows. It doesn't come with all of the bells and whistles that Vim's built-in make command does but it should work. It properly triggers the [QuickFixCmdPre] [] and [QuickFixCmdPost] [] events, although it does so using [:silent] [] to avoid printing two "No matching autocommands" messages.
52 |
53 | Because Vim's [v:shell_error] [] variable is read only (which means it cannot be set by a Vim plug-in) the vim-shell plug-in defines its own variable with the exit code of the `make` process executed by `:MakeWithShell`. This variable is called `g:xolox#shell#make_exit_code`. The semantics are exactly the same as for [v:shell_error] [].
54 |
55 | The `:MakeWithShell` command uses Vim's [quickfix window] []. To make the shell plug-in use the [location-list] [] instead you can use the command `:LMakeWithShell` instead.
56 |
57 | ### The `xolox#shell#execute_with_dll()` function
58 |
59 | The function `xolox#shell#execute_with_dll()` is used by `xolox#misc#os#exec()` and shouldn't be called directly; instead please call `xolox#misc#os#exec()` (this is what my plug-ins do). For this reason the remainder of the following text discusses the `xolox#misc#os#exec()` function.
60 |
61 | This function enables other Vim plug-ins to execute external commands in the background (i.e. asynchronously) *without opening a command prompt window on Windows*. For example try to execute the following command on Windows ([vimrun.exe] [vimrun] is only included with Vim for Windows because it isn't needed on other platforms):
62 |
63 | :call xolox#misc#os#exec({'command': 'vimrun', 'async': 1})
64 |
65 | Immediately after executing this command Vim will respond to input again because `xolox#misc#os#exec()` doesn't wait for the external command to finish when the 'async' argument is true (1). In addition no command prompt window will be shown which means [vimrun.exe] [vimrun] is running completely invisible in the background.
66 |
67 | The function returns a dictionary of return values. In asynchronous mode the dictionary is empty. In synchronous mode it contains the following key/value pairs:
68 |
69 | :echo xolox#misc#os#exec({'command': 'echo "this is stdout" && echo "this is stderr" >&2 && exit 42', 'check': 0})
70 | {'exit_code': 42, 'stdout': ['this is stdout'], 'stderr': ['this is stderr']}
71 |
72 | If you want to verify that this function works as described, execute the command mentioning `vimrun` above, open the Windows task manager by pressing `Control-Shift-Escape` and check that the process `vimrun.exe` is listed in the processes tab. If you don't see the problem this is solving, try executing [vimrun.exe] [vimrun] using Vim's built-in [system()] [system] function instead:
73 |
74 | :call system('vimrun')
75 |
76 | Vim will be completely unresponsive until you "press any key to continue" in the command prompt window that's running [vimrun.exe] [vimrun]. Of course the [system()] [system] function should only be used with non-interactive programs (the documentation says as much) but the point is to simulate an external command that takes a while to finish and blocks Vim while doing so.
77 |
78 | Note that on Windows this function uses Vim's ['shell'] [sh_opt] and ['shellcmdflag'] [shcf_opt] options to compose the command line passed to the DLL.
79 |
80 | ### The `xolox#shell#fullscreen()` function
81 |
82 | Call this function to toggle Vim's full screen status. The `:Fullscreen` command is just a shorter way to call this function.
83 |
84 | ### The `xolox#shell#is_fullscreen()` function
85 |
86 | Call this function to determine whether Vim is in full screen mode. My [session.vim plug-in] [vim-session] uses this to persist full screen mode.
87 |
88 | ### The `g:shell_fullscreen_items` option
89 |
90 | This variable is a string containing any combination of the following characters:
91 |
92 | * `m`: Hide the [main menu] [go-m] when switching to full-screen;
93 | * `T`: Hide the [toolbar] [go-T] when switching to full-screen;
94 | * `e`: Hide the [tabline] [go-e] when switching to full-screen (this also toggles the [showtabline option] [stal]).
95 |
96 | By default all the above items are hidden in full-screen mode. You can also set the buffer local variable `b:shell_fullscreen_items` to change these settings for specific buffers.
97 |
98 | ### The `g:shell_fullscreen_always_on_top` option
99 |
100 | On Windows the `:Fullscreen` command sets the Vim window to "always on top". Some people don't like this which is why this option was added. Its default value is true (1) so to disable the "always on top" feature you would add this to your [vimrc script] [vimrc]:
101 |
102 | :let g:shell_fullscreen_always_on_top = 0
103 |
104 | ### The `g:shell_fullscreen_message` option
105 |
106 | When you enter full screen the plug-in shows a Vim message explaining how to leave full screen. If you don't want to see this message you can set this option to false (0).
107 |
108 | ### The `g:shell_mappings_enabled` option
109 |
110 | If you don't like the default mappings for the `:Open` and `:Fullscreen` commands then add the following to your [vimrc script] [vimrc]:
111 |
112 | :let g:shell_mappings_enabled = 0
113 |
114 | Since no mappings will be defined now you can add something like the following to your [vimrc script] [vimrc]:
115 |
116 | :inoremap fs :Fullscreen
117 | :nnoremap fs :Fullscreen
118 | :inoremap op :Open
119 | :nnoremap op :Open
120 |
121 | ### The `g:shell_verify_urls` option
122 |
123 | When you use the `:Open` command or the `` mapping to open the URL under the text cursor, the shell plug-in uses a regular expression to guess where the URL starts and ends. This works 99% percent of the time but it can break, because in this process the shell plug-in will strip trailing punctuation characters like dots (because they were likely not intended to be included in the URL).
124 |
125 | If you actually deal with URLs that include significant trailing punctuation and your Vim is compiled with Python support you can enable the option `g:shell_verify_urls` (by setting it to 1 in your [vimrc script] [vimrc]). When you do this the plug-in will perform an HTTP HEAD request on the URL without stripping trailing punctuation. If the request returns an HTTP status code that indicates some form of success (the status code is at least 200 and less than 400) the URL including trailing punctuation is opened. If the HEAD request fails the plug-in will try again without trailing punctuation.
126 |
127 | ### The `g:shell_use_dll` option
128 |
129 | If you set this to false (0) the DDL is never used. This is very useful during testing :-).
130 |
131 | ## Background
132 |
133 | Vim has a limited ability to call external libraries using the Vim script function [libcall()] [libcall]. A few years ago when I was still using Windows a lot I created a [Windows DLL] [dll] that could be used with [libcall()] [libcall] to toggle [Vim] [vim]'s GUI window between regular and full-screen mode. I also added a few other useful functions, e.g. `openurl()` to launch the default web browser and `execute()` which works like Vim's [system()] [system] function but doesn't wait for the process to finish and doesn't show a command prompt.
134 |
135 | Since then I switched to Linux and didn't look back, which meant the DLL sat in my `~/.vim/etc/` waiting to be revived. Now that I've published my [easytags.vim] [easytags] plug-in and put a lot of effort into making it Windows compatible, the `execute()` function from the DLL would be very useful to run [Exuberant Ctags] [ctags] in the background without stealing Vim's focus by opening a command prompt window. This is why I've decided to release the DLL. Because I switched to Linux I've also added an autoload script that wraps the DLL on Windows and calls out to external programs such as `wmctrl`, `gnome-open`, `kde-open`, and others on UNIX.
136 |
137 | ## Other full-screen implementations
138 |
139 | After publishing this plug-in I found that the Vim plug-ins [VimTweak] [vimtweak] and [gvimfullscreen_win32] [gvimfullscreen_win32] also implement full-screen on Windows using a similar approach as my plug-in. I prefer the effect of my plug-in because it seems to hide window decorations more effectively. Also note that my plug-in was developed independently of the other two.
140 |
141 | ## Contact
142 |
143 | If you have questions, bug reports, suggestions, etc. the author can be contacted at . The latest version is available at and . If you like the plug-in please vote for it on [Vim Online] [vim_scripts_entry].
144 |
145 | ## License
146 |
147 | This software is licensed under the [MIT license] [mit].
148 | © 2014 Peter Odding <>.
149 |
150 |
151 | [:make]: http://vimdoc.sourceforge.net/htmldoc/quickfix.html#:make
152 | [:silent]: http://vimdoc.sourceforge.net/htmldoc/various.html#:silent
153 | [ctags]: http://en.wikipedia.org/wiki/Ctags
154 | [dll]: http://en.wikipedia.org/wiki/Dynamic-link_library
155 | [download-misc]: http://peterodding.com/code/vim/downloads/misc.zip
156 | [download-shell]: http://peterodding.com/code/vim/downloads/shell.zip
157 | [easytags]: http://peterodding.com/code/vim/easytags/
158 | [github-misc]: http://github.com/xolox/vim-misc
159 | [github-shell]: http://github.com/xolox/vim-shell
160 | [go-e]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27go-e%27
161 | [go-m]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27go-m%27
162 | [go-T]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27go-T%27
163 | [gui]: http://vimdoc.sourceforge.net/htmldoc/gui.html#GUI
164 | [gvimfullscreen_win32]: http://www.vim.org/scripts/script.php?script_id=2596
165 | [libcall]: http://vimdoc.sourceforge.net/htmldoc/eval.html#libcall()
166 | [location-list]: http://vimdoc.sourceforge.net/htmldoc/quickfix.html#location-list
167 | [mit]: http://en.wikipedia.org/wiki/MIT_License
168 | [pathogen]: http://www.vim.org/scripts/script.php?script_id=2332
169 | [quickfix window]: http://vimdoc.sourceforge.net/htmldoc/quickfix.html#quickfix
170 | [QuickFixCmdPost]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#QuickFixCmdPost
171 | [QuickFixCmdPre]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#QuickFixCmdPre
172 | [screenshots]: http://peterodding.com/code/vim/shell/screenshots/
173 | [sh_opt]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27shell%27
174 | [shcf_opt]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27shellcmdflag%27
175 | [stal]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27showtabline%27
176 | [system]: http://vimdoc.sourceforge.net/htmldoc/eval.html#system()
177 | [taskbars]: http://en.wikipedia.org/wiki/Taskbar
178 | [v:shell_error]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:shell_error
179 | [vim-session]: http://peterodding.com/code/vim/session/
180 | [vim]: http://www.vim.org/
181 | [vim_scripts_entry]: http://www.vim.org/scripts/script.php?script_id=3123
182 | [vimrc]: http://vimdoc.sourceforge.net/htmldoc/starting.html#vimrc
183 | [vimrun]: http://vimdoc.sourceforge.net/htmldoc/gui_w32.html#win32-vimrun
184 | [vimtweak]: http://www.vim.org/scripts/script.php?script_id=687
185 | [vundle]: https://github.com/gmarik/vundle
186 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # To-do list
2 |
3 | * Test the `shell.dll` library on as many configurations as possible! (different Windows versions, 32 vs. 64 bit, etc.)
4 |
5 | * **Bug:** On Windows when I enter full-screen for the 1st time it works and I can leave full-screen. But when I then try to enter full-screen a second time (without changing Vim's window state in any way) then it fails to actually toggle the full-screen state on!
6 | **Update:** This might just be a redraw bug in VirtualBox after all?! Vim does switch to full-screen
7 |
8 | * Document how to pass standard input to shell commands using xolox#shell#execute().
9 |
10 | * Replace the temporary file hack with a proper silent `popen()` implementation?
11 |
12 | * I've [announced this plug-in](http://groups.google.com/group/vim_dev/browse_frm/thread/2cdeb5709fbfc0a0) on the vim-dev mailing list but received some criticism. So for future reference: The problem solved by `xolox#shell#execute()` really does exist, see for example the [Syntastic script page](http://www.vim.org/scripts/script.php?script_id=2736) which says: "This plugin is currently only recommended for UNIX users. It is functional on Windows, but since the syntax checking plugins shell out, the command window briefly appears whenever one is executed."
13 |
--------------------------------------------------------------------------------
/addon-info.json:
--------------------------------------------------------------------------------
1 | {"vim_script_nr": 3123, "dependencies": {"vim-misc": {}}, "homepage": "http://peterodding.com/code/vim/shell", "name": "vim-shell"}
--------------------------------------------------------------------------------
/autoload/xolox/shell.vim:
--------------------------------------------------------------------------------
1 | " Vim auto-load script
2 | " Author: Peter Odding
3 | " Last Change: July 7, 2014
4 | " URL: http://peterodding.com/code/vim/shell/
5 |
6 | let g:xolox#shell#version = '0.13.6'
7 |
8 | if !exists('s:fullscreen_enabled')
9 | let s:enoimpl = "%s() hasn't been implemented on your platform! %s"
10 | let s:contact = "If you have suggestions, please contact peter@peterodding.com."
11 | let s:fullscreen_enabled = 0
12 | let s:maximized = 0
13 | endif
14 |
15 | function! xolox#shell#open_cmd(arg) " {{{1
16 | " Implementation of the :Open command.
17 | try
18 | " No argument?
19 | if a:arg !~ '\S'
20 | " Filename, URL or e-mail address at text cursor location?
21 | if !s:open_at_cursor()
22 | " Open the directory of the current buffer.
23 | let bufdir = expand('%:p:h')
24 | call xolox#misc#msg#debug("shell.vim %s: Opening directory of current buffer '%s'.", g:xolox#shell#version, bufdir)
25 | call xolox#misc#open#file(bufdir)
26 | endif
27 | elseif (a:arg =~ xolox#shell#url_pattern()) || (a:arg =~ xolox#shell#mail_pattern())
28 | " Open the URL or e-mail address given as an argument.
29 | call xolox#misc#msg#debug("shell.vim %s: Opening URL or e-mail address '%s'.", g:xolox#shell#version, a:arg)
30 | call xolox#misc#open#url(a:arg)
31 | else
32 | let arg = fnamemodify(a:arg, ':p')
33 | " Does the argument point to an existing file or directory?
34 | if isdirectory(arg) || filereadable(arg)
35 | call xolox#misc#msg#debug("shell.vim %s: Opening valid filename '%s'.", g:xolox#shell#version, arg)
36 | call xolox#misc#open#file(arg)
37 | else
38 | let msg = "I don't know how to open '%s'! %s"
39 | echoerr printf(msg, a:arg, s:contact)
40 | endif
41 | endif
42 | catch
43 | call xolox#misc#msg#warn("shell.vim %s: %s at %s", g:xolox#shell#version, v:exception, v:throwpoint)
44 | endtry
45 | endfunction
46 |
47 | function! s:open_at_cursor()
48 | let cWORD = expand('')
49 | " Start by trying to match a URL in because URLs can be more-or-less
50 | " unambiguously distinguished from e-mail addresses and filenames.
51 | if g:shell_verify_urls && cWORD =~ '^\(http\|https\)://.\{-}[[:punct:]]$' && xolox#shell#url_exists(cWORD)
52 | let match = cWORD
53 | else
54 | let match = matchstr(cWORD, xolox#shell#url_pattern())
55 | endif
56 | if match != ''
57 | call xolox#misc#msg#debug("shell.vim %s: Matched URL '%s' in cWORD '%s'.", g:xolox#shell#version, match, cWORD)
58 | else
59 | " Now try to match an e-mail address in because most filenames
60 | " won't contain an @-sign while e-mail addresses require it.
61 | let match = matchstr(cWORD, xolox#shell#mail_pattern())
62 | if match != ''
63 | call xolox#misc#msg#debug("shell.vim %s: Matched e-mail address '%s' in cWORD '%s'.", g:xolox#shell#version, match, cWORD)
64 | endif
65 | endif
66 | if match != ''
67 | call xolox#misc#open#url(match)
68 | return 1
69 | else
70 | call xolox#misc#msg#debug("shell.vim %s: Trying to match filename in current line ..", g:xolox#shell#version)
71 | " As a last resort try to match a filename at the text cursor position.
72 | let line = getline('.')
73 | let idx = col('.') - 1
74 | let match = matchstr(line[0 : idx], '\f*$')
75 | let match .= matchstr(line[idx+1 : -1], '^\f*')
76 | " Expand leading tilde and/or environment variables in filename?
77 | if match =~ '^\~' || match =~ '\$'
78 | let match = split(expand(match), "\n")[0]
79 | endif
80 | if match != '' && (isdirectory(match) || filereadable(match))
81 | call xolox#misc#msg#debug("shell.vim %s: Matched valid filename '%s' in current line ..", g:xolox#shell#version, match)
82 | call xolox#misc#open#file(match)
83 | return 1
84 | elseif match != ''
85 | call xolox#misc#msg#debug("shell.vim %s: File or directory '%s' doesn't exist.", g:xolox#shell#version, match)
86 | endif
87 | endif
88 | endfunction
89 |
90 | function! xolox#shell#open_with_windows_shell(location) " {{{1
91 | " Open a location using the compiled DLL.
92 | if xolox#shell#can_use_dll()
93 | let error = s:library_call('openurl', a:location)
94 | if error != ''
95 | let msg = "shell.vim %s: Failed to open '%s' with Windows shell! (error: %s)"
96 | throw printf(msg, g:xolox#shell#version, a:location, strtrans(xolox#misc#str#trim(error)))
97 | endif
98 | endif
99 | endfunction
100 |
101 | function! xolox#shell#highlight_urls() " {{{1
102 | " Highlight URLs and e-mail addresses embedded in source code comments.
103 | " URL highlighting breaks highlighting of tags in HTML.
104 | if exists('g:syntax_on') && &ft !~ xolox#misc#option#get('shell_hl_exclude', '^\(x|ht\)ml$')
105 | if &ft == 'help'
106 | let command = 'syntax match %s /%s/'
107 | let urlgroup = 'HelpURL'
108 | let mailgroup = 'HelpEmail'
109 | else
110 | let command = 'syntax match %s /%s/ contained containedin=.*Comment.*,.*String.*'
111 | let urlgroup = 'CommentURL'
112 | let mailgroup = 'CommentEmail'
113 | endif
114 | execute printf(command, urlgroup, escape(xolox#shell#url_pattern(), '/'))
115 | execute printf(command, mailgroup, escape(xolox#shell#mail_pattern(), '/'))
116 | execute 'highlight def link' urlgroup 'Underlined'
117 | execute 'highlight def link' mailgroup 'Underlined'
118 | endif
119 | endfunction
120 |
121 | function! xolox#shell#execute_with_dll(cmd, async) " {{{1
122 | " Execute external commands on Windows using the compiled DLL.
123 | let fn = 'execute_' . (a:async ? 'a' : '') . 'synchronous'
124 | " Command line parsing on Windows is batshit insane. I intended to define
125 | " exactly how it happens here, but the Microsoft documentation can't even
126 | " explain it properly, so I won't bother either. Suffice to say that the
127 | " outer double quotes with unescaped double quotes in between are
128 | " intentional... Here's a small excerpt from "help cmd":
129 | "
130 | " Otherwise, old behavior is to see if the first character is a quote
131 | " character and if so, strip the leading character and remove the last
132 | " quote character on the command line, preserving any text after the last
133 | " quote character.
134 | "
135 | let cmd = printf('cmd.exe /c "%s"', a:cmd)
136 | call xolox#misc#msg#debug("shell.vim %s: Executing external command: %s", g:xolox#shell#version, cmd)
137 | let result = s:library_call(fn, cmd)
138 | if result =~ '^exit_code=\d\+$'
139 | return matchstr(result, '^exit_code=\zs\d\+$') + 0
140 | elseif result =~ '\S'
141 | let msg = printf('%s(%s) failed!', fn, string(cmd))
142 | if result =~ '\S'
143 | let msg .= ' (output: ' . xolox#misc#str#trim(result) . ')'
144 | endif
145 | throw msg
146 | endif
147 | endfunction
148 |
149 | function! xolox#shell#make(mode, bang, args) " {{{1
150 | " Run :make silent (without a console window).
151 | let command = &makeprg
152 | if a:args =~ '\S'
153 | let command .= ' ' . a:args
154 | endif
155 | call xolox#misc#msg#info("shell.vim %s: Running make command: %s", g:xolox#shell#version, command)
156 | if a:bang == '!'
157 | execute printf('%sgetexpr s:make_cmd(a:mode, command)', a:mode)
158 | else
159 | execute printf('%sexpr s:make_cmd(a:mode, command)', a:mode)
160 | endif
161 | execute a:mode . 'window'
162 | endfunction
163 |
164 | function! s:make_cmd(mode, command)
165 | let event = (a:mode == 'l') ? 'lmake' : 'make'
166 | execute 'silent doautocmd QuickFixCmdPre' event
167 | let command = a:command . ' 2>&1'
168 | let result = xolox#misc#os#exec({'command': command, 'check': 0})
169 | let g:xolox#shell#make_exit_code = result['exit_code']
170 | execute 'silent doautocmd QuickFixCmdPost' event
171 | return join(result['stdout'], "\n")
172 | endfunction
173 |
174 | if !exists('g:xolox#shell#make_exit_code')
175 | let g:xolox#shell#make_exit_code = 0
176 | endif
177 |
178 | function! xolox#shell#maximize(...) " {{{1
179 | " Show/hide Vim's menu, tool bar and/or tab line.
180 | let new_state = a:0 == 0 ? !s:maximized : a:1
181 | if new_state && !s:maximized
182 | " Hide the main menu, tool bar and/or tab line. Remember what was hidden
183 | " so its visibility can be restored when the user leaves full-screen.
184 | let s:go_toggled = ''
185 | let fullscreen_items = xolox#misc#option#get('shell_fullscreen_items', 'mTe')
186 | for item in split(fullscreen_items, '.\zs')
187 | if &go =~# item
188 | let s:go_toggled .= item
189 | execute 'set go-=' . item
190 | endif
191 | endfor
192 | if fullscreen_items =~# 'e' && &stal != 0
193 | let s:stal_save = &stal
194 | set showtabline=0
195 | endif
196 | let s:maximized = 1
197 | elseif s:maximized && !new_state
198 | " Restore display of previously hidden GUI components?
199 | let &go .= s:go_toggled
200 | if exists('s:stal_save')
201 | let &stal = s:stal_save
202 | unlet s:stal_save
203 | endif
204 | unlet s:go_toggled
205 | let s:maximized = 0
206 | endif
207 | return s:maximized
208 | endfunction
209 |
210 | function! xolox#shell#fullscreen() " {{{1
211 | " Toggle Vim between normal and full-screen mode.
212 |
213 | " When entering full-screen...
214 | if !s:fullscreen_enabled
215 | " Save the window position and size when running Windows, because my
216 | " dynamic link library doesn't save/restore them while "wmctrl" does.
217 | if xolox#misc#os#is_win()
218 | let [s:lines_save, s:columns_save] = [&lines, &columns]
219 | let [s:winpos_x_save, s:winpos_y_save] = [getwinposx(), getwinposy()]
220 | endif
221 | call xolox#shell#maximize(1)
222 | endif
223 |
224 | " Now try to toggle the real full-screen status of Vim's GUI window using a
225 | " custom dynamic link library on Windows or the "wmctrl" program on UNIX.
226 | try
227 | if xolox#shell#can_use_dll()
228 | let options = s:fullscreen_enabled ? 'disable' : 'enable'
229 | if g:shell_fullscreen_always_on_top
230 | let options .= ', always on top'
231 | endif
232 | let error = s:library_call('fullscreen', options)
233 | if error != ''
234 | throw "shell.dll failed with: " . error
235 | endif
236 | elseif has('macunix') && has('gui')
237 | if !s:fullscreen_enabled
238 | set fullscreen
239 | else
240 | set nofullscreen
241 | endif
242 | elseif has('unix')
243 | if !executable('wmctrl')
244 | let msg = "Full-screen on UNIX requires the `wmctrl' program!"
245 | throw msg . " On Debian/Ubuntu you can install it by executing `sudo apt-get install wmctrl'."
246 | endif
247 | let command = 'wmctrl -r :ACTIVE: -b toggle,fullscreen 2>&1'
248 | let output = system(command)
249 | if v:shell_error
250 | let msg = "Command %s failed!"
251 | if a:output =~ '^\_s*$'
252 | throw printf(msg, string(a:cmd))
253 | else
254 | let msg .= ' (output: %s)'
255 | let output = strtrans(xolox#misc#str#trim(a:output))
256 | throw printf(msg, string(a:cmd), output)
257 | endif
258 | endif
259 | else
260 | throw printf(s:enoimpl, 'fullscreen', s:contact)
261 | endif
262 | catch
263 | call xolox#misc#msg#warn("shell.vim %s: %s at %s", g:xolox#shell#version, v:exception, v:throwpoint)
264 | endtry
265 |
266 | " When leaving full-screen...
267 | if s:fullscreen_enabled
268 | call xolox#shell#maximize(0)
269 | " Restore window position and size only on Windows -- I don't know why
270 | " but the following actually breaks when running under "wmctrl"...
271 | if xolox#misc#os#is_win()
272 | let [&lines, &columns] = [s:lines_save, s:columns_save]
273 | execute 'winpos' s:winpos_x_save s:winpos_y_save
274 | unlet s:lines_save s:columns_save s:winpos_x_save s:winpos_y_save
275 | endif
276 | endif
277 |
278 | " Toggle the boolean status returned by xolox#shell#is_fullscreen().
279 | let s:fullscreen_enabled = !s:fullscreen_enabled
280 |
281 | " Let the user know how to leave full-screen mode?
282 | if s:fullscreen_enabled && g:shell_fullscreen_message
283 | " Take a moment to let Vim's GUI finish redrawing (:redraw is
284 | " useless here because it only redraws Vim's internal state).
285 | sleep 50 m
286 | call xolox#misc#msg#info("shell.vim %s: To return from full-screen type or execute :Fullscreen.", g:xolox#shell#version)
287 | endif
288 |
289 | endfunction
290 |
291 | function! xolox#shell#is_fullscreen() " {{{1
292 | " Check whether Vim is currently in full-screen mode.
293 | return s:fullscreen_enabled
294 | endfunction
295 |
296 | function! xolox#shell#persist_fullscreen() " {{{1
297 | " Return Vim commands needed to restore Vim's full-screen state.
298 | let commands = []
299 | if xolox#shell#is_fullscreen()
300 | " The vim-session plug-in persists and restores Vim's &guioptions while
301 | " the :Fullscreen command also manipulates &guioptions. This can cause
302 | " several weird interactions. To avoid this, we do some trickery here.
303 | call add(commands, "let &guioptions = " . string(&guioptions . s:go_toggled))
304 | if exists('s:stal_save')
305 | call add(commands, "let &stal = " . s:stal_save)
306 | endif
307 | call add(commands, "call xolox#shell#fullscreen()")
308 | endif
309 | return commands
310 | endfunction
311 |
312 | function! xolox#shell#url_exists(url) " {{{1
313 | " Check whether a URL points to an existing resource (using Python).
314 | try
315 | " Embedding Python code in Vim scripts is always a bit awkward :-(
316 | " (because of the forced indentation thing Python insists on).
317 | let starttime = xolox#misc#timer#start()
318 | python <]*\w@\w[^@ \t\r<>]\+\w\>')
369 | endfunction
370 |
371 | function! xolox#shell#can_use_dll() " {{{1
372 | " Check whether the compiled DLL is usable in the current environment.
373 | if xolox#misc#os#is_win()
374 | try
375 | call xolox#misc#msg#debug("shell.vim %s: Checking if compiled DDL is supported ..", g:xolox#shell#version)
376 | if !xolox#misc#option#get('shell_use_dll', 1)
377 | call xolox#misc#msg#debug("shell.vim %s: Use of DDL is disabled using 'g:shell_use_dll'.", g:xolox#shell#version)
378 | return 0
379 | endif
380 | let expected_version = '0.5'
381 | let actual_version = s:library_call('libversion', '')
382 | if actual_version == expected_version
383 | call xolox#misc#msg#debug("shell.vim %s: Yes the DDL works. Good for you! :-)", g:xolox#shell#version)
384 | return 1
385 | endif
386 | call xolox#misc#msg#debug("shell.vim %s: The DDL works but reports version %s while I was expecting %s!", g:xolox#shell#version, string(actual_version), string(expected_version))
387 | catch
388 | call xolox#misc#msg#debug("shell.vim %s: Looks like the DDL is not working! (Vim raised an exception: %s)", g:xolox#shell#version, v:exception)
389 | return 0
390 | endtry
391 | endif
392 | endfunction
393 |
394 | " s:library_call() - Only defined on Windows. {{{1
395 |
396 | if xolox#misc#os#is_win()
397 |
398 | let s:cpu_arch = has('win64') ? 'x64' : 'x86'
399 | let s:library = expand(':p:h:h:h') . '\misc\shell\shell-' . s:cpu_arch . '.dll'
400 |
401 | function! s:library_call(fn, arg)
402 | let starttime = xolox#misc#timer#start()
403 | let result = libcall(s:library, a:fn, a:arg)
404 | let friendly_result = empty(result) ? '(empty string)' : printf('string %s', string(result))
405 | call xolox#misc#timer#stop("shell.vim %s: Called function %s() in DLL %s, returning %s in %s.", g:xolox#shell#version, a:fn, s:library, friendly_result, starttime)
406 | return result
407 | endfunction
408 |
409 | endif
410 |
411 | " vim: ts=2 sw=2 et fdm=marker
412 |
--------------------------------------------------------------------------------
/doc/shell.txt:
--------------------------------------------------------------------------------
1 | *shell.txt* Improved integration between Vim and its environment
2 |
3 | ===============================================================================
4 | Contents ~
5 |
6 | 1. Introduction |shell-introduction|
7 | 2. Installation |shell-installation|
8 | 3. Usage (commands & functions) |shell-usage|
9 | 1. The |:Maximize| command
10 | 2. The |:Fullscreen| command
11 | 3. The |:Open| command
12 | 4. The |:MakeWithShell| command
13 | 5. The |xolox#shell#execute_with_dll()| function
14 | 6. The |xolox#shell#fullscreen()| function
15 | 7. The |xolox#shell#is_fullscreen()| function
16 | 8. The |g:shell_fullscreen_items| option
17 | 9. The |g:shell_fullscreen_always_on_top| option
18 | 10. The |g:shell_fullscreen_message| option
19 | 11. The |g:shell_mappings_enabled| option
20 | 12. The |g:shell_verify_urls| option
21 | 13. The |g:shell_use_dll| option
22 | 4. Background |shell-background|
23 | 5. Other full-screen implementations |shell-other-full-screen-implementations|
24 | 6. Contact |shell-contact|
25 | 7. License |shell-license|
26 | 8. References |shell-references|
27 |
28 | ===============================================================================
29 | *shell-introduction*
30 | Introduction ~
31 |
32 | This plug-in aims to improve the integration between Vim and its environment
33 | (your operating system) by providing the following functionality:
34 |
35 | - The |:Fullscreen| command and '' mapping toggle Vim between normal and
36 | full-screen mode (see the screenshots [1]). To invoke this functionality
37 | without using the |:Fullscreen| command see the |xolox#shell#fullscreen()|
38 | and |xolox#shell#is_fullscreen()| functions.
39 |
40 | - The |:Maximize| command and '' mapping toggle Vim between
41 | normal and maximized state: They show/hide Vim's menu bar, tool bar and/or
42 | tab line without hiding the operating system task bar.
43 |
44 | - The |:Open| command and '' mapping know how to open file and directory
45 | names, URLs and e-mail addresses in your favorite programs (file manager,
46 | web browser, e-mail client, etc).
47 |
48 | - The 'xolox#misc#os#exec()' function enables other Vim plug-ins (like my
49 | easytags.vim [2] plug-in) to execute external commands in the background
50 | (i.e. asynchronously) _without opening a command prompt window on Windows_.
51 |
52 | Two Windows DLL files [3] are included to perform these functions on Windows,
53 | while on UNIX external commands are used. MacVim supports full-screen out of
54 | the box (and vim-shell knows how to enable it) but is otherwise treated as
55 | UNIX.
56 |
57 | ===============================================================================
58 | *shell-installation*
59 | Installation ~
60 |
61 | _Please note that the vim-shell plug-in requires my vim-misc plug-in which is
62 | separately distributed._
63 |
64 | Unzip the most recent ZIP archives of the vim-shell [4] and vim-misc [5] plug-
65 | ins inside your Vim profile directory (usually this is '~/.vim' on UNIX and
66 | '%USERPROFILE%\vimfiles' on Windows), restart Vim and execute the command
67 | ':helptags ~/.vim/doc' (use ':helptags ~\vimfiles\doc' instead on Windows).
68 |
69 | If you prefer you can also use Pathogen [6], Vundle [7] or a similar tool to
70 | install & update the vim-shell [8] and vim-misc [9] plug-ins using a local
71 | clone of the git repository.
72 |
73 | After you've installed the plug-in and restarted Vim, the following commands
74 | will be available to you:
75 |
76 | ===============================================================================
77 | *shell-usage*
78 | Usage (commands & functions) ~
79 |
80 | -------------------------------------------------------------------------------
81 | The *:Maximize* command
82 |
83 | This command toggles the visibility of Vim's main menu, tool bar and/or tab
84 | line. It's mapped to '' by default, see |g:shell_mappings_enabled|
85 | if you don't like this. If you want to change which items are hidden see the
86 | |g:shell_fullscreen_items| option.
87 |
88 | -------------------------------------------------------------------------------
89 | The *:Fullscreen* command
90 |
91 | The |:Fullscreen| command toggles Vim between normal and full-screen mode [1].
92 | It's mapped to '' by default, see |g:shell_mappings_enabled| if you don't
93 | like this. This command first executes |:Maximize| and then (if possible)
94 | switches Vim's |GUI| window to real full-screen mode (hiding any taskbars,
95 | panels or docks [10]). When you leave full-screen Vim's main menu, toolbar and
96 | tabline are restored and the |GUI| window is switched back to normal mode.
97 |
98 | Note that on UNIX this command even works inside of graphical terminal
99 | emulators like 'gnome-terminal' or 'xterm' (try it out!).
100 |
101 | -------------------------------------------------------------------------------
102 | The *:Open* command
103 |
104 | The |:Open| command knows how to open files, directories, URLs and e-mail
105 | addresses. It's mapped to '' by default, see |g:shell_mappings_enabled| if
106 | you don't like this. You can provide a filename, URL or e-mail address as
107 | argument to the command or if there's a filename, URL or e-mail address under
108 | the text cursor that will be used. If both of those fail, the directory
109 | containing the current file will be opened. You can use the command as follows:
110 | >
111 | :Open http://www.vim.org/
112 | <
113 | This will launch your preferred (or the best available) web browser. Likewise
114 | the following command will open your file manager in the directory of Vim's
115 | runtime files:
116 | >
117 | :Open $VIMRUNTIME
118 | <
119 | Note that on UNIX if the environment variable '$DISPLAY' is empty the plug-in
120 | will fall back to a command-line web browser. Because such web browsers are
121 | executed in front of Vim you have to quit the web browser to return to Vim.
122 |
123 | -------------------------------------------------------------------------------
124 | The *:MakeWithShell* command
125 |
126 | This command is a very simple replacement for the |:make| command that does not
127 | pop up a console window on Windows. It doesn't come with all of the bells and
128 | whistles that Vim's built-in make command does but it should work. It properly
129 | triggers the |QuickFixCmdPre| and |QuickFixCmdPost| events, although it does so
130 | using |:silent| to avoid printing two "No matching autocommands" messages.
131 |
132 | Because Vim's |v:shell_error| variable is read only (which means it cannot be
133 | set by a Vim plug-in) the vim-shell plug-in defines its own variable with the
134 | exit code of the 'make' process executed by |:MakeWithShell|. This variable is
135 | called 'g:xolox#shell#make_exit_code'. The semantics are exactly the same as
136 | for |v:shell_error|.
137 |
138 | The |:MakeWithShell| command uses Vim's |quickfix| window. To make the shell
139 | plug-in use the |location-list| instead you can use the command
140 | ':LMakeWithShell' instead.
141 |
142 | -------------------------------------------------------------------------------
143 | The *xolox#shell#execute_with_dll()* function
144 |
145 | The function |xolox#shell#execute_with_dll()| is used by 'xolox#misc#os#exec()'
146 | and shouldn't be called directly; instead please call 'xolox#misc#os#exec()'
147 | (this is what my plug-ins do). For this reason the remainder of the following
148 | text discusses the 'xolox#misc#os#exec()' function.
149 |
150 | This function enables other Vim plug-ins to execute external commands in the
151 | background (i.e. asynchronously) _without opening a command prompt window on
152 | Windows_. For example try to execute the following command on Windows
153 | (vimrun.exe (see |win32-vimrun|) is only included with Vim for Windows because
154 | it isn't needed on other platforms):
155 | >
156 | :call xolox#misc#os#exec({'command': 'vimrun', 'async': 1})
157 | <
158 | Immediately after executing this command Vim will respond to input again
159 | because 'xolox#misc#os#exec()' doesn't wait for the external command to finish
160 | when the 'async' argument is true (1). In addition no command prompt window
161 | will be shown which means vimrun.exe (see |win32-vimrun|) is running completely
162 | invisible in the background.
163 |
164 | The function returns a dictionary of return values. In asynchronous mode the
165 | dictionary is empty. In synchronous mode it contains the following key/value
166 | pairs:
167 | >
168 | :echo xolox#misc#os#exec({'command': 'echo "this is stdout" && echo "this is stderr" >&2 && exit 42', 'check': 0})
169 | {'exit_code': 42, 'stdout': ['this is stdout'], 'stderr': ['this is stderr']}
170 | <
171 | If you want to verify that this function works as described, execute the
172 | command mentioning 'vimrun' above, open the Windows task manager by pressing
173 | 'Control-Shift-Escape' and check that the process 'vimrun.exe' is listed in the
174 | processes tab. If you don't see the problem this is solving, try executing
175 | vimrun.exe (see |win32-vimrun|) using Vim's built-in |system()| function
176 | instead:
177 | >
178 | :call system('vimrun')
179 | <
180 | Vim will be completely unresponsive until you "press any key to continue" in
181 | the command prompt window that's running vimrun.exe (see |win32-vimrun|). Of
182 | course the |system()| function should only be used with non-interactive
183 | programs (the documentation says as much) but the point is to simulate an
184 | external command that takes a while to finish and blocks Vim while doing so.
185 |
186 | Note that on Windows this function uses Vim's |'shell'| and |'shellcmdflag'|
187 | options to compose the command line passed to the DLL.
188 |
189 | -------------------------------------------------------------------------------
190 | The *xolox#shell#fullscreen()* function
191 |
192 | Call this function to toggle Vim's full screen status. The |:Fullscreen|
193 | command is just a shorter way to call this function.
194 |
195 | -------------------------------------------------------------------------------
196 | The *xolox#shell#is_fullscreen()* function
197 |
198 | Call this function to determine whether Vim is in full screen mode. My
199 | session.vim plug-in [11] uses this to persist full screen mode.
200 |
201 | -------------------------------------------------------------------------------
202 | The *g:shell_fullscreen_items* option
203 |
204 | This variable is a string containing any combination of the following
205 | characters:
206 |
207 | - 'm': Hide the main menu (see |'go-m'|) when switching to full-screen;
208 | - 'T': Hide the toolbar (see |'go-T'|) when switching to full-screen;
209 | - 'e': Hide the tabline (see |'go-e'|) when switching to full-screen (this
210 | also toggles the showtabline option (see |'showtabline'|)).
211 |
212 | By default all the above items are hidden in full-screen mode. You can also set
213 | the buffer local variable 'b:shell_fullscreen_items' to change these settings
214 | for specific buffers.
215 |
216 | -------------------------------------------------------------------------------
217 | The *g:shell_fullscreen_always_on_top* option
218 |
219 | On Windows the |:Fullscreen| command sets the Vim window to "always on top".
220 | Some people don't like this which is why this option was added. Its default
221 | value is true (1) so to disable the "always on top" feature you would add this
222 | to your |vimrc| script:
223 | >
224 | :let g:shell_fullscreen_always_on_top = 0
225 | <
226 | -------------------------------------------------------------------------------
227 | The *g:shell_fullscreen_message* option
228 |
229 | When you enter full screen the plug-in shows a Vim message explaining how to
230 | leave full screen. If you don't want to see this message you can set this
231 | option to false (0).
232 |
233 | -------------------------------------------------------------------------------
234 | The *g:shell_mappings_enabled* option
235 |
236 | If you don't like the default mappings for the |:Open| and |:Fullscreen|
237 | commands then add the following to your |vimrc| script:
238 | >
239 | :let g:shell_mappings_enabled = 0
240 | <
241 | Since no mappings will be defined now you can add something like the following
242 | to your |vimrc| script:
243 | >
244 | :inoremap fs :Fullscreen
245 | :nnoremap fs :Fullscreen
246 | :inoremap op :Open
247 | :nnoremap op :Open
248 | <
249 | -------------------------------------------------------------------------------
250 | The *g:shell_verify_urls* option
251 |
252 | When you use the |:Open| command or the '' mapping to open the URL under
253 | the text cursor, the shell plug-in uses a regular expression to guess where the
254 | URL starts and ends. This works 99% percent of the time but it can break,
255 | because in this process the shell plug-in will strip trailing punctuation
256 | characters like dots (because they were likely not intended to be included in
257 | the URL).
258 |
259 | If you actually deal with URLs that include significant trailing punctuation
260 | and your Vim is compiled with Python support you can enable the option
261 | |g:shell_verify_urls| (by setting it to 1 in your |vimrc| script). When you do
262 | this the plug-in will perform an HTTP HEAD request on the URL without stripping
263 | trailing punctuation. If the request returns an HTTP status code that indicates
264 | some form of success (the status code is at least 200 and less than 400) the
265 | URL including trailing punctuation is opened. If the HEAD request fails the
266 | plug-in will try again without trailing punctuation.
267 |
268 | -------------------------------------------------------------------------------
269 | The *g:shell_use_dll* option
270 |
271 | If you set this to false (0) the DDL is never used. This is very useful during
272 | testing :-).
273 |
274 | ===============================================================================
275 | *shell-background*
276 | Background ~
277 |
278 | Vim has a limited ability to call external libraries using the Vim script
279 | function |libcall()|. A few years ago when I was still using Windows a lot I
280 | created a Windows DLL [3] that could be used with |libcall()| to toggle Vim's
281 | GUI window between regular and full-screen mode. I also added a few other
282 | useful functions, e.g. 'openurl()' to launch the default web browser and
283 | 'execute()' which works like Vim's |system()| function but doesn't wait for the
284 | process to finish and doesn't show a command prompt.
285 |
286 | Since then I switched to Linux and didn't look back, which meant the DLL sat in
287 | my '~/.vim/etc/' waiting to be revived. Now that I've published my easytags.vim
288 | [2] plug-in and put a lot of effort into making it Windows compatible, the
289 | 'execute()' function from the DLL would be very useful to run Exuberant Ctags
290 | [12] in the background without stealing Vim's focus by opening a command prompt
291 | window. This is why I've decided to release the DLL. Because I switched to
292 | Linux I've also added an autoload script that wraps the DLL on Windows and
293 | calls out to external programs such as 'wmctrl', 'gnome-open', 'kde-open', and
294 | others on UNIX.
295 |
296 | ===============================================================================
297 | *shell-other-full-screen-implementations*
298 | Other full-screen implementations ~
299 |
300 | After publishing this plug-in I found that the Vim plug-ins VimTweak [13] and
301 | gvimfullscreen_win32 [14] also implement full-screen on Windows using a similar
302 | approach as my plug-in. I prefer the effect of my plug-in because it seems to
303 | hide window decorations more effectively. Also note that my plug-in was
304 | developed independently of the other two.
305 |
306 | ===============================================================================
307 | *shell-contact*
308 | Contact ~
309 |
310 | If you have questions, bug reports, suggestions, etc. the author can be
311 | contacted at peter@peterodding.com. The latest version is available at
312 | http://peterodding.com/code/vim/shell/ and http://github.com/xolox/vim-shell.
313 | If you like the plug-in please vote for it on Vim Online [15].
314 |
315 | ===============================================================================
316 | *shell-license*
317 | License ~
318 |
319 | This software is licensed under the MIT license [16]. Š 2014 Peter Odding
320 | .
321 |
322 | ===============================================================================
323 | *shell-references*
324 | References ~
325 |
326 | [1] http://peterodding.com/code/vim/shell/screenshots/
327 | [2] http://peterodding.com/code/vim/easytags/
328 | [3] http://en.wikipedia.org/wiki/Dynamic-link_library
329 | [4] http://peterodding.com/code/vim/downloads/shell.zip
330 | [5] http://peterodding.com/code/vim/downloads/misc.zip
331 | [6] http://www.vim.org/scripts/script.php?script_id=2332
332 | [7] https://github.com/gmarik/vundle
333 | [8] http://github.com/xolox/vim-shell
334 | [9] http://github.com/xolox/vim-misc
335 | [10] http://en.wikipedia.org/wiki/Taskbar
336 | [11] http://peterodding.com/code/vim/session/
337 | [12] http://en.wikipedia.org/wiki/Ctags
338 | [13] http://www.vim.org/scripts/script.php?script_id=687
339 | [14] http://www.vim.org/scripts/script.php?script_id=2596
340 | [15] http://www.vim.org/scripts/script.php?script_id=3123
341 | [16] http://en.wikipedia.org/wiki/MIT_License
342 |
343 | vim: ft=help
344 |
--------------------------------------------------------------------------------
/misc/shell/make.cmd:
--------------------------------------------------------------------------------
1 | :: This Windows batch script compiles the Windows DLL for the
2 | :: shell.vim plug-in for the x86 and x64 processor architectures.
3 |
4 | :: Build shell-x86.dll.
5 | CALL SETENV /Release /x86 /xp
6 | CL /nologo /Wall /LD /D_CRT_SECURE_NO_WARNINGS shell.c /link /out:shell-x86.dll shell32.lib user32.lib
7 | DEL shell.exp shell.lib shell.obj
8 |
9 | :: Build shell-x64.dll.
10 | CALL SETENV /Release /x64 /xp
11 | CL /nologo /Wall /LD /D_CRT_SECURE_NO_WARNINGS shell.c /link /out:shell-x64.dll shell32.lib user32.lib
12 | DEL shell.exp shell.lib shell.obj
13 |
--------------------------------------------------------------------------------
/misc/shell/shell-x64.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xolox/vim-shell/c19945c6cb08db8d17b4815239e2e7e0051fb33c/misc/shell/shell-x64.dll
--------------------------------------------------------------------------------
/misc/shell/shell-x86.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xolox/vim-shell/c19945c6cb08db8d17b4815239e2e7e0051fb33c/misc/shell/shell-x86.dll
--------------------------------------------------------------------------------
/misc/shell/shell.c:
--------------------------------------------------------------------------------
1 | /* This is a dynamic link library for Vim on Windows that makes the following
2 | * features available to Vim:
3 | *
4 | * - Open the user's preferred web browser with a given URL;
5 | * - Execute external commands *without* showing a command prompt,
6 | * optionally waiting for the command to finish;
7 | * - Toggle Vim's full-screen state using a bit of Windows API magic.
8 | *
9 | * If you want to compile this library yourself you need to have the Microsoft
10 | * Windows SDK installed, you can find a download link on the following web
11 | * page: http://en.wikipedia.org/wiki/Microsoft_Windows_SDK. It comes in a web
12 | * install and when you leave all features checked it clocks in at a few
13 | * gigabytes, but since we don't need any of the .NET tools you can just
14 | * uncheck all items mentioning .NET :-)
15 | *
16 | * Open the Windows SDK command prompt and run the following command:
17 | *
18 | * CL /LD shell.c shell32.lib user32.lib
19 | *
20 | * This should create the dynamic link library "shell.dll" which you can call
21 | * from Vim using for example :call libcall('c:/shell.dll', 'fullscreen', 'enable').
22 | *
23 | * Happy Vimming!
24 | *
25 | * - Peter Odding
26 | */
27 |
28 | #define _WIN32_WINNT 0x0500 /* GetConsoleWindow() */
29 | #define WIN32_LEAN_AND_MEAN
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include /* ShellExecute? */
35 |
36 | /* Dynamic strings are returned using static buffers to avoid memory leaks. */
37 | static char message_buffer[1024 * 10];
38 | static char rv_buffer[512];
39 |
40 | #undef MessageBox
41 | #define MessageBox(message) MessageBoxA(NULL, message, "Vim Library", 0)
42 |
43 | static const char *GetError(void) /* {{{1 */
44 | {
45 | size_t i;
46 |
47 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
48 | NULL, GetLastError(), 0, message_buffer, sizeof message_buffer, NULL);
49 | i = strlen(message_buffer);
50 | while (i >= 2 && isspace(message_buffer[i-2])) {
51 | message_buffer[i-2] = '\0';
52 | i--;
53 | }
54 | return message_buffer;
55 | }
56 |
57 | static const char *Success(const char *result) /* {{{1 */
58 | {
59 | /* printf("OK\n"); */
60 | return result;
61 | }
62 |
63 | static const char *Failure(const char *result) /* {{{1 */
64 | {
65 | /* if (result && strlen(result)) MessageBox(result); */
66 | return result;
67 | }
68 |
69 | static const char *execute(char *command, int wait) /* {{{1 */
70 | {
71 | STARTUPINFO si;
72 | PROCESS_INFORMATION pi;
73 | ZeroMemory(&si, sizeof(si));
74 | ZeroMemory(&pi, sizeof(pi));
75 | si.cb = sizeof(si);
76 | if (CreateProcess(0, command, 0, 0, 0, CREATE_NO_WINDOW, 0, 0, &si, &pi)) {
77 | if (!wait) {
78 | return Success(NULL);
79 | } else {
80 | DWORD exit_code;
81 | if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED
82 | && GetExitCodeProcess(pi.hProcess, &exit_code)
83 | && CloseHandle(pi.hProcess)
84 | && CloseHandle(pi.hThread)
85 | && sprintf(rv_buffer, "exit_code=%u", exit_code)) {
86 | return Success(rv_buffer);
87 | }
88 | }
89 | }
90 | return Failure(GetError());
91 | }
92 |
93 | __declspec(dllexport)
94 | const char *execute_synchronous(char *command) /* {{{1 */
95 | {
96 | return execute(command, 1);
97 | }
98 |
99 | __declspec(dllexport)
100 | const char *execute_asynchronous(char *command) /* {{{1 */
101 | {
102 | return execute(command, 0);
103 | }
104 |
105 | __declspec(dllexport)
106 | const char *libversion(const char *ignored) /* {{{1 */
107 | {
108 | (void)ignored;
109 | return Success("0.5");
110 | }
111 |
112 | __declspec(dllexport)
113 | const char *openurl(const char *path) /* {{{1 */
114 | {
115 | ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWNORMAL);
116 | return Success(NULL);
117 | }
118 |
119 | __declspec(dllexport)
120 | const char *fullscreen(const char *options) /* {{{1 */
121 | {
122 | HWND window;
123 | LONG styles, exStyle, enable, always_on_top;
124 | HMONITOR monitor;
125 | MONITORINFO info = { sizeof info };
126 |
127 | enable = (strstr(options, "enable") != NULL);
128 | always_on_top = (strstr(options, "always on top") != NULL);
129 |
130 | window = GetForegroundWindow();
131 | if (!window)
132 | return Failure("Could not get handle to foreground window!");
133 |
134 | styles = GetWindowLong(window, GWL_STYLE);
135 | if (!styles)
136 | return Failure("Could not query window styles!");
137 |
138 | exStyle = GetWindowLong(window, GWL_EXSTYLE);
139 | if (!exStyle)
140 | return Failure("Could not query window ex style!");
141 |
142 | if (enable) {
143 | styles ^= WS_CAPTION | WS_THICKFRAME;
144 | if (always_on_top)
145 | exStyle |= WS_EX_TOPMOST;
146 | } else {
147 | styles |= WS_CAPTION | WS_THICKFRAME;
148 | if (always_on_top)
149 | exStyle &= ~WS_EX_TOPMOST;
150 | }
151 |
152 | if (!SetWindowLong(window, GWL_STYLE, styles))
153 | return Failure("Could not apply window styles!");
154 |
155 | if (!SetWindowLong(window, GWL_EXSTYLE, exStyle))
156 | return Failure("Could not apply window ex style!");
157 |
158 | if (enable) {
159 | monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
160 | if (!monitor)
161 | return Failure("Could not get handle to monitor!");
162 | if (!GetMonitorInfo(monitor, &info))
163 | return Failure("Could not get monitor information!");
164 | if (!SetWindowPos(window,
165 | always_on_top ? HWND_TOPMOST : HWND_TOP,
166 | info.rcMonitor.left,
167 | info.rcMonitor.top,
168 | info.rcMonitor.right - info.rcMonitor.left,
169 | info.rcMonitor.bottom - info.rcMonitor.top,
170 | SWP_SHOWWINDOW))
171 | return Failure("Could not resize window!");
172 | } else if (!SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0,
173 | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
174 | return Failure("Could not restore window!");
175 |
176 | return Success(NULL);
177 | }
178 |
179 | __declspec(dllexport)
180 | const char *console(char *command) /* {{{1 */
181 | {
182 | /* TODO: The quest to embedding a command prompt in Vim :)
183 | * This doesn't quite work and I'm afraid it never will.
184 | */
185 | HWND gvim, console;
186 |
187 | gvim = GetForegroundWindow();
188 | if (!gvim)
189 | return Failure("Could not get handle to foreground window");
190 |
191 | // destroy old console?
192 | if (GetConsoleWindow()) FreeConsole();
193 |
194 | // allocate new console
195 | if (!AllocConsole())
196 | return Failure("Could not allocate console");
197 |
198 | // get handle to console window
199 | console = GetConsoleWindow();
200 | if (!console)
201 | return Failure("Could not get handle to console window");
202 |
203 | // embed console inside foreground window
204 | if (!(SetParent(console, gvim)))
205 | return Failure("Could not embed console in Gvim window");
206 |
207 | if (!CreateProcess(0, command, 0, 0, 0, 0, 0, 0, 0, 0))
208 | return Failure("Could not create child process");
209 |
210 | MessageBox("Injection performed!");
211 |
212 | return Success(NULL);
213 | }
214 |
215 | /* vim: set ff=dos ts=2 sw=2 noet : */
216 |
--------------------------------------------------------------------------------
/plugin/shell.vim:
--------------------------------------------------------------------------------
1 | " Vim plug-in
2 | " Author: Peter Odding
3 | " Last Change: July 7, 2014
4 | " URL: http://peterodding.com/code/vim/shell/
5 |
6 | " Support for automatic update using the GLVS plug-in.
7 | " GetLatestVimScripts: 3123 1 :AutoInstall: shell.zip
8 |
9 | " Don't source the plug-in when it's already been loaded or &compatible is set.
10 | if &cp || exists('g:loaded_shell')
11 | finish
12 | endif
13 |
14 | " Make sure vim-misc is installed. {{{1
15 |
16 | try
17 | " The point of this code is to do something completely innocent while making
18 | " sure the vim-misc plug-in is installed. We specifically don't use Vim's
19 | " exists() function because it doesn't load auto-load scripts that haven't
20 | " already been loaded yet (last tested on Vim 7.3).
21 | call type(g:xolox#misc#version)
22 | catch
23 | echomsg "Warning: The vim-shell plug-in requires the vim-misc plug-in which seems not to be installed! For more information please review the installation instructions in the readme (also available on the homepage and on GitHub). The vim-shell plug-in will now be disabled."
24 | let g:loaded_shell = 1
25 | finish
26 | endtry
27 |
28 | " Configuration defaults. {{{1
29 |
30 | if !exists('g:shell_fullscreen_always_on_top')
31 | " Set this to false (0) if you don't like the "always on top" behavior.
32 | let g:shell_fullscreen_always_on_top = 1
33 | endif
34 |
35 | if !exists('g:shell_mappings_enabled')
36 | " Set this to false (0) if you don't like the default mappings.
37 | let g:shell_mappings_enabled = 1
38 | endif
39 |
40 | if !exists('g:shell_verify_urls')
41 | " Set this to true if your URLs include significant trailing punctuation and
42 | " your Vim is compiled with Python support. XXX In this case the shell
43 | " plug-in will perform HTTP HEAD requests on your behalf.
44 | let g:shell_verify_urls = 0
45 | endif
46 |
47 | if !exists('g:shell_fullscreen_message')
48 | " Set this to false (0) to disable the message when entering full screen.
49 | let g:shell_fullscreen_message = 1
50 | endif
51 |
52 | " Automatic commands. {{{1
53 |
54 | augroup PluginShell
55 | " These enable automatic highlighting of URLs and e-mail addresses.
56 | autocmd! BufNew,BufRead,Syntax * call xolox#shell#highlight_urls()
57 | augroup END
58 |
59 | " Regular commands. {{{1
60 |
61 | command! -bar -nargs=? -complete=file Open call xolox#shell#open_cmd()
62 | command! -bar Maximize call xolox#shell#maximize()
63 | command! -bar Fullscreen call xolox#shell#fullscreen()
64 | command! -bar -bang -nargs=? MakeWithShell :call xolox#shell#make('c', , )
65 | command! -bar -bang -nargs=? LMakeWithShell :call xolox#shell#make('l', , )
66 |
67 | " Default key mappings. {{{1
68 |
69 | if g:shell_mappings_enabled
70 | inoremap :Open
71 | nnoremap :Open
72 | inoremap :Fullscreen
73 | nnoremap :Fullscreen
74 | inoremap :Maximize
75 | nnoremap :Maximize
76 | endif
77 |
78 | " Make sure the plug-in is only loaded once.
79 | let g:loaded_shell = 1
80 |
81 | " vim: ts=2 sw=2 et fdm=marker
82 |
--------------------------------------------------------------------------------