You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2016/09/07 16:07:37 UTC

karaf git commit: [KARAF-4273] Add -o (--only-matching) option to grep command [KARAF-4376] Make grep return the list of results rather than null Also refactor grep command using the gogo jline grep implementation which uses the AttributedString for ease

Repository: karaf
Updated Branches:
  refs/heads/master 7cc5f5032 -> 7660ee68c


[KARAF-4273] Add -o (--only-matching) option to grep command
[KARAF-4376] Make grep return the list of results rather than null
Also refactor grep command using the gogo jline grep implementation which uses the AttributedString for ease of use.


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/7660ee68
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/7660ee68
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/7660ee68

Branch: refs/heads/master
Commit: 7660ee68ca903f0531f6fb2ae902bb37c4754dd3
Parents: 7cc5f50
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Sep 7 18:07:25 2016 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Sep 7 18:07:25 2016 +0200

----------------------------------------------------------------------
 .../karaf/shell/commands/impl/GrepAction.java   | 211 ++++++++-----
 .../karaf/shell/commands/impl/LessAction.java   |   2 +-
 .../karaf/shell/commands/impl/GrepTest.java     | 294 +++++++++++++++++--
 3 files changed, 401 insertions(+), 106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/7660ee68/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
index 3d866f3..754a8b1 100644
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
+++ b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
@@ -18,21 +18,33 @@
  */
 package org.apache.karaf.shell.commands.impl;
 
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.FileOrUriCompleter;
+import org.jline.builtins.Source;
+import org.jline.builtins.Source.StdInSource;
+import org.jline.builtins.Source.URLSource;
+import org.jline.terminal.Terminal;
+import org.jline.utils.AttributedString;
+import org.jline.utils.AttributedStringBuilder;
+import org.jline.utils.AttributedStyle;
+
 import java.io.BufferedReader;
-import java.io.IOException;
 import java.io.InputStreamReader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ansi.SimpleAnsi;
-
 @Command(scope = "shell", name="grep", description="Prints lines matching the given pattern.", detailedDescription="classpath:grep.txt")
 @Service
 public class GrepAction implements Action {
@@ -46,6 +58,10 @@ public class GrepAction implements Action {
     @Argument(index = 0, name = "pattern", description = "Regular expression", required = true, multiValued = false)
     private String regex;
 
+    @Argument(index = 1, multiValued = true)
+    @Completion(FileOrUriCompleter.class)
+    List<String> files;
+
     @Option(name = "-n", aliases = { "--line-number" }, description = "Prefixes each line of output with the line number within its input file.", required = false, multiValued = false)
     private boolean lineNumber;
 
@@ -81,6 +97,12 @@ public class GrepAction implements Action {
     @Option(name = "-C", aliases = { "--context" }, description = "Print NUM lines of output context.  Places a line containing -- between contiguous groups of matches.", required = false, multiValued = false)
     private int context = 0;
 
+    @Option(name = "-o", aliases = { "--only-matching"}, description = "Print only the matching section of a line", required = false, multiValued = false)
+    private boolean onlyMatching;
+
+    @Reference
+    Session session;
+
     @Override
     public Object execute() throws Exception {
         if (after < 0) {
@@ -89,11 +111,10 @@ public class GrepAction implements Action {
         if (before < 0) {
             before = context;
         }
-        List<String> lines = new ArrayList<String>();
 
         String regexp = regex;
         if (wordRegexp) {
-            regexp = "\\b" + regexp + "\\b";
+            regex = regexp = "\\b" + regexp + "\\b";
         }
         if (lineRegexp) {
             regexp = "^" + regexp + "$";
@@ -109,99 +130,127 @@ public class GrepAction implements Action {
             p = Pattern.compile(regexp);
             p2 = Pattern.compile(regex);
         }
-        try {
+
+        List<Source> sources = new ArrayList<>();
+        if (files == null || files.isEmpty()) {
+            files = Collections.singletonList("-");
+        }
+        Path pwd = Paths.get(System.getProperty("karaf.home", System.getProperty("user.dir")));
+        for (String arg : files) {
+            if ("-".equals(arg)) {
+                sources.add(new StdInSource());
+            } else {
+                sources.add(new URLSource(pwd.toUri().resolve(arg).toURL(), arg));
+            }
+        }
+
+        Terminal terminal = session != null ? (Terminal) session.get(".jline.terminal") : null;
+        List<Object> output = new ArrayList<>();
+        for (Source source : sources) {
             boolean firstPrint = true;
             int nb = 0;
             int lineno = 1;
             String line;
             int lineMatch = 0;
-            BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
-            while ((line = r.readLine()) != null) {
-                if (line.length() == 1 && line.charAt(0) == '\n') {
-                    break;
-                }
-                if (p.matcher(line).matches() ^ invertMatch) {
-                    Matcher matcher2 = p2.matcher(line);
-                    StringBuffer sb = new StringBuffer();
-                    while (matcher2.find()) {
+            List<String> lines = new ArrayList<>();
+            try (BufferedReader r = new BufferedReader(new InputStreamReader(source.read()))) {
+                while ((line = r.readLine()) != null) {
+                    if (line.length() == 1 && line.charAt(0) == '\n') {
+                        break;
+                    }
+                    if (p.matcher(line).matches() ^ invertMatch) {
+                        AttributedStringBuilder sbl = new AttributedStringBuilder();
+                        if (color != ColorOption.never) {
+                            sbl.style(getSourceStyle());
+                        }
+                        if (!count && sources.size() > 1) {
+                            sbl.append(source.getName());
+                            sbl.append(":");
+                        }
+                        if (!count && lineNumber) {
+                            sbl.append(String.format("%6d  ", lineno));
+                        }
+                        sbl.style(AttributedStyle.DEFAULT);
+                        Matcher matcher2 = p2.matcher(line);
+                        AttributedString aLine = AttributedString.fromAnsi(line);
+                        AttributedStyle style;
                         if (!invertMatch && color != ColorOption.never) {
-                            int index = matcher2.start(0);
-                            String prefix = line.substring(0,index);
-                            matcher2.appendReplacement(sb,
-                                    "\u001b[33;40m" + matcher2.group() + "\u001b[39;49m" + lastEscapeSequence(prefix));
+                            style = getMatchingStyle();
                         } else {
-                            matcher2.appendReplacement(sb, matcher2.group());
+                            style = AttributedStyle.DEFAULT;
                         }
-                        nb++;
-                    }
-                    matcher2.appendTail(sb);
-                    if(color != ColorOption.never) {
-                        sb.append(SimpleAnsi.RESET);
-                    }
-                    if (!count && lineNumber) {
-                        lines.add(String.format("%6d  ", lineno) + sb.toString());
+                        if (invertMatch) {
+                            nb++;
+                            sbl.append(aLine);
+                        } else if (onlyMatching) {
+                            while (matcher2.find()) {
+                                int index = matcher2.start(0);
+                                int cur = matcher2.end();
+                                sbl.append(aLine.subSequence(index, cur), style);
+                                nb++;
+                            }
+                        } else {
+                            int cur = 0;
+                            while (matcher2.find()) {
+                                int index = matcher2.start(0);
+                                AttributedString prefix = aLine.subSequence(cur, index);
+                                sbl.append(prefix);
+                                cur = matcher2.end();
+                                sbl.append(aLine.subSequence(index, cur), style);
+                                nb++;
+                            }
+                            sbl.append(aLine.subSequence(cur, aLine.length()));
+                        }
+                        lines.add(sbl.toAnsi(terminal));
+                        lineMatch = lines.size();
                     } else {
-                        lines.add(sb.toString());
-                    }
-					lineMatch = lines.size();
-                } else {
-                    if (lineMatch != 0 & lineMatch + after + before <= lines.size()) {
-                        if (!count) {
-                            if (!firstPrint && before + after > 0) {
-                                System.out.println("--");
-                            } else {
-                                firstPrint = false;
+                        if (lineMatch != 0 & lineMatch + after + before <= lines.size()) {
+                            if (!count) {
+                                if (!firstPrint && before + after > 0) {
+                                    output.add("--");
+                                } else {
+                                    firstPrint = false;
+                                }
+                                for (int i = 0; i < lineMatch + after; i++) {
+                                    output.add(lines.get(i));
+                                }
                             }
-                            for (int i = 0; i < lineMatch + after; i++) {
-                                System.out.println(lines.get(i));
+                            while (lines.size() > before) {
+                                lines.remove(0);
                             }
+                            lineMatch = 0;
                         }
-                        while (lines.size() > before) {
+                        lines.add(line);
+                        while (lineMatch == 0 && lines.size() > before) {
                             lines.remove(0);
                         }
-                        lineMatch = 0;
-                    }
-                    lines.add(line);
-                    while (lineMatch == 0 && lines.size() > before) {
-                        lines.remove(0);
                     }
+                    lineno++;
                 }
-                lineno++;
-            }
-            if (!count && lineMatch > 0) {
-                if (!firstPrint && before + after > 0) {
-                    System.out.println("--");
-                } else {
-                    firstPrint = false;
+                if (!count && lineMatch > 0) {
+                    if (!firstPrint && before + after > 0) {
+                        output.add("--");
+                    } else {
+                        firstPrint = false;
+                    }
+                    for (int i = 0; i < lineMatch + after && i < lines.size(); i++) {
+                        output.add(lines.get(i));
+                    }
                 }
-                for (int i = 0; i < lineMatch + after && i < lines.size(); i++) {
-                    System.out.println(lines.get(i));
+                if (count) {
+                    output.add(nb);
                 }
             }
-            if (count) {
-                System.out.println(nb);
-            }
-        } catch (IOException e) {
         }
-        return null;
+        return output;
     }
 
+    private AttributedStyle getSourceStyle() {
+        return AttributedStyle.DEFAULT.foreground(AttributedStyle.BLACK + AttributedStyle.BRIGHT);
+    }
 
-    /**
-     * Returns the last escape pattern found inside the String.
-     * This method is used to restore the formating after highliting the grep pattern.
-     * If no pattern is found just returns the reset String.
-     * @param str
-     * @return
-     */
-    private String lastEscapeSequence(String str) {
-        String escapeSequence = SimpleAnsi.RESET;
-        String escapePattern = "(\\\u001B\\[[0-9;]*[0-9]+m)+";
-        Pattern pattern =  Pattern.compile(escapePattern);
-        Matcher matcher = pattern.matcher(str);
-        while(matcher.find()) {
-            escapeSequence = matcher.group();
-        }
-        return escapeSequence;
+    private AttributedStyle getMatchingStyle() {
+        return AttributedStyle.DEFAULT.bold().foreground(AttributedStyle.RED);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/7660ee68/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
index 6d972f6..0479ba8 100644
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
+++ b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
@@ -89,7 +89,7 @@ public class LessAction implements Action {
         if (files == null || files.isEmpty()) {
             files = Collections.singletonList("-");
         }
-        Path pwd = Paths.get(System.getProperty("karaf.home"));
+        Path pwd = Paths.get(System.getProperty("karaf.home", System.getProperty("user.dir")));
         for (String arg : files) {
             if ("-".equals(arg)) {
                 sources.add(new StdInSource());

http://git-wip-us.apache.org/repos/asf/karaf/blob/7660ee68/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java b/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
index 10dbe51..b96d1da 100644
--- a/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
+++ b/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
@@ -18,49 +18,295 @@
  */
 package org.apache.karaf.shell.commands.impl;
 
+import org.apache.karaf.shell.impl.action.command.DefaultActionPreparator;
+import org.junit.Test;
+
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
 
-import junit.framework.TestCase;
-import org.apache.karaf.shell.impl.action.command.DefaultActionPreparator;
+import static org.junit.Assert.*;
+
+public class GrepTest {
 
-public class GrepTest extends TestCase {
+    private static final String ANSI_COLOR = "\u001b[1;31m";
+    private static final String ANSI_RESET = "\u001b[0m";
 
+    @Test
     public void testGrep() throws Exception {
-        InputStream input = System.in;
-        try {
-            ByteArrayInputStream bais = new ByteArrayInputStream("1\n2\n3\n4\n5\n6\n7\n8\n9\n".getBytes());
-            System.setIn(bais);
+        final String expectedColoredString = "1\n" + ANSI_COLOR + "2"
+            + ANSI_RESET + "\n"
+            + "3\n4\n5\n6\n7\n8\n9";
 
-            GrepAction grep = new GrepAction();
-            DefaultActionPreparator preparator = new DefaultActionPreparator();
-            preparator.prepare(grep, null, Arrays.<Object>asList("-C", "100", "2"));
-            grep.execute();
-        } finally {
-            System.setIn(input);
-        }
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-C", "100", "2"));
+        final String returnedString = systemInOutDecorator("1\n2\n3\n4\n5\n6\n7\n8\n9\n", grep);
+        assertEquals(expectedColoredString, returnedString);
+    }
+
+    @Test
+    public void testGrepInverted() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-v", "--color", "never", "mine"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("This is Hello World\nHello World!", returnedString);
+    }
+
+    @Test
+    public void testGrepMatching() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("--color", "never", "mine"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("World is mine", returnedString);
     }
 
+    @Test
+    public void testGrepMatchingWithColours() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("--color", "always", "mine"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("World is " + ANSI_COLOR + "mine" + ANSI_RESET, returnedString);
+    }
+
+    @Test
+    public void testGrepCount() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-c", "Hello World"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("2", returnedString);
+    }
+
+    @Test
+    public void testGrepCountInvert() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-c", "-v", "Hello World"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("1", returnedString);
+    }
+
+    @Test
+    public void testGrepInvertedWithLineNumbers() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-n", "-v", "--color", "never", "mine"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("     1  This is Hello World\n     3  Hello World!", returnedString);
+    }
+
+    @Test
+    public void testGrepMatchingWithLineNumbers() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-n", "--color", "never", "Hello"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("     1  This is Hello World\n     3  Hello World!", returnedString);
+    }
+
+    @Test
+    public void testGrepWordRegExp() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-w", "--color", "never", "is"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("This is Hello World\nWorld is mine", returnedString);
+    }
+
+    @Test
+    public void testGrepIs() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("--color", "never", "is"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("This is Hello World\nWorld is mine", returnedString);
+    }
+
+    @Test
+    public void testGrepRegExpWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = "Th"
+            + ANSI_COLOR
+            + "is" + ANSI_RESET
+            + " "
+            + ANSI_COLOR
+            + "is" + ANSI_RESET
+            + " Hello World\nWorld "
+            + ANSI_COLOR
+            + "is" + ANSI_RESET
+            + " mine";
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("--color", "always", "is"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepWordRegExpWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = "This "
+            + ANSI_COLOR
+            + "is" + ANSI_RESET
+            + " Hello World\nWorld "
+            + ANSI_COLOR
+            + "is" + ANSI_RESET
+            + " mine";
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-w", "--color", "always", "is"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepLineRegExpWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = ANSI_COLOR
+            + "This is Hello World" + ANSI_RESET;
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-x", "--color", "always", ".*Hello World"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepTwoLinesRegExpWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = ANSI_COLOR
+            + "This is Hello World" + ANSI_RESET + "\n"
+            + ANSI_COLOR
+            + "Hello World!" + ANSI_RESET;
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-x", "--color", "always", ".*Hello World.*"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepIgnoreCaseWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = "This is "
+            + ANSI_COLOR
+            + "hello" + ANSI_RESET + " World\n"
+            + ANSI_COLOR
+            + "Hello" + ANSI_RESET + " World!";
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-i", "--color", "always", "HELLO"));
+        final String returnedString = systemInOutDecorator("This is hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepContextOneWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = "This is "
+            + ANSI_COLOR
+            + "Hello" + ANSI_RESET + " World\n"
+            + "World is mine\n"
+            + ANSI_COLOR
+            + "Hello" + ANSI_RESET + " World!";
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-C", "1", "--color", "always", "Hello"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepBeforeContextOneWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = "World is mine\n"
+            + ANSI_COLOR
+            + "Hello World!" + ANSI_RESET;
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-B", "1", "--color", "always", "Hello World!"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepAfterContextOneWithColour() throws Exception {
+        GrepAction grep = new GrepAction();
+        final String expected = "World is "
+            + ANSI_COLOR
+            + "mine" + ANSI_RESET
+            + "\nHello World!";
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-A", "1", "--color", "always", "mine"));
+        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals(expected, returnedString);
+    }
+
+    @Test
+    public void testGrepOnlyMatching() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-o", "--color", "never", "He.*rld"));
+        final String expectedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("Hello World\nHello World", expectedString);
+    }
+
+    @Test
+    public void testGrepOnlyMatchingGroup() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("-o", "--color", "never", "(This).*(Hello)"));
+        final String expectedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
+            grep);
+        assertEquals("This is Hello", expectedString);
+    }
+
+    @Test
     public void testHonorColorNever() throws Exception {
+        GrepAction grep = new GrepAction();
+        DefaultActionPreparator preparator = new DefaultActionPreparator();
+        preparator.prepare(grep, null, Arrays.asList("--color", "never", "b"));
+        final String expectedString = systemInOutDecorator("abc\n",
+            grep);
+        assertEquals("abc", expectedString);
+
+    }
+
+    private String systemInOutDecorator(String inputString, GrepAction grepExecute) throws Exception {
         InputStream input = System.in;
         PrintStream output = System.out;
         try {
-            ByteArrayInputStream bais = new ByteArrayInputStream("abc".getBytes());
+            ByteArrayInputStream bais = new ByteArrayInputStream(inputString.getBytes());
             System.setIn(bais);
-            ByteArrayOutputStream outContent = new ByteArrayOutputStream();
-            System.setOut(new PrintStream(outContent));
-
-            GrepAction grep = new GrepAction();
-            DefaultActionPreparator preparator = new DefaultActionPreparator();
-            preparator.prepare(grep, null, Arrays.<Object>asList( "--color", "never", "b"));
-            grep.execute();
-            assertEquals("abc", outContent.toString().trim());
+
+            String result = ((List<Object>) grepExecute.execute()).stream()
+                    .map(Object::toString).collect(Collectors.joining("\n"));
+            if (result.length() > 1 && result.charAt(result.length() - 1) == '\n') {
+                result = result.substring(0, result.length() - 1);
+            }
+            return result;
         } finally {
             System.setIn(input);
             System.setOut(output);
         }
     }
+
 }