Files
.cache
bash
c
gdb
git
haskell
info
python
qckcmd
rss
sql
tf2
tmux
vim
.vim
autoload
quickui
command.vim
confirm.vim
context.vim
core.vim
highlight.vim
input.vim
listbox.vim
menu.vim
palette.vim
palette9.vim
preview.vim
readline.vim
style.vim
terminal.vim
textbox.vim
tools.vim
utils.vim
window.vim
DrawIt.vim
acp.vim
markx.vim
tagbar.vim
colors
dist
doc
ftdetect
plugin
syntax
.vimrc
.vimrc9
x11
xterm
zsh
.gitignore
dotfiles/vim/.vim/autoload/quickui/tools.vim
2024-02-19 17:02:19 +01:00

524 lines
15 KiB
VimL

"======================================================================
"
" tools.vim -
"
" Created by skywind on 2019/12/23
" Last Modified: 2021/11/30 14:43
"
"======================================================================
" vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 :
"----------------------------------------------------------------------
" list buffer ids
"----------------------------------------------------------------------
function! s:buffer_list()
let l:ls_cli = get(g:, 'quickui_buffer_list_cli', 'ls t')
redir => buflist
silent execute l:ls_cli
redir END
let bids = []
for curline in split(buflist, '\n')
if curline =~ '^\s*\d\+'
let bid = str2nr(matchstr(curline, '^\s*\zs\d\+'))
let bids += [bid]
endif
endfor
return bids
endfunc
"----------------------------------------------------------------------
" get default width
"----------------------------------------------------------------------
function! s:get_tools_width()
let width = get(g:, 'quickui_tools_width', 70)
endfunc
"----------------------------------------------------------------------
" locals
"----------------------------------------------------------------------
let s:keymaps = '123456789abcdefimnopqrstuvwxyz'
"----------------------------------------------------------------------
" switch buffer callback
"----------------------------------------------------------------------
function! quickui#tools#buffer_switch(bid)
let switch = get(g:, 'quickui_switch_mode', &switchbuf)
let code = g:quickui#listbox#current.tag
let name = fnamemodify(bufname(a:bid), ':p')
let opts = {}
let bid = str2nr('' . a:bid)
if code == ''
let opts.switch = get(g:, 'quickui_switch_enter', switch)
call quickui#utils#switch(bid, opts)
elseif code == '1'
let opts.switch = get(g:, 'quickui_switch_space', switch)
call quickui#utils#switch(bid, opts)
elseif code == '2'
exec 'b '. a:bid
elseif code == '3'
exec 'vs'
exec 'b '. a:bid
elseif code == '4'
exec 'split'
exec 'b '. a:bid
elseif code == '5'
exec 'tab split'
exec 'b '. a:bid
elseif code == '6'
exec 'tab drop ' . fnameescape(name)
endif
endfunc
"----------------------------------------------------------------------
" get content
"----------------------------------------------------------------------
function! quickui#tools#list_buffer(switch)
let bids = s:buffer_list()
let content = []
let index = 0
let current = -1
let bufnr = bufnr()
let s:switch = a:switch
for bid in bids
let key = (index < len(s:keymaps))? strpart(s:keymaps, index, 1) : ''
let text = '[' . ((key == '')? ' ' : ('&' . key)) . "]\t"
let text .= "\t"
let name = fnamemodify(bufname(bid), ':p')
let main = fnamemodify(name, ':t')
let path = fnamemodify(name, ':h')
let buftype = getbufvar(bid, '&buftype')
if main == ''
continue
elseif buftype == 'nofile' || buftype == 'quickfix'
continue
endif
let text = text . main . " " . "(" . bid . ")\t" . path
let cmd = 'call quickui#tools#buffer_switch(' . bid . ')'
if a:switch != ''
" let cmd = a:switch . ' ' . fnameescape(name)
endif
let content += [[text, cmd]]
if bid == bufnr()
let current = index
endif
let index += 1
endfor
let opts = {'title': 'Switch Buffer', 'index':current, 'close':'button'}
let opts.border = g:quickui#style#border
let opts.keymap = {}
let opts.keymap["\<space>"] = 'TAG:1'
let opts.keymap["\<c-e>"] = 'TAG:2'
let opts.keymap["\<c-]>"] = 'TAG:3'
let opts.keymap["\<c-x>"] = 'TAG:4'
let opts.keymap["\<c-t>"] = 'TAG:5'
let opts.keymap["\<c-g>"] = 'TAG:6'
if exists('g:quickui_tools_width')
let opts.w = quickui#utils#tools_width()
endif
" let opts.syntax = 'cpp'
let maxheight = (&lines) * 60 / 100
if len(content) > maxheight
let opts.h = maxheight
endif
if len(content) == 0
redraw
echohl ErrorMsg
echo "Empty buffer list"
echohl None
return -1
endif
call quickui#listbox#open(content, opts)
endfunc
"----------------------------------------------------------------------
" list function
"----------------------------------------------------------------------
function! quickui#tools#list_function()
let ctags = get(g:, 'quickui_ctags_exe', 'ctags')
if !executable(ctags)
let msg = 'Not find ctags, add to $PATH or specify in '
call quickui#utils#errmsg(msg . 'g:quickui_ctags_exe')
return -1
endif
let items = quickui#tags#function_list(bufnr(), &ft)
if len(items) == 0
call quickui#utils#errmsg('No content !')
return -2
endif
let content = []
let cursor = -1
let index = 0
let ln = line('.')
let maxsize = (&columns) * 60 / 100
let maxheight = (&lines) * 60 / 100
let maxwidth = 0
let indents = get(g:, 'quickui_tags_indent', {})
for item in items
if ln >= item.line
let cursor = index
endif
let index += 1
let space = get(indents, item.mode, '')
let text = '' . item.mode . '' . " \t" . space . item.text
let text = text . ' [:' . item.line . ']'
let maxwidth = (maxwidth < len(text))? len(text) : maxwidth
let text = substitute(text, '&', '&&', 'g')
let content += [[text, ':' . item.line]]
endfor
let opts = {'title': 'Function List', 'close':'button'}
if cursor >= 0
let opts.index = cursor
endif
let limit = &columns * 90 / 100
let opts.h = len(content)
let opts.h = (opts.h < maxheight)? opts.h : maxheight
let opts.w = (maxwidth < limit)? maxwidth : limit
if opts.w < maxsize
let opts.w = (opts.w < 60)? 60 : opts.w
endif
let opts.syntax = 'qui_func'
if exists('g:quickui_tools_width')
let opts.w = quickui#utils#tools_width()
endif
" let content += ["1\t".repeat('0', 100)]
call quickui#listbox#open(content, opts)
return 0
endfunc
"----------------------------------------------------------------------
" preview register in popup and choose to paste
"----------------------------------------------------------------------
function! quickui#tools#list_register()
endfunc
"----------------------------------------------------------------------
" display python help in the textbox
"----------------------------------------------------------------------
function! quickui#tools#python_help(word)
let python = get(g:, 'quickui_tools_python', '')
if python == ''
if executable('python')
let python = 'python'
elseif executable('python3')
let python = 'python3'
elseif executable('python2')
let python = 'python2'
endif
endif
if a:word == ''
let text = getline('.')
let pre = text[:col('.') - 1]
let suf = text[col('.'):]
let word = matchstr(pre, "[A-Za-z0-9_.]*$")
let word = word . matchstr(suf, "^[A-Za-z0-9_]*")
else
let word = a:word
endif
let cmd = python . ' -m pydoc ' . shellescape(word)
let title = 'PyDoc <'. a:word . '>'
let opts = {'title':title}
let opts.color = 'QuickBG'
" let opts.bordercolor = 'QuickBG'
let opts.tabstop = 12
call quickui#textbox#command(cmd, opts)
endfunc
"----------------------------------------------------------------------
" display messages
"----------------------------------------------------------------------
function! quickui#tools#display_messages()
let x = ''
redir => x
silent! messages
redir END
let x = substitute(x, '[\n\r]\+\%$', '', 'g')
let content = filter(split(x, "\n"), 'v:key != ""')
if len(content) == 0
call quickui#utils#errmsg('Empty messages')
return -1
endif
let opts = {"close":"button", "title":"Vim Messages"}
if exists('g:quickui_tools_width')
let opts.w = quickui#utils#tools_width()
endif
call quickui#textbox#open(content, opts)
endfunc
"----------------------------------------------------------------------
" preview quickfix
"----------------------------------------------------------------------
function! quickui#tools#preview_quickfix(...)
if quickui#preview#visible()
call quickui#preview#close()
return 0
endif
if &bt != 'quickfix'
call quickui#utils#errmsg('Not in quickfix window !')
return -1
endif
if !exists('b:__quickui_qf__')
let b:__quickui_qf__ = {}
endif
let obj = b:__quickui_qf__
if !has_key(obj, 'version')
let obj.version = -1
endif
if b:changedtick != obj.version
if getwininfo(win_getid())[0].loclist != 0
let obj.items = getloclist(0)
else
let obj.items = getqflist()
endif
let obj.version = b:changedtick
endif
let index = (a:0 > 0)? a:1 : line('.')
if index < 1 || index > len(obj.items)
call quickui#utils#errmsg('No information in this line')
return -2
endif
let item = obj.items[index - 1]
if item.valid == 0
return -3
endif
if item.bufnr <= 0
return -4
endif
let name = bufname(item.bufnr)
let opts = {'cursor':item.lnum}
call quickui#preview#open(name, opts)
" echom 'lnum:'. item.lnum
endfunc
"----------------------------------------------------------------------
" preview tag
"----------------------------------------------------------------------
function! quickui#tools#preview_tag(tagname)
let tagname = (a:tagname == '')? expand('<cword>') : a:tagname
if tagname == ''
call quickui#utils#errmsg('Error: empty tagname')
return 0
endif
let obj = quickui#core#object(0)
let reuse = 0
if has_key(obj, 'ptag')
let ptag = obj.ptag
if get(ptag, 'tagname', '') == tagname
let reuse = 1
endif
endif
if reuse == 0
let obj.ptag = {}
let ptag = obj.ptag
let ptag.taglist = quickui#tags#tagfind(tagname)
let ptag.tagname = tagname
let ptag.index = 0
else
let ptag = obj.ptag
let ptag.index += 1
if ptag.index >= len(ptag.taglist)
let ptag.index = 0
endif
endif
if len(ptag.taglist) == 0
call quickui#utils#errmsg('E257: preview: tag not find "' . tagname . '"')
return 1
endif
if ptag.index >= len(ptag.taglist) || ptag.index < 0
let ptag.index = 0
endif
let taginfo = ptag.taglist[ptag.index]
let filename = taginfo.filename
if !filereadable(filename)
call quickui#utils#errmsg('E484: Can not open file '.filename)
return 2
endif
if !has_key(taginfo, 'line')
call quickui#utils#errmsg('Error: no "line" information in your tags, regenerate with -n')
return 3
endif
let text = '('.(ptag.index + 1).'/'.len(ptag.taglist).')'
let opts = {'cursor':taginfo.line, 'title':text}
call quickui#preview#open(filename, opts)
let text = taginfo.name
let text.= ' ('.(ptag.index + 1).'/'.len(ptag.taglist).') '
let text.= filename
if has_key(taginfo, 'line')
let text .= ':'.taginfo.line
endif
let display = has('gui_running')? 0 : 1
let display = get(g:, 'quickui_preview_tag_msg', display)
if display != 0
call quickui#utils#print(text, 1)
endif
return 0
endfunc
"----------------------------------------------------------------------
" display vim help in popup
"----------------------------------------------------------------------
function! quickui#tools#display_help(tag)
if !exists('s:help_tags')
let fn = expand('$VIMRUNTIME/doc/tags')
if filereadable(fn)
let content = readfile(fn)
let s:help_tags = {}
for line in content
let parts = split(line, "\t")
if len(parts) >= 3
let s:help_tags[parts[0]] = [parts[1], parts[2]]
endif
endfor
endif
endif
if !exists('s:help_tags')
call quickui#utils#errmsg('Sorry, not find help tags in $VIMRUNTIME')
return -1
endif
if !has_key(s:help_tags, a:tag)
call quickui#utils#errmsg('E149: Sorry, no help for '. a:tag)
return -2
endif
let item = s:help_tags[a:tag]
let name = expand($VIMRUNTIME . '/doc/' . item[0])
let command = substitute(item[1], '\*', '', 'g')
if !filereadable(name)
call quickui#utils#errmsg('E484: Sorry, cannot open file '.name)
return -3
endif
let content = readfile(name)
let opts = {'syntax':'help', 'color':'QuickPreview', 'close':'button'}
let opts.title = 'Help: ' . fnamemodify(name, ':t')
let g:quickui#tools#hint = item[1]
let opts.command = ['silent! exec g:quickui#tools#hint']
let opts.command += ["exec 'nohl'"]
let opts.command += ["normal zz"]
let opts.w = 80
" echom opts
let winid = quickui#textbox#open(content, opts)
return 0
endfunc
"----------------------------------------------------------------------
" save curses help
"----------------------------------------------------------------------
let s:previous_cursor = {}
function! s:remember_cursor_context(code)
let hwnd = g:quickui#context#current
let name = hwnd.opts.keep_name
let s:previous_cursor[name] = g:quickui#context#cursor
endfunc
function! s:remember_cursor_listbox(code)
let hwnd = g:quickui#listbox#current
let name = hwnd.opts.keep_name
let s:previous_cursor[name] = g:quickui#listbox#cursor
endfunc
function! quickui#tools#clever_context(name, content, opts)
let opts = deepcopy(a:opts)
let opts.index = get(s:previous_cursor, a:name, -1)
let opts.keep_name = a:name
let opts.callback = function('s:remember_cursor_context')
let content = quickui#context#reduce_items(a:content)
call quickui#context#open_nested(content, opts)
endfunc
function! quickui#tools#clever_listbox(name, content, opts)
let opts = deepcopy(a:opts)
let opts.index = get(s:previous_cursor, a:name, -1)
let opts.keep_name = a:name
let opts.callback = function('s:remember_cursor_listbox')
call quickui#listbox#open(a:content, opts)
endfunc
"----------------------------------------------------------------------
" terminal
"----------------------------------------------------------------------
function! quickui#tools#terminal(name)
if !exists('g:quickui_terminal_tools')
let g:quickui_terminal_tools = {}
endif
if !has_key(g:quickui_terminal_tools, a:name)
call quickui#utils#errmsg('ERROR: tool ' . a:name . ' not defined !')
return -1
endif
let tools = g:quickui_terminal_tools[a:name]
if !has_key(tools, 'cmd')
call quickui#utils#errmsg('ERROR: key cmd not present in tool ' . a:name)
return -1
endif
let opts = {}
let cmd = tools.cmd
let w = get(g:, 'quickui_terminal_w', 80)
let h = get(g:, 'quickui_terminal_h', 24)
let opts.w = get(tools, 'w', w)
let opts.h = get(tools, 'h', h)
if has_key(tools, 'color')
if tools.color != ''
let opts.color = tools.color
endif
endif
if has_key(tools, 'title')
let opts.title = tools.title
endif
if has_key(tools, 'callback')
let opts.callback = tools.callback
endif
if has_key(tools, 'prepare')
let opts.prepare = tools.prepare
endif
if has_key(tools, 'cwd')
let opts.cwd = tools.cwd
endif
if has_key(tools, 'script')
let opts.safe = tools.script
endif
if has_key(tools, 'pause')
if tools.pause
let opts.pause = 1
endif
endif
if has_key(tools, 'close')
if tools.close
let opts.close = 1
endif
endif
call quickui#terminal#dialog(cmd, opts)
return 0
endfunc
"----------------------------------------------------------------------
" search inputbox
"----------------------------------------------------------------------
function! quickui#tools#input_search()
let cword = expand('<cword>')
let title = 'Enter text to search:'
let text = quickui#input#open(title, cword, 'search')
redraw
if text != ''
let text = escape(text, '[\/*~^.')
call feedkeys("\<ESC>/" . text . "\<cr>", 'n')
endif
endfunc