Merged the changes from 2.1.4 upstream release tag

This commit is contained in:
George Sokianos 2024-04-24 21:24:48 +01:00
parent 79f42686a7
commit 3f6207b4af
22 changed files with 263 additions and 99 deletions

View File

@ -9,13 +9,15 @@ on:
inputs: inputs:
version: version:
description: Release Version description: Release Version
default: v2.1.3 default: v2.1.4
required: true required: true
jobs: jobs:
release: release:
name: Create Release name: Create Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
outputs: outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
version: ${{ steps.tag.outputs.version }} version: ${{ steps.tag.outputs.version }}

View File

@ -1,4 +1,6 @@
Copyright (c) 2020-present Lite XL Team Copyright (c) 2020 rxi
Copyright (c) 2020-2022 Francesco Abbate
Copyright (c) 2022-present Lite XL Team
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

View File

@ -1,5 +1,58 @@
# Changes Log # Changes Log
## [2.1.4] - 2024-04-16
This release addresses severe bugs not found in previous releases,
and improves the usability of the program.
### Features
* Add `.pyi` extension to `language_python`.
([#1728](https://github.com/lite-xl/lite-xl/pull/1728))
* Improve autocomplete suggestions box behavior with long text
([#1734](https://github.com/lite-xl/lite-xl/pull/1734))
* Improve `CommandView` and autocomplete scroll behavior
([#1732](https://github.com/lite-xl/lite-xl/pull/1732))
* Add `from` symbol to support ESM
([#1754](https://github.com/lite-xl/lite-xl/pull/1754))
* Add Arduino syntax highlighting support in `language_cpp`
([#1767](https://github.com/lite-xl/lite-xl/pull/1767))
* Skip patterns matching nothing in tokenizer
([#1743](https://github.com/lite-xl/lite-xl/pull/1743))
### Fixes
* Fix uninitialized variables in `src/api/process.c`
([#1719](https://github.com/lite-xl/lite-xl/pull/1719))
* Fix `language_js` regex/comment distinction
([#1731](https://github.com/lite-xl/lite-xl/pull/1731))
* Fix compilation on non-MINGW64 platforms
([#1739](https://github.com/lite-xl/lite-xl/pull/1739))
* Limit `language_js` regex avoidance to numbers, and fix starting `/*` comments
([#1744](https://github.com/lite-xl/lite-xl/pull/1744))
* Fix `buffer_size` in `g_read` for Windows
([#1722](https://github.com/lite-xl/lite-xl/pull/1722))
* Fix missing permission for creating releases
([#1770](https://github.com/lite-xl/lite-xl/pull/1770))
### Other Changes
* Rectify LICENSE dates and owners
([#1748](https://github.com/lite-xl/lite-xl/pull/1748))
* Fix some typos in `core.init`
([#1755](https://github.com/lite-xl/lite-xl/pull/1755))
## [2.1.3] - 2024-01-29 ## [2.1.3] - 2024-01-29
This release addresses severe bugs not found in previous releases. This release addresses severe bugs not found in previous releases.
@ -1451,6 +1504,7 @@ A new global variable `USERDIR` is exposed to point to the user's directory.
- subpixel font rendering with gamma correction - subpixel font rendering with gamma correction
[2.1.4]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.4
[2.1.3]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.3 [2.1.3]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.3
[2.1.2]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.2 [2.1.2]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.2
[2.1.1]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.1 [2.1.1]: https://github.com/lite-xl/lite-xl/releases/tag/v2.1.1

View File

@ -50,6 +50,7 @@ local default_state = {
function CommandView:new() function CommandView:new()
CommandView.super.new(self, SingleLineDoc()) CommandView.super.new(self, SingleLineDoc())
self.suggestion_idx = 1 self.suggestion_idx = 1
self.suggestions_offset = 1
self.suggestions = {} self.suggestions = {}
self.suggestions_height = 0 self.suggestions_height = 0
self.last_change_id = 0 self.last_change_id = 0
@ -123,6 +124,24 @@ function CommandView:move_suggestion_idx(dir)
end end
end end
local function get_suggestions_offset()
local max_visible = math.min(max_suggestions, #self.suggestions)
if dir > 0 then
if self.suggestions_offset + max_visible < self.suggestion_idx + 1 then
return self.suggestion_idx - max_visible + 1
elseif self.suggestions_offset > self.suggestion_idx then
return self.suggestion_idx
end
else
if self.suggestions_offset > self.suggestion_idx then
return self.suggestion_idx
elseif self.suggestions_offset + max_visible < self.suggestion_idx + 1 then
return self.suggestion_idx - max_visible + 1
end
end
return self.suggestions_offset
end
if self.state.show_suggestions then if self.state.show_suggestions then
local n = self.suggestion_idx + dir local n = self.suggestion_idx + dir
self.suggestion_idx = overflow_suggestion_idx(n, #self.suggestions) self.suggestion_idx = overflow_suggestion_idx(n, #self.suggestions)
@ -146,6 +165,8 @@ function CommandView:move_suggestion_idx(dir)
self.last_change_id = self.doc:get_change_id() self.last_change_id = self.doc:get_change_id()
self.state.suggest(self:get_text()) self.state.suggest(self:get_text())
end end
self.suggestions_offset = get_suggestions_offset()
end end
@ -256,6 +277,7 @@ function CommandView:update_suggestions()
end end
self.suggestions = res self.suggestions = res
self.suggestion_idx = 1 self.suggestion_idx = 1
self.suggestions_offset = 1
end end
@ -299,7 +321,7 @@ function CommandView:update()
self:move_towards("suggestions_height", dest, nil, "commandview") self:move_towards("suggestions_height", dest, nil, "commandview")
-- update suggestion cursor offset -- update suggestion cursor offset
local dest = math.min(self.suggestion_idx, max_suggestions) * self:get_suggestion_line_height() local dest = (self.suggestion_idx - self.suggestions_offset + 1) * self:get_suggestion_line_height()
self:move_towards("selection_offset", dest, nil, "commandview") self:move_towards("selection_offset", dest, nil, "commandview")
-- update size based on whether this is the active_view -- update size based on whether this is the active_view
@ -335,6 +357,7 @@ local function draw_suggestions_box(self)
local h = math.ceil(self.suggestions_height) local h = math.ceil(self.suggestions_height)
local rx, ry, rw, rh = self.position.x, self.position.y - h - dh, self.size.x, h local rx, ry, rw, rh = self.position.x, self.position.y - h - dh, self.size.x, h
core.push_clip_rect(rx, ry, rw, rh)
-- draw suggestions background -- draw suggestions background
if #self.suggestions > 0 then if #self.suggestions > 0 then
renderer.draw_rect(rx, ry, rw, rh, style.background3) renderer.draw_rect(rx, ry, rw, rh, style.background3)
@ -344,14 +367,12 @@ local function draw_suggestions_box(self)
end end
-- draw suggestion text -- draw suggestion text
local offset = math.max(self.suggestion_idx - max_suggestions, 0) local first = math.max(self.suggestions_offset, 1)
local last = math.min(offset + max_suggestions, #self.suggestions) local last = math.min(self.suggestions_offset + max_suggestions, #self.suggestions)
core.push_clip_rect(rx, ry, rw, rh)
local first = 1 + offset
for i=first, last do for i=first, last do
local item = self.suggestions[i] local item = self.suggestions[i]
local color = (i == self.suggestion_idx) and style.accent or style.text local color = (i == self.suggestion_idx) and style.accent or style.text
local y = self.position.y - (i - offset) * lh - dh local y = self.position.y - (i - first + 1) * lh - dh
common.draw_text(self:get_font(), color, item.text, nil, x, y, 0, lh) common.draw_text(self:get_font(), color, item.text, nil, x, y, 0, lh)
if item.info then if item.info then

View File

@ -250,7 +250,6 @@ function core.add_project_directory(path)
-- will be simply the name of the directory, without its path. -- will be simply the name of the directory, without its path.
-- The field item.topdir will identify it as a top level directory. -- The field item.topdir will identify it as a top level directory.
path = common.normalize_volume(path) path = common.normalize_volume(path)
local topdir = { local topdir = {
name = path, name = path,
item = {filename = common.basename(path), type = "dir", topdir = true}, item = {filename = common.basename(path), type = "dir", topdir = true},
@ -573,22 +572,22 @@ local config = require "core.config"
-- --
-- Here some examples: -- Here some examples:
-- --
-- "^%." match any file of directory whose basename begins with a dot. -- "^%." matches any file of directory whose basename begins with a dot.
-- --
-- When there is an '/' or a '/$' at the end the pattern it will only match -- When there is an '/' or a '/$' at the end, the pattern will only match
-- directories. When using such a pattern a final '/' will be added to the name -- directories. When using such a pattern a final '/' will be added to the name
-- of any directory entry before checking if it matches. -- of any directory entry before checking if it matches.
-- --
-- "^%.git/" matches any directory named ".git" anywhere in the project. -- "^%.git/" matches any directory named ".git" anywhere in the project.
-- --
-- If a "/" appears anywhere in the pattern except if it appears at the end or -- If a "/" appears anywhere in the pattern (except when it appears at the end or
-- is immediately followed by a '$' then the pattern will be applied to the full -- is immediately followed by a '$'), then the pattern will be applied to the full
-- path of the file or directory. An initial "/" will be prepended to the file's -- path of the file or directory. An initial "/" will be prepended to the file's
-- or directory's path to indicate the project's root. -- or directory's path to indicate the project's root.
-- --
-- "^/node_modules/" will match a directory named "node_modules" at the project's root. -- "^/node_modules/" will match a directory named "node_modules" at the project's root.
-- "^/build.*/" match any top level directory whose name begins with "build" -- "^/build.*/" will match any top level directory whose name begins with "build".
-- "^/subprojects/.+/" match any directory inside a top-level folder named "subprojects". -- "^/subprojects/.+/" will match any directory inside a top-level folder named "subprojects".
-- You may activate some plugins on a per-project basis to override the user's settings. -- You may activate some plugins on a per-project basis to override the user's settings.
-- config.plugins.trimwitespace = true -- config.plugins.trimwitespace = true

View File

@ -1,5 +1,5 @@
-- this file is used by lite-xl to setup the Lua environment when starting -- this file is used by lite-xl to setup the Lua environment when starting
VERSION = "2.1.3r2" VERSION = "2.1.4r1"
MOD_VERSION = "3" MOD_VERSION = "3"
SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or 1 SCALE = tonumber(os.getenv("LITE_SCALE") or os.getenv("GDK_SCALE") or os.getenv("QT_SCALE_FACTOR")) or 1
@ -12,7 +12,6 @@ else
local prefix = os.getenv('LITE_PREFIX') or EXEDIR:match("^(.+)[/\\]bin$") local prefix = os.getenv('LITE_PREFIX') or EXEDIR:match("^(.+)[/\\]bin$")
DATADIR = prefix and (prefix .. PATHSEP .. 'share' .. PATHSEP .. 'lite-xl') or (EXEDIR .. PATHSEP .. 'data') DATADIR = prefix and (prefix .. PATHSEP .. 'share' .. PATHSEP .. 'lite-xl') or (EXEDIR .. PATHSEP .. 'data')
end end
USERDIR = (system.get_file_info(EXEDIR .. PATHSEP .. 'user') and (EXEDIR .. PATHSEP .. 'user')) USERDIR = (system.get_file_info(EXEDIR .. PATHSEP .. 'user') and (EXEDIR .. PATHSEP .. 'user'))
or os.getenv("LITE_USERDIR") or os.getenv("LITE_USERDIR")
or ((os.getenv("XDG_CONFIG_HOME") and os.getenv("XDG_CONFIG_HOME") .. PATHSEP .. "lite-xl")) or ((os.getenv("XDG_CONFIG_HOME") and os.getenv("XDG_CONFIG_HOME") .. PATHSEP .. "lite-xl"))

View File

@ -123,8 +123,10 @@ local function report_bad_pattern(log_fn, syntax, pattern_idx, msg, ...)
end end
if bad_patterns[syntax][pattern_idx] then return end if bad_patterns[syntax][pattern_idx] then return end
bad_patterns[syntax][pattern_idx] = true bad_patterns[syntax][pattern_idx] = true
log_fn("Malformed pattern #%d in %s language plugin. " .. msg, log_fn("Malformed pattern #%d <%s> in %s language plugin.\n" .. msg,
pattern_idx, syntax.name or "unnamed", ...) pattern_idx,
syntax.patterns[pattern_idx].pattern or syntax.patterns[pattern_idx].regex,
syntax.name or "unnamed", ...)
end end
---@param incoming_syntax table ---@param incoming_syntax table
@ -265,7 +267,6 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume)
local text_len = text:ulen() local text_len = text:ulen()
local start_time = system.get_time() local start_time = system.get_time()
local starting_i = i local starting_i = i
while text_len ~= nil and i <= text_len do while text_len ~= nil and i <= text_len do
-- Every 200 chars, check if we're out of time -- Every 200 chars, check if we're out of time
if i - starting_i > 200 then if i - starting_i > 200 then
@ -334,6 +335,14 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume)
for n, p in ipairs(current_syntax.patterns) do for n, p in ipairs(current_syntax.patterns) do
local find_results = { find_text(text, p, i, true, false) } local find_results = { find_text(text, p, i, true, false) }
if find_results[1] then if find_results[1] then
-- Check for patterns successfully matching nothing
if find_results[1] > find_results[2] then
report_bad_pattern(core.warn, current_syntax, n,
"Pattern successfully matched, but nothing was captured.")
goto continue
end
-- Check for patterns with mismatching number of `types`
local type_is_table = type(p.type) == "table" local type_is_table = type(p.type) == "table"
local n_types = type_is_table and #p.type or 1 local n_types = type_is_table and #p.type or 1
if #find_results == 2 and type_is_table then if #find_results == 2 and type_is_table then
@ -347,6 +356,7 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume)
report_bad_pattern(core.warn, current_syntax, n, report_bad_pattern(core.warn, current_syntax, n,
"Too many token types: got %d needed %d.", n_types, #find_results - 1) "Too many token types: got %d needed %d.", n_types, #find_results - 1)
end end
-- matched pattern; make and add tokens -- matched pattern; make and add tokens
push_tokens(res, current_syntax, p, text, find_results) push_tokens(res, current_syntax, p, text, find_results)
-- update state if this was a start|end pattern pair -- update state if this was a start|end pattern pair
@ -362,6 +372,7 @@ function tokenizer.tokenize(incoming_syntax, text, state, resume)
i = find_results[2] + 1 i = find_results[2] + 1
matched = true matched = true
break break
::continue::
end end
end end

View File

@ -212,12 +212,14 @@ end)
local partial = "" local partial = ""
local suggestions_offset = 1
local suggestions_idx = 1 local suggestions_idx = 1
local suggestions = {} local suggestions = {}
local last_line, last_col local last_line, last_col
local function reset_suggestions() local function reset_suggestions()
suggestions_offset = 1
suggestions_idx = 1 suggestions_idx = 1
suggestions = {} suggestions = {}
@ -261,6 +263,7 @@ local function update_suggestions()
end end
end end
suggestions_idx = 1 suggestions_idx = 1
suggestions_offset = 1
end end
local function get_partial_symbol() local function get_partial_symbol()
@ -276,8 +279,10 @@ local function get_active_view()
end end
end end
local last_max_width = 0
local function get_suggestions_rect(av) local function get_suggestions_rect(av)
if #suggestions == 0 then if #suggestions == 0 then
last_max_width = 0
return 0, 0, 0, 0 return 0, 0, 0, 0
end end
@ -287,38 +292,47 @@ local function get_suggestions_rect(av)
local font = av:get_font() local font = av:get_font()
local th = font:get_height() local th = font:get_height()
local ah = config.plugins.autocomplete.max_height
local max_items = math.min(ah, #suggestions)
local show_count = math.min(#suggestions, ah)
local start_index = math.max(suggestions_idx-(ah-1), 1)
local max_width = 0 local max_width = 0
for _, s in ipairs(suggestions) do for i = start_index, start_index + show_count - 1 do
local s = suggestions[i]
local w = font:get_width(s.text) local w = font:get_width(s.text)
if s.info then if s.info then
w = w + style.font:get_width(s.info) + style.padding.x w = w + style.font:get_width(s.info) + style.padding.x
end end
max_width = math.max(max_width, w) max_width = math.max(max_width, w)
end end
max_width = math.max(last_max_width, max_width)
last_max_width = max_width
local ah = config.plugins.autocomplete.max_height max_width = max_width + style.padding.x * 2
x = x - style.padding.x
local max_items = #suggestions
if max_items > ah then
max_items = ah
end
-- additional line to display total items -- additional line to display total items
max_items = max_items + 1 max_items = max_items + 1
if max_width < 150 then if max_width > core.root_view.size.x then
max_width = 150 max_width = core.root_view.size.x
end
if max_width < 150 * SCALE then
max_width = 150 * SCALE
end end
-- if portion not visiable to right, reposition to DocView right margin -- if portion not visiable to right, reposition to DocView right margin
if (x - av.position.x) + max_width > av.size.x then if x + max_width > core.root_view.size.x then
x = (av.size.x + av.position.x) - max_width - (style.padding.x * 2) x = (av.size.x + av.position.x) - max_width
end end
return return
x - style.padding.x, x,
y - style.padding.y, y - style.padding.y,
max_width + style.padding.x * 2, max_width,
max_items * (th + style.padding.y) + style.padding.y max_items * (th + style.padding.y) + style.padding.y
end end
@ -446,16 +460,29 @@ local function draw_suggestions_box(av)
local font = av:get_font() local font = av:get_font()
local lh = font:get_height() + style.padding.y local lh = font:get_height() + style.padding.y
local y = ry + style.padding.y / 2 local y = ry + style.padding.y / 2
local show_count = #suggestions <= ah and #suggestions or ah local show_count = math.min(#suggestions, ah)
local start_index = suggestions_idx > ah and (suggestions_idx-(ah-1)) or 1 local start_index = suggestions_offset
for i=start_index, start_index+show_count-1, 1 do for i=start_index, start_index+show_count-1, 1 do
if not suggestions[i] then if not suggestions[i] then
break break
end end
local s = suggestions[i] local s = suggestions[i]
local info_size = s.info and (style.font:get_width(s.info) + style.padding.x) or style.padding.x
local color = (i == suggestions_idx) and style.accent or style.text local color = (i == suggestions_idx) and style.accent or style.text
common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh) -- Push clip to avoid that the suggestion text gets drawn over suggestion type/icon
core.push_clip_rect(rx + style.padding.x, y, rw - info_size - style.padding.x, lh)
local x_adv = common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh)
core.pop_clip_rect()
-- If the text wasn't fully visible, draw an ellipsis
if x_adv > rx + rw - info_size then
local ellipsis_size = font:get_width("")
local ell_x = rx + rw - info_size - ellipsis_size
renderer.draw_rect(ell_x, y, ellipsis_size, lh, style.background3)
common.draw_text(font, color, "", "left", ell_x, y, ellipsis_size, lh)
end
if s.info then if s.info then
color = (i == suggestions_idx) and style.text or style.dim color = (i == suggestions_idx) and style.text or style.dim
common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh) common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh)
@ -641,7 +668,7 @@ command.add(predicate, {
local current_partial = get_partial_symbol() local current_partial = get_partial_symbol()
local sz = #current_partial local sz = #current_partial
for idx, line1, col1, line2, col2 in doc:get_selections(true) do for _, line1, col1, line2, _ in doc:get_selections(true) do
local n = col1 - 1 local n = col1 - 1
local line = doc.lines[line1] local line = doc.lines[line1]
for i = 1, sz + 1 do for i = 1, sz + 1 do
@ -662,10 +689,24 @@ command.add(predicate, {
["autocomplete:previous"] = function() ["autocomplete:previous"] = function()
suggestions_idx = (suggestions_idx - 2) % #suggestions + 1 suggestions_idx = (suggestions_idx - 2) % #suggestions + 1
local ah = math.min(config.plugins.autocomplete.max_height, #suggestions)
if suggestions_offset > suggestions_idx then
suggestions_offset = suggestions_idx
elseif suggestions_offset + ah < suggestions_idx + 1 then
suggestions_offset = suggestions_idx - ah + 1
end
end, end,
["autocomplete:next"] = function() ["autocomplete:next"] = function()
suggestions_idx = (suggestions_idx % #suggestions) + 1 suggestions_idx = (suggestions_idx % #suggestions) + 1
local ah = math.min(config.plugins.autocomplete.max_height, #suggestions)
if suggestions_offset + ah < suggestions_idx + 1 then
suggestions_offset = suggestions_idx - ah + 1
elseif suggestions_offset > suggestions_idx then
suggestions_offset = suggestions_idx
end
end, end,
["autocomplete:cycle"] = function() ["autocomplete:cycle"] = function()

View File

@ -5,7 +5,8 @@ syntax.add {
name = "C++", name = "C++",
files = { files = {
"%.h$", "%.inl$", "%.cpp$", "%.cc$", "%.C$", "%.cxx$", "%.h$", "%.inl$", "%.cpp$", "%.cc$", "%.C$", "%.cxx$",
"%.c++$", "%.hh$", "%.H$", "%.hxx$", "%.hpp$", "%.h++$" "%.c++$", "%.hh$", "%.H$", "%.hxx$", "%.hpp$", "%.h++$",
"%.ino$"
}, },
comment = "//", comment = "//",
block_comment = { "/*", "*/" }, block_comment = { "/*", "*/" },

View File

@ -20,10 +20,10 @@ local syntax = require "core.syntax"
-- followed by pattern options, and anything that can -- followed by pattern options, and anything that can
-- be after a pattern. -- be after a pattern.
-- --
-- Demo with some unit tests (click on the Unit Tests entry): https://regex101.com/r/R0w8Qw/1 -- Demo with some unit tests (click on the Unit Tests entry): https://regex101.com/r/Vx5L5V/1
-- Note that it has a couple of changes to make it work on that platform. -- Note that it has a couple of changes to make it work on that platform.
local regex_pattern = { local regex_pattern = {
[=[/(?=(?!/)(?:(?>[^\\[\/]++|\\.|\[(?:[^\\\]]++|\\.)*+\])*+)++/[gmiyuvsd]*\s*[\n,;\)\]\}\.])()]=], [=[\/(?=(?!\/)(?:(?>[^\\[\/]++|\\.|\[(?:[^\\\]]++|\\.)*+\])*+)++\/[gmiyuvsd]*\s*(?:[\n,;\)\]\}\.]|\/[\/*]))()]=],
"/()[gmiyuvsd]*", "\\" "/()[gmiyuvsd]*", "\\"
} }
@ -57,18 +57,19 @@ syntax.add {
comment = "//", comment = "//",
block_comment = { "/*", "*/" }, block_comment = { "/*", "*/" },
patterns = { patterns = {
{ pattern = "//.*", type = "comment" }, { pattern = "//.*", type = "comment" },
{ pattern = { "/%*", "%*/" }, type = "comment" }, { pattern = { "/%*", "%*/" }, type = "comment" },
{ regex = regex_pattern, syntax = inner_regex_syntax, type = {"string", "string"} }, { regex = regex_pattern, syntax = inner_regex_syntax, type = {"string", "string"} },
{ pattern = { '"', '"', '\\' }, type = "string" }, { pattern = { '"', '"', '\\' }, type = "string" },
{ pattern = { "'", "'", '\\' }, type = "string" }, { pattern = { "'", "'", '\\' }, type = "string" },
{ pattern = { "`", "`", '\\' }, type = "string" }, { pattern = { "`", "`", '\\' }, type = "string" },
{ pattern = "-?0[xXbBoO][%da-fA-F_]+n?()%s*()/?", type = {"number", "normal", "operator"} }, -- Use (?:\/(?!\/|\*))? to avoid that a regex can start after a number, while also allowing // and /* comments
{ pattern = "-?%d+[%d%.eE_n]*()%s*()/?", type = {"number", "normal", "operator"} }, { regex = [[-?0[xXbBoO][\da-fA-F_]+n?()\s*()(?:\/(?!\/|\*))?]], type = {"number", "normal", "operator"} },
{ pattern = "-?%.?%d+()%s*()/?", type = {"number", "normal", "operator"} }, { regex = [[-?\d+[0-9.eE_n]*()\s*()(?:\/(?!\/|\*))?]], type = {"number", "normal", "operator"} },
{ pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" }, { regex = [[-?\.?\d+()\s*()(?:\/(?!\/|\*))?]], type = {"number", "normal", "operator"} },
{ pattern = "[%a_][%w_]*%f[(]", type = "function" }, { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" },
{ pattern = "[%a_][%w_]*()%s*()/?", type = {"symbol", "normal", "operator"} }, { pattern = "[%a_][%w_]*%f[(]", type = "function" },
{ pattern = "[%a_][%w_]*", type = "symbol" },
}, },
symbols = { symbols = {
["async"] = "keyword", ["async"] = "keyword",
@ -92,6 +93,7 @@ syntax.add {
["get"] = "keyword", ["get"] = "keyword",
["if"] = "keyword", ["if"] = "keyword",
["import"] = "keyword", ["import"] = "keyword",
["from"] = "keyword",
["in"] = "keyword", ["in"] = "keyword",
["of"] = "keyword", ["of"] = "keyword",
["instanceof"] = "keyword", ["instanceof"] = "keyword",

View File

@ -3,7 +3,7 @@ local syntax = require "core.syntax"
syntax.add { syntax.add {
name = "Python", name = "Python",
files = { "%.py$", "%.pyw$", "%.rpy$" }, files = { "%.py$", "%.pyw$", "%.rpy$", "%.pyi$" },
headers = "^#!.*[ /]python", headers = "^#!.*[ /]python",
comment = "#", comment = "#",
block_comment = { '"""', '"""' }, block_comment = { '"""', '"""' },

View File

@ -1,6 +1,6 @@
project('lite-xl', project('lite-xl',
['c'], ['c'],
version : '2.1.3', version : '2.1.4',
license : 'MIT', license : 'MIT',
meson_version : '>= 0.56', meson_version : '>= 0.56',
default_options : [ default_options : [

View File

@ -2,13 +2,13 @@
* lite_xl_plugin_api.h * lite_xl_plugin_api.h
* API for writing C extension modules loaded by Lite XL. * API for writing C extension modules loaded by Lite XL.
* This file is licensed under MIT. * This file is licensed under MIT.
* *
* The Lite XL plugin API is quite simple. * The Lite XL plugin API is quite simple.
* You would write a lua C extension and replace any references to lua.h, lauxlib.h * You would write a lua C extension and replace any references to lua.h, lauxlib.h
* and lualib.h with lite_xl_plugin_api.h. * and lualib.h with lite_xl_plugin_api.h.
* In your main file (where your entrypoint resides), define LITE_XL_PLUGIN_ENTRYPOINT. * In your main file (where your entrypoint resides), define LITE_XL_PLUGIN_ENTRYPOINT.
* If you have multiple entrypoints, define LITE_XL_PLUGIN_ENTRYPOINT in one of them. * If you have multiple entrypoints, define LITE_XL_PLUGIN_ENTRYPOINT in one of them.
* *
* After that, you need to create a Lite XL entrypoint, which is formatted as * After that, you need to create a Lite XL entrypoint, which is formatted as
* luaopen_lite_xl_xxxxx instead of luaopen_xxxxx. * luaopen_lite_xl_xxxxx instead of luaopen_xxxxx.
* This entrypoint accepts a lua_State and an extra parameter of type void *. * This entrypoint accepts a lua_State and an extra parameter of type void *.
@ -16,9 +16,9 @@
* If you have multiple entrypoints, you must call lite_xl_plugin_init() in * If you have multiple entrypoints, you must call lite_xl_plugin_init() in
* each of them. * each of them.
* This function is not thread safe, so don't try to do anything stupid. * This function is not thread safe, so don't try to do anything stupid.
* *
* An example: * An example:
* *
* #define LITE_XL_PLUGIN_ENTRYPOINT * #define LITE_XL_PLUGIN_ENTRYPOINT
* #include "lite_xl_plugin_api.h" * #include "lite_xl_plugin_api.h"
* int luaopen_lite_xl_xxxxx(lua_State* L, void* XL) { * int luaopen_lite_xl_xxxxx(lua_State* L, void* XL) {
@ -26,11 +26,11 @@
* ... * ...
* return 1; * return 1;
* } * }
* *
* You can compile the library just like any Lua library without linking to Lua. * You can compile the library just like any Lua library without linking to Lua.
* An example command would be: gcc -shared -o xxxxx.so xxxxx.c * An example command would be: gcc -shared -o xxxxx.so xxxxx.c
* You must not link to ANY lua library to avoid symbol collision. * You must not link to ANY lua library to avoid symbol collision.
* *
* This file contains stock configuration for a typical installation of Lua 5.4. * This file contains stock configuration for a typical installation of Lua 5.4.
* DO NOT MODIFY ANYTHING. MODIFYING STUFFS IN HERE WILL BREAK * DO NOT MODIFY ANYTHING. MODIFYING STUFFS IN HERE WILL BREAK
* COMPATIBILITY WITH LITE XL AND CAUSE UNDEBUGGABLE BUGS. * COMPATIBILITY WITH LITE XL AND CAUSE UNDEBUGGABLE BUGS.
@ -60,8 +60,8 @@
#define FE_7(what, x, ...) what x,FE_6(what, __VA_ARGS__) #define FE_7(what, x, ...) what x,FE_6(what, __VA_ARGS__)
#define FE_8(what, x, ...) what x,FE_7(what, __VA_ARGS__) #define FE_8(what, x, ...) what x,FE_7(what, __VA_ARGS__)
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N()) #define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__) #define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N #define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 #define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FOR_EACH_(N, what, ...) CONCAT(FE_, N)(what, __VA_ARGS__) #define FOR_EACH_(N, what, ...) CONCAT(FE_, N)(what, __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__) #define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
@ -2560,4 +2560,4 @@ void lite_xl_plugin_init(void *XL);
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/ ******************************************************************************/

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<component type="desktop"> <component type="desktop">
<id>com.lite_xl.LiteXL</id> <id>org.lite_xl.lite_xl</id>
<metadata_license>MIT</metadata_license> <metadata_license>MIT</metadata_license>
<project_license>MIT</project_license> <project_license>MIT</project_license>
<name>Lite XL</name> <name>Lite XL</name>
<summary>A lightweight text editor written in Lua</summary> <summary>A lightweight text editor written in Lua</summary>
<content_rating type="oars-1.0" /> <content_rating type="oars-1.0" />
<launchable type="desktop-id">com.lite_xl.LiteXL.desktop</launchable> <launchable type="desktop-id">org.lite_xl.lite_xl.desktop</launchable>
<description> <description>
<p> <p>
@ -29,6 +29,6 @@
</provides> </provides>
<releases> <releases>
<release version="2.1.3" date="2024-01-29" /> <release version="2.1.4" date="2024-04-16" />
</releases> </releases>
</component> </component>

View File

@ -13,9 +13,9 @@ diff -ruN lua-5.4.4\src\luaconf.h lua-5.4.4-patched\src\luaconf.h
--- lua-5.4.4\src\luaconf.h Thu Jan 13 19:24:43 2022 --- lua-5.4.4\src\luaconf.h Thu Jan 13 19:24:43 2022
+++ lua-5.4.4-patched\src\luaconf.h Wed Feb 22 04:10:02 2023 +++ lua-5.4.4-patched\src\luaconf.h Wed Feb 22 04:10:02 2023
@@ -782,5 +782,15 @@ @@ -782,5 +782,15 @@
+#if defined(lua_c) || defined(luac_c) || (defined(LUA_LIB) && \ +#if defined(lua_c) || defined(luac_c) || (defined(LUA_LIB) && \
+ (defined(lauxlib_c) || defined(liolib_c) || \ + (defined(lauxlib_c) || defined(liolib_c) || \
+ defined(loadlib_c) || defined(loslib_c))) + defined(loadlib_c) || defined(loslib_c)))
@ -27,19 +27,19 @@ diff -ruN lua-5.4.4\src\luaconf.h lua-5.4.4-patched\src\luaconf.h
+ +
+ +
#endif #endif
diff -ruN lua-5.4.4\src\Makefile lua-5.4.4-patched\src\Makefile diff -ruN lua-5.4.4\src\Makefile lua-5.4.4-patched\src\Makefile
--- lua-5.4.4\src\Makefile Thu Jul 15 22:01:52 2021 --- lua-5.4.4\src\Makefile Thu Jul 15 22:01:52 2021
+++ lua-5.4.4-patched\src\Makefile Wed Feb 22 04:10:02 2023 +++ lua-5.4.4-patched\src\Makefile Wed Feb 22 04:10:02 2023
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris PLATS= guess aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris
LUA_A= liblua.a LUA_A= liblua.a
-CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o -CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o
+CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o utf8_wrappers.o +CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o utf8_wrappers.o
LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
diff -ruN lua-5.4.4\src\utf8_wrappers.c lua-5.4.4-patched\src\utf8_wrappers.c diff -ruN lua-5.4.4\src\utf8_wrappers.c lua-5.4.4-patched\src\utf8_wrappers.c
--- lua-5.4.4\src\utf8_wrappers.c Thu Jan 01 08:00:00 1970 --- lua-5.4.4\src\utf8_wrappers.c Thu Jan 01 08:00:00 1970
+++ lua-5.4.4-patched\src\utf8_wrappers.c Wed Feb 22 18:13:45 2023 +++ lua-5.4.4-patched\src\utf8_wrappers.c Wed Feb 22 18:13:45 2023

View File

@ -77,11 +77,17 @@ get_platform_arch() {
platform=$(get_platform_name) platform=$(get_platform_name)
arch=${CROSS_ARCH:-$(uname -m)} arch=${CROSS_ARCH:-$(uname -m)}
if [[ $MSYSTEM != "" ]]; then if [[ $MSYSTEM != "" ]]; then
if [[ $MSYSTEM == "MINGW64" ]]; then case "$MSYSTEM" in
MINGW64|UCRT64|CLANG64)
arch=x86_64 arch=x86_64
else ;;
MINGW32|CLANG32)
arch=i686 arch=i686
fi ;;
CLANGARM64)
arch=aarch64
;;
esac
fi fi
echo "$arch" echo "$arch"
} }

View File

@ -26,12 +26,16 @@ AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL} AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL} AppUpdatesURL={#MyAppURL}
#if Arch=="x64" #if Arch=="x86"
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
#define ArchInternal "x86_64"
#else
#define ArchInternal "i686" #define ArchInternal "i686"
#else
ArchitecturesAllowed={#Arch}
ArchitecturesInstallIn64BitMode={#Arch}
#if Arch=="x64"
#define ArchInternal "x86_64"
#elif Arch=="arm64"
#define ArchInternal "aarch64"
#endif
#endif #endif
AllowNoIcons=yes AllowNoIcons=yes

View File

@ -29,13 +29,24 @@ main() {
local version local version
local output local output
if [[ $MSYSTEM == "MINGW64" ]]; then case "$MSYSTEM" in
MINGW64|UCRT64|CLANG64)
arch=x64 arch=x64
arch_file=x86_64 arch_file=x86_64
else ;;
arch=i686; MINGW32|CLANG32)
arch=x86
arch_file=i686 arch_file=i686
fi ;;
CLANGARM64)
arch=arm64
arch_file=aarch64
;;
*)
echo "error: unsupported MSYSTEM type: $MSYSTEM"
exit 1
;;
esac
initial_arg_count=$# initial_arg_count=$#

View File

@ -213,14 +213,18 @@ main() {
if [[ $platform == "windows" ]]; then if [[ $platform == "windows" ]]; then
exe_file="${exe_file}.exe" exe_file="${exe_file}.exe"
stripcmd="strip --strip-all" stripcmd="strip --strip-all"
# Copy MinGW libraries dependencies. if command -v ntldd >/dev/null 2>&1; then
# MSYS2 ldd command seems to be only 64bit, so use ntldd # Copy MinGW libraries dependencies.
# see https://github.com/msys2/MINGW-packages/issues/4164 # MSYS2 ldd command seems to be only 64bit, so use ntldd
ntldd -R "${exe_file}" \ # see https://github.com/msys2/MINGW-packages/issues/4164
| grep mingw \ ntldd -R "${exe_file}" \
| awk '{print $3}' \ | grep mingw \
| sed 's#\\#/#g' \ | awk '{print $3}' \
| xargs -I '{}' cp -v '{}' "$(pwd)/${dest_dir}/" | sed 's#\\#/#g' \
| xargs -I '{}' cp -v '{}' "$(pwd)/${dest_dir}/"
else
echo "WARNING: ntldd not found; assuming program is static"
fi
else else
# Windows archive is always portable # Windows archive is always portable
package_name+="-portable" package_name+="-portable"

View File

@ -29,3 +29,4 @@ void api_load_libs(lua_State *L) {
for (int i = 0; libs[i].name; i++) for (int i = 0; libs[i].name; i++)
luaL_requiref(L, libs[i].name, libs[i].func, 1); luaL_requiref(L, libs[i].name, libs[i].func, 1);
} }

View File

@ -39,6 +39,7 @@ typedef wchar_t *process_env_t;
#define HANDLE_INVALID (INVALID_HANDLE_VALUE) #define HANDLE_INVALID (INVALID_HANDLE_VALUE)
#define PROCESS_GET_HANDLE(P) ((P)->process_information.hProcess) #define PROCESS_GET_HANDLE(P) ((P)->process_information.hProcess)
#define PROCESS_ARGLIST_INITIALIZER { 0 }
static volatile long PipeSerialNumber; static volatile long PipeSerialNumber;
@ -52,6 +53,7 @@ typedef char **process_env_t;
#define HANDLE_INVALID (0) #define HANDLE_INVALID (0)
#define PROCESS_GET_HANDLE(P) ((P)->pid) #define PROCESS_GET_HANDLE(P) ((P)->pid)
#define PROCESS_ARGLIST_INITIALIZER NULL
#endif #endif
@ -440,6 +442,7 @@ static int process_arglist_add(process_arglist_t *list, size_t *list_len, const
static void process_arglist_free(process_arglist_t *list) { static void process_arglist_free(process_arglist_t *list) {
if (!*list) return;
#ifndef _WIN32 #ifndef _WIN32
char **cmd = *list; char **cmd = *list;
for (int i = 0; cmd[i]; i++) for (int i = 0; cmd[i]; i++)
@ -577,7 +580,8 @@ static void process_env_free(process_env_t *list, size_t list_len) {
static int process_start(lua_State* L) { static int process_start(lua_State* L) {
int r, retval = 1; int r, retval = 1;
size_t env_len = 0, cmd_len = 0, arglist_len = 0, env_vars_len = 0; size_t env_len = 0, cmd_len = 0, arglist_len = 0, env_vars_len = 0;
process_arglist_t arglist; process_t *self = NULL;
process_arglist_t arglist = PROCESS_ARGLIST_INITIALIZER;
process_env_t env_vars = NULL; process_env_t env_vars = NULL;
const char *cwd = NULL; const char *cwd = NULL;
bool detach = false, escape = true; bool detach = false, escape = true;
@ -667,7 +671,7 @@ static int process_start(lua_State* L) {
lua_pop(L, 1); lua_pop(L, 1);
} }
process_t* self = lua_newuserdata(L, sizeof(process_t)); self = lua_newuserdata(L, sizeof(process_t));
memset(self, 0, sizeof(process_t)); memset(self, 0, sizeof(process_t));
luaL_setmetatable(L, API_TYPE_PROCESS); luaL_setmetatable(L, API_TYPE_PROCESS);
self->deadline = deadline; self->deadline = deadline;
@ -825,10 +829,12 @@ static int process_start(lua_State* L) {
if (control_pipe[0]) close(control_pipe[0]); if (control_pipe[0]) close(control_pipe[0]);
if (control_pipe[1]) close(control_pipe[1]); if (control_pipe[1]) close(control_pipe[1]);
#endif #endif
for (int stream = 0; stream < 3; ++stream) { if (self) {
process_stream_t* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1]; for (int stream = 0; stream < 3; ++stream) {
if (*pipe) { process_stream_t* pipe = &self->child_pipes[stream][stream == STDIN_FD ? 0 : 1];
close_fd(pipe); if (*pipe) {
close_fd(pipe);
}
} }
} }
process_arglist_free(&arglist); process_arglist_free(&arglist);
@ -848,7 +854,7 @@ static int g_read(lua_State* L, int stream, unsigned long read_size) {
return luaL_error(L, "error: redirect to handles, FILE* and paths are not supported"); return luaL_error(L, "error: redirect to handles, FILE* and paths are not supported");
#if _WIN32 #if _WIN32
int writable_stream_idx = stream - 1; int writable_stream_idx = stream - 1;
if (self->reading[writable_stream_idx] || !ReadFile(self->child_pipes[stream][0], self->buffer[writable_stream_idx], READ_BUF_SIZE, NULL, &self->overlapped[writable_stream_idx])) { if (self->reading[writable_stream_idx] || !ReadFile(self->child_pipes[stream][0], self->buffer[writable_stream_idx], read_size > READ_BUF_SIZE ? READ_BUF_SIZE : read_size, NULL, &self->overlapped[writable_stream_idx])) {
if (self->reading[writable_stream_idx] || GetLastError() == ERROR_IO_PENDING) { if (self->reading[writable_stream_idx] || GetLastError() == ERROR_IO_PENDING) {
self->reading[writable_stream_idx] = true; self->reading[writable_stream_idx] = true;
DWORD bytesTransferred = 0; DWORD bytesTransferred = 0;