diff options
author | balatt <56897347+balatt@users.noreply.github.com> | 2019-11-04 06:44:32 -0500 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-04 12:44:32 +0100 |
commit | d5b66a02c404d1d70dcf870bdd1a6973615f5a1b (patch) | |
tree | 402a73be5113df67b17b8cf46e94a14a55f2af0a | |
parent | 0d471266ce21b64df9030faccd8d997c189ff12b (diff) | |
download | serenity-d5b66a02c404d1d70dcf870bdd1a6973615f5a1b.zip |
Userland: Add the utility "nl" (number line) (#693)
I wrote a version of nl for Serenity with a lot but not all of the
options in POSIX nl. It includes line count type (-b), increment (-i),
delimiter (-s), start number (-v), and width (-w).
-rw-r--r-- | Userland/nl.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/Userland/nl.cpp b/Userland/nl.cpp new file mode 100644 index 0000000000..b871ef56bf --- /dev/null +++ b/Userland/nl.cpp @@ -0,0 +1,114 @@ +#include <AK/String.h> +#include <AK/Vector.h> +#include <LibCore/CArgsParser.h> + +#include <stdio.h> +#include <string.h> + +int main(int argc, char** argv) +{ + CArgsParser args_parser("nl"); + args_parser.add_arg("b", "type", "Line count type. \n\tt counts non-empty lines. \n\ta counts all lines. \n\tn counts no lines."); + args_parser.add_arg("i", "incr", "Set line count increment."); + args_parser.add_arg("s", "delim", "Set buffer between the line numbers and text. 1-63 bytes"); + args_parser.add_arg("v", "startnum", "Initial value used to number logical page lines."); + args_parser.add_arg("w", "width", "The number of characters used for the line number."); + args_parser.add_single_value("file"); + CArgsParserResult args = args_parser.parse(argc, argv); + + bool all_lines_flag = false; + bool line_numbers_flag = true; + String value_of_b; + if (args.is_present("b")) { + value_of_b = args.get("b"); + if (value_of_b == "a") + all_lines_flag = true; + else if (value_of_b == "t") + all_lines_flag = false; + else if (value_of_b == "n") + line_numbers_flag = false; + else { + args_parser.print_usage(); + return 1; + } + } + + long line_number_increment = 1; + String value_of_i; + if (args.is_present("i")) { + value_of_i = args.get("i"); + line_number_increment = atol(value_of_i.characters()); + if (!line_number_increment) { + args_parser.print_usage(); + return 1; + } + } + + bool delimiter_flag = false; + String value_of_s; + if (args.is_present("s")) { + value_of_s = args.get("s"); + if (value_of_s.length() > 0 && value_of_s.length() < 64) + delimiter_flag = true; + else { + args_parser.print_usage(); + return 1; + } + } + char delimiter[64]; + strcpy(delimiter, delimiter_flag ? value_of_s.characters() : " "); + + long line_number = 1; + String value_of_v; + if (args.is_present("v")) { + value_of_v = args.get("v"); + line_number = atol(value_of_v.characters()); + } + + String value_of_w; + unsigned int line_number_width = 6; + if (args.is_present("w")) { + value_of_w = args.get("w"); + line_number_width = atol(value_of_w.characters()); + } + + Vector<String> files = args.get_single_values(); + Vector<FILE*> file_pointers; + if (files.size() > 0) { + for (auto& file : files) { + FILE* file_pointer; + if ((file_pointer = fopen(file.characters(), "r")) == NULL) { + fprintf(stderr, "unable to open %s\n", file.characters()); + continue; + } + file_pointers.append(file_pointer); + } + } else { + file_pointers.append(stdin); + } + + line_number -= line_number_increment; // so the line number can start at 1 when added below + for (auto& file_pointer : file_pointers) { + int previous_character = 0; + int next_character = 0; + while ((next_character = fgetc(file_pointer)) != EOF) { + if (previous_character == 0 || previous_character == '\n') { + if (!all_lines_flag && next_character == '\n') { + // skips printing line count on empty lines if all_lines_flags is false + printf("\n"); + continue; + } + if (line_numbers_flag) + printf("%*lu%s", line_number_width, (line_number += line_number_increment), delimiter); + else + printf("%*s", line_number_width, ""); + } + putchar(next_character); + previous_character = next_character; + } + fclose(file_pointer); + if (previous_character != '\n') + printf("\n"); // for cases where files have no trailing newline + } + return 0; +} |