in gogo/jline/src/main/java/org/apache/felix/gogo/jline/Posix.java [1535:1739]
protected void grep(CommandSession session, Process process, String[] argv) throws Exception {
final String[] usage = {
"grep - search for PATTERN in each FILE or standard input.",
"Usage: grep [OPTIONS] PATTERN [FILES]",
" -? --help Show help",
" -i --ignore-case Ignore case distinctions",
" -n --line-number Prefix each line with line number within its input file",
" -q --quiet, --silent Suppress all normal output",
" -v --invert-match Select non-matching lines",
" -w --word-regexp Select only whole words",
" -x --line-regexp Select only whole lines",
" -c --count Only print a count of matching lines per file",
" --color=WHEN Use markers to distinguish the matching string, may be `always', `never' or `auto'",
" -B --before-context=NUM Print NUM lines of leading context before matching lines",
" -A --after-context=NUM Print NUM lines of trailing context after matching lines",
" -C --context=NUM Print NUM lines of output context",
" --pad-lines Pad line numbers"
};
Options opt = parseOptions(session, usage, argv);
List<String> args = opt.args();
if (args.isEmpty()) {
throw new IllegalArgumentException("no pattern supplied");
}
String regex = args.remove(0);
String regexp = regex;
if (opt.isSet("word-regexp")) {
regexp = "\\b" + regexp + "\\b";
}
if (opt.isSet("line-regexp")) {
regexp = "^" + regexp + "$";
} else {
regexp = ".*" + regexp + ".*";
}
Pattern p;
Pattern p2;
if (opt.isSet("ignore-case")) {
p = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
p2 = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
} else {
p = Pattern.compile(regexp);
p2 = Pattern.compile(regex);
}
int after = opt.isSet("after-context") ? opt.getNumber("after-context") : -1;
int before = opt.isSet("before-context") ? opt.getNumber("before-context") : -1;
int context = opt.isSet("context") ? opt.getNumber("context") : 0;
String lineFmt = opt.isSet("pad-lines") ? "%6d" : "%d";
if (after < 0) {
after = context;
}
if (before < 0) {
before = context;
}
List<String> lines = new ArrayList<>();
boolean invertMatch = opt.isSet("invert-match");
boolean lineNumber = opt.isSet("line-number");
boolean count = opt.isSet("count");
String color = opt.isSet("color") ? opt.get("color") : "auto";
boolean colored;
switch (color) {
case "always":
case "yes":
case "force":
colored = true;
break;
case "never":
case "no":
case "none":
colored = false;
break;
case "auto":
case "tty":
case "if-tty":
colored = process.isTty(1);
break;
default:
throw new IllegalArgumentException("invalid argument ‘" + color + "’ for ‘--color’");
}
Map<String, String> colors = colored ? getColorMap(session, "GREP", DEFAULT_GREP_COLORS) : Collections.emptyMap();
List<Source> sources = new ArrayList<>();
if (opt.args().isEmpty()) {
opt.args().add("-");
}
for (String arg : opt.args()) {
if ("-".equals(arg)) {
sources.add(new StdInSource(process));
} else {
sources.add(new PathSource(session.currentDir().resolve(arg), arg));
}
}
boolean match = false;
for (Source source : sources) {
boolean firstPrint = true;
int nb = 0;
int lineno = 1;
String line;
int lineMatch = 0;
try (BufferedReader r = new BufferedReader(new InputStreamReader(source.read()))) {
while ((line = r.readLine()) != null) {
if (line.length() == 1 && line.charAt(0) == '\n') {
break;
}
boolean matches = p.matcher(line).matches();
AttributedStringBuilder sbl = new AttributedStringBuilder();
if (!count) {
if (sources.size() > 1) {
if (colored) {
applyStyle(sbl, colors, "fn");
}
sbl.append(source.getName());
if (colored) {
applyStyle(sbl, colors, "se");
}
sbl.append(":");
}
if (lineNumber) {
if (colored) {
applyStyle(sbl, colors, "ln");
}
sbl.append(String.format(lineFmt, lineno));
if (colored) {
applyStyle(sbl, colors, "se");
}
sbl.append((matches ^ invertMatch) ? ":" : "-");
}
String style = matches ^ invertMatch ^ (invertMatch && colors.containsKey("rv"))
? "sl" : "cx";
if (colored) {
applyStyle(sbl, colors, style);
}
AttributedString aLine = AttributedString.fromAnsi(line);
Matcher matcher2 = p2.matcher(aLine.toString());
int cur = 0;
while (matcher2.find()) {
int index = matcher2.start(0);
AttributedString prefix = aLine.subSequence(cur, index);
sbl.append(prefix);
cur = matcher2.end();
if (colored) {
applyStyle(sbl, colors, invertMatch ? "mc" : "ms", "mt");
}
sbl.append(aLine.subSequence(index, cur));
if (colored) {
applyStyle(sbl, colors, style);
}
nb++;
}
sbl.append(aLine.subSequence(cur, aLine.length()));
}
if (matches ^ invertMatch) {
lines.add(sbl.toAnsi(Shell.getTerminal(session)));
lineMatch = lines.size();
} else {
if (lineMatch != 0 & lineMatch + after + before <= lines.size()) {
if (!count) {
if (!firstPrint && before + after > 0) {
AttributedStringBuilder sbl2 = new AttributedStringBuilder();
if (colored) {
applyStyle(sbl2, colors, "se");
}
sbl2.append("--");
process.out().println(sbl2.toAnsi(Shell.getTerminal(session)));
} else {
firstPrint = false;
}
for (int i = 0; i < lineMatch + after; i++) {
process.out().println(lines.get(i));
}
}
while (lines.size() > before) {
lines.remove(0);
}
lineMatch = 0;
}
lines.add(sbl.toAnsi(Shell.getTerminal(session)));
while (lineMatch == 0 && lines.size() > before) {
lines.remove(0);
}
}
lineno++;
}
if (!count && lineMatch > 0) {
if (!firstPrint && before + after > 0) {
AttributedStringBuilder sbl2 = new AttributedStringBuilder();
if (colored) {
applyStyle(sbl2, colors, "se");
}
sbl2.append("--");
process.out().println(sbl2.toAnsi(Shell.getTerminal(session)));
} else {
firstPrint = false;
}
for (int i = 0; i < lineMatch + after && i < lines.size(); i++) {
process.out().println(lines.get(i));
}
}
if (count) {
process.out().println(nb);
}
match |= nb > 0;
}
}
Process.Utils.current().error(match ? 0 : 1);
}