### Async File Reading (coop.uv.fs_open, fs_read, fs_close) Source: https://context7.com/gregorias/coop.nvim/llms.txt Provides asynchronous versions of libuv file operations for non-blocking file I/O. This example demonstrates opening a file, getting its stats to determine its size, reading the content, and then closing the file descriptor. ```lua local coop = require("coop") local uv = require("coop.uv") coop.spawn(function() -- Open file local err_open, fd = uv.fs_open("/etc/hosts", "r", 438) if err_open then print("Error opening:", fd) return end -- Get file stats for size local err_stat, stat = uv.fs_fstat(fd) if err_stat then uv.fs_close(fd) print("Error getting stats:", stat) return end -- Read entire file local err_read, content = uv.fs_read(fd, stat.size, 0) uv.fs_close(fd) if not err_read then print("File size:", stat.size) print("Content preview:", content:sub(1, 100)) end end):await(5000, 10) ``` -------------------------------- ### Install coop.nvim with Lazy Package Manager Source: https://github.com/gregorias/coop.nvim/blob/main/README.md This code snippet demonstrates how to install the coop.nvim plugin using the Lazy package manager in Neovim. It's a simple configuration entry. ```lua { "gregorias/coop.nvim", } ``` -------------------------------- ### Launch Subprocesses with subprocess.spawn Source: https://context7.com/gregorias/coop.nvim/llms.txt Spawns subprocesses asynchronously with I/O redirection for stdin, stdout, and stderr using coop.subprocess.spawn. This example shows simple command execution and piping between processes. Requires 'coop' and 'coop.subprocess'. ```lua local coop = require("coop") local subprocess = require("coop.subprocess") coop.spawn(function() -- Simple command execution local echo = subprocess.spawn("echo", { args = { "Hello from subprocess!" }, stdio = { nil, subprocess.STREAM, nil }, }) local output = echo.stdout:read_until_eof() echo:await() -- Wait for process to finish print("Output:", output) -- "Hello from subprocess!\n" -- Piping between processes local printf_proc = subprocess.spawn("printf", { args = { "Line1\nLine2\nLine3" }, stdio = { nil, subprocess.PIPE }, }) local grep_proc = subprocess.spawn("grep", { args = { "Line2" }, stdio = { printf_proc.stdout, subprocess.STREAM }, }) local filtered = grep_proc.stdout:read_until_eof() printf_proc:await() grep_proc:await() print("Filtered:", filtered) -- "Line2\n" end):await(5000, 10) ``` -------------------------------- ### Stream Example using uv-utils in Lua Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Demonstrates how to use StreamReader and StreamWriter from coop.uv-utils to wrap Libuv streams and handle asynchronous data transfer. It shows writing data, closing the writer, reading until EOF, and closing the reader. ```lua local coop = require("coop") local StreamReader = require('coop.uv-utils').StreamReader local StreamWriter = require('coop.uv-utils').StreamWriter local fds = vim.uv.pipe({ nonblock = true }, { nonblock = true }) local sr = StreamReader.from_fd(fds.read) local sw = StreamWriter.from_fd(fds.write) local result = coop.spawn(function() sw:write("Hello, world!") sw:close() local data = sr:read_until_eof() sr:close() return data end).await(5000, 1) assert(result == "Hello, world!") ``` -------------------------------- ### Manual Task Control with coop.task Source: https://context7.com/gregorias/coop.nvim/llms.txt Illustrates manual control over task execution using `task.create` and `task.resume`. This allows creating a task without starting it immediately and then resuming its execution with specific arguments. ```lua local task = require("coop.task") local sleep = require("coop.uv-utils").sleep -- Create a task without starting it local my_task = task.create(function(initial_value) print("Started with:", initial_value) sleep(100) return "completed" end) -- Check task status print(task.status(my_task)) -- "suspended" -- Manually resume the task with arguments local success, result = task.resume(my_task, "hello world") print(success) -- true -- The task runs until it yields or completes print(task.status(my_task)) -- "suspended" or "dead" ``` -------------------------------- ### Async Stream I/O with StreamReader / StreamWriter Source: https://context7.com/gregorias/coop.nvim/llms.txt Provides asynchronous stream reading and writing capabilities using StreamReader and StreamWriter from coop.uv-utils. This example demonstrates creating a pipe, writing data, and reading it back. Requires 'coop' and 'coop.uv-utils'. ```lua local coop = require("coop") local StreamReader = require("coop.uv-utils").StreamReader local StreamWriter = require("coop.uv-utils").StreamWriter coop.spawn(function() -- Create a pipe pair local fds = vim.uv.pipe({ nonblock = true }, { nonblock = true }) local reader = StreamReader.from_fd(fds.read) local writer = StreamWriter.from_fd(fds.write) -- Write data writer:write("Hello, Coop streams!") writer:close() -- Read all data local data = reader:read_until_eof() reader:close() print("Received:", data) -- "Hello, Coop streams!" end):await(5000, 10) ``` -------------------------------- ### Install Lefthook for coop.nvim Source: https://github.com/gregorias/coop.nvim/blob/main/DEV.md Installs the Lefthook tool, a pre-commit framework, which is a required dependency for the coop.nvim development environment. This command ensures that code changes adhere to project standards before committing. ```shell lefthook install ``` -------------------------------- ### Spawn and Manage Subprocesses with coop.subprocess Source: https://github.com/gregorias/coop.nvim/blob/main/README.md The `coop.subprocess` module allows for launching external processes and managing their input/output streams asynchronously using task functions. The example shows how to spawn a `printf` process, pipe its output to a `cat` process, and then read the final output, demonstrating inter-process communication and asynchronous waiting. ```lua local coop = require("coop") local subprocess = require("coop.subprocess") --@async function pass_printf_to_cat() local printf = subprocess.spawn("printf", { args = { "Hello, world!" }, stdio = { nil, subprocess.PIPE }, }) local cat = subprocess.spawn("cat", { stdio = { printf.stdout, subprocess.STREAM }, }) vim.print(cat.stdout:read_until_eof()) printf:await() cat:await() end coop.spawn(pass_printf_to_cat) ``` -------------------------------- ### Concurrent File Reading with Coop.nvim Source: https://github.com/gregorias/coop.nvim/blob/main/README.md This example shows how to concurrently read two files ('foo.txt' and 'bar.txt') using Coop.nvim. It defines an asynchronous readFileAsync function using uv.fs_* operations and then spawns two tasks to read the files concurrently, awaiting their results within a 1-second timeout. ```lua local coop = require("coop") local uv = require("coop.uv") --- -- Reads a file. --- --@async --@param path string --@return string function readFileAsync(path) local err_open, fd = uv.fs_open(path, "r", 438) assert(err_open == nil) local err_fstat, stat = uv.fs_fstat(fd) assert(err_fstat == nil) local err_read, data = uv.fs_read(fd, stat.size, 0) assert(err_read == nil) local err_close = uv.fs_close(fd) assert(err_close == nil) return data end --- -- Read `foo.txt` and `bar.txt` concurrently. local foo_task = coop.spawn(readFileAsync, "foo.txt") local bar_task = coop.spawn(readFileAsync, "bar.txt") --- -- Wait 1s for both tasks to finish and print their results. print(foo_task:await(1000), bar_task:await(1000)) ``` -------------------------------- ### MPSC Queue for Concurrent Data Handling in Lua Source: https://github.com/gregorias/coop.nvim/blob/main/README.md The `coop.mpsc-queue` module implements a multiple-producer, single-consumer concurrent queue. It provides an asynchronous `pop` method, suitable for scenarios where multiple asynchronous producers need to feed data to a single consumer. The example demonstrates setting up a queue, spawning producer and consumer tasks, and handling data flow. ```lua local MpscQueue = require('coop.mpsc-queue').MpscQueue local q = MpscQueue.new() -- Asynchronously print whatever is provided to q. coop.spawn(function() while true do vim.print("Read: " .. q:pop()) end end) -- Start two threads that will asynchronously get strings from two sources. coop.spawn(function() while true do q:push(read_string_from_user()) end end) coop.spawn(function() while true do q:push(read_string_from_something_else()) end end) ``` -------------------------------- ### Spawn and Run Tasks with Coop.nvim Source: https://context7.com/gregorias/coop.nvim/llms.txt Demonstrates how to use `coop.spawn` to create and immediately run asynchronous tasks. It shows spawning a task to read a file, awaiting its result with a timeout, and spawning multiple tasks that run concurrently. ```lua local coop = require("coop") local uv = require("coop.uv") -- Spawn a task that reads a file asynchronously local read_task = coop.spawn(function() local err_open, fd = uv.fs_open("config.json", "r", 438) assert(err_open == nil, "Failed to open file") local err_fstat, stat = uv.fs_fstat(fd) assert(err_fstat == nil) local err_read, data = uv.fs_read(fd, stat.size, 0) assert(err_read == nil) uv.fs_close(fd) return data end) -- Wait for task to complete with timeout (5 seconds, poll every 100ms) local content = read_task:await(5000, 100) print("File content:", content) -- Spawn multiple tasks that run in parallel local task_a = coop.spawn(function() require("coop.uv-utils").sleep(100) return "result A" end) local task_b = coop.spawn(function() require("coop.uv-utils").sleep(50) return "result B" end) -- Both tasks run concurrently - task_b finishes first print(task_a:await(1000), task_b:await(1000)) -- "result A", "result B" ``` -------------------------------- ### Async File Writing with uv.fs_write Source: https://context7.com/gregorias/coop.nvim/llms.txt Demonstrates asynchronous file writing using uv.fs_write. It opens a file, writes content, synchronizes, and closes the file asynchronously. Requires the 'coop' and 'coop.uv' modules. ```lua local coop = require("coop") local uv = require("coop.uv") coop.spawn(function() -- Create and write to file (flags: w+, mode: 644) local err_open, fd = uv.fs_open("/tmp/coop-test.txt", "w+", 420) assert(err_open == nil, "Failed to create file") local content = "Hello from Coop!\nAsync file writing works!" local err_write, bytes = uv.fs_write(fd, content, 0) -- Sync and close uv.fs_fsync(fd) uv.fs_close(fd) print("Wrote", bytes, "bytes") -- Wrote 42 bytes end):await(5000, 10) ``` -------------------------------- ### Async Directory Scanning and Stat with uv.fs_scandir / uv.fs_stat Source: https://context7.com/gregorias/coop.nvim/llms.txt Performs asynchronous directory scanning and retrieves file statistics using uv.fs_scandir and uv.fs_stat. It opens a directory, reads entries, and prints their names, types, and sizes. Requires 'coop' and 'coop.uv'. ```lua local coop = require("coop") local uv = require("coop.uv") coop.spawn(function() -- Open directory for scanning local err_open, dir = uv.fs_opendir(".", 100) assert(err_open == nil, "Failed to open directory") -- Read directory entries local err_read, entries = uv.fs_readdir(dir) uv.fs_closedir(dir) if entries then for _, entry in ipairs(entries) do -- Get detailed stats for each entry local err_stat, stat = uv.fs_stat(entry.name) if not err_stat then print(entry.name, entry.type, stat.size .. " bytes") end end end end):await(5000, 10) ``` -------------------------------- ### Await Task Results with coop.task.await and pawait Source: https://context7.com/gregorias/coop.nvim/llms.txt Demonstrates different ways to await task completion using `task.await` and `task.pawait`. This includes callback-based awaiting, blocking busy-waiting, and protected awaiting that returns success status instead of throwing errors. ```lua local coop = require("coop") local sleep = require("coop.uv-utils").sleep local my_task = coop.spawn(function() sleep(100) return "result", 42 end) -- Mode 1: Callback-based await (non-blocking) my_task:await(function(success, result, extra) print("Callback received:", success, result, extra) -- true, "result", 42 end) -- Mode 2: Blocking busy-wait (for synchronous code) -- Wait 1 second, poll every 50ms local result, extra = my_task:await(1000, 50) print(result, extra) -- "result", 42 -- Mode 3: Protected await (returns success boolean instead of throwing) local another_task = coop.spawn(function() sleep(50) error("something went wrong") end) coop.spawn(function() local success, err = another_task:pawait() print(success, err) -- false, "something went wrong" end) ``` -------------------------------- ### Task Creation and Management Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Functions for creating, resuming, yielding, and checking the status of tasks. ```APIDOC ## Task API Reference ### `task.create(task_function)` * **Description**: Creates a task from a given asynchronous task function. * **Method**: `task.create` * **Parameters**: * `task_function` (fun) - The asynchronous function to be executed as a task. * **Returns**: * `Coop.Task` - The created task object. ### `task.resume(task, ...)` * **Description**: Resumes the execution of a suspended task. * **Method**: `task.resume` * **Parameters**: * `task` (Coop.Task) - The task to resume. * `...` - Optional arguments to pass to the task upon resumption. * **Returns**: * `boolean success` - True if the task resumed successfully, false otherwise. * `... results` - The results returned by the task. ### `task.yield(...)` * **Description**: Yields control from the current task function. If the task is cancelled, it throws `error("cancelled")`. * **Method**: `task.yield` * **Parameters**: * `...` - Optional values to return when the task is resumed. * **Returns**: * `...` - Values returned when the task is resumed. ### `task.pyield(...)` * **Description**: A variant of `task.yield` that returns `success, results` instead of throwing an error on cancellation. * **Method**: `task.pyield` * **Parameters**: * `...` - Optional values to return when the task is resumed. * **Returns**: * `boolean success` - True if yielded successfully, false if cancelled. * `... results` - The results returned by the task or error information. ### `task.status(task)` * **Description**: Returns the current status of a task. * **Method**: `task.status` * **Parameters**: * `task` (Coop.Task) - The task to check. * **Returns**: * `string` - The status of the task, which can be one of: "running", "suspended", "normal", "dead". ### `task.running()` * **Description**: Returns the currently running task, if any. * **Method**: `task.running` * **Returns**: * `Coop.Task?` - The running task object, or nil if no task is running. ``` -------------------------------- ### coop.ui Module Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Provides task function versions of functions in vim.ui. ```APIDOC ## coop.ui Module ### Description Provides task function versions of functions in `vim.ui` (specifically `input` and `select`). This allows these UI elements to be used within asynchronous task flows managed by coop.nvim. ### Functions (Specific function signatures and details would be listed here if available in the source documentation.) ``` -------------------------------- ### Async System Commands with vim-coop.system Source: https://context7.com/gregorias/coop.nvim/llms.txt Provides an asynchronous wrapper for vim.system using coop.vim.system for simple command execution. It allows running commands and retrieving their exit codes and standard output asynchronously. Requires 'coop' and 'coop.vim'. ```lua local coop = require("coop") local vim_coop = require("coop.vim") coop.spawn(function() -- Run a command and get output local result = vim_coop.system({ "ls", "-la", "/tmp" }) print("Exit code:", result.code) print("Stdout:", result.stdout:sub(1, 200)) -- Run with custom options local grep_result = vim_coop.system( { "grep", "-r", "pattern", "." }, { cwd = "/some/directory", timeout = 5000 } ) if grep_result.code == 0 then print("Matches found:", grep_result.stdout) end end):await(10000, 10) ``` -------------------------------- ### coop.mpsc-queue Module Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Provides a multiple-producer single-consumer concurrent queue with an asynchronous pop method. ```APIDOC ## coop.mpsc-queue Module ### Description Provides a multiple-producer single-consumer concurrent queue with an asynchronous `pop` method. ### Usage Example ```lua local MpscQueue = require('coop.mpsc-queue').MpscQueue local q = MpscQueue.new() -- Asynchronously print whatever is provided to q. coop.spawn(function() while true do vim.print("Read: " .. q:pop()) end end) -- Start two threads that will asynchronously get strings from two sources. coop.spawn(function() while true do q:push(read_string_from_user()) end end) coop.spawn(function() while true do q:push(read_string_from_something_else()) end end) ``` ### Methods #### `MpscQueue.new()` - **Description**: Creates a new MPSC queue. - **Returns**: `MpscQueue` - The new queue instance. #### `q:push(item)` - **Description**: Pushes an item onto the queue. - **Parameters**: - `item` - The item to push onto the queue. #### `q:pop()` - **Description**: Asynchronously pops an item from the queue. Blocks if the queue is empty. - **Returns**: The next item from the queue. ``` -------------------------------- ### MpscQueue for Producer-Consumer Patterns Source: https://context7.com/gregorias/coop.nvim/llms.txt Implements an asynchronous Multi-Producer Single-Consumer queue (MpscQueue) from coop.mpsc-queue. This is useful for managing concurrent tasks where multiple producers send data to a single consumer. Requires 'coop', 'coop.mpsc-queue', and 'coop.uv-utils'. ```lua local coop = require("coop") local MpscQueue = require("coop.mpsc-queue").MpscQueue local sleep = require("coop.uv-utils").sleep coop.spawn(function() local queue = MpscQueue.new() -- Producer 1 coop.spawn(function() for i = 1, 3 do sleep(50) queue:push("producer1: " .. i) end end) -- Producer 2 coop.spawn(function() for i = 1, 3 do sleep(70) queue:push("producer2: " .. i) end end) -- Consumer - processes items as they arrive for _ = 1, 6 do local item = queue:pop() -- Async wait if queue is empty print("Consumed:", item) end end):await(5000, 10) ``` -------------------------------- ### coop.subprocess Module Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Provides a way to launch subprocesses and control their I/O with task functions. ```APIDOC ## coop.subprocess Module ### Description Provides a way to launch subprocesses and control their I/O with task functions. ### Functions #### `subprocess.spawn(command, options)` - **Description**: Spawns a new subprocess. - **Parameters**: - `command` (string) - The command to execute. - `options` (table) - Optional - Configuration options for the subprocess. - `args` (string[]) - Arguments for the command. - `stdio` (table) - Standard I/O configuration. Can include `nil`, `subprocess.PIPE`, or `subprocess.STREAM`. - **Returns**: A table representing the subprocess with methods like `await()` and properties like `stdout`. ### Usage Example ```lua local coop = require("coop") local subprocess = require("coop.subprocess") --@async function pass_printf_to_cat() local printf = subprocess.spawn("printf", { args = { "Hello, world!" }, stdio = { nil, subprocess.PIPE }, }) local cat = subprocess.spawn("cat", { stdio = { printf.stdout, subprocess.STREAM }, }) vim.print(cat.stdout:read_until_eof()) printf:await() cat:await() end coop.spawn(pass_printf_to_cat) ``` ``` -------------------------------- ### coop.control Module Functions Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Utilities for combining task functions and awaitables, including gathering results, shielding tasks from cancellation, setting timeouts, and awaiting tasks. ```APIDOC ## coop.control Module Functions ### Description Provides utilities for combining task functions and awaitables. ### Functions #### `gather(tasks)` - **Description**: Runs tasks in the sequence concurrently. Returns an aggregate list of results if all tasks complete successfully. Propagates the first raised exception immediately. Active tasks are not cancelled but will continue to run. Cancelling `gather` cancels all tasks in the sequence. - **Parameters**: - `tasks` (Coop.Task[]) - Required - The list of tasks to run concurrently. - **Returns**: `any ...` - The results of the tasks in the order they were provided. #### `shield(tf, ...)` - **Description**: Protects a task function from being cancelled. Executes the task function in a new task. If no cancellation occurs, it's equivalent to calling `tf(...)`. If the task wrapping `shield` is cancelled, the task function is allowed to complete, and then `shield` throws the cancellation error. For complete cancellation ignorance, combine with `copcall`. - **Parameters**: - `tf` (async function) - Required - The task function to protect. - `...` (...) - Optional - Arguments to pass to the task function. - **Returns**: `any ...` - The results of the task function. #### `timeout(duration, tf, ...)` - **Description**: Creates a task function that times out after a specified duration. If no timeout occurs, it's equivalent to `tf(...)`. If a timeout happens, it throws `error("timeout")`. If the returned task function is cancelled, the wrapped task function is also cancelled. - **Parameters**: - `duration` (integer) - Required - The duration in milliseconds. - `tf` (async function) - Required - The task function to run. - `...` (...) - Optional - Arguments to pass to the task function. - **Returns**: `...` - The results of the task function. #### `await_any(tasks)` - **Description**: Waits for any of the given tasks to complete. - **Parameters**: - `tasks` (Coop.Task[]) - Required - The list of tasks to wait on. - **Returns**: - `Coop.Task` - The first task that completed. - `Coop.Task[]` - The remaining tasks. #### `await_all(tasks)` - **Description**: Awaits all tasks in the list. - **Parameters**: - `tasks` (Coop.Task[]) - Required - The list of tasks to wait on. - **Returns**: - `table` - The results of the tasks. #### `as_completed(tasks)` - **Description**: Asynchronously iterates over the given awaitables and waits for each to complete. - **Parameters**: - `tasks` (Coop.Task[]) - Required - The list of tasks to iterate over. ``` -------------------------------- ### Task Awaiting Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Methods for awaiting the completion of tasks, with different overloads for callbacks, timeouts, and protected mode. ```APIDOC ## Task Awaiting API ### `task:await(cb_or_timeout, interval)` * **Description**: Awaits the completion of the task. This method has multiple overloads: * `result = task:await()`: Waits for the task to finish and returns its result. * `task:await(cb)`: Calls the provided callback function `cb` once the task is finished. It does not block execution. * `task:await(timeout, interval)`: Implements a busy-waiting loop using `vim.wait` to poll for task completion within a specified timeout and interval. * **Method**: `task.await` (instance method) * **Parameters**: * `cb_or_timeout` (function | number) - Either a callback function or a timeout value in milliseconds. * `interval` (number, optional) - The interval in milliseconds for polling when using a timeout. * **Returns**: * (When called without arguments or with timeout) `any` - The result of the task. * (When called with callback) `nil` ### `task:pawait()` * **Description**: Awaits the completion of the task in a protected mode. Unlike `await`, this method does not rethrow errors. Instead, it returns `false` and an error message if the task fails. * **Method**: `task.pawait` (instance method) * **Returns**: * `boolean success` - True if the task completed successfully, false otherwise. * `any ... results` - The results of the task if successful, or an error message if not. ``` -------------------------------- ### Task Spawning and Call Operator Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Using `coop.spawn` to create and resume tasks, and the call operator for a fluent interface. ```APIDOC ## Task Spawning and Call Operator ### `coop.spawn(task_function, ...)` * **Description**: Creates a new task from the `task_function` and immediately resumes it. This is the recommended way to start new tasks. * **Method**: `coop.spawn` * **Parameters**: * `task_function` (fun) - The asynchronous function to be executed as a task. * `...` - Arguments to pass to the `task_function`. * **Returns**: * `Coop.Task` - The newly created and spawned task object. ### Task Call Operator `task()` * **Description**: Tasks implement a call operator (`()`) that internally calls their `await` method. This allows for a fluent interface, making tasks appear as if they were regular functions that return their results directly upon completion. * **Usage Example**: ```lua local get_result_1 = coop.spawn(compute, 100) local get_result_2 = coop.spawn(compute, 200) local result = get_result_1() -- Calls task:await() internally ``` ``` -------------------------------- ### coop.uv Module Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Provides task function versions of asynchronous functions in vim.uv. ```APIDOC ## coop.uv Module ### Description Provides task function versions of asynchronous functions available in `vim.uv`. This module bridges Neovim's low-level asynchronous I/O operations with coop.nvim's task-based concurrency model. ### Functions (Specific function signatures and details would be listed here if available in the source documentation.) ``` -------------------------------- ### Task Awaiting and Protected Awaiting in Lua Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Methods for awaiting task completion, with support for callbacks, timeouts, and intervals. `pawait` provides a protected mode that returns errors instead of rethrowing them. ```lua -- Awaits task completion. function task.await(self, cb_or_timeout, interval) end -- task.await() is a task function that waits for the task finish and return a -- result result = task:await() -- task.await(cb) is a callback-based function that calls the callback once the -- task is finished. -- It doesn’t wait for the task. task:await(function(success, result) end) -- task.await(timeout, interval) is a blocking function that uses vim.wait to -- implement a busy-waiting loop. task:await(1000, 100) -- Wait for 1s for the task to finish. Check every 100ms -- Awaits task completion in a protected mode. -- This variant of await doesn’t rethrow errors. -- Instead it returns false, err_msg. --@async --@param self Coop.Task --@return boolean success --@return any ... results function task.pawait(self) -- … end ``` -------------------------------- ### Task Creation and Future Completion Source: https://github.com/gregorias/coop.nvim/blob/main/How it works.md Illustrates how a new Coop task is created and how its result is wired to complete an associated Future. This is fundamental to Coop's task abstraction, enabling result holding and awaiting. ```lua task.create = function(tf) local new_task -- ... new_task.thread = coroutine.create(function(...) new_task.future:complete(tf(...)) end) -- ... end ``` -------------------------------- ### Wait for First Task Completion (coop.await_any) Source: https://context7.com/gregorias/coop.nvim/llms.txt Waits for any one of the provided tasks to complete. It returns the completed task and a list of the remaining tasks, which can then be cancelled. This is useful for scenarios where you need the result of the fastest task. ```lua local coop = require("coop") local sleep = require("coop.uv-utils").sleep coop.spawn(function() local task_fast = coop.spawn(function() sleep(50) return "fast" end) local task_slow = coop.spawn(function() sleep(200) return "slow" end) -- Wait for first task to complete local done, remaining = coop.await_any({ task_fast, task_slow }) print("Winner:", done()) -- "fast" -- Cancel remaining tasks for _, task in ipairs(remaining) do task:cancel() end end):await(1000, 10) ``` -------------------------------- ### Async Selection Menu with coop.ui.select Source: https://context7.com/gregorias/coop.nvim/llms.txt An asynchronous function for presenting users with a selection menu, analogous to vim.ui.select. It allows for custom item formatting and returns the selected item along with its index, or nil if the selection is cancelled. ```lua local coop = require("coop") local ui = require("coop.ui") coop.spawn(function() local items = { "Option A", "Option B", "Option C" } local choice, idx = ui.select(items, { prompt = "Choose an option:", format_item = function(item) return ">> " .. item end, }) if choice then print("Selected:", choice, "at index", idx) else print("Selection cancelled") end end):await(30000, 100) ``` -------------------------------- ### Lua: Task Creation Capturing Return Values Source: https://github.com/gregorias/coop.nvim/blob/main/How it works.md Illustrates the basic structure of `task.create` in Coop.nvim, showing how it captures the return value of a coroutine function into a future. This is the foundation for task execution. ```lua task.create = function(tf) -- ... new_task.thread = coroutine.create(function(...) new_task.future:complete(tf(...)) end) -- ... end ``` -------------------------------- ### Callback to Coroutine Conversion Utility Source: https://github.com/gregorias/coop.nvim/blob/main/How it works.md Demonstrates a generic function to convert callback-based non-blocking operations into a coroutine syntax. This utility is crucial for Coop's mechanism of providing coroutines by reusing Neovim's standard library non-blocking functions. ```lua coroutine-utils.cb_to_co = function(tf) -- ... implementation details ... end ``` -------------------------------- ### Task Creation and Management in Lua Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Provides functions for creating, resuming, yielding, and checking the status of tasks. Tasks are extensions of Lua coroutines with added capabilities for results, awaiting, and cancellation. ```lua -- Creates a task from a task function. --@param task_function @async fun --@return Coop.Task task task.create -- Resumes a task. --@param task Coop.Task --@param ... --@return boolean success --@return any ... results task.resume -- Yields from a task functions it’s in. -- Yield throws `error("cancelled")` if in a cancelled task. --@async --@param ... --@return ... task.yield -- Returns the task’s status. --@param task Coop.Task --@return string "running" | "suspended" | "normal" | "dead" task.status -- Returns the running task. --@return Coop.Task? task.running ``` -------------------------------- ### Async LSP Requests with coop.lsp.client.request Source: https://context7.com/gregorias/coop.nvim/llms.txt Enables sending asynchronous requests to Language Server Protocol (LSP) clients with built-in support for automatic cancellation. This function handles requests like 'textDocument/hover' and 'textDocument/definition', returning results or errors. ```lua local coop = require("coop") local lsp_client = require("coop.lsp.client") coop.spawn(function() -- Get attached LSP clients local clients = vim.lsp.get_clients({ bufnr = 0 }) if #clients == 0 then print("No LSP clients attached") return end local client = clients[1] -- Make hover request local err, result, ctx = lsp_client.request( client, "textDocument/hover", { textDocument = vim.lsp.util.make_text_document_params(), position = { line = 0, character = 0 }, }, 0 -- bufnr ) if not err and result then print("Hover content:", vim.inspect(result.contents)) end -- Request with timeout using control.timeout local timeout = require("coop.control").timeout local copcall = require("coop.coroutine-utils").copcall local success, err_timeout = copcall(timeout, 1000, function() return lsp_client.request(client, "textDocument/definition", { textDocument = vim.lsp.util.make_text_document_params(), position = { line = 10, character = 5 }, }, 0) end) if not success then print("Request timed out:", err_timeout) end end):await(10000, 100) ``` -------------------------------- ### Async User Input with coop.ui.input Source: https://context7.com/gregorias/coop.nvim/llms.txt Provides an asynchronous way to prompt the user for text input, similar to vim.ui.input. It supports default values and file completion. The function returns the user's input or nil if cancelled. ```lua local coop = require("coop") local ui = require("coop.ui") coop.spawn(function() -- Prompt user for input local name = ui.input({ prompt = "Enter your name: ", default = "World", }) if name then print("Hello, " .. name .. "!") else print("Input cancelled") end -- Input with completion local filepath = ui.input({ prompt = "Select file: ", completion = "file", }) end):await(30000, 100) ``` -------------------------------- ### Task Cancellation Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Functions for cancelling tasks and checking their cancellation status. ```APIDOC ## Task Cancellation API ### `task.cancel(task)` * **Description**: Cancels the specified task. The task will throw `error("cancelled")` on its next yield. If cancellation is intercepted, the `cancelled` flag must be manually unset using `task.unset_cancelled`. * **Method**: `task.cancel` * **Parameters**: * `task` (Coop.Task) - The task to cancel. * **Returns**: * `boolean success` - True if the cancellation signal was sent successfully. * `... results` - Any results associated with the cancellation process. ### `task.unset_cancelled(task)` * **Description**: Unsets the cancellation flag for a given task. * **Method**: `task.unset_cancelled` * **Parameters**: * `task` (Coop.Task) - The task for which to unset the cancellation flag. ### `task.is_cancelled(task)` * **Description**: Checks if a task has been cancelled. * **Method**: `task.is_cancelled` * **Parameters**: * `task` (Coop.Task) - The task to check. * **Returns**: * `boolean is_cancelled` - True if the task is cancelled, false otherwise. ``` -------------------------------- ### Convert Callbacks to Task Functions with coop.cb_to_tf Source: https://context7.com/gregorias/coop.nvim/llms.txt A utility function to convert traditional callback-based functions into task functions compatible with Coop's asynchronous system. It supports optional cleanup handlers for cancellation scenarios, allowing for graceful resource management. ```lua local coop = require("coop") -- Example: Converting vim.fn.jobstart to async local async_job = coop.cb_to_tf(function(cb, cmd) local output = {} local job_id = vim.fn.jobstart(cmd, { on_stdout = function(_, data) for _, line in ipairs(data) do if line ~= "" then table.insert(output, line) end end end, on_exit = function(_, exit_code) cb(exit_code, output) end, }) return job_id end) coop.spawn(function() local exit_code, output = async_job({ "ls", "-la" }) print("Exit code:", exit_code) print("Output lines:", #output) end):await(5000, 10) -- With cleanup handlers for cancellation local async_http = coop.cb_to_tf(function(cb, url) local handle = some_http_library.get(url, function(response) cb(nil, response) end) return handle end, { on_cancel = function(args, ret) -- Called when task is cancelled before callback local handle = ret[1] if handle then handle:abort() end end, cleanup = function(err, response) -- Called when callback fires after cancellation if response then response:close() end end, }) ``` -------------------------------- ### Task Execution with Call Operator in Lua Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Demonstrates using the call operator on a task to await its completion, enabling a fluent interface where tasks can be called like regular functions. ```lua local get_result_1 = coop.spawn(compute, 100) local get_result_2 = coop.spawn(compute, 200) local result = get_result_1() ``` -------------------------------- ### Wait for All Task Completions (coop.await_all) Source: https://context7.com/gregorias/coop.nvim/llms.txt Waits for all tasks in a given list to complete. It returns a list containing the results of all tasks, maintaining the original order of the tasks provided. This is suitable when all asynchronous operations must finish before proceeding. ```lua local coop = require("coop") local sleep = require("coop.uv-utils").sleep coop.spawn(function() local tasks = { coop.spawn(function() sleep(100); return "a" end), coop.spawn(function() sleep(50); return "b" end), coop.spawn(function() sleep(150); return "c" end), } -- Wait for all tasks - they run in parallel local results = coop.await_all(tasks) -- Results are in original order for i, result in ipairs(results) do print(i, result[1]) -- 1 "a", 2 "b", 3 "c" end end):await(1000, 10) ``` -------------------------------- ### Combine and Protect Tasks with coop.control Source: https://github.com/gregorias/coop.nvim/blob/main/README.md The coop.control module offers utilities for managing asynchronous tasks. Functions like `gather` combine multiple tasks, `shield` protects tasks from cancellation, and `timeout` sets a time limit for task execution. It also includes `await_any`, `await_all`, and `as_completed` for managing task completion. ```lua --- Runs tasks in the sequence concurrently. --- --- If all tasks are completed successfully, the result is an aggregate list of returned --- values. The order of result values corresponds to the order of tasks. --- --- The first raised exception is immediately propagated to the task that awaits on gather(). --- Active tasks in the sequence won’t be cancelled and will continue to run. --- --- Cancelling the gather will cancel all tasks in the sequence. --- ---@async ---@param tasks Coop.Task[] the list of tasks. ---@return any ... results M.gather = function(tasks) end --- Protects a task function from being cancelled. --- --- The task function is executed in a new task. --- --- If no cancellation is taking place, `shield(tf, ...)` is equivalent to `tf(...)`. --- --- If the task wrapping `shield` is cancelled, the task function is allowed to complete. --- Afterwards `shield` throws the cancellation error. --- --- If it is desired to completely ignore cancellation, `shield` should be combined with `copcall`. --- ---@async ---@param tf async function The task function to protect. ---@param ... ... The arguments to pass to the task function. ---@return any ... The results of the task function. M.shield = function(tf, ...) end --- Creates a task function that times out after the given duration. --- --- If no timeout is taking place, `timeout(duration, tf, ...)` is equivalent to `tf(...)`. --- --- If a timeout happens, `timeout` throws `error("timeout")`. --- --- If the returned task function is cancelled, so is the wrapped task function. --- ---@async ---@param duration integer The duration in milliseconds. ---@param tf async function The task function to run. ---@param ... ... The arguments to pass to the task function. ---@return ... ... The results of the task function. M.timeout = function(duration, tf, ...) end --- Waits for any of the given tasks to complete. --- ---@async ---@param tasks Coop.Task[] ---@return Coop.Task done The first task that completed. ---@return Coop.Task[] done The remaining tasks. M.await_any = function(tasks) end --- Awaits all tasks in the list. --- ---@async ---@param tasks Coop.Task[] ---@return table results The results of the tasks. M.await_all = function(tasks) end --- Asynchronously iterates over the given awaitables and waits for each to complete. --- ---@async ---@param tasks Coop.Task[] M.as_completed = function(tasks) end ``` -------------------------------- ### Lua: Coroutine-Safe Pcall (copcall) Pseudocode Source: https://github.com/gregorias/coop.nvim/blob/main/How it works.md Presents pseudocode for `copcall`, a Coop.nvim utility designed to mimic `pcall`'s error-handling capabilities for coroutine functions. It achieves this by launching a new coroutine and managing its execution lifecycle. ```lua -- pseudocode M.copcall = function(f_co, ...) local thread = coroutine.create(f_co) local results = coroutine.resume(thread) while thread_not_dead(results) do results = coroutine.resume(thread, coroutine.yield()) end return results end ``` -------------------------------- ### Upload coop.nvim to LuaRocks Source: https://github.com/gregorias/coop.nvim/blob/main/DEV.md Uploads a new version of the coop.nvim project to the LuaRocks package manager. This process involves updating the Rockspec file with the new version and API key, then executing the upload command. ```shell luarocks upload ./coop.nvim-$VERSION-$REVISION.rockspec --api_key=$API_KEY ``` -------------------------------- ### Iterate Task Results as They Complete (coop.as_completed) Source: https://context7.com/gregorias/coop.nvim/llms.txt Asynchronously iterates over a list of tasks, yielding each task's result as soon as it completes. This allows for processing results in the order they become available, rather than waiting for all tasks to finish. ```lua local coop = require("coop") local sleep = require("coop.uv-utils").sleep local as_completed = require("coop.control").as_completed coop.spawn(function() local tasks = { coop.spawn(function() sleep(150); return 3 end), coop.spawn(function() sleep(50); return 1 end), coop.spawn(function() sleep(100); return 2 end), } -- Process results in completion order local completion_order = {} for completed_task in as_completed(tasks) do table.insert(completion_order, completed_task()) end print(table.concat(completion_order, ", ")) -- "1, 2, 3" end):await(1000, 10) ``` -------------------------------- ### Future Callback Execution Source: https://github.com/gregorias/coop.nvim/blob/main/How it works.md Shows how a Future's `complete` method processes results and iterates through its queue of callbacks. These callbacks are responsible for resuming tasks that are awaiting the Future's completion. ```lua Future.complete = function(self, ...) -- ... self.results = pack(...) -- ... for _, cb in ipairs(self.queue) do cb(unpack(self.results, 1, self.results.n)) end end ``` -------------------------------- ### Blocking Until Asynchronous Function Completion in Lua Source: https://github.com/gregorias/coop.nvim/blob/main/README.md Illustrates how to block synchronous code until an asynchronous task completes using Coop's `await` method. This is achieved through a busy-waiting mechanism based on `vim.wait`. ```lua --- -- This is a synchronous function. --- function main() local task = coop.spawn(...) -- Wait for 5 seconds and poll every 20 milliseconds. return task:await(5000, 20) end ``` -------------------------------- ### Async Sleep with uv-utils.sleep Source: https://context7.com/gregorias/coop.nvim/llms.txt Implements an asynchronous sleep function using coop.uv-utils.sleep. This allows tasks to pause execution for a specified duration without blocking the event loop. Requires 'coop' and 'coop.uv-utils'. ```lua local coop = require("coop") local sleep = require("coop.uv-utils").sleep coop.spawn(function() print("Starting at:", os.time()) -- Sleep for 500ms without blocking sleep(500) print("Woke up at:", os.time()) -- Multiple sleeps in sequence for i = 1, 3 do sleep(100) print("Tick", i) end end):await(5000, 10) ```