From 242da8c357f042757035b6c73cab85de870e592f Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Wed, 23 Oct 2024 23:11:51 +0800 Subject: [PATCH 1/2] feat(integration): General vim input helper --- .../snippet/integration/binding.vim | 21 +---- .../snippet/integration/plugin.vim | 88 +++++++++++++++++-- 2 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/sphinxnotes/snippet/integration/binding.vim b/src/sphinxnotes/snippet/integration/binding.vim index 5919f0b..a21edeb 100644 --- a/src/sphinxnotes/snippet/integration/binding.vim +++ b/src/sphinxnotes/snippet/integration/binding.vim @@ -38,27 +38,8 @@ function! g:SphinxNotesSnippetListAndUrl() call g:SphinxNotesSnippetList(function('s:CallUrl'), 'ds') endfunction -function! g:SphinxNotesSnippetInput(id, item) - let content = system(join([s:snippet, 'get', '--' . a:item, a:id, '2>/dev/null'], ' ')) - let content = substitute(content, '\n\+$', '', '') " skip trailing \n - if a:item == 'docname' - " Create doc reference. - let content = ':doc:`/' . content . '`' - endif - execute 'normal! i' . content -endfunction - -function! g:SphinxNotesSnippetListAndInputDocname() - function! s:InputDocname(selection) - call g:SphinxNotesSnippetInput(s:SplitID(a:selection), 'docname') - endfunction - call g:SphinxNotesSnippetList(function('s:InputDocname'), 'd') -endfunction - nmap e :call g:SphinxNotesSnippetListAndEdit() nmap u :call g:SphinxNotesSnippetListAndUrl() -nmap d :call g:SphinxNotesSnippetListAndInputDocname() -" FIXME: can't return to insert mode even use a/startinsert!/C-o -imap d :call g:SphinxNotesSnippetListAndInputDocname() +nmap i :call g:SphinxNotesSnippetListAndInput() " vim: set shiftwidth=2: diff --git a/src/sphinxnotes/snippet/integration/plugin.vim b/src/sphinxnotes/snippet/integration/plugin.vim index da79b48..7621c07 100644 --- a/src/sphinxnotes/snippet/integration/plugin.vim +++ b/src/sphinxnotes/snippet/integration/plugin.vim @@ -8,25 +8,103 @@ " NOTE: junegunn/fzf.vim is required let s:snippet = 'snippet' +let s:width = 0.9 +let s:height = 0.6 +" TODO: remove function! s:SplitID(row) return split(a:row, ' ')[0] endfunction -" TODO: extra opts +" Use fzf to list all snippets, callback with arguments (selection). function! g:SphinxNotesSnippetList(callback, tags) - let l:width = 0.9 let cmd = [s:snippet, 'list', \ '--tags', a:tags, - \ '--width', float2nr(&columns * l:width) - 2, + \ '--width', float2nr(&columns * s:width) - 2, \ ] " https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzfrun call fzf#run({ \ 'source': join(cmd, ' '), \ 'sink': a:callback, \ 'options': ['--with-nth', '2..', '--no-hscroll', '--header-lines', '1'], - \ 'window': {'width': l:width, 'height': 0.6}, + \ 'window': {'width': s:width, 'height': s:height}, \ }) endfunction -" vim: set shiftwidth=2: +" Return the attribute value of specific snippet. +function! g:SphinxNotesSnippetGet(id, attr) + let cmd = [s:snippet, 'get', a:id, '--' . a:attr] + return systemlist(join(cmd, ' ')) +endfunction + +" Use fzf to list all attr of specific snippet, +" callback with arguments (attr_name, attr_value). +function! g:SphinxNotesSnippetListSnippetAttrs(id, callback) + " Display attr -> Identify attr (also used as CLI option) + let attrs = { + \ 'Source': 'src', + \ 'URL': 'url', + \ 'Docname': 'docname', + \ 'Dependent files': 'deps', + \ 'Text': 'text', + \ 'Title': 'title', + \ } + let delim = ' ' + let table = ['OPTION' . delim . 'ATTRIBUTE'] + for name in keys(attrs) + call add(table, attrs[name] . delim . name) + endfor + + " Local scope -> script scope, so vars can be access from inner function. + let s:id_for_list_snippet_attrs = a:id + let s:cb_for_list_snippet_attrs = a:callback + function! s:SphinxNotesSnippetListSnippetAttrs_CB(selection) + let opt = split(a:selection, ' ')[0] + let val = g:SphinxNotesSnippetGet(s:id_for_list_snippet_attrs, opt) + call s:cb_for_list_snippet_attrs(opt, val) " finally call user's cb + endfunction + + let preview_cmd = [s:snippet, 'get', a:id, '--$(echo {} | cut -d " " -f1)'] + let info_cmd = ['echo', 'Index ID:', a:id] + call fzf#run({ + \ 'source': table, + \ 'sink': function('s:SphinxNotesSnippetListSnippetAttrs_CB'), + \ 'options': [ + \ '--header-lines', '1', + \ '--with-nth', '2..', + \ '--preview', join(preview_cmd, ' '), + \ '--preview-window', ',wrap', + \ '--info-command', join(info_cmd, ' '), + \ ], + \ 'window': {'width': s:width, 'height': s:height}, + \ }) +endfunction + +function! g:SphinxNotesSnippetInput(id) + function! s:SphinxNotesSnippetInput_CB(attr, val) + if a:attr == 'docname' + " Create doc reference. + let content = ':doc:`/' . a:val[0] . '`' + elseif a:attr == 'title' + " Create local section reference. + let content = '`' . a:val[0] . '`_' + else + let content = join(a:val, '') + endif + + execute 'normal! i' . content + endfunction + + call g:SphinxNotesSnippetListSnippetAttrs(a:id, function('s:SphinxNotesSnippetInput_CB')) +endfunction + +function! g:SphinxNotesSnippetListAndInput() + function! s:SphinxNotesSnippetListAndInput_CB(selection) + let id = s:SplitID(a:selection) + call g:SphinxNotesSnippetInput(id) + endfunction + + call g:SphinxNotesSnippetList(function('s:SphinxNotesSnippetListAndInput_CB'), '"*"') +endfunction + + " vim: set shiftwidth=2: From a45b88be8b8ba09f9838c6d73405d243ac6f8a4e Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Thu, 24 Oct 2024 11:27:28 +0800 Subject: [PATCH 2/2] refactor(integration): Refactor vim plugin --- .../snippet/integration/binding.nvim | 6 +-- .../snippet/integration/binding.vim | 26 +++++----- .../snippet/integration/plugin.vim | 51 +++++++++---------- 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/sphinxnotes/snippet/integration/binding.nvim b/src/sphinxnotes/snippet/integration/binding.nvim index 0414214..25f0f34 100644 --- a/src/sphinxnotes/snippet/integration/binding.nvim +++ b/src/sphinxnotes/snippet/integration/binding.nvim @@ -8,10 +8,10 @@ " TODO: Support vim? function! g:SphinxNotesSnippetListAndView() - function! s:CallView(selection) - call g:SphinxNotesSnippetView(s:SplitID(a:selection)) + function! ListAndView_CB(id) + call g:SphinxNotesSnippetView(a:id) endfunction - call g:SphinxNotesSnippetList(function('s:CallView'), '*') + call g:SphinxNotesSnippetList('"*"', function('ListAndView_CB')) endfunction " https://github.com/anhmv/vim-float-window/blob/master/plugin/float-window.vim diff --git a/src/sphinxnotes/snippet/integration/binding.vim b/src/sphinxnotes/snippet/integration/binding.vim index a21edeb..6225080 100644 --- a/src/sphinxnotes/snippet/integration/binding.vim +++ b/src/sphinxnotes/snippet/integration/binding.vim @@ -6,9 +6,9 @@ " :Version: 20211114 " -function! g:SphinxNotesSnippetEdit(id) - let file = system(join([s:snippet, 'get', '--file', a:id, '2>/dev/null'], ' ')) - let line = system(join([s:snippet, 'get', '--line-start', a:id, '2>/dev/null'], ' ')) +function g:SphinxNotesSnippetEdit(id) + let file = g:SphinxNotesSnippetGet(a:id, 'file')[0] + let line = g:SphinxNotesSnippetGet(a:id, 'line-start')[0] if &modified execute 'vsplit ' . file else @@ -17,25 +17,25 @@ function! g:SphinxNotesSnippetEdit(id) execute line endfunction -function! g:SphinxNotesSnippetListAndEdit() - function! s:CallEdit(selection) - call g:SphinxNotesSnippetEdit(s:SplitID(a:selection)) +function g:SphinxNotesSnippetListAndEdit() + function! ListAndEdit_CB(id) + call g:SphinxNotesSnippetEdit(a:id) endfunction - call g:SphinxNotesSnippetList(function('s:CallEdit'), 'ds') + call g:SphinxNotesSnippetList('ds', function('ListAndEdit_CB')) endfunction -function! g:SphinxNotesSnippetUrl(id) - let url_list = systemlist(join([s:snippet, 'get', '--url', a:id, '2>/dev/null'], ' ')) +function g:SphinxNotesSnippetUrl(id) + let url_list = g:SphinxNotesSnippetGet(a:id, 'url') for url in url_list echo system('xdg-open ' . shellescape(url)) endfor endfunction -function! g:SphinxNotesSnippetListAndUrl() - function! s:CallUrl(selection) - call g:SphinxNotesSnippetUrl(s:SplitID(a:selection)) +function g:SphinxNotesSnippetListAndUrl() + function! ListAndUrl_CB(id) + call g:SphinxNotesSnippetUrl(a:id) endfunction - call g:SphinxNotesSnippetList(function('s:CallUrl'), 'ds') + call g:SphinxNotesSnippetList('ds', function('ListAndUrl_CB')) endfunction nmap e :call g:SphinxNotesSnippetListAndEdit() diff --git a/src/sphinxnotes/snippet/integration/plugin.vim b/src/sphinxnotes/snippet/integration/plugin.vim index 7621c07..3cf01c5 100644 --- a/src/sphinxnotes/snippet/integration/plugin.vim +++ b/src/sphinxnotes/snippet/integration/plugin.vim @@ -11,35 +11,39 @@ let s:snippet = 'snippet' let s:width = 0.9 let s:height = 0.6 -" TODO: remove -function! s:SplitID(row) - return split(a:row, ' ')[0] -endfunction - -" Use fzf to list all snippets, callback with arguments (selection). -function! g:SphinxNotesSnippetList(callback, tags) +" Use fzf to list all snippets, callback with argument id. +function g:SphinxNotesSnippetList(tags, callback) let cmd = [s:snippet, 'list', \ '--tags', a:tags, \ '--width', float2nr(&columns * s:width) - 2, \ ] + + " Use closure keyword so that inner function can access outer one's + " localvars (l:) and arguments (a:). + " https://vi.stackexchange.com/a/21807 + function! List_CB(selection) closure + let id = split(a:selection, ' ')[0] + call a:callback(id) + endfunction + " https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzfrun call fzf#run({ \ 'source': join(cmd, ' '), - \ 'sink': a:callback, + \ 'sink': function('List_CB'), \ 'options': ['--with-nth', '2..', '--no-hscroll', '--header-lines', '1'], \ 'window': {'width': s:width, 'height': s:height}, \ }) endfunction " Return the attribute value of specific snippet. -function! g:SphinxNotesSnippetGet(id, attr) +function g:SphinxNotesSnippetGet(id, attr) let cmd = [s:snippet, 'get', a:id, '--' . a:attr] return systemlist(join(cmd, ' ')) endfunction " Use fzf to list all attr of specific snippet, " callback with arguments (attr_name, attr_value). -function! g:SphinxNotesSnippetListSnippetAttrs(id, callback) +function g:SphinxNotesSnippetListSnippetAttrs(id, callback) " Display attr -> Identify attr (also used as CLI option) let attrs = { \ 'Source': 'src', @@ -55,20 +59,17 @@ function! g:SphinxNotesSnippetListSnippetAttrs(id, callback) call add(table, attrs[name] . delim . name) endfor - " Local scope -> script scope, so vars can be access from inner function. - let s:id_for_list_snippet_attrs = a:id - let s:cb_for_list_snippet_attrs = a:callback - function! s:SphinxNotesSnippetListSnippetAttrs_CB(selection) + function! ListSnippetAttrs_CB(selection) closure let opt = split(a:selection, ' ')[0] - let val = g:SphinxNotesSnippetGet(s:id_for_list_snippet_attrs, opt) - call s:cb_for_list_snippet_attrs(opt, val) " finally call user's cb + let val = g:SphinxNotesSnippetGet(a:id, opt) + call a:callback(opt, val) " finally call user's cb endfunction let preview_cmd = [s:snippet, 'get', a:id, '--$(echo {} | cut -d " " -f1)'] let info_cmd = ['echo', 'Index ID:', a:id] call fzf#run({ \ 'source': table, - \ 'sink': function('s:SphinxNotesSnippetListSnippetAttrs_CB'), + \ 'sink': function('ListSnippetAttrs_CB'), \ 'options': [ \ '--header-lines', '1', \ '--with-nth', '2..', @@ -80,8 +81,8 @@ function! g:SphinxNotesSnippetListSnippetAttrs(id, callback) \ }) endfunction -function! g:SphinxNotesSnippetInput(id) - function! s:SphinxNotesSnippetInput_CB(attr, val) +function g:SphinxNotesSnippetInput(id) + function! Input_CB(attr, val) " TODO: became g:func. if a:attr == 'docname' " Create doc reference. let content = ':doc:`/' . a:val[0] . '`' @@ -91,20 +92,18 @@ function! g:SphinxNotesSnippetInput(id) else let content = join(a:val, '') endif - execute 'normal! i' . content endfunction - call g:SphinxNotesSnippetListSnippetAttrs(a:id, function('s:SphinxNotesSnippetInput_CB')) + call g:SphinxNotesSnippetListSnippetAttrs(a:id, function('Input_CB')) endfunction -function! g:SphinxNotesSnippetListAndInput() - function! s:SphinxNotesSnippetListAndInput_CB(selection) - let id = s:SplitID(a:selection) - call g:SphinxNotesSnippetInput(id) +function g:SphinxNotesSnippetListAndInput() + function! ListAndInput_CB(id) + call g:SphinxNotesSnippetInput(a:id) endfunction - call g:SphinxNotesSnippetList(function('s:SphinxNotesSnippetListAndInput_CB'), '"*"') + call g:SphinxNotesSnippetList('"*"', function('ListAndInput_CB')) endfunction " vim: set shiftwidth=2: