zk-nvim
Neovim extension for the zk plain text
note-taking assistant.
Checkout Shivan's video, Note-taking System ALL Programmers Should Consider, to see it in action.
Join us on Matrix for general, support and development discussion: #zk-org:pub.solar.
Requirements
zk-nvim |
zk |
Neovim |
|---|---|---|
| 0.4.0 - HEAD | >=0.15.1 | >= 0.11.0 |
| 0.2.0 - 0.3.0 | 0.14.1 - 0.15.1 | 0.9.5 - 0.10.4 |
| 0.1.1 | 0.13.0 - 0.14.1 | 0.9.5 |
| 0.1.0 | 0.13.0 - 0.14.1 | 0.8.0 - 0.9.5 |
Installation
Via packer.nvim
use("zk-org/zk-nvim")
Via vim-plug
Plug 'zk-org/zk-nvim'
Via lazy.nvim
{
"zk-org/zk-nvim",
name = "zk",
opts = {
-- See Setup section below
},
}
To get the best experience, it's recommended to also install either Telescope, fzf, mini.pick, or snacks.picker
Setup
[!IMPORTANT]
If you have the zk cli installed, then you do not need to installzk lspvia Mason (or otherwise).
Default lazy.nvim setup:
return {
"zk-org/zk-nvim",
name = "zk",
opts = {
-- Can be "telescope", "fzf", "fzf_lua", "minipick", "snacks_picker",
-- or select" (`vim.ui.select`).
picker = "select",
lsp = {
-- `config` is passed to `vim.lsp.start(config)`
config = {
name = "zk",
cmd = { "zk", "lsp" },
filetypes = { "markdown" },
-- on_attach = ...
-- etc, see `:h vim.lsp.start()`
},
-- automatically attach buffers in a zk notebook that match the given filetypes
auto_attach = {
enabled = true,
},
},
tags = {
-- Configure how multiple tags should be combined in a ZkTags search
-- Can be "AND" or "OR"
multi_select_strategy = "AND",
}
},
}
Note that this will not add any key mappings for you. If you want to add key mappings, see the example mappings.
Picker Options
You can define default configurations for the pickers opened by zk-nvim,
allowing you to apply a specific theme or layout for zk-nvim. This works for
all supported pickers, but you'll need to refer to the relevant configuration
options for each picker.
require("zk").setup({
picker_options = {
telescope = require("telescope.themes").get_ivy(),
-- or if you use snacks picker
snacks_picker = {
layout = {
preset = "ivy",
}
},
},
...
})
Notebook Directory Discovery
When you run a notebook command, this plugin will look for a notebook in the following places and order:
- the current buffer path (i.e. the file you are currently editing),
- the current working directory,
- the
$ZK_NOTEBOOK_DIRenvironment variable.
We recommend you to export the $ZK_NOTEBOOK_DIR environment variable, so that
a notebook can always be found.
It is worth noting that for some notebook commands you can explicitly specify a notebook by providing a path to any file or directory within the notebook. An explicitly provided path will always take precedence and override the automatic notebook discovery. However, this is always optional, and usually not necessary.
Getting Started
After you have installed the plugin and added the setup code to your config, you
are good to go. If you are not familiar with zk, we recommend you to read
through the
getting started guide.
When using the default config, the zk LSP client will automatically attach
itself to buffers inside your notebook and provide capabilities like completion,
hover and go-to-definition; see https://github.com/zk-org/zk/issues/22 for a
full list of what is supported.
Try out different commands such as :ZkNotes or :ZkNew,
see what they can do, and learn as you go.
Built-in Commands
Indexing
:ZkIndex [{options}]
Indexes the notebook.
Creating Notes
:ZkNew [{options}]
Creates and edits a new note.:'ZkNewFromTitleSelection [{options}]
Creates a new note from the visual selection (used as the title) and replaces the selection with a link to the note (unlessappend = trueis passed to options).:'ZkNewFromContentSelection [{options}]
Creates a new note from the visual selection (used as the content) and replaces the selection with a link to the note (unlessappend = trueis passed to options).
Navigation
:ZkCd [{options}]
Changes directory to the notebook root.:ZkNotes [{options}]
Opens a notes picker.:ZkBuffers [{options}]
Opens a notes picker for active buffers (notebook files only).:ZkBacklinks [{options}]
Opens a notes picker showing backlinks of the current buffer.:ZkLinks [{options}]
Opens a notes picker showing outbound links of the current buffer.
Linking
:ZkInsertLink
Inserts a link at the cursor location.:'ZkInsertLinkAtSelection [{options}]
Inserts a link around the selected text.- Special option:
matchSelected = true→ filters notes similar to the selection.
- Special option:
Searching & Tagging
:ZkMatch [{options}]
Opens a notes picker, filtering for notes matching a search term. The term is resolved from, in priority order: an explicitoptions.match(see thematchoption in Options (ZkList)), a visual selection (:'ZkMatch), or — in normal mode — the word under the cursor.:ZkTags [{options}]
Opens a notes picker for selected tags.
In addition, options.notebook_path can be used to explicitly specify a
notebook by providing a path to any file or directory within the notebook; see
Notebook Directory Discovery.
Examples:
:ZkNew { dir = "daily", date = "yesterday" }
:ZkNotes { createdAfter = "3 days ago", tags = { "work" } }
:'<,'>ZkNewFromTitleSelection " this will use your last visual mode selection. Note that you *must* call this command with the '<,'> range.
:ZkCd
:ZkMatch { match = { "foo", "bar" } } " search notes matching "foo" or "bar"
:ZkMatch { sort = { "created" } } " no match given, falls back to the word under the cursor (or visual selection)
Via Lua
You can access the underlying Lua function of a command, with
require("zk.commands").get.
Examples:
require("zk.commands").get("ZkNew")({ dir = "daily" })
require("zk.commands").get("ZkNotes")({ createdAfter = "3 days ago", tags = { "work" } })
require("zk.commands").get("ZkNewFromTitleSelection")()
Custom Commands
---A thin wrapper around `vim.api.nvim_add_user_command` which parses the `params.args` of the command as a Lua table and passes it on to `fn`.
---@param name string
---@param fn function
---@param opts? table {needs_selection} makes sure the command is called with a range
---@see vim.api.nvim_add_user_command
require("zk.commands").add(name, fn, opts)
Example 1:
Let us add a custom :ZkOrphans command that will list all notes that are
orphans, i.e. not referenced by any other note.
local zk = require("zk")
local commands = require("zk.commands")
commands.add("ZkOrphans", function(options)
options = vim.tbl_extend("force", { orphan = true }, options or {})
zk.edit(options, { title = "Zk Orphans" })
end)
This adds the :ZkOrphans [{options}] vim user command, which accepts an
options Lua table as an argument. We can execute it like this
:ZkOrphans { tags = { "work" } } for example.
Note: The
zk.editfunction is from the high-level API, which also contains other functions that might be useful for your custom commands.
Example 2:
Chances are that this will not be our only custom command following this
pattern. So let's also add a :ZkRecents command and make the pattern a bit
more reusable.