aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fl.fischer@fau.de>2021-03-20 12:36:00 +0100
committerFlorian Fischer <florian.fl.fischer@fau.de>2021-03-20 12:36:00 +0100
commitc668b0905cc80daf11b85bb28f4573a3dd653703 (patch)
treef11efa6641c5ca2878f01fd7f8f565d366706a4f
parent92cff24d4a19f2d37eb8e2525b23b92d78b1eee0 (diff)
downloadvis-spellcheck-c668b0905cc80daf11b85bb28f4573a3dd653703.tar.gz
make format
-rw-r--r--init.lua6
-rw-r--r--spellcheck.lua723
2 files changed, 374 insertions, 355 deletions
diff --git a/init.lua b/init.lua
index bec5899..60552a8 100644
--- a/init.lua
+++ b/init.lua
@@ -1,6 +1,6 @@
-- Copyright (c) 2021 Florian Fischer. All rights reserved.
-- Use of this source code is governed by a MIT license found in the LICENSE file.
-local source_str = debug.getinfo(1, "S").source:sub(2)
-local script_path = source_str:match("(.*/)")
+local source_str = debug.getinfo(1, 'S').source:sub(2)
+local script_path = source_str:match('(.*/)')
-return dofile(script_path .. 'spellcheck.lua') \ No newline at end of file
+return dofile(script_path .. 'spellcheck.lua')
diff --git a/spellcheck.lua b/spellcheck.lua
index d64505c..3236430 100644
--- a/spellcheck.lua
+++ b/spellcheck.lua
@@ -1,39 +1,38 @@
-- Copyright (c) 2017-2019 Florian Fischer. All rights reserved.
-- Use of this source code is governed by a MIT license found in the LICENSE file.
-
local spellcheck = {}
-if os.getenv("LANG") then
- spellcheck.lang = os.getenv("LANG"):sub(0,5)
+if os.getenv('LANG') then
+ spellcheck.lang = os.getenv('LANG'):sub(0, 5)
else
- spellcheck.lang = "en_US"
+ spellcheck.lang = 'en_US'
end
-local supress_stdout = " >/dev/null"
-local supress_stderr = " 2>/dev/null"
+local supress_stdout = ' >/dev/null'
+local supress_stderr = ' 2>/dev/null'
local supress_output = supress_stdout .. supress_stderr
-if os.execute("type enchant"..supress_output) then
- spellcheck.cmd = "enchant -d %s -a"
- spellcheck.list_cmd = "enchant -l -d %s"
-elseif os.execute("type enchant-2"..supress_output) then
- spellcheck.cmd = "enchant-2 -d %s -a"
- spellcheck.list_cmd = "enchant-2 -l -d %s"
-elseif os.execute("type aspell"..supress_output) then
- spellcheck.cmd = "aspell pipe -l %s"
- spellcheck.list_cmd = "aspell list -l %s"
-elseif os.execute("type hunspell"..supress_output) then
- spellcheck.cmd = "hunspell -d %s"
- spellcheck.list_cmd = "hunspell -l -d %s"
+if os.execute('type enchant' .. supress_output) then
+ spellcheck.cmd = 'enchant -d %s -a'
+ spellcheck.list_cmd = 'enchant -l -d %s'
+elseif os.execute('type enchant-2' .. supress_output) then
+ spellcheck.cmd = 'enchant-2 -d %s -a'
+ spellcheck.list_cmd = 'enchant-2 -l -d %s'
+elseif os.execute('type aspell' .. supress_output) then
+ spellcheck.cmd = 'aspell pipe -l %s'
+ spellcheck.list_cmd = 'aspell list -l %s'
+elseif os.execute('type hunspell' .. supress_output) then
+ spellcheck.cmd = 'hunspell -d %s'
+ spellcheck.list_cmd = 'hunspell -l -d %s'
else
- return nil
+ return nil
end
-spellcheck.typo_style = "fore:red"
+spellcheck.typo_style = 'fore:red'
spellcheck.check_full_viewport = {}
spellcheck.disable_syntax_awareness = false
spellcheck.check_tokens = {
- [vis.lexers.STRING] = true,
- [vis.lexers.COMMENT] = true,
- [vis.lexers.DEFAULT] = true,
+ [vis.lexers.STRING] = true,
+ [vis.lexers.COMMENT] = true,
+ [vis.lexers.DEFAULT] = true,
}
-- Return nil or a string of misspelled word in a specific file range or text
@@ -43,37 +42,37 @@ spellcheck.check_tokens = {
-- to a temporary file. See http://lua-users.org/lists/lua-l/2007-10/msg00189.html.
-- The returned string consists of each misspell followed by a newline.
local function get_typos(range_or_text)
- local cmd = spellcheck.list_cmd:format(spellcheck.lang)
- local typos
- if type(range_or_text) == "string" then
- local text = range_or_text
- local tmp_name = os.tmpname()
- local full_cmd = cmd .. "> " .. tmp_name .. supress_stderr
- local proc = assert(io.popen(full_cmd, "w"))
- proc:write(text)
- -- this error detection may need lua5.2
- local success, _, exit_code = proc:close()
- if not success then
- vis:info("calling " .. cmd .. " failed ("..exit_code..")")
- return nil
- end
-
- local tmp_file = assert(io.open(tmp_name, "r"))
- typos = tmp_file:read("*a")
- tmp_file:close()
- os.remove(tmp_name)
- else
- local range = range_or_text
- local ret, so, _ = vis:pipe(vis.win.file, range, cmd)
-
- if ret ~= 0 then
- vis:info("calling " .. cmd .. " failed ("..ret..")")
- return nil
- end
- typos = so
- end
-
- return typos
+ local cmd = spellcheck.list_cmd:format(spellcheck.lang)
+ local typos
+ if type(range_or_text) == 'string' then
+ local text = range_or_text
+ local tmp_name = os.tmpname()
+ local full_cmd = cmd .. '> ' .. tmp_name .. supress_stderr
+ local proc = assert(io.popen(full_cmd, 'w'))
+ proc:write(text)
+ -- this error detection may need lua5.2
+ local success, _, exit_code = proc:close()
+ if not success then
+ vis:info('calling ' .. cmd .. ' failed (' .. exit_code .. ')')
+ return nil
+ end
+
+ local tmp_file = assert(io.open(tmp_name, 'r'))
+ typos = tmp_file:read('*a')
+ tmp_file:close()
+ os.remove(tmp_name)
+ else
+ local range = range_or_text
+ local ret, so, _ = vis:pipe(vis.win.file, range, cmd)
+
+ if ret ~= 0 then
+ vis:info('calling ' .. cmd .. ' failed (' .. ret .. ')')
+ return nil
+ end
+ typos = so
+ end
+
+ return typos
end
-- plugin global list of ignored typos
@@ -83,328 +82,348 @@ local ignored = {}
-- The returned iterator is a self contained statefull iterator function closure.
-- Which will return the next typo and its start and finish in the text, starting by 1.
local function typo_iter(text, typos, ignored)
- local index = 1
- local unfiltered_iterator, iter_state = typos:gmatch("(.-)\n")
-
--- see https://stackoverflow.com/questions/6705872/how-to-escape-a-variable-in-lua
- local escape_lua_pattern
- do
- local matches =
- {
- ["^"] = "%^";
- ["$"] = "%$";
- ["("] = "%(";
- [")"] = "%)";
- ["%"] = "%%";
- ["."] = "%.";
- ["["] = "%[";
- ["]"] = "%]";
- ["*"] = "%*";
- ["+"] = "%+";
- ["-"] = "%-";
- ["?"] = "%?";
- }
-
- escape_lua_pattern = function(s)
- return (s:gsub(".", matches))
- end
- end
-
- return function()
- local typo
- repeat
- typo = unfiltered_iterator(iter_state)
- until(not typo or (typo ~= "" and not ignored[typo]))
-
- if typo then
- -- to prevent typos from being found in correct words before them
- -- ("stuff stuf", "broken ok", ...)
- -- we match typos only when they are enclosed in non-letter characters.
- local start, finish = text:find("[%A]" .. escape_lua_pattern(typo) .. "[%A]", index)
- -- typo was not found by our pattern this means it must be either
- -- the first or last word in the text
- if not start then
- -- check start of text
- start = 1
- finish = #typo
- -- typo is not the beginning must be the end of text
- if text:sub(start, finish) ~= typo then
- start = #text - #typo + 1
- finish = start + #typo - 1
- end
-
- if text:sub(start, finish) ~= typo then
- vis:info(string.format("can't find typo %s after %d. Please report this bug.",
- typo, index))
- end
- -- our pettern [%A]typo[%A] found it
- else
- start = start + 1 -- ignore leading non letter char
- finish = finish - 1 -- ignore trailing non letter char
- end
- index = finish
-
- return typo, start, finish
- end
- end
+ local index = 1
+ local unfiltered_iterator, iter_state = typos:gmatch('(.-)\n')
+
+ -- see https://stackoverflow.com/questions/6705872/how-to-escape-a-variable-in-lua
+ local escape_lua_pattern
+ do
+ local matches = {
+ ['^'] = '%^',
+ ['$'] = '%$',
+ ['('] = '%(',
+ [')'] = '%)',
+ ['%'] = '%%',
+ ['.'] = '%.',
+ ['['] = '%[',
+ [']'] = '%]',
+ ['*'] = '%*',
+ ['+'] = '%+',
+ ['-'] = '%-',
+ ['?'] = '%?',
+ }
+
+ escape_lua_pattern = function(s)
+ return (s:gsub('.', matches))
+ end
+ end
+
+ return function()
+ local typo
+ repeat
+ typo = unfiltered_iterator(iter_state)
+ until (not typo or (typo ~= '' and not ignored[typo]))
+
+ if typo then
+ -- to prevent typos from being found in correct words before them
+ -- ("stuff stuf", "broken ok", ...)
+ -- we match typos only when they are enclosed in non-letter characters.
+ local start, finish = text:find('[%A]' .. escape_lua_pattern(typo) ..
+ '[%A]', index)
+ -- typo was not found by our pattern this means it must be either
+ -- the first or last word in the text
+ if not start then
+ -- check start of text
+ start = 1
+ finish = #typo
+ -- typo is not the beginning must be the end of text
+ if text:sub(start, finish) ~= typo then
+ start = #text - #typo + 1
+ finish = start + #typo - 1
+ end
+
+ if text:sub(start, finish) ~= typo then
+ vis:info(string.format(
+ 'can\'t find typo %s after %d. Please report this bug.',
+ typo, index))
+ end
+ -- our pettern [%A]typo[%A] found it
+ else
+ start = start + 1 -- ignore leading non letter char
+ finish = finish - 1 -- ignore trailing non letter char
+ end
+ index = finish
+
+ return typo, start, finish
+ end
+ end
end
-local last_viewport, last_data, last_typos = nil, "", ""
+local last_viewport, last_data, last_typos = nil, '', ''
vis.events.subscribe(vis.events.WIN_HIGHLIGHT, function(win)
- if not spellcheck.check_full_viewport[win] or not win:style_define(42, spellcheck.typo_style) then
- return false
- end
- local viewport = win.viewport
- local viewport_text = win.file:content(viewport)
-
- local typos
- if last_viewport == viewport_text then
- typos = last_typos
- else
- typos = get_typos(viewport) or ""
- if not typos then
- return false
- end
- end
-
- for _, start, finish in typo_iter(viewport_text, typos, ignored) do
- win:style(42, viewport.start + start - 1, viewport.start + finish)
- end
-
- last_viewport = viewport_text
- last_typos = typos
- return true
+ if not spellcheck.check_full_viewport[win] or
+ not win:style_define(42, spellcheck.typo_style) then
+ return
+ end
+ local viewport = win.viewport
+ local viewport_text = win.file:content(viewport)
+
+ local typos
+ if last_viewport == viewport_text then
+ typos = last_typos
+ else
+ typos = get_typos(viewport) or ''
+ if not typos then
+ return
+ end
+ end
+
+ for _, start, finish in typo_iter(viewport_text, typos, ignored) do
+ win:style(42, viewport.start + start - 1, viewport.start + finish)
+ end
+
+ last_viewport = viewport_text
+ last_typos = typos
+ -- TODO: think about returning true here
+ -- http://martanne.github.io/vis/doc/index.html#Events
+ -- The vis documentation states that a no further event handlers are called if one
+ -- returns not nil
+ -- Should we terminate the WIN_HIGHLIGHT event handling if we are ready highltighting
+ -- typos ?
+ return true
end)
local wrapped_lex_funcs = {}
local wrap_lex_func = function(old_lex_func)
- local old_new_tokens = {}
-
- return function(lexer, data, index, redrawtime_max)
- local tokens, timedout = old_lex_func(lexer, data, index, redrawtime_max)
-
- -- quit early if the lexer already took to long
- -- TODO: investigate further if timedout is actually set by the lexer.
- -- As I understand lpeg.match used by lexer.lex timedout will always be nil
- if timedout then
- return tokens, timedout
- end
-
- local new_tokens = {}
-
- local typos
- if last_data ~= data
- then
- typos = get_typos(data)
- if not typos then
- return tokens, timedout
- end
- last_data = data
- else
- return old_new_tokens
- end
-
- local i = 1
- for _, typo_start, typo_end in typo_iter(data, typos, ignored) do
- repeat
- -- no tokens left
- if i > #tokens -1 then
- break
- end
-
- local token_type = tokens[i]
- local token_start = (tokens[i-1] or 1) - 1
- local token_end = tokens[i+1]
-
- -- the current token ends before our typo -> append to new stream
- -- or is not spellchecked
- if token_end < typo_start or not spellcheck.check_tokens[token_type] then
- table.insert(new_tokens, token_type)
- table.insert(new_tokens, token_end)
-
- -- done with this token -> advance token stream
- i = i + 2
- -- typo and checked token overlap
- else
- local pre_typo_end = typo_start - 1
- -- unchanged token part before typo
- if pre_typo_end > token_start then
- table.insert(new_tokens, token_type)
- table.insert(new_tokens, pre_typo_end + 1)
- end
-
- -- highlight typo
- table.insert(new_tokens, vis.lexers.ERROR)
- -- the typo spans multiple tokens
- if token_end < typo_end then
- table.insert(new_tokens, token_end + 1)
- i = i + 2
- else
- table.insert(new_tokens, typo_end + 1)
- end
- end
- until(not token_end or token_end >= typo_end)
- end
-
- -- add tokens left after we handled all typos
- for i = i, #tokens, 1 do
- table.insert(new_tokens, tokens[i])
- end
-
- old_new_tokens = new_tokens
- return new_tokens, timedout
- end
+ local old_new_tokens = {}
+
+ return function(lexer, data, index, redrawtime_max)
+ local tokens, timedout = old_lex_func(lexer, data, index, redrawtime_max)
+
+ -- quit early if the lexer already took to long
+ -- TODO: investigate further if timedout is actually set by the lexer.
+ -- As I understand lpeg.match used by lexer.lex timedout will always be nil
+ if timedout then
+ return tokens, timedout
+ end
+
+ local new_tokens = {}
+
+ local typos
+ if last_data ~= data then
+ typos = get_typos(data)
+ if not typos then
+ return tokens, timedout
+ end
+ last_data = data
+ else
+ return old_new_tokens
+ end
+
+ local i = 1
+ for _, typo_start, typo_end in typo_iter(data, typos, ignored) do
+ repeat
+ -- no tokens left
+ if i > #tokens - 1 then
+ break
+ end
+
+ local token_type = tokens[i]
+ local token_start = (tokens[i - 1] or 1) - 1
+ local token_end = tokens[i + 1]
+
+ -- the current token ends before our typo -> append to new stream
+ -- or is not spellchecked
+ if token_end < typo_start or not spellcheck.check_tokens[token_type] then
+ table.insert(new_tokens, token_type)
+ table.insert(new_tokens, token_end)
+
+ -- done with this token -> advance token stream
+ i = i + 2
+ -- typo and checked token overlap
+ else
+ local pre_typo_end = typo_start - 1
+ -- unchanged token part before typo
+ if pre_typo_end > token_start then
+ table.insert(new_tokens, token_type)
+ table.insert(new_tokens, pre_typo_end + 1)
+ end
+
+ -- highlight typo
+ table.insert(new_tokens, vis.lexers.ERROR)
+ -- the typo spans multiple tokens
+ if token_end < typo_end then
+ table.insert(new_tokens, token_end + 1)
+ i = i + 2
+ else
+ table.insert(new_tokens, typo_end + 1)
+ end
+ end
+ until (not token_end or token_end >= typo_end)
+ end
+
+ -- add tokens left after we handled all typos
+ for i = i, #tokens, 1 do
+ table.insert(new_tokens, tokens[i])
+ end
+
+ old_new_tokens = new_tokens
+ return new_tokens, timedout
+ end
end
local enable_spellcheck = function()
- -- prevent wrapping the lex function multiple times
- if wrapped_lex_funcs[vis.win] then
- return
- end
-
- if not spellcheck.disable_syntax_awareness and vis.win.syntax and vis.lexers.load then
- local lexer = vis.lexers.load(vis.win.syntax, nil, true)
- if lexer and lexer.lex then
- local old_lex_func = lexer.lex
- wrapped_lex_funcs[vis.win] = old_lex_func
- lexer.lex = wrap_lex_func(old_lex_func)
- -- reset last data to enforce new highlighting
- last_data = ""
- return
- end
- end
-
- -- fallback check spellcheck the full viewport
- spellcheck.check_full_viewport[vis.win] = true
+ -- prevent wrapping the lex function multiple times
+ if wrapped_lex_funcs[vis.win] then
+ return
+ end
+
+ if not spellcheck.disable_syntax_awareness and vis.win.syntax and
+ vis.lexers.load then
+ local lexer = vis.lexers.load(vis.win.syntax, nil, true)
+ if lexer and lexer.lex then
+ local old_lex_func = lexer.lex
+ wrapped_lex_funcs[vis.win] = old_lex_func
+ lexer.lex = wrap_lex_func(old_lex_func)
+ -- reset last data to enforce new highlighting
+ last_data = ''
+ return
+ end
+ end
+
+ -- fallback check spellcheck the full viewport
+ spellcheck.check_full_viewport[vis.win] = true
end
local is_spellcheck_enabled = function()
- return spellcheck.check_full_viewport[vis.win] or wrapped_lex_funcs[vis.win]
+ return spellcheck.check_full_viewport[vis.win] or wrapped_lex_funcs[vis.win]
end
-vis:map(vis.modes.NORMAL, "<C-w>e", function()
- enable_spellcheck()
-end, "Enable spellchecking in the current window")
+vis:map(vis.modes.NORMAL, '<C-w>e', function()
+ enable_spellcheck()
+end, 'Enable spellchecking in the current window')
local disable_spellcheck = function()
- local old_lex_func = wrapped_lex_funcs[vis.win]
- if old_lex_func then
- local lexer = vis.lexers.load(vis.win.syntax, nil, true)
- lexer.lex = old_lex_func
- wrapped_lex_funcs[vis.win] = nil
- else
- spellcheck.check_full_viewport[vis.win] = nil
- end
+ local old_lex_func = wrapped_lex_funcs[vis.win]
+ if old_lex_func then
+ local lexer = vis.lexers.load(vis.win.syntax, nil, true)
+ lexer.lex = old_lex_func
+ wrapped_lex_funcs[vis.win] = nil
+ else
+ spellcheck.check_full_viewport[vis.win] = nil
+ end
end
-vis:map(vis.modes.NORMAL, "<C-w>d", function()
- disable_spellcheck()
- -- force new highlight
- vis.win:draw()
-end, "Disable spellchecking in the current window")
+vis:map(vis.modes.NORMAL, '<C-w>d', function()
+ disable_spellcheck()
+ -- force new highlight
+ vis.win:draw()
+end, 'Disable spellchecking in the current window')
-- toggle spellchecking on <F7>
-- <F7> is used by some word processors (LibreOffice) for spellchecking
-- Thanks to @leorosa for the hint.
-vis:map(vis.modes.NORMAL, "<F7>", function()
- if not is_spellcheck_enabled() then
- enable_spellcheck()
- else
- disable_spellcheck()
- vis.win:draw()
- end
- return 0
-end, "Toggle spellchecking in the current window")
-
-vis:map(vis.modes.NORMAL, "<C-w>w", function()
- local win = vis.win
- local file = win.file
- local pos = win.selection.pos
- if not pos then return end
- local range = file:text_object_word(pos);
- if not range then return end
- if range.start == range.finish then return end
-
- local cmd = spellcheck.cmd:format(spellcheck.lang)
- local ret, so, se = vis:pipe(win.file, range, cmd)
- if ret ~= 0 then
- vis:message("calling " .. cmd .. " failed ("..se..")")
- return false
- end
-
- local answer_line = so:match(".-\n(.-)\n.*")
- if not answer_line then
- return false
- end
-
- local suggestions
- local first_char = answer_line:sub(0,1)
- if first_char == "*" then
- vis:info(file:content(range).." is correctly spelled")
- return true
- elseif first_char == "#" then
- vis:info("No corrections available for "..file:content(range))
- return false
- elseif first_char == "&" then
- suggestions = answer_line:match("& %S+ %d+ %d+: (.*)")
- else
- vis:info("Unknown answer: "..answer_line)
- return false
- end
-
- -- select a correction
- cmd = 'printf "' .. suggestions:gsub(", ", "\\n") .. '\\n" | vis-menu'
- local status, correction = vis:pipe(file, {start = 0, finish = 0}, cmd)
- if status == 0 then
- -- trim correction
- correction = correction:match("^%s*(.-)%s*$")
- win.file:delete(range)
- win.file:insert(range.start, correction)
- end
-
- win.selection.pos = pos
-
- win:draw()
-
- return 0
-end, "Correct misspelled word")
-
-vis:map(vis.modes.NORMAL, "<C-w>i", function()
- local win = vis.win
- local file = win.file
- local pos = win.selection.pos
- if not pos then return end
- local range = file:text_object_word(pos);
- if not range then return end
- if range.start == range.finish then return end
-
- ignored[file:content(range)] = true
-
- -- Check if we use our syntax aware spellcheck lex-closure
- -- We must rebuild the closure because it captures ignored
- -- to include the new addition
- local old_lex_func = wrapped_lex_funcs[vis.win]
- if old_lex_func then
- local lexer = vis.lexers.load(vis.win.syntax, nil, true)
- lexer.lex = wrap_lex_func(old_lex_func)
- -- reset last data to enforce new highlighting
- last_data = ""
- end
-
- win:draw()
- return 0
-end, "Ignore misspelled word")
-
-vis:option_register("spelllang", "string", function(value)
- spellcheck.lang = value
- vis:info("Spellchecking language is now "..value)
- -- force new highlight for full viewport
- last_viewport = nil
- -- force new highlight for syntax aware
- last_data = nil
- return true
-end, "The language used for spellchecking")
+vis:map(vis.modes.NORMAL, '<F7>', function()
+ if not is_spellcheck_enabled() then
+ enable_spellcheck()
+ else
+ disable_spellcheck()
+ vis.win:draw()
+ end
+ return 0
+end, 'Toggle spellchecking in the current window')
+
+vis:map(vis.modes.NORMAL, '<C-w>w', function()
+ local win = vis.win
+ local file = win.file
+ local pos = win.selection.pos
+ if not pos then
+ return
+ end
+ local range = file:text_object_word(pos);
+ if not range then
+ return
+ end
+ if range.start == range.finish then
+ return
+ end
+
+ local cmd = spellcheck.cmd:format(spellcheck.lang)
+ local ret, so, se = vis:pipe(win.file, range, cmd)
+ if ret ~= 0 then
+ vis:message('calling ' .. cmd .. ' failed (' .. se .. ')')
+ return false
+ end
+
+ local answer_line = so:match('.-\n(.-)\n.*')
+ if not answer_line then
+ return false
+ end
+
+ local suggestions
+ local first_char = answer_line:sub(0, 1)
+ if first_char == '*' then
+ vis:info(file:content(range) .. ' is correctly spelled')
+ return true
+ elseif first_char == '#' then
+ vis:info('No corrections available for ' .. file:content(range))
+ return false
+ elseif first_char == '&' then
+ suggestions = answer_line:match('& %S+ %d+ %d+: (.*)')
+ else
+ vis:info('Unknown answer: ' .. answer_line)
+ return false
+ end
+
+ -- select a correction
+ cmd = 'printf "' .. suggestions:gsub(', ', '\\n') .. '\\n" | vis-menu'
+ local status, correction = vis:pipe(file, {start = 0, finish = 0}, cmd)
+ if status == 0 then
+ -- trim correction
+ correction = correction:match('^%s*(.-)%s*$')
+ win.file:delete(range)
+ win.file:insert(range.start, correction)
+ end
+
+ win.selection.pos = pos
+
+ win:draw()
+
+ return 0
+end, 'Correct misspelled word')
+
+vis:map(vis.modes.NORMAL, '<C-w>i', function()
+ local win = vis.win
+ local file = win.file
+ local pos = win.selection.pos
+ if not pos then
+ return
+ end
+ local range = file:text_object_word(pos);
+ if not range then
+ return
+ end
+ if range.start == range.finish then
+ return
+ end
+
+ ignored[file:content(range)] = true
+
+ -- Check if we use our syntax aware spellcheck lex-closure
+ -- We must rebuild the closure because it captures ignored
+ -- to include the new addition
+ local old_lex_func = wrapped_lex_funcs[vis.win]
+ if old_lex_func then
+ local lexer = vis.lexers.load(vis.win.syntax, nil, true)
+ lexer.lex = wrap_lex_func(old_lex_func)
+ -- reset last data to enforce new highlighting
+ last_data = ''
+ end
+
+ win:draw()
+ return 0
+end, 'Ignore misspelled word')
+
+vis:option_register('spelllang', 'string', function(value)
+ spellcheck.lang = value
+ vis:info('Spellchecking language is now ' .. value)
+ -- force new highlight for full viewport
+ last_viewport = nil
+ -- force new highlight for syntax aware
+ last_data = nil
+ return true
+end, 'The language used for spellchecking')
return spellcheck