完美搞定 obsidian.nvim 作为知识库录入工具
安装配置环境
lazyvim + obsidian.nvim 具备了所有想要的功能
美中不足的是 obsidian.nvim 存在了一些问题, 我就做了一些修改, 使其更加完美.
lazyvim 安装完毕后, plugins 下添加 obsidian.lua 文件, 内容如下:
return {
"bigzhu/obsidian.nvim",
version = "*",
lazy = false,
dependencies = {
"nvim-lua/plenary.nvim",
-- https://www.lazyvim.org/extras/coding/nvim-cmp
-- :LazyExtras 确保安装 coding.nvim-cmp, 这里添加无用
"hrsh7th/nvim-cmp",
},
opts = {
completion = {
nvim_cmp = true,
min_chars = 1,
},
preferred_link_style = "markdown",
workspaces = {
{
name = "cheese",
path = "~/Sync/home/cheese",
},
},
-- Optional, customize how note IDs are generated given an optional title.
---@param title string|?
---@return string
---使用 title 作为 node 的文件名
note_id_func = function(title)
-- Create note IDs in a Zettelkasten format with a timestamp and a suffix.
-- In this case a note with the title 'My new note' will be given an ID that looks
-- like '1657296016-my-new-note', and therefore the file name '1657296016-my-new-note.md'
local suffix = ""
if title ~= nil then
-- vim.notify("first title : " .. title, vim.log.levels.INFO)
-- 移除末尾的空白字符和不可见字符
suffix = vim.fn.trim(title)
-- :gsub(" ", "-") -- 空格转连字符
-- :gsub("[\n\r]+", "") -- 移除换行
-- :gsub("[<>:\"/\\|?*]+", "-") -- 移除非法字符
else
-- If title is nil, just add 4 random uppercase letters to the suffix.
for _ = 1, 4 do
suffix = suffix .. string.char(math.random(65, 90))
end
end
-- vim.notify("Final suffix: " .. suffix, vim.log.levels.INFO)
return suffix
end,
-- Optional, by default when you use `:ObsidianFollowLink` on a link to an external
-- URL it will be ignored but you can customize this behavior here.
---@param url string
follow_url_func = function(url)
-- Open the URL in the default web browser.
vim.fn.jobstart({ "open", url }) -- Mac OS
-- vim.fn.jobstart({"xdg-open", url}) -- linux
-- vim.cmd(':silent exec "!start ' .. url .. '"') -- Windows
-- vim.ui.open(url) -- need Neovim 0.10.0+
end,
-- Optional, by default when you use `:ObsidianFollowLink` on a link to an image
-- file it will be ignored but you can customize this behavior here.
---@param img string
follow_img_func = function(img)
-- Get the current buffer's directory as base path
local current_file = vim.fn.expand("%:p:h")
local abs_path = current_file .. "/" .. img
abs_path = vim.fn.expand(abs_path)
vim.fn.jobstart({ "open", abs_path }) -- Mac OS
-- vim.notify("Opening image: " .. abs_path, vim.log.levels.INFO)
-- vim.fn.jobstart({ "qlmanage", "-p", abs_path }) -- Mac OS quick look preview
-- vim.fn.jobstart({ "kitty", "+kitten", "icat", abs_path })
-- vim.fn.jobstart({"xdg-open", url}) -- linux
-- vim.cmd(':silent exec "!start ' .. url .. '"') -- Windows
end,
},
}
修改和完善的点
新建时候乱码问题
obsidian.nvim 存在的一个致命问题是 create link
时候作者没有考虑对 multibyte character
的支持
比如你选中一段文字, 想要以此为标题来新建一个文章, 如果最后一个字符是 multibyte character
, 比如中文或者日文, 那么你会发现建立的 link 中字符被切断了, 出现了乱码.
我 fork 修改了支持了 multibyte character
, 也向作者提了 pull request, 但是作者似乎很久又没出现了, 先凑合用我的吧.
排序问题
查找排序问题, ObsidianQuickSwitch
原本默认是按文件名排序的, 我增加了 sort_by = "modified"
相关的功能, 作者也接受支持了, 而且还将其作为默认值, 还不错.
后续发现 ObsidianQuickSwitch
以后, 如果输入关键词查找, 过滤出来的结果肯定还是希望依然按照modified
排序, 但是作者没有支持这个功能, 我也提了 pull request, 作者消失没合并, 就只能用我的了.
链接问题
默认对链接的处理也很有问题, 基础的对新建, url, 图片等的操作处理都没默认弄好, 所以上面的配置文件我都做了处理.
- 用标题做文件名应该是默认操作, 作者选择了用随机字符串, 这样和他
[
来索引引用文章的功能其实是冲突了, 搞不懂他为何那么做. 所以配置了note_id_func
, 让其好好用标题当文件名 follow_url_func
配置了用默认浏览器打开 urlfollow_img_func
原本配置了预览, 发现容易让界面混乱, 所以改回用 mac 默认工具打开了.
链接引用问题
作者文档说的是支持 [
来引用文章, 但是弄来弄去都发现无法激活.
preferred_link_style = "markdown"
等配置都加了也无效, 最后发现添加的 dependencies 并不会生效.
要进入 :LazyExtras
确保安装 coding.nvim-cmp
热键
obsidian.nvim 的mappings不生效, 而且还要考虑激活问题, 我是随时都会调用查询或者写文章的, 所以直接在 lazyvim keymaps.lua 添加热键绑定了:
vim.keymap.set("n", "<C-f>", "<cmd>ObsidianQuickSwitch<CR>", { desc = "Search cheese by file name" })
vim.keymap.set("n", "<C-j>", "<cmd>ObsidianSearch<CR>", { desc = "Search cheese by content" })
vim.keymap.set("n", "<C-g>", "<cmd>ObsidianToday<CR>", { desc = "Cheese create a new daily note" })
vim.keymap.set("n", "<C-n>", "<cmd>ObsidianNew<CR>", { desc = "Cheese to create a new note" })
vim.keymap.set("n", "<C-t>", "o<CR><Esc><cmd>ObsidianTemplate main.md<CR>", { desc = "Using templates" })
map("v", "<CR>", "<cmd>ObsidianLinkNew<cr>", { desc = "create link" })