temp: stdin ok, context lines ok?
This commit is contained in:
parent
dcbfe05296
commit
34003390f2
@ -31,11 +31,12 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "rclinit.h"
|
#include "rclinit.h"
|
||||||
@ -109,58 +110,98 @@ static std::string current_topdir;
|
|||||||
static int beforecontext;
|
static int beforecontext;
|
||||||
static int aftercontext;
|
static int aftercontext;
|
||||||
|
|
||||||
void grepit(const Rcl::Doc& doc)
|
static void dequeshift(std::deque<std::string>& q, int n, const std::string& ln)
|
||||||
|
{
|
||||||
|
if (n <= 0)
|
||||||
|
return;
|
||||||
|
if (q.size() >= unsigned(n)) {
|
||||||
|
q.pop_front();
|
||||||
|
}
|
||||||
|
q.push_back(ln);
|
||||||
|
}
|
||||||
|
static void dequeprint(std::deque<std::string>& q)
|
||||||
|
{
|
||||||
|
for (const auto& ln : q) {
|
||||||
|
std::cout << ln;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void grepit(std::istream& instream, const Rcl::Doc& doc)
|
||||||
{
|
{
|
||||||
std::vector<std::string> lines;
|
|
||||||
int matchcount = 0;
|
|
||||||
stringToTokens(doc.text, lines, "\n");
|
|
||||||
|
|
||||||
std::string ppath;
|
std::string ppath;
|
||||||
|
std::string indic;
|
||||||
|
std::string nindic;
|
||||||
if (op_flags & OPT_H) {
|
if (op_flags & OPT_H) {
|
||||||
ppath = fileurltolocalpath(doc.url);
|
ppath = fileurltolocalpath(doc.url);
|
||||||
if (ppath.size() > current_topdir.size()) {
|
if (path_isabsolute(ppath) && ppath.size() > current_topdir.size()) {
|
||||||
ppath = ppath.substr(current_topdir.size());
|
ppath = ppath.substr(current_topdir.size());
|
||||||
}
|
}
|
||||||
ppath += ":";
|
ppath += ":";
|
||||||
ppath += doc.ipath + "::";
|
ppath += doc.ipath;
|
||||||
|
indic = "::";
|
||||||
|
nindic = "--";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int matchcount = 0;
|
||||||
|
std::deque<std::string> beflines;
|
||||||
int lnum = 0;
|
int lnum = 0;
|
||||||
int idx;
|
int idx;
|
||||||
std::string ln;
|
std::string ln;
|
||||||
bool inmatch{false};
|
bool inmatch{false};
|
||||||
for (const auto& line: lines) {
|
int aftercount = 0;
|
||||||
|
for (;;) {
|
||||||
|
std::string line;
|
||||||
|
getline(instream, line, '\n');
|
||||||
|
if (!instream.good()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
idx = lnum;
|
idx = lnum;
|
||||||
++lnum;
|
++lnum;
|
||||||
//std::cout << "LINE:[" << line << "]\n";
|
if ((op_flags & OPT_n) && !(op_flags & OPT_c)) {
|
||||||
|
ln = ulltodecstr(lnum) + ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ismatch = true;
|
||||||
for (const auto e_p : g_expressions) {
|
for (const auto e_p : g_expressions) {
|
||||||
auto match = e_p->simpleMatch(line);
|
auto match = e_p->simpleMatch(line);
|
||||||
if (((op_flags & OPT_v) && match) || (!(op_flags & OPT_v) && !match)) {
|
if (((op_flags & OPT_v) && match) || (!(op_flags & OPT_v) && !match)) {
|
||||||
if (inmatch && aftercontext && !(op_flags&OPT_c) && idx < int(lines.size())) {
|
ismatch = false;
|
||||||
for (int i = idx; i < std::min(int(lines.size()), idx + aftercontext); i++) {
|
break;
|
||||||
std::cout << ppath << ln << lines[i] << "\n";
|
|
||||||
}
|
|
||||||
std::cout << "--\n";
|
|
||||||
}
|
|
||||||
inmatch = false;
|
|
||||||
goto nextline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (op_flags & OPT_c) {
|
|
||||||
matchcount++;
|
if (ismatch) {
|
||||||
|
// We have a winner line.
|
||||||
|
if (op_flags & OPT_c) {
|
||||||
|
matchcount++;
|
||||||
|
} else {
|
||||||
|
// Stop printing after-context
|
||||||
|
aftercount = 0;
|
||||||
|
// If this is the beginning/first matching line, possibly output the before context
|
||||||
|
if (!inmatch && beforecontext) {
|
||||||
|
dequeprint(beflines);
|
||||||
|
}
|
||||||
|
inmatch=true;
|
||||||
|
std::cout << ppath << indic << ln << line << "\n";
|
||||||
|
if (beforecontext && !beflines.empty()) {
|
||||||
|
beflines.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (op_flags & OPT_n) {
|
// Non-matching line.
|
||||||
ln = ulltodecstr(lnum) + ":";
|
if (inmatch && aftercontext && !(op_flags&OPT_c)) {
|
||||||
|
aftercount = aftercontext;
|
||||||
}
|
}
|
||||||
if (!inmatch && !(op_flags&OPT_c) && beforecontext) {
|
inmatch = false;
|
||||||
for (int i = std::max(0, idx - beforecontext); i < idx; i++) {
|
if (aftercount) {
|
||||||
std::cout << ppath << ln << lines[i] << "\n";
|
std::cout << ppath << nindic << ln << line << "\n";
|
||||||
}
|
aftercount--;
|
||||||
|
if (aftercount == 0)
|
||||||
|
std::cout << "--\n";
|
||||||
|
} else if (beforecontext) {
|
||||||
|
dequeshift(beflines, beforecontext, ppath + nindic + ln + line + "\n");
|
||||||
}
|
}
|
||||||
inmatch=true;
|
|
||||||
std::cout << ppath << ln << line << "\n";
|
|
||||||
}
|
}
|
||||||
nextline:
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (op_flags & OPT_L) {
|
if (op_flags & OPT_L) {
|
||||||
if (matchcount == 0) {
|
if (matchcount == 0) {
|
||||||
@ -171,58 +212,65 @@ void grepit(const Rcl::Doc& doc)
|
|||||||
std::cout << ppath << "\n";
|
std::cout << ppath << "\n";
|
||||||
}
|
}
|
||||||
} else if (op_flags & OPT_c) {
|
} else if (op_flags & OPT_c) {
|
||||||
std::cout << ppath << matchcount << "\n";
|
std::cout << ppath << "::" << matchcount << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool processpath(RclConfig *config, const std::string& path)
|
bool processpath(RclConfig *config, const std::string& path)
|
||||||
{
|
{
|
||||||
LOGINF("processpath: [" << path << "]\n");
|
LOGINF("processpath: [" << path << "]\n");
|
||||||
struct PathStat st;
|
if (path.empty()) {
|
||||||
if (path_fileprops(path, &st, false) < 0) {
|
// stdin
|
||||||
std::cerr << path << " : ";
|
Rcl::Doc doc;
|
||||||
perror("stat");
|
doc.url = std::string("file://") + "(standard input)";
|
||||||
return false;
|
grepit(std::cin, doc);
|
||||||
}
|
} else {
|
||||||
|
struct PathStat st;
|
||||||
config->setKeyDir(path_getfather(path));
|
if (path_fileprops(path, &st, false) < 0) {
|
||||||
|
std::cerr << path << " : ";
|
||||||
string mimetype;
|
perror("stat");
|
||||||
|
|
||||||
FileInterner interner(path, &st, config, FileInterner::FIF_none);
|
|
||||||
if (!interner.ok()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mimetype = interner.getMimetype();
|
|
||||||
|
|
||||||
FileInterner::Status fis = FileInterner::FIAgain;
|
|
||||||
bool hadNonNullIpath = false;
|
|
||||||
Rcl::Doc doc;
|
|
||||||
while (fis == FileInterner::FIAgain) {
|
|
||||||
doc.erase();
|
|
||||||
try {
|
|
||||||
fis = interner.internfile(doc);
|
|
||||||
} catch (CancelExcept) {
|
|
||||||
LOGERR("fsIndexer::processone: interrupted\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fis == FileInterner::FIError) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc.url.empty())
|
config->setKeyDir(path_getfather(path));
|
||||||
doc.url = path_pathtofileurl(path);
|
|
||||||
|
|
||||||
grepit(doc);
|
string mimetype;
|
||||||
|
|
||||||
|
FileInterner interner(path, &st, config, FileInterner::FIF_none);
|
||||||
|
if (!interner.ok()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mimetype = interner.getMimetype();
|
||||||
|
|
||||||
|
FileInterner::Status fis = FileInterner::FIAgain;
|
||||||
|
bool hadNonNullIpath = false;
|
||||||
|
Rcl::Doc doc;
|
||||||
|
while (fis == FileInterner::FIAgain) {
|
||||||
|
doc.erase();
|
||||||
|
try {
|
||||||
|
fis = interner.internfile(doc);
|
||||||
|
} catch (CancelExcept) {
|
||||||
|
LOGERR("fsIndexer::processone: interrupted\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fis == FileInterner::FIError) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.url.empty())
|
||||||
|
doc.url = path_pathtofileurl(path);
|
||||||
|
|
||||||
|
std::istringstream str(doc.text);
|
||||||
|
grepit(str, doc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class WalkerCB : public FsTreeWalkerCB {
|
class WalkerCB : public FsTreeWalkerCB {
|
||||||
public:
|
public:
|
||||||
WalkerCB(list<string>& files, const vector<string>& selpats, RclConfig *config)
|
WalkerCB(std::list<std::string>& files, const vector<string>& selpats, RclConfig *config)
|
||||||
: m_files(files), m_pats(selpats), m_config(config) {}
|
: m_files(files), m_pats(selpats), m_config(config) {}
|
||||||
virtual FsTreeWalker::Status processone(
|
virtual FsTreeWalker::Status processone(
|
||||||
const string& fn, const struct PathStat *, FsTreeWalker::CbFlag flg) {
|
const string& fn, const struct PathStat *, FsTreeWalker::CbFlag flg) {
|
||||||
@ -240,14 +288,14 @@ public:
|
|||||||
}
|
}
|
||||||
return FsTreeWalker::FtwOk;
|
return FsTreeWalker::FtwOk;
|
||||||
}
|
}
|
||||||
list<string>& m_files;
|
std::list<std::string>& m_files;
|
||||||
const vector<string>& m_pats;
|
const vector<string>& m_pats;
|
||||||
RclConfig *m_config{nullptr};
|
RclConfig *m_config{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool recursive_grep(RclConfig *config, const string& top, const vector<string>& selpats)
|
bool recursive_grep(RclConfig *config, const string& top, const vector<string>& selpats)
|
||||||
{
|
{
|
||||||
list<string> files;
|
std::list<std::string> files;
|
||||||
WalkerCB cb(files, selpats, config);
|
WalkerCB cb(files, selpats, config);
|
||||||
FsTreeWalker walker;
|
FsTreeWalker walker;
|
||||||
current_topdir = top;
|
current_topdir = top;
|
||||||
@ -409,6 +457,7 @@ int main(int argc, char *argv[])
|
|||||||
std::vector<std::string> paths;
|
std::vector<std::string> paths;
|
||||||
if (aremain == 0) {
|
if (aremain == 0) {
|
||||||
// Read from stdin
|
// Read from stdin
|
||||||
|
processpath(config, std::string());
|
||||||
} else {
|
} else {
|
||||||
while (aremain--) {
|
while (aremain--) {
|
||||||
paths.push_back(argv[optind++]);
|
paths.push_back(argv[optind++]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user