File: doc/obsidian.txt
obsidian.nvim a plugin for writing and navigating an Obsidian vault
obsidian.nvim
A Neovim plugin for writing and navigating Obsidian https://obsidian.md
vaults, written in Lua.
Built for people who love the concept of Obsidian β a simple, markdown-based
notes app β but love Neovim too much to stand typing characters into anything
else.
If youβre new to Obsidian I highly recommend watching this excellent YouTube
video https://youtu.be/5ht8NYkU9wQ?si=8nbnNsRVnw0xfX2S for a great overview.
Keep in mind this plugin is not meant to replace Obsidian, but to complement
it. The Obsidian app is very powerful in its own way; it comes with a mobile
app and has a lot of functionality thatβs not feasible to implement in
Neovim, such as the graph explorer view. That said, this plugin stands on its
own as well. You donβt necessarily need to use it alongside the Obsidian app.
==============================================================================
- Table of contents obsidian-table-of-contents
- π |obsidian-features|
- |obsidian-commands|
- |obsidian-demo|
- βοΈ |obsidian-setup|
- |obsidian-system-requirements|
- |obsidian-install-and-configure|
- |obsidian-plugin-dependencies|
- |obsidian-configuration-options|
- |obsidian-notes-on-configuration|
- |obsidian-using-templates|
- |obsidian-usage-outside-of-a-workspace-or-vault|
- β |obsidian-contributing|
==============================================================================
2. Features obsidian-features
βΆοΈ Completion: Ultra-fast, asynchronous autocompletion for note
references and tags via nvim-cmp https://github.com/hrsh7th/nvim-cmp
(triggered by typing [[ for wiki links, [ for markdown links, or # for
tags), powered by ripgrep https://github.com/BurntSushi/ripgrep.
https://github.com/epwalsh/obsidian.nvim/assets/8812459/90d5f218-06cd-4ebb-b00b-b59c2f5c3cc1
π Navigation: Navigate throughout your vault by typing gf on any link
to another note.
π· Images: Paste images into notes.
π
Syntax: Additional markdown syntax highlighting, concealing, and
extmarks for references, tags, and check-boxes.
https://github.com/epwalsh/obsidian.nvim/assets/8812459/e74f5267-21b5-49bc-a3bb-3b9db5fa6687
COMMANDS obsidian-commands
:ObsidianOpen [QUERY]to open a note in the Obsidian app. This command has
one optional argument: a query used to resolve the note to open by ID, path, or
alias. If not given, the note corresponding to the current buffer is opened.:ObsidianNew [TITLE]to create a new note. This command has one optional
argument: the title of the new note.:ObsidianQuickSwitchto quickly switch to (or open) another note in your
vault, searching by its name using ripgrep
https://github.com/BurntSushi/ripgrep with your preferred picker (see
|obsidian-plugin-dependencies| below).:ObsidianFollowLink [vsplit|hsplit]to follow a note reference under the
cursor, optionally opening it in a vertical or horizontal split.:ObsidianBacklinksfor getting a picker list of references to the current
buffer.:ObsidianTags [TAG ...]for getting a picker list of all occurrences of the
given tags.:ObsidianToday [OFFSET]to open/create a new daily note. This command also
takes an optional offset in days, e.g.Β use:ObsidianToday -1to go to
yesterdayβs note. Unlike:ObsidianYesterdayand:ObsidianTomorrowthis
command does not differentiate between weekdays and weekends.:ObsidianYesterdayto open/create the daily note for the previous working
day.:ObsidianTomorrowto open/create the daily note for the next working day.:ObsidianDailies [OFFSET ...]to open a picker list of daily notes. For
example,:ObsidianDailies -2 1to list daily notes from 2 days ago until
tomorrow.:ObsidianTemplate [NAME]to insert a template from the templates folder,
selecting from a list using your preferred picker. See
|obsidian-"using-templates"| for more information.:ObsidianSearch [QUERY]to search for (or create) notes in your vault using
ripgrepwith your preferred picker.:ObsidianLink [QUERY]to link an inline visual selection of text to a note.
This command has one optional argument: a query that will be used to resolve
the note by ID, path, or alias. If not given, the selected text will be used as
the query.:ObsidianLinkNew [TITLE]to create a new note and link it to an inline visual
selection of text. This command has one optional argument: the title of the new
note. If not given, the selected text will be used as the title.:ObsidianLinksto collect all links within the current buffer into a picker
window.:ObsidianExtractNote [TITLE]to extract the visually selected text into a new
note and link to it.:ObsidianWorkspace [NAME]to switch to another workspace.:ObsidianPasteImg [IMGNAME]to paste an image from the clipboard into the
note at the cursor position by saving it to the vault and adding a markdown
image link. You can configure the default folder to save images to with the
attachments.img_folderoption.:ObsidianRename [NEWNAME] [--dry-run]to rename the note of the current
buffer or reference under the cursor, updating all backlinks across the vault.
Since this command is still relatively new and could potentially write a lot of
changes to your vault, I highly recommend committing the current state of your
vault (if youβre using version control) before running it, or doing a dry-run
first by appending "βdry-run" to the command, e.g.Β:ObsidianRename new-id --dry-run.:ObsidianToggleCheckboxto cycle through checkbox options.:ObsidianNewFromTemplate [TITLE]to create a new note from a template in the
templates folder. Selecting from a list using your preferred picker. This
command has one optional argument: the title of the new note.:ObsidianTOCto load the table of contents of the current note into a picker
list.
DEMO obsidian-demo
https://github.com/epwalsh/obsidian.nvim/assets/8812459/2986e1d2-13e8-40e2-9c9e-75691a3b662e
==============================================================================
3. Setup obsidian-setup
SYSTEM REQUIREMENTS obsidian-system-requirements
- NeoVim >= 0.8.0 (this plugin uses
vim.fswhich was only added in 0.8). - If you want completion and search features (recommended) youβll need ripgrep https://github.com/BurntSushi/ripgrep to be installed and on your
$PATH.
See ripgrep#installation https://github.com/BurntSushi/ripgrep for install options.
Specific operating systems also require additional dependencies in order to use
all of obsidian.nvimβs functionality:
- Windows WSL users need
wsl-openhttps://gitlab.com/4U6U57/wsl-open for the:ObsidianOpencommand. - MacOS users need
pngpastehttps://github.com/jcsalterego/pngpaste (brew install pngpaste) for the:ObsidianPasteImgcommand. - Linux users need xclip (X11) or wl-clipboard (Wayland) for the
:ObsidianPasteImgcommand.
Search functionality (e.g.Β via the :ObsidianSearch and:ObsidianQuickSwitch commands) also requires a picker such telescope.nvim
https://github.com/nvim-telescope/telescope.nvim (see
|obsidian-plugin-dependencies| below).
INSTALL AND CONFIGURE obsidian-install-and-configure
To configure obsidian.nvim you just need to call require("obsidian").setup({ ... }) with the desired options. Here are some examples using different plugin
managers. The full set of |obsidian-plugin-dependencies| and
|obsidian-configuration-options| are listed below.
β οΈ WARNING: if you install from the latest release (recommended for
stability) instead of main, be aware that the README on main may reference
features that havenβt been released yet. For that reason I recommend viewing
the README on the tag for the latest release
https://github.com/epwalsh/obsidian.nvim/releases instead of main.
USING LAZY.NVIM ~
lua
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'." .. "/my-vault/.md"
-- -- E.g. "BufReadPre " .. vim.fn.expand "
-- -- refer to:h file-patternfor 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 π
},
}<
USING PACKER.NVIM ~
lua
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,
})<
PLUGIN DEPENDENCIES obsidian-plugin-dependencies
The only required plugin dependency is plenary.nvim
https://github.com/nvim-lua/plenary.nvim, but there are a number of optional
dependencies that enhance the obsidian.nvim experience.
Completion:
- [recommended] hrsh7th/nvim-cmp https://github.com/hrsh7th/nvim-cmp: for completion of note references.
Pickers:
- [recommended] nvim-telescope/telescope.nvim https://github.com/nvim-telescope/telescope.nvim: for search and quick-switch functionality.
- Mini.Pick https://github.com/echasnovski/mini.pick from the mini.nvim library: an alternative to telescope for search and quick-switch functionality.
- ibhagwan/fzf-lua https://github.com/ibhagwan/fzf-lua: another alternative to telescope for search and quick-switch functionality.
Syntax highlighting:
- [recommended] nvim-treesitter https://github.com/nvim-treesitter/nvim-treesitter: for base markdown syntax highlighting. See |obsidian-syntax-highlighting| for more details.
- preservim/vim-markdown https://github.com/preservim/vim-markdown: an alternative to nvim-treesitter for syntax highlighting (see |obsidian-syntax-highlighting| for more details), plus other cool features.
Miscellaneous:
- π pomo.nvim https://github.com/epwalsh/pomo.nvim: for running lightweight pomodoro https://en.wikipedia.org/wiki/Pomodoro_Technique timers.
If you choose to use any of these you should include them in the "dependencies"
or "requires" field of the obsidian.nvim plugin spec for your package manager.
CONFIGURATION OPTIONS obsidian-configuration-options
This is a complete list of all of the options that can be passed torequire("obsidian").setup(). The settings below are not necessarily the
defaults, but represent reasonable default settings. Please read each option
carefully and customize it to your needs:
lua
{
-- 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.obsidianfolder is located).
-- When obsidian.nvim is loaded by your plugin manager, it will automatically set
-- the workspace to the first workspace in the list whosepathis a parent of the
-- current markdown file being edited.
workspaces = {
{
name = "personal",
path = "/vaults/personal",/vaults/work",
},
{
name = "work",
path = "
-- 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,
},
}<
NOTES ON CONFIGURATION obsidian-notes-on-configuration
WORKSPACES ~
For most Obsidian users, each workspace you configure in your obsidian.nvim
config should correspond to a unique Obsidian vault, in which case the path
of each workspace should be set to the corresponding vault root path.
For example, suppose you have an Obsidian vault at ~/vaults/personal, then
the workspaces field in your config would look like this:
lua
config = {
workspaces = {
{
name = "personal",
path = "~/vaults/personal",
},
}
}
<
However obsidian.nvimβs concept of workspaces is a little more general than
that of vaults, since itβs also valid to configure a workspace that doesnβt
correspond to a vault, or to configure multiple workspaces for a single vault.
The latter case can be useful if you want to segment a single vault into
multiple directories with different settings applied to each directory. For
example:
lua
config = {
workspaces = {
{
name = "project-1",
path = "/vaults/personal/project-1",/vaults/personal/project-2",
--strict=truehere tells obsidian to use thepathas the workspace/vault root,
-- even though the actual Obsidian vault root may be~/vaults/personal/.
strict = true,
overrides = {
-- ...
},
},
{
name = "project-2",
path = "
strict = true,
overrides = {
-- ...
},
},
}
}
<
obsidian.nvim also supports "dynamic" workspaces. These are simply workspaces
where the path is set to a Lua function (that returns a path) instead of a
hard-coded path. This can be useful in several scenarios, such as when you want
a workspace whose path is always set to the parent directory of the current
buffer:
lua
config = {
workspaces = {
{
name = "buf-parent",
path = function()
return assert(vim.fs.dirname(vim.api.nvim_buf_get_name(0)))
end,
},
}
}
<
Dynamic workspaces are also useful when you want to use a subset of this
pluginβs functionality on markdown files outside of your "fixed" vaults. See
|obsidian-using-obsidian.nvim-outside-of-a-workspace-/-obsidian-vault|.
COMPLETION ~
obsidian.nvim will set itself up as an nvim-cmp source automatically when you
enter a markdown buffer within your vault directory, you do not need to
specify this plugin as a cmp source manually.
Note that in order to trigger completion for tags within YAML frontmatter you
still need to type the "#" at the start of the tag. obsidian.nvim will remove
the "#" when you hit enter on the tag completion item.
SYNTAX HIGHLIGHTING ~
If youβre using nvim-treesitter
https://github.com/nvim-treesitter/nvim-treesitter/blob/master/README.md
youβre configuration should include both "markdown" and "markdown_inline"
sources:
lua
require("nvim-treesitter.configs").setup({
ensure_installed = { "markdown", "markdown_inline", ... },
highlight = {
enable = true,
},
})
<
If you use vim-markdown youβll probably want to disable its frontmatter
syntax highlighting (vim.g.vim_markdown_frontmatter = 1) which Iβve found
doesnβt work very well.
CONCEALING CHARACTERS ~
If you wish to use the formatting concealment features, you will need to haveconceallevel set to a value that allows it (either 1 or 2), for example:set conceallevel=1 in viml or vim.opt.conceallevel = 1 in a lua config.
NOTE NAMING AND LOCATION ~
The notes_subdir and note_id_func options are not mutually exclusive. You
can use them both. For example, using a combination of both of the above
settings, a new note called "My new note" will assigned a path likenotes/1657296016-my-new-note.md.
GF PASSTHROUGH ~
If you want the gf passthrough functionality but youβve already overridden
the gf keybinding, just change your gf mapping definition to something like
this:
lua
vim.keymap.set("n", "gf", function()
if require("obsidian").util.cursor_on_markdown_link() then
return "ObsidianFollowLink "
else
return "gf"
end
end, { noremap = false, expr = true })
<
Then make sure to comment out the gf keybinding in your obsidian.nvim config:
lua
mappings = {
-- ["gf"] = ...
},
<
Or alternatively you could map obsidian.nvimβs follow functionality to a
different key:
lua
mappings = {
["fo"] = {
action = function()
return require("obsidian").util.gf_passthrough()
end,
opts = { noremap = false, expr = true, buffer = true },
},
},
<
USING TEMPLATES obsidian-using-templates
To insert a template in the current note, run the command :ObsidianTemplate.
This will open a list of available templates in your templates folder with your
preferred picker. Select a template and hit <CR> to insert. To create a new
note from a template, run the command :ObsidianNewFromTemplate. This will
prompt you for an optional path for the new note and will open a list of
available templates in your templates folder with your preferred picker. Select
a template and hit <CR> to create the new note with the selected template.
Substitutions for {{id}}, {{title}}, {{path}}, {{date}}, and {{time}}
are supported out-of-the-box. For example, with the following configuration
lua
{
-- other fields ...
templates = {
folder = "my-templates-folder",
date_format = "%Y-%m-%d-%a",
time_format = "%H:%M",
},
}<
and the file ~/my-vault/my-templates-folder/note template.md:
markdown
# {{title}}
Date created: {{date}}<
creating the note Configuring Neovim.md and executing :ObsidianTemplate
will insert
markdown
# Configuring Neovim
Date created: 2023-03-01-Wed<
above the cursor position.
You can also define custom template substitutions with the configuration fieldtemplates.substitutions. For example, to automatically substitute the
template variable {{yesterday}} when inserting a template, you could add this
to your config:
lua
{
-- other fields ...
templates = {
substitutions = {
yesterday = function()
return os.date("%Y-%m-%d", os.time() - 86400)
end
}
}
<
USAGE OUTSIDE OF A WORKSPACE OR VAULTobsidian-usage-outside-of-a-workspace-or-vault
Itβs possible to configure obsidian.nvim to work on individual markdown files
outside of a regular workspace / Obsidian vault by configuring a "dynamic"
workspace. To do so you just need to add a special workspace with a function
for the path field (instead of a string), which should return a parent
directory of the current buffer. This tells obsidian.nvim to use that directory
as the workspace path and root (vault root) when the buffer is not located
inside another fixed workspace.
For example, to extend the configuration above this way:
diff
{
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,
+ },
+ },
+ },
...
}
<
With this configuration, anytime you enter a markdown buffer outside of
"~/vaults/personal" (or whatever your configured fixed vaults are),
obsidian.nvim will switch to the dynamic workspace with the path / root set to
the parent directory of the buffer.
Please note that in order to avoid unexpected behavior (like a new directory
being created for notes_subdir) itβs important to carefully set the
workspace overrides options. And keep in mind that to reset a configuration
option to nil youβll have to use vim.NIL there instead of the builtin Luanil due to the way Lua tables work.
==============================================================================
4. Contributing obsidian-contributing
Please read the CONTRIBUTING
https://github.com/epwalsh/obsidian.nvim/blob/main/.github/CONTRIBUTING.md
guide before submitting a pull request.
And if youβre feeling especially generous I always appreciate some coffee
funds! β€οΈ
https://www.buymeacoffee.com/epwalsh
==============================================================================
5. Links obsidian-links
- See this screenshot: https://github.com/epwalsh/obsidian.nvim/assets/8812459/90d5f218-06cd-4ebb-b00b-b59c2f5c3cc1
- See this screenshot: https://github.com/epwalsh/obsidian.nvim/assets/8812459/e74f5267-21b5-49bc-a3bb-3b9db5fa6687
- 2024-01-31 14 22 52: https://github.com/epwalsh/obsidian.nvim/assets/8812459/2986e1d2-13e8-40e2-9c9e-75691a3b662e
- BuyMeACoffee: https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black
Generated by panvimdoc https://github.com/kdheepak/panvimdoc
vim:tw=78:ts=8:noet:ft=help:norl:
File: doc/obsidian_api.txt
obsidian-api
The Obsidian.nvim Lua API.
==============================================================================
Table of contents
obsidian.Client............................................|obsidian.Client|
obsidian.Note................................................|obsidian.Note|
obsidian.Workspace......................................|obsidian.Workspace|
obsidian.Path................................................|obsidian.Path|
*obsidian.SearchOpts*
`SearchOpts`Class ~
{obsidian.SearchOpts} : obsidian.ABC
Fields ~
{sort} (boolean|?)
{include_templates} (boolean|?)
{ignore_case} (boolean|?)
*obsidian.SearchOpts.from_tbl()*
`SearchOpts.from_tbl`({opts})Parameters ~
{opts} (obsidian.SearchOpts|table<string, any>)
Return ~
obsidian.SearchOpts
*obsidian.SearchOpts.default()*
`SearchOpts.default`()Return ~
obsidian.SearchOpts
*obsidian.Client*
`Client`The Obsidian client is the main API for programmatically interacting with obsidian.nvim's features
in Lua. To get the client instance, run:
local client = require("obsidian").get_client()
Class ~
{obsidian.Client} : obsidian.ABC
Fields ~
{current_workspace} obsidian.Workspace The current workspace.
{dir} obsidian.Path The root of the vault for the current workspace.
{opts} obsidian.config.ClientOpts The client config.
{buf_dir} obsidian.Path|? The parent directory of the current buffer.
{callback_manager} obsidian.CallbackManager
{log} obsidian.Logger
{_default_opts} obsidian.config.ClientOpts
{_quiet} (boolean)
*obsidian.Client.new()*
`Client.new`({opts})Create a new Obsidian client without additional setup.
This is mostly used for testing. In practice you usually want to obtain the existing
client through:
require("obsidian").get_client()
Parameters ~
{opts} obsidian.config.ClientOpts
Return ~
obsidian.Client
*obsidian.Client.set_workspace()*
`Client.set_workspace`({self}, {workspace}, {opts})Parameters ~
{workspace} obsidian.Workspace
{opts} { lock: (boolean|?) }|?
*obsidian.Client.opts_for_workspace()*
`Client.opts_for_workspace`({self}, {workspace})Get the normalize opts for a given workspace.
Parameters ~
{workspace} obsidian.Workspace|?
Return ~
obsidian.config.ClientOpts
*obsidian.Client.switch_workspace()*
`Client.switch_workspace`({self}, {workspace}, {opts})Switch to a different workspace.
Parameters ~
{workspace} (obsidian.Workspace|string) The workspace object or the name of an existing workspace.
{opts} { lock: (boolean|?) }|?
*obsidian.Client.path_is_note()*
`Client.path_is_note`({self}, {path}, {workspace})Check if a path represents a note in the workspace.
Parameters ~
{path} (string|obsidian.Path)
{workspace} obsidian.Workspace|?
Return ~(boolean)
*obsidian.Client.vault_root()*
`Client.vault_root`({self}, {workspace})Get the absolute path to the root of the Obsidian vault for the given workspace or the
current workspace.
Parameters ~
{workspace} obsidian.Workspace|?
Return ~
obsidian.Path
*obsidian.Client.vault_name()*
`Client.vault_name`({self})Get the name of the current vault.
Return ~(string)
*obsidian.Client.vault_relative_path()*
`Client.vault_relative_path`({self}, {path}, {opts})Make a path relative to the vault root, if possible.
Parameters ~
{path} (string|obsidian.Path)
{opts} { strict: (boolean|?) }|?
Return ~
obsidian.Path| (optional)
*obsidian.Client.templates_dir()*
`Client.templates_dir`({self}, {workspace})Get the templates folder.
Parameters ~
{workspace} obsidian.Workspace|?
Return ~
obsidian.Path| (optional)
*obsidian.Client.should_save_frontmatter()*
`Client.should_save_frontmatter`({self}, {note})Determines whether a note's frontmatter is managed by obsidian.nvim.
Parameters ~
{note} obsidian.Note
Return ~(boolean)
*obsidian.Client.command()*
`Client.command`({self}, {cmd_name}, {cmd_data})Run an obsidian command directly.
Usage ~client:command("ObsidianNew", { args = "Foo" })
Parameters ~
{cmd_name} (string) The name of the command.
{cmd_data} (table|?) The payload for the command.
*obsidian.Client.search_defaults()*
`Client.search_defaults`({self})Get the default search options.
Return ~
obsidian.SearchOpts
*obsidian.Client.find_notes()*
`Client.find_notes`({self}, {term}, {opts})Find notes matching the given term. Notes are searched based on ID, title, filename, and aliases.
Parameters ~
{term} (string) The term to search for
{opts} { search: obsidian.SearchOpts|?, notes: obsidian.note.LoadOpts|?, timeout: (integer|?) }|?
Return ~
obsidian.Note[]
*obsidian.Client.find_notes_async()*
`Client.find_notes_async`({self}, {term}, {callback}, {opts})An async version of find_notes() that runs the callback with an array of all matching notes.
Parameters ~
{term} (string) The term to search for
{callback} (fun(notes: obsidian.Note[]))
{opts} { search: obsidian.SearchOpts|?, notes: obsidian.note.LoadOpts|? }|?
*obsidian.Client.find_files()*
`Client.find_files`({self}, {term}, {opts})Find non-markdown files in the vault.
Parameters ~
{term} (string) The search term.
{opts} { search: obsidian.SearchOpts, timeout: (integer|?) }|?
Return ~
obsidian.Path[]
*obsidian.Client.find_files_async()*
`Client.find_files_async`({self}, {term}, {callback}, {opts})An async version of find_files.
Parameters ~
{term} (string) The search term.
{callback} (fun(paths: obsidian.Path[]))
{opts} { search: obsidian.SearchOpts }|?
*obsidian.Client.resolve_note()*
`Client.resolve_note`({self}, {query}, {opts})Resolve the query to a single note if possible, otherwise all close matches are returned.
The 'query' can be a path, filename, note ID, alias, title, etc.
Parameters ~
{query} (string)
{opts} { timeout: (integer|?,) notes: obsidian.note.LoadOpts|? }|?
Return ~
obsidian.Note (...)
*obsidian.Client.resolve_note_async()*
`Client.resolve_note_async`({self}, {query}, {callback}, {opts})An async version of resolve_note().
Parameters ~
{query} (string)
{callback} (fun(...: obsidian.Note))
{opts} { notes: obsidian.note.LoadOpts|? }|?
Return ~
obsidian.Note| (optional)
*obsidian.Client.resolve_note_async_with_picker_fallback()*Client.resolve_note_async_with_picker_fallback({self}, {query}, {callback}, {opts})
Same as resolve_note_async but opens a picker to choose a single note when
there are multiple matches.
Parameters ~
{query} (string)
{callback} (fun(obsidian.Note))
{opts} { notes: obsidian.note.LoadOpts|?, prompt_title: (string|?) }|?
Return ~
obsidian.Note| (optional)
Class ~
{obsidian.ResolveLinkResult}
Fields ~
{location} (string)
{name} (string)
{link_type} obsidian.search.RefTypes
{path} obsidian.Path|?
{note} obsidian.Note|?
{url} (string|?)
{line} (integer|?)
{col} (integer|?)
{anchor} obsidian.note.HeaderAnchor|?
{block} obsidian.note.Block|?
*obsidian.Client.resolve_link_async()*
`Client.resolve_link_async`({self}, {link}, {callback})Resolve a link. If the link argument is nil we attempt to resolve a link under the cursor.
Parameters ~
{link} (string|?)
{callback} (fun(...: obsidian.ResolveLinkResult))
*obsidian.Client.follow_link_async()*
`Client.follow_link_async`({self}, {link}, {opts})Follow a link. If the link argument is nil we attempt to follow a link under the cursor.
Parameters ~
{link} (string|?)
{opts} { open_strategy: obsidian.config.OpenStrategy|? }|?
*obsidian.Client.open_note()*
`Client.open_note`({self}, {note_or_path}, {opts})Open a note in a buffer.
Parameters ~
{note_or_path} (string|obsidian.Path|obsidian.Note)
{opts} { line: (integer|?,) col: integer|?, open_strategy: obsidian.config.OpenStrategy|?, sync: boolean|?, callback: fun(bufnr: integer)|? }|?
*obsidian.Client.current_note()*
`Client.current_note`({self}, {bufnr}, {opts})Get the current note from a buffer.
Parameters ~
{bufnr} (integer|?)
{opts} obsidian.note.LoadOpts|?
Return ~
obsidian.Note| (optional)
Class ~
{obsidian.TagLocation}
Fields ~
{tag} (string) The tag found.
{note} obsidian.Note The note instance where the tag was found.
{path} (string|obsidian.Path) The path to the note where the tag was found.
{line} (integer) The line number (1-indexed) where the tag was found.
{text} (string) The text (with whitespace stripped) of the line where the tag was found.
{tag_start} (integer|?) The index within 'text' where the tag starts.
{tag_end} (integer|?) The index within 'text' where the tag ends.
*obsidian.Client.find_tags()*
`Client.find_tags`({self}, {term}, {opts})Find all tags starting with the given search term(s).
Parameters ~
{term} (string|string[]) The search term.
{opts} { search: obsidian.SearchOpts|?, timeout: (integer|?) }|?
Return ~
obsidian.TagLocation[]
*obsidian.Client.find_tags_async()*
`Client.find_tags_async`({self}, {term}, {callback}, {opts})An async version of 'find_tags()'.
Parameters ~
{term} (string|string[]) The search term.
{callback} (fun(tags: obsidian.TagLocation[]))
{opts} { search: obsidian.SearchOpts }|?
Class ~
{obsidian.BacklinkMatches}
Fields ~
{note} obsidian.Note The note instance where the backlinks were found.
{path} (string|obsidian.Path) The path to the note where the backlinks were found.
{matches} obsidian.BacklinkMatch[] The backlinks within the note.
Class ~
{obsidian.BacklinkMatch}
Fields ~
{line} (integer) The line number (1-indexed) where the backlink was found.
{text} (string) The text of the line where the backlink was found.
*obsidian.Client.find_backlinks()*
`Client.find_backlinks`({self}, {note}, {opts})Find all backlinks to a note.
Parameters ~
{note} obsidian.Note The note to find backlinks for.
{opts} { search: obsidian.SearchOpts|?, timeout: (integer|?,) anchor: string|?, block: string|? }|?
Return ~
obsidian.BacklinkMatches[]
*obsidian.Client.find_backlinks_async()*
`Client.find_backlinks_async`({self}, {note}, {callback}, {opts})An async version of 'find_backlinks()'.
Parameters ~
{note} obsidian.Note The note to find backlinks for.
{callback} (fun(backlinks: obsidian.BacklinkMatches[]))
{opts} { search: obsidian.SearchOpts, anchor: (string|?,) block: string|? }|?
*obsidian.Client.list_tags()*
`Client.list_tags`({self}, {term}, {timeout})Gather a list of all tags in the vault. If 'term' is provided, only tags that partially match the search
term will be included.
Parameters ~
{term} (string|?) An optional search term to match tags
{timeout} (integer|?) Timeout in milliseconds
Return ~(string[])
*obsidian.Client.list_tags_async()*
`Client.list_tags_async`({self}, {term}, {callback})An async version of 'list_tags()'.
Parameters ~
{term} (string|?)
{callback} (fun(tags: string[]))
*obsidian.Client.apply_async()*
`Client.apply_async`({self}, {on_note}, {opts})Apply a function over all notes in the current vault.
Parameters ~
{on_note} (fun(note: obsidian.Note))
{opts} { on_done: (fun()|?,) timeout: integer|?, pattern: string|? }|?
Options:
on_done: A function to call when all notes have been processed.timeout: An optional timeout.pattern: A Lua search pattern. Defaults to ".*%.md".
*obsidian.Client.apply_async_raw()*
`Client.apply_async_raw`({self}, {on_path}, {opts})Like apply, but the callback takes a path instead of a note instance.
Parameters ~
{on_path} (fun(path: string))
{opts} { on_done: (fun()|?,) timeout: integer|?, pattern: string|? }|?
Options:
on_done: A function to call when all paths have been processed.timeout: An optional timeout.pattern: A Lua search pattern. Defaults to ".*%.md".
*obsidian.Client.new_note_id()*
`Client.new_note_id`({self}, {title})Generate a unique ID for a new note. This respects the user's note_id_func if configured,
otherwise falls back to generated a Zettelkasten style ID.
Parameters ~
{title} (string|?)
Return ~(string)
*obsidian.Client.new_note_path()*
`Client.new_note_path`({self}, {spec})Generate the file path for a new note given its ID, parent directory, and title.
This respects the user's note_path_func if configured, otherwise essentially falls back tospec.dir / (spec.id .. ".md").
Parameters ~
{spec} { id: (string,) dir: obsidian.Path, title: string|? }
Return ~
obsidian.Path
*obsidian.Client.parse_title_id_path()*
`Client.parse_title_id_path`({self}, {title}, {id}, {dir})Parse the title, ID, and path for a new note.
Parameters ~
{title} (string|?)
{id} (string|?)
{dir} (string|obsidian.Path|?)
Return ~(string|) (optional),string,obsidian.Path
*obsidian.Client.new_note()*
`Client.new_note`({self}, {title}, {id}, {dir}, {aliases})Create and save a new note.
Deprecated: prefer Client:create_note() instead.
Parameters ~
{title} (string|?) The title for the note.
{id} (string|?) An optional ID for the note. If not provided one will be generated.
{dir} (string|obsidian.Path|?) An optional directory to place the note. If this is a relative path it will be interpreted relative the workspace / vault root.
{aliases} (string[]|?) Additional aliases to assign to the note.
Return ~
obsidian.Note
Class ~
{obsidian.CreateNoteOpts}
Fields ~
{title} (string|?)
{id} (string|?)
{dir} (string|obsidian.Path|?)
{aliases} (string[]|?)
{tags} (string[]|?)
{no_write} (boolean|?)
{template} (string|?)
*obsidian.Client.create_note()*
`Client.create_note`({self}, {opts})Create a new note with the following options.
Parameters ~
{opts} obsidian.CreateNoteOpts|? Options.
Options:
title: A title to assign the note.id: An ID to assign the note. If not specified one will be generated.dir: An optional directory to place the note in. Relative paths will be interpreted
relative to the workspace / vault root. If the directory doesn't exist it will be created,
regardless of the value of theno_writeoption.aliases: Additional aliases to assign to the note.tags: Additional tags to assign to the note.no_write: Don't write the note to disk.template: The name of a template to apply when writing the note to disk.
Return ~
obsidian.Note
*obsidian.Client.write_note()*
`Client.write_note`({self}, {note}, {opts})Write the note to disk.
Parameters ~
{note} obsidian.Note
{opts} { path: (string|obsidian.Path,) template: string|?, update_content: (fun(lines: string[]): string[])|? }|? Options.
Options:
path: Override the path to write to.template: The name of a template to use if the note file doesn't already exist.update_content: A function to update the contents of the note. This takes a list of lines
representing the text to be written excluding frontmatter, and returns the lines that will
actually be written (again excluding frontmatter).
Return ~
obsidian.Note
*obsidian.Client.write_note_to_buffer()*
`Client.write_note_to_buffer`({self}, {note}, {opts})Write the note to a buffer.
Parameters ~
{note} obsidian.Note
{opts} { bufnr: (integer|?,) template: string|? }|? Options.
Options:
bufnr: Override the buffer to write to. Defaults to current buffer.template: The name of a template to use if the buffer is empty.
Return ~(boolean) updated If the buffer was updated.
*obsidian.Client.update_frontmatter()*
`Client.update_frontmatter`({self}, {note}, {bufnr})Update the frontmatter in a buffer for the note.
Parameters ~
{note} obsidian.Note
{bufnr} (integer|?)
Return ~(boolean) updated If the the frontmatter was updated.
*obsidian.Client.daily_note_path()*
`Client.daily_note_path`({self}, {datetime})Get the path to a daily note.
Parameters ~
{datetime} (integer|?)
Return ~
obsidian.Path, (string) (Path, ID) The path and ID of the note.
*obsidian.Client.today()*
`Client.today`({self})Open (or create) the daily note for today.
Return ~
obsidian.Note
*obsidian.Client.yesterday()*
`Client.yesterday`({self})Open (or create) the daily note from the last weekday.
Return ~
obsidian.Note
*obsidian.Client.tomorrow()*
`Client.tomorrow`({self})Open (or create) the daily note for the next weekday.
Return ~
obsidian.Note
*obsidian.Client.daily()*
`Client.daily`({self}, {offset_days}, {opts})Open (or create) the daily note for today + offset_days.
Parameters ~
{offset_days} (integer|?)
{opts} { no_write: (boolean|?,) load: obsidian.note.LoadOpts|? }|?
Return ~
obsidian.Note
*obsidian.Client.update_ui()*
`Client.update_ui`({self}, {bufnr})Manually update extmarks in a buffer.
Parameters ~
{bufnr} (integer|?)
*obsidian.Client.format_link()*
`Client.format_link`({self}, {note}, {opts})Create a formatted markdown / wiki link for a note.
Parameters ~
{note} (obsidian.Note|obsidian.Path|string) The note/path to link to.
{opts} { label: (string|?,) link_style: obsidian.config.LinkStyle|?, id: string|integer|?, anchor: obsidian.note.HeaderAnchor|?, block: obsidian.note.Block|? }|? Options.
Return ~(string)
*obsidian.Client.picker()*
`Client.picker`({self}, {picker_name})Get the Picker.
Parameters ~
{picker_name} obsidian.config.Picker|?
Return ~
obsidian.Picker| (optional)
Class ~
{obsidian.note.HeaderAnchor}
Fields ~
{anchor} (string)
{header} (string)
{level} (integer)
{line} (integer)
{parent} obsidian.note.HeaderAnchor|?
Class ~
{obsidian.note.Block}
Fields ~
{id} (string)
{line} (integer)
{block} (string)
*obsidian.Note*
`Note`A class that represents a note within a vault.
Class ~
{obsidian.Note} : obsidian.ABC
Fields ~
{id} (string|integer)
{aliases} (string[])
{title} (string|?)
{tags} (string[])
{path} obsidian.Path|?
{metadata} (table|?)
{has_frontmatter} (boolean|?)
{frontmatter_end_line} (integer|?)
{contents} (string[]|?)
{anchor_links} (table<string, obsidian.note.HeaderAnchor>|?)
{blocks} (table<string, obsidian.note.Block>?)
{alt_alias} (string|?)
{bufnr} (integer|?)
*obsidian.Note.new()*
`Note.new`({id}, {aliases}, {tags}, {path})Create new note object.
Keep in mind that you have to call note:save(...) to create/update the note on disk.
Parameters ~
{id} (string|number)
{aliases} (string[])
{tags} (string[])
{path} (string|obsidian.Path|?)
Return ~
obsidian.Note
*obsidian.Note.display_info()*
`Note.display_info`({self}, {opts})Get markdown display info about the note.
Parameters ~
{opts} { label: (string|?,) anchor: obsidian.note.HeaderAnchor|?, block: obsidian.note.Block|? }|?
Return ~(string)
*obsidian.Note.exists()*
`Note.exists`({self})Check if the note exists on the file system.
Return ~(boolean)
*obsidian.Note.fname()*
`Note.fname`({self})Get the filename associated with the note.
Return ~(string|) (optional)
*obsidian.Note.reference_ids()*
`Note.reference_ids`({self}, {opts})Get a list of all of the different string that can identify this note via references,
including the ID, aliases, and filename.
Parameters ~
{opts} { lowercase: (boolean|?) }|?
Return ~(string[])
*obsidian.Note.has_alias()*
`Note.has_alias`({self}, {alias})Check if a note has a given alias.
Parameters ~
{alias} (string)
Return ~(boolean)
*obsidian.Note.has_tag()*
`Note.has_tag`({self}, {tag})Check if a note has a given tag.
Parameters ~
{tag} (string)
Return ~(boolean)
*obsidian.Note.add_alias()*
`Note.add_alias`({self}, {alias})Add an alias to the note.
Parameters ~
{alias} (string)
Return ~(boolean) added True if the alias was added, false if it was already present.
*obsidian.Note.add_tag()*
`Note.add_tag`({self}, {tag})Add a tag to the note.
Parameters ~
{tag} (string)
Return ~(boolean) added True if the tag was added, false if it was already present.
*obsidian.Note.add_field()*
`Note.add_field`({self}, {key}, {value})Add or update a field in the frontmatter.
Parameters ~
{key} (string)
{value} (any)
*obsidian.Note.get_field()*
`Note.get_field`({self}, {key})Get a field in the frontmatter.
Parameters ~
{key} (string)
Return ~(any) result
Class ~
{obsidian.note.LoadOpts}
Fields ~
{max_lines} (integer|?)
{load_contents} (boolean|?)
{collect_anchor_links} (boolean|?)
{collect_blocks} (boolean|?)
*obsidian.Note.from_file()*
`Note.from_file`({path}, {opts})Initialize a note from a file.
Parameters ~
{path} (string|obsidian.Path)
{opts} obsidian.note.LoadOpts|?
Return ~
obsidian.Note
*obsidian.Note.from_file_async()*
`Note.from_file_async`({path}, {opts})An async version of .from_file(), i.e. it needs to be called in an async context.
Parameters ~
{path} (string|obsidian.Path)
{opts} obsidian.note.LoadOpts|?
Return ~
obsidian.Note
*obsidian.Note.from_file_with_contents_async()*
`Note.from_file_with_contents_async`({path}, {opts})Like .from_file_async() but also returns the contents of the file as a list of lines.
Parameters ~
{path} (string|obsidian.Path)
{opts} obsidian.note.LoadOpts|?
Return ~(obsidian.Note,string[])
*obsidian.Note.from_buffer()*
`Note.from_buffer`({bufnr}, {opts})Initialize a note from a buffer.
Parameters ~
{bufnr} (integer|?)
{opts} obsidian.note.LoadOpts|?
Return ~
obsidian.Note
*obsidian.Note.display_name()*
`Note.display_name`({self})Get the display name for note.
Return ~(string)
*obsidian.Note.from_lines()*
`Note.from_lines`({lines}, {path}, {opts})Initialize a note from an iterator of lines.
Parameters ~
{lines} (fun(): string|?)
{path} (string|obsidian.Path)
{opts} obsidian.note.LoadOpts|?
Return ~
obsidian.Note
*obsidian.Note.frontmatter()*
`Note.frontmatter`({self})Get the frontmatter table to save.
Return ~(table)
*obsidian.Note.frontmatter_lines()*
`Note.frontmatter_lines`({self}, {eol}, {frontmatter})Get frontmatter lines that can be written to a buffer.
Parameters ~
{eol} (boolean|?)
{frontmatter} (table|?)
Return ~(string[])
*obsidian.Note.save()*
`Note.save`({self}, {opts})Save the note to a file.
In general this only updates the frontmatter and header, leaving the rest of the contents unchanged
unless you use the update_content() callback.
Parameters ~
{opts} { path: (string|obsidian.Path|?,) insert_frontmatter: boolean|?, frontmatter: table|?, update_content: (fun(lines: string[]): string[])|? }|? Options.
Options:
path: Specify a path to save to. Defaults toself.path.insert_frontmatter: Whether to insert/update frontmatter. Defaults totrue.frontmatter: Override the frontmatter. Defaults to the result ofself:frontmatter().update_content: A function to update the contents of the note. This takes a list of lines
representing the text to be written excluding frontmatter, and returns the lines that will
actually be written (again excluding frontmatter).
*obsidian.Note.save_to_buffer()*
`Note.save_to_buffer`({self}, {opts})Save frontmatter to the given buffer.
Parameters ~
{opts} { bufnr: (integer|?,) insert_frontmatter: boolean|?, frontmatter: table|? }|? Options.
Return ~(boolean) updated True if the buffer lines were updated, false otherwise.
*obsidian.Note.resolve_anchor_link()*
`Note.resolve_anchor_link`({self}, {anchor_link})Try to resolve an anchor link to a line number in the note's file.
Parameters ~
{anchor_link} (string)
Return ~
obsidian.note.HeaderAnchor| (optional)
*obsidian.Note.resolve_block()*
`Note.resolve_block`({self}, {block_id})Try to resolve a block identifier.
Parameters ~
{block_id} (string)
Return ~
obsidian.note.Block| (optional)
Class ~
{obsidian.workspace.WorkspaceSpec}
Fields ~
{path} (string|obsidian.Path|(fun():) string|obsidian.Path)
{name} (string|?)
{strict} (boolean|?) If true, the workspace root will be fixed to 'path' instead of the vault root (if different).
{overrides} (table|obsidian.config.ClientOpts|?)
Class ~
{obsidian.workspace.WorkspaceOpts}
Fields ~
{name} (string|?)
{strict} (boolean|?) If true, the workspace root will be fixed to 'path' instead of the vault root (if different).
{overrides} (table|obsidian.config.ClientOpts|?)
*obsidian.Workspace*
`Workspace`Each workspace represents a working directory (usually an Obsidian vault) along with
a set of configuration options specific to the workspace.
Workspaces are a little more general than Obsidian vaults as you can have a workspace
outside of a vault or as a subdirectory of a vault.
Class ~
{obsidian.Workspace} : obsidian.ABC
Fields ~
{name} (string) An arbitrary name for the workspace.
{path} obsidian.Path The normalized path to the workspace.
{root} obsidian.Path The normalized path to the vault root of the workspace. This usually matches 'path'.
{overrides} (table|obsidian.config.ClientOpts|?)
{locked} (boolean|?)
*obsidian.find_vault_root()*
`find_vault_root`({base_dir})Find the vault root from a given directory.
This will traverse the directory tree upwards until a '.obsidian/' folder is found to
indicate the root of a vault, otherwise the given directory is used as-is.
Parameters ~
{base_dir} (string|obsidian.Path)
Return ~
obsidian.Path| (optional)
*obsidian.Workspace.new()*
`Workspace.new`({path}, {opts})Create a new 'Workspace' object. This assumes the workspace already exists on the filesystem.
Parameters ~
{path} (string|obsidian.Path) Workspace path.
{opts} obsidian.workspace.WorkspaceOpts|?
Return ~
obsidian.Workspace
*obsidian.Workspace.new_from_spec()*
`Workspace.new_from_spec`({spec})Initialize a new 'Workspace' object from a workspace spec.
Parameters ~
{spec} obsidian.workspace.WorkspaceSpec
Return ~
obsidian.Workspace
*obsidian.Workspace.new_from_cwd()*
`Workspace.new_from_cwd`({opts})Initialize a 'Workspace' object from the current working directory.
Parameters ~
{opts} obsidian.workspace.WorkspaceOpts|?
Return ~
obsidian.Workspace
*obsidian.Workspace.new_from_buf()*
`Workspace.new_from_buf`({bufnr}, {opts})Initialize a 'Workspace' object from the parent directory of the current buffer.
Parameters ~
{bufnr} (integer|?)
{opts} obsidian.workspace.WorkspaceOpts|?
Return ~
obsidian.Workspace
*obsidian.Workspace.lock()*
`Workspace.lock`({self})Lock the workspace.
*obsidian.Workspace._unlock()*
`Workspace._unlock`({self})Unlock the workspace.
*obsidian.Workspace.get_workspace_for_dir()*
`Workspace.get_workspace_for_dir`({cur_dir}, {workspaces})Get the workspace corresponding to the directory (or a parent of), if there
is one.
Parameters ~
{cur_dir} (string|obsidian.Path)
{workspaces} obsidian.workspace.WorkspaceSpec[]
Return ~
obsidian.Workspace| (optional)
*obsidian.Workspace.get_workspace_for_cwd()*
`Workspace.get_workspace_for_cwd`({workspaces})Get the workspace corresponding to the current working directory (or a parent of), if there
is one.
Parameters ~
{workspaces} obsidian.workspace.WorkspaceSpec[]
Return ~
obsidian.Workspace| (optional)
*obsidian.Workspace.get_default_workspace()*
`Workspace.get_default_workspace`({workspaces})Returns the default workspace.
Parameters ~
{workspaces} obsidian.workspace.WorkspaceSpec[]
Return ~(obsidian.Workspace|nil)
*obsidian.Workspace.get_from_opts()*
`Workspace.get_from_opts`({opts})Resolves current workspace from the client config.
Parameters ~
{opts} obsidian.config.ClientOpts
Return ~
obsidian.Workspace| (optional)
*obsidian.cached_get()*
`cached_get`({path}, {k}, {factory})Parameters ~
{path} (table)
{k} (string)
{factory} (fun(obsidian.Path): any)
*obsidian.Path*
`Path`A Path class that provides a subset of the functionality of the Python pathlib library while
staying true to its API. It improves on a number of bugs in plenary.path.
Class ~
{obsidian.Path} : obsidian.ABC
Fields ~
{filename} (string) The underlying filename as a string.
{name} (string|?) The final path component, if any.
{suffix} (string|?) The final extension of the path, if any.
{suffixes} (string[]) A list of all of the path's extensions.
{stem} (string|?) The final path component, without its suffix.
*obsidian.Path.is_path_obj()*
`Path.is_path_obj`({path})Check if an object is an obsidian.Path object.
Parameters ~
{path} (any)
Return ~(boolean)
Constructors.
*obsidian.Path.new()*
`Path.new`({...})Create a new path from a string.
Parameters ~
{...} (string|obsidian.Path)
Return ~
obsidian.Path
*obsidian.Path.temp()*
`Path.temp`({opts})Get a temporary path with a unique name.
Parameters ~
{opts} { suffix: (string|?) }|?
Return ~
obsidian.Path
*obsidian.Path.cwd()*
`Path.cwd`()Get a path corresponding to the current working directory as given by vim.loop.cwd().
Return ~
obsidian.Path
*obsidian.Path.buffer()*
`Path.buffer`({bufnr})Get a path corresponding to a buffer.
Parameters ~
{bufnr} (integer|?) The buffer number or 0 / nil for the current buffer.
Return ~
obsidian.Path
*obsidian.Path.buf_dir()*
`Path.buf_dir`({bufnr})Get a path corresponding to the parent of a buffer.
Parameters ~
{bufnr} (integer|?) The buffer number or 0 / nil for the current buffer.
Return ~
obsidian.Path
Pure path methods.
*obsidian.Path.with_suffix()*
`Path.with_suffix`({self}, {suffix})Return a new path with the suffix changed.
Parameters ~
{suffix} (string)
Return ~
obsidian.Path
*obsidian.Path.is_absolute()*
`Path.is_absolute`({self})Returns true if the path is already in absolute form.
Return ~(boolean)
*obsidian.Path.joinpath()*
`Path.joinpath`({self}, {...})Parameters ~
{...} (obsidian.Path|string)
Return ~
obsidian.Path
*obsidian.Path.relative_to()*
`Path.relative_to`({self}, {other})Try to resolve a version of the path relative to the other.
An error is raised when it's not possible.
Parameters ~
{other} (obsidian.Path|string)
Return ~
obsidian.Path
*obsidian.Path.parent()*
`Path.parent`({self})The logical parent of the path.
Return ~
obsidian.Path| (optional)
*obsidian.Path.parents()*
`Path.parents`({self})Get a list of the parent directories.
Return ~
obsidian.Path[]
*obsidian.Path.is_parent_of()*
`Path.is_parent_of`({self}, {other})Check if the path is a parent of other. This is a pure path method, so it only checks by
comparing strings. Therefore in practice you probably want to :resolve() each path before
using this.
Parameters ~
{other} (obsidian.Path|string)
Return ~(boolean)
Concrete path methods.
*obsidian.Path.resolve()*
`Path.resolve`({self}, {opts})Make the path absolute, resolving any symlinks.
If strict is true and the path doesn't exist, an error is raised.
Parameters ~
{opts} { strict: (boolean) }|?
Return ~
obsidian.Path
*obsidian.Path.stat()*
`Path.stat`({self})Get OS stat results.
Return ~(table|) (optional)
*obsidian.Path.exists()*
`Path.exists`({self})Check if the path points to an existing file or directory.
Return ~(boolean)
*obsidian.Path.is_file()*
`Path.is_file`({self})Check if the path points to an existing file.
Return ~(boolean)
*obsidian.Path.is_dir()*
`Path.is_dir`({self})Check if the path points to an existing directory.
Return ~(boolean)
*obsidian.Path.mkdir()*
`Path.mkdir`({self}, {opts})Create a new directory at the given path.
Parameters ~
{opts} { mode: (integer|?,) parents: boolean|?, exist_ok: boolean|? }|?
*obsidian.Path.rmdir()*
`Path.rmdir`({self})Remove the corresponding directory. This directory must be empty.
*obsidian.Path.rmtree()*
`Path.rmtree`({self})Recursively remove an entire directory and its contents.
*obsidian.Path.touch()*
`Path.touch`({self}, {opts})Create a file at this given path.
Parameters ~
{opts} { mode: (integer|?,) exist_ok: boolean|? }|?
*obsidian.Path.rename()*
`Path.rename`({self}, {target})Rename this file or directory to the given target.
Parameters ~
{target} (obsidian.Path|string)
Return ~
obsidian.Path
*obsidian.Path.unlink()*
`Path.unlink`({self}, {opts})Remove the file.
Parameters ~
{opts} { missing_ok: (boolean|?) }|?
vim:tw=78:ts=8:noet:ft=help:norl: