saul/src/main.rs

87 lines
2.5 KiB
Rust

// Copyright (c) 2024 Marceline Cramer
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This file is part of Saul.
//
// Saul is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Saul is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Saul. If not, see <https://www.gnu.org/licenses/>.
use std::{
borrow::Cow,
io::{self, BufRead},
};
/// Configuration of a particular language. Affects parsing and output.
pub struct Language {
/// A string that appears before all commented lines.
pub comment: Cow<'static, str>,
}
impl Language {
/// The default Rust language config.
pub const RUST: Self = Self {
comment: Cow::Borrowed("// "),
};
/// Extracts a header (as a list of lines) from an input in this language.
///
/// Don't reply on the state of the reader being consistent after this function
/// is called.
pub fn read_header(&self, f: &mut impl BufRead) -> io::Result<Vec<String>> {
let mut header = Vec::new();
let mut is_first_line = true;
for line in f.lines() {
let line = line?;
if is_first_line && line.starts_with("#!") {
is_first_line = false;
continue;
}
is_first_line = false;
let Some(content) = line.strip_prefix(self.comment.as_ref()) else {
break;
};
header.push(content.trim().to_string());
}
Ok(header)
}
}
fn main() {
println!("Hello, world!");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn header() {
let src = b"// header content\n// header content 2\nbody";
let lines = Language::RUST.read_header(&mut src.as_slice()).unwrap();
assert_eq!(lines, vec!["header content", "header content 2"]);
}
#[test]
fn skip_header_shebang() {
let src = b"#!/bin/sh\n// header content\nbody goes here";
let lines = Language::RUST.read_header(&mut src.as_slice()).unwrap();
assert_eq!(lines, vec!["header content"]);
}
}