shitbox/CONTRIBUTING.md

88 lines
4.0 KiB
Markdown
Raw Permalink Normal View History

Contents
========
* [The **Cmd** trait](#the-cmd-trait)
* [A simple example applet](#a-simple-example-applet)
* [Incorporating a new applet](#incorporating-a-new-applet)
* [Dependencies](#dependencies)
* [Coding Guidelines](#coding_guidelines)
2022-12-25 22:30:46 -05:00
## The Cmd trait
The `Cmd` trait is defined in `src/cmd/mod.rs`. All applets should live in their
own submodule under `crate::cmd` and include a struct with the name of the command,
in snake case. This struct must implement `Cmd`. It is recommended that this struct
have at least the fields `name: &'static str` and `path: crate::Path`. The
trait methods `name` and `path` can then just return the corresponding fields.
For simplicity's sake, `run` will always return `Box<dyn Error>` on failure and
bubble the error up to the caller, where the error will be presented to the user.
2023-01-06 23:53:41 -05:00
The applet module should further implement `Default` for the struct which implements
the `Cmd` trait.
## A Simple Example Applet
```Rust
// src/cmd/myapplet/mod.rs
use clap::Command;
use super::Cmd;
#[derive(Debug, Default)]
pub struct MyApplet;
impl Cmd for MyApplet {
fn cli(&self) -> clap::Command {
Command::new(self.name)
.version(env!("CARGO_PKG_VERSION"))
.author("Zaphod Beeblebrox")
.about("Does sketchy things")
}
fn run(&self, _matches: Option<&clap::ArgMatches>) -> Result<(), Box<dyn std::error::Error>> {
println!("If there's anything more important than my ego around, I want it caught and shot now.");
Ok(())
}
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::UsrBin)
}
}
```
## Incorporating a new applet
Each command module should be public in `src/cmd/mod.rs` and both the struct which
2023-01-06 23:53:41 -05:00
implements `Cmd` should be exported as public in that file. The function `cmd::get`
has a match statement, to which should be added a line which matches the name of
the new command and returns an `Option<Box<dyn Cmd>>` for your type. The static
`cmd::COMMANDS` should have your new command's name added and the array's number
incremented by 1.
## Dependencies
In order to accept a new dependency, the crate should provide utility that can be
used in multiple applets. It should introduce as few transitive dependencies as
possible, and the functionality provided should be something that cannot be easily
replicated cleanly. Preference is given to crates that are standalone and do not
significantly increase binary size. The prospective crate must be well maintained
and as free of security issues as can be realistically achieved. All that said,
it is sometimes better to take on a dependency than to implement the desired
functionality from scratch. This is absolutely a judgement call.
## Coding Guidelines
Before accepting changes, the code should be formatted using `cargo fmt` and all
lints discovered via `cargo clippy` should be addressed. The default lint level
is pedantic. If there is good reason, an individual lint may be allowed for a
specific block of code with `#[allow(clippy::<lint>)]`.
New applets must be Posix compliant. They can and should implement GNU or BSD extensions
to Posix if the extended behavior is in widespread enough to cause widespread shell
script failures if left unimplemented. Further extension is allowed under the
following conditions.
- the extended behavior does not conflict with Posix
- the extended behavior increases utility
- the extended behavior is in keeping with behavior of other applets and increases
consistency of behavior for the overall userland
### Unsafe
As a functional Unix userland exposes much low level functionality to the user, it
is unavoidable that there will be cases of `unsafe` in this codebase. Please limit
use of `unsafe` to those places where the desired functionality is not exposed via
Rust's std library. Blocks of `unsafe` should only encapsulate the desired calls,
and not contain logic etc.
Keep memory usage small be preferring pass by reference, use of techniques such as
bitflags and avoiding unneeded allocations.