1

I use BibDesk on a Mac to edit .bib files (in biblatex, using biber to compile). This generally works, but for various reasons it would be nice to be able to edit them in nvim too. My current setup lets me do that reasonably well (I think because of vimtex and vim-snippets), but I haven't figured out a way to achieve easy "keyword" completion, where here "keyword" means something appearing in any bib-entry's keywords field (e.g., keywords = {keyword1; keyword2}). C-N completes it based on any word in the file, not bib-keywords specifically.

Is there any setup or plugin that offers this and other similar completion features comparable to those offered by BibDesk (e.g., author completion, and in general completion by bib-field, as well as completing by citekey when appropriate, for instance in crossref fields)?

Update

As explained by @KarlYngveLervag on github, what I should be using is omnicompletion. When I do that in a bib file, it seems to pull up a list of possible fields (author, title, year, etc.) that could complete the word I am typing, even if I am within the braces {} of a field itself (e.g., cursor is * in author = {Ye*}).

So my question is really about how to make omnicompletion aware of what field the cursor is in.

1

2 Answers 2

0

In input (insert or replace) mode, try ^x to enter completion mode selection then ^n to activate buffer based completion.
If you don't have a plugin or a setting in your ~/.vimrc that's making some interference it would do it (buffer completion) by default. Otherwise, check :set complete? (default value iscomplete=.,w,b,u,t) and :set omnifunc? (if not set default, should only be triggered by ^x then ^o) and :set completefunc? (usually triggered by ^x then ^u) so we can debug the stuff.

edit: I misread the question and thought you wanted to complete based on other data already inputed, but in fact you are seeking for keywords only right? Also note that completion is disabled by vimtex for bib files.

5
  • That didn't work for me. It just pulled up the list of all words in the file that could possibly complete what I began to type (rather than only those appearing in the bib field I was in). :set omnifunc? returns omnifunc=syntaxcomplete#Complete, and :set completefunc? returns completefunc= (with nothing after the = sign). Commented Jan 19, 2023 at 5:25
  • Yes, that's the purpose: have completion from all words already typed. Sorry, I misunderstood the "that could complete the word I am typing, even if I am within the braces". OK, completefunc= (empty) means it's not in use (and <kbd>^x</kbd><kbd>^u</kbd> won't have any effect, but asking myself if it isn't the way to look for.) Omni completion is what you are using, I guess, and we have to dig deeper the function used. First, is it defined in your ~/.vimrc or sourced from a plugin?
    – gildux
    Commented Jan 19, 2023 at 12:50
  • Edit lat (over five minutes, time to do a local check) Use :verbose set omnifunc? to have more information on it's activation...
    – gildux
    Commented Jan 19, 2023 at 13:04
  • Running it verbose tells me that omnifunc is set in my .vimrc with the line set omnifunc=syntaxcomplete#Complete. Commented Jan 19, 2023 at 20:39
  • OK, check your file that you have it set up as described in the documentation: it should be on only for file types that can use it. In another hand, VimTeX has no support for that syntax-based completion and disable it among others I'll come with another answer a bit later for a workaround.
    – gildux
    Commented Jan 20, 2023 at 13:23
0

Vim can use a keywords file(s) for completion. I setup two with the help of the biblatex cheatsheet (PDF):

(For the contents of these two files hosted here on this site rather than remotely, see below.)

Now, in my session I have to declare those files for use with the completion

:set dictionary=~/.vim/kwd/biber_entries.dict
:set dictionary+=~/.vim/kwd/biber_fields.dict

Note that I made my test with the at sign in my entries file, but Vim doesn't consider symbols here, unless it's tell (not tested and usable so) to do so? There's no way to put comments either, words after # or " are read too.

:set iskeyword+=@

Once the dictionaries declared, we're ready to complete based on them, after triggering a ^x ^k.

If happy with the files and that completion, add it permanently in your ~/.vimrc but only for Bib files and make the setting local in order to not disturb the other buffers.

au FileType bib execute 'setlocal dict+=~/.vim/kwd/biber_entries.dict,~/.vim/kwd/biber_fields.dict'
au BufNewFile,BufRead *.bib execute 'let &l:dictionary .= "," . tr(expand("~/.vim/kwd/biber_*.dict"), "\n", ",")'

There's still one annoyance: continuously switching to dictionary completion sub mode. By default, ^n and ^p, unless the appropriate ^x switch, Vim scans: the current buffer (.), buffers from other windows (w), other loaded buffers that are in the buffer list (b), the unloaded buffers that are in the buffer list (u), then do tag completion (t). Let's change it to always use our words list first, then the current buffer:

:set complete=k,.

Now, we have homemade Bib files keywords completion, but also any word/name, and even line already there. (full line still require ^x^l and I cannot found how to add that in the option.) Also, when pleased with that option value, save it to the ~/.vimrc and still ensure it's local. Good news, both actions (defining desired completions and lookup files) can be done in one step:

" also make the following fileType dependent
complete=k~/.vim/kwd/biber_entries.dict,k~/.vim/kwd/biber_fields.dict,.

Some people may prefer the use of ~/.vim/after/ftplugin/bib.vim which is always associated to that file type (hence easier to write: this file is triggered like an autocmd fileType, the cons is that there're more to backup and restore.) As I don't use vimtex, I don't know which method is more compatible with its behaviour.

Last notes.

  1. Entries type may not be needed because you use vim-snippets which let you define nice input templates, just add yours for Bib files. I'm also thinking to use such plugin, but for now I'm using abbreviations…
  2. There's no need to have two different files and it may be better to have one global per file type… I did split because I feel more comfortable working in smaller files.
  3. For switching between completion methods easily I'm planning to use finally mucomplete plugin. To be followed.

Here are the content of the .dict files linked above

First, biber_entries.dict:

article
periodical
suppperiodical
inbook
suppbook
bookinbook
book
mvbook
incollection
suppcollection
collection
mvcollection
inproceedings
proceedings
mvproceedings
inreference
reference
mvreference
manual
report
patent
thesis
online
booklet
unpublished
misc
set
xdata

Second, biber_fields.dict:

author shortauthor
bookauthor
editor shorteditor
editora editorb editorc
afterword
annotator
commentator
forward
introduction
translator
holder
institution
organization
publisher origpublisher
title titleaddon origtitle shorttitle subtitle
indextitle
booktitle booktitleaddon subbooktitle
maintitle maintitleaddon submaintitle
journaltitle subjournaltitle
issuetitle subissuetitle
eventtitle eventtitleaddon
reprinttitle
series shortseries
volume
number
part
issue
volumes
edition
version
pubstate
pages
pagetotal
pagination bookpagination
date origdate
eventdate
urldate
location origlocation
venue
url
doi
eid
eprint
eprinttype
type
entrysubtype
addendum
note
howpublished
language origlanguage
isan
isbn
ismn
isrn
iswc
abstract
annotation
file
library
related
relatedtype
relatedstring
entryset
crossref
xref
xdata
langid
langidopts
gender
presort
sortkey
sortname
sortshorthand
sorttitle
indexsorttitle
sortyear
execute
keywords
options
ids
9
  • I am planning to test this soon, but meanwhile might I ask you to edit your answer to include the contents of biber_entries.dict and biber_fields.dict rather than linking to a remote site? This would improve the usefulness of this answer in the long run. Commented Jan 22, 2023 at 15:39
  • Done. :) Those lists of words are a bit long (when putting one word per line), that's while I avoided those listings here (I was afraid to make the answer uselessly too long.)
    – gildux
    Commented Jan 22, 2023 at 16:14
  • 1
    Should the :set commands be changed to :setlocal so that they apply only to the .bib buffer that has been opened? Commented Jan 24, 2023 at 16:46
  • I just tested the setup described in this answer but all it seems to do is to allow me to autocomplete the names of bib entries and bib fields. But my question was how I can autocomplete based on the contents of all existing bib entries. E.g., if there is a book entry with the author field author = {Dylan, Bob} and then I make a new article entry and begin filling the author field by typing author = {Dy*} (with my cursor at *, I would like to be able to press a key to make nvim suggest completing the field as author = {Dylan, Bob}. Commented Jan 24, 2023 at 20:21
  • 1
    Sorry, I've understood in first place that you wanted to complete bib-keywords and replicate identical lines. :) I played last night around ability to do a context completion of keywords' values, and it seems very difficult (at least for me :D or maybe am i not using the right approach.) If I achieve to got something working I'll publish the plugin (things are wider than a quick answer here) and let you know here.
    – gildux
    Commented Jan 27, 2023 at 0:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.