diff options
-rw-r--r-- | autoload/xolox/easytags.vim | 32 | ||||
-rw-r--r-- | autoload/xolox/misc/compat.vim | 4 | ||||
-rw-r--r-- | autoload/xolox/misc/os.vim | 120 | ||||
-rw-r--r-- | plugin/easytags.vim | 40 |
4 files changed, 128 insertions, 68 deletions
diff --git a/autoload/xolox/easytags.vim b/autoload/xolox/easytags.vim index 180d469..6183e11 100644 --- a/autoload/xolox/easytags.vim +++ b/autoload/xolox/easytags.vim @@ -1,11 +1,11 @@ " Vim script " Author: Peter Odding <peter@peterodding.com> -" Last Change: May 5, 2013 +" Last Change: May 13, 2013 " URL: http://peterodding.com/code/vim/easytags/ -let g:xolox#easytags#version = '3.2' +let g:xolox#easytags#version = '3.3' -call xolox#misc#compat#check('easytags', 2) +call xolox#misc#compat#check('easytags', 3) " Public interface through (automatic) commands. {{{1 @@ -238,19 +238,8 @@ function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3 let has_updates = 1 if a:cmdline != '' call xolox#misc#msg#debug("easytags.vim %s: Executing %s.", g:xolox#easytags#version, a:cmdline) - try - let lines = xolox#shell#execute(a:cmdline, 1) - let has_updates = a:firstrun || s:has_updates(a:cfile, join(lines, "\n")) - catch /^Vim\%((\a\+)\)\=:E117/ - " Ignore missing shell.vim plug-in. - let output = system(a:cmdline) - if v:shell_error - let msg = "Failed to update tags file %s: %s!" - throw printf(msg, fnamemodify(a:tagsfile, ':~'), strtrans(output)) - endif - let lines = split(output, "\n") - let has_updates = a:firstrun || s:has_updates(a:cfile, output) - endtry + let lines = xolox#misc#os#exec({'command': a:cmdline})['stdout'] + let has_updates = a:firstrun || s:has_updates(a:cfile, join(lines, "\n")) if a:firstrun if a:cfile != '' call xolox#misc#timer#stop("easytags.vim %s: Created tags for %s in %s.", g:xolox#easytags#version, expand('%:p:~'), a:starttime) @@ -493,16 +482,7 @@ function! xolox#easytags#supported_filetypes() " {{{2 let listing = [] if !empty(g:easytags_cmd) let command = g:easytags_cmd . ' --list-languages' - try - let listing = xolox#shell#execute(command, 1) - catch /^Vim\%((\a\+)\)\=:E117/ - " Ignore missing shell.vim plug-in. - let listing = split(system(command), "\n") - if v:shell_error - let msg = "Failed to get supported languages! (output: %s)" - throw printf(msg, strtrans(join(listing, "\n"))) - endif - endtry + let listing = xolox#misc#os#exec({'command': command})['stdout'] endif let s:supported_filetypes = map(copy(listing) + keys(xolox#misc#option#get('easytags_languages', {})), 's:check_filetype(listing, v:val)') let msg = "easytags.vim %s: Retrieved %i supported languages in %s." diff --git a/autoload/xolox/misc/compat.vim b/autoload/xolox/misc/compat.vim index 52c5c28..70a4287 100644 --- a/autoload/xolox/misc/compat.vim +++ b/autoload/xolox/misc/compat.vim @@ -1,13 +1,13 @@ " Vim auto-load script " Author: Peter Odding <peter@peterodding.com> -" Last Change: April 28, 2013 +" Last Change: May 13, 2013 " URL: http://peterodding.com/code/vim/misc/ " The following integer will be bumped whenever a change in the miscellaneous " scripts breaks backwards compatibility. This enables my Vim plug-ins to fail " early when they detect an incompatible version, instead of breaking at the " worst possible moments :-). -let g:xolox#misc#compat#version = 2 +let g:xolox#misc#compat#version = 3 " Remember the directory where the miscellaneous scripts are loaded from " so the user knows which plug-in to update if incompatibilities arise. diff --git a/autoload/xolox/misc/os.vim b/autoload/xolox/misc/os.vim index 451ca57..ef036df 100644 --- a/autoload/xolox/misc/os.vim +++ b/autoload/xolox/misc/os.vim @@ -1,29 +1,117 @@ " Vim auto-load script " Author: Peter Odding <peter@peterodding.com> -" Last Change: November 24, 2011 +" Last Change: May 13, 2013 " URL: http://peterodding.com/code/vim/misc/ -let g:xolox#misc#os#version = '0.1' +let g:xolox#misc#os#version = '0.2' -" Check whether Vim is running on Microsoft Windows. - -function! xolox#misc#os#is_win() +function! xolox#misc#os#is_win() " {{{1 + " Check whether Vim is running on Microsoft Windows. return has('win16') || has('win32') || has('win64') endfunction -" Execute an external command (hiding the console on Windows when possible). - -function! xolox#misc#os#exec(cmdline, ...) +function! xolox#misc#os#exec(options) " {{{1 + " Execute an external command (hiding the console on Windows when possible). + " NB: Everything below is wrapped in a try/finally block to guarantee + " cleanup of temporary files. try - " Try using my shell.vim plug-in. - return call('xolox#shell#execute', [a:cmdline, 1] + a:000) - catch /^Vim\%((\a\+)\)\=:E117/ - " Fall back to system() when we get an "unknown function" error. - let output = call('system', [a:cmdline] + a:000) - if v:shell_error - throw printf("os.vim %s: Command %s failed: %s", g:xolox#misc#os#version, a:cmdline, xolox#misc#str#trim(output)) + + " Unpack the options. + let cmd = a:options['command'] + let async = get(a:options, 'async', 0) + + " Write the input for the external command to a temporary file? + if has_key(a:options, 'stdin') + let tempin = tempname() + if type(a:options['stdin']) == type([]) + let lines = a:options['stdin'] + else + let lines = split(a:options['stdin'], "\n") + endif + call writefile(lines, tempin) + let cmd .= ' < ' . xolox#misc#escape#shell(tempin) + endif + + " Redirect the standard output and standard error streams of the external + " process to temporary files? (only in synchronous mode, which is the + " default). + if !async + let tempout = tempname() + let temperr = tempname() + let cmd = printf('(%s) 1>%s 2>%s', cmd, + \ xolox#misc#escape#shell(tempout), + \ xolox#misc#escape#shell(temperr)) + endif + + " If A) we're on Windows, B) the vim-shell plug-in is installed and C) the + " compiled DLL works, we'll use that because it's the most user friendly + " method. If the plug-in is not installed Vim will raise the exception + " "E117: Unknown function" which is caught and handled below. + try + if xolox#shell#can_use_dll() + " Let the user know what's happening (in case they're interested). + call xolox#misc#msg#debug("os.vim %s: Executing external command using compiled DLL: %s", g:xolox#misc#os#version, cmd) + let exit_code = xolox#shell#execute_with_dll(cmd, async) + endif + catch /^Vim\%((\a\+)\)\=:E117/ + call xolox#misc#msg#debug("os.vim %s: The vim-shell plug-in is not installed, falling back to system() function.", g:xolox#misc#os#version) + endtry + + " If we cannot use the DLL, we fall back to the default and generic + " implementation using Vim's system() function. + if !exists('exit_code') + + " Enable asynchronous mode (very platform specific). + if async + if xolox#misc#os#is_win() + let cmd = 'start /b ' . cmd + elseif has('unix') + let cmd = '(' . cmd . ') &' + else + call xolox#misc#msg#warn("os.vim %s: I don't know how to run commands asynchronously on your platform! Falling back to synchronous mode.", g:xolox#misc#os#version) + endif + endif + + " Let the user know what's happening (in case they're interested). + call xolox#misc#msg#debug("os.vim %s: Executing external command using system() function: %s", g:xolox#misc#os#version, cmd) + call system(cmd) + let exit_code = v:shell_error + endif - return split(output, "\n") + + let result = {} + if !async + " If we just executed a synchronous command and the caller didn't + " specifically ask us *not* to check the exit code of the external + " command, we'll do so now. + if get(a:options, 'check', 1) && exit_code != 0 + let msg = "os.vim %s: External command failed with exit code %d: %s" + throw printf(msg, g:xolox#misc#os#version, result['exit_code'], result['command']) + endif + " Return the results as a dictionary with three key/value pairs. + let result['exit_code'] = exit_code + let result['stdout'] = s:readfile(tempout) + let result['stderr'] = s:readfile(temperr) + endif + return result + + finally + " Cleanup any temporary files we created. + for name in ['tempin', 'tempout', 'temperr'] + if exists(name) + call delete({name}) + endif + endfor + endtry + +endfunction + +function! s:readfile(fname) " {{{1 + " readfile() that swallows errors. + try + return readfile(a:fname) + catch + return [] endtry endfunction diff --git a/plugin/easytags.vim b/plugin/easytags.vim index 935ef40..64361a7 100644 --- a/plugin/easytags.vim +++ b/plugin/easytags.vim @@ -1,6 +1,6 @@ " Vim plug-in " Author: Peter Odding <peter@peterodding.com> -" Last Change: April 19, 2013 +" Last Change: May 13, 2013 " URL: http://peterodding.com/code/vim/easytags/ " Requires: Exuberant Ctags (http://ctags.sf.net) @@ -58,12 +58,12 @@ function! s:InitEasyTags(version) " FIXME The code below that searches the $PATH is not used on Windows at " the moment because xolox#misc#path#which() generally produces absolute " paths and on Windows these absolute paths tend to contain spaces which - " makes xolox#shell#execute() fail. I've tried quoting the program name - " with double quotes but it fails just the same (it works with system() - " though). Anyway the problem of having multiple conflicting versions of - " Exuberant Ctags installed is not that relevant to Windows since it - " doesn't have a package management system. I still want to fix - " xolox#shell#execute() though. + " makes xolox#shell#execute_with_dll() fail. I've tried quoting the + " program name with double quotes but it fails just the same (it works + " with system() though). Anyway the problem of having multiple conflicting + " versions of Exuberant Ctags installed is not that relevant to Windows + " since it doesn't have a package management system. I still want to fix + " xolox#shell#execute_with_dll() though. if s:CheckCtags('ctags', a:version) let g:easytags_cmd = 'ctags' return 1 @@ -96,23 +96,15 @@ function! s:CheckCtags(name, version) " --list-languages option (and more). if executable(a:name) let command = a:name . ' --version' - try - let listing = join(xolox#shell#execute(command, 1), '\n') - catch /^Vim\%((\a\+)\)\=:E117/ - " Ignore missing shell.vim plug-in. - let listing = system(command) - catch - " xolox#shell#execute() converts shell errors to exceptions and since - " we're checking whether one of several executables exists we don't want - " to throw an error when the first one doesn't! - return - endtry - let pattern = 'Exuberant Ctags \zs\(\d\+\(\.\d\+\)*\|Development\)' - let g:easytags_ctags_version = matchstr(listing, pattern) - if g:easytags_ctags_version == 'Development' - return 1 - else - return s:VersionToNumber(g:easytags_ctags_version) >= a:version + let result = xolox#misc#os#exec({'command': command, 'check': 0}) + if result['exit_code'] == 0 + let pattern = 'Exuberant Ctags \zs\(\d\+\(\.\d\+\)*\|Development\)' + let g:easytags_ctags_version = matchstr(result['stdout'][0], pattern) + if g:easytags_ctags_version == 'Development' + return 1 + else + return s:VersionToNumber(g:easytags_ctags_version) >= a:version + endif endif endif endfunction |