Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Include more labels in completion menu #402

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
210 changes: 209 additions & 1 deletion autoload/pandoc/completion.vim
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,68 @@ function! pandoc#completion#Init() abort "{{{1
let g:pandoc#completion#bib#use_preview = 0
endif
endif

"
" If your images are in the same directory as the markdown file, they are included
Copy link
Contributor

@Konfekt Konfekt Apr 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is figures that standard? Most natural would be images (what I use). Also, rather figs than fig following the convention to name a directory in the plural form (Documents, Pictures, Downloads...)

I now realize that g:pandoc#completion#figdirpre is not initialized by default; if there is such a standard (like labelling section by sec:...) maybe it could be set to it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a commit to take care of this.

" by default in the completion menu. However, many authors like to keep their
" images in a directory such as 'images' or 'figures'. The options called
" 'g:pandoc#completion#imgdirtype' and 'g:pandoc#completion#imgdirpre' are
" used to define such image directories
"
let s:imgdir = ''
if exists('g:pandoc#completion#imgdirtype')
if g:pandoc#completion#imgdirtype == 1
if exists('g:pandoc#completion#imgdirpre')
let s:imgdir = g:pandoc#completion#imgdirpre
endif
elseif g:pandoc#completion#imgdirtype == 2
if exists('g:pandoc#completion#imgdirpre')
let s:imgdir = g:pandoc#completion#imgdirpre . expand('%:r')
endif
endif
endif
"
" User can specify the sources from where reference list consisting of
" labels such as fig:, lst:, eq: etc. will be populated. Currently two
" sourses are supported: g:pandoc#completion#refsources = 'buffers' and
" g:pandoc#completion#refsources = 'pandocfiles'. These correspond to all
" open buffers ('buffers') and the pandoc files found (recursively) in the
" current directory ('pandocfiles'), respectively. 'buffers' is the
" default
"
let s:refsources = 'buffers'
if exists('g:pandoc#completion#refsources')
let s:refsources = g:pandoc#completion#refsources
endif
"
let l:currArgs = argv()
execute '%argd'
if s:refsources ==# 'buffers'
" do nothing
elseif s:refsources ==# 'pandocfiles'
" this will populate the bufferlist and we can then work with bufdo
" argdo does not work very well with unsaved buffers
let l:pandocfiles = []
call extend(l:pandocfiles, glob('**/*.pandoc', 1, 1))
call extend(l:pandocfiles, glob('**/*.pdk', 1, 1))
call extend(l:pandocfiles, glob('**/*.pd', 1, 1))
call extend(l:pandocfiles, glob('**/*.pdc', 1, 1))
execute 'argadd ' . join(l:pandocfiles)
if get(g:, 'pandoc#filetypes#pandoc_markdown', 1) == 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason the entries in globbed files in the current work dir did not appear. Only those of open buffers.

let l:pandocfiles = []
call extend(l:pandocfiles, glob('**/*.markdown', 1, 1))
call extend(l:pandocfiles, glob('**/*.mdown', 1, 1))
call extend(l:pandocfiles, glob('**/*.mkd', 1, 1))
call extend(l:pandocfiles, glob('**/*.mkdn', 1, 1))
call extend(l:pandocfiles, glob('**/*.mkdwn', 1, 1))
call extend(l:pandocfiles, glob('**/*.md', 1, 1))
execute 'argadd ' . join(l:pandocfiles)
endif
endif
execute '%argd'
execute 'argadd ' . join(l:currArgs)
"
" set the correct omnifunc completion
"
if has('python3')
setlocal omnifunc=pandoc#completion#Complete
endif
Expand All @@ -37,19 +97,167 @@ function! pandoc#completion#Init() abort "{{{1
endif
endfunction

"
" Write a function that fills s:mylist with unused image file paths
"
fun! s:FetchImageNames() abort
"
" Add all image extensions to l:filelist
"
let l:filelist = []
call extend(l:filelist, globpath(s:imgdir, '*.png', 1, 1))
call extend(l:filelist, globpath(s:imgdir, '*.jpg', 1, 1))
call extend(l:filelist, globpath(s:imgdir, '*.svg', 1, 1))
call extend(l:filelist, globpath(s:imgdir, '*.gif', 1, 1))
call extend(l:filelist, globpath(s:imgdir, '*.eps', 1, 1))
"
let l:currBuff = bufnr('%')
"
for l:file in l:filelist
let l:occurrences = 0
bufdo if &l:filetype ==# 'pandoc' | if search(l:file, 'nw') | let l:occurrences += 1 | endif | endif
if l:occurrences == 0
call add(s:mylist, {
\ 'icase': 0,
\ 'word': l:file,
\ 'menu': ' [ins-Figure]',
\ })
endif
endfor
"
execute 'buffer ' . l:currBuff
"
endfun

"
" Populate s:mylist with labels such as tbl:, eq:, fig: and tbl:
"
fun! s:FetchRefLabels() abort
let l:reflist = []
let l:currBuff = bufnr('%')
call execute(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could be done for all open buffers at least by bufdo? (...and at some point by all globbed markdown in the work dir?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense when you split your work among multiple files.I have made use of the bufdo feature in the most recent commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! It makes sense to restrict to only all those buffers that have &l:filetype='pandoc'.

There is also argdo after argadd *.{pandoc,md} (where the extensions are given by ftdetect/pandoc.vim). The argument list should be stored and restore.
Maybe optionally glob in the all sub directories, that is, argadd **/*.{pandoc,md}.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it, **/*.{pandoc,md} seems more reasonable by default. Since this could take time, better load it once initially and then refresh it by an autocmd BufWrite.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you still wish to store and restore arglist ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Temporarily overriding the arglist is, not unusual in Vimscript, not the cleanest solution, but readily implemented once everything set up for the buffer list. Perhaps the autocmd update can be skipped for the time being: New items are in the buffer list anyway. Of course such a buffer can be closed, but whether the effort is worth it remains questionable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a variable called g:pandoc#completion#refsources that lets the user to choose to use all pandoc files from currently opened buffers, or to use all 'pandoc' files in the current directory (recursively). This is in the most recent commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good. Thank you! Let's see if the maintainers @alerque and @fmoralesc deem it good to go?!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to avoid the flicker when the completion entry list is first populated?

\ 'bufdo if &l:filetype ==# "pandoc" | %s/\v#\zs(eq:|fig:|lst:|sec:|tbl:)(\w|-)+/' .
\ '\=add(l:reflist, submatch(0))/gn | endif',
\ 'silent!'
\ )
execute 'buffer ' . l:currBuff
"
" Lets add the list items to s:mylist
"
for l:item in l:reflist
if l:item[0:3] ==# 'fig:'
let l:menu = ' [Figure]'
elseif l:item[0:2] ==# 'eq:'
let l:menu = ' [Equation]'
elseif l:item[0:3] ==# 'tbl:'
let l:menu = ' [Table]'
elseif l:item[0:3] ==# 'lst:'
let l:menu = ' [Listing]'
elseif l:item[0:3] ==# 'sec:'
let l:menu = ' [Section]'
else
let l:menu = ' [Unknown]'
endif
call add(s:mylist, {
\ 'icase': 1,
\ 'word': l:item,
\ 'menu': l:menu,
\ })
endfor
endfun

"
" Putting it all together
"
fun! s:PopulatePandoc() abort
"
" This is the main function that populates the omni-completion menu
"
" Save the cursor position
"
let l:save_cursor = getcurpos()
"
let s:mylist = []
"
" Populate s:mylist with names (relative path) of image files
"
call s:FetchImageNames()
"
" Add to s:mylist ref labels for figures, tables, equations etc.
"
call s:FetchRefLabels()
"
" Make a new list where first letter of some words in s:mylist is upper
" case. This is useful for cases where [@Fig:somefigname] like references
" are inserted in the markdown file, e.g., at the beginning of a sentence.
"
let s:mycaplist = deepcopy(s:mylist)
for l:item in s:mycaplist
"
" l:item is a reference (not copy) to each dictionary in s:mycaplist
"
let l:word = l:item['word']
let l:menu = l:item['menu']
if l:menu ==# ' [ins-Figure]'
continue
endif
let l:item['word'] = toupper(l:word[0]) . l:word[1:]
endfor
"
" Restore the cursor position
"
call setpos('.', l:save_cursor)
endfun

function! pandoc#completion#Complete(findstart, base) abort "{{{1
if has('python3')
if index(g:pandoc#modules#enabled, 'bibliographies') >= 0
if a:findstart
"
" Populate the s:mylist and s:mycaplist with plausible
" completion candidates
"
call s:PopulatePandoc()
"
let l:line = getline('.')
if l:line[:col('.')-1] =~# '@'
let l:pos = searchpos('@', 'Wncb')
if l:pos != [0,0]
return l:pos[1]
endif
else
"
" This for the images to be inserted into the markdown
" file. i_CTRL-X_CTRL-O is required for this
"
let start = col('.') - 1
while start > 0 && (
\ line[start - 1] =~# '\a'
\ || line[start - 1] =~# '-'
\ || line[start - 1] =~# ':'
\ || line[start - 1] =~# '\d')
let start -= 1
endwhile
return start
endif
else
"
" First citation entries in completion menu
"
let suggestions = pandoc#bibliographies#GetSuggestions(a:base)
"
" Then include labels for fig:, eq:, lst: etc, and also names
" of images to be inserted in markdown file
"
let l:finallist = s:mylist
if match(a:base[0], '\u') != -1
let l:finallist = s:mycaplist
endif
for m in l:finallist
if m['word'] =~ '^' . a:base
call add(suggestions, m)
endif
endfor
return suggestions
endif
endif
Expand Down