feat(lua): add basic LuaCATS types for internal lua code

This commit adds rudimentary types for the internal lua code. This does
not have a big effect on its own, but it can be a part of a bigger
effort to add types to the codebase.

The types are only usable within yazi itself and are not published for
plugin developers to use (yet).

I only added types for the things that are defined in the lua side of
the codebase. This means most of the useful typing is still missing. I
want to add that separately, as it would be difficult to keep the types
in sync with the actual codebase.
This commit is contained in:
Mika Vilpas 2024-05-01 13:27:20 +03:00
parent bdb28f7691
commit 372ecdd403
25 changed files with 139 additions and 2 deletions

View file

@ -1,7 +1,11 @@
---@class yazi.Current
---@field area? unknown
Current = {
area = ui.Rect.default,
}
---@param area unknown
---@return table
function Current:empty(area)
local folder = Folder:by_kind(Folder.CURRENT)
@ -17,6 +21,8 @@ function Current:empty(area)
}
end
---@param area unknown
---@return table
function Current:render(area)
self.area = area

View file

@ -1,5 +1,8 @@
---@class yazi.File
File = {}
---@param file unknown
---@return table
function File:icon(file)
local icon = file:icon()
if not icon then
@ -11,11 +14,15 @@ function File:icon(file)
end
end
---@param file unknown
---@return table
function File:prefix(file)
local prefix = file:prefix() or ""
return prefix == "" and {} or { ui.Span(prefix .. "/") }
end
---@param file unknown
---@return table
function File:highlights(file)
local name = file.name:gsub("\r", "?", 1)
local highlights = file:highlights()
@ -53,6 +60,8 @@ function File:found(file)
}
end
---@param file unknown
---@return table
function File:symlink(file)
if not MANAGER.show_symlink then
return {}
@ -62,6 +71,8 @@ function File:symlink(file)
return to and { ui.Span(" -> " .. tostring(to)):italic() } or {}
end
---@param file unknown
---@return table
function File:full(file)
return ya.flat {
self:icon(file),
@ -72,6 +83,8 @@ function File:full(file)
}
end
---@param file unknown
---@return table
function File:style(file)
local style = file:style()
if not file:is_hovered() then
@ -83,6 +96,8 @@ function File:style(file)
end
end
---@param file unknown
---@return 0 | 1 | 2 | 3 | 4
function File:marker(file)
local yanked = file:is_yanked()
if yanked ~= 0 then

View file

@ -1,9 +1,12 @@
---@class yazi.Folder
Folder = {
PARENT = 0,
CURRENT = 1,
PREVIEW = 2,
}
---@param area unknown
---@param files unknown[]
function Folder:linemode(area, files)
local mode = cx.active.conf.linemode
if mode == "none" then
@ -29,6 +32,9 @@ function Folder:linemode(area, files)
return ui.Paragraph(area, lines):align(ui.Paragraph.RIGHT)
end
---@param area unknown
---@param markers unknown[]
---@return table
function Folder:markers(area, markers)
if #markers == 0 or area.w * area.h == 0 then
return {}
@ -73,6 +79,7 @@ function Folder:markers(area, markers)
return elements
end
---@param kind yazi.FolderType
function Folder:by_kind(kind)
if kind == self.PARENT then
return cx.active.parent

View file

@ -1,7 +1,10 @@
---@class yazi.Header
Header = {
area = ui.Rect.default,
}
---@param max integer
---@return table
function Header:cwd(max)
local cwd = cx.active.current.cwd
local readable = ya.readable_path(tostring(cwd))
@ -10,6 +13,7 @@ function Header:cwd(max)
return ui.Span(ya.truncate(text, { max = max, rtl = true })):style(THEME.manager.cwd)
end
---@return table
function Header:count()
local yanked = #cx.yanked
@ -35,6 +39,7 @@ function Header:count()
}
end
---@return table
function Header:tabs()
local tabs = #cx.tabs
if tabs == 1 then
@ -57,6 +62,9 @@ function Header:tabs()
end
-- TODO: remove this function after v0.2.5 release
--
---@param area unknown
---@return table
function Header:layout(area)
if not ya.deprecated_header_layout then
ya.deprecated_header_layout = true
@ -76,6 +84,8 @@ function Header:layout(area)
:split(area)
end
---@param area unknown
---@return table
function Header:render(area)
self.area = area

View file

@ -1,7 +1,10 @@
---@class yazi.Manager
Manager = {
area = ui.Rect.default,
}
---@param area unknown
---@return unknown[]
function Manager:layout(area)
self.area = area
@ -15,6 +18,8 @@ function Manager:layout(area)
:split(area)
end
---@param area unknown
---@return unknown[]
function Manager:render(area)
local chunks = self:layout(area)

View file

@ -1,7 +1,10 @@
---@class yazi.Parent
Parent = {
area = ui.Rect.default,
}
---@param area unknown
---@return table
function Parent:render(area)
self.area = area

View file

@ -1,7 +1,10 @@
---@class yazi.Preview
Preview = {
area = ui.Rect.default,
}
---@param area unknown
---@return table
function Preview:render(area)
self.area = area
return {}

View file

@ -1,7 +1,11 @@
---@class yazi.Progress
Progress = {
area = ui.Rect.default,
}
---@param area unknown
---@param offset integer
---@return table
function Progress:render(area, offset)
self.area = ui.Rect {
x = math.max(0, area.w - offset - 21),
@ -18,6 +22,7 @@ end
--
-- However, at this time, we can only access `cx.tasks`. If you need certain data from the complete `cx`,
-- just cache it to `self` during `render()`, and read it in `partial_render()` - this process is referred to as "composition".
---@return table
function Progress:partial_render()
local progress = cx.tasks.progress
if progress.total == 0 then

View file

@ -1,7 +1,9 @@
---@class yazi.Status
Status = {
area = ui.Rect.default,
}
---@return unknown
function Status.style()
if cx.active.mode.is_select then
return THEME.status.mode_select
@ -12,6 +14,7 @@ function Status.style()
end
end
---@return table
function Status:mode()
local mode = tostring(cx.active.mode):upper()
if mode == "UNSET" then
@ -25,6 +28,7 @@ function Status:mode()
}
end
---@return table
function Status:size()
local h = cx.active.current.hovered
if not h then
@ -38,6 +42,7 @@ function Status:size()
}
end
---@return table
function Status:name()
local h = cx.active.current.hovered
if not h then
@ -47,6 +52,7 @@ function Status:name()
return ui.Span(" " .. h.name)
end
---@return table
function Status:permissions()
local h = cx.active.current.hovered
if not h then
@ -76,6 +82,7 @@ function Status:permissions()
return ui.Line(spans)
end
---@return table
function Status:percentage()
local percent = 0
local cursor = cx.active.current.cursor
@ -99,6 +106,7 @@ function Status:percentage()
}
end
---@return table
function Status:position()
local cursor = cx.active.current.cursor
local length = #cx.active.current.files
@ -110,6 +118,8 @@ function Status:position()
}
end
---@param area unknown
---@return table
function Status:render(area)
self.area = area

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local _, bound = ya.preview_archive(self)
if bound then
@ -7,6 +8,7 @@ function M:peek()
end
end
---@param units number
function M:seek(units)
local h = cx.active.current.hovered
if h and h.url == self.file.url then

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local _, bound = ya.preview_code(self)
if bound then
@ -7,6 +8,7 @@ function M:peek()
end
end
---@param units number
function M:seek(units)
local h = cx.active.current.hovered
if h and h.url == self.file.url then

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:setup()
ps.sub_remote("dds-cd", function(url) ya.manager_emit("cd", { url }) end)
end

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local cmd = os.getenv("YAZI_FILE_ONE") or "file"
local output, code = Command(cmd):args({ "-bL", tostring(self.file.url) }):stdout(Command.PIPED):output()
@ -16,6 +17,7 @@ function M:peek()
ya.preview_widgets(self, { p:wrap(ui.Paragraph.WRAP) })
end
---@return nil
function M:seek() end
return M

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local folder = Folder:by_kind(Folder.PREVIEW)
if not folder or folder.cwd ~= self.file.url then
@ -38,6 +39,7 @@ function M:peek()
)
end
---@return nil
function M:seek(units)
local folder = Folder:by_kind(Folder.PREVIEW)
if folder and folder.cwd == self.file.url then

View file

@ -1,7 +1,9 @@
local state = ya.sync(function() return cx.active.current.cwd end)
---@return nil
local function fail(s, ...) ya.notify { title = "Fzf", content = string.format(s, ...), timeout = 5, level = "error" } end
---@return nil
local function entry()
local _permit = ya.hide()
local cwd = tostring(state())

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local url = ya.file_cache(self)
if not url or not fs.cha(url) then
@ -10,8 +11,10 @@ function M:peek()
ya.preview_widgets(self, {})
end
---@return nil
function M:seek() end
---@return yazi.PreloaderReturnValue
function M:preload()
local cache = ya.file_cache(self)
if not cache or fs.cha(cache) then

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local child = Command("jq")
:args({
@ -41,6 +42,7 @@ function M:peek()
end
end
---@return nil
function M:seek(units)
local h = cx.active.current.hovered
if h and h.url == self.file.url then
@ -52,6 +54,7 @@ function M:seek(units)
end
end
---@return nil
function M:fallback_to_builtin()
local _, bound = ya.preview_code(self)
if bound then

View file

@ -2,6 +2,8 @@ local SUPPORTED_TYPES = "application/audio/biosig/chemical/font/image/inode/mess
local M = {}
---@param s string
---@return string | nil
local function match_mimetype(s)
local type, sub = s:match("([-a-z]+/)([+-.a-zA-Z0-9]+)%s*$")
if type and sub and string.find(SUPPORTED_TYPES, type, 1, true) then
@ -9,6 +11,7 @@ local function match_mimetype(s)
end
end
---@return yazi.PreloaderReturnValue
function M:preload()
local urls = {}
for _, file in ipairs(self.files) do

View file

@ -4,6 +4,7 @@ function M:peek() end
function M:seek() end
---@return yazi.PreloaderReturnValue
function M:preload() return 1 end
return M

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local cache = ya.file_cache(self)
if not cache then
@ -12,6 +13,7 @@ function M:peek()
end
end
---@return nil
function M:seek(units)
local h = cx.active.current.hovered
if h and h.url == self.file.url then
@ -20,6 +22,7 @@ function M:seek(units)
end
end
---@return yazi.PreloaderReturnValue
function M:preload()
local cache = ya.file_cache(self)
if not cache or fs.cha(cache) then

View file

@ -1,3 +1,4 @@
---@return nil
local function setup(_, opts)
if opts.sync_yanked then
ps.sub_remote("yank", function(body) ya.manager_emit("update_yanked", { cut = body.cut, urls = body }) end)

View file

@ -1,5 +1,6 @@
local M = {}
---@return nil
function M:peek()
local cache = ya.file_cache(self)
if not cache then
@ -12,6 +13,7 @@ function M:peek()
end
end
---@return nil
function M:seek(units)
local h = cx.active.current.hovered
if h and h.url == self.file.url then
@ -22,6 +24,7 @@ function M:seek(units)
end
end
---@return yazi.PreloaderReturnValue
function M:preload()
local percentage = 5 + self.skip
if percentage > 95 then

View file

@ -11,6 +11,8 @@ local function fail(s, ...)
ya.notify { title = "Zoxide", content = string.format(s, ...), timeout = 5, level = "error" }
end
---@param cwd string
---@return integer
local function head(cwd)
local child = Command("zoxide"):args({ "query", "-l" }):stdout(Command.PIPED):spawn()
if not child then
@ -31,6 +33,10 @@ local function head(cwd)
return n
end
---@class yazi.ZoxideOpts
---@field update_db? boolean
---@param opts yazi.ZoxideOpts
local function setup(_, opts)
opts = opts or {}
@ -48,6 +54,7 @@ local function setup(_, opts)
end
end
---@return nil
local function entry()
local st = state()
if st.empty == true then

View file

@ -0,0 +1,13 @@
---@meta
-- This file contains some of the types used in yazi. It only exists to
-- provide these types and should not be loaded at runtime.
return
---@alias yazi.FolderType "PARENT" | "CURRENT" | "PREVIEW"
---@alias yazi.PreloaderReturnValue
---| 0 # Failure, don't continue
---| 1 # Success, don't continue
---| 2 # Failure, continue
---| 3 # Success, continue

View file

@ -1,7 +1,13 @@
table.unpack = table.unpack or unpack
---@class yazi.Ya
ya = ya or {}
---@param min number
---@param x number
---@param max number
---@return number
---@nodiscard
function ya.clamp(min, x, max)
if x < min then
return min
@ -12,8 +18,16 @@ function ya.clamp(min, x, max)
end
end
function ya.round(x) return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5) end
---@param x number
---@return number
---@nodiscard
function ya.round(x)
return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5)
end
---@param t table
---@return table
---@nodiscard
function ya.flat(t)
local r = {}
for _, v in ipairs(t) do
@ -28,8 +42,17 @@ function ya.flat(t)
return r
end
function ya.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end
---@param str string
---@return string
---@nodiscard
function ya.basename(str)
---@diagnostic disable-next-line: redundant-return-value
return string.gsub(str, "(.*[/\\])(.*)", "%2")
end
---@param size number
---@return string
---@nodiscard
function ya.readable_size(size)
local units = { "B", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q" }
local i = 1
@ -40,6 +63,8 @@ function ya.readable_size(size)
return string.format("%.1f%s", size, units[i])
end
---@param path string
---@return string
function ya.readable_path(path)
local home = os.getenv("HOME") or os.getenv("USERPROFILE")
if not home then