Sublime Forum

Command Callbacks

#1

Since my plugin sometimes has to operate on a different views, sometimes wanting to do several edits in sequence I had to build in an event system and make my own editing text commands so i could chain editing commands via callbacks pushed through my own event system. This is due to the fact that editing commands all run async so i cant easily delete some text, then insert something else, then do something else on the buffer as the insert and delete may not have completed yet.

It would be amazing if there were a way to do this built in to the system. A sort of promises like chaining pattern or something. I know others have run into this as well.

0 Likes

#2

have you considered using an EventListener’s on_post_text_command?

0 Likes

#3

Yeah, I am using my own little event system.
I think with post_text_event i would still need to dispatch to the specific subsytem waiting to do the next thing? IE I think I would still need to build a dispatch mechanism of some form?

I would like to just have that built in to run_command, perhaps it returns a promise or something that i can just do something like:

run_command(blah).then(
dootherthings())

Or even just pass in a callback.

IE: the ability to chain edits is a 1st order api feature.

0 Likes

#4

Commands are run synchronously. So if you want to run a couple commands in sequence, just call run_command a couple times.

0 Likes

#5

Hmmm, okay, I guess I assumed there were threads involved because when I inserted a timer to call me back sometimes the operation had completed and sometimes it had not. BUUUT now that I think about it that was a silly assumption. Regardless, when I run an insert command from another parent text command and then check the buffer in the parent command after calling run_command, the insert has not completed.

Instead, I run the command and hook a callback as part of that run_command. I can’t pass a function pointer to a text command so I pass an event Id in my event system. When the insert has completed it triggers the event, which allows me to chain. If I just call run_command and then try to find a cursor position for the next run_command that I am running in sequence, the buffer has not always updated and I will get erroneous results. I found my event chaining was the only reliable way to make that work. I found other allusions to doing something like that being the right way somewhere else on the forums a while back.

0 Likes

#6

All API calls are serialized onto the main thread of ST. You can’t read from the buffer until the command has finished running. Maybe you’re running a command that has some asynchronous behavior? Could you provide an example of this not working?

0 Likes

#7

I am communicating this poorly. That’s precisely the issue.

IE:

I want to:

  1. run_command on another view that I am currently not looking at.
  2. I want to read from that view and change my cursor position after that first command finishes.
  3. I want to run_command on that view again.

All of this I am doing from some command the user has run.

I do this when working on my capture buffer, when changing the state of a TODO in the agenda view, when opening up the date picker, when inserting drawers because some task has changed state.

In each of these cases, because I need to adjust the cursor after the previous change… I have to run AFTER the previous command has run. Async or not, it doesn’t matter as long as they are deferred and not run immediately. I have solved my issue locally, but I have seen others on the boards struggling with this and I think it would be great if run_command would return something that would let you chain to it in some way and execute some more code after that command completes. :slight_smile:

0 Likes

#8

That’s what I’m saying. They aren’t deferred. view.run_command only returns once the command has completed (though I’m not sure if that includes python callbacks or not).

0 Likes