-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnl.cpp
More file actions
84 lines (74 loc) · 2.8 KB
/
nl.cpp
File metadata and controls
84 lines (74 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <cstdio>
#include <string>
#include <cfbox/args.hpp>
#include <cfbox/help.hpp>
#include <cfbox/stream.hpp>
#include <cfbox/error.hpp>
namespace {
constexpr cfbox::help::HelpEntry HELP = {
.name = "nl",
.version = CFBOX_VERSION_STRING,
.one_line = "number lines of files",
.usage = "nl [-b STYLE] [-n FORMAT] [-s SEP] [FILE]...",
.options = " -b STYLE body numbering style: a(all), t(non-empty), n(none)\n"
" -n FORMAT line number format: ln, rn, rz\n"
" -s SEP add SEP after line number (default: TAB)",
.extra = "",
};
} // namespace
auto nl_main(int argc, char* argv[]) -> int {
auto parsed = cfbox::args::parse(argc, argv, {
cfbox::args::OptSpec{'b', true, "body-numbering"},
cfbox::args::OptSpec{'n', true, "number-format"},
cfbox::args::OptSpec{'s', true, "number-separator"},
});
if (parsed.has_long("help")) { cfbox::help::print_help(HELP); return 0; }
if (parsed.has_long("version")) { cfbox::help::print_version(HELP); return 0; }
char body_style = 't';
if (auto b = parsed.get_any('b', "body-numbering")) {
body_style = (*b)[0];
}
std::string num_fmt = "rn";
if (auto n = parsed.get_any('n', "number-format")) {
num_fmt = std::string{*n};
}
std::string sep = "\t";
if (auto s = parsed.get_any('s', "number-separator")) {
sep = std::string{*s};
}
const auto& pos = parsed.positional();
auto paths = pos.empty() ? std::vector<std::string_view>{"-"} : pos;
int rc = 0;
for (auto p : paths) {
int line_num = 0;
auto result = cfbox::stream::for_each_line(p, [&](const std::string& line, std::size_t) {
bool should_number = false;
switch (body_style) {
case 'a': should_number = true; break;
case 't': should_number = !line.empty(); break;
case 'n': should_number = false; break;
default: should_number = !line.empty(); break;
}
if (should_number) {
++line_num;
char numbuf[16];
if (num_fmt == "ln") {
std::snprintf(numbuf, sizeof(numbuf), "%-6d", line_num);
} else if (num_fmt == "rz") {
std::snprintf(numbuf, sizeof(numbuf), "%06d", line_num);
} else {
std::snprintf(numbuf, sizeof(numbuf), "%6d", line_num);
}
std::printf("%s%s%s\n", numbuf, sep.c_str(), line.c_str());
} else {
std::printf(" %s%s\n", sep.c_str(), line.c_str());
}
return true;
});
if (!result) {
CFBOX_ERR("nl", "%s", result.error().msg.c_str());
rc = 1;
}
}
return rc;
}