From 34003390f2c9b0345c9c4fac21e2e059b77902b0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Wed, 7 Sep 2022 18:40:25 +0200 Subject: [PATCH] temp: stdin ok, context lines ok? --- src/rclgrep/rclgrep.cpp | 181 +++++++++++++++++++++++++--------------- 1 file changed, 115 insertions(+), 66 deletions(-) diff --git a/src/rclgrep/rclgrep.cpp b/src/rclgrep/rclgrep.cpp index fc43af38..294da79b 100644 --- a/src/rclgrep/rclgrep.cpp +++ b/src/rclgrep/rclgrep.cpp @@ -31,11 +31,12 @@ #include #include +#include #include #include #include +#include -using namespace std; #include "log.h" #include "rclinit.h" @@ -109,58 +110,98 @@ static std::string current_topdir; static int beforecontext; static int aftercontext; -void grepit(const Rcl::Doc& doc) +static void dequeshift(std::deque& 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& q) +{ + for (const auto& ln : q) { + std::cout << ln; + } +} +void grepit(std::istream& instream, const Rcl::Doc& doc) { - std::vector lines; - int matchcount = 0; - stringToTokens(doc.text, lines, "\n"); - std::string ppath; + std::string indic; + std::string nindic; if (op_flags & OPT_H) { 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 += doc.ipath + "::"; + ppath += doc.ipath; + indic = "::"; + nindic = "--"; } + + int matchcount = 0; + std::deque beflines; int lnum = 0; int idx; std::string ln; 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; ++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) { auto match = e_p->simpleMatch(line); if (((op_flags & OPT_v) && match) || (!(op_flags & OPT_v) && !match)) { - if (inmatch && aftercontext && !(op_flags&OPT_c) && idx < int(lines.size())) { - for (int i = idx; i < std::min(int(lines.size()), idx + aftercontext); i++) { - std::cout << ppath << ln << lines[i] << "\n"; - } - std::cout << "--\n"; - } - inmatch = false; - goto nextline; + ismatch = false; + break; } } - 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 { - if (op_flags & OPT_n) { - ln = ulltodecstr(lnum) + ":"; + // Non-matching line. + if (inmatch && aftercontext && !(op_flags&OPT_c)) { + aftercount = aftercontext; } - if (!inmatch && !(op_flags&OPT_c) && beforecontext) { - for (int i = std::max(0, idx - beforecontext); i < idx; i++) { - std::cout << ppath << ln << lines[i] << "\n"; - } + inmatch = false; + if (aftercount) { + 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 (matchcount == 0) { @@ -171,58 +212,65 @@ void grepit(const Rcl::Doc& doc) std::cout << ppath << "\n"; } } else if (op_flags & OPT_c) { - std::cout << ppath << matchcount << "\n"; + std::cout << ppath << "::" << matchcount << "\n"; } } bool processpath(RclConfig *config, const std::string& path) { LOGINF("processpath: [" << path << "]\n"); - struct PathStat st; - if (path_fileprops(path, &st, false) < 0) { - std::cerr << path << " : "; - perror("stat"); - return false; - } - - config->setKeyDir(path_getfather(path)); - - 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"); + if (path.empty()) { + // stdin + Rcl::Doc doc; + doc.url = std::string("file://") + "(standard input)"; + grepit(std::cin, doc); + } else { + struct PathStat st; + if (path_fileprops(path, &st, false) < 0) { + std::cerr << path << " : "; + perror("stat"); return false; } - if (fis == FileInterner::FIError) { + + config->setKeyDir(path_getfather(path)); + + 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); + if (doc.url.empty()) + doc.url = path_pathtofileurl(path); - grepit(doc); + std::istringstream str(doc.text); + grepit(str, doc); + } } - return true; } class WalkerCB : public FsTreeWalkerCB { public: - WalkerCB(list& files, const vector& selpats, RclConfig *config) + WalkerCB(std::list& files, const vector& selpats, RclConfig *config) : m_files(files), m_pats(selpats), m_config(config) {} virtual FsTreeWalker::Status processone( const string& fn, const struct PathStat *, FsTreeWalker::CbFlag flg) { @@ -240,14 +288,14 @@ public: } return FsTreeWalker::FtwOk; } - list& m_files; + std::list& m_files; const vector& m_pats; RclConfig *m_config{nullptr}; }; bool recursive_grep(RclConfig *config, const string& top, const vector& selpats) { - list files; + std::list files; WalkerCB cb(files, selpats, config); FsTreeWalker walker; current_topdir = top; @@ -409,6 +457,7 @@ int main(int argc, char *argv[]) std::vector paths; if (aremain == 0) { // Read from stdin + processpath(config, std::string()); } else { while (aremain--) { paths.push_back(argv[optind++]);