mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 19:05:08 +00:00
Userland: Add more(1) emulation to less(1)
This patch also removes the existing implementation of more, as it is now redundant.
This commit is contained in:
parent
30aa9b837c
commit
c6fa2f196a
4 changed files with 38 additions and 65 deletions
1
Base/bin/more
Symbolic link
1
Base/bin/more
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/bin/less
|
|
@ -8,7 +8,7 @@ list(APPEND REQUIRED_TARGETS
|
||||||
)
|
)
|
||||||
list(APPEND RECOMMENDED_TARGETS
|
list(APPEND RECOMMENDED_TARGETS
|
||||||
adjtime aplay avol bt checksum chres cksum copy fortune gunzip gzip init keymap lsirq lsof lspci man mknod mktemp
|
adjtime aplay avol bt checksum chres cksum copy fortune gunzip gzip init keymap lsirq lsof lspci man mknod mktemp
|
||||||
modload modunload more nc netstat notify ntpquery open pape passwd pls printf pro shot tar tt unzip zip
|
modload modunload nc netstat notify ntpquery open pape passwd pls printf pro shot tar tt unzip zip
|
||||||
)
|
)
|
||||||
|
|
||||||
# FIXME: Support specifying component dependencies for utilities (e.g. WebSocket for telws)
|
# FIXME: Support specifying component dependencies for utilities (e.g. WebSocket for telws)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
|
#include <AK/LexicalPath.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <AK/Utf8View.h>
|
#include <AK/Utf8View.h>
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
static struct termios g_save;
|
static struct termios g_save;
|
||||||
static struct winsize g_wsize;
|
static struct winsize g_wsize;
|
||||||
|
|
||||||
static void setup_tty()
|
static void setup_tty(bool switch_buffer)
|
||||||
{
|
{
|
||||||
// Save previous tty settings.
|
// Save previous tty settings.
|
||||||
if (tcgetattr(STDOUT_FILENO, &g_save) == -1) {
|
if (tcgetattr(STDOUT_FILENO, &g_save) == -1) {
|
||||||
|
@ -40,17 +41,21 @@ static void setup_tty()
|
||||||
perror("tcsetattr(3)");
|
perror("tcsetattr(3)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save cursor and switch to alternate buffer.
|
if (switch_buffer) {
|
||||||
out("\e[s\e[?1047h");
|
// Save cursor and switch to alternate buffer.
|
||||||
|
out("\e[s\e[?1047h");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void teardown_tty()
|
static void teardown_tty(bool switch_buffer)
|
||||||
{
|
{
|
||||||
if (tcsetattr(STDOUT_FILENO, TCSAFLUSH, &g_save) == -1) {
|
if (tcsetattr(STDOUT_FILENO, TCSAFLUSH, &g_save) == -1) {
|
||||||
perror("tcsetattr(3)");
|
perror("tcsetattr(3)");
|
||||||
}
|
}
|
||||||
|
|
||||||
out("\e[?1047l\e[u");
|
if (switch_buffer) {
|
||||||
|
out("\e[?1047l\e[u");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector<String> wrap_line(Utf8View const& string, size_t width)
|
static Vector<String> wrap_line(Utf8View const& string, size_t width)
|
||||||
|
@ -260,6 +265,7 @@ private:
|
||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Don't save scrollback when emulating more.
|
||||||
Vector<String> m_lines;
|
Vector<String> m_lines;
|
||||||
size_t m_line { 0 };
|
size_t m_line { 0 };
|
||||||
FILE* m_file;
|
FILE* m_file;
|
||||||
|
@ -284,10 +290,19 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
char const* filename = "-";
|
char const* filename = "-";
|
||||||
char const* prompt = "?f%f :.(line %l)?e (END):.";
|
char const* prompt = "?f%f :.(line %l)?e (END):.";
|
||||||
|
bool dont_switch_buffer = false;
|
||||||
|
bool quit_at_eof = false;
|
||||||
|
bool emulate_more = false;
|
||||||
|
|
||||||
|
if (LexicalPath::basename(argv[0]) == "more"sv)
|
||||||
|
emulate_more = true;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.add_positional_argument(filename, "The paged file", "file", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(filename, "The paged file", "file", Core::ArgsParser::Required::No);
|
||||||
args_parser.add_option(prompt, "Prompt line", "prompt", 'P', "Prompt");
|
args_parser.add_option(prompt, "Prompt line", "prompt", 'P', "Prompt");
|
||||||
|
args_parser.add_option(dont_switch_buffer, "Don't use xterm alternate buffer", "no-init", 'X');
|
||||||
|
args_parser.add_option(quit_at_eof, "Exit when the end of the file is reached", "quit-at-eof", 'e');
|
||||||
|
args_parser.add_option(emulate_more, "Pretend that we are more(1)", "emulate-more", 'm');
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
FILE* file;
|
FILE* file;
|
||||||
|
@ -297,7 +312,14 @@ int main(int argc, char** argv)
|
||||||
file = fopen(filename, "r");
|
file = fopen(filename, "r");
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_tty();
|
if (emulate_more) {
|
||||||
|
// Configure options that match more's behavior
|
||||||
|
dont_switch_buffer = true;
|
||||||
|
quit_at_eof = true;
|
||||||
|
prompt = "--More--";
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_tty(!dont_switch_buffer);
|
||||||
|
|
||||||
Pager pager(file, stdout, g_wsize.ws_col, g_wsize.ws_row);
|
Pager pager(file, stdout, g_wsize.ws_col, g_wsize.ws_row);
|
||||||
pager.set_filename(filename);
|
pager.set_filename(filename);
|
||||||
|
@ -311,12 +333,18 @@ int main(int argc, char** argv)
|
||||||
} else if (sequence == "j" || sequence == "\e[B" || sequence == "\n") {
|
} else if (sequence == "j" || sequence == "\e[B" || sequence == "\n") {
|
||||||
pager.down();
|
pager.down();
|
||||||
} else if (sequence == "k" || sequence == "\e[A") {
|
} else if (sequence == "k" || sequence == "\e[A") {
|
||||||
pager.up();
|
if (!emulate_more)
|
||||||
|
pager.up();
|
||||||
} else if (sequence == " ") {
|
} else if (sequence == " ") {
|
||||||
pager.down_page();
|
pager.down_page();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (quit_at_eof && pager.at_end())
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown_tty();
|
pager.clear_status();
|
||||||
|
|
||||||
|
teardown_tty(!dont_switch_buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <AK/Format.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static int key_fd;
|
|
||||||
|
|
||||||
static void wait_for_key()
|
|
||||||
{
|
|
||||||
out("\033[7m--[ more ]--\033[0m");
|
|
||||||
fflush(stdout);
|
|
||||||
char dummy;
|
|
||||||
[[maybe_unused]] auto rc = read(key_fd, &dummy, 1);
|
|
||||||
outln();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv)
|
|
||||||
{
|
|
||||||
if (pledge("stdio rpath tty", nullptr) < 0) {
|
|
||||||
perror("pledge");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
key_fd = STDOUT_FILENO;
|
|
||||||
|
|
||||||
struct winsize ws;
|
|
||||||
ioctl(1, TIOCGWINSZ, &ws);
|
|
||||||
|
|
||||||
if (pledge("stdio", nullptr) < 0) {
|
|
||||||
perror("pledge");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned lines_printed = 0;
|
|
||||||
while (!feof(stdin)) {
|
|
||||||
char buffer[BUFSIZ];
|
|
||||||
auto* str = fgets(buffer, sizeof(buffer), stdin);
|
|
||||||
if (!str)
|
|
||||||
break;
|
|
||||||
out("{}", str);
|
|
||||||
++lines_printed;
|
|
||||||
if ((lines_printed % (ws.ws_row - 1)) == 0) {
|
|
||||||
wait_for_key();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(key_fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue