1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use clap::Parser;
use regex::Regex;
/// Represents the configuration options for PyTV.
#[derive(Debug)]
pub struct Config {
/// The magic comment string used to identify template sections in the input file.
pub magic_comment_str: String,
/// The regular expression used to match template sections in the input file.
pub template_re: Regex,
/// Whether to run the Python script or not.
pub run_python: bool,
/// Whether to delete the Python script after running or not.
pub delete_python: bool,
/// The tab size used for parsing in the input file.
pub tab_size: u32,
}
/// Represents the options for input and output file for PyTV.
#[derive(Debug, Default)]
pub struct FileOptions {
/// The input file path.
pub input: String,
/// The output file path (optional).
pub output: Option<String>,
}
impl Default for Config {
/// Creates a new `Config` instance with default values.
fn default() -> Self {
Self::new(
"!".to_string(),
Self::default_template_re(),
false,
false,
4,
)
}
}
/// Python Templated Verilog
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
/// Input file
#[arg(index = 1, value_name = "FILE")]
input: String,
/// Output file
#[arg(short, long)]
output: Option<String>,
/// Run python (keep Python script)
#[arg(
short = 'r',
long = "run-py",
conflicts_with = "run_python_del",
default_value = "false"
)]
run_python: bool,
/// Run python (delete Python script)
#[arg(
short = 'R',
long = "run-py-del",
conflicts_with = "run_python",
default_value = "false"
)]
run_python_del: bool,
/// Tab size
#[arg(short, long, default_value = "4", value_name = "INT")]
tab_size: u32,
/// Magic comment string (after "//")
#[arg(short, long, default_value = "!", value_name = "STRING")]
magic: String,
}
impl Config {
/// Creates a new `Config` instance with the specified values.
///
/// # Example
/// ```
/// use pytv::Config;
/// use regex::Regex;
/// let config = Config::new("!".to_string(), Regex::new(r"`([^`]+)`").unwrap(), false, false, 4);
/// let default_config = Config::default();
/// assert_eq!(config.magic_comment_str, default_config.magic_comment_str);
/// ```
pub fn new(
magic_comment_str: String,
template_re: Regex,
run_python: bool,
delete_python: bool,
tab_size: u32,
) -> Config {
Config {
magic_comment_str,
template_re,
run_python,
delete_python,
tab_size,
}
}
/// Parses the command line arguments and returns a tuple of `Config` and `FileOptions`.
pub fn from_args() -> (Config, FileOptions) {
let args = Args::parse();
(
Self::new(
args.magic,
Self::default_template_re(),
args.run_python || args.run_python_del,
args.run_python_del && !args.run_python,
args.tab_size,
),
FileOptions {
input: args.input,
output: args.output,
},
)
}
/// Returns the default regular expression used to match template sections in the input file.
fn default_template_re() -> Regex {
Regex::new(r"`([^`]+)`").unwrap()
}
}