mirror of
https://github.com/nix-community/nixvim.git
synced 2025-06-21 08:35:43 +02:00
plugins/obsidian: switch to mkNeovimPlugin
This commit is contained in:
parent
becfe75a67
commit
8226d825de
5 changed files with 1002 additions and 806 deletions
|
@ -159,7 +159,7 @@
|
||||||
./utils/nvim-colorizer.nix
|
./utils/nvim-colorizer.nix
|
||||||
./utils/nvim-osc52.nix
|
./utils/nvim-osc52.nix
|
||||||
./utils/nvim-ufo.nix
|
./utils/nvim-ufo.nix
|
||||||
./utils/obsidian.nix
|
./utils/obsidian
|
||||||
./utils/oil.nix
|
./utils/oil.nix
|
||||||
./utils/ollama.nix
|
./utils/ollama.nix
|
||||||
./utils/persistence.nix
|
./utils/persistence.nix
|
||||||
|
|
|
@ -1,617 +0,0 @@
|
||||||
{
|
|
||||||
lib,
|
|
||||||
helpers,
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.plugins.obsidian;
|
|
||||||
|
|
||||||
configOptions = {
|
|
||||||
logLevel = helpers.defaultNullOpts.mkLogLevel "info" ''
|
|
||||||
Set the log level for obsidian.nvim.
|
|
||||||
'';
|
|
||||||
|
|
||||||
notesSubdir = helpers.mkNullOrStr ''
|
|
||||||
If you keep notes in a specific subdirectory of your vault.
|
|
||||||
'';
|
|
||||||
|
|
||||||
templates = {
|
|
||||||
subdir = helpers.mkNullOrStr ''
|
|
||||||
The name of the directory where templates are stored.
|
|
||||||
|
|
||||||
Example: "templates"
|
|
||||||
'';
|
|
||||||
|
|
||||||
dateFormat = helpers.mkNullOrStr ''
|
|
||||||
Which date format to use.
|
|
||||||
|
|
||||||
Example: "%Y-%m-%d"
|
|
||||||
'';
|
|
||||||
|
|
||||||
timeFormat = helpers.mkNullOrStr ''
|
|
||||||
Which time format to use.
|
|
||||||
|
|
||||||
Example: "%H:%M"
|
|
||||||
'';
|
|
||||||
|
|
||||||
substitutions =
|
|
||||||
helpers.defaultNullOpts.mkNullable
|
|
||||||
(with helpers.nixvimTypes; attrsOf (either str rawLua))
|
|
||||||
"{}"
|
|
||||||
"A map for custom variables, the key should be the variable and the value a function.";
|
|
||||||
};
|
|
||||||
|
|
||||||
noteIdFunc = helpers.mkNullOrLuaFn ''
|
|
||||||
Customize how names/IDs for new notes are created.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```lua
|
|
||||||
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
|
|
||||||
```
|
|
||||||
'';
|
|
||||||
|
|
||||||
followUrlFunc = helpers.mkNullOrLuaFn ''
|
|
||||||
By default when you use `:ObsidianFollowLink` on a link to an external URL it will be
|
|
||||||
ignored but you can customize this behavior here.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```lua
|
|
||||||
function(url)
|
|
||||||
-- Open the URL in the default web browser.
|
|
||||||
vim.fn.jobstart({"open", url}) -- Mac OS
|
|
||||||
-- vim.fn.jobstart({"xdg-open", url}) -- linux
|
|
||||||
end
|
|
||||||
```
|
|
||||||
'';
|
|
||||||
|
|
||||||
noteFrontmatterFunc = helpers.mkNullOrLuaFn ''
|
|
||||||
You can customize the frontmatter data.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```lua
|
|
||||||
function(note)
|
|
||||||
-- This is equivalent to the default frontmatter function.
|
|
||||||
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
|
|
||||||
```
|
|
||||||
'';
|
|
||||||
|
|
||||||
disableFrontmatter = helpers.mkNullOrStrLuaFnOr types.bool ''
|
|
||||||
Boolean or a function that takes a filename and returns a boolean.
|
|
||||||
`true` indicates that you don't want obsidian.nvim to manage frontmatter.
|
|
||||||
|
|
||||||
Default: `false`
|
|
||||||
'';
|
|
||||||
|
|
||||||
backlinks = {
|
|
||||||
height = helpers.defaultNullOpts.mkUnsignedInt 10 ''
|
|
||||||
The default height of the backlinks pane.
|
|
||||||
'';
|
|
||||||
|
|
||||||
wrap = helpers.defaultNullOpts.mkBool true ''
|
|
||||||
Whether or not to wrap lines.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
completion = {
|
|
||||||
nvimCmp = helpers.mkNullOrOption types.bool ''
|
|
||||||
Set to false to disable completion.
|
|
||||||
|
|
||||||
Default: `true` if `cmp` is enabled.
|
|
||||||
'';
|
|
||||||
|
|
||||||
minChars = helpers.defaultNullOpts.mkUnsignedInt 2 ''
|
|
||||||
Trigger completion at this many chars.
|
|
||||||
'';
|
|
||||||
|
|
||||||
newNotesLocation = helpers.defaultNullOpts.mkEnumFirstDefault ["current_dir" "notes_subdir"] ''
|
|
||||||
Where to put new notes created from completion.
|
|
||||||
|
|
||||||
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.
|
|
||||||
'';
|
|
||||||
|
|
||||||
prependNoteId = helpers.defaultNullOpts.mkBool true ''
|
|
||||||
Whether to add the note ID during completion.
|
|
||||||
|
|
||||||
E.g. "[[Foo" completes to "[[foo|Foo]]" assuming "foo" is the ID of the note.
|
|
||||||
Mutually exclusive with 'prependNotePath' and 'usePathOnly'.
|
|
||||||
'';
|
|
||||||
|
|
||||||
prependNotePath = helpers.defaultNullOpts.mkBool false ''
|
|
||||||
Whether to add the note path during completion.
|
|
||||||
|
|
||||||
E.g. "[[Foo" completes to "[[notes/foo|Foo]]" assuming "notes/foo.md" is the path of the note.
|
|
||||||
Mutually exclusive with 'prependNoteId' and 'usePathOnly'.
|
|
||||||
'';
|
|
||||||
|
|
||||||
usePathOnly = helpers.defaultNullOpts.mkBool false ''
|
|
||||||
Whether to only use paths during completion.
|
|
||||||
|
|
||||||
E.g. "[[Foo" completes to "[[notes/foo]]" assuming "notes/foo.md" is the path of the note.
|
|
||||||
Mutually exclusive with 'prependNoteId' and 'prependNotePath'.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
mappings =
|
|
||||||
helpers.defaultNullOpts.mkNullable
|
|
||||||
(
|
|
||||||
with types;
|
|
||||||
attrsOf (submodule {
|
|
||||||
options = {
|
|
||||||
action = mkOption {
|
|
||||||
type = helpers.nixvimTypes.strLua;
|
|
||||||
description = "The lua code for this keymap action.";
|
|
||||||
apply = helpers.mkRaw;
|
|
||||||
};
|
|
||||||
opts =
|
|
||||||
helpers.keymaps.mapConfigOptions
|
|
||||||
// {
|
|
||||||
buffer = helpers.defaultNullOpts.mkBool false ''
|
|
||||||
If true, the mapping will be effective in the current buffer only.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
''
|
|
||||||
{
|
|
||||||
gf = {
|
|
||||||
action = "require('obsidian').util.gf_passthrough";
|
|
||||||
opts = {
|
|
||||||
noremap = false;
|
|
||||||
expr = true;
|
|
||||||
buffer = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
"<leader>ch" = {
|
|
||||||
action = "require('obsidian').util.toggle_checkbox";
|
|
||||||
opts.buffer = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
''
|
|
||||||
''
|
|
||||||
Configure key mappings.
|
|
||||||
'';
|
|
||||||
|
|
||||||
dailyNotes = {
|
|
||||||
folder = helpers.mkNullOrStr ''
|
|
||||||
Optional, if you keep daily notes in a separate directory.
|
|
||||||
'';
|
|
||||||
|
|
||||||
dateFormat = helpers.mkNullOrStr ''
|
|
||||||
Optional, if you want to change the date format for the ID of daily notes.
|
|
||||||
|
|
||||||
Example: "%Y-%m-%d"
|
|
||||||
'';
|
|
||||||
|
|
||||||
aliasFormat = helpers.mkNullOrStr ''
|
|
||||||
Optional, if you want to change the date format of the default alias of daily notes.
|
|
||||||
|
|
||||||
Example: "%B %-d, %Y"
|
|
||||||
'';
|
|
||||||
|
|
||||||
template = helpers.mkNullOrStr ''
|
|
||||||
Optional, if you want to automatically insert a template from your template directory like
|
|
||||||
'daily.md'.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
useAdvancedUri = helpers.mkNullOrOption types.bool ''
|
|
||||||
Set to true if you use the Obsidian Advanced URI plugin.
|
|
||||||
https://github.com/Vinzent03/obsidian-advanced-uri
|
|
||||||
'';
|
|
||||||
|
|
||||||
openAppForeground = helpers.defaultNullOpts.mkBool false ''
|
|
||||||
Set to true to force `:ObsidianOpen` to bring the app to the foreground.
|
|
||||||
'';
|
|
||||||
|
|
||||||
finder = helpers.mkNullOrStr ''
|
|
||||||
By default commands like `:ObsidianSearch` will attempt to use `telescope.nvim`, `fzf-lua`,
|
|
||||||
`fzf.vim`, or `mini.pick` (in that order), and use the first one they find.
|
|
||||||
You can set this option to tell `obsidian.nvim` to always use this finder.
|
|
||||||
'';
|
|
||||||
|
|
||||||
sortBy = helpers.defaultNullOpts.mkEnum ["path" "modified" "accessed" "created"] "modified" ''
|
|
||||||
Sort search results by "path", "modified", "accessed", or "created".
|
|
||||||
The recommend value is "modified" and `true` for `sortReversed`, which means, for example,
|
|
||||||
that `:ObsidianQuickSwitch` will show the notes sorted by latest modified time.
|
|
||||||
'';
|
|
||||||
|
|
||||||
sortReversed = helpers.defaultNullOpts.mkBool true ''
|
|
||||||
Whether search results should be reversed.
|
|
||||||
'';
|
|
||||||
|
|
||||||
openNotesIn = helpers.defaultNullOpts.mkEnumFirstDefault ["current" "vsplit" "hsplit"] ''
|
|
||||||
Determines how certain commands open notes.
|
|
||||||
|
|
||||||
The valid options are:
|
|
||||||
- "current" (the default) - to always open in the current window
|
|
||||||
- "vsplit" - to open in a vertical split if there's not already a vertical split
|
|
||||||
- "hsplit" - to open in a horizontal split if there's not already a horizontal split
|
|
||||||
'';
|
|
||||||
|
|
||||||
ui = {
|
|
||||||
enable = helpers.defaultNullOpts.mkBool true ''
|
|
||||||
Set to false to disable all additional syntax features.
|
|
||||||
'';
|
|
||||||
|
|
||||||
updateDebounce = helpers.defaultNullOpts.mkUnsignedInt 200 ''
|
|
||||||
Update delay after a text change (in milliseconds).
|
|
||||||
'';
|
|
||||||
|
|
||||||
checkboxes =
|
|
||||||
helpers.defaultNullOpts.mkNullable
|
|
||||||
(
|
|
||||||
with types;
|
|
||||||
attrsOf (
|
|
||||||
submodule {
|
|
||||||
options = {
|
|
||||||
char = mkOption {
|
|
||||||
type = with helpers.nixvimTypes; maybeRaw str;
|
|
||||||
description = "The character to use for this checkbox.";
|
|
||||||
};
|
|
||||||
|
|
||||||
hlGroup = mkOption {
|
|
||||||
type = with helpers.nixvimTypes; maybeRaw str;
|
|
||||||
description = "The name of the highlight group to use for this checkbox.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
''
|
|
||||||
{
|
|
||||||
" " = {
|
|
||||||
char = "";
|
|
||||||
hlGroup = "ObsidianTodo";
|
|
||||||
};
|
|
||||||
"x" = {
|
|
||||||
char = "";
|
|
||||||
hlGroup = "ObsidianDone";
|
|
||||||
};
|
|
||||||
">" = {
|
|
||||||
char = "";
|
|
||||||
hlGroup = "ObsidianRightArrow";
|
|
||||||
};
|
|
||||||
"~" = {
|
|
||||||
char = "";
|
|
||||||
hlGroup = "ObsidianTilde";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
''
|
|
||||||
''
|
|
||||||
Define how various check-boxes are displayed.
|
|
||||||
You can also add more custom ones...
|
|
||||||
|
|
||||||
NOTE: the 'char' value has to be a single character, and the highlight groups are defined
|
|
||||||
in the `ui.hlGroups` option.
|
|
||||||
'';
|
|
||||||
|
|
||||||
externalLinkIcon = {
|
|
||||||
char = helpers.defaultNullOpts.mkStr "" ''
|
|
||||||
Which character to use for the external link icon.
|
|
||||||
'';
|
|
||||||
|
|
||||||
hlGroup = helpers.defaultNullOpts.mkStr "ObsidianExtLinkIcon" ''
|
|
||||||
The name of the highlight group to use for the external link icon.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
referenceText = {
|
|
||||||
hlGroup = helpers.defaultNullOpts.mkStr "ObsidianRefText" ''
|
|
||||||
The name of the highlight group to use for reference text.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
highlightText = {
|
|
||||||
hlGroup = helpers.defaultNullOpts.mkStr "ObsidianHighlightText" ''
|
|
||||||
The name of the highlight group to use for highlight text.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
tags = {
|
|
||||||
hlGroup = helpers.defaultNullOpts.mkStr "ObsidianTag" ''
|
|
||||||
The name of the highlight group to use for tags.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
hlGroups =
|
|
||||||
helpers.defaultNullOpts.mkNullable
|
|
||||||
(with helpers.nixvimTypes; attrsOf highlight)
|
|
||||||
''
|
|
||||||
{
|
|
||||||
ObsidianTodo = {
|
|
||||||
bold = true;
|
|
||||||
fg = "#f78c6c";
|
|
||||||
};
|
|
||||||
ObsidianDone = {
|
|
||||||
bold = true;
|
|
||||||
fg = "#89ddff";
|
|
||||||
};
|
|
||||||
ObsidianRightArrow = {
|
|
||||||
bold = true;
|
|
||||||
fg = "#f78c6c";
|
|
||||||
};
|
|
||||||
ObsidianTilde = {
|
|
||||||
bold = true;
|
|
||||||
fg = "#ff5370";
|
|
||||||
};
|
|
||||||
ObsidianRefText = {
|
|
||||||
underline = true;
|
|
||||||
fg = "#c792ea";
|
|
||||||
};
|
|
||||||
ObsidianExtLinkIcon = {
|
|
||||||
fg = "#c792ea";
|
|
||||||
};
|
|
||||||
ObsidianTag = {
|
|
||||||
italic = true;
|
|
||||||
fg = "#89ddff";
|
|
||||||
};
|
|
||||||
ObsidianHighlightText = {
|
|
||||||
bg = "#75662e";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
''
|
|
||||||
"Highlight group definitions.";
|
|
||||||
};
|
|
||||||
|
|
||||||
attachments = {
|
|
||||||
imgFolder = helpers.defaultNullOpts.mkStr "assets/imgs" ''
|
|
||||||
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.
|
|
||||||
'';
|
|
||||||
|
|
||||||
imgTextFunc =
|
|
||||||
helpers.defaultNullOpts.mkLuaFn
|
|
||||||
''
|
|
||||||
function(client, path)
|
|
||||||
---@type string
|
|
||||||
local link_path
|
|
||||||
local vault_relative_path = client:vault_relative_path(path)
|
|
||||||
if vault_relative_path ~= nil then
|
|
||||||
-- Use relative path if the image is saved in the vault dir.
|
|
||||||
link_path = vault_relative_path
|
|
||||||
else
|
|
||||||
-- Otherwise use the absolute path.
|
|
||||||
link_path = tostring(path)
|
|
||||||
end
|
|
||||||
local display_name = vim.fs.basename(link_path)
|
|
||||||
return string.format("", display_name, link_path)
|
|
||||||
end
|
|
||||||
''
|
|
||||||
''
|
|
||||||
A function that determines the text to insert in the note when pasting an image.
|
|
||||||
It takes two arguments, the `obsidian.Client` and a plenary `Path` to the image file.
|
|
||||||
|
|
||||||
```lua
|
|
||||||
@param client obsidian.Client
|
|
||||||
@param path Path the absolute path to the image file
|
|
||||||
@return string
|
|
||||||
```
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
yamlParser = helpers.defaultNullOpts.mkEnumFirstDefault ["native" "yq"] ''
|
|
||||||
Set the YAML parser to use.
|
|
||||||
|
|
||||||
The valid options are:
|
|
||||||
- "native" - uses a pure Lua parser that's fast but potentially misses some edge cases.
|
|
||||||
- "yq" - uses the command-line tool yq (https://github.com/mikefarah/yq), which is more robust
|
|
||||||
but much slower and needs to be installed separately.
|
|
||||||
|
|
||||||
In general you should be using the native parser unless you run into a bug with it, in which
|
|
||||||
case you can temporarily switch to the "yq" parser until the bug is fixed.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
meta.maintainers = [maintainers.GaetanLepage];
|
|
||||||
|
|
||||||
options.plugins.obsidian =
|
|
||||||
helpers.neovim-plugin.extraOptionsOptions
|
|
||||||
// {
|
|
||||||
enable = mkEnableOption "obsidian.nvim";
|
|
||||||
|
|
||||||
package = helpers.mkPackageOption "obsidian.nvim" pkgs.vimPlugins.obsidian-nvim;
|
|
||||||
|
|
||||||
dir = helpers.mkNullOrOption types.str ''
|
|
||||||
Alternatively to `workspaces` - and for backwards compatibility - you can set `dir` to a
|
|
||||||
single path instead of `workspaces`.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
```nix
|
|
||||||
dir = "~/vaults/work";
|
|
||||||
```
|
|
||||||
'';
|
|
||||||
|
|
||||||
workspaces =
|
|
||||||
helpers.defaultNullOpts.mkNullable
|
|
||||||
(
|
|
||||||
with types;
|
|
||||||
listOf
|
|
||||||
(types.submodule {
|
|
||||||
options = {
|
|
||||||
name = mkOption {
|
|
||||||
type = with helpers.nixvimTypes; maybeRaw str;
|
|
||||||
description = "The name for this workspace";
|
|
||||||
};
|
|
||||||
|
|
||||||
path = mkOption {
|
|
||||||
type = with helpers.nixvimTypes; maybeRaw str;
|
|
||||||
description = "The of the workspace.";
|
|
||||||
};
|
|
||||||
|
|
||||||
overrides = configOptions;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
"[]"
|
|
||||||
''
|
|
||||||
A list of vault names and paths.
|
|
||||||
Each path should be the path to the vault root.
|
|
||||||
If you use the Obsidian app, the vault root is the parent directory of the `.obsidian`
|
|
||||||
folder.
|
|
||||||
You can also provide configuration overrides for each workspace through the `overrides`
|
|
||||||
field.
|
|
||||||
'';
|
|
||||||
|
|
||||||
detectCwd = helpers.defaultNullOpts.mkBool false ''
|
|
||||||
Set to true to use the current directory as a vault; otherwise the first workspace
|
|
||||||
is opened by default.
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
// configOptions;
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
extraPlugins = [cfg.package];
|
|
||||||
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = let
|
|
||||||
nvimCmpEnabled = isBool cfg.completion.nvimCmp && cfg.completion.nvimCmp;
|
|
||||||
in
|
|
||||||
nvimCmpEnabled -> config.plugins.cmp.enable;
|
|
||||||
message = ''
|
|
||||||
Nixvim (plugins.obsidian): You have enabled `completion.nvimCmp` but `plugins.cmp.enable` is `false`.
|
|
||||||
You need to enable `cmp` to use this setting.
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
extraConfigLua = let
|
|
||||||
processConfigOptions = configOptions:
|
|
||||||
with configOptions; {
|
|
||||||
log_level = logLevel;
|
|
||||||
notes_subdir = notesSubdir;
|
|
||||||
templates = with templates; {
|
|
||||||
inherit subdir;
|
|
||||||
date_format = dateFormat;
|
|
||||||
time_format = timeFormat;
|
|
||||||
inherit substitutions;
|
|
||||||
};
|
|
||||||
note_id_func = noteIdFunc;
|
|
||||||
follow_url_func = followUrlFunc;
|
|
||||||
note_formatter_func = noteFrontmatterFunc;
|
|
||||||
disable_frontmatter = disableFrontmatter;
|
|
||||||
backlinks = with backlinks; {
|
|
||||||
inherit
|
|
||||||
height
|
|
||||||
wrap
|
|
||||||
;
|
|
||||||
};
|
|
||||||
completion = with completion; {
|
|
||||||
nvim_cmp = nvimCmp;
|
|
||||||
min_chars = minChars;
|
|
||||||
new_notes_location = newNotesLocation;
|
|
||||||
prepend_note_id = prependNoteId;
|
|
||||||
prepend_note_path = prependNotePath;
|
|
||||||
use_path_only = usePathOnly;
|
|
||||||
};
|
|
||||||
inherit mappings;
|
|
||||||
daily_notes = with dailyNotes; {
|
|
||||||
inherit folder;
|
|
||||||
date_format = dateFormat;
|
|
||||||
alias_format = aliasFormat;
|
|
||||||
inherit template;
|
|
||||||
};
|
|
||||||
use_advanced_uri = useAdvancedUri;
|
|
||||||
open_app_foreground = openAppForeground;
|
|
||||||
inherit finder;
|
|
||||||
sort_by = sortBy;
|
|
||||||
sort_reversed = sortReversed;
|
|
||||||
open_notes_in = openNotesIn;
|
|
||||||
ui = with ui; {
|
|
||||||
inherit enable;
|
|
||||||
update_debounce = updateDebounce;
|
|
||||||
checkboxes =
|
|
||||||
helpers.ifNonNull' checkboxes
|
|
||||||
(
|
|
||||||
mapAttrs
|
|
||||||
(
|
|
||||||
_: checkbox: {
|
|
||||||
inherit (checkbox) char;
|
|
||||||
hl_group = checkbox.hlGroup;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
checkboxes
|
|
||||||
);
|
|
||||||
external_link_icon = with externalLinkIcon; {
|
|
||||||
inherit char;
|
|
||||||
hl_group = hlGroup;
|
|
||||||
};
|
|
||||||
reference_text = with referenceText; {
|
|
||||||
hl_group = hlGroup;
|
|
||||||
};
|
|
||||||
highlight_text = with highlightText; {
|
|
||||||
hl_group = hlGroup;
|
|
||||||
};
|
|
||||||
tags = with tags; {
|
|
||||||
hl_group = hlGroup;
|
|
||||||
};
|
|
||||||
hl_groups = hlGroups;
|
|
||||||
};
|
|
||||||
attachments = with attachments; {
|
|
||||||
img_folder = imgFolder;
|
|
||||||
img_text_func = imgTextFunc;
|
|
||||||
};
|
|
||||||
yaml_parser = yamlParser;
|
|
||||||
};
|
|
||||||
|
|
||||||
setupOptions = with cfg;
|
|
||||||
{
|
|
||||||
inherit dir;
|
|
||||||
workspaces =
|
|
||||||
helpers.ifNonNull' workspaces
|
|
||||||
(
|
|
||||||
map
|
|
||||||
(
|
|
||||||
workspaceConfig: {
|
|
||||||
inherit
|
|
||||||
(workspaceConfig)
|
|
||||||
name
|
|
||||||
path
|
|
||||||
;
|
|
||||||
overrides = processConfigOptions workspaceConfig.overrides;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
workspaces
|
|
||||||
);
|
|
||||||
detect_cwd = detectCwd;
|
|
||||||
}
|
|
||||||
// (processConfigOptions cfg)
|
|
||||||
// cfg.extraOptions;
|
|
||||||
in ''
|
|
||||||
require('obsidian').setup(${helpers.toLuaObject setupOptions})
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
175
plugins/utils/obsidian/default.nix
Normal file
175
plugins/utils/obsidian/default.nix
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
helpers,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
helpers.neovim-plugin.mkNeovimPlugin config {
|
||||||
|
name = "obsidian";
|
||||||
|
originalName = "obsidian.nvim";
|
||||||
|
defaultPackage = pkgs.vimPlugins.obsidian-nvim;
|
||||||
|
|
||||||
|
maintainers = [maintainers.GaetanLepage];
|
||||||
|
|
||||||
|
## DEPRECATIONS
|
||||||
|
# Introduced 2024-03-12
|
||||||
|
# TODO: remove 2024-05-12
|
||||||
|
deprecateExtraOptions = true;
|
||||||
|
optionsRenamedToSettings = [
|
||||||
|
"dir"
|
||||||
|
"logLevel"
|
||||||
|
"notesSubdir"
|
||||||
|
["templates" "subdir"]
|
||||||
|
["templates" "dateFormat"]
|
||||||
|
["templates" "timeFormat"]
|
||||||
|
["templates" "substitutions"]
|
||||||
|
"noteIdFunc"
|
||||||
|
"followUrlFunc"
|
||||||
|
"noteFrontmatterFunc"
|
||||||
|
"disableFrontmatter"
|
||||||
|
["completion" "nvimCmp"]
|
||||||
|
["completion" "minChars"]
|
||||||
|
"mappings"
|
||||||
|
["dailyNotes" "folder"]
|
||||||
|
["dailyNotes" "dateFormat"]
|
||||||
|
["dailyNotes" "aliasFormat"]
|
||||||
|
["dailyNotes" "template"]
|
||||||
|
"useAdvancedUri"
|
||||||
|
"openAppForeground"
|
||||||
|
"sortBy"
|
||||||
|
"sortReversed"
|
||||||
|
"openNotesIn"
|
||||||
|
["ui" "enable"]
|
||||||
|
["ui" "updateDebounce"]
|
||||||
|
["ui" "externalLinkIcon" "char"]
|
||||||
|
["ui" "externalLinkIcon" "hlGroup"]
|
||||||
|
["ui" "referenceText" "hlGroup"]
|
||||||
|
["ui" "highlightText" "hlGroup"]
|
||||||
|
["ui" "tags" "hlGroup"]
|
||||||
|
["ui" "hlGroups"]
|
||||||
|
["attachments" "imgFolder"]
|
||||||
|
["attachments" "imgTextFunc"]
|
||||||
|
"yamlParser"
|
||||||
|
];
|
||||||
|
imports = let
|
||||||
|
basePluginPath = ["plugins" "obsidian"];
|
||||||
|
in
|
||||||
|
[
|
||||||
|
( # We have to remove the option here because the user could set old-style camelCase options in each workspaces element.
|
||||||
|
mkRemovedOptionModule
|
||||||
|
(basePluginPath ++ ["workspaces"])
|
||||||
|
"Please use `plugins.obsidian.settings.workspaces` instead."
|
||||||
|
)
|
||||||
|
(
|
||||||
|
mkRenamedOptionModule
|
||||||
|
(basePluginPath ++ ["finder"])
|
||||||
|
(basePluginPath ++ ["settings" "picker" "name"])
|
||||||
|
)
|
||||||
|
(
|
||||||
|
# https://github.com/epwalsh/obsidian.nvim/blob/656d9c2c64528839db8b2d9a091843b3c90155a2/CHANGELOG.md?plain=1#L184
|
||||||
|
mkRenamedOptionModule
|
||||||
|
(basePluginPath ++ ["completion" "newNotesLocation"])
|
||||||
|
(basePluginPath ++ ["settings" "new_notes_location"])
|
||||||
|
)
|
||||||
|
( # We have to remove the option here because the user could set old-style camelCase options in each checkbox element.
|
||||||
|
mkRemovedOptionModule
|
||||||
|
(basePluginPath ++ ["ui" "checkboxes"])
|
||||||
|
"Please use `plugins.obsidian.settings.ui.checkboxes` instead."
|
||||||
|
)
|
||||||
|
]
|
||||||
|
++ (map (
|
||||||
|
optionPath:
|
||||||
|
mkRemovedOptionModule
|
||||||
|
(basePluginPath ++ optionPath)
|
||||||
|
"This option was deprecated by upstream."
|
||||||
|
)
|
||||||
|
[
|
||||||
|
["detectCwd"]
|
||||||
|
["backlinks"]
|
||||||
|
["completion" "prependNoteId"]
|
||||||
|
["completion" "prependNotePath"]
|
||||||
|
["completion" "usePathOnly"]
|
||||||
|
]);
|
||||||
|
|
||||||
|
settingsOptions = let
|
||||||
|
opts = import ./options.nix {inherit lib helpers;};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
dir = helpers.mkNullOrOption types.str ''
|
||||||
|
Alternatively to `workspaces` - and for backwards compatibility - you can set `dir` to a
|
||||||
|
single path instead of `workspaces`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```nix
|
||||||
|
dir = "~/vaults/work";
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
workspaces =
|
||||||
|
helpers.defaultNullOpts.mkNullable
|
||||||
|
(
|
||||||
|
with types;
|
||||||
|
listOf
|
||||||
|
(types.submodule {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = with helpers.nixvimTypes; maybeRaw str;
|
||||||
|
description = "The name for this workspace";
|
||||||
|
};
|
||||||
|
|
||||||
|
path = mkOption {
|
||||||
|
type = with helpers.nixvimTypes; maybeRaw str;
|
||||||
|
description = "The of the workspace.";
|
||||||
|
};
|
||||||
|
|
||||||
|
overrides = opts;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
)
|
||||||
|
"[]"
|
||||||
|
''
|
||||||
|
A list of vault names and paths.
|
||||||
|
Each path should be the path to the vault root.
|
||||||
|
If you use the Obsidian app, the vault root is the parent directory of the `.obsidian`
|
||||||
|
folder.
|
||||||
|
You can also provide configuration overrides for each workspace through the `overrides`
|
||||||
|
field.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
// opts;
|
||||||
|
|
||||||
|
settingsExample = {
|
||||||
|
workspaces = [
|
||||||
|
{
|
||||||
|
name = "work";
|
||||||
|
path = "~/obsidian/work";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "startup";
|
||||||
|
path = "~/obsidian/startup";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
new_notes_location = "current_dir";
|
||||||
|
completion = {
|
||||||
|
nvim_cmp = true;
|
||||||
|
min_chars = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = cfg: {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = let
|
||||||
|
nvimCmpEnabled = isBool cfg.settings.completion.nvim_cmp && cfg.settings.completion.nvim_cmp;
|
||||||
|
in
|
||||||
|
nvimCmpEnabled -> config.plugins.nvim-cmp.enable;
|
||||||
|
message = ''
|
||||||
|
Nixvim (plugins.obsidian): You have enabled `completion.nvim_cmp` but `plugins.cmp.enable` is `false`.
|
||||||
|
You need to enable `nvim-cmp` to use this setting.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
556
plugins/utils/obsidian/options.nix
Normal file
556
plugins/utils/obsidian/options.nix
Normal file
|
@ -0,0 +1,556 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
helpers,
|
||||||
|
}:
|
||||||
|
with lib; {
|
||||||
|
# https://github.com/epwalsh/obsidian.nvim/blob/main/lua/obsidian/config.lua
|
||||||
|
|
||||||
|
log_level = helpers.defaultNullOpts.mkLogLevel "info" ''
|
||||||
|
Set the log level for obsidian.nvim.
|
||||||
|
'';
|
||||||
|
|
||||||
|
notes_subdir = helpers.mkNullOrStr ''
|
||||||
|
If you keep notes in a specific subdirectory of your vault.
|
||||||
|
'';
|
||||||
|
|
||||||
|
templates = {
|
||||||
|
subdir = helpers.mkNullOrStr ''
|
||||||
|
The name of the directory where templates are stored.
|
||||||
|
|
||||||
|
Example: "templates"
|
||||||
|
'';
|
||||||
|
|
||||||
|
date_format = helpers.mkNullOrStr ''
|
||||||
|
Which date format to use.
|
||||||
|
|
||||||
|
Example: "%Y-%m-%d"
|
||||||
|
'';
|
||||||
|
|
||||||
|
time_format = helpers.mkNullOrStr ''
|
||||||
|
Which time format to use.
|
||||||
|
|
||||||
|
Example: "%H:%M"
|
||||||
|
'';
|
||||||
|
|
||||||
|
substitutions =
|
||||||
|
helpers.defaultNullOpts.mkAttrsOf
|
||||||
|
(with helpers.nixvimTypes; either str rawLua)
|
||||||
|
"{}"
|
||||||
|
"A map for custom variables, the key should be the variable and the value a function.";
|
||||||
|
};
|
||||||
|
|
||||||
|
new_notes_location = helpers.defaultNullOpts.mkEnumFirstDefault ["current_dir" "notes_subdir"] ''
|
||||||
|
Where to put new notes created from completion.
|
||||||
|
|
||||||
|
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.
|
||||||
|
'';
|
||||||
|
|
||||||
|
note_id_func = helpers.mkNullOrLuaFn ''
|
||||||
|
Customize how names/IDs for new notes are created.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
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
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
note_path_func = helpers.mkNullOrLuaFn ''
|
||||||
|
Customize how note file names are generated given the ID, target directory, and title.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
---@param spec { id: string, dir: obsidian.Path, title: string|? }
|
||||||
|
---@return string|obsidian.Path The full path to the new note.
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
function(spec)
|
||||||
|
-- This is equivalent to the default behavior.
|
||||||
|
local path = spec.dir / tostring(spec.id)
|
||||||
|
return path:with_suffix(".md")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
wiki_link_func =
|
||||||
|
helpers.mkNullOrLuaFn
|
||||||
|
''
|
||||||
|
Customize how wiki links are formatted.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
---@param opts {path: string, label: string, id: string|?}
|
||||||
|
---@return string
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
function(opts)
|
||||||
|
if opts.id == nil then
|
||||||
|
return string.format("[[%s]]", opts.label)
|
||||||
|
elseif opts.label ~= opts.id then
|
||||||
|
return string.format("[[%s|%s]]", opts.id, opts.label)
|
||||||
|
else
|
||||||
|
return string.format("[[%s]]", opts.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Default: See source
|
||||||
|
'';
|
||||||
|
|
||||||
|
markdown_link_func = helpers.mkNullOrLuaFn ''
|
||||||
|
Customize how markdown links are formatted.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
---@param opts {path: string, label: string, id: string|?}
|
||||||
|
---@return string links are formatted.
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
function(opts)
|
||||||
|
return string.format("[%s](%s)", opts.label, opts.path)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Default: See source
|
||||||
|
'';
|
||||||
|
|
||||||
|
preferred_link_style = helpers.defaultNullOpts.mkEnumFirstDefault ["wiki" "markdown"] ''
|
||||||
|
Either 'wiki' or 'markdown'.
|
||||||
|
'';
|
||||||
|
|
||||||
|
follow_url_func = helpers.mkNullOrLuaFn ''
|
||||||
|
By default when you use `:ObsidianFollowLink` on a link to an external URL it will be
|
||||||
|
ignored but you can customize this behavior here.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
function(url)
|
||||||
|
-- Open the URL in the default web browser.
|
||||||
|
vim.fn.jobstart({"open", url}) -- Mac OS
|
||||||
|
-- vim.fn.jobstart({"xdg-open", url}) -- linux
|
||||||
|
end
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
image_name_func = helpers.mkNullOrLuaFn ''
|
||||||
|
Customize the default name or prefix when pasting images via `:ObsidianPasteImg`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
function()
|
||||||
|
-- Prefix image names with timestamp.
|
||||||
|
return string.format("%s-", os.time())
|
||||||
|
end
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
note_frontmatter_func = helpers.mkNullOrLuaFn ''
|
||||||
|
You can customize the frontmatter data.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
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
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
disable_frontmatter = helpers.mkNullOrStrLuaFnOr types.bool ''
|
||||||
|
Boolean or a function that takes a filename and returns a boolean.
|
||||||
|
`true` indicates that you don't want obsidian.nvim to manage frontmatter.
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
'';
|
||||||
|
|
||||||
|
completion = {
|
||||||
|
nvim_cmp = helpers.mkNullOrOption types.bool ''
|
||||||
|
Set to false to disable completion.
|
||||||
|
|
||||||
|
Default: `true` if `nvim-cmp` is enabled (`plugins.cmp.enable`).
|
||||||
|
'';
|
||||||
|
|
||||||
|
min_chars = helpers.defaultNullOpts.mkUnsignedInt 2 ''
|
||||||
|
Trigger completion at this many chars.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mappings =
|
||||||
|
helpers.defaultNullOpts.mkNullable
|
||||||
|
(
|
||||||
|
with types;
|
||||||
|
attrsOf (submodule {
|
||||||
|
options = {
|
||||||
|
action = mkOption {
|
||||||
|
type = helpers.nixvimTypes.strLua;
|
||||||
|
description = "The lua code for this keymap action.";
|
||||||
|
apply = helpers.mkRaw;
|
||||||
|
};
|
||||||
|
opts =
|
||||||
|
helpers.keymaps.mapConfigOptions
|
||||||
|
// {
|
||||||
|
buffer = helpers.defaultNullOpts.mkBool false ''
|
||||||
|
If true, the mapping will be effective in the current buffer only.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
)
|
||||||
|
''
|
||||||
|
{
|
||||||
|
gf = {
|
||||||
|
action = "require('obsidian').util.gf_passthrough";
|
||||||
|
opts = {
|
||||||
|
noremap = false;
|
||||||
|
expr = true;
|
||||||
|
buffer = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
"<leader>ch" = {
|
||||||
|
action = "require('obsidian').util.toggle_checkbox";
|
||||||
|
opts.buffer = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
''
|
||||||
|
''
|
||||||
|
Configure key mappings.
|
||||||
|
'';
|
||||||
|
|
||||||
|
picker = {
|
||||||
|
name = helpers.mkNullOrOption (types.enum ["telescope.nvim" "fzf-lua" "mini.pick"]) ''
|
||||||
|
Set your preferred picker.
|
||||||
|
'';
|
||||||
|
|
||||||
|
note_mappings =
|
||||||
|
helpers.defaultNullOpts.mkAttrsOf types.str
|
||||||
|
''
|
||||||
|
{
|
||||||
|
new = "<C-x>";
|
||||||
|
insert_link = "<C-l>";
|
||||||
|
}
|
||||||
|
''
|
||||||
|
''
|
||||||
|
Optional, configure note mappings for the picker. These are the defaults.
|
||||||
|
Not all pickers support all mappings.
|
||||||
|
'';
|
||||||
|
|
||||||
|
tag_mappings =
|
||||||
|
helpers.defaultNullOpts.mkAttrsOf types.str
|
||||||
|
''
|
||||||
|
{
|
||||||
|
tag_note = "<C-x>";
|
||||||
|
insert_tag = "<C-l>";
|
||||||
|
}
|
||||||
|
''
|
||||||
|
''
|
||||||
|
Optional, configure tag mappings for the picker. These are the defaults.
|
||||||
|
Not all pickers support all mappings.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
daily_notes = {
|
||||||
|
folder = helpers.mkNullOrStr ''
|
||||||
|
Optional, if you keep daily notes in a separate directory.
|
||||||
|
'';
|
||||||
|
|
||||||
|
date_format = helpers.mkNullOrStr ''
|
||||||
|
Optional, if you want to change the date format for the ID of daily notes.
|
||||||
|
|
||||||
|
Example: "%Y-%m-%d"
|
||||||
|
'';
|
||||||
|
|
||||||
|
alias_format = helpers.mkNullOrStr ''
|
||||||
|
Optional, if you want to change the date format of the default alias of daily notes.
|
||||||
|
|
||||||
|
Example: "%B %-d, %Y"
|
||||||
|
'';
|
||||||
|
|
||||||
|
template = helpers.mkNullOrStr ''
|
||||||
|
Optional, if you want to automatically insert a template from your template directory like
|
||||||
|
'daily.md'.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
use_advanced_uri = helpers.defaultNullOpts.mkBool false ''
|
||||||
|
Set to true to force ':ObsidianOpen' to bring the app to the foreground.
|
||||||
|
'';
|
||||||
|
|
||||||
|
open_app_foreground = helpers.defaultNullOpts.mkBool false ''
|
||||||
|
Set to true to force `:ObsidianOpen` to bring the app to the foreground.
|
||||||
|
'';
|
||||||
|
|
||||||
|
sort_by = helpers.defaultNullOpts.mkEnum ["path" "modified" "accessed" "created"] "modified" ''
|
||||||
|
Sort search results by "path", "modified", "accessed", or "created".
|
||||||
|
The recommend value is "modified" and `true` for `sortReversed`, which means, for example,
|
||||||
|
that `:ObsidianQuickSwitch` will show the notes sorted by latest modified time.
|
||||||
|
'';
|
||||||
|
|
||||||
|
sort_reversed = helpers.defaultNullOpts.mkBool true ''
|
||||||
|
Whether search results should be reversed.
|
||||||
|
'';
|
||||||
|
|
||||||
|
open_notes_in = helpers.defaultNullOpts.mkEnumFirstDefault ["current" "vsplit" "hsplit"] ''
|
||||||
|
Determines how certain commands open notes.
|
||||||
|
|
||||||
|
The valid options are:
|
||||||
|
- "current" (the default) - to always open in the current window
|
||||||
|
- "vsplit" - to open in a vertical split if there's not already a vertical split
|
||||||
|
- "hsplit" - to open in a horizontal split if there's not already a horizontal split
|
||||||
|
'';
|
||||||
|
|
||||||
|
ui = {
|
||||||
|
enable = helpers.defaultNullOpts.mkBool true ''
|
||||||
|
Set to false to disable all additional syntax features.
|
||||||
|
'';
|
||||||
|
|
||||||
|
update_debounce = helpers.defaultNullOpts.mkUnsignedInt 200 ''
|
||||||
|
Update delay after a text change (in milliseconds).
|
||||||
|
'';
|
||||||
|
|
||||||
|
checkboxes =
|
||||||
|
helpers.defaultNullOpts.mkNullable
|
||||||
|
(
|
||||||
|
with types;
|
||||||
|
attrsOf (
|
||||||
|
submodule {
|
||||||
|
options = {
|
||||||
|
char = mkOption {
|
||||||
|
type = with helpers.nixvimTypes; maybeRaw str;
|
||||||
|
description = "The character to use for this checkbox.";
|
||||||
|
};
|
||||||
|
|
||||||
|
hl_group = mkOption {
|
||||||
|
type = with helpers.nixvimTypes; maybeRaw str;
|
||||||
|
description = "The name of the highlight group to use for this checkbox.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
''
|
||||||
|
{
|
||||||
|
" " = {
|
||||||
|
char = "";
|
||||||
|
hl_group = "ObsidianTodo";
|
||||||
|
};
|
||||||
|
"x" = {
|
||||||
|
char = "";
|
||||||
|
hl_group = "ObsidianDone";
|
||||||
|
};
|
||||||
|
">" = {
|
||||||
|
char = "";
|
||||||
|
hl_group = "ObsidianRightArrow";
|
||||||
|
};
|
||||||
|
"~" = {
|
||||||
|
char = "";
|
||||||
|
hl_group = "ObsidianTilde";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
''
|
||||||
|
''
|
||||||
|
Define how various check-boxes are displayed.
|
||||||
|
You can also add more custom ones...
|
||||||
|
|
||||||
|
NOTE: the 'char' value has to be a single character, and the highlight groups are defined
|
||||||
|
in the `ui.hl_groups` option.
|
||||||
|
'';
|
||||||
|
|
||||||
|
bullets = {
|
||||||
|
char = helpers.defaultNullOpts.mkStr "•" ''
|
||||||
|
Which character to use for the bullets.
|
||||||
|
'';
|
||||||
|
|
||||||
|
hl_group = helpers.defaultNullOpts.mkStr "ObsidianBullet" ''
|
||||||
|
The name of the highlight group to use for the bullets.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
external_link_icon = {
|
||||||
|
char = helpers.defaultNullOpts.mkStr "" ''
|
||||||
|
Which character to use for the external link icon.
|
||||||
|
'';
|
||||||
|
|
||||||
|
hl_group = helpers.defaultNullOpts.mkStr "ObsidianExtLinkIcon" ''
|
||||||
|
The name of the highlight group to use for the external link icon.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
reference_text = {
|
||||||
|
hl_group = helpers.defaultNullOpts.mkStr "ObsidianRefText" ''
|
||||||
|
The name of the highlight group to use for reference text.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
highlight_text = {
|
||||||
|
hl_group = helpers.defaultNullOpts.mkStr "ObsidianHighlightText" ''
|
||||||
|
The name of the highlight group to use for highlight text.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
hl_group = helpers.defaultNullOpts.mkStr "ObsidianTag" ''
|
||||||
|
The name of the highlight group to use for tags.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
hl_groups =
|
||||||
|
helpers.defaultNullOpts.mkNullable
|
||||||
|
(with helpers.nixvimTypes; attrsOf highlight)
|
||||||
|
''
|
||||||
|
{
|
||||||
|
ObsidianTodo = {
|
||||||
|
bold = true;
|
||||||
|
fg = "#f78c6c";
|
||||||
|
};
|
||||||
|
ObsidianDone = {
|
||||||
|
bold = true;
|
||||||
|
fg = "#89ddff";
|
||||||
|
};
|
||||||
|
ObsidianRightArrow = {
|
||||||
|
bold = true;
|
||||||
|
fg = "#f78c6c";
|
||||||
|
};
|
||||||
|
ObsidianTilde = {
|
||||||
|
bold = true;
|
||||||
|
fg = "#ff5370";
|
||||||
|
};
|
||||||
|
ObsidianRefText = {
|
||||||
|
underline = true;
|
||||||
|
fg = "#c792ea";
|
||||||
|
};
|
||||||
|
ObsidianExtLinkIcon = {
|
||||||
|
fg = "#c792ea";
|
||||||
|
};
|
||||||
|
ObsidianTag = {
|
||||||
|
italic = true;
|
||||||
|
fg = "#89ddff";
|
||||||
|
};
|
||||||
|
ObsidianHighlightText = {
|
||||||
|
bg = "#75662e";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
''
|
||||||
|
"Highlight group definitions.";
|
||||||
|
};
|
||||||
|
|
||||||
|
attachments = {
|
||||||
|
img_folder = helpers.defaultNullOpts.mkStr "assets/imgs" ''
|
||||||
|
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_text_func =
|
||||||
|
helpers.defaultNullOpts.mkLuaFn
|
||||||
|
''
|
||||||
|
function(client, path)
|
||||||
|
---@type string
|
||||||
|
local link_path
|
||||||
|
local vault_relative_path = client:vault_relative_path(path)
|
||||||
|
if vault_relative_path ~= nil then
|
||||||
|
-- Use relative path if the image is saved in the vault dir.
|
||||||
|
link_path = vault_relative_path
|
||||||
|
else
|
||||||
|
-- Otherwise use the absolute path.
|
||||||
|
link_path = tostring(path)
|
||||||
|
end
|
||||||
|
local display_name = vim.fs.basename(link_path)
|
||||||
|
return string.format("", display_name, link_path)
|
||||||
|
end
|
||||||
|
''
|
||||||
|
''
|
||||||
|
A function that determines the text to insert in the note when pasting an image.
|
||||||
|
It takes two arguments, the `obsidian.Client` and a plenary `Path` to the image file.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
@param client obsidian.Client
|
||||||
|
@param path Path the absolute path to the image file
|
||||||
|
@return string
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
|
||||||
|
confirm_img_paste = helpers.defaultNullOpts.mkBool true ''
|
||||||
|
Whether to prompt for confirmation when pasting an image.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
callbacks = {
|
||||||
|
post_setup = helpers.mkNullOrLuaFn ''
|
||||||
|
`fun(client: obsidian.Client)`
|
||||||
|
|
||||||
|
Runs right after the `obsidian.Client` is initialized.
|
||||||
|
'';
|
||||||
|
|
||||||
|
enter_note = helpers.mkNullOrLuaFn ''
|
||||||
|
`fun(client: obsidian.Client, note: obsidian.Note)`
|
||||||
|
|
||||||
|
Runs when entering a note buffer.
|
||||||
|
'';
|
||||||
|
|
||||||
|
leave_note = helpers.mkNullOrLuaFn ''
|
||||||
|
`fun(client: obsidian.Client, note: obsidian.Note)`
|
||||||
|
|
||||||
|
Runs when leaving a note buffer.
|
||||||
|
'';
|
||||||
|
|
||||||
|
pre_write_note = helpers.mkNullOrLuaFn ''
|
||||||
|
`fun(client: obsidian.Client, note: obsidian.Note)`
|
||||||
|
|
||||||
|
Runs right before writing a note buffer.
|
||||||
|
'';
|
||||||
|
|
||||||
|
post_set_workspace = helpers.mkNullOrLuaFn ''
|
||||||
|
`fun(client: obsidian.Client, workspace: obsidian.Workspace)`
|
||||||
|
|
||||||
|
Runs anytime the workspace is set/changed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
yaml_parser = helpers.defaultNullOpts.mkEnumFirstDefault ["native" "yq"] ''
|
||||||
|
Set the YAML parser to use.
|
||||||
|
|
||||||
|
The valid options are:
|
||||||
|
- "native" - uses a pure Lua parser that's fast but potentially misses some edge cases.
|
||||||
|
- "yq" - uses the command-line tool yq (https://github.com/mikefarah/yq), which is more robust
|
||||||
|
but much slower and needs to be installed separately.
|
||||||
|
|
||||||
|
In general you should be using the native parser unless you run into a bug with it, in which
|
||||||
|
case you can temporarily switch to the "yq" parser until the bug is fixed.
|
||||||
|
'';
|
||||||
|
}
|
|
@ -1,42 +1,73 @@
|
||||||
{
|
{
|
||||||
|
# Note: we can only use `~/` as a workspace as the workspace folder need to exist in the sandbox.
|
||||||
|
|
||||||
empty = {
|
empty = {
|
||||||
# TODO fix the plugin tests
|
plugins.obsidian = {
|
||||||
plugins.obsidian.enable = false;
|
enable = true;
|
||||||
|
# At least one workspaces is needed for the plugin to work
|
||||||
|
settings.workspaces = [
|
||||||
|
{
|
||||||
|
name = "foo";
|
||||||
|
path = "~/";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
example = {
|
simple-example = {
|
||||||
|
plugins = {
|
||||||
|
cmp.enable = true;
|
||||||
|
|
||||||
|
obsidian = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
dir = null;
|
||||||
|
workspaces = [
|
||||||
|
{
|
||||||
|
name = "work";
|
||||||
|
path = "~";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
new_notes_location = "current_dir";
|
||||||
|
completion = {
|
||||||
|
nvim_cmp = true;
|
||||||
|
min_chars = 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
complete-example = {
|
||||||
plugins = {
|
plugins = {
|
||||||
cmp.enable = true;
|
cmp.enable = true;
|
||||||
|
|
||||||
obsidian = {
|
obsidian = {
|
||||||
enable = false;
|
enable = false;
|
||||||
|
|
||||||
|
settings = {
|
||||||
dir = null;
|
dir = null;
|
||||||
workspaces = [
|
workspaces = [
|
||||||
{
|
|
||||||
name = "personal";
|
|
||||||
path = "~/vaults/personal";
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
name = "work";
|
name = "work";
|
||||||
path = "~/vaults/work";
|
path = "~/";
|
||||||
overrides = {
|
overrides = {
|
||||||
notesSubdir = "notes";
|
notes_subdir = "notes";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
detectCwd = false;
|
log_level = "info";
|
||||||
|
notes_subdir = "notes";
|
||||||
logLevel = "info";
|
|
||||||
notesSubdir = "notes";
|
|
||||||
templates = {
|
templates = {
|
||||||
# We cannot set this as it doesn't exist in the testing environment
|
# We cannot set this as it doesn't exist in the testing environment
|
||||||
# subdir = "templates";
|
# subdir = "templates";
|
||||||
dateFormat = "%Y-%m-%d";
|
date_format = "%Y-%m-%d";
|
||||||
timeFormat = "%H:%M";
|
time_format = "%H:%M";
|
||||||
substitutions = {};
|
substitutions = {};
|
||||||
};
|
};
|
||||||
noteIdFunc = ''
|
new_notes_location = "current_dir";
|
||||||
|
note_id_func = ''
|
||||||
function(title)
|
function(title)
|
||||||
-- Create note IDs in a Zettelkasten format with a timestamp and a suffix.
|
-- 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
|
-- In this case a note with the title 'My new note' will be given an ID that looks
|
||||||
|
@ -54,17 +85,52 @@
|
||||||
return tostring(os.time()) .. "-" .. suffix
|
return tostring(os.time()) .. "-" .. suffix
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
followUrlFunc = ''
|
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
|
||||||
|
'';
|
||||||
|
wiki_link_func = ''
|
||||||
|
function(opts)
|
||||||
|
if opts.id == nil then
|
||||||
|
return string.format("[[%s]]", opts.label)
|
||||||
|
elseif opts.label ~= opts.id then
|
||||||
|
return string.format("[[%s|%s]]", opts.id, opts.label)
|
||||||
|
else
|
||||||
|
return string.format("[[%s]]", opts.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
'';
|
||||||
|
markdown_link_func = ''
|
||||||
|
function(opts)
|
||||||
|
return string.format("[%s](%s)", opts.label, opts.path)
|
||||||
|
end
|
||||||
|
'';
|
||||||
|
preferred_link_style = "wiki";
|
||||||
|
follow_url_func = ''
|
||||||
function(url)
|
function(url)
|
||||||
-- Open the URL in the default web browser.
|
-- Open the URL in the default web browser.
|
||||||
vim.fn.jobstart({"open", url}) -- Mac OS
|
vim.fn.jobstart({"open", url}) -- Mac OS
|
||||||
-- vim.fn.jobstart({"xdg-open", url}) -- linux
|
-- vim.fn.jobstart({"xdg-open", url}) -- linux
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
noteFrontmatterFunc = ''
|
image_name_func = ''
|
||||||
|
function()
|
||||||
|
-- Prefix image names with timestamp.
|
||||||
|
return string.format("%s-", os.time())
|
||||||
|
end
|
||||||
|
'';
|
||||||
|
note_frontmatter_func = ''
|
||||||
function(note)
|
function(note)
|
||||||
-- This is equivalent to the default frontmatter function.
|
-- 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 }
|
local out = { id = note.id, aliases = note.aliases, tags = note.tags }
|
||||||
|
|
||||||
-- `note.metadata` contains any manually added fields in the frontmatter.
|
-- `note.metadata` contains any manually added fields in the frontmatter.
|
||||||
-- So here we just make sure those fields are kept 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
|
if note.metadata ~= nil and not vim.tbl_isempty(note.metadata) then
|
||||||
|
@ -72,21 +138,14 @@
|
||||||
out[k] = v
|
out[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
disableFrontmatter = false;
|
disable_frontmatter = false;
|
||||||
backlinks = {
|
|
||||||
height = 10;
|
|
||||||
wrap = true;
|
|
||||||
};
|
|
||||||
completion = {
|
completion = {
|
||||||
nvimCmp = true;
|
nvim_cmp = true;
|
||||||
minChars = 2;
|
min_chars = 2;
|
||||||
newNotesLocation = "current_dir";
|
|
||||||
prependNoteId = true;
|
|
||||||
prependNotePath = false;
|
|
||||||
usePathOnly = false;
|
|
||||||
};
|
};
|
||||||
mappings = {
|
mappings = {
|
||||||
gf = {
|
gf = {
|
||||||
|
@ -103,53 +162,67 @@
|
||||||
opts.buffer = true;
|
opts.buffer = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
dailyNotes = {
|
picker = {
|
||||||
|
name = "telescope.nvim";
|
||||||
|
note_mappings = {
|
||||||
|
new = "<C-x>";
|
||||||
|
insert_link = "<C-l>";
|
||||||
|
};
|
||||||
|
tag_mappings = {
|
||||||
|
tag_note = "<C-x>";
|
||||||
|
insert_tag = "<C-l>";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
daily_notes = {
|
||||||
folder = "notes";
|
folder = "notes";
|
||||||
dateFormat = "%Y-%m-%d";
|
date_format = "%Y-%m-%d";
|
||||||
aliasFormat = "%B %-d, %Y";
|
alias_format = "%B %-d, %Y";
|
||||||
template = "daily.md";
|
template = "daily.md";
|
||||||
};
|
};
|
||||||
useAdvancedUri = false;
|
use_advanced_uri = false;
|
||||||
openAppForeground = false;
|
open_app_foreground = false;
|
||||||
finder = "telescope.nvim";
|
sort_by = "modified";
|
||||||
sortBy = "modified";
|
sort_reversed = true;
|
||||||
sortReversed = true;
|
open_notes_in = "current";
|
||||||
openNotesIn = "current";
|
|
||||||
ui = {
|
ui = {
|
||||||
enable = true;
|
enable = true;
|
||||||
updateDebounce = 200;
|
update_debounce = 200;
|
||||||
checkboxes = {
|
checkboxes = {
|
||||||
" " = {
|
" " = {
|
||||||
char = "";
|
char = "";
|
||||||
hlGroup = "ObsidianTodo";
|
hl_group = "ObsidianTodo";
|
||||||
};
|
};
|
||||||
"x" = {
|
"x" = {
|
||||||
char = "";
|
char = "";
|
||||||
hlGroup = "ObsidianDone";
|
hl_group = "ObsidianDone";
|
||||||
};
|
};
|
||||||
">" = {
|
">" = {
|
||||||
char = "";
|
char = "";
|
||||||
hlGroup = "ObsidianRightArrow";
|
hl_group = "ObsidianRightArrow";
|
||||||
};
|
};
|
||||||
"~" = {
|
"~" = {
|
||||||
char = "";
|
char = "";
|
||||||
hlGroup = "ObsidianTilde";
|
hl_group = "ObsidianTilde";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
externalLinkIcon = {
|
bullets = {
|
||||||
|
char = "•";
|
||||||
|
hl_group = "ObsidianBullet";
|
||||||
|
};
|
||||||
|
external_link_icon = {
|
||||||
char = "";
|
char = "";
|
||||||
hlGroup = "ObsidianExtLinkIcon";
|
hl_group = "ObsidianExtLinkIcon";
|
||||||
};
|
};
|
||||||
referenceText = {
|
reference_text = {
|
||||||
hlGroup = "ObsidianRefText";
|
hl_group = "ObsidianRefText";
|
||||||
};
|
};
|
||||||
highlightText = {
|
highlight_text = {
|
||||||
hlGroup = "ObsidianHighlightText";
|
hl_group = "ObsidianHighlightText";
|
||||||
};
|
};
|
||||||
tags = {
|
tags = {
|
||||||
hlGroup = "ObsidianTag";
|
hl_group = "ObsidianTag";
|
||||||
};
|
};
|
||||||
hlGroups = {
|
hl_groups = {
|
||||||
ObsidianTodo = {
|
ObsidianTodo = {
|
||||||
bold = true;
|
bold = true;
|
||||||
fg = "#f78c6c";
|
fg = "#f78c6c";
|
||||||
|
@ -183,8 +256,8 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
attachments = {
|
attachments = {
|
||||||
imgFolder = "assets/imgs";
|
img_folder = "assets/imgs";
|
||||||
imgTextFunc = ''
|
img_text_func = ''
|
||||||
function(client, path)
|
function(client, path)
|
||||||
---@type string
|
---@type string
|
||||||
local link_path
|
local link_path
|
||||||
|
@ -200,8 +273,17 @@
|
||||||
return string.format("", display_name, link_path)
|
return string.format("", display_name, link_path)
|
||||||
end
|
end
|
||||||
'';
|
'';
|
||||||
|
confirm_img_paste = true;
|
||||||
|
};
|
||||||
|
callbacks = {
|
||||||
|
post_setup = "function(client) end";
|
||||||
|
enter_note = "function(client, note) end";
|
||||||
|
leave_note = "function(client, note) end";
|
||||||
|
pre_write_note = "function(client, note) end";
|
||||||
|
post_set_workspace = "function(client, workspace) end";
|
||||||
|
};
|
||||||
|
yaml_parser = "native";
|
||||||
};
|
};
|
||||||
yamlParser = "native";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue