需要帮助在我的自定义 CLI 中使用 ncurses 进行命令输出分页
Need help using ncurses for command output pagination in my custom CLI
我的 CLI 命令输出需要一个简单的寻呼机。我希望能够在输出中滚动 up/down,一次滚动一整页或逐行滚动。
我看了 "less" 源代码,但是它太复杂了,帮不了我。于是开始自己写一个简单的。到目前为止,我所做的是将命令输出写入文件。然后逐行读取文件并写入ncurses window。当我到达 window 底部时,我等待用户按下一个键,然后清除屏幕并写入新页面等等。结果类似于 "more" 命令。
这是我使用的简单代码:
int print()
{
FILE *fp;
ssize_t read;
int row, col, x, y;
char *line = NULL;
char c;
size_t len;
initscr();
getmaxyx(stdscr, row, col);
fp = fopen("path_to_output_file", "r");
if (!fp)
{
printf("Failed to open CLI output file.\n");
return -1;
}
while ((read = getline(&line, &len, fp)) != -1)
{
getyx(stdscr, y, x);
if (y == (row - 1))
{
printw("Press Any Key to continue...");
c = getch();
if (c == 'q')
{
break;
}
clear();
move(0, 0);
}
printw(line);
refresh();
}
fclose(fp);
getch();
endwin();
return 0
}
现在我需要帮助来找到实现向后滚动以在输出中向上移动一位 page/line 的想法。我应该如何遍历文件并将行打印到 ncurses window 以获得我想要的结果。
除此之外,欢迎任何改进我的简单寻呼机的想法...
虽然您已经在着手处理它,但这里有一个向后移动的实现,它利用 fseek()
来记录 (physical/window) 行开头的偏移量,这些行是在读取行时收集的:
…
keypad(stdscr, TRUE); // enable returning function key tokens
long offset, *pos = NULL, lineno = 0;
char buffer[col+1];
TABSIZE = 1;
do
{ y = 0;
long topline = lineno;
while (offset = ftell(fp), line = fgets(buffer, sizeof buffer, fp))
{
pos = realloc(pos, (lineno+1) * sizeof *pos); if (!pos) exit(1);
pos[lineno++] = offset; // save offset of current line
addstr(line);
getyx(stdscr, y, x);
if (y == row-1)
break;
}
printw("Press [upward arrow] or [Page Up] or any key to continue...");
int c = getch();
if (c == KEY_UP) // Up arrow
fseek(fp, pos[lineno = topline>1 ? topline-1 : 0], SEEK_SET);
else
if (c == KEY_PPAGE) // Previous page
fseek(fp, pos[lineno = topline>=row ? topline-row+1 : 0], SEEK_SET);
else
if (c == 'q' || !line)
break;
clear();
move(0, 0);
} while (1);
fclose(fp);
endwin();
…
作为处理 TAB 问题的简单方法,我将 TABSIZE
设置为 1。
我的 CLI 命令输出需要一个简单的寻呼机。我希望能够在输出中滚动 up/down,一次滚动一整页或逐行滚动。
我看了 "less" 源代码,但是它太复杂了,帮不了我。于是开始自己写一个简单的。到目前为止,我所做的是将命令输出写入文件。然后逐行读取文件并写入ncurses window。当我到达 window 底部时,我等待用户按下一个键,然后清除屏幕并写入新页面等等。结果类似于 "more" 命令。
这是我使用的简单代码:
int print()
{
FILE *fp;
ssize_t read;
int row, col, x, y;
char *line = NULL;
char c;
size_t len;
initscr();
getmaxyx(stdscr, row, col);
fp = fopen("path_to_output_file", "r");
if (!fp)
{
printf("Failed to open CLI output file.\n");
return -1;
}
while ((read = getline(&line, &len, fp)) != -1)
{
getyx(stdscr, y, x);
if (y == (row - 1))
{
printw("Press Any Key to continue...");
c = getch();
if (c == 'q')
{
break;
}
clear();
move(0, 0);
}
printw(line);
refresh();
}
fclose(fp);
getch();
endwin();
return 0
}
现在我需要帮助来找到实现向后滚动以在输出中向上移动一位 page/line 的想法。我应该如何遍历文件并将行打印到 ncurses window 以获得我想要的结果。
除此之外,欢迎任何改进我的简单寻呼机的想法...
虽然您已经在着手处理它,但这里有一个向后移动的实现,它利用 fseek()
来记录 (physical/window) 行开头的偏移量,这些行是在读取行时收集的:
…
keypad(stdscr, TRUE); // enable returning function key tokens
long offset, *pos = NULL, lineno = 0;
char buffer[col+1];
TABSIZE = 1;
do
{ y = 0;
long topline = lineno;
while (offset = ftell(fp), line = fgets(buffer, sizeof buffer, fp))
{
pos = realloc(pos, (lineno+1) * sizeof *pos); if (!pos) exit(1);
pos[lineno++] = offset; // save offset of current line
addstr(line);
getyx(stdscr, y, x);
if (y == row-1)
break;
}
printw("Press [upward arrow] or [Page Up] or any key to continue...");
int c = getch();
if (c == KEY_UP) // Up arrow
fseek(fp, pos[lineno = topline>1 ? topline-1 : 0], SEEK_SET);
else
if (c == KEY_PPAGE) // Previous page
fseek(fp, pos[lineno = topline>=row ? topline-row+1 : 0], SEEK_SET);
else
if (c == 'q' || !line)
break;
clear();
move(0, 0);
} while (1);
fclose(fp);
endwin();
…
作为处理 TAB 问题的简单方法,我将 TABSIZE
设置为 1。