aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2015-04-10 17:04:28 -0500
committerRob Landley <rob@landley.net>2015-04-10 17:04:28 -0500
commit56af7086b2d6f59f54c661602252a0e84562ac7c (patch)
tree7e188cc8a8c367e83be964da25603973ef4f449f
parent70722144e3352567ab6a519a7ec11a831e377914 (diff)
downloadtoybox-56af7086b2d6f59f54c661602252a0e84562ac7c.tar.gz
Make more(1) usable.
> Yes, I know, "don't use pending". Sadly, more(1) is pretty useless > without this. It gets confused by long lines or tabs. > > This patch also adds the missing prompt between multiple files. actually, it looks like we're already hard-coding some escape sequences? more(1) doesn't need anything that isn't in ANSI, so here's an alternative patch that fixes the same bugs as the other patch but also has a reverse-video prompt:
-rw-r--r--toys/pending/more.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/toys/pending/more.c b/toys/pending/more.c
index eb48fa7b..59392ffe 100644
--- a/toys/pending/more.c
+++ b/toys/pending/more.c
@@ -32,19 +32,45 @@ static void signal_handler(int sig)
_exit(sig | 128);
}
+static void show_file_header(const char *name)
+{
+ printf(":::::::::::::::::::::::\n%s\n:::::::::::::::::::::::\n", name);
+}
+
+static int prompt(FILE *cin, const char* fmt, ...)
+{
+ int input_key;
+ va_list ap;
+
+ printf("\33[7m"); // Reverse video before printing the prompt.
+
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ while (1) {
+ fflush(NULL);
+ input_key = tolower(getc(cin));
+ printf("\33[0m\33[1K\r"); // Reset all attributes, erase to start of line.
+ if (strchr(" \nrq", input_key)) {
+ return input_key;
+ }
+ printf("\33[7m(Enter:Next line Space:Next page Q:Quit R:Show the rest)");
+ }
+}
+
static void do_cat_operation(int fd, char *name)
{
char *buf = NULL;
- if(toys.optc > 1) printf(":::::::::::::::::::::::\n"
- "%s\n:::::::::::::::::::::::\n",name);
+ if (toys.optc > 1) show_file_header(name);
for (; (buf = get_line(fd)); free(buf)) printf("%s\n", buf);
}
void more_main()
{
- int ch, lines, input_key = 0, disp_more, more_msg_len;
- unsigned rows = 24, cols = 80;
+ int ch, input_key = 0, show_prompt;
+ unsigned rows = 24, cols = 80, row = 0, col = 0;
struct stat st;
struct termios newf;
FILE *fp, *cin;
@@ -55,7 +81,8 @@ void more_main()
}
TT.cin_fd = fileno(cin);
- tcgetattr(TT.cin_fd,&TT.inf);
+ tcgetattr(TT.cin_fd, &TT.inf);
+
//Prepare terminal for input
memcpy(&newf, &TT.inf, sizeof(struct termios));
newf.c_lflag &= ~(ICANON | ECHO);
@@ -71,46 +98,46 @@ void more_main()
perror_msg("'%s'", *toys.optargs);
continue;
}
- st.st_size = disp_more = more_msg_len = lines = 0;
+ st.st_size = show_prompt = col = row = 0;
fstat(fileno(fp), &st);
terminal_size(&cols, &rows);
rows--;
- if(toys.optc > 1) {
- printf(":::::::::::::::::::::::\n"
- "%s\n:::::::::::::::::::::::\n",*toys.optargs);
- rows -= 3;
+
+ if (toys.optc > 1) {
+ show_file_header(*toys.optargs);
+ row += 3;
}
while ((ch = getc(fp)) != EOF) {
- if (input_key != 'r' && disp_more) {
- more_msg_len = printf("--More-- ");
- if (st.st_size)
- more_msg_len += printf("(%d%% of %lld bytes)",
- (int) (100 * ( (double) ftell(fp) / (double) st.st_size)),
+ if (input_key != 'r' && show_prompt) {
+ if (st.st_size)
+ input_key = prompt(cin, "--More--(%d%% of %lld bytes)",
+ (int) (100 * ( (double) ftell(fp) / (double) st.st_size)),
(long long)st.st_size);
- fflush(NULL);
-
- while (1) {
- input_key = getc(cin);
- input_key = tolower(input_key);
- printf("\r%*s\r", more_msg_len, ""); // Remove previous msg
- if (input_key == ' ' || input_key == '\n' || input_key == 'q'
- || input_key == 'r') break;
- more_msg_len = printf("(Enter:Next line Space:Next page Q:Quit R:Show the rest)");
- }
- more_msg_len = lines = disp_more = 0;
+ else
+ input_key = prompt(cin, "--More--");
if (input_key == 'q') goto stop;
+
+ col = row = show_prompt = 0;
terminal_size(&cols, &rows);
rows--;
}
- if (ch == '\n')
- if (++lines >= rows || input_key == '\n') disp_more = 1;
putchar(ch);
+ if (ch == '\t') col = (col | 0x7) + 1; else col++;
+ if (col == cols) putchar(ch = '\n');
+ if (ch == '\n') {
+ col = 0;
+ if (++row >= rows || input_key == '\n') show_prompt = 1;
+ }
}
fclose(fp);
- fflush(NULL);
- } while (*toys.optargs && *++toys.optargs);
+
+ if (*toys.optargs && *++toys.optargs) {
+ input_key = prompt(cin, "--More--(Next file: %s)", *toys.optargs);
+ if (input_key == 'q') goto stop;
+ }
+ } while (*toys.optargs);
stop:
tcsetattr(TT.cin_fd, TCSANOW, &TT.inf);