Skip to content

Instantly share code, notes, and snippets.

@nixpulvis
Last active April 30, 2023 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nixpulvis/59d4f60db401f4b3fba6d6781063c7f5 to your computer and use it in GitHub Desktop.
Save nixpulvis/59d4f60db401f4b3fba6d6781063c7f5 to your computer and use it in GitHub Desktop.
# Commands to be executed directly by this shell.
BUILTINS = {}
# The builtin `cd` for changing the shell's working directory.
BUILTINS['cd'] = lambda do |args|
# Change to the home directory by default.
args << ENV['HOME'] if args.empty?
# Read the destination path, doing very basic path expansion.
dest = args.pop.gsub(/~/, ENV['HOME'])
# Try to change this shell's working directory.
begin
Dir.chdir(dest)
rescue Exception
puts("no such directory: #{dest}")
end
end
# The builtin to exit the shell.
BUILTINS['exit'] = lambda do |args|
# Exit with a status of 0 by default.
args << 0 if args.empty?
# Exit the shell.
exit args.pop.to_i
end
# Print a prompt, then read a line from STDIN.
def read
print('$ ')
# Try to read a line, exiting if there's no more lines.
line = STDIN.gets
if line
line.chomp.split(' ')
else
exit
end
end
# Run the given command in a subprocess.
def evaluate(argv)
if BUILTINS[argv[0]]
BUILTINS[argv[0]].call(argv[1..-1])
else
success = system(*argv)
unless success
puts("unknown command '#{argv[0]}'")
end
end
end
# Don't exit on `SIGINT`, instead simply return a new prompt.
trap('INT') { print("\n$ ") }
# The glorious REPL itself.
loop { evaluate(read) }
use std::io::{self, Read, Write};
use std::process::{Command, Output};
use std::str;
// Our shell, for the greater good. Ready and waiting.
fn main() {
// Standard input file descriptor (0), used for user input from the user
// of the shell.
let mut stdin = io::stdin();
// Standard output file descriptor (1), used to display program output to
// the user of the shell.
let mut stdout = io::stdout();
// STDIN, input buffer, used to `read` text into for further processing.
// TODO: Full fledged parser will be neato.
let mut input = [0; 24];
loop {
// XXX: Blindly drop the contents of input, again this will be better
// with a real parser.
input = [0; 24];
// Print a boring static prompt.
print!("oursh> ");
stdout.lock().flush();
loop {
// TODO: Enable raw access to STDIN, so we can read as the user
// types. By default the underlying file is line buffered. This
// will allow us to process history, syntax, and more!
// Read what's avalible to us.
stdin.read(&mut input).expect("error reading STDIN");
// Once we've read a complete "program" (§2.10.2) we handle it,
// until then we keep reading. Once we have a proper parser this
// wont look like a huge hack.
let vec: Vec<&[u8]> = input.splitn(2, |b| *b == '\n' as u8).collect();
match &vec[..] {
[line, rest] => {
let program = str::from_utf8(&line).expect("error reading utf8");
let mut output = handle_program(program);
stdout.write(&output.stdout).expect("error writing to STDOUT");
break
}
_ => {},
}
}
}
}
// Obviously very wrong. Most notably this blocks until the command completes.
fn handle_program(program: &str) -> Output {
Command::new(program)
.output()
.expect("error executing program")
}
@nixpulvis
Copy link
Author

oursh progress

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Rust                             7            100            478            594
-------------------------------------------------------------------------------

@nixpulvis
Copy link
Author

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Rust                            30            296            788           2257

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment