haematite-cli 0.21.1

The haematite command: serve a store, its door and Studio, answer MCP, query with jq, and host the store's assistant seat
Documentation
//! Outside quotes, stage braces belong to the pipeline grammar before jq admission.

use super::super::parser::{Plan, Refused, Source, Stage};
use crate::serve::storage::Failure;

pub(super) fn parse(text: &str) -> Result<Result<Plan, Refused>, Failure> {
    let parsed = super::rg::parsed(text)?;
    if braces(text) {
        parsed
            .map(Ok)
            .map_err(|error| Failure::new(error.code(), error.to_string()))
    } else {
        Ok(parsed)
    }
}

pub(super) fn shaped(plan: &Plan) -> bool {
    matches!(plan.source, Source::Shaped(_))
        || plan
            .stages
            .iter()
            .any(|stage| matches!(stage.value, Stage::Shape(_)))
}

/// Compile the selected jq program when shape syntax has fixed the pipeline reading.
pub(super) fn program(text: &str, parsed: &Result<Plan, Refused>) -> String {
    match parsed {
        Ok(plan) if shaped(plan) => super::plan::jq(plan).to_owned(),
        _ => text.to_owned(),
    }
}

fn braces(text: &str) -> bool {
    let mut quote = None;
    let mut escaped = false;
    let mut depth = 0_usize;
    let mut beginning = true;
    for character in text.chars() {
        if let Some(delimiter) = quote {
            if escaped {
                escaped = false;
            } else if character == '\\' && delimiter == '"' {
                escaped = true;
            } else if character == delimiter {
                quote = None;
            }
            continue;
        }
        if beginning && character.is_whitespace() {
            continue;
        }
        if beginning && character == '{' {
            return true;
        }
        beginning = false;
        match character {
            '\'' | '"' => quote = Some(character),
            '(' | '[' | '{' => depth += 1,
            ')' | ']' | '}' => depth = depth.saturating_sub(1),
            '|' if depth == 0 => beginning = true,
            _ => {}
        }
    }
    false
}