Skip to content

Commit

Permalink
[prompt] more grinding
Browse files Browse the repository at this point in the history
  • Loading branch information
tstack committed Mar 5, 2025
1 parent 2780bb8 commit c656e33
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 158 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ Features:
lnav's internal debug log to a file.
* Added a `:clear-adjusted-log-time` command to clear the time offset
set by the `:adjust-log-time` command.
* Added a `measure_with_units` collation function that can compare
numbers with unit suffixes, like "10KB" or "1.2ms".
Bug Fixes:
* The default terminal colors will now be used in the default theme.
Expand Down
7 changes: 7 additions & 0 deletions docs/source/sqlext.rst
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ Collators
values. For example, "foo10" would be considered greater than "foo2".
* **naturalnocase** - The same as naturalcase, but case-insensitive.
* **ipaddress** - Compare IPv4/IPv6 addresses.
* **loglevel** - Compare log levels.
* **measure_with_units** - Compare numbers with unit suffixes. The
currently supported suffixes are:

- Sizes with an E/P/T/G/M/K prefix.
- Seconds with an f/p/n/u/m prefix.
- Durations of the form :code:`HH:MM:SS` or :code:`HH:MM:SS`

Reference
---------
Expand Down
8 changes: 6 additions & 2 deletions docs/source/ui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,21 @@ DB
^^

The DB view shows the results of queries done through the SQLite interface.
You can execute a query by pressing :kbd:`;` and then entering a SQL statement.
You can execute a query by pressing :kbd:`;` and then entering a SQL or
PRQL [#]_ statement.

Press :kbd:`v` to switch to the database result view.

.. [#] lnav must be compiled in an environment with Rust/Cargo available
for PRQL support.
HELP
^^^^

The help view displays the builtin help text. While in the help view, the
breadcrumb bar can be used to navigate to different sections of the document.

Press :kbd:`?` to switch to the help view.
Press :kbd:`?` to switch to the help view or use the command :code:`:help`.

HIST
^^^^
Expand Down
1 change: 0 additions & 1 deletion src/base/humanize.file_size.tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <chrono>
#include <iostream>

#include "base/humanize.hh"
Expand Down
134 changes: 62 additions & 72 deletions src/cmds.bookmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ com_mark(exec_context& ec, std::string cmdline, std::vector<std::string>& args)
{
std::string retval;

if (args.empty() || lnav_data.ld_view_stack.empty()) {
if (lnav_data.ld_view_stack.empty()) {
} else if (!ec.ec_dry_run) {
auto* tc = *lnav_data.ld_view_stack.top();
lnav_data.ld_last_user_mark[tc] = tc->get_selection();
Expand All @@ -55,24 +55,20 @@ com_goto_mark(exec_context& ec,
{
std::string retval;

if (args.empty()) {
args.emplace_back("mark-type");
} else {
static const std::set<const bookmark_type_t*> DEFAULT_TYPES = {
&textview_curses::BM_USER,
&textview_curses::BM_USER_EXPR,
&textview_curses::BM_META,
};

textview_curses* tc = get_textview_for_mode(lnav_data.ld_mode);
std::set<const bookmark_type_t*> mark_types;

if (args.size() > 1) {
for (size_t lpc = 1; lpc < args.size(); lpc++) {
auto bt_opt = bookmark_type_t::find_type(args[lpc]);
if (!bt_opt) {
auto um
= lnav::console::user_message::error(
static const std::set<const bookmark_type_t*> DEFAULT_TYPES = {
&textview_curses::BM_USER,
&textview_curses::BM_USER_EXPR,
&textview_curses::BM_META,
};

auto* tc = get_textview_for_mode(lnav_data.ld_mode);
std::set<const bookmark_type_t*> mark_types;

if (args.size() > 1) {
for (size_t lpc = 1; lpc < args.size(); lpc++) {
auto bt_opt = bookmark_type_t::find_type(args[lpc]);
if (!bt_opt) {
auto um = lnav::console::user_message::error(
attr_line_t("unknown bookmark type: ")
.append(args[lpc]))
.with_snippets(ec.ec_source)
Expand All @@ -84,74 +80,68 @@ com_goto_mark(exec_context& ec,
| lnav::itertools::sorted(),
", "))
.move();
return Err(um);
}
mark_types.insert(bt_opt.value());
return Err(um);
}
} else {
mark_types = DEFAULT_TYPES;
mark_types.insert(bt_opt.value());
}
} else {
mark_types = DEFAULT_TYPES;
}

if (!ec.ec_dry_run) {
std::optional<vis_line_t> new_top;
if (!ec.ec_dry_run) {
std::optional<vis_line_t> new_top;

if (args[0] == "next-mark") {
auto search_from_top = search_forward_from(tc);
if (args[0] == "next-mark") {
auto search_from_top = search_forward_from(tc);

for (const auto& bt : mark_types) {
auto bt_top
= next_cluster(&bookmark_vector<vis_line_t>::next,
bt,
search_from_top);
for (const auto& bt : mark_types) {
auto bt_top = next_cluster(
&bookmark_vector<vis_line_t>::next, bt, search_from_top);

if (bt_top && (!new_top || bt_top < new_top.value())) {
new_top = bt_top;
}
if (bt_top && (!new_top || bt_top < new_top.value())) {
new_top = bt_top;
}
}

if (!new_top) {
auto um = lnav::console::user_message::info(fmt::format(
FMT_STRING("no more {} bookmarks after here"),
fmt::join(mark_types
| lnav::itertools::map(
&bookmark_type_t::get_name),
", ")));

return Err(um);
}
} else {
for (const auto& bt : mark_types) {
auto bt_top
= next_cluster(&bookmark_vector<vis_line_t>::prev,
bt,
tc->get_selection());

if (bt_top && (!new_top || bt_top > new_top.value())) {
new_top = bt_top;
}
}
if (!new_top) {
auto um = lnav::console::user_message::info(fmt::format(
FMT_STRING("no more {} bookmarks after here"),
fmt::join(
mark_types
| lnav::itertools::map(&bookmark_type_t::get_name),
", ")));

if (!new_top) {
auto um = lnav::console::user_message::info(fmt::format(
FMT_STRING("no more {} bookmarks before here"),
fmt::join(mark_types
| lnav::itertools::map(
&bookmark_type_t::get_name),
", ")));
return Err(um);
}
} else {
for (const auto& bt : mark_types) {
auto bt_top = next_cluster(&bookmark_vector<vis_line_t>::prev,
bt,
tc->get_selection());

return Err(um);
if (bt_top && (!new_top || bt_top > new_top.value())) {
new_top = bt_top;
}
}

if (new_top) {
tc->get_sub_source()->get_location_history() |
[new_top](auto lh) {
lh->loc_history_append(new_top.value());
};
tc->set_selection(new_top.value());
if (!new_top) {
auto um = lnav::console::user_message::info(fmt::format(
FMT_STRING("no more {} bookmarks before here"),
fmt::join(
mark_types
| lnav::itertools::map(&bookmark_type_t::get_name),
", ")));

return Err(um);
}
lnav_data.ld_bottom_source.grep_error("");
}

if (new_top) {
tc->get_sub_source()->get_location_history() |
[new_top](auto lh) { lh->loc_history_append(new_top.value()); };
tc->set_selection(new_top.value());
}
lnav_data.ld_bottom_source.grep_error("");
}

return Ok(retval);
Expand Down
32 changes: 31 additions & 1 deletion src/collation-functions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include <string.h>
#include <sys/socket.h>

#include "base/humanize.hh"
#include "base/intern_string.hh"
#include "base/strnatcmp.h"
#include "config.h"
#include "log_level.hh"
Expand Down Expand Up @@ -64,7 +66,7 @@ try_inet_pton(int p_len, const char* p, char* n)
static int
convert_v6_to_v4(int family, char* n)
{
struct in6_addr* ia = (struct in6_addr*) n;
auto* ia = (struct in6_addr*) n;

if (family == AF_INET6
&& (IN6_IS_ADDR_V4COMPAT(ia) || IN6_IS_ADDR_V4MAPPED(ia)))
Expand Down Expand Up @@ -140,6 +142,32 @@ sql_loglevelcmp(
return levelcmp((const char*) a_in, a_len, (const char*) b_in, b_len);
}

static int
sql_measure_with_units(
void* ptr, int a_len, const void* a_in, int b_len, const void* b_in)
{
auto a_sf = string_fragment::from_bytes((const char*) a_in, a_len);
auto b_sf = string_fragment::from_bytes((const char*) b_in, b_len);

auto a_opt = humanize::try_from<double>(a_sf);
auto b_opt = humanize::try_from<double>(b_sf);

if (a_opt && b_opt) {
auto a_val = a_opt.value();
auto b_val = b_opt.value();

if (a_val < b_val) {
return -1;
}
if (a_val == b_val) {
return 0;
}
return 1;
}

return sql_strnatcasecmp(nullptr, a_len, a_in, b_len, b_in);
}

int
register_collation_functions(sqlite3* db)
{
Expand All @@ -150,6 +178,8 @@ register_collation_functions(sqlite3* db)
db, "naturalnocase", SQLITE_UTF8, nullptr, sql_strnatcasecmp);
sqlite3_create_collation(
db, "loglevel", SQLITE_UTF8, nullptr, sql_loglevelcmp);
sqlite3_create_collation(
db, "measure_with_units", SQLITE_UTF8, nullptr, sql_measure_with_units);

return 0;
}
5 changes: 3 additions & 2 deletions src/column_namer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@

#include "column_namer.hh"

#include "base/intern_string.hh"
#include "base/itertools.hh"
#include "base/lnav_log.hh"
#include "config.h"
#include "sql_util.hh"

const string_fragment column_namer::BUILTIN_COL = "col"_frag;
constexpr string_fragment column_namer::BUILTIN_COL = "col"_frag;

column_namer::column_namer(language lang) : cn_language(lang)
{
Expand Down Expand Up @@ -108,7 +109,7 @@ column_namer::add_column(const string_fragment& in_name)

fmt::format_to(
std::back_inserter(buf), FMT_STRING("{}_{}"), base_name, num);
log_debug("column name already exists (%.*s), trying (%.*s)",
log_trace("column name already exists (%.*s), trying (%.*s)",
retval.length(),
retval.data(),
buf.size(),
Expand Down
32 changes: 21 additions & 11 deletions src/lnav.prompt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include <filesystem>
#include <string>
#include <unordered_set>

#include "lnav.prompt.hh"

Expand All @@ -41,6 +42,7 @@
#include "base/string_attr_type.hh"
#include "bound_tags.hh"
#include "data_scanner.hh"
#include "db_sub_source.hh"
#include "external_editor.hh"
#include "itertools.similar.hh"
#include "lnav.hh"
Expand Down Expand Up @@ -846,18 +848,26 @@ prompt::get_cmd_parameter_completion(textview_curses& tc,
case help_parameter_format_t::HPF_FORMAT_FIELD: {
std::unordered_set<std::string> field_names;

tc.map_top_row([&field_names](const auto& al) {
auto attr_opt = get_string_attr(al.al_attrs, SA_FORMAT);
if (attr_opt) {
auto format_name = attr_opt->get();
auto format
= log_format::find_root_format(format_name.c_str());
for (const auto& lvm : format->get_value_metadata()) {
field_names.emplace(lvm.lvm_name.to_string());
}
auto* tss = tc.get_sub_source();
auto* dls = dynamic_cast<db_label_source*>(tss);
if (dls != nullptr) {
for (const auto& hdr : dls->dls_headers) {
field_names.emplace(hdr.hm_name);
}
return std::nullopt;
});
} else {
tc.map_top_row([&field_names](const auto& al) {
auto attr_opt = get_string_attr(al.al_attrs, SA_FORMAT);
if (attr_opt) {
auto format_name = attr_opt->get();
auto format
= log_format::find_root_format(format_name.c_str());
for (const auto& lvm : format->get_value_metadata()) {
field_names.emplace(lvm.lvm_name.to_string());
}
}
return std::nullopt;
});
}

if (field_names.empty()) {
for (const auto& format : log_format::get_root_formats()) {
Expand Down
Loading

0 comments on commit c656e33

Please sign in to comment.