mirror of
https://github.com/tstack/lnav.git
synced 2024-08-17 00:40:30 +03:00
[ui] make the cylon status mode actually cylon-like
This commit is contained in:
parent
a5a02d6243
commit
ff44e37f7e
@ -91,7 +91,7 @@ run_test() {
|
||||
|
||||
run_cap_test() {
|
||||
LAST_CAP_TEST=("test: $@")
|
||||
local full_cmd=$(echo "${LAST_CAP_TEST[@]}" | sed -e "s;${test_dir};{test_dir};g")
|
||||
local full_cmd=$(echo "${LAST_CAP_TEST[@]}" | sed -e "s;${test_dir};{test_dir};g" -e "s;${top_srcdir};{top_srcdir};g")
|
||||
export test_hash=$(echo "${full_cmd}" | shasum | cut -f 1 -d ' ')
|
||||
echo "${full_cmd}" > ${test_file_base}_${test_hash}.cmd
|
||||
"$@" > ${test_file_base}_${test_hash}.out 2> ${test_file_base}_${test_hash}.err
|
||||
|
@ -43,7 +43,6 @@ bottom_status_source::bottom_status_source()
|
||||
this->bss_fields[BSF_SEARCH_TERM].set_min_width(10);
|
||||
this->bss_fields[BSF_SEARCH_TERM].set_share(1);
|
||||
this->bss_fields[BSF_LOADING].set_width(13);
|
||||
this->bss_fields[BSF_LOADING].set_cylon(true);
|
||||
this->bss_fields[BSF_LOADING].right_justify(true);
|
||||
this->bss_fields[BSF_HELP].set_width(14);
|
||||
this->bss_fields[BSF_HELP].set_value("?:View Help");
|
||||
@ -198,18 +197,18 @@ bottom_status_source::update_loading(file_off_t off, file_size_t total)
|
||||
}
|
||||
} else if ((size_t) off == total) {
|
||||
static const std::vector<std::string> DOTS = {
|
||||
"",
|
||||
".",
|
||||
"..",
|
||||
" ",
|
||||
". ",
|
||||
".. ",
|
||||
"...",
|
||||
"..",
|
||||
".",
|
||||
".. ",
|
||||
". ",
|
||||
};
|
||||
|
||||
this->bss_load_percent += 1;
|
||||
sf.set_cylon(true);
|
||||
sf.set_role(role_t::VCR_ACTIVE_STATUS2);
|
||||
sf.set_value(" Working%s ",
|
||||
sf.set_value(" Working%s ",
|
||||
DOTS[this->bss_load_percent % DOTS.size()].c_str());
|
||||
} else {
|
||||
int pct = (int) (((double) off / (double) total) * 100.0);
|
||||
|
@ -40,7 +40,7 @@
|
||||
void
|
||||
status_field::set_value(std::string value)
|
||||
{
|
||||
string_attrs_t& sa = this->sf_value.get_attrs();
|
||||
auto& sa = this->sf_value.get_attrs();
|
||||
|
||||
sa.clear();
|
||||
|
||||
@ -55,29 +55,31 @@ status_field::set_value(std::string value)
|
||||
void
|
||||
status_field::do_cylon()
|
||||
{
|
||||
string_attrs_t& sa = this->sf_value.get_attrs();
|
||||
auto& sa = this->sf_value.get_attrs();
|
||||
|
||||
remove_string_attr(sa, &VC_STYLE);
|
||||
|
||||
struct line_range lr(this->sf_cylon_pos, this->sf_width);
|
||||
view_colors& vc = view_colors::singleton();
|
||||
auto cycle_pos = (this->sf_cylon_pos % (4 + this->sf_width * 2)) - 2;
|
||||
auto start = cycle_pos < this->sf_width
|
||||
? cycle_pos
|
||||
: (this->sf_width - (cycle_pos - this->sf_width));
|
||||
auto stop = std::min(start + 3, this->sf_width);
|
||||
struct line_range lr(std::max(start, 0L), stop);
|
||||
log_debug("cylon %d:%d %d", lr.lr_start, lr.lr_end, this->sf_width);
|
||||
auto& vc = view_colors::singleton();
|
||||
|
||||
sa.emplace_back(
|
||||
lr,
|
||||
VC_STYLE.value(
|
||||
vc.attrs_for_role(role_t::VCR_ACTIVE_STATUS) | A_REVERSE));
|
||||
sa.emplace_back(lr,
|
||||
VC_STYLE.value(vc.attrs_for_role(role_t::VCR_ACTIVE_STATUS)
|
||||
| A_REVERSE));
|
||||
|
||||
this->sf_cylon_pos += 1;
|
||||
if (this->sf_cylon_pos > this->sf_width) {
|
||||
this->sf_cylon_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
status_field::set_stitch_value(role_t left,
|
||||
role_t right)
|
||||
{
|
||||
string_attrs_t& sa = this->sf_value.get_attrs();
|
||||
auto& sa = this->sf_value.get_attrs();
|
||||
struct line_range lr(0, 1);
|
||||
|
||||
this->sf_value.get_string() = "::";
|
||||
@ -92,7 +94,7 @@ void
|
||||
statusview_curses::do_update()
|
||||
{
|
||||
int top, attrs, field, field_count, left = 0, right;
|
||||
view_colors& vc = view_colors::singleton();
|
||||
auto& vc = view_colors::singleton();
|
||||
unsigned long width, height;
|
||||
|
||||
if (!this->vc_visible) {
|
||||
@ -218,7 +220,7 @@ statusview_curses::window_change()
|
||||
std::stable_sort(begin(resizable), end(resizable), [](auto l, auto r) {
|
||||
return r->get_share() < l->get_share();
|
||||
});
|
||||
for (auto sf : resizable) {
|
||||
for (auto* sf : resizable) {
|
||||
double divisor = total_shares / sf->get_share();
|
||||
int available = remaining / divisor;
|
||||
int actual_width;
|
||||
|
@ -922,8 +922,12 @@ EXPECTED_FILES = \
|
||||
$(srcdir)/%reldir%/test_sql_xml_func.sh_b036c73528a446cba46625767517cdac868aba72.out \
|
||||
$(srcdir)/%reldir%/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.err \
|
||||
$(srcdir)/%reldir%/test_sql_xml_func.sh_fefeb387ae14d4171225ea06cbbff3ec43990cf0.out \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.err \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_5b51b55dff7332c5bee2c9b797c401c5614d574a.out \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.err \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_801414c6bb6d3f9225973eafa3c6dfa49cd2081d.out \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.err \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_87943c6be50d701a03e901f16493314c839af1ab.out \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.err \
|
||||
$(srcdir)/%reldir%/test_text_file.sh_c21295f131c221861568bda5014b76ef99bdd11f.out \
|
||||
$()
|
||||
|
@ -0,0 +1,159 @@
|
||||
Build[1][2] Docs[3][4] Coverage Status[5][6] lnav[7][8]
|
||||
|
||||
▌[1] - https://github.com/tstack/lnav/workflows/ci-build/badge.svg
|
||||
▌[2] - https://github.com/tstack/lnav/actions?[4mquery[0m=workflow%3Aci-build
|
||||
▌[3] - https://readthedocs.org/projects/lnav/badge/?[4mversion[0m=latest&[4mstyle[0m=plastic
|
||||
▌[4] - https://docs.lnav.org
|
||||
▌[5] - https://coveralls.io/repos/github/tstack/lnav/badge.svg?[4mbranch[0m=master
|
||||
▌[6] - https://coveralls.io/github/tstack/lnav?[4mbranch[0m=master
|
||||
▌[7] - https://snapcraft.io//lnav/badge.svg
|
||||
▌[8] - https://snapcraft.io/lnav
|
||||
|
||||
This is the source repository for [1mlnav[0m, visit https://lnav.org[1] for
|
||||
a high level overview.
|
||||
|
||||
▌[1] - https://lnav.org
|
||||
|
||||
[1m[35mLNAV – The Logfile Navigator[0m
|
||||
|
||||
The Log File Navigator, [1mlnav[0m for short, is an advanced log file viewer
|
||||
for the small-scale. It is a terminal application that can understand
|
||||
your log files and make it easy for you to find problems with little
|
||||
to no setup.
|
||||
|
||||
[1mScreenshot[0m
|
||||
|
||||
The following screenshot shows a syslog file. Log lines are displayed
|
||||
with highlights. Errors are red and warnings are yellow.
|
||||
|
||||
Screenshot[1][2]
|
||||
|
||||
▌[1] - file://{top_srcdir}/docs/assets/images/lnav-syslog-thumb.png
|
||||
▌[2] - file://{top_srcdir}/docs/assets/images/lnav-syslog.png
|
||||
|
||||
[1mFeatures[0m
|
||||
|
||||
[33m•[0m Log messages from different files are collated together
|
||||
into a single view
|
||||
[33m•[0m Automatic detection of log format
|
||||
[33m•[0m Automatic decompression of GZip and BZip2 files
|
||||
[33m•[0m Filter log messages based on regular expressions
|
||||
[33m•[0m Use SQL to analyze your logs
|
||||
[33m•[0m And more...
|
||||
|
||||
[1mInstallation[0m
|
||||
|
||||
Download a statically-linked binary for Linux/MacOS from the release
|
||||
page[1]
|
||||
|
||||
▌[1] - https://github.com/tstack/lnav/releases/latest#release-artifacts
|
||||
|
||||
[1mUsage[0m
|
||||
|
||||
The only file installed is the executable, [37m[40m lnav [0m. You can execute it
|
||||
with no arguments to view the default set of files:
|
||||
|
||||
▌[37m[40m$ lnav [0m
|
||||
|
||||
You can view all the syslog messages by running:
|
||||
|
||||
▌[37m[40m$ lnav /var/log/messages* [0m
|
||||
|
||||
[4mUsage with [0m[4m[37m[40m systemd-journald [0m
|
||||
|
||||
On systems running [37m[40m systemd-journald [0m, you can use [37m[40m lnav [0m as the
|
||||
pager:
|
||||
|
||||
▌[37m[40m$ journalctl | lnav [0m
|
||||
|
||||
or in follow mode:
|
||||
|
||||
▌[37m[40m$ journalctl -f | lnav [0m
|
||||
|
||||
Since [37m[40m journalctl [0m's default output format omits the year, if you are
|
||||
viewing logs which span multiple years you will need to change the
|
||||
output format to include the year, otherwise [37m[40m lnav [0m gets confused:
|
||||
|
||||
▌[37m[40m$ journalctl -o short-iso | lnav [0m
|
||||
|
||||
It is also possible to use [37m[40m journalctl [0m's json output format and [37m[40m lnav[0m
|
||||
will make use of additional fields such as PRIORITY and _SYSTEMD_UNIT:
|
||||
|
||||
▌[37m[40m$ journalctl -o json | lnav [0m
|
||||
|
||||
In case some MESSAGE fields contain special characters such as ANSI
|
||||
color codes which are considered as unprintable by journalctl,
|
||||
specifying [37m[40m journalctl [0m's [37m[40m -a [0m option might be preferable in order to
|
||||
output those messages still in a non binary representation:
|
||||
|
||||
▌[37m[40m$ journalctl -a -o json | lnav [0m
|
||||
|
||||
If using systemd v236 or newer, the output fields can be limited to
|
||||
the ones actually recognized by [37m[40m lnav [0m for increased efficiency:
|
||||
|
||||
▌[37m[40m$ journalctl -o json [0m[4m[37m[40m--output-fields[0m[37m[40m=MESSAGE,PRIORITY,_PID,SYSLOG_IDENTIFIER,_SYSTEMD_UNIT | lnav [0m
|
||||
|
||||
If your system has been running for a long time, for increased
|
||||
efficiency you may want to limit the number of log lines fed into [37m[40m lnav[0m
|
||||
, e.g. via [37m[40m journalctl [0m's [37m[40m -n [0m or [37m[40m [0m[4m[37m[40m--since[0m[37m[40m=... [0m options.
|
||||
|
||||
In case of a persistent journal, you may want to limit the number of
|
||||
log lines fed into [37m[40m lnav [0m via [37m[40m journalctl [0m's [37m[40m -b [0m option.
|
||||
|
||||
[1mLinks[0m
|
||||
|
||||
[33m•[0m Main Site[1]
|
||||
[33m•[0m [1mDocumentation[0m[2] on Read the Docs
|
||||
[33m•[0m Internal Architecture[3]
|
||||
|
||||
▌[1] - https://lnav.org
|
||||
▌[2] - https://docs.lnav.org
|
||||
▌[3] - file://{top_srcdir}/ARCHITECTURE.md
|
||||
|
||||
[1mContributing[0m
|
||||
|
||||
[33m•[0m Become a Sponsor on GitHub[1]
|
||||
|
||||
▌[1] - https://github.com/sponsors/tstack
|
||||
|
||||
[4mBuilding From Source[0m
|
||||
|
||||
[4mPrerequisites[0m
|
||||
|
||||
The following software packages are required to build lnav:
|
||||
|
||||
[33m•[0m gcc/clang - A C++14-compatible compiler.
|
||||
[33m•[0m libpcre - The Perl Compatible Regular Expression
|
||||
(PCRE) library.
|
||||
[33m•[0m sqlite - The SQLite database engine. Version 3.9.0
|
||||
or higher is required.
|
||||
[33m•[0m ncurses - The ncurses text UI library.
|
||||
[33m•[0m readline - The readline line editing library.
|
||||
[33m•[0m zlib - The zlib compression library.
|
||||
[33m•[0m bz2 - The bzip2 compression library.
|
||||
[33m•[0m libcurl - The cURL library for downloading files
|
||||
from URLs. Version 7.23.0 or higher is required.
|
||||
[33m•[0m libarchive - The libarchive library for opening archive
|
||||
files, like zip/tgz.
|
||||
[33m•[0m wireshark - The [35m'tshark'[0m program is used to interpret
|
||||
pcap files.
|
||||
|
||||
[4mBuild[0m
|
||||
|
||||
Lnav follows the usual GNU style for configuring and installing
|
||||
software:
|
||||
|
||||
Run [37m[40m ./autogen.sh [0m if compiling from a cloned repository.
|
||||
|
||||
▌[37m[40m$ ./configure [0m
|
||||
▌[37m[40m$ make [0m
|
||||
▌[37m[40m$ sudo make install [0m
|
||||
|
||||
[1mSee Also[0m
|
||||
|
||||
Angle-grinder[1] is a tool to slice and dice log files on the
|
||||
command-line. If you're familiar with the SumoLogic query language,
|
||||
you might find this tool more comfortable to work with.
|
||||
|
||||
▌[1] - https://github.com/rcoh/angle-grinder
|
||||
|
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) [1m2018[0m, Timothy Stack
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, [1m[36mthis[0m
|
||||
* list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* [1m[36mthis[0m list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of Timothy Stack nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from [1m[36mthis[0m software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* [1mTHIS[0m [1mSOFTWARE[0m [1mIS[0m [1mPROVIDED[0m [1mBY[0m [1mTHE[0m [1mREGENTS[0m [1mAND[0m [1mCONTRIBUTORS[0m [35m''[0m[1mAS[0m [1mIS[0m'' [1mAND[0m [1mANY[0m
|
||||
* [1mEXPRESS[0m [1mOR[0m [1mIMPLIED[0m [1mWARRANTIES[0m, [1mINCLUDING[0m, [1mBUT[0m [1mNOT[0m [1mLIMITED[0m [1mTO[0m, [1mTHE[0m [1mIMPLIED[0m
|
||||
* [1mWARRANTIES[0m [1mOF[0m [1mMERCHANTABILITY[0m [1mAND[0m [1mFITNESS[0m [1mFOR[0m A [1mPARTICULAR[0m [1mPURPOSE[0m [1mARE[0m
|
||||
* [1mDISCLAIMED[0m. [1mIN[0m [1mNO[0m [1mEVENT[0m [1mSHALL[0m [1mTHE[0m [1mREGENTS[0m [1mOR[0m [1mCONTRIBUTORS[0m [1mBE[0m [1mLIABLE[0m [1mFOR[0m [1mANY[0m
|
||||
* [1mDIRECT[0m, [1mINDIRECT[0m, [1mINCIDENTAL[0m, [1mSPECIAL[0m, [1mEXEMPLARY[0m, [1mOR[0m [1mCONSEQUENTIAL[0m [1mDAMAGES[0m
|
||||
* ([1mINCLUDING[0m, [1mBUT[0m [1mNOT[0m [1mLIMITED[0m [1mTO[0m, [1mPROCUREMENT[0m [1mOF[0m [1mSUBSTITUTE[0m [1mGOODS[0m [1mOR[0m [1mSERVICES[0m;
|
||||
* [1mLOSS[0m [1mOF[0m [1mUSE[0m, [1mDATA[0m, [1mOR[0m [1mPROFITS[0m; [1mOR[0m [1mBUSINESS[0m [1mINTERRUPTION[0m) [1mHOWEVER[0m [1mCAUSED[0m [1mAND[0m
|
||||
* [1mON[0m [1mANY[0m [1mTHEORY[0m [1mOF[0m [1mLIABILITY[0m, [1mWHETHER[0m [1mIN[0m [1mCONTRACT[0m, [1mSTRICT[0m [1mLIABILITY[0m, [1mOR[0m [1mTORT[0m
|
||||
* ([1mINCLUDING[0m [1mNEGLIGENCE[0m [1mOR[0m [1mOTHERWISE[0m) [1mARISING[0m [1mIN[0m [1mANY[0m [1mWAY[0m [1mOUT[0m [1mOF[0m [1mTHE[0m [1mUSE[0m [1mOF[0m [1mTHIS[0m
|
||||
* [1mSOFTWARE[0m, [1mEVEN[0m [1mIF[0m [1mADVISED[0m [1mOF[0m [1mTHE[0m [1mPOSSIBILITY[0m [1mOF[0m [1mSUCH[0m [1mDAMAGE[0m.
|
||||
*/
|
||||
|
||||
[32m#include [0m[32m"log_level.hh"[0m
|
||||
|
||||
[32m#include <[0m[32mctype.h[0m[32m>[0m
|
||||
|
||||
[32m#include [0m[32m"config.h"[0m
|
||||
|
||||
[1m[36mconst[0m [1m[36mchar[0m* level_names[[1mLEVEL__MAX[0m + [1m1[0m] = {
|
||||
[35m"unknown"[0m,
|
||||
[35m"trace"[0m,
|
||||
[35m"debug5"[0m,
|
||||
[35m"debug4"[0m,
|
||||
[35m"debug3"[0m,
|
||||
[35m"debug2"[0m,
|
||||
[35m"debug"[0m,
|
||||
[35m"info"[0m,
|
||||
[35m"stats"[0m,
|
||||
[35m"notice"[0m,
|
||||
[35m"warning"[0m,
|
||||
[35m"error"[0m,
|
||||
[35m"critical"[0m,
|
||||
[35m"fatal"[0m,
|
||||
[35m"invalid"[0m,
|
||||
|
||||
nullptr,
|
||||
};
|
||||
|
||||
log_level_t
|
||||
abbrev2level([1m[36mconst[0m [1m[36mchar[0m* levelstr, ssize_t len)
|
||||
{
|
||||
[1m[36mif[0m ([4mlen[0m == [1m0[0m || levelstr[[1m0[0m] == [35m'\[0m[1m[35m0[0m[35m'[0m) {
|
||||
[1m[36mreturn[0m [1mLEVEL_UNKNOWN[0m;
|
||||
}
|
||||
|
||||
[1m[36mswitch[0m (toupper(levelstr[[1m0[0m])) {
|
||||
[1m[36mcase[0m [35m'T'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_TRACE[0m;
|
||||
[1m[36mcase[0m [35m'D'[0m:
|
||||
[1m[36mcase[0m [35m'V'[0m:
|
||||
[1m[36mif[0m (len > [1m1[0m) {
|
||||
[1m[36mswitch[0m (levelstr[len - [1m1[0m]) {
|
||||
[1m[36mcase[0m [35m'[0m[1m[35m2[0m[35m'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_DEBUG2[0m;
|
||||
[1m[36mcase[0m [35m'[0m[1m[35m3[0m[35m'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_DEBUG3[0m;
|
||||
[1m[36mcase[0m [35m'[0m[1m[35m4[0m[35m'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_DEBUG4[0m;
|
||||
[1m[36mcase[0m [35m'[0m[1m[35m5[0m[35m'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_DEBUG5[0m;
|
||||
}
|
||||
}
|
||||
[1m[36mreturn[0m [1mLEVEL_DEBUG[0m;
|
||||
[1m[36mcase[0m [35m'I'[0m:
|
||||
[1m[36mif[0m ([4mlen[0m == [1m7[0m && toupper(levelstr[[1m1[0m]) == [35m'N'[0m
|
||||
&& toupper(levelstr[[1m2[0m]) == [35m'V'[0m && toupper(levelstr[[1m3[0m]) == [35m'A'[0m
|
||||
&& toupper(levelstr[[1m4[0m]) == [35m'L'[0m && toupper(levelstr[[1m5[0m]) == [35m'I'[0m
|
||||
&& toupper(levelstr[[1m6[0m]) == [35m'D'[0m)
|
||||
{
|
||||
[1m[36mreturn[0m [1mLEVEL_INVALID[0m;
|
||||
}
|
||||
[1m[36mreturn[0m [1mLEVEL_INFO[0m;
|
||||
[1m[36mcase[0m [35m'S'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_STATS[0m;
|
||||
[1m[36mcase[0m [35m'N'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_NOTICE[0m;
|
||||
[1m[36mcase[0m [35m'W'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_WARNING[0m;
|
||||
[1m[36mcase[0m [35m'E'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_ERROR[0m;
|
||||
[1m[36mcase[0m [35m'C'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_CRITICAL[0m;
|
||||
[1m[36mcase[0m [35m'F'[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_FATAL[0m;
|
||||
[1m[36mdefault[0m:
|
||||
[1m[36mreturn[0m [1mLEVEL_UNKNOWN[0m;
|
||||
}
|
||||
}
|
||||
|
||||
[1m[36mint[0m
|
||||
levelcmp([1m[36mconst[0m [1m[36mchar[0m* l1, ssize_t l1_len, [1m[36mconst[0m [1m[36mchar[0m* l2, ssize_t l2_len)
|
||||
{
|
||||
[1m[36mreturn[0m abbrev2level(l1, l1_len) - abbrev2level(l2, l2_len);
|
||||
}
|
Loading…
Reference in New Issue
Block a user