docs: enforce documentation on all public things

Signed-off-by: Charlotte Meyer <dev@buffet.sh>
This commit is contained in:
buffet 2023-01-16 15:33:52 +01:00
parent 009947fa29
commit cafd3cafe1
10 changed files with 83 additions and 2 deletions

View file

@ -1,4 +1,6 @@
//! Contains the proc macro used to define builtins.
#![deny(unreachable_pub)]
#![warn(missing_docs)]
use darling::FromMeta;
use proc_macro::TokenStream;
@ -16,6 +18,20 @@ struct AttrArgs {
nofork: bool,
}
/// Define a built in with the given description and name.
///
/// ```rust
/// use oyster_builtin_proc::builtin;
///
/// #[builtin(
/// name = "greet", // optionally override name
/// description = "greets the user",
/// nofork = true, // optionally don't fork, required for cd and similar
/// )]
/// fn hello(_shell: &mut Shell, _args: &[Cow<OsStr>]) {
/// println!("Hello world!");
/// }
/// ```
#[proc_macro_attribute]
pub fn builtin(attr: TokenStream, item: TokenStream) -> TokenStream {
let attrs = parse_macro_input!(attr as AttributeArgs);
@ -49,7 +65,7 @@ pub fn builtin(attr: TokenStream, item: TokenStream) -> TokenStream {
};
TokenStream::from(quote! {
#[allow(non_upper_case_globals)]
#[allow(non_upper_case_globals, missing_docs)]
#vis static #ident: #builtin = {
#fn_token #ident(#inputs) #block

View file

@ -1,7 +1,10 @@
//! Readline implementation used in oyster.
#![deny(unreachable_pub)]
#![warn(missing_docs)]
use std::io::{self, Write};
/// Read a line from stdin and return it.
pub fn readline(prompt: &str) -> Result<String, io::Error> {
print!("{}", prompt);
io::stdout().flush()?;

View file

@ -1,32 +1,46 @@
//! Defines the abstract syntax tree of a valid program.
use crate::{NodeKind, ParseError, ParseEvent, Parser};
/// Abtract, lossy representation of the syntax.
/// Abtract, lossy representation of the syntax of an entire program.
#[derive(Debug)]
pub struct Code<'a>(pub Vec<Statement<'a>>);
/// A statement in a program.
#[derive(Debug)]
pub enum Statement<'a> {
/// See [Pipeline].
Pipeline(Pipeline<'a>),
}
/// A pipeline consisting of multiple commands.
#[derive(Debug)]
pub struct Pipeline<'a>(pub Vec<Command<'a>>);
/// Redirects between commands in a [Pipeline].
#[derive(Debug, Clone, Copy)]
pub enum Redirect {
/// No redirect.
None,
/// Stdout is getting redirected.
Stdout,
}
/// A command within a [Pipeline].
#[derive(Debug)]
pub struct Command<'a>(pub Vec<Word<'a>>, pub Redirect);
/// A word within a [Command].
#[derive(Debug)]
pub struct Word<'a>(pub Vec<WordPart<'a>>);
/// Part of a [Word].
/// This can be anything from different parts of a quoted string, to escaped symbols, or even
/// subcommands.
#[derive(Debug)]
pub enum WordPart<'a> {
/// Plain text.
Text(&'a str),
/// A command substitution that needs to be run first.
CommandSubstitution(Code<'a>),
}

View file

@ -1,18 +1,30 @@
use crate::{NodeKind, ParseError, ParseEvent, Parser};
/// A concrete, loss-less representation of the parsed program.
/// Only leafs contain actual code.
#[derive(Debug)]
pub enum ParseTree {
/// A sub-tree in the program.
/// These do not contain data.
Tree {
/// What kind of node are we dealing with.
kind: NodeKind,
/// The children of this tree.
children: Vec<ParseTree>,
},
/// A leaf node.
/// This contains all the code snippets.
Leaf {
/// What kind of node we are dealing with.
kind: NodeKind,
/// The length of the code referred to by this node.
len: usize,
},
/// A parse error occured.
Error {
/// Which error occured.
kind: ParseError,
/// How much code to skip until recovery?
len: usize,
},
}

View file

@ -34,7 +34,10 @@ pub enum TokenKind {
/// The parser is responsible for getting that information, if required.
#[derive(Debug)]
pub struct Token {
/// The [TokenKind] of the token.
pub kind: TokenKind,
/// How long the token is.
/// To actually get the code, you need to keep count yourself.
pub len: usize,
}

View file

@ -1,4 +1,5 @@
#![deny(unreachable_pub)]
#![warn(missing_docs)]
//! Parser for the oyster shell, the grammar is outlined below, `extras` are allowed everywhere,
//! *except* inside `word`.

View file

@ -4,6 +4,7 @@ use crate::{lexer::Lexer, Token, TokenKind};
/// Errors that might occur during parsing.
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum ParseError {
#[error("unexpected pipe")]
UnexpectedPipe,
@ -16,8 +17,12 @@ pub enum ParseError {
}
/// Type of the node.
/// For specific information refer to [TokenKind].
#[derive(Debug)]
#[allow(missing_docs)]
pub enum NodeKind {
// TokenKinds
Whitespace,
Newlines,
Semicolon,
@ -29,6 +34,8 @@ pub enum NodeKind {
EscapedChar,
Comment,
// Nodes in the tree, that appear in the cst.
Program,
CommandSubstitution,
Pipeline,
@ -36,6 +43,8 @@ pub enum NodeKind {
Word,
DQuotedString,
// Nodes in the tree, that don't appear in the cst.
/// Read a pipe but didn't start word yet.
PipelineCont,
}
@ -43,9 +52,14 @@ pub enum NodeKind {
/// Events required to build a syntax tree.
#[derive(Debug)]
pub enum ParseEvent {
/// An error occured.
Error(ParseError, usize),
/// Start a new tree node.
/// From now on, all nodes are child notes.
StartNode(NodeKind),
/// End the most recently started tree node.
EndNode,
/// A new leaf note.
NewLeaf(NodeKind, usize),
}

View file

@ -1,3 +1,4 @@
//! Standard math builtins.
use std::{
borrow::Cow,
ffi::OsStr,

View file

@ -1,3 +1,4 @@
//! Definition of all the builtin builtins, and the general framework managing builtins.
pub mod math;
use std::{borrow::Cow, collections::HashMap, ffi::OsStr};
@ -6,11 +7,18 @@ use oyster_builtin_proc::builtin;
use crate::Shell;
/// Definition of a builtin.
/// See [oyster_builtin_proc::builtin] for an easier way to generate them.
#[derive(Clone, Copy)]
pub struct Builtin {
/// Name of the builtin.
pub name: &'static str,
/// Description of the builtin, used in `help`.
pub description: &'static str,
/// Whether the builtin should fork when executed.
/// Should be false for most builtins.
pub nofork: bool,
/// The actual function to call when the builtin runs.
pub fun: fn(shell: &mut Shell, args: &[Cow<OsStr>]),
}

View file

@ -1,4 +1,7 @@
//! The runtime of the shell.
//! This contains all the code related to actually running the program.
#![deny(unreachable_pub)]
#![warn(missing_docs)]
//! The runtime for executing oyster programs.
//! Panics when an invalid ast gets passed.
@ -33,14 +36,19 @@ use thiserror::Error;
pub struct Status(pub i32);
impl Status {
/// The command succeeded.
pub const SUCCESS: Status = Status(0);
/// The command failed to execute (most likely permissions).
pub const COULD_NOT_EXEC: Status = Status(126);
/// The command could not be found.
pub const COMMAND_NOT_FOUND: Status = Status(127);
/// The base whch signals get added onto, i.e. SIGINT (2) results in 130.
pub const SIG_BASE: Status = Status(128);
}
/// Errors that occur during runtime.
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum RuntimeError {
#[error("failed to create pipe: {0}")]
PipeCreationFailed(#[source] nix::Error),
@ -67,6 +75,7 @@ pub enum RuntimeError {
IOError(#[source] io::Error),
}
/// The main "app struct", containing all the data related to the current shell instance.
pub struct Shell {
is_running: bool,
builtins: BuiltinMap,