Page not found :(
+The page you are looking for doesn't exist or has been moved.
+diff --git a/404.html b/404.html new file mode 100644 index 00000000..e498ad90 --- /dev/null +++ b/404.html @@ -0,0 +1,241 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The page you are looking for doesn't exist or has been moved.
+Creator of AdiDoks.
+ + +The authors of the blog articles.
+ +How you can help out with shrs
+To see current feature status and what would needs to be done, look at the github actions kanban
+ +It is also helpful to fix open issues. If you are a new contributor you can use the good first issue
label to filter issues.
Firstly, thanks for taking the time to contribute to shrs! This page will +go over starting steps to get you ready to create your first PR!.
+Since shrs is a rust project, you should have a working rust development +environment. You can get started with installing rust by using +rustup - the rust toolchain installer. You should also +install the nightly rust toolchain as some parts of the developer workflow +depends on nightly versions of rust tools.
+shrs uses just as it's command runner. +Install it in whatever method suitable for your system.
+First we will get an example build of shrs up and running to take a tour of +all the features it offers.
+Clone the repository and enter the project directory:
+git clone https://github.com/MrPicklePinosaur/shrs.git
+cd shrs
+
+There are a couple of special git hooks that are run on commit that or +especially for developers. These git hooks do things like lint your code and +format it. You can install them with:
+just devsetup
+
+Now to run the example shell
+just
+
+You should now be throw into the example shrs shell, which shows off a good
+number of the features shrs offers. Take some time to explore what the
+shell is capable of. You can also examine shrs_example/src/main.rs
to see the
+actual configuration.
Next is to use shrs as it was intended, as a library. To get started with +creating your own shell, take a look at the Quick Start section.
+Once you are decently familiar with the shrs API, you can try to tackle an +actual issue and open your first PR! See the open issues, especially those +marked good first issue. +If you have any questions, don't be afraid to reach out for help!
+ + + + + +Branch name should be in the format your-name/description
. For example, if I were to implement tab completion I would create a branch called pinosaur/tab-completion
.
shrs_example +is an example shell that makes use of the default features provided by +shrs. If you want a working shell quickly, you can simply install the +binary directly. However, the goal of shrs is to provide a fully +customizable shell that you can build yourself in rust, it is recommended that +you make your own project, which you can learn about in the Quick Start section.
+ + + + + +Welcome to shrs, the toolkit that will help you build and configure your +own shell in Rust!
+First of all shrs is NOT a shell, it is a library for YOU to build your own +shell. It is meant for those that have reached the limits of what can be +accomplished with just tinkering with the configuration files of pre-existing +shells and would like to go beyond and add experimental and wild features to +their own shells.
+Get a working shell up and quickly: Quick Start →
+Contributing and Help.
+Find out how to contribute to Doks. Contributing →
+Get help on Doks. Help →
+ + + + + +To get started with using shrs, you need a functioning Rust installation. +To install Rust, you can use the rustup, the Rust +toolchain installer. You will also need cargo, the Rust package manager.
+Finally, you will need some basic knowledge on how Rust works, if you are +still new to Rust, you can consult the rust +book.
+Create your own shell project using cargo:
+cargo init <project-name>
+cd <project-name>
+
+Next, add shrs as a dependency in your Cargo.toml
shrs = { version = "0.1" }
+
+Next, you can create a basic shell using all of the shrs provided defaults with the following:
+use shrs::prelude::*;
+
+fn main() {
+ let myshell = ShellBuilder::default()
+ .build()
+ .unwrap();
+
+ myshell.run();
+}
+
+Now to run the shell
+cargo run
+
+From here we can start digging into all the potential configuration and +extensions that can be applied to shrs. See the next section for details.
+ + + + + +The autocompletion system works on rules, which are pairs of predicates +and actions. Predicates help determine when an action is allowed to run, +and actions return the actual word list for the completion system to display to +the user.
+There are a variety of commonly used builtin predicates to make write
+completions a bit easier, these include cmdname_pred
which checks that the
+current completion is for a specific command name and flag_pred
which checks
+if we are attempting to complete a flag.
Similarly, there are also builtin actions like cmdname_action
which
+returns a list of all executables in the PATH, and filename_action
which
+outputs all the files in the current working directory.
As an example, let's write completion rules for the popular ls command.
+Let's begin by initializing the DefaultCompleter
. This comes with a couple of
+sensible rules that most completion engines are expected to have, such as
+autocompleting the command name from PATH:
use shrs::line::completion::*;
+
+let mut completer = DefaultCompleter::default();
+
+Next, we need to create a rule that will provide completion options for each of
+the flags ls has. We can do this by writign a rule that first checks if the
+user has already typed the command ls using cmdname_pred
:
let ls_pred = Pred::new(cmdname_pred("ls"));
+
+However, we also want to complete the flags for ls, so we need to also
+check if we are currently typing a flag. We can use the provided flag_pred
+for this. Notice how we can chain predicates with .and()
:
let ls_pred = Pred::new(cmdname_pred("ls")).and(flag_pred);
+
+Next we need to write the action that returns all the possible flags. An action
+is just a function that takes in CompletionCtx
and returns a list of possible
+completions. Completion
holds a bit more metadata that we will not touch for
+now, but if we just wish to return a list of strings to the completer, we can
+use the helper function default_format
to generate default options for Completion
.
let ls_action = Box::new(|ctx: &CompletionCtx| -> Vec<Completion> {
+ default_format(vec!["-a".into(), "-l".into(), "-h".into()])
+});
+
+And with that we can register our first completion rule:
+completer.register(Rule::new(ls_pred, ls_action));
+
+In the end, our resulting code looks like:
+use shrs::line::completion::*;
+
+let mut completer = DefaultCompleter::default();
+
+let ls_pred = Pred::new(cmdname_pred("ls")).and(flag_pred);
+let ls_action = Box::new(|ctx: &CompletionCtx| -> Vec<Completion> {
+ default_format(vec!["-a".into(), "-l".into(), "-h".into()])
+});
+
+completer.register(Rule::new(ls_pred, ls_action));
+
+The plugin shrs_derive_completion
provides a declarative way to create
+completions in the form of a procedual macro. If you are familiar with the
+crate clap this should feel very familiar.
History is the ability for the shell to remember previous commands you have
+typed, providing the ability to cycle back to re-run commands. Currently
+shrs offers two history implementations, DefaultHistory
and
+FileBackedHistory
. DefaultHistory
is a very basic memory based history,
+which means that your history will not persist if you close the shell. On the
+other hand, FileBackedHistory
uses an actual file on disk, providing
+persistent completions.
Here is an example of using FileBackedHistory
:
// Put the path to your history file here
+let history_file = PathBuf::from(" ... ");
+let history = FileBackedHistory::new(history_file).unwrap();
+
+myline.with_history(history)
+
+
+
+
+
+
+ Keybindings allow you to run arbitrary commands in respond to arbitrary key
+presses in the shell. A common example is the ability to clear the terminal
+when Control+L
is pressed. How keybindings are represented is a bit more of an
+internal detail and not very fun to write, so a macro is provided to make the
+experience a bit better.
ley keybinding = keybindings! {
+ "C-l" => Command::new("clear").spawn(),
+};
+
+myline.with_keybinding(keybinding);
+
+The macro allows us to represent key combinations in terms of strings. You can +also include modifier keys (such as control and shift). Here are the supported modifiers:
+Modifier | Usage |
---|---|
Shift | "S" or "Shift" |
Alt | "A" or "Alt" |
Control | "C" or "Ctrl" |
Super | "Super" |
Meta | "M" or "Meta" |
Furthermore, there are also some keys that are hard to represent in a string, +so we use a special notation to denote them:
+Key | Usage |
---|---|
Space | "<space>" |
Backspace | "<backspace>" |
Escape | "<esc>" |
Enter | "<enter>" |
Tab | "<tab>" |
Here are some example keybinding strings:
+Meaning | Usage |
---|---|
Control + Alt + q | "C-A-q" |
Super + Space | "Super-<space>" |
Alt + Tab | "A-<tab>" |
Vi Mode is currently not configurable. In the future, hopefully custom commands +and keybindings will be supported.
+ + + + + +Plugins are a way to add addition functionality that may be opinionated or heavy to shrs in a modular fashion. shrs comes with a couple officially maintained plugins, which you can see in the plugins directory.
+Some examples of official plugins are:
+shrs_output_capture
: add a builtin called again
that will output the result of the previous commandshrs_prompt_builder
: configure your prompt using the builder patternMaking a plugin is as easy as implementing the Plugin
trait. The Plugin
+trait has an init
method that is ran when the plugin is registered with the
+with_plugin
function. In the init
method, you get the shell
as context
+and are free to modify it however you please, be it registering additional
+hooks are adding a new builtin function.
use shrs::plugin::Plugin;
+
+pub struct MyPlugin;
+
+impl Plugin for PlugPlugin {
+ fn init(&self, shell: &mut shrs::ShellConfig) {
+ shell.hooks.after_command.register(after_command_hook);
+ shell.builtins.insert("my_builtin", MyBuiltin::new());
+ shell.state.insert(MyState::new());
+ }
+}
+
+
+You can see some of the official maintained plugins for an example on how +plugins are created.
+ + + + + +Plugins are just regular crates that can be obtained from
+crates.io. Most shrs related crates have the prefix
+shrs_
. Simply add the crate to your project. To make shrs use the plugin,
+it's as using as using with_plugin
when constructing the shell and pass in
+the plugin.
let myshell = ShellBuilder::default()
+ .with_plugin(OutputCapturePlugin)
+ .build()
+ .unwrap();
+
+myshell.run();
+
+
+
+
+
+
+ Aliases can be specified as a key value pair of the alias name and the actual command it expands to. Keep in mind that aliases are not evaluated or syntax checked at time of definition, only during substitution. This means that it is possible to define aliases that are invalid commands.
+let alias = Alias::from_iter([
+ ("l", "ls"),
+ ("c", "cd"),
+ ("g", "git"),
+ ("v", "vim"),
+ ("la", "ls -a"),
+]);
+
+myshell.with_alias(alias);
+
+
+
+
+
+
+ You can load all the current environment variables into shrs by using env.load()
. This is useful in the case that you are launching your shrs shell from another shell, like bash.
let mut env = Env::new();
+env.load();
+
+myshell.with_env(env);
+
+In the case that the shrs shell is your login shell, or that you wish to define additional environment variables, you can do so by appending to the Env
object. Note that environment variables are also case insensitive.
env.set("SHELL", "my_shrs");
+
+
+
+
+
+
+ Hooks are a collection of predefined functions that shrs will call when +certain events occur. This lets you hook onto shell events and add your own +additional functionality.
+Some examples include startup
hook, which is great for printing a welcome
+message and after_command
hook which you can use to print out the exit status
+of the last command.
An example usage of the startup
hook.
let startup_msg = | _sh: &Shell, _sh_ctx: &mut Context, _sh_rt: &mut Runtime, _ctx: StartupHookCtx | {
+ let welcome_str = "Welcome to my shell!";
+ println!("{}", welcome_str);
+};
+let hooks = Hooks {
+ startup: HookList::from_iter(vec![startup_msg]),
+ ..Default::default()
+};
+
+myshell.with_hooks(hooks);
+
+Hooks also have additional context that is passed as a parameter which you can +leverage. For a list of all the hooks and the context that is passed, please +refer to the rust docs.
+Also notice that each type of hook actually takes in a list of hooks to run. +These hooks are ran in the order they are registered.
+ + + + + +First define your own prompt and implement the Prompt
trait.
use shrs::{Prompt, prompt::top_pwd};
+
+struct MyPrompt;
+
+impl Prompt for MyPrompt {
+ fn prompt_left(&self) -> String {
+ format!(" {} > ", top_pwd())
+ }
+}
+
+Then add it when building the shell:
+let prompt = MyPrompt;
+
+myshell.with_prompt(prompt);
+
+The prompt
module comes with a variety of helpful functions for building the prompt. We can build a something that looks like the bash prompt with:
struct BashPrompt;
+
+impl Prompt for BashPrompt {
+ fn prompt_left(&self) -> String {
+ format!("{}@{}:{}$ ", hostname(), username(), top_pwd())
+ }
+}
+
+
+
+
+
+
+ shrs comes with it's own readline implementation that is just as +configurable and extensible as the core.
+See the section on Line Configuration for details on all the configuration +options. To pass in your own configured readline to shrs:
+let readline = LineBuilder::default()
+ .build()
+ .unwrap();
+
+myshell.with_readline(readline);
+
+
+
+
+
+
+ shrs is a framework for building and configuring your own shell in rust.
+ Get started + +Fully configurable and extensible in Rust
+Includes modern shell features like completion, hinting and history
+Comfortable transition from your favorite shells
+Numerous community maintained plugins to take your shell to the next level
+Community maintained and completely free and open source
+Of course it is blazingly fast
+TLDR: We do not use cookies and we do not collect any personal data.
+Contact us if you have any questions.
+Effective Date: 1st May 2021
+ +