From 6bc4fbb238f75546cf217e7aacedf2afa341ce47 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Tue, 9 Nov 2021 22:21:45 +0100 Subject: [PATCH 01/11] Restore `TitleView` only when needed Before, every time the user came back from fullscreen, the `TitleView` was shown regardless of its previous status. --- data/core/commands/core.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data/core/commands/core.lua b/data/core/commands/core.lua index 62be4bc6..ad0d4b10 100644 --- a/data/core/commands/core.lua +++ b/data/core/commands/core.lua @@ -6,6 +6,7 @@ local LogView = require "core.logview" local fullscreen = false +local restore_title_view = false local function suggest_directory(text) text = common.home_expand(text) @@ -28,9 +29,12 @@ command.add(nil, { ["core:toggle-fullscreen"] = function() fullscreen = not fullscreen + if fullscreen then + restore_title_view = core.title_view.visible + end system.set_window_mode(fullscreen and "fullscreen" or "normal") - core.show_title_bar(not fullscreen) - core.title_view:configure_hit_test(not fullscreen) + core.show_title_bar(not fullscreen and restore_title_view) + core.title_view:configure_hit_test(not fullscreen and restore_title_view) end, ["core:reload-module"] = function() From f24aa64cd5af8ab2ae07bf567c4ee91d4d7095c6 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 20 Nov 2021 01:15:13 +0100 Subject: [PATCH 02/11] Add `soft_reset` to highlighter This allows clearing the `lines` table without removing entries. --- data/core/doc/highlighter.lua | 7 +++++++ data/core/doc/init.lua | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/data/core/doc/highlighter.lua b/data/core/doc/highlighter.lua index c77e1138..68b66356 100644 --- a/data/core/doc/highlighter.lua +++ b/data/core/doc/highlighter.lua @@ -40,6 +40,13 @@ end function Highlighter:reset() self.lines = {} + self:soft_reset() +end + +function Highlighter:soft_reset() + for i=1,#self.lines do + self.lines[i] = false + end self.first_invalid_line = 1 self.max_wanted_line = 0 end diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index 2e72907a..b0f07921 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -47,7 +47,7 @@ function Doc:reset_syntax() local syn = syntax.get(self.filename or "", header) if self.syntax ~= syn then self.syntax = syn - self.highlighter:reset() + self.highlighter:soft_reset() end end From d0a2c913f505a6e357bb4edff127d00cd3834930 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 20 Nov 2021 01:18:37 +0100 Subject: [PATCH 03/11] Pre-populate the highlighter This avoids problems with calls to `[insert,remove]_notify` on lines that the highlighter has not yet added. --- data/core/doc/init.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index b0f07921..06cde9f9 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -62,12 +62,15 @@ function Doc:load(filename) local fp = assert( io.open(filename, "rb") ) self:reset() self.lines = {} + local i = 1 for line in fp:lines() do if line:byte(-1) == 13 then line = line:sub(1, -2) self.crlf = true end table.insert(self.lines, line .. "\n") + self.highlighter.lines[i] = false + i = i + 1 end if #self.lines == 0 then table.insert(self.lines, "\n") From 3176b467ca26d904dc2cac06f02e2394da57f9ba Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 21 Nov 2021 03:46:43 +0100 Subject: [PATCH 04/11] Add names to language plugins --- data/plugins/language_c.lua | 1 + data/plugins/language_cpp.lua | 1 + data/plugins/language_css.lua | 1 + data/plugins/language_html.lua | 1 + data/plugins/language_js.lua | 1 + data/plugins/language_lua.lua | 1 + data/plugins/language_md.lua | 1 + data/plugins/language_python.lua | 1 + data/plugins/language_xml.lua | 1 + 9 files changed, 9 insertions(+) diff --git a/data/plugins/language_c.lua b/data/plugins/language_c.lua index 44c3b895..b0a4dec5 100644 --- a/data/plugins/language_c.lua +++ b/data/plugins/language_c.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "C", files = { "%.c$", "%.h$", "%.inl$" }, comment = "//", patterns = { diff --git a/data/plugins/language_cpp.lua b/data/plugins/language_cpp.lua index 499a09db..8d6aef4b 100644 --- a/data/plugins/language_cpp.lua +++ b/data/plugins/language_cpp.lua @@ -4,6 +4,7 @@ pcall(require, "plugins.language_c") local syntax = require "core.syntax" syntax.add { + name = "C++", files = { "%.h$", "%.inl$", "%.cpp$", "%.cc$", "%.C$", "%.cxx$", "%.c++$", "%.hh$", "%.H$", "%.hxx$", "%.hpp$", "%.h++$" diff --git a/data/plugins/language_css.lua b/data/plugins/language_css.lua index 222e2f94..395e375c 100644 --- a/data/plugins/language_css.lua +++ b/data/plugins/language_css.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "CSS", files = { "%.css$" }, patterns = { { pattern = "\\.", type = "normal" }, diff --git a/data/plugins/language_html.lua b/data/plugins/language_html.lua index cebb3f1a..1f4515bc 100644 --- a/data/plugins/language_html.lua +++ b/data/plugins/language_html.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "HTML", files = { "%.html?$" }, patterns = { { diff --git a/data/plugins/language_js.lua b/data/plugins/language_js.lua index 7556b00b..291c1287 100644 --- a/data/plugins/language_js.lua +++ b/data/plugins/language_js.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "JavaScript", files = { "%.js$", "%.json$", "%.cson$" }, comment = "//", patterns = { diff --git a/data/plugins/language_lua.lua b/data/plugins/language_lua.lua index 165633b6..5c770d43 100644 --- a/data/plugins/language_lua.lua +++ b/data/plugins/language_lua.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "Lua", files = "%.lua$", headers = "^#!.*[ /]lua", comment = "--", diff --git a/data/plugins/language_md.lua b/data/plugins/language_md.lua index 3c1c329a..62cb8a86 100644 --- a/data/plugins/language_md.lua +++ b/data/plugins/language_md.lua @@ -4,6 +4,7 @@ local syntax = require "core.syntax" syntax.add { + name = "Markdown", files = { "%.md$", "%.markdown$" }, patterns = { { pattern = "\\.", type = "normal" }, diff --git a/data/plugins/language_python.lua b/data/plugins/language_python.lua index 60aa41a6..f1430fb1 100644 --- a/data/plugins/language_python.lua +++ b/data/plugins/language_python.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "Python", files = { "%.py$", "%.pyw$" }, headers = "^#!.*[ /]python", comment = "#", diff --git a/data/plugins/language_xml.lua b/data/plugins/language_xml.lua index 95e310bb..c858d3cf 100644 --- a/data/plugins/language_xml.lua +++ b/data/plugins/language_xml.lua @@ -2,6 +2,7 @@ local syntax = require "core.syntax" syntax.add { + name = "XML", files = { "%.xml$" }, headers = "<%?xml", patterns = { From 23a0f6ca796651e122f3e921aea35f6e495e3f65 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Mon, 22 Nov 2021 06:23:16 +0100 Subject: [PATCH 05/11] Speed up highlighter notify Avoid calling `table.{insert,remove}` multiple times, as this causes multiple shifts in the `self.lines` table. --- data/core/doc/highlighter.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/data/core/doc/highlighter.lua b/data/core/doc/highlighter.lua index c77e1138..22ed12a4 100644 --- a/data/core/doc/highlighter.lua +++ b/data/core/doc/highlighter.lua @@ -1,4 +1,5 @@ local core = require "core" +local common = require "core.common" local config = require "core.config" local tokenizer = require "core.tokenizer" local Object = require "core.object" @@ -51,16 +52,16 @@ end function Highlighter:insert_notify(line, n) self:invalidate(line) + local blanks = { } for i = 1, n do - table.insert(self.lines, line, false) + blanks[i] = false end + common.splice(self.lines, line, 0, blanks) end function Highlighter:remove_notify(line, n) self:invalidate(line) - for i = 1, n do - table.remove(self.lines, line) - end + common.splice(self.lines, line, n) end From 23f83857c5634a3db3c9945261145d0b9f4f6705 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 24 Nov 2021 05:03:42 +0100 Subject: [PATCH 06/11] Don't search if there are no files --- data/core/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/data/core/init.lua b/data/core/init.lua index 4a16e6b7..6f3754e4 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -191,6 +191,7 @@ end local function file_search(files, info) local filename, type = info.filename, info.type local inf, sup = 1, #files + if sup <= 0 then return 1, false end while sup - inf > 8 do local curr = math.floor((inf + sup) / 2) if system.path_compare(filename, type, files[curr].filename, files[curr].type) then From e512c576379fd806f83a89ef0a274f6ed95920d7 Mon Sep 17 00:00:00 2001 From: Adam Harrison Date: Tue, 23 Nov 2021 22:35:11 -0500 Subject: [PATCH 07/11] Added an exclusion for lineguide in the commandview. --- data/plugins/lineguide.lua | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/data/plugins/lineguide.lua b/data/plugins/lineguide.lua index 61debbff..41109e4f 100644 --- a/data/plugins/lineguide.lua +++ b/data/plugins/lineguide.lua @@ -2,20 +2,22 @@ local config = require "core.config" local style = require "core.style" local DocView = require "core.docview" +local CommandView = require "core.commandview" local draw_overlay = DocView.draw_overlay function DocView:draw_overlay(...) - local ns = ("n"):rep(config.line_limit) - local ss = self:get_font():subpixel_scale() - local offset = self:get_font():get_width_subpixel(ns) / ss - local x = self:get_line_screen_position(1) + offset - local y = self.position.y - local w = math.ceil(SCALE * 1) - local h = self.size.y - - local color = style.guide or style.selection - renderer.draw_rect(x, y, w, h, color) - + if not self:is(CommandView) then + local ns = ("n"):rep(config.line_limit) + local ss = self:get_font():subpixel_scale() + local offset = self:get_font():get_width_subpixel(ns) / ss + local x = self:get_line_screen_position(1) + offset + local y = self.position.y + local w = math.ceil(SCALE * 1) + local h = self.size.y + + local color = style.guide or style.selection + renderer.draw_rect(x, y, w, h, color) + end draw_overlay(self, ...) end From 405bd1c2bd5c18b32e7a81adf1857897cec42d27 Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Fri, 26 Nov 2021 13:45:13 +0100 Subject: [PATCH 08/11] Fix logic in project's file insertion The function "file_search" in core.init was sometimes giving a wrong index value, off by one. The problem happened for example when the entry to search was "less than" the first entry, the function returned a value of two instead of one as expected. The bug was easily observed creating a new directory with a name that comes as the first in alphabetical order within the project. --- data/core/init.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index 6f3754e4..f5d38ac0 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -191,7 +191,6 @@ end local function file_search(files, info) local filename, type = info.filename, info.type local inf, sup = 1, #files - if sup <= 0 then return 1, false end while sup - inf > 8 do local curr = math.floor((inf + sup) / 2) if system.path_compare(filename, type, files[curr].filename, files[curr].type) then @@ -200,12 +199,12 @@ local function file_search(files, info) inf = curr end end - repeat + while inf <= sup and not system.path_compare(filename, type, files[inf].filename, files[inf].type) do if files[inf].filename == filename then return inf, true end inf = inf + 1 - until inf > sup or system.path_compare(filename, type, files[inf].filename, files[inf].type) + end return inf, false end From 37c00c877a5e21827b00c8f134da7ba7dc507abd Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Mon, 20 Dec 2021 11:03:49 +0100 Subject: [PATCH 09/11] Ensure TreeView cache entry is removed on delete Address issue: https://github.com/lite-xl/lite-xl/issues/689 Attempt to provide a more accurate fix to commit: 59f64088e1e88f2f2a29e4d5418ccdf781fdc12e For this latter what happens is that any change inside a directory cause the corresponding entry to be folded in the TreeView. The new change is more accurate because we remove only the stale entry corresponding to the delete event and we do not reset the cache of the parent directory using the modify event. --- data/core/init.lua | 5 +++-- data/plugins/treeview.lua | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/data/core/init.lua b/data/core/init.lua index f5d38ac0..9e4676f0 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -1164,8 +1164,8 @@ end -- no-op but can be overrided by plugins -function core.on_dirmonitor_modify() -end +function core.on_dirmonitor_modify() end +function core.on_dirmonitor_delete() end function core.on_dir_change(watch_id, action, filepath) @@ -1174,6 +1174,7 @@ function core.on_dir_change(watch_id, action, filepath) core.dir_rescan_add_job(dir, filepath) if action == "delete" then project_scan_remove_file(dir, filepath) + core.on_dirmonitor_delete(dir, filepath) elseif action == "create" then project_scan_add_file(dir, filepath) core.on_dirmonitor_modify(dir, filepath); diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 77b6732f..2909768c 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -42,6 +42,19 @@ function TreeView:new() self.target_size = default_treeview_size self.cache = {} self.tooltip = { x = 0, y = 0, begin = 0, alpha = 0 } + self:add_core_hooks() +end + + +function TreeView:add_core_hooks() + -- When a file or directory is deleted we delete the corresponding cache entry + -- because if the entry is recreated we may use wrong information from cache. + local on_delete = core.on_dirmonitor_delete + core.on_dirmonitor_delete = function(dir, filepath) + local cache = self.cache[dir.name] + if cache then cache[filepath] = nil end + on_delete(dir, filepath) + end end From 29318be9c71e1be290e7507e9f8b1c9445aad1b0 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sat, 11 Dec 2021 03:43:33 +0100 Subject: [PATCH 10/11] Consume unmatched character correctly We must consume the whole UTF-8 character, not just a single byte. --- data/core/tokenizer.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index d95baeb1..57c17a0b 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -237,8 +237,13 @@ function tokenizer.tokenize(incoming_syntax, text, state) -- consume character if we didn't match if not matched then - push_token(res, "normal", text:sub(i, i)) - i = i + 1 + local n = 0 + -- reach the next character + while text:byte(i + n + 1) and common.is_utf8_cont(text, i + n + 1) do + n = n + 1 + end + push_token(res, "normal", text:sub(i, i + n)) + i = i + n + 1 end end From 3109263c5d5ca0009c604ad8de1f51ac9d38bb78 Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Mon, 20 Dec 2021 14:42:48 +0100 Subject: [PATCH 11/11] Call dmon_unwatch when changing project Fix a conspicuous omission to call the dmon_unwatch function when changing project directory. This uncovered a bug or a quirk of the dmon library where the watch_ids can change as a result of calling dmon_unwatch because they are just indexes on a contiguous array. Use a workaround to always unwatch the first valid watch_id N times. --- data/core/commands/core.lua | 5 ++++- data/core/init.lua | 16 ++++++++++++++++ src/api/system.c | 8 ++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/data/core/commands/core.lua b/data/core/commands/core.lua index ad0d4b10..16b371f3 100644 --- a/data/core/commands/core.lua +++ b/data/core/commands/core.lua @@ -164,7 +164,10 @@ command.add(nil, { core.error("Cannot open folder %q", text) return end - core.confirm_close_docs(core.docs, core.open_folder_project, text) + core.confirm_close_docs(core.docs, function(dirpath) + core.close_current_project() + core.open_folder_project(dirpath) + end, text) end, suggest_directory) end, diff --git a/data/core/init.lua b/data/core/init.lua index 9e4676f0..928df227 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -64,6 +64,22 @@ function core.set_project_dir(new_dir, change_project_fn) return false end +function core.close_current_project() + -- When using system.unwatch_dir we need to pass the watch_id provided by dmon. + -- In reality when unwatching a directory the dmon library shifts the other watch_id + -- values so the actual watch_id changes. To workaround this problem we assume the + -- first watch_id is always 1 and the watch_id are continguous and we unwatch the + -- first watch_id repeateadly up to the number of watch_ids. + local watch_id_max = 0 + for _, project_dir in ipairs(core.project_directories) do + if project_dir.watch_id and project_dir.watch_id > watch_id_max then + watch_id_max = project_dir.watch_id + end + end + for i = 1, watch_id_max do + system.unwatch_dir(1) + end +end function core.open_folder_project(dir_path_abs) if core.set_project_dir(dir_path_abs, core.on_quit_project) then diff --git a/src/api/system.c b/src/api/system.c index 0ebf78f1..4c14843b 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -723,6 +723,13 @@ static int f_watch_dir(lua_State *L) { return 1; } +static int f_unwatch_dir(lua_State *L) { + dmon_watch_id watch_id; + watch_id.id = luaL_checkinteger(L, 1); + dmon_unwatch(watch_id); + return 0; +} + #if __linux__ static int f_watch_dir_add(lua_State *L) { dmon_watch_id watch_id; @@ -826,6 +833,7 @@ static const luaL_Reg lib[] = { { "fuzzy_match", f_fuzzy_match }, { "set_window_opacity", f_set_window_opacity }, { "watch_dir", f_watch_dir }, + { "unwatch_dir", f_unwatch_dir }, { "path_compare", f_path_compare }, #if __linux__ { "watch_dir_add", f_watch_dir_add },