diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/colorpicker.lua | 56 | ||||
-rw-r--r-- | plugins/ipc.lua | 2 | ||||
-rw-r--r-- | plugins/language_nix.lua | 87 | ||||
-rw-r--r-- | plugins/language_rivet.lua | 6 | ||||
-rw-r--r-- | plugins/minimap.lua | 33 | ||||
-rw-r--r-- | plugins/settings.lua | 77 | ||||
-rw-r--r-- | plugins/spellcheck.lua | 100 |
7 files changed, 300 insertions, 61 deletions
diff --git a/plugins/colorpicker.lua b/plugins/colorpicker.lua new file mode 100644 index 0000000..c280fb6 --- /dev/null +++ b/plugins/colorpicker.lua @@ -0,0 +1,56 @@ +-- mod-version:3 +local command = require "core.command" +local keymap = require "core.keymap" +local ColorPickerDialog = require "libraries.widget.colorpickerdialog" + +---Get the color format of given text. +---@param text string +---@return "html" | "html_opacity" | "rgb" +local function get_color_type(text) + local found = text:find("#%x%x%x%x%x%x%x?%x?") + if found then + found = text:find("#%x%x%x%x%x%x%x%x") + if found then return "html_opacity" end + return "html" + else + found = text:find("#%x%x%x") + if found then + return "html" + else + found = text:find( + "rgba?%((%d+)%D+(%d+)%D+(%d+)[%s,]-([%.%d]-)%s-%)" + ) + if found then return "rgb" end + end + end + return "html" +end + +command.add("core.docview!", { + ["color-picker:open"] = function(dv) + ---@type core.doc + local doc = dv.doc + local selection = doc:get_text(doc:get_selection()) + local type = get_color_type(selection) + + ---@type widget.colorpickerdialog + local picker = ColorPickerDialog(nil, selection) + function picker:on_apply(c) + local value + if type == "html" then + value = string.format("#%02X%02X%02X", c[1], c[2], c[3]) + elseif type == "html_opacity" then + value = string.format("#%02X%02X%02X%02X", c[1], c[2], c[3], c[4]) + elseif type == "rgb" then + value = string.format("rgba(%d, %d, %d, %.2f)", c[1], c[2], c[3], c[4]/255) + end + doc:text_input(value) + end + picker:show() + picker:centered() + end, +}) + +keymap.add { + ["ctrl+alt+k"] = "color-picker:open" +} diff --git a/plugins/ipc.lua b/plugins/ipc.lua index 0f9a172..16eab5d 100644 --- a/plugins/ipc.lua +++ b/plugins/ipc.lua @@ -866,7 +866,7 @@ end local system_get_time = system.get_time system.get_time = function() - if settings_found and not settings.ui then + if settings_found and settings and not settings.ui then return system_get_time() end diff --git a/plugins/language_nix.lua b/plugins/language_nix.lua new file mode 100644 index 0000000..149c2fa --- /dev/null +++ b/plugins/language_nix.lua @@ -0,0 +1,87 @@ +-- mod-version:3 +-- https://nixos.wiki/wiki/Overview_of_the_Nix_Language +local syntax = require "core.syntax" + +local function merge_tables(a, b) + for _, v in pairs(b) do + table.insert(a, v) + end +end + +local default_symbols = { + ["import"] = "keyword2", + ["with"] = "keyword2", + ["builtins"] = "keyword2", + ["inherit"] = "keyword2", + ["assert"] = "keyword2", + ["let"] = "keyword2", + ["in"] = "keyword2", + ["rec"] = "keyword2", + ["if"] = "keyword", + ["else"] = "keyword", + ["then"] = "keyword", + ["true"] = "literal", + ["false"] = "literal", + ["null"] = "literal", +} + +local default_patterns = {} + +local string_interpolation = { + { pattern = {"%${", "}"}, type = "keyword2", syntax = { + patterns = default_patterns, + symbols = default_symbols, + }}, + { pattern = "[%S][%w]*", type = "string" }, +} + +merge_tables(default_patterns, { + { pattern = "#.*", type = "comment" }, + { pattern = {"/%*", "%*/"}, type = "comment" }, + { pattern = "-?%.?%d+", type = "number" }, + + -- interpolation + { pattern = {"%${", "}"}, type = "keyword2", syntax = { + patterns = default_patterns, + symbols = default_symbols, + }}, + { pattern = {'"', '"', '\\'}, type = "string", syntax = { + patterns = string_interpolation, + symbols = {}, + }}, + { pattern = {"''", "''"}, type = "string", syntax = { + patterns = string_interpolation, + symbols = {}, + }}, + + -- operators + { pattern = "[%+%-%?!>%*]", type = "operator" }, + { pattern = "/ ", type = "operator" }, + { pattern = "< ", type = "operator" }, + { pattern = "//", type = "operator" }, + { pattern = "&&", type = "operator" }, + { pattern = "%->", type = "operator" }, + { pattern = "||", type = "operator" }, + { pattern = "==", type = "operator" }, + { pattern = "!=", type = "operator" }, + { pattern = ">=", type = "operator" }, + { pattern = "<=", type = "operator" }, + + -- paths (function because its not used otherwise) + { pattern = "%.?%.?/[^%s%[%]%(%){};,:]+", type = "function" }, + { pattern = "~/[^%s%[%]%(%){};,:]+", type = "function" }, + { pattern = {"<", ">"}, type = "function" }, + + -- every other symbol + { pattern = "[%a%-%_][%w%-%_]*", type = "symbol" }, + { pattern = ";%.,:", type = "normal" }, +}) + +syntax.add { + name = "Nix", + files = {"%.nix$"}, + comment = "#", + block_comment = {"/*", "*/"}, + patterns = default_patterns, + symbols = default_symbols, +} diff --git a/plugins/language_rivet.lua b/plugins/language_rivet.lua index 0416850..aceb5a1 100644 --- a/plugins/language_rivet.lua +++ b/plugins/language_rivet.lua @@ -28,11 +28,11 @@ syntax.add { type = "number" }, {pattern = "[A-Z][%w_]*", type = "keyword2"}, -- types + {pattern = "%@%s?[%a_][%w_]*", type = "literal"}, -- builtin func/var {pattern = "[%a_][%w_]*%f[(]", type = "function"}, - {pattern = "[%a_][%w_]*!%f[(]", type = "keyword2"}, -- builtin function {pattern = "[%a_][%w_]*", type = "symbol"}, {pattern = {"#%[", "%]"}, type = "literal"}, - {pattern = "#%s?[%a_][%w_]*", type = "comment"} -- #if/#elif/#else/#endif + {pattern = "#%s?[%a_][%w_]*", type = "comment"} -- if/elif/else/endif }, symbols = { ["and"] = "keyword", @@ -49,9 +49,11 @@ syntax.add { ["errdefer"] = "keyword", ["extend"] = "keyword", ["extern"] = "keyword", + ["export"] = "keyword", ["false"] = "literal", ["fn"] = "keyword", ["for"] = "keyword", + ["from"] = "keyword", ["if"] = "keyword", ["import"] = "keyword", ["in"] = "keyword", diff --git a/plugins/minimap.lua b/plugins/minimap.lua index 75eb272..ac94849 100644 --- a/plugins/minimap.lua +++ b/plugins/minimap.lua @@ -135,29 +135,21 @@ config.plugins.minimap = common.merge({ }, { label = "Selection Color", - description = "Background color of selected text in html notation eg: #FFFFFF. Leave empty to use default.", - path = "selection_color_html", - type = "string", - on_apply = function(value) - if value and value:match("#%x%x%x%x%x%x") then - config.plugins.minimap.selection_color = { common.color(value) } - else - config.plugins.minimap.selection_color = nil - end - end + description = "Background color of selected text.", + path = "selection_color", + type = "color", + default = string.format("#%02X%02X%02X%02X", + style.dim[1], style.dim[2], style.dim[3], style.dim[4] + ) }, { label = "Caret Color", - description = "Background color of active line in html notation eg: #FFFFFF. Leave empty to use default.", - path = "caret_color_html", - type = "string", - on_apply = function(value) - if value and value:match("#%x%x%x%x%x%x") then - config.plugins.minimap.caret_color = { common.color(value) } - else - config.plugins.minimap.caret_color = nil - end - end + description = "Background color of active line.", + path = "caret_color", + type = "color", + default = string.format("#%02X%02X%02X%02X", + style.caret[1], style.caret[2], style.caret[3], style.caret[4] + ) }, { label = "Highlight Alignment", @@ -663,4 +655,3 @@ command.add("core.docview!", { }) return MiniMap - diff --git a/plugins/settings.lua b/plugins/settings.lua index 17ce998..d3af077 100644 --- a/plugins/settings.lua +++ b/plugins/settings.lua @@ -9,28 +9,29 @@ local View = require "core.view" local DocView = require "core.docview" -- check if widget is installed before proceeding -local widget_found, Widget = pcall(require, "widget") +local widget_found, Widget = pcall(require, "libraries.widget") if not widget_found then core.error("Widget library not found: https://github.com/lite-xl/lite-xl-widgets") - return + return false end -local Label = require "widget.label" -local Line = require "widget.line" -local NoteBook = require "widget.notebook" -local Button = require "widget.button" -local TextBox = require "widget.textbox" -local SelectBox = require "widget.selectbox" -local NumberBox = require "widget.numberbox" -local Toggle = require "widget.toggle" -local ListBox = require "widget.listbox" -local FoldingBook = require "widget.foldingbook" -local FontsList = require "widget.fontslist" -local ItemsList = require "widget.itemslist" -local KeybindingDialog = require "widget.keybinddialog" -local Fonts = require "widget.fonts" -local FilePicker = require "widget.filepicker" -local MessageBox = require "widget.messagebox" +local Label = require "libraries.widget.label" +local Line = require "libraries.widget.line" +local NoteBook = require "libraries.widget.notebook" +local Button = require "libraries.widget.button" +local TextBox = require "libraries.widget.textbox" +local SelectBox = require "libraries.widget.selectbox" +local NumberBox = require "libraries.widget.numberbox" +local Toggle = require "libraries.widget.toggle" +local ListBox = require "libraries.widget.listbox" +local FoldingBook = require "libraries.widget.foldingbook" +local FontsList = require "libraries.widget.fontslist" +local ItemsList = require "libraries.widget.itemslist" +local KeybindingDialog = require "libraries.widget.keybinddialog" +local Fonts = require "libraries.widget.fonts" +local FilePicker = require "libraries.widget.filepicker" +local ColorPicker = require "libraries.widget.colorpicker" +local MessageBox = require "libraries.widget.messagebox" ---@class plugins.settings local settings = {} @@ -53,7 +54,8 @@ settings.type = { BUTTON = 6, FONT = 7, FILE = 8, - DIRECTORY = 9 + DIRECTORY = 9, + COLOR = 10 } ---@alias settings.types @@ -65,6 +67,8 @@ settings.type = { ---| `settings.type.BUTTON` ---| `settings.type.FONT` ---| `settings.type.FILE` +---| `settings.type.DIRECTORY` +---| `settings.type.COLOR` ---Represents a setting to render on a settings pane. ---@class settings.option @@ -1261,6 +1265,14 @@ local function add_control(pane, option, plugin_name) file.filters = option.filters or {} widget = file found = true + + elseif option.type == settings.type.COLOR then + ---@type widget.label + Label(pane, option.label .. ":") + ---@type widget.colorpicker + local color = ColorPicker(pane, option_value) + widget = color + found = true end if widget and type(path) ~= "nil" then @@ -1624,11 +1636,13 @@ function Settings:load_keymap_settings() end table.sort(ordered) + ---@type widget.textbox + local textbox = TextBox(self.keybinds, "", "filter bindings...") + ---@type widget.listbox local listbox = ListBox(self.keybinds) listbox.border.width = 0 - listbox:enable_expand(true) listbox:add_column("Command") listbox:add_column("Bindings") @@ -1653,8 +1667,15 @@ function Settings:load_keymap_settings() }, name) end - function listbox:on_row_click(idx, data) - if not keymap_dialog:is_visible() then + function textbox:on_change(value) + listbox:filter(value) + end + + function listbox:on_mouse_pressed(button, x, y, clicks) + listbox.super.on_mouse_pressed(self, button, x, y, clicks) + local idx = listbox:get_selected() + local data = listbox:get_row_data(idx) + if clicks == 2 and not keymap_dialog:is_visible() then local bindings = { keymap.get_binding(data) } keymap_dialog:set_bindings(bindings) keymap_dialog.row_id = idx @@ -1663,6 +1684,14 @@ function Settings:load_keymap_settings() keymap_dialog:show() end end + + ---@param self widget + function self.keybinds:update_positions() + textbox:set_position(0, 0) + textbox:set_size(self:get_width() - self.border.width * 2) + listbox:set_position(0, textbox:get_bottom()) + listbox:set_size(self:get_width() - self.border.width * 2, self:get_height() - textbox:get_height()) + end end function Settings:setup_about() @@ -1819,6 +1848,10 @@ function Settings:update() end end + if self.keybinds:is_visible() then + self.keybinds:update_positions() + end + if self.about:is_visible() then self.about:update_positions() end diff --git a/plugins/spellcheck.lua b/plugins/spellcheck.lua index 29db94c..fbe40f9 100644 --- a/plugins/spellcheck.lua +++ b/plugins/spellcheck.lua @@ -5,6 +5,7 @@ local config = require "core.config" local command = require "core.command" local common = require "core.common" local DocView = require "core.docview" +local Highlighter = require "core.doc.highlighter" local Doc = require "core.doc" local platform_dictionary_file @@ -24,6 +25,58 @@ local last_input_time = 0 local word_pattern = "%a+" local words +local spell_cache = setmetatable({}, { __mode = "k" }) +local font_canary +local font_size_canary + + +-- Move cache to make space for new lines +local prev_insert_notify = Highlighter.insert_notify +function Highlighter:insert_notify(line, n, ...) + prev_insert_notify(self, line, n, ...) + local blanks = { } + if not spell_cache[self] then + spell_cache[self] = {} + end + for i = 1, n do + blanks[i] = false + end + common.splice(spell_cache[self], line, 0, blanks) +end + + +-- Close the cache gap created by removed lines +local prev_remove_notify = Highlighter.remove_notify +function Highlighter:remove_notify(line, n, ...) + prev_remove_notify(self, line, n, ...) + if not spell_cache[self] then + spell_cache[self] = {} + end + common.splice(spell_cache[self], line, n) +end + + +-- Remove changed lines from the cache +local prev_tokenize_line = Highlighter.tokenize_line +function Highlighter:tokenize_line(idx, state, ...) + local res = prev_tokenize_line(self, idx, state, ...) + if not spell_cache[self] then + spell_cache[self] = {} + end + spell_cache[self][idx] = false + return res +end + +local function reset_cache() + for i=1,#spell_cache do + local cache = spell_cache[i] + for j=1,#cache do + cache[j] = false + end + end +end + + local function load_dictionary() core.add_thread(function() local t = {} @@ -61,7 +114,6 @@ end local text_input = Doc.text_input - function Doc:text_input(...) text_input(self, ...) last_input_time = system.get_time() @@ -69,7 +121,6 @@ end local draw_line_text = DocView.draw_line_text - function DocView:draw_line_text(idx, x, y) local lh = draw_line_text(self, idx, x, y) @@ -83,20 +134,39 @@ function DocView:draw_line_text(idx, x, y) return lh end - local s, e = 0, 0 - local text = self.doc.lines[idx] - - while true do - s, e = text:find(word_pattern, e + 1) - if not s then break end - local word = text:sub(s, e):lower() - if not words[word] and not active_word(self.doc, idx, e + 1) then - local color = style.spellcheck_error or style.syntax.keyword2 - local x1, y1 = self:get_line_screen_position(idx, s) - local x2, y2 = self:get_line_screen_position(idx, e + 1) - local h = math.ceil(1 * SCALE) - renderer.draw_rect(x1, y1 + self:get_line_height() - h, x2 - x1, h, color) + if font_canary ~= style.code_font + or font_size_canary ~= style.code_font:get_size() + then + spell_cache[self.doc.highlighter] = {} + font_canary = style.code_font + font_size_canary = style.code_font:get_size() + reset_cache() + end + if not spell_cache[self.doc.highlighter][idx] then + local calculated = {} + local s, e = 0, 0 + local text = self.doc.lines[idx] + + while true do + s, e = text:find(word_pattern, e + 1) + if not s then break end + local word = text:sub(s, e):lower() + if not words[word] and not active_word(self.doc, idx, e + 1) then + table.insert(calculated, self:get_col_x_offset(idx, s)) + table.insert(calculated, self:get_col_x_offset(idx, e + 1)) + end end + + spell_cache[self.doc.highlighter][idx] = calculated + end + + local color = style.spellcheck_error or style.syntax.keyword2 + local h = math.ceil(1 * SCALE) + local lh = self:get_line_height() + local calculated = spell_cache[self.doc.highlighter][idx] + for i=1,#calculated,2 do + local x1, x2 = calculated[i] + x, calculated[i+1] + x + renderer.draw_rect(x1, y + lh - h, x2 - x1, h, color) end return lh end |