Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nithin/state docs #462

Merged
merged 6 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 6 additions & 22 deletions docs/content/docs/shell-config/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,24 @@ help builtins
## Creating your own Builtin

An example of creating a builtin and registering it is provided below.

First, define a builtin and implement the `BuiltinCmd` trait:
Builtins are simply functions that have a required parameter `&Vec<String>`.
Other states can also be accessed by adding them to the parameters; see [States](../states/).

```rust
struct MyBuiltin { }

impl BuiltinCmd for MyBuiltin {
fn run(
&self,
sh: &Shell,
ctx: &mut Context,
rt: &mut Runtime,
args: &[String],
) -> ::anyhow::Result<CmdOutput> {

// builtin implementation ...
println!("this is my builtin~");

// return command status code
Ok(CmdOutput::success())
}
fn my_builtin(args: &Vec<String>){
Ok(CmdOutput::success())
}
```

Then you can register it like so
```rust
let mut builtins = Builtins::default();
builtins.insert("mybuiltin", MyBuiltin {});
builtins.insert("mybuiltin", my_builtin);

myshell.with_builtins(builtins);
```
The builtin can then be ran by calling `mybuiltin`. Any existing builtins of the same name will also be overwritten, so this is a good way to override default builtins with your own version.
The builtin can then be run by calling `mybuiltin`. Any existing builtins of the same name will also be overwritten, so this is a good way to override default builtins with your own version.

A much more comprehensive example can be found in the `shrs` examples directory, [here](https://github.com/MrPicklePinosaur/shrs/blob/master/crates/shrs/examples/custom_builtin.rs).

Note that we used `Builtins::default` instead of `Builtins::new`, it is highly recommended that you use the default builtins since it gives you many essential builtin commands like `cd` and `exit`, where `Builtins::new` gives you literally nothing. So it is much better practice to start with `Builtins::default` and override the ones you want.

70 changes: 70 additions & 0 deletions docs/content/docs/shell-config/states.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
+++
title = "States"
description = ""
date = 2023-12-01t08:00:00+00:00
updated = 2023-12-01t08:00:00+00:00
draft = false
weight = 10
sort_by = "weight"
template = "docs/page.html"

[extra]
lead = ''
toc = true
top = false
+++

**shrs** is highly extensible and allows customizing the states of the different parts of the shell. Shrs also allows users to define their own states which can be used to control various behaviours.

## Accessing states
States can be accessed in various defined callbacks such as [builtins](../builtins/), [hooks](../hooks/), [keybindings](../keybindings/), [prompt](../prompt/) and when initializing a plugin.

States are accessed by adding it to the function parameters, wrapped in either `State` or `StateMut`, depending on if the state should be mutable or not. Accessing `OutputWriter` in a keybinding to write to console can be done like so.

```rust
fn clear_screen(mut out: StateMut<OutputWriter>)-> {
out.println("Clear Screen")?;
}
```

Parameters can also be wrapped in an Option, if the state may not exist when the function is called. Otherwise, **shrs** will panic.

```rust
fn clear_screen(mut out: Option<StateMut<OutputWriter>>)-> {
if let Some(o) = out{
out.println("Clear Screen")?;
}
}
```

Shell is a special state that can only be accessed immutably and is guaranteed to always exist. Accessing state does not require `State` or `StateMut`.

```rust
fn clear_screen(mut out: Option<StateMut<OutputWriter>>,sh: &Shell)-> {
out.println("Clear Screen")?;
}
```

## Defining custom states
Custom states allow users to create states that can be accessed in the same manner as above. States can be easily inserted before the shell starts.

```rust
pub struct T{}
fn main(){
let myshell = ShellBuilder::default().with_state(T{}).build.unwrap();
myshell.run().unwrap();
}

```
States can also be queued to be inserted during callbacks and are inserted directly after.
```rust
pub struct H{}

pub fn f(sh: &Shell, ctx: &SCtx) -> Result<()> {
sh.run_cmd(|sh: &mut Shell, states: &mut States| {
states.insert(H{});
});

Ok(())
}
```