Skip to content
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

Sort/remove entries based on whether they are checked or not #17

Open
thegoodhen opened this issue Jul 15, 2015 · 17 comments
Open

Sort/remove entries based on whether they are checked or not #17

thegoodhen opened this issue Jul 15, 2015 · 17 comments

Comments

@thegoodhen
Copy link

It might be useful to add an option to make the resolved issues fall to the bottom so they don't mix with the resolved ones as well as to delete the resolved ones.

I think the built-in :sort command of Vim with its range set by some clever regular expressions could do the trick. I'll look into it!

@vitalk
Copy link
Owner

vitalk commented Jul 15, 2015

Looks promising!

@thegoodhen
Copy link
Author

Okay, well. Almost there. It turned out to be a bit more complicated than I expected.

I figured the best way will be to let the user select the block he wants to sort and then do operation on it.

If the [ ] is at the beginning of each line and each task is on a separate line, this is trivial and only
requires remapping keys to :sort or :sort! ex commands.

However, if a task spans across multiple lines, and/or if the checkbox is at the end of each line, this is a bit less trivial.

I'll take another look into it! It's almost done, but it's still a bit silly.

@vitalk
Copy link
Owner

vitalk commented Jul 16, 2015

if the checkbox is at the end of each line

What do you mean? I don't see any reason to pull checkbox to the end.

@thegoodhen
Copy link
Author

Well, as in:

Shopping list

Rolls: [x]
Bananas: [x]
Other stuff: [ ]

@vitalk
Copy link
Owner

vitalk commented Jul 16, 2015

@thegoodhen thank you for clarification, I never use this format before.

@thegoodhen
Copy link
Author

I just thought some may want to do that. Also, if it spans across multiple lines, it rules out the option to use :sort.
Instead, it seems like it will be necessary to append everything into a buffer. Right now I am able to copy all tasks that are marked as done into a register. I can't select range yet, the last task stays on its place and they all have one character from the line after them.

@thegoodhen
Copy link
Author

Hello! Believe it or not, I am working on it. :D Please, just tell me one thing. I cannot find it anywhere. How do you match following string? [] ?

I need this to be able to jump to the end of the line that is right before the line with a new task...

/$_.* matches nothing.

/[ and then k0 (as in, find it on this line, jump one line up and to the end of the line) causes problems.

I can't seem to be able to find any answer online...

@vitalk
Copy link
Owner

vitalk commented Jul 18, 2015

Did you mean match []? Use \ to escape it, e.g. \[\].

@thegoodhen
Copy link
Author

Nonono... I mean to match a regEx that starts with the "end of line" symbol...
/$_.* doesn't match anything...

@thegoodhen
Copy link
Author

Oh, sorry, I see it now. I have written a string here and it has been misinterpreted as xml tags, thus I am causing confusion. My original text was:

<end of line><any characters>[<any character>] ?

@vitalk
Copy link
Owner

vitalk commented Jul 18, 2015

$ actually marks the end of line, e.g. there is no characters after it.

If you provide an example of text you are working on, then maybe I can help you.

@thegoodhen
Copy link
Author

Hello. $ marks end of the line, but \_. marks any character... So I assumed it would match end of the line and the new line after it... similar to \_.*$ which matches from current position across first EOL up to another EOL. (by EOL I mean end of line...)

And well... So far I've got this:

vnoremap aa <esc>'<ma'>o[ ]TGH_LINE_FOR_REMOVAL_TGH<esc>mbqaq:'a,'bg/.*\[x\]\_.*\[.\].*$/normal! v/\[<C-V><C-M>k$"Ad<CR>

This is a temp thingy. What I want from it: Once you select text which has completed and uncompleted tasks in it, it should delete all completed tasks (even if the task spans across multiple lines) and append it to the register a.

How it should work:

vnoremap - remap when in visual mode
aa - two presses of a, this is temporary
<esc> -escape-get out of visual selection mode
'< - go to the beginning of last visual selection made (this works)
ma - add mark a here. (This is needed since we will be selecting stuff later and the '< and '> registers will get changed

'> -go to the end of last visual selection made
o - create a new line under it
[ ]TGH_LINE_FOR_REMOVAL_TGH - write this text on the new line. This is a dummy line. I will be finding text that spans from [x] up to next [.], but after the last task there is no [.]. By adding this line, I am making sure the last task is correctly detected. (By basically adding a dummy task after the last one). I will delete this line then (not implemented yet).
<esc> - press escape (exit insert mode, back to normal)
mb - add mark b here. Now our text for sorting spans between marks a and b

qaq-store an empty macro in register a. This is a trick to clear register a. equivalent of :let @a=''
: -go into ex mode

'a,'b - set range for next command to be from the mark a to the mark b
g/ - with each line matching a following regular expression, do something

.*\[x\]\_.*\[.\].*$ - a regexp to match one line containing [x] up to the next line containing [ ] or [x]
normal! -the command to be ran for each line should be to press following keystrokes in normal mode:

v/ -start selecting in visual mode up to the next occurance of a following RegEx
\[-up to next [
<C-V><C-M> - weeeell... Print the "end of line symbol"... Basically this will press "enter" . I couldn't write <CR>, as that would press enter immediatelly. This is like... Press enter in the normal mode to perform search. 
k-since the search has thrown us on the line with a next task, we need to move up one line now.
$ - and to the end of this line...
"Ad-and append the selection to register a
<CR>-this is the end of the ex command. Execute.


Aaaand it is buggy. When 2 tasks after one another are both checked, the second is skipped... I am not sure how to fix it. Also some odd problems occur with trailing whitespace before each line... I don't know.

@thegoodhen
Copy link
Author

Okay, seems like I am close to a solution now... It's kinda ugly but should work...

@vitalk
Copy link
Owner

vitalk commented Jul 18, 2015

I never like regexps (my favorite on xkcd https://xkcd.com/1171/). A long time ago when I created this plugin I used them to quickly toggle list markers, and nothing more.

As you said, the built-in :sort command is good for sorting single lines, but require a more complex logic for sorting multiline items. This regexp implementation:

  • reuse existing registers (a, b), which may rewrite important user's information
  • hard to understand and debug

This task require to rework core logic, e.g. detect each task item separately and then rearrange them while keeping internal state into script specific variables.

@thegoodhen how often do you sort your tasks? Looks like I'm able to sort them manually with any of existing plugins (vim-unimpaired or vim-move can rearrange lines in visual and normal modes).

@thegoodhen
Copy link
Author

Yea, I am starting to dislike them as well... Unfortunately, I am not yet too good with Vimscript... Maybe Java and embedded C, but not Vimscript... I am aware of the issue with the overwritten registers, but it looked extremely daunting to implement it any other way. I finally almost got it to work. Now I am in state where it sorts the list nicely, but only when you have the word "end" on the end of each task. (That was for debug purposes, but when I tried to change it to what it's supposed to be, it died on me. It just stopped working.)

I have a script that can delete all tasks marked as done. It doesn't use user registers and it's a simple regex search/replace. I guess I'll stop trying tomorrow and give you a pull request with at least that and then I'll be done with it. :D Sorry! At least I tried, sigh.

@vitalk
Copy link
Owner

vitalk commented Jul 18, 2015

No problem, thank you anyway. I keep this issue opened as the reminder.

@thegoodhen
Copy link
Author

As a reminder you can't always win against RegEx? :D

This. Is scary. But at like... 80% of cases, it kinda works.

vnoremap aa <esc>'<ma'>o[ ]TGH_LINE_FOR_REMOVAL_TGH<esc>mbqaq:'a,'bg/.*\[x\]\_.*\[.\].*$/normal! v/\[<C-V><C-M>$"Ay<CR>:'a,'bs/\zs.\{-}\[x\]\_.\{-}\n\ze.\{-}\[.\]//g<CR>:%s/\[ \]TGH_LINE_FOR_REMOVAL_TGH//g<CR>:nohlsearch<CR>'aO<esc>"ap

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

No branches or pull requests

2 participants