summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Gottula <justin@jgottula.com>2023-01-18 16:46:52 +1100
committerCraig Small <csmall@dropbear.xyz>2023-01-18 16:46:52 +1100
commit8a65a304e00e39011e84c0b4e75d5ed3c53db53b (patch)
tree68e90b5437181025aef50e5cd36a39d12b4c0001
parentb2bfd76b06efc8c8b2a9d4b2d7d20c19b50a6fb4 (diff)
downloadprocps-ng-8a65a304e00e39011e84c0b4e75d5ed3c53db53b.tar.gz
watch: Fix buggy line-deletion behaviour with --no-linewrap
This change is largely based upon Justin's patch, I just moved the reset_ansi() parts out otherwise you get strange colour reset behaviours. Original patch message: I used the --no-linewrap (-w) option for the first time today, watching some wide output that didn't quite fit in my tmux pane. Quickly I noticed a problem: while --no-linewrap did indeed eliminate the spillover of lines too long for the terminal "window" width, it *also* resulted in a bunch of lines from the program output being hidden entirely. After some fiddling around, the exact problematic behavior appears to be as follows: 1. Lines which would have wrapped (more than $COLUMNS chars long) are handled correctly. 2. Lines which would *not* have wrapped (shorter than $COLUMNS) are printed; but then the next line is *not* printed! For long sequences of non-wrap-length lines, you get an every-other-line-is-visible sort of effect. The logic underlying the problem seems to be this: in the run_command loop, if the x loop goes all the way to completion (meaning we've reached the right-side edge of the window area), there's a small block of code for --no-linewrap whose main purpose is to call find_eol, which eats input until it hits a newline (or EOF). Clearly this is intended to be done for lines that are too long, so that the excess characters are discarded and the input pointer is ready to go for the subsequent line. However, this code isn't in any way conditional on the value of eolseen! Short/wouldn't-wrap lines will have encountered a newline character before exhausting the entire x loop, and therefore eolseen will be true. Long/would-wrap lines will not have encountered a newline when the x loop is exhausted, and so eolseen will be false. Nevertheless, find_eol is called in *both* cases. For long lines, it does what it's meant to do. For short lines, *the newline has already been encountered and dealt with*, and so the actual effect of find_eol is to eat the entirety of the next line, all the way through to its newline, such that it isn't printed at all. References: procps-ng/procps!157 Signed-off-by: Craig Small <csmall@dropbear.xyz>
-rw-r--r--NEWS1
-rw-r--r--src/watch.c5
2 files changed, 5 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index c319ad5..0c473c7 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ procps-ng-NEXT
* w: Add --pids option merge #159
* watch: Pass through beep issue #104
* watch: -r option to not re-exec on SIGWINCH merge #125
+ * watch: find eol with --no-linewrap merge #157
procps-ng-4.0.2
---------------
diff --git a/src/watch.c b/src/watch.c
index b7ad005..f9a152d 100644
--- a/src/watch.c
+++ b/src/watch.c
@@ -774,8 +774,11 @@ static int run_command(char *restrict command, char **restrict command_argv)
reset_ansi();
if (flags & WATCH_COLOR)
attrset(A_NORMAL);
- find_eol(p);
}
+ if (!line_wrap && !eolseen)
+ {
+ find_eol(p);
+ }
}
fclose(p);