Expand description
§Command providers
Command providers can be anything from where a command could be installed. These differ from the environments in that a provider merely tells whether a program can be found there or not, but it doesn’t provide the ability to immediately run the program. On the other hand, an execution environment is something that allows the active execution of commands.
Generally speaking, a provider is any sort of package manager (cargo
, pip
, apt
, dnf
,
…).
Execution environments may have zero or more providers available. Containers usually don’t have providers, whereas a host operating system will offer some means of installing packages.
§Implementing a new provider
The following instructions relate to writing a new provider in Rust, with the goal of inclusion
into the application in mind. Of course you don’t have to submit your own provider for
inclusion if you don’t want to. Similarly, you can write a custom
provider first and
then open an issue to discuss long-term reimplementation and inclusion in the application.
Here are the mandatory steps you must take to write a new provider:
- Create a new module file in the
providers
module (here) and name if after the desired provider. - Next, in the
providers
root module:- Include your new module (
pub mod ...
) - Import the module into the code (
use ...
) - Add your new module to the
Provider
struct - Pass through the
fmt::Display
of your new module forProvider
- Include your new module (
- In your new provider module:
- Import the prelude:
use crate::provider::prelude::*;
- Create a new type (struct) for your provider with any internal state you need (or none at all)
- Implement
fmt::Display
, and please adhere to the projects naming convention. For example,dnf
is usually referred to as DNF. - Implement
IsProvider
for your new provider - (Optional) Write some tests, in case your provider can be tested
- Import the prelude:
- In
src/lib.rs
:- Add your provider into the
providers
vector
- Add your provider into the
Following you will find a set of guidelines to help you in the process of writing a robust provider. It’s written as a checklist, so feel free to copy it and check the boxes if you want.
- Interacting with the provider:
- Test all the different existent queries you can find (i.e. when your provider returns a successful result for existing applications). Some providers change their output format based on what they find, for example by adding optional fields.
-
Test a non-existent search query (Personally I like ‘asdwasda’ for that purpose) and
return such errors as
ProviderError::NotFound
-
When pre-conditions for your provider aren’t fulfilled (i.e. it needs a specific
application/package manager), return a
ProviderError::Requirements
- Prefer offline operation and fall back to online operation only when e.g. package manager caches don’t exist. Log an info message in such cases so the user can deduce from the log why searching took longer than expected.
- Prefer parsing results from machine-readable output when possible
- Error handling:
-
Never cause a panic by calling e.g.
unwrap()
: Prefer wrapping errors intoanyhow::Error
and returning that asProviderError::ApplicationError
instead. Panics ruin the TUI output and don’t add any value for the end-user. - If you want to recover from errors, consider writing a concrete error type for your provider
-
Check if
ProviderError
already has the error variant you need and reuse that before reimplementing your own version of it
-
Never cause a panic by calling e.g.
- Other things:
-
A
Candidate
must have at least its’package
andactions.execute
fields populated. Try to populate as many as you can. - Prefer a precise search and returning only few relevant results over generic searches with many results. Built-in providers currently try to stick with less or equal 10 results each.
-
Try to check whether any of the results you find are already installed. Most package
managers will happily report that e.g.
coreutils
provides thels
command, butcoreutils
is likely already installed.
-
A
Feel free to look at some of the existing providers as a reference.
Modules§
- apt
- APT provider
- cargo
- Search packages with cargo (Rust)
- custom
- Custom provider
- cwd
- Current Working Directory Provider
- dnf
- Search packages with DNF.
- flatpak
- Search packages with Flatpak.
- pacman
- Search packages with pacman
- path
- Path provider.
Structs§
- Actions
- Action specification for a Candidate.
- Candidate
- Potential candidate for a command.
- Query
- A convenient representation of a search query with its’ results.
Enums§
- Error
- Provider
- Wrapper type for everything implementing
IsProvider
.
Traits§
- IsProvider
- A command provider.
Functions§
- search_
in - Search for
command
inside the givenIsProvider
, targeting a specificEnvironment
.