Coder Social home page Coder Social logo

crust's Introduction

 ▄████████    ▄████████ ███    █▄     ▄████████     ███
███    ███   ███    ███ ███    ███   ███    ███ ▀█████████▄
███    █▀    ███    ███ ███    ███   ███    █▀     ▀███▀▀██
███         ▄███▄▄▄▄██▀ ███    ███   ███            ███   ▀
███        ▀▀███▀▀▀▀▀   ███    ███ ▀███████████     ███    
███    █▄  ▀███████████ ███    ███          ███     ███    
███    ███   ███    ███ ███    ███    ▄█    ███     ███    
████████▀    ███    ███ ████████▀   ▄████████▀     ▄████▀  
             ███    ███

crusty mascot

^ Say hello to crust's mascot :D ^

crust is a WIP shell written in Rust by Phate6660 and Zenomat.

Some of the functionality is split off into features, to reduce the amount of crates pulled in by default. They are:

  • colors (for colorized output in ls (and other builtins once implemented))
  • readline (a default feature (but can be turned off), for having a nice interactible prompt)
    • when disabled, you'll have very basic line input (think of shells like dash)
    • NOTE: the prompt is customizable regardless of whether or not you choose to enable the feature
  • time (for getting the time with the %{D12} and %{D24} variables)

If you don't want any features at all, then build or run with the arg --no-default-features.

Running

To run an interactive shell:
cargo run --release

To run a non-interactive shell with a command:
cargo run --release -- -c "echo test | sed s/test/success/g"

Roadmap

Shell

FEATURE TODO WIP DONE
Basic commands X
CMDs with args X
Paging X
Piping X
Prompt X
Redirection X
Builtins X
Config file X
Job control X
Line editor X
Env variables X
Scripting X

Prompt

FEATURE TODO WIP DONE
Automatically update X
Colors X
Command output X
File content X
Replaceable variables X
Set via env var X

The default prompt looks like:
Default Prompt

Customize the prompt by setting the PROMPT variable in the environment or through the config.
What you can use in the prompt:

Information variables:

  • %{CL} for the full current working directory (e.g. /home/valley/projects/crust).
  • %{CS} for the short current working directory (e.g. crust).
  • %{D} for the date (e.g. Wed Dec 15).
  • %{H} for the current user's home directory.
  • %{T12} and %{T24} for 12 and 24 hour time respectively.
  • %{U} for the current user.
  • %(command) for capturing the output of command.
  • %[file] to get the contents of file.

Formatting:

  • %{b} to make text bold.
  • %{i} to italicize text.
  • %{rb} to reset the background color.
  • %{re} to reset all text attributes.
  • %{rf} to reset the text color.
  • %{u} to underline text.
  • B<COLOR> for changing the background color.
  • F<COLOR> for changing the text color.
  • \n for newline.
  • Anything else will be printed as-is.

COLOR should be replaced with one of:

  • BLACK
  • RED
  • GREEN
  • YELLOW
  • BLUE
  • MAGENTA
  • CYAN
  • WHITE

Example for formatting:
PROMPT="%{b}F<MAGENTA>%{T24}%{re} - %{i}%{U}@%(hostname)%{re}\nB<GREEN>F<BLACK>%{CL}%{re}» "
Which for me looks like this:
Customized Prompt
This showcases a multiline prompt with different foreground and background colors, as well as a command substitution and shell-prompt-features, like time and user.

Line Editing

Basic Line Editing
FEATURE TODO WIP DONE
Command Input X
Arrow Keys X
Backspace X
Rustyline
FEATURE TODO WIP DONE
Basic line editing X
Command history X
Completions X
Modifiable keybindings X
Syntax highlighting X

Builtins

calc

FEATURE TODO WIP DONE
Basic math X
Equations X
PEMDAS X

cat

FEATURE TODO WIP DONE
Read file X
Print line numbers X
Print specific line X
Paging support X
Syntax highlighting X

cd

FEATURE TODO WIP DONE
Exact paths X
Relative paths X
Previous dir X

echo

FEATURE TODO WIP DONE
Basic output X
Escape sequences X

help

FEATURE TODO WIP DONE
Invidual helps for builtins X
List builtins X
Quick start / tutorial X

ls

FEATURE TODO WIP DONE
Basic colored output X
Cross-platform X
List files X
Additional details X

Config File

OPTION TODO WIP DONE
Edit mode X
History auto add lines X
History file X
History ignore spaces X
History size X
Prompt X

Notes:

  • A default config is created for you if non-existant, look at example-config in the repo for an example.
  • Comments (lines that start with *) or ignored.
  • Invalid options are ignored and a warning is issued.

crust's People

Contributors

phate6660 avatar theonandonlyzenomat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

crust's Issues

Can't run pagers

While fixing the quoted args issue, I found, that we aren't able to run pagers like less or more, as well as the programs depending on it, like man or info.
When trying to run a pager, crusty just doesn't to anything.
I don't know if this is a known issue, but one definitely worth addressing.
@Phate6660 do you have an idea what is causing this?

Updating branches to reflect current codebase

For example, the configuration branch does not reflect the current master branch, so updating code could cause trouble when merging.
How should I handle this? Just merge master into the branch?

Begin work on lexing and parsing

Currently the REPL is very basic.
It uses basic pattern matching features on larger variable contents.
It's about to time to implement a lexer and parser to more accurately scan the line being entered.
And once I get lexing and parsing set up I can get going on the shell scripting side of things.

Add test cases to the project to help streamline, well, testing

A current WIP I have modifies process_input() and ShellCommand::run(), to make them return a bool for if the command succeeded. Which the test function in src/test.rs will test for. Here is a gist containing a diff of the current source files, as well as the src/test.rs file so you can see what I did for sure.

Personally, I feel could definitely be done much better.
So I thought I should ping you @TheOnAndOnlyZenomat.
You've contributed a lot, and I'd like your input on this.

The idea is to be able test that:

  • builtins (calc, echo, etc)
  • external commands (grep, sed, etc)
  • whatever other shell parts

Are working properly all with a single cargo test.
It should also help alleviate the faulty CI.

Add case in parsing a command for quoted args

Happened to find this bug when git commiting in crusty.
Since the shell is splitting based on whitespace, we need to add a special case to treat everything in quotations as a single arg.
Making this issue to get it tracked, but I plan to take care of it tonight :D

Edit: Ok, this might take a little bit. I can see a solution, but I'm looking at a very hacky-mathy solution.
The way I'm looking at it, if the command line contains quotes, we'll create 2 vectors:

  • split_input
  • input_quote_vec -- this is the new one, where we split based on quotation

Then we math to figure out which elements of the split_input vector need to be,
removed/replaced to contain what we want in the input_quote_vec.

I kind of feel like this solution is too complex though.
Do you have an opinion @TheOnAndOnlyZenomat?

rustfmt.toml

Working on configuring rustfmt so I can minimize the amount of stuff I need to fix after formatting.
Currently, the configuration I have setup is:

chain_width                = 80
# Don't combine control expressions with function calls.
combine_control_expr       = false
# Replace multiple `_` with a single `..` in tuple patterns.
condense_wildcard_suffixes = true
# Flatten any single-line expressions.
fn_single_line             = true
# Format string literals if they are too long.
format_strings             = true
# Set the layout of imports in a block.
imports_layout             = "HorizontalVertical"
# Include leading pipes in match statements for easier visuals.
match_arm_leading_pipes    = "Always"
# Put a trailing comma after a block-based match arm.
match_block_trailing_comma = true
# Set the max code width to 120.
# This will automatically set the margins of a lot of other options.
max_width                  = 120
# When structs, slices, arrays, and block/array-like macros are 
# used as the last argument in an expression list, allow them to overflow 
# (like blocks/closures) instead of being indented on a new line.
overflow_delimited_expr    = true
# Reports TODOs in the code.
report_todo                = "Always"
# Removes commas from the last element.
trailing_comma             = "Never"
unstable_features          = true
wrap_comments              = true

How do you feel about it @TheOnAndOnlyZenomat?
Anything else you would want to add or modify?

Optimizations

I went through and started benchmarking with perf, valgrind, etc.
Major things I'm noticing that need to be optimized are:

  • statements using clone, they take a lot more time and resources than anything else
    • clone statements were taking over 30% of the time used in the program!
  • reading/writing files
  • the pipeline for running the commands and gathering output

Builtins print their own output after piping

I noticed, that builtins print their own output, even after piping.
e.g.:

echo hello | figlet

prints

 _          _ _                            _     _
| |__   ___| | | ___   __      _____  _ __| | __| |
| '_ \ / _ \ | |/ _ \  \ \ /\ / / _ \| '__| |/ _` |
| | | |  __/ | | (_) |  \ V  V / (_) | |  | | (_| |
|_| |_|\___|_|_|\___/    \_/\_/ \___/|_|  |_|\__,_|


hello world | figlet

This doesn't happen with /usr/bin/echo, and I also tested with ls and calc. So I guess,that they handle their arguments, but don't stop at the redirection char.

Unify lexing and parsing interface

Just leaving this and a couple other issues as a reminder.

This one will focus on tracking the unification of lexing and parsing, in which we currently have 2 separate implementations for.

Pagers don't properly work

When running pagers, e.g. less, more, and programs depending on pagers, e.g. man, info, they either just output the file contents or man contents, without pager functionality, or just plain don't work and hang.

Repo / README renovation

So, I have a few things planned:

  • Rename the project (to either rush or crust)
  • Update the README to use a format that supports embeds*
  • Create a logo and/or mascot for the project (I'll be making them in Blender/GIMP)

* I don't really want to go with the standard markdown or rst to be honest.
In my opinion, it should be something simple with minimal/plaintext styling by default, but can be more robust.

Pinging @TheOnAndOnlyZenomat for any opinions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.