lervag / wiki.vim

A wiki plugin for Vim
MIT License
656 stars 69 forks source link

Feature request - Treesitter plugin support - add link #329

Closed ForecastHealth closed 9 months ago

ForecastHealth commented 10 months ago

This is really a question: Does the following thing exist?

The bottleneck in me adding links is:

  1. manually typing links
  2. selecting the whole name of the link
  3. remembering whether I have written the correct name of the link (was it foo_bar? or bar_foo?)

A great addition was @lervag 's reference of their dotfiles, where they add the treesitter files_wiki function.

I was wondering if anyone had implemented a similar add_link function. I would do it myself, but I am confused about pathing e.g. if you are in a journal, how do you link back to the root etc.

So a minimal example might be

-- local sorters = require("telescope.sorters")
function M.files_wiki()
  builtin.find_files({
    prompt_title = "Wiki files",
    cwd = '~/foo',
    disable_devicons = true,
    find_command = { "rg", "--files", "--sort", "path" },
    file_ignore_patterns = {
      "%.stversions/",
      "%.git/",
    },
    path_display = function(_, path)
      local name = path:match "(.+)%.[^.]+$"
      return name or path
    end,
    attach_mappings = function(prompt_bufnr, _)
      actions.select_default:replace_if(function()
        return action_state.get_selected_entry() == nil
      end, function()
        actions.close(prompt_bufnr)

        local new_name = action_state.get_current_line()
        if new_name == nil or new_name == "" then
          return
        end

        vim.fn["ADD_LINK_APPROPRIATELY"](new_name)
      end)

      return true
    end,
  })
end

Where "ADD_LINK_APPROPRIATELY" is the function that adds a link to the root / journal correctly.

lervag commented 10 months ago

A great addition was @lervag 's reference of their dotfiles, where they add the treesitter files_wiki function.

Hmm; do you mean Telescope?

So a minimal example might be

vim.fn["ADD_LINK_APPROPRIATELY"](new_name)

Where "ADD_LINK_APPROPRIATELY" is the function that adds a link to the root / journal correctly.

So, essentially, you want an API function to add a link to a target location at the cursor position. E.g., in Vimscript notation, something like this:

" Add link to target at the cursor position
call wiki#link#add_at_cursor(target)

" Add link to target at the specified location
call wiki#link#add(target, location)

where target should be a link URL. These functions do not exist, but the related wiki#link#templates#TYPE(url, text) do exist. This works like so:

local link = vim.fn["wiki#link#templates#md"](link_url, link_text)

-- url  = "/index"
-- text = "My wiki index"
-- link ā†’ "[My wiki index](/index)
ForecastHealth commented 10 months ago

Thanks, and sorry for the confusion: telescope is what I meant, yes. I might have a play around with "wiki#link#templates#md then, thanks for your help.

lervag commented 10 months ago

Thanks, and sorry for the confusion: telescope is what I meant, yes.

šŸ‘šŸ»

I might have a play around with "wiki#link#templates#md then, thanks for your help.

Great. I might consider adding some functions like what you are asking for when I get the time. In the meantime, if you do play around and find something that seems to work, please feel free to share it.

ForecastHealth commented 10 months ago

That would be great. And yep, i'll let you know!

lervag commented 9 months ago

I realize I forgot about an essential and more convenient template function: wiki#link#template(URL, TEXT). This function will create a link string based on your g:wiki_link_creation settings.

lervag commented 9 months ago

I've added an initial version of wiki#link#add. It works like this:

" Adds link to "my url" at cursor position
call wiki#link#add("my url")

" Adds link to "my url" with given link text at cursor position
call wiki#link#add('my url', { 'text': 'My link text' })

" Adds link to "my url" at line 5 column 30
call wiki#link#add('my url', { 'position': [5, 30] })

The second argument is optional; if you pass it it must be a dictionary with one or both of these keys:

{
  'text': 'Link text',
  'position': [line_number, column_number],
}

You can use it in Lua with vim.fn["wiki#link#add"](URL[, option_table]).

Please let me know if this is close to what you are looking for. If it is, I'll document it and add some tests.

ForecastHealth commented 9 months ago

Hi, thanks for this. That function is exactly right, and the goal would be to implement it similar to pages, tags and toc e.g.

vim.g.wiki_select_method = {
  pages = require("wiki.telescope").pages,
  tags = require("wiki.telescope").tags,
  toc = require("wiki.telescope").toc,
}

So that when adding a link, you are prompted to select from your pages.

lervag commented 9 months ago

Hi, thanks for this. That function is exactly right, ā€¦

Cool, glad to hear it!

and the goal would be to implement it similar to pages, tags and toc e.g. ā€¦

Is this something you are comfortable looking into yourself or something you think should be added as part of wiki.vim?

ForecastHealth commented 9 months ago

Is this something you are comfortable looking into yourself or something you think should be added as part of wiki.vim?

It's probably not something i'm comfortable with (I have no lua / vim experience!). Whether or not it should be added as part of wiki.vim is really up to you. However I would add that most wiki/note-taking applications would have an "add link" as a standard feature (thinking of roam, obsidian, notion, but presumably org-mode although I can't remember at the moment)?

lervag commented 9 months ago

Ok, I've added a command WikiLinkAdd with a normal mode and insert mode mapping <plug>(wiki-link-add) now. It is still work in progress and undocumented. I've used <f5> as the current default mapping. I would be glad to get some feedback:

ForecastHealth commented 9 months ago

Thanks Karl, I'll get on this

ForecastHealth commented 9 months ago

Thanks Karl,

I've updated to the latest commit and originally was playing around with WikiLinkAdd using ui_select . But, to be very honest, I don't really understand how to interact with that list. When I run WikiLinkAdd, it brings up all the several thousand notes I have, all numbered, with the -- More --, and I have no sensible way to select anything. This isn't a fault of wiki.vim of course, it's just that i'm very naive, and don't really understand how to use that selection mode.

However, I hacked up a telescope function (see below), and that works as I would expect. That is, on calling WikiAddLink, the telescope prompt is brought up, and I can search my notes, and it adds the link as expected.

Thanks very much for your help, it's been a profound improvement to my notetaking.

function M.links()
  local pages = vim.fn["wiki#page#get_all"]()
  local formatted_pages = {}

  -- Format each page for display
  for _, page in ipairs(pages) do
    local display_path = page[2]:sub(1,1) == "/" and page[2]:sub(2) or page[2]
    table.insert(formatted_pages, {value = page[1], display = display_path})
  end

  pickers.new({}, {
    prompt_title = "Insert Wiki Link",
    finder = finders.new_table {
      results = formatted_pages,
      entry_maker = function(entry)
        return {
          value = entry.value,
          display = entry.display,
          ordinal = entry.display,
        }
      end,
    },
    sorter = conf.generic_sorter({}),
    attach_mappings = function(prompt_bufnr, _)
      actions.select_default:replace(function()
        local selection = action_state.get_selected_entry()
        actions.close(prompt_bufnr)
        if selection then
          local root = vim.fn["wiki#get_root"]()
          local url = vim.fn["wiki#paths#to_wiki_url"](selection.value, root)
          vim.fn["wiki#link#add"](url)
          -- Optionally, enter insert mode after adding the link
          -- vim.cmd "startinsert"
        end
      end)
      return true
    end,
  }):find()
end
ForecastHealth commented 9 months ago

And just as a note, I reconfigured f5 to f6, as f5 conflicts with the standard DAP keymaps.

lervag commented 9 months ago

I've updated to the latest commit and originally was playing around with WikiLinkAdd using ui_select . But, to be very honest, I don't really understand how to interact with that list. When I run WikiLinkAdd, it brings up all the several thousand notes I have, all numbered, with the -- More --, and I have no sensible way to select anything. This isn't a fault of wiki.vim of course, it's just that i'm very naive, and don't really understand how to use that selection mode.

Ah; you've set the g:wiki_select_method option, probably, and thus overridden the default. Or, perhaps more likely, you have not configured Telescope to be your vim.ui.select provider.

However, I hacked up a telescope function (see below), and that works as I would expect. That is, on calling WikiAddLink, the telescope prompt is brought up, and I can search my notes, and it adds the link as expected.

This is what I expected my last commit to provide. But it does require Telescope to be your vim.ui.select provider. I do that by use of dressing.nvim; my config is here.

Thanks very much for your help, it's been a profound improvement to my notetaking.

I'm glad to hear that! <3

function M.links()
-- ā€¦
end

Clearly, you can just do it like this. However, if we can provide this from wiki.vim, it would be easier to combine efforts to have it work better for everyone.

And just as a note, I reconfigured f5 to f6, as f5 conflicts with the standard DAP keymaps.

I'm curious, though; should we use some CTRL-... keybinding instead? My intuition is that we should use something like <leader>wā€¦ binding for normal mode and some CTRL-ā€¦ for insert mode.

ForecastHealth commented 9 months ago

Thanks for the comments Karl.

I find that reaching for f6 is not as streamlined as it could be, so your suggestion for <leader>w... and CTRL-... could be a good idea.

Interestingly, with my current set-up, in insert mode, when I call WikiLinkAdd, it places an A in the start of the search. This does not happen in normal mode. I'll investigate by removing the function I added, and trying dressing.nvim. Thanks for the recommendation.

ForecastHealth commented 9 months ago

Yep, changed to dressing.nvim and changed back to

vim.g.wiki_select_method = {
  pages = require("wiki.ui_select").pages,
  tags = require("wiki.ui_select").tags,
  toc = require("wiki.ui_select").toc,
  links = require("wiki.ui_select").links
}

Rather than "wiki.telescope".

This fixed the problem with the capitalised "A" appearing in the search box after calling WikiLinkAdd in insert mode.

lervag commented 9 months ago

ā€¦ changed back to

vim.g.wiki_select_method = {
  pages = require("wiki.ui_select").pages,
  tags = require("wiki.ui_select").tags,
  toc = require("wiki.ui_select").toc,
  links = require("wiki.ui_select").links
}

You don't need to set that since it is the default value.

Now, it seems you are more or less happy with the current state, which means the remaining work is:

lervag commented 9 months ago

Oh, I'm very sorry! I've completely forgotten that I already had wiki.telescope and I missed that you were changing to this version! My bad! I'll implement both the telescope version and fzf version, then!

lervag commented 9 months ago

I've pushed an update that changes to these default mappings: <leader>wa from normal mode and <c-a> in insert mode. I've also added documentation and I've started to add the fzf version.

lervag commented 9 months ago

Now I've added docs, added fzf and Telescope version, and I think things should mostly work as expected. Please let me know otherwise! Also, feel free to comment on the documentation - is it good enough?

ForecastHealth commented 9 months ago

Thanks Karl,

<leader>wa and <c-a> are intuitive I think. I have no pre-existing keymaps on those mappings.

One thing, and I wonder if this is a separate GitHub issue: Would you want to integrate this with WikiOpen? That is, a function that either adds a pre-existing link, or creates a new link.

In my day-to-day use, I'm not often sure if I've created a note for, say, foo.md, and if it doesn't exist, it would be useful to be able to create it from the same function. Simply adding it by highlighting it and pressing <CR> or calling WikiOpen is also straightforward of course.

ForecastHealth commented 9 months ago

Documentation looks good too!

lervag commented 9 months ago

<leader>wa and <c-a> are intuitive I think. I have no pre-existing keymaps on those mappings.

<c-a> in insert mode is actually a built-in mapping (to insert last inserted text). But I believe it is a relatively small group of people who even know about it. I know of it, but I never use it. And I like the a for the "add" mnemonic here.

One thing, and I wonder if this is a separate GitHub issue: Would you want to integrate this with WikiOpen? That is, a function that either adds a pre-existing link, or creates a new link.

In my day-to-day use, I'm not often sure if I've created a note for, say, foo.md, and if it doesn't exist, it would be useful to be able to create it from the same function. Simply adding it by highlighting it and pressing <CR> or calling WikiOpen is also straightforward of course.

My workflow for this would be to use telescope version of WikiPages to search for a page. If it doesn't exist, then using <cr> will open that buffer (possibly with a template, if you use that) - and saving the buffer would create that page. In fact, I use a personal telescope based function for this instead of WikiPages (see here) - this is mostly for historical reasons, though.

I also often use the <cr> mapping from normal mode to create links from words, then <cr> again to open the link.

Now, perhaps your point was that you want want WikiLinkAdd to also allow adding a link to something that doesn't exist. E.g., if I from insert mode do <c-a>MyNewPage<cr>, then you would want [[MyNewPage]] to be created (or [](MyNewPage) or similar if you use other link types)?

Simply adding it by highlighting it and pressing <CR>

I assume you know this is already possible, right?

ForecastHealth commented 9 months ago

E.g., if I from insert mode do MyNewPage, then you would want [[MyNewPage]] to be created (or or similar if you use other link types)?

Correct, that is what I was imagining.

I assume you know this is already possible, right?

Sorry, yes! I was saying that I use this currently and it is also straightforward.

lervag commented 8 months ago

E.g., if I from insert mode do MyNewPage, then you would want [[MyNewPage]] to be created (or or similar if you use other link types)?

Correct, that is what I was imagining.

Ok! Well, this is not possible with vim.ui.select, unfortunately. But it is possible with Telescope and fzf, so I've updated the implementations correspondingly. Thus, if you want this, you need to change the wiki_select_method for the .links key.

ForecastHealth commented 8 months ago

Thanks very much!

lervag commented 8 months ago

Glad to help; and thanks for opening this issue. I think you are correct that this feature is relevant and that it may be useful to a lot of people.

ForecastHealth commented 8 months ago

Cheers!