Skip to content

Commit 0ec28da

Browse files
author
skywind3000
committed
new: quickui#context#open_nested api
fixed: border issues in window.vim
1 parent 2fd05c8 commit 0ec28da

File tree

5 files changed

+259
-9
lines changed

5 files changed

+259
-9
lines changed

autoload/quickui/context.vim

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,197 @@ function! quickui#context#open(textlist, opts)
692692
endfunc
693693

694694

695+
"----------------------------------------------------------------------
696+
" open the context window and wait for selection
697+
"----------------------------------------------------------------------
698+
function! s:context_wait(textlist, opts) abort
699+
let border = get(a:opts, 'border', g:quickui#style#border)
700+
let ignore_case = get(a:opts, 'ignore_case', 1)
701+
let hwnd = quickui#context#compile(a:textlist, border)
702+
let cwnd = quickui#window#new()
703+
let w = hwnd.width
704+
let h = hwnd.height
705+
let hwnd.index = get(a:opts, 'index', -1)
706+
let hwnd.opts = a:opts
707+
let opts = {'w':w, 'h':h, 'border':0}
708+
if has_key(a:opts, 'x') && has_key(a:opts, 'y')
709+
let opts.x = a:opts.x
710+
let opts.y = a:opts.y
711+
else
712+
let pos = quickui#core#around_cursor(w, h)
713+
let opts.y = pos[0] - 1
714+
let opts.x = pos[1] - 1
715+
endif
716+
let opts.z = get(a:opts, 'z', 500)
717+
let opts.color = get(a:opts, 'color', 'QuickBG')
718+
let hwnd.direct = get(a:opts, 'direct', 0)
719+
if hwnd.direct == 0
720+
let hwnd.direct = (opts.x <= (&columns / 2))? 1 : -1
721+
endif
722+
call cwnd.open(hwnd.image, opts)
723+
call cwnd.show(1)
724+
let keymap = quickui#utils#keymap()
725+
let keymap['J'] = 'BOTTOM'
726+
let keymap['K'] = 'TOP'
727+
let hwnd.code = 0
728+
let hwnd.state = 1
729+
let hwnd.keymap = keymap
730+
let hwnd.hotkey = {}
731+
for item in hwnd.items
732+
if item.enable != 0 && item.key_pos >= 0
733+
let key = ignore_case ? tolower(item.key_char) : item.key_char
734+
if get(a:opts, 'reserve', 0) == 0
735+
let hwnd.hotkey[key] = item.index
736+
elseif get(g:, 'quickui_protect_hjkl', 0) != 0
737+
let hwnd.hotkey[key] = item.index
738+
else
739+
if key != 'h' && key != 'j' && key != 'k' && key != 'l'
740+
let hwnd.hotkey[key] = item.index
741+
endif
742+
endif
743+
endif
744+
endfor
745+
let hwnd.winid = cwnd.winid
746+
let retval = -1
747+
while 1
748+
noautocmd call quickui#context#update(hwnd)
749+
redraw
750+
try
751+
let code = getchar()
752+
catch /^Vim:Interrupt$/
753+
let code = "\<C-C>"
754+
endtry
755+
let ch = (type(code) == v:t_number)? nr2char(code) : code
756+
if ch == "\<ESC>" || ch == "\<c-c>"
757+
break
758+
elseif ch == " " || ch == "\<cr>"
759+
let index = hwnd.index
760+
if index >= 0 && index < len(hwnd.items)
761+
let item = hwnd.items[index]
762+
if item.is_sep == 0 && item.enable != 0
763+
let retval = index
764+
break
765+
endif
766+
endif
767+
elseif ch == "\<LeftMouse>"
768+
let pos = cwnd.mouse_click()
769+
if pos.x >= 0
770+
let x1 = (hwnd.border == 0)? 0 : 1
771+
let x2 = (hwnd.border == 0)? w : (w - 1)
772+
let ii = (hwnd.border == 0)? pos.y : (pos.y - 1)
773+
if pos.x >= x1 && pos.x < x2
774+
if ii >= 0 && ii < len(hwnd.items)
775+
let item = hwnd.items[ii]
776+
if item.is_sep == 0 && item.enable != 0
777+
let hwnd.index = ii
778+
let retval = ii
779+
noautocmd call quickui#context#update(hwnd)
780+
redraw
781+
break
782+
endif
783+
endif
784+
endif
785+
endif
786+
elseif has_key(hwnd.hotkey, ch)
787+
let hr = hwnd.hotkey[ch]
788+
if hr >= 0
789+
let hwnd.index = hr
790+
let retval = hr
791+
break
792+
endif
793+
elseif has_key(hwnd.keymap, ch)
794+
let key = hwnd.keymap[ch]
795+
if key == 'ESC'
796+
break
797+
elseif key == 'UP'
798+
let hwnd.index = s:cursor_move(hwnd, hwnd.index, -1)
799+
elseif key == 'DOWN'
800+
let hwnd.index = s:cursor_move(hwnd, hwnd.index, 1)
801+
elseif key == 'TOP'
802+
let hwnd.index = s:cursor_move(hwnd, hwnd.index, 'TOP')
803+
elseif key == 'BOTTOM'
804+
let hwnd.index = s:cursor_move(hwnd, hwnd.index, 'BOTTOM')
805+
endif
806+
endif
807+
endwhile
808+
noautocmd call quickui#context#update(hwnd)
809+
let hr = ''
810+
if retval >= 0 && retval < len(hwnd.items)
811+
let item = hwnd.items[retval]
812+
if item.is_sep == 0 && item.enable != 0
813+
let hwnd.index = retval
814+
if !has_key(item, 'child')
815+
let hr = item.cmd
816+
else
817+
let child = item.child
818+
let cc = quickui#context#compile(child, border)
819+
let cw = cc.width
820+
let ch = cc.height
821+
unlet cc
822+
let op = {}
823+
let op.z = opts.z + 1
824+
let op.y = opts.y + retval
825+
let op.y = (op.y + ch > &lines)? (&lines - ch) : op.y
826+
let op.y = (op.y < 0)? 0 : op.y
827+
for i in range(5)
828+
if hwnd.direct >= 0
829+
let tx = opts.x + opts.w
830+
if tx + cw > &columns
831+
let hwnd.direct = -1
832+
else
833+
let op.x = tx
834+
break
835+
endif
836+
elseif hwnd.direct < 0
837+
let tx = opts.x - cw
838+
if tx < 0
839+
let hwnd.direct = 1
840+
else
841+
let op.x = tx
842+
break
843+
endif
844+
endif
845+
endfor
846+
if !has_key(op, 'x')
847+
let op.x = 1
848+
endif
849+
let op.direct = hwnd.direct
850+
let op.border = get(a:opts, 'border', border)
851+
let hr = s:context_wait(child, op)
852+
endif
853+
endif
854+
endif
855+
let g:quickui#context#cursor = hwnd.index
856+
let g:quickui#context#current = hwnd
857+
call cwnd.close()
858+
unlet cwnd
859+
return hr
860+
endfunc
861+
862+
863+
"----------------------------------------------------------------------
864+
" open the context window and wait for selection
865+
"----------------------------------------------------------------------
866+
function! quickui#context#wait(textlist, opts) abort
867+
return s:context_wait(a:textlist, a:opts)
868+
endfunc
869+
870+
871+
"----------------------------------------------------------------------
872+
" open context menu and execute commands
873+
"----------------------------------------------------------------------
874+
function! quickui#context#open_nested(textlist, opts) abort
875+
let cmd = s:context_wait(a:textlist, a:opts)
876+
if has_key(a:opts, 'callback')
877+
call a:opts.callback(0)
878+
endif
879+
if cmd != ''
880+
exec cmd
881+
endif
882+
endfunc
883+
884+
885+
695886
"----------------------------------------------------------------------
696887
" testing suit
697888
"----------------------------------------------------------------------

autoload/quickui/palette.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
" palette.vim -
44
"
55
" Created by skywind on 2021/12/23
6-
" Last Modified: 2021/12/23 13:29:47
6+
" Last Modified: 2022/09/25 01:31
77
"
88
"======================================================================
99

@@ -461,7 +461,7 @@ endfunc
461461

462462

463463
"----------------------------------------------------------------------
464-
" optimize if possible: achieve 30x times faster
464+
" optimize if possible: achieve 40x times faster
465465
"----------------------------------------------------------------------
466466
if has('vim9script')
467467
import './palette9.vim'

autoload/quickui/tools.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ function! quickui#tools#clever_context(name, content, opts)
432432
let opts.keep_name = a:name
433433
let opts.callback = function('s:remember_cursor_context')
434434
let content = quickui#context#reduce_items(a:content)
435-
call quickui#context#open(content, opts)
435+
call quickui#context#open_nested(content, opts)
436436
endfunc
437437

438438
function! quickui#tools#clever_listbox(name, content, opts)

autoload/quickui/utils.vim

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,26 @@
1515
"----------------------------------------------------------------------
1616
function! quickui#utils#item_parse(description)
1717
let obj = {'text':'', 'key_pos':-1, 'key_char':'', 'is_sep':0, 'help':''}
18-
let obj.info = []
1918
let text = ''
19+
let child = 0
2020
if type(a:description) == v:t_string
2121
let text = a:description
2222
let obj.help = ''
2323
let obj.cmd = ''
24-
let obj.info = [ text ]
2524
elseif type(a:description) == v:t_list
2625
let size = len(a:description)
2726
let text = (size >= 1)? a:description[0] : ''
28-
let obj.cmd = (size >= 2)? a:description[1] : ''
2927
let obj.help = (size >= 3)? a:description[2] : ''
30-
let obj.info = deepcopy(a:description)
28+
let obj.cmd = ''
29+
if size >= 2
30+
if type(a:description[1]) == v:t_string
31+
let obj.cmd = a:description[1]
32+
elseif type(a:description[1]) == v:t_list
33+
let obj.cmd = ''
34+
let obj.child = a:description[1]
35+
let child = 1
36+
endif
37+
endif
3138
endif
3239
if text =~ '^-\+$'
3340
let obj.is_sep = 1
@@ -44,6 +51,7 @@ function! quickui#utils#item_parse(description)
4451
let obj.enable = 0
4552
endif
4653
let pos = stridx(text, "\t")
54+
let sep = ">"
4755
if pos < 0
4856
let obj.text = text
4957
let obj.desc = ""
@@ -52,6 +60,7 @@ function! quickui#utils#item_parse(description)
5260
let obj.desc = strpart(text, pos + 1)
5361
let obj.desc = substitute(obj.desc, "\t", " ", "g")
5462
endif
63+
let obj.desc = (child == 0)? obj.desc : sep
5564
let text = obj.text
5665
let rest = ''
5766
let start = 0

autoload/quickui/window.vim

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,12 @@ function! s:window.__prepare_opts(textlist, opts)
7373
let sum_pad = pad[0] + pad[1] + pad[2] + pad[3]
7474
let info.has_padding = (sum_pad > 0)? 1 : 0
7575
let border = quickui#core#border_auto(self.opts.border)
76-
let info.has_border = (len(border) > 0)? 1 : 0
76+
let info.has_border = (self.opts.border > 0)? 1 : 0
7777
if info.has_border != 0
7878
let info.tw += 2
7979
let info.th += 2
8080
endif
81+
" echom info
8182
call self.set_text(a:textlist)
8283
if opts.h < 0
8384
let opts.h = len(self.text)
@@ -179,7 +180,7 @@ function! s:window.__vim_create()
179180
let opts.callback = function('s:popup_exit')
180181
let opts.highlight = self.opts.color
181182
let border = quickui#core#border_auto(self.opts.border)
182-
if len(border) > 0
183+
if self.info.has_border
183184
let opts.borderchars = border
184185
let opts.border = [1,1,1,1,1,1,1,1,1]
185186
let bc = get(self.opts, 'bordercolor', 'QuickBorder')
@@ -690,6 +691,55 @@ function! s:window.syntax_region(color, x1, y1, x2, y2)
690691
endfunc
691692

692693

694+
"----------------------------------------------------------------------
695+
" click window
696+
"----------------------------------------------------------------------
697+
function! s:window.mouse_click()
698+
let winid = self.winid
699+
let retval = {'x':-1, 'y':-1}
700+
if g:quickui#core#has_nvim == 0
701+
let pos = getmousepos()
702+
if pos.winid != winid
703+
return retval
704+
endif
705+
if self.info.has_border == 0
706+
let retval.x = pos.column - 1
707+
let retval.y = pos.line - 1
708+
else
709+
let retval.x = pos.column - 2
710+
let retval.y = pos.line - 2
711+
endif
712+
else
713+
if v:mouse_winid != winid
714+
return retval
715+
endif
716+
if self.info.has_border == 0
717+
let retval.x = v:mouse_col - 1
718+
let retval.y = v:mouse_lnum - 1
719+
else
720+
let retval.x = v:mouse_col - 2
721+
let retval.y = v:mouse_lnum - 2
722+
endif
723+
endif
724+
return retval
725+
endfunc
726+
727+
728+
"----------------------------------------------------------------------
729+
" refresh redraw
730+
"----------------------------------------------------------------------
731+
function! s:window.refresh()
732+
let winid = self.winid
733+
if g:quickui#core#has_nvim == 0
734+
if winid >= 0
735+
call popup_setoptions(winid, {})
736+
endif
737+
else
738+
endif
739+
redraw
740+
endfunc
741+
742+
693743
"----------------------------------------------------------------------
694744
" constructor
695745
"----------------------------------------------------------------------

0 commit comments

Comments
 (0)