zk-org / zk-nvim

Neovim extension for zk
https://github.com/zk-org/zk
GNU General Public License v3.0
503 stars 41 forks source link

Insert link via filepicker #61

Closed nathanbraun closed 2 years ago

nathanbraun commented 2 years ago

Hi there, just found this plugin, seems awesome so far!

One thing I'm trying to figure out how to implement is adding a command to insert a link (in markdown form) using a filepicker. Looking around on here this is what i have so far:

local function yankName(options, picker_options)
  zk.pick_notes(options, picker_options, function(notes)
    local pos = vim.api.nvim_win_get_cursor(0)[2]
    local line = vim.api.nvim_get_current_line()

    if picker_options.multi_select == false then
      notes = { notes }
    end
    for _, note in ipairs(notes) do
      local nline = line:sub(0, pos) .. note.absPath  .. line:sub(pos + 1)
      vim.api.nvim_set_current_line(nline)
    end
  end)
end
commands.add("ZkYankName", function(options) yankName(options, { title = "Zk Yank" }) end)

This inserts a link to the full path (see note.absPath) but I can't figure out how to access the title etc (I tried note.title and am not getting anything). Any ideas?

Once I get this working I'll probably also tweak it to put the link in the main register instead of insert it. With that, it'd also be cool to be able to pick a bunch of them out in multiselect. Is it easy to do that too?

Thank you!

mickael-menu commented 2 years ago

By default zk.list (used by zk.pick_notes) returns a limited number of properties, that you can customize with the option select:

As the output of this command might be very verbose and put a heavy load on the LSP client, you need to explicitly set which note fields you want to receive with the select option. The following fields are available: filename, filenameStem, path, absPath, title, lead, body, snippets, rawContent, wordCount, tags, metadata, created, modified and checksum. https://github.com/mickael-menu/zk/blob/main/docs/editors-integration.md#zklist

However, the default should already contain the title, I'm not sure why you can't read it:

https://github.com/mickael-menu/zk-nvim/blob/fab4bb7fd95edd9eaab7cd7bb517a291351e0574/lua/zk/pickers/telescope.lua#L13

But for your use case, I think zk.list should be able to return a properly formatted link (using the config template) relative to the current document.

nathanbraun commented 2 years ago

Ok great. I tried it again and note.title and note.path both work, not sure what was happening before.

So this works:

local function yankName(options, picker_options)
  zk.pick_notes(options, picker_options, function(notes)
    local pos = vim.api.nvim_win_get_cursor(0)[2]
    local line = vim.api.nvim_get_current_line()

    if picker_options.multi_select == false then
      notes = { notes }
    end
    for _, note in ipairs(notes) do
      local nline = line:sub(0, pos) .. "[" .. note.title  .. "]" .. "(" .. note.path .. ")" .. line:sub(pos + 1)
      vim.api.nvim_set_current_line(nline)
    end
  end)
end
commands.add("ZkYankName", function(options) yankName(options, { title = "Zk Yank" }) end)

I'm not sure what you mean by using the config template. Is there someway to check the current config inside zk and return the proper type based on whether it's markdown, wiki etc?

mickael-menu commented 2 years ago

I'm not sure what you mean by using the config template. Is there someway to check the current config inside zk and return the proper type based on whether it's markdown, wiki etc?

You can customize the format zk uses to generate links, for example when you auto-complete links with [[:

https://github.com/mickael-menu/zk/blob/main/docs/note-format.md#customizing-the-markdown-links-generated-by-zk

If there was an additional link field returned by zk using this template you could have the same result as the [[ auto completion.

nathanbraun commented 2 years ago

If there was an additional link field returned by zk using this template you could have the same result as the [[ auto completion.

So you're saying I can modify my zk.pick_notes call somehow to return a link that will be automatically formatted? I played around with trying to pass that but haven't gotten it to work yet (my lua isn't great though).

In the meantime this is working for what I need:

local function yankName(options, picker_options)
  zk.pick_notes(options, picker_options, function(notes)
    local pos = vim.api.nvim_win_get_cursor(0)[2]
    local line = vim.api.nvim_get_current_line()

    if picker_options.multi_select == false then
      notes = { notes }
    end
    for _, note in ipairs(notes) do
      local nline = line:sub(0, pos) .. "[" .. note.title  .. "]" .. "(" .. note.path .. ")" .. line:sub(pos + 1)
      vim.api.nvim_set_current_line(nline)
    end
  end)
end
commands.add("ZkYankName", function(options) yankName(options, { title = "Zk Yank" }) end)

But it seems like what you're suggesting would make it more flexible for other types of links? Could be something to look at at some point.

mickael-menu commented 2 years ago

So you're saying I can modify my zk.pick_notes call somehow to return a link that will be automatically formatted? I played around with trying to pass that but haven't gotten it to work yet (my lua isn't great though).

Yes but this is not supported yet, I'll take a look into it.