├── .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 | --------------------------------------------------------------------------------