diff options
Diffstat (limited to 'SciTEStartup.lua')
-rw-r--r-- | SciTEStartup.lua | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/SciTEStartup.lua b/SciTEStartup.lua new file mode 100644 index 0000000..82a9467 --- /dev/null +++ b/SciTEStartup.lua @@ -0,0 +1,98 @@ +-- Primitive syntax-aware spell checker for the SciTE editor based on aspell. +-- It only requires the aspell CLI tool to be installed, but perhaps it won't work on +-- Windows. +-- You can just copy this into SciTEStartup.lua. +-- +-- TODO: Dictionaries should be configurable per file +-- TODO: Support named styles in aspell.styles.lexer? +-- +-- The following should be copied into SciTEUser.properties and adapted: +--[[ +aspell.enabled=1 +# Comma-separated list of dictionaries +aspell.dicts=en_US +# Restrict spell checking to certain lexer styles +aspell.styles.lua=1,2,3 + +command.name.9.*=Manuall Spell Checking +command.mode.9.*=subsystem:lua,savebefore:no +command.9.*=aspell +command.name.10.*=Toggle Automatic Spell Checking +command.mode.10.*=subsystem:lua,savebefore:no +command.10.*=aspell_toggle +]] + +function aspell_toggle() + props['aspell.enabled'] = props['aspell.enabled'] == '1' and '0' or '1' + if props['aspell.enabled'] == "1" then + aspell() + else + editor.IndicatorCurrent = 2 + editor:IndicatorClearRange(0, editor.Length) + end +end + +function aspell() + local styles = props['aspell.styles.'..editor.LexerLanguage] + local styles_table = {} + for style in styles:gmatch("%d+") do styles_table[tonumber(style)] = true end + + local in_name = os.tmpname() + local in_file = io.open(in_name, 'w') + in_file:write('^') + + -- NOTE: Unfortunately, SCI_GETSTYLEDTEXT (editor:GetStyledText()) is not exposed. + for pos = 0, editor.Length-1 do + local c = editor.CharAt[pos] & 0xFF + + if c == 10 then + -- Each line is prefixed with ^ since ispell/aspell accepts special + -- commands as well + in_file:write('\n^') + else + local must_spellcheck = styles == "" or styles_table[editor.StyleAt[pos]] + in_file:write(must_spellcheck and string.char(c) or ' ') + end + end + + in_file:close() + + editor.IndicatorCurrent = 2 + editor.IndicStyle[2] = INDIC_SQUIGGLEPIXMAP + editor:IndicatorClearRange(0, editor.Length) + + local out = io.popen('aspell -d '..props['aspell.dicts'].. + ' --dont-guess --dont-suggest --byte-offsets -a <'..in_name) + + local line = 0 + for cmd in out:lines() do + if cmd == "" then -- no more commands on the current line + line = line + 1 + elseif cmd:sub(1, 1) == "#" then -- word not found + local word, offset = cmd:match("^. ([^ ]+) (%d+)$") + editor:IndicatorFillRange(editor:PositionFromLine(line)+offset-1, #word) + end + end + + out:close() + os.remove(in_name) +end + +function OnOpen() + if props['aspell.enabled'] == '0' then return end + + -- Make sure that everything is already styled as we spell check per style: + editor:Colourise(0, -1) + aspell() +end + +function OnChar(new_chr) + -- Called on every inserted character + if props['aspell.enabled'] == '0' then return end + + local wordchars = editor.WordChars + + -- NOTE: new_chr is a string but not Unicode-aware. + -- FIXME: Even better would be spell checking only chunks of recently styled text. + if not wordchars:find(new_chr, 1, true) then aspell() end +end |