public raw_filter_row(string text, bool apply_to_existing_lines) { this.apply_to_existing_lines = apply_to_existing_lines; List <filter_line> lines = new List <filter_line>(); List <addition> additions = new List <addition>(); lines_ = text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines_) { filter_line item = filter_line.parse(line); if (item != null) { lines.Add(item); } addition add = addition.parse(line); if (add != null) { additions.Add(add); } bool is_comment = line.StartsWith("#"), is_empty = line.Trim() == ""; if (!is_comment && !is_empty && !filter_line.is_color_or_font_line(line)) { unique_id_ += line.Trim() + "\r\n"; } if (item == null && add == null) { if (!is_comment && !is_empty) { // in this case, the line is not valid yet valid_ = false; } } } unique_id_ += "" + apply_to_existing_lines; font_ = font_info.default_font_copy; init(lines, additions); if (items_.Count < 1) { valid_ = false; } }
// note: in the future, we might allow for more "font" data - at that point, I'll think about the syntax // // at this point, we allow a simple "color" line: // color fg [bg] private static filter_line parse_font(string line) { // future: if "font" -> account for that as well Debug.Assert(is_color_or_font_line(line)); bool is_color = line.StartsWith("color"); string[] colors = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); filter_line fi = new filter_line(line) { part = part_type.font }; if (colors.Length >= 2) { if (is_color) { fi.fi.fg = util.str_to_color(colors[1]); } else { fi.fi.match_fg = util.str_to_color(colors[1]); } } if (colors.Length >= 3) { if (is_color) { fi.fi.bg = util.str_to_color(colors[2]); } else { fi.fi.match_bg = util.str_to_color(colors[2]); } } return(fi); }
// tries to parse a line - if it fails, it will return null private static filter_line parse_impl(string line) { line = line.Trim(); if (line.StartsWith("#")) { // allow comments return(null); } if (line.StartsWith("font") || line.StartsWith("color") || line.StartsWith("match_color")) { return(parse_font(line)); } if (line == "case-insensitive") { return new filter_line(line) { part = part_type.case_sensitive_info, case_sensitive = false } } ; if (!line.StartsWith("$")) { return(null); } string[] words = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); // Syntax: // $ColumnName Comparison Text bool ok = words.Length >= 3 || (words.Length == 2 && is_regex_expression(words[1])); if (!ok) { // we need at least $c compare word(s) return(null); } filter_line fi = new filter_line(line); fi.part = part_type_io.from_str(words[0]); if (fi.part == part_type.invalid) { return(null); } if (words.Length == 2) { // comparison is not present; inferred as regex fi.text = words[1]; fi.comparison = comparison_type.regex; fi.lo_text = fi.text.ToLower(); fi.create_regex(); return(fi.regex_ != null ? fi : null); } switch (words[1].ToLower()) { case "!=": fi.comparison = comparison_type.not_equal; break; case "==": case "=": fi.comparison = comparison_type.equal; break; case "+": case "startswith": fi.comparison = comparison_type.starts_with; break; case "-": case "!startswith": fi.comparison = comparison_type.does_not_start_with; break; case "++": case "contains": fi.comparison = comparison_type.contains; break; case "--": case "!contains": fi.comparison = comparison_type.does_not_contain; break; case "containsany": case "any": fi.comparison = comparison_type.contains_any; break; case "containsnone": case "none": fi.comparison = comparison_type.contains_none; break; case "matches": case "match": fi.comparison = comparison_type.regex; break; default: return(null); } // take the rest of the text int compare_idx = line.IndexOf(words[1]); if (compare_idx + words[1].Length + 1 >= line.Length) { // nothing following the comparison return(null); } // 1.2.20+ - don't trim the end! - very likely the user wants the beginning/ending spaces to be in the comparison line = line.Substring(compare_idx + words[1].Length + 1); if (fi.comparison == comparison_type.contains_any || fi.comparison == comparison_type.contains_none) { fi.words = line.Split('|'); fi.lo_words = fi.words.Select(w => w.ToLower()).ToArray(); } fi.text = line; fi.lo_text = line.ToLower(); fi.create_regex(); if (fi.comparison == comparison_type.regex && fi.regex_ == null) { // the regex is invalid at this point return(null); } return(fi); }
protected bool Equals(filter_line other) { return(Equals(fi, other.fi) && case_sensitive_ == other.case_sensitive_ && string.Equals(lo_text, other.lo_text) && string.Equals(text, other.text) && comparison == other.comparison && part == other.part); }
// tries to parse a line - if it fails, it will return null private static filter_line parse_impl(string line) { line = line.Trim(); if (line.StartsWith("#")) // allow comments return null; if (line == "full-word") // 1.8.17 - can happen from Find >> To Filter - but we don't handle it yet return null; if (line.StartsWith("font") || line.StartsWith("color") || line.StartsWith("match_color")) return parse_font(line); if (line == "case-insensitive") return new filter_line(line) {part = part_type.case_sensitive_info, case_sensitive = false }; if ( !line.StartsWith("$")) return null; string[] words = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); // Syntax: // $ColumnName Comparison Text bool ok = words.Length >= 3 || (words.Length == 2 && is_regex_expression(words[1])); if (!ok) // we need at least $c compare word(s) return null; filter_line fi = new filter_line(line); fi.part = part_type_io.from_str(words[0]); if (fi.part == part_type.invalid) return null; if (words.Length == 2) { // comparison is not present; inferred as regex fi.text = words[1]; fi.comparison = comparison_type.regex; fi.lo_text = fi.text.ToLower(); fi.create_regex(); return fi.regex_ != null ? fi : null ; } switch ( words[1].ToLower() ) { case "!=": fi.comparison = comparison_type.not_equal; break; case "==": case "=": fi.comparison = comparison_type.equal; break; case "+": case "startswith": fi.comparison = comparison_type.starts_with; break; case "-": case "!startswith": fi.comparison = comparison_type.does_not_start_with; break; case "++": case "contains": fi.comparison = comparison_type.contains; break; case "--": case "!contains": fi.comparison = comparison_type.does_not_contain; break; case "containsany": case "any": fi.comparison = comparison_type.contains_any; break; case "containsnone": case "none": fi.comparison = comparison_type.contains_none; break; case "matches": case "match": fi.comparison = comparison_type.regex; break; default: return null; } // take the rest of the text int compare_idx = line.IndexOf(words[1]); if (compare_idx + words[1].Length + 1 >= line.Length) // nothing following the comparison return null; // 1.2.20+ - don't trim the end! - very likely the user wants the beginning/ending spaces to be in the comparison line = line.Substring(compare_idx + words[1].Length + 1); if (fi.comparison == comparison_type.contains_any || fi.comparison == comparison_type.contains_none) { fi.words = line.Split('|'); fi.lo_words = fi.words.Select(w => w.ToLower()).ToArray(); } // 1.8.17+ - allow specifying quotes for contains or !contains line = trim_quotes(line); fi.text = line; fi.lo_text = line.ToLower(); fi.create_regex(); if (fi.comparison == comparison_type.regex && fi.regex_ == null) // the regex is invalid at this point return null; return fi; }
// note: in the future, we might allow for more "font" data - at that point, I'll think about the syntax // // at this point, we allow a simple "color" line: // color fg [bg] private static filter_line parse_font(string line) { // future: if "font" -> account for that as well Debug.Assert( is_color_or_font_line( line)); bool is_color = line.StartsWith("color"); string[] colors = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); filter_line fi = new filter_line(line) { part = part_type.font }; if (colors.Length >= 2) if ( is_color) fi.fi.fg = util.str_to_color(colors[1]); else fi.fi.match_fg = util.str_to_color(colors[1]); if (colors.Length >= 3) if (is_color) fi.fi.bg = util.str_to_color(colors[2]); else fi.fi.match_bg = util.str_to_color(colors[2]); return fi; }
protected bool Equals(filter_line other) { return Equals(fi, other.fi) && case_sensitive_ == other.case_sensitive_ && string.Equals(lo_text, other.lo_text) && string.Equals(text, other.text) && comparison == other.comparison && part == other.part; }
// tries to parse a line - if it fails, it will return null private static filter_line parse_impl(string line) { line = line.Trim(); if (line.StartsWith("#")) { // allow comments return(null); } if (line == "full-word") { // 1.8.17 - can happen from Find >> To Filter - but we don't handle it yet return(null); } if (line.StartsWith("font") || line.StartsWith("color") || line.StartsWith("match_color")) { return(parse_font(line)); } if (line == "case-insensitive") { return new filter_line(line) { part = part_type.case_sensitive_info, case_sensitive = false } } ; if (!line.StartsWith("$")) { return(null); } string[] words = line.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); // Syntax: // $ColumnName Comparison Text if (words.Length < 3) { // we need at least $c compare word(s) return(null); } filter_line fi = new filter_line(line) { part = part_type_io.from_str(words[0]) }; if (fi.part == part_type.invalid) { return(null); } switch (words[1].ToLower()) { case "!=": fi.comparison = comparison_type.not_equal; break; case "==": case "=": fi.comparison = comparison_type.equal; break; case "+": case "startswith": fi.comparison = comparison_type.starts_with; break; case "-": case "!startswith": fi.comparison = comparison_type.does_not_start_with; break; case "++": case "contains": fi.comparison = comparison_type.contains; break; case "--": case "!contains": fi.comparison = comparison_type.does_not_contain; break; case "containsany": case "any": case "in": fi.comparison = comparison_type.contains_any; break; case "containsnone": case "none": case "!in": fi.comparison = comparison_type.contains_none; break; case "matches": case "match": case "regex": case "r": fi.comparison = comparison_type.regex; break; default: return(null); } // take the rest of the text int compare_idx = line.IndexOf(words[1]); if (compare_idx + words[1].Length + 1 >= line.Length) { // nothing following the comparison return(null); } // 1.2.20+ - don't trim the end! - very likely the user wants the beginning/ending spaces to be in the comparison line = line.Substring(compare_idx + words[1].Length + 1); if (fi.comparison == comparison_type.contains_any || fi.comparison == comparison_type.contains_none) { fi.words = line.Split('|'); fi.lo_words = fi.words.Select(w => w.ToLower()).ToArray(); } // 1.8.17+ - allow specifying quotes for contains or !contains line = trim_quotes(line); fi.text = line; fi.lo_text = line.ToLower(); fi.create_regex(); if (fi.comparison == comparison_type.regex && fi.regex_ == null) { // the regex is invalid at this point return(null); } return(fi); }