diff options
Diffstat (limited to '')
-rw-r--r-- | src/base/lnav.console.cc | 143 |
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; } |