feat: update types to include new Yazi APIs

This commit is contained in:
sxyazi
2025-12-31 15:59:41 +08:00
parent da5b69563c
commit 398796d88f
5 changed files with 287 additions and 100 deletions

View File

@@ -8,20 +8,20 @@ local function info(content)
} }
end end
local selected_url = ya.sync(function() local selected_path = ya.sync(function()
for _, u in pairs(cx.active.selected) do for _, u in pairs(cx.active.selected) do
return u return u.cache or u
end end
end) end)
local hovered_url = ya.sync(function() local hovered_path = ya.sync(function()
local h = cx.active.current.hovered local h = cx.active.current.hovered
return h and h.url return h and (h.path or h.url) -- TODO: remove "or h.url"
end) end)
return { return {
entry = function() entry = function()
local a, b = selected_url(), hovered_url() local a, b = selected_path(), hovered_path()
if not a then if not a then
return info("No file selected") return info("No file selected")
elseif not b then elseif not b then

View File

@@ -3,7 +3,8 @@
local M = {} local M = {}
function M:peek(job) function M:peek(job)
local child, err = Command("lsar"):arg(tostring(job.file.url)):stdout(Command.PIPED):spawn() -- TODO: remove "or job.file.url"
local child, err = Command("lsar"):arg(tostring(job.file.path or job.file.url)):stdout(Command.PIPED):spawn()
if not child then if not child then
return ya.err("spawn `lsar` command failed: " .. err) return ya.err("spawn `lsar` command failed: " .. err)
end end

View File

@@ -6,6 +6,7 @@ local function fail(job, s) ya.preview_widget(job, ui.Text.parse(s):area(job.are
function M:peek(job) function M:peek(job)
local child, err = Command("sh") local child, err = Command("sh")
-- TODO: use `job.file.path` instead
:arg({ "-c", job.args[1], "sh", tostring(job.file.cache or job.file.url) }) :arg({ "-c", job.args[1], "sh", tostring(job.file.cache or job.file.url) })
:env("w", job.area.w) :env("w", job.area.w)
:env("h", job.area.h) :env("h", job.area.h)

View File

@@ -65,15 +65,21 @@ ya = ya
-- | Alias | `"black"` \| `"white"` \| `"red"` \| `"lightred"` \| `"green"` \| `"lightgreen"` \| `"yellow"` \| `"lightyellow"` \| `"blue"` \| `"lightblue"` \| `"magenta"` \| `"lightmagenta"` \| `"cyan"` \| `"lightcyan"` \| `"gray"` \| `"darkgray"` \| `"reset"` \| `string` | -- | Alias | `"black"` \| `"white"` \| `"red"` \| `"lightred"` \| `"green"` \| `"lightgreen"` \| `"yellow"` \| `"lightyellow"` \| `"blue"` \| `"lightblue"` \| `"magenta"` \| `"lightmagenta"` \| `"cyan"` \| `"lightcyan"` \| `"gray"` \| `"darkgray"` \| `"reset"` \| `string` |
---@alias AsColor "black"|"white"|"red"|"lightred"|"green"|"lightgreen"|"yellow"|"lightyellow"|"blue"|"lightblue"|"magenta"|"lightmagenta"|"cyan"|"lightcyan"|"gray"|"darkgray"|"reset"|string ---@alias AsColor "black"|"white"|"red"|"lightred"|"green"|"lightgreen"|"yellow"|"lightyellow"|"blue"|"lightblue"|"magenta"|"lightmagenta"|"cyan"|"lightcyan"|"gray"|"darkgray"|"reset"|string
-- Create a Url: -- Create a URL:
-- ```lua -- ```lua
-- -- regular file -- -- regular file
-- local url = Url("/root/Downloads/logo.png") -- local url = Url("/root/Downloads/logo.png")
-- -- `bgm.mp3` from the archive `ost.zip` -- -- `/root/dog.jpg` on `my-server` via SFTP
-- local url = Url("archive:///root/ost.zip#bgm.mp3") -- local url = Url("sftp://my-server//root/dog.jpg")
-- ``` -- ```
---@class (exact) Url ---@class (exact) Url
-- Filename of the url. -- [`Path`](#path) portion of the URL.
-- For the URL `sftp://my-server//path/to/file`, the path is `/path/to/file`.
-- | | |
-- | ---- | ------ |
-- | Type | `Path` |
---@field path Path
-- Filename of the URL.
-- | | | -- | | |
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `string?` | -- | Type | `string?` |
@@ -83,87 +89,164 @@ ya = ya
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `string?` | -- | Type | `string?` |
---@field stem string? ---@field stem string?
-- Url fragment. -- Extension of the file.
-- Let's say the url `archive:///root/my-archive.zip#1.jpg`, the fragment `1.jpg`.
-- | | | -- | | |
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `string?` | -- | Type | `string?` |
---@field frag string? ---@field ext string?
-- Parent directory. -- Parent directory.
-- | | | -- | | |
-- | ---- | ------- | -- | ---- | ------- |
-- | Type | `Self?` | -- | Type | `Self?` |
---@field parent self? ---@field parent self?
-- Whether the file represented by the url is a regular file. -- Domain of the URL.
-- For the URL `sftp://my-server//root/dog.jpg`, the domain is `my-server`.
-- | | |
-- | ---- | --------- |
-- | Type | `string?` |
---@field domain string?
-- Whether the file represented by the URL is a regular file.
-- | | | -- | | |
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `boolean` | -- | Type | `boolean` |
---@field is_regular boolean ---@field is_regular boolean
-- Whether the file represented by the url is from an archive. -- Whether the file represented by the URL is from an archive.
-- | | | -- | | |
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `boolean` | -- | Type | `boolean` |
---@field is_archive boolean ---@field is_archive boolean
-- Whether the path represented by the url has a root. -- Whether the path represented by the URL has a root.
-- | | | -- | | |
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `boolean` | -- | Type | `boolean` |
---@field has_root boolean ---@field has_root boolean
-- Join with `another` to create a new url. -- Join with `other` to create a new URL.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ------------------ | -- | ------- | ------------------ |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `Self` \| `string` | -- | `other` | `Self` \| `string` |
-- | Return | `Self` | -- | Return | `Self` |
---@field join fun(self: self, another: self|string): self ---@field join fun(self: self, other: self|string): self
-- Whether the url starts with `another`. -- Whether the URL starts with `base`.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ------------------ | -- | ------ | ------------------ |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `Self` \| `string` | -- | `base` | `Self` \| `string` |
-- | Return | `boolean` | -- | Return | `boolean` |
---@field starts_with fun(self: self, another: self|string): boolean ---@field starts_with fun(self: self, base: self|string): boolean
-- Whether the url ends with `another`. -- Whether the URL ends with `base`.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ------------------ | -- | ------ | ------------------ |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `Self` \| `string` | -- | `base` | `Self` \| `string` |
-- | Return | `boolean` | -- | Return | `boolean` |
---@field ends_with fun(self: self, another: self|string): boolean ---@field ends_with fun(self: self, base: self|string): boolean
-- Strips the prefix of `another`. -- Strips the prefix of `base`.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ------------------ | -- | ------ | ------------------ |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `Self` \| `string` | -- | `base` | `Self` \| `string` |
-- | Return | `Self` | -- | Return | `Path` |
---@field strip_prefix fun(self: self, another: self|string): self ---@field strip_prefix fun(self: self, base: self|string): Path
-- Whether the url is equal to `another`. -- Whether the URL is equal to `other`.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | --------- | -- | ------- | --------- |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `Self` | -- | `other` | `Self` |
-- | Return | `boolean` | -- | Return | `boolean` |
---@field __eq fun(self: self, another: self): boolean ---@field __eq fun(self: self, other: self): boolean
-- Convert the url to string. -- Convert the URL to string.
-- | In/Out | Type | -- | In/Out | Type |
-- | ------ | -------- | -- | ------ | -------- |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | Return | `string` | -- | Return | `string` |
---@field __tostring fun(self: self): string ---@field __tostring fun(self: self): string
-- Concatenate the url with `another`. -- Concatenate the URL with `other`.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | -------- | -- | ------- | -------- |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `string` | -- | `other` | `string` |
-- | Return | `Self` | -- | Return | `Self` |
---@field __concat fun(self: self, another: string): self ---@field __concat fun(self: self, other: string): self
-- Make a new url. -- Make a new URL.
-- | In/Out | Type | -- | In/Out | Type |
-- | ------- | ------------------ | -- | ------- | ------------------ |
-- | `value` | `string` \| `Self` | -- | `value` | `string` \| `Self` |
-- | Return | `Self` | -- | Return | `Self` |
---@overload fun(value: string|self): Url ---@overload fun(value: string|self): Url
-- `Path` is the path portion of a [`Url`](#url).
-- For the URL `sftp://my-server//path/to/file`, the path is `/path/to/file`.
---@class (exact) Path
-- Filename of the path.
-- | | |
-- | ---- | --------- |
-- | Type | `string?` |
---@field name string?
-- Filename without the extension.
-- | | |
-- | ---- | --------- |
-- | Type | `string?` |
---@field stem string?
-- Parent directory.
-- | | |
-- | ---- | ------- |
-- | Type | `Self?` |
---@field parent self?
-- Whether the path has a root.
-- | | |
-- | ---- | --------- |
-- | Type | `boolean` |
---@field has_root boolean
-- Join with `other` to create a new path.
-- | In/Out | Type |
-- | ------- | ------------------ |
-- | `self` | `Self` |
-- | `other` | `Self` \| `string` |
-- | Return | `Self` |
---@field join fun(self: self, other: self|string): self
-- Whether the path starts with `base`.
-- | In/Out | Type |
-- | ------ | ------------------ |
-- | `self` | `Self` |
-- | `base` | `Self` \| `string` |
-- | Return | `boolean` |
---@field starts_with fun(self: self, base: self|string): boolean
-- Whether the path ends with `base`.
-- | In/Out | Type |
-- | ------ | ------------------ |
-- | `self` | `Self` |
-- | `base` | `Self` \| `string` |
-- | Return | `boolean` |
---@field ends_with fun(self: self, base: self|string): boolean
-- Strips the prefix of `base`.
-- | In/Out | Type |
-- | ------ | ------------------ |
-- | `self` | `Self` |
-- | `base` | `Self` \| `string` |
-- | Return | `Self` |
---@field strip_prefix fun(self: self, base: self|string): self
-- Whether the path is equal to `other`.
-- | In/Out | Type |
-- | ------- | --------- |
-- | `self` | `Self` |
-- | `other` | `Self` |
-- | Return | `boolean` |
---@field __eq fun(self: self, other: self): boolean
-- Convert the path to string.
-- | In/Out | Type |
-- | ------ | -------- |
-- | `self` | `Self` |
-- | Return | `string` |
---@field __tostring fun(self: self): string
-- Concatenate the path with `other`.
-- | In/Out | Type |
-- | ------- | -------- |
-- | `self` | `Self` |
-- | `other` | `string` |
-- | Return | `Self` |
---@field __concat fun(self: self, other: string): self
-- One file's characteristics. -- One file's characteristics.
---@class (exact) Cha ---@class (exact) Cha
-- Whether the file is a directory. -- Whether the file is a directory.
@@ -186,7 +269,7 @@ ya = ya
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `boolean` | -- | Type | `boolean` |
---@field is_orphan boolean ---@field is_orphan boolean
-- Whether the file is dummy, which fails to load complete metadata, possibly the filesystem doesn't support it, such as FUSE. -- Whether the file is dummy, which fails to load complete metadata. It could be due to the file system not supporting it, such as FUSE.
-- | | | -- | | |
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `boolean` | -- | Type | `boolean` |
@@ -269,7 +352,7 @@ ya = ya
-- A bare file without any context information. See also [`fs::File`](/docs/plugins/context#fs-file). -- A bare file without any context information. See also [`fs::File`](/docs/plugins/context#fs-file).
---@class (exact) File ---@class (exact) File
-- Url of the file. -- URL of the file.
-- | | | -- | | |
-- | ---- | ----- | -- | ---- | ----- |
-- | Type | `Url` | -- | Type | `Url` |
@@ -279,11 +362,11 @@ ya = ya
-- | ---- | ----- | -- | ---- | ----- |
-- | Type | `Cha` | -- | Type | `Cha` |
---@field cha Cha ---@field cha Cha
-- Url of the file points to, if it's a symlink. -- Path of the file points to, if it's a symlink.
-- | | | -- | | |
-- | ---- | ------ | -- | ---- | ------- |
-- | Type | `Url?` | -- | Type | `Path?` |
---@field link_to Url? ---@field link_to Path?
-- Name of the file. -- Name of the file.
-- | | | -- | | |
-- | ---- | -------- | -- | ---- | -------- |
@@ -316,13 +399,13 @@ ya = ya
-- | `self` | `Self` | -- | `self` | `Self` |
-- | Return | `string` | -- | Return | `string` |
---@field __tostring fun(self: self): string ---@field __tostring fun(self: self): string
-- Concatenate the error with `another`. -- Concatenate the error with `other`.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | -------- | -- | ------- | -------- |
-- | `self` | `Self` | -- | `self` | `Self` |
-- | `another` | `string` | -- | `other` | `string` |
-- | Return | `Error` | -- | Return | `Error` |
---@field __concat fun(self: self, another: string): Error ---@field __concat fun(self: self, other: string): Error
-- --
---@class (exact) Window ---@class (exact) Window
@@ -622,7 +705,7 @@ ya = ya
---@field patch fun(self: self, another: self): self ---@field patch fun(self: self, another: self): self
-- Make a new style. -- Make a new style.
-- | In/Out | Type | -- | In/Out | Type |
-- | ------ | ------ | -- | ------- | ------- |
-- | Return | `Self` | -- | Return | `Self` |
---@overload fun(): ui.Style ---@overload fun(): ui.Style
@@ -1645,7 +1728,7 @@ ya = ya
-- | ---- | --------- | -- | ---- | --------- |
-- | Type | `boolean` | -- | Type | `boolean` |
---@field is_hovered boolean ---@field is_hovered boolean
-- Url of the file. -- URL of the file.
-- | | | -- | | |
-- | ---- | ----- | -- | ---- | ----- |
-- | Type | `Url` | -- | Type | `Url` |
@@ -1655,11 +1738,11 @@ ya = ya
-- | ---- | ----- | -- | ---- | ----- |
-- | Type | `Cha` | -- | Type | `Cha` |
---@field cha Cha ---@field cha Cha
-- Url of the file points to, if it's a symlink. -- Path of the file points to, if it's a symlink.
-- | | | -- | | |
-- | ---- | ------ | -- | ---- | ------- |
-- | Type | `Url?` | -- | Type | `Path?` |
---@field link_to Url? ---@field link_to Path?
-- Name of the file. -- Name of the file.
-- | | | -- | | |
-- | ---- | -------- | -- | ---- | -------- |
@@ -1954,7 +2037,7 @@ ya = ya
-- ya.file_cache { -- ya.file_cache {
-- -- File to be cached. -- -- File to be cached.
-- file = file, -- file = file,
-- -- Number of units to skip. It's units largely depend on your previewer, -- -- Number of units to skip. Its units largely depend on your previewer,
-- -- such as lines for code, and percentages for videos. -- -- such as lines for code, and percentages for videos.
-- skip = 1, -- skip = 1,
-- } -- }
@@ -2032,14 +2115,14 @@ ya = ya
-- Request user input: -- Request user input:
-- ```lua -- ```lua
-- local value, event = ya.input { -- local value, event = ya.input {
-- -- Position
-- pos = { "top-center", y = 3, w = 40 },
-- -- Title -- -- Title
-- title = "Archive name:", -- title = "Archive name:",
-- -- Default value -- -- Default value
-- value = "", -- value = "",
-- -- Whether to obscure the input. -- -- Whether to obscure the input.
-- obscure = false, -- obscure = false,
-- -- Position
-- position = { "top-center", y = 3, w = 40 },
-- -- Whether to report user input in real time. -- -- Whether to report user input in real time.
-- realtime = false, -- realtime = false,
-- -- Number of seconds to wait for the user to stop typing, available if `realtime = true`. -- -- Number of seconds to wait for the user to stop typing, available if `realtime = true`.
@@ -2056,8 +2139,8 @@ ya = ya
-- When `realtime = true` specified, `ya.input()` returns a receiver, which has a `recv()` method that can be called multiple times to receive events: -- When `realtime = true` specified, `ya.input()` returns a receiver, which has a `recv()` method that can be called multiple times to receive events:
-- ```lua -- ```lua
-- local input = ya.input { -- local input = ya.input {
-- pos = { "center", w = 50 },
-- title = "Input in realtime:", -- title = "Input in realtime:",
-- position = { "center", w = 50 },
-- realtime = true, -- realtime = true,
-- } -- }
-- while true do -- while true do
@@ -2069,11 +2152,11 @@ ya = ya
-- end -- end
-- ``` -- ```
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | -------------------------------------------------------------------------------------------------------------- | -- | --------- | --------------------------------------------------------------------------------------------------------- |
-- | `opts` | `{ title: string, value: string?, obscure: boolean?, position: AsPos, realtime: boolean?, debounce: number? }` | -- | `opts` | `{ pos: AsPos, title: string, value: string?, obscure: boolean?, realtime: boolean?, debounce: number? }` |
-- | Return | `(string?, integer)` \| `Recv` | -- | Return | `(string?, integer)` \| `Recv` |
-- | Available | Async context only | -- | Available | Async context only |
---@field input fun(opts: { title: string, value: string?, obscure: boolean?, position: AsPos, realtime: boolean?, debounce: number? }): (string?, integer)|Recv ---@field input fun(opts: { pos: AsPos, title: string, value: string?, obscure: boolean?, realtime: boolean?, debounce: number? }): (string?, integer)|Recv
-- Send a foreground notification to the user: -- Send a foreground notification to the user:
-- ```lua -- ```lua
-- ya.notify { -- ya.notify {
@@ -2181,12 +2264,35 @@ ya = ya
-- | Return | `unknown` | -- | Return | `unknown` |
-- | Available | Async context only | -- | Available | Async context only |
---@field preview_widget fun(opts: { area: ui.Rect, file: File, mime: string, skip: integer }, widget: Renderable|Renderable[]): unknown ---@field preview_widget fun(opts: { area: ui.Rect, file: File, mime: string, skip: integer }, widget: Renderable|Renderable[]): unknown
-- Make a function synchronous.
-- See [Async context](/docs/plugins/overview#async-context). -- See [Async context](/docs/plugins/overview#async-context).
-- | In/Out | Type | -- | In/Out | Type |
-- | ------ | -------------------- | -- | ------ | -------------------- |
-- | `fn` | `fun(...: any): any` | -- | `fn` | `fun(...: any): any` |
-- | Return | `fun(...: any): any` | -- | Return | `fun(...: any): any` |
---@field sync fun(fn: fun(...: any): any): fun(...: any): any ---@field sync fun(fn: fun(...: any): any): fun(...: any): any
-- :::warning
-- This API is highly experimental at the moment, and its behavior may change in the future.
-- :::
-- Run a function asynchronously on the main thread.
-- `fn` should contain only async I/O operations, i.g., calls to other async APIs, and should not include any sync I/O, or blocking tasks, such as Lua's `io.open()`, `os.system()`.
-- `fn` runs in an asynchronous context but can access any [Sendable values](/docs/plugins/overview#sendable) from the outer synchronous context, for example:
-- ```lua
-- --- @sync entry
-- local function entry()
-- local cwd = cx.active.current.cwd
-- ya.async(function ()
-- ya.dbg(cwd) -- `cwd` is a Url, which is sendable
-- end)
-- end
-- return { entry }
-- ```
-- See [Async context](/docs/plugins/overview#async-context).
-- | In/Out | Type |
-- | ------ | -------------------- |
-- | `fn` | `fun(...: any): any` |
-- | Return | `any` |
---@field async fun(fn: fun(...: any): any): any
-- Returns a string describing the specific operating system in use. -- Returns a string describing the specific operating system in use.
-- | In/Out | Type | -- | In/Out | Type |
-- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -2385,7 +2491,7 @@ ya = ya
-- local url, err = fs.cwd() -- local url, err = fs.cwd()
-- ``` -- ```
-- You probably will never need it, and more likely, you'll need [`cx.active.current.cwd`][folder-cwd], which is the current directory where the user is working. -- You probably will never need it, and more likely, you'll need [`cx.active.current.cwd`][folder-cwd], which is the current directory where the user is working.
-- Specifically, when the user changes the directory, `cx.active.current.cwd` gets updated immediately, while synchronizing this update with the filesystem via `chdir` involves I/O operations, such as checking if the directory is valid. -- Specifically, when the user changes the directory, `cx.active.current.cwd` gets updated immediately, while synchronizing this update with the file system via `chdir` involves I/O operations, such as checking if the directory is valid.
-- So, there may be some delay, which is particularly noticeable on slow devices. For example, when an HDD wakes up from sleep, it typically takes 3~4 seconds. -- So, there may be some delay, which is particularly noticeable on slow devices. For example, when an HDD wakes up from sleep, it typically takes 3~4 seconds.
-- It is useful if you just need a valid directory as the CWD of a process to start some work that doesn't depend on the CWD. -- It is useful if you just need a valid directory as the CWD of a process to start some work that doesn't depend on the CWD.
-- | In/Out | Type | -- | In/Out | Type |
@@ -2396,13 +2502,16 @@ ya = ya
-- [chdir]: https://man7.org/linux/man-pages/man2/chdir.2.html -- [chdir]: https://man7.org/linux/man-pages/man2/chdir.2.html
-- [folder-cwd]: /docs/plugins/context#tab-folder.cwd -- [folder-cwd]: /docs/plugins/context#tab-folder.cwd
---@field cwd fun(): Url?, Error? ---@field cwd fun(): Url?, Error?
-- Get the [Cha](/docs/plugins/types#cha) of the specified `url`: -- Get the [Cha][cha] of the specified `url`:
-- ```lua -- ```lua
-- -- Not following symbolic links -- -- Not following symbolic links
-- local cha, err = fs.cha(url) -- local cha, err = fs.cha(url)
-- -- Follow symbolic links -- -- Follow symbolic links
-- local cha, err = fs.cha(url, true) -- local cha, err = fs.cha(url, true)
-- ``` -- ```
-- Returns `(cha, err)`:
-- - `cha`: The [Cha][cha] of the specified `url` if the operation succeeds.
-- - `err`: [`Error`][error] of the failure.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ------------------ | -- | --------- | ------------------ |
-- | `url` | `Url` | -- | `url` | `Url` |
@@ -2428,6 +2537,9 @@ ya = ya
-- Where `type` can be one of the following: -- Where `type` can be one of the following:
-- - `"dir"`: Creates a new, empty directory. -- - `"dir"`: Creates a new, empty directory.
-- - `"dir_all"`: Recursively create a directory and all of its parents if they are missing. -- - `"dir_all"`: Recursively create a directory and all of its parents if they are missing.
-- Returns `(ok, err)`:
-- - `ok`: Whether the operation succeeds, which is a `boolean`.
-- - `err`: [`Error`][error] of the failure.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ---------------------------------- | -- | --------- | ---------------------------------- |
-- | `type` | `string` \| `"dir"` \| `"dir_all"` | -- | `type` | `string` \| `"dir"` \| `"dir_all"` |
@@ -2440,10 +2552,13 @@ ya = ya
-- local ok, err = fs.remove("file", Url("/tmp/test.txt")) -- local ok, err = fs.remove("file", Url("/tmp/test.txt"))
-- ``` -- ```
-- Where `type` can be one of the following: -- Where `type` can be one of the following:
-- - `"file"`: Removes a file from the filesystem. -- - `"file"`: Removes a file from the file system.
-- - `"dir"`: Removes an existing, empty directory. -- - `"dir"`: Removes an existing, empty directory.
-- - `"dir_all"`: Removes a directory at this url, after removing all its contents. Use carefully! -- - `"dir_all"`: Removes a directory at this url, after removing all its contents. Use carefully!
-- - `"dir_clean"`: Remove all empty directories under it, and if the directory itself is empty afterward, remove it as well. -- - `"dir_clean"`: Remove all empty directories under it, and if the directory itself is empty afterward, remove it as well.
-- Returns `(ok, err)`:
-- - `ok`: Whether the operation succeeds, which is a `boolean`.
-- - `err`: [`Error`][error] of the failure.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | --------------------------------------------------------------- | -- | --------- | --------------------------------------------------------------- |
-- | `type` | `string` \| `"file"` \| `"dir"` \| `"dir_all"` \| `"dir_clean"` | -- | `type` | `string` \| `"file"` \| `"dir"` \| `"dir_all"` \| `"dir_clean"` |
@@ -2469,11 +2584,61 @@ ya = ya
-- | Return | `File[]?, Error?` | -- | Return | `File[]?, Error?` |
-- | Available | Async context only | -- | Available | Async context only |
---@field read_dir fun(url: Url, options: { glob: string?, limit: integer?, resolve: boolean? }): File[]?, Error? ---@field read_dir fun(url: Url, options: { glob: string?, limit: integer?, resolve: boolean? }): File[]?, Error?
-- Get a unique name from the given `url` to ensure it's unique in the filesystem: -- Copy a file from the source `from`, to the destination `to`:
-- ```lua
-- local len, err = fs.copy(Url("/tmp/src.txt"), Url("/tmp/dest.txt"))
-- ```
-- Returns `(len, err)`:
-- - `len`: Length of the copied content, which is an `integer`, or `nil` if the operation fails.
-- - `err`: [`Error`][error] of the failure.
-- Note that:
-- - This function will overwrite the destination file.
-- - If `from` and `to` are the same file, the file will likely be truncated by this function.
-- - This function follows symlinks for both `from` and `to`.
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `from` | `Url` |
-- | `to` | `Url` |
-- | Return | `integer?, Error?` |
-- | Available | Async context only |
---@field copy fun(from: Url, to: Url): integer?, Error?
-- Rename a file from the source `from`, to the destination `to`.
-- ```lua
-- local ok, err = fs.rename(Url("/tmp/old.txt"), Url("/tmp/new.txt"))
-- ```
-- Returns `(ok, err)`:
-- - `ok`: Whether the operation succeeds, which is a `boolean`.
-- - `err`: [`Error`][error] of the failure.
-- Note that:
-- - This function will overwrite the destination file.
-- - This function does not work if `from` and `to` are on different file systems.
-- To move files across file systems, use a combination of [`fs.copy()`](#fs.copy) and [`fs.remove()`](#fs.remove):
-- ```lua
-- local from = Url("/mnt/dev1/a")
-- local to = Url("/mnt/dev2/b")
-- local ok, err = fs.rename(from, to)
-- if not ok and err.kind == "CrossesDevices" then
-- local len, err = fs.copy(from, to)
-- if len and not err then
-- fs.remove("file", from)
-- end
-- end
-- ```
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `from` | `Url` |
-- | `to` | `Url` |
-- | Return | `integer?, Error?` |
-- | Available | Async context only |
---@field rename fun(from: Url, to: Url): integer?, Error?
-- Get a unique name from the given `url` to ensure it's unique in the file system:
-- ```lua -- ```lua
-- local url, err = fs.unique_name(Url("/tmp/test.txt")) -- local url, err = fs.unique_name(Url("/tmp/test.txt"))
-- ``` -- ```
-- If the file already exists, it will append `_n` to the filename, where `n` is a number, and keep incrementing until the first available name is found. -- If the file already exists, it will append `_n` to the filename, where `n` is a number, and keep incrementing until the first available name is found.
-- Returns `(url, err)`:
-- - `url`: The [`Url`][url] with the unique filename.
-- - `err`: [`Error`][error] of the failure.
-- | In/Out | Type | -- | In/Out | Type |
-- | --------- | ------------------ | -- | --------- | ------------------ |
-- | `url` | `Url` | -- | `url` | `Url` |
@@ -2484,13 +2649,28 @@ ya = ya
-- You can invoke external programs through: -- You can invoke external programs through:
-- ```lua -- ```lua
-- local child, err = Command("ls") -- local child, err = Command("ls")
-- :args({ "-a", "-l" }) -- :arg { "-a", "-l" }
-- :stdout(Command.PIPED) -- :stdout(Command.PIPED)
-- :spawn() -- :spawn()
-- ``` -- ```
-- Compared to Lua's `os.execute`, it provides many comprehensive and convenient methods, and the entire process is async. -- Compared to Lua's `os.execute`, it provides many comprehensive and convenient methods, and the entire process is async.
-- It takes better advantage of the benefits of concurrent scheduling. However, it can only be used in async contexts, such as preloaders, previewers, and async functional plugins. -- It takes better advantage of the benefits of concurrent scheduling. However, it can only be used in async contexts, such as preloaders, previewers, and async functional plugins.
---@class (exact) Command ---@class (exact) Command
-- A `Stdio` indicating that the stream will be ignored, which is the equivalent of attaching the stream to `/dev/null`.
-- | | |
-- | ---- | ------- |
-- | Type | `Stdio` |
---@field NULL Stdio
-- A `Stdio` indicating that a new pipe should be arranged to connect the parent and child processes.
-- | | |
-- | ---- | ------- |
-- | Type | `Stdio` |
---@field PIPED Stdio
-- A `Stdio` indicating that the child inherits from the corresponding parent descriptor.
-- | | |
-- | ---- | ------- |
-- | Type | `Stdio` |
---@field INHERIT Stdio
-- Append one or more arguments to the command: -- Append one or more arguments to the command:
-- ```lua -- ```lua
-- local cmd = Command("ls"):arg("-a"):arg("-l") -- local cmd = Command("ls"):arg("-a"):arg("-l")
@@ -2575,10 +2755,11 @@ ya = ya
-- | `self` | `Self` | -- | `self` | `Self` |
-- | Return | `Child?, Error?` | -- | Return | `Child?, Error?` |
---@field spawn fun(self: self): Child?, Error? ---@field spawn fun(self: self): Child?, Error?
-- Spawn the command and wait for it to finish: -- Executes the command as a child process, waiting for it to finish and collecting all of its output:
-- ```lua -- ```lua
-- local output, err = Command("ls"):output() -- local output, err = Command("ls"):output()
-- ``` -- ```
-- This method sets both stdout and stderr to `Command.PIPED` and closes the stdin stream.
-- | In/Out | Type | -- | In/Out | Type |
-- | ------ | ----------------- | -- | ------ | ----------------- |
-- | `self` | `Self` | -- | `self` | `Self` |
@@ -2588,6 +2769,7 @@ ya = ya
-- ```lua -- ```lua
-- local status, err = Command("ls"):status() -- local status, err = Command("ls"):status()
-- ``` -- ```
-- This method closes the stdin, stdout, and stderr streams if they were set to `Command.PIPED`.
-- | In/Out | Type | -- | In/Out | Type |
-- | ------ | ----------------- | -- | ------ | ----------------- |
-- | `self` | `Self` | -- | `self` | `Self` |
@@ -2755,6 +2937,9 @@ ya = ya
-- <!-- Links --> -- <!-- Links -->
-- [sendable]: /docs/plugins/overview#sendable -- [sendable]: /docs/plugins/overview#sendable
-- [ownership]: /docs/plugins/overview#ownership -- [ownership]: /docs/plugins/overview#ownership
-- [url]: /docs/plugins/types#url
-- [cha]: /docs/plugins/types#cha
-- [error]: /docs/plugins/types#error
---@field code integer? ---@field code integer?

View File

@@ -79,7 +79,7 @@ local function peek(_, job)
local tmp = os.tmpname() local tmp = os.tmpname()
-- stylua: ignore -- stylua: ignore
local status, err = Command("magick"):arg { local status, err = Command("magick"):arg {
tostring(url), tostring(job.file.path or url), -- TODO: remove `or url`
"-auto-orient", "-strip", "-auto-orient", "-strip",
"-sample", string.format("%dx%d", new_w, new_h), "-sample", string.format("%dx%d", new_w, new_h),
"-quality", rt.preview.image_quality, "-quality", rt.preview.image_quality,