Permalink
Browse files

Updated miscellaneous scripts

  • Loading branch information...
xolox committed May 13, 2013
2 parents 6539185 + 9c88b0e commit f8ee02d1d8bc18d593064c4c267ae303d1166cc1
Showing with 151 additions and 45 deletions.
  1. +2 −2 autoload/xolox/misc/compat.vim
  2. +104 −16 autoload/xolox/misc/os.vim
  3. +45 −27 autoload/xolox/shell.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.
View
@@ -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
View
@@ -3,9 +3,9 @@
" Last Change: May 13, 2013
" URL: http://peterodding.com/code/vim/shell/
-let g:xolox#shell#version = '0.12'
+let g:xolox#shell#version = '0.12.1'
-call xolox#misc#compat#check('shell', 2)
+call xolox#misc#compat#check('shell', 3)
if !exists('s:fullscreen_enabled')
let s:enoimpl = "%s() hasn't been implemented on your platform! %s"
@@ -14,7 +14,8 @@ if !exists('s:fullscreen_enabled')
let s:maximized = 0
endif
-function! xolox#shell#open_cmd(arg) " -- implementation of the :Open command {{{1
+function! xolox#shell#open_cmd(arg) " {{{1
+ " Implementation of the :Open command.
try
" No argument?
if a:arg !~ '\S'
@@ -88,7 +89,8 @@ function! s:open_at_cursor()
endif
endfunction
-function! xolox#shell#open_with_windows_shell(location)
+function! xolox#shell#open_with_windows_shell(location) " {{{1
+ " Open a location using the compiled DLL.
if xolox#shell#can_use_dll()
let error = s:library_call('openurl', a:location)
if error != ''
@@ -98,7 +100,8 @@ function! xolox#shell#open_with_windows_shell(location)
endif
endfunction
-function! xolox#shell#highlight_urls() " -- highlight URLs and e-mail addresses embedded in source code comments {{{1
+function! xolox#shell#highlight_urls() " {{{1
+ " Highlight URLs and e-mail addresses embedded in source code comments.
" URL highlighting breaks highlighting of <a href="..."> tags in HTML.
if exists('g:syntax_on') && &ft !~ xolox#misc#option#get('shell_hl_exclude', '^\(x|ht\)ml$')
if &ft == 'help'
@@ -117,7 +120,8 @@ function! xolox#shell#highlight_urls() " -- highlight URLs and e-mail addresses
endif
endfunction
-function! xolox#shell#execute_with_dll(cmd, async) " -- execute external commands on Windows using the compiled DLL {{{1
+function! xolox#shell#execute_with_dll(cmd, async) " {{{1
+ " Execute external commands on Windows using the compiled DLL.
let fn = 'execute_' . (a:async ? 'a' : '') . 'synchronous'
let cmd = &shell . ' ' . &shellcmdflag . ' ' . a:cmd
let result = s:library_call(fn, cmd)
@@ -132,21 +136,29 @@ function! xolox#shell#execute_with_dll(cmd, async) " -- execute external command
endif
endfunction
-function! xolox#shell#make(bang, args) " -- run :make silent (without a console window) {{{1
+function! xolox#shell#make(bang, args) " {{{1
+ " Run :make silent (without a console window).
let command = &makeprg
if a:args =~ '\S'
let command .= ' ' . a:args
endif
call xolox#misc#msg#info("shell.vim %s: Running make command %s ..", g:xolox#shell#version, command)
if a:bang == '!'
- cgetexpr xolox#shell#execute(command, 1)
+ cgetexpr s:make_cmd(command)
else
- cexpr xolox#shell#execute(command, 1)
+ cexpr s:make_cmd(command)
endif
cwindow
endfunction
-function! xolox#shell#maximize(...) " -- show/hide Vim's menu, tool bar and/or tab line {{{1
+function! s:make_cmd(command)
+ let command = a:command . ' 2>&1'
+ let result = xolox#misc#os#exec({'command': command, 'check': 0})
+ return join(result['stdout'], "\n")
+endfunction
+
+function! xolox#shell#maximize(...) " {{{1
+ " Show/hide Vim's menu, tool bar and/or tab line.
let new_state = a:0 == 0 ? !s:maximized : a:1
if new_state && !s:maximized
" Hide the main menu, tool bar and/or tab line. Remember what was hidden
@@ -177,7 +189,8 @@ function! xolox#shell#maximize(...) " -- show/hide Vim's menu, tool bar and/or t
return s:maximized
endfunction
-function! xolox#shell#fullscreen() " -- toggle Vim between normal and full-screen mode {{{1
+function! xolox#shell#fullscreen() " {{{1
+ " Toggle Vim between normal and full-screen mode.
" When entering full-screen...
if !s:fullscreen_enabled
@@ -251,11 +264,13 @@ function! xolox#shell#fullscreen() " -- toggle Vim between normal and full-scree
endfunction
-function! xolox#shell#is_fullscreen() " -- check whether Vim is currently in full-screen mode {{{1
+function! xolox#shell#is_fullscreen() " {{{1
+ " Check whether Vim is currently in full-screen mode.
return s:fullscreen_enabled
endfunction
-function! xolox#shell#url_exists(url) " -- check whether a URL points to an existing resource (using Python) {{{1
+function! xolox#shell#url_exists(url) " {{{1
+ " Check whether a URL points to an existing resource (using Python).
try
" Embedding Python code in Vim scripts is always a bit awkward :-(
" (because of the forced indentation thing Python insists on).
@@ -303,37 +318,40 @@ EOF
endtry
endfunction
-function! xolox#shell#url_pattern() " -- get the preferred/default pattern to match URLs {{{1
+function! xolox#shell#url_pattern() " {{{1
+ " Get the preferred/default pattern to match URLs.
return xolox#misc#option#get('shell_patt_url', '\<\w\{3,}://\(\(\S\&[^"]\)*\w\)\+[/?#]\?')
endfunction
-function! xolox#shell#mail_pattern() " -- get the preferred/default pattern to match e-mail addresses {{{1
+function! xolox#shell#mail_pattern() " {{{1
+ " Get the preferred/default pattern to match e-mail addresses.
return xolox#misc#option#get('shell_patt_mail', '\<\w[^@ \t\r<>]*\w@\w[^@ \t\r<>]\+\w\>')
endfunction
-" Miscellaneous script-local functions. {{{1
+function! xolox#shell#can_use_dll() " {{{1
+ " Check whether the compiled DLL is usable in the current environment.
+ if xolox#misc#os#is_win()
+ try
+ return s:library_call('libversion', '') == '0.5'
+ catch
+ return 0
+ endtry
+ endif
+endfunction
+
+" s:library_call() - Only defined on Windows. {{{1
if xolox#misc#os#is_win()
let s:cpu_arch = has('win64') ? 'x64' : 'x86'
let s:library = expand('<sfile>:p:h:h:h') . '\misc\shell\shell-' . s:cpu_arch . '.dll'
- function! s:library_call(fn, arg) " {{{2
+ function! s:library_call(fn, arg)
let result = libcall(s:library, a:fn, a:arg)
call xolox#misc#msg#debug("Called %s:%s, returning %s", s:library, a:fn, result)
return result
endfunction
- function! xolox#shell#can_use_dll() " {{{2
- if xolox#misc#os#is_win()
- try
- return s:library_call('libversion', '') == '0.5'
- catch
- return 0
- endtry
- endif
- endfunction
-
endif
" vim: ts=2 sw=2 et fdm=marker

0 comments on commit f8ee02d

Please sign in to comment.