Vendored from upstream, pinned by commit (see debian/extra/README.source): - gitstatus, gitopen, fontconfig, open_ext, select_colorscheme, smoothcaret, nerdicons (font mapping patched to DATADIR, Ships the Symbols Nerd Font Mono TTF, SIL OFL 1.1) - lite-xl-lsp (complete LSP client; idle until a language server is configured) plus the lite-xl-widgets library it requires - 104 language syntax plugins (none duplicate the nine bundled in core) settings GUI left out upstream is broken: it requires a libraries.widget.fonts widget that does not exist in lite-xl-widgets at any revision. Co-developed-with: ZCode (Z.ai)
163 lines
4.7 KiB
Lua
163 lines
4.7 KiB
Lua
-- mod-version:3
|
|
|
|
-- The general idea is to check if the file opened is valid utf-8
|
|
-- since lite-xl only supports UTF8 text, others can be safely assumed
|
|
-- to be binary
|
|
local core = require "core"
|
|
local common = require "core.common"
|
|
local style = require "core.style"
|
|
local DocView = require "core.docview"
|
|
local RootView = require "core.rootview"
|
|
local View = require "core.view"
|
|
|
|
|
|
local function validate_utf8(s, max_len)
|
|
local i, p, len = 1, 1, #s
|
|
while p <= len and i <= max_len do
|
|
if p == s:find("[%z\1-\127]", p) then p = p + 1
|
|
elseif p == s:find("[\194-\223][\128-\191]", p) then p = p + 2
|
|
elseif p == s:find( "\224[\160-\191][\128-\191]", p)
|
|
or p == s:find("[\225-\236][\128-\191][\128-\191]", p)
|
|
or p == s:find( "\237[\128-\159][\128-\191]", p)
|
|
or p == s:find("[\238-\239][\128-\191][\128-\191]", p) then p = p + 3
|
|
elseif p == s:find( "\240[\144-\191][\128-\191][\128-\191]", p)
|
|
or p == s:find("[\241-\243][\128-\191][\128-\191][\128-\191]", p)
|
|
or p == s:find( "\244[\128-\143][\128-\191][\128-\191]", p) then p = p + 4
|
|
else
|
|
return false
|
|
end
|
|
i = i + 1
|
|
end
|
|
return true
|
|
end
|
|
|
|
|
|
local function replace_view(this, that)
|
|
local node = core.root_view.root_node:get_node_for_view(this)
|
|
local idx = node:get_view_idx(this)
|
|
node:remove_view(core.root_view.root_node, this)
|
|
node:add_view(that, idx)
|
|
core.root_view.root_node:update_layout()
|
|
core.redraw = true
|
|
end
|
|
|
|
|
|
local msg = "This file is not displayed because it is either binary or uses an unsupported text encoding."
|
|
local cmd -- here's evil code again...
|
|
if PLATFORM == "Windows" then
|
|
cmd = "start %q"
|
|
elseif PLATFORM == "Linux" then
|
|
cmd = "xdg-open %q"
|
|
else
|
|
cmd = "open %q"
|
|
end
|
|
|
|
local opt = { "Open anyway", "Open with other program", "Close" }
|
|
local opt_actions = {
|
|
function(self)
|
|
-- open anyway
|
|
local view = DocView(core.open_doc(self.filename))
|
|
replace_view(self, view)
|
|
end,
|
|
function(self)
|
|
-- open externally
|
|
local node = core.root_view.root_node:get_node_for_view(self)
|
|
node:close_view(core.root_view.root_node, self)
|
|
system.exec(string.format(cmd, self.filename))
|
|
end,
|
|
function(self)
|
|
local node = core.root_view.root_node:get_node_for_view(self)
|
|
node:close_view(core.root_view.root_node, self)
|
|
end
|
|
}
|
|
|
|
|
|
local OpenExtView = View:extend()
|
|
|
|
|
|
function OpenExtView:new(filename)
|
|
OpenExtView.super.new(self)
|
|
self.filename = filename
|
|
end
|
|
|
|
|
|
function OpenExtView:get_name()
|
|
return common.basename(self.filename)
|
|
end
|
|
|
|
|
|
function OpenExtView:each_option()
|
|
return coroutine.wrap(function()
|
|
local w = (self.size.x - style.padding.x * (#opt + 1)) / #opt
|
|
local h = style.font:get_height() + style.padding.y
|
|
local x, y = self:get_content_offset()
|
|
x = x + style.padding.x
|
|
y = y + self.size.y / 2 + style.padding.y
|
|
for i, o in ipairs(opt) do
|
|
coroutine.yield(i, o, x, y, w, h)
|
|
x = x + w + style.padding.x
|
|
end
|
|
end)
|
|
end
|
|
|
|
|
|
function OpenExtView:on_mouse_moved(px, py, dx, dy)
|
|
OpenExtView.super.on_mouse_moved(self, px, py, dx, dy)
|
|
self.hovered = nil
|
|
for i, _, x, y, w, h in self:each_option() do
|
|
if px > x and px <= x + w and py > y and py <= y + h then
|
|
self.hovered = i
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function OpenExtView:on_mouse_pressed(button, x, y, clicks)
|
|
if OpenExtView.super.on_mouse_pressed(self, button, x, y, clicks) then return end
|
|
if self.hovered then
|
|
opt_actions[self.hovered](self)
|
|
end
|
|
end
|
|
|
|
|
|
function OpenExtView:draw()
|
|
self:draw_background(style.background)
|
|
local x, y = self:get_content_offset()
|
|
local lh = style.font:get_height()
|
|
y = y + self.size.y / 2 - style.padding.y - lh
|
|
common.draw_text(style.font, style.text, msg, "center", x, y, self.size.x, lh)
|
|
for i, opt, x, y, w, h in self:each_option() do
|
|
local text_color = i == self.hovered and style.background or style.text
|
|
renderer.draw_rect(x, y, w, h, style.accent)
|
|
if i ~= self.hovered then
|
|
renderer.draw_rect(x + 1, y + 1, w - 2, h - 2, style.background)
|
|
end
|
|
common.draw_text(style.font, text_color, opt, "center", x, y, w, h)
|
|
end
|
|
end
|
|
|
|
|
|
local function validate_doc(doc)
|
|
local f = io.open(doc.abs_filename or "")
|
|
if not f then return true end
|
|
local str = f:read(128 * 4) -- max bytes for 128 codepoints
|
|
f:close()
|
|
return validate_utf8(str or "", 128)
|
|
end
|
|
|
|
|
|
local rootview_open_doc = RootView.open_doc
|
|
function RootView:open_doc(doc)
|
|
-- 128 * 4 == max number of bytes for 128 codepoints
|
|
if validate_doc(doc) then
|
|
return rootview_open_doc(self, doc)
|
|
else
|
|
local node = self:get_active_node_default()
|
|
local view = OpenExtView(doc.abs_filename or doc.filename)
|
|
node:add_view(view)
|
|
self.root_node:update_layout()
|
|
return view
|
|
end
|
|
end
|