From ad4c221dd8adfc16de05f16a4f9d1e686fe44dd0 Mon Sep 17 00:00:00 2001 From: George Sokianos Date: Sun, 11 Feb 2024 17:51:12 +0000 Subject: [PATCH] Manual sync with 2.1.3 tag --- README.md | 52 +------ data/core/commands/doc.lua | 7 +- data/core/commands/findreplace.lua | 31 ++-- data/core/commands/root.lua | 90 +++--------- data/core/commandview.lua | 5 - data/core/config.lua | 203 +-------------------------- data/core/doc/highlighter.lua | 2 +- data/core/doc/init.lua | 90 ++++++------ data/core/docview.lua | 25 +--- data/core/init.lua | 80 ++--------- data/core/keymap-macos.lua | 2 - data/core/keymap.lua | 8 +- data/core/modkeys-generic.lua | 4 - data/core/nagview.lua | 10 +- data/core/node.lua | 57 ++------ data/core/object.lua | 23 --- data/core/rootview.lua | 135 +++--------------- data/core/scrollbar.lua | 11 +- data/core/start.lua | 9 +- data/core/statusview.lua | 52 +------ data/core/style.lua | 13 +- data/core/syntax.lua | 4 +- data/core/titleview.lua | 6 - data/core/tokenizer.lua | 40 +++--- data/core/view.lua | 37 +---- data/plugins/autocomplete.lua | 218 +++-------------------------- data/plugins/detectindent.lua | 29 +--- data/plugins/drawwhitespace.lua | 49 +------ data/plugins/language_md.lua | 2 - data/plugins/lineguide.lua | 22 +-- data/plugins/projectsearch.lua | 2 +- data/plugins/toolbarview.lua | 14 +- data/plugins/treeview.lua | 179 +++-------------------- meson.build | 4 +- scripts/appimage.sh | 2 +- scripts/innosetup/innosetup.iss.in | 6 +- src/api/api.c | 1 + src/api/renderer.c | 1 - src/api/system.c | 31 +--- src/main.c | 18 +-- src/rencache.h | 1 - src/renderer.c | 21 +-- src/renwindow.c | 1 - subprojects/lua.wrap | 18 ++- 44 files changed, 252 insertions(+), 1363 deletions(-) diff --git a/README.md b/README.md index 05949e80..a4feaf7f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Lite XL [![CI]](https://github.com/lite-xl/lite-xl/actions/workflows/build.yml) -[![Discord Badge Image]](https://discord.gg/UQKnzBhY5H) +[![Discord Badge Image]](https://discord.gg/RWzqC3nx7K) ![screenshot-dark] @@ -124,7 +124,6 @@ cd lite-xl ``` To run lite-xl without installing: - ```sh ./lite-xl ``` @@ -137,68 +136,31 @@ mkdir -p $HOME/.local/bin && cp lite-xl $HOME/.local/bin/ mkdir -p $HOME/.local/share/lite-xl && cp -r data/* $HOME/.local/share/lite-xl/ ``` -#### Add Lite XL to PATH - -To run Lite XL from the command line, you must add it to PATH. - If `$HOME/.local/bin` is not in PATH: ```sh echo -e 'export PATH=$PATH:$HOME/.local/bin' >> $HOME/.bashrc ``` -Alternatively on recent versions of GNOME and KDE Plasma, -you can add `$HOME/.local/bin` to PATH via `~/.config/environment.d/envvars.conf`: - -```ini -PATH=$HOME/.local/bin:$PATH -``` - -> **Note** -> Some systems might not load `.bashrc` when logging in. -> This can cause problems with launching applications from the desktop / menu. - -#### Add Lite XL to application launchers - -To get the icon to show up in app launcher, you need to create a desktop -entry and put it into `/usr/share/applications` or `~/.local/share/applications`. - -Here is an example for a desktop entry in `~/.local/share/applications/com.lite_xl.LiteXL.desktop`, -assuming Lite XL is in PATH: - -```ini -[Desktop Entry] -Type=Application -Name=Lite XL -Comment=A lightweight text editor written in Lua -Exec=lite-xl %F -Icon=lite-xl -Terminal=false -StartupWMClass=lite-xl -Categories=Development;IDE; -MimeType=text/plain;inode/directory; -``` - -To get the icon to show up in app launcher immediately, run: +To get the icon to show up in app launcher: ```sh xdg-desktop-menu forceupdate ``` -Alternatively, you may log out and log in again. +You may need to logout and login again to see icon in app launcher. -#### Uninstall - -To uninstall Lite XL, run: +To uninstall just run: ```sh rm -f $HOME/.local/bin/lite-xl rm -rf $HOME/.local/share/icons/hicolor/scalable/apps/lite-xl.svg \ - $HOME/.local/share/applications/com.lite_xl.LiteXL.desktop \ - $HOME/.local/share/metainfo/com.lite_xl.LiteXL.appdata.xml \ + $HOME/.local/share/applications/org.lite_xl.lite_xl.desktop \ + $HOME/.local/share/metainfo/org.lite_xl.lite_xl.appdata.xml \ $HOME/.local/share/lite-xl ``` + ## Contributing Any additional functionality that can be added through a plugin should be done diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 65c92e28..e841bb9c 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -363,7 +363,7 @@ local commands = { ["doc:select-lines"] = function(dv) for idx, line1, _, line2 in dv.doc:get_selections(true) do append_line_if_last_line(line2) - dv.doc:set_selections(idx, line2 + 1, 1, line1, 1) + dv.doc:set_selections(idx, line1, 1, line2 + 1, 1) end end, @@ -548,11 +548,6 @@ local commands = { dv.doc.crlf = not dv.doc.crlf end, - ["doc:toggle-overwrite"] = function(dv) - dv.doc.overwrite = not dv.doc.overwrite - core.blink_reset() -- to show the cursor has changed edit modes - end, - ["doc:save-as"] = function(dv) local last_doc = core.last_active_view and core.last_active_view.doc local text diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua index b77bbcf2..21b62c46 100644 --- a/data/core/commands/findreplace.lua +++ b/data/core/commands/findreplace.lua @@ -196,23 +196,6 @@ local function select_next(reverse) if l2 then doc():set_selection(l2, c2, l1, c1) end end ----@param in_selection? boolean whether to replace in the selections only, or in the whole file. -local function find_replace(in_selection) - local l1, c1, l2, c2 = doc():get_selection() - local selected_text = "" - if not in_selection then - selected_text = doc():get_text(l1, c1, l2, c2) - doc():set_selection(l2, c2, l2, c2) - end - replace("Text", l1 == l2 and selected_text or "", function(text, old, new) - if not find_regex then - return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil) - end - local result, matches = regex.gsub(regex.compile(old, "m"), text, new) - return result, matches - end) -end - command.add(has_unique_selection, { ["find-replace:select-next"] = select_next, ["find-replace:select-previous"] = function() select_next(true) end, @@ -229,11 +212,15 @@ command.add("core.docview!", { end, ["find-replace:replace"] = function() - find_replace() - end, - - ["find-replace:replace-in-selection"] = function() - find_replace(true) + local l1, c1, l2, c2 = doc():get_selection() + local selected_text = doc():get_text(l1, c1, l2, c2) + replace("Text", l1 == l2 and selected_text or "", function(text, old, new) + if not find_regex then + return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil) + end + local result, matches = regex.gsub(regex.compile(old, "m"), text, new) + return result, matches + end) end, ["find-replace:replace-symbol"] = function() diff --git a/data/core/commands/root.lua b/data/core/commands/root.lua index 03f22c25..61e3890b 100644 --- a/data/core/commands/root.lua +++ b/data/core/commands/root.lua @@ -4,7 +4,6 @@ local DocView = require "core.docview" local command = require "core.command" local common = require "core.common" local config = require "core.config" -local Node = require "core.node" local t = { @@ -30,6 +29,20 @@ local t = { core.confirm_close_docs(docs, core.root_view.close_all_docviews, core.root_view, true) end, + ["root:switch-to-previous-tab"] = function(node) + local idx = node:get_view_idx(core.active_view) + idx = idx - 1 + if idx < 1 then idx = #node.views end + node:set_active_view(node.views[idx]) + end, + + ["root:switch-to-next-tab"] = function(node) + local idx = node:get_view_idx(core.active_view) + idx = idx + 1 + if idx > #node.views then idx = 1 end + node:set_active_view(node.views[idx]) + end, + ["root:move-tab-left"] = function(node) local idx = node:get_view_idx(core.active_view) if idx > 1 then @@ -104,7 +117,7 @@ end, t) command.add(nil, { ["root:scroll"] = function(delta) - local view = core.root_view.overlapping_view or core.active_view + local view = (core.root_view.overlapping_node and core.root_view.overlapping_node.active_view) or core.active_view if view and view.scrollable then view.scroll.to.y = view.scroll.to.y + delta * -config.mouse_wheel_scroll return true @@ -112,7 +125,7 @@ command.add(nil, { return false end, ["root:horizontal-scroll"] = function(delta) - local view = core.root_view.overlapping_view or core.active_view + local view = (core.root_view.overlapping_node and core.root_view.overlapping_node.active_view) or core.active_view if view and view.scrollable then view.scroll.to.x = view.scroll.to.x + delta * -config.mouse_wheel_scroll return true @@ -120,74 +133,3 @@ command.add(nil, { return false end }) - -command.add(function(node) - if not Node:is_extended_by(node) then node = nil end - -- No node was specified, use the active one - node = node or core.root_view:get_active_node() - if not node then return false end - return true, node - end, - { - ["root:switch-to-previous-tab"] = function(node) - local idx = node:get_view_idx(node.active_view) - idx = idx - 1 - if idx < 1 then idx = #node.views end - node:set_active_view(node.views[idx]) - end, - - ["root:switch-to-next-tab"] = function(node) - local idx = node:get_view_idx(node.active_view) - idx = idx + 1 - if idx > #node.views then idx = 1 end - node:set_active_view(node.views[idx]) - end, - - ["root:scroll-tabs-backward"] = function(node) - node:scroll_tabs(1) - end, - - ["root:scroll-tabs-forward"] = function(node) - node:scroll_tabs(2) - end - } -) - -command.add(function() - local node = core.root_view.root_node:get_child_overlapping_point(core.root_view.mouse.x, core.root_view.mouse.y) - if not node then return false end - return (node.hovered_tab or node.hovered_scroll_button > 0) and true, node - end, - { - ["root:switch-to-hovered-previous-tab"] = function(node) - command.perform("root:switch-to-previous-tab", node) - end, - - ["root:switch-to-hovered-next-tab"] = function(node) - command.perform("root:switch-to-next-tab", node) - end, - - ["root:scroll-hovered-tabs-backward"] = function(node) - command.perform("root:scroll-tabs-backward", node) - end, - - ["root:scroll-hovered-tabs-forward"] = function(node) - command.perform("root:scroll-tabs-forward", node) - end - } -) - --- double clicking the tab bar, or on the emptyview should open a new doc -command.add(function(x, y) - local node = x and y and core.root_view.root_node:get_child_overlapping_point(x, y) - return node and node:is_in_tab_area(x, y) -end, { - ["tabbar:new-doc"] = function() - command.perform("core:new-doc") - end -}) -command.add("core.emptyview", { - ["emptyview:new-doc"] = function() - command.perform("core:new-doc") - end -}) diff --git a/data/core/commandview.lua b/data/core/commandview.lua index dd2c5e42..1f388678 100644 --- a/data/core/commandview.lua +++ b/data/core/commandview.lua @@ -84,11 +84,6 @@ function CommandView:get_line_screen_position(line, col) end -function CommandView:supports_text_input() - return true -end - - function CommandView:get_scrollable_size() return 0 end diff --git a/data/core/config.lua b/data/core/config.lua index 4f32f244..c1a16b11 100644 --- a/data/core/config.lua +++ b/data/core/config.lua @@ -2,71 +2,15 @@ local common = require "core.common" local config = {} ----The frame rate of Lite XL. ----Note that setting this value to the screen's refresh rate ----does not eliminate screen tearing. ---- ----Defaults to 60. ----@type number config.fps = 60 - ----Maximum number of log items that will be stored. ----When the number of log items exceed this value, old items will be discarded. ---- ----Defaults to 800. ----@type number config.max_log_items = 800 - ----The timeout, in seconds, before a message dissapears from StatusView. ---- ----Defaults to 5. ----@type number config.message_timeout = 5 - ----The number of pixels scrolled per-step. ---- ----Defaults to 50 * SCALE. ----@type number config.mouse_wheel_scroll = 50 * SCALE - ----Enables/disables transitions when scrolling with the scrollbar. ----When enabled, the scrollbar will have inertia and slowly move towards the cursor. ----Otherwise, the scrollbar will immediately follow the cursor. ---- ----Defaults to false. ----@type boolean config.animate_drag_scroll = false - ----Enables/disables scrolling past the end of a document. ---- ----Defaults to true. ----@type boolean config.scroll_past_end = true - ----@alias config.scrollbartype ----| "expanded" # A thicker scrollbar is shown at all times. ----| "contracted" # A thinner scrollbar is shown at all times. ----| false # The scrollbar expands when the cursor hovers over it. - ----Controls whether the DocView scrollbar is always shown or hidden. ----This option does not affect other View's scrollbars. ---- ----Defaults to false. ----@type config.scrollbartype +---@type "expanded" | "contracted" | false @Force the scrollbar status of the DocView config.force_scrollbar_status = false - ----The file size limit, in megabytes. ----Files larger than this size will not be shown in the file picker. ---- ----Defaults to 10. ----@type number config.file_size_limit = 10 - ----A list of files and directories to ignore. ----Each element is a Lua pattern, where patterns ending with a forward slash ----are recognized as directories while patterns ending with an anchor ("$") are ----recognized as files. ----@type string[] config.ignore_files = { -- folders "^%.svn/", "^%.git/", "^%.hg/", "^CVS/", "^%.Trash/", "^%.Trash%-.*/", @@ -77,181 +21,40 @@ config.ignore_files = { "%.suo$", "%.pdb$", "%.idb$", "%.class$", "%.psd$", "%.db$", "^desktop%.ini$", "^%.DS_Store$", "^%.directory$", } - ----Lua pattern used to find symbols when advanced syntax highlighting ----is not available. ----This pattern is also used for navigation, e.g. move to next word. ---- ----The default pattern matches all letters, followed by any number ----of letters and digits. ----@type string config.symbol_pattern = "[%a_][%w_]*" - ----A list of characters that delimits a word. ---- ----The default is ``" \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-"`` ----@type string config.non_word_chars = " \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" - ----The timeout, in seconds, before several consecutive actions ----are merged as a single undo step. ---- ----The default is 0.3 seconds. ----@type number config.undo_merge_timeout = 0.3 - ----The maximum number of undo steps per-document. ---- ----The default is 10000. ----@type number config.max_undos = 10000 - ----The maximum number of tabs shown at a time. ---- ----The default is 8. ----@type number config.max_tabs = 8 - ----Shows/hides the tab bar when there is only one tab open. ---- ----The tab bar is always shown by default. ----@type boolean config.always_show_tabs = true - ----@alias config.highlightlinetype ----| true # Always highlight the current line. ----| false # Never highlight the current line. ----| "no_selection" # Highlight the current line if no text is selected. - ----Highlights the current line. ---- ----The default is true. ----@type config.highlightlinetype +-- Possible values: false, true, "no_selection" config.highlight_current_line = true - ----The spacing between each line of text. ---- ----The default is 120% of the height of the text (1.2). ----@type number config.line_height = 1.2 - ----The number of spaces each level of indentation represents. ---- ----The default is 2. ----@type number config.indent_size = 2 - ----The type of indentation. ---- ----The default is "soft" (spaces). ----@type "soft" | "hard" config.tab_type = "soft" - ----Do not remove whitespaces when advancing to the next line. ---- ----Defaults to false. ----@type boolean config.keep_newline_whitespace = false - ----Default line endings for new files. ---- ----Defaults to `crlf` (`\r\n`) on Windows and `lf` (`\n`) on everything else. ----@type "crlf" | "lf" -config.line_endings = PLATFORM == "Windows" and "crlf" or "lf" - ----Maximum number of characters per-line for the line guide. ---- ----Defaults to 80. ----@type number config.line_limit = 80 - ----Maximum number of project files to keep track of. ----If the number of files in the project exceeds this number, ----Lite XL will not be able to keep track of them. ----They will be not be searched when searching for files or text. ---- ----Defaults to 2000. ----@type number config.max_project_files = 2000 - ----Enables/disables all transitions. ---- ----Defaults to true. ----@type boolean config.transitions = true - ----Enable/disable individual transitions. ----These values are overriden by `config.transitions`. config.disabled_transitions = { - ---Disables scrolling transitions. scroll = false, - ---Disables transitions for CommandView's suggestions list. commandview = false, - ---Disables transitions for showing/hiding the context menu. contextmenu = false, - ---Disables transitions when clicking on log items in LogView. logview = false, - ---Disables transitions for showing/hiding the Nagbar. nagbar = false, - ---Disables transitions when scrolling the tab bar. tabs = false, - ---Disables transitions when a tab is being dragged. tab_drag = false, - ---Disables transitions when a notification is shown. statusbar = false, } - ----The rate of all transitions. ---- ----Defaults to 1. ----@type number config.animation_rate = 1.0 - ----The caret's blinking period, in seconds. ---- ----Defaults to 0.8. ----@type number config.blink_period = 0.8 - ----Disables caret blinking. ---- ----Defaults to false. ----@type boolean config.disable_blink = false - ----Draws whitespaces as dots. ----This option is deprecated. ----Please use the drawwhitespace plugin instead. ----@deprecated config.draw_whitespace = false - ----Disables system-drawn window borders. ---- ----When set to true, Lite XL draws its own window decorations, ----which can be useful for certain setups. ---- ----Defaults to false. ----@type boolean config.borderless = false - ----Shows/hides the close buttons on tabs. ----When hidden, users can close tabs via keyboard shortcuts or commands. ---- ----Defaults to true. ----@type boolean config.tab_close_button = true - ----Maximum number of clicks recognized by Lite XL. ---- ----Defaults to 3. ----@type number config.max_clicks = 3 ----Disables plugin version checking. ----Do not change this unless you know what you are doing. ---- ----Defaults to false. ----@type boolean +-- set as true to be able to test non supported plugins config.skip_plugins_version = false -- holds the plugins real config table diff --git a/data/core/doc/highlighter.lua b/data/core/doc/highlighter.lua index 14868674..b1367049 100644 --- a/data/core/doc/highlighter.lua +++ b/data/core/doc/highlighter.lua @@ -48,7 +48,7 @@ function Highlighter:start() self:update_notify(retokenized_from, max - retokenized_from) end core.redraw = true - coroutine.yield(0) + coroutine.yield() end self.max_wanted_line = 0 self.running = false diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index e44610e5..c3eeba87 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -1,6 +1,5 @@ local Object = require "core.object" local Highlighter = require "core.doc.highlighter" -local translate = require "core.doc.translate" local core = require "core" local syntax = require "core.syntax" local config = require "core.config" @@ -28,11 +27,9 @@ function Doc:new(filename, abs_filename, new_file) self:load(filename) end end - if new_file then - self.crlf = config.line_endings == "crlf" - end end + function Doc:reset() self.lines = { "\n" } self.selections = { 1, 1, 1, 1 } @@ -41,10 +38,10 @@ function Doc:reset() self.redo_stack = { idx = 1 } self.clean_change_id = 1 self.highlighter = Highlighter(self) - self.overwrite = false self:reset_syntax() end + function Doc:reset_syntax() local header = self:get_text(1, 1, self:position_offset(1, 1, 128)) local path = self.abs_filename @@ -59,14 +56,16 @@ function Doc:reset_syntax() end end + function Doc:set_filename(filename, abs_filename) self.filename = filename self.abs_filename = abs_filename self:reset_syntax() end + function Doc:load(filename) - local fp = assert(io.open(filename, "rb")) + local fp = assert( io.open(filename, "rb") ) self:reset() self.lines = {} local i = 1 @@ -86,6 +85,7 @@ function Doc:load(filename) self:reset_syntax() end + function Doc:reload() if self.filename then local sel = { self:get_selection() } @@ -95,6 +95,7 @@ function Doc:reload() end end + function Doc:save(filename, abs_filename) if not filename then assert(self.filename, "no filename set to default to") @@ -103,7 +104,7 @@ function Doc:save(filename, abs_filename) else assert(self.filename or abs_filename, "calling save on unnamed doc without absolute path") end - local fp = assert(io.open(filename, "wb")) + local fp = assert( io.open(filename, "wb") ) for _, line in ipairs(self.lines) do if self.crlf then line = line:gsub("\n", "\r\n") end fp:write(line) @@ -114,10 +115,12 @@ function Doc:save(filename, abs_filename) self:clean() end + function Doc:get_name() return self.filename or "unsaved" end + function Doc:is_dirty() if self.new_file then if self.filename then return true end @@ -127,17 +130,20 @@ function Doc:is_dirty() end end + function Doc:clean() self.clean_change_id = self:get_change_id() end + function Doc:get_indent_info() if not self.indent_info then return config.tab_type, config.indent_size, false end return self.indent_info.type or config.tab_type, - self.indent_info.size or config.indent_size, - self.indent_info.confirmed + self.indent_info.size or config.indent_size, + self.indent_info.confirmed end + function Doc:get_change_id() return self.undo_stack.idx end @@ -161,14 +167,13 @@ function Doc:get_selection(sort) return line1, col1, line2, col2, swap end + ---Get the selection specified by `idx` ---@param idx integer @the index of the selection to retrieve ---@param sort? boolean @whether to sort the selection returned ---@return integer,integer,integer,integer,boolean? @line1, col1, line2, col2, was the selection sorted function Doc:get_selection_idx(idx, sort) - local line1, col1, line2, col2 = self.selections[idx * 4 - 3], self.selections[idx * 4 - 2], - self.selections[idx * 4 - 1], - self.selections[idx * 4] + local line1, col1, line2, col2 = self.selections[idx*4-3], self.selections[idx*4-2], self.selections[idx*4-1], self.selections[idx*4] if line1 and sort then return sort_positions(line1, col1, line2, col2) else @@ -212,7 +217,7 @@ function Doc:set_selections(idx, line1, col1, line2, col2, swap, rm) if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end line1, col1 = self:sanitize_position(line1, col1) line2, col2 = self:sanitize_position(line2 or line1, col2 or col1) - common.splice(self.selections, (idx - 1) * 4 + 1, rm == nil and 4 or rm, { line1, col1, line2, col2 }) + common.splice(self.selections, (idx - 1)*4 + 1, rm == nil and 4 or rm, { line1, col1, line2, col2 }) end function Doc:add_selection(line1, col1, line2, col2, swap) @@ -228,6 +233,7 @@ function Doc:add_selection(line1, col1, line2, col2, swap) self.last_selection = target end + function Doc:remove_selection(idx) if self.last_selection >= idx then self.last_selection = self.last_selection - 1 @@ -235,6 +241,7 @@ function Doc:remove_selection(idx) common.splice(self.selections, (idx - 1) * 4 + 1, 4) end + function Doc:set_selection(line1, col1, line2, col2, swap) self.selections = {} self:set_selections(1, line1, col1, line2, col2, swap) @@ -245,24 +252,24 @@ function Doc:merge_cursors(idx) for i = (idx or (#self.selections - 3)), (idx or 5), -4 do for j = 1, i - 4, 4 do if self.selections[i] == self.selections[j] and - self.selections[i + 1] == self.selections[j + 1] then - common.splice(self.selections, i, 4) - if self.last_selection >= (i + 3) / 4 then - self.last_selection = self.last_selection - 1 - end - break + self.selections[i+1] == self.selections[j+1] then + common.splice(self.selections, i, 4) + if self.last_selection >= (i+3)/4 then + self.last_selection = self.last_selection - 1 + end + break end end end end local function selection_iterator(invariant, idx) - local target = invariant[3] and (idx * 4 - 7) or (idx * 4 + 1) + local target = invariant[3] and (idx*4 - 7) or (idx*4 + 1) if target > #invariant[1] or target <= 0 or (type(invariant[3]) == "number" and invariant[3] ~= idx - 1) then return end if invariant[2] then - return idx + (invariant[3] and -1 or 1), sort_positions(table.unpack(invariant[1], target, target + 4)) + return idx+(invariant[3] and -1 or 1), sort_positions(table.unpack(invariant[1], target, target+4)) else - return idx + (invariant[3] and -1 or 1), table.unpack(invariant[1], target, target + 4) + return idx+(invariant[3] and -1 or 1), table.unpack(invariant[1], target, target+4) end end @@ -270,9 +277,8 @@ end -- If a number, runs for exactly that iteration. function Doc:get_selections(sort_intra, idx_reverse) return selection_iterator, { self.selections, sort_intra, idx_reverse }, - idx_reverse == true and ((#self.selections / 4) + 1) or ((idx_reverse or -1) + 1) + idx_reverse == true and ((#self.selections / 4) + 1) or ((idx_reverse or -1)+1) end - -- End of cursor seciton. function Doc:sanitize_position(line, col) @@ -285,6 +291,7 @@ function Doc:sanitize_position(line, col) return line, common.clamp(col, 1, #self.lines[line]) end + local function position_offset_func(self, line, col, fn, ...) line, col = self:sanitize_position(line, col) return fn(self, line, col, ...) @@ -323,6 +330,7 @@ function Doc:position_offset(line, col, ...) end end + function Doc:get_text(line1, col1, line2, col2) line1, col1 = self:sanitize_position(line1, col1) line2, col2 = self:sanitize_position(line2, col2) @@ -338,11 +346,13 @@ function Doc:get_text(line1, col1, line2, col2) return table.concat(lines) end + function Doc:get_char(line, col) line, col = self:sanitize_position(line, col) return self.lines[line]:sub(col, col) end + local function push_undo(undo_stack, time, type, ...) undo_stack[undo_stack.idx] = { type = type, time = time, ... } undo_stack[undo_stack.idx - config.max_undos] = nil @@ -403,8 +413,7 @@ function Doc:raw_insert(line, col, text, undo_stack, time) if cline1 < line then break end local line_addition = (line < cline1 or col < ccol1) and #lines - 1 or 0 local column_addition = line == cline1 and ccol1 > col and len or 0 - self:set_selections(idx, cline1 + line_addition, ccol1 + column_addition, cline2 + line_addition, - ccol2 + column_addition) + self:set_selections(idx, cline1 + line_addition, ccol1 + column_addition, cline2 + line_addition, ccol2 + column_addition) end -- push undo @@ -417,6 +426,7 @@ function Doc:raw_insert(line, col, text, undo_stack, time) self:sanitize_selection() end + function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) -- push undo local text = self:get_text(line1, col1, line2, col2) @@ -475,6 +485,7 @@ function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) self:sanitize_selection() end + function Doc:insert(line, col, text) self.redo_stack = { idx = 1 } -- Reset the clean id when we're pushing something new before it @@ -486,6 +497,7 @@ function Doc:insert(line, col, text) self:on_text_change("insert") end + function Doc:remove(line1, col1, line2, col2) self.redo_stack = { idx = 1 } line1, col1 = self:sanitize_position(line1, col1) @@ -495,34 +507,28 @@ function Doc:remove(line1, col1, line2, col2) self:on_text_change("remove") end + function Doc:undo() pop_undo(self, self.undo_stack, self.redo_stack, false) end + function Doc:redo() pop_undo(self, self.redo_stack, self.undo_stack, false) end + function Doc:text_input(text, idx) for sidx, line1, col1, line2, col2 in self:get_selections(true, idx or true) do - local had_selection = false if line1 ~= line2 or col1 ~= col2 then self:delete_to_cursor(sidx) - had_selection = true end - - if self.overwrite - and not had_selection - and col1 < #self.lines[line1] - and text:ulen() == 1 then - self:remove(line1, col1, translate.next_char(self, line1, col1)) - end - self:insert(line1, col1, text) self:move_to_cursor(sidx, #text) end end + function Doc:ime_text_editing(text, start, length, idx) for sidx, line1, col1, line2, col2 in self:get_selections(true, idx or true) do if line1 ~= line2 or col1 ~= col2 then @@ -533,6 +539,7 @@ function Doc:ime_text_editing(text, start, length, idx) end end + function Doc:replace_cursor(idx, line1, col1, line2, col2, fn) local old_text = self:get_text(line1, col1, line2, col2) local new_text, res = fn(old_text) @@ -548,7 +555,7 @@ function Doc:replace_cursor(idx, line1, col1, line2, col2, fn) end function Doc:replace(fn) - local has_selection, results = false, {} + local has_selection, results = false, { } for idx, line1, col1, line2, col2 in self:get_selections(true) do if line1 ~= line2 or col1 ~= col2 then results[idx] = self:replace_cursor(idx, line1, col1, line2, col2, fn) @@ -562,6 +569,7 @@ function Doc:replace(fn) return results end + function Doc:delete_to_cursor(idx, ...) for sidx, line1, col1, line2, col2 in self:get_selections(true, idx) do if line1 ~= line2 or col1 ~= col2 then @@ -575,7 +583,6 @@ function Doc:delete_to_cursor(idx, ...) end self:merge_cursors(idx) end - function Doc:delete_to(...) return self:delete_to_cursor(nil, ...) end function Doc:move_to_cursor(idx, ...) @@ -584,9 +591,9 @@ function Doc:move_to_cursor(idx, ...) end self:merge_cursors(idx) end - function Doc:move_to(...) return self:move_to_cursor(nil, ...) end + function Doc:select_to_cursor(idx, ...) for sidx, line, col, line2, col2 in self:get_selections(false, idx) do line, col = self:position_offset(line, col, ...) @@ -594,9 +601,9 @@ function Doc:select_to_cursor(idx, ...) end self:merge_cursors(idx) end - function Doc:select_to(...) return self:select_to_cursor(nil, ...) end + function Doc:get_indent_string() local indent_type, indent_size = self:get_indent_info() if indent_type == "hard" then @@ -618,7 +625,7 @@ function Doc:get_line_indent(line, rnd_up) local indent = e and line:sub(1, e):gsub("\t", soft_tab) or "" local number = #indent / #soft_tab return e, indent:sub(1, - (rnd_up and math.ceil(number) or math.floor(number)) * #soft_tab) + (rnd_up and math.ceil(number) or math.floor(number))*#soft_tab) end end @@ -667,4 +674,5 @@ function Doc:on_close() core.log_quiet("Closed doc \"%s\"", self:get_name()) end + return Doc diff --git a/data/core/docview.lua b/data/core/docview.lua index 698f2169..643af6be 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -254,11 +254,6 @@ function DocView:scroll_to_line(line, ignore_if_visible, instant) end -function DocView:supports_text_input() - return true -end - - function DocView:scroll_to_make_visible(line, col) local _, oy = self:get_content_offset() local _, ly = self:get_line_screen_position(line, col) @@ -322,7 +317,7 @@ function DocView:mouse_selection(doc, snap_type, line1, col1, line2, col2) line1, col1 = translate.start_of_word(doc, line1, col1) line2, col2 = translate.end_of_word(doc, line2, col2) elseif snap_type == "lines" then - col1, col2, line2 = 1, 1, line2 + 1 + col1, col2 = 1, math.huge end if swap then return line2, col2, line1, col1 @@ -460,16 +455,9 @@ function DocView:draw_line_text(line, x, y) return self:get_line_height() end - -function DocView:draw_overwrite_caret(x, y, width) - local lh = self:get_line_height() - renderer.draw_rect(x, y + lh - style.caret_width, width, style.caret_width, style.caret) -end - - function DocView:draw_caret(x, y) - local lh = self:get_line_height() - renderer.draw_rect(x, y, style.caret_width, lh, style.caret) + local lh = self:get_line_height() + renderer.draw_rect(x, y, style.caret_width, lh, style.caret) end function DocView:draw_line_body(line, x, y) @@ -566,12 +554,7 @@ function DocView:draw_overlay() else if config.disable_blink or (core.blink_timer - core.blink_start) % T < T / 2 then - local x, y = self:get_line_screen_position(line1, col1) - if self.doc.overwrite then - self:draw_overwrite_caret(x, y, self:get_font():get_width(self.doc:get_char(line1, col1))) - else - self:draw_caret(x, y) - end + self:draw_caret(self:get_line_screen_position(line1, col1)) end end end diff --git a/data/core/init.lua b/data/core/init.lua index 9bc63838..d298922d 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -668,9 +668,6 @@ end function core.init() - core.log_items = {} - core.log_quiet("Lite XL version %s - mod-version %s", VERSION, MOD_VERSION_STRING) - command = require "core.command" keymap = require "core.keymap" dirwatch = require "core.dirwatch" @@ -724,6 +721,7 @@ function core.init() core.frame_start = 0 core.clip_rect_stack = {{ 0,0,0,0 }} + core.log_items = {} core.docs = {} core.cursor_clipboard = {} core.cursor_clipboard_whole_line = {} @@ -825,19 +823,15 @@ function core.init() local msg = {} for _, entry in pairs(plugins_refuse_list) do if #entry.plugins > 0 then - local msg_list = {} - for _, p in pairs(entry.plugins) do - table.insert(msg_list, string.format("%s[%s]", p.file, p.version_string)) - end - msg[#msg + 1] = string.format("Plugins from directory \"%s\":\n%s", common.home_encode(entry.dir), table.concat(msg_list, "\n")) + msg[#msg + 1] = string.format("Plugins from directory \"%s\":\n%s", common.home_encode(entry.dir), table.concat(entry.plugins, "\n")) end end core.nag_view:show( "Refused Plugins", string.format( - "Some plugins are not loaded due to version mismatch. Expected version %s.\n\n%s.\n\n" .. + "Some plugins are not loaded due to version mismatch.\n\n%s.\n\n" .. "Please download a recent version from https://github.com/lite-xl/lite-xl-plugins.", - MOD_VERSION_STRING, table.concat(msg, ".\n\n")), + table.concat(msg, ".\n\n")), opt, function(item) if item.text == "Exit" then os.exit(1) end end) @@ -926,8 +920,6 @@ function core.restart() end -local mod_version_regex = - regex.compile([[--.*mod-version:(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:$|\s)]]) local function get_plugin_details(filename) local info = system.get_file_info(filename) if info ~= nil and info.type == "dir" then @@ -939,32 +931,17 @@ local function get_plugin_details(filename) if not f then return false end local priority = false local version_match = false - local major, minor, patch - for line in f:lines() do if not version_match then - local _major, _minor, _patch = mod_version_regex:match(line) - if _major then - _major = tonumber(_major) or 0 - _minor = tonumber(_minor) or 0 - _patch = tonumber(_patch) or 0 - major, minor, patch = _major, _minor, _patch - - version_match = major == MOD_VERSION_MAJOR - if version_match then - version_match = minor <= MOD_VERSION_MINOR - end - if version_match then - version_match = patch <= MOD_VERSION_PATCH - end + local mod_version = line:match('%-%-.*%f[%a]mod%-version%s*:%s*(%d+)') + if mod_version then + version_match = (mod_version == MOD_VERSION) end end - if not priority then priority = line:match('%-%-.*%f[%a]priority%s*:%s*(%d+)') if priority then priority = tonumber(priority) end end - if version_match then break end @@ -972,7 +949,6 @@ local function get_plugin_details(filename) f:close() return true, { version_match = version_match, - version = major and {major, minor, patch} or {}, priority = priority or 100 } end @@ -1008,8 +984,6 @@ function core.load_plugins() plugin.dir = dir plugin.priority = details and details.priority or 100 plugin.version_match = details and details.version_match or false - plugin.version = details and details.version or {} - plugin.version_string = #plugin.version > 0 and table.concat(plugin.version, ".") or "unknown" end -- sort by priority or name for plugins that have same priority @@ -1025,35 +999,27 @@ function core.load_plugins() if plugin.valid then if not config.skip_plugins_version and not plugin.version_match then core.log_quiet( - "Version mismatch for plugin %q[%s] from %s", + "Version mismatch for plugin %q from %s", plugin.name, - plugin.version_string, plugin.dir ) local rlist = plugin.dir:find(USERDIR, 1, true) == 1 and 'userdir' or 'datadir' local list = refused_list[rlist].plugins - table.insert(list, plugin) + table.insert(list, plugin.file) elseif config.plugins[plugin.name] ~= false then local start = system.get_time() - local ok, loaded_plugin = core.try(require, "plugins." .. plugin.name) + local ok = core.try(require, "plugins." .. plugin.name) if ok then - local plugin_version = "" - if plugin.version_string ~= MOD_VERSION_STRING then - plugin_version = "["..plugin.version_string.."]" - end core.log_quiet( - "Loaded plugin %q%s from %s in %.1fms", + "Loaded plugin %q from %s in %.1fms", plugin.name, - plugin_version, plugin.dir, (system.get_time() - start) * 1000 ) end if not ok then no_errors = false - elseif config.plugins[plugin.name].onload then - core.try(config.plugins[plugin.name].onload, loaded_plugin) end end end @@ -1107,7 +1073,6 @@ function core.set_active_view(view) -- Reset the IME even if the focus didn't change ime.stop() if view ~= core.active_view then - system.text_input(view:supports_text_input()) if core.active_view and core.active_view.force_focus then core.next_active_view = view return @@ -1296,12 +1261,6 @@ function core.on_event(type, ...) if not core.root_view:on_mouse_wheel(...) then did_keymap = keymap.on_mouse_wheel(...) end - elseif type == "touchpressed" then - core.root_view:on_touch_pressed(...) - elseif type == "touchreleased" then - core.root_view:on_touch_released(...) - elseif type == "touchmoved" then - core.root_view:on_touch_moved(...) elseif type == "resized" then core.window_mode = system.get_window_mode() elseif type == "minimized" or type == "maximized" or type == "restored" then @@ -1351,11 +1310,6 @@ function core.step() did_keymap = false elseif type == "mousemoved" then core.try(core.on_event, type, a, b, c, d) - elseif type == "enteringforeground" then - -- to break our frame refresh in two if we get entering/entered at the same time. - -- required to avoid flashing and refresh issues on mobile - core.redraw = true - break else local _, res = core.try(core.on_event, type, a, b, c, d) did_keymap = res or did_keymap @@ -1510,16 +1464,4 @@ function core.on_error(err) end -local alerted_deprecations = {} ----Show deprecation notice once per `kind`. ---- ----@param kind string -function core.deprecation_log(kind) - if alerted_deprecations[kind] then return end - alerted_deprecations[kind] = true - core.warn("Used deprecated functionality [%s]. Check if your plugins are up to date.", kind) -end - - return core - diff --git a/data/core/keymap-macos.lua b/data/core/keymap-macos.lua index 965191ef..8fe04b39 100644 --- a/data/core/keymap-macos.lua +++ b/data/core/keymap-macos.lua @@ -36,8 +36,6 @@ local function keymap_macos(keymap) ["wheel"] = "root:scroll", ["hwheel"] = "root:horizontal-scroll", ["shift+hwheel"] = "root:horizontal-scroll", - ["wheelup"] = "root:scroll-hovered-tabs-backward", - ["wheeldown"] = "root:scroll-hovered-tabs-forward", ["cmd+f"] = "find-replace:find", ["cmd+r"] = "find-replace:replace", diff --git a/data/core/keymap.lua b/data/core/keymap.lua index 02636bd3..0ce2fc09 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -71,6 +71,7 @@ local function key_to_stroke(key) return normalize_stroke(table.concat(keys, "+")) end + ---Remove the given value from an array associated to a key in a table. ---@param tbl table The table containing the key ---@param k string The key containing the array @@ -124,6 +125,7 @@ end function keymap.add_direct(map) for stroke, commands in pairs(map) do stroke = normalize_stroke(stroke) + if type(commands) == "string" or type(commands) == "function" then commands = { commands } end @@ -323,8 +325,6 @@ keymap.add_direct { ["wheel"] = "root:scroll", ["hwheel"] = "root:horizontal-scroll", ["shift+wheel"] = "root:horizontal-scroll", - ["wheelup"] = "root:scroll-hovered-tabs-backward", - ["wheeldown"] = "root:scroll-hovered-tabs-forward", ["ctrl+f"] = "find-replace:find", ["ctrl+r"] = "find-replace:replace", @@ -341,7 +341,6 @@ keymap.add_direct { ["ctrl+x"] = "doc:cut", ["ctrl+c"] = "doc:copy", ["ctrl+v"] = "doc:paste", - ["insert"] = "doc:toggle-overwrite", ["ctrl+insert"] = "doc:copy", ["shift+insert"] = "doc:paste", ["escape"] = { "command:escape", "doc:select-none", "dialog:select-no" }, @@ -391,7 +390,7 @@ keymap.add_direct { ["shift+1lclick"] = "doc:select-to-cursor", ["ctrl+1lclick"] = "doc:split-cursor", ["1lclick"] = "doc:set-cursor", - ["2lclick"] = { "doc:set-cursor-word", "emptyview:new-doc", "tabbar:new-doc" }, + ["2lclick"] = "doc:set-cursor-word", ["3lclick"] = "doc:set-cursor-line", ["shift+left"] = "doc:select-to-previous-char", ["shift+right"] = "doc:select-to-next-char", @@ -412,4 +411,3 @@ keymap.add_direct { } return keymap - diff --git a/data/core/modkeys-generic.lua b/data/core/modkeys-generic.lua index c1642966..e239d8a9 100644 --- a/data/core/modkeys-generic.lua +++ b/data/core/modkeys-generic.lua @@ -7,10 +7,6 @@ modkeys.map = { ["right shift"] = "shift", ["left alt"] = "alt", ["right alt"] = "altgr", - ["left gui"] = "super", - ["left windows"] = "super", - ["right gui"] = "super", - ["right windows"] = "super" } modkeys.keys = { "ctrl", "shift", "alt", "altgr" } diff --git a/data/core/nagview.lua b/data/core/nagview.lua index 1a7fa193..b66da75c 100644 --- a/data/core/nagview.lua +++ b/data/core/nagview.lua @@ -24,7 +24,6 @@ function NagView:new() self.scrollable = true self.target_height = 0 self.on_mouse_pressed_root = nil - self.dim_alpha = 0 end function NagView:get_title() @@ -69,9 +68,7 @@ function NagView:dim_window_content() oy = oy + self.show_height local w, h = core.root_view.size.x, core.root_view.size.y - oy core.root_view:defer_draw(function() - local dim_color = { table.unpack(style.nagbar_dim) } - dim_color[4] = style.nagbar_dim[4] * self.dim_alpha - renderer.draw_rect(ox, oy, w, h, dim_color) + renderer.draw_rect(ox, oy, w, h, style.nagbar_dim) end) end @@ -175,13 +172,10 @@ function NagView:update() NagView.super.update(self) if self.visible and core.active_view == self and self.title then - local target_height = self:get_target_height() - self:move_towards(self, "show_height", target_height, nil, "nagbar") + self:move_towards(self, "show_height", self:get_target_height(), nil, "nagbar") self:move_towards(self, "underline_progress", 1, nil, "nagbar") - self:move_towards(self, "dim_alpha", self.show_height / target_height, nil, "nagbar") else self:move_towards(self, "show_height", 0, nil, "nagbar") - self:move_towards(self, "dim_alpha", 0, nil, "nagbar") if self.show_height <= 0 then self.title = nil self.message = nil diff --git a/data/core/node.lua b/data/core/node.lua index 86d4e4e0..2ce52cc2 100644 --- a/data/core/node.lua +++ b/data/core/node.lua @@ -18,6 +18,7 @@ function Node:new(type) if self.type == "leaf" then self:add_view(EmptyView()) end + self.hovered = {x = -1, y = -1 } self.hovered_close = 0 self.tab_shift = 0 self.tab_offset = 1 @@ -32,10 +33,9 @@ function Node:propagate(fn, ...) end ----@deprecated function Node:on_mouse_moved(x, y, ...) - core.deprecation_log("Node:on_mouse_moved") if self.type == "leaf" then + self.hovered.x, self.hovered.y = x, y self.active_view:on_mouse_moved(x, y, ...) else self:propagate("on_mouse_moved", x, y, ...) @@ -43,9 +43,7 @@ function Node:on_mouse_moved(x, y, ...) end ----@deprecated function Node:on_mouse_released(...) - core.deprecation_log("Node:on_mouse_released") if self.type == "leaf" then self.active_view:on_mouse_released(...) else @@ -54,9 +52,7 @@ function Node:on_mouse_released(...) end ----@deprecated function Node:on_mouse_left() - core.deprecation_log("Node:on_mouse_left") if self.type == "leaf" then self.active_view:on_mouse_left() else @@ -65,17 +61,6 @@ function Node:on_mouse_left() end ----@deprecated -function Node:on_touch_moved(...) - core.deprecation_log("Node:on_touch_moved") - if self.type == "leaf" then - self.active_view:on_touch_moved(...) - else - self:propagate("on_touch_moved", ...) - end -end - - function Node:consume(node) for k, _ in pairs(self) do self[k] = nil end for k, v in pairs(node) do self[k] = v end @@ -177,12 +162,8 @@ function Node:add_view(view, idx) assert(not self.locked, "Tried to add view to locked node") if self.views[1] and self.views[1]:is(EmptyView) then table.remove(self.views) - if idx and idx > 1 then - idx = idx - 1 - end end - idx = common.clamp(idx or (#self.views + 1), 1, (#self.views + 1)) - table.insert(self.views, idx, view) + table.insert(self.views, idx or (#self.views + 1), view) self:set_active_view(view) end @@ -320,7 +301,7 @@ function Node:tab_hovered_update(px, py) if px >= cx and px < cx + cw and py >= y and py < y + h and config.tab_close_button then self.hovered_close = tab_index end - elseif #self.views > self:get_visible_tabs_number() then + else self.hovered_scroll_button = self:get_scroll_button_index(px, py) or 0 end end @@ -338,17 +319,10 @@ function Node:get_child_overlapping_point(x, y) return child:get_child_overlapping_point(x, y) end --- returns: total height, text padding, top margin -local function get_tab_y_sizes() - local height = style.font:get_height() - local padding = style.padding.y - local margin = style.margin.tab.top - return height + (padding * 2) + margin, padding, margin -end function Node:get_scroll_button_rect(index) local w, pad = get_scroll_button_width() - local h = get_tab_y_sizes() + local h = style.font:get_height() + style.padding.y * 2 local x = self.position.x + (index == 1 and self.size.x - w * 2 or self.size.x - w) return x, self.position.y, w, h, pad end @@ -359,8 +333,8 @@ function Node:get_tab_rect(idx) local x0 = self.position.x local x1 = x0 + common.clamp(self.tab_width * (idx - 1) - self.tab_shift, 0, maxw) local x2 = x0 + common.clamp(self.tab_width * idx - self.tab_shift, 0, maxw) - local h, pad_y, margin_y = get_tab_y_sizes() - return x1, self.position.y, x2 - x1, h, margin_y + local h = style.font:get_height() + style.padding.y * 2 + return x1, self.position.y, x2 - x1, h end @@ -508,7 +482,7 @@ function Node:update() for _, view in ipairs(self.views) do view:update() end - self:tab_hovered_update(core.root_view.mouse.x, core.root_view.mouse.y) + self:tab_hovered_update(self.hovered.x, self.hovered.y) local tab_width = self:target_tab_width() self:move_towards("tab_shift", tab_width * (self.tab_offset - 1), nil, "tabs") self:move_towards("tab_width", tab_width, nil, "tabs") @@ -551,7 +525,6 @@ function Node:draw_tab_borders(view, is_active, is_hovered, x, y, w, h, standalo if is_active then color = style.text renderer.draw_rect(x, y, w, h, style.background) - renderer.draw_rect(x, y, w, ds, style.divider) renderer.draw_rect(x + w, y, ds, h, style.divider) renderer.draw_rect(x - ds, y, ds, h, style.divider) end @@ -559,8 +532,7 @@ function Node:draw_tab_borders(view, is_active, is_hovered, x, y, w, h, standalo end function Node:draw_tab(view, is_active, is_hovered, is_close_hovered, x, y, w, h, standalone) - local _, padding_y, margin_y = get_tab_y_sizes() - x, y, w, h = self:draw_tab_borders(view, is_active, is_hovered, x, y + margin_y, w, h - margin_y, standalone) + x, y, w, h = self:draw_tab_borders(view, is_active, is_hovered, x, y, w, h, standalone) -- Close button local cx, cw, cpad = close_button_location(x, w) local show_close_button = ((is_active or is_hovered) and not standalone and config.tab_close_button) @@ -636,13 +608,6 @@ function Node:is_empty() end -function Node:is_in_tab_area(x, y) - if not self:should_show_tabs() then return false end - local _, ty, _, th = self:get_scroll_button_rect(1) - return y >= ty and y < ty + th -end - - function Node:close_all_docviews(keep_active) local node_active_view = self.active_view local lost_active_view = false @@ -781,7 +746,7 @@ function Node:get_drag_overlay_tab_position(x, y, dragged_node, dragged_index) tab_index = self:get_visible_tabs_number() + (self.tab_offset - 1 or 0) end end - local tab_x, tab_y, tab_w, tab_h, margin_y = self:get_tab_rect(tab_index) + local tab_x, tab_y, tab_w, tab_h = self:get_tab_rect(tab_index) if x > tab_x + tab_w / 2 and tab_index <= #self.views then -- use next tab tab_x = tab_x + tab_w @@ -792,7 +757,7 @@ function Node:get_drag_overlay_tab_position(x, y, dragged_node, dragged_index) tab_index = tab_index - 1 tab_x = tab_x - tab_w end - return tab_index, tab_x, tab_y + margin_y, tab_w, tab_h - margin_y + return tab_index, tab_x, tab_y, tab_w, tab_h end return Node diff --git a/data/core/object.lua b/data/core/object.lua index 5466cb01..d42f9dbc 100644 --- a/data/core/object.lua +++ b/data/core/object.lua @@ -27,13 +27,6 @@ function Object:is(T) return getmetatable(self) == T end ----Check if the parameter is strictly of the object type. ----@param T any ----@return boolean -function Object:is_class_of(T) - return getmetatable(T) == self -end - ---Check if the object inherits from the given type. ---@param T any ---@return boolean @@ -48,22 +41,6 @@ function Object:extends(T) return false end ----Check if the parameter inherits from the object. ----@param T any ----@return boolean -function Object:is_extended_by(T) - local mt = getmetatable(T) - while mt do - if mt == self then - return true - end - local _mt = getmetatable(T) - if mt == _mt then break end - mt = _mt - end - return false -end - ---Metamethod to get a string representation of an object. ---@return string function Object:__tostring() diff --git a/data/core/rootview.lua b/data/core/rootview.lua index ec9d5e0e..047768cc 100644 --- a/data/core/rootview.lua +++ b/data/core/rootview.lua @@ -24,9 +24,6 @@ function RootView:new() base_color = style.drag_overlay_tab, color = { table.unpack(style.drag_overlay_tab) } } self.drag_overlay_tab.to = { x = 0, y = 0, w = 0, h = 0 } - self.grab = nil -- = {view = nil, button = nil} - self.overlapping_view = nil - self.touched_view = nil end @@ -119,31 +116,6 @@ function RootView:close_all_docviews(keep_active) end ----Obtain mouse grab. ---- ----This means that mouse movements will be sent to the specified view, even when ----those occur outside of it. ----There can't be multiple mouse grabs, even for different buttons. ----@see RootView:ungrab_mouse ----@param button core.view.mousebutton ----@param view core.view -function RootView:grab_mouse(button, view) - assert(self.grab == nil) - self.grab = {view = view, button = button} -end - - ----Release mouse grab. ---- ----The specified button *must* be the last button that grabbed the mouse. ----@see RootView:grab_mouse ----@param button core.view.mousebutton -function RootView:ungrab_mouse(button) - assert(self.grab and self.grab.button == button) - self.grab = nil -end - - ---Function to intercept mouse pressed events on the active view. ---Do nothing by default. ---@param button core.view.mousebutton @@ -160,10 +132,6 @@ end ---@param clicks integer ---@return boolean function RootView:on_mouse_pressed(button, x, y, clicks) - -- If there is a grab, release it first - if self.grab then - self:on_mouse_released(self.grab.button, x, y) - end local div = self.root_node:get_divider_overlapping_point(x, y) local node = self.root_node:get_child_overlapping_point(x, y) if div and (node and not node.active_view:scrollbar_overlaps_point(x, y)) then @@ -188,7 +156,6 @@ function RootView:on_mouse_pressed(button, x, y, clicks) end elseif not self.dragged_node then -- avoid sending on_mouse_pressed events when dragging tabs core.set_active_view(node.active_view) - self:grab_mouse(button, node.active_view) return self.on_view_mouse_pressed(button, x, y, clicks) or node.active_view:on_mouse_pressed(button, x, y, clicks) end end @@ -221,21 +188,6 @@ end ---@param x number ---@param y number function RootView:on_mouse_released(button, x, y, ...) - if self.grab then - if self.grab.button == button then - local grabbed_view = self.grab.view - grabbed_view:on_mouse_released(button, x, y, ...) - self:ungrab_mouse(button) - - -- If the mouse was released over a different view, send it the mouse position - local hovered_view = self.root_node:get_child_overlapping_point(x, y) - if grabbed_view ~= hovered_view then - self:on_mouse_moved(x, y, 0, 0) - end - end - return - end - if self.dragged_divider then self.dragged_divider = nil end @@ -276,6 +228,8 @@ function RootView:on_mouse_released(button, x, y, ...) end self.dragged_node = nil end + else -- avoid sending on_mouse_released events when dragging tabs + self.root_node:on_mouse_released(button, x, y, ...) end end @@ -296,14 +250,6 @@ end ---@param dx number ---@param dy number function RootView:on_mouse_moved(x, y, dx, dy) - self.mouse.x, self.mouse.y = x, y - - if self.grab then - self.grab.view:on_mouse_moved(x, y, dx, dy) - core.request_cursor(self.grab.view.cursor) - return - end - if core.active_view == core.nag_view then core.request_cursor("arrow") core.active_view:on_mouse_moved(x, y, dx, dy) @@ -323,6 +269,8 @@ function RootView:on_mouse_moved(x, y, dx, dy) return end + self.mouse.x, self.mouse.y = x, y + local dn = self.dragged_node if dn and not dn.dragging then -- start dragging only after enough movement @@ -335,33 +283,32 @@ function RootView:on_mouse_moved(x, y, dx, dy) -- avoid sending on_mouse_moved events when dragging tabs if dn then return end - local last_overlapping_view = self.overlapping_view - local overlapping_node = self.root_node:get_child_overlapping_point(x, y) - self.overlapping_view = overlapping_node and overlapping_node.active_view + self.root_node:on_mouse_moved(x, y, dx, dy) - if last_overlapping_view and last_overlapping_view ~= self.overlapping_view then - last_overlapping_view:on_mouse_left() + local last_overlapping_node = self.overlapping_node + self.overlapping_node = self.root_node:get_child_overlapping_point(x, y) + + if last_overlapping_node and last_overlapping_node ~= self.overlapping_node then + last_overlapping_node:on_mouse_left() end - if not self.overlapping_view then return end - - self.overlapping_view:on_mouse_moved(x, y, dx, dy) - core.request_cursor(self.overlapping_view.cursor) - - if not overlapping_node then return end - local div = self.root_node:get_divider_overlapping_point(x, y) - if overlapping_node:get_scroll_button_index(x, y) or overlapping_node:is_in_tab_area(x, y) then + local tab_index = self.overlapping_node and self.overlapping_node:get_tab_overlapping_point(x, y) + if self.overlapping_node and self.overlapping_node:get_scroll_button_index(x, y) then core.request_cursor("arrow") - elseif div and not self.overlapping_view:scrollbar_overlaps_point(x, y) then + elseif div and (self.overlapping_node and not self.overlapping_node.active_view:scrollbar_overlaps_point(x, y)) then core.request_cursor(div.type == "hsplit" and "sizeh" or "sizev") + elseif tab_index then + core.request_cursor("arrow") + elseif self.overlapping_node then + core.request_cursor(self.overlapping_node.active_view.cursor) end end function RootView:on_mouse_left() - if self.overlapping_view then - self.overlapping_view:on_mouse_left() + if self.overlapping_node then + self.overlapping_node:on_mouse_left() end end @@ -387,50 +334,6 @@ function RootView:on_text_input(...) core.active_view:on_text_input(...) end -function RootView:on_touch_pressed(x, y, ...) - local touched_node = self.root_node:get_child_overlapping_point(x, y) - self.touched_view = touched_node and touched_node.active_view -end - -function RootView:on_touch_released(x, y, ...) - self.touched_view = nil -end - -function RootView:on_touch_moved(x, y, dx, dy, ...) - if not self.touched_view then return end - if core.active_view == core.nag_view then - core.active_view:on_touch_moved(x, y, dx, dy, ...) - return - end - - if self.dragged_divider then - local node = self.dragged_divider - if node.type == "hsplit" then - x = common.clamp(x - node.position.x, 0, self.root_node.size.x * 0.95) - resize_child_node(node, "x", x, dx) - elseif node.type == "vsplit" then - y = common.clamp(y - node.position.y, 0, self.root_node.size.y * 0.95) - resize_child_node(node, "y", y, dy) - end - node.divider = common.clamp(node.divider, 0.01, 0.99) - return - end - - local dn = self.dragged_node - if dn and not dn.dragging then - -- start dragging only after enough movement - dn.dragging = common.distance(x, y, dn.drag_start_x, dn.drag_start_y) > style.tab_width * .05 - if dn.dragging then - core.request_cursor("hand") - end - end - - -- avoid sending on_touch_moved events when dragging tabs - if dn then return end - - self.touched_view:on_touch_moved(x, y, dx, dy, ...) -end - function RootView:on_ime_text_editing(...) core.active_view:on_ime_text_editing(...) end diff --git a/data/core/scrollbar.lua b/data/core/scrollbar.lua index 29352dd4..5e64b19f 100644 --- a/data/core/scrollbar.lua +++ b/data/core/scrollbar.lua @@ -58,9 +58,9 @@ function Scrollbar:new(options) ---@type "expanded" | "contracted" | false @Force the scrollbar status self.force_status = options.force_status self:set_forced_status(options.force_status) - ---@type number? @Override the default value specified by `style.scrollbar_size` - self.contracted_size = options.contracted_size ---@type number? @Override the default value specified by `style.expanded_scrollbar_size` + self.contracted_size = options.contracted_size + ---@type number? @Override the default value specified by `style.scrollbar_size` self.expanded_size = options.expanded_size end @@ -121,7 +121,7 @@ function Scrollbar:_get_thumb_rect_normal() across_size = across_size + (expanded_scrollbar_size - scrollbar_size) * self.expand_percent return nr.across + nr.across_size - across_size, - nr.along + self.percent * (nr.along_size - along_size), + nr.along + self.percent * nr.scrollable * (nr.along_size - along_size) / (sz - nr.along_size), across_size, along_size end @@ -238,8 +238,7 @@ end function Scrollbar:_on_mouse_moved_normal(x, y, dx, dy) if self.dragging then local nr = self.normal_rect - local _, _, _, along_size = self:_get_thumb_rect_normal() - return common.clamp((y - nr.along + self.drag_start_offset) / (nr.along_size - along_size), 0, 1) + return common.clamp((y - nr.along + self.drag_start_offset) / nr.along_size, 0, 1) end return self:_update_hover_status_normal(x, y) end @@ -282,7 +281,7 @@ function Scrollbar:set_size(x, y, w, h, scrollable) end ---Updates the scrollbar location ----@param percent number @number between 0 and 1 where 0 means thumb at the top and 1 at the bottom +---@param percent number @number between 0 and 1 representing the position of the middle part of the thumb function Scrollbar:set_percent(percent) self.percent = percent end diff --git a/data/core/start.lua b/data/core/start.lua index 746ae00c..7858770a 100644 --- a/data/core/start.lua +++ b/data/core/start.lua @@ -1,9 +1,6 @@ -- this file is used by lite-xl to setup the Lua environment when starting -VERSION = "2.1.2r1" -MOD_VERSION_MAJOR = 3 -MOD_VERSION_MINOR = 0 -MOD_VERSION_PATCH = 0 -MOD_VERSION_STRING = string.format("%d.%d.%d", MOD_VERSION_MAJOR, MOD_VERSION_MINOR, MOD_VERSION_PATCH) +VERSION = "2.1.3r1" +MOD_VERSION = "3" SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or 1 PATHSEP = package.config:sub(1, 1) @@ -25,7 +22,7 @@ package.path = DATADIR .. '/?/init.lua;' .. package.path package.path = USERDIR .. '/?.lua;' .. package.path package.path = USERDIR .. '/?/init.lua;' .. package.path -local suffix = PLATFORM == "Windows" and 'dll' or 'so' +local suffix = PLATFORM == "Mac OS X" and 'lib' or (PLATFORM == "Windows" and 'dll' or 'so') package.cpath = USERDIR .. '/?.' .. ARCH .. "." .. suffix .. ";" .. USERDIR .. '/?/init.' .. ARCH .. "." .. suffix .. ";" .. diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 74124768..9c4e33fa 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -232,42 +232,15 @@ function StatusView:register_docview_items() return { style.text, line, ":", col > config.line_limit and style.accent or style.text, col, - style.text + style.text, + self.separator, + string.format("%.f%%", line / #dv.doc.lines * 100) } end, command = "doc:go-to-line", tooltip = "line : column" }) - self:add_item({ - predicate = predicate_docview, - name = "doc:position-percent", - alignment = StatusView.Item.LEFT, - get_item = function() - local dv = core.active_view - local line = dv.doc:get_selection() - return { - string.format("%.f%%", line / #dv.doc.lines * 100) - } - end, - tooltip = "caret position" - }) - - self:add_item({ - predicate = predicate_docview, - name = "doc:selections", - alignment = StatusView.Item.LEFT, - get_item = function() - local dv = core.active_view - local nsel = math.floor(#dv.doc.selections / 4) - if nsel > 1 then - return { style.text, nsel, " selections" } - end - - return {} - end - }) - self:add_item({ predicate = predicate_docview, name = "doc:indentation", @@ -319,19 +292,6 @@ function StatusView:register_docview_items() end, command = "doc:toggle-line-ending" }) - - self:add_item { - predicate = predicate_docview, - name = "doc:overwrite-mode", - alignment = StatusView.Item.RIGHT, - get_item = function() - return { - style.text, core.active_view.doc.overwrite and "OVR" or "INS" - } - end, - command = "doc:toggle-overwrite", - separator = StatusView.separator2 - } end @@ -1014,12 +974,6 @@ function StatusView:on_mouse_pressed(button, x, y, clicks) end -function StatusView:on_mouse_left() - StatusView.super.on_mouse_left(self) - self.hovered_item = {} -end - - function StatusView:on_mouse_moved(x, y, dx, dy) if not self.visible then return end StatusView.super.on_mouse_moved(self, x, y, dx, dy) diff --git a/data/core/style.lua b/data/core/style.lua index 9857ed07..3e340c57 100644 --- a/data/core/style.lua +++ b/data/core/style.lua @@ -1,23 +1,13 @@ local common = require "core.common" local style = {} +style.padding = { x = common.round(14 * SCALE), y = common.round(7 * SCALE) } style.divider_size = common.round(1 * SCALE) style.scrollbar_size = common.round(4 * SCALE) style.expanded_scrollbar_size = common.round(12 * SCALE) style.caret_width = common.round(2 * SCALE) style.tab_width = common.round(170 * SCALE) -style.padding = { - x = common.round(14 * SCALE), - y = common.round(7 * SCALE), -} - -style.margin = { - tab = { - top = common.round(-style.divider_size * SCALE) - } -} - -- The function renderer.font.load can accept an option table as a second optional argument. -- It shoud be like the following: -- @@ -50,4 +40,3 @@ style.syntax_fonts = {} style.log = {} return style - diff --git a/data/core/syntax.lua b/data/core/syntax.lua index 6555a17c..9862fbdf 100644 --- a/data/core/syntax.lua +++ b/data/core/syntax.lua @@ -3,7 +3,7 @@ local common = require "core.common" local syntax = {} syntax.items = {} -syntax.plain_text_syntax = { name = "Plain Text", patterns = {}, symbols = {} } +local plain_text_syntax = { name = "Plain Text", patterns = {}, symbols = {} } function syntax.add(t) @@ -46,7 +46,7 @@ end function syntax.get(filename, header) return (filename and find(filename, "files")) or (header and find(header, "headers")) - or syntax.plain_text_syntax + or plain_text_syntax end diff --git a/data/core/titleview.lua b/data/core/titleview.lua index 482d6c8e..69315be1 100644 --- a/data/core/titleview.lua +++ b/data/core/titleview.lua @@ -112,12 +112,6 @@ function TitleView:on_mouse_pressed(button, x, y, clicks) end -function TitleView:on_mouse_left() - TitleView.super.on_mouse_left(self) - self.hovered_item = nil -end - - function TitleView:on_mouse_moved(px, py, ...) if self.size.y == 0 then return end TitleView.super.on_mouse_moved(self, px, py, ...) diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index 5d00dcf1..8f3e05d0 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -28,8 +28,11 @@ local function push_tokens(t, syn, pattern, full_text, find_results) -- Each position spans characters from i_n to ((i_n+1) - 1), to form -- consecutive spans of text. -- - -- Insert the start index at i_1 to make iterating easier - table.insert(find_results, 3, find_results[1]) + -- If i_1 is not equal to start, start is automatically inserted at + -- that index. + if find_results[3] ~= find_results[1] then + table.insert(find_results, 3, find_results[1]) + end -- Copy the ending index to the end of the table, so that an ending index -- always follows a starting index after position 3 in the table. table.insert(find_results, find_results[2] + 1) @@ -39,10 +42,8 @@ local function push_tokens(t, syn, pattern, full_text, find_results) local fin = find_results[i + 1] - 1 local type = pattern.type[i - 2] -- ↑ (i - 2) to convert from [3; n] to [1; n] - if fin >= start then - local text = full_text:usub(start, fin) - push_token(t, syn.symbols[text] or type, text) - end + local text = full_text:usub(start, fin) + push_token(t, syn.symbols[text] or type, text) end else local start, fin = find_results[1], find_results[2] @@ -133,10 +134,8 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) local res local i = 1 - state = state or string.char(0) - if #incoming_syntax.patterns == 0 then - return { "normal", text }, state + return { "normal", text } end state = state or string.char(0) @@ -243,7 +242,6 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) res[1] = char_pos_1 res[2] = char_pos_2 end - if not res[1] then return end if res[1] and target[3] then -- Check to see if the escaped character is there, -- and if it is not itself escaped. @@ -255,12 +253,12 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) if count % 2 == 0 then -- The match is not escaped, so confirm it break - else - -- The match is escaped, so avoid it - res[1] = false + elseif not close then + -- The *open* match is escaped, so avoid it + return end end - until at_start or not close or not target[3] + until not res[1] or not close or not target[3] return table.unpack(res) end @@ -286,9 +284,6 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) if current_pattern_idx > 0 then local p = current_syntax.patterns[current_pattern_idx] local s, e = find_text(text, p, i, false, true) - -- Use the first token type specified in the type table for the "middle" - -- part of the subsyntax. - local token_type = type(p.type) == "table" and p.type[1] or p.type local cont = true -- If we're in subsyntax mode, always check to see if we end our syntax @@ -301,7 +296,7 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) -- treat the bit after as a token to be normally parsed -- (as it's the syntax delimiter). if ss and (s == nil or ss < s) then - push_token(res, token_type, text:usub(i, ss - 1)) + push_token(res, p.type, text:usub(i, ss - 1)) i = ss cont = false end @@ -310,11 +305,11 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) -- continue on as normal. if cont then if s then - push_token(res, token_type, text:usub(i, e)) + push_token(res, p.type, text:usub(i, e)) set_subsyntax_pattern_idx(0) i = e + 1 else - push_token(res, token_type, text:usub(i)) + push_token(res, p.type, text:usub(i)) break end end @@ -323,10 +318,9 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume) -- we're ending early in the middle of a delimiter, or -- just normally, upon finding a token. while subsyntax_info do - local find_results = { find_text(text, subsyntax_info, i, true, true) } - local s, e = find_results[1], find_results[2] + local s, e = find_text(text, subsyntax_info, i, true, true) if s then - push_tokens(res, current_syntax, subsyntax_info, text, find_results) + push_token(res, subsyntax_info.type, text:usub(i, e)) -- On finding unescaped delimiter, pop it. pop_subsyntax() i = e + 1 diff --git a/data/core/view.lua b/data/core/view.lua index bab75b01..77378b90 100644 --- a/data/core/view.lua +++ b/data/core/view.lua @@ -108,10 +108,6 @@ function View:get_h_scrollable_size() end -function View:supports_text_input() - return false -end - ---@param x number ---@param y number ---@return boolean @@ -142,14 +138,14 @@ function View:on_mouse_pressed(button, x, y, clicks) local result = self.v_scrollbar:on_mouse_pressed(button, x, y, clicks) if result then if result ~= true then - self.scroll.to.y = result * (self:get_scrollable_size() - self.size.y) + self.scroll.to.y = result * self:get_scrollable_size() end return true end result = self.h_scrollbar:on_mouse_pressed(button, x, y, clicks) if result then if result ~= true then - self.scroll.to.x = result * (self:get_h_scrollable_size() - self.size.x) + self.scroll.to.x = result * self:get_h_scrollable_size() end return true end @@ -177,7 +173,7 @@ function View:on_mouse_moved(x, y, dx, dy) result = self.v_scrollbar:on_mouse_moved(x, y, dx, dy) if result then if result ~= true then - self.scroll.to.y = result * (self:get_scrollable_size() - self.size.y) + self.scroll.to.y = result * self:get_scrollable_size() if not config.animate_drag_scroll then self:clamp_scroll_position() self.scroll.y = self.scroll.to.y @@ -191,7 +187,7 @@ function View:on_mouse_moved(x, y, dx, dy) result = self.h_scrollbar:on_mouse_moved(x, y, dx, dy) if result then if result ~= true then - self.scroll.to.x = result * (self:get_h_scrollable_size() - self.size.x) + self.scroll.to.x = result * self:get_h_scrollable_size() if not config.animate_drag_scroll then self:clamp_scroll_position() self.scroll.x = self.scroll.to.x @@ -248,23 +244,6 @@ function View:get_content_bounds() return x, y, x + self.size.x, y + self.size.y end ----@param x number ----@param y number ----@param dx number ----@param dy number ----@param i number -function View:on_touch_moved(x, y, dx, dy, i) - if not self.scrollable then return end - if self.dragging_scrollbar then - local delta = self:get_scrollable_size() / self.size.y * dy - self.scroll.to.y = self.scroll.to.y + delta - end - self.hovered_scrollbar = self:scrollbar_overlaps_point(x, y) - - self.scroll.to.y = self.scroll.to.y + -dy - self.scroll.to.x = self.scroll.to.x + -dx -end - ---@return number x ---@return number y @@ -287,16 +266,12 @@ end function View:update_scrollbar() local v_scrollable = self:get_scrollable_size() self.v_scrollbar:set_size(self.position.x, self.position.y, self.size.x, self.size.y, v_scrollable) - local v_percent = self.scroll.y/(v_scrollable - self.size.y) - -- Avoid setting nan percent - self.v_scrollbar:set_percent(v_percent == v_percent and v_percent or 0) + self.v_scrollbar:set_percent(self.scroll.y/v_scrollable) self.v_scrollbar:update() local h_scrollable = self:get_h_scrollable_size() self.h_scrollbar:set_size(self.position.x, self.position.y, self.size.x, self.size.y, h_scrollable) - local h_percent = self.scroll.x/(h_scrollable - self.size.x) - -- Avoid setting nan percent - self.h_scrollbar:set_percent(h_percent == h_percent and h_percent or 0) + self.h_scrollbar:set_percent(self.scroll.x/h_scrollable) self.h_scrollbar:update() end diff --git a/data/plugins/autocomplete.lua b/data/plugins/autocomplete.lua index 98b2dcd0..cf228b6e 100644 --- a/data/plugins/autocomplete.lua +++ b/data/plugins/autocomplete.lua @@ -10,10 +10,6 @@ local RootView = require "core.rootview" local DocView = require "core.docview" local Doc = require "core.doc" ----Symbols cache of all open documents ----@type table -local cache = setmetatable({}, { __mode = "k" }) - config.plugins.autocomplete = common.merge({ -- Amount of characters that need to be written for autocomplete min_len = 3, @@ -23,16 +19,8 @@ config.plugins.autocomplete = common.merge({ max_suggestions = 100, -- Maximum amount of symbols to cache per document max_symbols = 4000, - -- Which symbols to show on the suggestions list: global, local, related, none - suggestions_scope = "global", -- Font size of the description box desc_font_size = 12, - -- Do not show the icons associated to the suggestions - hide_icons = false, - -- Position where icons will be displayed on the suggestions list - icon_position = "left", - -- Do not show the additional information related to a suggestion - hide_info = false, -- The config specification used by gui generators config_spec = { name = "Autocomplete", @@ -72,26 +60,6 @@ config.plugins.autocomplete = common.merge({ min = 1000, max = 10000 }, - { - label = "Suggestions Scope", - description = "Which symbols to show on the suggestions list.", - path = "suggestions_scope", - type = "selection", - default = "global", - values = { - {"All Documents", "global"}, - {"Current Document", "local"}, - {"Related Documents", "related"}, - {"Known Symbols", "none"} - }, - on_apply = function(value) - if value == "global" then - for _, doc in ipairs(core.docs) do - if cache[doc] then cache[doc] = nil end - end - end - end - }, { label = "Description Font Size", description = "Font size of the description box.", @@ -99,31 +67,6 @@ config.plugins.autocomplete = common.merge({ type = "number", default = 12, min = 8 - }, - { - label = "Hide Icons", - description = "Do not show icons on the suggestions list.", - path = "hide_icons", - type = "toggle", - default = false - }, - { - label = "Icons Position", - description = "Position to display icons on the suggestions list.", - path = "icon_position", - type = "selection", - default = "left", - values = { - {"Left", "left"}, - {"Right", "Right"} - } - }, - { - label = "Hide Items Info", - description = "Do not show the additional info related to each suggestion.", - path = "hide_info", - type = "toggle", - default = false } } }, config.plugins.autocomplete) @@ -133,7 +76,6 @@ local autocomplete = {} autocomplete.map = {} autocomplete.map_manually = {} autocomplete.on_close = nil -autocomplete.icons = {} -- Flag that indicates if the autocomplete box was manually triggered -- with the autocomplete.complete() function to prevent the suggestions @@ -153,7 +95,6 @@ function autocomplete.add(t, manually_triggered) { text = text, info = info.info, - icon = info.icon, -- Name of icon to show desc = info.desc, -- Description shown on item selected onhover = info.onhover, -- A callback called once when item is hovered onselect = info.onselect, -- A callback called when item is selected @@ -178,35 +119,28 @@ end -- -- Thread that scans open document symbols and cache them -- -local global_symbols = {} +local max_symbols = config.plugins.autocomplete.max_symbols core.add_thread(function() - local function load_syntax_symbols(doc) - if doc.syntax and not autocomplete.map["language_"..doc.syntax.name] then - local symbols = { - name = "language_"..doc.syntax.name, - files = doc.syntax.files, - items = {} - } - for name, type in pairs(doc.syntax.symbols) do - symbols.items[name] = type + local cache = setmetatable({}, { __mode = "k" }) + + local function get_syntax_symbols(symbols, doc) + if doc.syntax then + for sym in pairs(doc.syntax.symbols) do + symbols[sym] = true end - autocomplete.add(symbols) - return symbols.items end - return {} end local function get_symbols(doc) local s = {} - local syntax_symbols = load_syntax_symbols(doc) - local max_symbols = config.plugins.autocomplete.max_symbols + get_syntax_symbols(s, doc) if doc.disable_symbols then return s end local i = 1 local symbols_count = 0 while i <= #doc.lines do for sym in doc.lines[i]:gmatch(config.symbol_pattern) do - if not s[sym] and not syntax_symbols[sym] then + if not s[sym] then symbols_count = symbols_count + 1 if symbols_count > max_symbols then s = nil @@ -252,18 +186,14 @@ core.add_thread(function() } end -- update symbol set with doc's symbol set - if config.plugins.autocomplete.suggestions_scope == "global" then - for sym in pairs(cache[doc].symbols) do - symbols[sym] = true - end + for sym in pairs(cache[doc].symbols) do + symbols[sym] = true end coroutine.yield() end - -- update global symbols list - if config.plugins.autocomplete.suggestions_scope == "global" then - global_symbols = symbols - end + -- update symbols list + autocomplete.add { name = "open-docs", items = symbols } -- wait for next scan local valid = true @@ -310,50 +240,12 @@ local function update_suggestions() map = autocomplete.map_manually end - local assigned_sym = {} - -- get all relevant suggestions for given filename local items = {} for _, v in pairs(map) do if common.match_pattern(filename, v.files) then for _, item in pairs(v.items) do table.insert(items, item) - assigned_sym[item.text] = true - end - end - end - - -- Append the global, local or related text symbols if applicable - local scope = config.plugins.autocomplete.suggestions_scope - - if not triggered_manually then - local text_symbols = nil - - if scope == "global" then - text_symbols = global_symbols - elseif scope == "local" and cache[doc] and cache[doc].symbols then - text_symbols = cache[doc].symbols - elseif scope == "related" then - for _, d in ipairs(core.docs) do - if doc.syntax == d.syntax then - if cache[d].symbols then - for name in pairs(cache[d].symbols) do - if not assigned_sym[name] then - table.insert(items, setmetatable( - {text = name, info = "normal"}, mt - )) - end - end - end - end - end - end - - if text_symbols then - for name in pairs(text_symbols) do - if not assigned_sym[name] then - table.insert(items, setmetatable({text = name, info = "normal"}, mt)) - end end end end @@ -394,23 +286,13 @@ local function get_suggestions_rect(av) y = y + av:get_line_height() + style.padding.y local font = av:get_font() local th = font:get_height() - local has_icons = false - local hide_info = config.plugins.autocomplete.hide_info - local hide_icons = config.plugins.autocomplete.hide_icons local max_width = 0 for _, s in ipairs(suggestions) do local w = font:get_width(s.text) - if s.info and not hide_info then + if s.info then w = w + style.font:get_width(s.info) + style.padding.x end - local icon = s.icon or s.info - if not hide_icons and icon and autocomplete.icons[icon] then - w = w + autocomplete.icons[icon].font:get_width( - autocomplete.icons[icon].char - ) + (style.padding.x / 2) - has_icons = true - end max_width = math.max(max_width, w) end @@ -437,8 +319,7 @@ local function get_suggestions_rect(av) x - style.padding.x, y - style.padding.y, max_width + style.padding.x * 2, - max_items * (th + style.padding.y) + style.padding.y, - has_icons + max_items * (th + style.padding.y) + style.padding.y end local function wrap_line(line, max_chars) @@ -558,7 +439,7 @@ local function draw_suggestions_box(av) local ah = config.plugins.autocomplete.max_height -- draw background rect - local rx, ry, rw, rh, has_icons = get_suggestions_rect(av) + local rx, ry, rw, rh = get_suggestions_rect(av) renderer.draw_rect(rx, ry, rw, rh, style.background3) -- draw text @@ -567,52 +448,17 @@ local function draw_suggestions_box(av) local y = ry + style.padding.y / 2 local show_count = #suggestions <= ah and #suggestions or ah local start_index = suggestions_idx > ah and (suggestions_idx-(ah-1)) or 1 - local hide_info = config.plugins.autocomplete.hide_info for i=start_index, start_index+show_count-1, 1 do if not suggestions[i] then break end local s = suggestions[i] - - local icon_l_padding, icon_r_padding = 0, 0 - - if has_icons then - local icon = s.icon or s.info - if icon and autocomplete.icons[icon] then - local ifont = autocomplete.icons[icon].font - local itext = autocomplete.icons[icon].char - local icolor = autocomplete.icons[icon].color - if i == suggestions_idx then - icolor = style.accent - elseif type(icolor) == "string" then - icolor = style.syntax[icolor] - end - if config.plugins.autocomplete.icon_position == "left" then - common.draw_text( - ifont, icolor, itext, "left", rx + style.padding.x, y, rw, lh - ) - icon_l_padding = ifont:get_width(itext) + (style.padding.x / 2) - else - common.draw_text( - ifont, icolor, itext, "right", rx, y, rw - style.padding.x, lh - ) - icon_r_padding = ifont:get_width(itext) + (style.padding.x / 2) - end - end - end - local color = (i == suggestions_idx) and style.accent or style.text - common.draw_text( - font, color, s.text, "left", - rx + icon_l_padding + style.padding.x, y, rw, lh - ) - if s.info and not hide_info then + common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh) + if s.info then color = (i == suggestions_idx) and style.text or style.dim - common.draw_text( - style.font, color, s.info, "right", - rx, y, rw - icon_r_padding - style.padding.x, lh - ) + common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh) end y = y + lh if suggestions_idx == i then @@ -773,31 +619,6 @@ function autocomplete.can_complete() return false end ----Register a font icon that can be assigned to completion items. ----@param name string ----@param character string ----@param font? renderer.font ----@param color? string | renderer.color A style.syntax[] name or specific color -function autocomplete.add_icon(name, character, font, color) - local color_type = type(color) - assert( - not color or color_type == "table" - or (color_type == "string" and style.syntax[color]), - "invalid icon color given" - ) - autocomplete.icons[name] = { - char = character, - font = font or style.code_font, - color = color or "keyword" - } -end - --- --- Register built-in syntax symbol types icon --- -for name, _ in pairs(style.syntax) do - autocomplete.add_icon(name, "M", style.icon_font, name) -end -- -- Commands @@ -811,6 +632,7 @@ command.add(predicate, { ["autocomplete:complete"] = function(dv) local doc = dv.doc local item = suggestions[suggestions_idx] + local text = item.text local inserted = false if item.onselect then inserted = item.onselect(suggestions_idx, item) diff --git a/data/plugins/detectindent.lua b/data/plugins/detectindent.lua index 9f22c66b..05070877 100644 --- a/data/plugins/detectindent.lua +++ b/data/plugins/detectindent.lua @@ -37,11 +37,7 @@ local function optimal_indent_from_stat(stat) elseif indent > stat[y] and - ( - indent_occurrences_more_than_once(stat, y) - or - (y == count and stat[y] > 1) - ) + indent_occurrences_more_than_once(stat, y) then score = 0 break @@ -122,10 +118,10 @@ local function get_comment_patterns(syntax, _loop) end if type(pattern.regex) == "table" then table.insert(comments, { - "r", regex.compile(startp), regex.compile(pattern.regex[2]), r=startp + "r", regex.compile(startp), regex.compile(pattern.regex[2]) }) elseif not_is_string then - table.insert(comments, {"r", regex.compile(startp), r=startp}) + table.insert(comments, {"r", regex.compile(startp)}) end end elseif pattern.syntax then @@ -156,25 +152,6 @@ local function get_comment_patterns(syntax, _loop) table.insert(comments, {"p", "^%s*" .. block_comment[1], block_comment[2]}) end end - -- Put comments first and strings last - table.sort(comments, function(c1, c2) - local comment1, comment2 = false, false - if - (c1[1] == "p" and string.find(c1[2], "^%s*", 1, true)) - or - (c1[1] == "r" and string.find(c1["r"], "^\\s*", 1, true)) - then - comment1 = true - end - if - (c2[1] == "p" and string.find(c2[2], "^%s*", 1, true)) - or - (c2[1] == "r" and string.find(c2["r"], "^\\s*", 1, true)) - then - comment2 = true - end - return comment1 and not comment2 - end) comments_cache[syntax] = comments if #comments > 0 then return comments diff --git a/data/plugins/drawwhitespace.lua b/data/plugins/drawwhitespace.lua index 8b8567b3..5c174356 100644 --- a/data/plugins/drawwhitespace.lua +++ b/data/plugins/drawwhitespace.lua @@ -1,6 +1,5 @@ -- mod-version:3 -local core = require "core" local style = require "core.style" local DocView = require "core.docview" local common = require "core.common" @@ -13,7 +12,6 @@ config.plugins.drawwhitespace = common.merge({ show_leading = true, show_trailing = true, show_middle = true, - show_selected_only = false, show_middle_min = 1, @@ -67,13 +65,6 @@ config.plugins.drawwhitespace = common.merge({ type = "toggle", default = true, }, - { - label = "Show Selected Only", - description = "Only draw whitespaces if it is within a selection.", - path = "show_selected_only", - type = "toggle", - default = false, - }, { label = "Show Trailing as Error", description = "Uses an error square to spot them easily, requires 'Show Trailing' enabled.", @@ -302,41 +293,11 @@ function DocView:draw_line_text(idx, x, y) for i=1,#cache,4 do local tx = cache[i + 1] + x local tw = cache[i + 2] - local sub = cache[i] - local color = cache[i + 3] - local partials = {} - if config.plugins.drawwhitespace.show_selected_only and self.doc:has_any_selection() then - for _, l1, c1, l2, c2 in self.doc:get_selections(true) do - if idx > l1 and idx < l2 then - -- Between selection lines, so everything is selected - table.insert(partials, false) - elseif idx == l1 and idx == l2 then - -- Both ends of the selection are on the same line - local _x1 = math.max(cache[i + 1], self:get_col_x_offset(idx, c1)) - local _x2 = math.min((cache[i + 1] + tw), self:get_col_x_offset(idx, c2)) - if _x1 < _x2 then - table.insert(partials, {_x1 + x, 0, _x2 - _x1, math.huge}) - end - elseif idx >= l1 and idx <= l2 then - -- On one of the selection ends - if idx == l1 then -- Start of the selection - local _x = math.max(cache[i + 1], self:get_col_x_offset(idx, c1)) - table.insert(partials, {_x + x, 0, math.huge, math.huge}) - else -- End of the selection - local _x = math.min((cache[i + 1] + tw), self:get_col_x_offset(idx, c2)) - table.insert(partials, {0, 0, _x + x, math.huge}) - end - end - end - end - - if #partials == 0 and not config.plugins.drawwhitespace.show_selected_only then - renderer.draw_text(font, sub, tx, ty, color) - else - for _, p in pairs(partials) do - if p then core.push_clip_rect(table.unpack(p)) end - renderer.draw_text(font, sub, tx, ty, color) - if p then core.pop_clip_rect() end + if tx <= x2 then + local sub = cache[i] + local color = cache[i + 3] + if tx + tw >= x1 then + tx = renderer.draw_text(font, sub, tx, ty, color) end end end diff --git a/data/plugins/language_md.lua b/data/plugins/language_md.lua index 9ed0a43a..8d8a855c 100644 --- a/data/plugins/language_md.lua +++ b/data/plugins/language_md.lua @@ -128,7 +128,6 @@ syntax.add { { pattern = { "```go", "```" }, type = "string", syntax = ".go" }, { pattern = { "```lobster", "```" }, type = "string", syntax = ".lobster" }, { pattern = { "```liquid", "```" }, type = "string", syntax = ".liquid" }, - { pattern = { "```nix", "```" }, type = "string", syntax = ".nix" }, { pattern = { "```", "```" }, type = "string" }, { pattern = { "``", "``" }, type = "string" }, { pattern = { "%f[\\`]%`[%S]", "`" }, type = "string" }, @@ -267,4 +266,3 @@ core.add_thread(function() coroutine.yield(1) end end) - diff --git a/data/plugins/lineguide.lua b/data/plugins/lineguide.lua index 5c4a9204..da9f9b97 100644 --- a/data/plugins/lineguide.lua +++ b/data/plugins/lineguide.lua @@ -15,8 +15,6 @@ config.plugins.lineguide = common.merge({ -- 120, config.line_limit }, - use_custom_color = false, - custom_color = style.selection, -- The config specification used by gui generators config_spec = { name = "Line Guide", @@ -65,21 +63,7 @@ config.plugins.lineguide = common.merge({ end return new_rulers end - }, - { - label = "Use Custom Color", - description = "Enable the utilization of a custom line color.", - path = "use_custom_color", - type = "toggle", - default = false - }, - { - label = "Custom Color", - description = "Applied when the above toggle is enabled.", - path = "custom_color", - type = "color", - default = style.selection - }, + } } }, config.plugins.lineguide) @@ -102,12 +86,10 @@ function DocView:draw_overlay(...) and self:is(DocView) then - local conf = config.plugins.lineguide local line_x = self:get_line_screen_position(1) local character_width = self:get_font():get_width("n") local ruler_width = config.plugins.lineguide.width - local ruler_color = conf.use_custom_color and conf.custom_color - or (style.guide or style.selection) + local ruler_color = style.guide or style.selection for k,v in ipairs(config.plugins.lineguide.rulers) do local ruler = get_ruler(v) diff --git a/data/plugins/projectsearch.lua b/data/plugins/projectsearch.lua index 8c8dfd95..cc5e1324 100644 --- a/data/plugins/projectsearch.lua +++ b/data/plugins/projectsearch.lua @@ -37,7 +37,7 @@ local function find_all_matches_in_file(t, filename, fn) table.insert(t, { file = filename, text = (start_index > 1 and "..." or "") .. line:sub(start_index, 256 + start_index), line = n, col = s }) core.redraw = true end - if n % 100 == 0 then coroutine.yield(0) end + if n % 100 == 0 then coroutine.yield() end n = n + 1 core.redraw = true end diff --git a/data/plugins/toolbarview.lua b/data/plugins/toolbarview.lua index ddc0f39d..9cfa15e8 100644 --- a/data/plugins/toolbarview.lua +++ b/data/plugins/toolbarview.lua @@ -48,7 +48,7 @@ end function ToolbarView:get_icon_width() local max_width = 0 - for i,v in ipairs(self.toolbar_commands) do max_width = math.max(max_width, (v.font or self.toolbar_font):get_width(v.symbol)) end + for i,v in ipairs(self.toolbar_commands) do max_width = math.max(max_width, self.toolbar_font:get_width(v.symbol)) end return max_width end @@ -83,7 +83,7 @@ function ToolbarView:draw() for item, x, y, w, h in self:each_item() do local color = item == self.hovered_item and command.is_valid(item.command) and style.text or style.dim - common.draw_text(item.font or self.toolbar_font, color, item.symbol, nil, x, y, 0, h) + common.draw_text(self.toolbar_font, color, item.symbol, nil, x, y, 0, h) end end @@ -100,16 +100,6 @@ function ToolbarView:on_mouse_pressed(button, x, y, clicks) end -function ToolbarView:on_mouse_left() - ToolbarView.super.on_mouse_left(self) - if self.tooltip then - core.status_view:remove_tooltip() - self.tooltip = false - end - self.hovered_item = nil -end - - function ToolbarView:on_mouse_moved(px, py, ...) if not self.visible then return end ToolbarView.super.on_mouse_moved(self, px, py, ...) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 9dc65d31..f1dd6310 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -9,15 +9,10 @@ local View = require "core.view" local ContextMenu = require "core.contextmenu" local RootView = require "core.rootview" local CommandView = require "core.commandview" -local DocView = require "core.docview" config.plugins.treeview = common.merge({ -- Default treeview width - size = 200 * SCALE, - highlight_focused_file = true, - expand_dirs_to_focused_file = false, - scroll_to_focused_file = false, - animate_scroll_to_focused_file = true + size = 200 * SCALE }, config.plugins.treeview) local tooltip_offset = style.font:get_height() @@ -51,7 +46,7 @@ function TreeView:new() self.target_size = config.plugins.treeview.size self.cache = {} self.tooltip = { x = 0, y = 0, begin = 0, alpha = 0 } - self.last_scroll_y = 0 + self.cursor_pos = { x = 0, y = 0 } self.item_icon_width = 0 self.item_text_spacing = 0 @@ -174,73 +169,20 @@ function TreeView:each_item() end -function TreeView:set_selection(selection, selection_y, center, instant) +function TreeView:set_selection(selection, selection_y) self.selected_item = selection if selection and selection_y and (selection_y <= 0 or selection_y >= self.size.y) then + local lh = self:get_item_height() - if not center and selection_y >= self.size.y - lh then + if selection_y >= self.size.y - lh then selection_y = selection_y - self.size.y + lh end - if center then - selection_y = selection_y - (self.size.y - lh) / 2 - end local _, y = self:get_content_offset() - self.scroll.to.y = selection_y - y - self.scroll.to.y = common.clamp(self.scroll.to.y, 0, self:get_scrollable_size() - self.size.y) - if instant then - self.scroll.y = self.scroll.to.y - end + self.scroll.to.y = selection and (selection_y - y) end end ----Sets the selection to the file with the specified path. ---- ----@param path string #Absolute path of item to select ----@param expand boolean #Expand dirs leading to the item ----@param scroll_to boolean #Scroll to make the item visible ----@param instant boolean #Don't animate the scroll ----@return table? #The selected item -function TreeView:set_selection_to_path(path, expand, scroll_to, instant) - local to_select, to_select_y - local let_it_finish, done - ::restart:: - for item, x,y,w,h in self:each_item() do - if not done then - if item.type == "dir" then - local _, to = string.find(path, item.abs_filename..PATHSEP, 1, true) - if to and to == #item.abs_filename + #PATHSEP then - to_select, to_select_y = item, y - if expand and not item.expanded then - -- Use TreeView:toggle_expand to update the directory structure. - -- Directly using item.expanded doesn't update the cached tree. - self:toggle_expand(true, item) - -- Because we altered the size of the TreeView - -- and because TreeView:get_scrollable_size uses self.count_lines - -- which gets updated only when TreeView:each_item finishes, - -- we can't stop here or we risk that the scroll - -- gets clamped by View:clamp_scroll_position. - let_it_finish = true - -- We need to restart the process because if TreeView:toggle_expand - -- altered the cache, TreeView:each_item risks looping indefinitely. - goto restart - end - end - else - if item.abs_filename == path then - to_select, to_select_y = item, y - done = true - if not let_it_finish then break end - end - end - end - end - if to_select then - self:set_selection(to_select, scroll_to and to_select_y, true, instant) - end - return to_select -end - function TreeView:get_text_bounding_box(item, x, y, w, h) local icon_width = style.icon_font:get_width("D") @@ -251,9 +193,10 @@ function TreeView:get_text_bounding_box(item, x, y, w, h) end - function TreeView:on_mouse_moved(px, py, ...) if not self.visible then return end + self.cursor_pos.x = px + self.cursor_pos.y = py if TreeView.super.on_mouse_moved(self, px, py, ...) then -- mouse movement handled by the View (scrollbar) self.hovered_item = nil @@ -280,12 +223,6 @@ function TreeView:on_mouse_moved(px, py, ...) end -function TreeView:on_mouse_left() - TreeView.super.on_mouse_left(self) - self.hovered_item = nil -end - - function TreeView:update() -- update width local dest = self.visible and self.target_size or 0 @@ -296,7 +233,7 @@ function TreeView:update() self:move_towards(self.size, "x", dest, nil, "treeview") end - if self.size.x == 0 or self.size.y == 0 or not self.visible then return end + if not self.visible then return end local duration = system.get_time() - self.tooltip.begin if self.hovered_item and self.tooltip.x and duration > tooltip_delay then @@ -309,30 +246,10 @@ function TreeView:update() self.item_text_spacing = style.icon_font:get_width("f") / 2 -- this will make sure hovered_item is updated - local dy = math.abs(self.last_scroll_y - self.scroll.y) - if dy > 0 then - self:on_mouse_moved(core.root_view.mouse.x, core.root_view.mouse.y, 0, 0) - self.last_scroll_y = self.scroll.y - end - - local config = config.plugins.treeview - if config.highlight_focused_file then - -- Try to only highlight when we actually change tabs - local current_node = core.root_view:get_active_node() - local current_active_view = core.active_view - if current_node and not current_node.locked - and current_active_view ~= self and current_active_view ~= self.last_active_view then - self.selected_item = nil - self.last_active_view = current_active_view - if DocView:is_extended_by(current_active_view) then - local abs_filename = current_active_view.doc - and current_active_view.doc.abs_filename or "" - self:set_selection_to_path(abs_filename, - config.expand_dirs_to_focused_file, - config.scroll_to_focused_file, - not config.animate_scroll_to_focused_file) - end - end + -- we don't want events when the thing is scrolling fast + local dy = math.abs(self.scroll.to.y - self.scroll.y) + if self.scroll.to.y ~= 0 and dy < self:get_item_height() then + self:on_mouse_moved(self.cursor_pos.x, self.cursor_pos.y, 0, 0) end TreeView.super.update(self) @@ -505,8 +422,8 @@ function TreeView:get_previous(item) end -function TreeView:toggle_expand(toggle, item) - item = item or self.selected_item +function TreeView:toggle_expand(toggle) + local item = self.selected_item if not item then return end @@ -524,11 +441,6 @@ function TreeView:toggle_expand(toggle, item) end -function TreeView:open_doc(filename) - core.root_view:open_doc(core.open_doc(filename)) -end - - -- init local view = TreeView() local node = core.root_view:get_active_node() @@ -707,7 +619,8 @@ command.add( if core.last_active_view and core.active_view == view then core.set_active_view(core.last_active_view) end - view:open_doc(core.normalize_to_project_dir(item.abs_filename)) + local doc_filename = core.normalize_to_project_dir(item.abs_filename) + core.root_view:open_doc(core.open_doc(doc_filename)) end) end end, @@ -753,26 +666,6 @@ command.add( view:toggle_expand(true) end end, - - ["treeview-context:show"] = function() - if view.hovered_item then - menu:show(core.root_view.mouse.x, core.root_view.mouse.y) - return - end - - local item = view.selected_item - if not item then return end - - local x, y - for _i, _x, _y, _w, _h in view:each_item() do - if _i == item then - x = _x + _w / 2 - y = _y + _h / 2 - break - end - end - menu:show(x, y) - end }) @@ -866,7 +759,7 @@ command.add( local file = io.open(doc_filename, "a+") file:write("") file:close() - view:open_doc(doc_filename) + core.root_view:open_doc(core.open_doc(doc_filename)) core.log("Created %s", doc_filename) end, suggest = function(text) @@ -896,12 +789,10 @@ command.add( ["treeview:open-in-system"] = function(item) if PLATFORM == "Windows" then system.exec(string.format("start \"\" %q", item.abs_filename)) - elseif string.find(PLATFORM, "Mac") or PLATFORM == "MorphOS" then + elseif string.find(PLATFORM, "Mac") then system.exec(string.format("open %q", item.abs_filename)) elseif PLATFORM == "Linux" or string.find(PLATFORM, "BSD") then system.exec(string.format("xdg-open %q", item.abs_filename)) - elseif PLATFORM == "AmigaOS 4" then - system.exec(string.format("WBRUN %q SHOW=all VIEWBY=name", item.abs_filename)) end end }) @@ -911,8 +802,8 @@ if projectsearch then menu:register(function() local item = treeitem() return item and item.type == "dir" - end, { - { text = "Find in directory", command = "treeview:search-in-directory" } + end, { + { text = "Find in directory", command = "treeview:search-in-directory" } }) command.add(function() return view.hovered_item and view.hovered_item.type == "dir" @@ -935,25 +826,6 @@ command.add(function() }) -command.add( - function() - return menu.show_context_menu == true and core.active_view:is(TreeView) - end, { - ["treeview-context:focus-previous"] = function() - menu:focus_previous() - end, - ["treeview-context:focus-next"] = function() - menu:focus_next() - end, - ["treeview-context:hide"] = function() - menu:hide() - end, - ["treeview-context:on-selected"] = function() - menu:call_selected_item() - end, -}) - - keymap.add { ["ctrl+\\"] = "treeview:toggle", ["up"] = "treeview:previous", @@ -969,15 +841,6 @@ keymap.add { ["ctrl+lclick"] = "treeview:new-folder" } -keymap.add { - ["menu"] = "treeview-context:show", - ["return"] = "treeview-context:on-selected", - ["up"] = "treeview-context:focus-previous", - ["down"] = "treeview-context:focus-next", - ["escape"] = "treeview-context:hide" -} - - -- The config specification used by gui generators config.plugins.treeview.config_spec = { name = "Treeview", diff --git a/meson.build b/meson.build index f01e702c..3f88be37 100644 --- a/meson.build +++ b/meson.build @@ -208,10 +208,10 @@ else install_data('resources/icons/lite-xl.svg', install_dir : 'share/icons/hicolor/scalable/apps' ) - install_data('resources/linux/com.lite_xl.LiteXL.desktop', + install_data('resources/linux/org.lite_xl.lite_xl.desktop', install_dir : 'share/applications' ) - install_data('resources/linux/com.lite_xl.LiteXL.appdata.xml', + install_data('resources/linux/org.lite_xl.lite_xl.appdata.xml', install_dir : 'share/metainfo' ) endif diff --git a/scripts/appimage.sh b/scripts/appimage.sh index 0548450d..17551a48 100644 --- a/scripts/appimage.sh +++ b/scripts/appimage.sh @@ -138,7 +138,7 @@ generate_appimage() { mv AppRun LiteXL.AppDir/ # These could be symlinks but it seems they doesn't work with AppimageLauncher cp resources/icons/lite-xl.svg LiteXL.AppDir/ - cp resources/linux/com.lite_xl.LiteXL.desktop LiteXL.AppDir/ + cp resources/linux/org.lite_xl.lite_xl.desktop LiteXL.AppDir/ if [[ $ADDONS == true ]]; then addons_download "${BUILD_DIR}" diff --git a/scripts/innosetup/innosetup.iss.in b/scripts/innosetup/innosetup.iss.in index 628733ff..5b2d41b2 100644 --- a/scripts/innosetup/innosetup.iss.in +++ b/scripts/innosetup/innosetup.iss.in @@ -1,7 +1,7 @@ #define MyAppName "Lite XL" #define MyAppVersion "@PROJECT_VERSION@" #define MyAppPublisher "Lite XL Team" -#define MyAppURL "https://lite-xl.github.io" +#define MyAppURL "https://lite-xl.com" #define MyAppExeName "lite-xl.exe" #define BuildDir "@PROJECT_BUILD_DIR@" #define SourceDir "@PROJECT_SOURCE_DIR@" @@ -69,9 +69,7 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip Name: "portablemode"; Description: "Portable Mode"; Flags: unchecked [Files] -Source: "{#BuildDir}/src/lite-xl.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "{#BuildDir}/mingwLibs{#Arch}/*"; DestDir: "{app}"; Flags: ignoreversion ; Check: DirExists(ExpandConstant('{#BuildDir}/mingwLibs{#Arch}')) -Source: "{#SourceDir}/data/*"; DestDir: "{app}/data"; Flags: ignoreversion recursesubdirs +Source: "{#SourceDir}/lite-xl/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] diff --git a/src/api/api.c b/src/api/api.c index dfd8b95f..61828baf 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -29,3 +29,4 @@ void api_load_libs(lua_State *L) { for (int i = 0; libs[i].name; i++) luaL_requiref(L, libs[i].name, libs[i].func, 1); } + diff --git a/src/api/renderer.c b/src/api/renderer.c index 31862643..674dc244 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -391,4 +391,3 @@ int luaopen_renderer(lua_State *L) { lua_setfield(L, -2, "font"); return 1; } - diff --git a/src/api/system.c b/src/api/system.c index 0cbcc437..dcdb035e 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -369,21 +369,6 @@ top: lua_pushinteger(L, (lua_Integer)(e.tfinger.dy * h)); lua_pushinteger(L, e.tfinger.fingerId); return 6; - case SDL_APP_WILLENTERFOREGROUND: - case SDL_APP_DIDENTERFOREGROUND: - #ifdef LITE_USE_SDL_RENDERER - rencache_invalidate(); - #else - SDL_UpdateWindowSurface(window_renderer->window); - #endif - lua_pushstring(L, e.type == SDL_APP_WILLENTERFOREGROUND ? "enteringforeground" : "enteredforeground"); - return 1; - case SDL_APP_WILLENTERBACKGROUND: - lua_pushstring(L, "enteringbackground"); - return 1; - case SDL_APP_DIDENTERBACKGROUND: - lua_pushstring(L, "enteredbackground"); - return 1; default: goto top; @@ -1021,7 +1006,7 @@ static int f_library_gc(lua_State *L) { lua_getfield(L, 1, "handle"); void* handle = lua_touserdata(L, -1); SDL_UnloadObject(handle); - + return 0; } @@ -1087,7 +1072,6 @@ static int f_path_compare(lua_State *L) { size_t offset = 0, i, j; for (i = 0; i < len1 && i < len2; i++) { if (path1[i] != path2[i]) break; - if (isdigit(path1[i])) break; if (path1[i] == PATHSEP) { offset = i + 1; } @@ -1158,15 +1142,6 @@ static int f_path_compare(lua_State *L) { } -static int f_text_input(lua_State* L) { - if (lua_toboolean(L, 1)) - SDL_StartTextInput(); - else - SDL_StopTextInput(); - return 0; -} - - static const luaL_Reg lib[] = { { "poll_event", f_poll_event }, { "wait_event", f_wait_event }, @@ -1200,16 +1175,14 @@ static const luaL_Reg lib[] = { { "load_native_plugin", f_load_native_plugin }, { "path_compare", f_path_compare }, { "get_fs_type", f_get_fs_type }, - { "text_input", f_text_input }, { NULL, NULL } }; int luaopen_system(lua_State *L) { - luaL_newmetatable(L, API_TYPE_NATIVE_PLUGIN); + luaL_newmetatable(L, API_TYPE_NATIVE_PLUGIN); lua_pushcfunction(L, f_library_gc); lua_setfield(L, -2, "__gc"); luaL_newlib(L, lib); return 1; } - diff --git a/src/main.c b/src/main.c index 685277ad..6daf3f44 100644 --- a/src/main.c +++ b/src/main.c @@ -111,8 +111,6 @@ void set_macos_bundle_resources(lua_State *L); // https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-140 #if defined(__x86_64__) || defined(_M_AMD64) || defined(__MINGW64__) #define ARCH_PROCESSOR "x86_64" - #elif __arm__ - #define ARCH_PROCESSOR "arm" #elif defined(__amigaos4__) || defined(__morphos__) #define ARCH_PROCESSOR "ppc" #elif defined(__i386__) || defined(_M_IX86) || defined(__MINGW32__) @@ -157,7 +155,6 @@ int main(int argc, char **argv) { signal(SIGPIPE, SIG_IGN); #endif - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { fprintf(stderr, "Error initializing sdl: %s", SDL_GetError()); exit(1); @@ -209,7 +206,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error creating lite-xl window: %s", SDL_GetError()); exit(1); } - window_renderer = ren_init(window); + ren_init(window); lua_State *L; init_lua: @@ -269,23 +266,22 @@ init_lua: " core.init()\n" " core.run()\n" "end, function(err)\n" - " local error_path = 'error.txt'\n" + " local error_dir\n" " io.stdout:write('Error: '..tostring(err)..'\\n')\n" " io.stdout:write(debug.traceback(nil, 2)..'\\n')\n" " if core and core.on_error then\n" - " error_path = USERDIR .. PATHSEP .. error_path\n" + " error_dir=USERDIR\n" " pcall(core.on_error, err)\n" " else\n" - " local fp = io.open(error_path, 'wb')\n" + " error_dir=system.absolute_path('.')\n" + " local fp = io.open('error.txt', 'wb')\n" " fp:write('Error: ' .. tostring(err) .. '\\n')\n" - " fp:write(debug.traceback(nil, 2)..'\\n')\n" + " fp:write(debug.traceback(nil, 4)..'\\n')\n" " fp:close()\n" - " error_path = system.absolute_path(error_path)\n" " end\n" " system.show_fatal_error('Lite XL internal error',\n" " 'An internal error occurred in a critical part of the application.\\n\\n'..\n" - " 'Error: '..tostring(err)..'\\n\\n'..\n" - " 'Details can be found in \\\"'..error_path..'\\\"')\n" + " 'Please verify the file \\\"error.txt\\\" in the directory '..error_dir)\n" " os.exit(1)\n" "end)\n" "return core and core.restart_request\n"; diff --git a/src/rencache.h b/src/rencache.h index 327671ec..03963485 100644 --- a/src/rencache.h +++ b/src/rencache.h @@ -14,4 +14,3 @@ void rencache_begin_frame(RenWindow *window_renderer); void rencache_end_frame(RenWindow *window_renderer); #endif - diff --git a/src/renderer.c b/src/renderer.c index c998f3c9..cd5ec7ba 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -236,7 +236,7 @@ static void font_file_close(FT_Stream stream) { RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) { RenFont *font = NULL; FT_Face face = NULL; - + SDL_RWops *file = SDL_RWFromFile(path, "rb"); if (!file) goto rwops_failure; @@ -515,7 +515,7 @@ void ren_init(SDL_Window *win) { int error = FT_Init_FreeType( &library ); if ( error ) { fprintf(stderr, "internal font error when starting the application\n"); - return NULL; + return; } window_renderer.window = win; renwin_init_surface(&window_renderer); @@ -523,23 +523,6 @@ void ren_init(SDL_Window *win) { renwin_clip_to_surface(&window_renderer); draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); - - return window_renderer; -} - -void ren_free(RenWindow* window_renderer) { - assert(window_renderer); - renwin_free(window_renderer); - SDL_FreeSurface(draw_rect_surface); - free(window_renderer->command_buf); - window_renderer->command_buf = NULL; - window_renderer->command_buf_size = 0; - free(window_renderer); -} - -void ren_resize_window(RenWindow *window_renderer) { - renwin_resize_surface(window_renderer); - renwin_update_scale(window_renderer); } diff --git a/src/renwindow.c b/src/renwindow.c index 03a89e6b..2ec282d0 100644 --- a/src/renwindow.c +++ b/src/renwindow.c @@ -149,4 +149,3 @@ void renwin_free(RenWindow *ren) { SDL_FreeSurface(ren->rensurface.surface); #endif } - diff --git a/subprojects/lua.wrap b/subprojects/lua.wrap index 16502616..5a2d615b 100644 --- a/subprojects/lua.wrap +++ b/subprojects/lua.wrap @@ -1,14 +1,12 @@ [wrap-file] -directory = lua-5.4.6 -source_url = https://www.lua.org/ftp/lua-5.4.6.tar.gz -source_filename = lua-5.4.6.tar.gz -source_hash = 7d5ea1b9cb6aa0b59ca3dde1c6adcb57ef83a1ba8e5432c0ecd06bf439b3ad88 -patch_filename = lua_5.4.6-3_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.6-3/get_patch -patch_hash = 9b72a95422fd47f79f969d9abdb589ee95712d5512a5246f94e7e4f63d2cb7b7 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/lua_5.4.6-3/lua-5.4.6.tar.gz -wrapdb_version = 5.4.6-3 +directory = lua-5.4.4 +source_url = https://www.lua.org/ftp/lua-5.4.4.tar.gz +source_filename = lua-5.4.4.tar.gz +source_hash = 164c7849653b80ae67bec4b7473b884bf5cc8d2dca05653475ec2ed27b9ebf61 +patch_filename = lua_5.4.4-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/lua_5.4.4-1/get_patch +patch_hash = e61cd965c629d6543176f41a9f1cb9050edfd1566cf00ce768ff211086e40bdc [provide] lua-5.4 = lua_dep -lua = lua_dep +