vit-project / vit

VIT is a lightweight, fast, curses-based front end to Taskwarrior
MIT License
496 stars 52 forks source link

Methods for modifying multiple tasks #240

Open jmriego opened 4 years ago

jmriego commented 4 years ago

Hi! First of all, thank you for your hard work. I found out very recently about vit and I find it amazing. I can't believe it's not a lot more popular between the Taskwarrior tools!

I was trying to make changes in multiple tasks at the same time and was wondering if there's some way of doing this.

The two ways I would think of are similar as what you would do in vim:

  1. Mark multiple tasks with something like mt and then you run a command that would affect all of them. This should also work for when you have mappings that use the task UUID and would run them multiple times with a different UUID each
  2. Add a . mapping that will repeat the previous action. In my opinion itt would also have to work for things like :!rw task .... so it would be a bit different of the same mapping in vim that don't include :commands.

Does this sounds like something that could be added? Thanks!

jmriego commented 4 years ago

I suppose another option would be a v or V mapping to start a selection but that would require the tasks you want to modify to be next to each other

thehunmonkgroup commented 4 years ago

Multi-task operations have been on my wish list for awhile.

It's not something I have time to implement now, but I'd be happy to look at a PR for it.

I do suspect the implementation will be a lot trickier than you may imagine. Adjusting the interface to display multiple selections and operate on multiple tasks will likely involve some fairly major refactors, and a poor implementation would likely be pretty buggy.

jmriego commented 4 years ago

I can imagine! That's why I mentioned several methods that could potentially work. As you said, there's the interface part with also changes in the highlighting. You have to think about multiple types of changes and running task commands that you don't know what could affect... So I think the easiest method would probably be the dot, but what do you think? I might have time to have a look at the code if that makes sense

thehunmonkgroup commented 4 years ago

The dot would probably be a good start. I still think that might have some dragons in it, but conceptually, "store last action, repeat when told" seems fairly straightforward.

Also, I think even if we start here, adding the multiple highlighting later wouldn't conflict, it would just be another usable method.

thehunmonkgroup commented 4 years ago

267 is taking a first stab at this, still a long ways to go...

kevinstadler commented 3 years ago

Since bulk-editing is also a feature I'd really like to be able to use from within vit I've had a little look at the code. Here's some ideas, would love to hear some feedback before I go forward and actually implement anything:

With these two things in mind I think there could be a nice 3-step roadmap, each of which provides new functionality that builds/relies on the previous ones:

  1. expose current filter as well as the underlying filters of the current report via variables that users can use in their macros to make external calls like :!rw task {VIEW_FILTER} modify ...
  2. for each task operation that supports bulk editing, add a TASK_*_BULK action to the already existing ones, making sure that vit's underlying task invocation functions support filter expressions and task-list targets https://github.com/vit-project/vit/blob/62273a260db5e2594ed46c6531a0c35fa85dea03/vit/application.py#L737-L784
  3. add support for manual task selection (like in the pull request above), with the selection list populated by the UI seamlessly passed through to the newly added _BULK commands

I'd be keen to get some work done on this (especially step 1) soon, so let me know what you think!

thehunmonkgroup commented 3 years ago

@kevinstadler on first read, this sounds like a solid plan. I'm a little concerned about ripping out the tasklib stuff and replacing it with direct calls to the task binary -- it's been so long since I coded that, I can't remember what the specific advantages were when using tasklib. I'm sure there were some ;)

At the same time, it's always felt clunky to me to have that hybrid model of tasklib/task binary. If we went the route you're proposing, perhaps we should expunge tasklib (at least for all the write operations).

If you want to take a crack at the PR, I'll commit the time to review and offer suggestions/improvements. I agree that having this feature would be a big plus, and I don't have the time to code it. As long as the code is clean and maintainable, we can get it in.

scottkosty commented 3 years ago

Thanks for working on this!

I did not read the details, but would it make sense to add the under-the-hood work to tasklib? Is the library still maintained? It seems these features might be useful to other Taskwarrior tools that rely on tasklib. I don't know anything about it though so perhaps it is inherently out of the scope of tasklib.

Regarding the interface, two tools that I've used as inspiration for working on vit are mutt and ranger. Multiline (non-consecutive) selections are more natural in those two tools than in Vim so their interfaces might provide some good inspiration.

Again, thanks for your time on this! It is a feature that has been requested by a lot of users over the years and no one has dared to jump down the rabbit hole :)

thehunmonkgroup commented 3 years ago

I did not read the details, but would it make sense to add the under-the-hood work to tasklib?

The problem with that is that the task binary is so darn flexible. I think it's going to be a challenge to account for all that we want to support only using tasklib. The project is still maintained, so it might be worth filing a ticket to see what the dev says.

scottkosty commented 3 years ago

The problem with that is that the task binary is so darn flexible. I think it's going to be a challenge to account for all that we want to support only using tasklib. The project is still maintained, so it might be worth filing a ticket to see what the dev says.

Ah that is good to know. Thanks. Sounds like it might be one of those "sure that's the nice thing to do in theory but in practice it makes things a lot more complicated" things.

tbabej commented 3 years ago

Hey guys,

just randomly chiming in here, but I'm wondering if you want to jump on a call to discuss this? I wrote like ~70% of tasklib and if my memory serves me right, it covers a pretty broad range of use cases. I am using it quite successfully in taskwiki.

kevinstadler commented 3 years ago

I didn't even realise that tasklib was being used, as the modify command that I looked at already executes task directly via the application's self.execute_command() (same as at least 6 other commands, in particular undo, sync, edit, info, add and context). I wonder if the choice not to go through tasklib for these was the fact that many of them are quite complex so that their failure might require interactive prompting, which is then automatically handled by task?

Unless you want to make a push towards passing modify through tasklib as well, the current code: https://github.com/vit-project/vit/blob/62273a260db5e2594ed46c6531a0c35fa85dea03/vit/application.py#L361 can already support bulk-editing via any of the following minimal changes:

thehunmonkgroup commented 3 years ago

@tbabej @kevinstadler I'm game to jump on a call to discuss the best implementation.

Again, it's been so long since I built those pieces, I cannot recall the precise reasoning. I do remember that I tried to use tasklib as much as possible, and where I couldn't figure out how to use it, I fell back to the task binary directly.

I'm a little concerned about scope creep if we elect to run everything through tasklib. I guess it depends how hard that is, I haven't studied that code enough to have an opinion.

kevinstadler commented 3 years ago

Just to point out that any decision to change operation execution from task to tasklib is independent of the present multiple-task-modification issue, as the current implementation already supports batch operations (at least for modify). The biggest part of step 2 (adding TASK_*_BULK operations) concerns how command arguments should be represented within vit. If it turns out that tasklib is an option for batch modification as well, then the actual external execution can still be swapped in/out without affecting vit's internal processing of batch modifications.

I've had a go at streamlining access to all current filter information within vit and providing access to them via keybinding replacements. I wasn't 100% sure about naming conventions in the codebase, so please have a look and let me know if it looks alright to you so far!

kevinstadler commented 3 years ago

After #290 is merged, it will actually be possible to achieve @jmriego's use case by means of a workaround that uses a tag (say selected) for marking tasks as selected, then filtering the view for all +selected tasks before calling {ACTION_TASK_MODIFY_ALL}:

[keybinding]

# select/de-select tasks by applying a `selected` tag (assumes default m = {ACTION_TASK_MODIFY} to work)
n = m+selected<Enter>
N = m-selected<Enter>

# could use a nice chunky `tag.selected.label = ✓` to visually mark selected tasks

# bind bulk modification to some key, just so it can be used by the actual command below
@ = {ACTION_TASK_MODIFY_ALL}
# prompt modification of all +selected tasks (assumes default f = {ACTION_REPORT_FILTER} to work)
M = f+selected<Enter>@-selected<Space>

Note that the above will also apply to any +selected tasks which were hidden from view because of extra filters that were active at the time of hitting M. Because {ACTION_REPORT_FILTER} overrides (rather than appends to) the extra filters, to be absolutely accurate one would still require access to the current extra filter information through variable replacement (see #289), then use the following:

M = f({REPORT_FILTER_EXTRA}) +selected<Enter>@-selected<Space>
thehunmonkgroup commented 3 years ago

This hadn't occurred to me, and is a brilliant use of the existing tools.

Have a look at my proposal in https://github.com/vit-project/vit/issues/291 -- I think this could be fairly easy to implement, solve this issue more elegantly, and offer other benefits in the future.

yukiohmiya commented 3 years ago

At first, Thank you for doing good job, and I've used vit everyday. I implemented about multi-select operation.In my opinion, I think I want to use more simple method in this issue.

https://github.com/yukiohmiya/vit/tree/feature/multiple_select

I implemented this multi-select operation by following flow.

  1. Select a task by v command. Add selected task_id to bulk_id list.
  2. If you select same task again by v, Delete selected task_id from bulk_id list.
  3. If you push ESC key, Clear all bulk_id list.
  4. Output bulk_id list after :!rw task whne you push t command.

This implementation works well in my environment. I want to hear your opinion.

Tanks.

https://user-images.githubusercontent.com/22073586/126651856-1dc7bafc-d02e-4f1f-87d8-542c3fc3d60a.mp4

jmriego commented 3 years ago

thanks a lot @yukiohmiya ! This looks really promising

Some feedback I can think of: When I use the {bulk_id} in a mapping for some reason it seems to be using the id instead of the uuid. Even in your video you get something like :!rw task 4 5 instead of !rw task abd-1234-abc def-4567-dfe which would be safer

Also, do you think instead of creating {BULK_ID} it would make sense to make {TASK_UUID} have the value of the bulk list if there's a multiple selection or the current row if not? That way I can use the same mapping for both multi and single selection

yukiohmiya commented 3 years ago

@jmriego Thanks for your feedback!!

I use buld_id because I want to display command more simply and I don't know difference task id from uuid. I realized maintainer use uuid in vit source code now.

I agree with your idea using uuid and {TASK_UUID}. I'm going to update my code.

lyndhurst commented 1 year ago

Hi,

I was about to ask about the possibilities of adding this feature to vit, and I see people have already done some work on this. I was wondering if this feature plan was still alive...

Thanks again for this great tool, and all the work from the maintainer and contributors to make it even better !

thehunmonkgroup commented 1 year ago

@lyndhurst https://github.com/vit-project/vit/pull/290 was the main thrust of this feature request, and if you read that issue, you'll see it got hung up on some key naming/convention decisions.

Someone will need to pick up that PR and continue it pushing it forward if we want to see this in.

lyndhurst commented 1 year ago

Thank you for the pointer, I am going to read it carefully so I will hopefully understand the issue better.