summaryrefslogtreecommitdiffstats
path: root/src/base/lnav.console.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/base/lnav.console.cc143
1 files changed, 136 insertions, 7 deletions
diff --git a/src/base/lnav.console.cc b/src/base/lnav.console.cc
index a34ebac..b9d2d6c 100644
--- a/src/base/lnav.console.cc
+++ b/src/base/lnav.console.cc
@@ -45,6 +45,45 @@ using namespace lnav::roles::literals;
namespace lnav {
namespace console {
+snippet
+snippet::from_content_with_offset(intern_string_t src,
+ const attr_line_t& content,
+ size_t offset,
+ const std::string& errmsg)
+{
+ auto content_sf = string_fragment::from_str(content.get_string());
+ auto line_with_error = content_sf.find_boundaries_around(
+ offset, string_fragment::tag1{'\n'});
+ auto line_with_context = content_sf.find_boundaries_around(
+ offset, string_fragment::tag1{'\n'}, 3);
+ auto line_number = content_sf.sub_range(0, offset).count('\n');
+ auto erroff_in_line = offset - line_with_error.sf_begin;
+
+ attr_line_t pointer;
+
+ pointer.append(erroff_in_line, ' ')
+ .append("^ "_snippet_border)
+ .append(lnav::roles::error(errmsg))
+ .with_attr_for_all(VC_ROLE.value(role_t::VCR_QUOTED_CODE));
+
+ snippet retval;
+ retval.s_content
+ = content.subline(line_with_context.sf_begin,
+ line_with_error.sf_end - line_with_context.sf_begin);
+ if (line_with_error.sf_end >= retval.s_content.get_string().size()) {
+ retval.s_content.append("\n");
+ }
+ retval.s_content.append(pointer).append(
+ content.subline(line_with_error.sf_end,
+ line_with_context.sf_end - line_with_error.sf_end));
+ retval.s_location = source_location{
+ src,
+ static_cast<int32_t>(1 + line_number),
+ };
+
+ return retval;
+}
+
user_message
user_message::raw(const attr_line_t& al)
{
@@ -238,13 +277,38 @@ curses_color_to_terminal_color(int curses_color)
}
}
+static bool
+get_no_color()
+{
+ return getenv("NO_COLOR") != nullptr;
+}
+
+static bool
+get_yes_color()
+{
+ return getenv("YES_COLOR") != nullptr;
+}
+
+static bool
+get_fd_tty(int fd)
+{
+ return isatty(fd);
+}
+
void
println(FILE* file, const attr_line_t& al)
{
+ static const auto IS_NO_COLOR = get_no_color();
+ static const auto IS_YES_COLOR = get_yes_color();
+ static const auto IS_STDOUT_TTY = get_fd_tty(STDOUT_FILENO);
+ static const auto IS_STDERR_TTY = get_fd_tty(STDERR_FILENO);
+
const auto& str = al.get_string();
- if (getenv("NO_COLOR") != nullptr
- || (!isatty(fileno(file)) && getenv("YES_COLOR") == nullptr))
+ if (IS_NO_COLOR || (file != stdout && file != stderr)
+ || (((file == stdout && !IS_STDOUT_TTY)
+ || (file == stderr && !IS_STDERR_TTY))
+ && !IS_YES_COLOR))
{
fmt::print(file, "{}\n", str);
return;
@@ -273,6 +337,7 @@ println(FILE* file, const attr_line_t& al)
auto line_style = fmt::text_style{};
auto fg_style = fmt::text_style{};
auto start = last_point.value();
+ nonstd::optional<std::string> href;
for (const auto& attr : al.get_attrs()) {
if (!attr.sa_range.contains(start)
@@ -282,7 +347,10 @@ println(FILE* file, const attr_line_t& al)
}
try {
- if (attr.sa_type == &VC_BACKGROUND) {
+ if (attr.sa_type == &VC_HYPERLINK) {
+ auto saw = string_attr_wrapper<std::string>(&attr);
+ href = saw.get();
+ } else if (attr.sa_type == &VC_BACKGROUND) {
auto saw = string_attr_wrapper<int64_t>(&attr);
auto color_opt = curses_color_to_terminal_color(saw.get());
@@ -349,6 +417,9 @@ println(FILE* file, const attr_line_t& al)
case role_t::VCR_TEXT:
case role_t::VCR_IDENTIFIER:
break;
+ case role_t::VCR_ALT_ROW:
+ line_style |= fmt::emphasis::bold;
+ break;
case role_t::VCR_SEARCH:
line_style |= fmt::emphasis::reverse;
break;
@@ -407,6 +478,7 @@ println(FILE* file, const attr_line_t& al)
case role_t::VCR_LIST_GLYPH:
line_style |= fmt::fg(fmt::terminal_color::yellow);
break;
+ case role_t::VCR_INLINE_CODE:
case role_t::VCR_QUOTED_CODE:
default_fg_style
= fmt::fg(fmt::terminal_color::white);
@@ -442,12 +514,69 @@ println(FILE* file, const attr_line_t& al)
line_style |= default_bg_style;
}
+ if (line_style.has_foreground() && line_style.has_background()
+ && !line_style.get_foreground().is_rgb
+ && !line_style.get_background().is_rgb
+ && line_style.get_foreground().value.term_color
+ == line_style.get_background().value.term_color)
+ {
+ auto new_style = fmt::text_style{};
+
+ if (line_style.has_emphasis()) {
+ new_style |= line_style.get_emphasis();
+ }
+ new_style |= fmt::fg(line_style.get_foreground());
+ if (line_style.get_background().value.term_color
+ == lnav::enums::to_underlying(fmt::terminal_color::black))
+ {
+ new_style |= fmt::bg(fmt::terminal_color::white);
+ } else {
+ new_style |= fmt::bg(fmt::terminal_color::black);
+ }
+ line_style = new_style;
+ }
+
+ if (href) {
+ fmt::print(file, FMT_STRING("\x1b]8;;{}\x1b\\"), href.value());
+ }
if (start < str.size()) {
auto actual_end = std::min(str.size(), static_cast<size_t>(point));
- fmt::print(file,
- line_style,
- FMT_STRING("{}"),
- str.substr(start, actual_end - start));
+ auto sub = std::string{};
+
+ for (auto lpc = start; lpc < actual_end;) {
+ auto cp_start = lpc;
+ auto read_res = ww898::utf::utf8::read(
+ [&str, &lpc]() { return str[lpc++]; });
+
+ if (read_res.isErr()) {
+ sub.append(fmt::format(
+ FMT_STRING("{:?}"),
+ fmt::string_view{&str[cp_start], lpc - cp_start}));
+ continue;
+ }
+
+ auto ch = read_res.unwrap();
+ switch (ch) {
+ case '\b':
+ sub.append("\u232b");
+ break;
+ case '\x1b':
+ sub.append("\u238b");
+ break;
+ case '\x07':
+ sub.append("\U0001F514");
+ break;
+
+ default:
+ sub.append(&str[cp_start], lpc - cp_start);
+ break;
+ }
+ }
+
+ fmt::print(file, line_style, FMT_STRING("{}"), sub);
+ }
+ if (href) {
+ fmt::print(file, FMT_STRING("\x1b]8;;\x1b\\"));
}
last_point = point;
}