Skip to content

Commit 6e068d7

Browse files
committed
TUI stdin pipe following #540
1 parent a900b5a commit 6e068d7

4 files changed

Lines changed: 104 additions & 62 deletions

File tree

lib/input.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ bool Input::file_ready()
10331033
#if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__)
10341034
return !ferror(file_);
10351035
#else
1036+
int fd = fileno(file_);
10361037
if (ferror(file_))
10371038
{
10381039
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
@@ -1042,7 +1043,7 @@ bool Input::file_ready()
10421043
if (errno == EAGAIN)
10431044
{
10441045
struct stat buf;
1045-
if (fstat(fileno(file_), &buf) == 0 && S_ISREG(buf.st_mode))
1046+
if (fstat(fd, &buf) == 0 && S_ISREG(buf.st_mode))
10461047
return false;
10471048
}
10481049
#endif
@@ -1053,13 +1054,13 @@ bool Input::file_ready()
10531054
fd_set rfds, efds;
10541055
FD_ZERO(&rfds);
10551056
FD_ZERO(&efds);
1056-
FD_SET(0, &rfds);
1057-
FD_SET(0, &efds);
1057+
FD_SET(fd, &rfds);
1058+
FD_SET(fd, &efds);
10581059
tv.tv_sec = 0;
1059-
tv.tv_usec = 1000; // 1ms timeout
1060-
clearerr(file_); // unset EAGAIN etc
1061-
if (::select(fileno(file_) + 1, &rfds, NULL, &efds, &tv) >= 0)
1062-
return FD_ISSET(fileno(file_), &efds) == 0;
1060+
tv.tv_usec = 10000; // 10ms timeout
1061+
clearerr(file_); // unset EAGAIN etc
1062+
if (::select(fd + 1, &rfds, NULL, &efds, &tv) >= 0)
1063+
return FD_ISSET(fd, &efds) == 0;
10631064
if (errno != EINTR)
10641065
return false;
10651066
}

lib/pattern.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4423,7 +4423,7 @@ void Pattern::gen_min(std::set<DFA::State*>& states)
44234423
// find min between 0 and Const::BITS
44244424
min_ = Const::BITS;
44254425
std::set<DFA::State*> prev, next(states);
4426-
for (size_t level = 0; level < min_; ++level)
4426+
for (uint16_t level = 0; level < min_; ++level)
44274427
{
44284428
bool none = true;
44294429
prev.clear();

src/query.cpp

Lines changed: 89 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ void Query::draw()
581581
void Query::disp(int row)
582582
{
583583
Screen::normal();
584-
if (row < rows_)
584+
if (row < rows_ + append_)
585585
{
586586
if (selected_[row])
587587
Screen::select();
@@ -683,7 +683,7 @@ void Query::redraw()
683683
}
684684
else
685685
{
686-
// do not show dots
686+
// reset to 4 to do not show dots
687687
tick_ = 4;
688688

689689
if (error_ == -1)
@@ -698,7 +698,7 @@ void Query::redraw()
698698
if (row_ < 0)
699699
row_ = 0;
700700

701-
int end = row_ + maxrows_ - 2;
701+
int end = row_ + append_ + maxrows_ - 2;
702702

703703
for (int i = row_; i < end; ++i)
704704
disp(i);
@@ -919,6 +919,7 @@ void Query::query()
919919
search_thread_.join();
920920

921921
// join the stdin sender thread
922+
stdin_stop = true;
922923
if (stdin_thread_.joinable())
923924
stdin_thread_.join();
924925
}
@@ -1482,6 +1483,8 @@ void Query::query_ui()
14821483
// start a new search, cancel the previous search when still running
14831484
void Query::search()
14841485
{
1486+
stop_stdin();
1487+
14851488
bool cancel = !eof_;
14861489

14871490
if (cancel)
@@ -1494,6 +1497,22 @@ void Query::search()
14941497
Static::cancel_ugrep();
14951498
}
14961499

1500+
if (search_thread_.joinable())
1501+
{
1502+
if (cancel && error_ == -1)
1503+
{
1504+
const int banlen = 256;
1505+
char banner[banlen];
1506+
snprintf(banner, banlen, "restarting: please be patient while I cancel searching large files...%*s", banlen - 70, "");
1507+
Screen::normal();
1508+
Screen::invert();
1509+
Screen::put(maxrows_ - 1, 0, banner);
1510+
Screen::normal();
1511+
}
1512+
1513+
search_thread_.join();
1514+
}
1515+
14971516
#ifdef OS_WIN
14981517

14991518
hPipe_ = nonblocking_pipe(search_pipe_);
@@ -1522,23 +1541,8 @@ void Query::search()
15221541

15231542
#endif
15241543

1525-
if (search_thread_.joinable())
1526-
{
1527-
if (cancel && error_ == -1)
1528-
{
1529-
const int banlen = 256;
1530-
char banner[banlen];
1531-
snprintf(banner, banlen, "restarting: please be patient while I cancel searching large files...%*s", banlen - 70, "");
1532-
Screen::normal();
1533-
Screen::invert();
1534-
Screen::put(maxrows_ - 1, 0, banner);
1535-
Screen::normal();
1536-
}
1537-
1538-
search_thread_.join();
1539-
}
1540-
15411544
eof_ = false;
1545+
append_ = false;
15421546
row_ = 0;
15431547
rows_ = 0;
15441548
skip_ = 0;
@@ -1568,7 +1572,7 @@ void Query::search()
15681572

15691573
set_flags();
15701574

1571-
set_stdin();
1575+
start_stdin();
15721576

15731577
if (error_ == -1)
15741578
{
@@ -1668,19 +1672,19 @@ bool Query::update()
16681672
fetch(row_ - (row_ % Screen::rows) + 2 * Screen::rows);
16691673

16701674
// display the viewable portion when updated
1671-
if (rows_ > begin && begin < row_ + maxrows_ - 2)
1675+
if (rows_ + append_ > begin && begin < row_ + append_ + maxrows_ - 2)
16721676
{
16731677
Screen::normal();
16741678

1675-
if (begin + maxrows_ - 2 > rows_)
1676-
begin = rows_ - maxrows_ + 2;
1679+
int end = rows_ + append_;
1680+
1681+
if (begin + maxrows_ - 2 > end)
1682+
begin = end - maxrows_ + 2;
16771683
if (begin < 0)
16781684
begin = 0;
16791685
if (begin < row_)
16801686
begin = row_;
16811687

1682-
int end = rows_;
1683-
16841688
if (end > row_ + maxrows_ - 2)
16851689
end = row_ + maxrows_ - 2;
16861690

@@ -1690,9 +1694,11 @@ bool Query::update()
16901694

16911695
if (error_ == -1)
16921696
{
1693-
if (tick_ < 8 && rows_ < row_ + maxrows_ - 2)
1697+
int end = rows_ + append_;
1698+
1699+
if (tick_ < 8 && end < row_ + maxrows_ - 2)
16941700
{
1695-
int row = rows_ - row_ + 1;
1701+
int row = end - row_ + 1;
16961702

16971703
// no dots and clear below when we hit eof
16981704
if (eof_)
@@ -4115,34 +4121,22 @@ void Query::get_stdin()
41154121
// if standard input is searched, then buffer all its text
41164122
if (flag_stdin)
41174123
{
4118-
reflex::BufferedInput input(stdin, flag_encoding_type);
4124+
#ifndef OS_WIN
4125+
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
4126+
#endif
41194127

4120-
while (true)
4121-
{
4122-
size_t len = input.get(buffer_, QUERY_BUFFER_SIZE);
4123-
if (len == 0)
4124-
break;
4125-
stdin_buffer_.append(buffer_, len);
4126-
}
4128+
stdin_input_ = stdin;
4129+
stdin_input_.file_encoding(flag_encoding_type);
4130+
stdin_buffer_.clear();
41274131
}
41284132
}
41294133

4130-
void Query::set_stdin()
4134+
// start a new stdin sender thread and pipe from sender to the search engine
4135+
void Query::start_stdin()
41314136
{
41324137
// if standard input is searched, start thread to reproduce its text on demand
41334138
if (flag_stdin)
41344139
{
4135-
// close the stdin pipe when open
4136-
if (Static::source != stdin && Static::source != NULL)
4137-
{
4138-
fclose(Static::source);
4139-
Static::source = NULL;
4140-
}
4141-
4142-
// join the stdin_sender
4143-
if (stdin_thread_.joinable())
4144-
stdin_thread_.join();
4145-
41464140
// create a new pipe
41474141
if (pipe(stdin_pipe_) < 0)
41484142
{
@@ -4156,19 +4150,61 @@ void Query::set_stdin()
41564150
Static::source = fdopen(stdin_pipe_[0], "rb");
41574151

41584152
// run stdin_sender in the background to push buffered standard input down the pipe
4153+
stdin_stop = false;
41594154
stdin_thread_ = std::thread(Query::stdin_sender, stdin_pipe_[1]);
41604155
}
41614156
}
41624157

4158+
// stop stdin sender thread
4159+
void Query::stop_stdin()
4160+
{
4161+
if (flag_stdin)
4162+
{
4163+
// close the stdin pipe when open
4164+
if (Static::source != stdin && Static::source != NULL)
4165+
fclose(Static::source);
4166+
4167+
// join the stdin_sender
4168+
stdin_stop = true;
4169+
if (stdin_thread_.joinable())
4170+
stdin_thread_.join();
4171+
}
4172+
}
4173+
41634174
// push standard input down the specified pipe fd
4164-
ssize_t Query::stdin_sender(int fd)
4175+
void Query::stdin_sender(int fd)
41654176
{
41664177
// write the stdin data all at once, we can ignore the return value
4167-
ssize_t nwritten = write(fd, stdin_buffer_.c_str(), stdin_buffer_.size());
4178+
ssize_t len = stdin_buffer_.size(), nwritten = write(fd, stdin_buffer_.c_str(), len);
41684179

4169-
close(fd);
4180+
#ifndef OS_WIN
4181+
while (!stdin_stop && !feof(stdin) && nwritten == len)
4182+
{
4183+
len = stdin_input_.file_get(buffer_, QUERY_BUFFER_SIZE);
4184+
if (len == 0)
4185+
{
4186+
struct timeval tv;
4187+
fd_set rfds, efds;
4188+
FD_ZERO(&rfds);
4189+
FD_ZERO(&efds);
4190+
FD_SET(0, &rfds);
4191+
FD_SET(0, &efds);
4192+
tv.tv_sec = 0;
4193+
tv.tv_usec = 10000; // 10ms timeout
4194+
clearerr(stdin);
4195+
if (::select(0 + 1, &rfds, NULL, &efds, &tv) >= 0 && FD_ISSET(0, &efds) != 0)
4196+
break;
4197+
nwritten = 0;
4198+
}
4199+
else
4200+
{
4201+
stdin_buffer_.append(buffer_, len);
4202+
nwritten = write(fd, buffer_, len);
4203+
}
4204+
}
4205+
#endif
41704206

4171-
return nwritten;
4207+
close(fd);
41724208
}
41734209

41744210
// true if view_[ref] has a valid filename/filepath identified by three \0 markers and differs from the given filename, then assigns filename
@@ -4413,9 +4449,11 @@ size_t Query::buflen_ = 0;
44134449
char Query::buffer_[QUERY_BUFFER_SIZE];
44144450
int Query::search_pipe_[2];
44154451
std::thread Query::search_thread_;
4452+
reflex::Input Query::stdin_input_;
44164453
std::string Query::stdin_buffer_;
44174454
int Query::stdin_pipe_[2];
44184455
std::thread Query::stdin_thread_;
4456+
volatile bool Query::stdin_stop = false;
44194457
size_t Query::searched_ = 0;
44204458
size_t Query::found_ = 0;
44214459
int Query::tick_ = 0;

src/query.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,10 @@ class Query {
263263

264264
static void get_stdin();
265265

266-
static void set_stdin();
266+
static void start_stdin();
267+
static void stop_stdin();
267268

268-
static ssize_t stdin_sender(int fd);
269+
static void stdin_sender(int fd);
269270

270271
static bool find_filename(int ref, std::string& filename, bool compare_dir = false, bool find_path = false, std::string *partname = NULL);
271272

@@ -310,14 +311,16 @@ class Query {
310311
static std::vector<std::string> view_; // search output text to display, incrementally fetched
311312
static std::vector<bool> selected_; // marked lines in view_[] selected in selection mode
312313
static bool eof_; // end of results, no more results can be fetched
313-
static bool append_;
314+
static bool append_; // flag to append search output to the last incomplete line
314315
static size_t buflen_;
315316
static char buffer_[QUERY_BUFFER_SIZE];
316317
static int search_pipe_[2];
317318
static std::thread search_thread_;
319+
static reflex::Input stdin_input_;
318320
static std::string stdin_buffer_;
319321
static int stdin_pipe_[2];
320322
static std::thread stdin_thread_;
323+
static volatile bool stdin_stop;
321324
static size_t searched_; // last update number of files searched
322325
static size_t found_; // last update number of files found
323326
static int tick_; // 100ms tick 0 to 7 or steady 8

0 commit comments

Comments
 (0)