Implemented assignments, working on job control

This commit is contained in:
2025-03-15 16:56:53 -04:00
parent 97b4b1835d
commit 2acf70ef96
25 changed files with 1390 additions and 280 deletions

View File

@@ -1,25 +1,40 @@
use std::{fmt::Display, str::FromStr};
use std::{fmt::Display, ops::Range, str::FromStr};
use crate::{parse::lex::Span, prelude::*};
pub type ShResult<'s,T> = Result<T,ShErr<'s>>;
pub type ShResult<T> = Result<T,ShErr>;
#[derive(Debug)]
pub enum ShErr<'s> {
Simple { kind: ShErrKind, msg: String },
Full { kind: ShErrKind, msg: String, span: Span<'s> }
pub struct ErrSpan {
range: Range<usize>,
source: String
}
impl<'s> ShErr<'s> {
impl<'s> From<Span<'s>> for ErrSpan {
fn from(value: Span<'s>) -> Self {
let range = value.range();
let source = value.get_source().to_string();
Self { range, source }
}
}
#[derive(Debug)]
pub enum ShErr {
Simple { kind: ShErrKind, msg: String },
Full { kind: ShErrKind, msg: String, span: ErrSpan }
}
impl<'s> ShErr {
pub fn simple(kind: ShErrKind, msg: impl Into<String>) -> Self {
let msg = msg.into();
Self::Simple { kind, msg }
}
pub fn full(kind: ShErrKind, msg: impl Into<String>, span: Span<'s>) -> Self {
let msg = msg.into();
let span = span.into();
Self::Full { kind, msg, span }
}
pub fn unpack(self) -> (ShErrKind,String,Option<Span<'s>>) {
pub fn unpack(self) -> (ShErrKind,String,Option<ErrSpan>) {
match self {
ShErr::Simple { kind, msg } => (kind,msg,None),
ShErr::Full { kind, msg, span } => (kind,msg,Some(span))
@@ -27,11 +42,12 @@ impl<'s> ShErr<'s> {
}
pub fn with_span(sherr: ShErr, span: Span<'s>) -> Self {
let (kind,msg,_) = sherr.unpack();
let span = span.into();
Self::Full { kind, msg, span }
}
}
impl<'s> Display for ShErr<'s> {
impl Display for ShErr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Simple { msg, kind: _ } => writeln!(f, "{}", msg),
@@ -40,26 +56,26 @@ impl<'s> Display for ShErr<'s> {
}
}
impl<'s> From<std::io::Error> for ShErr<'s> {
impl From<std::io::Error> for ShErr {
fn from(_: std::io::Error) -> Self {
let msg = std::io::Error::last_os_error();
ShErr::simple(ShErrKind::IoErr, msg.to_string())
}
}
impl<'s> From<std::env::VarError> for ShErr<'s> {
impl From<std::env::VarError> for ShErr {
fn from(value: std::env::VarError) -> Self {
ShErr::simple(ShErrKind::InternalErr, &value.to_string())
}
}
impl<'s> From<rustyline::error::ReadlineError> for ShErr<'s> {
impl From<rustyline::error::ReadlineError> for ShErr {
fn from(value: rustyline::error::ReadlineError) -> Self {
ShErr::simple(ShErrKind::ParseErr, &value.to_string())
}
}
impl<'s> From<Errno> for ShErr<'s> {
impl From<Errno> for ShErr {
fn from(value: Errno) -> Self {
ShErr::simple(ShErrKind::Errno, &value.to_string())
}

144
src/libsh/flog.rs Normal file
View File

@@ -0,0 +1,144 @@
use std::fmt::Display;
use super::term::{Style, Styled};
#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq , Debug)]
#[repr(u8)]
pub enum FernLogLevel {
NONE = 0,
ERROR = 1,
WARN = 2,
INFO = 3,
DEBUG = 4,
TRACE = 5
}
impl Display for FernLogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use FernLogLevel::*;
match self {
ERROR => write!(f,"{}","ERROR".styled(Style::Red | Style::Bold)),
WARN => write!(f,"{}","WARN".styled(Style::Yellow | Style::Bold)),
INFO => write!(f,"{}","INFO".styled(Style::Green | Style::Bold)),
DEBUG => write!(f,"{}","DEBUG".styled(Style::Magenta | Style::Bold)),
TRACE => write!(f,"{}","TRACE".styled(Style::Blue | Style::Bold)),
NONE => write!(f,"")
}
}
}
pub fn log_level() -> FernLogLevel {
use FernLogLevel::*;
let level = std::env::var("FERN_LOG_LEVEL").unwrap_or_default();
match level.to_lowercase().as_str() {
"error" => ERROR,
"warn" => WARN,
"info" => INFO,
"debug" => DEBUG,
"trace" => TRACE,
_ => NONE
}
}
/// A structured logging macro designed for `fern`.
///
/// `flog!` was implemented because `rustyline` uses `env_logger`, which clutters the debug output.
/// This macro prints log messages in a structured format, including the log level, filename, and line number.
///
/// # Usage
///
/// The macro supports three types of arguments:
///
/// ## 1. **Formatted Messages**
/// Similar to `println!` or `format!`, allows embedding values inside a formatted string.
///
/// ```rust
/// flog!(ERROR, "foo is {}", foo);
/// ```
/// **Output:**
/// ```plaintext
/// [ERROR][file.rs:10] foo is <value of foo>
/// ```
///
/// ## 2. **Literals**
/// Directly prints each literal argument as a separate line.
///
/// ```rust
/// flog!(WARN, "foo", "bar");
/// ```
/// **Output:**
/// ```plaintext
/// [WARN][file.rs:10] foo
/// [WARN][file.rs:10] bar
/// ```
///
/// ## 3. **Expressions**
/// Logs the evaluated result of each given expression, displaying both the expression and its value.
///
/// ```rust
/// flog!(INFO, 1.min(2));
/// ```
/// **Output:**
/// ```plaintext
/// [INFO][file.rs:10] 1
/// ```
///
/// # Considerations
/// - This macro uses `eprintln!()` internally, so its formatting rules must be followed.
/// - **Literals and formatted messages** require arguments that implement [`std::fmt::Display`].
/// - **Expressions** require arguments that implement [`std::fmt::Debug`].
#[macro_export]
macro_rules! flog {
($level:path, $fmt:literal, $($args:expr),+ $(,)?) => {{
use $crate::libsh::flog::log_level;
use $crate::libsh::term::Styled;
use $crate::libsh::term::Style;
if $level <= log_level() {
let file = file!().styled(Style::Cyan);
let line = line!().to_string().styled(Style::Cyan);
eprintln!(
"[{}][{}:{}] {}",
$level, file, line, format!($fmt, $($args),+)
);
}
}};
($level:path, $($val:expr),+ $(,)?) => {{
use $crate::libsh::flog::log_level;
use $crate::libsh::term::Styled;
use $crate::libsh::term::Style;
if $level <= log_level() {
let file = file!().styled(Style::Cyan);
let line = line!().to_string().styled(Style::Cyan);
$(
let val_name = stringify!($val);
eprintln!(
"[{}][{}:{}] {} = {:#?}",
$level, file, line, val_name, &$val
);
)+
}
}};
($level:path, $($lit:literal),+ $(,)?) => {{
use $crate::libsh::flog::log_level;
use $crate::libsh::term::Styled;
use $crate::libsh::term::Style;
if $level <= log_level() {
let file = file!().styled(Style::Cyan);
let line = line!().to_string().styled(Style::Cyan);
$(
eprintln!(
"[{}][{}:{}] {}",
$level, file, line, $lit
);
)+
}
}};
}

View File

@@ -1,2 +1,3 @@
pub mod error;
pub mod term;
pub mod flog;