fn parse_command(&self, data: &str, command_format: &str) -> TemplateCommand {
        let mut split_command = command_format.split("*");
        let command_prefix = split_command.next().unwrap();
        let command_suffix = split_command.next().unwrap();

        let index = data.find(command_prefix).unwrap();

        let mut char_iterator = data.chars().peekable();
        char_iterator.nth(index + (command_prefix.len() - 1));

        let mut command_name = String::new();
        while char_iterator.peek().is_some() {
            let next = char_iterator.next();
            if next == command_suffix.chars().next() {
                break;
            };
            command_name.push(next.unwrap())
        }

        // println!("Parsed out command {}", command_name);

        let mut arguments: Vec<String> = Vec::new();
        let mut argument_size_in_text: usize = 0;

        // each loop advances the char iterator all the way through a command
        // so this condition may seem like it only matches continuous
        // repetitions of an open bracket ("[[[", or something) but because the
        // loop body advances char_iterator, it will loop twice on the following
        // string: "[arg1][arg2]" because the loop body will advance the char
        // iterator 6 characters (the length of "[arg1]"), in the process of
        // parsing out its value.
        // note that it doesn't skip whitespace, so a command like "!{command1}[argument1] [argument2]"
        // will only have argument1 parsed out and "[argument2]" will be treated as text
        // that has nothing to do with the command
        while char_iterator.next().unwrap_or('_') == '[' {
            // println!("Bang also has arguments!");
            let mut argument = String::new();
            while char_iterator.peek().is_some() {
                let next = char_iterator.next();
                if next.unwrap_or(']') == ']' {
                    break;
                };
                argument.push(next.unwrap())
            }
            // println!("Which is {:?}", argument);

            // this 2 compensates for the two brackets that
            // surround each argument
            // we have the length of the arguments plus
            // the two bracket characters we omitted
            argument_size_in_text += 2 + argument.len();
            arguments.push(argument);
        }

        return TemplateCommand {
            arguments: arguments,
            start_index: index,
            total_length: command_prefix.len()
                + command_name.len()
                + command_suffix.len()
                + argument_size_in_text,
            name: command_name,
        };
    }
// finds an instance of a command somewhere in the data parameter
// returns a TemplateCommand with the arguments that the command
// have and the char position of the command so you can replace
// the text.
// It takes a command format that expects an asterisk where
// the command name is.
// For example, to find a bang, you would use !{*},
// which matches anything that starts with "!{", has the name here, and then ends with "}".
// so the command_format "!{*}" will match "!{myBang}" or "!{makeTitle}" or "!{todaysDate}"
// then it will search the end of that command for an argument in square brackets,
// with more arguments following the brackets
// for example, "${myCommand}[myArgument1]" or "#{myCommand}[myArgument1][myArgument2][myArgument3]"
// however, arguments are hardcoded and the same between all command_formats
// therefore you don't include them in command_format.
// a few possible command formats are: "${*}", "#{*}", "~{*}"
// it is critically important that * is not the last character
// of a command_format, because it will match all of the rest
// of the template as a command_name, and then it will look for
// brackets after the end of the file, which will not end well.
// so all commands need to have their * enclosed in some way.
finds an instance of a command somewhere in the data parameter
returns a TemplateCommand with the arguments that the command
have and the char position of the command so you can replace
the text.
It takes a command format that expects an asterisk where
the command name is.
For example, to find a bang, you would use !{*},
which matches anything that starts with "!{", has the name here, and then ends with "}".
finds an instance of a command somewhere in the data parameter returns a TemplateCommand with the arguments that the command have and the char position of the command so you can replace the text . It takes a command format that expects an asterisk where the command name is . For example to find a bang you would use ! { * } which matches anything that starts with " ! { " has the name here and then ends with " } " .
fn parse_command(&self, data: &str, command_format: &str) -> TemplateCommand {
        let mut split_command = command_format.split("*");
        let command_prefix = split_command.next().unwrap();
        let command_suffix = split_command.next().unwrap();
        let index = data.find(command_prefix).unwrap();
        let mut char_iterator = data.chars().peekable();
        char_iterator.nth(index + (command_prefix.len() - 1));
        let mut command_name = String::new();
        while char_iterator.peek().is_some() {
            let next = char_iterator.next();
            if next == command_suffix.chars().next() {
                break;
            };
            command_name.push(next.unwrap())
        }
        // println!("Parsed out command {}", command_name);
        let mut arguments: Vec<String> = Vec::new();
        let mut argument_size_in_text: usize = 0;
        // each loop advances the char iterator all the way through a command
        // so this condition may seem like it only matches continuous
        // repetitions of an open bracket ("[[[", or something) but because the
        // loop body advances char_iterator, it will loop twice on the following
        // string: "[arg1][arg2]" because the loop body will advance the char
        // iterator 6 characters (the length of "[arg1]"), in the process of
        // parsing out its value.
        // note that it doesn't skip whitespace, so a command like "!{command1}[argument1] [argument2]"
        // will only have argument1 parsed out and "[argument2]" will be treated as text
        // that has nothing to do with the command
        while char_iterator.next().unwrap_or('_') == '[' {
            // println!("Bang also has arguments!");
            let mut argument = String::new();
            while char_iterator.peek().is_some() {
                let next = char_iterator.next();
                if next.unwrap_or(']') == ']' {
                    break;
                };
                argument.push(next.unwrap())
            }
            // println!("Which is {:?}", argument);
            // this 2 compensates for the two brackets that
            // surround each argument
            // we have the length of the arguments plus
            // the two bracket characters we omitted
            argument_size_in_text += 2 + argument.len();
            arguments.push(argument);
        }
        return TemplateCommand {
            arguments: arguments,
            start_index: index,
            total_length: command_prefix.len()
                + command_name.len()
                + command_suffix.len()
                + argument_size_in_text,
            name: command_name,
        };
    }
fn parse_command ( & self , data : & str , command_format : & str ) -> TemplateCommand { let mut split_command = command_format . split ( " " ) ; let command_prefix = split_command . next ( ) . unwrap ( ) ; let command_suffix = split_command . next ( ) . unwrap ( ) ; let index = data . find ( command_prefix ) . unwrap ( ) ; let mut char_iterator = data . chars ( ) . peekable ( ) ; char_iterator . nth ( index + ( command_prefix . len ( ) - 1 ) ) ; let mut command_name = String :: new ( ) ; while char_iterator . peek ( ) . is_some ( ) { let next = char_iterator . next ( ) ; if next == command_suffix . chars ( ) . next ( ) { break ; } ; command_name . push ( next . unwrap ( ) ) } // println!("Parsed out command {}", command_name); let mut arguments : Vec < String > = Vec :: new ( ) ; let mut argument_size_in_text : usize = 0 ; // each loop advances the char iterator all the way through a command // so this condition may seem like it only matches continuous // repetitions of an open bracket ("[[[", or something) but because the // loop body advances char_iterator, it will loop twice on the following // string: "[arg1][arg2]" because the loop body will advance the char // iterator 6 characters (the length of "[arg1]"), in the process of // parsing out its value. // note that it doesn't skip whitespace, so a command like "!{command1}[argument1] [argument2]" // will only have argument1 parsed out and "[argument2]" will be treated as text // that has nothing to do with the command while char_iterator . next ( ) . unwrap_or ( '_' ) == '[' { // println!("Bang also has arguments!"); let mut argument = String :: new ( ) ; while char_iterator . peek ( ) . is_some ( ) { let next = char_iterator . next ( ) ; if next . unwrap_or ( ']' ) == ']' { break ; } ; argument . push ( next . unwrap ( ) ) } // println!("Which is {:?}", argument); // this 2 compensates for the two brackets that // surround each argument // we have the length of the arguments plus // the two bracket characters we omitted argument_size_in_text += 2 + argument . len ( ) ; arguments . push ( argument ) ; } return TemplateCommand { arguments : arguments , start_index : index , total_length : command_prefix . len ( ) + command_name . len ( ) + command_suffix . len ( ) + argument_size_in_text , name : command_name , } ; }
finds an instance of a command somewhere in the data parameter
returns a TemplateCommand with the arguments that the command
have and the char position of the command so you can replace
the text.
finds an instance of a command somewhere in the data parameter returns a TemplateCommand with the arguments that the command have and the char position of the command so you can replace the text .
&self
data
&str
command_format
&str