Language struct + header reading

This commit is contained in:
mars 2024-02-10 15:55:37 -07:00
parent fc09286364
commit be6e6089f0
1 changed files with 65 additions and 0 deletions

View File

@ -16,6 +16,71 @@
// 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"]);
}
}