aboutsummaryrefslogtreecommitdiff
path: root/SciTEStartup.lua
diff options
context:
space:
mode:
Diffstat (limited to 'SciTEStartup.lua')
-rw-r--r--SciTEStartup.lua98
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