Skip to content

Commit 16a0e56

Browse files
author
jghauser
committed
feat!: enable inserting multiple refs at once
- requires breaking change in `cite_formats` option
1 parent 091e6df commit 16a0e56

File tree

5 files changed

+97
-63
lines changed

5 files changed

+97
-63
lines changed

lua/papis/at-cursor/init.lua

+33-18
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ local NuiPopup = require("nui.popup")
99
local nuiAutocmd = require("nui.utils.autocmd")
1010
local nuiEvent = require("nui.utils.autocmd").event
1111

12-
local fn = vim.fn
13-
1412
local log = require("papis.log")
1513
local config = require("papis.config")
1614
local popup_format = config["at-cursor"].popup_format
15+
local cite_format = config:get_cite_format()
1716
local utils = require("papis.utils")
1817
local commands = require("papis.commands")
1918
local keymaps = require("papis.keymaps")
@@ -25,24 +24,40 @@ end
2524
---Tries to identify the ref under cursor
2625
---@return string|nil #Nil if nothing is found, otherwise is the identified ref
2726
local function get_ref_under_cursor()
28-
-- get the word under the cursor
29-
local ref = fn.expand("<cWORD>")
30-
local filetype = vim.bo.filetype
31-
log.debug("The filetype is: " .. filetype)
32-
local cite_format = utils.get_cite_format(filetype)
33-
if type(cite_format) == "table" then
34-
cite_format = cite_format[2]
35-
end
36-
log.debug("The cite_format is: " .. cite_format)
37-
local _, prefix_end = string.find(cite_format, "%%s")
38-
prefix_end = prefix_end - 2
39-
local cite_format_prefix = string.sub(cite_format, 1, prefix_end)
40-
local _, ref_start = string.find(ref, cite_format_prefix)
27+
local start_str = cite_format.start_str
28+
local ref_prefix = cite_format.ref_prefix
29+
30+
-- get current line and cursor position
31+
local current_line = vim.api.nvim_get_current_line()
32+
local _, cursor_col = unpack(vim.api.nvim_win_get_cursor(0))
33+
34+
-- Find the start and end of the word under the cursor
35+
local line_until_cursor = current_line:sub(1, cursor_col)
36+
local word_start_col = line_until_cursor:find("[^%s,;]*$") or 1
37+
local line_after_cursor = current_line:sub(cursor_col)
38+
local word_end_col = cursor_col + (line_after_cursor:find("[%s,;]") or #line_after_cursor) - 1
39+
40+
-- Extract the word
41+
local ref = current_line:sub(word_start_col, word_end_col)
42+
4143
-- if we found the cite_format prefix in the string, we need to strip it
42-
if ref_start then
43-
ref_start = ref_start + 1
44-
ref = string.sub(ref, ref_start)
44+
if start_str then
45+
local escaped_start_str = start_str:gsub("%W", "%%%0")
46+
local _, ref_start = string.find(ref, escaped_start_str)
47+
if ref_start then
48+
ref = string.sub(ref, ref_start + 1)
49+
end
4550
end
51+
-- if we found the ref_prefix in the string, we need to strip it
52+
if ref_prefix then
53+
local escaped_ref_prefix = ref_prefix:gsub("%W", "%%%0")
54+
local _, ref_start = string.find(ref, escaped_ref_prefix)
55+
if ref_start then
56+
ref_start = ref_start + 1
57+
ref = string.sub(ref, ref_start)
58+
end
59+
end
60+
4661
-- remove all punctuation characters at the beginning and end of string
4762
ref = ref:gsub("^[%p]*(.-)[%p]*$", "%1")
4863

lua/papis/config.lua

+48-6
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,33 @@ local default_config = {
1818
["testing"] = false,
1919
}, -- can be set to nil or false or left out
2020
cite_formats = {
21-
tex = { "\\cite{%s}", "\\cite[tp]?%*?{%s}" },
22-
markdown = "@%s",
23-
rmd = "@%s",
24-
plain = "%s",
25-
org = { "[cite:@%s]", "%[cite:@%s]" },
26-
norg = "{= %s}",
21+
tex = {
22+
start_str = [[\cite{]],
23+
end_str = "}",
24+
separator_str = ", ",
25+
},
26+
markdown = {
27+
ref_prefix = "@",
28+
separator_str = "; "
29+
},
30+
rmd = {
31+
ref_prefix = "@",
32+
separator_str = "; "
33+
},
34+
plain = {
35+
separator_str = ", "
36+
},
37+
org = {
38+
start_str = "[cite:",
39+
end_str = "]",
40+
ref_prefix = "@",
41+
separator_str = ";",
42+
},
43+
norg = {
44+
start_str = "{= ",
45+
end_str = "}",
46+
separator_str = "; ",
47+
},
2748
},
2849
cite_formats_fallback = "plain",
2950
always_use_plain = false,
@@ -145,6 +166,27 @@ local default_config = {
145166

146167
local M = vim.deepcopy(default_config)
147168

169+
---Get the cite_format for the current filetype
170+
---@return table #cite_format to be used for the filetype. If table, then first is for inserting, second for parsing
171+
function M:get_cite_format()
172+
local filetype = vim.bo.filetype
173+
174+
local cite_formats = self.cite_formats
175+
local cite_formats_fallback = self.cite_formats_fallback
176+
177+
local fallback = {
178+
separator_str = ", "
179+
}
180+
181+
if self.always_use_plain then
182+
local cite_format = cite_formats.plain or fallback
183+
return cite_format
184+
else
185+
local cite_format = cite_formats[filetype] or cite_formats[cite_formats_fallback]
186+
return cite_format
187+
end
188+
end
189+
148190
---Updates the default configuration with user supplied options and gets conf from Papis
149191
---@param opts table #Same format as default_config and contains user config
150192
function M:update(opts)

lua/papis/utils.lua

-17
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,6 @@ end
2828

2929
local M = {}
3030

31-
---Get the cite_format for the current filetype
32-
---@param filetype string #Filetype for which we need a cite_format
33-
---@return string|table #cite_format to be used for the filetype. If table, then first is for inserting, second for parsing
34-
function M.get_cite_format(filetype)
35-
local config = require("papis.config")
36-
local cite_formats = config.cite_formats
37-
local cite_formats_fallback = config.cite_formats_fallback
38-
39-
if config.always_use_plain then
40-
local cite_format = cite_formats.plain or "%s"
41-
return cite_format
42-
else
43-
local cite_format = cite_formats[filetype] or cite_formats[cite_formats_fallback]
44-
return cite_format
45-
end
46-
end
47-
4831
---Splits string by `inputstr` and trims whitespace
4932
---@param inputstr string #String to be split
5033
---@param sep? string #String giving each character by which to split

lua/telescope/_extensions/papis.lua

+2-14
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,12 @@ local telescope_config = require("telescope.config").values
1515
local papis_actions = require("telescope._extensions.papis.actions")
1616

1717
local utils = require("papis.utils")
18+
local config = require("papis.config")
1819
local db = require("papis.sqlite-wrapper")
1920
if not db then
2021
return nil
2122
end
2223

23-
---Gets the cite format for the filetype
24-
---@return string #The cite format for the filetype (or fallback if undefined)
25-
local function parse_format_string()
26-
local cite_format = utils.get_cite_format(vim.bo.filetype)
27-
if type(cite_format) == "table" then
28-
cite_format = cite_format[1]
29-
end
30-
return cite_format
31-
end
32-
3324
local wrap, preview_format, initial_sort_by_time_added
3425

3526
---Defines the papis.nvim telescope picker
@@ -40,9 +31,6 @@ local function papis_picker(opts)
4031
-- get precalculated entries for the telescope picker
4132
local telescope_precalc = require("papis.search").get_precalc()
4233

43-
-- local results = db.data:get(nil, required_db_keys)
44-
local format_string = parse_format_string()
45-
4634
-- amend the generic_sorter so that we can change initial sorting
4735
local generic_sorter = telescope_config.generic_sorter(opts)
4836
local papis_sorter = {}
@@ -88,7 +76,7 @@ local function papis_picker(opts)
8876
sorter = papis_sorter,
8977
attach_mappings = function(prompt_bufnr, map)
9078
actions.select_default:replace(
91-
function() papis_actions.ref_insert(prompt_bufnr, format_string) end)
79+
function() papis_actions.ref_insert(prompt_bufnr) end)
9280
map("i", "<c-o>f",
9381
function() papis_actions.open_file(prompt_bufnr) end,
9482
{ desc = "Open file" })

lua/telescope/_extensions/papis/actions.lua

+14-8
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,27 @@ local M = {}
2121

2222
---This function inserts a formatted ref string at the cursor
2323
---@param prompt_bufnr number @The buffer number of the prompt
24-
---@param format_string string @The string to be inserted
25-
M.ref_insert = function(prompt_bufnr, format_string)
24+
M.ref_insert = function(prompt_bufnr)
2625
local multi = get_multi(prompt_bufnr)
27-
2826
actions.close(prompt_bufnr)
29-
local string_to_insert = ""
27+
local cite_format = config:get_cite_format()
28+
local start_str = cite_format.start_str
29+
local end_str = cite_format.end_str
30+
local ref_prefix = cite_format.ref_prefix or ""
31+
local separator_str = cite_format.separator_str
32+
local string_to_insert = start_str or ""
33+
3034
if vim.tbl_isempty(multi) then
31-
local ref = string.format(format_string, action_state.get_selected_entry().id.ref)
32-
string_to_insert = ref
35+
local ref = ref_prefix .. action_state.get_selected_entry().id.ref
36+
string_to_insert = string_to_insert .. ref
3337
else
38+
local refs = {}
3439
for _, entry in pairs(multi) do
35-
local ref = string.format(format_string, entry.id.ref)
36-
string_to_insert = string_to_insert .. ref .. " "
40+
refs[#refs + 1] = ref_prefix .. entry.id.ref
3741
end
42+
string_to_insert = string_to_insert .. table.concat(refs, separator_str)
3843
end
44+
string_to_insert = string_to_insert .. (end_str or "")
3945
vim.api.nvim_put({ string_to_insert }, "", false, true)
4046
end
4147

0 commit comments

Comments
 (0)