Merge branch 'master' into master-2.1
This commit is contained in:
commit
b9bb64a2f0
|
@ -6,15 +6,44 @@ command.map = {}
|
||||||
local always_true = function() return true end
|
local always_true = function() return true end
|
||||||
|
|
||||||
|
|
||||||
function command.add(predicate, map)
|
---Used iternally by command.add, statusview, and contextmenu to generate a
|
||||||
|
---function with a condition to evaluate returning the boolean result of this
|
||||||
|
---evaluation.
|
||||||
|
---
|
||||||
|
---If a string predicate is given it is treated as a require import that should
|
||||||
|
---return a valid object which is checked against the current active view,
|
||||||
|
---eg: "core.docview" will match any view that inherits from DocView. Appending
|
||||||
|
---a `!` at the end of the string means we want to match the given object
|
||||||
|
---from the import strcitly eg: "core.docview!" only DocView is matched.
|
||||||
|
---A function that returns a boolean can be used instead to perform a custom
|
||||||
|
---evaluation, setting to nil means always evaluates to true.
|
||||||
|
---
|
||||||
|
---@param predicate string | table | function
|
||||||
|
---@return function
|
||||||
|
function command.generate_predicate(predicate)
|
||||||
predicate = predicate or always_true
|
predicate = predicate or always_true
|
||||||
|
local strict = false
|
||||||
if type(predicate) == "string" then
|
if type(predicate) == "string" then
|
||||||
|
if predicate:match("!$") then
|
||||||
|
strict = true
|
||||||
|
predicate = predicate:gsub("!$", "")
|
||||||
|
end
|
||||||
predicate = require(predicate)
|
predicate = require(predicate)
|
||||||
end
|
end
|
||||||
if type(predicate) == "table" then
|
if type(predicate) == "table" then
|
||||||
local class = predicate
|
local class = predicate
|
||||||
predicate = function() return core.active_view:is(class) end
|
if not strict then
|
||||||
|
predicate = function() return core.active_view:extends(class) end
|
||||||
|
else
|
||||||
|
predicate = function() return core.active_view:is(class) end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
return predicate
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function command.add(predicate, map)
|
||||||
|
predicate = command.generate_predicate(predicate)
|
||||||
for name, fn in pairs(map) do
|
for name, fn in pairs(map) do
|
||||||
assert(not command.map[name], "command already exists: " .. name)
|
assert(not command.map[name], "command already exists: " .. name)
|
||||||
command.map[name] = { predicate = predicate, perform = fn }
|
command.map[name] = { predicate = predicate, perform = fn }
|
||||||
|
|
|
@ -180,7 +180,7 @@ local commands = {
|
||||||
local line, col = doc():get_selection()
|
local line, col = doc():get_selection()
|
||||||
doc():set_selection(line, col)
|
doc():set_selection(line, col)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:cut"] = function()
|
["doc:cut"] = function()
|
||||||
cut_or_copy(true)
|
cut_or_copy(true)
|
||||||
end,
|
end,
|
||||||
|
@ -402,11 +402,11 @@ local commands = {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:upper-case"] = function()
|
["doc:upper-case"] = function()
|
||||||
doc():replace(string.upper)
|
doc():replace(string.uupper)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:lower-case"] = function()
|
["doc:lower-case"] = function()
|
||||||
doc():replace(string.lower)
|
doc():replace(string.ulower)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["doc:go-to-line"] = function()
|
["doc:go-to-line"] = function()
|
||||||
|
|
|
@ -39,14 +39,7 @@ local function get_item_size(item)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ContextMenu:register(predicate, items)
|
function ContextMenu:register(predicate, items)
|
||||||
if type(predicate) == "string" then
|
predicate = command.generate_predicate(predicate)
|
||||||
predicate = require(predicate)
|
|
||||||
end
|
|
||||||
if type(predicate) == "table" then
|
|
||||||
local class = predicate
|
|
||||||
predicate = function() return core.active_view:is(class) end
|
|
||||||
end
|
|
||||||
|
|
||||||
local width, height = 0, 0 --precalculate the size of context menu
|
local width, height = 0, 0 --precalculate the size of context menu
|
||||||
for i, item in ipairs(items) do
|
for i, item in ipairs(items) do
|
||||||
if item ~= DIVIDER then
|
if item ~= DIVIDER then
|
||||||
|
|
|
@ -458,7 +458,7 @@ end
|
||||||
|
|
||||||
function Doc:replace_cursor(idx, line1, col1, line2, col2, fn)
|
function Doc:replace_cursor(idx, line1, col1, line2, col2, fn)
|
||||||
local old_text = self:get_text(line1, col1, line2, col2)
|
local old_text = self:get_text(line1, col1, line2, col2)
|
||||||
local new_text, n = fn(old_text)
|
local new_text, res = fn(old_text)
|
||||||
if old_text ~= new_text then
|
if old_text ~= new_text then
|
||||||
self:insert(line2, col2, new_text)
|
self:insert(line2, col2, new_text)
|
||||||
self:remove(line1, col1, line2, col2)
|
self:remove(line1, col1, line2, col2)
|
||||||
|
@ -467,22 +467,22 @@ function Doc:replace_cursor(idx, line1, col1, line2, col2, fn)
|
||||||
self:set_selections(idx, line1, col1, line2, col2)
|
self:set_selections(idx, line1, col1, line2, col2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return n
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
function Doc:replace(fn)
|
function Doc:replace(fn)
|
||||||
local has_selection, n = false, 0
|
local has_selection, results = false, { }
|
||||||
for idx, line1, col1, line2, col2 in self:get_selections(true) do
|
for idx, line1, col1, line2, col2 in self:get_selections(true) do
|
||||||
if line1 ~= line2 or col1 ~= col2 then
|
if line1 ~= line2 or col1 ~= col2 then
|
||||||
n = n + self:replace_cursor(idx, line1, col1, line2, col2, fn)
|
results[idx] = self:replace_cursor(idx, line1, col1, line2, col2, fn)
|
||||||
has_selection = true
|
has_selection = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not has_selection then
|
if not has_selection then
|
||||||
self:set_selection(table.unpack(self.selections))
|
self:set_selection(table.unpack(self.selections))
|
||||||
n = n + self:replace_cursor(1, 1, 1, #self.lines, #self.lines[#self.lines], fn)
|
results[1] = self:replace_cursor(1, 1, 1, #self.lines, #self.lines[#self.lines], fn)
|
||||||
end
|
end
|
||||||
return n
|
return results
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,33 +3,111 @@ local command = require "core.command"
|
||||||
local config = require "core.config"
|
local config = require "core.config"
|
||||||
local keymap = {}
|
local keymap = {}
|
||||||
|
|
||||||
|
---@alias keymap.shortcut string
|
||||||
|
---@alias keymap.command string
|
||||||
|
---@alias keymap.modkey string
|
||||||
|
---@alias keymap.pressed boolean
|
||||||
|
---@alias keymap.map table<keymap.shortcut,keymap.command|keymap.command[]>
|
||||||
|
---@alias keymap.rmap table<keymap.command, keymap.shortcut|keymap.shortcut[]>
|
||||||
|
|
||||||
|
---Pressed status of mod keys.
|
||||||
|
---@type table<keymap.modkey, keymap.pressed>
|
||||||
keymap.modkeys = {}
|
keymap.modkeys = {}
|
||||||
|
|
||||||
|
---List of commands assigned to a shortcut been the key of the map the shortcut.
|
||||||
|
---@type keymap.map
|
||||||
keymap.map = {}
|
keymap.map = {}
|
||||||
|
|
||||||
|
---List of shortcuts assigned to a command been the key of the map the command.
|
||||||
|
---@type keymap.rmap
|
||||||
keymap.reverse_map = {}
|
keymap.reverse_map = {}
|
||||||
|
|
||||||
local macos = PLATFORM == "Mac OS X"
|
local macos = PLATFORM == "Mac OS X"
|
||||||
|
|
||||||
-- Thanks to mathewmariani, taken from his lite-macos github repository.
|
-- Thanks to mathewmariani, taken from his lite-macos github repository.
|
||||||
local modkeys_os = require("core.modkeys-" .. (macos and "macos" or "generic"))
|
local modkeys_os = require("core.modkeys-" .. (macos and "macos" or "generic"))
|
||||||
|
|
||||||
|
---@type table<keymap.modkey, keymap.modkey>
|
||||||
local modkey_map = modkeys_os.map
|
local modkey_map = modkeys_os.map
|
||||||
|
|
||||||
|
---@type keymap.modkey[]
|
||||||
local modkeys = modkeys_os.keys
|
local modkeys = modkeys_os.keys
|
||||||
|
|
||||||
local function key_to_stroke(k)
|
|
||||||
|
---Generates a stroke sequence including currently pressed mod keys.
|
||||||
|
---@param key string
|
||||||
|
---@return string
|
||||||
|
local function key_to_stroke(key)
|
||||||
local stroke = ""
|
local stroke = ""
|
||||||
for _, mk in ipairs(modkeys) do
|
for _, mk in ipairs(modkeys) do
|
||||||
if keymap.modkeys[mk] then
|
if keymap.modkeys[mk] then
|
||||||
stroke = stroke .. mk .. "+"
|
stroke = stroke .. mk .. "+"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return stroke .. k
|
return stroke .. key
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---Remove the given value from an array associated to a key in a table.
|
||||||
|
---@param tbl table<string, string> The table containing the key
|
||||||
|
---@param k string The key containing the array
|
||||||
|
---@param v? string The value to remove from the array
|
||||||
|
local function remove_only(tbl, k, v)
|
||||||
|
if tbl[k] then
|
||||||
|
if v then
|
||||||
|
local j = 0
|
||||||
|
for i=1, #tbl[k] do
|
||||||
|
while tbl[k][i + j] == v do
|
||||||
|
j = j + 1
|
||||||
|
end
|
||||||
|
tbl[k][i] = tbl[k][i + j]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
tbl[k] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---Removes from a keymap.map the bindings that are already registered.
|
||||||
|
---@param map keymap.map
|
||||||
|
local function remove_duplicates(map)
|
||||||
|
for stroke, commands in pairs(map) do
|
||||||
|
if type(commands) == "string" or type(commands) == "function" then
|
||||||
|
commands = { commands }
|
||||||
|
end
|
||||||
|
if keymap.map[stroke] then
|
||||||
|
for _, registered_cmd in ipairs(keymap.map[stroke]) do
|
||||||
|
local j = 0
|
||||||
|
for i=1, #commands do
|
||||||
|
while commands[i + j] == registered_cmd do
|
||||||
|
j = j + 1
|
||||||
|
end
|
||||||
|
commands[i] = commands[i + j]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #commands < 1 then
|
||||||
|
map[stroke] = nil
|
||||||
|
else
|
||||||
|
map[stroke] = commands
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---Add bindings by replacing commands that were previously assigned to a shortcut.
|
||||||
|
---@param map keymap.map
|
||||||
function keymap.add_direct(map)
|
function keymap.add_direct(map)
|
||||||
for stroke, commands in pairs(map) do
|
for stroke, commands in pairs(map) do
|
||||||
if type(commands) == "string" then
|
if type(commands) == "string" or type(commands) == "function" then
|
||||||
commands = { commands }
|
commands = { commands }
|
||||||
end
|
end
|
||||||
|
if keymap.map[stroke] then
|
||||||
|
for _, cmd in ipairs(keymap.map[stroke]) do
|
||||||
|
remove_only(keymap.reverse_map, cmd, stroke)
|
||||||
|
end
|
||||||
|
end
|
||||||
keymap.map[stroke] = commands
|
keymap.map[stroke] = commands
|
||||||
for _, cmd in ipairs(commands) do
|
for _, cmd in ipairs(commands) do
|
||||||
keymap.reverse_map[cmd] = keymap.reverse_map[cmd] or {}
|
keymap.reverse_map[cmd] = keymap.reverse_map[cmd] or {}
|
||||||
|
@ -38,15 +116,23 @@ function keymap.add_direct(map)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---Adds bindings by appending commands to already registered shortcut or by
|
||||||
|
---replacing currently assigned commands if overwrite is specified.
|
||||||
|
---@param map keymap.map
|
||||||
|
---@param overwrite? boolean
|
||||||
function keymap.add(map, overwrite)
|
function keymap.add(map, overwrite)
|
||||||
|
remove_duplicates(map)
|
||||||
for stroke, commands in pairs(map) do
|
for stroke, commands in pairs(map) do
|
||||||
if macos then
|
if macos then
|
||||||
stroke = stroke:gsub("%f[%a]ctrl%f[%A]", "cmd")
|
stroke = stroke:gsub("%f[%a]ctrl%f[%A]", "cmd")
|
||||||
end
|
end
|
||||||
if type(commands) == "string" or type(commands) == "function" then
|
|
||||||
commands = { commands }
|
|
||||||
end
|
|
||||||
if overwrite then
|
if overwrite then
|
||||||
|
if keymap.map[stroke] then
|
||||||
|
for _, cmd in ipairs(keymap.map[stroke]) do
|
||||||
|
remove_only(keymap.reverse_map, cmd, stroke)
|
||||||
|
end
|
||||||
|
end
|
||||||
keymap.map[stroke] = commands
|
keymap.map[stroke] = commands
|
||||||
else
|
else
|
||||||
keymap.map[stroke] = keymap.map[stroke] or {}
|
keymap.map[stroke] = keymap.map[stroke] or {}
|
||||||
|
@ -62,35 +148,34 @@ function keymap.add(map, overwrite)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function remove_only(tbl, k, v)
|
---Unregisters the given shortcut and associated command.
|
||||||
for key, values in pairs(tbl) do
|
---@param shortcut string
|
||||||
if key == k then
|
---@param cmd string
|
||||||
if v then
|
function keymap.unbind(shortcut, cmd)
|
||||||
for i, value in ipairs(values) do
|
remove_only(keymap.map, shortcut, cmd)
|
||||||
if value == v then
|
remove_only(keymap.reverse_map, cmd, shortcut)
|
||||||
table.remove(values, i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
tbl[key] = nil
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function keymap.unbind(key, cmd)
|
|
||||||
remove_only(keymap.map, key, cmd)
|
|
||||||
remove_only(keymap.reverse_map, cmd, key)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---Returns all the shortcuts associated to a command unpacked for easy assignment.
|
||||||
|
---@param cmd string
|
||||||
|
---@return ...
|
||||||
function keymap.get_binding(cmd)
|
function keymap.get_binding(cmd)
|
||||||
return table.unpack(keymap.reverse_map[cmd] or {})
|
return table.unpack(keymap.reverse_map[cmd] or {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---Returns all the shortcuts associated to a command packed in a table.
|
||||||
|
---@param cmd string
|
||||||
|
---@return table<integer, string> | nil shortcuts
|
||||||
|
function keymap.get_bindings(cmd)
|
||||||
|
return keymap.reverse_map[cmd]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Events listening
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
function keymap.on_key_pressed(k, ...)
|
function keymap.on_key_pressed(k, ...)
|
||||||
local mk = modkey_map[k]
|
local mk = modkey_map[k]
|
||||||
if mk then
|
if mk then
|
||||||
|
@ -101,7 +186,7 @@ function keymap.on_key_pressed(k, ...)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local stroke = key_to_stroke(k)
|
local stroke = key_to_stroke(k)
|
||||||
local commands, performed = keymap.map[stroke]
|
local commands, performed = keymap.map[stroke], false
|
||||||
if commands then
|
if commands then
|
||||||
for _, cmd in ipairs(commands) do
|
for _, cmd in ipairs(commands) do
|
||||||
if type(cmd) == "function" then
|
if type(cmd) == "function" then
|
||||||
|
@ -143,6 +228,9 @@ function keymap.on_key_released(k)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Register default bindings
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
if macos then
|
if macos then
|
||||||
local keymap_macos = require("core.keymap-macos")
|
local keymap_macos = require("core.keymap-macos")
|
||||||
keymap_macos(keymap)
|
keymap_macos(keymap)
|
||||||
|
|
|
@ -21,6 +21,11 @@ end
|
||||||
|
|
||||||
|
|
||||||
function Object:is(T)
|
function Object:is(T)
|
||||||
|
return getmetatable(self) == T
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Object:extends(T)
|
||||||
local mt = getmetatable(self)
|
local mt = getmetatable(self)
|
||||||
while mt do
|
while mt do
|
||||||
if mt == T then
|
if mt == T then
|
||||||
|
|
|
@ -113,9 +113,6 @@ function StatusView.Item:hide() self.visible = false end
|
||||||
---Show the item on the status bar.
|
---Show the item on the status bar.
|
||||||
function StatusView.Item:show() self.visible = true end
|
function StatusView.Item:show() self.visible = true end
|
||||||
|
|
||||||
---Function assiged by default when user provides a nil predicate.
|
|
||||||
local function predicate_always_true() return true end
|
|
||||||
|
|
||||||
---A condition to evaluate if the item should be displayed. If a string
|
---A condition to evaluate if the item should be displayed. If a string
|
||||||
---is given it is treated as a require import that should return a valid object
|
---is given it is treated as a require import that should return a valid object
|
||||||
---which is checked against the current active view, the sames applies if a
|
---which is checked against the current active view, the sames applies if a
|
||||||
|
@ -123,15 +120,7 @@ local function predicate_always_true() return true end
|
||||||
---perform a custom evaluation, setting to nil means always evaluates to true.
|
---perform a custom evaluation, setting to nil means always evaluates to true.
|
||||||
---@param predicate string | table | StatusView.Item.predicate
|
---@param predicate string | table | StatusView.Item.predicate
|
||||||
function StatusView.Item:set_predicate(predicate)
|
function StatusView.Item:set_predicate(predicate)
|
||||||
predicate = predicate or predicate_always_true
|
self.predicate = command.generate_predicate(predicate)
|
||||||
if type(predicate) == "string" then
|
|
||||||
predicate = require(predicate)
|
|
||||||
end
|
|
||||||
if type(predicate) == "table" then
|
|
||||||
local class = predicate
|
|
||||||
predicate = function() return core.active_view:is(class) end
|
|
||||||
end
|
|
||||||
self.predicate = predicate
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -655,14 +644,14 @@ local function merge_deprecated_items(destination, items, alignment)
|
||||||
local position = alignment == StatusView.Item.LEFT and "left" or "right"
|
local position = alignment == StatusView.Item.LEFT and "left" or "right"
|
||||||
|
|
||||||
local item_start = StatusView.Item(
|
local item_start = StatusView.Item(
|
||||||
predicate_always_true,
|
nil,
|
||||||
"deprecated:"..position.."-start",
|
"deprecated:"..position.."-start",
|
||||||
alignment
|
alignment
|
||||||
)
|
)
|
||||||
item_start.get_item = items_start
|
item_start.get_item = items_start
|
||||||
|
|
||||||
local item_end = StatusView.Item(
|
local item_end = StatusView.Item(
|
||||||
predicate_always_true,
|
nil,
|
||||||
"deprecated:"..position.."-end",
|
"deprecated:"..position.."-end",
|
||||||
alignment
|
alignment
|
||||||
)
|
)
|
||||||
|
|
|
@ -169,12 +169,12 @@ function tokenizer.tokenize(incoming_syntax, text, state)
|
||||||
if p.whole_line[p_idx] and next > 1 then
|
if p.whole_line[p_idx] and next > 1 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- go to the start of the next utf-8 character
|
|
||||||
while text:byte(next) and common.is_utf8_cont(text, next) do
|
|
||||||
next = next + 1
|
|
||||||
end
|
|
||||||
res = p.pattern and { text:ufind((at_start or p.whole_line[p_idx]) and "^" .. code or code, next) }
|
res = p.pattern and { text:ufind((at_start or p.whole_line[p_idx]) and "^" .. code or code, next) }
|
||||||
or { regex.match(code, text, next, (at_start or p.whole_line[p_idx]) and regex.ANCHORED or 0) }
|
or { regex.match(code, text, text:ucharpos(next), (at_start or p.whole_line[p_idx]) and regex.ANCHORED or 0) }
|
||||||
|
if p.regex and #res > 0 then -- set correct utf8 len for regex result
|
||||||
|
res[2] = res[1] + string.ulen(text:sub(res[1], res[2])) - 1
|
||||||
|
res[1] = next
|
||||||
|
end
|
||||||
if res[1] and close and target[3] then
|
if res[1] and close and target[3] then
|
||||||
local count = 0
|
local count = 0
|
||||||
for i = res[1] - 1, 1, -1 do
|
for i = res[1] - 1, 1, -1 do
|
||||||
|
@ -189,7 +189,8 @@ function tokenizer.tokenize(incoming_syntax, text, state)
|
||||||
return table.unpack(res)
|
return table.unpack(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
while i <= #text do
|
local text_len = text:ulen()
|
||||||
|
while i <= text_len do
|
||||||
-- continue trying to match the end pattern of a pair if we have a state set
|
-- continue trying to match the end pattern of a pair if we have a state set
|
||||||
if current_pattern_idx > 0 then
|
if current_pattern_idx > 0 then
|
||||||
local p = current_syntax.patterns[current_pattern_idx]
|
local p = current_syntax.patterns[current_pattern_idx]
|
||||||
|
@ -262,13 +263,8 @@ function tokenizer.tokenize(incoming_syntax, text, state)
|
||||||
|
|
||||||
-- consume character if we didn't match
|
-- consume character if we didn't match
|
||||||
if not matched then
|
if not matched then
|
||||||
local n = 0
|
push_token(res, "normal", text:usub(i, i))
|
||||||
-- reach the next character
|
i = i + 1
|
||||||
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:usub(i, i + n))
|
|
||||||
i = i + n + 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
-- inject utf8 functions to strings
|
-- inject utf8 functions to strings
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local utf8 = require "utf8extra"
|
||||||
|
|
||||||
string.ubyte = utf8.byte
|
string.ubyte = utf8.byte
|
||||||
string.uchar = utf8.char
|
string.uchar = utf8.char
|
||||||
string.ufind = utf8.find
|
string.ufind = utf8.find
|
||||||
|
|
|
@ -3,7 +3,6 @@ local core = require "core"
|
||||||
local command = require "core.command"
|
local command = require "core.command"
|
||||||
local keymap = require "core.keymap"
|
local keymap = require "core.keymap"
|
||||||
local ContextMenu = require "core.contextmenu"
|
local ContextMenu = require "core.contextmenu"
|
||||||
local DocView = require "core.docview"
|
|
||||||
local RootView = require "core.rootview"
|
local RootView = require "core.rootview"
|
||||||
|
|
||||||
local menu = ContextMenu()
|
local menu = ContextMenu()
|
||||||
|
@ -33,7 +32,7 @@ function RootView:draw(...)
|
||||||
menu:draw()
|
menu:draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
command.add(function() return getmetatable(core.active_view) == DocView end, {
|
command.add("core.docview!", {
|
||||||
["context:show"] = function()
|
["context:show"] = function()
|
||||||
menu:show(core.active_view.position.x, core.active_view.position.y)
|
menu:show(core.active_view.position.x, core.active_view.position.y)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
renderer = {}
|
renderer = {}
|
||||||
|
|
||||||
---
|
---
|
||||||
---Represents a color used by the rendering functions.
|
---Array of bytes that represents a color used by the rendering functions.
|
||||||
|
---Note: indexes for rgba are numerical 1 = r, 2 = g, 3 = b, 4 = a but for
|
||||||
|
---documentation purposes the letters r, g, b, a were used.
|
||||||
---@class renderer.color
|
---@class renderer.color
|
||||||
---@field public r number Red
|
---@field public r number Red
|
||||||
---@field public g number Green
|
---@field public g number Green
|
||||||
|
@ -17,7 +19,7 @@ renderer.color = {}
|
||||||
---
|
---
|
||||||
---Represent options that affect a font's rendering.
|
---Represent options that affect a font's rendering.
|
||||||
---@class renderer.fontoptions
|
---@class renderer.fontoptions
|
||||||
---@field public antialiasing "'grayscale'" | "'subpixel'"
|
---@field public antialiasing "'none'" | "'grayscale'" | "'subpixel'"
|
||||||
---@field public hinting "'slight'" | "'none'" | '"full"'
|
---@field public hinting "'slight'" | "'none'" | '"full"'
|
||||||
-- @field public bold boolean
|
-- @field public bold boolean
|
||||||
-- @field public italic boolean
|
-- @field public italic boolean
|
||||||
|
@ -38,6 +40,16 @@ renderer.font = {}
|
||||||
---@return renderer.font
|
---@return renderer.font
|
||||||
function renderer.font.load(path, size, options) end
|
function renderer.font.load(path, size, options) end
|
||||||
|
|
||||||
|
---
|
||||||
|
---Combines an array of fonts into a single one for broader charset support,
|
||||||
|
---the order of the list determines the fonts precedence when retrieving
|
||||||
|
---a symbol from it.
|
||||||
|
---
|
||||||
|
---@param fonts renderer.font[]
|
||||||
|
---
|
||||||
|
---@return renderer.font
|
||||||
|
function renderer.font.group(fonts) end
|
||||||
|
|
||||||
---
|
---
|
||||||
---Clones a font object into a new one.
|
---Clones a font object into a new one.
|
||||||
---
|
---
|
||||||
|
@ -80,25 +92,6 @@ function renderer.font:get_size() end
|
||||||
---@param size number
|
---@param size number
|
||||||
function renderer.font:set_size(size) end
|
function renderer.font:set_size(size) end
|
||||||
|
|
||||||
---
|
|
||||||
---Assistive functionality to replace characters in a
|
|
||||||
---rendered text with other characters.
|
|
||||||
---@class renderer.replacements
|
|
||||||
renderer.replacements = {}
|
|
||||||
|
|
||||||
---
|
|
||||||
---Create a new character replacements object.
|
|
||||||
---
|
|
||||||
---@return renderer.replacements
|
|
||||||
function renderer.replacements.new() end
|
|
||||||
|
|
||||||
---
|
|
||||||
---Add to internal map a character to character replacement.
|
|
||||||
---
|
|
||||||
---@param original_char string Should be a single character like '\t'
|
|
||||||
---@param replacement_char string Should be a single character like '»'
|
|
||||||
function renderer.replacements:add(original_char, replacement_char) end
|
|
||||||
|
|
||||||
---
|
---
|
||||||
---Toggles drawing debugging rectangles on the currently rendered sections
|
---Toggles drawing debugging rectangles on the currently rendered sections
|
||||||
---of the window to help troubleshoot the renderer.
|
---of the window to help troubleshoot the renderer.
|
||||||
|
@ -141,29 +134,13 @@ function renderer.set_clip_rect(x, y, width, height) end
|
||||||
function renderer.draw_rect(x, y, width, height, color) end
|
function renderer.draw_rect(x, y, width, height, color) end
|
||||||
|
|
||||||
---
|
---
|
||||||
---Draw text.
|
---Draw text and return the x coordinate where the text finished drawing.
|
||||||
---
|
---
|
||||||
---@param font renderer.font
|
---@param font renderer.font
|
||||||
---@param text string
|
---@param text string
|
||||||
---@param x number
|
---@param x number
|
||||||
---@param y number
|
---@param y number
|
||||||
---@param color renderer.color
|
---@param color renderer.color
|
||||||
---@param replace renderer.replacements
|
|
||||||
---@param color_replace renderer.color
|
|
||||||
---
|
---
|
||||||
---@return number x_subpixel
|
---@return number x
|
||||||
function renderer.draw_text(font, text, x, y, color, replace, color_replace) end
|
function renderer.draw_text(font, text, x, y, color) end
|
||||||
|
|
||||||
---
|
|
||||||
---Draw text at subpixel level.
|
|
||||||
---
|
|
||||||
---@param font renderer.font
|
|
||||||
---@param text string
|
|
||||||
---@param x number
|
|
||||||
---@param y number
|
|
||||||
---@param color renderer.color
|
|
||||||
---@param replace renderer.replacements
|
|
||||||
---@param color_replace renderer.color
|
|
||||||
---
|
|
||||||
---@return number x_subpixel
|
|
||||||
function renderer.draw_text_subpixel(font, text, x, y, color, replace, color_replace) end
|
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
---@meta
|
---@meta
|
||||||
|
|
||||||
|
---Additional utf8 support not provided by lua.
|
||||||
|
---@class utf8extra
|
||||||
|
utf8extra = {}
|
||||||
|
|
||||||
---UTF-8 equivalent of string.byte
|
---UTF-8 equivalent of string.byte
|
||||||
---@param s string
|
---@param s string
|
||||||
---@param i? integer
|
---@param i? integer
|
||||||
---@param j? integer
|
---@param j? integer
|
||||||
---@return integer
|
---@return integer
|
||||||
---@return ...
|
---@return ...
|
||||||
function utf8.byte(s, i, j) end
|
function utf8extra.byte(s, i, j) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.char
|
---UTF-8 equivalent of string.char
|
||||||
---@param byte integer
|
---@param byte integer
|
||||||
---@param ... integer
|
---@param ... integer
|
||||||
---@return string
|
---@return string
|
||||||
---@return ...
|
---@return ...
|
||||||
function utf8.char(byte, ...) end
|
function utf8extra.char(byte, ...) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.find
|
---UTF-8 equivalent of string.find
|
||||||
---@param s string
|
---@param s string
|
||||||
|
@ -23,14 +27,14 @@ function utf8.char(byte, ...) end
|
||||||
---@return integer start
|
---@return integer start
|
||||||
---@return integer end
|
---@return integer end
|
||||||
---@return ... captured
|
---@return ... captured
|
||||||
function utf8.find(s, pattern, init, plain) end
|
function utf8extra.find(s, pattern, init, plain) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.gmatch
|
---UTF-8 equivalent of string.gmatch
|
||||||
---@param s string
|
---@param s string
|
||||||
---@param pattern string
|
---@param pattern string
|
||||||
---@param init? integer
|
---@param init? integer
|
||||||
---@return fun():string, ...
|
---@return fun():string, ...
|
||||||
function utf8.gmatch(s, pattern, init) end
|
function utf8extra.gmatch(s, pattern, init) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.gsub
|
---UTF-8 equivalent of string.gsub
|
||||||
---@param s string
|
---@param s string
|
||||||
|
@ -39,41 +43,41 @@ function utf8.gmatch(s, pattern, init) end
|
||||||
---@param n integer
|
---@param n integer
|
||||||
---@return string
|
---@return string
|
||||||
---@return integer count
|
---@return integer count
|
||||||
function utf8.gsub(s, pattern, repl, n) end
|
function utf8extra.gsub(s, pattern, repl, n) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.len
|
---UTF-8 equivalent of string.len
|
||||||
---@param s string
|
---@param s string
|
||||||
---@return integer
|
---@return integer
|
||||||
function utf8.len(s) end
|
function utf8extra.len(s) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.lower
|
---UTF-8 equivalent of string.lower
|
||||||
---@param s string
|
---@param s string
|
||||||
---@return string
|
---@return string
|
||||||
function utf8.lower(s) end
|
function utf8extra.lower(s) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.match
|
---UTF-8 equivalent of string.match
|
||||||
---@param s string
|
---@param s string
|
||||||
---@param pattern string
|
---@param pattern string
|
||||||
---@param init? integer
|
---@param init? integer
|
||||||
---@return string | number captured
|
---@return string | number captured
|
||||||
function utf8.match(s, pattern, init) end
|
function utf8extra.match(s, pattern, init) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.reverse
|
---UTF-8 equivalent of string.reverse
|
||||||
---@param s string
|
---@param s string
|
||||||
---@return string
|
---@return string
|
||||||
function utf8.reverse(s) end
|
function utf8extra.reverse(s) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.sub
|
---UTF-8 equivalent of string.sub
|
||||||
---@param s string
|
---@param s string
|
||||||
---@param i integer
|
---@param i integer
|
||||||
---@param j? integer
|
---@param j? integer
|
||||||
---@return string
|
---@return string
|
||||||
function utf8.sub(s, i, j) end
|
function utf8extra.sub(s, i, j) end
|
||||||
|
|
||||||
---UTF-8 equivalent of string.upper
|
---UTF-8 equivalent of string.upper
|
||||||
---@param s string
|
---@param s string
|
||||||
---@return string
|
---@return string
|
||||||
function utf8.upper(s) end
|
function utf8extra.upper(s) end
|
||||||
|
|
||||||
---Escape a str to UTF-8 format string. It support several escape format:
|
---Escape a str to UTF-8 format string. It support several escape format:
|
||||||
---* %ddd - which ddd is a decimal number at any length: change Unicode code point to UTF-8 format.
|
---* %ddd - which ddd is a decimal number at any length: change Unicode code point to UTF-8 format.
|
||||||
|
@ -91,7 +95,7 @@ function utf8.upper(s) end
|
||||||
---```
|
---```
|
||||||
---@param s string
|
---@param s string
|
||||||
---@return string utf8_string
|
---@return string utf8_string
|
||||||
function utf8.escape(s) end
|
function utf8extra.escape(s) end
|
||||||
|
|
||||||
---Convert UTF-8 position to byte offset. if only index is given, return byte
|
---Convert UTF-8 position to byte offset. if only index is given, return byte
|
||||||
---offset of this UTF-8 char index. if both charpos and index is given, a new
|
---offset of this UTF-8 char index. if both charpos and index is given, a new
|
||||||
|
@ -103,7 +107,7 @@ function utf8.escape(s) end
|
||||||
---@param index? integer
|
---@param index? integer
|
||||||
---@return integer charpos
|
---@return integer charpos
|
||||||
---@return integer codepoint
|
---@return integer codepoint
|
||||||
function utf8.charpos(s, charpos, index) end
|
function utf8extra.charpos(s, charpos, index) end
|
||||||
|
|
||||||
---Iterate though the UTF-8 string s. If only s is given, it can used as a iterator:
|
---Iterate though the UTF-8 string s. If only s is given, it can used as a iterator:
|
||||||
---```lua
|
---```lua
|
||||||
|
@ -120,7 +124,7 @@ function utf8.charpos(s, charpos, index) end
|
||||||
---@param index? integer
|
---@param index? integer
|
||||||
---@return integer charpos
|
---@return integer charpos
|
||||||
---@return integer codepoint
|
---@return integer codepoint
|
||||||
function utf8.next(s, charpos, index) end
|
function utf8extra.next(s, charpos, index) end
|
||||||
|
|
||||||
---Insert a substring to s. If idx is given, insert substring before char at
|
---Insert a substring to s. If idx is given, insert substring before char at
|
||||||
---this index, otherwise substring will concat to s. idx can be negative.
|
---this index, otherwise substring will concat to s. idx can be negative.
|
||||||
|
@ -128,7 +132,7 @@ function utf8.next(s, charpos, index) end
|
||||||
---@param idx? integer
|
---@param idx? integer
|
||||||
---@param substring string
|
---@param substring string
|
||||||
---return string new_string
|
---return string new_string
|
||||||
function utf8.insert(s, idx, substring) end
|
function utf8extra.insert(s, idx, substring) end
|
||||||
|
|
||||||
---Delete a substring in s. If neither start nor stop is given, delete the last
|
---Delete a substring in s. If neither start nor stop is given, delete the last
|
||||||
---UTF-8 char in s, otherwise delete char from start to end of s. if stop is
|
---UTF-8 char in s, otherwise delete char from start to end of s. if stop is
|
||||||
|
@ -138,7 +142,7 @@ function utf8.insert(s, idx, substring) end
|
||||||
---@param start? integer
|
---@param start? integer
|
||||||
---@param stop? integer
|
---@param stop? integer
|
||||||
---return string new_string
|
---return string new_string
|
||||||
function utf8.remove(s, start, stop) end
|
function utf8extra.remove(s, start, stop) end
|
||||||
|
|
||||||
---Calculate the width of UTF-8 string s. if ambi_is_double is given, the
|
---Calculate the width of UTF-8 string s. if ambi_is_double is given, the
|
||||||
---ambiguous width character's width is 2, otherwise it's 1. fullwidth/doublewidth
|
---ambiguous width character's width is 2, otherwise it's 1. fullwidth/doublewidth
|
||||||
|
@ -150,7 +154,7 @@ function utf8.remove(s, start, stop) end
|
||||||
---@param ambi_is_double? boolean
|
---@param ambi_is_double? boolean
|
||||||
---@param default_width? integer
|
---@param default_width? integer
|
||||||
---@return integer width
|
---@return integer width
|
||||||
function utf8.width(s, ambi_is_double, default_width) end
|
function utf8extra.width(s, ambi_is_double, default_width) end
|
||||||
|
|
||||||
---Return the character index at given location in string s. this is a reverse
|
---Return the character index at given location in string s. this is a reverse
|
||||||
---operation of utf8.width(). this function returns a index of location, and a
|
---operation of utf8.width(). this function returns a index of location, and a
|
||||||
|
@ -164,24 +168,24 @@ function utf8.width(s, ambi_is_double, default_width) end
|
||||||
---@return integer idx
|
---@return integer idx
|
||||||
---@return integer offset
|
---@return integer offset
|
||||||
---@return integer width
|
---@return integer width
|
||||||
function utf8.widthindex(s, location, ambi_is_double, default_width) end
|
function utf8extra.widthindex(s, location, ambi_is_double, default_width) end
|
||||||
|
|
||||||
---Convert UTF-8 string s to title-case, used to compare by ignore case. if s
|
---Convert UTF-8 string s to title-case, used to compare by ignore case. if s
|
||||||
---is a number, it's treat as a code point and return a convert code point
|
---is a number, it's treat as a code point and return a convert code point
|
||||||
---(number). utf8.lower/utf8.pper has the same extension.
|
---(number). utf8.lower/utf8.pper has the same extension.
|
||||||
---@param s string
|
---@param s string
|
||||||
---return string new_string
|
---return string new_string
|
||||||
function utf8.title(s) end
|
function utf8extra.title(s) end
|
||||||
|
|
||||||
---Convert UTF-8 string s to folded case, used to compare by ignore case. if s
|
---Convert UTF-8 string s to folded case, used to compare by ignore case. if s
|
||||||
---is a number, it's treat as a code point and return a convert code point
|
---is a number, it's treat as a code point and return a convert code point
|
||||||
---(number). utf8.lower/utf8.pper has the same extension.
|
---(number). utf8.lower/utf8.pper has the same extension.
|
||||||
---@param s string
|
---@param s string
|
||||||
---return string new_string
|
---return string new_string
|
||||||
function utf8.fold(s) end
|
function utf8extra.fold(s) end
|
||||||
|
|
||||||
---Compare a and b without case, -1 means a < b, 0 means a == b and 1 means a > b.
|
---Compare a and b without case, -1 means a < b, 0 means a == b and 1 means a > b.
|
||||||
---@param a string
|
---@param a string
|
||||||
---@param b string
|
---@param b string
|
||||||
---@return integer result
|
---@return integer result
|
||||||
function utf8.ncasecmp(a, b) end
|
function utf8extra.ncasecmp(a, b) end
|
|
@ -174,6 +174,7 @@ endif
|
||||||
|
|
||||||
install_data('licenses/licenses.md', install_dir : lite_docdir)
|
install_data('licenses/licenses.md', install_dir : lite_docdir)
|
||||||
|
|
||||||
|
install_subdir('docs/api' , install_dir : lite_datadir, strip_directory: true)
|
||||||
install_subdir('data/core' , install_dir : lite_datadir, exclude_files : 'start.lua')
|
install_subdir('data/core' , install_dir : lite_datadir, exclude_files : 'start.lua')
|
||||||
foreach data_module : ['fonts', 'plugins', 'colors']
|
foreach data_module : ['fonts', 'plugins', 'colors']
|
||||||
install_subdir(join_paths('data', data_module), install_dir : lite_datadir)
|
install_subdir(join_paths('data', data_module), install_dir : lite_datadir)
|
||||||
|
|
|
@ -5,7 +5,7 @@ int luaopen_renderer(lua_State *L);
|
||||||
int luaopen_regex(lua_State *L);
|
int luaopen_regex(lua_State *L);
|
||||||
int luaopen_process(lua_State *L);
|
int luaopen_process(lua_State *L);
|
||||||
int luaopen_dirmonitor(lua_State* L);
|
int luaopen_dirmonitor(lua_State* L);
|
||||||
int luaopen_utf8(lua_State* L);
|
int luaopen_utf8extra(lua_State* L);
|
||||||
|
|
||||||
static const luaL_Reg libs[] = {
|
static const luaL_Reg libs[] = {
|
||||||
{ "system", luaopen_system },
|
{ "system", luaopen_system },
|
||||||
|
@ -13,7 +13,7 @@ static const luaL_Reg libs[] = {
|
||||||
{ "regex", luaopen_regex },
|
{ "regex", luaopen_regex },
|
||||||
{ "process", luaopen_process },
|
{ "process", luaopen_process },
|
||||||
{ "dirmonitor", luaopen_dirmonitor },
|
{ "dirmonitor", luaopen_dirmonitor },
|
||||||
{ "utf8", luaopen_utf8 },
|
{ "utf8extra", luaopen_utf8extra },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1264,7 +1264,7 @@ static const char UTF8PATT[] = "[\0-\x7F\xC2-\xF4][\x80-\xBF]*";
|
||||||
static const char UTF8PATT[] = "[%z\1-\x7F\xC2-\xF4][\x80-\xBF]*";
|
static const char UTF8PATT[] = "[%z\1-\x7F\xC2-\xF4][\x80-\xBF]*";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int luaopen_utf8 (lua_State *L) {
|
int luaopen_utf8extra (lua_State *L) {
|
||||||
luaL_Reg libs[] = {
|
luaL_Reg libs[] = {
|
||||||
#define ENTRY(name) { #name, Lutf8_##name }
|
#define ENTRY(name) { #name, Lutf8_##name }
|
||||||
ENTRY(offset),
|
ENTRY(offset),
|
||||||
|
|
Loading…
Reference in New Issue