if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1 " ___vital___ " NOTE: lines between '" ___vital___' is generated by :Vitalize. " Do not mofidify the code nor insert new lines before '" ___vital___' function! s:_SID() abort return matchstr(expand(''), '\zs\d\+\ze__SID$') endfunction execute join(['function! vital#_crystal#Process#import() abort', printf("return map({'shellescape': '', 'has_vimproc': '', 'system': '', 'iconv': '', 'spawn': '', 'get_last_status': ''}, \"vital#_crystal#function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") delfunction s:_SID " ___vital___ " 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('') function! s:spawn(expr, ...) abort if type(a:expr) is s:TYPE_LIST let special = 1 let cmdline = join(map(a:expr, 's: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 'vital: Process: invalid argument (value type:' . type(a:expr) . ')' endif if s:is_windows silent execute '!start' cmdline else silent execute '!' cmdline '&' endif 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 'vital: Process: 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 'vital: Process: 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) if has('nvim') throw "vital: Process: neovim's system() doesn't support background(&) process (cmdline:" . string(a:str) . ')' endif 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(...) abort try let shellslash = &shellslash set noshellslash return call('shellescape', a:000) finally let &shellslash = shellslash endtry 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