diff --git a/main.go b/main.go index f9538ab..c8a1b4e 100644 --- a/main.go +++ b/main.go @@ -126,7 +126,7 @@ func shuntingYard(re string) []postfixNode { 6. If current character is '{', find the appropriate numeric specifier (range start, range end). Apply the range to the postfixNode at the end of outQueue. */ c := re_postfix[i] - if isAlphaNum(c) { + if isNormalChar(c) { outQueue = append(outQueue, newPostfixNode(c)) continue } @@ -379,7 +379,9 @@ func main() { // 1. Without '-v': Prints only matches. Prints a newline after every match. // 2. With '-v': Substitutes all matches with empty string. onlyFlag := flag.Bool("o", false, "Print only colored content. Overrides -l.") - lineFlag := flag.Bool("l", false, "Only print lines with a match (or with no matches, if -v is enabled") + lineFlag := flag.Bool("l", false, "Only print lines with a match (or with no matches, if -v is enabled (similar to grep's default") + multiLineFLag := flag.Bool("t", false, "Multi-line mode. Treats newline just like any character.") + printMatchesFlag := flag.Bool("p", false, "Prints start and end index of each match. Can only be used with '-t' for multi-line mode.") flag.Parse() // -l and -o are mutually exclusive: -o overrides -l @@ -402,16 +404,50 @@ func main() { var test_str string var test_runes []rune // Rune-slice representation of test_str var err error - // Create reader for stdin and writer for stdout // End index is one more than last index of match + var linesRead bool // Whether or not we have read the lines in the file + // Create reader for stdin and writer for stdout reader := bufio.NewReader(os.Stdin) out := bufio.NewWriter(os.Stdout) re_postfix := shuntingYard(re) startState := thompson(re_postfix) - // Read every string from stdin until we encounter an error. If the error isn't EOF, panic.' - for test_str, err = reader.ReadString('\n'); err == nil; test_str, err = reader.ReadString('\n') { + for true { + if linesRead { + break + } + if !(*multiLineFLag) { + // Read every string from stdin until we encounter an error. If the error isn't EOF, panic. + test_str, err = reader.ReadString('\n') + if err != nil { + if err == io.EOF { + linesRead = true + } else { + panic(err) + } + } + } else { + // Multi-line mode - read every line of input into a temp. string. + // test_str will contain all lines of input (including newline characters) + // as one string. + var temp string + for temp, err = reader.ReadString('\n'); err == nil; temp, err = reader.ReadString('\n') { + test_str += temp + } + // Assuming err != nil + if err == io.EOF { + linesRead = true + } else { + panic(err) + } + } test_runes = []rune(test_str) matchIndices := findAllMatches(startState, []rune(test_runes)) + if *printMatchesFlag { + for _, idx := range matchIndices { + fmt.Printf("%s\n", idx.toString()) + } + continue + } // Decompose the array of matchIndex structs into a flat unique array of ints - if matchIndex is {4,7}, flat array will contain 4,5,6 // This should make checking O(1) instead of O(n) indicesToPrint := new_uniq_arr[int]() @@ -463,7 +499,4 @@ func main() { panic(err) } } - if err != io.EOF { - panic(err) - } }