obsidian.nvim
一个用于编写和导航 Obsidian 库的 Neovim 插件,使用 Lua 编写。
专为那些喜爱 Obsidian 理念——一款基于 Markdown 的简单笔记应用——但又太爱 Neovim 而无法忍受在其他任何地方打字的人而建。
如果你是 Obsidian 的新手,我强烈推荐观看 这个精彩的 YouTube 视频 以获取出色的概览。
请记住,此插件并非旨在取代 Obsidian,而是对其进行补充。 Obsidian 应用本身功能非常强大;它附带移动应用,并拥有许多在 Neovim 中无法实现的功能,例如图谱浏览器视图。话虽如此,此插件也可以独立使用。您不一定需要将其与 Obsidian 应用配合使用。
目录
功能
▶️ 补全: 通过 nvim-cmp(输入 [[ 触发 wiki 链接,输入 [ 触发 markdown 链接,或输入 # 触发标签)为笔记引用和标签提供超快、异步的自动补全,由 ripgrep 提供支持。
🏃 导航: 在任意指向其他笔记的链接上输入 gf 即可在整个库中导航。
📷 图片: 将图片粘贴到笔记中。
💅 语法: 为引用、标签和复选框提供额外的 Markdown 语法高亮、隐藏和 extmarks 支持。
命令
-
:ObsidianOpen [QUERY]用于在 Obsidian 应用中打开一个笔记。 此命令有一个可选参数:一个用于通过 ID、路径或别名解析要打开的笔记的查询。如果未提供,则打开与当前缓冲区对应的笔记。 -
:ObsidianNew [TITLE]用于创建一个新的笔记。 此命令有一个可选参数:新笔记的标题。 -
:ObsidianQuickSwitch用于快速切换(或打开)库中的另一个笔记,使用 ripgrep 通过其名称进行搜索,并使用您首选的选取器(参见下文 插件依赖项)。 -
:ObsidianFollowLink [vsplit|hsplit]用于跟随光标下的笔记引用,可选择在垂直或水平分屏中打开。 -
:ObsidianBacklinks用于获取当前缓冲区的引用选取器列表。 -
:ObsidianTags [TAG ...]用于获取给定标签所有出现位置的选取器列表。 -
:ObsidianToday [OFFSET]用于打开/创建一个新的每日笔记。此命令还接受一个可选的天数偏移量,例如使用:ObsidianToday -1前往昨天的笔记。与:ObsidianYesterday和:ObsidianTomorrow不同,此命令不区分工作日和周末。 -
:ObsidianYesterday用于打开/创建上一个工作日的每日笔记。 -
:ObsidianTomorrow用于打开/创建下一个工作日的每日笔记。 -
:ObsidianDailies [OFFSET ...]用于打开每日笔记的选取器列表。例如,:ObsidianDailies -2 1用于列出从 2 天前到明天的每日笔记。 -
:ObsidianTemplate [NAME]用于从模板文件夹中插入模板,使用您首选的选取器从列表中进行选择。有关更多信息,请参阅 "使用模板"。 -
:ObsidianSearch [QUERY]用于使用ripgrep和您首选的选取器在库中搜索(或创建)笔记。 -
:ObsidianLink [QUERY]用于将文本的内联可视选择链接到笔记。 此命令有一个可选参数:一个查询,将用于通过 ID、路径或别名解析笔记。如果未提供,则选中的文本将用作查询。 -
:ObsidianLinkNew [TITLE]用于创建新笔记并将其链接到文本的内联可视选择。 此命令有一个可选参数:新笔记的标题。如果未提供,则选中的文本将用作标题。 -
:ObsidianLinks用于将当前缓冲区中的所有链接收集到一个选择器窗口中。 -
:ObsidianExtractNote [TITLE]用于将可视选中的文本提取到新笔记中并链接到该笔记。 -
:ObsidianWorkspace [NAME]用于切换到另一个工作区。 -
:ObsidianPasteImg [IMGNAME]用于将剪贴板中的图像粘贴到笔记中光标所在的位置,方法是将其保存到 vault 并添加一个 markdown 图像链接。您可以通过attachments.img_folder选项配置保存图像的默认文件夹。 -
:ObsidianRename [NEWNAME] [--dry-run]用于重命名当前缓冲区或光标下引用的笔记,并更新 vault 中的所有反向链接。由于此命令仍然相对较新,并且可能会向您的 vault 写入大量更改,我强烈建议在运行之前提交 vault 的当前状态(如果您正在使用版本控制),或者通过在命令后附加 "--dry-run" 先进行试运行,例如:ObsidianRename new-id --dry-run。 -
:ObsidianToggleCheckbox用于循环切换复选框选项。 -
:ObsidianNewFromTemplate [TITLE]用于从模板文件夹中的模板创建新笔记。使用你偏好的选择器从列表中进行选择。 此命令有一个可选参数:新笔记的标题。 -
:ObsidianTOC用于将当前笔记的目录加载到选择器列表中。
演示
安装
系统要求
- NeoVim >= 0.8.0(此插件使用了
vim.fs,该功能仅在 0.8 版本中添加)。 - 如果你需要补全和搜索功能(推荐),你需要安装 ripgrep 并将其添加到你的
$PATH中。 请参阅 ripgrep#installation 了解安装选项。
特定的操作系统还需要额外的依赖项才能使用 obsidian.nvim 的所有功能:
- Windows WSL 用户需要
wsl-open来使用:ObsidianOpen命令。 - MacOS 用户需要
pngpaste(brew install pngpaste)来使用:ObsidianPasteImg命令。 - Linux 用户需要 xclip (X11) 或 wl-clipboard (Wayland) 来使用
:ObsidianPasteImg命令。
搜索功能(例如通过 :ObsidianSearch 和 :ObsidianQuickSwitch 命令)还需要一个选择器,例如 telescope.nvim(请参阅下方的 plugin dependencies)。
安装和配置
要配置 obsidian.nvim,你只需要使用所需的选项调用 require("obsidian").setup({ ... })。
以下是一些使用不同插件管理器的示例。完整的 plugin dependencies 和 configuration options 列表如下。
⚠️ 警告:如果你从最新发行版(推荐用于稳定性)而不是
main安装,请注意main上的 README 可能引用了尚未发布的功能。因此,我建议在 latest release 的标签上查看 README,而不是在main上查看。
使用 lazy.nvim
return {
"epwalsh/obsidian.nvim",
version = "*", -- recommended, use latest release instead of latest commit
lazy = true,
ft = "markdown",
-- Replace the above line with this if you only want to load obsidian.nvim for markdown files in your vault:
-- event = {
-- -- If you want to use the home shortcut '~' here you need to call 'vim.fn.expand'.
-- -- E.g. "BufReadPre " .. vim.fn.expand "~" .. "/my-vault/*.md"
-- -- refer to `:h file-pattern` for more examples
-- "BufReadPre path/to/my-vault/*.md",
-- "BufNewFile path/to/my-vault/*.md",
-- },
dependencies = {
-- Required.
"nvim-lua/plenary.nvim",
-- see below for full list of optional dependencies 👇
},
opts = {
workspaces = {
{
name = "personal",
path = "~/vaults/personal",
},
{
name = "work",
path = "~/vaults/work",
},
},
-- see below for full list of options 👇
},
}
使用 packer.nvim
use({
"epwalsh/obsidian.nvim",
tag = "*", -- recommended, use latest release instead of latest commit
requires = {
-- Required.
"nvim-lua/plenary.nvim",
-- see below for full list of optional dependencies 👇
},
config = function()
require("obsidian").setup({
workspaces = {
{
name = "personal",
path = "~/vaults/personal",
},
{
name = "work",
path = "~/vaults/work",
},
},
-- see below for full list of options 👇
})
end,
})
插件依赖
唯一的必需插件依赖是 plenary.nvim,但还有一些可选依赖可以增强 obsidian.nvim 的体验。
补全:
- [推荐] hrsh7th/nvim-cmp:用于笔记引用的补全。
选择器:
- [推荐] nvim-telescope/telescope.nvim:用于搜索和快速切换功能。
- 来自 mini.nvim 库的 Mini.Pick:telescope 的替代方案,用于搜索和快速切换功能。
- ibhagwan/fzf-lua:telescope 的另一个替代方案,用于搜索和快速切换功能。
语法高亮:
- [推荐] nvim-treesitter:用于基础 markdown 语法高亮。有关更多详细信息,请参阅 syntax highlighting。
- preservim/vim-markdown:nvim-treesitter 的替代方案,用于语法高亮(有关更多详细信息,请参阅 syntax highlighting),以及其他实用功能。
其他:
如果你选择使用其中任何一个,你应该将它们包含在你的包管理器中 obsidian.nvim 插件规范的 "dependencies" 或 "requires" 字段中。
配置选项
这是可以传递给 require("obsidian").setup() 的所有选项的完整列表。以下设置不一定是默认值,但代表合理的默认设置。请仔细阅读每个选项并根据你的需求进行自定义:
{
-- A list of workspace names, paths, and configuration overrides.
-- If you use the Obsidian app, the 'path' of a workspace should generally be
-- your vault root (where the `.obsidian` folder is located).
-- When obsidian.nvim is loaded by your plugin manager, it will automatically set
-- the workspace to the first workspace in the list whose `path` is a parent of the
-- current markdown file being edited.
workspaces = {
{
name = "personal",
path = "~/vaults/personal",
},
{
name = "work",
path = "~/vaults/work",
-- Optional, override certain settings.
overrides = {
notes_subdir = "notes",
},
},
},
-- Alternatively - and for backwards compatibility - you can set 'dir' to a single path instead of
-- 'workspaces'. For example:
-- dir = "~/vaults/work",
-- Optional, if you keep notes in a specific subdirectory of your vault.
notes_subdir = "notes",
-- Optional, set the log level for obsidian.nvim. This is an integer corresponding to one of the log
-- levels defined by "vim.log.levels.*".
log_level = vim.log.levels.INFO,
daily_notes = {
-- Optional, if you keep daily notes in a separate directory.
folder = "notes/dailies",
-- Optional, if you want to change the date format for the ID of daily notes.
date_format = "%Y-%m-%d",
-- Optional, if you want to change the date format of the default alias of daily notes.
alias_format = "%B %-d, %Y",
-- Optional, default tags to add to each new daily note created.
default_tags = { "daily-notes" },
-- Optional, if you want to automatically insert a template from your template directory like 'daily.md'
template = nil
},
-- Optional, completion of wiki links, local markdown links, and tags using nvim-cmp.
completion = {
-- Set to false to disable completion.
nvim_cmp = true,
-- Trigger completion at 2 chars.
min_chars = 2,
},
-- Optional, configure key mappings. These are the defaults. If you don't want to set any keymappings this
-- way then set 'mappings = {}'.
mappings = {
-- Overrides the 'gf' mapping to work on markdown/wiki links within your vault.
["gf"] = {
action = function()
return require("obsidian").util.gf_passthrough()
end,
opts = { noremap = false, expr = true, buffer = true },
},
-- Toggle check-boxes.
["<leader>ch"] = {
action = function()
return require("obsidian").util.toggle_checkbox()
end,
opts = { buffer = true },
},
-- Smart action depending on context, either follow link or toggle checkbox.
["<cr>"] = {
action = function()
return require("obsidian").util.smart_action()
end,
opts = { buffer = true, expr = true },
}
},
-- Where to put new notes. Valid options are
-- * "current_dir" - put new notes in same directory as the current buffer.
-- * "notes_subdir" - put new notes in the default notes subdirectory.
new_notes_location = "notes_subdir",
-- Optional, customize how note IDs are generated given an optional title.
---@param title string|?
---@return string
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
-- If title is given, transform it into valid file name.
suffix = title:gsub(" ", "-"):gsub("[^A-Za-z0-9-]", ""):lower()
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
return tostring(os.time()) .. "-" .. suffix
end,
-- Optional, customize how note file names are generated given the ID, target directory, and title.
---@param spec { id: string, dir: obsidian.Path, title: string|? }
---@return string|obsidian.Path The full path to the new note.
note_path_func = function(spec)
-- This is equivalent to the default behavior.
local path = spec.dir / tostring(spec.id)
return path:with_suffix(".md")
end,
-- Optional, customize how wiki links are formatted. You can set this to one of:
-- * "use_alias_only", e.g. '[[Foo Bar]]'
-- * "prepend_note_id", e.g. '[[foo-bar|Foo Bar]]'
-- * "prepend_note_path", e.g. '[[foo-bar.md|Foo Bar]]'
-- * "use_path_only", e.g. '[[foo-bar.md]]'
-- Or you can set it to a function that takes a table of options and returns a string, like this:
wiki_link_func = function(opts)
return require("obsidian.util").wiki_link_id_prefix(opts)
end,
-- Optional, customize how markdown links are formatted.
markdown_link_func = function(opts)
return require("obsidian.util").markdown_link(opts)
end,
-- Either 'wiki' or 'markdown'.
preferred_link_style = "wiki",
-- Optional, boolean or a function that takes a filename and returns a boolean.
-- `true` indicates that you don't want obsidian.nvim to manage frontmatter.
disable_frontmatter = false,
-- Optional, alternatively you can customize the frontmatter data.
---@return table
note_frontmatter_func = function(note)
-- Add the title of the note as an alias.
if note.title then
note:add_alias(note.title)
end
local out = { id = note.id, aliases = note.aliases, tags = note.tags }
-- `note.metadata` contains any manually added fields in the frontmatter.
-- So here we just make sure those fields are kept in the frontmatter.
if note.metadata ~= nil and not vim.tbl_isempty(note.metadata) then
for k, v in pairs(note.metadata) do
out[k] = v
end
end
return out
end,
-- Optional, for templates (see below).
templates = {
folder = "templates",
date_format = "%Y-%m-%d",
time_format = "%H:%M",
-- A map for custom variables, the key should be the variable and the value a function
substitutions = {},
},
-- 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)
vim.fn.jobstart { "qlmanage", "-p", img } -- Mac OS quick look preview
-- vim.fn.jobstart({"xdg-open", url}) -- linux
-- vim.cmd(':silent exec "!start ' .. url .. '"') -- Windows
end,
-- Optional, set to true if you use the Obsidian Advanced URI plugin.
-- https://github.com/Vinzent03/obsidian-advanced-uri
use_advanced_uri = false,
-- Optional, set to true to force ':ObsidianOpen' to bring the app to the foreground.
open_app_foreground = false,
picker = {
-- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', or 'mini.pick'.
name = "telescope.nvim",
-- Optional, configure key mappings for the picker. These are the defaults.
-- Not all pickers support all mappings.
note_mappings = {
-- Create a new note from your query.
new = "<C-x>",
-- Insert a link to the selected note.
insert_link = "<C-l>",
},
tag_mappings = {
-- Add tag(s) to current note.
tag_note = "<C-x>",
-- Insert a tag at the current location.
insert_tag = "<C-l>",
},
},
-- Optional, sort search results by "path", "modified", "accessed", or "created".
-- The recommend value is "modified" and `true` for `sort_reversed`, which means, for example,
-- that `:ObsidianQuickSwitch` will show the notes sorted by latest modified time
sort_by = "modified",
sort_reversed = true,
-- Set the maximum number of lines to read from notes on disk when performing certain searches.
search_max_lines = 1000,
-- Optional, determines how certain commands open notes. The valid options are:
-- 1. "current" (the default) - to always open in the current window
-- 2. "vsplit" - to open in a vertical split if there's not already a vertical split
-- 3. "hsplit" - to open in a horizontal split if there's not already a horizontal split
open_notes_in = "current",
-- Optional, define your own callbacks to further customize behavior.
callbacks = {
-- Runs at the end of `require("obsidian").setup()`.
---@param client obsidian.Client
post_setup = function(client) end,
-- Runs anytime you enter the buffer for a note.
---@param client obsidian.Client
---@param note obsidian.Note
enter_note = function(client, note) end,
-- Runs anytime you leave the buffer for a note.
---@param client obsidian.Client
---@param note obsidian.Note
leave_note = function(client, note) end,
-- Runs right before writing the buffer for a note.
---@param client obsidian.Client
---@param note obsidian.Note
pre_write_note = function(client, note) end,
-- Runs anytime the workspace is set/changed.
---@param client obsidian.Client
---@param workspace obsidian.Workspace
post_set_workspace = function(client, workspace) end,
},
-- Optional, configure additional syntax highlighting / extmarks.
-- This requires you have `conceallevel` set to 1 or 2. See `:help conceallevel` for more details.
ui = {
enable = true, -- set to false to disable all additional syntax features
update_debounce = 200, -- update delay after a text change (in milliseconds)
max_file_length = 5000, -- disable UI features for files with more than this many lines
-- Define how various check-boxes are displayed
checkboxes = {
-- NOTE: the 'char' value has to be a single character, and the highlight groups are defined below.
[" "] = { char = "", hl_group = "ObsidianTodo" },
["x"] = { char = "", hl_group = "ObsidianDone" },
[">"] = { char = "", hl_group = "ObsidianRightArrow" },
["~"] = { char = "", hl_group = "ObsidianTilde" },
["!"] = { char = "", hl_group = "ObsidianImportant" },
-- Replace the above with this if you don't have a patched font:
-- [" "] = { char = "☐", hl_group = "ObsidianTodo" },
-- ["x"] = { char = "✔", hl_group = "ObsidianDone" },
-- You can also add more custom ones...
},
-- Use bullet marks for non-checkbox lists.
bullets = { char = "•", hl_group = "ObsidianBullet" },
external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" },
-- Replace the above with this if you don't have a patched font:
-- external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" },
reference_text = { hl_group = "ObsidianRefText" },
highlight_text = { hl_group = "ObsidianHighlightText" },
tags = { hl_group = "ObsidianTag" },
block_ids = { hl_group = "ObsidianBlockID" },
hl_groups = {
-- The options are passed directly to `vim.api.nvim_set_hl()`. See `:help nvim_set_hl`.
ObsidianTodo = { bold = true, fg = "#f78c6c" },
ObsidianDone = { bold = true, fg = "#89ddff" },
ObsidianRightArrow = { bold = true, fg = "#f78c6c" },
ObsidianTilde = { bold = true, fg = "#ff5370" },
ObsidianImportant = { bold = true, fg = "#d73128" },
ObsidianBullet = { bold = true, fg = "#89ddff" },
ObsidianRefText = { underline = true, fg = "#c792ea" },
ObsidianExtLinkIcon = { fg = "#c792ea" },
ObsidianTag = { italic = true, fg = "#89ddff" },
ObsidianBlockID = { italic = true, fg = "#89ddff" },
ObsidianHighlightText = { bg = "#75662e" },
},
},
-- Specify how to handle attachments.
attachments = {
-- The default folder to place images in via `:ObsidianPasteImg`.
-- If this is a relative path it will be interpreted as relative to the vault root.
-- You can always override this per image by passing a full path to the command instead of just a filename.
img_folder = "assets/imgs", -- This is the default
-- Optional, customize the default name or prefix when pasting images via `:ObsidianPasteImg`.
---@return string
img_name_func = function()
-- Prefix image names with timestamp.
return string.format("%s-", os.time())
end,
-- A function that determines the text to insert in the note when pasting an image.
-- It takes two arguments, the `obsidian.Client` and an `obsidian.Path` to the image file.
-- This is the default implementation.
---@param client obsidian.Client
---@param path obsidian.Path the absolute path to the image file
---@return string
img_text_func = function(client, path)
path = client:vault_relative_path(path) or path
return string.format("", path.name, path)
end,
},
}
配置说明
工作区
对于大多数 Obsidian 用户,你在 obsidian.nvim 配置中设置的每个工作区应对应一个唯一的 Obsidian vault,在这种情况下,每个工作区的 path 应设置为对应的 vault 根路径。
例如,假设你在 ~/vaults/personal 处有一个 Obsidian vault,那么你的配置中的 workspaces 字段将如下所示:
config = {
workspaces = {
{
name = "personal",
path = "~/vaults/personal",
},
}
}
然而,obsidian.nvim 的工作区概念比库的概念更为通用,因为配置一个不对应库的工作区也是有效的,或者为单个库配置多个工作区也是有效的。后者在需要将单个库分割为多个目录并对每个目录应用不同设置时可能很有用。例如:
config = {
workspaces = {
{
name = "project-1",
path = "~/vaults/personal/project-1",
-- `strict=true` here tells obsidian to use the `path` as the workspace/vault root,
-- even though the actual Obsidian vault root may be `~/vaults/personal/`.
strict = true,
overrides = {
-- ...
},
},
{
name = "project-2",
path = "~/vaults/personal/project-2",
strict = true,
overrides = {
-- ...
},
},
}
}
obsidian.nvim 还支持“动态”工作区。这些工作区只是将 path 设置为一个 Lua 函数(返回一个路径),而不是硬编码的路径。这在多种场景下非常有用,例如当你希望工作区的 path 始终设置为当前缓冲区的父目录时:
config = {
workspaces = {
{
name = "buf-parent",
path = function()
return assert(vim.fs.dirname(vim.api.nvim_buf_get_name(0)))
end,
},
}
}
动态工作空间在你希望将本插件的部分功能应用于“固定”库之外的 Markdown 文件时也很有用。 请参阅 在 workspace / Obsidian vault 之外使用 obsidian.nvim。
Completion
当你在库目录内进入 Markdown 缓冲区时,obsidian.nvim 会自动将自己设置为 nvim-cmp 数据源,你无需手动将此插件指定为 cmp 数据源。
请注意,为了触发 YAML frontmatter 内部标签的补全,你仍然需要在标签开头输入“#”。当你按下回车键选择标签补全项时,obsidian.nvim 会移除“#”。
Syntax highlighting
如果你正在使用 nvim-treesitter,你的配置应同时包含 "markdown" 和 "markdown_inline" 数据源:
require("nvim-treesitter.configs").setup({
ensure_installed = { "markdown", "markdown_inline", ... },
highlight = {
enable = true,
},
})
如果你使用 vim-markdown,你可能希望禁用其 frontmatter 语法高亮(vim.g.vim_markdown_frontmatter = 1),我发现它效果并不理想。
隐藏字符
如果你希望使用格式隐藏功能,你需要将 conceallevel 设置为允许该功能的值(即 1 或 2),例如:
在 viml 中为 set conceallevel=1,或在 lua 配置中为 vim.opt.conceallevel = 1。
笔记命名与位置
notes_subdir 和 note_id_func 选项并非互斥。你可以同时使用它们。例如,结合上述两种设置,一个名为 "My new note" 的新笔记将被分配类似 notes/1657296016-my-new-note.md 的路径。
gf 透传
如果你想要 gf 透传功能,但已经覆盖了 gf 键绑定,只需将你的 gf 映射定义更改为类似以下内容:
vim.keymap.set("n", "gf", function()
if require("obsidian").util.cursor_on_markdown_link() then
return "<cmd>ObsidianFollowLink<CR>"
else
return "gf"
end
end, { noremap = false, expr = true })
然后确保在您的 obsidian.nvim 配置中注释掉 gf 键绑定:
mappings = {
-- ["gf"] = ...
},
或者,您也可以将 obsidian.nvim 的 follow 功能映射到另一个按键:
mappings = {
["fo"] = {
action = function()
return require("obsidian").util.gf_passthrough()
end,
opts = { noremap = false, expr = true, buffer = true },
},
},
使用模板
要在当前笔记中插入模板,请运行命令 :ObsidianTemplate。这将使用你首选的选取器打开模板文件夹中可用模板的列表。选择一个模板并按 <CR> 进行插入。
要从模板创建新笔记,请运行命令 :ObsidianNewFromTemplate。这将提示你输入新笔记的可选路径,并使用你首选的选取器打开模板文件夹中可用模板的列表。选择一个模板并按 <CR> 使用所选模板创建新笔记。
开箱即支持 {{id}}、{{title}}、{{path}}、{{date}} 和 {{time}} 的替换。
例如,使用以下配置
{
-- other fields ...
templates = {
folder = "my-templates-folder",
date_format = "%Y-%m-%d-%a",
time_format = "%H:%M",
},
}
以及文件 ~/my-vault/my-templates-folder/note template.md:
# {{title}}
Date created: {{date}}
创建笔记 Configuring Neovim.md 并执行 :ObsidianTemplate 将插入
# Configuring Neovim
Date created: 2023-03-01-Wed
位于光标位置上方。
您还可以使用配置字段 templates.substitutions 定义自定义模板替换。例如,要在插入模板时自动替换模板变量 {{yesterday}},您可以将以下内容添加到您的配置中:
{
-- other fields ...
templates = {
substitutions = {
yesterday = function()
return os.date("%Y-%m-%d", os.time() - 86400)
end
}
}
在工作区或 vault 之外使用
可以通过配置“动态”工作区,使 obsidian.nvim 能够在常规工作区 / Obsidian vault 之外的单个 markdown 文件上工作。为此,您只需添加一个特殊的工作区,其 path 字段使用一个函数(而非字符串),该函数应返回当前 buffer 的父目录。这告诉 obsidian.nvim,当 buffer 不位于另一个固定工作区内时,使用该目录作为工作区 path 和 root(vault 根目录)。
例如,以这种方式扩展上述配置:
{
workspaces = {
{
name = "personal",
path = "~/vaults/personal",
},
...
+ {
+ name = "no-vault",
+ path = function()
+ -- alternatively use the CWD:
+ -- return assert(vim.fn.getcwd())
+ return assert(vim.fs.dirname(vim.api.nvim_buf_get_name(0)))
+ end,
+ overrides = {
+ notes_subdir = vim.NIL, -- have to use 'vim.NIL' instead of 'nil'
+ new_notes_location = "current_dir",
+ templates = {
+ folder = vim.NIL,
+ },
+ disable_frontmatter = true,
+ },
+ },
+ },
...
}
使用此配置,每当你在 "~/vaults/personal"(或你配置的任何固定 vault)之外进入一个 markdown 缓冲区时,obsidian.nvim 都会切换到动态工作区,并将路径 / 根目录设置为该缓冲区的父目录。
请注意,为了避免意外行为(例如为 notes_subdir 创建新目录),仔细设置工作区 overrides 选项非常重要。
并且请记住,要将配置选项重置为 nil,你必须在那里使用 vim.NIL,而不是内置的 Lua nil,这是由 Lua 表的工作方式决定的。
贡献
在提交拉取请求之前,请先阅读 CONTRIBUTING 指南。
如果你特别慷慨,我总是很感激一些咖啡基金! ❤️