Is this feature implemented? Maybe running the previous word through a filter on every white space and the inserting a color tag that is not exported if it is an unrecognized word. I would do it myself, but the texmacs docs seem really bad compared with Vim or Emacs. Also, are there any hooks like in Emacs or autocommands like in Vim in TeXmacs?
Spellcheck as-you-type
As far as I know it is not.
I have the feeling that the answer may be a partial yes but could you please explain in a synthetic way what are hooks and autocommands? Links with short explanations will also fit as an answer.
Autocommands in vim are functions that get called on specific events, e.g. file save, cursor movement, cursor at word boundary, loading a specific type of file etc. You can add your functions to the list of commands that Vim calls whenever the event occurs. Hooks are a similar concept in Emacs. There is a list of functions that each gets executed when some event that is associated with the hook occurs. This is another way to extend Emacs or Vim.
Vim autocommands:
https://vimdoc.sourceforge.net/htmldoc/autocmd.html
Emacs hooks:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html
I have experimented a bit. This is very hackish, spellchecking every 2 seconds, but perhaps it can lead to something useful
(delayed
(:while #t)
(:every 2000)
(with
sels ((@@ (generic spell-widgets) spell-buffer-tree))
(set-alt-selection "alternate" sels)))
Thanks for the effort. Maybe you could write something about what those functions do and put it in some TeXmacs release.
There is a mechanism for functions, keyboard mappings and menus with which they can be redefined and call their earlier definition (see Help->Scheme extensions-> Overview of the scheme extension language -> 5. Contextual overloading
).
For example, to highlight misspelled words on every press of the space bar, we can do
(tm-define (spell-highlight)
(with
sels ((@@ (generic spell-widgets) spell-buffer-tree))
(set-alt-selection "alternate" sels)))
(tm-define (kbd-space-bar t shift?)
(:require (and (tree-is-buffer? t) (in-text?)
(!= (get-env "language") "verbatim")))
(former t shift?)
(spell-highlight))
The :require
part sets up the conditions under which this version of the function should apply. The (former t shift?)
bit calls the existing definition of the function, so that the space character still gets inserted.
Iām not sure we want to ship this until some more experimentation. The implementation seems all right, however. Great work @jeroen. It would be nice if we have a way to change the display style of different kinds of selections.
At the moment there are only the āselection-colorā and āmatch-colorā environment variables that can be used to set the color of the standard and alternate selections.
One thing Iāve noticed now is that this also spell-checks and highlights things like source code and slideshows (also while in full-screen). This will need a bit of fine-tuning. Also a preference to enable it should be added.
Also the matching bracket highlighting in source code uses the same āalternate selectionā procedure, so the two donāt work together.
I was diving through the source for a different reason, when I found this in the src/TeXmacs/progs/utils/library/cursor.scm:
; Hook for notifications of any cursor
movement after it happens (mouse too)
(tm-define (notify-cursor-moved status)
(noop))
This is the hook I was talking about. The function notify-cursor-moved is called whenver the cursor is moved. Maybe someone can use this to implement spell checking on cursor movement?
Something like:
(tm-define (notify-cursor-moved status)
(former status)
... if on word boundary, check previous word ...)
Using your code, maybe something like this?
(tm-define (spell-highlight)
(with
sels ((@@ (generic spell-widgets) spell-buffer-tree))
(set-alt-selection "alternate" sels)))
(tm-define (notify-cursor-moved status)
(:require (and (in-text?) (!= (get-env "language") "verbatim")))
(spell-highlight))
This seems to work even inside words. The spelling should be checked in the document language. One can get the document locale using
(language-to-locale (get-document-language))
but Iām not sure how to adjust your snippet to take this into account, yet.
The problem seems to be with how hunspell is launched. It uses the locale language instead of the document language. See src/src/Plugins/Ispell/ispell.cpp
No the problem was in the arguments to tree-spell-at and tree-spell-selction in spell-buffer-tree.
For now, here is a hacky way to do it in your init file:
(define (spell-buffer-tree)
(let* ((t (buffer-tree))
(p (tree->path t))
(cp (cDr (cursor-path)))
(pos (if (list-starts? cp p) (list-tail cp (length p)) (list)))
(sel (get-alt-selection "spell-region")))
(if (null? sel)
(tree-spell-at (get-document-language) t p pos 1000)
(and-let* ((pos1 (car sel))
(pos2 (cadr sel))
(pos1* (and (list-starts? pos1 p)
(list-tail pos1 (length p))))
(pos2* (and (list-starts? pos2 p)
(list-tail pos2 (length p)))))
(tree-spell-selection (get-document-language) t p pos1* pos2* 1000)))))
(tm-define (spell-highlight)
(with
sels (spell-buffer-tree)
(set-alt-selection "alternate" sels)))
(tm-define (notify-cursor-moved status)
(:require (and (in-text?) (!= (get-env "language")
"verbatim")))
(former status)
(spell-highlight))
This will do the checking the the document language.