[readline] add support for default completions

pull/1242/head
Tim Stack 3 months ago
parent db5db6a07e
commit 6bb616e034

@ -7,6 +7,11 @@ Interface changes:
configuration panel instead of `q`. This should make configuration panel instead of `q`. This should make
it easier to avoid accidentally exiting lnav. it easier to avoid accidentally exiting lnav.
* Added some default help text for the command prompt. * Added some default help text for the command prompt.
* Suggestions are now shown for some commands and can
be accepted by pressing the right arrow key. For
example, after typing in `:filter-in` the current
search term for the view will be suggested (if
one is active).
## lnav v0.12.0 ## lnav v0.12.0

@ -680,6 +680,11 @@
"description": "Styling for hotkey highlights of status bars", "description": "Styling for hotkey highlights of status bars",
"title": "/ui/theme-defs/<theme_name>/status-styles/hotkey", "title": "/ui/theme-defs/<theme_name>/status-styles/hotkey",
"$ref": "#/definitions/style" "$ref": "#/definitions/style"
},
"suggestion": {
"description": "Styling for suggested values",
"title": "/ui/theme-defs/<theme_name>/status-styles/suggestion",
"$ref": "#/definitions/style"
} }
}, },
"additionalProperties": false "additionalProperties": false

@ -135,6 +135,7 @@ enum class role_t : int32_t {
VCR_FUNCTION, VCR_FUNCTION,
VCR_TYPE, VCR_TYPE,
VCR_SEP_REF_ACC, VCR_SEP_REF_ACC,
VCR_SUGGESTION,
VCR__MAX VCR__MAX
}; };
@ -535,6 +536,14 @@ h6(S str)
VC_ROLE.template value(role_t::VCR_H6)); VC_ROLE.template value(role_t::VCR_H6));
} }
template<typename S>
inline std::pair<S, string_attr_pair>
suggestion(S str)
{
return std::make_pair(std::move(str),
VC_ROLE.template value(role_t::VCR_SUGGESTION));
}
namespace literals { namespace literals {
inline std::pair<std::string, string_attr_pair> operator"" _ok(const char* str, inline std::pair<std::string, string_attr_pair> operator"" _ok(const char* str,

@ -300,6 +300,8 @@ breadcrumb_curses::handle_key(int ch)
case '\r': case '\r':
this->perform_selection(perform_behavior_t::always); this->perform_selection(perform_behavior_t::always);
break; break;
case KEY_ESCAPE:
break;
default: default:
if (isprint(ch)) { if (isprint(ch)) {
this->bc_current_search.push_back(ch); this->bc_current_search.push_back(ch);

@ -151,9 +151,9 @@ filter_sub_source::list_input_handle_key(listview_curses& lv, int ch)
return true; return true;
} }
case 'i': { case 'i': {
textview_curses* top_view = *lnav_data.ld_view_stack.top(); auto* top_view = *lnav_data.ld_view_stack.top();
text_sub_source* tss = top_view->get_sub_source(); auto* tss = top_view->get_sub_source();
filter_stack& fs = tss->get_filters(); auto& fs = tss->get_filters();
auto filter_index = fs.next_index(); auto filter_index = fs.next_index();
if (!filter_index) { if (!filter_index) {
@ -434,25 +434,32 @@ filter_sub_source::rl_change(readline_curses* rc)
case filter_lang_t::NONE: case filter_lang_t::NONE:
break; break;
case filter_lang_t::REGEX: { case filter_lang_t::REGEX: {
auto regex_res if (new_value.empty()) {
= lnav::pcre2pp::code::from(new_value, PCRE2_CASELESS); if (fs.get_filter(top_view->get_current_search()) == nullptr) {
this->fss_editor->set_suggestion(
if (regex_res.isErr()) { top_view->get_current_search());
auto pe = regex_res.unwrapErr(); }
lnav_data.ld_filter_help_status_source.fss_error.set_value(
"error: %s", pe.get_message().c_str());
} else { } else {
auto& hm = top_view->get_highlights(); auto regex_res
highlighter hl(regex_res.unwrap().to_shared()); = lnav::pcre2pp::code::from(new_value, PCRE2_CASELESS);
auto role = tf->get_type() == text_filter::EXCLUDE
? role_t::VCR_DIFF_DELETE if (regex_res.isErr()) {
: role_t::VCR_DIFF_ADD; auto pe = regex_res.unwrapErr();
hl.with_role(role); lnav_data.ld_filter_help_status_source.fss_error.set_value(
hl.with_attrs(text_attrs{A_BLINK | A_REVERSE}); "error: %s", pe.get_message().c_str());
} else {
hm[{highlight_source_t::PREVIEW, "preview"}] = hl; auto& hm = top_view->get_highlights();
top_view->set_needs_update(); highlighter hl(regex_res.unwrap().to_shared());
lnav_data.ld_filter_help_status_source.fss_error.clear(); auto role = tf->get_type() == text_filter::EXCLUDE
? role_t::VCR_DIFF_DELETE
: role_t::VCR_DIFF_ADD;
hl.with_role(role);
hl.with_attrs(text_attrs{A_BLINK | A_REVERSE});
hm[{highlight_source_t::PREVIEW, "preview"}] = hl;
top_view->set_needs_update();
lnav_data.ld_filter_help_status_source.fss_error.clear();
}
} }
break; break;
} }

@ -895,7 +895,7 @@ handle_key(int ch)
return handle_paging_key(ch); return handle_paging_key(ch);
case ln_mode_t::BREADCRUMBS: case ln_mode_t::BREADCRUMBS:
if (!breadcrumb_view.handle_key(ch)) { if (ch == '`' || !breadcrumb_view.handle_key(ch)) {
lnav_data.ld_mode = ln_mode_t::PAGING; lnav_data.ld_mode = ln_mode_t::PAGING;
lnav_data.ld_view_stack.set_needs_update(); lnav_data.ld_view_stack.set_needs_update();
return true; return true;

@ -436,47 +436,68 @@ com_set_file_timezone(exec_context& ec,
return Ok(retval); return Ok(retval);
} }
static std::string static readline_context::prompt_result_t
com_set_file_timezone_prompt(exec_context& ec, const std::string& cmdline) com_set_file_timezone_prompt(exec_context& ec, const std::string& cmdline)
{ {
std::string retval;
auto* tc = *lnav_data.ld_view_stack.top(); auto* tc = *lnav_data.ld_view_stack.top();
auto* lss = dynamic_cast<logfile_sub_source*>(tc->get_sub_source()); auto* lss = dynamic_cast<logfile_sub_source*>(tc->get_sub_source());
if (lss != nullptr && lss->text_line_count() > 0) { if (lss == nullptr || lss->text_line_count() == 0) {
auto line_pair = lss->find_line_with_file(lss->at(tc->get_selection())); return {};
if (line_pair) { }
try {
static auto& safe_options_hier
= injector::get<lnav::safe_file_options_hier&>();
safe::ReadAccess<lnav::safe_file_options_hier> options_hier( shlex lexer(cmdline);
safe_options_hier); auto split_res = lexer.split(ec.create_resolver());
auto file_zone = date::get_tzdb().current_zone()->name(); if (split_res.isErr()) {
auto pattern_arg = line_pair->first->get_filename(); return {};
auto match_res }
= options_hier->match(line_pair->first->get_filename());
if (match_res) {
file_zone
= match_res->second.fo_default_zone.pp_value->name();
pattern_arg = match_res->first;
}
retval = fmt::format(FMT_STRING("{} {} {}"), auto line_pair = lss->find_line_with_file(lss->at(tc->get_selection()));
trim(cmdline), if (!line_pair) {
date::get_tzdb().current_zone()->name(), return {};
pattern_arg); }
} catch (const std::runtime_error& e) {
log_error("cannot get timezones: %s", e.what()); auto elems = split_res.unwrap();
auto pattern_arg = line_pair->first->get_filename();
if (elems.size() == 1) {
try {
static auto& safe_options_hier
= injector::get<lnav::safe_file_options_hier&>();
safe::ReadAccess<lnav::safe_file_options_hier> options_hier(
safe_options_hier);
auto file_zone = date::get_tzdb().current_zone()->name();
auto match_res = options_hier->match(pattern_arg);
if (match_res) {
file_zone = match_res->second.fo_default_zone.pp_value->name();
pattern_arg = match_res->first;
auto new_prompt = fmt::format(FMT_STRING("{} {} {}"),
trim(cmdline),
file_zone,
pattern_arg);
return {new_prompt};
} }
return {"", file_zone};
} catch (const std::runtime_error& e) {
log_error("cannot get timezones: %s", e.what());
} }
} }
auto arg_path = ghc::filesystem::path(pattern_arg);
auto arg_parent = arg_path.parent_path().string() + "/";
if (elems.size() == 2 && endswith(cmdline, " ")) {
return {"", arg_parent};
}
if (elems.size() == 3 && elems.back().se_value == arg_parent) {
return {"", arg_path.filename().string()};
}
return retval; return {};
} }
static std::string static readline_context::prompt_result_t
com_clear_file_timezone_prompt(exec_context& ec, const std::string& cmdline) com_clear_file_timezone_prompt(exec_context& ec, const std::string& cmdline)
{ {
std::string retval; std::string retval;
@ -511,7 +532,7 @@ com_clear_file_timezone_prompt(exec_context& ec, const std::string& cmdline)
} }
} }
return retval; return {retval};
} }
static Result<std::string, lnav::console::user_message> static Result<std::string, lnav::console::user_message>
@ -1031,18 +1052,20 @@ com_mark_expr(exec_context& ec,
return Ok(retval); return Ok(retval);
} }
static std::string static readline_context::prompt_result_t
com_mark_expr_prompt(exec_context& ec, const std::string& cmdline) com_mark_expr_prompt(exec_context& ec, const std::string& cmdline)
{ {
textview_curses* tc = *lnav_data.ld_view_stack.top(); textview_curses* tc = *lnav_data.ld_view_stack.top();
if (tc != &lnav_data.ld_views[LNV_LOG]) { if (tc != &lnav_data.ld_views[LNV_LOG]) {
return ""; return {""};
} }
return fmt::format(FMT_STRING("{} {}"), return {
trim(cmdline), fmt::format(FMT_STRING("{} {}"),
trim(lnav_data.ld_log_source.get_sql_marker_text())); trim(cmdline),
trim(lnav_data.ld_log_source.get_sql_marker_text())),
};
} }
static Result<std::string, lnav::console::user_message> static Result<std::string, lnav::console::user_message>
@ -2388,6 +2411,20 @@ com_filter(exec_context& ec,
return Ok(retval); return Ok(retval);
} }
static readline_context::prompt_result_t
com_filter_prompt(exec_context& ec, const std::string& cmdline)
{
const auto* tc = lnav_data.ld_view_stack.top().value();
std::vector<std::string> args;
split_ws(cmdline, args);
if (args.size() > 1) {
return {};
}
return {"", tc->get_current_search()};
}
static Result<std::string, lnav::console::user_message> static Result<std::string, lnav::console::user_message>
com_delete_filter(exec_context& ec, com_delete_filter(exec_context& ec,
std::string cmdline, std::string cmdline,
@ -2564,18 +2601,20 @@ com_filter_expr(exec_context& ec,
return Ok(retval); return Ok(retval);
} }
static std::string static readline_context::prompt_result_t
com_filter_expr_prompt(exec_context& ec, const std::string& cmdline) com_filter_expr_prompt(exec_context& ec, const std::string& cmdline)
{ {
textview_curses* tc = *lnav_data.ld_view_stack.top(); auto* tc = *lnav_data.ld_view_stack.top();
if (tc != &lnav_data.ld_views[LNV_LOG]) { if (tc != &lnav_data.ld_views[LNV_LOG]) {
return ""; return {""};
} }
return fmt::format(FMT_STRING("{} {}"), return {
trim(cmdline), fmt::format(FMT_STRING("{} {}"),
trim(lnav_data.ld_log_source.get_sql_filter_text())); trim(cmdline),
trim(lnav_data.ld_log_source.get_sql_filter_text())),
};
} }
static Result<std::string, lnav::console::user_message> static Result<std::string, lnav::console::user_message>
@ -3616,13 +3655,13 @@ com_comment(exec_context& ec,
return Ok(retval); return Ok(retval);
} }
static std::string static readline_context::prompt_result_t
com_comment_prompt(exec_context& ec, const std::string& cmdline) com_comment_prompt(exec_context& ec, const std::string& cmdline)
{ {
textview_curses* tc = *lnav_data.ld_view_stack.top(); auto* tc = *lnav_data.ld_view_stack.top();
if (tc != &lnav_data.ld_views[LNV_LOG]) { if (tc != &lnav_data.ld_views[LNV_LOG]) {
return ""; return {""};
} }
auto& lss = lnav_data.ld_log_source; auto& lss = lnav_data.ld_log_source;
@ -3633,10 +3672,10 @@ com_comment_prompt(exec_context& ec, const std::string& cmdline)
auto buf = auto_buffer::alloc(trimmed_comment.size() + 16); auto buf = auto_buffer::alloc(trimmed_comment.size() + 16);
quote_content(buf, trimmed_comment, 0); quote_content(buf, trimmed_comment, 0);
return trim(cmdline) + " " + buf.to_string(); return {trim(cmdline) + " " + buf.to_string()};
} }
return ""; return {""};
} }
static Result<std::string, lnav::console::user_message> static Result<std::string, lnav::console::user_message>
@ -6052,30 +6091,37 @@ readline_context::command_t STD_COMMANDS[] = {
.with_opposites({"highlight"}) .with_opposites({"highlight"})
.with_example( .with_example(
{"To clear the highlight with the pattern 'foobar'", "foobar"})}, {"To clear the highlight with the pattern 'foobar'", "foobar"})},
{"filter-in", {
com_filter, "filter-in",
com_filter,
help_text(":filter-in") help_text(":filter-in")
.with_summary("Only show lines that match the given regular " .with_summary("Only show lines that match the given regular "
"expression in the current view") "expression in the current view")
.with_parameter( .with_parameter(
help_text("pattern", "The regular expression to match")) help_text("pattern", "The regular expression to match"))
.with_tags({"filtering"}) .with_tags({"filtering"})
.with_example({"To filter out log messages that do not have the " .with_example({"To filter out log messages that do not have the "
"string 'dhclient'", "string 'dhclient'",
"dhclient"})}, "dhclient"}),
{"filter-out", com_filter_prompt,
com_filter, },
{
help_text(":filter-out") "filter-out",
.with_summary("Remove lines that match the given regular expression " com_filter,
"in the current view")
.with_parameter( help_text(":filter-out")
help_text("pattern", "The regular expression to match")) .with_summary(
.with_tags({"filtering"}) "Remove lines that match the given regular expression "
.with_example({"To filter out log messages that contain the string " "in the current view")
"'last message repeated'", .with_parameter(
"last message repeated"})}, help_text("pattern", "The regular expression to match"))
.with_tags({"filtering"})
.with_example({"To filter out log messages that contain the string "
"'last message repeated'",
"last message repeated"}),
com_filter_prompt,
},
{"delete-filter", {"delete-filter",
com_delete_filter, com_delete_filter,

@ -969,6 +969,10 @@ static const struct json_path_container theme_status_styles_handlers = {
.with_description("Styling for hotkey highlights of status bars") .with_description("Styling for hotkey highlights of status bars")
.for_child(&lnav_theme::lt_style_status_hotkey) .for_child(&lnav_theme::lt_style_status_hotkey)
.with_children(style_config_handlers), .with_children(style_config_handlers),
yajlpp::property_handler("suggestion")
.with_description("Styling for suggested values")
.for_child(&lnav_theme::lt_style_suggestion)
.with_children(style_config_handlers),
}; };
static const struct json_path_container theme_log_level_styles_handlers = { static const struct json_path_container theme_log_level_styles_handlers = {

@ -116,6 +116,7 @@ private:
}; };
class generic_log_format : public log_format { class generic_log_format : public log_format {
public:
static const pcre_format* get_pcre_log_formats() static const pcre_format* get_pcre_log_formats()
{ {
static const pcre_format log_fmt[] = { static const pcre_format log_fmt[] = {
@ -258,6 +259,9 @@ class generic_log_format : public log_format {
auto lr = to_line_range(ts_cap.trim()); auto lr = to_line_range(ts_cap.trim());
sa.emplace_back(lr, logline::L_TIMESTAMP.value()); sa.emplace_back(lr, logline::L_TIMESTAMP.value());
values.lvv_values.emplace_back(TS_META, line, lr);
values.lvv_values.back().lv_meta.lvm_format = (log_format*) this;
prefix_len = ts_cap.sf_end; prefix_len = ts_cap.sf_end;
auto level_cap = md[2]; auto level_cap = md[2];
if (level_cap) { if (level_cap) {
@ -265,6 +269,11 @@ class generic_log_format : public log_format {
!= LEVEL_UNKNOWN) != LEVEL_UNKNOWN)
{ {
prefix_len = level_cap->sf_end; prefix_len = level_cap->sf_end;
values.lvv_values.emplace_back(
LEVEL_META, line, to_line_range(level_cap->trim()));
values.lvv_values.back().lv_meta.lvm_format
= (log_format*) this;
} }
} }
@ -284,6 +293,41 @@ class generic_log_format : public log_format {
retval->lf_specialized = true; retval->lf_specialized = true;
return retval; return retval;
} }
bool hide_field(const intern_string_t field_name, bool val) override
{
if (field_name == TS_META.lvm_name) {
TS_META.lvm_user_hidden = val;
return true;
} else if (field_name == LEVEL_META.lvm_name) {
LEVEL_META.lvm_user_hidden = val;
return true;
}
return false;
}
std::map<intern_string_t, logline_value_meta> get_field_states() override
{
return {
{TS_META.lvm_name, TS_META},
{LEVEL_META.lvm_name, LEVEL_META},
};
}
private:
static logline_value_meta TS_META;
static logline_value_meta LEVEL_META;
};
logline_value_meta generic_log_format::TS_META{
intern_string::lookup("log_time"),
value_kind_t::VALUE_TEXT,
logline_value_meta::table_column{2},
};
logline_value_meta generic_log_format::LEVEL_META{
intern_string::lookup("log_level"),
value_kind_t::VALUE_TEXT,
logline_value_meta::table_column{4},
}; };
std::string std::string

@ -326,7 +326,9 @@ rl_change(readline_curses* rc)
if (!args.empty()) { if (!args.empty()) {
iter = lnav_commands.find(args[0]); iter = lnav_commands.find(args[0]);
} }
if (iter == lnav_commands.end()) { if (iter == lnav_commands.end()
|| (args.size() == 1 && !endswith(line, " ")))
{
lnav_data.ld_doc_source.replace_with(CMD_HELP); lnav_data.ld_doc_source.replace_with(CMD_HELP);
lnav_data.ld_example_source.replace_with(CMD_EXAMPLE); lnav_data.ld_example_source.replace_with(CMD_EXAMPLE);
lnav_data.ld_preview_source.clear(); lnav_data.ld_preview_source.clear();
@ -361,12 +363,12 @@ rl_change(readline_curses* rc)
} else if ((args[0] != "filter-expr" && args[0] != "mark-expr") } else if ((args[0] != "filter-expr" && args[0] != "mark-expr")
|| !rl_sql_help(rc)) || !rl_sql_help(rc))
{ {
readline_context::command_t& cmd = *iter->second; const auto& cmd = *iter->second;
const help_text& ht = cmd.c_help; const auto& ht = cmd.c_help;
if (ht.ht_name) { if (ht.ht_name) {
textview_curses& dtc = lnav_data.ld_doc_view; auto& dtc = lnav_data.ld_doc_view;
textview_curses& etc = lnav_data.ld_example_view; auto& etc = lnav_data.ld_example_view;
unsigned long width; unsigned long width;
vis_line_t height; vis_line_t height;
attr_line_t al; attr_line_t al;
@ -383,15 +385,17 @@ rl_change(readline_curses* rc)
etc.set_needs_update(); etc.set_needs_update();
} }
if (cmd.c_prompt != nullptr && generation == 0 if (cmd.c_prompt != nullptr) {
&& trim(line) == args[0]) const auto prompt_res
{
const auto new_prompt
= cmd.c_prompt(lnav_data.ld_exec_context, line); = cmd.c_prompt(lnav_data.ld_exec_context, line);
if (!new_prompt.empty()) { if (generation == 0 && trim(line) == args[0]
rc->rewrite_line(line.length(), new_prompt); && !prompt_res.pr_new_prompt.empty())
{
rc->rewrite_line(line.length(),
prompt_res.pr_new_prompt);
} }
rc->set_suggestion(prompt_res.pr_suggestion);
} }
lnav_data.ld_bottom_source.grep_error(""); lnav_data.ld_bottom_source.grep_error("");

@ -53,10 +53,16 @@ typedef void (*readline_highlighter_t)(attr_line_t& line, int x);
*/ */
class readline_context { class readline_context {
public: public:
typedef Result<std::string, lnav::console::user_message> (*command_func_t)( using command_func_t = Result<std::string, lnav::console::user_message> (*)(
exec_context& ec, std::string cmdline, std::vector<std::string>& args); exec_context& ec, std::string cmdline, std::vector<std::string>& args);
typedef std::string (*prompt_func_t)(exec_context& ec,
const std::string& cmdline); struct prompt_result_t {
std::string pr_new_prompt;
std::string pr_suggestion;
};
using prompt_func_t
= prompt_result_t (*)(exec_context& ec, const std::string& cmdline);
typedef struct _command_t { typedef struct _command_t {
const char* c_name; const char* c_name;
command_func_t c_func; command_func_t c_func;
@ -113,10 +119,7 @@ public:
return *this; return *this;
} }
int get_append_character() const int get_append_character() const { return this->rc_append_character; }
{
return this->rc_append_character;
}
readline_context& set_highlighter(readline_highlighter_t hl) readline_context& set_highlighter(readline_highlighter_t hl)
{ {

@ -92,6 +92,8 @@ static const char* RL_INIT[] = {
"set menu-complete-display-prefix on", "set menu-complete-display-prefix on",
"TAB: menu-complete", "TAB: menu-complete",
"\"\\e[Z\": menu-complete-backward", "\"\\e[Z\": menu-complete-backward",
"\"\\eC\": lnav-forward-complete",
"\"\\C-f\": lnav-forward-complete",
}; };
readline_context* readline_context::loaded_context; readline_context* readline_context::loaded_context;
@ -100,6 +102,7 @@ static std::string last_match_str;
static bool last_match_str_valid; static bool last_match_str_valid;
static bool arg_needs_shlex; static bool arg_needs_shlex;
static nonstd::optional<std::string> rewrite_line_start; static nonstd::optional<std::string> rewrite_line_start;
static std::string rc_local_suggestion;
static void static void
sigalrm(int sig) sigalrm(int sig)
@ -542,6 +545,22 @@ readline_context::attempted_completion(const char* text, int start, int end)
return retval; return retval;
} }
static int
lnav_forward_complete(int count, int key)
{
if (!rc_local_suggestion.empty() && rl_point == rl_end) {
rl_extend_line_buffer(strlen(rl_line_buffer)
+ rc_local_suggestion.size() + 1);
strcat(rl_line_buffer, rc_local_suggestion.c_str());
rl_point = strlen(rl_line_buffer);
rl_end = rl_point;
rc_local_suggestion.clear();
return 0;
}
return rl_forward_char(count, key);
}
static int static int
rubout_char_or_abort(int count, int key) rubout_char_or_abort(int count, int key)
{ {
@ -828,6 +847,7 @@ readline_curses::start()
using_history(); using_history();
stifle_history(HISTORY_SIZE); stifle_history(HISTORY_SIZE);
rl_add_defun("lnav-forward-complete", lnav_forward_complete, -1);
rl_add_defun("rubout-char-or-abort", rubout_char_or_abort, '\b'); rl_add_defun("rubout-char-or-abort", rubout_char_or_abort, '\b');
rl_add_defun("alt-done", alt_done_func, '\x0a'); rl_add_defun("alt-done", alt_done_func, '\x0a');
// rl_add_defun("command-complete", readline_context::command_complete, // rl_add_defun("command-complete", readline_context::command_complete,
@ -835,7 +855,10 @@ readline_curses::start()
for (const auto* init_cmd : RL_INIT) { for (const auto* init_cmd : RL_INIT) {
snprintf(buffer, sizeof(buffer), "%s", init_cmd); snprintf(buffer, sizeof(buffer), "%s", init_cmd);
rl_parse_and_bind(buffer); /* NOTE: buffer is modified */ /* NOTE: buffer is modified */
if (rl_parse_and_bind(buffer)) {
log_error("rl_parse_and_bind(%s) failed", init_cmd);
}
} }
child_this = this; child_this = this;
@ -964,6 +987,8 @@ readline_curses::start()
const char* cwd = &msg[3]; const char* cwd = &msg[3];
log_perror(chdir(cwd)); log_perror(chdir(cwd));
} else if (startswith(msg, "sugg:")) {
rc_local_suggestion = &msg[5];
} else if (sscanf(msg, "i:%d:%n", &rl_point, &prompt_start) } else if (sscanf(msg, "i:%d:%n", &rl_point, &prompt_start)
== 1) == 1)
{ {
@ -1213,6 +1238,7 @@ readline_curses::check_poll_set(const std::vector<struct pollfd>& pollfds)
if (rc > 0) { if (rc > 0) {
int old_x = this->vc_x; int old_x = this->vc_x;
this->rc_suggestion.clear();
this->map_output(buffer, rc); this->map_output(buffer, rc);
if (this->vc_x != old_x) { if (this->vc_x != old_x) {
this->rc_change(this); this->rc_change(this);
@ -1300,6 +1326,7 @@ readline_curses::check_poll_set(const std::vector<struct pollfd>& pollfds)
case 'l': case 'l':
this->rc_line_buffer = &msg[2]; this->rc_line_buffer = &msg[2];
if (this->rc_active_context != -1) { if (this->rc_active_context != -1) {
this->rc_suggestion.clear();
this->rc_change(this); this->rc_change(this);
} }
this->rc_matches.clear(); this->rc_matches.clear();
@ -1310,6 +1337,7 @@ readline_curses::check_poll_set(const std::vector<struct pollfd>& pollfds)
case 'c': case 'c':
this->rc_line_buffer = &msg[2]; this->rc_line_buffer = &msg[2];
this->rc_suggestion.clear();
this->rc_change(this); this->rc_change(this);
this->rc_display_match(this); this->rc_display_match(this);
break; break;
@ -1361,8 +1389,13 @@ readline_curses::focus(int context,
{ {
perror("focus: write failed"); perror("focus: write failed");
} }
wmove(this->vc_window, this->get_actual_y(), this->vc_left); auto al = attr_line_t();
wclrtoeol(this->vc_window); al.append(lnav::roles::suggestion(this->rc_suggestion));
view_curses::mvwattrline(this->vc_window,
this->get_actual_y(),
this->vc_left,
al,
line_range{0, (int) this->get_actual_width()});
if (!initial.empty()) { if (!initial.empty()) {
this->rewrite_line(initial.size(), initial); this->rewrite_line(initial.size(), initial);
} }
@ -1384,6 +1417,21 @@ readline_curses::rewrite_line(int pos, const std::string& value)
} }
} }
void
readline_curses::set_suggestion(const std::string& value)
{
char buffer[1024];
snprintf(buffer, sizeof(buffer), "sugg:%s", value.c_str());
if (sendstring(
this->rc_command_pipe[RCF_MASTER], buffer, strlen(buffer) + 1)
== -1)
{
perror("set_suggestion: write failed");
}
this->rc_suggestion = value;
}
void void
readline_curses::abort() readline_curses::abort()
{ {
@ -1543,13 +1591,14 @@ readline_curses::do_update()
} }
if (this->rc_active_context != -1) { if (this->rc_active_context != -1) {
readline_context* rc = this->rc_contexts[this->rc_active_context]; auto* rc = this->rc_contexts[this->rc_active_context];
readline_highlighter_t hl = rc->get_highlighter(); auto hl = rc->get_highlighter();
attr_line_t al = this->vc_line; auto al = this->vc_line;
if (hl != nullptr) { if (hl != nullptr) {
hl(al, this->vc_left + this->vc_x); hl(al, this->vc_left + this->vc_x);
} }
al.append(lnav::roles::suggestion(this->rc_suggestion));
view_curses::mvwattrline(this->vc_window, view_curses::mvwattrline(this->vc_window,
this->get_actual_y(), this->get_actual_y(),
this->vc_left, this->vc_left,

@ -171,6 +171,8 @@ public:
void rewrite_line(int pos, const std::string& value); void rewrite_line(int pos, const std::string& value);
void set_suggestion(const std::string& value);
readline_context* get_active_context() const readline_context* get_active_context() const
{ {
require(this->rc_active_context != -1); require(this->rc_active_context != -1);
@ -328,6 +330,7 @@ private:
bool rc_is_alt_focus{false}; bool rc_is_alt_focus{false};
bool rc_ready_for_input{false}; bool rc_ready_for_input{false};
std::string rc_remote_complete_path; std::string rc_remote_complete_path;
std::string rc_suggestion;
action rc_focus; action rc_focus;
action rc_change; action rc_change;

@ -151,7 +151,9 @@ shlex::tokenize()
switch (this->s_state) { switch (this->s_state) {
case state_t::STATE_NORMAL: case state_t::STATE_NORMAL:
retval.tr_frag.sf_begin = this->s_index; retval.tr_frag.sf_begin = this->s_index;
while (isspace(this->s_str[this->s_index])) { while (this->s_index < this->s_len
&& isspace(this->s_str[this->s_index]))
{
this->s_index += 1; this->s_index += 1;
} }
retval.tr_frag.sf_end = this->s_index; retval.tr_frag.sf_end = this->s_index;
@ -345,11 +347,13 @@ shlex::split(const scoped_resolver& vars)
auto tokenize_res = TRY(this->tokenize()); auto tokenize_res = TRY(this->tokenize());
if (start_new) { if (start_new) {
retval.emplace_back(split_element_t{ if (last_index < this->s_len) {
string_fragment::from_byte_range( retval.emplace_back(split_element_t{
this->s_str, last_index, tokenize_res.tr_frag.sf_begin), string_fragment::from_byte_range(
"", this->s_str, last_index, tokenize_res.tr_frag.sf_begin),
}); "",
});
}
start_new = false; start_new = false;
} else if (tokenize_res.tr_token != shlex_token_t::whitespace) { } else if (tokenize_res.tr_token != shlex_token_t::whitespace) {
retval.back().se_origin.sf_end = tokenize_res.tr_frag.sf_end; retval.back().se_origin.sf_end = tokenize_res.tr_frag.sf_end;

@ -147,6 +147,7 @@ struct lnav_theme {
positioned_property<style_config> lt_style_function; positioned_property<style_config> lt_style_function;
positioned_property<style_config> lt_style_type; positioned_property<style_config> lt_style_type;
positioned_property<style_config> lt_style_sep_ref_acc; positioned_property<style_config> lt_style_sep_ref_acc;
positioned_property<style_config> lt_style_suggestion;
positioned_property<style_config> lt_style_re_special; positioned_property<style_config> lt_style_re_special;
positioned_property<style_config> lt_style_re_repeat; positioned_property<style_config> lt_style_re_repeat;
positioned_property<style_config> lt_style_diff_delete; positioned_property<style_config> lt_style_diff_delete;

@ -283,6 +283,9 @@
"inactive-alert": { "inactive-alert": {
"color": "$red", "color": "$red",
"background-color": "#2f2f2f" "background-color": "#2f2f2f"
},
"suggestion": {
"color": "#888"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -278,6 +278,9 @@
"inactive-alert": { "inactive-alert": {
"color": "$red", "color": "$red",
"background-color": "Grey" "background-color": "Grey"
},
"suggestion": {
"color": "#888"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -218,6 +218,9 @@
"inactive-alert": { "inactive-alert": {
"color": "$red", "color": "$red",
"background-color": "#2f2f2f" "background-color": "#2f2f2f"
},
"suggestion": {
"color": "#888"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -281,6 +281,9 @@
"inactive-alert": { "inactive-alert": {
"color": "$red", "color": "$red",
"background-color": "#2f2f2f" "background-color": "#2f2f2f"
},
"suggestion": {
"color": "#888"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -279,6 +279,9 @@
"background-color": "#2d5a80", "background-color": "#2d5a80",
"bold": true, "bold": true,
"underline": true "underline": true
},
"suggestion": {
"color": "#888"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -287,6 +287,9 @@
"inactive-alert": { "inactive-alert": {
"color": "$red", "color": "$red",
"background-color": "$base02" "background-color": "$base02"
},
"suggestion": {
"color": "$base02"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -193,6 +193,9 @@
"inactive-alert": { "inactive-alert": {
"color": "$red", "color": "$red",
"background-color": "$base03" "background-color": "$base03"
},
"suggestion": {
"color": "$base03"
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -977,6 +977,8 @@ view_colors::init_roles(const lnav_theme& lt,
= this->to_attrs(lt, lt.lt_style_type, reporter); = this->to_attrs(lt, lt.lt_style_type, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SEP_REF_ACC)] this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SEP_REF_ACC)]
= this->to_attrs(lt, lt.lt_style_sep_ref_acc, reporter); = this->to_attrs(lt, lt.lt_style_sep_ref_acc, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_SUGGESTION)]
= this->to_attrs(lt, lt.lt_style_suggestion, reporter);
this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_RE_SPECIAL)] this->vc_role_attrs[lnav::enums::to_underlying(role_t::VCR_RE_SPECIAL)]
= this->to_attrs(lt, lt.lt_style_re_special, reporter); = this->to_attrs(lt, lt.lt_style_re_special, reporter);

@ -90,6 +90,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out \ $(srcdir)/%reldir%/test_cmds.sh_38fa2a95b703d4ce12e82882eca1938264822690.out \
$(srcdir)/%reldir%/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err \ $(srcdir)/%reldir%/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.err \
$(srcdir)/%reldir%/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out \ $(srcdir)/%reldir%/test_cmds.sh_3b20a298e2c059d7f6045cbc0c07ca3db3917695.out \
$(srcdir)/%reldir%/test_cmds.sh_3b4bea458c59d2bac492e568616b610625037ad0.err \
$(srcdir)/%reldir%/test_cmds.sh_3b4bea458c59d2bac492e568616b610625037ad0.out \
$(srcdir)/%reldir%/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err \ $(srcdir)/%reldir%/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.err \
$(srcdir)/%reldir%/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out \ $(srcdir)/%reldir%/test_cmds.sh_453054e29aaca4c2662c45c2a1f2f63f3510d8dd.out \
$(srcdir)/%reldir%/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err \ $(srcdir)/%reldir%/test_cmds.sh_4b2d91b19008d5b775090e3ef87c111f9e603b15.err \
@ -574,6 +576,8 @@ EXPECTED_FILES = \
$(srcdir)/%reldir%/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out \ $(srcdir)/%reldir%/test_shlexer.sh_e0599f0b53d1bd27af767113853f8e84291f137d.out \
$(srcdir)/%reldir%/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err \ $(srcdir)/%reldir%/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.err \
$(srcdir)/%reldir%/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out \ $(srcdir)/%reldir%/test_shlexer.sh_e8fa2239ab17e7563d0c524f5400a79d6ff8bfda.out \
$(srcdir)/%reldir%/test_shlexer.sh_e99fe1cde36b85ebbab86ca820f55ec861cdc20b.err \
$(srcdir)/%reldir%/test_shlexer.sh_e99fe1cde36b85ebbab86ca820f55ec861cdc20b.out \
$(srcdir)/%reldir%/test_sql.sh_02def66745b063518473df862987747909f56ccc.err \ $(srcdir)/%reldir%/test_sql.sh_02def66745b063518473df862987747909f56ccc.err \
$(srcdir)/%reldir%/test_sql.sh_02def66745b063518473df862987747909f56ccc.out \ $(srcdir)/%reldir%/test_sql.sh_02def66745b063518473df862987747909f56ccc.out \
$(srcdir)/%reldir%/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err \ $(srcdir)/%reldir%/test_sql.sh_0a5d13b62da4cb66a59a51b0240b5fe0b6036b7e.err \

@ -578,6 +578,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": true "bold": true
},
"suggestion": {
"color": "",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -1168,6 +1174,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": false "bold": false
},
"suggestion": {
"color": "#888",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -1720,6 +1732,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": false "bold": false
},
"suggestion": {
"color": "#888",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -2272,6 +2290,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": false "bold": false
},
"suggestion": {
"color": "#888",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -2825,6 +2849,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": false "bold": false
},
"suggestion": {
"color": "#888",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -3377,6 +3407,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": true "bold": true
},
"suggestion": {
"color": "#888",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -3938,6 +3974,12 @@
"background-color": "", "background-color": "",
"underline": true, "underline": true,
"bold": false "bold": false
},
"suggestion": {
"color": "$base02",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {
@ -4499,6 +4541,12 @@
"background-color": "", "background-color": "",
"underline": false, "underline": false,
"bold": false "bold": false
},
"suggestion": {
"color": "$base03",
"background-color": "",
"underline": false,
"bold": false
} }
}, },
"log-level-styles": { "log-level-styles": {

@ -297,10 +297,10 @@
/ui/theme-defs/default/syntax-styles/type/color -> default-theme.json:218 /ui/theme-defs/default/syntax-styles/type/color -> default-theme.json:218
/ui/theme-defs/default/syntax-styles/variable/color -> default-theme.json:167 /ui/theme-defs/default/syntax-styles/variable/color -> default-theme.json:167
/ui/theme-defs/default/vars/semantic_highlight_color -> default-theme.json:7 /ui/theme-defs/default/vars/semantic_highlight_color -> default-theme.json:7
/ui/theme-defs/dracula/log-level-styles/critical/color -> dracula.json:296 /ui/theme-defs/dracula/log-level-styles/critical/color -> dracula.json:299
/ui/theme-defs/dracula/log-level-styles/error/color -> dracula.json:293 /ui/theme-defs/dracula/log-level-styles/error/color -> dracula.json:296
/ui/theme-defs/dracula/log-level-styles/fatal/color -> dracula.json:299 /ui/theme-defs/dracula/log-level-styles/fatal/color -> dracula.json:302
/ui/theme-defs/dracula/log-level-styles/warning/color -> dracula.json:290 /ui/theme-defs/dracula/log-level-styles/warning/color -> dracula.json:293
/ui/theme-defs/dracula/status-styles/active/background-color -> dracula.json:277 /ui/theme-defs/dracula/status-styles/active/background-color -> dracula.json:277
/ui/theme-defs/dracula/status-styles/active/color -> dracula.json:276 /ui/theme-defs/dracula/status-styles/active/color -> dracula.json:276
/ui/theme-defs/dracula/status-styles/alert/background-color -> dracula.json:273 /ui/theme-defs/dracula/status-styles/alert/background-color -> dracula.json:273
@ -319,6 +319,7 @@
/ui/theme-defs/dracula/status-styles/subtitle/background-color -> dracula.json:247 /ui/theme-defs/dracula/status-styles/subtitle/background-color -> dracula.json:247
/ui/theme-defs/dracula/status-styles/subtitle/bold -> dracula.json:248 /ui/theme-defs/dracula/status-styles/subtitle/bold -> dracula.json:248
/ui/theme-defs/dracula/status-styles/subtitle/color -> dracula.json:246 /ui/theme-defs/dracula/status-styles/subtitle/color -> dracula.json:246
/ui/theme-defs/dracula/status-styles/suggestion/color -> dracula.json:288
/ui/theme-defs/dracula/status-styles/text/background-color -> dracula.json:265 /ui/theme-defs/dracula/status-styles/text/background-color -> dracula.json:265
/ui/theme-defs/dracula/status-styles/text/color -> dracula.json:264 /ui/theme-defs/dracula/status-styles/text/color -> dracula.json:264
/ui/theme-defs/dracula/status-styles/title-hotkey/background-color -> dracula.json:256 /ui/theme-defs/dracula/status-styles/title-hotkey/background-color -> dracula.json:256
@ -427,10 +428,10 @@
/ui/theme-defs/dracula/vars/semantic_highlight_color -> dracula.json:18 /ui/theme-defs/dracula/vars/semantic_highlight_color -> dracula.json:18
/ui/theme-defs/dracula/vars/white -> dracula.json:14 /ui/theme-defs/dracula/vars/white -> dracula.json:14
/ui/theme-defs/dracula/vars/yellow -> dracula.json:10 /ui/theme-defs/dracula/vars/yellow -> dracula.json:10
/ui/theme-defs/eldar/log-level-styles/critical/color -> eldar.json:291 /ui/theme-defs/eldar/log-level-styles/critical/color -> eldar.json:294
/ui/theme-defs/eldar/log-level-styles/error/color -> eldar.json:288 /ui/theme-defs/eldar/log-level-styles/error/color -> eldar.json:291
/ui/theme-defs/eldar/log-level-styles/fatal/color -> eldar.json:294 /ui/theme-defs/eldar/log-level-styles/fatal/color -> eldar.json:297
/ui/theme-defs/eldar/log-level-styles/warning/color -> eldar.json:285 /ui/theme-defs/eldar/log-level-styles/warning/color -> eldar.json:288
/ui/theme-defs/eldar/status-styles/active/background-color -> eldar.json:259 /ui/theme-defs/eldar/status-styles/active/background-color -> eldar.json:259
/ui/theme-defs/eldar/status-styles/active/color -> eldar.json:258 /ui/theme-defs/eldar/status-styles/active/color -> eldar.json:258
/ui/theme-defs/eldar/status-styles/alert/background-color -> eldar.json:255 /ui/theme-defs/eldar/status-styles/alert/background-color -> eldar.json:255
@ -449,6 +450,7 @@
/ui/theme-defs/eldar/status-styles/subtitle/background-color -> eldar.json:242 /ui/theme-defs/eldar/status-styles/subtitle/background-color -> eldar.json:242
/ui/theme-defs/eldar/status-styles/subtitle/bold -> eldar.json:243 /ui/theme-defs/eldar/status-styles/subtitle/bold -> eldar.json:243
/ui/theme-defs/eldar/status-styles/subtitle/color -> eldar.json:241 /ui/theme-defs/eldar/status-styles/subtitle/color -> eldar.json:241
/ui/theme-defs/eldar/status-styles/suggestion/color -> eldar.json:283
/ui/theme-defs/eldar/status-styles/text/background-color -> eldar.json:247 /ui/theme-defs/eldar/status-styles/text/background-color -> eldar.json:247
/ui/theme-defs/eldar/status-styles/text/color -> eldar.json:246 /ui/theme-defs/eldar/status-styles/text/color -> eldar.json:246
/ui/theme-defs/eldar/status-styles/title-hotkey/background-color -> eldar.json:267 /ui/theme-defs/eldar/status-styles/title-hotkey/background-color -> eldar.json:267
@ -552,10 +554,10 @@
/ui/theme-defs/eldar/vars/semantic_highlight_color -> eldar.json:15 /ui/theme-defs/eldar/vars/semantic_highlight_color -> eldar.json:15
/ui/theme-defs/eldar/vars/white -> eldar.json:14 /ui/theme-defs/eldar/vars/white -> eldar.json:14
/ui/theme-defs/eldar/vars/yellow -> eldar.json:8 /ui/theme-defs/eldar/vars/yellow -> eldar.json:8
/ui/theme-defs/grayscale/log-level-styles/critical/color -> grayscale.json:231 /ui/theme-defs/grayscale/log-level-styles/critical/color -> grayscale.json:234
/ui/theme-defs/grayscale/log-level-styles/error/color -> grayscale.json:228 /ui/theme-defs/grayscale/log-level-styles/error/color -> grayscale.json:231
/ui/theme-defs/grayscale/log-level-styles/fatal/color -> grayscale.json:234 /ui/theme-defs/grayscale/log-level-styles/fatal/color -> grayscale.json:237
/ui/theme-defs/grayscale/log-level-styles/warning/color -> grayscale.json:225 /ui/theme-defs/grayscale/log-level-styles/warning/color -> grayscale.json:228
/ui/theme-defs/grayscale/status-styles/active/background-color -> grayscale.json:208 /ui/theme-defs/grayscale/status-styles/active/background-color -> grayscale.json:208
/ui/theme-defs/grayscale/status-styles/active/color -> grayscale.json:207 /ui/theme-defs/grayscale/status-styles/active/color -> grayscale.json:207
/ui/theme-defs/grayscale/status-styles/alert/background-color -> grayscale.json:204 /ui/theme-defs/grayscale/status-styles/alert/background-color -> grayscale.json:204
@ -574,6 +576,7 @@
/ui/theme-defs/grayscale/status-styles/subtitle/background-color -> grayscale.json:182 /ui/theme-defs/grayscale/status-styles/subtitle/background-color -> grayscale.json:182
/ui/theme-defs/grayscale/status-styles/subtitle/bold -> grayscale.json:183 /ui/theme-defs/grayscale/status-styles/subtitle/bold -> grayscale.json:183
/ui/theme-defs/grayscale/status-styles/subtitle/color -> grayscale.json:181 /ui/theme-defs/grayscale/status-styles/subtitle/color -> grayscale.json:181
/ui/theme-defs/grayscale/status-styles/suggestion/color -> grayscale.json:223
/ui/theme-defs/grayscale/status-styles/text/background-color -> grayscale.json:196 /ui/theme-defs/grayscale/status-styles/text/background-color -> grayscale.json:196
/ui/theme-defs/grayscale/status-styles/text/color -> grayscale.json:195 /ui/theme-defs/grayscale/status-styles/text/color -> grayscale.json:195
/ui/theme-defs/grayscale/status-styles/title-hotkey/background-color -> grayscale.json:187 /ui/theme-defs/grayscale/status-styles/title-hotkey/background-color -> grayscale.json:187
@ -655,10 +658,10 @@
/ui/theme-defs/grayscale/vars/red -> grayscale.json:8 /ui/theme-defs/grayscale/vars/red -> grayscale.json:8
/ui/theme-defs/grayscale/vars/white -> grayscale.json:14 /ui/theme-defs/grayscale/vars/white -> grayscale.json:14
/ui/theme-defs/grayscale/vars/yellow -> grayscale.json:10 /ui/theme-defs/grayscale/vars/yellow -> grayscale.json:10
/ui/theme-defs/monocai/log-level-styles/critical/color -> monocai.json:294 /ui/theme-defs/monocai/log-level-styles/critical/color -> monocai.json:297
/ui/theme-defs/monocai/log-level-styles/error/color -> monocai.json:291 /ui/theme-defs/monocai/log-level-styles/error/color -> monocai.json:294
/ui/theme-defs/monocai/log-level-styles/fatal/color -> monocai.json:297 /ui/theme-defs/monocai/log-level-styles/fatal/color -> monocai.json:300
/ui/theme-defs/monocai/log-level-styles/warning/color -> monocai.json:288 /ui/theme-defs/monocai/log-level-styles/warning/color -> monocai.json:291
/ui/theme-defs/monocai/status-styles/active/background-color -> monocai.json:275 /ui/theme-defs/monocai/status-styles/active/background-color -> monocai.json:275
/ui/theme-defs/monocai/status-styles/active/color -> monocai.json:274 /ui/theme-defs/monocai/status-styles/active/color -> monocai.json:274
/ui/theme-defs/monocai/status-styles/alert/background-color -> monocai.json:271 /ui/theme-defs/monocai/status-styles/alert/background-color -> monocai.json:271
@ -677,6 +680,7 @@
/ui/theme-defs/monocai/status-styles/subtitle/background-color -> monocai.json:245 /ui/theme-defs/monocai/status-styles/subtitle/background-color -> monocai.json:245
/ui/theme-defs/monocai/status-styles/subtitle/bold -> monocai.json:246 /ui/theme-defs/monocai/status-styles/subtitle/bold -> monocai.json:246
/ui/theme-defs/monocai/status-styles/subtitle/color -> monocai.json:244 /ui/theme-defs/monocai/status-styles/subtitle/color -> monocai.json:244
/ui/theme-defs/monocai/status-styles/suggestion/color -> monocai.json:286
/ui/theme-defs/monocai/status-styles/text/background-color -> monocai.json:263 /ui/theme-defs/monocai/status-styles/text/background-color -> monocai.json:263
/ui/theme-defs/monocai/status-styles/text/color -> monocai.json:262 /ui/theme-defs/monocai/status-styles/text/color -> monocai.json:262
/ui/theme-defs/monocai/status-styles/title-hotkey/background-color -> monocai.json:254 /ui/theme-defs/monocai/status-styles/title-hotkey/background-color -> monocai.json:254
@ -783,10 +787,10 @@
/ui/theme-defs/monocai/vars/semantic_highlight_color -> monocai.json:16 /ui/theme-defs/monocai/vars/semantic_highlight_color -> monocai.json:16
/ui/theme-defs/monocai/vars/white -> monocai.json:14 /ui/theme-defs/monocai/vars/white -> monocai.json:14
/ui/theme-defs/monocai/vars/yellow -> monocai.json:10 /ui/theme-defs/monocai/vars/yellow -> monocai.json:10
/ui/theme-defs/night-owl/log-level-styles/critical/color -> night-owl.json:292 /ui/theme-defs/night-owl/log-level-styles/critical/color -> night-owl.json:295
/ui/theme-defs/night-owl/log-level-styles/error/color -> night-owl.json:289 /ui/theme-defs/night-owl/log-level-styles/error/color -> night-owl.json:292
/ui/theme-defs/night-owl/log-level-styles/fatal/color -> night-owl.json:295 /ui/theme-defs/night-owl/log-level-styles/fatal/color -> night-owl.json:298
/ui/theme-defs/night-owl/log-level-styles/warning/color -> night-owl.json:286 /ui/theme-defs/night-owl/log-level-styles/warning/color -> night-owl.json:289
/ui/theme-defs/night-owl/status-styles/active/background-color -> night-owl.json:262 /ui/theme-defs/night-owl/status-styles/active/background-color -> night-owl.json:262
/ui/theme-defs/night-owl/status-styles/active/color -> night-owl.json:261 /ui/theme-defs/night-owl/status-styles/active/color -> night-owl.json:261
/ui/theme-defs/night-owl/status-styles/alert/background-color -> night-owl.json:258 /ui/theme-defs/night-owl/status-styles/alert/background-color -> night-owl.json:258
@ -805,6 +809,7 @@
/ui/theme-defs/night-owl/status-styles/info/color -> night-owl.json:245 /ui/theme-defs/night-owl/status-styles/info/color -> night-owl.json:245
/ui/theme-defs/night-owl/status-styles/subtitle/background-color -> night-owl.json:242 /ui/theme-defs/night-owl/status-styles/subtitle/background-color -> night-owl.json:242
/ui/theme-defs/night-owl/status-styles/subtitle/color -> night-owl.json:241 /ui/theme-defs/night-owl/status-styles/subtitle/color -> night-owl.json:241
/ui/theme-defs/night-owl/status-styles/suggestion/color -> night-owl.json:284
/ui/theme-defs/night-owl/status-styles/text/background-color -> night-owl.json:250 /ui/theme-defs/night-owl/status-styles/text/background-color -> night-owl.json:250
/ui/theme-defs/night-owl/status-styles/text/color -> night-owl.json:249 /ui/theme-defs/night-owl/status-styles/text/color -> night-owl.json:249
/ui/theme-defs/night-owl/status-styles/title-hotkey/background-color -> night-owl.json:279 /ui/theme-defs/night-owl/status-styles/title-hotkey/background-color -> night-owl.json:279
@ -909,10 +914,10 @@
/ui/theme-defs/night-owl/vars/semantic_highlight_color -> night-owl.json:15 /ui/theme-defs/night-owl/vars/semantic_highlight_color -> night-owl.json:15
/ui/theme-defs/night-owl/vars/white -> night-owl.json:14 /ui/theme-defs/night-owl/vars/white -> night-owl.json:14
/ui/theme-defs/night-owl/vars/yellow -> night-owl.json:10 /ui/theme-defs/night-owl/vars/yellow -> night-owl.json:10
/ui/theme-defs/solarized-dark/log-level-styles/critical/color -> solarized-dark.json:300 /ui/theme-defs/solarized-dark/log-level-styles/critical/color -> solarized-dark.json:303
/ui/theme-defs/solarized-dark/log-level-styles/error/color -> solarized-dark.json:297 /ui/theme-defs/solarized-dark/log-level-styles/error/color -> solarized-dark.json:300
/ui/theme-defs/solarized-dark/log-level-styles/fatal/color -> solarized-dark.json:303 /ui/theme-defs/solarized-dark/log-level-styles/fatal/color -> solarized-dark.json:306
/ui/theme-defs/solarized-dark/log-level-styles/warning/color -> solarized-dark.json:294 /ui/theme-defs/solarized-dark/log-level-styles/warning/color -> solarized-dark.json:297
/ui/theme-defs/solarized-dark/status-styles/active/background-color -> solarized-dark.json:268 /ui/theme-defs/solarized-dark/status-styles/active/background-color -> solarized-dark.json:268
/ui/theme-defs/solarized-dark/status-styles/active/color -> solarized-dark.json:267 /ui/theme-defs/solarized-dark/status-styles/active/color -> solarized-dark.json:267
/ui/theme-defs/solarized-dark/status-styles/alert/background-color -> solarized-dark.json:264 /ui/theme-defs/solarized-dark/status-styles/alert/background-color -> solarized-dark.json:264
@ -931,6 +936,7 @@
/ui/theme-defs/solarized-dark/status-styles/subtitle/background-color -> solarized-dark.json:251 /ui/theme-defs/solarized-dark/status-styles/subtitle/background-color -> solarized-dark.json:251
/ui/theme-defs/solarized-dark/status-styles/subtitle/bold -> solarized-dark.json:252 /ui/theme-defs/solarized-dark/status-styles/subtitle/bold -> solarized-dark.json:252
/ui/theme-defs/solarized-dark/status-styles/subtitle/color -> solarized-dark.json:250 /ui/theme-defs/solarized-dark/status-styles/subtitle/color -> solarized-dark.json:250
/ui/theme-defs/solarized-dark/status-styles/suggestion/color -> solarized-dark.json:292
/ui/theme-defs/solarized-dark/status-styles/text/background-color -> solarized-dark.json:256 /ui/theme-defs/solarized-dark/status-styles/text/background-color -> solarized-dark.json:256
/ui/theme-defs/solarized-dark/status-styles/text/color -> solarized-dark.json:255 /ui/theme-defs/solarized-dark/status-styles/text/color -> solarized-dark.json:255
/ui/theme-defs/solarized-dark/status-styles/title-hotkey/background-color -> solarized-dark.json:276 /ui/theme-defs/solarized-dark/status-styles/title-hotkey/background-color -> solarized-dark.json:276
@ -1043,10 +1049,10 @@
/ui/theme-defs/solarized-dark/vars/semantic_highlight_color -> solarized-dark.json:24 /ui/theme-defs/solarized-dark/vars/semantic_highlight_color -> solarized-dark.json:24
/ui/theme-defs/solarized-dark/vars/violet -> solarized-dark.json:20 /ui/theme-defs/solarized-dark/vars/violet -> solarized-dark.json:20
/ui/theme-defs/solarized-dark/vars/yellow -> solarized-dark.json:16 /ui/theme-defs/solarized-dark/vars/yellow -> solarized-dark.json:16
/ui/theme-defs/solarized-light/log-level-styles/critical/color -> solarized-light.json:206 /ui/theme-defs/solarized-light/log-level-styles/critical/color -> solarized-light.json:209
/ui/theme-defs/solarized-light/log-level-styles/error/color -> solarized-light.json:203 /ui/theme-defs/solarized-light/log-level-styles/error/color -> solarized-light.json:206
/ui/theme-defs/solarized-light/log-level-styles/fatal/color -> solarized-light.json:209 /ui/theme-defs/solarized-light/log-level-styles/fatal/color -> solarized-light.json:212
/ui/theme-defs/solarized-light/log-level-styles/warning/color -> solarized-light.json:200 /ui/theme-defs/solarized-light/log-level-styles/warning/color -> solarized-light.json:203
/ui/theme-defs/solarized-light/status-styles/active/background-color -> solarized-light.json:183 /ui/theme-defs/solarized-light/status-styles/active/background-color -> solarized-light.json:183
/ui/theme-defs/solarized-light/status-styles/active/color -> solarized-light.json:182 /ui/theme-defs/solarized-light/status-styles/active/color -> solarized-light.json:182
/ui/theme-defs/solarized-light/status-styles/alert/background-color -> solarized-light.json:179 /ui/theme-defs/solarized-light/status-styles/alert/background-color -> solarized-light.json:179
@ -1060,6 +1066,7 @@
/ui/theme-defs/solarized-light/status-styles/subtitle/background-color -> solarized-light.json:166 /ui/theme-defs/solarized-light/status-styles/subtitle/background-color -> solarized-light.json:166
/ui/theme-defs/solarized-light/status-styles/subtitle/bold -> solarized-light.json:167 /ui/theme-defs/solarized-light/status-styles/subtitle/bold -> solarized-light.json:167
/ui/theme-defs/solarized-light/status-styles/subtitle/color -> solarized-light.json:165 /ui/theme-defs/solarized-light/status-styles/subtitle/color -> solarized-light.json:165
/ui/theme-defs/solarized-light/status-styles/suggestion/color -> solarized-light.json:198
/ui/theme-defs/solarized-light/status-styles/text/background-color -> solarized-light.json:171 /ui/theme-defs/solarized-light/status-styles/text/background-color -> solarized-light.json:171
/ui/theme-defs/solarized-light/status-styles/text/color -> solarized-light.json:170 /ui/theme-defs/solarized-light/status-styles/text/color -> solarized-light.json:170
/ui/theme-defs/solarized-light/status-styles/title/background-color -> solarized-light.json:161 /ui/theme-defs/solarized-light/status-styles/title/background-color -> solarized-light.json:161

@ -0,0 +1,2 @@
⋮:⋮:foo bar baz
⋮:⋮:foo bar baz

@ -0,0 +1,6 @@
abc
wsp ^
eof ^
eval -- abc
split:
0 ^-^ -- abc

@ -179,6 +179,10 @@ run_cap_test ${lnav_test} -n \
-c ":hide-fields access_log.c_ip access_log.cs_uri_stem" \ -c ":hide-fields access_log.c_ip access_log.cs_uri_stem" \
${test_dir}/logfile_access_log.0 ${test_dir}/logfile_access_log.0
run_cap_test ${lnav_test} -n \
-c ':hide-fields log_time log_level' \
${test_dir}/logfile_generic.0
run_cap_test ${lnav_test} -f- -n < ${test_dir}/formats/scripts/multiline-echo.lnav run_cap_test ${lnav_test} -f- -n < ${test_dir}/formats/scripts/multiline-echo.lnav
run_cap_test ${lnav_test} -n \ run_cap_test ${lnav_test} -n \

@ -30,3 +30,5 @@ run_cap_test ./drive_shlexer 'abc $DEF 123'
run_cap_test ./drive_shlexer '~ foo' run_cap_test ./drive_shlexer '~ foo'
run_cap_test ./drive_shlexer '~nonexistent/bar baz' run_cap_test ./drive_shlexer '~nonexistent/bar baz'
run_cap_test ./drive_shlexer 'abc '

Loading…
Cancel
Save