I write a lot of text in German and English and I'm getting tired of switching the dictionary of my spell-checker all the time. In true Emacs spirit, I decided to do something about this and dusted off my grandpa's parentheses. The code I wrote guesses the language of the current paragraph and then changes the language in ispell and typo-mode. It also reruns flyspell on the current paragraph, but only on that paragraph because sometimes I also write documents in multiple languages.

All this is working really nicely and I will publish this code after some more testing, so other people can use it, too. However, I want the process of switching languages to be fully automatic so I don't have to think about it at all. This means that my function should run every once in a while during text editing. Perhaps it's overkill to run it on every key stroke but I thought it might be good to run it every time I start a new word, i.e., when I enter a space or newline. Alternatively, it might also be enough to run it only when I enter punctuation marks.

My question: How can I fire off the function when certain characters are inserted in the buffer? Is there a hook for that? Thanks for your help.

FYI: Here is my code: https://github.com/tmalsburg/guess-language.el

  • 1
    post-self-insert-hook fires after every insert, but could be made to work by doing the check for the character in the hook. – wasamasa Jan 31 '17 at 21:03
  • @wasamasa But how do I know which character was inserted? – tmalsburg Jan 31 '17 at 21:05
  • Oh, it's simply the character at point I guess. That was too easy for me ;-) – tmalsburg Jan 31 '17 at 21:06
  • 1
    Not a direct answer but another approach might be to run on a timer, or whenever Emacs is idle for a few seconds. See run-with-idle-timer and run-with-timer. – glucas Jan 31 '17 at 21:19

Here's a simple function that you can use to check if the character you just entered should set off your do-my-awesome-thing function:

(defun do-awesome-thing-maybe ()
  (when (memq (char-before) '(?\  ?\t))
    (message "You should do-my-awesome-thing now")))

Here, it checks if the character you just entered was either a space or a tab (which seems like a reasonable compromise between doing it after every character, which is probably overkill, and doing it on a timer, which would require you to stop typing for a while). If so, you would do-my-awesome-thing. You can then add it to the hook:

(add-hook 'post-self-insert-hook #'do-awesome-thing-maybe)
  • It works, very nice. Unfortunately, it turns out that running flyspell-region on the paragraph every time a space is entered is a little too slow. I can also see the cursor running through the paragraph which is distracting. Probably also drains the battery of my notebook. Hm ... – tmalsburg Jan 31 '17 at 21:28
  • 2
    I see that flyspell has a flyspell-incorrect-hook. If you're already using flyspell to find errors on the fly, maybe you could use that hook to check (and possibly change) the language when flyspell finds an incorrect word? – glucas Jan 31 '17 at 21:30
  • 2
    @tmalsburg: it might make sense to post a new question along the lines of "I need to run an expensive function every once in a while, how do I do it?" It'll get more views (and hopefully help!) than these comments will get. Plus, that question will probably be useful to others as well. – Dan Jan 31 '17 at 21:55
  • 1
    @tmalsburg You may be able to prevent the recursive loop by keeping some additional state. Basically, you want a flyspell error to trigger your custom function unless it is already running. So you might check some buffer-local variable; if it is false, set it to true and schedule your custom function to do its thing and reset the flag when it is done. (Something along those lines...) :-) – glucas Feb 1 '17 at 19:18
  • 1
    @glucas Thank you. I solved it by removing the hook for temporarily and then reinserting it after flyspell is finished. – tmalsburg Feb 2 '17 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.