slash-lang 0.1.0

Parser and AST for the slash-command language
Documentation
use crate::parser::ast::Urgency;

/// Strips trailing `!` markers (urgency). Returns `Some((bare, urgency))` for 0–3, `None` for 4+.
pub fn strip_urgency(token: &str) -> Option<(&str, Urgency)> {
    let bare = token.trim_end_matches('!');
    let count = token.len() - bare.len();
    let urgency = match count {
        0 => Urgency::None,
        1 => Urgency::Low,
        2 => Urgency::Medium,
        3 => Urgency::High,
        _ => return None,
    };
    Some((bare, urgency))
}

/// Strips trailing `+` or `-` markers (verbosity). Returns `(bare, verbosity)`.
/// Positive = more verbose, negative = quieter. Each additional `+`/`-` adds one level.
/// Saturates at `i8::MAX` / `i8::MIN` to avoid overflow.
pub fn strip_verbosity(token: &str) -> (&str, i8) {
    if token.ends_with('+') {
        let bare = token.trim_end_matches('+');
        let count = token.len() - bare.len();
        (bare, count.min(i8::MAX as usize) as i8)
    } else if token.ends_with('-') {
        let bare = token.trim_end_matches('-');
        let count = token.len() - bare.len();
        (bare, -(count.min(i8::MAX as usize) as i8))
    } else {
        (token, 0)
    }
}

/// Strips a single trailing `?` (optional return). Returns `Ok((bare, optional))`.
/// Returns `Err(())` if the token ends with `??` (double optional is invalid).
#[allow(clippy::result_unit_err)]
pub fn strip_optional(token: &str) -> Result<(&str, bool), ()> {
    match token.strip_suffix('?') {
        Some(bare) if bare.ends_with('?') => Err(()),
        Some(bare) => Ok((bare, true)),
        None => Ok((token, false)),
    }
}