Tried your package, initial comments
minad opened this issue ยท 42 comments
At first sight, it seems to work quite well. I have ispell configured in my setup and your jit-spell just works out of the box, which is great. Some comments:
-
I have package-lint installed and it showed a few warnings, which you probably want to fix (e.g., requiring cl-lib at compile time). Please also add a commentary. The package is young and experimental, so I think I should give it a bit more time. :)
-
I have the following in my config for Org. These settings are respected, right?
(add-to-list 'ispell-skip-region-alist
'("#\\+begin_\\(src\\|example\\)" . "#\\+end_\\(src\\|example\\)"))
(add-to-list 'ispell-skip-region-alist
'(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:")))
-
Your completion predicates don't seem to correctly. Are the predicates executed in the minibuffer and jit-spell-mode is buffer-local in the original buffer?
-
You provide a lighter. I am not a fan of those, so I would just remove it. I use Minions anyway. If you want to keep it, consider to cache the values, since the modeline can add severe costs to the redisplay. The cost here should be negligible, but I wanted to mention it nevertheless, since the mode line code is interpreted. You could also introduce a jit-spell--lighter function which will then at least be compiled.
-
Org mode spell checking does not yet work great. I have the following in my config for face-based configuration in spell-fu. Maybe you want to add something like this too? You told me that you don't like this way of configuration, but I really don't find it that bad.
(defvar +spell-fu-faces-exclude
'((markdown-mode
markdown-code-face markdown-html-attr-name-face
markdown-html-attr-value-face markdown-html-tag-name-face
markdown-inline-code-face markdown-link-face
markdown-markup-face markdown-plain-url-face
markdown-reference-face markdown-url-face)
(org-mode
org-block org-block-begin-line org-block-end-line
org-code org-cite org-cite-key org-date org-footnote
org-formula org-latex-and-related org-link org-meta-line
org-property-value org-ref-cite-face org-special-keyword
org-tag org-todo org-todo-keyword-done
org-todo-keyword-habt org-todo-keyword-kill
org-todo-keyword-outd org-todo-keyword-todo
org-todo-keyword-wait org-verbatim
org-modern-tag org-modern-date-active org-modern-date-inactive)
(latex-mode
font-latex-math-face font-latex-sedate-face
font-lock-function-name-face font-lock-keyword-face
font-lock-variable-name-face)))
-
I am not fond of the @ accept action via completion. Maybe you are going to replace this with a dedicated keybinding? I think the UI needs a bit more polishing, but I have to try it for longer to tell how I would want it.
-
You install a jit-mode-map which grabs important keys. I think I would prefer if you don't do that and only install a local keymap on the overlay. You could at least add the actions to the overlay keymap too and then I could as a user decide to empty jit-mode-map.
-
You highlight the active word with
highlight
. Maybe introduce an extra face inheriting from highlight? -
Why do you unhide the overlays immediately? I think it would be sufficient if you always delay the unhiding, since you have to wait anway for the ispell process to return.
-
I find it a bit hard to understand how you handle the request queue. Why is the queue of requests added to the process object as a parameter? Why is it not a buffer-local variable?
Thanks for the comments. Some of the little bugs I already noticed and fixed or don't know yet how I want to handle. Regarding the rest:
2/ There's no Org integration whatsoever, except for handling org-self-insert-command
.
4/ I'm tending to keep the lighter because it's borderline useful and easier to remove than add. In fact, Flyspell was one of the few lighters I didn't remove... PS: I use a condensed sans serif face in my mode line, which then fits quite a bit of stuff and at the same time becomes more subdued.
5/ Thanks for the face list!
6/ What do you think is gained by a dedicated keybinding? I actually liked it because you can easily edit the new word, which I often want to do (change capitalization, remove plural, etc.)
7/ Interesting idea about a local map. I was debating a bit about the global binding. It is "reserved" by Flyspell so it should be safe in terms of conflicts, though.
9/ I'm a bit confused by this question, but if you set jit-spell-delayed-commands
to nil you'll see immediately what the delaying is about.
10/ That's the secret sauce :-). The queue is not buffer local because buffers can (and do) share a process. And conversely, if I were to add the ability to mark regions of the buffer with a different language (which actually wouldn't be too hard in architecture), then one buffer would need more than one process.
You could at least add the actions to the overlay keymap too
Actually, this is basically in the real of the customizable already:
(put 'jit-spell 'keymap (let ((map (make-sparse-keymap))) (define-key map "x" 'jit-spell-correct-word) map))
I should probably predefine a keymap to put there. Then the question is, which ones to leave empty.
2/ I wonder if these skip region alists from ispell are respected properly by jit-spell?
4/ I also used a condensed variable pitch font for a while but it made to many problems with stuff moving around.
6/ The idea is nice, but I find the interface a bit awkward to use. I just have to get accustomed to it.
9/ Regarding jit-spell-delayed-commands
- I meant that you could make all commands delayed. What do we actually win if we have immediate commands?
10/ Would be great if you support multiple languages! But in my use cases, the documents are mostly mixes without dedicated regions, such that this wouldn't help me. I am rather looking for functionality to load multiple dictionaries, but this is more of an issue with ispell I guess? Otoh you could start multiple ispells and check all of them until one succeeds if the slowdown permits.
2/ I'll check, but ideally there should be a local mechanism provided by the major modes. Only the major mode who knows how far back you need to go to find out the context of a region for jit-locking purposes.
9/ Ah okay, your suggestion is equivalent to getting rid of the pre-command hook. The result is not horrible but makes things inconsistent, since typing space still triggers a check immediately, while moving away from a word with navigation commands has a delay.
10/ Multiple dictionaries at the same time is a thing the spellchecker should (and can) do. I don't know how ispell.el's interface works in this case (ispell-change-dictionary
does not use CRM, for instance).
2/ I'll check, but ideally there should be a local mechanism provided by the major modes. Only the major mode who knows how far back you need to go to find out the context of a region for jit-locking purposes.
So what is your plan to support modes like Org, Markdown or Rst? This is the main blocker which prevents me from using your package and replacing spell-fu. Could we add some alists which handle the configuration per mode? This way one wouldn't have to patch so many modes and the configuration could be centralized in jit-spell. An alternative would be to just provide these variables, which could be set locally. Then modes could configure jit-spell themselves or one could just configure it in the init.el. I also have to do that in my user configuration for spell-fu. I hope that jit-spell would provide me with a bit more facilities such that I could easily configure at least Org, Markdown, TeX and Rst. Even better if they work out of the box via an alist configuration.
9/ Ah okay, your suggestion is equivalent to getting rid of the pre-command hook. The result is not horrible but makes things inconsistent, since typing space still triggers a check immediately, while moving away from a word with navigation commands has a delay.
Why? Couldn't you delay all the updates? I think it would be better if you could avoid the jit-spell-delayed-commands
configuration variable altogether?
So what is your plan to support modes like Org, Markdown or Rst?
I want to think this through before implementing anything. E.g., why is the major mode alist better than a single variable that you can set either globally or in a mode hook, depending on your perfectionism and Elisp skills?
I believe in the lists you provided, but for Org, I'm pretty sure that this list of faces is not the complete story. Inside an example or src block without a language name I see these properties:
There are text properties here:
face (:inherit (org-block))
font-lock-fontified t
font-lock-multiline t
fontified t
isearch-open-invisible org-fold-core--isearch-show
isearch-open-invisible-temporary org-fold-core--isearch-show-temporary
src-block t
So checking for the src-block
property might be more reliable, and in fact I can filter out the text and not even send it to the subprocess. These details need to be figured out.
Anyway, as I write this I conclude Org needs special code to support. The others maybe just need a list of faces.
Re 9, you can override the pre command hook with an advice and see for yourself what happens. And actually I should try that too :-). Maybe it's not incredibly necessary, but I suspect the list of delayed commands has those 5 elements and that's it, so it doesn't cost much to keep.
Actually I just want something which works, ideally without much configuration. There is simply no solution in Emacs which just works. I agree that Org needs special block handling. Of course it would be nice if we don't need ugly code. Most importantly I would avoid any hard coding like you have it with derived-mode-p in the mode activation.
Re 9, you can override the pre command hook with an advice and see for yourself what happens. And actually I should try that too :-). Maybe it's not incredibly necessary, but I suspect the list of delayed commands has those 5 elements and that's it, so it doesn't cost much to keep.
I am not sure. There are probably more commands you have to add. Org already needs its own. Cc-mode too maybe. If possible I would try to avoid this complication - and ugliness ;)
Another question - did you profile jit-spell for a while? How much does it cost when doing simple operations like typing, moving around, scrolling?
We're on the same page about "just working" solutions, but I want as much as possible to avoid maintaining a face list.
I think this (which for now you can test in jit-spell-mode-hook
if you are eager to) will do the trick, but I need to test. Beware that it will run some ugly code in the background.
(when-let ((pred (or (bound-and-true-p flyspell-generic-check-word-predicate)
(get major-mode 'flyspell-mode-predicate))))
(add-function :after-until (local 'jit-spell-ignored-p)
(lambda (_start end)
(save-excursion
(goto-char end)
(not (funcall pred))))))
Cc-mode too maybe
I checked and they reinvent DEL, but fortunately not self-insert-command
so I guess I could just ignore the problem ๐คท. But I thought of a variation of your idea that might work and get rid of the list.
As to performance, I haven't measured (or felt a need to measure) anything. Let me know if you have any ideas in mind, e.g. what to compare it to. Obviously, the async nature makes things harder to measure. In one regard jit-spell is ludicrously inneficient: you compute a lot of comparatively expensive corrections to almost surely throw them away. This is done in the subprocess so it doesn't really matter; sadly the ispell -a
interface doesn't support turning it off.
We're on the same page about "just working" solutions, but I want as much as possible to avoid maintaining a face list.
Well, someone has to bite the bullet and I think it should rather be done here than in every user config.
I think this (which for now you can test in jit-spell-mode-hook if you are eager to) will do the trick, but I need to test. Beware that it will run some ugly code in the background.
I wonder why you use some flyspell facilities here. Does this require flyspell to be loaded? If yes, I wouldn't like it :-P
I would be very happy to get rid of crappy flyspell completely.
As to performance, I haven't measured (or felt a need to measure) anything. Let me know if you have any ideas in mind, e.g. what to compare it to.
If you didn't perceive a difference that's good. I think it makes sense to let the profiler run for a while during jit-spell operation, just to make sure that there are no hotspots. Also does it add to the memory or GC pressure? I am really critical about everything which is always on and runs in the background. It must not fail and should ideally not cause any kind of pause or latency increase.
I wonder why you use some flyspell facilities here.
Because it is the de facto API?
Does this require flyspell to be loaded? If yes, I wouldn't like it :-P
No, it's just a function that major modes declare. The API is a bit suboptimal in that (i) the predicate is usually declared via a symbol property hence unheritable and (ii) it expects point to be after the word so we need an extra save-excursion
. Otherwise it's fine. I'm not sure major modes implement it with performance in mind, but Org's seems plenty fast despite looking rather complex (have a look at it org-compat, if you want).
Okay, sounds good. You could offer your own API and just provide an adapter which makes use of the flyspell function if available. It seems this is what you already do? My initial sentiment was to just avoid anything from flyspell given how bad it is. At least it is great if your package doesn't just sit on top of flyspell and is a clean and better reimplementation. There have been attempts before at fixing flyspell, iirc there is flyspell-lazy.
My API is jit-spell-ignored-p
, as shown in the snippet above. It's a variable holding a function where you can add-function to however you please. But it does not purport to be a generic API for any spellchecker in Emacs.
I guess a totally generic API would have to be a hook variable? Maybe I should make mine a hook variable?
Yes. A hook is a good idea. You could preregister various predicates there which are all checked, among them the prog mode, face and flyspell predicates. Users or modes could turn add more if the wish.
Right, but between a hook or a function var one can add-function
to, I'm not quite sure which is best. Any thoughts?
Hook is better. add-function is essentially an advice and harder to inspect. The general recommendation is to prefer hooks, in particular if the variable is meant to be extended/configured.
I find the idea of using a list of predicates appealing. The only problem is that this won't work if you want to formulate more complex predicates and combine the predicates more flexibly. I hope such complexity is not needed.
Right, more complex predicates seem not as likely but not totally impossible, cf. prog-mode where you want a list of allowed faces. I will keep my function var for sure, but probably should make it double-dashed.
The hook idea only makes sense if a critical mass of modes adopt it, so I'm skeptical it can fly.
Why not just provide a list of useful predicates such that thing just works out of the box for the relevant modes? Why not make something which is useful now? Spell checking is a major pain point of Emacs. A solution which just works out of the box like in the browser would be great.
Of course I will make something which is usable now, and that's why I'll use the Flyspell API. I thought we were discussing a bit what a good API would look like in an ideal world, which admittedly has no practical use right now.
Actually, I think I would be willing to touch flyspell.el to implement this ideal-world API if we arrive at a conclusion.
Ah okay. I must admit I am not interested in the ideal solution. I just want something which works, and which also works on Emacs 29 and older (on newer Emacsen the ideal solution should be used of course). I am repeating myself, but spell checking has been a pain point for me and I am so glad that you initiated this. I experimented before with various other solutions, flyspell, flymake, but then I settled on spell-fu now. Now that you bad-mouthed the spell-fu approach (the memory usage is really not good), I am eager to move over to something else. But the switch should still be painless and should not require me to write a large amount of ignore code. ๐
Just chiming in to say that 1) I like this package approach (but I've never used spell-fu
) and I've been using it happily since yesterday 2) I like that you're already discussing gory details.
All in all, just thank you @astoff for another great package and thank you @minad for raising thoughtful questions.
I've pushed a bunch of changes and more or less all major modes should be supported now. The big exception is TeX and friends. For that one I have a couple of ugly options ๐.
I also got rid of the unhiding pre-command hook. I might add back a post-command hook for that, but it won't need a command list.
@minad: Are you still keen on having a keymap over the overlays? As mentioned above, this is borderline doable in the user configuration space.
I also got rid of the unhiding pre-command hook. I might add back a post-command hook for that, but it won't need a command list.
Great!
@minad: Are you still keen on having a keymap over the overlays? As mentioned #1 (comment), this is borderline doable in the user configuration space.
Not really keen, but it may be nice to experiment with this. I am a fan of context local bindings, since they don't grab some valuable global bindings. Otoh it may be more convenient to use a global binding since then you can also jump to the misspelling right away. I assume that's how you intend the package to be used?
(My only criticism is that you are still going with the add-function
code instead of hooks, which I would prefer for scenarios, which are explicitly meant to be configured and modified. I am not saying this only because the Elisp code guidelines recommends hooks, since I am actually a big fan of advices.)
I just tried jit-spell again and it works really well! What about adding a command which runs jit-spell-correct-word
in a loop for all misspellings (maybe C-u M-x jit-spell-correct-word)? I have to work a bit more with it to give you better feedback on the UI. I will kick out spell-fu from my config now.
maybe C-u M-x jit-spell-correct-word
Maybe some key you press instead of RET? Since right now you can already cycle without correcting by pressing the same key again.
My only criticism is that you are still going with the add-function code instead of hooks
At least I renamed that var now to be double dashed. I may have overengineered the predicate business a bit, but let me convince myself first that I won't need all that.
Maybe some key you press instead of RET? Since right now you can already cycle without correcting by pressing the same key again.
Sure, that may work as well. I would really have to try to see what I like more. But generally I don't recommend to tweak the completion interface too heavily if it can be avoided, to keep the UI somewhat consistent.
I've noticed that jit-spell starts quite soon and "aggressively" runs aspell - at least aspell shows prominently in top. Could we add some additional delays between requests? I have stealth jit enabled, I assume that jit-spell is also affected by that? Would it be possible to prioritize requests, such that visible requests are handled immediately and invisible requests are delayed? I may worry a bit too much about this, but I am usually not a fan of such always on background processes which may eat the battery.
I have stealth jit enabled, I assume that jit-spell is also affected by that?
I guess. What is stealth jit?
Would it be possible to prioritize requests, such that visible requests are handled immediately and invisible requests are delayed?
This is the main reason why the request queue is a FIFO. But there's no throttling of the request, they're sent as soon as possible.
BTW, one annoying detail about hooks is that it's problematic to define hooks which are not empty by default...
I guess. What is stealth jit?
See jit-lock-stealth-time
and the other jit-lock-stealth-*
variables.
This is the main reason why the request queue is a FIFO. But there's no throttling of the request, they're sent as soon as possible.
Makes sense. Throttling would be a nice feature nevertheless.
BTW, one annoying detail about hooks is that it's problematic to define hooks which are not empty by default...
Right. Users of the hook would always have to add in a with-eval-after-load block. As an alternative you could autoload the variable. But anyway, I don't care much about the details of the ignore logic as long as it just works. Your package is the first which just works well out of the box! But I am sure I will find some issues when I dig a bit deeper with personal dictionaries, multiple languages and so on... :-P
I've pushed a bunch of changes and more or less all major modes should be supported now. The big exception is TeX and friends. For that one I have a couple of ugly options smile.
TeX is the only thing missing in the package, but honestly I was never happy with Flyspell in TeX, to the point that I've always run ispell
manually in those buffers. Eager to see what you come up with here. And if you need me to test jit-spell
with TeX, just let me know.
Does this require flyspell to be loaded? If yes, I wouldn't like it :-P
No, it's just a function that major modes declare.
This is not entirely true. For example mhtml uses flyspell-generic-progmode-verify
in its predicate and will as such require flyspell. Also it seems that you are reinventing the wheel regarding the face mechanism here introduced by flyspell-generic-progmode-verify
. The problem is that we end up with an unfortunate coupling of the packages here.
See jit-lock-stealth-time and the other jit-lock-stealth-* variables.
Regarding the stealth mechanism - the stealth jit locking is already quite resource friendly itself, since it introduces delays between fontification of the chunks (checkout all the stealth variables). However jit-spell is still considerably more expensive than font locking, so I am not sure if one should still introduce some additional "niceness" delays. I often see aspell now in my process list.
I've pushed support for TeX. It's a bit of an experiment which also affects prog-mode: I now send only the relevant chunks to the subprocess, i.e., only strings and comments in the prog-mode case.
This has some interaction issues with font-lock. First, it means we need to run after font lock. Second, we would have to know which regions font lock messed with, but that seems not possible as jit-lock backend. It might be that we need to run via font-lock, but I haven't thought about that yet.
I often see aspell now in my process list.
Apart from the latest commit, maybe adding --sug-mode=ultra
option helps? The expensive part is computing the corrections, not checking the words.
mhtml uses flyspell-generic-progmode-verify in its predicate
Yep, I noticed, cf. 3985db5. But that predicate is garbage anyway, it says HTML tag names should be checked. Note also that it tries to call flyspell-generic-progmode-verify
, a non-autoloaded function, without loading flyspell before. ๐คท
Also it seems that you are reinventing the wheel [...] flyspell-generic-progmode-verify [...] we end up with an unfortunate coupling of the packages here.
I don't understand this point. I'm reinventing the prog-mode wheel, yes, so that there's no coupling with Flyspell. Also, AFAICT, none of the prog-modes set their flyspell-mode-predicate
symbol property, fortunately.
I've pushed support for TeX. It's a bit of an experiment which also affects prog-mode: I now send only the relevant chunks to the subprocess, i.e., only strings and comments in the prog-mode case.
Great!
This has some interaction issues with font-lock. First, it means we need to run after font lock. Second, we would have to know which regions font lock messed with, but that seems not possible as jit-lock backend. It might be that we need to run via font-lock, but I haven't thought about that yet.
Is it not possible to control the order of the jit lock backends, such that font locking always comes first? I wonder how this works anyway since you rely on the applied faces?
Apart from the latest commit, maybe adding --sug-mode=ultra option helps? The expensive part is computing the corrections, not checking the words.
Yes, that could be a good idea. How can I do that? I haven't found an option.
But that predicate is garbage anyway, it says HTML tag names should be checked. Note also that it tries to call flyspell-generic-progmode-verify, a non-autoloaded function, without loading flyspell before.
Okay, checking tags is nonsense. But calling the non-autoloaded function is fine, since mhtml can reasonably assume that the predicate is only called by flyspell. Anyway, your statement that flyspell is the de-facto standard is more or less refuted. There are like three uses of these predicates in the entire Emacs code base and one of them is a broken one. You could just roll your own entirely.
I don't understand this point. I'm reinventing the prog-mode wheel, yes, so that there's no coupling with Flyspell. Also, AFAICT, none of the prog-modes set their flyspell-mode-predicate symbol property, fortunately.
Yes, the decoupling is good of course. My point is that it only works if the predicate does not make use of any Flyspell facilities (as in the case of mhtml). If a predicate makes use of Flyspell facilities we end up with two coupled systems with duplicate code with duplicate configuration and so on. I have no good solution for this, either introduce some allow/deny lists or disable the flyspell predicate immediately if it errors, or just roll your own predicates entirely.
I found that I can create a .aspell.conf file which contains sug-mode ultra
, but it seems that there is no option to configure aspell directly within Emacs, such that other uses are not affected?
Is it not possible to control the order of the jit lock backends, such that font locking always comes first? I wonder how this works anyway since you rely on the applied faces?
This is not allowed but I did it :-). The problem is on edits. Say you add back a stray double quote character. Jit-lock tells me region (100 . 102) changed and I recheck that, but font-lock realizes it needs to refontify (100 . 589) and there's no way for me to know it.
option to configure aspell directly within Emacs, such that other uses are not affected?
Presumably there is ispell-extra-args
. I haven't tested.
Anyway, your statement that flyspell is the de-facto standard is more or less refuted.
I don't think so. I'm supporting Org mode, Markdown mode, probably Rst as well without mentioning them at all in the code. (Not 100% true: I forgot to delete a TODO comment :-P)
If a predicate makes use of Flyspell facilities we end up with two coupled systems with duplicate code with duplicate configuration and so on.
Yeah, I totally agree with that. But what can I do? Rolling my own for every mode is not an option. I dare say, if a predicate doesn't work without Flyspell, then let it be. Either nobody cares, or someone cares and the predicate should be fixed.
This is not allowed but I did it :-). The problem is on edits. Say you add back a stray double quote character. Jit-lock tells me region (100 . 102) changed and I recheck that, but font-lock realizes it needs to refontify (100 . 589) and there's no way for me to know it.
I saw that you added priorities. I don't have good ideas, but let's just hope for the best. It is not too bad if from time to time some regions are not checked.
Presumably there is ispell-extra-args. I haven't tested.
Thanks! How did I miss that? I saw other ispell-*-options
variables, but not args
.
EDIT: ispell-extra-args
works!
I don't think so. I'm supporting Org mode, Markdown mode, probably Rst as well without mentioning them at all in the code. (Not 100% true: I forgot to delete a TODO comment :-P)
Rst doesn't seem to use Flyspell. Otoh Markdown and Org use it. Still, three times in the entire code base is not much. Of course I haven't checked ELPA/MELPA - maybe there are hundreds of uses and maybe all of them are well written such that they don't actually use flyspell.
I only worry that your package becomes too strongly coupled with Flyspell or even worse ends up as a patch to Flyspell instead of a better reimplementation, which it already is.
I saw that you added priorities. I don't have good ideas, but let's just hope for the best. It is not too bad if from time to time some regions are not checked.
bug-reference-mode doesn't suffer from that, so I think it's just a little thing I can fix on my side ๐
By the way, if you want decent suggestion, Hunspell is the way. Very expensive, though.
I only worry that your package becomes too strongly coupled with Flyspell or even worse ends up as a patch to Flyspell instead of a better reimplementation, which it already is.
Emacs just needs an API for this. Note that even ispell.el reinvents some wheels in that area.
I've pushed support for TeX. It's a bit of an experiment which also affects prog-mode: I now send only the relevant chunks to the subprocess, i.e., only strings and comments in the prog-mode case.
Thank you! I'm going to try it out later on my thesis and report back if I see any issue.
bug-reference-mode doesn't suffer from that, so I think it's just a little thing I can fix on my side
Oh okay. I thought bug-reference-mode just uses font lock keywords.
By the way, if you want decent suggestion, Hunspell is the way. Very expensive, though.
Expensive is no go for me. I try hard to not add anything slow to my Emacs which is always enabled.
If one wants to go even further there is also langtool. Have you tried that?
Emacs just needs an API for this. Note that even ispell.el reinvents some wheels in that area.
Yes, probably. Maybe it would be best if you add the API to ispell. Would you then deprecate the flyspell API in favor of it?
I've pushed something, I think I've fixed it.
Expensive is no go for me. I try hard to not add anything slow to my Emacs which is always enabled.
I think now with the filtering this is a no-issue, basically. But I haven' tested enough.
Yes, probably. Maybe it would be best if you add the API to ispell. Would you then deprecate the flyspell API in favor of it?
Hum, I'm willing to fix Flyspell. Ispell is even more confusing.
@astoff Everything works as expected in my TeX file! Just to give you some notes of my setup. I have the following for ispell
:
(setq-default ispell-dictionary "en"
ispell-quietly t
ispell-silently-savep t)
Then I have this at the end of my .tex
file:
%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% ispell-local-dictionary: "it"
%%% End:
TeX keywords are not highlighted as misspelled and the same goes for correctly spelled Italian text. Of course, English words are highlighted as misspelled here, but that's what I would expect.
Again, thanks for this package.
Since we have version 0.2 now, I guess the initial comments can be archived :-).