mirror of
https://github.com/uutils/sed.git
synced 2026-06-10 16:14:15 -07:00
Create processing context out of CLI options
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 uutils
|
||||
Copyright (c) 2025 Diomidis Spinellis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Definitions for the compiled code data structures
|
||||
//
|
||||
// This file is part of the uutils sed package.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2025 Diomidis Spinellis
|
||||
//
|
||||
// This file is part of the uutils sed package.
|
||||
// It is licensed under the MIT License.
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
@@ -13,6 +16,29 @@ use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf; // For file descriptors and equivalent
|
||||
|
||||
// Compilation and processing context
|
||||
#[derive(Debug)]
|
||||
pub struct Context {
|
||||
// Input file/string and position
|
||||
pub input: String,
|
||||
pub line: usize,
|
||||
|
||||
// Command-line flags with corresponding names
|
||||
pub all_output_files: bool,
|
||||
pub debug: bool,
|
||||
pub regexp_extended: bool,
|
||||
pub follow_symlinks: bool,
|
||||
pub in_place: bool,
|
||||
pub in_place_suffix: Option<String>,
|
||||
pub length: usize,
|
||||
pub quiet: bool,
|
||||
pub posix: bool,
|
||||
pub separate: bool,
|
||||
pub sandbox: bool,
|
||||
pub unbuffered: bool,
|
||||
pub null_data: bool,
|
||||
}
|
||||
|
||||
// The specification of a script: through a string or a file
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ScriptValue {
|
||||
|
||||
+126
-3
@@ -1,5 +1,10 @@
|
||||
// This file is part of the uutils sed package.
|
||||
// Program entry point and CLI processing
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2025 Diomidis Spinellis
|
||||
//
|
||||
// This file is part of the uutils sed package.
|
||||
// It is licensed under the MIT License.
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
@@ -7,7 +12,7 @@ pub mod command;
|
||||
pub mod compiler;
|
||||
pub mod processor;
|
||||
|
||||
use crate::command::ScriptValue;
|
||||
use crate::command::{Context, ScriptValue};
|
||||
use crate::compiler::compile;
|
||||
use crate::processor::process;
|
||||
use clap::{arg, Arg, ArgMatches, Command};
|
||||
@@ -96,6 +101,8 @@ fn get_scripts_files(matches: &ArgMatches) -> UResult<(Vec<ScriptValue>, Vec<Pat
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let matches = uu_app().try_get_matches_from(args)?;
|
||||
let (scripts, files) = get_scripts_files(&matches)?;
|
||||
let _context = build_context(&matches);
|
||||
|
||||
let executable = compile(scripts)?;
|
||||
process(executable, files)?;
|
||||
Ok(())
|
||||
@@ -123,7 +130,8 @@ pub fn uu_app() -> Command {
|
||||
.short('E')
|
||||
.long("regexp-extended")
|
||||
.short_alias('r')
|
||||
.help("Use extended regular expressions."),
|
||||
.help("Use extended regular expressions.")
|
||||
.action(clap::ArgAction::SetTrue),
|
||||
arg!(-e --expression <SCRIPT> "Add script to executed commands.")
|
||||
.action(clap::ArgAction::Append),
|
||||
// Access with .get_many::<PathBuf>("file")
|
||||
@@ -160,6 +168,38 @@ pub fn uu_app() -> Command {
|
||||
])
|
||||
}
|
||||
|
||||
// Parse CLI flag arguments and return a Context struct based on them
|
||||
fn build_context(matches: &ArgMatches) -> Context {
|
||||
Context {
|
||||
input: String::new(),
|
||||
line: 1,
|
||||
|
||||
// Flags
|
||||
all_output_files: matches.get_flag("all-output-files"),
|
||||
debug: matches.get_flag("debug"),
|
||||
regexp_extended: matches.get_flag("regexp-extended"),
|
||||
follow_symlinks: matches.get_flag("follow-symlinks"),
|
||||
in_place: matches.contains_id("in-place"),
|
||||
in_place_suffix: matches.get_one::<String>("in-place").and_then(|s| {
|
||||
if s.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(s.clone())
|
||||
}
|
||||
}),
|
||||
length: matches
|
||||
.get_one::<u32>("length")
|
||||
.map(|v| *v as usize)
|
||||
.unwrap_or(70),
|
||||
quiet: matches.get_flag("quiet"),
|
||||
posix: matches.get_flag("posix"),
|
||||
separate: matches.get_flag("separate"),
|
||||
sandbox: matches.get_flag("sandbox"),
|
||||
unbuffered: matches.get_flag("unbuffered"),
|
||||
null_data: matches.get_flag("null-data"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*; // Allows access to private functions/items in this module
|
||||
@@ -257,4 +297,87 @@ mod tests {
|
||||
);
|
||||
assert_eq!(files, vec![PathBuf::from("-")]); // Stdin should be used
|
||||
}
|
||||
|
||||
fn test_matches(args: &[&str]) -> ArgMatches {
|
||||
uu_app().get_matches_from(["sed"].into_iter().chain(args.iter().copied()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_defaults() {
|
||||
let matches = test_matches(&[]);
|
||||
let ctx = build_context(&matches);
|
||||
|
||||
assert_eq!(ctx.input.len(), 0);
|
||||
assert_eq!(ctx.line, 1);
|
||||
assert!(!ctx.all_output_files);
|
||||
assert!(!ctx.debug);
|
||||
assert!(!ctx.regexp_extended);
|
||||
assert!(!ctx.follow_symlinks);
|
||||
assert!(!ctx.in_place);
|
||||
assert_eq!(ctx.in_place_suffix, None);
|
||||
assert_eq!(ctx.length, 70);
|
||||
assert!(!ctx.quiet);
|
||||
assert!(!ctx.posix);
|
||||
assert!(!ctx.separate);
|
||||
assert!(!ctx.sandbox);
|
||||
assert!(!ctx.unbuffered);
|
||||
assert!(!ctx.null_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_flags() {
|
||||
let matches = test_matches(&[
|
||||
"--all-output-files",
|
||||
"--debug",
|
||||
"-E",
|
||||
"--follow-symlinks",
|
||||
"-i",
|
||||
"-l",
|
||||
"80",
|
||||
"-n",
|
||||
"--posix",
|
||||
"-s",
|
||||
"--sandbox",
|
||||
"-u",
|
||||
"-z",
|
||||
]);
|
||||
|
||||
let ctx = build_context(&matches);
|
||||
|
||||
assert_eq!(ctx.input.len(), 0);
|
||||
assert!(ctx.all_output_files);
|
||||
assert!(ctx.debug);
|
||||
assert!(ctx.regexp_extended);
|
||||
assert!(ctx.follow_symlinks);
|
||||
assert!(ctx.in_place);
|
||||
assert!(ctx.in_place_suffix.is_none());
|
||||
assert_eq!(ctx.length, 80);
|
||||
assert!(ctx.quiet);
|
||||
assert!(ctx.posix);
|
||||
assert!(ctx.separate);
|
||||
assert!(ctx.sandbox);
|
||||
assert!(ctx.unbuffered);
|
||||
assert!(ctx.null_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_in_place_with_suffix() {
|
||||
let matches = test_matches(&["-i", ".bak"]);
|
||||
let ctx = build_context(&matches);
|
||||
|
||||
assert!(ctx.in_place);
|
||||
assert_eq!(ctx.in_place_suffix, Some(".bak".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_length_default_and_custom() {
|
||||
let matches_default = test_matches(&[]);
|
||||
let matches_custom = test_matches(&["-l", "120"]);
|
||||
|
||||
let ctx_default = build_context(&matches_default);
|
||||
let ctx_custom = build_context(&matches_custom);
|
||||
|
||||
assert_eq!(ctx_default.length, 70);
|
||||
assert_eq!(ctx_custom.length, 120);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user