Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I run an elisp function asynchronously?

for those who don't know, imenu is a thing in emacs that lets a mode insert one or more menu items into the menu bar. The most common usage is to make a "table of contents" accessible from a drop-down menu, so the user can quickly jump to declarations of functions or classes or sections in a document, etc.

imenu has a couple different ways of working - in the first and more commonly used way, a major mode provides regexps to imenu, and imenu uses those regexps to perform the scan of the buffer and build the index. A major mode sets this up by putting the list of regexps into imenu-generic-expression. The second way is for the major mode to perform its own scan. It can do this by instead setting the variable imenu-create-index-function to the name of a function defined by themode, which returns a list containing the table of contents.

I'm doing the latter - imenu-create-index-function - but sometimes the fn takes a looong time to run, say 3 or 4 seconds or more, which freezes the UI. If I make the operation asynchronous, that would solve that problem.

I know about asynch processes. The scan logic is implemented in elisp. Is it possible to run elisp in an asynch process? If so, how?

Or, is there a way to run regular elisp asynchronously in emacs, without resorting to an asynch process?

I think the way font-lock does it is, it fontifies on idle. It keeps state and fontifies a little at a time, always remembering where it left off, what else needs to be fontified, what has changed since the last fontification run, etc. Is my understanding correct? Maybe I could use this incremental approach .

Recommendations?

like image 779
Cheeso Avatar asked May 20 '11 14:05

Cheeso


2 Answers

To run elisp asynchronously you can use either run-with-idle-timer or run-with-timer. I imagine you'll want the idle version. Check the documentation links for more details.

Note: If the code takes 3 or 4 seconds to run, it'll still take that long (and freeze your Emacs while it runs), so if you can break the work up into small enough chunks that it only takes .5 seconds or so at a time, that might work well.

One package that I use all the time, pabbrev.el, uses idle timers really well - I never notice it running. That might be a good package to examine to see how it breaks up the work (it is scanning all open buffers and building up a word frequency list).

like image 80
Trey Jackson Avatar answered Oct 23 '22 01:10

Trey Jackson


The answers posted by TreyJackson and jeremiahd were valid back in year 2011. Now, in 2018, here is a link to the emacs documentation for asynchronous processes.

like image 20
user1404316 Avatar answered Oct 23 '22 01:10

user1404316