summaryrefslogtreecommitdiffstats
path: root/autoload/vital/_crystal/Process.vim
diff options
context:
space:
mode:
Diffstat (limited to 'autoload/vital/_crystal/Process.vim')
-rw-r--r--autoload/vital/_crystal/Process.vim185
1 files changed, 185 insertions, 0 deletions
diff --git a/autoload/vital/_crystal/Process.vim b/autoload/vital/_crystal/Process.vim
new file mode 100644
index 00000000..c2deb9e5
--- /dev/null
+++ b/autoload/vital/_crystal/Process.vim
@@ -0,0 +1,185 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1
+
+" TODO: move all comments to doc file.
+"
+"
+" FIXME: This module name should be Vital.System ?
+" But the name has been already taken.
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+
+" FIXME: Unfortunately, can't use s:_vital_loaded() for this purpose.
+" Because these variables are used when this script file is loaded.
+let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95')
+let s:is_unix = has('unix')
+" As of 7.4.122, the system()'s 1st argument is converted internally by Vim.
+" Note that Patch 7.4.122 does not convert system()'s 2nd argument and
+" return-value. We must convert them manually.
+let s:need_trans = v:version < 704 || (v:version == 704 && !has('patch122'))
+
+let s:TYPE_DICT = type({})
+let s:TYPE_LIST = type([])
+let s:TYPE_STRING = type("")
+
+
+" Execute program in the background from Vim.
+" Return an empty string always.
+"
+" If a:expr is a List, shellescape() each argument.
+" If a:expr is a String, the arguments are passed as-is.
+"
+" Windows:
+" Using :!start , execute program without via cmd.exe.
+" Spawning 'expr' with 'noshellslash'
+" keep special characters from unwanted expansion.
+" (see :help shellescape())
+"
+" Unix:
+" using :! , execute program in the background by shell.
+function! s:spawn(expr, ...) abort
+ let shellslash = 0
+ if s:is_windows
+ let shellslash = &l:shellslash
+ setlocal noshellslash
+ endif
+ try
+ if type(a:expr) is s:TYPE_LIST
+ let special = 1
+ let cmdline = join(map(a:expr, 'shellescape(v:val, special)'), ' ')
+ elseif type(a:expr) is s:TYPE_STRING
+ let cmdline = a:expr
+ if a:0 && a:1
+ " for :! command
+ let cmdline = substitute(cmdline, '\([!%#]\|<[^<>]\+>\)', '\\\1', 'g')
+ endif
+ else
+ throw 'Process.spawn(): invalid argument (value type:'.type(a:expr).')'
+ endif
+ if s:is_windows
+ silent execute '!start' cmdline
+ else
+ silent execute '!' cmdline '&'
+ endif
+ finally
+ if s:is_windows
+ let &l:shellslash = shellslash
+ endif
+ endtry
+ return ''
+endfunction
+
+" iconv() wrapper for safety.
+function! s:iconv(expr, from, to) abort
+ if a:from == '' || a:to == '' || a:from ==? a:to
+ return a:expr
+ endif
+ let result = iconv(a:expr, a:from, a:to)
+ return result != '' ? result : a:expr
+endfunction
+
+" Check vimproc.
+function! s:has_vimproc() abort
+ if !exists('s:exists_vimproc')
+ try
+ call vimproc#version()
+ let s:exists_vimproc = 1
+ catch
+ let s:exists_vimproc = 0
+ endtry
+ endif
+ return s:exists_vimproc
+endfunction
+
+" * {command} [, {input} [, {timeout}]]
+" * {command} [, {dict}]
+" {dict} = {
+" use_vimproc: bool,
+" input: string,
+" timeout: bool,
+" background: bool,
+" }
+function! s:system(str, ...) abort
+ " Process optional arguments at first
+ " because use_vimproc is required later
+ " for a:str argument.
+ let input = ''
+ let use_vimproc = s:has_vimproc()
+ let background = 0
+ let args = []
+ if a:0 ==# 1
+ " {command} [, {dict}]
+ " a:1 = {dict}
+ if type(a:1) is s:TYPE_DICT
+ if has_key(a:1, 'use_vimproc')
+ let use_vimproc = a:1.use_vimproc
+ endif
+ if has_key(a:1, 'input')
+ let args += [s:iconv(a:1.input, &encoding, 'char')]
+ endif
+ if use_vimproc && has_key(a:1, 'timeout')
+ " ignores timeout unless you have vimproc.
+ let args += [a:1.timeout]
+ endif
+ if has_key(a:1, 'background')
+ let background = a:1.background
+ endif
+ elseif type(a:1) is s:TYPE_STRING
+ let args += [s:iconv(a:1, &encoding, 'char')]
+ else
+ throw 'Process.system(): invalid argument (value type:'.type(a:1).')'
+ endif
+ elseif a:0 >= 2
+ " {command} [, {input} [, {timeout}]]
+ " a:000 = [{input} [, {timeout}]]
+ let [input; rest] = a:000
+ let input = s:iconv(input, &encoding, 'char')
+ let args += [input] + rest
+ endif
+
+ " Process a:str argument.
+ if type(a:str) is s:TYPE_LIST
+ let expr = use_vimproc ? '"''" . v:val . "''"' : 's:shellescape(v:val)'
+ let command = join(map(copy(a:str), expr), ' ')
+ elseif type(a:str) is s:TYPE_STRING
+ let command = a:str
+ else
+ throw 'Process.system(): invalid argument (value type:'.type(a:str).')'
+ endif
+ if s:need_trans
+ let command = s:iconv(command, &encoding, 'char')
+ endif
+ let args = [command] + args
+ if background && (use_vimproc || !s:is_windows)
+ let args[0] = args[0] . ' &'
+ endif
+
+ let funcname = use_vimproc ? 'vimproc#system' : 'system'
+ let output = call(funcname, args)
+ let output = s:iconv(output, 'char', &encoding)
+ return output
+endfunction
+
+function! s:get_last_status() abort
+ return s:has_vimproc() ?
+ \ vimproc#get_last_status() : v:shell_error
+endfunction
+
+if s:is_windows
+ function! s:shellescape(command) abort
+ return substitute(a:command, '[&()[\]{}^=;!''+,`~]', '^\0', 'g')
+ endfunction
+else
+ function! s:shellescape(...) abort
+ return call('shellescape', a:000)
+ endfunction
+endif
+
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
+
+" vim:set et ts=2 sts=2 sw=2 tw=0:
+
+endif