Compare commits
2 commits
b7c8dc3fba
...
fdfddec576
Author | SHA1 | Date | |
---|---|---|---|
fdfddec576 | |||
2bb2c69269 |
3 changed files with 73 additions and 22 deletions
32
build.rs
32
build.rs
|
@ -1,4 +1,6 @@
|
|||
#![allow(unused_imports)]
|
||||
use roff::{Roff, bold, italic, roman};
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
fn main() {
|
||||
let page = Roff::new()
|
||||
|
@ -6,27 +8,23 @@ fn main() {
|
|||
.control("SH", ["NAME"])
|
||||
.text([roman("sesh - Semantic Shell")])
|
||||
.control("SH", ["SYNOPSIS"])
|
||||
.text([
|
||||
bold("sesh"),
|
||||
roman(" [options]"),
|
||||
])
|
||||
.text([bold("sesh"), roman(" [options]")])
|
||||
.control("SH", ["DESCRIPTION"])
|
||||
.text([
|
||||
bold("sesh"),
|
||||
roman("is a shell designed to be as semantic to use as possible"),
|
||||
])
|
||||
.control("SH", ["OPTIONS"])
|
||||
.control("TP", [])
|
||||
.text([
|
||||
bold("-n"),
|
||||
roman(", "),
|
||||
bold("--bits"),
|
||||
roman("="),
|
||||
italic("BITS"),
|
||||
])
|
||||
.text([roman(
|
||||
"Set the number of bits to modify. Default is one bit.",
|
||||
)])
|
||||
.render();
|
||||
print!("{}", page);
|
||||
std::fs::write(
|
||||
PathBuf::from(env::var_os("OUT_DIR").unwrap())
|
||||
.parent()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("sesh.1"),
|
||||
page,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
#![allow(clippy::type_complexity)]
|
||||
|
||||
/// List of builtins
|
||||
pub const BUILTINS: [(&str, fn (args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32); 3] = [("cd", cd), ("exit", exit), ("echo", echo)];
|
||||
pub const BUILTINS: [(
|
||||
&str,
|
||||
fn(args: Vec<String>, unsplit_args: String, state: &mut super::State) -> i32,
|
||||
); 4] = [("cd", cd), ("exit", exit), ("echo", echo), ("alias", alias)];
|
||||
|
||||
/// Change the directory
|
||||
pub fn cd(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
|
||||
|
@ -25,7 +28,7 @@ pub fn exit(_: Vec<String>, _: String, _: &mut super::State) -> i32 {
|
|||
|
||||
/// Echo a string
|
||||
pub fn echo(args: Vec<String>, mut unsplit_args: String, _: &mut super::State) -> i32 {
|
||||
unsplit_args = unsplit_args[5..].to_string();
|
||||
unsplit_args = unsplit_args[(args[0].len() + 1)..].to_string();
|
||||
if args.len() != 1 && args[1] == "-e" {
|
||||
unsplit_args = unsplit_args[3..].to_string();
|
||||
let escaped = crate::escapes::interpret_escaped_string(&unsplit_args);
|
||||
|
@ -38,3 +41,29 @@ pub fn echo(args: Vec<String>, mut unsplit_args: String, _: &mut super::State) -
|
|||
println!("{}", unsplit_args);
|
||||
0
|
||||
}
|
||||
|
||||
/// Add an alias
|
||||
pub fn alias(args: Vec<String>, _: String, state: &mut super::State) -> i32 {
|
||||
if args.len() == 1 {
|
||||
for alias in &state.aliases {
|
||||
println!("`{}`: `{}`", alias.name, alias.to);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if args.len() == 2 {
|
||||
for alias in &state.aliases {
|
||||
if alias.name != args[1] {
|
||||
continue;
|
||||
}
|
||||
println!("`{}`: `{}`", alias.name, alias.to);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
state.aliases.push(super::Alias {
|
||||
name: args[1].clone(),
|
||||
to: args[2].clone(),
|
||||
});
|
||||
|
||||
0
|
||||
}
|
||||
|
|
30
src/main.rs
30
src/main.rs
|
@ -48,6 +48,14 @@ enum Variable {
|
|||
Nonlocal(OsString),
|
||||
}
|
||||
|
||||
/// A single alias
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
struct Alias {
|
||||
/// alias from
|
||||
name: String,
|
||||
/// to
|
||||
to: String
|
||||
}
|
||||
/// The state of the shell
|
||||
#[derive(Clone, Debug)]
|
||||
struct State {
|
||||
|
@ -61,6 +69,8 @@ struct State {
|
|||
history: Vec<State>,
|
||||
/// Current working directory.
|
||||
working_dir: PathBuf,
|
||||
/// A list of aliases from name to actual
|
||||
aliases: Vec<Alias>
|
||||
}
|
||||
|
||||
unsafe impl Sync for State {}
|
||||
|
@ -160,13 +170,26 @@ fn eval(statement: &str, state: &mut State) {
|
|||
let statements = split_statements(&statement);
|
||||
|
||||
for statement in statements {
|
||||
let statement_split = split_statement(&statement);
|
||||
let mut statement_split = split_statement(&statement);
|
||||
if statement.is_empty() || statement_split[0].is_empty() {
|
||||
continue;
|
||||
}
|
||||
let mut program_name = statement_split[0].clone();
|
||||
|
||||
for alias in &state.aliases {
|
||||
if program_name == alias.name {
|
||||
let to_split = split_statement(&alias.to);
|
||||
for (i, item) in to_split[1..].iter().enumerate() {
|
||||
statement_split.insert(i+1, (*item).clone());
|
||||
}
|
||||
program_name = to_split[0].clone();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(builtin) = builtins::BUILTINS
|
||||
.iter()
|
||||
.find(|v| v.0 == statement_split[0])
|
||||
.find(|v| v.0 == program_name)
|
||||
{
|
||||
let status = builtin.1(statement_split, statement.to_string(), state);
|
||||
for (i, var) in state.shell_env.clone().into_iter().enumerate() {
|
||||
|
@ -181,7 +204,7 @@ fn eval(statement: &str, state: &mut State) {
|
|||
});
|
||||
continue;
|
||||
}
|
||||
match std::process::Command::new(statement_split[0].clone())
|
||||
match std::process::Command::new(program_name.clone())
|
||||
.args(&statement_split[1..])
|
||||
.current_dir(state.working_dir.clone())
|
||||
.spawn()
|
||||
|
@ -258,6 +281,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
history: Vec::new(),
|
||||
working_dir: std::env::current_dir()
|
||||
.unwrap_or(std::env::home_dir().unwrap_or(PathBuf::from("/"))),
|
||||
aliases: Vec::new(),
|
||||
};
|
||||
state.shell_env.push(ShellVar {
|
||||
name: "PROMPT1".to_string(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue