fidget.nvim icon indicating copy to clipboard operation
fidget.nvim copied to clipboard

Delay before showing progress

Open ratmice opened this issue 3 years ago • 6 comments

One thing I have noticed is that if a task completes very quickly sometimes it takes longer to display the fidget than the task itself. Perhaps it would be nice to have an option to time delay showing the fidget, and only after that time if it is still running show progress.

ratmice avatar Apr 27 '22 14:04 ratmice

Can you give an example of such a task? I can see how this might be useful, but adding some kind of "high pass filter" logic could significantly complicate the logic of the current implementation.

In particular, the $progress endpoint receives messages that comprise a task, and we can't tell from individual messages whether the task is short- or long-lived. So we'd have to start little one-shot timers every time we receive a start message, and cancel those timer threads on subsequent report messages, but let the timer expire if we receive an end message. Or we could do the same thing but implemented using timestamps rather than threads.

But then I worry that doing so much to distinguish between message types is only going to make it more complicated to handle language servers that don't seem to conform to the progress protocol as precisely.

j-hui avatar Apr 27 '22 16:04 j-hui

In the lsp i'm developing, https://github.com/ratmice/nimbleparse_lsp which builds a lex/yacc grammar, on grammar edit, it starts a server side task, which then parses a bunch of test cases.

The behavior is a lot better than I thought, (I had accidentally running with a delay on the server side so that I could even see the progress in vscode), but still when editing fidgets sometimes stack up, when the server abandons a task and starts up a new one due to a new edit that has arrived.

ratmice avatar Apr 27 '22 16:04 ratmice

Oh neat! How does VScode respond when it's flooded with short-lived notifications?

j-hui avatar Apr 27 '22 16:04 j-hui

It appears to just not show anything either in the status line, or the fidget-similar window you can get by clicking tasks in the status line, I could do a little fiddling and see if I can come up with number on how long a task takes before it starts showing them.

ratmice avatar Apr 27 '22 16:04 ratmice

The delay doesn't seem particularly stable, e.g. between 200ms up to as high as 400 ms, I have seen no progress, I'm guessing that rather than a delay it might just be putting things onto a data structure, and popping them off as the achieve WorkDone, and then if they get pushed and popped, before some refresh rate the statusline/fidget never notice perhaps.

Anyhow I wonder if something like that might be a design achievable without the timer/thread cancelation, I'm still pretty much a lua/nvim noob though, so I can't really judge!

But by all means close this if you don't think there is a feasible design within the constraints of fidget!

ratmice avatar Apr 27 '22 17:04 ratmice

I'd like to keep this open, because it's a great suggestion. I'm currently (and slowly) working on a rewrite/reimagining of this plugin as a modular reactive UI library; I think your idea of a notification debouncer could work well in that context!

j-hui avatar Apr 27 '22 21:04 j-hui

I think this need is addressed in 893ceb3, which introduces a setting that doesn't create a new notification if the message indicates it's already done.

It builds off the update_only feature I added to the notifications API in 7880df0133556697a8efee0278b52c6add32df8a, which drops notifications that aren't updating an existing item. If a task is so short-lived that it is already done by the time we first process it, then setting progress.ignore_done_already = true means Fidget won't create a new notification just to announce the completion of that short-lived task.

This works even better now that polling is sample-driven (rather than primarily event-driven, as it was prior to the rewrite), because it means that the logic of waiting for some time to wait for a burst of events to accumulate is baked into the semantics of the system. You can simply lower the progress.poll_rate to tell Fidget to wait longer before deciding to display anything. Because this is independent of notification.poll_rate, it is still responsive to asynchronous notification events, and can still have smooth animations.

For instance, here the same demo as in the README.md, but with progress.poll_rate = 0.5 and progress.ignore_done_already = true:

https://github.com/j-hui/fidget.nvim/assets/11800204/05660c4e-b216-412a-aafe-77266cd4eb62

Sorry for blabbing a little, but I'm just really happy about how straightforward that feature was to implement after redesigning the plugin's execution model (: Thanks for your patience!

j-hui avatar Nov 11 '23 02:11 j-hui