Merge pull request #40 from fischerling/add-pager

add simple `more(1)` implementation and use it for man pages
This commit is contained in:
Enrico Fraccaroli
2024-03-01 13:32:27 -05:00
committed by GitHub
4 changed files with 112 additions and 1 deletions
+13
View File
@@ -0,0 +1,13 @@
SYNOPSIS
more [FILE]
DESCRIPTION
more is a filter for paging through text one screenful at a time.
OPTIONS
-h, --help: shows command help.
KEY BINDINGS
q Exit from more
space Display next screen size
return Display next line
+1
View File
@@ -1,5 +1,6 @@
# List of programs.
set(PROGRAM_LIST
more.c
chmod.c
chown.c
id.c
+1 -1
View File
@@ -40,7 +40,7 @@ int main(int argc, char *argv[])
}
else if (argc == 2)
{
char *pager = "cat";
char *pager = "more";
char filepath[PATH_MAX];
strcpy(filepath, "/usr/share/man/");
strcat(filepath, argv[1]);
+97
View File
@@ -0,0 +1,97 @@
/// @file more.c
/// @brief `more` program.
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "stdbool.h"
#include "stddef.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/unistd.h>
#include <strerror.h>
#include <sys/stat.h>
#include <termios.h>
// Video dimensions defined in mentos/src/io/video.c
#define HEIGHT 25
#define WIDTH 80
#define LAST_LINE (HEIGHT - 1)
static void erase_backwards(int n)
{
for (int i = 0; i < n; i++) {
putchar('\b');
}
}
static void page_content(int fd)
{
int lines = 0;
char line[WIDTH + 2];
char *lineend;
while((lineend = fgets(line, WIDTH, fd))) {
if (lineend - line == WIDTH && line[WIDTH-1] != '\n') {
line[WIDTH - 1] = '+';
line[WIDTH] = '\n';
line[WIDTH + 1] = 0;
}
printf("%s", line);
lines++;
if (lines == LAST_LINE) {
int prompt = printf("--more--");
int c;
bool_t quit = false;
do {
c = getchar();
if (c == 'q') {
quit = true;
} else if (c == '\n') {
lines = LAST_LINE - 1;
} else if (c == ' ') {
lines = 0;
} else {
continue;
}
break;
} while(1);
erase_backwards(prompt);
if (quit)
exit(EXIT_SUCCESS);
}
}
}
int main(int argc, char **argv)
{
// Check if `--help` is provided.
for (int i = 1; i < argc; ++i) {
if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0)) {
printf("Display the content of a file.\n");
printf("Usage:\n");
printf(" more [FILE]\n");
return 0;
}
}
struct termios _termios;
tcgetattr(STDIN_FILENO, &_termios);
_termios.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, 0, &_termios);
int fd = STDOUT_FILENO;
if (argc > 1) {
fd = open(argv[1], O_RDONLY, 0);
if (fd < 0) {
printf("more: %s: %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
}
page_content(fd);
return 0;
}