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
local selected_url = ya.sync(function()
local selected_path = ya.sync(function()
for _, u in pairs(cx.active.selected) do
return u
return u.cache or u
end
end)
local hovered_url = ya.sync(function()
local hovered_path = ya.sync(function()
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)
return {
entry = function()
local a, b = selected_url(), hovered_url()
local a, b = selected_path(), hovered_path()
if not a then
return info("No file selected")
elseif not b then

View File

@@ -3,7 +3,8 @@
local M = {}
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
return ya.err("spawn `lsar` command failed: " .. err)
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)
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) })
:env("w", job.area.w)
: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 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
-- -- regular file
-- local url = Url("/root/Downloads/logo.png")
-- -- `bgm.mp3` from the archive `ost.zip`
-- local url = Url("archive:///root/ost.zip#bgm.mp3")
-- -- `/root/dog.jpg` on `my-server` via SFTP
-- local url = Url("sftp://my-server//root/dog.jpg")
-- ```
---@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?` |
@@ -83,87 +89,164 @@ ya = ya
-- | ---- | --------- |
-- | Type | `string?` |
---@field stem string?
-- Url fragment.
-- Let's say the url `archive:///root/my-archive.zip#1.jpg`, the fragment `1.jpg`.
-- Extension of the file.
-- | | |
-- | ---- | --------- |
-- | Type | `string?` |
---@field frag string?
---@field ext string?
-- Parent directory.
-- | | |
-- | ---- | ------- |
-- | Type | `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` |
---@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` |
---@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` |
---@field has_root boolean
-- Join with `another` to create a new url.
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `self` | `Self` |
-- | `another` | `Self` \| `string` |
-- | Return | `Self` |
---@field join fun(self: self, another: self|string): self
-- Whether the url starts with `another`.
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `self` | `Self` |
-- | `another` | `Self` \| `string` |
-- | Return | `boolean` |
---@field starts_with fun(self: self, another: self|string): boolean
-- Whether the url ends with `another`.
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `self` | `Self` |
-- | `another` | `Self` \| `string` |
-- | Return | `boolean` |
---@field ends_with fun(self: self, another: self|string): boolean
-- Strips the prefix of `another`.
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `self` | `Self` |
-- | `another` | `Self` \| `string` |
-- | Return | `Self` |
---@field strip_prefix fun(self: self, another: self|string): self
-- Whether the url is equal to `another`.
-- | In/Out | Type |
-- | --------- | --------- |
-- | `self` | `Self` |
-- | `another` | `Self` |
-- | Return | `boolean` |
---@field __eq fun(self: self, another: self): boolean
-- Convert the url to string.
-- Join with `other` to create a new URL.
-- | In/Out | Type |
-- | ------- | ------------------ |
-- | `self` | `Self` |
-- | `other` | `Self` \| `string` |
-- | Return | `Self` |
---@field join fun(self: self, other: self|string): self
-- Whether the URL 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 URL 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 | `Path` |
---@field strip_prefix fun(self: self, base: self|string): Path
-- Whether the URL is equal to `other`.
-- | In/Out | Type |
-- | ------- | --------- |
-- | `self` | `Self` |
-- | `other` | `Self` |
-- | Return | `boolean` |
---@field __eq fun(self: self, other: self): boolean
-- Convert the URL to string.
-- | In/Out | Type |
-- | ------ | -------- |
-- | `self` | `Self` |
-- | Return | `string` |
---@field __tostring fun(self: self): string
-- Concatenate the url with `another`.
-- | In/Out | Type |
-- | --------- | -------- |
-- | `self` | `Self` |
-- | `another` | `string` |
-- | Return | `Self` |
---@field __concat fun(self: self, another: string): self
-- Make a new url.
-- Concatenate the URL with `other`.
-- | In/Out | Type |
-- | ------- | -------- |
-- | `self` | `Self` |
-- | `other` | `string` |
-- | Return | `Self` |
---@field __concat fun(self: self, other: string): self
-- Make a new URL.
-- | In/Out | Type |
-- | ------- | ------------------ |
-- | `value` | `string` \| `Self` |
-- | Return | `Self` |
---@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.
---@class (exact) Cha
-- Whether the file is a directory.
@@ -186,7 +269,7 @@ ya = ya
-- | ---- | --------- |
-- | Type | `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` |
@@ -269,7 +352,7 @@ ya = ya
-- A bare file without any context information. See also [`fs::File`](/docs/plugins/context#fs-file).
---@class (exact) File
-- Url of the file.
-- URL of the file.
-- | | |
-- | ---- | ----- |
-- | Type | `Url` |
@@ -279,11 +362,11 @@ ya = ya
-- | ---- | ----- |
-- | Type | `Cha` |
---@field cha Cha
-- Url of the file points to, if it's a symlink.
-- | | |
-- | ---- | ------ |
-- | Type | `Url?` |
---@field link_to Url?
-- Path of the file points to, if it's a symlink.
-- | | |
-- | ---- | ------- |
-- | Type | `Path?` |
---@field link_to Path?
-- Name of the file.
-- | | |
-- | ---- | -------- |
@@ -316,13 +399,13 @@ ya = ya
-- | `self` | `Self` |
-- | Return | `string` |
---@field __tostring fun(self: self): string
-- Concatenate the error with `another`.
-- | In/Out | Type |
-- | --------- | -------- |
-- | `self` | `Self` |
-- | `another` | `string` |
-- | Return | `Error` |
---@field __concat fun(self: self, another: string): Error
-- Concatenate the error with `other`.
-- | In/Out | Type |
-- | ------- | -------- |
-- | `self` | `Self` |
-- | `other` | `string` |
-- | Return | `Error` |
---@field __concat fun(self: self, other: string): Error
--
---@class (exact) Window
@@ -621,9 +704,9 @@ ya = ya
-- | Private | This method can't be inherited. |
---@field patch fun(self: self, another: self): self
-- Make a new style.
-- | In/Out | Type |
-- | ------ | ------ |
-- | Return | `Self` |
-- | In/Out | Type |
-- | ------- | ------- |
-- | Return | `Self` |
---@overload fun(): ui.Style
-- `ui.Span` is the smallest unit of text, yet a component of `ui.Line`. Create a span:
@@ -1645,7 +1728,7 @@ ya = ya
-- | ---- | --------- |
-- | Type | `boolean` |
---@field is_hovered boolean
-- Url of the file.
-- URL of the file.
-- | | |
-- | ---- | ----- |
-- | Type | `Url` |
@@ -1655,11 +1738,11 @@ ya = ya
-- | ---- | ----- |
-- | Type | `Cha` |
---@field cha Cha
-- Url of the file points to, if it's a symlink.
-- | | |
-- | ---- | ------ |
-- | Type | `Url?` |
---@field link_to Url?
-- Path of the file points to, if it's a symlink.
-- | | |
-- | ---- | ------- |
-- | Type | `Path?` |
---@field link_to Path?
-- Name of the file.
-- | | |
-- | ---- | -------- |
@@ -1954,7 +2037,7 @@ ya = ya
-- ya.file_cache {
-- -- File to be cached.
-- 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.
-- skip = 1,
-- }
@@ -2032,14 +2115,14 @@ ya = ya
-- Request user input:
-- ```lua
-- local value, event = ya.input {
-- -- Position
-- pos = { "top-center", y = 3, w = 40 },
-- -- Title
-- title = "Archive name:",
-- -- Default value
-- value = "",
-- -- Whether to obscure the input.
-- obscure = false,
-- -- Position
-- position = { "top-center", y = 3, w = 40 },
-- -- Whether to report user input in real time.
-- realtime = false,
-- -- 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:
-- ```lua
-- local input = ya.input {
-- pos = { "center", w = 50 },
-- title = "Input in realtime:",
-- position = { "center", w = 50 },
-- realtime = true,
-- }
-- while true do
@@ -2068,12 +2151,12 @@ ya = ya
-- ya.dbg(value)
-- end
-- ```
-- | In/Out | Type |
-- | --------- | -------------------------------------------------------------------------------------------------------------- |
-- | `opts` | `{ title: string, value: string?, obscure: boolean?, position: AsPos, realtime: boolean?, debounce: number? }` |
-- | Return | `(string?, integer)` \| `Recv` |
-- | Available | Async context only |
---@field input fun(opts: { title: string, value: string?, obscure: boolean?, position: AsPos, realtime: boolean?, debounce: number? }): (string?, integer)|Recv
-- | In/Out | Type |
-- | --------- | --------------------------------------------------------------------------------------------------------- |
-- | `opts` | `{ pos: AsPos, title: string, value: string?, obscure: boolean?, realtime: boolean?, debounce: number? }` |
-- | Return | `(string?, integer)` \| `Recv` |
-- | Available | Async context only |
---@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:
-- ```lua
-- ya.notify {
@@ -2181,12 +2264,35 @@ ya = ya
-- | Return | `unknown` |
-- | Available | Async context only |
---@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).
-- | In/Out | Type |
-- | ------ | -------------------- |
-- | `fn` | `fun(...: any): any` |
-- | Return | `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.
-- | In/Out | Type |
-- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -2385,7 +2491,7 @@ ya = ya
-- 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.
-- 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.
-- 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 |
@@ -2396,13 +2502,16 @@ ya = ya
-- [chdir]: https://man7.org/linux/man-pages/man2/chdir.2.html
-- [folder-cwd]: /docs/plugins/context#tab-folder.cwd
---@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
-- -- Not following symbolic links
-- local cha, err = fs.cha(url)
-- -- Follow symbolic links
-- 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 |
-- | --------- | ------------------ |
-- | `url` | `Url` |
@@ -2428,6 +2537,9 @@ ya = ya
-- Where `type` can be one of the following:
-- - `"dir"`: Creates a new, empty directory.
-- - `"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 |
-- | --------- | ---------------------------------- |
-- | `type` | `string` \| `"dir"` \| `"dir_all"` |
@@ -2440,10 +2552,13 @@ ya = ya
-- local ok, err = fs.remove("file", Url("/tmp/test.txt"))
-- ```
-- 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_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.
-- Returns `(ok, err)`:
-- - `ok`: Whether the operation succeeds, which is a `boolean`.
-- - `err`: [`Error`][error] of the failure.
-- | In/Out | Type |
-- | --------- | --------------------------------------------------------------- |
-- | `type` | `string` \| `"file"` \| `"dir"` \| `"dir_all"` \| `"dir_clean"` |
@@ -2469,11 +2584,61 @@ ya = ya
-- | Return | `File[]?, Error?` |
-- | Available | Async context only |
---@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
-- 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.
-- Returns `(url, err)`:
-- - `url`: The [`Url`][url] with the unique filename.
-- - `err`: [`Error`][error] of the failure.
-- | In/Out | Type |
-- | --------- | ------------------ |
-- | `url` | `Url` |
@@ -2484,13 +2649,28 @@ ya = ya
-- You can invoke external programs through:
-- ```lua
-- local child, err = Command("ls")
-- :args({ "-a", "-l" })
-- :arg { "-a", "-l" }
-- :stdout(Command.PIPED)
-- :spawn()
-- ```
-- 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.
---@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:
-- ```lua
-- local cmd = Command("ls"):arg("-a"):arg("-l")
@@ -2575,10 +2755,11 @@ ya = ya
-- | `self` | `Self` |
-- | Return | `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
-- local output, err = Command("ls"):output()
-- ```
-- This method sets both stdout and stderr to `Command.PIPED` and closes the stdin stream.
-- | In/Out | Type |
-- | ------ | ----------------- |
-- | `self` | `Self` |
@@ -2588,6 +2769,7 @@ ya = ya
-- ```lua
-- 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 |
-- | ------ | ----------------- |
-- | `self` | `Self` |
@@ -2755,6 +2937,9 @@ ya = ya
-- <!-- Links -->
-- [sendable]: /docs/plugins/overview#sendable
-- [ownership]: /docs/plugins/overview#ownership
-- [url]: /docs/plugins/types#url
-- [cha]: /docs/plugins/types#cha
-- [error]: /docs/plugins/types#error
---@field code integer?

View File

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