pub mod pretty;
use crate::alias::Alias;
use std::cell::RefCell;
use std::num::NonZeroU64;
use std::ops::Range;
use std::rc::Rc;
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Source {
Unknown,
Stdin,
Alias {
original: Location,
alias: Rc<Alias>,
},
CommandSubst { original: Location },
Arith { original: Location },
Trap {
condition: String,
origin: Location,
},
}
impl Source {
pub fn is_alias_for(&self, name: &str) -> bool {
if let Source::Alias { original, alias } = self {
alias.name == name || original.code.source.is_alias_for(name)
} else {
false
}
}
pub fn label(&self) -> &str {
use Source::*;
match self {
Unknown => "<?>",
Stdin => "<stdin>",
Alias { .. } => "<alias>",
CommandSubst { .. } => "<command_substitution>",
Arith { .. } => "<arith>",
Trap { condition, .. } => condition,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Code {
pub value: RefCell<String>,
pub start_line_number: NonZeroU64,
pub source: Source,
}
pub fn source_chars<'a>(
s: &'a str,
code: &'a Rc<Code>,
index_offset: usize,
) -> impl Iterator<Item = SourceChar> + 'a {
s.chars().enumerate().map(move |(i, value)| SourceChar {
value,
location: Location {
code: Rc::clone(code),
range: index_offset + i..index_offset + i + 1,
},
})
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Location {
pub code: Rc<Code>,
pub range: Range<usize>,
}
impl Location {
#[inline]
pub fn dummy<S: Into<String>>(value: S) -> Location {
fn with_line(value: String) -> Location {
let range = 0..value.chars().count();
let code = Rc::new(Code {
value: RefCell::new(value),
start_line_number: NonZeroU64::new(1).unwrap(),
source: Source::Unknown,
});
Location { code, range }
}
with_line(value.into())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SourceChar {
pub value: char,
pub location: Location,
}