From 74769422eef2d31cfd29385c826afe6b72c55264 Mon Sep 17 00:00:00 2001 From: Dmitry Gusarov <1462777+gusarov@users.noreply.github.com> Date: Sun, 19 Jul 2020 17:45:14 -0400 Subject: [PATCH] add context lines --- Grep Options Analysis.xlsx | Bin 11789 -> 11793 bytes Grepl.Tests/Commands/BasicCommands.cs | 81 ++++++++++++++++++++++++++ Grepl/Executor.cs | 51 ++++++++++++++++ Grepl/Grepl.cs | 10 +++- 4 files changed, 141 insertions(+), 1 deletion(-) diff --git a/Grep Options Analysis.xlsx b/Grep Options Analysis.xlsx index e8d7fd0e1c1754121c496424e07698191faf12de..1ab891038194b210cf5fe7884bd0e875561e85ff 100644 GIT binary patch delta 3538 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 MEh7fiDgXcg08x;&iU0rr delta 3540 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 OljtoY2GJ@20001cCdtPD diff --git a/Grepl.Tests/Commands/BasicCommands.cs b/Grepl.Tests/Commands/BasicCommands.cs index 9040c29..775eb23 100644 --- a/Grepl.Tests/Commands/BasicCommands.cs +++ b/Grepl.Tests/Commands/BasicCommands.cs @@ -93,6 +93,87 @@ public void Should_10_search_multiple_entries_per_line() } + [TestMethod] + public void Should_10_search_with_context() + { + CreateData("2"); + var r = GreplEntry("-e", "//3", "file1.txt", "-C", "1"); + Assert.AreEqual(0, r.Code); + + var raw = r.Output; + var exp = + @"//2 aaaa aaaa data aaaa +//3 bbbb aaaa +//4 cccc data bbbb data aaaa +"; + + CompareDetails(exp, raw); + + Assert.AreEqual(exp, raw); + + } + + [TestMethod] + public void Should_10_search_with_context_2() + { + CreateData("2"); + var r = GreplEntry("-e", "//3", "file1.txt", "-C", "2"); + Assert.AreEqual(0, r.Code); + + var raw = r.Output; + var exp = + @"//1 aaaa bbbb cccc dddd +//2 aaaa aaaa data aaaa +//3 bbbb aaaa +//4 cccc data bbbb data aaaa +//5 aaaa +"; + + CompareDetails(exp, raw); + + Assert.AreEqual(exp, raw); + + } + + [TestMethod] + public void Should_10_search_with_context_before_1() + { + CreateData("2"); + var r = GreplEntry("-e", "//3", "file1.txt", "-B", "1"); + Assert.AreEqual(0, r.Code); + + var raw = r.Output; + var exp = + @"//2 aaaa aaaa data aaaa +//3 bbbb aaaa +"; + + CompareDetails(exp, raw); + + Assert.AreEqual(exp, raw); + + } + + [TestMethod] + public void Should_10_search_with_context_before_2() + { + CreateData("2"); + var r = GreplEntry("-e", "//3", "file1.txt", "-B", "2"); + Assert.AreEqual(0, r.Code); + + var raw = r.Output; + var exp = + @"//1 aaaa bbbb cccc dddd +//2 aaaa aaaa data aaaa +//3 bbbb aaaa +"; + + CompareDetails(exp, raw); + + Assert.AreEqual(exp, raw); + + } + [TestMethod] public void Should_10_SearchRecursivelyProc() { diff --git a/Grepl/Executor.cs b/Grepl/Executor.cs index 12f746b..d34f733 100644 --- a/Grepl/Executor.cs +++ b/Grepl/Executor.cs @@ -33,10 +33,18 @@ class FilesSelectorOptions public List ExcludeGlobs { get; } = new List(); } + class ContextCaptureOptions + { + public int Before { get; set; } + public int After { get; set; } + public int ContextAround { get; set; } + } + public class Executor { internal OutputControlOptions OutputControlOptions { get; } = new OutputControlOptions(); internal FilesSelectorOptions FilesSelectorOptions { get; } = new FilesSelectorOptions(); + internal ContextCaptureOptions ContextCaptureOptions { get; } = new ContextCaptureOptions(); private bool Recursive => FilesSelectorOptions.Recursive; private const int FileBufferSize = 16 * 1024; @@ -290,6 +298,49 @@ void Process(string file, bool printFileName, Dictionary 0; before--) + { + if (prev >= 2) + { + prev = body.LastIndexOf('\n', prev - 2); + prev++; + if (!matchLines.ContainsKey(prev)) + { + matchLines[prev] = new Line + { + Start = prev, + }; + } + } + } + prev = line.Start; + var after = Math.Max(ContextCaptureOptions.After, ContextCaptureOptions.ContextAround); + for (; after > 0; after--) + { + prev = body.IndexOf('\n', prev); + if (prev > 0) + { + prev++; + if (!matchLines.ContainsKey(prev)) + { + matchLines[prev] = new Line + { + Start = prev, + }; + } + } + } + } + } foreach (var line in matchLines.Values) { diff --git a/Grepl/Grepl.cs b/Grepl/Grepl.cs index 647a981..b195729 100644 --- a/Grepl/Grepl.cs +++ b/Grepl/Grepl.cs @@ -132,7 +132,15 @@ public static int MainHandler(params string[] args) case "-include": executor.FilesSelectorOptions.IncludeGlobs.Add(args[++i]); break; - + case "A": + executor.ContextCaptureOptions.After = int.Parse(args[++i]); + break; + case "B": + executor.ContextCaptureOptions.Before = int.Parse(args[++i]); + break; + case "C": + executor.ContextCaptureOptions.ContextAround = int.Parse(args[++i]); + break; default: using (Color(ConsoleColor.Red)) {