- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 168
feat: allow to define multiple todo keyword sequences #974
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
feat: allow to define multiple todo keyword sequences #974
Conversation
fc18036    to
    2d74d78      
    Compare
  
    | @kristijanhusak It seems, that the indentation test is a bit flaky (those are the both failing test). It also failed occasionally locally on my machine, but that is unrelated to my changes. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left few comments around the code, some around code styling changes (mostly around avoiding else when there's early return), and some comments around the logic.
I think we should approach this in a slightly different , and potentially simpler way:
- Always store the todo keywords as sequences. You already did that here more-less, but there's no need have a separate logic like parse_single_sequenceorparse_multiple_sequence. WhenTodoKeywordsget'sorg_todo_keywordsvalue, just check if it's astring[]orstring[][]. If it's former, just convert it tostring[][]and handle it accordingly.
- Instead of keeping the sequence index on the TodoKeyword, andsequenceson theTodoKeywords, we can just search things on the fly. These things are used only when mutating the document, so it's not that necessary to do these optimizations. Lua is fast enough to handle this, and I doubt users have a lot of todo sequences.
Another approach could be to keep the TodoKeywords as they are, which is basically as single sequence, and have a layer above that will know to figure out which of the sequence we need at the given point, and just return it and use it where necessary.
This might complicate some other things so it might not be the best idea, but I wanted to point it out.
Let me know what you think.
| self:_parse_single_sequence(self.org_todo_keywords) | ||
| return | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just return directly here, method returns void anyway. Same for the if below.
| self:_parse_single_sequence(self.org_todo_keywords) | |
| return | |
| return self:_parse_single_sequence(self.org_todo_keywords) | 
        
          
                lua/orgmode/objects/todo_state.lua
              
                Outdated
          
        
      | return keyword | ||
| -- When we're starting from an empty state and moving backward, | ||
| -- go to the last todo keyword of the last sequence | ||
| else | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need for else block when if block returns. It removes one level of indentation.
| used_shortcuts[todo_keyword.shortcut] = true | ||
| elseif not used_shortcuts[todo_keyword.shortcut] then | ||
| -- Mark it as a fast access key when we have multiple sequences | ||
| if type(self.org_todo_keywords[1]) == 'table' and #self.org_todo_keywords > 1 then | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having multiple sequences doesn't necessarily mean we use fast access. When there is no fast access defined in the config of the todo keywords, Emacs just cycles through the sequence it figured out that is being used.
There's a catch though. Emacs somehow keeps in memory which was the last sequence used. For example, if you have these keywords:
(setq org-todo-keywords
      '((sequence "TODO" "|" "DONE")
        (sequence "REPORT" "BUG" "TESTING" "|" "FIXED")))And you have a headline with * REPORT foo, cycling without the fast access will go REPORT -> BUG -> TESTING -> FIXED -> {EMPTY} -> REPORT -> etc.. So it keeps in memory that the last sequence is 2nd one. Now, if you switch to an empty headline without todo keyword, restart emacs, and try switching the todo state, it will use the first sequence. So it's only in memory while the emacs is open.
I'm not sure what's the best way to access that issue, but I wanted to bring it up in case you have some ideas.
2d74d78    to
    68597a8      
    Compare
  
    8148136    to
    ddf3801      
    Compare
  
    ddf3801    to
    ea8b362      
    Compare
  
    e1f8a89    to
    0b75b39      
    Compare
  
    | @kristijanhusak Thanks for the feedback! I've implemented most of your suggestions: Simplified parsing and code style: 
 Regarding the sequence index approach: cycles  stays within that sequence. Without sequence_index, we can't determine which sequence a keyword belongs to, especially when keywords are duplicated across sequences (like having "TODO" in both bug and feature workflows). The next step would be implementing proper cycling behavior instead of jumping to fast access mode in a separate PR, which is where this becomes important. What do you think? | 
26af6c0    to
    f7a065d      
    Compare
  
    f7a065d    to
    4906c90      
    Compare
  
    ae38aa8    to
    de701e8      
    Compare
  
    | Hey @seflue , sorry for the delay! I didn't see any feedback on the PR comments and I thought you are still working on it. Can you just answer this comment: https://github.com/nvim-orgmode/orgmode/pull/974/files#r2083571890 Regarding this: 
 Just to confirm. Is this an answer to #974 (comment)? | 
| Hey @kristijanhusak , yes my comment was an answer to your review. Sorry that I didn't directly react to your code comments, it was a small amount of time I had to continue on this PR. I was pretty busy lately and still am, so I am not sure when I will find the time to continue on the multilevel cycling. Do you think, we can already merge this as a first step? | 
| Yes, I will give it a final test and it's probably good to go, but I want to reduce the amount of changes if possible. If we can just revert that refactoring that was done for the repeating task it should be good to go. | 
4906c90    to
    b636e61      
    Compare
  
    b636e61    to
    e4eee3e      
    Compare
  
    e4eee3e    to
    c1db178      
    Compare
  
    c1db178    to
    5ecfd71      
    Compare
  
    | @kristijanhusak Sorry for the long delay, I just didn't found the time to get back to this PR in the last month. I reverted the refactoring as you requested, hopefully it is now ready to merge. | 
5ecfd71    to
    1aaa3b7      
    Compare
  
    They can be defined in the config or within an org file.
1aaa3b7    to
    e2f32d0      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is good to go now. I'll do some minor changes around building the TodoKeywords, but nothing major.
Next up we should remove the fast access if not declared, and document this.
Thanks for the PR and the patience!
They can be defined in the config or within an org file.
Summary
This PR adds the ability to define multiple todo keyword sets as described in Orgmode manual.
Related Issues
Relates to #250, #157, PR #956
Closes #250
Changes
org_todo_keywordsallows to define a table of keyword sets#+TODO:directivesorg_todokeymap triggers fast access mode to select a keywordorg_todo_prevbehaves likeS-RIGHTin Emacs OrgmodeFalling back to fast access mode when multiple sets are defined is a bit of a shortcut to get a first version of this feature out of the door. Emacs Orgmode defines some additional keybindings to switch between keyword sets. This is a bit more elaborated and could be implemented in a further PR.
Checklist
I confirm that I have:
Conventional Commits
specification (e.g.,
feat: add new feature,fix: correct bug,docs: update documentation).make test.