Skip to content

bibtex citation picker #13

@ashiklom

Description

@ashiklom

A way to use fzf, telescope, or some other picker to quickly search for and insert references from bibtex files.

https://github.com/msprev/fzf-bibtex may be a good option, but has a few heavy-ish dependencies.

Here's a lua file for configuring fzf-bibtex once it's installed.

-- default list of bibfiles
-- can be overriden by changing vim.b.bibfiles inside buffer
local default_bibfiles = {
  -- put your default bibfiles here
}

-- default cache directory
-- uses neovim's stdpath to set up a cache - no need to fiddle with this
local cachedir = vim.fn.stdpath("state") .. "/fzf-bibtex/"

-- actions
local pandoc = function(selected, opts)
  local result = vim.fn.system("bibtex-cite", selected)
  vim.api.nvim_put({ result }, "c", false, true)
  if opts.fzf_bibtex.mode == "i" then
    vim.api.nvim_feedkeys("i", "n", true)
  end
end

local citet = function(selected, opts)
  local result = vim.fn.system('bibtex-cite -prefix="\\\\citet{" -postfix="}" -separator=","', selected)
  vim.api.nvim_put({ result }, "c", false, true)
  if opts.fzf_bibtex.mode == "i" then
    vim.api.nvim_feedkeys("i", "n", true)
  end
end

local citep = function(selected, opts)
  local result = vim.fn.system('bibtex-cite -prefix="\\\\citep{" -postfix="}" -separator=","', selected)
  vim.api.nvim_put({ result }, "c", false, true)
  if opts.fzf_bibtex.mode == "i" then
    vim.api.nvim_feedkeys("i", "n", true)
  end
end

local markdown_print = function(selected, opts)
  local result =
    vim.fn.system("bibtex-markdown -cache=" .. cachedir .. " " .. table.concat(vim.b.bibfiles, " "), selected)
  local result_lines = {}
  for line in result:gmatch("[^\\n]+") do
    table.insert(result_lines, line)
  end
  vim.api.nvim_put(result_lines, "l", true, true)
  if opts.fzf_bibtex.mode == "i" then
    vim.api.nvim_feedkeys("i", "n", true)
  end
end

local fzf_bibtex_menu = function(mode)
  return function()
    -- check cache directory hasn't mysteriously disappeared
    if vim.fn.isdirectory(cachedir) == 0 then
      vim.fn.mkdir(cachedir, "p")
    end

    require("fzf-lua").config.set_action_helpstr(pandoc, "@-pandoc")
    require("fzf-lua").config.set_action_helpstr(citet, "\\\\citet{}")
    require("fzf-lua").config.set_action_helpstr(citep, "\\\\citep{}")
    require("fzf-lua").config.set_action_helpstr(markdown_print, "markdown-pretty-print")

    -- header line: the bibtex filenames
    local filenames = {}
    for i, fullpath in ipairs(vim.b.bibfiles) do
      filenames[i] = vim.fn.fnamemodify(fullpath, ":t")
    end
    local header = table.concat(filenames, "\\\\ ")

    -- set default action
    local default_action_list = {
      markdown = pandoc,
      quarto = pandoc,
      tex = citet,
    }

    local default_action = default_action_list[vim.bo.ft]

    -- run fzf
    return require("fzf-lua").fzf_exec(
      "bibtex-ls " .. "-cache=" .. cachedir .. " " .. table.concat(vim.b.bibfiles, " "),
      {
        actions = {
          ["default"] = default_action,
          ["alt-a"] = pandoc,
          ["alt-t"] = citet,
          ["alt-p"] = citep,
          ["alt-m"] = markdown_print,
        },
        fzf_bibtex = { ["mode"] = mode },
        fzf_opts = { ["--multi"] = true, ["--prompt"] = "BibTeX> ", ["--header"] = header },
      }
    )
  end
end

-- Only enable mapping in tex or markdown
vim.api.nvim_create_autocmd("Filetype", {
  desc = "Set up keymaps for fzf-bibtex",
  group = vim.api.nvim_create_augroup("fzf-bibtex", { clear = true }),
  pattern = { "markdown", "tex", "quarto" },
  callback = function()
    vim.b.bibfiles = default_bibfiles
    vim.keymap.set("n", "<localleader>c", fzf_bibtex_menu("n"), { buffer = true, desc = "FZF: BibTeX [C]itations" })
    vim.keymap.set("i", "@@", fzf_bibtex_menu("i"), { buffer = true, desc = "FZF: BibTeX [C]itations" })
  end,
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions