Download CommonLua/X/XTextEditorPlugins.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 9.18 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/X/XTextEditorPlugins.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/X/XTextEditorPlugins.lua
-
curl -L -o XTextEditorPlugins.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/X/XTextEditorPlugins.lua
9.18 kB
| -- Small XTextEditor plugins should be implemented here | |
| ----- XSpellcheckPlugin | |
| DefineClass.XSpellcheckPlugin = { | |
| __parents = { "XTextEditorPlugin" }, | |
| UnderlineColor = RGB(255, 20, 20), | |
| } | |
| local word_chars = "[_%w\127-\255\39]" -- count any utf8 extented character as a word character | |
| local nonword_chars = "[^_%w\127-\255\39]" | |
| local word_pattern = "(" .. word_chars .. "*)" .. "(" .. nonword_chars .. "*)" | |
| local whitespace = "[\9\32]" | |
| local multiple_whitespace = "[\9\32][\9\32]+" | |
| local MeasureToCharStart = UIL.MeasureToCharStart | |
| local StretchText = UIL.StretchText | |
| function XSpellcheckPlugin:Init() | |
| LoadDictionary() | |
| end | |
| function XSpellcheckPlugin:OnDrawText(edit, line_idx, text, target_box, font, text_color) | |
| local y = target_box:maxy() - 4 | |
| local position_in_text = 0 | |
| local substitutions = { {"‘", "'"}, {"’", "'"}, {"“", "\""}, {"”", "\""}, {"–", "-"}, {"—", "-"}, {"…", "."}, {"−", "-"}} | |
| for i = 1, #substitutions do | |
| text = text:gsub(substitutions[i][1], substitutions[i][2]) | |
| end | |
| -- underline whitespace at the begining of the line | |
| if #text >= 1 and text:sub(1,1):find(whitespace) then | |
| self:Underline(text, target_box:minx(), y, 1, 2, font) | |
| end | |
| -- underline whitespace at the end of the line; lines always end with a space, so the second to last character in the string should be checked | |
| if #text >= 1 and text:sub(#text - 1,#text - 1):find(whitespace) then | |
| self:Underline(text, target_box:minx(), y, #text- 1, #text, font) | |
| end | |
| local untagged, tag, first, last = string.nexttag(text, 1) | |
| -- Check for unmatched closing tag bracket (>) at the beginning of the text and if found, skip the dictionary checks for the text before it | |
| local unmatched_closing_tag = false | |
| local close_tag_idx | |
| if not tag then | |
| local open_tag_idx = string.find(untagged, "<") | |
| close_tag_idx = string.find(untagged, ">") | |
| -- Find the farthest unmatched closing tag bracket (>) | |
| while open_tag_idx and close_tag_idx do | |
| local next_close_tag = string.find(untagged, ">", close_tag_idx + 1) | |
| if next_close_tag and next_close_tag < open_tag_idx then | |
| close_tag_idx = next_close_tag | |
| else | |
| break | |
| end | |
| end | |
| unmatched_closing_tag = (close_tag_idx and not open_tag_idx) or (close_tag_idx and open_tag_idx and close_tag_idx < open_tag_idx) | |
| end | |
| -- try this - if the current position_in_text is < and there's no closing tag until the end skip/break | |
| for word, non_word in text:gmatch(word_pattern) do | |
| -- Check for unmatched opening tag bracket (<) at the end of the text and if found, skip the dictionary checks for the text after it | |
| if string.sub(text, position_in_text, position_in_text) == "<" and not string.find(text, ">", position_in_text + 1) then | |
| break | |
| end | |
| local current_word_end_pos = position_in_text + utf8.len(word) | |
| local new_position_in_text = current_word_end_pos + utf8.len(non_word) | |
| if tag and position_in_text >= first and current_word_end_pos <= last then | |
| -- we have reached a word/text enclosed in < and > - don't check it against the dictionary | |
| if position_in_text < last and new_position_in_text >= last then | |
| -- find the next word in tags | |
| untagged, tag, first, last = string.nexttag(text, new_position_in_text) | |
| end | |
| -- Enter only if we're outside of the unmatched closing tag (if any) | |
| elseif not (unmatched_closing_tag and position_in_text <= close_tag_idx) then | |
| word = word:gsub("^'", ""):gsub("'$", "") -- remove leading and trailing ' characters | |
| local lowercase_word = word:lower() | |
| if not WordInDictionary(word, lowercase_word) then | |
| self:Underline(text, target_box:minx(), y, position_in_text + 1, current_word_end_pos + 1, font) | |
| end | |
| local comma_pos = non_word:find("[,;].*") | |
| local comma, other_chars = non_word:match("([,;])(.*)") | |
| -- , or ; is underlined only if it is not followed by space and is at the end of line | |
| -- however, every line ends with a space and if there's a space after the , or ;, it needs to be checked for eol | |
| if comma and (not other_chars or not other_chars:starts_with("<")) and | |
| (not other_chars or other_chars:sub(1, 1) ~= " " or | |
| (other_chars:sub(1, 1) == " " and current_word_end_pos + comma_pos == text:len())) | |
| then | |
| local underline_start = current_word_end_pos + comma_pos | |
| self:Underline(text, target_box:minx(), y, underline_start, underline_start + 1, font) | |
| end | |
| -- . or : is underlined only if it is not followed by space | |
| local dot_pos = non_word:find("[%.:][^%s]*$") | |
| local dot_idx = dot_pos and current_word_end_pos + dot_pos | |
| if dot_idx and dot_idx ~= text:len() then | |
| local next_char = text:sub(dot_idx + 1, dot_idx + 1) | |
| if next_char ~= "\"" and next_char ~= "\'" and next_char ~= "." and next_char ~= "<" then | |
| self:Underline(text, target_box:minx(), y, dot_idx, dot_idx + 1, font) | |
| end | |
| end | |
| -- multiple whitespace handling | |
| local whitespace_start, whitespace_end = non_word:find(multiple_whitespace) | |
| if whitespace_start then | |
| self:Underline(text, target_box:minx(), y, current_word_end_pos + whitespace_start, current_word_end_pos + whitespace_end + 1, font) | |
| end | |
| end | |
| position_in_text = new_position_in_text | |
| end | |
| end | |
| function XSpellcheckPlugin:Underline(text, x, y, underline_start, underline_end, font) | |
| local x_start = MeasureToCharStart(text, font, underline_start) | |
| local x_end = MeasureToCharStart(text, font, underline_end) | |
| UIL.DrawSolidRect(box(x + x_start, y, x + x_end, y + 2), self.UnderlineColor) | |
| end | |
| function XSpellcheckPlugin:OnRightButtonDown(edit, pt) | |
| local word = edit:GetWordUnderCursor(pt) or "" | |
| local lowercase_word = word:lower() | |
| if not WordInDictionary(word, lowercase_word) then | |
| CreateRealTimeThread(function() | |
| local title = "Add to dictionary" | |
| local text = "Do you want to save '"..word.."' to the dictionary?" | |
| local dialog = StdMessageDialog:new({}, edit.desktop, { question = true, title = title, text = text }) | |
| dialog:Open() | |
| dialog:SetZOrder(BaseLoadingScreen.ZOrder + 2) -- above the bug report dialog... | |
| local result, win = dialog:Wait() | |
| if result == "ok" then | |
| local new_entry = word:match("%l") and lowercase_word or word | |
| SpellcheckDict[new_entry] = true | |
| WriteToDictionary(SpellcheckDict) | |
| end | |
| end) | |
| return "break" | |
| end | |
| end | |
| ----- XExternalTextEditorPlugin | |
| if FirstLoad then | |
| g_ExternalTextEditorActiveCtrl = false | |
| end | |
| DefineClass.XExternalTextEditorPlugin = { | |
| __parents = { "XTextEditorPlugin" }, | |
| } | |
| function XExternalTextEditorPlugin:Init() | |
| g_ExternalTextEditorActiveCtrl = false | |
| end | |
| function XExternalTextEditorPlugin:Done() | |
| if g_ExternalTextEditorActiveCtrl then | |
| g_ExternalTextEditorActiveCtrl = false | |
| end | |
| end | |
| function XExternalTextEditorPlugin:OpenEditor(edit) | |
| g_ExternalTextEditorActiveCtrl = edit | |
| AsyncCreatePath("AppData/editorplugin/") | |
| local file_path = "AppData/editorplugin/" .. config.DefaultExternalTextEditorTempFile | |
| AsyncStringToFile(file_path, edit:GetText()) | |
| local cmd = config.DefaultExternelTextEditorCmd | |
| and string.format(config.DefaultExternelTextEditorCmd, ConvertToOSPath(file_path)) | |
| or string.format("\"%s\" %s",config.DefaultExternelTextEditorPath, ConvertToOSPath(file_path)) | |
| os.execute(cmd) | |
| end | |
| function XExternalTextEditorPlugin:OnShortcut(edit, shortcut, source, ...) | |
| if shortcut == "Ctrl-E" then | |
| self:OpenEditor(edit) | |
| return true | |
| end | |
| end | |
| function XExternalTextEditorPlugin:OnTextChanged(edit) | |
| -- update external file | |
| if g_ExternalTextEditorActiveCtrl == edit then | |
| local file_path = "AppData/editorplugin/" .. config.DefaultExternalTextEditorTempFile | |
| AsyncStringToFile(file_path, edit:GetText()) | |
| end | |
| end | |
| function XExternalTextEditorPlugin.ApplyEdit(file, change) | |
| if change == "Modified" then | |
| local err, content = AsyncFileToString(file) | |
| if not err then | |
| if g_ExternalTextEditorActiveCtrl then | |
| g_ExternalTextEditorActiveCtrl:SetText(content) | |
| end | |
| end | |
| end | |
| end | |
| ----- XHighlightTextPlugin | |
| DefineClass.XHighlightTextPlugin = { | |
| __parents = { "XTextEditorPlugin" }, | |
| HighlightColor = RGB(188, 168, 70), | |
| SingleInstance = false, | |
| highlighted_text = false, | |
| ignore_case = true, | |
| } | |
| local function find_next(str_lower, str, substr, start_pos) | |
| local idx = string.find(str_lower, substr, start_pos, true) | |
| if idx then | |
| return str:sub(start_pos, idx - 1), str:sub(idx, idx + #substr - 1) | |
| else | |
| return str:sub(start_pos) | |
| end | |
| end | |
| function XHighlightTextPlugin:OnAfterDrawText(edit, line_idx, text, target_box, font, text_color) | |
| if not self.highlighted_text or self.highlighted_text == "" then return end | |
| local pos = 1 | |
| local text_start = target_box:minx() | |
| local lower_text = self.ignore_case and text:lower() or text | |
| local other, word | |
| repeat | |
| other, word = find_next(lower_text, text, self.highlighted_text, pos) | |
| if word then | |
| local len_word = utf8.len(word) | |
| local len_other = utf8.len(other) | |
| local x1 = MeasureToCharStart(text, font, pos + len_other) | |
| local x2 = MeasureToCharStart(text, font, pos + len_word + len_other) | |
| local word_box = box(text_start + x1, target_box:miny(), text_start + x2, target_box:maxy()) | |
| StretchText(word, word_box, font, self.HighlightColor) | |
| pos = pos + len_word + len_other | |
| end | |
| until not word | |
| return true | |
| end | |