Skip to content

Prompt for creating a new note#268

Open
riodelphino wants to merge 17 commits intozk-org:mainfrom
riodelphino:prompt_for_new
Open

Prompt for creating a new note#268
riodelphino wants to merge 17 commits intozk-org:mainfrom
riodelphino:prompt_for_new

Conversation

@riodelphino
Copy link

@riodelphino riodelphino commented Nov 12, 2025

I'm not sure whether this feature is important for other users.

But this is essential for my daily use.

It’s convenient for users who include a group section in config.toml or include several templates or directories, but less so for those who don’t.

Purpose

Add prompt for choosing group, path and template interactively for creating new note based on config.toml

Screenshots

1. Group selection:

screenshot 2025-11-23 17 28 22

2. Path or directory selection:

screenshot 2025-11-23 17 28 50

3. Template selection:

screenshot 2025-11-23 17 29 15

Summary

:ZkNew can create a new note in a directory using a template.

But normally it consumes some keybinds.
(e.g.)

  • <leader>znn -> ZkNew note
  • <leader>znd -> ZkNew dialy
  • <leader>zni -> ZkNew inbox { template = 'inbox.md' }

zk.new_prompt() function enables to select interactively from:

  • groups
  • paths (and directories)
  • templates

based on config.toml or filesystem, with vim.ui.select() at once.

This fills the gap between config.toml, templates, directories, zk and zk-nvim efficiently.

And it's highly customizable with callback.

Details

When groups are defined, the user selects a group, then a path if available (or chooses a directory from all directories list).
The group’s single note.template is applied automatically; if it’s missing, an error is shown.
If no groups are defined, templates are collected from .zk/templates, and user selects one. Then chooses a directory from all directories list.

The callback function receives options table contains group, dir, template, and also fetched config table.

Dependencies

ltoml (Should we avoid adding new dependencies?)

Usage

---@param options table?
---@param fun(_options: table, _toml: table)
require('zk').new_prompt(options, function(_options, _toml)
  -- your code here
end)

or just simply create new:

:ZkNewPrompt

Test

One-liner for easy test:

:lua require('zk').new_prompt(nil, function(options, toml) vim.notify(vim.inspect(options), vim.log.levels.INFO, { title = "zk-nvim" }) end)

Example code

Example code for zk.new:

---@param options table?
---@param fun(_options: table, _toml: table)
require("zk").new_prompt(options, function(_options, _toml)
  require('zk').new(_options)
end)

Example code for zk.new with title input:

---@param options table?
---@param fun(_options: table, _toml: table)
require("zk").new_prompt(nil, function(_options, _toml)
  vim.ui.input({ prompt = "Enter the title:" }, function(title)
    -- you can add customization here, branch depends on _options.group, _options.dir and _options.template.
    require('zk').new(_options)
  end)
end)

Example code for zk.new with title select from existing notes and modify it:
(NOT WORKS: because vim.ui.select accepts only existing item. But telescope can, I guess.)

Show code
---@param options table
---@param fun(_options: table, _toml: table)
require("zk").new_prompt(nil, function(_options, _toml)
  require('zk.api').list(nil, { select = { "title" }}, function(notes)
    vim.ui.select(notes, { format_item = function(note) return note.title end )}, function(title)
      require('zk').new(_options)
    end)
  end)
end)

Keymaps

I think it can replace :ZkNew keymap, if user wishs.

lazy.nvim:

keys = {
  { '<leader>zn', ':ZkNewPrompt<cr>', desc = 'ZkNewPrompt' },
}

Additional functions

These functions are added in this PR.

  • zk.util.get_config_toml(cwd)
  • zk.util.get_templates(cwd)
  • zk.util.get_dirs(cwd)

Enabled to chose also paths

The zk.new command automatically selects the group whose paths include the specified directory (e.g., zk.new notes → group containing notes), and determines the template from that group’s note.template = ....
However, if multiple groups include the same path in paths, the one defined first is always chosen, making the others ineffective.
Therefore, although this behavior differs slightly from the original zk command logic, selection from paths is also supported.

Should ignore the weird behavior of zk new?

I guess that zk new uses first found template in another group if the specified group does not include note.template = "...". Currently that behavior is ignored.

Sample config

Since the group sections may not be familiar for many users, see the following example.

group example in config.toml:

# 'inbox' group

[group."inbox"]
id-charset = "alphanum"
id-length = 6
id-case = "lower"
paths = ["inbox"]

[group."inbox".note]
filename = "{{id}}"
template = "inbox.md"

When it's converted into a lua table:

inbox = {
  ["id-case"] = "lower",
  ["id-charset"] = "alphanum",
  ["id-length"] = 6,
  note = {
    filename = "{{id}}",
    template = "inbox.md"
  },
  paths = { "inbox" }
}

To add the root dir (= notebook_path) in paths selection, use an empty string:

[group."note"]
paths = [""]

Or, just removing paths = [] line will work fine too.

@riodelphino riodelphino changed the title Prompt for new Prompt for creating a new note Nov 14, 2025
@tjex
Copy link
Member

tjex commented Nov 23, 2025

I'm painfully stuck on this one. It's such a great feature idea, and something I've been wanting myself. But we really should do the config parsing with native zk api functions, instead of implementing dependencies.

E.g, zk-org/zk#484 lists the aliases, filters and extras from the config file. It would then be a case of extending this (not in the same pr though) to list also the groups, and then implementing it as an api function in zk-nvim

@riodelphino
Copy link
Author

riodelphino commented Nov 26, 2025

Thanks, and I agree with you!
I was hoping that zk already had zk config command to parse all the config.toml.

I’ll take a look at the PR first. (Oh, it hasn't been merged for long time.)

So, the step is:

  1. zk implements parsing and returning the config. (e.g. zk config command)
  2. Use that command or api instead, in this PR.

right ?

(I wish I could help, but I'm not familiar with Go lang at all for now.)

@tjex
Copy link
Member

tjex commented Nov 30, 2025

Yep, that's correct. It would ultimately result in a new M.config function in lua/ak/api.lua

Comment on lines +158 to +169
---Load and decode 'config.toml'
---@param cwd? string Notebook root directory (optional)
---@return table? config Decoded TOML config if successful
function M.get_config_toml(cwd)
local ltoml = require("toml")
cwd = cwd or require("zk.util").notebook_root(vim.fn.getcwd())
if not cwd then
return
end
toml_path = vim.fs.joinpath(cwd, ".zk/config.toml")
local result, config = pcall(ltoml.decodeFromFile, toml_path)
if not result then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, just as a general comment for future work. Rembmer that a zk config can either be global (in $XDG_CONFIG_HOME/zk/config.toml), local (in the notebook) or a combination of both.

This implementation only considers local configs.

This (and many other reasons) are why it's best to develop the zk-nvim plugin, to use as much as possible, the functionality built into zk already.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your review.
That's right, I completely forgot about $XDG_CONFIG_HOME/zk/config.toml.
I understand that we should use zk as much as possible before implementing in zk-nvim.

@riodelphino
Copy link
Author

Temporarily I've migrated this functionality to a new repository:
riodelphino/zk-new.nvim

I needed this functionality immediately, so I decided to create a separate plugin. If the repository name is confusing, it can be changed anytime.

Though the issue with retrieving config.toml remains, it will be fixed soon.

Once zk-org/zk#484 is merged, zk-new.nvim can be deprecated and (maybe) integrated into zk-nvim.

Thanks @tjex !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants