"====================================================================== " " core.vim - " " Created by skywind on 2019/12/18 " Last Modified: 2022/08/31 16:25 " "====================================================================== " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : "====================================================================== " core routines "====================================================================== "---------------------------------------------------------------------- " global variables "---------------------------------------------------------------------- let g:quickui#core#has_nvim = has('nvim') let g:quickui#core#has_vim9 = v:version >= 900 let g:quickui#core#has_popup = exists('*popup_create') && v:version >= 800 let g:quickui#core#has_floating = has('nvim-0.4') let g:quickui#core#has_nvim_040 = has('nvim-0.4') let g:quickui#core#has_nvim_050 = has('nvim-0.5.0') let g:quickui#core#has_nvim_060 = has('nvim-0.6.0') let g:quickui#core#has_vim_820 = (has('nvim') == 0 && has('patch-8.2.1')) let g:quickui#core#has_win_exe = exists('*win_execute') let g:quickui#core#has_vim9script = (v:version >= 900) && has('vim9script') "---------------------------------------------------------------------- " internal variables "---------------------------------------------------------------------- let s:windows = has('win32') || has('win16') || has('win64') || has('win95') "---------------------------------------------------------------------- " object pool acquire "---------------------------------------------------------------------- function! quickui#core#object_acquire(name) if !exists('g:quickui#core#__object_pool__') let g:quickui#core#__object_pool__ = {} endif if !has_key(g:quickui#core#__object_pool__, a:name) let g:quickui#core#__object_pool__[a:name] = [] endif let array = g:quickui#core#__object_pool__[a:name] if len(array) == 0 return v:null endif let obj = remove(array, -1) return obj endfunc "---------------------------------------------------------------------- " object pool release "---------------------------------------------------------------------- function! quickui#core#object_release(name, obj) if !exists('g:quickui#core#__object_pool__') let g:quickui#core#__object_pool__ = {} endif if !has_key(g:quickui#core#__object_pool__, a:name) let g:quickui#core#__object_pool__[a:name] = [] endif call add(g:quickui#core#__object_pool__[a:name], a:obj) endfunc "---------------------------------------------------------------------- " replace string "---------------------------------------------------------------------- function! quickui#core#string_replace(text, old, new) let l:data = split(a:text, a:old, 1) return join(l:data, a:new) endfunc "---------------------------------------------------------------------- " compose two string "---------------------------------------------------------------------- function! quickui#core#string_compose(target, pos, source) if a:source == '' return a:target endif let pos = a:pos let source = a:source if pos < 0 let source = strcharpart(a:source, -pos) let pos = 0 endif let target = strcharpart(a:target, 0, pos) if strchars(target) < pos let target .= repeat(' ', pos - strchars(target)) endif let target .= source let target .= strcharpart(a:target, pos + strchars(source)) return target endfunc "---------------------------------------------------------------------- " fit size "---------------------------------------------------------------------- function! quickui#core#string_fit(source, size) let require = a:size let source = a:source let size = len(source) if size <= require return source endif if require <= 2 return repeat('.', (require < 0)? 0 : require) endif let avail = require - 2 let left = avail / 2 let right = avail - left let p1 = strpart(source, 0, left) let p2 = strpart(source, size - right) let text = p1 . '..' . p2 return text endfunc "---------------------------------------------------------------------- " eval & expand: '%{script}' in string "---------------------------------------------------------------------- function! quickui#core#expand_text(string) abort let partial = [] let index = 0 while 1 let pos = stridx(a:string, '%{', index) if pos < 0 let partial += [strpart(a:string, index)] break endif let head = '' if pos > index let partial += [strpart(a:string, index, pos - index)] endif let endup = stridx(a:string, '}', pos + 2) if endup < 0 let partial += [strpart(a:stirng, index)] break endif let index = endup + 1 if endup > pos + 2 let script = strpart(a:string, pos + 2, endup - (pos + 2)) let script = substitute(script, '^\s*\(.\{-}\)\s*$', '\1', '') let result = eval(script) let partial += [result] endif endwhile return join(partial, '') endfunc "---------------------------------------------------------------------- " escape key character (starts by &) from string "---------------------------------------------------------------------- function! quickui#core#escape(text) let text = a:text let rest = '' let start = 0 let obj = ['', '', -1, -1, -1] while 1 let pos = stridx(text, '&', start) if pos < 0 let rest .= strpart(text, start) break end let rest .= strpart(text, start, pos - start) let key = strpart(text, pos + 1, 1) let start = pos + 2 if key == '&' let rest .= '&' elseif key == '~' let rest .= '~' else let obj[1] = key let obj[2] = strlen(rest) let obj[3] = strchars(rest) let obj[4] = strdisplaywidth(rest) let rest .= key endif endwhile let obj[0] = rest return obj endfunc "---------------------------------------------------------------------- " list parse "---------------------------------------------------------------------- function! quickui#core#single_parse(description) let item = { 'part': [], 'size': 0 } let item.key_char = '' let item.key_pos = -1 let item.key_idx = -1 if type(a:description) == v:t_string let text = a:description let item.cmd = '' elseif type(a:description) == v:t_list let size = len(a:description) let text = (size > 0)? a:description[0] : '' let item.cmd = (size > 1)? a:description[1] : '' endif for text in split(text, "\t") let obj = quickui#core#escape(text) let item.part += [obj[0]] if obj[2] >= 0 && item.key_idx < 0 let item.key_char = obj[1] let item.key_pos = obj[4] let item.key_idx = item.size endif let item.size += 1 endfor return item endfunc "---------------------------------------------------------------------- " tabpage instance "---------------------------------------------------------------------- function! quickui#core#instance(local) let local = a:local if local != 0 if exists('t:__quickui__') return t:__quickui__ endif let t:__quickui__ = {} return t:__quickui__ else if exists('g:__quickui__') return g:__quickui__ endif let g:__quickui__ = {} return g:__quickui__ endif endfunc "---------------------------------------------------------------------- " buffer instance "---------------------------------------------------------------------- function! quickui#core#object(bid) let name = '__quickui__' let bid = (a:bid > 0)? a:bid : (bufnr()) if bufexists(bid) == 0 return v:null endif let obj = getbufvar(bid, name) if type(obj) != v:t_dict call setbufvar(bid, name, {}) let obj = getbufvar(bid, name) endif return obj endfunc "---------------------------------------------------------------------- " object cache: acquire "---------------------------------------------------------------------- function! quickui#core#popup_alloc(name) let inst = quickui#core#instance(1) if !has_key(inst, 'popup_cache') let inst.popup_cache = {} endif if !has_key(inst.popup_cache, a:name) let inst.popup_cache[a:name] = [] endif if !empty(inst.popup_cache[a:name]) let winid = remove(inst.popup_cache[a:name], -1) return winid endif let opts = {"line":1, "col":1, "wrap":0, "pos": 'topleft'} let winid = popup_create([], opts) call popup_hide(winid) call win_execute(winid, 'setlocal nonumber nowrap signcolumn=no') call setwinvar(winid, '&wincolor', 'QuickBG') return winid endfunc "---------------------------------------------------------------------- " object cache: release "---------------------------------------------------------------------- function! quickui#core#popup_release(name, winid) let inst = quickui#core#instance(1) if !has_key(inst, 'popup_cache') let inst.popup_cache = {} endif if !has_key(inst.popup_cache, a:name) let inst.popup_cache[a:name] = [] endif silent! call popup_hide(a:winid) let size = len(inst.popup_cache[a:name]) call insert(inst.popup_cache[a:name], a:winid, size) endfunc "---------------------------------------------------------------------- " local object "---------------------------------------------------------------------- function! quickui#core#popup_local(winid) let inst = quickui#core#instance(0) if !has_key(inst, 'popup_local') let inst.popup_local = {} endif if !has_key(inst.popup_local, a:winid) let inst.popup_local[a:winid] = {} endif return inst.popup_local[a:winid] endfunc "---------------------------------------------------------------------- " erase local data "---------------------------------------------------------------------- function! quickui#core#popup_clear(winid) let inst = quickui#core#instance(0) if !has_key(inst, 'popup_local') let inst.popup_local = {} endif if has_key(inst.popup_local, a:winid) call remove(inst.popup_local, a:winid) endif endfunc "---------------------------------------------------------------------- " vim/nvim compatible "---------------------------------------------------------------------- function! quickui#core#win_execute(winid, command, ...) let silent = (a:0 < 1)? 0 : (a:1) if g:quickui#core#has_popup != 0 if type(a:command) == v:t_string keepalt call win_execute(a:winid, a:command, silent) elseif type(a:command) == v:t_list keepalt call win_execute(a:winid, join(a:command, "\n"), silent) endif elseif g:quickui#core#has_win_exe == 0 let current = nvim_get_current_win() keepalt call nvim_set_current_win(a:winid) if type(a:command) == v:t_string if silent == 0 exec a:command else silent exec a:command endif elseif type(a:command) == v:t_list if silent == 0 exec join(a:command, "\n") else silent exec join(a:command, "\n") endif endif keepalt call nvim_set_current_win(current) else if type(a:command) == v:t_string keepalt call win_execute(a:winid, a:command, silent) elseif type(a:command) == v:t_list keepalt call win_execute(a:winid, join(a:command, "\n"), silent) endif endif endfunc "---------------------------------------------------------------------- " close window "---------------------------------------------------------------------- function! quickui#core#win_close(winid, force) let [tnr, wnr] = win_id2tabwin(a:winid) if tnr <= 0 || wnr <= 0 return -1 endif if g:quickui#core#has_nvim == 0 let cmd = 'close' . ((a:force != 0)? '!' : '') call quickui#core#win_execute(a:winid, cmd) else call nvim_win_close(a:winid, a:force) endif return 0 endfunc "---------------------------------------------------------------------- " alloc a new buffer "---------------------------------------------------------------------- function! quickui#core#buffer_alloc() if !exists('s:buffer_array') let s:buffer_array = {} endif let index = len(s:buffer_array) - 1 if index >= 0 let bid = s:buffer_array[index] unlet s:buffer_array[index] else if g:quickui#core#has_nvim == 0 let bid = bufadd('') call bufload(bid) call setbufvar(bid, '&buflisted', 0) call setbufvar(bid, '&bufhidden', 'hide') call setbufvar(bid, '&buftype', 'nofile') call setbufvar(bid, 'noswapfile', 1) else let bid = nvim_create_buf(v:false, v:true) call setbufvar(bid, '&buftype', 'nofile') call setbufvar(bid, '&bufhidden', 'hide') call setbufvar(bid, 'noswapfile', 1) endif endif call setbufvar(bid, '&modifiable', 1) call deletebufline(bid, 1, '$') call setbufvar(bid, '&modified', 0) call setbufvar(bid, '&filetype', '') return bid endfunc "---------------------------------------------------------------------- " free a buffer "---------------------------------------------------------------------- function! quickui#core#buffer_free(bid) if !exists('s:buffer_array') let s:buffer_array = {} endif let index = len(s:buffer_array) let s:buffer_array[index] = a:bid call setbufvar(a:bid, '&modifiable', 1) call deletebufline(a:bid, 1, '$') call setbufvar(a:bid, '&modified', 0) endfunc "---------------------------------------------------------------------- " update content "---------------------------------------------------------------------- function! quickui#core#buffer_update(bid, textlist) if type(a:textlist) == v:t_list let textlist = a:textlist else let textlist = split('' . a:textlist, '\n', 1) endif call setbufvar(a:bid, '&modifiable', 1) call deletebufline(a:bid, 1, '$') call setbufline(a:bid, 1, textlist) call setbufvar(a:bid, '&modified', 0) endfunc "---------------------------------------------------------------------- " clear content "---------------------------------------------------------------------- function! quickui#core#buffer_clear(bid) call quickui#core#buffer_update(a:bid, []) endfunc "---------------------------------------------------------------------- " get a named buffer "---------------------------------------------------------------------- function! quickui#core#scratch_buffer(name, textlist) if !exists('s:buffer_cache') let s:buffer_cache = {} endif if a:name != '' let bid = get(s:buffer_cache, a:name, -1) else let bid = -1 endif if bid < 0 let bid = quickui#core#buffer_alloc() if a:name != '' let s:buffer_cache[a:name] = bid endif endif call quickui#core#buffer_update(bid, a:textlist) call setbufvar(bid, 'current_syntax', '') return bid endfunc "---------------------------------------------------------------------- " dummy filter "---------------------------------------------------------------------- function! quickui#core#mock_function(id, text) return 0 endfunc "---------------------------------------------------------------------- " highlight region "---------------------------------------------------------------------- function! quickui#core#high_region(name, srow, scol, erow, ecol, virtual) let sep = (a:virtual == 0)? 'c' : 'v' let cmd = 'syn region ' . a:name . ' ' let cmd .= ' start=/\%' . a:srow . 'l\%' . a:scol . sep . '/' let cmd .= ' end=/\%' . a:erow . 'l\%' . a:ecol . sep . '/' return cmd endfunc "---------------------------------------------------------------------- " patterns "---------------------------------------------------------------------- function! quickui#core#border_extract(pattern) let parts = ['', '', '', '', '', '', '', '', '', '', ''] for idx in range(11) let parts[idx] = strcharpart(a:pattern, idx, 1) endfor return parts endfunc function! quickui#core#border_convert(pattern, nvim_format) if type(a:pattern) == v:t_string let p = quickui#core#border_extract(a:pattern) else let p = a:pattern endif if len(p) == 0 return [] endif if a:nvim_format == 0 let pattern = [ p[1], p[5], p[7], p[3], p[0], p[2], p[8], p[6] ] else let pattern = [ p[0], p[1], p[2], p[5], p[8], p[7], p[6], p[3] ] endif return pattern endfunc let s:border_styles = {} let s:border_styles[0] = quickui#core#border_extract(' ') let s:border_styles[1] = quickui#core#border_extract('+-+|-|+-+++') let s:border_styles[2] = quickui#core#border_extract('┌─┐│─│└─┘├┤') let s:border_styles[3] = quickui#core#border_extract('╔═╗║─║╚═╝╟╢') let s:border_styles[4] = quickui#core#border_extract('╭─╮│─│╰─╯├┤') let s:border_styles[5] = quickui#core#border_extract('/-\|-|\-/++') let s:border_ascii = quickui#core#border_extract('+-+|-|+-+++') let s:border_styles['none'] = [] let s:border_styles['single'] = s:border_styles[2] let s:border_styles['double'] = s:border_styles[3] let s:border_styles['rounded'] = s:border_styles[4] let s:border_styles['solid'] = s:border_styles[0] let s:border_styles['ascii'] = s:border_styles[1] let s:border_styles['default'] = s:border_styles[1] function! quickui#core#border_install(name, pattern) let s:border_styles[a:name] = quickui#core#border_extract(a:pattern) endfunc function! quickui#core#border_get(name) if has_key(s:border_styles, a:name) return s:border_styles[a:name] endif return s:border_ascii endfunc function! quickui#core#border_vim(name) let border = quickui#core#border_get(a:name) return quickui#core#border_convert(border, 0) endfunc function! quickui#core#border_nvim(name) let border = quickui#core#border_get(a:name) return quickui#core#border_convert(border, 1) endfunc function! quickui#core#border_auto(name) if g:quickui#core#has_nvim == 0 return quickui#core#border_vim(a:name) else return quickui#core#border_nvim(a:name) endif endfunc "---------------------------------------------------------------------- " returns cursor position for screen coordination "---------------------------------------------------------------------- function! quickui#core#cursor_pos() let pos = win_screenpos('.') return [pos[0] + winline() - 1, pos[1] + wincol() - 1] endfunc "---------------------------------------------------------------------- " screen boundary check, returns 1 for in screen, 0 for exceeding "---------------------------------------------------------------------- function! quickui#core#in_screen(line, column, width, height) let x = a:column - 1 let y = a:line - 1 let w = a:width let h = a:height let screenw = &columns let screenh = &lines return (x >= 0 && y >= 0 && x + w <= screenw && y + h <= screenh)? 1 : 0 endfunc "---------------------------------------------------------------------- " window fit screen "---------------------------------------------------------------------- function! quickui#core#screen_fit(line, column, width, height) let x = a:column - 1 let y = a:line - 1 let w = a:width let h = a:height let screenw = &columns let screenh = &lines let x = (x + w > screenw)? screenw - w : x let y = (y + h > screenh)? screenh - h : y let x = (x < 0)? 0 : x let y = (y < 0)? 0 : y return [y + 1, x + 1] endfunc "---------------------------------------------------------------------- " fit screen "---------------------------------------------------------------------- function! quickui#core#around_cursor(width, height) let cursor_pos = quickui#core#cursor_pos() let row = cursor_pos[0] + 1 let col = cursor_pos[1] + 1 if quickui#core#in_screen(row, col, a:width, a:height) return [row, col] endif if col + a:width - 1 > &columns let col = col - (1 + a:width) if quickui#core#in_screen(row, col, a:width, a:height) return [row, col] endif endif if row + a:height - 1 > &lines let row = row - (1 + a:height) if quickui#core#in_screen(row, col, a:width, a:height) return [row, col] endif endif if cursor_pos[0] + a:height + 2 < &lines let row = cursor_pos[0] + 1 else let row = cursor_pos[0] - a:height endif if cursor_pos[1] + a:width + 2 < &columns let col = cursor_pos[1] + 1 else let col = cursor_pos[1] - a:width endif return quickui#core#screen_fit(row, col, a:width, a:height) endfunc "---------------------------------------------------------------------- " safe input "---------------------------------------------------------------------- function! quickui#core#input(prompt, text) call inputsave() try let t = input(a:prompt, a:text) catch /^Vim:Interrupt$/ let t = "\" endtry call inputrestore() return t endfunc "---------------------------------------------------------------------- " safe change dir "---------------------------------------------------------------------- function! quickui#core#chdir(path) if has('nvim') let cmd = haslocaldir()? 'lcd' : (haslocaldir(-1, 0)? 'tcd' : 'cd') else let cmd = haslocaldir()? ((haslocaldir() == 1)? 'lcd' : 'tcd') : 'cd' endif silent execute cmd . ' '. fnameescape(a:path) endfunc "---------------------------------------------------------------------- " full file name "---------------------------------------------------------------------- function! quickui#core#fullname(f) let f = a:f if f =~ "'." try redir => m silent exe ':marks' f[1] redir END let f = split(split(m, '\n')[-1])[-1] let f = filereadable(f)? f : '' catch let f = '%' endtry endif if f == '%' let f = expand('%') if &bt == 'terminal' || &bt == 'nofile' let f = '' endif endif let f = fnamemodify(f, ':p') if s:windows let f = substitute(f, "\\", '/', 'g') endif if f =~ '\/$' let f = fnamemodify(f, ':h') endif return f endfunc "---------------------------------------------------------------------- " returns nearest parent directory contains one of the markers "---------------------------------------------------------------------- function! quickui#core#find_root(name, markers, strict) let name = fnamemodify((a:name != '')? a:name : bufname('%'), ':p') let finding = '' " iterate all markers for marker in a:markers if marker != '' " search as a file let x = findfile(marker, name . '/;') let x = (x == '')? '' : fnamemodify(x, ':p:h') " search as a directory let y = finddir(marker, name . '/;') let y = (y == '')? '' : fnamemodify(y, ':p:h:h') " which one is the nearest directory ? let z = (strchars(x) > strchars(y))? x : y " keep the nearest one in finding let finding = (strchars(z) > strchars(finding))? z : finding endif endfor if finding == '' let path = (a:strict == 0)? fnamemodify(name, ':h') : '' else let path = fnamemodify(finding, ':p') endif if has('win32') || has('win16') || has('win64') || has('win95') let path = substitute(path, '\/', '\', 'g') endif if path =~ '[\/\\]$' let path = fnamemodify(path, ':h') endif return path endfunc "---------------------------------------------------------------------- " find project root "---------------------------------------------------------------------- function! quickui#core#project_root(name, ...) let markers = ['.project', '.git', '.hg', '.svn', '.root'] if exists('g:quickui_rootmarks') let markers = g:quickui_rootmarks elseif exists('g:asyncrun_rootmarks') let markers = g:asyncrun_rootmarks endif let path = quickui#core#fullname(a:name) let strict = (a:0 > 0)? (a:1) : 0 return quickui#core#find_root(path, markers, strict) endfunc "---------------------------------------------------------------------- " expand macros "---------------------------------------------------------------------- function! quickui#core#expand_macros() let macros = {} let macros['VIM_FILEPATH'] = expand("%:p") let macros['VIM_FILENAME'] = expand("%:t") let macros['VIM_FILEDIR'] = expand("%:p:h") let macros['VIM_FILENOEXT'] = expand("%:t:r") let macros['VIM_PATHNOEXT'] = expand("%:p:r") let macros['VIM_FILEEXT'] = "." . expand("%:e") let macros['VIM_FILETYPE'] = (&filetype) let macros['VIM_CWD'] = getcwd() let macros['VIM_RELDIR'] = expand("%:h:.") let macros['VIM_RELNAME'] = expand("%:p:.") let macros['VIM_CWORD'] = expand("") let macros['VIM_CFILE'] = expand("") let macros['VIM_CLINE'] = line('.') let macros['VIM_VERSION'] = ''.v:version let macros['VIM_SVRNAME'] = v:servername let macros['VIM_COLUMNS'] = ''.&columns let macros['VIM_LINES'] = ''.&lines let macros['VIM_GUI'] = has('gui_running')? 1 : 0 let macros['VIM_ROOT'] = quickui#core#project_root('%', 0) let macros['VIM_HOME'] = expand(split(&rtp, ',')[0]) let macros['VIM_PRONAME'] = fnamemodify(macros['VIM_ROOT'], ':t') let macros['VIM_DIRNAME'] = fnamemodify(macros['VIM_CWD'], ':t') let macros[''] = macros['VIM_CWD'] let macros[''] = macros['VIM_ROOT'] if expand("%:e") == '' let macros['VIM_FILEEXT'] = '' endif return macros endfunc "---------------------------------------------------------------------- " write script to a file and return filename "---------------------------------------------------------------------- function! quickui#core#write_script(command, pause) let tmpname = fnamemodify(tempname(), ':h') . '\quickui1.cmd' let command = a:command if s:windows != 0 let lines = ["@echo off\r"] let $VIM_COMMAND = a:command let $VIM_PAUSE = (a:pause)? 'pause' : '' let lines += ["call %VIM_COMMAND% \r"] let lines += ["set VIM_EXITCODE=%ERRORLEVEL%\r"] let lines += ["call %VIM_PAUSE% \r"] let lines += ["exit %VIM_EXITCODE%\r"] else let shell = split(&shell, ' ', 1)[0] let lines = ['#! ' . shell] let lines += [command] if a:pause != 0 if executable('bash') let pause = 'read -n1 -rsp "press any key to continue ..."' let lines += ['bash -c ''' . pause . ''''] else let lines += ['echo "press enter to continue ..."'] let lines += ['sh -c "read _tmp_"'] endif endif let tmpname = fnamemodify(tempname(), ':h') . '/quickui1.sh' endif call writefile(lines, tmpname) if s:windows == 0 if exists('*setfperm') silent! call setfperm(tmpname, 'rwxrwxrws') endif endif return tmpname endfunc "---------------------------------------------------------------------- " string replace "---------------------------------------------------------------------- function! quickui#core#string_replace(text, old, new) let data = split(a:text, a:old, 1) return join(data, a:new) endfunc "---------------------------------------------------------------------- " string strip "---------------------------------------------------------------------- function! quickui#core#string_strip(text) return substitute(a:text, '^\s*\(.\{-}\)[\t\r\n ]*$', '\1', '') endfunc "---------------------------------------------------------------------- " extract opts+command "---------------------------------------------------------------------- function! quickui#core#extract_opts(command) let cmd = substitute(a:command, '^\s*\(.\{-}\)[\s\r\n]*$', '\1', '') let opts = {} while cmd =~# '^-\%(\w\+\)\%([= ]\|$\)' let opt = matchstr(cmd, '^-\zs\w\+') if cmd =~ '^-\w\+=' let val = matchstr(cmd, '^-\w\+=\zs\%(\\.\|\S\)*') else let val = '' endif let opts[opt] = substitute(val, '\\\(\s\)', '\1', 'g') let cmd = substitute(cmd, '^-\w\+\%(=\%(\\.\|\S\)*\)\=\s*', '', '') endwhile let cmd = substitute(cmd, '^\s*\(.\{-}\)\s*$', '\1', '') let cmd = substitute(cmd, '^@\s*', '', '') return [cmd, opts] endfunc "---------------------------------------------------------------------- " split cmdline to argv "---------------------------------------------------------------------- function! quickui#core#split_argv(cmdline) let cmd = quickui#core#string_strip(a:cmdline) let argv = [] while cmd =~# '^\%(\\.\|\S\)\+' let arg = matchstr(cmd, '^\%(\\.\|\S\)\+') let cmd = substitute(cmd, '^\%(\\.\|\S\)\+\s*', '', '') let val = substitute(arg, '\\\(\s\)', '\1', 'g') let argv += [val] endwhile return argv endfunc "---------------------------------------------------------------------- " execute string "---------------------------------------------------------------------- function! quickui#core#execute_string(text) let cmd = a:text if cmd =~ '^[a-zA-Z0-9_#]\+(.*)$' exec 'call ' . cmd elseif cmd =~ '^' let keys = strpart(cmd, 5) call feedkeys(keys) elseif cmd =~ '^@' let keys = strpart(cmd, 1) call feedkeys(keys) elseif cmd =~ '^' let keys = strpart(cmd, 6) call feedkeys("\" . keys) else exec cmd endif endfunc