static void PaintLines(TextReader reader, Color defaultColor, IEnumerable <Marker> markers) { markers = markers.ToArray(); var colors = new Color[1024]; for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { if (colors.Length < line.Length) { colors = new Color[line.Length]; } { // ReSharper disable once AccessToModifiedClosure var markups = markers.SelectMany(m => m(line)); var count = 0; foreach (var markup in markups) { count++; for (var i = markup.Run.Index; i < markup.Run.End; i++) { colors[i] = new Color(markup.Color.Foreground ?? colors[i].Foreground, markup.Color.Background ?? colors[i].Background); } } if (count == 0) { Console.WriteLine(line); continue; } } { var anchor = 0; var cc = default(Color); for (var i = 0; i < line.Length; i++) { var color = colors[i]; if (color != cc) { cc.ApplyToConsole(); Console.Write(line.Substring(anchor, i - anchor)); anchor = i; cc = color; } } if (anchor < line.Length) { cc.ApplyToConsole(); Console.Write(line.Substring(anchor, line.Length - anchor)); } defaultColor.ApplyToConsole(); Console.WriteLine(); } } }
static void Wain(string[] args) { bool PopSwitch(string name1, string name2 = null, string name3 = null) { var i = Array.FindIndex(args, arg => arg == name1 || arg == name2 || arg == name3); var found = i >= 0; if (found) { args = args.Splice(i, 1); } return(found); } var debug = PopSwitch("--debug"); if (debug) { Debugger.Launch(); } var verbose = PopSwitch("--verbose", "-v"); if (PopSwitch("-?", "-h", "--help")) { ShowHelp(Console.Out); return; } var tail = Enumerable.ToArray( from arg in args select !arg.StartsWith("@") ? new[] { arg }.AsEnumerable() : arg.Length == 1 ? Enumerable.Empty <string>() : ParseResponseFile(arg.Substring(1)) into argz from arg in argz select arg); if (verbose && tail.Any()) { Console.Error.WriteLine(FormattableString.Invariant($"Command-line arguments ({tail.Length}):")); foreach (var arg in tail) { Console.Error.WriteLine("- " + arg); } } var defaultColor = new Color(Console.ForegroundColor, Console.BackgroundColor); var markers = from arg in tail let tokens = arg.TrimStart() .Split(StringSeparatorStock.Equal, 2, StringSplitOptions.RemoveEmptyEntries) where tokens.Length > 1 select new { Color = tokens[0], Regex = new Regex(tokens[1]), } into arg let all = arg.Color.EndsWith("*") let color = Color.Parse(all ? arg.Color.Slice(0, -1) : arg.Color) select CreateMarker(arg.Regex, all, color); try { PaintLines(Console.In, defaultColor, markers.Prepend(line => new[] { new Markup(0, line.Length, defaultColor) })); } finally { defaultColor.ApplyToConsole(); } }