Skip to content

feature: add support for cookies #166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

lukas-reineke
Copy link
Contributor

Adds support for cookies in headlines and lists

https://orgmode.org/manual/Checkboxes.html

Add [/] or [%] to a headline or list with sub-items, and it should display the cookie.
It needs this to work emiasims/tree-sitter-org#11

fix #81


orgmode also supports this for TODO states if the cookie is in the headline. This PR does not cover that.

Comment on lines 72 to 50
local closest_parent = utils.get_closest_parent_of_type(checkbox, parent_type)
if closest_parent and closest_parent == parent then -- only count direct children
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it would be nicer if the query could do this directly, but I don't know if that is possible.

Copy link
Member

Choose a reason for hiding this comment

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

I'm thinking (I could be wrong, didn't try it) that this section could be done with an iter_children and some recursion. Basically, you find all checkboxes as a single list, iterate through them, check their children, and do a recursion if they have it. It might end up as more code, but I think it would be faster and easier to understand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it doesn't need recursion. It should only check the first level of checkboxes. The treesitter query finds all nested ones as well, so I had to do this hacky check.

The implementation with just iter_children isn't super pretty either, but you are probably right, it's easier to understand and faster

local function _get_cookie_checked_and_total(parent)
  local checked, total = 0, 0
  for child in parent:iter_children() do
    if child:type() == 'listitem' then
      for listitem_child in child:iter_children() do
        if listitem_child:type() == 'checkbox' then
          local checkbox_text = vim.treesitter.get_node_text(listitem_child, 0)
          if checkbox_text:match('%[[x|X]%]') then
            checked = checked + 1
          end
          total = total + 1
        end
      end
    end
  end
  return checked, total
end

@kristijanhusak
Copy link
Member

orgmode also supports this for TODO states if the cookie is in the headline. This PR does not cover that.

Can you give an example of this? I don't understand it.

@lukas-reineke
Copy link
Contributor Author

lukas-reineke commented Dec 1, 2021

and we check the last box, then TODO will be converted to DONE automatically

No, this is not what I mean.
TODO and DONE headlines can also be the source for cookies.
Like this:

* TODO bake a cake [3/6]
** DONE buy ingredients
** DONE start cooking
** DONE realize you forgot eggs, dammit
** TODO drive back to the store and buy eggs
** TODO wait, I needed THREE sticks of butter?
** TODO drive back to the store and just buy a damn cake

This is from the documentation

In a headline, a cookie can count either checkboxes below the heading or TODO states of children, and it displays whatever was changed last. Set the property ‘COOKIE_DATA’ to either ‘checkbox’ or ‘todo’ to resolve this issue.

And this PR only handles checkbox, not todo

text = '[0%]'
end
end
vim.api.nvim_buf_set_extmark(0, cookie_namespace, row, column + (leading_spaces or 0), {
Copy link
Member

Choose a reason for hiding this comment

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

Emacs orgmode is actually modifying the content for this instead of using something like virtual text. That's why they require [/] to be added to the end. I'd love to propose 2 solutions to this:

  1. Do the same thing that emacs does (Really replace the text)
  2. Implement this as a virtual text without a need for a user to type [/]

Current solution is kind of a hybrid, and I think having empty [/] as a content will cause confusion.
I'd love to go with 1st solution, since it copies the emacs orgmode functionality which I'm trying to achieve most of the time.
I know that 2nd solution is simpler, and we could have it enabled by default, and to allow it to be disabled through config.
If first one is too complicated, we can go with 2nd one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 I didn't know emacs modifies the file.
shouldn't be that hard to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updating the text in the buffer is very expensive.. it gets very slow even with only a couple cookies.
Maybe we use virtual text and only update the actual text on save?

Copy link
Member

Choose a reason for hiding this comment

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

@lukas-reineke how are you updating it? It should update only when you check/uncheck something, maybe you are triggering it more often. Maybe if you have file with several thousand lines, but even than shouldn't cause that many issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was updating all of them before, but yeah without virt text it makes much more sense to only trigger this on checkbox toggle.
I rewrote the logic to do this.
Added bonus, checkboxes update their parents now as well.

@@ -36,7 +41,115 @@ local function add_todo_keywords_to_spellgood()
end
end

local function _get_cookie_checked_and_total(parent)
Copy link
Member

Choose a reason for hiding this comment

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

Lets move this thing to a separate file, it's fairly big at this point.

@kristijanhusak
Copy link
Member

This looks ok to me for now. I'll wait for the upstream tree-sitter-org PR to get merged to test this. I'm just not sure why tests started to fail.

@lukas-reineke
Copy link
Contributor Author

The treesitter queries will need to be updated anyway after the change in tree-sitter-org.

I'll take a look at the tests then.

Do you want to keep support for 0.5 now that 0.6 is released? I think I used some 0.6 APIs.
Other plugins like nvim-lspconfig have already dropped support for 0.5, and it would make it easier. But I can try to make it work in 0.5 as well.

@kristijanhusak
Copy link
Member

Do you know what exactly did you use from 0.6? I would love to keep 0.5 support, but if it complicates things drastically, we could have a release before merging it.

@lukas-reineke
Copy link
Contributor Author

Oh maybe I didn't. I thought vim.treesitter.get_node_text and tsnode:named_child were 0.6, but I just checked and they are 0.5.
Maybe it's fine then. I'll write tests for this anyway, then we'll know for sure.

@YuCao16
Copy link

YuCao16 commented Mar 13, 2022

Is there any progress on this feature? Other than that, I think it might be useful if the concept of weights could be introduced.

Thanks for you work, enjoy this Plug so much!

@lukas-reineke
Copy link
Contributor Author

I am waiting on this emiasims/tree-sitter-org#13

Once that is done I can update this PR.

Is weights a native org feature?

@YuCao16
Copy link

YuCao16 commented Mar 13, 2022

I am waiting on this emiasims/tree-sitter-org#13

Once that is done I can update this PR.

Is weights a native org feature?

No, as far as I know it isn't. But weights can be very useful if you can prioritize checkboxes. But this is just an idea :D

@lukas-reineke
Copy link
Contributor Author

I agree it could be useful, but if it is not in org, it will most likely also not make it in this repo.

@YuCao16
Copy link

YuCao16 commented Mar 13, 2022

I agree it could be useful, but if it is not in org, it will most likely also not make it in this repo.

I totally understand and look forward to the cookie going merge soon, thank you for your work.

@PhosCity
Copy link

PhosCity commented Apr 9, 2022

I am waiting on this milisims/tree-sitter-org#13

Once that is done I can update this PR.

milisims/tree-sitter-org#13 has been closed. Will there be any update to this? It would be wonderful to have this feature in the plugin.

@lukas-reineke
Copy link
Contributor Author

I will finish this. Just have to see when I can find some time.

@gerazov
Copy link
Contributor

gerazov commented Apr 15, 2022

This is awesome 😎

I saw it's mentioned but atm will it also work with TODO/DONE cookies as well?

@kristijanhusak
Copy link
Member

Closing in favor of #287

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.

Auto-updating checkbox cookies
5 participants