260421.1 · ba4c5b611448acdbb4c6295fb30dfef4dc9a401d
TUI stdin pipe following #540
fix a TUI stdin buffering issue to support #540
reading declarations
@@ -256,7 +256,7 @@ void Output::header(const char *pathname, const std::string& partname, bool& hea size_t columno = flag_column_number && matcher != NULL ? matcher->columno() + 1 : 1; // -Q: mark pathname with three \0 markers in headings, unless -a- bool nul = heading && flag_query && !flag_text;+ bool nul = flag_query && heading && !flag_text; if (nul) chr('\0');
@@ -851,13 +851,9 @@ void Query::query() #else signal(SIGINT, sigint);- signal(SIGQUIT, sigint);- signal(SIGTERM, sigint);- signal(SIGPIPE, SIG_IGN);- signal(SIGWINCH, sigwinch); #endif@@ -890,7 +886,7 @@ void Query::query() VKey::cleanup(); Screen::cleanup(); - // check TTY again for color support, this time without --query+ // check TTY a final time for color support to print results, if any, this time without --query flag_query = false; terminal(); @@ -909,10 +905,7 @@ void Query::query() // close the stdin pipe if (flag_stdin && Static::source != stdin && Static::source != NULL)- {- fclose(Static::source);- Static::source = NULL;- }+ fclose(Static::source); // close source but don't reset to NULL, source is used by the search thread // join the search thread if (search_thread_.joinable())@@ -1671,13 +1664,13 @@ bool Query::update() // fetch viewable portion plus one up to two screenfuls more fetch(row_ - (row_ % Screen::rows) + 2 * Screen::rows); + int end = rows_ + append_;+ // display the viewable portion when updated- if (rows_ + append_ > begin && begin < row_ + append_ + maxrows_ - 2)+ if (end > begin && begin < row_ + maxrows_ - 2) { Screen::normal(); - int end = rows_ + append_;- if (begin + maxrows_ - 2 > end) begin = end - maxrows_ + 2; if (begin < 0)@@ -1685,17 +1678,12 @@ bool Query::update() if (begin < row_) begin = row_; - if (end > row_ + maxrows_ - 2)- end = row_ + maxrows_ - 2;-- for (int i = begin; i < end; ++i)+ for (int i = begin; i < std::min(end, row_ + maxrows_ - 2); ++i) disp(i); } if (error_ == -1) {- int end = rows_ + append_;- if (tick_ < 8 && end < row_ + maxrows_ - 2) { int row = end - row_ + 1;@@ -1919,7 +1907,8 @@ bool Query::fetch(int row) if (!incomplete) { // added another row- ++rows_;+ if (++rows_ < static_cast<int>(view_.size()))+ view_[rows_].clear(); // skip \n if (nlptr < buffer_ + buflen_)@@ -1929,9 +1918,8 @@ bool Query::fetch(int row) // append the next chunk of text from the buffer append_ = incomplete; + // shift the buffer to make room buflen_ -= nlptr - buffer_;-- // shift the buffer memmove(buffer_, nlptr, buflen_); } }@@ -4118,10 +4106,11 @@ void Query::set_prompt() void Query::get_stdin() {- // if standard input is searched, then buffer all its text+ // if standard input is searched, then dynamically buffer the input to search if (flag_stdin) { #ifndef OS_WIN+ // make stdin non-blocking to read and buffer dynamically fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK); #endif @@ -4162,7 +4151,7 @@ void Query::stop_stdin() { // close the stdin pipe when open if (Static::source != stdin && Static::source != NULL)- fclose(Static::source);+ fclose(Static::source); // close source but don't reset to NULL, source is used by the search thread // join the stdin_sender stdin_stop = true;@@ -4174,15 +4163,21 @@ void Query::stop_stdin() // push standard input down the specified pipe fd void Query::stdin_sender(int fd) {- // write the stdin data all at once, we can ignore the return value+ // write the stdin data all at once to the search pipe+ char buf[QUERY_BUFFER_SIZE]; ssize_t len = stdin_buffer_.size(), nwritten = write(fd, stdin_buffer_.c_str(), len); -#ifndef OS_WIN+ // when more stdin input arrives, buffer it and write it to the search pipe while (!stdin_stop && !feof(stdin) && nwritten == len) {- len = stdin_input_.file_get(buffer_, QUERY_BUFFER_SIZE);+ len = stdin_input_.file_get(buf, QUERY_BUFFER_SIZE);+ if (len == 0) {+ if (feof(stdin))+ break;++#ifndef OS_WIN struct timeval tv; fd_set rfds, efds; FD_ZERO(&rfds);@@ -4194,15 +4189,16 @@ void Query::stdin_sender(int fd) clearerr(stdin); if (::select(0 + 1, &rfds, NULL, &efds, &tv) >= 0 && FD_ISSET(0, &efds) != 0) break;+#endif+ nwritten = 0; } else {- stdin_buffer_.append(buffer_, len);- nwritten = write(fd, buffer_, len);+ stdin_buffer_.append(buf, len);+ nwritten = write(fd, buf, len); } }-#endif close(fd); }@@ -4453,7 +4449,7 @@ reflex::Input Query::stdin_input_; std::string Query::stdin_buffer_; int Query::stdin_pipe_[2]; std::thread Query::stdin_thread_;-volatile bool Query::stdin_stop = false;+std::atomic_bool Query::stdin_stop; size_t Query::searched_ = 0; size_t Query::found_ = 0; int Query::tick_ = 0;
@@ -320,7 +320,7 @@ class Query { static std::string stdin_buffer_; static int stdin_pipe_[2]; static std::thread stdin_thread_;- static volatile bool stdin_stop;+ static std::atomic_bool stdin_stop; static size_t searched_; // last update number of files searched static size_t found_; // last update number of files found static int tick_; // 100ms tick 0 to 7 or steady 8
@@ -43,6 +43,10 @@ void Stats::report(FILE *output) { size_t sf = searched_files(); size_t sd = searched_dirs();+ size_t si = searched_indexed();+ size_t ss = searched_skipped();+ size_t sc = searched_changed();+ size_t sa = searched_added(); size_t sl = searched_lines(); size_t ff = found_files(); size_t fp = found_parts();@@ -71,17 +75,17 @@ void Stats::report(FILE *output) if (flag_index && indexed > 0) {- fprintf(output, "Skipped %zu file%s of %zu (%.4g%%) not matching %zu indexes\n", skipped, (skipped == 1 ? "" : "s"), sf - ff, 100.0 * skipped / (sf - ff), indexed);- if (changed > 0 || added > 0)+ fprintf(output, "Skipped %zu file%s of %zu (%.4g%%) not matching %zu indexes\n", ss, (ss == 1 ? "" : "s"), sf - ff, 100.0 * ss / (sf - ff), si);+ if (sc > 0 || sa > 0) { fprintf(output, "Detected outdated or missing index files, run ugrep-indexer to re-index:\n");- if (changed > 1)- fprintf(output, " searched %zu changed files\n", changed);- else if (changed == 1)+ if (sc > 1)+ fprintf(output, " searched %zu changed files\n", sc);+ else if (sc == 1) fprintf(output, " searched 1 changed file\n");- if (added > 1)- fprintf(output, " searched %zu new files\n", added);- else if (added == 1)+ if (sa > 1)+ fprintf(output, " searched %zu new files\n", sa);+ else if (sa == 1) fprintf(output, " searched 1 new file\n"); } }@@ -200,12 +204,12 @@ void Stats::report(FILE *output) } reflex::timer_type Stats::timer;-size_t Stats::files = 0;-size_t Stats::dirs = 0;-size_t Stats::indexed = 0;-size_t Stats::skipped = 0;-size_t Stats::changed = 0;-size_t Stats::added = 0;+std::atomic_size_t Stats::files;+std::atomic_size_t Stats::dirs;+std::atomic_size_t Stats::indexed;+std::atomic_size_t Stats::skipped;+std::atomic_size_t Stats::changed;+std::atomic_size_t Stats::added; std::atomic_size_t Stats::fileno; std::atomic_size_t Stats::partno; std::atomic_size_t Stats::matchno;
@@ -126,6 +126,30 @@ class Stats { return dirs; } + // number of indexed files visited+ static size_t searched_indexed()+ {+ return indexed;+ }++ // numbder of indexed files skipped from search+ static size_t searched_skipped()+ {+ return skipped;+ }++ // number of indexed files changed and searched (stale index file)+ static size_t searched_changed()+ {+ return changed;+ }++ // number of non-indexed files added and searched (stale index file)+ static size_t searched_added()+ {+ return added;+ }+ // number of lines searched static size_t searched_lines() {@@ -190,12 +214,12 @@ class Stats { protected: static reflex::timer_type timer; // elapsed wall-clock time in milli seconds (ms)- static size_t files; // number of files searched, excluding files in archives- static size_t dirs; // number of directories searched- static size_t indexed; // number of files found to be indexed- static size_t skipped; // number of files found to be indexed that were skipped as not matching- static size_t changed; // number of files found to be indexed but changed (stale index file)- static size_t added; // number of files found to be added (stale index file)+ static std::atomic_size_t files; // number of files searched, excluding files in archives+ static std::atomic_size_t dirs; // number of directories searched+ static std::atomic_size_t indexed; // number of files found to be indexed+ static std::atomic_size_t skipped; // number of files found to be indexed that were skipped as not matching+ static std::atomic_size_t changed; // number of files found to be indexed but changed (stale index file)+ static std::atomic_size_t added; // number of files found to be added (stale index file) static std::atomic_size_t fileno; // number of matching files, excluding files in archives, atomic for GrepWorker::search() update static std::atomic_size_t partno; // number of matching files, including files in archives, atomic for GrepWorker::search() update static std::atomic_size_t lineno; // number of lines searched cummulatively