mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
less: Add -N
option to show line numbers
Co-authored-by: Liav A <liavalb@gmail.com>
This commit is contained in:
parent
499f459f0b
commit
4eb52351b4
2 changed files with 33 additions and 5 deletions
|
@ -5,8 +5,8 @@
|
|||
## Synopsis
|
||||
|
||||
```**sh
|
||||
$ cat file | less [-PXem]
|
||||
$ less [-PXem] [file]
|
||||
$ cat file | less [-PXNem]
|
||||
$ less [-PXNem] [file]
|
||||
$ cat file | more
|
||||
$ more [file]
|
||||
```
|
||||
|
@ -21,6 +21,7 @@ but largely incompatible with
|
|||
|
||||
* `-P`, `--prompt`: Set the prompt format string. See [Prompts](#prompts) for more details.
|
||||
* `-X`, `--no-init`: Don't switch to the xterm alternate buffer on startup.
|
||||
* `-N`, `--line-numbers`: Show line numbers before printed lines.
|
||||
* `-e`, `--quit-at-eof`: Immediately exit less when the last line of the document is reached.
|
||||
* `-m`, `--emulate-more`: Apply `-Xe`, set the prompt to `--More--`, and disable
|
||||
scrollback. This option is automatically applied when `less` is executed as `more`
|
||||
|
|
|
@ -20,6 +20,9 @@ static Atomic<bool> g_resized { false };
|
|||
|
||||
static Atomic<bool> g_restore_buffer_on_close { false };
|
||||
|
||||
constexpr size_t line_number_column_padding = 7;
|
||||
static constexpr StringView line_number_column_separator = " "sv;
|
||||
|
||||
static ErrorOr<void> setup_tty(bool switch_buffer)
|
||||
{
|
||||
// Save previous tty settings.
|
||||
|
@ -68,11 +71,12 @@ static Vector<StringView> wrap_line(DeprecatedString const& string, size_t width
|
|||
|
||||
class Pager {
|
||||
public:
|
||||
Pager(StringView filename, FILE* file, FILE* tty, StringView prompt)
|
||||
Pager(StringView filename, FILE* file, FILE* tty, StringView prompt, bool show_line_numbers)
|
||||
: m_file(file)
|
||||
, m_tty(tty)
|
||||
, m_filename(filename)
|
||||
, m_prompt(prompt)
|
||||
, m_show_line_numbers(show_line_numbers)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -216,10 +220,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static size_t count_digits_in_number(size_t line_numbers)
|
||||
{
|
||||
return line_numbers > 0 ? static_cast<size_t>(log10(static_cast<double>(line_numbers))) + 1 : 1;
|
||||
}
|
||||
|
||||
size_t write_range(size_t line, size_t subline, size_t length)
|
||||
{
|
||||
size_t lines = 0;
|
||||
for (size_t i = line; i < m_lines.size(); ++i) {
|
||||
auto digits_count_for_max_line_number = count_digits_in_number(i + 1);
|
||||
auto column_width = 0;
|
||||
if (m_width > line_number_column_padding + line_number_column_separator.length())
|
||||
column_width = max(line_number_column_padding, digits_count_for_max_line_number);
|
||||
|
||||
for (auto string : sublines(i)) {
|
||||
if (subline > 0) {
|
||||
--subline;
|
||||
|
@ -228,6 +242,9 @@ public:
|
|||
if (lines >= length)
|
||||
return lines;
|
||||
|
||||
if (m_show_line_numbers)
|
||||
out(m_tty, "\e[1m{:>{}}\e[22m{}", i + 1, column_width, line_number_column_separator);
|
||||
|
||||
outln(m_tty, "{}", string);
|
||||
++lines;
|
||||
}
|
||||
|
@ -350,7 +367,13 @@ private:
|
|||
Vector<StringView> const& sublines(size_t line)
|
||||
{
|
||||
return m_subline_cache.ensure(line, [&]() {
|
||||
return wrap_line(m_lines[line], m_width);
|
||||
auto width = m_width;
|
||||
if (m_show_line_numbers) {
|
||||
auto line_number_column_width = max(line_number_column_padding, count_digits_in_number(line)) + line_number_column_separator.length();
|
||||
if (width > line_number_column_width)
|
||||
width -= line_number_column_width;
|
||||
}
|
||||
return wrap_line(m_lines[line], width);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -453,6 +476,8 @@ private:
|
|||
|
||||
DeprecatedString m_filename;
|
||||
DeprecatedString m_prompt;
|
||||
|
||||
bool m_show_line_numbers { false };
|
||||
};
|
||||
|
||||
/// Return the next key sequence, or nothing if a signal is received while waiting
|
||||
|
@ -498,6 +523,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
bool dont_switch_buffer = false;
|
||||
bool quit_at_eof = false;
|
||||
bool emulate_more = false;
|
||||
bool show_line_numbers = false;
|
||||
|
||||
if (LexicalPath::basename(arguments.strings[0]) == "more"sv)
|
||||
emulate_more = true;
|
||||
|
@ -506,6 +532,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
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(dont_switch_buffer, "Don't use xterm alternate buffer", "no-init", 'X');
|
||||
args_parser.add_option(show_line_numbers, "Show line numbers", "line-numbers", 'N');
|
||||
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(arguments);
|
||||
|
@ -558,7 +585,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
ignore_action.sa_handler = { SIG_IGN };
|
||||
TRY(Core::System::sigaction(SIGINT, &ignore_action, nullptr));
|
||||
|
||||
Pager pager(filename, file, stdout, prompt);
|
||||
Pager pager(filename, file, stdout, prompt, show_line_numbers);
|
||||
pager.init();
|
||||
|
||||
StringBuilder modifier_buffer = StringBuilder(10);
|
||||
|
|
Loading…
Reference in a new issue