From f5e88b7158b8dd10e928c7dc513cd189ef7623ef Mon Sep 17 00:00:00 2001 From: Timothy Stack Date: Sat, 13 Feb 2021 12:41:48 -0800 Subject: [PATCH] [docs] add ARCHITECTURE.md and various other things --- .github/workflows/check-md-links.yml | 10 + ARCHITECTURE.md | 80 +++ NEWS | 1 + README.md | 3 +- aminclude_static.am | 2 +- docs/README.md | 4 + docs/lnav-architecture.png | Bin 0 -> 212540 bytes docs/lnav-tui.png | Bin 0 -> 156641 bytes docs/source/_ext/__init__.py | 0 docs/source/_ext/lnavlexer.py | 26 + docs/source/_static/theme_overrides.css | 34 + docs/source/cli.rst | 103 ++- docs/source/commands.rst | 25 +- docs/source/conf.py | 20 +- docs/source/config.rst | 2 +- docs/source/cookbook.rst | 33 +- docs/source/docutils.conf | 2 + docs/source/faq.rst | 57 ++ docs/source/formats.rst | 5 + docs/source/hotkeys.rst | 185 ++--- docs/source/index.rst | 3 +- docs/source/intro.rst | 10 +- docs/source/kbd.rst | 32 - docs/source/sqlext.rst | 20 +- docs/source/usage.rst | 21 +- release/README.md | 4 + src/CMakeLists.txt | 1 + src/Makefile.am | 66 +- src/archive_manager.cc | 10 +- src/base/date_time_scanner.cc | 2 +- src/base/date_time_scanner.hh | 2 +- src/base/file_range.hh | 8 +- src/bottom_status_source.cc | 4 +- src/bottom_status_source.hh | 2 +- src/files_sub_source.cc | 3 - src/filter_observer.hh | 2 +- src/filter_sub_source.cc | 6 +- src/formats/README.md | 3 +- src/formats/formats.am | 38 + src/help_text_formatter.cc | 6 +- src/highlighter.cc | 25 +- src/highlighter.hh | 12 +- src/internals/cmd-ref.rst | 471 ++++-------- src/internals/config-v1.schema.json | 5 - src/internals/sql-ref.rst | 909 ++++++++---------------- src/keymaps/README.md | 3 +- src/keymaps/keymaps.am | 8 + src/line_buffer.cc | 18 +- src/line_buffer.hh | 26 +- src/lnav.cc | 4 +- src/lnav_config.cc | 4 - src/log_format.cc | 11 +- src/log_format_fwd.hh | 10 +- src/log_format_loader.cc | 2 +- src/logfile.cc | 13 +- src/logfile.hh | 14 +- src/logfile_sub_source.cc | 8 +- src/readline_highlighters.cc | 4 +- src/readline_possibilities.cc | 2 +- src/scripts/README.md | 3 +- src/scripts/scripts.am | 12 + src/styling.cc | 15 + src/styling.hh | 42 +- src/textfile_highlighters.cc | 8 +- src/textview_curses.cc | 21 +- src/themes/README.md | 3 +- src/themes/default-theme.json | 14 +- src/themes/eldar.json | 6 +- src/themes/grayscale.json | 141 ++++ src/themes/monocai.json | 6 +- src/themes/night-owl.json | 6 +- src/themes/solarized-dark.json | 6 +- src/themes/solarized-light.json | 6 +- src/themes/themes.am | 10 + src/top_status_source.cc | 7 +- src/view_curses.cc | 129 +++- src/view_curses.hh | 21 +- src/yajlpp/yajlpp_def.hh | 2 +- test/CMakeLists.txt | 3 + test/drive_view_colors.cc | 29 +- test/view_colors_output.0 | 34 +- test/xpath_tui.0 | 179 ++--- 82 files changed, 1556 insertions(+), 1531 deletions(-) create mode 100644 .github/workflows/check-md-links.yml create mode 100644 ARCHITECTURE.md create mode 100644 docs/README.md create mode 100644 docs/lnav-architecture.png create mode 100644 docs/lnav-tui.png create mode 100644 docs/source/_ext/__init__.py create mode 100644 docs/source/_ext/lnavlexer.py create mode 100644 docs/source/docutils.conf create mode 100644 docs/source/faq.rst delete mode 100644 docs/source/kbd.rst create mode 100644 release/README.md create mode 100644 src/formats/formats.am create mode 100644 src/keymaps/keymaps.am create mode 100644 src/scripts/scripts.am create mode 100644 src/themes/grayscale.json create mode 100644 src/themes/themes.am diff --git a/.github/workflows/check-md-links.yml b/.github/workflows/check-md-links.yml new file mode 100644 index 00000000..453a2091 --- /dev/null +++ b/.github/workflows/check-md-links.yml @@ -0,0 +1,10 @@ +name: Check Markdown links + +on: push + +jobs: + markdown-link-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@v1 diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000..ac221b58 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,80 @@ +# Architecture + +This document covers the internal architecture of the Logfile Navigator (lnav), +a terminal-based tool for viewing and analyzing log files. + +## Goals + +The following goals drive the design and implementation of lnav: + +- Don't make the user do something that can be done automatically. + + Example: Automatically detect log formats for files instead of making them + specify the format for each file. + +- Be performant on low-spec hardware. + + Example: Prefer single-threaded optimizations over trying to parallelize + +- Operations should be "live" and not block the user from continuing to work. + + Example: Searches are run in the background. + +- Provide context-sensitive help. + + Example: When the cursor is over a SQL keyword/function, the help text for + that is shown above. + +- Show a preview of operations so the user knows what is going to happen. + + Example: When entering a `:filter-out` command, the matched parts of the + lines are highlighted in red. + +## Overview + +The whole of lnav consists of a +[log file parser](https://lnav.readthedocs.io/en/latest/formats.html), +[text UI](https://lnav.readthedocs.io/en/latest/ui.html), +[integrations with SQLite](https://lnav.readthedocs.io/en/latest/sqlext.html), +[command-line interface](https://lnav.readthedocs.io/en/latest/cli.html), +and +[commands for operating on logs](https://lnav.readthedocs.io/en/latest/commands.html). +Since the majority of lnav's operations center around logs, the core +data-structure is the combined log message index. The message index +is populated when new messages are read from log files. The text UI +displays a subset of messages from the index. The SQLite virtual-tables +allow for programmatic access to the messages and lnav's internal state. + +[![lnav architecture](docs/lnav-architecture.png)](https://whimsical.com/lnav-architecture-UM594Qo4G3nt2XWaSZA1mh) + +## File Monitoring + +Each file being monitored by lnav has an associated [`logfile`](src/logfile.hh) +object, be they plaintext files or files with a recognized format. These +objects are periodically polled by the main event loop to check if the file +was deleted, truncated, or new lines added. While reading new lines, if no +log format has matched yet, each line will be passed through the log format +regular expressions to try and find a match. Each line that is read is added +to an index + +### Why is `mmap()` not used? + +Note that file contents are consumed using `pread(2)`/`read(2)` and not +`mmap(2)` since `mmap(2)` does not react well to files changing out from +underneath it. For example, a truncated file would likely result in a +`SIGBUS`. + +## Log Messages + +As files are being indexed, if a matching format is found, the file is +"promoted" from a plaintext file to a log file. When the file is promoted, +it is added to the [logfile_sub_source](src/logfile_sub_source.hh), which +collates all log messages together into a single index. + +## User Interface + +[![lnav TUI](docs/lnav-tui.png)](https://whimsical.com/lnav-tui-MQjXc7Vx23BxQTHrnuNp5F) + +The lnav text-user-interface is built on top of the basic drawing functionality +of [ncurses](https://invisible-island.net/ncurses/announce.html). However, + diff --git a/NEWS b/NEWS index a7f8ad19..cacf95fd 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,7 @@ lnav v0.9.1: "lnav_views" SQLite table. * Themes can now include definitions for text highlights under: /ui/theme-defs//highlights + * Added a "grayscale" theme that isn't so colorful. Interface Changes: * When copying log lines, the file name and time offset will be included diff --git a/README.md b/README.md index 2e28f5ea..306c64bd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build](https://github.com/tstack/lnav/workflows/ci-build/badge.svg) +[![Build](https://github.com/tstack/lnav/workflows/ci-build/badge.svg)](https://github.com/tstack/lnav/actions?query=workflow%3Aci-build) [![Coverage Status](https://coveralls.io/repos/github/tstack/lnav/badge.svg?branch=master)](https://coveralls.io/github/tstack/lnav?branch=master) [![lnav](https://snapcraft.io//lnav/badge.svg)](https://snapcraft.io/lnav) @@ -15,6 +15,7 @@ no setup. - [Main Site](https://lnav.org) - [**Documentation**](https://lnav.readthedocs.io) on Read the Docs +- [Architecture](ARCHITECTURE.md) ## Contributing diff --git a/aminclude_static.am b/aminclude_static.am index 613a90b6..322753df 100644 --- a/aminclude_static.am +++ b/aminclude_static.am @@ -1,6 +1,6 @@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Tue Feb 2 19:06:51 PST 2021 +# from AX_AM_MACROS_STATIC on Tue Feb 9 14:05:27 PST 2021 # Code coverage diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..3e4fb6c5 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,4 @@ +# Docs + +This directory contains the ReST documentation that is published to +[lnav.readthedocs.io](https://lnav.readthedocs.io) diff --git a/docs/lnav-architecture.png b/docs/lnav-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..75414508638d99a1bf9ba1fa3a9395b1c4eaa79f GIT binary patch literal 212540 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
{mW!iI=}Rc16n)1Zoi-=U4M=3V`gXe{J? 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
-mL3|5YKlm$Yz6^UY>ngBVa)4gGZHnm`NOMwK7vGL#boxQIHUOr>RR_T;=N<-vFXItCoRvpfF8YqUmZY1lbv zCUg5jOe0|P-=dOj05j{@if)LV)f39OMLxE6b3tfxo_09~aUkAyY%aL#PT8`38mr-p z6n%7UPx3$v06kJ;E81?qIFS{x%EO;Psb1lXd+U+aJH)Ye@^EPPS)Q5xw#k$u`PjN< zp+8R;Q+77RRFtwkn=0mA8D=n|xo-9VCc+kl;WlQ}*08u!9N}{{ot!lsdjEei8xq9? zm|zYa6yRFPNH2z}=RNxp+Zv}v(wxCg`o#cDmFt*(A>?^-ame%N_WS329$eoyYuuf> zxE;Th-%MJ8^m;%Q`Lv%!-LK1K>chKXUbd#?PE+!Os-7AH)PwSJ`WgXzy8bZRs%h=! zS<*tq2q^7&LLgwuqPg>|dlm*{*4>iWq$tNrc%6h-zOus$ltY8tE692Sq_VlNi<)}f zXZpS+21R49yPq6pKj<+!c?o8L8qZ#yl3mX%_D2;{qQ)B@TiaK30cDP|fpS7u_-UIA z-Z;JKC$W{5AiNDzvZ`!RMm`K&2C{bSh~<-bm0%f(d+riTBZyZ8#}#aTBs&A(6PC8> z&BygzlWe+`lzKv{^$s1V;>dgL63JbQBGaipy*E+E?z*r0A33kNYea%vtJ2E?Ya*tq z7_4iyeHFC?geqAPjVuGUpG3-$@~$SEG{r#zxf?a`>b21ai6&GR5s}1n${YyoyTu!B z2wbb0a%Stp*`T+rO#zt|>7-udG6MXNIQM%)+4(Qw>R~%i_j*rmZ@s*bbW%U|Al6h+ z*OFoAHKH@KBBIYbsAO^@rlYYcy}Cvt#nDgF&qg1ad+M3Y^-@ue64UiRwR7{nOH|am zilI$;7+sw@`m@v`L-&rzti~^0`}YNRDX@K?LnofZpw9!&CXN&dq7=x=O=eg6Qk9PO zAknE6xW!?4|C%|s2R=_=_0s9;IY&l{*Zm_yPxIwb_!6Q1K={3nU0+B0GKI3k;vTzK zk3x^5VYKIM=xOC{UAq0QpQ|Ofe8x(E73-U z!(T7b)Dvn;+WVik-c+^G1g{Y{er+ioD3X-TFV&@1>wDhWJ#j_Ga>7BODL1~{aD6lX zb8M!=c)c&YCWJwG%(Ss=oL^N2-}sUs#AnBQY=70;yxwc69~Y95){;y}=LnR>mt5z*)?t z(1}x)jm+%S`oLl?C)W-ceO+zT2Wu}?ADA_g3aBDgjPqv;Yy$<8D7tr7td5S>Dz{q{ zQA$?j?qDNKOE<~5V*vrNK7ltslc zRhFrd72f-CWdOQ6lr6XQY*OPF|l-zQrX72QzcXW`DWCevX$RI1~z)t&+} z?V2%H<#?XdcP+h52kirvN!#-8_fG@c1(pre70mP+&Ns6$Vw%sRq!Do?&tk8z%Om$c zBSkfo^rQ9R?#ydh=^f^vM;##18upw|OFllqjS>};fPX_ualA#=Fp8+I9keB2QfJ%V z@;+TF5bv*7`_#=r!cvoOe9rj5tfc@u@con1810c~es0y=&fNAKm@%-1sKdGj!DhI- zs2_t_jOJdyqTS-4a9Qxvg9m%UynSAT1U6qlw>!+7eOU2jvQFV$u@GZNSrIsoIhuG@j1`7O+!JA!((%+ot|4aW}Vp7?Xt9)2Hu;oan!X zv{)T4PWZq!yP_CUjnN|&{o9&lfpxx@$!zW71}z!BOOky8ODIMb$&>^BXR;C!Ma}N{ zIC){oV>EA7z_#^Vl@mGeBi@wKAN5|L6-~h-0^zF^qoL}LUxf2cokWD3%a*c` zD%)vohN*#dw+GM1zETs=+LV_Th%(q@IET2GuteFG7*`61GN`%W17+^Mz@qo{Sq~^C zL{-opp1L?HD6Y*JV4as-$<8=f7mdnx{wsWK{D4F1U@g=-2f8mkgx|G>Xnf!`X6Q9H$qXrtg)eWeA3%`#s4e0hUr!G(-ZxIJn$iq)7!-oV`CYzEaA%3W#ti-MWE!P zF5`PK7%Y2U1}1%ivi?$W!(8P2P}xD=8=}ACRC8WPpsCdprc(OAv=U%73ooC+%H>)U zk)-6?{50*AUg%TzwtHI|o^p${f&14b)w4|An4s1Vby*(K>zFdHMQ^mVDBh3tEgj6% zXjSyud@m8%8XS8F7~Rd=rPd`~dQY@++Ajvs`mAhE9&(NN&bL-Ld!PNT zL;S|#Lrz9*{BUwmW}!}XEm!)MUY2QJIA(_Pnw!cJx?eR+a#0pT*5itoMB6l)$qKc~ z#{XHq|DxwKp1$kYECuq@^~KI8$0z;V(&FE(BjgrCfj9avW~R99-D;Kmzw>Icg6EY3 zXD|9)kJ9_35gd?7c=z3njWz{uhekhMLC8=q5PC9yUyfa+&X3_N*Zz->HG^!Y$i0$nnR@V$4a1;E%x$785RrMFF` zal~YTKs0)ybRrgGv-RuM^g=hd_LTeV)bU=~tloYDalA{P1O6PP^O9qz;)qYfsb^Y~(fyAbyMEansk8V^L_)$O=EuVNa^3k()nKbAAKXoI( zin)bOdD+lZ z{4o)Gf62)pPj^Rr%Uc@Xe4M~j)EbshnX|?23>b zH)?GKUY5!@7UP(IVc@x#3{XU7^`;{w_*c)$cL~8ay0J5w)1LPCQ3e#7^p%v1j8t)V zMgRExiNDx^fVi>sK>&tQ8q-{#tzYAH`r0hSM@G+Esb!pWa`O5ymFYj3vZ!emTrrmX)pFXktj` zJHQPtVKEA8f8a~kin3guZylrmcPUyA_i63wf|B{gpOZo?6t9W$6%$sP3HWZ_2g=GY zmj1bkFGAm2OnihX;ZZ}vQv0YPGwK(geqC_M0ofGU%9+Doi-+u2A^VNbN)t;p?DqU- zgWKg&E(iW}#`47WG>vI|v^oM*{C>3mb5P$1RX)X~^l;pVpTbJ?!Rn)YEs3Wg(^2|N zo##g_h&ji37$u8yJ$J;<_kOiv@Cg9UG@a7l3hT>X?~e_Hv<$RaKny>V0+Fx94s|$# z1#bVM`folZGGGE_M9n5W7k}yu2ocfeoc`g#6M!E-SX zP_;H-GxtkV5|U)sJr-rgb0*79+xpJAy2mggr@v|Z^{T84@NNHA(aMcq!nuBF|9%B7 z+grN74dK6333miA>V*mlt)Bz@{sz~>)9P!A2s|6an~5&J`ZAq@oz-l!$3vjscboi8 z2%rkHqp4s1gRSPT>-am^L}-W|L?1sGi6_yw7fj=sd&>By+DH}}pa#x|H9YN1`7BUY z4aZ{^J~19E@u|?51N-u;a)=O7kL z1=b_!?px&>yD2aITYK7?HzQqFNdgsrO{ag5R8j@NCcO5Qz~AUUeWQ!HAk(bTr~JLB zXO7Lg)+Xat_t+n}{ReA-O)_BsXG*sQ`hhc#|ArBvxh2FgLVv%V(1DE%Ozp@k^eZ%vxP`d&ml6~00{f7-cN7Y3~MXlpO;_?V3jXH{$aelqbm z&)_XMMRmrtKQ#@)(h^S01IO=)Vj&Cd{;A0xh3V5iE<6IoXW}Ftf1fC`J2bw zp<=-Qa0fWG9&4qQMH!U-G2#FQcD5>h z#uJ;j1G4mgD-l04bb~CcXn;P`gt?$Ya8`N2iyz~F++zJYV&OY=u0r9tm^fxQi}ql6 zN14|rsxULgfW_B~?KC4aza!}v1NtQrZ=RfsKRPBY%6H`mK_8j)FJvwKv_Of|7(Qm{ z`?5D9R*O}mc|XkRpMohv^D9DdeVD?*ur->1#IAnswvS@~(zW#udJsZKWZwK7>d@Ul zP#|bM60(e(mFejmLTx)CloA%nk?T9lQ?M zyuGQzLz#5vPbi~;1QJhpW>CeAt%$1KQ4c%x=eE{P-R%t~hl7oh z_Z{THH-;Hlp3420`jJT(V1k3A-2S^XTn+R_>0f{l zAzD~a%vjaS0@@Wv#?)${`o0q+>MGvnKMGhQQS-v+3_-@o^U_t?$J>3Bn*F;CDNnSw zF4zdIZ_VwN&fP5Q(3esgs4$NI1=V(p&5^sT%Unv%!jUO3IX%Y^_3^-bYwsd$d`tha zc^NGiw+gS{6w4Wyejm}7N2eVZ#rccIhU1i_T8sdKAtyfocHHJhMDGH)H#Qn@ar^@o3_afBIHBD<<>b&m(2b3ZrJmCt_;UA{Q z_pikKaZ8lMw2$n0$Q4=8^*j#gWA<^_h0QzG?AjFxK(zfS1$1TY;HS&cY*Uq@DLgG5z9rD-^)uxDlj6`xi~>Xzlx0z%dEiV$x6n*`*;FR|w%mnLBRyxq z^;X(k4|7=U&yfrgKTh!Pi*G`6vrGiSH!(|7cT+&xznh+a!ZdLmqw98$T4wR4-DWocdU zPV1nwI+cfxyJtn7iXQ2YW(@=`rNCsu202(_;%(I(NEq^!+7=>FSKpU^|%)+_A{l#$Lz+S-{_wRA=%^-uz2v!iPF zhcm{x&WX_6=NpT8NmwQnz|Xq$fE7&A{qO}d_~ZUx^Qd1l@yLx~A|Dz^WTCgBRFjbQ zZ`{1a=m=*a6EZsh*Rm3i)~L!_*GY)*?N_+wVXNdypCK>$Vd71U(Z5uWsCdZUhfgS! zb%3qq`juCmkCOCCC~%SF(dM7^!9<2vm)P zQ1EH-AN+)}8u4B5dfU2LS--d1f2xw3Shi!1ZEhY@$34c|RLBo+v09=c@eU{_p^MPP zfbC~~XUtm91B~1oJw%$b1lc2rP;QpIVu+3X)PtW8FHlWXdajjP;`*?3C%1IuR9*ij zM-{^T6^r!CN3A%lZiZ$jb-Pk~c{ks_qhHRe2@E7|sc3a9F#g+*AT(z=^_=`G!d?J} zyQqj>cHcI(W;FWAGm>j0YX{~fo`Jss<;GU6Q+DkEQf9JoBdj$G|axJ`5LH^E~#Xt2e51xuUwse1%DyNor>1@gw zKz|>aFD|nva&?NP|5c5%MhnSxBXaBA0=l370w~Pmph&xSh660jJ#VQ?Ov+~o@|Qyb z+r!t@watPu)g*peQ(zOJD{C~ax+djM0=|z8*hU;%yR#a^rt3Z3OEss*TSGS|dJ9f6 zRTy}N$BC*~TA)`@>B;4czm_YMZvC9HkSON&BJ`>7DC;D|KX_F~b8*Ky+RIsF&Xxq8 zIm59zTu70A){)I+>sg^L32*|k8KwWDo(aNmO#`}`8WSE5?sXJrJ>s=!m?4cR442Q2(VP)zCmxM{-@!swswfrpU_=p*@eC~MoNfZ4oNj)O z_ZgI*d4Ae%^y5Uc*$W8VgN?W>Iq9uSCRs%9&#Wug$r1uhT+b^K`RU%Df$)#f!qtYq{?Y{2ee@2E}kAczPR}5F2QD?smOH0gP?V`w#nTAdv!XWd)_-%A(GW0HvV%6@IhmNN(g{!So}Hj~mV^+$eZ(7f+hgyELI#}xE&GdT#l zvDJQU4VqSmB?GGwusGPv9dXY+vz0P27(>F`DkZPt4%*@DKU(h4<-Gjc?K8OO*9Hb?HW{|F@q#6Pc|x=L@6D;F zTI1Sz>XNW$!+*x)8P$9Ge&#hm?5bPc|B#;!!f}-A* zYe}L<^+#7?OsD(a=d;t-{yFAT@p8x1J%(U*4XUl3$_^4m`yL&5ZJbv)&ucGQK8Ru& z>pKS6)gTrJI`oM)Ic1RlP8yJ~e#M#pk)lgs3dG?6$=WGrT zJJ_x-ajm)D!)vpyK>lBlF}Q@;e)3Ew7q>J#+quf=+d$YUAidr_vb6~kOnmWND&Oze5P4c<6|Ae&IO~@+c8@xx|{EM*% z3SKM9Q}(|tMPxYSJpJCU1;)#lFOm5=wiV01O!-w?Ys5Ow>PL%0TM;GU==$Ou zwtf?rVMhtgR*4QaCfgsbytzFjxCWIi+?v{|(qX4{?YxbghXwcV`}Ds{6bN!3pWM~4 zo^U&U;Sny-(Hm`&7*jsu&h)t-HJL?(6El?z;mBB#j&Rq@RWK$32X^gk$*S zI&W3CxY~&>>()LhivKV{vU7XR2Hursi({ejsH<5BPc?E+pl#|%W2&_;QE<%#?XG3u z|GDJ9dST#!=A{dP^Z*|A8FjA70P|$+f06kA;pKmRo$oDz;gg(}=@HJ-vEQsos>4)1 ze09yQ$#Egr-3)&7y4J>Mt;TaZZZqIH_Cm3wST}9J=Ny>h{p{$^Z9@-FMnM}58$`ht>$-mrYS`yi?ggwwo38bD*DI4hrhE)DI2e7S)LniyRAWXQ`aj6 z=pSy;h|mcwxn7Kg9VB#TzdO#nD|-9FelGREgJypB`>exdy=CK{l01AFH}KtPKUDAr z<9J>e?gyC7KIFkRswq&sNXOrLkbu`YO8acy=GwW{?8`ra|BPAqS~n-@LrMt9& zul{alge8I}C~bs^Emjar^Xfn0RIdXkRmuAT_8~g;RTrZ19{bj@Mg&L|76$W zvIIE4;*bErkms|_pzT>kGmV-mv&Wcnn3Tp1>BzG`Oyz$?s6XPUhET@6=-PpYQ}8)I z(;xc;A63M|5!I7?wHq&YcjF1H*c5h5wYCY%Z@nNUcY^#+h=JsA;@X(~#h>;uV)%Cu zgXA3t)8XK&>Y9l&ZOuINe*%5~8_G^!j_KA&n1r~@s;ZqF891gj84uMoMBG7P^8tzC zExNT5wqt*+5lpOMhLY!Pr-}Eq<@C%kcKu zLo(~Cygy#Nmmb_KwBq2h!W)fDm;n6hyY{2`fR3$@i6_rhD9L(-xLIiQUnWXJ_&yzJ zjY+^wMeGx|Ur&nx~P&H|%dXwF2J^H9g%|9<_Z4$qg} z746`u8+t$s4=AuXM|FG_mLXe}Ki4Ls4?b+}v_#I?x?p5V0`d_fh($CC2JzP;Yy6L# z=szzDrdaX@G=cA<8Ld|Qd+9RT;93Sgz2g$NP`^7ptk=2h2fO(+8vbQrOn{8z61mHJ zIkz-1hyHZ-vGY6)CuU^}X21Vl?{9x#Qp~u2y%mL@6P^0Pm@F9ZSDIdfVCkYFmQFtA zz{T9Ud7ThvZ6j_z91G)y&l>;3(f;qYHbfoqkp1nfR$<`J1)PC*>j_;fSrYBEhyeK8 zbC#_`8y7El5^w+XL6{K8`*e&oCKyIV7a#1MOWmQtn(!b$q09AZ)YvPG=Ny3_*oz7t!L;N$Xf~7{iJe-ESBy5@RrTLu`uv_kBNu0(KG_ zJ6YUQy;h43*T{dGmkEgF9tR_idK_;1KiCXQKerlk(FO(m&ANDPp^80S&vVg?q5WYx z^z3jgFUWfu=G4dVQ?>og1;+lmI|(?Nr+0)IrDI01B7gU^|Fu`It@mP{G1g&Irhjee zBZF|`YYqH-noP_3bN~9czogK`JOgB=E1$m4|EFC2C{5sQES63@c46AXqTKS&o5|lj zTp~4$5ZnR)x&Ma9{9i_;YYsmquOwnFOk*U%0r+cXtEBW8< z?tk}BOJHn7iQiva#6P_%=5Rg^SBXaJv^X=wzv5m9+%A(~qjfiH*c=%wpFpGhUw8O- zSMd@@HQmKeCl~G&|I5%%5I_@5em`nYwDf!a3O0Xd+5g+G_!eOV%w(#P@Bj6ie?2Na z9xQ)dm$!TO-v$4_{4nub!C_Hc`Ty2t{@)u||4mrqvHZVB_?Pwnf2;7P&Hta35Q{S-+yzLVKfu=!wb!x_w%fT+*${hbCSou{Kty{}2Nb9q}N4xNJWH7wAS~^XeE{;4jHLYbL+w0(n zl@tq||8V*McCgVevry@Eut!QYu(Rp4SyH;PEBI#URXh7O2p-n$BVBve^^mvNTjN`+ zeik%@0~^Yzw}L5*yn)+yD@9y6_$#oGR28-NZQJN~}$Gl{@y zs*T+L2I6K{NlHz}O?=LKJ-yZft4<`~``f0om@jMZysj6$S3>;(aB!?8oHPhIlG;hz; zkz`kaiP?2DeeE3UHeFG~$2_$NWfgwHyIyj(d>q7-orDRS>@01c=#8g)Doiuw6aVUx zusbZhTH0T@`4KUXcFqQC@ui0~1vlP?=gpI?ZTi6{f8NO39SrHx3XwG6fgVq9Ms8P@8#1P zj`_f0x$nJQ&64#X{6h%1dz%(H7}Gk{yBslj{#3g0=|ML2Y^7=1onyE6Ok_`r2gCw# zGbLuR|Fm_1dkxY9@39{jI-r>1I7VSgs+~tkMu|0NIuA;-x%0w0kF^z-ei~bj$7GxS zVZ6*We7R56nT0qd-~Z9Jy;Lx-Mz`2MyTj_~n40`Z z^5M&xxU1n`zxb|KdT6Pc3yZ6nxS$h?pJtmW%Yh|4ic2d}FOb>4J$+kwyz}F|zll4J zwRy1l`T#QVUxW#x=J^b{A}m~m_3%?R z>bcY1*_Nr(rJFsBWhAEs2ieT!eAp_Q@rG`yxhEa^Igg&n(l8gcw(`2|tjV%!o@umj zUxCj~%Ei5BJtFLL@^ouwRt;O^VY%_QO%qbZU=>X&XslQul#gb^<3-LsLy4;JObk5Od;$M-}d2*~whCKT3JtyiCV9irnf$0O{ zFP*f6`$&sNK*K#;r3vL6=1GI|K+@x@8+9HV8%Hh{crEmaeCL}6hv6_43M$r+<1BStY!J49V^C?nv?C9~r!I*y9j-TGx z_mc8IpQl|iCS!cJf0q7et66_>$@ymYY-<=v6xVj8f)OoAGNY-O8ux6bqeIr?yVb{! zxbK#4+QK^|b6#nahaoY=51%>$0}9qqNw`S zk|bCSGthmKkmcD1B0Jm8d|Ql{>{p)K{Yxat{|Fo|Ud80444X~5se52{Rsn|*$5P;1Y zp;U*vS;Le-ZWmc#0bKz9_aG3-BUJD!A6DH0zmJ56$_wC|5)R_t8cP!=w zIwmP=_55i2t%=0I&Wh->N14|X>gH*))3omQeh4<0Es6orwB?%}cAi&Kkfy~l#((f0 zseTF+*InoF{m~}ip%2ryxX^omi9!7CFz+MWC?+V+VXv7!zGW>yP9HCs9w2Z++Lo^`u&#tj#4$tx40s1Pa$vN zvOjd~ojT|we^qm_=<&x?afkPIx=u6Ol=jVP4y1KXqqe(L;>v={>81vzECFw@vg@bg z&TzhXaVKz?%E?RSQqIL|f8?f%)?8)69L&`^`dpRL>|1(kpSLbuU$NaYm4qk+uwvUXye+;fbUT?1JVP zihFb7-?Vx9ws6|u&Oz?ySuH%&ju);zz}3I)>${rjmxO#g+qTVK*A0)u;p%ppbr%@1M6WtM4-AltSc+#@?VJIu-!d_ruJBK`62U1 zEuvP@-IB|J!E3wKWN{46@Vcb7unL#v9u8|RxQ3DFRBPs&=bq!~WmF*}D(_4siw@a$ z3bS8<{wv5dqOw{|C%(UQRbN5zDz8g^R773BVwRQe_S<(*g?ZOHg#~ObagKifSh1rh zy!9*Md+O9TTw#7wmCn;^t8ZnS2tbhKvikHzSZvw;Jq(D-;lvGkf35OqB2E&{7Y}x3 z#tdzUE-3fW4W{;VgJy-5a$BpPq3GfP8yb0kkM-i&_Pyuj@C&IRDvOT%@r`GKGDPge z^5SqoL?8LOzHC(#TgCPB?&qHj=N&WUve0O3c>WNs@ zcV>jE7Qs+xhGOBZhuhCLSj|?}S)0+o@Z6B^S9SpMkr<6F;-!NPVm+5bvrrJvWeAxD zN1PC7TRCCiEM~;|+2_Y&*z@ zCY!FWDqzu<5wY99sHXVY6jV)lWQ|eFnOW)(Z^A-O-3bgdZnbsW?z*DumXEm!ApKsd zWKrcge0jy{w=$z{QKvJ*DojD`+`l;ckKL< z#PUsu@9=G#S@};Y>RjfL&6jIKRs4kPUtaRCZZM{Y12(5bu#`p}rZr}{&dU#a{5G!D zk~&XO*<22-kyUnN?GhndvXaJiVhe9%sQCRbwX86Yiqc1d(O2 zoMb4|Z*Nv;3k1%drwX}k4g+L;gO|oJ&L|bzjZX{T869lO+n}8?tcNrS2F;#ZkXV6@-CqgN20;JS>qrTs2AB^tQ_2W$)$e4dUxd~_&+-zB3jRtStd<`*EZjOgf z297YM*}T9MY}Bwv)Ucx1s5K)lUmq!Y{qxP`#=BeYd*4|nJUKdJrVyPWsT?q>9snkL z9L>Dfe9%(b` zPY7Meo)(NY z;wsYY2lJ#)oJ?+=+>ED`s!Ou^;?TrZ#AA>V(vPc=#s6PZFmy6ooiP`L1o_3lqymH@W5 z9eHOhbc8zJY5hMR4C(RqP=v&`3GsE~U68yi)FJp-@2gD7{@R#9^QMeNsZoy*YLZAa zD0SeLMYv%(C(ib5W_mWZeJT$btTl^cWj$DE{~-HlHv}g_%4~2I9cl&Y#v~;=3_W74 z;(4mBO8Nk?ym!0nc)G<2G^vPr+*VkHK=)lMuNZ>=2!4~lgI@{PYn4h?%Z$lHF%#O( zJH9-#RGVshRF@-7YcQ?mBs4)L0_B(n{i z$!Q+DNJeg>YuZjX!V@)$uSxL_!kh2mlI{lwzO0=2(@V{L7;QJecJ|@z!cmqo0mK&PQ)3i8=GJ=VBuwa9h4^_;WUPo`hA^)#nWI zbWdM3wsttttUH_5z^YG%pSs^n8Sh`Fo*$MpxaB?S;%TZ8B#ODaI_AU9v>SmpNtX$& z`b1@bJ3OQ)z+1LaU1vL_(ZAHBqpp(<;5MBI{JEQD2g%yl_#yV|o5AqQrYqMid|5zi zxq7}dF(pIfTrD!xS4_wO-<=`Vcu1R%^G54{HzB*ia;yNg#(Xry?>G@A-qU94hJprUv zT}{GACYyJ;ivEtz`Ek-4?1s5$;z&PFT3xaG-KU0Uoy4!WO8DrwWO<@1J9_J!Zs`=n zZTavH34J9sbCJ2o3*3#dbY_`G#7!KM zl%|sesk%wKEK9M*G<=;foZ6%lp?O3-QDq0hQ!k#|k%lXzX*~k_rZ$7>2PYfzZSi0G zyTq{EaBceCB{2!NddS=?a~n~}s9k&pegeuQCv)dM4=j*`iVuQ4gImLIH+$G^+W4uK z(Vd_6Upv(7lo+{hlG^Y5obOZBD2Q=UKiK4{h?STc&h&OEud1+m8EdOSmod)aFW$+K zFDLlv2X_huD8;8kAZs)k9;M`Vz+Bsdd-MI-TJn~aFZPreA?>i#rU

>^sRbeofp}ebe{Pp8w;gApGTwf@md+V`j>R;yW&)0?$qb^9CN?Xl_Q zhYaO(7UP&rZ&qx#t(2QDEvEzTxbWz>&!DesfJx{&kb8bq#llUZXJ~h)^Rq!eL}=oR z12#8^$=Zp*8PaOpmlJQ#Z_d?mONQxY6hEol6B04sAOx#_3E|uh89gt54aZxxGoLih z*yF@=uZ7xO=&+V4(P=ksGL&g!49WF}Hu?(dn-omO0qPECgqd1U0`SUO@7E-}S?!WB zhmyu(!dvJoC@8*U!Ap85^DG}XFMFJbQ_)gp?mv0(ihF|lZsW?eO5Ix0*!=;w(Cmq3 zGXr;Yn$HJICtJB#AP383){^ap(B!(4Pf%qar@0(#- z$sR|L?umjC2DQUlCqHOWtMF%Cpf{tL>9r^(7JR?(TIWDzW3^Nx*I;t!( z6T4RWfyl`uEt)39nM_f%<9CH{B_wC}uVGx36KzHhRsqXr~U*^&2am z%d#_K;PbP$b84X?j>zs*aM^NXdP;9wJX;hTW@|AHYRsu}krN9h`|4f!lT}cS+S8J9 zYm|f>zkGaWyyhU&Z2p-N-EYld&@#xM>(V>lFOcQ!E7HL{A3vp1%Y8=7YWED|nqs!6 zXZ}aPluugk-+z_ZY2B-se8on3(3kis{QD#D^-(cve03`CzPhK_OppL7{T{qknek_q zwq)i=xe9pRmQ3VK?YCR4;)tJLSF6^SX(TEKnqG+8ICz$}hyb?+p)V5sW0&Dibd{SAB$2r}ywT=R zlq&kJRH9owOA!-uM+OKZ&tT<@LOAc5EZ-yD^N;_RTwh3fMMoC=QEAW^Z{-;<=5}5i zWqhw@e@K}GkXZ)4Sd!3Zwd!p z5`ARBhmWGLuXxvBp)U96ct{4vmyHz7*I5a=10AMMc?Wemm!^Yin%NmryF7~mDUL`k zzvXKC{{u>b^JjWFIO^$ zT=PDn{$ru=J8zVhau{vMAuqE35W2o#dTZY~5aYv9g21E~i+@w3a!sbCmfl0jSpWuXJo2Aw= zEn!98R1u;DG;|cZBE(h;x~2$M$9)0cgFdUN=JcKU*|P~4h+xY5&>YjTd<*_!ib05W zvK5=0T)x=AFY;?WQbjHD{qwo4QZM{C{}ZN6pE)Dc6fP#5S%c+!;nopVrWV!q`!xCt zl+ZO3Q5*Cbi)3f<578!am+tp7iWkx`ppdJ9(`C@v;= z`U4S^Z4y?&v2T2%6yH%(bB3!G-&njWc(6h)yQw>-k=L9@m_Zw-s2r!a(l~wLIomC) z0g#TlKY5WG+89~w5hGg0l}g$#J=W@LK>&)2 zZFTIo+#)P4RAkrSGf*u{;_=488y8MlzzR_P)2uy%y;WeLp9kebx4eGSqhA%D$gnJ* zDH);mx*n_c3?KF~*v4*WzT&I24`4Wt$a}rI6XLTpcvtT0G|5&Z)`VjDRzc$-OYKsG zi`b8GR@9_g=Fxl+Pr@tq&U7-d&OGH=c+p?JfLt;(r}V`{=7}dlUF}BuJ)O$wmko%U zA7eMS9AZj<)=!t>l8N{5ai~8sh8SZ$BK)fx@Or7{yJh%p#Y_UeUG6gP9>E5F)9tp* z>=!YxM%m*ZVv#>z0-N9KjaDtIC_eF+_tIrSS|4Thi32&U8^g!|-)dFJ^tgc41-qk9 zJms-nOoV!v!p`Jt_zZ}4pQJ`EY5eylk`Y#wI4?i8=ErU12uY7jWw|I~YB{JRD>VYR zPu%tvR@FXrXHkPA#6C&X4|?=m1 z=8mRqzJ&=OP^>kV90>~?6mpuYI zo6^k3RJhW?$8#TQ0)!$kN;7Ddnvu8ReGqncyYX*o5bf5&dD%?W*v=yel9l%bdn!dy#q*k;|_149G(Ib`oazOxFY{afD`*X`mQOd|KhH3-pa()eIV z-77kwH1D4q=9Anz&F)5|Npk$noTL?|g_dUurKRef1cZ+QI0N_tM$NtYl|smYNsfC% z8?cTA(#l%;9C2D}y_h(Y5N04XUY!GL%bqO)6(O+Ru z-EJC?>O^~9+pl#>Tp?{mmSjb8kJkI6c_`s~gT~Yv;bJSxdZTg{Nvh6v1$JIFc|DdS z!86zTkO;;$o`UXHFKyO>a4{YLpFzgF$+wfq^RksC56O9FNW6OW8G zo%p%bF`jsSD#+9a2&ak2M&9rX7$wIAlytp3zzp|a{TCSLcXXzFezKE`B2Sr#1Z_C< zlPI>Dt4HN_d^+?y^=-W`+7w2pauEF`>ErC&bbf!L0ZyuSZdaENj-2382IrBGkMBf2 zhnNhgl;thX0;!SM+*Js;45np17fAM8#?Eyr5D>ARWEo>t@AiD;woQn`fSQw%=4$XL z2?)qMUi3>+D?1&HgjqMOnhW086iTp3{_*wTvP%3%{cvQUI$nU_Cfzj;Vk(4ey=7I%876yk&^o zzCc4d-?;eM8{|g2p6gyrxnww*Qu2t2edZ3_)X+JFjscxFw+z7_qFg`S?Qz@OyuJV~ zGB5C@ueRC59~B4RA?vwuP|5xxoB z@d&2Lua9{D8lT=iM}57yiDf!~N@t!aaFohy`95&P`02T)+UTTb$@Hz&QfmC#?xOkCb|cH^R1Ycvq2Ol`G@S zMjGN`LsezbAZ4FD#cwZpK4>yI{+*|c{v4E>MPx_OYuf?=YPW-Z4dRenG94R>t zcbjRb00~(Lj$pd7v%m*B%W;!oLe%@hT7zk8(l5nH_z+0-Y)MkEi68>mMk!}SyJZmWsgfT zulA@&e=gE&-|m?>u>4-62qZsGb)kV>H#x?Nr`UbD>~B&wA?_X^o9aZNFKZ)!XeHPh z?XsvxQ#kOg--#>&a)^R+L`}yE3g4KO>eP(L0&ph_3Rx4|paKI* z-{X*i@cAfvbUvDWE#)}?tG~>=!ZilOvx>b#MBGfe8Zx|WxnuAiU0!oni_ge|GY)Yu>kGH+Id%ufMG9xl zb$p|Jk_MORbWU?Wh>0i){`LB%FuXkxOJf9B|0X~b4TmW#wy|HOCCn&YKSo~6iD95>OD3$ec$G5qm-!= zYJVcF--mng?I@EZPNR>_cTs(?iaL&;eIWX}U!RlHb0Oub-kp{+mQxbksfsy$61%J> zQ#T*4TRod%gojVv-n)5ni^kTQE@M&wEfgC@VzJHdO>w#Tjcs%gz`Y(6f+aqvgm_ zWD3^B4HbBD7f*XGD(LyuB@vX^;No7U!d-A(x641hZEkkXj02LVpL$JuQn0F)@a*3R*DWwom&H<9bcz8YIav0+ms#3zS) z59&hv;s^iFIL|Y$Tak>65sDo#X;}YpCrIfjynKwJm4IM{l8W)M!U}maA74p;d@82$ z$B*uC?pT298TV#fa;>F7NTFh{%3x-CZtuZfSp9rw+Bv4msCR;h&NE-@J%f-(+c z1#cqvbBWYgJ9#L^fjJCI=?uNSZVtjFjZ7EIhRyt!=kXLs043f!d>A1YTK=q#Z zt38&xG~Zz{T`8&AJc+*a+^6r7TTarL9)N=nG7JyOV_77M&AnM=%XBEpRLC4ZO2MD0jhnuirML*x z7AY7K0HlV_f8xpw>|v~)5j#9Eosp0hagaXX3W0$#9ebop64BzRON0Ak(`LKo2rrC6 zs)kxCL~EfGMk_C^#DEfHF8v{%Hv0aFSWv%*KW4!R*FWg7e*`)4`h7toh==E_t>E8dT}{l79)k(g zuSCvrs9p)?fYkgi{v8xw$EFJpCyU8@!xzo9xysgMdAr^}p6^3jRIRJmu2?{#SS_aq z87#b2e-8c-rK=WYe7N6i za9QPj${C>JVlx!esR0Kplr`SaMvdgONwo(Ag;Pv+N+u`xKrq_!%-02dAT_qMdth(v zQrEiPnG@Gm+_K{`@~a5B0kkDd6$dyPJiyoK?QidlW~Zh;ihl2z!5cClS+N`o>j1oJ zPIs|&R2VH!m*2fjZ})hEB}1s=!bgxwpr4V$ym>^#H4+??f-Avfbv+qtOs4M*ihfck zY*z3Rx5T8H$o2_=k&hC&N2_nNXc`svDyXSgzOx?k6?T*}#Kc3jta^*FStg1$J|hVL zKS*QKdnGMi5gVnr*d#>6;I7AA39+Q-r*!$=OS>%VFg()eYqhL|?iEA{FAj8hco5;L6Fy8r) zFO{r9Q~30qdv|(Sh0^KT_>!w}eQO_Ssic!>yf^b_5%oK$Cwz+Xj{<7iRuV-b7K zb2mH~>wZKicLF!(<6eK}Z=MZQrDagv2jFHMSyL^7)KHxouB;ULqZ?DDV42ad84eK2 z5gpYSmIFHhJSt#gVRj!jr^V>^P2y{9`k3gW+^uSfJaq^W>QGA7N3tz4;Q=0URL_FA znHwQ<=MzPxc9UGU9;&Sr8MH7amtQU$y_R{*lAJfM0G?iJL(+#>Lz9{b2BvZCnJ?V$ zc}41BM|rl76~%T9w7!IIVEm63z)JNA8%wcsE4r*D+UaC+Yxq?NWbJ!?bik<6SuCak zA`p&Qb95}6@&V*&+68NoDCjHIi6Uo94lf87rWbMcP+u5BjUwAQp;B4e`P# zu{b=@N6m!6gep~0PNl`dSV*bcBeebL56w~W(6-L9jvLNHLsB|uaL9L*kxVBWm6m0Y zjF_6tGjG;`NPWJ4q-0=hO+ot0K|&EyE#t5A4auH^#TEA2*P|ilKk}&x0Wbs(>C=d+ zm3e)cCiH1_TJGcaAiGJ()Jv<^$Xg?_ymYyVc3T!s-0Kt3y_-dko&cRju9aN_-Q}h8 z+v@0_VZ~T4%%cM$dY5qKfRYTsi^$ts=EO=yZl!kI;u9~+*BhNCO#_{nPb7>l$?{kV z#B%a;M=Q`@QQ*5T+7v%!XhPk6F7c0_V8okE8~CL-J|bt)o4E}xI*qE37Ng8Oa|4mk zfE`4cISmG^i?ppj?3)c{-@LOpY34l_2YF=QOUb&bOh-zNt91=G73UVYgST2J{z`%_f;i57BEYHcm6O(^&C%xLFoNu2Mc3foV_1T*6pRD?7aH>TsGgOqcX z`ev%lZb|K^r>Ht*7RSvS1O_qwjm$-$ixgeM5 zY9~Vyf16Y#EFYCJBL`sr>TYjZD92-R{yg+_+4`lKCrnA!1LlhIOIE^Pg#5a~e{g#U z8W{eYHNkQ}p$w~J6~AL&UYbXijnmGb6LD7aHMhTU{@t*{`An+(vM!vHa-2|!BKWS zDW?{wMTgn}Y;*xM$#>jYJ_p}ED8cM$i5t$lw(8V&uF>5jw(oLxHkGz%1-G;{g&Zs@ zRO*c`_!=q0So)KN@Y6lS?iGrSN%fCv4p^}-u-NmvNX3U0sm|Ss(yj64*k!O%)po2Z z%UD}eTGw9_BK*mBS?fJW*jp*|*2loLI=i{z-&CiOBI@L`Au>=A@)VOAD{{5&ik7Be(wW1bEf;CY%PUl@ ze3pT4F{$xulska0PA5hcuYAi;I+uVDusCt5kE!29M6Yz$$CAXpJFgjwIXaSgWkZUH z@-Z}Ux+JCUsU48w5ti4G8JbdAWtI8#n9X__i!qv6NaVrnYOlCIq>9*}S#VI;;8zFH zE-EQ^yPE5d#ULHa`}UYjxDSKLG5&%&R;?%hpt#`o=iKs2?rAH$W1Z14R;erLHEPnNt9T>c)TPq4aV0DdG~K6sDs~+A?y29`}pCeq{e`p zP9d23dv#JS`x(}EieYwGQsCSSXtWqZe>FPsqXj%+9`)W2Y`;|GcrYgz{-m>s-+=GA zwP_yc0mA7{5ZgR1$PdHKyXYT!>#U1fDFv~9{z`*bn}~sdf8cX3drs~JV%>Z;zCA_cj`Httqs@+5*4|v6@h@&~n#nH#%%vid>W&B5lC5&pF zprO}NEq{onZ8&1Rg>lcgrC$OFva&9g9-e>ai|$q@1edUXwJ!yL@=#Q%1gcuVjW|c; z5H*H)(`z*t;@{A-{!j%2K{yJ4aUBffXM!BAaJ6rFPMAGSM@zq;G=u`Nbt1a;2uzty zE10(}=SJxPCslOsZp5%pe3b9!&-s`x+qW!dBnGe^?|C+5fIfmYMTrb;CJ8bGFNE0{d#XgaTXhEs$4~edYLd3T^)_w;@Z$I(_9YE)Zp)vKjiX2MY>^L z!8#hV>2X3ITb3-EV_+qw`i{utc;$(f6ctgTenEF@sR`EmnIHt~wHTVrYz^4{uq77jR-WwpDM z7fLc}!3t$Y=e`*F3B=F-ALj@RXuN(5j?8^$`1G&TEZ=9Mk$U+!y;`XIDLjj1f_SMW zYyQi4$>OHt1tzif&qbFAKp+(r6|6l8B_}TwXS9FPVt3tadF(W{c#Uw3#bj z+8nw(NDlvtJB92LzfS{xNQ~k>cD{o$2VK+oa?4BH1@7~#5`f2uM%AS>iRFjmY!yr^ z0Ux<5o?DVdhk*;`jq67eLY??hEnyq!hlv$znM<%}{4pHZ6sjISuk5c1f`lDo1N+5{ zP)HtzN*e4Roei9;VOY!fg=cHJVEYy&WR@Jp?6LtkBVDVXF%xr3H%87Ms&rc8?=@pN zLdV1l-(J8TAuLaI`6eTZ@92Pj=~ZcxB*?AAwGQD$@iH9@7@Qn&++TN#N@fRUENxk>AWJJ65!^M; zU4l>5)T*ilo{8A6be#!0u*C%bl6on+#vVFCsfS7+`jhKxNC1MM zkl0Q0D@4Icx$|p{*OMt%}UHE}pH?{@VMZfcnn6@Ko>;jO^#X3#y><+?_0Pct#i_4mIf?T`4rB{p|h_@@y$}iF4ho_j`Odo>quXxmm3?}?s$Q=*r{V|3o%i>g^g&!5w)sZS!9VPsIPf5eu4-CmkSSLFdb&L6inlN}X5qmd?fPs#eprE4KN!a~b zzNY+fE>BsKqeaI?qslT@<;z2ND7WxHGP=qTsRqw)%Hp$1t4>QAwliHQFE=w2li)_N zNXE^J;JiZ@!(N0(iQ6PmU0?BE%{FS$BFvv>1(N|2AIpM| zDdrzF>&f)?55BlcnR;@?J~EIO_;Vl{B}{Bfb$mSfIhu+nm_HX&Y5GT#N{Hg(mDs{C ztTowU{A6@X|HR2Fz|dmjA&cf&pffsO@2E3+_w~QQCvvY5#CqEqvi($(%*+xQm}5Ft zGgQ+b*=o!tvlQla;n}pETuAAZ#$-B~>3Aq{I)V~;4X~Y zi~j9PCXUa$+zuilQ#H zt;uF|2?odAaxL+1RErNv((y9*@}wWOk}h@jta~~wJpaw$WD)Di+DNI#w~8gM<7JfW zFOjKA8hnKD>2HiuJjmH`K4&BC@YHkb?`W1XpgDLy8|F`)A(N^?Mk~0d%i^dXhHKr>AM}n=l-)o8K+%MPucNH&fz?XtUtj4@Xf-7R(IzI zGSfOP457HL-Wp1~RD^8HZjXo>r~5V%ro)F#j*8;qg+$l8li6>P4(5|DE2mk(xg@GV zeEH?I%XCMhF)#$t0*tlrA5SHvmQ4@fDDA5lI38|8eLzzYra#C|{qcVtWnh?~J zLmIoTq*<#tTF6!7leXJYB5wa_RfYlfCshW6G}$-Mn%OL~>`QSO8HMPWxFi8qfB}W% z7E_6ah-+igJD~g8YEvwIS`~`&>Th3;uJ?hA{(SP#NDOx-X}+v_ThkEuUed>Ky*ouf zkv(T;8@G&gdql4kkiOGHX#V8U!7|Y*E9?Hf*B;hR`_5rI1(nCGEY>bCE*u7Us29LU zfpU8QaZi;D8j}q^rp0Ezzv!%E}La*yw5m+f+!2+=tvDmMBYn8LPSZ*3@3_;OvRVoV_FV$x6 zE-6=OnV1-1DQP#MKL+Yl5$_bG-uuAT%_QdjEY?y@id7Cl$DqtLSYyjhnEzwxMFNwR z`OJ+el7)Etp`+c*n7fjef&daDQ-ON)$`@gw8kc=X7*B{3=v*usFXJZ{qpTg~e1;~! z*z)3a-==+}Pw59bJy$O^<({&E2a@wGWwyman$=*+r)=8PIqD@yQ3rLBiD+7)9qnCk z)imSti={b3slbi~7m!1b%v>~Brw|ny&;zm-Uu&bs1fGOC?f!1nX$+Xz&$r<*er~~s zfIXx(nJUTbHsR8Fw@7pqcKR_}QReg%wX4iE7DO=+YjK$^7(!)J_Cq>iFH| zJyvmoG>57a?f=K#S4DNz>Rv(ji^a($d}a zZcKQNa=iGizI9k!{MU}zGr!K6zAbSA`8dFNRc$_9SW4}DOd0dm8r)tW+gOcO9trZR z1WH^11#$wyQ^}m6R{bh%@v$goSU^k{xW>utJN0n%{$tAsKzdD1GJUMJLU2jUvD$>u zdT^URw;$|c!&*6))T#^A;XViIzAY}c5hW*>+7 zsiNE`InaU`;2_PNY2xkCn1o4&DrO~X0=bBjp%m|MEX*-K@c<#nbdAY?`Sww9gn7|cW@di=H9dOrQLl1gW6=I(1;8a+4y-C@SYn$$J5m1^{`QTcXUo_So7h& zSY1y`hzNE^xvF=2$cEP+I4y$COpz_iRidO+D|2|BoO_PB#=kjS_mUgh)2*or9l&bh z1>DxWmgGzW(Y~>&oVXwSRv4lfkQ@jV^_xPb%aR5)fz}(cdPTMG0$6_guMi4AZwuO_ z>w_|uGRbV0F76(OW?+6~-~wt4#92QKn_V0YWL#xorL}nO1ByklQ3CvCR@`ya5ue_S7Sv&K>NOX}`WU#2)dfcB_X7cir;=c^2U#^79?Bn-slzr;mc z=o50jUjeNzT3K5W=mCN}19LEwSB_d9iDd2$bJnR-#*Sa#zX~Yp;elkP{A)P3+ney3 z1lSuK{m~h{oaAeRWpd6#hO?DKW6IVOTl@;I{I5ZOHg!=H{;n8We@mU>2d?>`jMntw zMyIRN0%+g_qou-G`Rl7{3tk^u5egnOy?e){H<`=;_2g4Pa7f6?tVHH>?P`@wcc?hP z=J@rWCiXHi-hD2DCB0OqpK=E9HGF|$#_Fm*I zoOa7C7g(1>sHN-R`upDiU;z;)V{jM$&TS&@H(>u>W$^;7`C8E1^8_e z=+By#0QPp~ym6OZ>FFy$K5Xq2+IgM9aCDTeHbo0BW(KA(X>b(qult2NP9n(hD$La3B`a zNcuv_s@Q@*zC56LOm@r%SB^p~j3OH|6>8bssh~S^MwjvG0!@K6oXc#pAk=i&Q6Zu+ zVTw0()oE~tmlFgMXR|O0=w~D+III;8Vj2!c^o|pKcOOY;Sj+s&WK6ojI0PA{esb=v zmt~C(49LFUl@>ANEqL;`I848PM>cCiLvY6)ba#FYw^LI(#NRB9MS)~E zxYr2_DAIOal7MTaj+P&dBV}ij1m{*L|578svZm`txLSzBUtP(Dmh_#^@M`PWI^r14?}s%R#K&St z?R64J)mq;TN{dB@QY1>IKaZr<1_4}KIt-g-9GrMw<}OK-df3^)5F`e7J?15I+?M-p zPhVghf&zlZ^(pU_0B?O_edWpg-M`msc8(Zj+^IpS-3mcq!og??EN))a_`Jul7o$ZpiPB^MVitx8GL5(2s;Wi4lb_|I( zI+Q{%8Ihku>YI7i{I1}@*zWfjP}bzr6=Q)gQQ+8GAqU`wrzn-)+H^a1keZ8ci}{zG zp&!niv6V0Z4wFWbpq0=Jo^}YP0}W!tv6uMv z!iw7IzIf_I<4|4e?aLkx(p3IDt;m&OxtHyMFyU~fK{n3jB`ZnNOt!Iw^blh&bL_=i zR*Y8ktz1T#x+7iMm4_25D4=L3~tO<8=*L_RuF z#_^n0Koyp!RPkD8;M)Fr3coM%h|kgsuH1~LxihMTGaBe@Sl_hR|X`%%Y8~{eWF2p?8p-+ zljO@~k(yw>64==QF&2F4r%fqqZ^*7vVXD$djn(`x{K6?}4pX8@bU)2oObe~Jx@$AE;gOZaEqfsMiGwJFT8nm6P!m(G7pYrgYB_D{ zBS+D733q+cHG+k7i z2gC$1SUo42KgeIh;U5f#1uFO?+2OEDbyV6ne52v1Qozm(=t)71Vk^Sca1{y`eMsWp zHc3dDeId|92Ut7LZ5|0SE#HSOqhngk_r@_1=p5Ar^CMEFqV72+ux}+Mus*PZ?~6ID zM>I3nkpyaW1u9g{D&Kago@Gp+rCQUXa5R{retaIDlzX45U_)`oRK0{EvSY8>h*+62 zPJr&~wha{uhl{X<>U>;oKHkVdHE#T1{a(qu&M*r-!C};d>+^Mbc!vitp)~RIb`_O!_L^D(*U^*s zYDaY1-G_MD@5=~f!BgaG%^w5&HRI2EfIAY+d90jn!yv^Qyp;Q@yHjttUtij$$sQ^d z4M}`7T;*|6WNbUv0V-iUwzMFM1*NC@x%)Ijs-C!zY*zdOxRK==)(%!gU^@$zd_$Qj z*I8EzU^fdNu!y6mVC!)B6WaHq$&_H|ETC_v`+0jR3nc#53i#&^#+}0pvWwUN7Mjts z*R;$gGztFq(as<*GmlUf`{-ouL_hUs|??^Zwv5O;;2A>RCaQ1Pe3 zb%{oc-KA;{Zr?OLO`wKeVmlLM@Jl5T>GMvhj>p*Io(OV-rE>a6MB>#eOae^Hc3tYy zSAoULQzZE`&Aq*d!Ck3Fv1UpSIvR^%O=xF}GSynMCkFhw9=(MHg#%E=@)BI43*%06 z6*ACCtALc(RE!|Ok(6DH?_j||5q^~Cjx%38mf7)CS)cG^-@M~;gQ$@T;pinz>`|;$ zE*E4}Z)u)t9ux+ShQtHKUFLEHP-a+xwn`J}8sC$kv8hz+uhs z@jfhzwKmowH*w}#Gcv~)GfSY(=-b~k;p0eo#l36*Uwr&=Myhf0!xH7NjMwGcHzm~C zqWVqB8)G^lB;%EDn+-5^Y-whuds=~N5zCTg!#3Uyo83dn(Zy5+>I!R)stW~Wcv@{7 zUwaRI&DnLq?UvLqDKhNj>Q}Q&DvF6;|1`WVa45_L#)8PDYDBAOnGQ;;Yh=U|_u71`E@i02>7bl?i9 z06Qxb9Huyn0VN#mHO|0J6Dlniv;t_B>YCy)?SheAPZ~v+fYMS*@0qtDS=+JhEQ5;6 zJlo|hPmW*9Ma}w=i7gonQ}ShPaW~gF>+1wg=)c8I_+(2s3NKMy7(7J%bS-W8xk0kU z`Rn|B%bb2-UnvSrID=stUrVS|{UxF#U$>khz%ceu17~~rxM;_=H&2u!nHK1FhMpdm z+ek93CDk zh`H5QMVbMTV99_l9bCi>Y_2mD0?!D&C>8|;IVtI>^rE@Wu`9WX*|}n5Uem8JoJSvi zcJLLxX>3w%xaO7aK}p?1Izh=arnP|uK^_IPQ*$}x}GYUln&><;IQzZ3dj&4 z_kkQDkgEvm;T#=SA<8&yA2Wof=Q2ig_L`=NpD+mC>Y6Q(;Hm(&!gw&ntpI}yI8%E7 zbqox!qyDX3&W?q1r-~nWfrJENoRLq%l6562J2SDXV=2j-9e?_S2>76P{MaF#BuiNNemO&b3<`ZGC-fmukoc-ckOekGMNuaT zANyowgzlLu%Wz4aBw;|^RRwR>kDOY|@Y|E;WHdaY8QhDn2p#O&bZigOGFT-8_u7ZV z(ARvAx+a_?lcE&w9y_Ec(K8TgpjH+Xjl~b~afW~2QBC9&BuPSjL(vTb_snSV_%e4u zt+YHRiRYlVa_I%AmFHAd7_bLSm-6V_*YdkTg%!bsj(a(w6ZY8^5P)F?Y+bz7>ydJ6 zm(&f>0E=*^h_{sQNpKT&gr1$Tp`JW*E}p);`}>Ew%RpW5BoDJ^JL;hAxFnicWWUf3 z;)0$bZV=TgkW}b81)@%7ZTMq{CuYxewRPsmK2px>o44r0?>r_umwGsfsyhWwTR<#R ztM3P|*EjkFIn`dxbFMu;nwy^mWQKw0>Tu%SS(#DL%+E&9E`*5Iy@V3BXI z{2>Y?dSA$Gsc-osVl(UZQf7*!`wR`{PBkjTGe7MuHUhBuXeM>e!^- z2W!I#yX{`&$mq)Ud{|egEG2NjpwSfH_oj`8xqVi~9@=Qn^!2BVkBnQmiMoc*Sh-s6sYx2lG1%d2B_a z?lqjS^10Rb31GdII?~~OZTYw1f`7mWK{;#^%r>X>{t5kLi)Q06mfs6v@g|%qWVH!Lq zlVeMb^<7(EKjq22eO^)wy=iCz8X=;JO9l(->e8m?=HefZuL`C7!ev(@7?0p_ zCea0DhH=QHD{XZVhViPoc~swJ$+L&P*Kc`J!H81rwY-YEZZI({Mjl_u0UiVRDN$9t z-Mm}SNVYCMh^jVC=1@B#eF<>q4q=Q+t_0S3&ya9X+&!y25IuBkryWXC*WI!zz3-QQu=h;Ia%LxN~_tau>I$c{D>?Azu?rPpH;*r92 z5-6Y+Qc(hxrhJPZdS)a}!c&>Y&-f@X*e)Oummdu`g7~OU%nq{cp5QW@7M(iHA5PYw*OtFXJwAG9FhBT)H2g4tz}VTVl<>Z5 zO3XhT{!b=P1BPxPMlSr%bNJX!WPTGUWZ#2>iO>jvo9v$e53z~2+Xpr|cesWS*hVqK zVnB`iXlAO6|EWav*+azjGvUrO$k;?1wGc7;sWZoUy~&v10H!#u!S~U5#eo8!5Tr@N z8TWwAefoQVttF^h*|>C{=BD)T?`Ak0G6LH@;@GP(@_!isqH#e_iz;RifsXh#ipJ#N>&&!TaK?{tRev zh5G8+!IS1_LgiyJeqgtlufWad^fL=XG+F;CyR=j({vMn?Vk^{C0xS#}~|DoED33 zGNBceTc)bG-f4*n&<*;U5H1`&gwp&#HPyfwdOD>3Qd&Mmp8gUFu^pXPMClVB+-E?g zF@6#Y>!9j!bT?zGN#JTi>TV(lnWB~~FO^uD*tTDLT}pT;47ZKp?D}GlfP?keoof5j zLYFU2wtD)V^6I^w<9T)QU>e_>FT#IlhX(H!kS#MGZg%PNLDfCu=l4 z7pIAMGT#fJhy60`p4YRJB|?c~qenv|?}mcg8{iQ%{l1ML<@0(b7b z%MJ7icX-!>1E{{lr!IjhjL3Zd%1z%ee%K*F2UWNhP?_&bL%JmqeYbiBDefF^^gBlk zZLOPDjR_^b`oIJfM8sr}VSNgeP?3kjh$fyzOVK7&g5i{CFh?X-NAr2Ag)61mtuHIl zK2|Xy!%_-YMFcfrPiNBBTgA~W-el=HRTI^5nC)xCE=dy8$Q`wG?h8K#MKLt!K)d3o zjy?3X?7s{s`$x(J%KkZ0(VYF?+qTidmjcmo7!SK`<onYaSK-51+1p8C zv%Vczab?Q{&)1_pL0*=lc*?yMUz&~d?rwv~7utnKH$Mhtujc}&6aiM_wxBMS3+TN>#gvFL~1o2c85EER~!y})8 zHve8Neq3+!0?m_f52$z8(1z*#Ae)!iz`Yq9!%6M&95Kv`j}WMhwb&}jqQ_mv#Eubo zV`JT6yGlNB5tN^VQp4?;@ws&*%+xX7%uoofgrRUu$ClrV?>!^_%wy@@Ff^dNeNUUh z*Kpd3s8S*T;}Kj$^kj|8 zBo&3t69*qkt3riYD0Ouag|qy=t&!XQP(*V>qk13eM|&Hcj_I=*Z?}&s@#G9lIO$N$ z9K#4?Frz&y%rHBwghw;nj9WW+%z2`2c5fw*iE+kZHWRB+L^HXssw+UTUxoHQ&~?H2 zttGb#HbH%ynt!?Aw8KI-JH0YI)53R!msfaqc2DKINJcQ7j%G4|5%@yr;$q_>Tm>n1ImGJ5!nSi#738 zsIbCI1wLvtBr`fgM)+0!_%lwze_Kd5>SYT4`nCKI>|Vv9d?C> znnlwwsfWz;30(TzU1m1nAKMaTS-z%?A|<7FbyxR)3N%wnl^@*=2a`HbMyf^<_|DB( zPM|BkiNY5gzn|7m^^=ZzXTj464wQNKBeksgQE7=Z+Wndz_JIR*RmF0UBGPjv9IIw%Ej=9th4$NtO)IxG#5MnDf6l<%y^8#I0G`?In2|E9O_Ok8Ya+mmoX2$v{6TY};H9#$z{7g!+3Vz6bF-Kg#6# z;KA^De5DYxS;tP3Fm8+_#{PaF3L^s!|y!)p<^E1*|iQ} zP?6lNcl-|5Z@C#PVt_KZ-+=qwxcaZWO+A(j0y++uShL<@@!;wzF8TZLWAmdQ*~eK< ztVo@%m+yO42dJK!v$7U7-E6Igbq8|(FA@`P-E1ov7mMvE3x~#0p)yPDpAuyi{GY`` zgP?czPx+k59iv!tjNP8!fCxI=RYDeSt^9{Fy`gWv#T(c$@UYlUR`2N*LOMnfL-dx3 zcMjsMt`1VY{7$9y#2|~C80Y1SjONN?_ell7j>^IWd8GmG$}c?}Y{oJ?nvZ_ZC}!P#t8)&6z?qS{V#B zTRHH{_@FwM+_(NEcCx3i%cleqj%13^@9$nK$`MlmXYZ9!u|`}4x%Rc|Uj}}A(cL+o zVGGp}-pE0^@2-!uX{+Y&b!x6D5iS>1gy?T{#^0dbwfw%2Z{FT3aA3xyAG}`NLWuqn zAesMQ1-}wDv<_8kDEtOYJ)%1fY(xEiABumy`B?}5pBLkO)u(byH^}7%b+|}_O1)sm zRgIB8Y^47IR1A=nLmA5!c9mbSyjs!2D{#Jk>~@QFhn@<$2Xe=2+`pgGMe_>m>|}U} zm;RZll1O{jHhPJ7 z_oU7K65;U7&{fk-{Xd0~tAb#?vc9&5_jS>D1N1)vf#_jZgVxO%XvDNjl+Nq~6^CMk zQRM%}-oNx6fMB%>HKY%Jc#Rl;7bYl)s%HtP8|)RC>ap=BskmxW|)fJ^|@&wik~zC5gu(vx2T;;@jBi1Xn{6pm}RvU+fv1 zy)_5{uQUPlS=YP^Iu`7PqR5Nnmk1wfVH*}1Sk-va@u z1WSWGdG}*40Oi$f0_D|aoKB)PvP0q5=oM|0yPG5L7-?95zo^{!+!bR-){smN`RF&eYm|cSPv7DF=Gj7wb+dRg{suRMKa>)Z@Jb zJ%cWN+${l1zS1~$e1 zUR2&Hl+qG3-KS4H2Kwde^aparK8gT9coCNo`@NBn@Gc ziVs>NVURVUg@8H$3QUGaF45ZkbcE&Gyu^fDUn;5d>5wdXib-9Y==HG^$?idy?{tW( zN03$|KQH%-p|AH-k11HkFU=qV7FX=XZnn!HU)C7;*7e&gbW~jDqp{`7Hu+ZH3UMf6 zp#S#d_A5NQEo5cW`JA$;pV+$jgS{0Z zmj1l@F!Tw+7N-22rc!lG`I0;(U}_pzy=?=M!HndZy>>y)rB=k8+UY)CqPdzIY@ z)W;&{Gg9T5!^YdtU+B1j|9P3u+xx?4k1HGOq8^B?q)f;zVk}?bJqo;u;Qc#iHQvUJKLgEGvC0vvHEL`2T7@*T zh*O9D-O1hGuo8_=p}rE@$!dOJ?ZjZ!7wmUmub5@-IQ4s{vtg$<5CDk;I=h2%h!RO^7PT|sq(_sJ~$DuvFL8v!S4RBCmB*?ah z8KWv0hNc;5#d2)6EQ$2Wv&nq_B_;Wjip)KPvMgr-?z^QJ0rKA{+SLKPN#C^`cLa3V zQZ&OsZCRURnZT$uVQ;(N2rq-oNS2&`d}!fmC3%t|*RiF@FSP$Bxv_gbY(i@vYB%JU zKk=}ret{9O(JxxaB1ffYS+#Kg?E87!^Bh=l2H^&2c~G-f!S#qE?N$;5_oHHw%0g0Q zPQ^Ju|jG~Wh-?tRf5HxNrQ~)-9z-EiwPmf#G^}8FK@ScNx*MV zz#R86d@XInl<66N4Eg49$hXgGYibaRuN% z1zVE(3hrNYre5HFJvWQF8A`TJl8zQi0EGS-c9FAX^PewMh!(t@MkxV;&Hk02RueA&{DiASX-;UV1L%rg;Wo5!3H zg=|#Rh&`=Q1XGZpsF`t@wtwl3-W> zU7;U)(S;9y>n@*bRGloEOT-6CV+JfN(}vg$f2RsoP(8=8G~RgDsWvNSIwkT+8AU@u z9sR6j3gqiXz;)gFmC_ldu%=##5G3N!#j4Batn)+$@1ka8L4PCGKyufW&Eq{MJ0|bU zE1t}`nyelp=F0K%0btQIX^X?&`u?Mri6{3hQ^1YxX~TUxUj2)X>&mJd$E&NipF`X# z^<1G52|}sRT_P3w zXT^Mzb=f=b;TD&~zV!UBBY#Jim>^(Sl0DY^+vj`DfC-Tij9}lo%xj|o`PyC?LGJGu z|L=e*ehEydv)%GfM*Ge60;?zi#VsC^5a+p}Kdw#S-<a z2@7C13U70LCf-uF9mYm5!LCOd51!EV|6!1{{fA!V$z2YD=EjTh#3F+V*dO%*t{43CuoAM zz(2t0#^3;Hh;ad0f;(24^3Q9zK|olZSD_kuT@RtZlj5#8Ky-j)HrvPh-(UWNf?;@s z9M?#R_Ivp3JnIcR{O9f0h|8EnVi_5)rr0m|dSGEC8G^}W{#Iqb0s{#i_Haohz5@Jn z?!+nU0FAQuu=+o(N-TW<67moAZ-#TeE#6fGK0Si3mmgXU516*=0Ro>hFTas~-7zK3 z54^Z)0)TONbOTsFKt$o-Y7tz&r8ofc73*y>SjSUb^h+_%3<+? zq{GJA%z9^Sl#D2=#4_9N_=n&Nj}=x`*-v)7K>G^KSMH#8c6RZx)Y{!OWs_Fp!bMtL zjG8TPQOKpB@SM{4^|Ck$etwaH3iu#Ti&EY%MEnB6ykepX)i{cFY(ZlmFQ((@(e_+f zyR{CF=+%6=5xl^M^>a#wEA2NbmSU_XEk|ku_(vWjm^6UX$u<*Z~};4=~@;j6CDt4X}gr8Q)o1s{=Uq8o;PLNbPAfUIxaG zCtb0@`E=0WBRYNp;rfp+Pd{rpV?r}sT?2&gv?fFBbIu=8??>_g%!9OL4X(fOFBkaw zt+pUQiJ%LIC;dX(ucvzvLE<$A5C>j;b!!4$T{g=h#c23{&vgpP&#tC_mwW+An?^T23yX60H<<)hYR}!U~MlLcfXDN zFW>nw?3+gb>9pxSe)MC6>+cCa+8T_;SJV3%>Nmst%tRqOpqc+2Hm+&_`bk=teQtHh zt_@oOP-*xn(WC2MxDMxEK>fz-KG=W~MBXKY_<{3lWBu;Ed1U~v8);(y{O;xr%KbJ2 zLJt71Y9CVwf576uyccK>;Iblt1L&RnoizH7WhEkCi3rMoqgHHQcs9Vb#y_&Nx9@Cyb~((T>b5_;ESned5ZQ8P%{T5k*t#AAA+wjFIlnbw zT-g0VpEw*9Z0)TvEWojye_V@xny}lm)F7FmZobr=B@YaV@|z*II{Fsv^!%=W=Qimq z1NcAV5Dg4}{X#Sepj#^96>d!xU84op$AF$JeQhH0*DowyYn7VLDRMw@=`^I_grZ(h~R;?^WdE=1Xcm9~xP#zgPrGlp6OuFzmoMPgw5Wf%dUW;#cmwKIwGKM#*)eX?$mDgomKn? zV;>0pHOoc#nXRX-oy+G>Wjz&*>ZqA7nj{yR%KK7yJ=@0(9#8FgjCjIema9ZkIK7mp znXZhQ5@ls!inZOK6Xe%VVqPL}K8Q5gbcAtNIX{4z@rb!Z+;IL9M4|QZOMa_Sl?Rb0 z272j~T9MP7_dV+=bCvS)M+4IrPO>&oe9iF+4NngtZvTHvKbt)yn2td>60Ly9ygSEe}o9LUh6p~wNrYQJPOBHdJMbPlY|QD18#ZvgAFrlthf z@Uj}sGLuU;n1~Q(wYc-C64|4jCI3~~^E|pKR935x+hIGLY!>Y0^AFe{1S6j1gr?F} z3dn1w#cpLtQ1w>zHw#bJUNLx30z-z8LqTJt&Y|&TrRdQik*BA$Y}6-h$R(%KV3QBr z5fPoU1*=-;={?(f-46neEXqql+a5<)SMQU}tdYmXvZ9am5klvqh-?!Xq$QZYC|~PH z*z>Ni)9&Kecc*?Ihio-z>$$?Ya86niz%U!Q^K$q^sHJDl+3BKuE8cNR8AaB?XDp)D zO!??Tz(tjWjQ-p{Q!Q;Q(_CnNM^kM=oXv%Jgf?75_}-}m&&zeERn*1cI0Jebo#Z#R7V z^F&+{B zF&{Bgd0AC4a}XnL`p!=cvdipbM^+0u`Xl0LjFKJ4R3AYsyiwh5eEE3)Lbb69<7aKN z)B^R!tg@-h9-H@F^xC}|r8W)wbd#vij62lltoqw$M;7%T!jCkX8d+&d&fJ?mtT0}q zpMPAr>PdJJ!1aHx&k5b@1Du_NZL;?S+BCdHiN@6r>D(uk>m-qxtc1#o_M)3qE@ygX zqDFi0r8`z5y@tO~WmYk*9WT;((A7G%!m2PGA69KZ)m?4#7B$o_;fZx$NAy6u^XUP%w(mU$T>>9wOU?|E6m5 zq;l)Mk~K71n6jw-2+JiH+wnp+Y=RkbgmWmXDBb1yrfNc2O=>l!3QG(t+reqAbzO?a zPGx?}N|xs(NzKmQ(#ToqnKe#4EW&xM-G?_bBx(DOnJN{O&ez#A@ybU)CG`2d6vwIq zVY_I~W_4qm4TSL!#oX^((Ai&kjrnuSxOfi9e?K8zfuN#SWlY2bO zTAeZdR1R@!6#I)Hd#>@v#OsE*6YSmO_YTAwR(W&zPM4xO2QLG+1LvD`g_rQj9D%8AvC;qksMP#~i?{tA+1J7#Hd6TKJ7$HE| zs?q6m1H=EQ?LmVR=7r7Cl6g-==jFj+RfAvI#1pGArz(M(Y&sr4)W^?QH$R$DDfW*{ z+1E0BjH$yCLS}nLM4VS=y8YPk0LE^*&Z8$Rcq&*kVA2Zw!Ny@O#ljJJXh=Wn;ix)s zyFr1-{&5=mWyV(CX*C%Gi$T>sqUvRE=PB!scSp!*?(rmMV*w`HbA#d!c42n3*C9y} z$iC|AhM|Mo@jG`HaGUBW?x|6Y#vM+`>S|UQmO`|mU(9qk6&4(m(1Eu)@3aBCYOZ47 z8>6va^ug>iX=in*p!lCRB{_B&SDbgVo_2k*1>`tMS9a}~UYJIyz)YcE$?(gk4qsdj z!xM0297$KtgJ^xWp+<;U3&_vMK6TNK5(=>#Ae?_0RyLP7>Tge2m%NBrHU3hRurDI? z>aD0&mU3pu=q!m&Ufp)MK*^C*-5jeemnPe&oMVZsyI?mP$;Zl*e%O$s;42M%vn~lBj@HXI`ye9{CM*kO&9(mVSg8oY!oQpW^HeNCm9Tm!Q@w zg+#3GCz|0SnwMF!R&`kCo|~Ji;JFgsj2nN1I-t;5CD7X6S#xQFRWlyCUNRCbrAvUn zsbtc(fL*&%7#9vK7O~ONZoYt^;URftX?d+w`-^|&~sdqZ>9r&62J}-h4s`K>)im+L{uGl&Do~>#dkxE)I|vx=>lCl zc80kOx_+?Zj;0%(-eS9phZv$=_dVsxS4GA>J9E$Y7qZRk9Qlv5mT7`bU&a^|I}sJ= zN!Tp3puIV=s8kSL&y0-(+FsC_dp%Y|t2v&lj+qq+hjc}++AtrJvK%%%q*>LFF7F=G z2fEbFdk!&1UQtTZoizB89}u1FU!E~c9M*F>cJwm|hLh&3b=w|Pbd*9}m%f7tK-@&M zmGb(vUxK48jQwO;-1PHM-pg!gt+R5|A#S$~7^`k~@Ht{|!`&si%XZz%o%ev0wi?ao zS*1WCQ%2vYJj7f`u=po$%xu@B13Up@TUS2kCC?aP3**bQmH9Ssgq9J!Sb9~Cg(F|{ zCFxSdf`YNktmlKmmO==EdG|3osEns}(u$gQolaZz(O4ZnG%Q{!>6Dv4zQ$W^VJ@=% zi+Yui;lH=6SHSm3*O$$0q^#FR{P4qgEXgmmcX(9T81)8s%!94^S1n=$?ZerUh?TVI z$4z6G;NgXmI>dMN>3YCo2FJ8BdqnDXYZx8BQ6Sm5rGSLFeJU8>D5eB;K;yl-6Y4Y$* zT6{c4yv@q8$su49wk9}a_D?iOyj^lU?WfrNC`qC@gy!~UDqXnWhzYs50J2qAZ3tl$ zk#z0Uq7Zjjqh>30At7~pZk6pgZ*;01`MzQR>JZ%r^Zdxn@hm5SNlIRHc;%Y?@S!2S z4dcpf51P)$*RAnH1t36G;^p`Un#p0`&w7UGJiB~HUB23eKXP}C?Ey1uuPZ@IQoe3Ww@H{o_ ziK8R0F4hrexRX8oLE?j0+*mtdOA(I9P`hFPO93-~et2I>0Gm9KGT#14pMa`f%IH+a z`&FY{iG82Gy~x%0^0m*IsXdBzqZ%nt4T@IdcuE>K0-247>6b6}RO#}riK^?k#Oh^q z-5*w}64f4=wh&A>-|H53KDC!CwlS?tPg-9!Dz~k-qnj{O{IV>6@vdxtL`l28QvS&& zrz*on&*?gqR9~c}Zm4Afujae@*#|xy+ee_K4=|mI3lpXQucW#kVfwxZq|k_P>F%pX ztqMIv`1*cNYR)SDajx9(z^!&#J>sf<@WifMq83mW83qJs@^%D{kfl>P=ldKdVdc)p ztA1{A{YytJXgQcI{wR_}RVUh){a&h9^fO)Yq0w^g;=MS$b3|ko5Hv)&*&WDUSa<~#Jb{9Pdx*5wv6~{%V z-uF0BTLEU`hDk46s|V(#n#`m|a$0fRO-s#KmXc<;ji% zI`Z0NBepP~3_n1YbE4!*?u~6oD@rGyOk(Ciu_f$RU1`VSG=f+PL!Jb#mN@IkSoGZN zqP<)Tsh`q1`c8JS>>7MOx%Mfs793~7YHB&OQY98;o?r4@CO1Q46T1swLV4=A5wP~ zwpAnnKUQ?<@T_U%t+Mk#&dd>c?2{*eHe%gJo%Hr*B#5)pVyIXiU5Y0!LqV`-Jv}D( z+#^9Bi7n=_*&psiNJcfRQ?5D1bf8B+jtb#)Nd3~T!bsxqrLD)E?Q-8^tHIZtB#jL4 zrO&p~>LA(5Pqf1d4a=qq3*!u`Poxz+DAmK+T-ONd&MfJ7tBpM)BatG?FIMg$z45Jc zmNpY;Tn&2e<7N;(;Cfn@CHgTfetX|!LDUKEN?PPwEccrw%fxzGGz>H9=b%j0wr)6f z`!dPf9j<1Je0Xp$UDneFoIQo;bhfMCFi@l-;_}v+T&-|vbV&vIVso+X%^{|pQ2B2B zDe;oSmg8owL91V$NNCkq~IlZaryxu;9TxEv4N@eHX!KD9^EVP{%3A$qJeUG%Qi zHSvfghL?XvHY7;pDLjE6>`(5o+5sN==H(ad1+F6ci^w+G{XuFDS=o`mgy*zk zXGKfQXd?8Qc9XPh2Okdi`H|7mbCN=PPRKeILl5cXjN`U^q-BW+ zhEfqGDyynas-2!QFyK$r9LCv)g-ol-3vrwpEqg0$Yw!1mY^bpn7;r}fQTfanh7SN9 zzr4VgD#i)N&2vqU$n3`m^($nO&`jk$`V1kJ^7aJhkfr|SPW(jgPciM@y`-u2r^R<{ z(VQp`YkYn0Vdr=|=I$an*fxRu)b?~`K4ubJeXS*n%u(Ppoh=;JAa8yZ1D{1y;+b(cx zL{q6#@1jIEKf+esm3quNexFvND8%sDwxMKw#&?iUv8T5l&z5mZO@Tq zl^wAa-IS01Gs`CW7n8OQ`+8`7bgy>J>Ep4z{3%BLLnei|kEI<=;4|YY=RNtm2c0TO zjG0wc2Ek4x#{FWOYdw5Av-AhnvKMf+}ws~>=2 z=YMq-@LLi|K)ecoL_ZlfEV3+LL(}$@HLS2*I3h+MkSQHNo0Cz_C`1dfRjYas5j^x& zOp4N~q47T1aoyTqP8(#7A5`qK6zcbFS18J@#0Bj0yN#$>d9<%2nQ9k@X6%t-G5lH2 z8t($(qb`~b=+o+TGF8AAJ{|NeXu*BgS!Ziy)0L$n%}}~Re14^#po^nK`o6SIpYqV} zaXxT&WqmqsTxLjrnLW@D$_bN8KQsow>g>q0q!KNk6yN+}zR=h`AUqzY+-zkxj#agF z#7H*!)V$#tlX1ecXU47cxs^v}CWE{%5D53b*!%TMUO+RLTyCi##iP-V>bN->5?<$> zdUg=M^G&V0aXGR7vX791>j#&YMjVYt_A(^Ta#?Z3!vOy4g?C-Kq$M~Fvt0J(@>QgQ zkIN3McRXZ!^u%$teJ6`o*10(o2(HmV#uyg%L6n5C64egxZdy+w#K*G`yhUNbZ<2K~ zDmf7vnF=Ij(&j>= zt7sDpQ@9nSk11WFF5qdDulrYZ5qpE8Jd+m)noaPBO}>2UweuPd3Z7Rp;vNDIW=?(IU%@Qnkecy zKDWY{V&a}gM`TpYnZHDh$o+&+g46G%wO1gbddzq60dGL$`SobU6^T`oVkLDET=kw* zJW9W?9@MBS4DSu^w58DjZdz0WUbX)v*grpjUz}S1r4&8v#qVRt|G2&eV?N$nqnOi2 za!*Z7Q-RX<&hvbm=SsTLkdaPJ^6a`n1t|=Kf_tk6uSr0Z3#qmCui}a#5Ab8ueFX^*(=jHzcc{DC3l6(y=*# z!tjI5u09=2)I0RCrTAYhUtohsSK+@YJDT^RakJL@cI^JZ@?U9yW?qiRuE`G9)YSO$ zYUzA0eIR+(J2XV|-ok2!NnoE*m!3%UAm^6`&>-%O(_Q^@L&kLl@-?#obrqe46`;8e zx$BGnw;S3f1DLL*wF*B|_dhWAhnHOM1G!8ZuvFCRaQHv=zA`Mz?EPO^uoY0SNF}60 zQfjb38YQK>yBk>r6a^HdBnFo5ZU#_FKtj3(q?sXx8U_Xie$ODe>+W}7{9paAefM0< z!+FlR>)hv#&-u$Nj`)gtKtP^ZRWtL50sF@^sPIc5xq9=}vwt1&&jZpFp_$o-wKxAX z8(>wj_W|>H@j>dpu3PQLmX-7<%^q3Q-w@{~P1<7tB{&r)|F1I&W&la`XVdNfEzgXw zMPV;x)BZ-O{=ymIB7mfM$Zo#B{Bl%(jx3K8TcviNuKRyb@<5g-RRNOrqfL&bkB*G@ z7joSMk}f@zA5H%0oueOrp9zrE%)Ri>#^^5t@Bh<(YVf~E`=1&di0|J${HF#-^^0-` z2eN^GA9q)D0CwuY=8ui(DBIS!#NJ})^C8*CyPMc!g4ZJoOZ$iKKPEzuysd*n5u)L zW40=Sv|)FS!i;~aB2`keu1me9;WWB(ah36V=1FRWgSC8Ol|@l#eHw|rdg#hvR|Dir zC8Iq&ppg$clckr+T?{=RJ(76=G<(bM@bE#vW_M<$%DB+}}!$(K!0hE=oyz;=;!iMRg6v z=doqd;QF7e_0m4qgn@ypzH4& z0J{N%CL9Zb?f=uRLL{Ay;&q=|P>xZoB+0RdlD+*x&Sc-f2KFw%lCQKNm&NyLcNK@|>6y4EDOA_tt$5>p8y&W}yBhA%U7@Q7_}pq`J+kVQW4)&dBw! z5cRSQX{7eCObMkd0if4-5l^&#LC#&uRGeobEpBa$W1QpHB2CntcEceJ}k2U zn+bx$XzOpN5_C-?G}v$7RRgPS@J{y2PN5 zO{IMp(2)UGk9Psbd3!J?BE=sGFpj`8akK5j_&KxfVS~y`SECM!zIUZ_o(5nsWU9vK zxRf1?C@i{**D~w!u(!14B6ktt;7tqu)??>uuQdX|T#y6Vjbqb06n>!3LCCd-r}u)o zx>5*^M(Wx7*+hd3#r?19Irp#x_NGh)oUYCFFv!0<81ae!c)^%W%H_})#3+8>a;UbN zC&0YED6%gp>DctOZ~^i6KT*c=cf3wM0v(b+9*7+SnzeRpjMzeex+=4oJjd9!FHL|Q z%*DAQ4MGS)Zf%Jwp2(f=6IGlyJ+5wf*h+FpF8Q%>4|y!ya9%Q!JF`5!c+>RxLoC$B zb5#8CtlL+SYF4}c5|fYve*Ed-$ytHQVVC#^O3JJXA6pDk18p?>3$p$sYRZ7**H?c! z#elRo&~ zCVv%axlyA?$d@$#tae)og{NTXa67~u{CijH0lbG<+SlXwHWQM-G+SxES^XW;V(>y~ zqArHpaoeLe>}w*~k>kZZnLj9xuH?*w3Q&P$E9ib|w}g9jjaVE|WAA|o+Zt#+^^E#|&t>;>Ukd@dpe6(UeAJx(!<=Gy zvHLzp*zKb=mVXkGqr4K%!dCCQpfAMy!%Ihhssnrh#i&xEv%jLoFBWCP44CTPPQ%4t z{PrtFpbG#NJoYW|$*+DqI`h3ry~lRKmBt9Y{9AE8K9I0A_CRCE@^}wS|^|^AxJjoV9DYSu*a@a7w6| zaL)z`=ig*K^r$x9)cD~dlT~Py{i@R zVwQ#i@91!U*0z7?N&FA1c5H6{Uwy)yvAw&9ii7QthIN;%=G8Mch%W9f+Q?hjl9BIw z!|SspLZs|2WZ0NVJ5CnGIYG$p`)NHppBJ8-uy@W^Y4+(PY>KO|Ht=_wbWxyC{=D*fxveXxP?k4i}AiDdC`Q9C2WC0S^YP&JVV(zrj!H zzWP1Pp916&sU~W$=W_#q15<5a&*^Uw9QZ<`udY~R5xzD{5lzf#6WVku{rHVL0t+^ZCA3xo-WZoy1@{e@wVlgO7Ct}b3Z)0|(}YAd@?qsv zv(Y|#qG{U^JJfTWCzcN5Dc2vx_HfzuRyeO%pwhnIpCH{62NhZZO)|wYc8GdvjY{^7 zOog7jT;d$6USGT@`C9;OVz1z-f$YXI-tH58ai_l=pSRQxeey?s817}4vkLcx{qXQk z!k(OdEH8T>m-s$?9Nq08+($AdDYu^y-+wCmbmuDWhf5v&zf+$1Fnr(Ta?sHB2$OSU zaU`Rwqa~uqjRHK5bgtTHm9VhcERUEXm|5^;Z6PeB+g}dunG62H_TbV2O{S|O;^ZJy z`>P-H`)m=yOCmn!?QEc~5M8YZ88OsmnNbkl$x$M|vrFhVxT_SOQgUDIrvi-bc)=+u z3*?~PhfxG!O`LAbO!J0@R!>w6>#bzIOba-_vS6x1^m{s{epeIvVV6u9@7Q`E89cPWeRLu=h+-7K);^$D8^{MT1IV2^~{JWA}isy!Jwy<_(4}VxVmL4EA zmwx`)1JeCNpalC<<{jXujvSEpKM<0CerW#)9Hl?y_2V8Ulm77wUOj*i_PCg*i5xET zAHQHE4iHVM-|Y8;o$8;R7~xrLmI1=8K(%kA53KdCA2<^MnNBj}K9(K$hc(0^0l_HL zh)g5=^>}}g;!n>2$&=%bjQuIA|MS1vU9e%*Y^mrT?f;gff&fV~ zdy`D|{pWwC=n1bRZ1v8^7Fuk@-(QyZi@y}a03_`(mE-#R9Kf+*gypbBY)uANIR7Vc zei{Z98Gxj-g{e3HWku9~YVZ#N{qv{))ZjoQ<*wDeBxOj3w8ZiC+7F!(4i zHn1NbO;Ly?M$4n`7Zw%G9*X}3Fd+4#`KUi5cWJ%GUE^CU*PdrCI)R|f!J)nh0va;=q5kaQUw-ZY#JE`{ zYd%((mg11Kyh&P;OU5B(Wqzam(;8>6mF*?4BK{g(83E$q7$Ns|_F5aT>u8tJJO%b|?|SsRnoK&$je-Qdg^7@fWPQQ#@4Q<`GMR8bS&4 zqJAIoP0y~Pmjr9v%QTFWJwxF((lnZ`xuw?UvJ&V`NLIL0IqHrtpv-`3GPR7N@?s7x zU-oPE&7Lc9?{k=KsY!WC<$BSx0g5`05?qwMe$Pg)Waf9U4~l6eOC#GcZwW8RQA_@^ zzO`aP_iOheOYd)A_(Djb@HNJOXvPwpmdwXe@B>FXmF5~g zLc=9>5f*4kF0|^U;8IrLR#8@^DDPv2~v)(+CHM3Nvyzp`-Lal6J)z*W!l@FGZ^Tnol%?ZQ8??x*ru(i&nTmQ~#Ib!-1 z1-ZR)U@sq#x%4veidzVi2YIq>J|rs_>ef0;Y%25+re0+18xiRU_wE)p7B>x)wyOcplijOo)x9Jj6H}G)y;30)&TgkZ?K7issHG%^Rrs z#p;Ln(_}WVYu7G?J2|Zn68E+~E%In5rM`4vdI*f@PEs9rI{_lP>}El?Uc>T}t}{^> zE&9g=xPN$jRXhntB`@I_o!zUttLi16yAwH`I|?xyoL z!<+LIJ2zR%(Gp0i!&3jRilxw1`kFgJCV3&rj%0 zob~5XzLNo7)y|V(kFeeZ`YF!sc+7mT>NIx@m8lbIwN8#A<{ojv_~jvAHa$Ahtj?JL zm}wugtH)XtwAS%@R4@-m^FUENTVAhURG+}x-YRZxcC;v2_@rI?ns5?R!IK2RIIK51 zSEbT9gpn1U_a!fpsmn!WSLpQF1YfKP>4jdew4eEq2ooB|+W`zOfhgUZP7D1o<%Rw# zwE3EBpM7$h&(g?H`Ixe#)n*^s)R)!6VUTSh7U3PHv8@T)@}%&*8?{po@`XBVyVW6K zt+b7&zp$6Guy~eD*qk+|e}~1zupw$sZX%R>T5}tqm_pRlO0#BP<)BkCZIvF;<{gm0 zxFJxU5skZJ7(B5B+M4WGtZQ>m8+6S(t$SBhM!#VeKqaWmX>+`E9%y_wfE7(^IOVQ3 zp9Bxtbegf>2c`U8vj>chJ-PW@W}7s6$mRQ&N}dW_7KqK->NAq;Drt>62h~>1pr^fg zat`$q-f+F5Isc`H!5`J$Je){0Je<#dt)Qr8QWGO@!ivh9rpN0`pq292 z7j8CorTNMTu(=`lH+`FT5ETT$(=IBZ%4TM-HDNYw5L7Z?zRwV(lncj<+<}wNu?fbi z``;{-A=Z4ky_Sw1^o79`nrGE#ECrBra`Oe4BH}kF83Cl^>$YayezSNagC8tQ4HJ9r z_AXT7PdE9dc=gBli`}HZ9~{?#(2WMpohWqYVi!l7PuMm}e1kAd6BD@jEx#>nEzG_5 z+2{-F@~}32o(0dvQ3BEPuRBi)MXP}T%Z^3bSscaBxXe9hgvseN1QCn)!?(do)-Exo zmL-MqL*d_TeJ$sZ-F_1vR`0R*&xjgg1O&DxIujqB{|2(0A@vkCF7N3ByP^B7I$$71 zsN9oNh6Ce_{N7mCV3p7|L(>)G&jy>|_|j!;8P@8)AV+~ul96w)QN}ypwgeJl6nk~< zR;c4lG3xwVrUI=EH)OqV)R>*0FPZx@9lm_|p=&|-g+0%03*moAZ1y`{Q`6ekd*o}a zo%J-n46+t@O;hpH7xox6qtAHaZv>$l;WeL6llvhWC=4JJZQig>!&e(q(RVURwroa& zRn0Fu3|S0Xj0A>PtZr6qWfFb<<2>uf^@TxQ&S{OsO)CTjKeRO)^*!(vnNYq|T_Lov z+mn3Ta$WWAgZ_C(Og<-E(M^=6UkjSk)>}z5w)(MK!t5;oz>+|7ON^miw7$x!#H(rJld7^L6kn)LQo9igbnbD{G2o4CjP7WO>0XS?GBZ2Y$mSBeAw!%yX}Z85Brn-a;N*V;R~AuLfui8 zPpDQ?b>yLiN}gzim-97x`lry-G^+Jlie& zFO8=C169%+W3R7xsEIGrtAE@W`A9EU!|XUDhel6&dtOK;^K?=+_MW_}RFQx058X#! zrN6J(1!dT@(l^k)d4P~S9X?FZyxz#_5xw9eKBInKn19Z8cphmog%GCnp+5CAMBpQ?XqinK-?L z=vH!-G%8bHNC`2PBPBt zTH%J1g*#s)b{MY_2TzOGb#c>epKE4Tl{R{dSBv7NB}i&sVXgdV;WHWL?&!?l=C7cr zCZy)MVxD*#(MXLmwQ)h85Woe%!N9`wOa=P@34&rJs5?7tTPRZ|#GT`Tv0aAbvVy8LTU3ALooU2^M$Eq~dg$ibFpZE3eQBSWJ0sDXE4H3CGXa!v!x2T#OCfBW8E+c8`t@CHh zF3;5gK{tAVg-P;^x-%bvP0^x9`QIyRbh+=j!!$rI7e2c@1VScHD^Ta_ zH^;bUm3}#`^t{xKj@FReYKD-j?ixr9vM3YwDl$Fk^E>a0Q-XA-gUu$0+W^NPPt8p7 zX8QEyV7d{v+319C>ruIl;AE9BxT&V6t;4^rJo5CWyAIu^Jp0<{jMByWC*U-+f3sy(kB5SWd-(MYtzqwiDd##lgi!bG z^GX3Hpo3MK9c9SE0I@fs(RL~udAyg0_)P6VE?FM35sjw~0yS7C;eqO(oP?CHYUgC| z`*)v^20>2TxlwG$r52t`<%qn8un*l73AHe?P8j7lp7puUyfo7dJ)1_#dZXSo=8c>I zo>C&bo4r*#a%G@^wAC68kE_xGW9=OtYo5{LRW}wYrYjeh8M8w#ft?2W#g_X-CE~x- z!6X`Xe)JI}Gc!mi?6^UPNWhq;2>WCkItoAH+!l}R54@=Ns=QT5PfBgaY3a{-H_|Aa^}CGP?9}a zIdM%{2a_kUh4+#-ZSgmJp{P~YY$ku{sF)GsO>53o^b?$vejAF@Kd@#Bx_H2;n4!H)OkUhM>>MLP`?@B8#eUwLQ_7_Z} zFAFRW>#T4q8@AXL7c9uksah62HNN?c_x3|Ioj;V3s~?xvX~HzglqP9BwD{lC;3r=U zrp{Tv-=iv*^zp%KF(vG_{FoQ;=zE^sRan!CdcaNlCbJZs)?YIU*V8Mr+xW4m$l#w7 zv@l(mm4#{rZ`!R}1kr`ESo3wUn(Z_K&UU4exXac;F^Z%^uP8ifeMK&il_o!t-5k>2 z5cIS*=@mR71pvdiL(id6JTazQliILD`3;DSz>2UQNiB*s;BLtddAUz>RwawuUE@eN z;l*^pQ!CSe71deHu2@q^y|m^am>xB>#$h{$%1{?!^X{vL|J#xf)uPO}G`5|gj8B@WSPz@O?LY>j;p`M`Drq~eh6`o%aXk7DZ_kY$3J-cfuu}t z?fB9)&9!Yfi}uh$`KnWdhio9H^r1I?UGbz`z$L~i-y;c`_SZPpj}qpLv2RK&=yQ^KLxthCYRmUKu6izDqD<VJoLdWK^Ujo5aJ`4GUu=kf*aTH|BHr#F$kT9r)`G^w8;qcE%5Uo~q2u;#mOe0&4(3 z=l3r<_CiI&b9(7;cxDlNvj%6SO-U$<>};HyRgVa1qUloZ+faN>2PCMe^K3o7O~A(R z=fqU0=4%(MsQ3p|qFko4!xRGQ*M8Il*VF`4Fosn^?-Vmxq712IlFi2YXDuskSU^_5 zld?KCgM~b;F(RA+KA|k#au?NIYcgS}9ee@ep{V7F&bE&td=kwV`Jj}(&eeC;3HiM6 zep%K?ixP{LKsC4Ae#FFYVt0Ssn2w_8Alx>gr*1=03R&hXC9o?=KZ+#JY%AmYo?&V* zPf^>NQO1oWun75%K(B79QYrGaLIiN51Xy@@R zIIn6iyIos;eMh{fTqY#CNKhy{{ypMKApc~B)xt*A+sBUOGpFsF$0!dsMeS=Tq|MHK zHH63Viawe@3VRI$=ZNA`1TUbTz3j-tuGCVg$W8TIOPeLk|;d7}>y8VoqIcmd!*X^7om@1W9^fSt*;I{%6Ls&rD zFxD^68$Xs?Pn4pV^6iwF#J;F`^y`avt~l_(RbvqM-)RHnM=D!+ZD1qZDg*8qq~kDn zRc&~dkc^7KFG@()rOv~Wzq{8U**23LlIe1;qhP2{aml@nWk&)|F3Kbs28UI2j9X*s zNi6jp9~R^Twu6$@tD;J#w!|k*h8WC61UQxcz$qntvb<{`yD1(&c)I+(sKC>_VfVDY zHRX%5ObyqVB43G?6NGkt#vt175Jb<#b>@rU6_xD zEQ9u8Dl;}0n*>&LeSMGw1~l&!fzwJ0J@HfdKpaKuJQKsFu2cn421gzhMEvM@q$Mc} zWO-ouO=76Bz+6>B)+FY$1yRt`i$W`Jm}_9uTWRuLRAP6BG5A8HLOD%-iG(qEXU*AT z9tWkepU#_rabodoN6SpT8M7d9L`@1}4+i5#hKmcLqZRE|0y8zyvh%>@pH?M6WK4W| zT#!AEnYISXIjby?i!|5(*w^en-qJJyh8z2han(SWx&mJ%Nb#t!n&q^98ud|Kp!3B5 z4$5|wZ9*!7V#}XElvXlKVC1Fpl-9V|xQdk*UPsH~0Ey+t;@Mnwn~B#1 zJ41<7ZV6|@3k7EVpErJj6~+fW#dOdB!Ff?jNl_N(+03S@$c|Zu5q)2Rs=Q`kKfQ7Z zJ^X$0;YtgKjB~k5{6MmcNmX#LXy88e_MWTN|0!Z3VDh zE9zgVVp5b5LJIaf2J*}2dEA+ou4$J^^k|yR-EL&nWx9+#<#(i*v43Dz_i!Gic<6Z6 z9DP6a{Sn;QdTi)Qx6t=!(~i*zudJ+rRlDzrN*}oq=;^929BqPN@=Jr}962x%-ILDz<{@IjZ`nnX!zt~$?Ri4R zp*q1A#RpZ*wp#fX62z>q$Bl44WHjOM*it5(4Qj;X*pvQTTxvFBdMyG3Ckmtg}KIJ@pL(b#T7Ki%m z^0V&3e%wao1-F$}RTg+iFN5f5Ch&~GxIYi0Xkw(}aLknfjmGs_{MXYlrdbx^cGv{+ zZ&$u~aAZr67>D&7Y7f|@i#?dmy;L$uY?^-Qm~ofbibk4oL>rA{H&muMjtch zOACcA)^N0*#lln9r5amSkPsyt^^MjaF0@m&EmWwPcN|eI8yn+Q z>D+epsWM0+@sDRS&-+{^_^}-|S`n?oWJ?n-SNHw%*kw`UNOoNj=Yd*Y=u^@NW|l}A zszNgR4&%gE#iw^T?g8jB`J2BfX(|q(w3bkc+ zFAdp7dhgp))^};yqZ(DGNUy{j~B9KxuJKnbv4=vh|47V&K7CdeeiCMM+pKuXQCsA$NQn) z<&g%49ii*xUmp+`zmsZmpGP{1gu7y~Ok0sfau}2(Q*!d;sHov4(@u=OOW8MTAQ^Pw zNi6xu9UaPt-N}A!X^vG4mVi^KkoW`(lJ_MUA$IHlb_Izoqdb+GUMpwKv zVr2}b3&9%#J`6xn3U5N!A ztZKp6V5B=4%w;w)PXtm^@to&s5__Vg?x^duIqw)WsKblhrSFYeHr6%x;8$8sT8;dM zA9~wAzChh|eC}1z+*fKY`9#gIZ=jJm!u&CR_6Um{2~sIWTJAN@yFC)DJC-?tDX{I0 zU`Njy`yK{&eM=yMy;%b|{Nx%=OOqX=gNVv(H$DU^R?RAp{k>DirqX8hW=9J_GSol* zj^Z7vP}Z;7y57`;Otg7*G#<(>y#Saom(bQ{4T%7A57lMVgRdP1_vCZ8s(TEb8?tGbv(ddf6C}aZ)1rVNbz$Q$(R1MIC%3f1-j;$PNNGU5iCd7X zgZJcXh7pB?Gc?J0RiLf0q?hL_oaW8V8Iu(bALn6Se@=8CGj2i=;ICi1t@W_}Azk1oKm zBOH^rv`%esmGzLtCxO%j4=<16w*tYX_-*7wqz0%DS!U{<@W<=?woR!z4@dqbL}(aC zr+Yo&nS6v|g<&+8Qg#XQPSv_S_Qzh@cw&QOZ;UK$X?FSSIGr0T$X+7wId(UZ@zOxk z02|8n03n48PeH(4BS~CJnop8J20V&KrRsb{I$i5P#g-$jP^m1XW1kiQSF|~f8OU$u z%$0|+An*;wyL&b89f366@C z`pmcJjm)iUuGf(a(ypcO(~9(`tybn8y}=mxmt_wJD%#u8w%dp=+?suYL(Xk;Pt)^y zYv;#3-4vbR5&fOq3z+Wc8W#$6DpCye(Ay!M(36?7qXqpUvkGqQM51MW5|ZCkJ)^l8$A)f4IB=?W%#LlJ zYm^Vp^+2kK1jg`ZRE(XQ9Ltsz3EBiQkfEr262qP4V(nh{OXslpgf%PUO{kcTn!`N= z&rTSW*%BP`Zb+#OmODo0$d9lVULUUuL!zUAyiqD?r;hG5F_Dt+@&fSBor`k(wVpL~ zm0c;vikE>4QyX$^(1L92i4p8_GCxL)Rm|LxI({hH3EdByOhj6gyH)Cd7RA+=}k(Tt?^>6g~{(%N<))s#-7g!_2i}(~@~qCp;z|Qhbdm0z5P?ay%e( zJ%Mr8;YG_6#>HULD*SaS(DF~?Y>Zch6y9;SImUh1l+U$v1$J_uhk?9te|&K0ALSt4 z{0;hMhntsrL;nvY4fjm7+9rg0Wks~b%<06-NAS>Y%4j_r_ohB_+gJ^YY>FQxP~^bR z&tIiv?+>LVEZKt3Hpi>iQODO|^H@MZz%38D$mjsJg$C2k$sYcl8|NB5bwvU%=?1%w z%}_4!YzJb=UBV5uq_ zdzt3+SsDy=2zZ*wVDU{mIX<2st8{zHMvMpQpoHDPw7);TDlN1algx>nXf%wu(z-qA z-MG1?2K%kNFX=4}Lb|LLR_%c-2YCZn)*W%Ye04ws#iv_neVYv^gb?pkj0t@w;JAQS zC2_f>qx?ZoMzLBS-wk)x@~#fW{@Kp?#y}x*he1y_r`0!i9!8BJ>s1#nNHDP%Z5iIy z-~kd)i@tAJE+$92Yup=U4xlcYSIi%z%0^LUJ9VH1cg7?}7xdt5B^4oC5&n(Z-4c>h zXdvgUA|#-6ciu1xhdUrtxw*GMPh|*j%qzMKa+xhFF$*@&*>9}HY?9N_l+|%ZhrTmG zfg1yTz*}QHqa|{!41qS+ER}Tu_k;(9HrW`qqZ;OMN53OT?v)55v4rHyTS(eTw1J`| z({GLx$4m1uS8St6V2QT^Dr~AtpiP_IB!G!!oy;4lTK3a!Q?F8Xe}kdDy#5*A!|Kr$ z??JP;Buq8uf?ZXGMe(+_Ct$?f!Pi@XQ|G$ZTDr-GP;}T+^zU%Fiy1P+7!%{{u6yd! z{n(hxSB@Cv1_87@wv44@sfS;@>Wt0An`EDz&DoKfZ_hD5*5CCNgSHpnXv;4*Kkk;W z_cZ^!G0lpU7%y1v&mKge4NGPaO5O+=zIy`i->pTlSmO@WTpF+p@JxoChEOH!ysxA` zR0Mx&w(0dIf1+sR!%8Or)*!!H9HGuKa`6wI zct7HEdS|7Th}U|xfMRF$T4FY@N?%uMXH%mfObP(}%y{DWwqd;Moi7=tW;KY-F^I`_ z4%MKfhMIS;x@u7}xwicAb=7(cMbJ~O9(>cRN|TMslBcF~{gD8qdtuIMki^HJw2twm z-=byAApdra!g=uwBiI`;Z95^yzz zR`aNhIrwerfOHPUn!u0u&jb)ECU2hI?g^Fwk!UniKdIBJoLh}w8mkz7SusYhK)InA zrHC3j@1Z#WVcvMbAuT~7YB6j6=8gMOdJj#&?F!+FiOW zaW?$S#>=G#tM%c z`1*p7!fJ{k5X6m#b9W}2R06V8BQWf3Fe_KLz48Wtw4S=bk%Z=2aM&4}2vZqT%4{Yt zUyw&n0@rdQU#2~tJB-8`k$MHxpM89+B|D|68k>S&R^74PwrDFT9?5cYl0>5$#YBDe zM<8}}OC?u=L(;DJ>pU1jvFME;A8g(3swnB>$YCPJp57dBybg@G7Sfr(Z-i3o-uyAwLk#td@7Blj4#4`dt>S%2s8R! zJF^=k?{3_OnAJRsQ1@tsJsp4I4&%RiWn|3P4XHe4q;`4^qFTq94YM7ap+?=IQq==) z1}L>Icc;&&TDu9;Pqf!S+}Bu2_*|EoIF_Po{U*i}GMBb0uij(LH;^yQm&O@wm5HzH zHuuNqwPbMnyzBc=!ojMl$@*HziZqCw3A`0CWBf+$gCKf6II+|ERnuIGs~~io7x4L> zd2O#sEUyc(4*`KZgv(m`GMo4yt@^B-ce@$j^E)_KoNws@5@nB;^5tl~?R(Kr(D13E z0IJ&vAhe)8lI`vsa2NS0dG&RC2nPO*!Ux}7D@3oU z%`P;D+L%FXDn&!5qZi@n;nFvo&VQ%#i33Qb`gY?J6>IsVk?pyLQNiYl^gmwn-t2lD z)=G{s>b%%1l?AOF`(!s=L*b^mUaz6a>@IsVuns1hUAi5*YG(`u_vQ0g>@;RJFE!wQ zb=cTS&QEq7A`hmXPLQauj3K{pYWAZLm3qVXMsBI3>r!Fs+GdjHW-Z>#mjK0Np)&3c zgPF~P$l=##A9|v@BW?x65MPNXQyt?Bng-k3C>v&Wm-DNOGi`N8-0_w%%e6LMt(<%O zU4ZsUjAxJ7tx5{O(}>8>FfmVuZ;pYz*1e|nt9Bl*qr<8Qu0D5)gG)4RS`+1I##le= zL(STHP+n(k8W#i%D(7M}2f}r&P1mI|xk#c7RhVTFs5~qqBSgD36OIT;+MI)J^Gd-! zkMuFBZ4KIfIfrbh4mUo}m zyz2>azkMSluXruHvR4RT3VM+B#y8X(Y-&`I;z?Cn52EuWJAA>vE7?Uf5#*lcB$_!N z!qrxe&(Y_23*n@rz53_HBAUbRoF566jM5azaUGn0Pnrxl3w}(=tkVi=aH4MmoNtG1>7FD`cyxBPHb8&Q#PQkO!Wd<(?){qr4$# zB7a%OS~0wPmJ_||RA#9jDU77Zz;4vjz(&1ErY8^<^}6@osbuVie-+CFrxu{$+r@yW>ZYf$NI7mywy~d zQhU>E)qGScz?wmoow$w~@_i#Itb68qTqgU#{UfZwazfM#@0v2D+bR_W`RbLc>P~U@ z!{T0yUb)WI6nOs`CLrKJ(ARn@7K)lJ{MnEapL-Ie#7*h`D4iUa!o zM2dYu{4=@QMF5fxq~t0b_9p)MmE)ZD2LQV>Kd6fS+gp*1r~s0hclD(mcB&nE6TkSB zmk0px)AKcxiu+Kn|B-tI*lU-$P0SSb+X(*$m4vAPd>PY;9zv48qsj3F;|@FlNJ_$0 z^y{1B|GJp})Zni)`O{ziQ-l8@q$mDU13)`XuG00mC7$2k9a^Yj134Cpba<@z9d|pS zZO^Zh_YKY8aoIB!{|`F-x@0IZnG+>3id7AC`|aoLmR@~4jcW>M^%o?ksNZw-f=CJC zBC!Tm>pI>lg%9CK{QeYiU9i?G-=E{qWVsMI&1M$UqMSPR+pDSx&d)?%V0YpP>^udH z<=yR*yvY2+Rp}v5;E#Q~Z4SVAWoAZdP96+xLi9v*m`>AUrG-aRaX5D$x$nAx7de{N zc2(Qw-Zw>;Ez%;vg8Pi!&(*O5#n$1vtPgWFph~W$7r_r?juVT0NNYrWh<(TzQ@t?_ z_UwzataP>VT=&qy{pF{S`GaH6o^jOW09_Edf^n0^=3k*K4*R94a6F z6Kw~*#FXu^INoU`d7Iwl3uUHgft7Ezvnr;Uh2K-2#$Qb@>tWe5zFJRkgHpec^KMK8 zSGkP6xg*3r>m{O)3U(_30hdcadqElC@*pe;C=E|ye539YAAItCIk1Q!G2-1T?y=-< ze}F?w@yr0Oz~|Aepd`3CWZS0BHUb2Tq$`sGfgZbs2XSngQ+$zotnnJcD=RCDabK#t zhA5j1Ro%85vTm6FM4d0FQuC0ytowz04Gr3ti?VdL&;F*2@J`&)z@tY8j1@eu=Xs)Y zMWOY8tOQ0fUhr)j2M|=c_bFX@w4c2rlc3>#zCY!0Y`I>+T&^9zdc)oPLFjz%vRdyq zdRb_3^Fs0y;vlRH?dG_-6n@y+Eeyqb*RJTO zgMZ*^80mPy@k#PG1^`3ya~rGQ$=16~q+F;^Oj z^YjK*bBxXb(|&;TkduG#{$P3YR6kDB&v*8i9PHa{Y+i67TL(}%nMC$50@hc3+xps1 zF1BakK;385+?mS3&;Wz(&3SmZ5+r@otsgVz;0AnHreWDn>fY|ql*BU&o1VzrIS&W^ z(5Db^sOdg^0BK#o5iv^V&pmxWQO;6fO^OF=_LYt4tZqM*JoYng*{0P!SEh2PR$Q?p zuRC%F%{OwFfMK_NQi`fweTNeJBWK9v1MFJi*>iTNnvkB%%uk1Y*Y$8=N6Zvlw|ley z4$^_eHQIdNiWCZ4Qm`q30VHF6d&dm)jkQfyVAL$MGSXv>9unQGVfYiS=fb1dV#H4O zbQ)@WrHr5ZJ@3$A#zspRSPKb3YAQiaB^%IxGA%%_FBrgWwVTSj%LcgugLDr4se;Cp9D!Zn)Ds1fXo+`ai5L} zFqBA}{4|Fw+BX@g!psz$C_5>chR(dq(|6kCD6*5s`;)tEq}E)1=G=j5iNe*BE@er{ z;~3{k)BS%0vc%%m_|m89rVaK#3!o9qr0)#%ZXB6>0FJwRAMhtWpB}}>sP3KFSvOVf zR3@xYTqqaT#JsF*#dpQSJ@BX6$#FblJILoVLJ!1j<80S}Zx*s_>$cqGJz;|56ncDB zo3+ne;F3qC7mg^++CL;Np2iA=uh0b2#*X5-oq;Y&$)A(m$+?E>3`)DVJCF2|xLwWH045$FZcw*liA5i>XJbZmzZFzF)OUjXU zVC=jcy_SNd2XhGc0{kx3wcF3+URi@wLZ!O)r^R;tBqsgyOzAPi)fVh^>CS`F69@do zKD1NfjNgeaRk>vc4S&Vamhpa=!6yJ27@dO>ym!@|#4imIEfYXX~1ZFwx z9(D9=Ae?^QuD}JaJ8++IKdIIw5u2aSu?^f_1~i$iS3GZMjkK47JdoYrsbUjxSF=^p z?kOCp)&dG(fD_c2Zg{~+@^+YptjMn_~RvvxJ}`$VEFQwEpuSc#}<#jyU~yIw_? z+pA2{rxc$b<-{sOd#~jOluLf_@gV^pfsen9Or7Z!h#Hy26~TO&`6l8GswgrHy$=P1 z2F8O+e04rLTtOJHeXp5V79M5I39tL-B*`#6#@@1O@l|!Tu451kqz$=0FU4!XypUHF zK}QE##iBLrRHz+j?yk(6GqG8B7`wib?Q{Qu>kS>D*Zo0LvJbA^E{=m%%Ix|C-*36c z3YV7~?zs)3c%q|Y1F}1Sb0y&3e0-ejy6Cg!($mj7jpLMui~u>aB+94|L&@S7Lfe*b>-(1-H5$!6X!R=_FqQWU)b7Fg5M0lA zvE8kO2R#bR>(zsGR|n?P9ggvo?THuhohm0McA_FuJ$Bn6^5%E?ZPs7* zLV&9uLkUjrkB=SgCKganh9b^!9FxAJ^ZlXYdI< z{Jy_d9|B;luMG(H@wIkM&rJ<%Bjv~=oc%pu*Z=VvC0g$hGi1HnJIE0VqxX3*Q&ygA zyX3@fmoePAQ9ONfqZS{33*9Uj?YMvcL%SbVuKUv9N1<1|wtx`Qq+#lD40)r6UT1@) zWllYxb&lZFrr23qh-lb#2C=&%DKL!fd)|E#>}p35w&YQjtGMadl8>9v1HTP;h_%KB z11$z$zx(@lj%`=wSRnMwPpbNdPRP;mj=hT|XL|`Y7+7rn=-&ndi?G2!#g@#xJ!Tvg zw_{Sa_bDSaY%p+;`}V&L2C8C%fqyoe|F8zmEI^9t%}G8S-#q?yUO+!35DZkXP2csf z{$b$#pMI@Gf1%_7pW79&!N9aqh2z&g`zUMG6M)*r_lYFM+}_{c-#dM^E-5San8m}^ zOI2=b_ZgmK!3xcq=V2zj`+} zCjd0J>ia@)aQ4UM^sDYF<*#2Omssi^ZsXs#bU%M?0j?~_>{pdNeq{k$296lFYBoih zbfhV|+?PujfB(qJ`9b*q+WXG9rnaWvBcjql=^~&<1*IcRkP`I>A_!RMO%SB_5<2E+ zK&2^2m3k0SA)zNgXo7%%6hV3o9VrRDgz|3G1R^};e!K6z=F|QqJFCo^`A=DE%_u0e z&lUUYx*?Y58;IB(l(RjuB_;+r;*q6+lIY^6#2y}H=Nw-w+EI+A5O~wyoG8loizQEqceQq^6?-Sebl@qic$OMmUY6Gp4wK0RIJL?8ky#MmM3bKi+qP-C}y z!H;%jbl4`F(spa_M(^U~_Xpis4nt5Lo)1E?2p7AtI06qxomJyw3We3LVaM|@t<}Z9 zECD@`j@{~S`D1?)O;i*PO47>*JyW{WxjY7D9Q>Sgi)aQQsg+IBC#Q@UKz}~MSZ-mN6o_m&*sbDr{ zF~8^EGmon6*Tkn=ml*%n5S)izm!T<=m6FStC!KT>zWu4af6 zBlCE0?Ixfp5qx~X238DEN2%zUZ zZ=GWTtGt&xtMq)`xC~uWFrQt$tKQHyVJ0cgY|-T60SnI_?qq;{pKEvaw14bZ1?@&K z;{%`J{8^k_Z?y}7U%PG(0LN2xAB;Z9^dVyxk^f93!MWJ$pqh8~@r~WE0#v5~P}8C! z?R%*lLQlhjO`Yy&y*mn}Zg#ilYKtQb$Rq;eFSzDxv(L<;)c0JD`#>1z6?v3nZvAmR z7a~2C=tGi1nrGZ0;eI8nJ(Z#2FwihV>bX2Zf4@GkLXJk;;A2tv1uZ*y2wpljSi@$U zRiAx|LAF`pR+?S@i1@srZ{^v@MTfW+0wfSWB-)TFOLmFhg#APGz0h5fxVTh4A(w?u zsL(N(T7^g>n~ck6gSa@BdHl-B@4s=4>*_4Pux;cwrr>AlceG>c<(<)ZaP5-}#sH{HDD9sb zswAE=3<18Z!XnDj-%vQ&FG3IsLbA>8Q#`H$Sf>?YPaonL_Iq=Q;iRE2uFI>i=d4@< zE{#^>v@;^FWMR9n2 zyZ{5GD%gb~f!t^&HH2*|uldGrR4Sw5Ub7Y}#FpY-0Q(?K}FmpY{>iZlKsEtrJ;b zf^${=8HeGI!ylt0Riprj%At@B54_>5sF37V({tyUrnBn|PCi-Pq+Hm{`WS`2p^9UL z_;q7l$<_B;jfVoD_1rg4fYp8ZXk?en=D`f9z0o~6#=bLkBRaFAjKYAfd`lV}Co~gyMYH`|5(}LDy_pA)O2>uSO*8au zp+XkR=0z80^eTB+!$okpaB7D3a%vm)A-h14{a?o#Ym(H8q-u=1WeUy)Ke@YQf?&~2 zS{YK~Tbk5nM^9fogl^)_c`8Bi6+A18t*2n9P|ZdWMJE6nY?t-bs31mAIu;VheVR_e z=m%CkZ)zBzH4Dj5ZvTN79G4%KHIbi57Gx@oc^%jreQ*8-7JW)`4l-N4X%g)t^G>VhyX$PU%Z@0*Sy)7u6GK- zEZCNF5bw6hlhSsVnOIqIK&~WRv{=udS5TeSI?D>19yo(#e#PwuXmYhM&?)Qg)>a4H zq30<}!~R+`ACl+205p5@`T7?DAK_@9`As0C zwl%Yv8hc^+k6IQie@$RQ0PV`?hkm!Mtf6JEe+(-bC?Xdp*SrLo>`LNWQ)XdIHQ>@0 z-kcPb<(F$-PS$aV7$sByjwA4+?2)YORNqozcm>~_==mF0-04oV3PZxFP;WRfonf?(@M_dwxUpp9Mw`+X8RY< zA>UjGfNq4n3l9*}zcl#|T&P{KX0&3XfE#I5`HIaHd1!Vz;wUm0-TjY(BL61%OAbmYjvW0U({EBlIPqN0%e&)#dH1YA2LR^+*`;$Q% zMTcZ3p6q4gXXvam{?qNyX!bEq@9}(`M`=DThdxBs<%@CBegEO9h9o+1<+eo}>l?S# z2ZmQMSAF~ZHN#4)Ih0m7R5zc<8k}>MX=9WMorYJVq{@efX#18s`C$0{fgk4e$tF(7 z+J?|uxm)>ob8VOU13jWR;WgD5`tgf}64;qBf`{pu5_fWZrAaem*l=@D*k8fwq0mNW3=@isT6{TCBgOTPvP!TjjlPj%Qu506Q=RdX zu;?)0iok4F`egcU3jXY!s-WzlPlx#MEe~Qn`CUCi4l_jAf1cod9E^pYId7eMMsliR zgF1_aLQckYz0Y$IY}v3WYu1?4a6Io*oqn31nx1IEa#;cB(qQ&|NcY=;QE2S}V)t3u?OPy0EH{OQltl`gl`emx4+(-8TBHTi&z$!e>Bq z!=8M~9t}O+hxndFJ#WSSI&Ng{Nyyk5CGsiO>x5MlMiiByp-|A8AO296FX?I(ER5q z7hHm4ZOk z_};H*I>>Cyz^=Fm`(!%o51g{4(y?~e82ir_hSzyTFfVV>hfYV)X%+`kv7=+7uo~Xw z#9sRketWdurqI{N2r@}AQ9-d8!(Crw z3=H|KrGVJ9m4`HjC}8$u_z*67AU8~ySkyiR%VO>%<~a3B$Olh#2|V4bl(o#%a`+24 z6-;Iw7CPwxIS#P3f>-V)X zzYak(Ep5PQ(qXV_Nquj5;$nb5@WuV8d5x07B7QG{SU6*SW*9@bhPn#hWaU9q8)b&_ zZ(6-i`?<5Z>(xIXCn&U%`2EA))a`}Bpwmsw$KdZ>L~ZzO+FNxrWr$Vf_h#G~=*;Ve z(kDcAGue0c0O|vLrYPQurFvjVebCaz%3|X__2S)q0PVT%0SKZ;B`$a$7W%tvHI;qi zmO1&di+BX0Y3}Q4Y8+O@Y_SI)E!%|`&&_~#q#NT)_G#xaNLRORBaZs@*~coA&TW3U zy|X3F7C6}yvB=s?w5#(2KKz)?tt{NLb1oyG2yUsgq5UAHh>|RK#QX3feq(Zn$|sje ziai><3UV$lOnq51Hgnl`^k880MU9D@dq+QPkl6llL>?^uWP)F&|66+SexnB}qc%k> zvwrp6vq+F0%JqRG{>m6@I!>DLS)c#o{zai>t%kU+z&9*!FYlE)V9N=ldq=hOzb#aF z@)E%Jozavs`>?_e&361t&>euVVv7rG|7{(wkOpa&j!u`mQlaFy`lwN`y$xPkRr;JWSu@UwJpM`WuF;Xp5&|dEBRIXr;wD}rW~&& zEKM{c_6YK`N>DH%rZ)Un8Rn~G^ts+&z2Dmh(1@2;2qCAFRwSD%5qYd%IPn996p^jy zO9_gkBoLba@c>dF`P+uQCjaMobGnn6O{D8bZIixu3gagMQaNO~!Cu(rA!*w5OBfY& z@(4-Z;WkTHS=! zovIMR!OQoF#{K7M^c_1WQ3TS~)+S8PrR+8mZ5F@U-jsB;)VI%l%v)=OH3`9UPJloc zJ~xP~?{i(OK2{z-;R7TEbmq&bdEjEiR?Sd|+-6mYH_rBXz|rwD_<8+YxTXb?Fm6>J z^jw{w-1^r$s_eH8U409qc&4;7c#XudzrEv-g#PG0rGQXE-8I|^Jgg|RW^NBziIZQqP5$6-;YJv#BqKJ1&r!;ukPsTnEF*ot z(a>|jqWQI%jaXsXXj#B7-~_Q{dZHV`^#O5NF{c&53Uh_M@=U~^GXQ#RJ@kIV0q${A zlfc1bqN$(}%xCC40)eO@SHO&(5#Du=_s7H!kiN;w&0W}VI}v^WQ9FN_1%8Ua@59#; z=R%y^Cy+injX>4pP21n&55a_&@ekk5J}2$+h{)AvHBOTje79>C2iU!r z`PQBru`@pWe}0)Me&IpW0FdVCzQdn)IN8)gGV#rt{HjGkfqEd(sY75gpK?GG;1ek$ z(jkidgf1Mn0|)cuUkNcLNFn*kF{EwoaiViBK#z_m2T(6gD2EE*=X(4WkX!$#S!)zw zbl=Vo)b)6Lvm_jR{>cVfO(Z3gT1|s}gzZluO(5P;Fqcml`Hr~ku+DByp}YY~w7IP4 zNlTb}{GoNFk^KTbc@!%&uQkpu?hK3TWRr%34)xyH%Kr2PX_At575J~7=5&N_{{6$JQXq=5Io3o*7;~Xv zS?P@#pF8|`YU6)drN^=>ZjLI4;Fqv~8HmAcFdW}at$)|s@vFeH36Fl+zJvdtsJ`9K zbII28S7t+RWhq)trP`_WnjFn!MvjID98l(`6^c26B_{%#+S)W8=1+VJ zsHo)?=cca$|30#N$!E47L}arI&Cd+RI9<@vMp&8NJu=#RPSP2ME*+&5|N zyiw*Cy?75)+T{7=8Y*K}3L%Q#*z(K51grK7ISjteP2VeaO)P-L5hNTUkH7c3YdVP! zAdf<%1&UUeE{ZFmiuWdfY9(puxmVE9 z5fL0l0~eHBCfviV=%d7KbaWi5(zPwL2@b-Ju~1gdL}#wsAu_PBx4U;`1NGuGSM5qp z$!P8xFyYUM1*9IL?e;-?_gV?B5I@3Xg@iouI z_d3fFm;C&WaC#Tn+tr*s{5VHNGRd-dwU`CBh10dAy^8TZSG2e^j-7eDOrdcwQkx6N z(m7|;{n4@i6w0qvL;GECnvZLz7<&54{qo1lTd(?1xV|G5;~xb$(qKi#+su@*{0#c# zel?VB%ihY(V)!lg!CZqm`&F9_+#+QiwH{Y`UX>-9*KozU!@22jrNZdiYI&VQpY5hw zUzHzl_1e!TV42#=*ElG%@p)XusUuU}wtb^r_bThT6FkJ%XBv@E7RSKqRB*R2Ri~-{ zGaVJYiM6u`+2_U9>hhL#+=6tJ;gNkG}OSR@X5Ays18dnYcy-TLyp5-uK z)TQFmEdx~Q2vCOM()tGHa_U$$$L#8R2qOP|dx(###i@>Pjm>-^)7q~>>ova2K0x_K z-SQFUSau)}cu=lRNCXFZ)8F4egiD1-&vWY$trS&muY2P`Q}14P6s%mOMs?(9_2xWp z2IWwgy|%P?r};)LPp_k_h%qmm8nfns2%5W zt5BkEX|AQSZ^oI=Om-hZ#_LZNs6K=r?i#GMlPkeyW5>GvHS`b7BtNC6uYQVd-71PF zo#LQ6G9z+keHg{f-1UAb;i6quF^hPbG?z-uiFl8t)$+#PWtkHKG8i1ROwY8qp~28= zq!pWIm!Pc$6Ko5*Trd5Dr}%I1Z0= zI>#G=cNu2#C;Jv^FDMBzx^{Tjdl*=ukBsT-iG9{s^`f$5_a2wT4fYAtnnxG2^S^s za5a2w;Gu~ryjnq8e|%5q~fme>bI$T%cWf2^EZbDd8) zR`fjiYTOII71`o$74%y{AGn&`L`p3ZtY2i8K&M%QO91ZJ@bV$8FV4*;P(Nxjlt|B> zqk!5N^(!I-H>T^6&`UG%^tX%9U|)D)vDrvbC9`emVk!lsN@MS+%PEl+#WnApEAJ;Swv#)w7S71V`&zhy1QBc%rjh#CicIqi18Dn4 z8?kmRoA6AWN;ed^D0)Hr>@*}(^+J3tW4m#j+k$pF__(>Q19YT3k-CjvFJmbonPy8* z3k(x0UsAl6xl&?W+!0bQ!OrkT`4y9&cacZ$B5KOh(Zf4 z1zKx!y}IO*Y!PcsoIJY7vX_kk|f8SHXed3Nzikg9C&DrvdQ1xNI zKCi16haWESuIG6U3{f&0E|!|=##KEWL55r^O#TMnPvC)IdPP{W)vxLVB2E4hj$qRK zTYjbYsqQP-Vp1>1}9#XFlE_I&fZ`W}H>S4F2w+@P2vK8TesnJ>W=8-tr!L?;2 z!AQ70lVHT*M%kE)=gEue`!0y}y^?f#kWD=iYxCETrE%qH+YN1xo-M4Ll4?afYDUYo zPoH~Rf746AmfB$OF2ijW29{?=*z?C@kYjM8tiIxa zRMP}u5VNLF+G74la1v0Fz$a3p->qV?T(wb3EI0S19px(xH9Uarm@%Jnw*g*8Mv4#( z!rPgjLdqgu*&Wj`a9G7Ijd$|qRN5$n$P8vW{{enU+QX!6@*)!xk4jm#=qe%8`DW@D^u?;wdbo-du zMqbUq>f<}fZq$~pjjl&3FqgYmwvNpBx;3~aJG2&TTOwFJ@Rr#mzc{7DCb})RQz>Ir zedSvAhNa%L^`g2a1;8s@UdDOql->SSYMNk9Ot7!uN40?{2aI1nkN&%9Hg;Hq9Kr2OrtPOLav$*9M zW~$AM6Z!qn92+Y-MMsf^>Frr{G~JJ<5nX>uORv`~Ft(U|CKD`~vqW&cQ#uRb`88)5bV_sdfaO`y22<10I4P6`?)6BKvI!r4UX|1V4bpnw# zKtcdq`~&FCw&^=D@nu)w_J?eMN=RjMmS;?LW%^vlIuHbMJg%#o&x*2Ox7*U)^Ji}G{iUckA0{UK>rz;NfFNm#frsf`x5+qR zbcw%zwJ!9uZSv|<9?ZEuOmO2iT&l=TOrlpZI5;-9{Q#)Rp`xszD(3RP1%uXA-ON5u zO&biMjGJb%t!&964eghtOV@goe2(5g((Aj7FjmN3btO-O=Ndnm??|qm@)gACWiwiM zX(}i*#*Z98oWE12*)=&{pp%i{QcI48C~QVIR6j9`r;8={wP10=QMT+GOiX#V@)6}MEOIXjatj} zl5e#}snZA^R9kqMk0Qvnn_oipks81XXOt6UFZD2Wcbej0SA_%ffQ-C;L4buJjVo7z zYJODjn(;MJNrXA)A>j)~2H%!cPayg&?a`?VtEutcvg@TH4K#qbXV|X-3&vmEJ2E%4 zwFX{O?r~g@D9{#L_!YP7UZvR_vz!j^u`D|@ihZgU~hcs|Mb)fcy{{0(zH zLx<^%il{71l`*=*DUv;)61r5-nMhp`Nh2xb?b~x9mj!!6P=hIyUn7luwzGLan<_}% zmR-lo7BFc8D&HqKTtmilW{fiNZezmx#X=7Upkz3CYAiOd{QkE8zS0#bmmog-!JiYF zpznIq1CGb}9i8x;76@B-eGW7DHOx)wcskQ9Tc@4ll3l`*#NmKv)m>I_j>9&YwzIi) z2@al3m)YQvvdbOxr_1vsHc!b2^5>qt44brFyWfFpN-i(m?47+~isDLodyOeN=f#JQ zieZ%XAJzI0fJfYA(jlWgo94zaSve1wP5d9TTIZkeR(PYM!pixqMp&rfTZ z85)k=+zi3B%r}<{0tII5haI^6CHgt^Jqj#WADh&5a>(d3dn$O(KF_u>wA<+JMc1tA zr3l#Q?X{ThLCDB*`RN`A?uqG$MwUT5Y2Qf=9F)p8$a6fxEa!{$F$D{(RxYAzCv9&a zNW3L;5eO)YC|kU>jQjd|Ge(VZz)(k)f8mbrGkR+S+VU|1^c%00Nc_}uYa?ye!vP=i zRMQbRP=%f|g;!Blz3xU|t?VA(FLinFME6QDkykOK$9HetET{W)(c8;Ss6gRL%I z=U<;0Eq&82u4fmQtEZ#oGmt%D(Id48U?oLzbucBMC^~J$Y+G3?o>mUc8TQf17jHh8 z&BaOr?uGpq#&*9;n0Fj1yfCkh%eaVmKh9XNBD#2}s*z@(7{~%#lNUfaEh9TPVgKn? zKb2sSboNwqZCHd5_h%+dCF5`jxR%@^kHvBweJJv=`Opqq;Ti3de_5=rM@-1(x3hbJ znT8b6W89M2Oi||#t_r;A$%c&Wv1{yYo_FW>@<7I2(W{(H(UfP5i4wEY$X|#tWb_$) zZ+RzG#R~biHkH)kRA)|wCXFJAh44uYkGr-Kz!8ORm2Sp9L+Ox&tFG_t5^ctdX`x#_ zSfjOC7VAq(ueS^@8oF1GR2)0F#*8?^Pn};GUUvh@d6QFx0w{ng?>6|(j3V-la`f?r z^%^L2PRa^?bknh=)uPqhd)@}j)KDGB#<{dru35pwW=j{rmalBY*2!$>F6Jfba9hXM z7RvHqz17Z6<*I{&Qp=#{P*J7NOTa&2_AT_VmRSii!pOMN_@Zzn<;mMoMYw7ou2qn| ztM$#-y@#o_$VfEIb;-sJ_H56YJ3}HOBCyfLU_rJ~ab4S^gG^C?(!bZ!${a_pp=+Ar zdb3jPu3mWB!jn@lxlPQ7QOjkvmj(j7mH*MKNc#k^n;pDv8Q4_Bp0L)&dz;GU(^Irhb$^R`xf z`joNb1)H^nY$a|E+(>4P{A6nTAcdQ-vcy8)k*j*wU@Q*;(3K6rEIjKYXUF^)BMssD zt+hhBTRs8)Rz5x|EJdAF)8E=0(Yf@c9Bcf25-^WS7l{ZcZwnj6E|~pkwMNrN&GYMz z7QVT<_cwPYp#HQ>3qS9Dt*L;7-qIHIw!fvrE!%=LsjFL%zy0JxzMQ`AH2@7upO+*r z`0xqFSx38nOgaMXH}tg7@@@_1wTq0ao)!al8ogT3p~|mRQ_s6UMBPs5F!^QBp{c}^ zDZm96muv&SOlLNC0PcJz8YSLul8l|?6{M*4T~uOkdwL+3Eo067$^EA`%puo! zG_nF3vS9i3Ru%&pT5`uZeLfvP$0+$6H+~|_;qa;rh}iLHoX6=ItwPXkY#9`Wo9iEp zvO)_4V8A`0N98w5^DkP9aT7MErgZ4fY&l>PNVLR7pG+0`gLy@*j#>F7HgMw zq3d$*&h3j#I#M2ARe|`_gqm7G5vD7pMWH{;qPKqvrR9kM-i(ghNNf8QtJ^dErG{EY z1*R2+HSaB2uV|^qd>To~KQv(l*(VBv}z|DIINsF zw>&)PzIMJTB8Rp0XBs_1j5sk4*v`FljG3UfFPzN0et0dBaxeFg9#^^dIe!*iqy(qR z32m(&9edL4RAqCKeVfu*ZE2^+=|_1b}p}g^bdJ_&2tIb z>mctlhwU*zjvpfJvV45|zs>PY`i&RZa4bF^B?l(TKDZ8uYq^@n^KkPG@?>&44 zPAO`ferdUnDD2y(njt{awKYrP++X{?`eS&O!1blHqc_C<>ltSNB=z>rBb+hYXO={h z5!+rfvXtZhf`WT!@KqBaX-SFBUX{G()$eTbTMYgqWq*soe_~S7-(o;Ed?%4Vp|_1V z@g*R0ASA^~@M~R3F@hdY+t#4`H+Irk{|mgvGbWHD8Gu!lsY3)5qdudyu30ndq;oK+ zPVE9=|5)BeSaL|z$>CC?QBU{h8J*vU#|qJM90xF$KfPhn$^0&zYwfC>sW z(IbF}RtEsQl%9u+2xr%T+ozSju-K)=tZELnnD}#h=HSTH^a0E^U2?FdGt-%nTouSI z3mombcZ{0gtKR!S+2h=Dv;UQ-MY9OyW_=%VP6}YoQF1@dci!LBnH9woWxJ5%Lb_^> z&Q99R=bn&=XGdSgBLi84jph4GytgFXumkMdr%p5ff#3NRqJgklC`{fke`PSB)C&z| zE?IRr0;`RviEhU4E`a6%@D;=Kuu0;31&xuIo=?27}$N3gMJ9UcsV~@xGg@3S35rcFXaXiMrI+-xH|kTnd`t z94{<&*>!3UI3GBIsY@BFbet6l&dt?3;htwz=_$L%Ojx9Q%OuZRtii`Dcc1e{U2DVS z7gd`bE7Y9(9u(nvMu5;4-StB}73L{p?BPQdDa*}O48L&F0TRl~AT^s)iJk=4w+uML zeYLx&+x@2*4x~qv1T1tj0U&y!5L7!K3>Wi{y|vTl51m7)lz8DI6YiEfY@sMu4>nVN z+<%$yj%dzvdQhSgNgVX66skWZ@*RPJ@enlr08*Q&V_mYKV^Q$R5VkAE ztIzy)sTv7K4&u|(0~SCKzuNTjXsuQFSjwMHC`}zzLMM2^5Go~cqI|2~mnI#8fxFuH z;D+6I7)6XyD+%_1hmk<)7_G!)kWSuYD_l%CF6mcGkQG>f+i9-+2lZPI;TwTGV8&J> z9&E`0)-|5;mW<=$;IUwMBtlmyu6b?enEOuwhqyDoJ^QxpR$MT=(aKPIXOknbj$|{l z&GZ5-z9llzERb2L9N4w==>*lUMvK-bfR3$FsM6;s3_kVj0h0PZ2WV~UFSJw}@!jp(?R7fl(S=NXbi3=XDn)paI2io{VY+?!BQtFmr`iL;? z2TzEWJZ#b#YRo!HU{M0Ke?Q;}j|apbcKrUP; Z?_A(YV#{fQVM literal 0 HcmV?d00001 diff --git a/docs/lnav-tui.png b/docs/lnav-tui.png new file mode 100644 index 0000000000000000000000000000000000000000..bcb87ca02e6f7bb06f82c2eea769aeff9500b63a GIT binary patch literal 156641 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¥ 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

BNHu1)sb6b%g2Dauo?-b7;M{Qj ztF3lex}YCx>43l~qB0>LdCbOB2_YdZj zR#O+kYxG@E5!7Cz>f$@)lL#3o%rtZ+)Z@jPXKd=|W?@{Ajd1l7QFuDeUpRfXsSZ;2 z#w9th_aV^)Q&VJMx#~-OE8?4dvE#OgLQ&mRwuisB=Y9rtssA9qtj^Cj!bVW4Fc|?N z$zCGb)Z03-REW1UFzIa-XP*!a2%}dI>57Z52-+t)B^kB|@d5rEriuJ2x@vS*CKqaz zbH>G)UfxH5GG6gJ6dI#KP<+HkFE)<;^!u%#rja0KRI^vRd zbwAei6e`r%DLq`C)~MmGBV!Rs{&y=v7UCCgXb{X*JtA?Zs$QoIFCWiu!uuFXbyTo| zG8g&n^ya!Cv!VpCo@~_EEQna6;;n-t~{Jrl`VS-m)edpP5(n_!>NRz|U%% zA%0}fU|$zBdGJWjo4IEcwemEws*w5q(IsL{m3tSjc*iaiCX-W+ALNDknO>Y*XBNsu zF{teE{Bydp2_t%dp{*0)>06502(ytHH@-On8Q^G7K%Xt)ooYJ?<_0pf@8c=j4T9sk zGy0B1*1q}E9f#~4a;m6CX%o$D(({AV=(uWw84JXOgS(l{m2J`1zic4d5xe=vsIxbF zCGBDQl3U_#vX57TtZ)~XhMXs+ifyt*k4QF!-9dwU6{~y%<&i+3k+r1B?Nnp}jHj7l zo4TR+>jiH!5AI?eVs%+-<-yzigxDVxPKtFK)*y*1qtZo!PJAdrBrKolPI4y~*CO&j zkM%39jeCrwah7%iIT>jg%H@$B63_u27{(6losZ}$B6z1W@DzsVWp3+B;$ggmyE@yw zCN!xeY$tXO^`cqDLWpldp+ci~a1>xinyR(;tQh3=?+(>p@UDyJ9q(`-iM$=^O7;-% zt={usTt4-rP(mkBjeOHuMTN4!k2KY2kF_6G%yUSP&fCs91ql+Iv;(`Sx_!5cvE*C2 zSDfSgkh@(@8N#86fG&PyE1yFvRTWAuMDuU@wlFLC)8A*3r<BjZSObB%HIY?O~UT9f>tPH5knJjsJiq&`wilVugI@ zn&7r-xAY9UTqB?C2Tco3n(0`gzvnM%1wSJNd`4<(rD35cXILUCQ*3`pEIb$x#%1A0 zi425qt{ZoTABv9gIONLhy2h^F&v5Vvkb#{tZSEP9m_#=${Bb`65%m)o2n|2ulBY1n z+|dEez9~2xh+B?z-C2q*?r0bo72Hys49ha=k1t-^@czYF`Z~Sla%^IAxR=1r)3UpT zP^+h#m|uwnot?l$M&Oi&arJmfT8BG%O9~&Z5(;^ILHeq{yH}dOrLt8!S36fcix}3e zY@?L(@|sNK9)p7a%F}Sl%T>Qp)XHgY78i2ywUYbCF%dS_?Kzy%Yx3wtae|eLwHj~{ zHVzC7hQU+@a3rl*tCOYys;djBG8c^G$OP=mZTV#ph_{Xs0)DW zKMeOjd%kiP&r}gr%n3#h{xyFbT>+gG2WqL3*4JEq=k7*(0Z$RdmfStjSx~xN)UcBF@1*(%MYGM-L4K{4d`A=l!uf)nClkh)8k5C|r8FaOY^pT_@nQOqEI!~W;v_$`GGhHbK0dE}#u?%d#J{WqiNY^x`JxtiX#9eN jFG%=5K?46s-@;NGgD1j^lTR}jfxiR$-S-vk4ZQGgdbLJ} literal 0 HcmV?d00001 diff --git a/docs/source/_ext/__init__.py b/docs/source/_ext/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/docs/source/_ext/lnavlexer.py b/docs/source/_ext/lnavlexer.py new file mode 100644 index 00000000..2509a5f2 --- /dev/null +++ b/docs/source/_ext/lnavlexer.py @@ -0,0 +1,26 @@ + +__all__ = ['LnavCommandLexer'] + +import re + +from pygments.token import Whitespace, Text, Keyword, Literal +from pygments.lexers._mapping import LEXERS +from pygments.lexers.python import RegexLexer + +class LnavCommandLexer(RegexLexer): + name = 'lnav' + + flags = re.IGNORECASE + tokens = { + 'root': [ + (r'\s+', Whitespace), + (r':[\w\-]+', Keyword), + (r'\<[\w\-]+\>', Literal.String.Doc), + (r'.', Text), + ] + } + +def setup(app): + LEXERS['LnavCommandLexer'] = ( + '_ext.lnavlexer', 'lnav', ('lnav',), ('*.lnav',), ('text/lnav',)) + app.add_lexer('lnav', LnavCommandLexer) diff --git a/docs/source/_static/theme_overrides.css b/docs/source/_static/theme_overrides.css index f054bd09..4fc1c9fc 100644 --- a/docs/source/_static/theme_overrides.css +++ b/docs/source/_static/theme_overrides.css @@ -20,3 +20,37 @@ th p { table.query-results p { font-size: 0.9em !important; } + +DL DT:target, :target > H2, :target > H3, span:target + H2, span:target + H3 { + border: 0 !important; + border-bottom: 1px solid #d3d381 !important; + background: #ffc !important; + /* padding: 1em !important;*/ +} + +DL DT { + border: 0 !important; + background: inherit !important; + border-bottom: 1px solid #c3c0ee !important; + display: block !important; +} + +kbd { + padding: 0.1em 0.6em; + border: 1px solid #ccc; + font-size: 11px; + font-family: Arial, Helvetica, sans-serif; + background-color: #f7f7f7; + color: #333; + -moz-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset; + -webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset; + box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2), 0 0 0 2px #ffffff inset; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + display: inline-block; + margin: 0 0.1em 0.1em 0.1em; + text-shadow: 0 1px 0 #fff; + line-height: 1.4; + white-space: nowrap; +} diff --git a/docs/source/cli.rst b/docs/source/cli.rst index 8d50cbcd..ca924f6d 100644 --- a/docs/source/cli.rst +++ b/docs/source/cli.rst @@ -6,33 +6,92 @@ Command Line Interface The following options can be used when starting **lnav**. There are not many flags because the majority of the functionality is accessed using -the :code:`-c` option to execute :ref:`commands` or +the :option:`-c` option to execute :ref:`commands` or :ref:`SQL queries`. --h Print these command-line options and exit. --H Start lnav and switch to the help view. --C Check the given files against the configuration, report any errors, and - exit. This option can be helpful for validating that a log format is - well-formed. --c cmd Execute the given lnav command, SQL query, or lnav script. The +Options +------- + +.. option:: -h + + Print these command-line options and exit. + +.. option:: -H + + Start lnav and switch to the help view. + +.. option:: -C + + Check the given files against the configuration, report any errors, and + exit. This option can be helpful for validating that a log format is + well-formed. + +.. option:: -c + + Execute the given lnav command, SQL query, or lnav script. The argument must be prefixed with the character used to enter the prompt to distinguish between the different types (i.e. ':', ';', '|'). This option can be given multiple times. --f path Execute the given command file. This option can be given multiple times. --I path Add a configuration directory. --i Install the format files in the :file:`.lnav/formats/` directory. - Individual files will be installed in the :file:`installed` - directory and git repositories will be cloned with a directory - name based on their repository URI. --u Update formats installed from git repositories. --d path Write debug messages to the given file. --n Run without the curses UI (headless mode). --r Recursively load files from the given base directories. --t Prepend timestamps to the lines of data being read in on the standard - input. --w path Write the contents of the standard input to this file. --V Print the version of lnav. --q Do not print the log messages after executing all of the commands. + +.. option:: -f + + Execute the given command file. This option can be given multiple times. + +.. option:: -I + + Add a configuration directory. + +.. option:: -i + + Install the format files in the :file:`.lnav/formats/` directory. + Individual files will be installed in the :file:`installed` + directory and git repositories will be cloned with a directory + name based on their repository URI. + +.. option:: -u + + Update formats installed from git repositories. + +.. option:: -d + + Write debug messages to the given file. + +.. option:: -n + + Run without the curses UI (headless mode). + +.. option:: -r + + Recursively load files from the given base directories. + +.. option:: -t + + Prepend timestamps to the lines of data being read in on the standard input. + +.. option:: -w + + Write the contents of the standard input to this file. + +.. option:: -V + + Print the version of lnav. + +.. option:: -q + + Do not print the log messages after executing all of the commands. + + +Environment Variables +--------------------- + +.. envvar:: XDG_CONFIG_HOME + + If this variable is set, + +.. envvar:: HOME + + + Examples -------- diff --git a/docs/source/commands.rst b/docs/source/commands.rst index 9638aa21..99c0d3d3 100644 --- a/docs/source/commands.rst +++ b/docs/source/commands.rst @@ -1,5 +1,7 @@ -.. include:: kbd.rst +.. role:: lnavcmd(code) + :language: lnav + :class: highlight .. _commands: @@ -7,13 +9,14 @@ Commands ======== Commands provide access to some of the more advanced features in **lnav**, like -filtering and "search tables". You can activate the command prompt by -pressing the |ks| : |ke| key. At the prompt, you can start typing in the -desired command and/or double-tap |ks| TAB |ke| to activate auto-completion -and show the available commands. To guide you in the usage of the commands, -a help window will appear above the command prompt with an explanation of the -command and its parameters (if it has any). For example, the screenshot below -shows the help for the :code:`:open` command: +:ref:`filtering` and +:ref:`"search tables"`. You can activate the command +prompt by pressing the :kbd:`:` key. At the prompt, you can start typing +in the desired command and/or double-tap :kbd:`TAB` to activate +auto-completion and show the available commands. To guide you in the usage of +the commands, a help window will appear above the command prompt with an +explanation of the command and its parameters (if it has any). For example, +the screenshot below shows the help for the :code:`:open` command: .. figure:: open-help.png :align: center @@ -22,7 +25,7 @@ shows the help for the :code:`:open` command: In addition to online help, many commands provide a preview of the effects that the command will have. This preview will activate shortly after you have -finished typing, but before you have pressed |ks| Enter |ke| to execute the +finished typing, but before you have pressed :kbd:`Enter` to execute the command. For example, the :code:`:open` command will show a preview of the first few lines of the file given as its argument: @@ -31,7 +34,7 @@ first few lines of the file given as its argument: Screenshot of the preview shown for the :code:`:open` command. -The :code:`:filter-out` command is another instance where the preview behavior +The :lnavcmd:`:filter-out pattern` command is another instance where the preview behavior can help you craft the correct command-line. This command takes a PCRE regular expression that specifies the log messages that should be filtered out of the view. The preview for this command will highlight the portion of the log @@ -58,7 +61,7 @@ an error message in the status bar, like so: Note that almost all commands support TAB-completion for their arguments. So, if you are in doubt as to what to type for an argument, you can double- - tap the |ks| TAB |ke| key to get suggestions. For example, the + tap the :kbd:`TAB` key to get suggestions. For example, the TAB-completion for the :code:`filter-in` command will suggest words that are currently displayed in the view. diff --git a/docs/source/conf.py b/docs/source/conf.py index 958f1c75..b93c47cf 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,6 +18,7 @@ import sys, os # documentation root, use os.path.abspath to make it absolute, like shown here. this_dir = os.path.abspath('.') src_dir = os.path.join(this_dir, "..", "..", "src") +sys.path.insert(0, this_dir) sys.path.insert(0, src_dir) import format2csv @@ -216,21 +217,6 @@ class CustSqliteLexer(RegexLexer): lexers['custsqlite'] = CustSqliteLexer(startinline=True) -class LnavCommandLexer(RegexLexer): - name = 'lnav' - - flags = re.IGNORECASE - tokens = { - 'root': [ - (r'\s+', Whitespace), - (r':[\w\-]+', Keyword), - (r'\<[\w\-]+\>', Literal.String.Doc), - (r'.', Text), - ] - } - -lexers['lnav'] = LnavCommandLexer() - # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -243,7 +229,9 @@ extensions = [ "sphinx_rtd_theme", 'sphinx-jsonschema', 'sphinx-prompt', + '_ext.lnavlexer', ] +import sphinx_rtd_theme # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -259,7 +247,7 @@ master_doc = 'index' # General information about the project. project = u'lnav' -copyright = u'2020, Tim Stack' +copyright = u'2021, Tim Stack' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/source/config.rst b/docs/source/config.rst index 10f08ab6..38946a04 100644 --- a/docs/source/config.rst +++ b/docs/source/config.rst @@ -14,7 +14,7 @@ The configuration for **lnav** is stored in the following JSON files in Removing the :file:`.sample` extension and editing the file will allow you to do basic customizations. * :file:`configs/installed/*.json` -- Contains configuration files installed - using the :code:`-i` flag (e.g. :code:`$ lnav -i /path/to/config.json`). + using the :option:`-i` flag (e.g. :code:`$ lnav -i /path/to/config.json`). * :file:`configs/*/*.json` -- Other directories that contain :file:`*.json` files will be loaded on startup. This structure is convenient for installing **lnav** configurations, like from a git repository. diff --git a/docs/source/cookbook.rst b/docs/source/cookbook.rst index 9c17c10d..44a8e5a3 100644 --- a/docs/source/cookbook.rst +++ b/docs/source/cookbook.rst @@ -1,6 +1,4 @@ -.. include:: kbd.rst - .. _Cookbook: Cookbook @@ -11,6 +9,16 @@ These recipes can be used as a starting point for your own needs after some adaptation. +Log Formats +----------- + +TBD + +Defining a New Format +^^^^^^^^^^^^^^^^^^^^^ + +TBD + Log Analysis ------------ @@ -19,11 +27,26 @@ following examples should give you some ideas to start leveraging this functionality. One thing to keep in mind is that if a query gets to be too large or multiple statements need to be executed, you can create a :code:`.lnav` script that contains the statements and execute it using the -|ks| | |ke| command prompt. +:kbd:`\|` command prompt. -* To count the number of times a client IP shows up in the loaded web access - logs: +Count client IPs in web access logs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To count the occurrences of an IP in web access logs and order the results +from highest to lowest: .. code-block:: custsqlite ;SELECT c_ip, count(*) as hits FROM access_log GROUP BY c_ip ORDER BY hits DESC + + +Show only lines where a numeric field is in a range +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :ref:`:filter-expr` command can be used to filter web access +logs to only show lines where the number of bytes transferred to the client is +between 10,000 and 40,000 bytes like so: + + .. code-block:: custsqlite + + :filter-expr :sc_bytes BETWEEN 10000 AND 40000 diff --git a/docs/source/docutils.conf b/docs/source/docutils.conf new file mode 100644 index 00000000..1bf4d832 --- /dev/null +++ b/docs/source/docutils.conf @@ -0,0 +1,2 @@ +[restructuredtext parser] +syntax_highlight = short diff --git a/docs/source/faq.rst b/docs/source/faq.rst new file mode 100644 index 00000000..6ca1d92c --- /dev/null +++ b/docs/source/faq.rst @@ -0,0 +1,57 @@ + +.. _faq: + +Frequently Asked Questions +========================== + +Q: How can I copy & paste without decorations? +---------------------------------------------- + +:Answer: There are a few ways to do this: + + * Use the :ref:`bookmark` hotkeys to mark lines and then + press :kbd:`c` to copy to the local system keyboard. + + * Press :kbd:`CTRL` + :kbd:`l` to temporarily switch to "lo-fi" + mode where the contents of the current view are printed to the terminal. + This option is useful when you are logged into a remote host. + + +Q: How can I force a format for a file? +--------------------------------------- + +:Answer: The log format for a file is automatically detected and cannot be + forced. + +:Solution: Add some of the log file lines to the :ref:`sample` + array and then startup lnav to get a detailed explanation of where the format + patterns are not matching the sample lines. + +:Details: The first lines of the file are matched against the + :ref:`regular expressions defined in the format definitions`. + The order of the formats is automatically determined so that more specific + formats are tried before more generic ones. Therefore, if the expected + format is not being chosen for a file, then it means the regular expressions + defined by that format are not matching the first few lines of the file. + + See :ref:`format_order` for more information. + +Q: Why isn't my log file highlighted correctly? +----------------------------------------------- + +TBD + +Q: Why isn't a file being displayed? +------------------------------------ + +:Answer: Plaintext files are displayed separately from log files in the TEXT + view. + +:Solution: Press the :kbd:`t` key to switch to the text view. Or, open the + files configuration panel by pressing :kbd:`TAB` to cycle through the + panels, and then press :kbd:`/` to search for the file you're interested in. + If the file is a log, a new :ref:`log format` will need to be + created or an existing one modified. + +:Details: If a file being monitored by lnav does not match a known log file + format, it is treated as plaintext and will be displayed in the TEXT view. diff --git a/docs/source/formats.rst b/docs/source/formats.rst index c5cd4f0d..07f98da4 100644 --- a/docs/source/formats.rst +++ b/docs/source/formats.rst @@ -62,6 +62,8 @@ fields: can be used to limit which files a format is applied to in case there is a potential for conflicts. + .. _format_regex: + :regex: This object contains sub-objects that describe the message formats to match in a plain log file. Log files that contain JSON messages should not specify this field. @@ -218,6 +220,8 @@ fields: SELECT message FROM http_status_codes WHERE status = :sc_status) || ') ' + .. _format_sample: + :sample: A list of objects that contain sample log messages. All formats must include at least one sample and it must be matched by one of the included regexes. Each object must contain the following field: @@ -377,6 +381,7 @@ Executing the format file should then install it automatically: $ ./myformat.json info: installed: /home/example/.lnav/formats/installed/myformat_log.json +.. _format_order: Format Order When Scanning a File --------------------------------- diff --git a/docs/source/hotkeys.rst b/docs/source/hotkeys.rst index 60e9d551..fbd264ff 100644 --- a/docs/source/hotkeys.rst +++ b/docs/source/hotkeys.rst @@ -1,6 +1,4 @@ -.. include:: kbd.rst - .. _hotkeys: Hotkey Reference @@ -21,86 +19,86 @@ Spatial Navigation - - - Command - * - |ks| Space |ke| - - |ks| PgDn |ke| + * - :kbd:`Space` + - :kbd:`PgDn` - - Down a page - * - |ks| b |ke| - - |ks| Backspace |ke| - - |ks| PgUp |ke| + * - :kbd:`b` + - :kbd:`Backspace` + - :kbd:`PgUp` - Up a page - * - |ks| j |ke| - - |ks| Return |ke| - - |ks| ↓ |ke| + * - :kbd:`j` + - :kbd:`Return` + - :kbd:`↓` - Down a line - * - |ks| k |ke| - - |ks| ↑ |ke| + * - :kbd:`k` + - :kbd:`↑` - - Up a line - * - |ks| h |ke| - - |ks| ← |ke| + * - :kbd:`h` + - :kbd:`←` - - Left half a page. In the log view, pressing left while at the start of the message text will reveal the source file name for each line. Pressing again will reveal the full path. - * - |ks| Shift |ke| + |ks| h |ke| - - |ks| Shift |ke| + |ks| ← |ke| + * - :kbd:`Shift` + :kbd:`h` + - :kbd:`Shift` + :kbd:`←` - - Left ten columns - * - |ks| l |ke| - - |ks| → |ke| + * - :kbd:`l` + - :kbd:`→` - - Right half a page - * - |ks| Shift |ke| + |ks| l |ke| - - |ks| Shift |ke| + |ks| → |ke| + * - :kbd:`Shift` + :kbd:`l` + - :kbd:`Shift` + :kbd:`→` - - Right ten columns - * - |ks| Home |ke| - - |ks| g |ke| + * - :kbd:`Home` + - :kbd:`g` - - Top of the view - * - |ks| End |ke| - - |ks| G |ke| + * - :kbd:`End` + - :kbd:`G` - - Bottom of the view - * - |ks| e |ke| - - |ks| Shift |ke| + |ks| e |ke| + * - :kbd:`e` + - :kbd:`Shift` + :kbd:`e` - - Next/previous error - * - |ks| w |ke| - - |ks| Shift |ke| + |ks| w |ke| + * - :kbd:`w` + - :kbd:`Shift` + :kbd:`w` - - Next/previous warning - * - |ks| n |ke| - - |ks| Shift |ke| + |ks| n |ke| + * - :kbd:`n` + - :kbd:`Shift` + :kbd:`n` - - Next/previous search hit - * - |ks| > |ke| - - |ks| < |ke| + * - :kbd:`>` + - :kbd:`<` - - Next/previous search hit (horizontal) - * - |ks| f |ke| - - |ks| Shift |ke| + |ks| f |ke| + * - :kbd:`f` + - :kbd:`Shift` + :kbd:`f` - - Next/previous file - * - |ks| u |ke| - - |ks| Shift |ke| + |ks| u |ke| + * - :kbd:`u` + - :kbd:`Shift` + :kbd:`u` - - Next/previous bookmark - * - |ks| o |ke| - - |ks| Shift |ke| + |ks| o |ke| + * - :kbd:`o` + - :kbd:`Shift` + :kbd:`o` - - Forward/backward through log messages with a matching "opid" field - * - |ks| y |ke| - - |ks| Shift |ke| + |ks| y |ke| + * - :kbd:`y` + - :kbd:`Shift` + :kbd:`y` - - - Next/prevous SQL result - * - |ks| s |ke| - - |ks| Shift |ke| + |ks| s |ke| + - Next/previous SQL result + * - :kbd:`s` + - :kbd:`Shift` + :kbd:`s` - - - Next/prevous slow down in the log message rate - * - |ks| { |ke| - - |ks| } |ke| + - Next/previous slow down in the log message rate + * - :kbd:`{` + - :kbd:`}` - - Previous/next location in history @@ -114,22 +112,25 @@ Chronological Navigation * - Keypress - - Command - * - |ks| d |ke| - - |ks| Shift |ke| + |ks| d |ke| + * - :kbd:`d` + - :kbd:`Shift` + :kbd:`d` - Forward/backward 24 hours - * - |ks| 1 |ke| - |ks| 6 |ke| - - |ks| Shift |ke| + |ks| 1 |ke| - |ks| 6 |ke| + * - :kbd:`1` - :kbd:`6` + - :kbd:`Shift` + :kbd:`1` - :kbd:`6` - Next/previous n'th ten minute of the hour - * - |ks| 7 |ke| - - |ks| 8 |ke| + * - :kbd:`7` + - :kbd:`8` - Previous/next minute - * - |ks| 0 |ke| - - |ks| Shift |ke| + |ks| 0 |ke| + * - :kbd:`0` + - :kbd:`Shift` + :kbd:`0` - Next/previous day - * - |ks| r |ke| - - |ks| Shift |ke| + |ks| r |ke| + * - :kbd:`r` + - :kbd:`Shift` + :kbd:`r` - Forward/backward by the relative time that was last used with the goto command. + +.. _hotkeys_bookmarks: + Bookmarks --------- @@ -139,17 +140,17 @@ Bookmarks * - Keypress - Command - * - |ks| m |ke| + * - :kbd:`m` - Mark/unmark the top line - * - |ks| Shift |ke| + |ks| m |ke| + * - :kbd:`Shift` + :kbd:`m` - Mark/unmark the range of lines from the last marked to the top - * - |ks| Shift |ke| + |ks| j |ke| + * - :kbd:`Shift` + :kbd:`j` - Mark/unmark the next line after the previously marked - * - |ks| Shift |ke| + |ks| k |ke| + * - :kbd:`Shift` + :kbd:`k` - Mark/unmark the previous line - * - |ks| c |ke| + * - :kbd:`c` - Copy marked lines to the clipboard - * - |ks| Shift |ke| + |ks| c |ke| + * - :kbd:`Shift` + :kbd:`c` - Clear marked lines Display @@ -161,51 +162,51 @@ Display * - Keypress - Command - * - |ks| ? |ke| + * - :kbd:`?` - View/leave builtin help - * - |ks| q |ke| + * - :kbd:`q` - Return to the previous view/quit - * - |ks| Shift |ke| + |ks| q |ke| + * - :kbd:`Shift` + :kbd:`q` - Return to the previous view/quit while matching the top times of the two views - * - |ks| a |ke| + * - :kbd:`a` - Restore the view that was previously popped with 'q/Q' - * - |ks| Shift |ke| + |ks| a |ke| + * - :kbd:`Shift` + :kbd:`a` - Restore the view that was previously popped with 'q/Q' and match the top times of the views - * - |ks| Shift |ke| + |ks| p |ke| + * - :kbd:`Shift` + :kbd:`p` - Switch to/from the pretty-printed view of the displayed log or text files - * - |ks| Shift |ke| + |ks| t |ke| + * - :kbd:`Shift` + :kbd:`t` - Display elapsed time between lines - * - |ks| t |ke| + * - :kbd:`t` - Switch to/from the text file view - * - |ks| i |ke| + * - :kbd:`i` - Switch to/from the histogram view - * - |ks| Shift |ke| + |ks| i |ke| + * - :kbd:`Shift` + :kbd:`i` - Switch to/from the histogram view - * - |ks| v |ke| + * - :kbd:`v` - Switch to/from the SQL result view - * - |ks| Shift |ke| + |ks| v |ke| + * - :kbd:`Shift` + :kbd:`v` - Switch to/from the SQL result view and move to the corresponding in the log_line column - * - |ks| p |ke| + * - :kbd:`p` - Toggle the display of the log parser results - * - |ks| Tab |ke| + * - :kbd:`Tab` - In the log/text views, focus on the configuration panel for editing filters and examining the list of loaded files. In the SQL result view, cycle through columns to display as bar graphs - * - |ks| Ctrl |ke| + |ks| l |ke| + * - :kbd:`Ctrl` + :kbd:`l` - Switch to lo-fi mode. The displayed log lines will be dumped to the terminal without any decorations so they can be copied easily. - * - |ks| Ctrl |ke| + |ks| w |ke| + * - :kbd:`Ctrl` + :kbd:`w` - Toggle word-wrap. - * - |ks| Ctrl |ke| + |ks| p |ke| + * - :kbd:`Ctrl` + :kbd:`p` - Show/hide the data preview panel that may be opened when entering commands or SQL queries. - * - |ks| Ctrl |ke| + |ks| f |ke| + * - :kbd:`Ctrl` + :kbd:`f` - Toggle the enabled/disabled state of all filters in the current view. - * - |ks| x |ke| + * - :kbd:`x` - Toggle the hiding of log message fields. The hidden fields will be replaced with three bullets and highlighted in yellow. - * - |ks| = |ke| + * - :kbd:`=` - Pause/unpause loading of new file data. Session @@ -217,11 +218,11 @@ Session * - Keypress - Command - * - |ks| Ctrl |ke| + |ks| R |ke| + * - :kbd:`Ctrl` + :kbd:`R` - Reset current session. -Query ------ +Query Prompts +------------- .. list-table:: :header-rows: 1 @@ -229,15 +230,15 @@ Query * - Keypress - Command - * - |ks| / |ke| + * - :kbd:`/` - Search for lines matching a regular expression - * - |ks| ; |ke| - - Execute an SQL query - * - |ks| : |ke| + * - :kbd:`;` + - Open the :ref:`sql-ext` to execute SQL statements/queries + * - :kbd:`:` - Execute an internal command, see :ref:`commands` for more information - * - |ks| \| |ke| - - Execute an lnav script located in a format directory. - * - |ks| Ctrl |ke| + |ks| ] |ke| + * - :kbd:`\|` + - Execute an lnav script located in a format directory + * - :kbd:`Ctrl` + :kbd:`]` - Abort the prompt Customizing diff --git a/docs/source/index.rst b/docs/source/index.rst index ff9eab6b..dbe892ab 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -18,16 +18,17 @@ Contents: usage cookbook howitworks + config cli ui hotkeys - config formats sessions commands sqlext sqltab data + faq Indices and tables diff --git a/docs/source/intro.rst b/docs/source/intro.rst index 0734bc24..2379ecb1 100644 --- a/docs/source/intro.rst +++ b/docs/source/intro.rst @@ -1,6 +1,4 @@ -.. include:: kbd.rst - Introduction ============ @@ -27,13 +25,14 @@ When compiling from source, the following dependencies are required: * `Bzip2 `_ * `Readline `_ * `libcurl `_ +* `libarchive `_ Installation ------------ Check the `downloads page `_ to see if there are -packages for your operating system. Compiling from source is just a matter of -doing: +packages for your operating system. To compile from source, use the following +commands: .. prompt:: bash @@ -70,7 +69,7 @@ Setup After starting **lnav**, you might want to set the :ref:`configuration options` mentioned below. Configuration in **lnav** is done using the :code:`:config` command. To change a configuration -option, start by pressing |ks|:|ke| to enter the command prompt. Then, +option, start by pressing :kbd:`:` to enter the command prompt. Then, type "config" followed by the option name and value. .. note:: @@ -113,6 +112,7 @@ command can be used to the change the theme: The builtin themes are: `default `_, `eldar `_, +`grayscale `_, `monocai `_, `night-owl `_, `solarized-dark `_, diff --git a/docs/source/kbd.rst b/docs/source/kbd.rst deleted file mode 100644 index 990303cc..00000000 --- a/docs/source/kbd.rst +++ /dev/null @@ -1,32 +0,0 @@ - -.. |ks| raw:: html - - - -.. |ke| raw:: html - - - -.. raw:: html - - diff --git a/docs/source/sqlext.rst b/docs/source/sqlext.rst index 62ebb9fd..38326cd2 100644 --- a/docs/source/sqlext.rst +++ b/docs/source/sqlext.rst @@ -1,6 +1,4 @@ -.. include:: kbd.rst - .. _sql-ext: SQLite Interface @@ -27,9 +25,9 @@ These columns would be available for its row in the :code:`access_log` table: results, but they can still be accessed when explicitly used. The hidden columns are: :code:`log_path`, :code:`log_text`, and :code:`log_body`. -You can activate the SQL prompt by pressing the |ks| ; |ke| key. At the +You can activate the SQL prompt by pressing the :kbd:`;` key. At the prompt, you can start typing in the desired SQL statement and/or double-tap -|ks| TAB |ke| to activate auto-completion. A help window will appear above +:kbd:`TAB` to activate auto-completion. A help window will appear above the prompt to guide you in the usage of SQL keywords and functions. .. figure:: sql-help.png @@ -49,12 +47,12 @@ and maximum number of bytes returned by the server, grouped by IP address: ;SELECT c_ip, avg(sc_bytes), max(sc_bytes) FROM access_log GROUP BY c_ip -After pressing |ks| Enter |ke|, SQLite will execute the query using **lnav**'s +After pressing :kbd:`Enter`, SQLite will execute the query using **lnav**'s virtual table implementation to extract the data directly from the log files. Once the query has finished, the main window will switch to the DB view to -show the results. Press |ks| q |ke| to return to the log view and press |ks| -v |ke| to return to the log view. If the SQL results contain a -:code:`log_line` column, you can press to |ks| Shift |ke| + |ks| V |ke| to +show the results. Press :kbd:`q` to return to the log view and press :kbd:`v` +to return to the log view. If the SQL results contain a +:code:`log_line` column, you can press to :kbd:`Shift` + :kbd:`V` to switch between the DB view and the log .. figure:: query-results.png @@ -66,9 +64,9 @@ The DB view has the following display features: * Column headers stick to the top of the view when scrolling. * A stacked bar chart of the numeric column values is displayed underneath the - rows. Pressing |ks| TAB |ke| will cycle through displaying no columns, each + rows. Pressing :kbd:`TAB` will cycle through displaying no columns, each individual column, or all columns. -* JSON columns in the top row can be pretty-printed by pressing |ks| p |ke|. +* JSON columns in the top row can be pretty-printed by pressing :kbd:`p`. The display will show the value and JSON-Pointer path that can be passed to the `jget`_ function. @@ -144,7 +142,7 @@ the current IP is different from the previous IP: Since the above can be a lot to type out interactively, you can put these commands into a :ref:`script` and execute that script with the -|ks| \| |ke| hotkey. +:kbd:`\|` hotkey. .. [#] The expression :code:`regexp_match('bound to ([^ ]+)', log_body) as ip` can be used to extract the IP address from the log message body. diff --git a/docs/source/usage.rst b/docs/source/usage.rst index ce93c2d6..32258527 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -1,4 +1,3 @@ -.. include:: kbd.rst .. _usage: @@ -13,8 +12,8 @@ Basic Controls Like most file viewers, scrolling through files can be done with the usual :ref:`hotkeys`. For non-trivial operations, you can enter the -:ref:`command` prompt by pressing |ks| : |ke|. To analyze data in a -log file, you can enter the :ref:`SQL prompt` by pressing |ks| ; |ke|. +:ref:`command` prompt by pressing :kbd:`:`. To analyze data in a +log file, you can enter the :ref:`SQL prompt` by pressing :kbd:`;`. .. tip:: @@ -24,8 +23,8 @@ log file, you can enter the :ref:`SQL prompt` by pressing |ks| ; |ke|. .. figure:: hotkey-tips.png :align: center - When **lnav** is first open, it suggests using |ks| e |ke| and - |ks| Shift |ke| + |ks| e |ke| to jump to error messages. + When **lnav** is first open, it suggests using :kbd:`e` and + :kbd:`Shift` + :kbd:`e` to jump to error messages. Viewing Files @@ -42,7 +41,7 @@ extracted to a temporary location and the files within will be loaded. The files that are found will be scanned to identify their file format. Files that match a log format will be collated by time and displayed in the LOG view. Plain text files can be viewed in the TEXT view, which can be accessed -by pressing |ks| t |ke|. +by pressing :kbd:`t`. Archive Support @@ -71,13 +70,15 @@ Searching Any log messages that are loaded into **lnav** are indexed by time and log level (e.g. error, warning) to make searching quick and easy with -:ref:`hotkeys`. For example, pressing |ks| e |ke| will jump to the -next error in the file and pressing |ks| Shift |ke| + |ks| e |ke| will jump to -the previous error. Plain text searches can be done by pressing |ks| / |ke| +:ref:`hotkeys`. For example, pressing :kbd:`e` will jump to the +next error in the file and pressing :kbd:`Shift` + :kbd:`e` will jump to +the previous error. Plain text searches can be done by pressing :kbd:`/` to enter the search prompt. A regular expression can be entered into the prompt to start a search through the current view. +.. _filtering: + Filtering --------- @@ -126,6 +127,8 @@ Log level To hide messages below a certain log level, you can use the :ref:`:set-min-log-level`. +.. _search_tables: + Search Tables ------------- diff --git a/release/README.md b/release/README.md new file mode 100644 index 00000000..1832b2af --- /dev/null +++ b/release/README.md @@ -0,0 +1,4 @@ +# Release + +This directory contains the [Makefile](Makefile) and scripts used to build the +binaries for a release. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ae6412c..5c1c1dce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -171,6 +171,7 @@ set(CONFIG_FILES keymaps/uk-keymap.json keymaps/us-keymap.json themes/default-theme.json + themes/grayscale.json themes/eldar.json themes/monocai.json themes/night-owl.json diff --git a/src/Makefile.am b/src/Makefile.am index c93dfbff..e048befc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,80 +21,28 @@ RE2C_V = $(RE2C_V_@AM_V@) RE2C_V_ = $(RE2C_V_@AM_DEFAULT_V@) RE2C_V_0 = @echo " RE2C " $@; -FORMAT_FILES = \ - $(srcdir)/formats/access_log.json \ - $(srcdir)/formats/alb_log.json \ - $(srcdir)/formats/autodeploy_log.json \ - $(srcdir)/formats/block_log.json \ - $(srcdir)/formats/candlepin_log.json \ - $(srcdir)/formats/choose_repo_log.json \ - $(srcdir)/formats/cups_log.json \ - $(srcdir)/formats/dpkg_log.json \ - $(srcdir)/formats/elb_log.json \ - $(srcdir)/formats/engine_log.json \ - $(srcdir)/formats/error_log.json \ - $(srcdir)/formats/fsck_hfs_log.json \ - $(srcdir)/formats/glog_log.json \ - $(srcdir)/formats/haproxy_log.json \ - $(srcdir)/formats/java_log.json \ - $(srcdir)/formats/journald_json_log.json \ - $(srcdir)/formats/katello_log.json \ - $(srcdir)/formats/openam_log.json \ - $(srcdir)/formats/openamdb_log.json \ - $(srcdir)/formats/openstack_log.json \ - $(srcdir)/formats/page_log.json \ - $(srcdir)/formats/papertrail_log.json \ - $(srcdir)/formats/snaplogic_log.json \ - $(srcdir)/formats/sssd_log.json \ - $(srcdir)/formats/strace_log.json \ - $(srcdir)/formats/sudo_log.json \ - $(srcdir)/formats/syslog_log.json \ - $(srcdir)/formats/s3_log.json \ - $(srcdir)/formats/tcf_log.json \ - $(srcdir)/formats/tcsh_history.json \ - $(srcdir)/formats/uwsgi_log.json \ - $(srcdir)/formats/vdsm_log.json \ - $(srcdir)/formats/vmk_log.json \ - $(srcdir)/formats/vmw_log.json \ - $(srcdir)/formats/xmlrpc_log.json \ - $() +include formats/formats.am default-formats.h default-formats.cc: bin2c$(BUILD_EXEEXT) $(FORMAT_FILES) $(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_format_json default-formats $(FORMAT_FILES) +include keymaps/keymaps.am +include themes/themes.am + CONFIG_FILES = \ $(srcdir)/root-config.json \ - $(srcdir)/keymaps/de-keymap.json \ - $(srcdir)/keymaps/default-keymap.json \ - $(srcdir)/keymaps/fr-keymap.json \ - $(srcdir)/keymaps/uk-keymap.json \ - $(srcdir)/keymaps/us-keymap.json \ - $(srcdir)/themes/default-theme.json \ - $(srcdir)/themes/eldar.json \ - $(srcdir)/themes/monocai.json \ - $(srcdir)/themes/night-owl.json \ - $(srcdir)/themes/solarized-dark.json \ - $(srcdir)/themes/solarized-light.json \ + $(KEYMAP_FILES) \ + $(THEME_FILES) \ $() default-config.h default-config.cc: bin2c$(BUILD_EXEEXT) $(CONFIG_FILES) $(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_config_json default-config $(CONFIG_FILES) -BUILTIN_LNAVSCRIPTS = \ - $(srcdir)/scripts/dhclient-summary.lnav \ - $(srcdir)/scripts/lnav-pop-view.lnav \ - $(srcdir)/scripts/partition-by-boot.lnav \ - $(srcdir)/scripts/rename-stdin.lnav \ - $(srcdir)/scripts/search-for.lnav \ - $() +include scripts/scripts.am builtin-scripts.h builtin-scripts.cc: bin2c$(BUILD_EXEEXT) $(BUILTIN_LNAVSCRIPTS) $(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_scripts builtin-scripts $(BUILTIN_LNAVSCRIPTS) -BUILTIN_SHSCRIPTS = \ - $(srcdir)/scripts/dump-pid.sh \ - $() - builtin-sh-scripts.h builtin-sh-scripts.cc: bin2c$(BUILD_EXEEXT) $(BUILTIN_SHSCRIPTS) $(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_sh_scripts builtin-sh-scripts $(BUILTIN_SHSCRIPTS) diff --git a/src/archive_manager.cc b/src/archive_manager.cc index bb3fa95d..d4643ff1 100644 --- a/src/archive_manager.cc +++ b/src/archive_manager.cc @@ -99,15 +99,21 @@ bool is_archive(const fs::path& filename) archive_read_support_filter_all(arc); archive_read_support_format_all(arc); archive_read_support_format_raw(arc); - auto r = archive_read_open_filename(arc, filename.c_str(), 16384); + log_debug("read open %s", filename.c_str()); + auto r = archive_read_open_filename(arc, filename.c_str(), 128 * 1024); if (r == ARCHIVE_OK) { struct archive_entry *entry; + auto format_name = archive_format_name(arc); + + log_debug("read next header %s %s", format_name, filename.c_str()); if (archive_read_next_header(arc, &entry) == ARCHIVE_OK) { + log_debug("read next done %s", filename.c_str()); + static const auto RAW_FORMAT_NAME = string_fragment("raw"); static const auto GZ_FILTER_NAME = string_fragment("gzip"); - auto format_name = archive_format_name(arc); + format_name = archive_format_name(arc); if (RAW_FORMAT_NAME == format_name) { auto filter_count = archive_filter_count(arc); diff --git a/src/base/date_time_scanner.cc b/src/base/date_time_scanner.cc index 8d22f693..5089be3d 100644 --- a/src/base/date_time_scanner.cc +++ b/src/base/date_time_scanner.cc @@ -34,7 +34,7 @@ #include "date_time_scanner.hh" #include "ptimec.hh" -size_t date_time_scanner::ftime(char *dst, size_t len, const exttm &tm) +size_t date_time_scanner::ftime(char *dst, size_t len, const exttm &tm) const { off_t off = 0; diff --git a/src/base/date_time_scanner.hh b/src/base/date_time_scanner.hh index 1ba623df..f95f525a 100644 --- a/src/base/date_time_scanner.hh +++ b/src/base/date_time_scanner.hh @@ -120,7 +120,7 @@ struct date_time_scanner { struct timeval &tv_out, bool convert_local = true); - size_t ftime(char *dst, size_t len, const struct exttm &tm);; + size_t ftime(char *dst, size_t len, const struct exttm &tm) const; bool convert_to_timeval(const char *time_src, ssize_t time_len, diff --git a/src/base/file_range.hh b/src/base/file_range.hh index 4b05d832..517bb4a2 100644 --- a/src/base/file_range.hh +++ b/src/base/file_range.hh @@ -34,10 +34,14 @@ #include "intern_string.hh" +using file_off_t = int64_t; +using file_size_t = uint64_t; +using file_ssize_t = int64_t; + class file_range { public: - off_t fr_offset{0}; - ssize_t fr_size{0}; + file_off_t fr_offset{0}; + file_ssize_t fr_size{0}; void clear() { this->fr_offset = 0; diff --git a/src/bottom_status_source.cc b/src/bottom_status_source.cc index 4b3ff031..fa751bfa 100644 --- a/src/bottom_status_source.cc +++ b/src/bottom_status_source.cc @@ -159,9 +159,9 @@ void bottom_status_source::update_hits(textview_curses *tc) this->update_marks(tc); } -void bottom_status_source::update_loading(off_t off, size_t total) +void bottom_status_source::update_loading(file_off_t off, file_size_t total) { - status_field &sf = this->bss_fields[BSF_LOADING]; + auto &sf = this->bss_fields[BSF_LOADING]; require(off >= 0); diff --git a/src/bottom_status_source.hh b/src/bottom_status_source.hh index 986bb1b1..c2592885 100644 --- a/src/bottom_status_source.hh +++ b/src/bottom_status_source.hh @@ -103,7 +103,7 @@ public: void update_hits(textview_curses *tc); - void update_loading(off_t off, size_t total); + void update_loading(file_off_t off, file_size_t total); private: status_field bss_prompt{1024, view_colors::VCR_STATUS}; diff --git a/src/files_sub_source.cc b/src/files_sub_source.cc index 4cfc68d4..d3c2bdbe 100644 --- a/src/files_sub_source.cc +++ b/src/files_sub_source.cc @@ -283,9 +283,6 @@ void files_sub_source::text_attrs_for_line(textview_curses &tc, int line, (int) filename_width + 3 + 4, (int) filename_width + 3 + 10, }; - value_out.emplace_back(lr, &view_curses::VC_FOREGROUND, COLOR_WHITE); - lr.lr_start = lr.lr_end; - lr.lr_end += 2; value_out.emplace_back(lr, &view_curses::VC_STYLE, A_BOLD); } diff --git a/src/filter_observer.hh b/src/filter_observer.hh index b1f80e8a..6936b779 100644 --- a/src/filter_observer.hh +++ b/src/filter_observer.hh @@ -42,7 +42,7 @@ public: }; - void logline_restart(const logfile &lf, size_t rollback_size) { + void logline_restart(const logfile &lf, file_size_t rollback_size) { for (auto &filter : this->lfo_filter_stack) { filter->revert_to_last(this->lfo_filter_state, rollback_size); } diff --git a/src/filter_sub_source.cc b/src/filter_sub_source.cc index a76586df..2dccac72 100644 --- a/src/filter_sub_source.cc +++ b/src/filter_sub_source.cc @@ -305,7 +305,11 @@ void filter_sub_source::text_value_for_line(textview_curses &tc, int line, value_out.append(" IN "); break; case text_filter::EXCLUDE: - value_out.append("OUT "); + if (tf->get_lang() == filter_lang_t::REGEX) { + value_out.append("OUT "); + } else { + value_out.append(" "); + } break; default: ensure(0); diff --git a/src/formats/README.md b/src/formats/README.md index 519e2693..518dff8d 100644 --- a/src/formats/README.md +++ b/src/formats/README.md @@ -1,4 +1,5 @@ # Formats This directory contains the built-in log file format definitions. These files -are converted to C by `bin2c` and compiled into the executable. +are converted to C by `bin2c` and compiled into the executable. New formats +need to be added to the [formats.am](formats.am) file. diff --git a/src/formats/formats.am b/src/formats/formats.am new file mode 100644 index 00000000..74be15cb --- /dev/null +++ b/src/formats/formats.am @@ -0,0 +1,38 @@ + +FORMAT_FILES = \ + $(srcdir)/%reldir%/access_log.json \ + $(srcdir)/%reldir%/alb_log.json \ + $(srcdir)/%reldir%/autodeploy_log.json \ + $(srcdir)/%reldir%/block_log.json \ + $(srcdir)/%reldir%/candlepin_log.json \ + $(srcdir)/%reldir%/choose_repo_log.json \ + $(srcdir)/%reldir%/cups_log.json \ + $(srcdir)/%reldir%/dpkg_log.json \ + $(srcdir)/%reldir%/elb_log.json \ + $(srcdir)/%reldir%/engine_log.json \ + $(srcdir)/%reldir%/error_log.json \ + $(srcdir)/%reldir%/fsck_hfs_log.json \ + $(srcdir)/%reldir%/glog_log.json \ + $(srcdir)/%reldir%/haproxy_log.json \ + $(srcdir)/%reldir%/java_log.json \ + $(srcdir)/%reldir%/journald_json_log.json \ + $(srcdir)/%reldir%/katello_log.json \ + $(srcdir)/%reldir%/openam_log.json \ + $(srcdir)/%reldir%/openamdb_log.json \ + $(srcdir)/%reldir%/openstack_log.json \ + $(srcdir)/%reldir%/page_log.json \ + $(srcdir)/%reldir%/papertrail_log.json \ + $(srcdir)/%reldir%/snaplogic_log.json \ + $(srcdir)/%reldir%/sssd_log.json \ + $(srcdir)/%reldir%/strace_log.json \ + $(srcdir)/%reldir%/sudo_log.json \ + $(srcdir)/%reldir%/syslog_log.json \ + $(srcdir)/%reldir%/s3_log.json \ + $(srcdir)/%reldir%/tcf_log.json \ + $(srcdir)/%reldir%/tcsh_history.json \ + $(srcdir)/%reldir%/uwsgi_log.json \ + $(srcdir)/%reldir%/vdsm_log.json \ + $(srcdir)/%reldir%/vmk_log.json \ + $(srcdir)/%reldir%/vmw_log.json \ + $(srcdir)/%reldir%/xmlrpc_log.json \ + $() diff --git a/src/help_text_formatter.cc b/src/help_text_formatter.cc index 7111c069..312d16ef 100644 --- a/src/help_text_formatter.cc +++ b/src/help_text_formatter.cc @@ -569,7 +569,7 @@ void format_help_text_for_rst(const help_text &ht, } if (param_count > 0) { - fprintf(rst_file, " **Parameters:**\n\n"); + fprintf(rst_file, " **Parameters**\n"); for (auto ¶m: ht.ht_parameters) { if (param.ht_summary && param.ht_summary[0]) { fprintf(rst_file, " * **%s%s** --- %s\n", @@ -584,7 +584,7 @@ void format_help_text_for_rst(const help_text &ht, prefix = ";"; } if (!ht.ht_example.empty()) { - fprintf(rst_file, " **Examples:**\n\n"); + fprintf(rst_file, " **Examples**\n"); for (auto &example: ht.ht_example) { fprintf(rst_file, " %s:\n\n", example.he_description); fprintf(rst_file, " .. code-block:: %s\n\n", @@ -616,7 +616,7 @@ void format_help_text_for_rst(const help_text &ht, } stable_sort(related_refs.begin(), related_refs.end()); - fmt::print(rst_file, " **See Also:**\n\n {}\n", + fmt::print(rst_file, " **See Also**\n {}\n", fmt::join(related_refs, ", ")); } diff --git a/src/highlighter.cc b/src/highlighter.cc index e8dad383..9d3e6cee 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -44,7 +44,6 @@ highlighter::highlighter(const highlighter &other) this->h_text_format = other.h_text_format; this->h_format_name = other.h_format_name; this->h_nestable = other.h_nestable; - this->h_semantic = other.h_semantic; } highlighter &highlighter::operator=(const highlighter &other) @@ -70,7 +69,6 @@ highlighter &highlighter::operator=(const highlighter &other) this->h_attrs = other.h_attrs; this->h_text_format = other.h_text_format; this->h_nestable = other.h_nestable; - this->h_semantic = other.h_semantic; return *this; } @@ -138,25 +136,6 @@ void highlighter::annotate(attr_line_t &al, int start) const if (this->h_attrs != -1) { attrs = this->h_attrs; } - if (this->h_semantic) { - bool found_color = false; - - if (str[lr.lr_start] == '#' && - (lr.length() == 4 || lr.length() == 7)) { - auto fg_res = rgb_color::from_str( - string_fragment(str.data(), lr.lr_start, lr.lr_end)); - if (fg_res.isOk()) { - sa.emplace_back(lr, - &view_curses::VC_FOREGROUND, - vc.match_color(fg_res.unwrap())); - found_color = true; - } - } - if (!found_color) { - attrs |= vc.attrs_for_ident(&str[lr.lr_start], - lr.length()); - } - } if (!this->h_fg.empty()) { sa.emplace_back(lr, &view_curses::VC_FOREGROUND, @@ -172,7 +151,9 @@ void highlighter::annotate(attr_line_t &al, int start) const &view_curses::VC_ROLE, this->h_role); } - sa.emplace_back(lr, &view_curses::VC_STYLE, attrs); + if (attrs) { + sa.emplace_back(lr, &view_curses::VC_STYLE, attrs); + } off = matches[1]; } diff --git a/src/highlighter.hh b/src/highlighter.hh index 69104bd9..287ec412 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -93,7 +93,7 @@ struct highlighter { return *this; }; - highlighter &with_color(const rgb_color &fg, const rgb_color &bg) { + highlighter &with_color(const styling::color_unit &fg, const styling::color_unit &bg) { this->h_fg = fg; this->h_bg = bg; @@ -105,11 +105,6 @@ struct highlighter { return *this; } - highlighter &with_semantic(bool val) { - this->h_semantic = val; - return *this; - } - int get_attrs() const { ensure(this->h_attrs != -1); @@ -121,15 +116,14 @@ struct highlighter { std::string h_pattern; view_colors::role_t h_role{view_colors::VCR_NONE}; - rgb_color h_fg; - rgb_color h_bg; + styling::color_unit h_fg{styling::color_unit::make_empty()}; + styling::color_unit h_bg{styling::color_unit::make_empty()}; pcre *h_code; pcre_extra *h_code_extra; int h_attrs{-1}; text_format_t h_text_format{text_format_t::TF_UNKNOWN}; intern_string_t h_format_name; bool h_nestable{true}; - bool h_semantic{false}; }; #endif diff --git a/src/internals/cmd-ref.rst b/src/internals/cmd-ref.rst index 616c8e96..a8a8e32a 100644 --- a/src/internals/cmd-ref.rst +++ b/src/internals/cmd-ref.rst @@ -6,12 +6,10 @@ Change the timestamps of the top file to be relative to the given date - **Parameters:** - + **Parameters** * **timestamp\*** --- The new timestamp for the top line in the view - **Examples:** - + **Examples** To set the top timestamp to a given date: .. code-block:: lnav @@ -35,20 +33,17 @@ Display a message in the alternate command position - **Parameters:** - + **Parameters** * **msg\*** --- The message to display - **Examples:** - + **Examples** To display 'Press t to switch to the text view' on the bottom right: .. code-block:: lnav :alt-msg Press t to switch to the text view - **See Also:** - + **See Also** :ref:`echo`, :ref:`eval`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to` ---- @@ -61,20 +56,17 @@ Append marked lines in the current view to the given file - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to append to - **Examples:** - + **Examples** To append marked lines to the file /tmp/interesting-lines.txt: .. code-block:: lnav :append-to /tmp/interesting-lines.txt - **See Also:** - + **See Also** :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to` ---- @@ -87,8 +79,7 @@ Clear the comment attached to the top log line - **See Also:** - + **See Also** :ref:`comment`, :ref:`tag` ---- @@ -101,8 +92,7 @@ Clear the filter expression - **See Also:** - + **See Also** :ref:`filter_expr`, :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -115,20 +105,17 @@ Remove a previously set highlight regular expression - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression previously used with :highlight - **Examples:** - + **Examples** To clear the highlight with the pattern 'foobar': .. code-block:: lnav :clear-highlight foobar - **See Also:** - + **See Also** :ref:`enable_word_wrap`, :ref:`hide_fields`, :ref:`highlight` ---- @@ -163,20 +150,17 @@ Attach a comment to the top log line - **Parameters:** - + **Parameters** * **text\*** --- The comment text - **Examples:** - + **Examples** To add the comment 'This is where it all went wrong' to the top line: .. code-block:: lnav :comment This is where it all went wrong - **See Also:** - + **See Also** :ref:`clear_comment`, :ref:`tag` ---- @@ -189,13 +173,11 @@ Read or write a configuration option - **Parameters:** - + **Parameters** * **option\*** --- The path to the option to read or write * **value** --- The value to write. If not given, the current value is returned - **Examples:** - + **Examples** To read the configuration of the '/ui/clock-format' option: .. code-block:: lnav @@ -208,8 +190,7 @@ :config /ui/dim-text false - **See Also:** - + **See Also** :ref:`reset_config` ---- @@ -222,20 +203,17 @@ Create an SQL table using the top line of the log view as a template - **Parameters:** - + **Parameters** * **table-name\*** --- The name for the new table - **Examples:** - + **Examples** To create a logline-style table named 'task_durations': .. code-block:: lnav :create-logline-table task_durations - **See Also:** - + **See Also** :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to` ---- @@ -248,21 +226,18 @@ Create an SQL table based on a regex search - **Parameters:** - + **Parameters** * **table-name\*** --- The name of the table to create * **pattern** --- The regular expression used to capture the table columns. If not given, the current search pattern is used. - **Examples:** - + **Examples** To create a table named 'task_durations' that matches log messages with the pattern 'duration=(?\d+)': .. code-block:: lnav :create-search-table task_durations duration=(?\d+) - **See Also:** - + **See Also** :ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`delete_search_table`, :ref:`delete_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to` ---- @@ -286,20 +261,17 @@ Delete the filter created with :filter-in or :filter-out - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression to match - **Examples:** - + **Examples** To delete the filter with the pattern 'last message repeated': .. code-block:: lnav :delete-filter last message repeated - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -312,20 +284,17 @@ Delete a table created with create-logline-table - **Parameters:** - + **Parameters** * **table-name\*** --- The name of the table to delete - **Examples:** - + **Examples** To delete the logline-style table named 'task_durations': .. code-block:: lnav :delete-logline-table task_durations - **See Also:** - + **See Also** :ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to` ---- @@ -338,20 +307,17 @@ Create an SQL table based on a regex search - **Parameters:** - + **Parameters** * **table-name\*** --- The name of the table to create - **Examples:** - + **Examples** To delete the search table named 'task_durations': .. code-block:: lnav :delete-search-table task_durations - **See Also:** - + **See Also** :ref:`create_logline_table`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`create_search_table`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to` ---- @@ -364,20 +330,17 @@ Remove the given tags from all log lines - **Parameters:** - + **Parameters** * **tag** --- The tags to delete - **Examples:** - + **Examples** To remove the tags '#BUG123' and '#needs-review' from all log lines: .. code-block:: lnav :delete-tags #BUG123 #needs-review - **See Also:** - + **See Also** :ref:`comment`, :ref:`tag` ---- @@ -390,20 +353,17 @@ Disable a filter created with filter-in/filter-out - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression used in the filter command - **Examples:** - + **Examples** To disable the filter with the pattern 'last message repeated': .. code-block:: lnav :disable-filter last message repeated - **See Also:** - + **See Also** :ref:`enable_filter`, :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -416,8 +376,7 @@ Disable word-wrapping for the current view - **See Also:** - + **See Also** :ref:`enable_word_wrap`, :ref:`hide_fields`, :ref:`highlight` ---- @@ -430,20 +389,17 @@ Echo the given message - **Parameters:** - + **Parameters** * **msg\*** --- The message to display - **Examples:** - + **Examples** To output 'Hello, World!': .. code-block:: lnav :echo Hello, World! - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`eval`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to` ---- @@ -456,20 +412,17 @@ Enable a previously created and disabled filter - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression used in the filter command - **Examples:** - + **Examples** To enable the disabled filter with the pattern 'last message repeated': .. code-block:: lnav :enable-filter last message repeated - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -482,8 +435,7 @@ Enable word-wrapping for the current view - **See Also:** - + **See Also** :ref:`disable_word_wrap`, :ref:`hide_fields`, :ref:`highlight` ---- @@ -496,12 +448,10 @@ Evaluate the given command/query after doing environment variable substitution - **Parameters:** - + **Parameters** * **command\*** --- The command or query to perform substitution on. - **Examples:** - + **Examples** To output the user's home directory: .. code-block:: lnav @@ -514,8 +464,7 @@ :eval ;SELECT * FROM ${table} - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`echo`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to` ---- @@ -528,12 +477,10 @@ Set the filter expression - **Parameters:** - + **Parameters** * **expr\*** --- The SQL expression to evaluate for each log message. The message values can be accessed using column names prefixed with a colon - **Examples:** - + **Examples** To set a filter expression that matched syslog messages from 'syslogd': .. code-block:: lnav @@ -546,8 +493,7 @@ :filter-expr :log_body REGEXP 'id\d+' AND :log_body REGEXP 'foo' - **See Also:** - + **See Also** :ref:`clear_filter_expr`, :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -560,20 +506,17 @@ Only show lines that match the given regular expression in the current view - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression to match - **Examples:** - + **Examples** To filter out log messages that do not have the string 'dhclient': .. code-block:: lnav :filter-in dhclient - **See Also:** - + **See Also** :ref:`delete_filter`, :ref:`disable_filter`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -586,20 +529,17 @@ Remove lines that match the given regular expression in the current view - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression to match - **Examples:** - + **Examples** To filter out log messages that contain the string 'last message repeated': .. code-block:: lnav :filter-out last message repeated - **See Also:** - + **See Also** :ref:`delete_filter`, :ref:`disable_filter`, :ref:`filter_in`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -612,12 +552,10 @@ Go to the given location in the top view - **Parameters:** - + **Parameters** * **line#|N%|date\*** --- A line number, percent into the file, or a timestamp - **Examples:** - + **Examples** To go to line 22: .. code-block:: lnav @@ -636,8 +574,7 @@ :goto 2017-01-01 - **See Also:** - + **See Also** :ref:`next_location`, :ref:`next_mark`, :ref:`prev_location`, :ref:`prev_mark`, :ref:`relative_goto` ---- @@ -661,12 +598,10 @@ Hide log message fields by replacing them with an ellipsis - **Parameters:** - + **Parameters** * **field-name** --- The name of the field to hide in the format for the top log line. A qualified name can be used where the field name is prefixed by the format name and a dot to hide any field. - **Examples:** - + **Examples** To hide the log_procname fields in all formats: .. code-block:: lnav @@ -679,8 +614,7 @@ :hide-fields syslog_log.log_procname - **See Also:** - + **See Also** :ref:`enable_word_wrap`, :ref:`highlight`, :ref:`show_fields` ---- @@ -693,8 +627,7 @@ Hide the given file(s) and skip indexing until it is shown again. If no path is given, the current file in the view is hidden - **Parameters:** - + **Parameters** * **path** --- A path or glob pattern that specifies the files to hide @@ -708,12 +641,10 @@ Hide lines that come after the given date - **Parameters:** - + **Parameters** * **date\*** --- An absolute or relative date - **Examples:** - + **Examples** To hide the lines after the top line in the view: .. code-block:: lnav @@ -726,8 +657,7 @@ :hide-lines-after 6am - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`show_lines_before_and_after`, :ref:`toggle_filtering` ---- @@ -740,12 +670,10 @@ Hide lines that come before the given date - **Parameters:** - + **Parameters** * **date\*** --- An absolute or relative date - **Examples:** - + **Examples** To hide the lines before the top line in the view: .. code-block:: lnav @@ -758,8 +686,7 @@ :hide-lines-before 6am - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_unmarked_lines`, :ref:`show_lines_before_and_after`, :ref:`toggle_filtering` ---- @@ -772,8 +699,7 @@ Hide lines that have not been bookmarked - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`mark`, :ref:`next_mark`, :ref:`prev_mark`, :ref:`toggle_filtering` ---- @@ -786,20 +712,17 @@ Add coloring to log messages fragments that match the given regular expression - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression to match - **Examples:** - + **Examples** To highlight numbers with three or more digits: .. code-block:: lnav :highlight \d{3,} - **See Also:** - + **See Also** :ref:`clear_highlight`, :ref:`enable_word_wrap`, :ref:`hide_fields` ---- @@ -823,8 +746,7 @@ Toggle the bookmark state for the top line in the current view - **See Also:** - + **See Also** :ref:`hide_unmarked_lines`, :ref:`next_mark`, :ref:`prev_mark` ---- @@ -837,8 +759,7 @@ Move to the next position in the location history - **See Also:** - + **See Also** :ref:`goto`, :ref:`next_mark`, :ref:`prev_location`, :ref:`prev_mark`, :ref:`relative_goto` ---- @@ -851,20 +772,17 @@ Move to the next bookmark of the given type in the current view - **Parameters:** - + **Parameters** * **type\*** --- The type of bookmark -- error, warning, search, user, file, meta - **Examples:** - + **Examples** To go to the next error: .. code-block:: lnav :next-mark error - **See Also:** - + **See Also** :ref:`goto`, :ref:`hide_unmarked_lines`, :ref:`mark`, :ref:`next_location`, :ref:`prev_location`, :ref:`prev_mark`, :ref:`prev_mark`, :ref:`relative_goto` ---- @@ -877,12 +795,10 @@ Open the given file(s) or URLs in lnav - **Parameters:** - + **Parameters** * **path** --- The path to the file to open - **Examples:** - + **Examples** To open the file '/path/to/file': .. code-block:: lnav @@ -900,12 +816,10 @@ Mark the top line in the log view as the start of a new partition with the given name - **Parameters:** - + **Parameters** * **name\*** --- The name for the new partition - **Examples:** - + **Examples** To mark the top line as the start of the partition named 'boot #1': .. code-block:: lnav @@ -923,20 +837,17 @@ Pipe the top line to the given shell command - **Parameters:** - + **Parameters** * **shell-cmd\*** --- The shell command-line to execute - **Examples:** - + **Examples** To write the top line to 'sed' for processing: .. code-block:: lnav :pipe-line-to sed -e 's/foo/bar/g' - **See Also:** - + **See Also** :ref:`append_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to` ---- @@ -949,20 +860,17 @@ Pipe the marked lines to the given shell command - **Parameters:** - + **Parameters** * **shell-cmd\*** --- The shell command-line to execute - **Examples:** - + **Examples** To write marked lines to 'sed' for processing: .. code-block:: lnav :pipe-to sed -e s/foo/bar/g - **See Also:** - + **See Also** :ref:`append_to`, :ref:`pipe_line_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_to` ---- @@ -975,8 +883,7 @@ Move to the previous position in the location history - **See Also:** - + **See Also** :ref:`goto`, :ref:`next_location`, :ref:`next_mark`, :ref:`prev_mark`, :ref:`relative_goto` ---- @@ -989,20 +896,17 @@ Move to the previous bookmark of the given type in the current view - **Parameters:** - + **Parameters** * **type\*** --- The type of bookmark -- error, warning, search, user, file, meta - **Examples:** - + **Examples** To go to the previous error: .. code-block:: lnav :prev-mark error - **See Also:** - + **See Also** :ref:`goto`, :ref:`hide_unmarked_lines`, :ref:`mark`, :ref:`next_location`, :ref:`next_mark`, :ref:`next_mark`, :ref:`prev_location`, :ref:`relative_goto` ---- @@ -1015,15 +919,13 @@ Open the given prompt - **Parameters:** - + **Parameters** * **type\*** --- The type of prompt -- command, script, search, sql, user * **--alt** --- Perform the alternate action for this prompt by default * **prompt** --- The prompt to display * **initial-value** --- The initial value to fill in for the prompt - **Examples:** - + **Examples** To open the command prompt with 'filter-in' already filled in: .. code-block:: lnav @@ -1080,20 +982,17 @@ Redirect the output of commands to the given file - **Parameters:** - + **Parameters** * **path** --- The path to the file to write. If not specified, the current redirect will be cleared - **Examples:** - + **Examples** To write the output of lnav commands to the file /tmp/script-output.txt: .. code-block:: lnav :redirect-to /tmp/script-output.txt - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1117,12 +1016,10 @@ Move the current view up or down by the given amount - **Parameters:** - + **Parameters** * **line-count|N%\*** --- The amount to move the view by. - **Examples:** - + **Examples** To move 22 lines down in the view: .. code-block:: lnav @@ -1135,8 +1032,7 @@ :relative-goto -10% - **See Also:** - + **See Also** :ref:`goto`, :ref:`next_location`, :ref:`next_mark`, :ref:`prev_location`, :ref:`prev_mark` ---- @@ -1149,20 +1045,17 @@ Reset the configuration option to its default value - **Parameters:** - + **Parameters** * **option\*** --- The path to the option to reset - **Examples:** - + **Examples** To reset the '/ui/clock-format' option back to the builtin default: .. code-block:: lnav :reset-config /ui/clock-format - **See Also:** - + **See Also** :ref:`config` ---- @@ -1197,12 +1090,10 @@ Add the given command to the session file (~/.lnav/session) - **Parameters:** - + **Parameters** * **lnav-command\*** --- The lnav command to save. - **Examples:** - + **Examples** To add the command ':highlight foobar' to the session file: .. code-block:: lnav @@ -1220,12 +1111,10 @@ Set the minimum log level to display in the log view - **Parameters:** - + **Parameters** * **log-level\*** --- The new minimum log level - **Examples:** - + **Examples** To set the minimum log level displayed to error: .. code-block:: lnav @@ -1243,20 +1132,17 @@ Show log message fields that were previously hidden - **Parameters:** - + **Parameters** * **field-name** --- The name of the field to show - **Examples:** - + **Examples** To show all the log_procname fields in all formats: .. code-block:: lnav :show-fields log_procname - **See Also:** - + **See Also** :ref:`enable_word_wrap`, :ref:`hide_fields`, :ref:`highlight` ---- @@ -1269,8 +1155,7 @@ Show the given file(s) and resume indexing. - **Parameters:** - + **Parameters** * **path** --- The path or glob pattern that specifies the files to show @@ -1284,8 +1169,7 @@ Show lines that were hidden by the 'hide-lines' commands - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`toggle_filtering` ---- @@ -1298,8 +1182,7 @@ Show lines that have not been bookmarked - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines`, :ref:`hide_unmarked_lines`, :ref:`mark`, :ref:`next_mark`, :ref:`prev_mark`, :ref:`toggle_filtering` ---- @@ -1312,12 +1195,10 @@ Visualize the given message field using a spectrogram - **Parameters:** - + **Parameters** * **field-name\*** --- The name of the numeric field to visualize. - **Examples:** - + **Examples** To visualize the sc_bytes field in the access_log format: .. code-block:: lnav @@ -1335,12 +1216,10 @@ Execute a SQL query that computes the characteristics of the values in the given column - **Parameters:** - + **Parameters** * **column-name\*** --- The name of the column to analyze. - **Examples:** - + **Examples** To get a summary of the sc_bytes column in the access_log table: .. code-block:: lnav @@ -1358,12 +1237,10 @@ Switch to the given view - **Parameters:** - + **Parameters** * **view-name\*** --- The name of the view to switch to. - **Examples:** - + **Examples** To switch to the 'schema' view: .. code-block:: lnav @@ -1381,20 +1258,17 @@ Attach tags to the top log line - **Parameters:** - + **Parameters** * **tag** --- The tags to attach - **Examples:** - + **Examples** To add the tags '#BUG123' and '#needs-review' to the top line: .. code-block:: lnav :tag #BUG123 #needs-review - **See Also:** - + **See Also** :ref:`comment`, :ref:`delete_tags`, :ref:`untag` ---- @@ -1407,8 +1281,7 @@ Toggle the filtering flag for the current view - **See Also:** - + **See Also** :ref:`filter_in`, :ref:`filter_out`, :ref:`hide_lines_after`, :ref:`hide_lines_before`, :ref:`hide_unmarked_lines` ---- @@ -1421,12 +1294,10 @@ Switch to the given view or, if it is already displayed, switch to the previous view - **Parameters:** - + **Parameters** * **view-name\*** --- The name of the view to toggle the display of. - **Examples:** - + **Examples** To switch to the 'schema' view if it is not displayed or switch back to the previous view: .. code-block:: lnav @@ -1444,12 +1315,10 @@ Convert epoch time to a human-readable form - **Parameters:** - + **Parameters** * **seconds\*** --- The epoch timestamp to convert - **Examples:** - + **Examples** To convert the epoch time 1490191111: .. code-block:: lnav @@ -1467,20 +1336,17 @@ Detach tags from the top log line - **Parameters:** - + **Parameters** * **tag** --- The tags to detach - **Examples:** - + **Examples** To remove the tags '#BUG123' and '#needs-review' from the top line: .. code-block:: lnav :untag #BUG123 #needs-review - **See Also:** - + **See Also** :ref:`comment`, :ref:`tag` ---- @@ -1493,20 +1359,17 @@ Write SQL results to the given file in a columnar format - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write SQL results as text to /tmp/table.txt: .. code-block:: lnav :write-cols-to /tmp/table.txt - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1519,20 +1382,17 @@ Write SQL results to the given file in CSV format - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write SQL results as CSV to /tmp/table.csv: .. code-block:: lnav :write-csv-to /tmp/table.csv - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1545,20 +1405,17 @@ Write SQL results to the given file in JSON format - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write SQL results as JSON to /tmp/table.json: .. code-block:: lnav :write-json-to /tmp/table.json - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1571,20 +1428,17 @@ Write SQL results to the given file in JSON Lines format - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write SQL results as JSON Lines to /tmp/table.json: .. code-block:: lnav :write-jsonlines-to /tmp/table.json - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1597,20 +1451,17 @@ Write the text in the top view to the given file without any formatting - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write the top view to /tmp/table.txt: .. code-block:: lnav :write-raw-to /tmp/table.txt - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_screen_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1623,20 +1474,17 @@ Write the displayed text or SQL results to the given file without any formatting - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write only the displayed text to /tmp/table.txt: .. code-block:: lnav :write-screen-to /tmp/table.txt - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`create_logline_table`, :ref:`create_search_table`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_to`, :ref:`write_to` ---- @@ -1649,20 +1497,17 @@ Overwrite the given file with any marked lines in the current view - **Parameters:** - + **Parameters** * **path\*** --- The path to the file to write - **Examples:** - + **Examples** To write marked lines to the file /tmp/interesting-lines.txt: .. code-block:: lnav :write-to /tmp/interesting-lines.txt - **See Also:** - + **See Also** :ref:`alt_msg`, :ref:`append_to`, :ref:`echo`, :ref:`eval`, :ref:`pipe_line_to`, :ref:`pipe_to`, :ref:`redirect_to`, :ref:`redirect_to`, :ref:`write_cols_to`, :ref:`write_cols_to`, :ref:`write_csv_to`, :ref:`write_csv_to`, :ref:`write_json_to`, :ref:`write_json_to`, :ref:`write_jsonlines_to`, :ref:`write_jsonlines_to`, :ref:`write_raw_to`, :ref:`write_raw_to`, :ref:`write_screen_to`, :ref:`write_screen_to` ---- @@ -1675,12 +1520,10 @@ Zoom the histogram view to the given level - **Parameters:** - + **Parameters** * **zoom-level\*** --- The zoom level - **Examples:** - + **Examples** To set the zoom level to '1-week': .. code-block:: lnav diff --git a/src/internals/config-v1.schema.json b/src/internals/config-v1.schema.json index 1f05841a..7feb3f8c 100644 --- a/src/internals/config-v1.schema.json +++ b/src/internals/config-v1.schema.json @@ -405,11 +405,6 @@ "type": "object", "$$target": "#/definitions/style", "properties": { - "semantic": { - "title": "/semantic", - "description": "Pick a color based on the text being highlighted", - "type": "boolean" - }, "color": { "title": "/color", "description": "The foreground color value for this style. The value can be the name of an xterm color, the hexadecimal value, or a theme variable reference.", diff --git a/src/internals/sql-ref.rst b/src/internals/sql-ref.rst index 653bcaa5..8a910f90 100644 --- a/src/internals/sql-ref.rst +++ b/src/internals/sql-ref.rst @@ -6,13 +6,11 @@ expr *\[NOT\]* BETWEEN *low* AND *hi* Test if an expression is between two values. - **Parameters:** - + **Parameters** * **low\*** --- The low point * **hi\*** --- The high point - **Examples:** - + **Examples** To check if 3 is between 5 and 10: .. code-block:: custsqlite @@ -38,13 +36,11 @@ ATTACH DATABASE *filename* AS *schema-name* Attach a database file to the current connection. - **Parameters:** - + **Parameters** * **filename\*** --- The path to the database file. * **schema-name\*** --- The prefix for tables in this database. - **Examples:** - + **Examples** To attach the database file '/tmp/customers.db' with the name customers: .. code-block:: custsqlite @@ -62,8 +58,7 @@ CREATE *\[TEMP\]* VIEW *\[IF NOT EXISTS\]* *\[schema-name.\]* *view-name* AS *s Assign a name to a SELECT statement - **Parameters:** - + **Parameters** * **IF NOT EXISTS** --- Do not create the view if it already exists * **schema-name.** --- The database to create the view in * **view-name\*** --- The name of the view @@ -91,8 +86,7 @@ WITH RECURSIVE *cte-table-name* AS *select-stmt* Create a temporary view that exists only for the duration of a SQL statement. - **Parameters:** - + **Parameters** * **cte-table-name\*** --- The name for the temporary table. * **select-stmt\*** --- The SELECT statement used to populate the temporary table. @@ -107,13 +101,11 @@ CAST(*expr* AS *type-name*) Convert the value of the given expression to a different storage class specified by type-name. - **Parameters:** - + **Parameters** * **expr\*** --- The value to convert. * **type-name\*** --- The name of the type to convert to. - **Examples:** - + **Examples** To cast the value 1.23 as an integer: .. code-block:: custsqlite @@ -132,14 +124,12 @@ CASE *\[base-expr\]* WHEN *cmp-expr* ELSE *\[else-expr\]* END Evaluate a series of expressions in order until one evaluates to true and then return it's result. Similar to an IF-THEN-ELSE construct in other languages. - **Parameters:** - + **Parameters** * **base-expr** --- The base expression that is used for comparison in the branches * **cmp-expr** --- The expression to test if this branch should be taken * **else-expr** --- The result of this CASE if no branches matched. - **Examples:** - + **Examples** To evaluate the number one and return the string 'one': .. code-block:: custsqlite @@ -158,12 +148,10 @@ expr COLLATE *collation-name* Assign a collating sequence to the expression. - **Parameters:** - + **Parameters** * **collation-name\*** --- The name of the collator. - **Examples:** - + **Examples** To change the collation method for string comparisons: .. code-block:: custsqlite @@ -183,12 +171,10 @@ DETACH DATABASE *schema-name* Detach a database from the current connection. - **Parameters:** - + **Parameters** * **schema-name\*** --- The prefix for tables in this database. - **Examples:** - + **Examples** To detach the database named 'customers': .. code-block:: custsqlite @@ -206,8 +192,7 @@ DELETE FROM *table-name* WHERE *\[cond\]* Delete rows from a table - **Parameters:** - + **Parameters** * **table-name\*** --- The name of the table * **cond** --- The conditions used to delete the rows. @@ -266,12 +251,10 @@ expr *\[NOT\]* GLOB *pattern* Match an expression against a glob pattern. - **Parameters:** - + **Parameters** * **pattern\*** --- The glob pattern to match against. - **Examples:** - + **Examples** To check if a value matches the pattern '*.log': .. code-block:: custsqlite @@ -290,12 +273,10 @@ expr *\[NOT\]* LIKE *pattern* Match an expression against a text pattern. - **Parameters:** - + **Parameters** * **pattern\*** --- The pattern to match against. - **Examples:** - + **Examples** To check if a value matches the pattern 'Hello, %!': .. code-block:: custsqlite @@ -314,12 +295,10 @@ expr *\[NOT\]* REGEXP *pattern* Match an expression against a regular expression. - **Parameters:** - + **Parameters** * **pattern\*** --- The regular expression to match against. - **Examples:** - + **Examples** To check if a value matches the pattern 'file-\d+': .. code-block:: custsqlite @@ -338,16 +317,14 @@ SELECT *result-column* FROM *table* WHERE *\[cond\]* GROUP BY *grouping-expr* OR Query the database and return zero or more rows of data. - **Parameters:** - + **Parameters** * **table** --- The table(s) to query for data * **cond** --- The conditions used to select the rows to return. * **grouping-expr** --- The expression to use when grouping rows. * **ordering-term** --- The values to use when ordering the result set. * **limit-expr** --- The maximum number of rows to return - **Examples:** - + **Examples** To select all of the columns from the table 'syslog_log': .. code-block:: custsqlite @@ -365,8 +342,7 @@ INSERT INTO *\[schema-name.\]* *table-name* *column-name* VALUES *expr* Insert rows into a table - **Examples:** - + **Examples** To insert the pair containing 'MSG' and 'HELLO, WORLD!' into the 'environ' table: .. code-block:: custsqlite @@ -384,8 +360,7 @@ OVER(*\[base-window-name\]* PARTITION BY *expr* ORDER BY *expr*, *\[frame-spec\] Executes the preceding function over a window - **Parameters:** - + **Parameters** * **base-window-name** --- The name of the window definition * **expr** --- The values to use for partitioning * **expr** --- The values used to order the rows in the window @@ -402,8 +377,7 @@ OVER *window-name* Executes the preceding function over a window - **Parameters:** - + **Parameters** * **window-name\*** --- The name of the window definition @@ -417,14 +391,12 @@ UPDATE *table* SET *column-name* WHERE *\[cond\]* Modify a subset of values in zero or more rows of the given table - **Parameters:** - + **Parameters** * **table\*** --- The table to update * **column-name** --- The columns in the table to update. * **cond** --- The condition used to determine whether a row should be updated. - **Examples:** - + **Examples** To mark the syslog message at line 40: .. code-block:: custsqlite @@ -442,12 +414,10 @@ abs(*x*) Return the absolute value of the argument - **Parameters:** - + **Parameters** * **x\*** --- The number to convert - **Examples:** - + **Examples** To get the absolute value of -1: .. code-block:: custsqlite @@ -455,8 +425,7 @@ abs(*x*) ;SELECT abs(-1) 1 - **See Also:** - + **See Also** :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -469,12 +438,10 @@ acos(*num*) Returns the arccosine of a number, in radians - **Parameters:** - + **Parameters** * **num\*** --- A cosine value that is between -1 and 1 - **Examples:** - + **Examples** To get the arccosine of 0.2: .. code-block:: custsqlite @@ -482,8 +449,7 @@ acos(*num*) ;SELECT acos(0.2) 1.36943840600457 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -496,12 +462,10 @@ acosh(*num*) Returns the hyperbolic arccosine of a number - **Parameters:** - + **Parameters** * **num\*** --- A number that is one or more - **Examples:** - + **Examples** To get the hyperbolic arccosine of 1.2: .. code-block:: custsqlite @@ -509,8 +473,7 @@ acosh(*num*) ;SELECT acosh(1.2) 0.622362503714779 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -523,12 +486,10 @@ asin(*num*) Returns the arcsine of a number, in radians - **Parameters:** - + **Parameters** * **num\*** --- A sine value that is between -1 and 1 - **Examples:** - + **Examples** To get the arcsine of 0.2: .. code-block:: custsqlite @@ -536,8 +497,7 @@ asin(*num*) ;SELECT asin(0.2) 0.201357920790331 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -550,12 +510,10 @@ asinh(*num*) Returns the hyperbolic arcsine of a number - **Parameters:** - + **Parameters** * **num\*** --- The number - **Examples:** - + **Examples** To get the hyperbolic arcsine of 0.2: .. code-block:: custsqlite @@ -563,8 +521,7 @@ asinh(*num*) ;SELECT asinh(0.2) 0.198690110349241 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -577,12 +534,10 @@ atan(*num*) Returns the arctangent of a number, in radians - **Parameters:** - + **Parameters** * **num\*** --- The number - **Examples:** - + **Examples** To get the arctangent of 0.2: .. code-block:: custsqlite @@ -590,8 +545,7 @@ atan(*num*) ;SELECT atan(0.2) 0.197395559849881 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -604,13 +558,11 @@ atan2(*y*, *x*) Returns the angle in the plane between the positive X axis and the ray from (0, 0) to the point (x, y) - **Parameters:** - + **Parameters** * **y\*** --- The y coordinate of the point * **x\*** --- The x coordinate of the point - **Examples:** - + **Examples** To get the angle, in degrees, for the point at (5, 5): .. code-block:: custsqlite @@ -618,8 +570,7 @@ atan2(*y*, *x*) ;SELECT degrees(atan2(5, 5)) 45.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -632,12 +583,10 @@ atanh(*num*) Returns the hyperbolic arctangent of a number - **Parameters:** - + **Parameters** * **num\*** --- The number - **Examples:** - + **Examples** To get the hyperbolic arctangent of 0.2: .. code-block:: custsqlite @@ -645,8 +594,7 @@ atanh(*num*) ;SELECT atanh(0.2) 0.202732554054082 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -659,13 +607,11 @@ atn2(*y*, *x*) Returns the angle in the plane between the positive X axis and the ray from (0, 0) to the point (x, y) - **Parameters:** - + **Parameters** * **y\*** --- The y coordinate of the point * **x\*** --- The x coordinate of the point - **Examples:** - + **Examples** To get the angle, in degrees, for the point at (5, 5): .. code-block:: custsqlite @@ -673,8 +619,7 @@ atn2(*y*, *x*) ;SELECT degrees(atn2(5, 5)) 45.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -687,12 +632,10 @@ avg(*X*) Returns the average value of all non-NULL numbers within a group. - **Parameters:** - + **Parameters** * **X\*** --- The value to compute the average of. - **Examples:** - + **Examples** To get the average of the column 'ex_duration' from the table 'lnav_example_log': .. code-block:: custsqlite @@ -709,8 +652,7 @@ avg(*X*) gw 5.0 hw 2.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -723,12 +665,10 @@ basename(*path*) Extract the base portion of a pathname. - **Parameters:** - + **Parameters** * **path\*** --- The path - **Examples:** - + **Examples** To get the base of a plain file name: .. code-block:: custsqlite @@ -771,8 +711,7 @@ basename(*path*) ;SELECT basename('/') / - **See Also:** - + **See Also** :ref:`dirname`, :ref:`joinpath`, :ref:`readlink`, :ref:`realpath` ---- @@ -785,12 +724,10 @@ ceil(*num*) Returns the smallest integer that is not less than the argument - **Parameters:** - + **Parameters** * **num\*** --- The number to raise to the ceiling - **Examples:** - + **Examples** To get the ceiling of 1.23: .. code-block:: custsqlite @@ -798,8 +735,7 @@ ceil(*num*) ;SELECT ceil(1.23) 2 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -823,12 +759,10 @@ char(*X*) Returns a string composed of characters having the given unicode code point values - **Parameters:** - + **Parameters** * **X** --- The unicode code point values - **Examples:** - + **Examples** To get a string with the code points 0x48 and 0x49: .. code-block:: custsqlite @@ -836,8 +770,7 @@ char(*X*) ;SELECT char(0x48, 0x49) HI - **See Also:** - + **See Also** :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -850,14 +783,12 @@ charindex(*needle*, *haystack*, *\[start\]*) Finds the first occurrence of the needle within the haystack and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X - **Parameters:** - + **Parameters** * **needle\*** --- The string to look for in the haystack * **haystack\*** --- The string to search within * **start** --- The one-based index within the haystack to start the search - **Examples:** - + **Examples** To search for the string 'abc' within 'abcabc' and starting at position 2: .. code-block:: custsqlite @@ -872,8 +803,7 @@ charindex(*needle*, *haystack*, *\[start\]*) ;SELECT charindex('abc', 'abcdef', 2) 0 - **See Also:** - + **See Also** :ref:`char`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -886,13 +816,11 @@ coalesce(*X*, *Y*) Returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - **Parameters:** - + **Parameters** * **X\*** --- A value to check for NULL-ness * **Y** --- A value to check for NULL-ness - **Examples:** - + **Examples** To get the first non-null value from three parameters: .. code-block:: custsqlite @@ -911,12 +839,10 @@ count(*X*) If the argument is '*', the total number of rows in the group is returned. Otherwise, the number of times the argument is non-NULL. - **Parameters:** - + **Parameters** * **X\*** --- The value to count. - **Examples:** - + **Examples** To get the count of the non-NULL rows of 'lnav_example_log': .. code-block:: custsqlite @@ -942,8 +868,7 @@ cume_dist() Returns the cumulative distribution - **See Also:** - + **See Also** :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -956,13 +881,11 @@ date(*timestring*, *modifier*) Returns the date in this format: YYYY-MM-DD. - **Parameters:** - + **Parameters** * **timestring\*** --- The string to convert to a date. * **modifier** --- A transformation that is applied to the value to the left. - **Examples:** - + **Examples** To get the date portion of the timestamp '2017-01-02T03:04:05': .. code-block:: custsqlite @@ -984,8 +907,7 @@ date(*timestring*, *modifier*) ;SELECT date(1491341842, 'unixepoch') 2017-04-04 - **See Also:** - + **See Also** :ref:`datetime`, :ref:`julianday`, :ref:`strftime`, :ref:`time`, :ref:`timediff`, :ref:`timeslice` ---- @@ -998,13 +920,11 @@ datetime(*timestring*, *modifier*) Returns the date and time in this format: YYYY-MM-DD HH:MM:SS. - **Parameters:** - + **Parameters** * **timestring\*** --- The string to convert to a date with time. * **modifier** --- A transformation that is applied to the value to the left. - **Examples:** - + **Examples** To get the date and time portion of the timestamp '2017-01-02T03:04:05': .. code-block:: custsqlite @@ -1026,8 +946,7 @@ datetime(*timestring*, *modifier*) ;SELECT datetime(1491341842, 'unixepoch') 2017-04-04 21:37:22 - **See Also:** - + **See Also** :ref:`date`, :ref:`julianday`, :ref:`strftime`, :ref:`time`, :ref:`timediff`, :ref:`timeslice` ---- @@ -1040,12 +959,10 @@ degrees(*radians*) Converts radians to degrees - **Parameters:** - + **Parameters** * **radians\*** --- The radians value to convert to degrees - **Examples:** - + **Examples** To convert PI to degrees: .. code-block:: custsqlite @@ -1053,8 +970,7 @@ degrees(*radians*) ;SELECT degrees(pi()) 180.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -1067,8 +983,7 @@ dense_rank() Returns the row_number() of the first peer in each group without gaps - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -1081,12 +996,10 @@ dirname(*path*) Extract the directory portion of a pathname. - **Parameters:** - + **Parameters** * **path\*** --- The path - **Examples:** - + **Examples** To get the directory of a relative file path: .. code-block:: custsqlite @@ -1122,8 +1035,7 @@ dirname(*path*) ;SELECT dirname('') . - **See Also:** - + **See Also** :ref:`basename`, :ref:`joinpath`, :ref:`readlink`, :ref:`realpath` ---- @@ -1136,13 +1048,11 @@ endswith(*str*, *suffix*) Test if a string ends with the given suffix - **Parameters:** - + **Parameters** * **str\*** --- The string to test * **suffix\*** --- The suffix to check in the string - **Examples:** - + **Examples** To test if the string 'notbad.jpg' ends with '.jpg': .. code-block:: custsqlite @@ -1157,8 +1067,7 @@ endswith(*str*, *suffix*) ;SELECT endswith('notbad.png', '.jpg') 0 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1171,12 +1080,10 @@ exp(*x*) Returns the value of e raised to the power of x - **Parameters:** - + **Parameters** * **x\*** --- The exponent - **Examples:** - + **Examples** To raise e to 2: .. code-block:: custsqlite @@ -1184,8 +1091,7 @@ exp(*x*) ;SELECT exp(2) 7.38905609893065 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -1198,12 +1104,10 @@ extract(*str*) Automatically Parse and extract data from a string - **Parameters:** - + **Parameters** * **str\*** --- The string to parse - **Examples:** - + **Examples** To extract key/value pairs from a string: .. code-block:: custsqlite @@ -1218,8 +1122,7 @@ extract(*str*) ;SELECT extract('1.0 abc 2.0') {"col_0":1.0,"col_1":2.0} - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1232,12 +1135,10 @@ first_value(*expr*) Returns the result of evaluating the expression against the first row in the window frame. - **Parameters:** - + **Parameters** * **expr\*** --- The expression to execute over the first row - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -1250,12 +1151,10 @@ floor(*num*) Returns the largest integer that is not greater than the argument - **Parameters:** - + **Parameters** * **num\*** --- The number to lower to the floor - **Examples:** - + **Examples** To get the floor of 1.23: .. code-block:: custsqlite @@ -1263,8 +1162,7 @@ floor(*num*) ;SELECT floor(1.23) 1 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -1277,12 +1175,10 @@ gethostbyaddr(*hostname*) Get the hostname for the given IP address - **Parameters:** - + **Parameters** * **hostname\*** --- The IP address to lookup. - **Examples:** - + **Examples** To get the hostname for the IP '127.0.0.1': .. code-block:: custsqlite @@ -1290,8 +1186,7 @@ gethostbyaddr(*hostname*) ;SELECT gethostbyaddr('127.0.0.1') localhost - **See Also:** - + **See Also** :ref:`gethostbyname` ---- @@ -1304,12 +1199,10 @@ gethostbyname(*hostname*) Get the IP address for the given hostname - **Parameters:** - + **Parameters** * **hostname\*** --- The DNS hostname to lookup. - **Examples:** - + **Examples** To get the IP address for 'localhost': .. code-block:: custsqlite @@ -1317,8 +1210,7 @@ gethostbyname(*hostname*) ;SELECT gethostbyname('localhost') 127.0.0.1 - **See Also:** - + **See Also** :ref:`gethostbyaddr` ---- @@ -1331,13 +1223,11 @@ glob(*pattern*, *str*) Match a string against Unix glob pattern - **Parameters:** - + **Parameters** * **pattern\*** --- The glob pattern * **str\*** --- The string to match - **Examples:** - + **Examples** To test if the string 'abc' matches the glob 'a*': .. code-block:: custsqlite @@ -1356,13 +1246,11 @@ group_concat(*X*, *\[sep\]*) Returns a string which is the concatenation of all non-NULL values of X separated by a comma or the given separator. - **Parameters:** - + **Parameters** * **X\*** --- The value to concatenate. * **sep** --- The separator to place between the values. - **Examples:** - + **Examples** To concatenate the values of the column 'ex_procname' from the table 'lnav_example_log': .. code-block:: custsqlite @@ -1384,8 +1272,7 @@ group_concat(*X*, *\[sep\]*) ;SELECT group_concat(DISTINCT ex_procname) FROM lnav_example_log hw,gw - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1398,12 +1285,10 @@ group_spooky_hash(*str*) Compute the hash value for the given arguments - **Parameters:** - + **Parameters** * **str** --- The string to hash - **Examples:** - + **Examples** To produce a hash of all of the values of 'column1': .. code-block:: custsqlite @@ -1411,8 +1296,7 @@ group_spooky_hash(*str*) ;SELECT group_spooky_hash(column1) FROM (VALUES ('abc'), ('123')) 4e7a190aead058cb123c94290f29c34a - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1425,12 +1309,10 @@ hex(*X*) Returns a string which is the upper-case hexadecimal rendering of the content of its argument. - **Parameters:** - + **Parameters** * **X\*** --- The blob to convert to hexadecimal - **Examples:** - + **Examples** To get the hexadecimal rendering of the string 'abc': .. code-block:: custsqlite @@ -1449,13 +1331,11 @@ ifnull(*X*, *Y*) Returns a copy of its first non-NULL argument, or NULL if both arguments are NULL - **Parameters:** - + **Parameters** * **X\*** --- A value to check for NULL-ness * **Y\*** --- A value to check for NULL-ness - **Examples:** - + **Examples** To get the first non-null value between null and zero: .. code-block:: custsqlite @@ -1474,13 +1354,11 @@ instr(*haystack*, *needle*) Finds the first occurrence of the needle within the haystack and returns the number of prior characters plus 1, or 0 if the needle was not found - **Parameters:** - + **Parameters** * **haystack\*** --- The string to search within * **needle\*** --- The string to look for in the haystack - **Examples:** - + **Examples** To test get the position of 'b' in the string 'abc': .. code-block:: custsqlite @@ -1488,8 +1366,7 @@ instr(*haystack*, *needle*) ;SELECT instr('abc', 'b') 2 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1502,14 +1379,12 @@ jget(*json*, *ptr*, *\[default\]*) Get the value from a JSON object using a JSON-Pointer. - **Parameters:** - + **Parameters** * **json\*** --- The JSON object to query. * **ptr\*** --- The JSON-Pointer to lookup in the object. * **default** --- The default value if the value was not found - **Examples:** - + **Examples** To get the root of a JSON value: .. code-block:: custsqlite @@ -1531,8 +1406,7 @@ jget(*json*, *ptr*, *\[default\]*) ;SELECT jget(null, '/msg', 'Hello') Hello - **See Also:** - + **See Also** :ref:`json_concat`, :ref:`json_contains`, :ref:`json_group_array`, :ref:`json_group_object` ---- @@ -1545,12 +1419,10 @@ joinpath(*path*) Join components of a path together. - **Parameters:** - + **Parameters** * **path** --- One or more path components to join together. If an argument starts with a forward or backward slash, it will be considered an absolute path and any preceding elements will be ignored. - **Examples:** - + **Examples** To join a directory and file name into a relative path: .. code-block:: custsqlite @@ -1579,8 +1451,7 @@ joinpath(*path*) ;SELECT joinpath('/', 'foo', '/bar') /bar - **See Also:** - + **See Also** :ref:`basename`, :ref:`dirname`, :ref:`readlink`, :ref:`realpath` ---- @@ -1593,13 +1464,11 @@ json_concat(*json*, *value*) Returns an array with the given values concatenated onto the end. If the initial value is null, the result will be an array with the given elements. If the initial value is an array, the result will be an array with the given values at the end. If the initial value is not null or an array, the result will be an array with two elements: the initial value and the given value. - **Parameters:** - + **Parameters** * **json\*** --- The initial JSON value. * **value** --- The value(s) to add to the end of the array. - **Examples:** - + **Examples** To append the number 4 to null: .. code-block:: custsqlite @@ -1621,8 +1490,7 @@ json_concat(*json*, *value*) ;SELECT json_concat('[1, 2, 3]', json('[4, 5]')) [1,2,3,4,5] - **See Also:** - + **See Also** :ref:`jget`, :ref:`json_contains`, :ref:`json_group_array`, :ref:`json_group_object` ---- @@ -1635,13 +1503,11 @@ json_contains(*json*, *value*) Check if a JSON value contains the given element. - **Parameters:** - + **Parameters** * **json\*** --- The JSON value to query. * **value\*** --- The value to look for in the first argument - **Examples:** - + **Examples** To test if a JSON array contains the number 4: .. code-block:: custsqlite @@ -1656,8 +1522,7 @@ json_contains(*json*, *value*) ;SELECT json_contains('["abc", "def"]', 'def') 1 - **See Also:** - + **See Also** :ref:`jget`, :ref:`json_concat`, :ref:`json_group_array`, :ref:`json_group_object` ---- @@ -1670,12 +1535,10 @@ json_group_array(*value*) Collect the given values from a query into a JSON array - **Parameters:** - + **Parameters** * **value** --- The values to append to the array - **Examples:** - + **Examples** To create an array from arguments: .. code-block:: custsqlite @@ -1690,8 +1553,7 @@ json_group_array(*value*) ;SELECT json_group_array(column1) FROM (VALUES (1), (2), (3)) [1,2,3] - **See Also:** - + **See Also** :ref:`jget`, :ref:`json_concat`, :ref:`json_contains`, :ref:`json_group_object` ---- @@ -1704,13 +1566,11 @@ json_group_object(*name*, *value*) Collect the given values from a query into a JSON object - **Parameters:** - + **Parameters** * **name\*** --- The property name for the value * **value** --- The value to add to the object - **Examples:** - + **Examples** To create an object from arguments: .. code-block:: custsqlite @@ -1725,8 +1585,7 @@ json_group_object(*name*, *value*) ;SELECT json_group_object(column1, column2) FROM (VALUES ('a', 1), ('b', 2)) {"a":1,"b":2} - **See Also:** - + **See Also** :ref:`jget`, :ref:`json_concat`, :ref:`json_contains`, :ref:`json_group_array` ---- @@ -1739,13 +1598,11 @@ julianday(*timestring*, *modifier*) Returns the number of days since noon in Greenwich on November 24, 4714 B.C. - **Parameters:** - + **Parameters** * **timestring\*** --- The string to convert to a date with time. * **modifier** --- A transformation that is applied to the value to the left. - **Examples:** - + **Examples** To get the julian day from the timestamp '2017-01-02T03:04:05': .. code-block:: custsqlite @@ -1767,8 +1624,7 @@ julianday(*timestring*, *modifier*) ;SELECT julianday(1491341842, 'unixepoch') 2457848.40094907 - **See Also:** - + **See Also** :ref:`date`, :ref:`datetime`, :ref:`strftime`, :ref:`time`, :ref:`timediff`, :ref:`timeslice` ---- @@ -1781,14 +1637,12 @@ lag(*expr*, *\[offset\]*, *\[default\]*) Returns the result of evaluating the expression against the previous row in the partition. - **Parameters:** - + **Parameters** * **expr\*** --- The expression to execute over the previous row * **offset** --- The offset from the current row in the partition * **default** --- The default value if the previous row does not exist instead of NULL - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -1812,12 +1666,10 @@ last_value(*expr*) Returns the result of evaluating the expression against the last row in the window frame. - **Parameters:** - + **Parameters** * **expr\*** --- The expression to execute over the last row - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -1830,14 +1682,12 @@ lead(*expr*, *\[offset\]*, *\[default\]*) Returns the result of evaluating the expression against the next row in the partition. - **Parameters:** - + **Parameters** * **expr\*** --- The expression to execute over the next row * **offset** --- The offset from the current row in the partition * **default** --- The default value if the next row does not exist instead of NULL - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -1850,13 +1700,11 @@ leftstr(*str*, *N*) Returns the N leftmost (UTF-8) characters in the given string. - **Parameters:** - + **Parameters** * **str\*** --- The string to return subset. * **N\*** --- The number of characters from the left side of the string to return. - **Examples:** - + **Examples** To get the first character of the string 'abc': .. code-block:: custsqlite @@ -1871,8 +1719,7 @@ leftstr(*str*, *N*) ;SELECT leftstr('abc', 10) abc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1885,12 +1732,10 @@ length(*str*) Returns the number of characters (not bytes) in the given string prior to the first NUL character - **Parameters:** - + **Parameters** * **str\*** --- The string to determine the length of - **Examples:** - + **Examples** To get the length of the string 'abc': .. code-block:: custsqlite @@ -1898,8 +1743,7 @@ length(*str*) ;SELECT length('abc') 3 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -1912,14 +1756,12 @@ like(*pattern*, *str*, *\[escape\]*) Match a string against a pattern - **Parameters:** - + **Parameters** * **pattern\*** --- The pattern to match. A percent symbol (%) will match zero or more characters and an underscore (_) will match a single character. * **str\*** --- The string to match * **escape** --- The escape character that can be used to prefix a literal percent or underscore in the pattern. - **Examples:** - + **Examples** To test if the string 'aabcc' contains the letter 'b': .. code-block:: custsqlite @@ -1945,8 +1787,7 @@ likelihood(*value*, *probability*) Provides a hint to the query planner that the first argument is a boolean that is true with the given probability - **Parameters:** - + **Parameters** * **value\*** --- The boolean value to return * **probability\*** --- A floating point constant between 0.0 and 1.0 @@ -1961,8 +1802,7 @@ likely(*value*) Short-hand for likelihood(X,0.9375) - **Parameters:** - + **Parameters** * **value\*** --- The boolean value to return @@ -1976,8 +1816,7 @@ load_extension(*path*, *\[entry-point\]*) Loads SQLite extensions out of the given shared library file using the given entry point. - **Parameters:** - + **Parameters** * **path\*** --- The path to the shared library containing the extension. @@ -1991,12 +1830,10 @@ log(*x*) Returns the natural logarithm of x - **Parameters:** - + **Parameters** * **x\*** --- The number - **Examples:** - + **Examples** To get the natual logarithm of 8: .. code-block:: custsqlite @@ -2004,8 +1841,7 @@ log(*x*) ;SELECT log(8) 2.07944154167984 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2018,12 +1854,10 @@ log10(*x*) Returns the base-10 logarithm of X - **Parameters:** - + **Parameters** * **x\*** --- The number - **Examples:** - + **Examples** To get the logarithm of 100: .. code-block:: custsqlite @@ -2031,8 +1865,7 @@ log10(*x*) ;SELECT log10(100) 2.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2067,12 +1900,10 @@ lower(*str*) Returns a copy of the given string with all ASCII characters converted to lower case. - **Parameters:** - + **Parameters** * **str\*** --- The string to convert. - **Examples:** - + **Examples** To lowercase the string 'AbC': .. code-block:: custsqlite @@ -2080,8 +1911,7 @@ lower(*str*) ;SELECT lower('AbC') abc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2094,13 +1924,11 @@ ltrim(*str*, *\[chars\]*) Returns a string formed by removing any and all characters that appear in the second argument from the left side of the first. - **Parameters:** - + **Parameters** * **str\*** --- The string to trim characters from the left side * **chars** --- The characters to trim. Defaults to spaces. - **Examples:** - + **Examples** To trim the leading whitespace from the string ' abc': .. code-block:: custsqlite @@ -2115,8 +1943,7 @@ ltrim(*str*, *\[chars\]*) ;SELECT ltrim('aaaabbbc', 'ab') c - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2129,12 +1956,10 @@ max(*X*) Returns the argument with the maximum value, or return NULL if any argument is NULL. - **Parameters:** - + **Parameters** * **X** --- The numbers to find the maximum of. If only one argument is given, this function operates as an aggregate. - **Examples:** - + **Examples** To get the largest value from the parameters: .. code-block:: custsqlite @@ -2149,8 +1974,7 @@ max(*X*) ;SELECT max(status) FROM http_status_codes 511 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2163,12 +1987,10 @@ min(*X*) Returns the argument with the minimum value, or return NULL if any argument is NULL. - **Parameters:** - + **Parameters** * **X** --- The numbers to find the minimum of. If only one argument is given, this function operates as an aggregate. - **Examples:** - + **Examples** To get the smallest value from the parameters: .. code-block:: custsqlite @@ -2183,8 +2005,7 @@ min(*X*) ;SELECT min(status) FROM http_status_codes 100 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2197,13 +2018,11 @@ nth_value(*expr*, *N*) Returns the result of evaluating the expression against the nth row in the window frame. - **Parameters:** - + **Parameters** * **expr\*** --- The expression to execute over the nth row * **N\*** --- The row number - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -2216,12 +2035,10 @@ ntile(*groups*) Returns the number of the group that the current row is a part of - **Parameters:** - + **Parameters** * **groups\*** --- The number of groups - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`percent_rank`, :ref:`rank`, :ref:`row_number` ---- @@ -2234,13 +2051,11 @@ nullif(*X*, *Y*) Returns its first argument if the arguments are different and NULL if the arguments are the same. - **Parameters:** - + **Parameters** * **X\*** --- The first argument to compare. * **Y\*** --- The argument to compare against the first. - **Examples:** - + **Examples** To test if 1 is different from 1: .. code-block:: custsqlite @@ -2266,13 +2081,11 @@ padc(*str*, *len*) Pad the given string with enough spaces to make it centered within the given length - **Parameters:** - + **Parameters** * **str\*** --- The string to pad * **len\*** --- The minimum desired length of the output string - **Examples:** - + **Examples** To pad the string 'abc' to a length of six characters: .. code-block:: custsqlite @@ -2287,8 +2100,7 @@ padc(*str*, *len*) ;SELECT padc('abcdef', 8) || 'ghi' abcdef ghi - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2301,13 +2113,11 @@ padl(*str*, *len*) Pad the given string with leading spaces until it reaches the desired length - **Parameters:** - + **Parameters** * **str\*** --- The string to pad * **len\*** --- The minimum desired length of the output string - **Examples:** - + **Examples** To pad the string 'abc' to a length of six characters: .. code-block:: custsqlite @@ -2322,8 +2132,7 @@ padl(*str*, *len*) ;SELECT padl('abcdef', 4) abcdef - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2336,13 +2145,11 @@ padr(*str*, *len*) Pad the given string with trailing spaces until it reaches the desired length - **Parameters:** - + **Parameters** * **str\*** --- The string to pad * **len\*** --- The minimum desired length of the output string - **Examples:** - + **Examples** To pad the string 'abc' to a length of six characters: .. code-block:: custsqlite @@ -2357,8 +2164,7 @@ padr(*str*, *len*) ;SELECT padr('abcdef', 4) || 'ghi' abcdefghi - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2371,8 +2177,7 @@ percent_rank() Returns (rank - 1) / (partition-rows - 1) - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`rank`, :ref:`row_number` ---- @@ -2385,8 +2190,7 @@ pi() Returns the value of PI - **Examples:** - + **Examples** To get the value of PI: .. code-block:: custsqlite @@ -2394,8 +2198,7 @@ pi() ;SELECT pi() 3.14159265358979 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2408,13 +2211,11 @@ power(*base*, *exp*) Returns the base to the given exponent - **Parameters:** - + **Parameters** * **base\*** --- The base number * **exp\*** --- The exponent - **Examples:** - + **Examples** To raise two to the power of three: .. code-block:: custsqlite @@ -2422,8 +2223,7 @@ power(*base*, *exp*) ;SELECT power(2, 3) 8.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2436,13 +2236,11 @@ printf(*format*, *X*) Returns a string with this functions arguments substituted into the given format. Substitution points are specified using percent (%) options, much like the standard C printf() function. - **Parameters:** - + **Parameters** * **format\*** --- The format of the string to return. * **X\*** --- The argument to substitute at a given position in the format. - **Examples:** - + **Examples** To substitute 'World' into the string 'Hello, %s!': .. code-block:: custsqlite @@ -2464,8 +2262,7 @@ printf(*format*, *X*) ;SELECT printf('value: %05d', 11) value: 00011 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2478,12 +2275,10 @@ proper(*str*) Capitalize the first character of words in the given string - **Parameters:** - + **Parameters** * **str\*** --- The string to capitalize. - **Examples:** - + **Examples** To capitalize the words in the string 'hello, world!': .. code-block:: custsqlite @@ -2491,8 +2286,7 @@ proper(*str*) ;SELECT proper('hello, world!') Hello, World! - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2505,12 +2299,10 @@ quote(*X*) Returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. - **Parameters:** - + **Parameters** * **X\*** --- The string to quote. - **Examples:** - + **Examples** To quote the string 'abc': .. code-block:: custsqlite @@ -2536,12 +2328,10 @@ radians(*degrees*) Converts degrees to radians - **Parameters:** - + **Parameters** * **degrees\*** --- The degrees value to convert to radians - **Examples:** - + **Examples** To convert 180 degrees to radians: .. code-block:: custsqlite @@ -2549,8 +2339,7 @@ radians(*degrees*) ;SELECT radians(180) 3.14159265358979 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2563,8 +2352,7 @@ raise_error(*msg*) Raises an error with the given message when executed - **Parameters:** - + **Parameters** * **msg\*** --- The error message @@ -2589,8 +2377,7 @@ randomblob(*N*) Return an N-byte blob containing pseudo-random bytes. - **Parameters:** - + **Parameters** * **N\*** --- The size of the blob in bytes. @@ -2604,8 +2391,7 @@ rank() Returns the row_number() of the first peer in each group with gaps - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`row_number` ---- @@ -2618,12 +2404,10 @@ readlink(*path*) Read the target of a symbolic link. - **Parameters:** - + **Parameters** * **path\*** --- The path to the symbolic link. - **See Also:** - + **See Also** :ref:`basename`, :ref:`dirname`, :ref:`joinpath`, :ref:`realpath` ---- @@ -2636,12 +2420,10 @@ realpath(*path*) Returns the resolved version of the given path, expanding symbolic links and resolving '.' and '..' references. - **Parameters:** - + **Parameters** * **path\*** --- The path to resolve. - **See Also:** - + **See Also** :ref:`basename`, :ref:`dirname`, :ref:`joinpath`, :ref:`readlink` ---- @@ -2654,8 +2436,7 @@ regexp(*re*, *str*) Test if a string matches a regular expression - **Parameters:** - + **Parameters** * **re\*** --- The regular expression to use * **str\*** --- The string to test against the regular expression @@ -2670,13 +2451,11 @@ regexp_capture(*string*, *pattern*) A table-valued function that executes a regular-expression over a string and returns the captured values. If the regex only matches a subset of the input string, it will be rerun on the remaining parts of the string until no more matches are found. - **Parameters:** - + **Parameters** * **string\*** --- The string to match against the given pattern. * **pattern\*** --- The regular expression to match. - **Examples:** - + **Examples** To extract the key/value pairs 'a'/1 and 'b'/2 from the string 'a=1; b=2': .. code-block:: custsqlite @@ -2690,8 +2469,7 @@ regexp_capture(*string*, *pattern*) 1 1 3 6 7 b 1 2 3 8 9 2 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2704,13 +2482,11 @@ regexp_match(*re*, *str*) Match a string against a regular expression and return the capture groups as JSON. - **Parameters:** - + **Parameters** * **re\*** --- The regular expression to use * **str\*** --- The string to test against the regular expression - **Examples:** - + **Examples** To capture the digits from the string '123': .. code-block:: custsqlite @@ -2732,8 +2508,7 @@ regexp_match(*re*, *str*) ;SELECT regexp_match('(?\d+) (?\w+)', '123 four') {"num":123,"str":"four"} - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_replace`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2746,14 +2521,12 @@ regexp_replace(*str*, *re*, *repl*) Replace the parts of a string that match a regular expression. - **Parameters:** - + **Parameters** * **str\*** --- The string to perform replacements on * **re\*** --- The regular expression to match * **repl\*** --- The replacement string. You can reference capture groups with a backslash followed by the number of the group, starting with 1. - **Examples:** - + **Examples** To replace the word at the start of the string 'Hello, World!' with 'Goodbye': .. code-block:: custsqlite @@ -2768,8 +2541,7 @@ regexp_replace(*str*, *re*, *repl*) ;SELECT regexp_replace('123 abc', '(\w+)', '<\1>') <123> - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_match`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2782,14 +2554,12 @@ replace(*str*, *old*, *replacement*) Returns a string formed by substituting the replacement string for every occurrence of the old string in the given string. - **Parameters:** - + **Parameters** * **str\*** --- The string to perform substitutions on. * **old\*** --- The string to be replaced. * **replacement\*** --- The string to replace any occurrences of the old string with. - **Examples:** - + **Examples** To replace the string 'x' with 'z' in 'abc': .. code-block:: custsqlite @@ -2804,8 +2574,7 @@ replace(*str*, *old*, *replacement*) ;SELECT replace('abc', 'a', 'z') zbc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2818,13 +2587,11 @@ replicate(*str*, *N*) Returns the given string concatenated N times. - **Parameters:** - + **Parameters** * **str\*** --- The string to replicate. * **N\*** --- The number of times to replicate the string. - **Examples:** - + **Examples** To repeat the string 'abc' three times: .. code-block:: custsqlite @@ -2832,8 +2599,7 @@ replicate(*str*, *N*) ;SELECT replicate('abc', 3) abcabcabc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2846,12 +2612,10 @@ reverse(*str*) Returns the reverse of the given string. - **Parameters:** - + **Parameters** * **str\*** --- The string to reverse. - **Examples:** - + **Examples** To reverse the string 'abc': .. code-block:: custsqlite @@ -2859,8 +2623,7 @@ reverse(*str*) ;SELECT reverse('abc') cba - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2873,13 +2636,11 @@ rightstr(*str*, *N*) Returns the N rightmost (UTF-8) characters in the given string. - **Parameters:** - + **Parameters** * **str\*** --- The string to return subset. * **N\*** --- The number of characters from the right side of the string to return. - **Examples:** - + **Examples** To get the last character of the string 'abc': .. code-block:: custsqlite @@ -2894,8 +2655,7 @@ rightstr(*str*, *N*) ;SELECT rightstr('abc', 10) abc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -2908,13 +2668,11 @@ round(*num*, *\[digits\]*) Returns a floating-point value rounded to the given number of digits to the right of the decimal point. - **Parameters:** - + **Parameters** * **num\*** --- The value to round. * **digits** --- The number of digits to the right of the decimal to round to. - **Examples:** - + **Examples** To round the number 123.456 to an integer: .. code-block:: custsqlite @@ -2936,8 +2694,7 @@ round(*num*, *\[digits\]*) ;SELECT round(123.456, 5) 123.456 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`sign`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -2950,8 +2707,7 @@ row_number() Returns the number of the row within the current partition, starting from 1. - **Examples:** - + **Examples** To number messages from a process: .. code-block:: custsqlite @@ -2963,8 +2719,7 @@ row_number() 3 gw Goodbye, World! 1 hw Hello, World! - **See Also:** - + **See Also** :ref:`cume_dist`, :ref:`dense_rank`, :ref:`first_value`, :ref:`lag`, :ref:`last_value`, :ref:`lead`, :ref:`nth_value`, :ref:`ntile`, :ref:`percent_rank`, :ref:`rank` ---- @@ -2977,13 +2732,11 @@ rtrim(*str*, *\[chars\]*) Returns a string formed by removing any and all characters that appear in the second argument from the right side of the first. - **Parameters:** - + **Parameters** * **str\*** --- The string to trim characters from the right side * **chars** --- The characters to trim. Defaults to spaces. - **Examples:** - + **Examples** To trim the whitespace from the end of the string 'abc ': .. code-block:: custsqlite @@ -2998,8 +2751,7 @@ rtrim(*str*, *\[chars\]*) ;SELECT rtrim('abbbbcccc', 'bc') a - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -3012,12 +2764,10 @@ sign(*num*) Returns the sign of the given number as -1, 0, or 1 - **Parameters:** - + **Parameters** * **num\*** --- The number - **Examples:** - + **Examples** To get the sign of 10: .. code-block:: custsqlite @@ -3039,8 +2789,7 @@ sign(*num*) ;SELECT sign(-10) -1 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`square`, :ref:`sum`, :ref:`total` ---- @@ -3053,12 +2802,10 @@ spooky_hash(*str*) Compute the hash value for the given arguments. - **Parameters:** - + **Parameters** * **str** --- The string to hash - **Examples:** - + **Examples** To produce a hash for the string 'Hello, World!': .. code-block:: custsqlite @@ -3087,8 +2834,7 @@ spooky_hash(*str*) ;SELECT spooky_hash('Hello, World!', 123) f96b3d9c1a19f4394c97a1b79b1880df - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -3101,8 +2847,7 @@ sqlite_compileoption_get(*N*) Returns the N-th compile-time option used to build SQLite or NULL if N is out of range. - **Parameters:** - + **Parameters** * **N\*** --- The option number to get @@ -3116,12 +2861,10 @@ sqlite_compileoption_used(*option*) Returns true (1) or false (0) depending on whether or not that compile-time option was used during the build. - **Parameters:** - + **Parameters** * **option\*** --- The name of the compile-time option. - **Examples:** - + **Examples** To check if the SQLite library was compiled with ENABLE_FTS3: .. code-block:: custsqlite @@ -3162,12 +2905,10 @@ square(*num*) Returns the square of the argument - **Parameters:** - + **Parameters** * **num\*** --- The number to square - **Examples:** - + **Examples** To get the square of two: .. code-block:: custsqlite @@ -3175,8 +2916,7 @@ square(*num*) ;SELECT square(2) 4 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`sum`, :ref:`total` ---- @@ -3189,13 +2929,11 @@ startswith(*str*, *prefix*) Test if a string begins with the given prefix - **Parameters:** - + **Parameters** * **str\*** --- The string to test * **prefix\*** --- The prefix to check in the string - **Examples:** - + **Examples** To test if the string 'foobar' starts with 'foo': .. code-block:: custsqlite @@ -3210,8 +2948,7 @@ startswith(*str*, *prefix*) ;SELECT startswith('foobar', 'bar') 0 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -3224,13 +2961,11 @@ strfilter(*source*, *include*) Returns the source string with only the characters given in the second parameter - **Parameters:** - + **Parameters** * **source\*** --- The string to filter * **include\*** --- The characters to include in the result - **Examples:** - + **Examples** To get the 'b', 'c', and 'd' characters from the string 'abcabc': .. code-block:: custsqlite @@ -3238,8 +2973,7 @@ strfilter(*source*, *include*) ;SELECT strfilter('abcabc', 'bcd') bcbc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -3252,14 +2986,12 @@ strftime(*format*, *timestring*, *modifier*) Returns the date formatted according to the format string specified as the first argument. - **Parameters:** - + **Parameters** * **format\*** --- A format string with substitutions similar to those found in the strftime() standard C library. * **timestring\*** --- The string to convert to a date with time. * **modifier** --- A transformation that is applied to the value to the left. - **Examples:** - + **Examples** To get the year from the timestamp '2017-01-02T03:04:05': .. code-block:: custsqlite @@ -3281,8 +3013,7 @@ strftime(*format*, *timestring*, *modifier*) ;SELECT strftime('Julian day: %J', 1491341842, 'unixepoch') Julian day: 2457848.400949074 - **See Also:** - + **See Also** :ref:`date`, :ref:`datetime`, :ref:`julianday`, :ref:`time`, :ref:`timediff`, :ref:`timeslice` ---- @@ -3295,14 +3026,12 @@ substr(*str*, *start*, *\[size\]*) Returns a substring of input string X that begins with the Y-th character and which is Z characters long. - **Parameters:** - + **Parameters** * **str\*** --- The string to extract a substring from. * **start\*** --- The index within 'str' that is the start of the substring. Indexes begin at 1. A negative value means that the substring is found by counting from the right rather than the left. * **size** --- The size of the substring. If not given, then all characters through the end of the string are returned. If the value is negative, then the characters before the start are returned. - **Examples:** - + **Examples** To get the substring starting at the second character until the end of the string 'abc': .. code-block:: custsqlite @@ -3331,8 +3060,7 @@ substr(*str*, *start*, *\[size\]*) ;SELECT substr('abc', -1, -1) b - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`trim`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -3345,12 +3073,10 @@ sum(*X*) Returns the sum of the values in the group as an integer. - **Parameters:** - + **Parameters** * **X\*** --- The values to add. - **Examples:** - + **Examples** To sum all of the values in the column 'ex_duration' from the table 'lnav_example_log': .. code-block:: custsqlite @@ -3358,8 +3084,7 @@ sum(*X*) ;SELECT sum(ex_duration) FROM lnav_example_log 17 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`total` ---- @@ -3372,13 +3097,11 @@ time(*timestring*, *modifier*) Returns the time in this format: HH:MM:SS. - **Parameters:** - + **Parameters** * **timestring\*** --- The string to convert to a time. * **modifier** --- A transformation that is applied to the value to the left. - **Examples:** - + **Examples** To get the time portion of the timestamp '2017-01-02T03:04:05': .. code-block:: custsqlite @@ -3400,8 +3123,7 @@ time(*timestring*, *modifier*) ;SELECT time(1491341842, 'unixepoch') 21:37:22 - **See Also:** - + **See Also** :ref:`date`, :ref:`datetime`, :ref:`julianday`, :ref:`strftime`, :ref:`timediff`, :ref:`timeslice` ---- @@ -3414,13 +3136,11 @@ timediff(*time1*, *time2*) Compute the difference between two timestamps in seconds - **Parameters:** - + **Parameters** * **time1\*** --- The first timestamp * **time2\*** --- The timestamp to subtract from the first - **Examples:** - + **Examples** To get the difference between two timestamps: .. code-block:: custsqlite @@ -3435,8 +3155,7 @@ timediff(*time1*, *time2*) ;SELECT timediff('today', 'yesterday') 86400.0 - **See Also:** - + **See Also** :ref:`date`, :ref:`datetime`, :ref:`julianday`, :ref:`strftime`, :ref:`time`, :ref:`timeslice` ---- @@ -3449,13 +3168,11 @@ timeslice(*time*, *slice*) Return the start of the slice of time that the given timestamp falls in. - **Parameters:** - + **Parameters** * **time\*** --- The timestamp to get the time slice for. * **slice\*** --- The size of the time slices - **Examples:** - + **Examples** To get the timestamp rounded down to the start of the ten minute slice: .. code-block:: custsqlite @@ -3473,8 +3190,7 @@ timeslice(*time*, *slice*) 2017-02-03 04:25:00.000 1 2017-02-03 04:55:00.000 1 - **See Also:** - + **See Also** :ref:`date`, :ref:`datetime`, :ref:`julianday`, :ref:`strftime`, :ref:`time`, :ref:`timediff` ---- @@ -3487,12 +3203,10 @@ total(*X*) Returns the sum of the values in the group as a floating-point. - **Parameters:** - + **Parameters** * **X\*** --- The values to add. - **Examples:** - + **Examples** To total all of the values in the column 'ex_duration' from the table 'lnav_example_log': .. code-block:: custsqlite @@ -3500,8 +3214,7 @@ total(*X*) ;SELECT total(ex_duration) FROM lnav_example_log 17.0 - **See Also:** - + **See Also** :ref:`abs`, :ref:`acos`, :ref:`acosh`, :ref:`asin`, :ref:`asinh`, :ref:`atan2`, :ref:`atan`, :ref:`atanh`, :ref:`atn2`, :ref:`avg`, :ref:`ceil`, :ref:`degrees`, :ref:`exp`, :ref:`floor`, :ref:`log10`, :ref:`log`, :ref:`max`, :ref:`min`, :ref:`pi`, :ref:`power`, :ref:`radians`, :ref:`round`, :ref:`sign`, :ref:`square`, :ref:`sum` ---- @@ -3525,13 +3238,11 @@ trim(*str*, *\[chars\]*) Returns a string formed by removing any and all characters that appear in the second argument from the left and right sides of the first. - **Parameters:** - + **Parameters** * **str\*** --- The string to trim characters from the left and right sides. * **chars** --- The characters to trim. Defaults to spaces. - **Examples:** - + **Examples** To trim whitespace from the start and end of the string ' abc ': .. code-block:: custsqlite @@ -3546,8 +3257,7 @@ trim(*str*, *\[chars\]*) ;SELECT trim('-+abc+-', '-+') abc - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`unicode`, :ref:`upper`, :ref:`xpath` ---- @@ -3560,12 +3270,10 @@ typeof(*X*) Returns a string that indicates the datatype of the expression X: "null", "integer", "real", "text", or "blob". - **Parameters:** - + **Parameters** * **X\*** --- The expression to check. - **Examples:** - + **Examples** To get the type of the number 1: .. code-block:: custsqlite @@ -3591,12 +3299,10 @@ unicode(*X*) Returns the numeric unicode code point corresponding to the first character of the string X. - **Parameters:** - + **Parameters** * **X\*** --- The string to examine. - **Examples:** - + **Examples** To get the unicode code point for the first character of 'abc': .. code-block:: custsqlite @@ -3604,8 +3310,7 @@ unicode(*X*) ;SELECT unicode('abc') 97 - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`upper`, :ref:`xpath` ---- @@ -3618,8 +3323,7 @@ unlikely(*value*) Short-hand for likelihood(X, 0.0625) - **Parameters:** - + **Parameters** * **value\*** --- The boolean value to return @@ -3633,12 +3337,10 @@ upper(*str*) Returns a copy of the given string with all ASCII characters converted to upper case. - **Parameters:** - + **Parameters** * **str\*** --- The string to convert. - **Examples:** - + **Examples** To uppercase the string 'aBc': .. code-block:: custsqlite @@ -3646,8 +3348,7 @@ upper(*str*) ;SELECT upper('aBc') ABC - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`xpath` ---- @@ -3660,13 +3361,11 @@ xpath(*xpath*, *xmldoc*) A table-valued function that executes an xpath expression over an XML string and returns the selected values. - **Parameters:** - + **Parameters** * **xpath\*** --- The XPATH expression to evaluate over the XML document. * **xmldoc\*** --- The XML document as a string. - **Examples:** - + **Examples** To select the XML nodes on the path '/abc/def': .. code-block:: custsqlite @@ -3692,8 +3391,7 @@ xpath(*xpath*, *xmldoc*) result node_path node_attr node_text Hello ★ /abc/def/text() {} Hello ★ - **See Also:** - + **See Also** :ref:`char`, :ref:`charindex`, :ref:`endswith`, :ref:`extract`, :ref:`group_concat`, :ref:`group_spooky_hash`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`trim`, :ref:`unicode`, :ref:`upper` ---- @@ -3706,8 +3404,7 @@ zeroblob(*N*) Returns a BLOB consisting of N bytes of 0x00. - **Parameters:** - + **Parameters** * **N\*** --- The size of the BLOB. diff --git a/src/keymaps/README.md b/src/keymaps/README.md index e29108ae..b30f920f 100644 --- a/src/keymaps/README.md +++ b/src/keymaps/README.md @@ -1,4 +1,5 @@ # Keymaps This directory contains the built-in keymap definitions. The files are -turned into C using `bin2c` and compiled into the executable. +turned into C using `bin2c` and compiled into the executable. New keymaps +need to be added to the [keymaps.am](keymaps.am) file. diff --git a/src/keymaps/keymaps.am b/src/keymaps/keymaps.am new file mode 100644 index 00000000..423be56b --- /dev/null +++ b/src/keymaps/keymaps.am @@ -0,0 +1,8 @@ + +KEYMAP_FILES = \ + $(srcdir)/%reldir%/de-keymap.json \ + $(srcdir)/%reldir%/default-keymap.json \ + $(srcdir)/%reldir%/fr-keymap.json \ + $(srcdir)/%reldir%/uk-keymap.json \ + $(srcdir)/%reldir%/us-keymap.json \ + $() diff --git a/src/line_buffer.cc b/src/line_buffer.cc index b6c99666..c1b83f09 100644 --- a/src/line_buffer.cc +++ b/src/line_buffer.cc @@ -319,7 +319,7 @@ line_buffer::~line_buffer() void line_buffer::set_fd(auto_fd &fd) { - off_t newoff = 0; + file_off_t newoff = 0; if (this->lb_gz_file) { this->lb_gz_file.close(); @@ -411,14 +411,14 @@ void line_buffer::resize_buffer(size_t new_max) } } -void line_buffer::ensure_available(off_t start, ssize_t max_length) +void line_buffer::ensure_available(file_off_t start, ssize_t max_length) { ssize_t prefill, available; require(max_length <= MAX_LINE_BUFFER_SIZE); if (this->lb_file_size != -1) { - if (start + (off_t)max_length > this->lb_file_size) { + if (start + (file_off_t)max_length > this->lb_file_size) { max_length = (this->lb_file_size - start); } } @@ -428,7 +428,7 @@ void line_buffer::ensure_available(off_t start, ssize_t max_length) * after. */ if (start < this->lb_file_offset || - start > (off_t)(this->lb_file_offset + this->lb_buffer_size)) { + start > (file_off_t)(this->lb_file_offset + this->lb_buffer_size)) { /* * The request is outside the cached range, need to reload the * whole thing. @@ -444,7 +444,7 @@ void line_buffer::ensure_available(off_t start, ssize_t max_length) */ this->lb_file_offset = this->lb_file_size - std::min(this->lb_file_size, - this->lb_buffer_max); + (file_ssize_t) this->lb_buffer_max); } else { this->lb_file_offset = start; @@ -483,7 +483,7 @@ void line_buffer::ensure_available(off_t start, ssize_t max_length) } } -bool line_buffer::fill_range(off_t start, ssize_t max_length) +bool line_buffer::fill_range(file_off_t start, ssize_t max_length) { bool retval = false; @@ -530,7 +530,7 @@ bool line_buffer::fill_range(off_t start, ssize_t max_length) lock_hack::guard guard; char scratch[32 * 1024]; BZFILE * bz_file; - off_t seek_to; + file_off_t seek_to; int bzfd; /* @@ -602,7 +602,7 @@ bool line_buffer::fill_range(off_t start, ssize_t max_length) if (!this->lb_seekable) { this->lb_file_size = this->lb_file_offset + this->lb_buffer_size; } - if (start < (off_t) this->lb_file_size) { + if (start < (file_off_t) this->lb_file_size) { retval = true; } @@ -763,7 +763,7 @@ Result line_buffer::read_range(const file_range { shared_buffer_ref retval; char *line_start; - ssize_t avail; + file_ssize_t avail; if (this->lb_last_line_offset != -1 && fr.fr_offset > this->lb_last_line_offset) { diff --git a/src/line_buffer.hh b/src/line_buffer.hh index 28ad07a5..51deb9c5 100644 --- a/src/line_buffer.hh +++ b/src/line_buffer.hh @@ -178,7 +178,7 @@ public: /** * @return The size of the file or the amount of data pulled from a pipe. */ - ssize_t get_file_size() const { return this->lb_file_size; }; + file_ssize_t get_file_size() const { return this->lb_file_size; }; bool is_pipe() const { return !this->lb_seekable; @@ -192,7 +192,7 @@ public: return this->lb_gz_file || this->lb_bz_file; }; - off_t get_read_offset(off_t off) const + file_off_t get_read_offset(file_off_t off) const { if (this->is_compressed()) { return this->lb_compressed_offset; @@ -202,7 +202,7 @@ public: } }; - bool is_data_available(off_t off, off_t stat_size) const { + bool is_data_available(file_off_t off, file_off_t stat_size) const { if (this->is_compressed()) { return (this->lb_file_size == -1 || off < this->lb_file_size); } @@ -253,10 +253,10 @@ private: * @param off The file offset to check for in the buffer. * @return True if the given offset is cached in the buffer. */ - bool in_range(off_t off) const + bool in_range(file_off_t off) const { return this->lb_file_offset <= off && - off < (int)(this->lb_file_offset + this->lb_buffer_size); + off < (this->lb_file_offset + this->lb_buffer_size); }; void resize_buffer(size_t new_max); @@ -273,7 +273,7 @@ private: * @param start The file offset of the start of the line. * @param max_length The amount of data to be cached in the buffer. */ - void ensure_available(off_t start, ssize_t max_length); + void ensure_available(file_off_t start, ssize_t max_length); /** * Fill the buffer with the given range of data from the file. @@ -283,7 +283,7 @@ private: * @param max_length The maximum amount of data to read from the file. * @return True if any data was read from the file. */ - bool fill_range(off_t start, ssize_t max_length); + bool fill_range(file_off_t start, ssize_t max_length); /** * After a successful fill, the cached data can be retrieved with this @@ -295,9 +295,9 @@ private: * @return A pointer to the start of the cached data in the internal * buffer. */ - char *get_range(off_t start, ssize_t &avail_out) const + char *get_range(file_off_t start, file_ssize_t &avail_out) const { - off_t buffer_offset = start - this->lb_file_offset; + auto buffer_offset = start - this->lb_file_offset; char *retval; require(buffer_offset >= 0); @@ -314,16 +314,16 @@ private: auto_fd lb_fd; /*< The file to read data from. */ gz_indexed lb_gz_file; /*< File reader for gzipped files. */ bool lb_bz_file; /*< Flag set for bzip2 compressed files. */ - off_t lb_compressed_offset; /*< The offset into the compressed file. */ + file_off_t lb_compressed_offset; /*< The offset into the compressed file. */ auto_mem lb_buffer; /*< The internal buffer where data is cached */ - ssize_t lb_file_size; /*< + file_ssize_t lb_file_size; /*< * The size of the file. When lb_fd refers to * a pipe, this is set to the amount of data * read from the pipe when EOF is reached. */ - off_t lb_file_offset; /*< + file_off_t lb_file_offset; /*< * Data cached in the buffer comes from this * offset in the file. */ @@ -332,6 +332,6 @@ private: ssize_t lb_buffer_max; /*< The amount of allocated memory for the * buffer. */ bool lb_seekable; /*< Flag set for seekable file descriptors. */ - off_t lb_last_line_offset; /*< */ + file_off_t lb_last_line_offset; /*< */ }; #endif diff --git a/src/lnav.cc b/src/lnav.cc index 1f472a3b..c5860e94 100644 --- a/src/lnav.cc +++ b/src/lnav.cc @@ -388,7 +388,9 @@ public: }; - void logfile_indexing(const shared_ptr& lf, off_t off, size_t total) + void logfile_indexing(const shared_ptr& lf, + file_off_t off, + file_size_t total) { static sig_atomic_t index_counter = 0; diff --git a/src/lnav_config.cc b/src/lnav_config.cc index ef982baa..32e1c020 100644 --- a/src/lnav_config.cc +++ b/src/lnav_config.cc @@ -459,10 +459,6 @@ static struct json_path_container global_var_handlers = { static struct json_path_container style_config_handlers = json_path_container{ - yajlpp::property_handler("semantic") - .with_description( - "Pick a color based on the text being highlighted") - .FOR_FIELD(style_config, sc_semantic), yajlpp::property_handler("color") .with_synopsis("#hex|color_name") .with_description( diff --git a/src/log_format.cc b/src/log_format.cc index 362d9f4b..6fa6c085 100644 --- a/src/log_format.cc +++ b/src/log_format.cc @@ -1926,11 +1926,12 @@ void external_log_format::build(std::vector &errors) { external_log_format::highlighter_def &hd = hd_pair.second; const std::string &pattern = hd.hd_pattern; const char *errptr; - rgb_color fg, bg; + auto fg = styling::color_unit::make_empty(); + auto bg = styling::color_unit::make_empty(); int eoff, attrs = 0; if (!hd.hd_color.empty()) { - fg = rgb_color::from_str(hd.hd_color) + fg = styling::color_unit::from_str(hd.hd_color) .unwrapOrElse([&](const auto& msg) { errors.push_back("error:" + this->elf_name.to_string() @@ -1938,12 +1939,12 @@ void external_log_format::build(std::vector &errors) { + hd_pair.first.to_string() + "/color:" + msg); - return rgb_color{}; + return styling::color_unit::make_empty(); }); } if (!hd.hd_background_color.empty()) { - bg = rgb_color::from_str(hd.hd_background_color) + bg = styling::color_unit::from_str(hd.hd_background_color) .unwrapOrElse([&](const auto& msg) { errors.push_back("error:" + this->elf_name.to_string() @@ -1951,7 +1952,7 @@ void external_log_format::build(std::vector &errors) { + hd_pair.first.to_string() + "/color:" + msg); - return rgb_color{}; + return styling::color_unit::make_empty(); }); } diff --git a/src/log_format_fwd.hh b/src/log_format_fwd.hh index 52065f05..edcfbc8c 100644 --- a/src/log_format_fwd.hh +++ b/src/log_format_fwd.hh @@ -62,7 +62,7 @@ public: * @param millis The millisecond timestamp for the line. * @param l The logging level. */ - logline(off_t off, + logline(file_off_t off, time_t t, uint16_t millis, log_level_t l, @@ -80,7 +80,7 @@ public: memset(this->ll_schema, 0, sizeof(this->ll_schema)); }; - logline(off_t off, + logline(file_off_t off, const struct timeval &tv, log_level_t l, uint8_t mod = 0, @@ -97,7 +97,7 @@ public: }; /** @return The offset of the line in the file. */ - off_t get_offset() const { return this->ll_offset; }; + file_off_t get_offset() const { return this->ll_offset; }; uint16_t get_sub_offset() const { return this->ll_sub_offset; }; @@ -283,8 +283,8 @@ public: (this->ll_millis <= (rhs.tv_usec / 1000)))); }; private: - off_t ll_offset; - time_t ll_time; + file_off_t ll_offset; + time_t ll_time; unsigned int ll_millis : 10; unsigned int ll_opid : 6; unsigned int ll_sub_offset : 15; diff --git a/src/log_format_loader.cc b/src/log_format_loader.cc index 68da8891..afa7846a 100644 --- a/src/log_format_loader.cc +++ b/src/log_format_loader.cc @@ -506,7 +506,7 @@ static struct json_path_container value_def_handlers = { yajlpp::property_handler("foreign-key") .with_synopsis("") .with_description("Indicates whether or not this field should be treated as a foreign key for row in another table") - .FOR_FIELD(external_log_format::value_def, vd_foreign_key), + .for_field(&external_log_format::value_def::vd_foreign_key), yajlpp::property_handler("hidden") .with_synopsis("") diff --git a/src/logfile.cc b/src/logfile.cc index 63737a93..0371a020 100644 --- a/src/logfile.cc +++ b/src/logfile.cc @@ -123,6 +123,9 @@ bool logfile::exists() const } if (::stat(this->lf_filename.c_str(), &st) == -1) { + log_error("%s: stat failed -- %s", + this->lf_filename.c_str(), + strerror(errno)); return false; } @@ -318,7 +321,7 @@ logfile::rebuild_result_t logfile::rebuild_index() // line buffer's notion of the file size since it may be compressed. bool has_format = this->lf_format.get() != nullptr; struct rusage begin_rusage; - off_t off; + file_off_t off; size_t begin_size = this->lf_index.size(); bool record_rusage = this->lf_index.size() == 1; off_t begin_index_size = this->lf_index_size; @@ -350,7 +353,7 @@ logfile::rebuild_result_t logfile::rebuild_index() if (!this->lf_index.empty()) { auto last_line = this->lf_index.end(); --last_line; - off_t check_line_off = last_line->get_offset(); + auto check_line_off = last_line->get_offset(); auto last_length = ssize_t(this->line_length(last_line, false)); auto read_result = this->lf_line_buffer.read_range({ @@ -384,6 +387,9 @@ logfile::rebuild_result_t logfile::rebuild_index() auto load_result = this->lf_line_buffer.load_next_line(prev_range); if (load_result.isErr()) { + log_error("%s: load next line failure -- %s", + this->lf_filename.c_str(), + load_result.unwrapErr().c_str()); this->close(); return RR_INVALID; } @@ -418,6 +424,9 @@ logfile::rebuild_result_t logfile::rebuild_index() auto read_result = this->lf_line_buffer.read_range(li.li_file_range); if (read_result.isErr()) { + log_error("%s:read failure -- %s", + this->lf_filename.c_str(), + read_result.unwrapErr().c_str()); this->close(); return RR_INVALID; } diff --git a/src/logfile.hh b/src/logfile.hh index e7841bd9..0cbe797a 100644 --- a/src/logfile.hh +++ b/src/logfile.hh @@ -68,8 +68,8 @@ public: * @param total The total size of the file. */ virtual void logfile_indexing(const std::shared_ptr& lf, - off_t off, - size_t total) = 0; + file_off_t off, + file_size_t total) = 0; }; struct logfile_activity { @@ -154,7 +154,7 @@ public: return this->lf_valid_filename; }; - off_t get_index_size() const { + file_off_t get_index_size() const { return this->lf_index_size; } @@ -302,7 +302,7 @@ public: file_range get_file_range(const_iterator ll, bool include_continues = true) { return {ll->get_offset(), - (ssize_t) this->line_length(ll, include_continues)}; + (file_ssize_t) this->line_length(ll, include_continues)}; } void read_full_message(const_iterator ll, shared_buffer_ref &msg_out, int max_lines=50); @@ -392,7 +392,7 @@ protected: std::shared_ptr lf_format; std::vector lf_index; time_t lf_index_time{0}; - off_t lf_index_size{0}; + file_off_t lf_index_size{0}; bool lf_sort_needed{false}; line_buffer lf_line_buffer; int lf_time_offset_line{0}; @@ -406,14 +406,14 @@ protected: text_format_t lf_text_format{text_format_t::TF_UNKNOWN}; uint32_t lf_out_of_time_order_count{0}; - nonstd::optional> lf_next_line_cache; + nonstd::optional> lf_next_line_cache; }; class logline_observer { public: virtual ~logline_observer() = default; - virtual void logline_restart(const logfile &lf, size_t rollback_size) = 0; + virtual void logline_restart(const logfile &lf, file_size_t rollback_size) = 0; virtual void logline_new_lines( const logfile &lf, diff --git a/src/logfile_sub_source.cc b/src/logfile_sub_source.cc index 1589783e..20884322 100644 --- a/src/logfile_sub_source.cc +++ b/src/logfile_sub_source.cc @@ -395,17 +395,15 @@ void logfile_sub_source::text_attrs_for_line(textview_curses &lv, continue; } - auto start = this->lss_token_value.c_str(); - int id_attrs = vc.attrs_for_ident(&start[line_value.lv_origin.lr_start], - line_value.lv_origin.sublen(this->lss_token_value)); - line_range ident_range = line_value.lv_origin; if (this->lss_token_flags & RF_FULL) { ident_range = line_value.origin_in_full_msg( this->lss_token_value.c_str(), this->lss_token_value.length()); } - value_out.emplace_back(ident_range, &view_curses::VC_STYLE, id_attrs); + value_out.emplace_back(ident_range, + &view_curses::VC_ROLE, + view_colors::VCR_IDENTIFIER); } if (this->lss_token_shift_size) { diff --git a/src/readline_highlighters.cc b/src/readline_highlighters.cc index 8ab4174e..799a1fd2 100644 --- a/src/readline_highlighters.cc +++ b/src/readline_highlighters.cc @@ -404,9 +404,9 @@ void readline_command_highlighter(attr_line_t &al, int x) attr_t color_hint_attrs = vc.attrs_for_role(view_colors::VCR_COLOR_HINT); int pnum = PAIR_NUMBER(color_hint_attrs); - rgb_color::from_str(hash_color).then([&](const auto& rgb_fg) { + styling::color_unit::from_str(hash_color).then([&](const auto& rgb_fg) { pnum -= 1; - vc.ensure_color_pair(pnum, rgb_fg, rgb_color{}); + vc.ensure_color_pair(pnum, rgb_fg, styling::color_unit::make_empty()); al.get_attrs().emplace_back( line_range{cap->c_begin, cap->c_begin + 1}, diff --git a/src/readline_possibilities.cc b/src/readline_possibilities.cc index bc87ade9..36c7284c 100644 --- a/src/readline_possibilities.cc +++ b/src/readline_possibilities.cc @@ -257,7 +257,7 @@ void add_filter_expr_possibilities(readline_curses *rlc, int context, const std: lf->read_full_message(ll, sbr); format->annotate(cl, sbr, sa, values); for (auto& lv : values) { - if (!lv.lv_meta.lvm_identifier) { + if (!lv.lv_meta.lvm_struct_name.empty()) { continue; } diff --git a/src/scripts/README.md b/src/scripts/README.md index ab4f9ed6..e06d6092 100644 --- a/src/scripts/README.md +++ b/src/scripts/README.md @@ -1,4 +1,5 @@ # Scripts This directory contains the built-in lnav scripts. The files are -turned into C using `bin2c` and compiled into the executable. +turned into C using `bin2c` and compiled into the executable. New scripts +need to be added to the [scripts.am](scripts.am) file. diff --git a/src/scripts/scripts.am b/src/scripts/scripts.am new file mode 100644 index 00000000..50e10fd1 --- /dev/null +++ b/src/scripts/scripts.am @@ -0,0 +1,12 @@ + +BUILTIN_LNAVSCRIPTS = \ + $(srcdir)/scripts/dhclient-summary.lnav \ + $(srcdir)/scripts/lnav-pop-view.lnav \ + $(srcdir)/scripts/partition-by-boot.lnav \ + $(srcdir)/scripts/rename-stdin.lnav \ + $(srcdir)/scripts/search-for.lnav \ + $() + +BUILTIN_SHSCRIPTS = \ + $(srcdir)/scripts/dump-pid.sh \ + $() diff --git a/src/styling.cc b/src/styling.cc index 70f4c952..b20eb1b2 100644 --- a/src/styling.cc +++ b/src/styling.cc @@ -211,3 +211,18 @@ short term_color_palette::match_color(const lab_color &to_match) return lowest_id; } + +namespace styling { + +Result color_unit::from_str(const string_fragment &sf) +{ + if (sf == "semantic()") { + return Ok(color_unit{ semantic{} }); + } + + auto retval = TRY(rgb_color::from_str(sf)); + + return Ok(color_unit{ retval }); +} + +} diff --git a/src/styling.hh b/src/styling.hh index 507d93a3..37cfe292 100644 --- a/src/styling.hh +++ b/src/styling.hh @@ -32,21 +32,27 @@ #include #include +#include #include #include "log_level.hh" #include "base/result.h" #include "base/intern_string.hh" +#include "mapbox/variant.hpp" struct rgb_color { static Result from_str(const string_fragment &sf); explicit rgb_color(short r = -1, short g = -1, short b = -1) - : rc_r(r), rc_g(g), rc_b(b) { + : rc_r(r), rc_g(g), rc_b(b) + { } - bool empty() const { - return this->rc_r == -1 && this->rc_g == -1 && this->rc_b == -1; + bool empty() const + { + return this->rc_r == -1 && + this->rc_g == -1 && + this->rc_b == -1; } bool operator==(const rgb_color &rhs) const; @@ -115,8 +121,36 @@ struct term_color_palette { std::vector tc_palette; }; +namespace styling { + +struct semantic {}; + +class color_unit { +public: + static Result from_str(const string_fragment& sf); + + static color_unit make_empty() { + return { rgb_color{} }; + } + + bool empty() const { + return this->cu_value.match( + [](semantic) { return false; }, + [](const rgb_color& rc) { return rc.empty(); } + ); + } + + using variants_t = mapbox::util::variant; + + variants_t cu_value; + +private: + color_unit(variants_t value) : cu_value(std::move(value)) {} +}; + +} + struct style_config { - bool sc_semantic{false}; std::string sc_color; std::string sc_background_color; bool sc_underline{false}; diff --git a/src/textfile_highlighters.cc b/src/textfile_highlighters.cc index 4e7332fd..12d38a9f 100644 --- a/src/textfile_highlighters.cc +++ b/src/textfile_highlighters.cc @@ -45,7 +45,7 @@ static pcre *xpcre_compile(const char *pattern, int options = 0) options, &errptr, &eoff, - NULL)) == NULL) { + nullptr)) == nullptr) { fprintf(stderr, "internal error: failed to compile -- %s\n", pattern); fprintf(stderr, "internal error: %s\n", errptr); @@ -395,10 +395,10 @@ void setup_highlights(highlight_map_t &hm) "\\d+")) .with_role(view_colors::VCR_FILE); hm[{highlight_source_t::INTERNAL, "1.stringd"}] = highlighter(xpcre_compile( - "\"(?:\\\\.|[^\"])*\"")) + R"("(?:\\.|[^"])*")")) .with_role(view_colors::VCR_STRING); hm[{highlight_source_t::INTERNAL, "1.strings"}] = highlighter(xpcre_compile( - "(?tc_highlights.erase(iter); } + std::map vars; + auto curr_theme_iter = lnav_config.lc_ui_theme_defs.find(lnav_config.lc_ui_theme); + if (curr_theme_iter != lnav_config.lc_ui_theme_defs.end()) { + vars = curr_theme_iter->second.lt_vars; + } + for (const auto& theme_name : {DEFAULT_THEME_NAME, lnav_config.lc_ui_theme}) { auto theme_iter = lnav_config.lc_ui_theme_defs.find(theme_name); @@ -171,20 +177,20 @@ void textview_curses::reload_config(error_reporter &reporter) fg1 = sc.sc_color; bg1 = sc.sc_background_color; - shlex(fg1).eval(fg_color, theme_iter->second.lt_vars); - shlex(bg1).eval(bg_color, theme_iter->second.lt_vars); + shlex(fg1).eval(fg_color, vars); + shlex(bg1).eval(bg_color, vars); - auto fg = rgb_color::from_str(fg_color) + auto fg = styling::color_unit::from_str(fg_color) .unwrapOrElse([&](const auto& msg) { reporter(&sc.sc_color, errmsg); invalid = true; - return rgb_color{}; + return styling::color_unit::make_empty(); }); - auto bg = rgb_color::from_str(bg_color) + auto bg = styling::color_unit::from_str(bg_color) .unwrapOrElse([&](const auto& msg) { reporter(&sc.sc_background_color, errmsg); invalid = true; - return rgb_color{}; + return styling::color_unit::make_empty(); }); if (invalid) { continue; @@ -200,8 +206,7 @@ void textview_curses::reload_config(error_reporter &reporter) highlighter(code) .with_pattern(hl_pair.second.hc_regex) .with_attrs(attrs != 0 ? attrs : -1) - .with_color(fg, bg) - .with_semantic(sc.sc_semantic); + .with_color(fg, bg); } } } diff --git a/src/themes/README.md b/src/themes/README.md index da69fe0e..f52affd3 100644 --- a/src/themes/README.md +++ b/src/themes/README.md @@ -1,4 +1,5 @@ # Themes This directory contains the built-in theme definitions. The files are -turned into C using `bin2c` and compiled into the executable. +turned into C using `bin2c` and compiled into the executable. New themes +need to be added to the [themes.am](themes.am) file. diff --git a/src/themes/default-theme.json b/src/themes/default-theme.json index cde0c74a..99d7c095 100644 --- a/src/themes/default-theme.json +++ b/src/themes/default-theme.json @@ -3,13 +3,17 @@ "ui": { "theme-defs": { "default": { + "vars": { + "semantic_highlight_color": "semantic()" + }, "styles": { "text": { "color": "Silver", "background-color": "Black" }, "identifier": { - "background-color": "" + "background-color": "", + "color": "semantic()" }, "alt-text": { "color": "Silver", @@ -158,21 +162,21 @@ }, "highlights": { "colors": { - "pattern": "(?:#[a-fA-F0-9]{6}|#[a-fA-F0-9]{3})", + "pattern": "(?:#[a-fA-F0-9]{6}|#[a-fA-F0-9]{3}\\b)", "style": { - "semantic": true + "color": "${semantic_highlight_color}" } }, "ipv4": { "pattern": "\\b(?=]+)[^>]*>", "style": { - "semantic": true + "color": "${semantic_highlight_color}" } } } diff --git a/src/themes/eldar.json b/src/themes/eldar.json index 9e91b6a2..b84511b3 100644 --- a/src/themes/eldar.json +++ b/src/themes/eldar.json @@ -11,11 +11,13 @@ "blue": "#729fcf", "cyan": "#34e2e2", "green": "#8ae234", - "white": "#ffffff" + "white": "#ffffff", + "semantic_highlight_color": "semantic()" }, "styles": { "identifier": { - "background-color": "" + "background-color": "", + "color": "semantic()" }, "text": { "color": "$white", diff --git a/src/themes/grayscale.json b/src/themes/grayscale.json new file mode 100644 index 00000000..4cf0df2a --- /dev/null +++ b/src/themes/grayscale.json @@ -0,0 +1,141 @@ +{ + "$schema": "https://lnav.org/schemas/config-v1.schema.json", + "ui": { + "theme-defs": { + "grayscale": { + "vars": { + "black": "#2d2a2e", + "red": "#f92772", + "green": "#a7e22e", + "yellow": "#fe9720", + "blue": "#5394ec", + "magenta": "#ae81ff", + "cyan": "#66d9ee", + "white": "#f6f6f6", + "plaintext": "#ccc" + }, + "styles": { + "identifier": { + "background-color": "", + "color": "", + "bold": true + }, + "text": { + "color": "", + "background-color": "" + }, + "alt-text": { + "color": "", + "background-color": "", + "bold": true + }, + "ok": { + "color": "$green", + "bold": true + }, + "error": { + "color": "$red", + "bold": true + }, + "warning": { + "color": "$yellow", + "bold": true + }, + "hidden": { + "color": "$yellow", + "bold": true + }, + "adjusted-time": { + "color": "$magenta" + }, + "skewed-time": { + "color": "$yellow" + }, + "offset-time": { + "color": "$cyan" + }, + "invalid-msg": { + "color": "$yellow" + }, + "focused": { + "color": "$black", + "background-color": "$plaintext" + }, + "disabled-focused": { + "color": "$plaintext", + "background-color": "#333" + }, + "popup": { + "color": "$plaintext", + "background-color": "#626262" + }, + "scrollbar": { + "color": "$black", + "background-color": "#888" + } + }, + "status-styles": { + "disabled-title": { + "color": "#5394ec", + "background-color": "#353535", + "bold": true + }, + "title": { + "color": "#f6f6f6", + "background-color": "#8a8a8a", + "bold": true + }, + "subtitle": { + "color": "#e4e4e4", + "background-color": "#626262", + "bold": true + }, + "title-hotkey": { + "color": "$black", + "background-color": "#5394ec", + "underline": true + }, + "hotkey": { + "color": "#fff", + "background-color": "#353535", + "underline": true + }, + "text": { + "color": "#f6f6f6", + "background-color": "#353535" + }, + "warn": { + "color": "$yellow", + "background-color": "#353535" + }, + "alert": { + "color": "$red", + "background-color": "#353535" + }, + "active": { + "color": "$green", + "background-color": "#353535" + }, + "inactive": { + "color": "#555", + "background-color": "#2f2f2f" + } + }, + "log-level-styles": { + "warning": { + "color": "$yellow" + }, + "error": { + "color": "$red" + }, + "critical": { + "color": "$red" + }, + "fatal": { + "color": "$red" + } + } + } + } + } +} \ No newline at end of file diff --git a/src/themes/monocai.json b/src/themes/monocai.json index 3f498d7e..2c6d5a74 100644 --- a/src/themes/monocai.json +++ b/src/themes/monocai.json @@ -11,11 +11,13 @@ "blue": "#5394ec", "magenta": "#ae81ff", "cyan": "#66d9ee", - "white": "#808080" + "white": "#808080", + "semantic_highlight_color": "semantic()" }, "styles": { "identifier": { - "background-color": "$black" + "background-color": "$black", + "color": "semantic()" }, "text": { "color": "#f6f6f6", diff --git a/src/themes/night-owl.json b/src/themes/night-owl.json index 74ca4867..8eb442a1 100644 --- a/src/themes/night-owl.json +++ b/src/themes/night-owl.json @@ -11,11 +11,13 @@ "blue": "#5394ec", "magenta": "#ff70ff", "cyan": "#33cccc", - "white": "#d6deeb" + "white": "#d6deeb", + "semantic_highlight_color": "semantic()" }, "styles": { "identifier": { - "background-color": "#011627" + "background-color": "#011627", + "color": "semantic()" }, "text": { "color": "#d6deeb", diff --git a/src/themes/solarized-dark.json b/src/themes/solarized-dark.json index 75376aef..6ff030dc 100644 --- a/src/themes/solarized-dark.json +++ b/src/themes/solarized-dark.json @@ -20,11 +20,13 @@ "violet": "#6c71c4", "blue": "#268bd2", "cyan": "#2aa198", - "green": "#859900" + "green": "#859900", + "semantic_highlight_color": "semantic()" }, "styles": { "identifier": { - "background-color": "$base03" + "background-color": "$base03", + "color": "semantic()" }, "text": { "color": "$base0", diff --git a/src/themes/solarized-light.json b/src/themes/solarized-light.json index 76d2bafd..f5b7e8dd 100644 --- a/src/themes/solarized-light.json +++ b/src/themes/solarized-light.json @@ -20,11 +20,13 @@ "violet": "#6c71c4", "blue": "#268bd2", "cyan": "#2aa198", - "green": "#859900" + "green": "#859900", + "semantic_highlight_color": "semantic()" }, "styles": { "identifier": { - "background-color": "$base3" + "background-color": "$base3", + "color": "semantic()" }, "text": { "color": "$base00", diff --git a/src/themes/themes.am b/src/themes/themes.am new file mode 100644 index 00000000..42eacb6f --- /dev/null +++ b/src/themes/themes.am @@ -0,0 +1,10 @@ + +THEME_FILES = \ + $(srcdir)/%reldir%/default-theme.json \ + $(srcdir)/%reldir%/eldar.json \ + $(srcdir)/%reldir%/grayscale.json \ + $(srcdir)/%reldir%/monocai.json \ + $(srcdir)/%reldir%/night-owl.json \ + $(srcdir)/%reldir%/solarized-dark.json \ + $(srcdir)/%reldir%/solarized-light.json \ + $() diff --git a/src/top_status_source.cc b/src/top_status_source.cc index cb13d7b8..072c7892 100644 --- a/src/top_status_source.cc +++ b/src/top_status_source.cc @@ -81,10 +81,9 @@ void top_status_source::update_time() void top_status_source::update_filename(listview_curses *lc) { - status_field & sf_partition = this->tss_fields[TSF_PARTITION_NAME]; - status_field & sf_format = this->tss_fields[TSF_FORMAT]; - status_field & sf_filename = this->tss_fields[TSF_FILENAME]; - struct line_range lr(0); + auto &sf_partition = this->tss_fields[TSF_PARTITION_NAME]; + auto &sf_format = this->tss_fields[TSF_FORMAT]; + auto &sf_filename = this->tss_fields[TSF_FILENAME]; if (lc->get_inner_height() > 0) { string_attrs_t::const_iterator line_attr; diff --git a/src/view_curses.cc b/src/view_curses.cc index c13094dc..f31e98ce 100644 --- a/src/view_curses.cc +++ b/src/view_curses.cc @@ -260,7 +260,13 @@ void view_curses::mvwattrline(WINDOW *window, if (!has_fg) { memset(fg_color, -1, line_width_chars * sizeof(short)); } - fill(&fg_color[attr_range.lr_start], &fg_color[attr_range.lr_end], (short) iter->sa_value.sav_int); + short attr_fg = iter->sa_value.sav_int; + if (attr_fg == view_colors::MATCH_COLOR_SEMANTIC) { + attr_fg = vc.color_for_ident( + &line[iter->sa_range.lr_start], + iter->sa_range.length()); + } + fill(&fg_color[attr_range.lr_start], &fg_color[attr_range.lr_end], attr_fg); has_fg = true; continue; } @@ -269,7 +275,13 @@ void view_curses::mvwattrline(WINDOW *window, if (!has_bg) { memset(bg_color, -1, line_width_chars * sizeof(short)); } - fill(bg_color + attr_range.lr_start, bg_color + attr_range.lr_end, (short) iter->sa_value.sav_int); + short attr_bg = iter->sa_value.sav_int; + if (attr_bg == view_colors::MATCH_COLOR_SEMANTIC) { + attr_bg = vc.color_for_ident( + &line[iter->sa_range.lr_start], + iter->sa_range.length()); + } + fill(bg_color + attr_range.lr_start, bg_color + attr_range.lr_end, attr_bg); has_bg = true; continue; } @@ -307,6 +319,24 @@ void view_curses::mvwattrline(WINDOW *window, int ch_width = min(awidth, (line_width_chars - attr_range.lr_start)); cchar_t row_ch[ch_width + 1]; + if (attrs & (A_LEFT|A_RIGHT)) { + short pair_fg, pair_bg; + + pair_content(color_pair, &pair_fg, &pair_bg); + if (attrs & A_LEFT) { + pair_fg = vc.color_for_ident( + &line[iter->sa_range.lr_start], + iter->sa_range.length()); + } + if (attrs & A_RIGHT) { + pair_bg = vc.color_for_ident( + &line[iter->sa_range.lr_start], + iter->sa_range.length()); + } + color_pair = vc.ensure_color_pair(pair_fg, pair_bg); + attrs &= ~(A_LEFT|A_RIGHT); + } + mvwin_wchnstr(window, y, x_pos, row_ch, ch_width); for (int lpc = 0; lpc < ch_width; lpc++) { bool clear_rev = false; @@ -535,7 +565,16 @@ inline attr_t attr_for_colors(int &pair_base, short fg, short bg) init_pair(pair, fg, bg); } - return COLOR_PAIR(pair); + auto retval = COLOR_PAIR(pair); + + if (fg == view_colors::MATCH_COLOR_SEMANTIC) { + retval |= A_LEFT; + } + if (bg == view_colors::MATCH_COLOR_SEMANTIC) { + retval |= A_RIGHT; + } + + return retval; } pair view_colors::to_attrs( @@ -556,13 +595,13 @@ pair view_colors::to_attrs( shlex(fg1).eval(fg_color, lt.lt_vars); shlex(bg1).eval(bg_color, lt.lt_vars); - auto fg = rgb_color::from_str(fg_color).unwrapOrElse([&](const auto& msg) { + auto fg = styling::color_unit::from_str(fg_color).unwrapOrElse([&](const auto& msg) { reporter(&sc.sc_color, msg); - return rgb_color{}; + return styling::color_unit::make_empty(); }); - auto bg = rgb_color::from_str(bg_color).unwrapOrElse([&](const auto& msg) { + auto bg = styling::color_unit::from_str(bg_color).unwrapOrElse([&](const auto& msg) { reporter(&sc.sc_background_color, msg); - return rgb_color{}; + return styling::color_unit::make_empty(); }); attr_t retval1 = attr_for_colors(pair_base, @@ -590,7 +629,7 @@ void view_colors::init_roles(const lnav_theme <, string err; if (COLORS == 256) { - const style_config &ident_sc = lt.lt_style_identifier; + const auto &ident_sc = lt.lt_style_identifier; int ident_bg = (lnav_config.lc_ui_default_colors ? -1 : COLOR_BLACK); if (!ident_sc.sc_background_color.empty()) { @@ -673,6 +712,8 @@ void view_colors::init_roles(const lnav_theme <, this->vc_role_colors[VCR_TEXT].second |= A_DIM; } this->vc_role_colors[VCR_SEARCH] = make_pair(A_REVERSE, A_REVERSE); + this->vc_role_colors[VCR_IDENTIFIER] = this->to_attrs( + color_pair_base, lt, lt.lt_style_identifier, lt.lt_style_text, reporter); this->vc_role_colors[VCR_OK] = this->to_attrs(color_pair_base, lt, lt.lt_style_ok, lt.lt_style_text, @@ -853,7 +894,7 @@ void view_colors::init_roles(const lnav_theme <, this->vc_role_colors[VCR_HIGH_THRESHOLD] = this->to_attrs( color_pair_base, lt, lt.lt_style_high_threshold, lt.lt_style_text, reporter); - for (log_level_t level = static_cast(LEVEL_UNKNOWN + 1); + for (auto level = static_cast(LEVEL_UNKNOWN + 1); level < LEVEL__MAX; level = static_cast(level + 1)) { auto level_iter = lt.lt_level_styles.find(level); @@ -875,8 +916,8 @@ void view_colors::init_roles(const lnav_theme <, int view_colors::ensure_color_pair(int &pair_base, short fg, short bg) { - require(fg >= -1); - require(bg >= -1); + require(fg >= -100); + require(bg >= -100); auto index_pair = make_pair(fg, bg); auto existing = this->vc_dyn_pairs.find(index_pair); @@ -902,38 +943,78 @@ int view_colors::ensure_color_pair(int &pair_base, short fg, short bg) return retval; } -int view_colors::ensure_color_pair(int &pair_base, const rgb_color &rgb_fg, const rgb_color &rgb_bg) +int view_colors::ensure_color_pair(int &pair_base, + const styling::color_unit &rgb_fg, + const styling::color_unit &rgb_bg) { - int fg = this->match_color(rgb_fg); - int bg = this->match_color(rgb_bg); + auto fg = this->match_color(rgb_fg); + auto bg = this->match_color(rgb_bg); return this->ensure_color_pair(pair_base, fg, bg); } -int view_colors::match_color(const rgb_color &color) +short view_colors::match_color(const styling::color_unit &color) const { - if (color.empty()) { - return -1; - } + return color.cu_value.match( + [](styling::semantic) { + return MATCH_COLOR_SEMANTIC; + }, + [](const rgb_color& color) { + if (color.empty()) { + return MATCH_COLOR_DEFAULT; + } - return vc_active_palette->match_color(lab_color(color)); + return vc_active_palette->match_color(lab_color(color)); + } + ); } -attr_t view_colors::attrs_for_ident(const char *str, size_t len) const +int view_colors::color_for_ident(const char *str, size_t len) const { unsigned long index = crc32(1, (const Bytef*)str, len); - attr_t retval; + int retval; if (COLORS >= 256) { + if (str[0] == '#' && (len == 4 || len == 7)) { + auto fg_res = styling::color_unit::from_str(string_fragment(str, 0, len)); + if (fg_res.isOk()) { + return this->match_color(fg_res.unwrap()); + } + } + unsigned long offset = index % HI_COLOR_COUNT; - retval = COLOR_PAIR(VC_ANSI_END + offset); + auto cpair = COLOR_PAIR(VC_ANSI_END + offset); short fg, bg; - int pnum = PAIR_NUMBER(retval); + auto pnum = PAIR_NUMBER(cpair); pair_content(pnum, &fg, &bg); + retval = fg; } else { - retval = A_BOLD; + retval = -1; + } + + return retval; +} + +attr_t view_colors::attrs_for_ident(const char *str, size_t len) +{ + auto retval = this->attrs_for_role(VCR_IDENTIFIER); + + if (retval & (A_LEFT|A_RIGHT)) { + auto color_pair = PAIR_NUMBER(retval); + short pair_fg, pair_bg; + + pair_content(color_pair, &pair_fg, &pair_bg); + if (retval & A_LEFT) { + pair_fg = this->color_for_ident(str, len); + } + if (retval & A_RIGHT) { + pair_bg = this->color_for_ident(str, len); + } + color_pair = this->ensure_color_pair(pair_fg, pair_bg); + retval &= ~(A_COLOR|A_LEFT|A_RIGHT); + retval |= COLOR_PAIR(color_pair); } return retval; diff --git a/src/view_curses.hh b/src/view_curses.hh index 7ed16564..684fb529 100644 --- a/src/view_curses.hh +++ b/src/view_curses.hh @@ -189,6 +189,7 @@ public: VCR_NONE = -1, VCR_TEXT, /*< Raw text. */ + VCR_IDENTIFIER, VCR_SEARCH, /*< A search hit. */ VCR_OK, VCR_ERROR, /*< An error message. */ @@ -283,13 +284,15 @@ public: return this->vc_role_reverse_colors[role]; }; - attr_t attrs_for_ident(const char *str, size_t len) const; + int color_for_ident(const char *str, size_t len) const; - attr_t attrs_for_ident(intern_string_t str) const { + attr_t attrs_for_ident(const char *str, size_t len); + + attr_t attrs_for_ident(intern_string_t str) { return this->attrs_for_ident(str.get(), str.size()); } - attr_t attrs_for_ident(const std::string &str) const { + attr_t attrs_for_ident(const std::string &str) { return this->attrs_for_ident(str.c_str(), str.length()); }; @@ -299,13 +302,19 @@ public: return this->ensure_color_pair(this->vc_color_pair_end, fg, bg); } - int ensure_color_pair(int &pair_base, const rgb_color &fg, const rgb_color &bg); + int ensure_color_pair(int &pair_base, + const styling::color_unit &fg, + const styling::color_unit &bg); - int ensure_color_pair(const rgb_color &fg, const rgb_color &bg) { + int ensure_color_pair(const styling::color_unit &fg, + const styling::color_unit &bg) { return this->ensure_color_pair(this->vc_color_pair_end, fg, bg); } - int match_color(const rgb_color &color); + static constexpr short MATCH_COLOR_DEFAULT = -1; + static constexpr short MATCH_COLOR_SEMANTIC = -10; + + short match_color(const styling::color_unit &color) const; static inline int ansi_color_pair_index(int fg, int bg) { diff --git a/src/yajlpp/yajlpp_def.hh b/src/yajlpp/yajlpp_def.hh index 5c73b607..411e6c95 100644 --- a/src/yajlpp/yajlpp_def.hh +++ b/src/yajlpp/yajlpp_def.hh @@ -631,7 +631,7 @@ struct json_path_handler : public json_path_handler_base { yajlpp_generator gen(handle); relative_time rt; - rt.from_timeval({ field.count() }); + rt.from_timeval({ field.count(), 0 }); return gen(rt.to_string()); }; this->jph_field_getter = [args...](void *root, nonstd::optional name) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e30d0868..53770281 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -62,6 +62,9 @@ add_executable(test_top_status test_top_status.cc) target_link_libraries(test_top_status diag PkgConfig::libpcre) add_test(NAME test_top_status COMMAND test_top_status) +add_executable(drive_view_colors drive_view_colors.cc) +target_link_libraries(drive_view_colors diag PkgConfig::ncursesw) + add_executable(drive_vt52_curses drive_vt52_curses.cc) target_link_libraries(drive_vt52_curses diag PkgConfig::ncursesw) diff --git a/test/drive_view_colors.cc b/test/drive_view_colors.cc index 80d681a8..79344cd4 100644 --- a/test/drive_view_colors.cc +++ b/test/drive_view_colors.cc @@ -39,11 +39,10 @@ class test_colors : public view_curses { public: test_colors() - : tc_window(NULL) { - + : tc_window(nullptr) { } - void do_update(void) { + void do_update() override { view_colors &vc = view_colors::singleton(); int lpc; @@ -54,21 +53,16 @@ public: line_range lr; snprintf(label, sizeof(label), "This is line: %d", lpc); - attrs = view_colors::singleton().attrs_for_ident(label); + attrs = vc.attrs_for_ident(label); al = label; - al.get_attrs().push_back(string_attr( + al.get_attrs().emplace_back( line_range(0, -1), &view_curses::VC_STYLE, attrs - )); + ); lr.lr_start = 0; lr.lr_end = 40; - this->mvwattrline(this->tc_window, - lpc, - 0, - al, - lr, - view_colors::VCR_TEXT); + test_colors::mvwattrline(this->tc_window, lpc, 0, al, lr); } attr_line_t al; @@ -76,14 +70,9 @@ public: al = "before <123> after"; al.with_attr({line_range{8, 11}, &VC_STYLE, - (int64_t) vc.ansi_color_pair(COLOR_CYAN, COLOR_BLACK)}); + (int64_t) view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK)}); al.with_attr({line_range{8, 11}, &VC_STYLE, A_REVERSE}); - this->mvwattrline(this->tc_window, - lpc, - 0, - al, - lr, - view_colors::VCR_TEXT); + test_colors::mvwattrline(this->tc_window, lpc, 0, al, lr); }; WINDOW *tc_window; @@ -107,7 +96,7 @@ int main(int argc, char *argv[]) } } - view_colors::singleton().init(); + view_colors::init(); curs_set(0); tc.tc_window = win; tc.do_update(); diff --git a/test/view_colors_output.0 b/test/view_colors_output.0 index dcd1774c..f6de4314 100644 --- a/test/view_colors_output.0 +++ b/test/view_colors_output.0 @@ -9,40 +9,38 @@ S -1 ┋ A └ normal, normal, normal CSI Erase all S 1 ┋This is line: 0 ┋ -A └ bold │ -A ········································└ carriage-return +A ···············└ carriage-return S 2 ┋This is line: 1 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 3 ┋This is line: 2 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 4 ┋This is line: 3 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 5 ┋This is line: 4 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 6 ┋This is line: 5 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 7 ┋This is line: 6 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 8 ┋This is line: 7 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 9 ┋This is line: 8 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 10 ┋This is line: 9 ┋ -A ········································└ carriage-return +A ···············└ carriage-return S 11 ┋This is line: 10 ┋ -A ········································└ carriage-return +A ················└ carriage-return S 12 ┋This is line: 11 ┋ -A ········································└ carriage-return +A ················└ carriage-return S 13 ┋This is line: 12 ┋ -A ········································└ carriage-return +A ················└ carriage-return S 14 ┋This is line: 13 ┋ -A ········································└ carriage-return +A ················└ carriage-return S 15 ┋This is line: 14 ┋ -A ········································└ carriage-return +A ················└ carriage-return S 16 ┋This is line: 15 ┋ -A ········································└ carriage-return +A ················└ carriage-return S 17 ┋before <123> after ┋ -A └ normal│ │ A ········└ fg(#008080), inverse A ···········└ normal S 17 ┋ ┋ diff --git a/test/xpath_tui.0 b/test/xpath_tui.0 index 0dddedd9..8b46cbbc 100644 --- a/test/xpath_tui.0 +++ b/test/xpath_tui.0 @@ -88,12 +88,11 @@ A ···································· A ·······································································└ normal, fg(#000000), bg(#c0c0c0) S 19 ┋ ┋ S 20 ┋→ ` logfile_xml_msg.0 0.0 B — x┋ -A ··├ fg(#008000), bg(#c0c0c0) │ │ │ -A └┛ alt │ │ │ │ -A ···└ fg(#000000), bg(#c0c0c0) │ │ │ -A ························└ fg(#c0c0c0), bg(#c0c0c0) │ -A ······························└ fg(#000000), bg(#c0c0c0), bold │ -A ································└ normal, fg(#000000), bg(#c0c0c0) │ +A ··├ fg(#008000), bg(#c0c0c0) │ │ +A └┛ alt │ │ │ +A ···└ fg(#000000), bg(#c0c0c0) │ │ +A ························└ bold│ │ +A ······························└ normal, fg(#000000), bg(#c0c0c0) │ A ················································································└ normal A └┛ alt A ················································································└ normal @@ -118,14 +117,13 @@ A ·············└ bold A ··················└ normal, fg(#000000), bg(#c0c0c0) S 20 ┋ 64.0 B 2020-12-10 06:56:41.061 — 2020-12-10 06:56:41. ┋ A ···························└ backspace │ -A ··························└ fg(#c0c0c0), bg(#c0c0c0) │ -A ······························└ fg(#000000), bg(#c0c0c0), bold │ -A ································└ normal, fg(#000000), bg(#c0c0c0) │ +A ··························└ bold │ +A ······························└ normal, fg(#000000), bg(#c0c0c0) │ A ···············································································└ carriage-return S 22 ┋ ┋ A └ normal, normal S 20 ┋ 628 ┋ -A ·························└ fg(#c0c0c0), bg(#c0c0c0) +A ·························└ fg(#000000), bg(#c0c0c0), bold A ····························└ carriage-return S 22 ┋ ┋ A └ normal, normal @@ -135,94 +133,66 @@ A ·······························└ fg(#c0c S 1 ┋ xml_msg_log ┋ A ······································································└ carriage-return S 2 ┋x x ┋ -A ├ normal, bold A └┛ alt│ A ·└ normal A ······└ carriage-return S 3 ┋x ┋ -A ├ bold ││ -A └┛ alt ││ -A ·└ normal││ -A ·····└ bold -A ·········└ normal +A └┛ alt │ +A ·└ normal │ A ··········└ carriage-return S 4 ┋x ┋ -A ├ bold ││ ││ ││ -A └┛ alt ││ ││ ││ -A ·└ normal││ ││ ││ -A ····└ bold│ ││ ││ -A ·········└ normal│ +A └┛ alt │ ││ ││ +A ·└ normal │ ││ ││ A ··········└ fg(#008080) A ············└ normal A ·············└ fg(#008000), bold A ················└ normal A ·················└ carriage-return S 5 ┋x ┋ -A ├ bold│ ││ -A └┛ alt│ ││ -A ·└ normal ││ -A ······└ bold││ -A ············└ normal +A └┛ alt │ +A ·└ normal │ A ·············└ carriage-return S 6 ┋x OK ┋ -A ├ bold ││ │ │ ││ -A └┛ alt ││ │ │ ││ -A ·└ normal │ │ ││ -A ·······└ bold, normal ││ -A ········└ bold│ │ ││ -A ··············└ normal ││ -A ···················└ bold││ -A ·························└ normal +A ·└ normal │ +A └┛ alt │ │ +A ·└ normal │ +A ·······└ normal │ A ··························└ carriage-return S 7 ┋x ┋ -A ├ bold │ ││ -A └┛ alt │ ││ -A ·└ normal ││ -A ·······└ bold││ -A ·············└ normal +A └┛ alt │ +A ·└ normal │ A ··············└ carriage-return S 8 ┋x ┋ -A ├ bold│ ││ -A └┛ alt│ ││ -A ·└ normal ││ -A ······└ bold -A ··········└ normal +A └┛ alt │ +A ·└ normal │ A ···········└ carriage-return S 9 ┋x x ┋ -A ├ bold ││ +A ·└ normal A └┛ alt ││ A ·└ normal -A ·······└ bold, normal +A ·······└ normal A ········└ carriage-return S 10 ┋x ┋ -A ├ bold │ ││ -A └┛ alt │ ││ -A ·└ normal ││ -A ·······└ bold -A ···········└ normal +A └┛ alt │ +A ·└ normal │ A ············└ carriage-return S 11 ┋x x┋ -A ├ bold │ ││ -A └┛ alt │ ││ -A ·└ normal │ ││ -A ·····└ bold ││ -A ··········└ normal ││ +A └┛ alt ││ +A ·└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt A ················································································└ normal S 12 ┋x x┋ -A ├ fg(#000000), bg(#c0c0c0), normal, bold ││ -A └┛ alt │ ││ -A ·└ normal │ ││ -A ····└ bold │ ││ -A ···················└ normal ││ +A ├ fg(#000000), bg(#c0c0c0) ││ +A └┛ alt ││ +A ·└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt A ················································································└ normal S 13 ┋x x x┋ -A ├ fg(#000000), bg(#c0c0c0), normal, bold ││ +A ├ fg(#000000), bg(#c0c0c0) ││ A └┛ alt ││ A ·└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) @@ -230,21 +200,17 @@ A ···································· A └┛ alt A ················································································└ normal S 14 ┋x x┋ -A ├ fg(#000000), bg(#c0c0c0), normal, bold ││ -A └┛ alt │ ││ -A ·└ normal │ ││ -A ·····└ bold │ ││ -A ····················└ normal ││ +A ├ fg(#000000), bg(#c0c0c0) ││ +A └┛ alt ││ +A ·└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt A ················································································└ normal S 15 ┋x x┋ -A ├ fg(#000000), bg(#c0c0c0), normal, bold ││ -A └┛ alt │ ││ -A ·└ normal │ ││ -A ···└ bold │ ││ -A ··········└ normal ││ +A ├ fg(#000000), bg(#c0c0c0) ││ +A └┛ alt ││ +A ·└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt @@ -283,12 +249,9 @@ A ···································· A ·······································································└ fg(#008080), bg(#000080) A ········································································└ fg(#c0c0c0), bg(#000080), bold S 2 ┋ [2020-12-10 06:56:41,092] DEBUG [connect.client:69] Full request text: ┋ -A ·└ normal │ │ -A ··································└ bold │ +A ·└ normal │ A ················································└ normal S 3 ┋ x┋ -A ··└ bold ││ ││ ││ │ ││ -A ······└ normal││ ││ ││ │ ││ A ·······└ fg(#008080)││ ││ │ ││ A ··············└ normal ││ │ ││ A ···············└ fg(#008000), bold │ ││ @@ -303,16 +266,12 @@ A A ················································································└ normal S 4 ┋ x┋ A ·└ fg(#000000), bg(#c0c0c0), normal ││ -A ··└ bold │ ││ -A ···········└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt A ················································································└ normal S 5 ┋ x┋ A ···└ fg(#000000), bg(#c0c0c0), normal ││ -A ····└ bold ││ -A ········└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt @@ -325,16 +284,13 @@ A A ················································································└ normal S 7 ┋ x┋ A ···└ fg(#000000), bg(#c0c0c0), normal ││ -A ·····└ bold ││ -A ·········└ normal ││ A ···············································································└ fg(#000000), bg(#c0c0c0) A ················································································└ normal A └┛ alt A ················································································└ normal S 8 ┋ ┋ -A ····└ fg(#000000), bg(#c0c0c0), normal, bold -A ···········└ normal +A ····└ fg(#000000), bg(#c0c0c0), normal A ············└ fg(#008080) A ··············└ normal A ···············└ fg(#008000), bold A ··················└ normal S 12 ┋ ┋ -A ······└ bold -A ··········└ normal S 13 ┋ x ┋ S 14 ┋ ┋ -A ·······└ bold -A ···········└ normal S 15 ┋ x┋ -A ·····└ bold │ ││ -A ············└ normal ││ A └┛ alt A ················································································└ normal S 16 ┋x x┋ -A ├ bold │ ││ -A └┛ alt │ ││ -A ·└ normal │ ││ -A ···└ bold │ ││ -A ············└ normal ││ +A └┛ alt ││ +A ·└ normal ││ A └┛ alt A ················································································└ normal S 17 ┋x x┋ -A ├ bold ││ A └┛ alt ││ A ·└ normal ││ A └┛ alt A ················································································└ normal S 18 ┋x[2020-12-10 06:56:41,099] DEBUG [m:85] Full reply text: x┋ -A ├ bold ││ ││ -A └┛ alt ││ ││ -A ·└ normal ││ ││ -A ··································└ bold ││ +A └┛ alt │ ││ +A ·└ normal │ ││ A ···································└ normal ││ A └┛ alt A ················································································└ normal S 19 ┋x x┋ -A ├ bold││ ││ ││ ││ │ ││ -A └┛ alt││ ││ ││ ││ │ ││ +A └┛ alt │ ││ ││ ││ │ ││ A ·└ normal ││ ││ ││ │ ││ -A ··└ bold ││ ││ ││ │ ││ -A ······└ normal││ ││ ││ │ ││ A ·······└ fg(#008080)││ ││ │ ││ A ··············└ normal ││ │ ││ A ···············└ fg(#008000), bold │ ││ @@ -409,19 +348,13 @@ A ···································· A └┛ alt A ················································································└ normal S 20 ┋x x┋ -A ├ bold │ ││ -A └┛ alt │ ││ -A ·└ normal│ ││ -A ··└ bold │ ││ -A ·········└ normal ││ +A └┛ alt ││ +A ·└ normal ││ A └┛ alt A ················································································└ normal S 21 ┋x x┋ -A ├ bold │ ││ -A └┛ alt │ ││ +A └┛ alt ││ A ·└ normal ││ -A ····└ bold ││ -A ········└ normal ││ A └┛ alt A ················································································└ normal S 22 ┋ Files :: Text Filters :: Press TAB to edit ┋ @@ -477,42 +410,36 @@ A ···································· A ············································└ carriage-return S 6 ┋ t timestamp = 2020-12-10 06:56:41,092 ┋ A └┛ alt │ │ │ -A ···└ bold │ │ │ A ············└ normal │ A ···············└ bold │ A ···············································································└ carriage-return S 7 ┋ t level = DEBUG ┋ A └ normal│ │ │ A └┛ alt │ │ │ -A ···└ bold │ │ A ········└ normal │ A ···············└ bold │ A ···············································································└ carriage-return S 8 ┋ t module = connect.client ┋ A └ normal │ │ │ A └┛ alt │ │ │ -A ···└ bold│ │ │ A ·········└ normal │ A ···············└ bold │ A ···············································································└ carriage-return S 9 ┋ t line = 69 ┋ A └ normal │ │ │ A └┛ alt │ │ │ -A ···└ bold │ │ │ A ·············└ normal │ A ···············└ bold │ A ···············································································└ carriage-return S 10 ┋ t body = Full request text: ┋ A └ normal │ │ A └┛ alt│ │ │ -A ···└ bold │ │ A ·······└ normal│ │ A ···············└ bold │ A ···············································································└ carriage-return S 11 ┋ t msg_data = ┋ A └ normal │ │ │ A └┛ alt │ │ │ -A ···└ bold │ │ │ A ···········└ normal │ A ···············└ bold │ A ···············································································└ carriage-return @@ -541,8 +468,6 @@ A ···································· S 17 ┋ No discovered message fields ┋ A └ normal S 18 ┋ ┋ -A ··└ bold ││ ││ ││ │ -A ······└ normal││ ││ ││ │ A ·······└ fg(#008080)││ ││ │ A ··············└ normal ││ │ A ···············└ fg(#008000), bold │ @@ -552,11 +477,7 @@ A ·····························└ normal A ······························└ fg(#008000), bold A ··········································└ normal S 19 ┋ a-request> ┋ -A ··└ bold │ -A ···········└ normal S 20 ┋ ┋ -A ····└ bold -A ········└ normal S 21 ┋ x ┋ A ·········└ carriage-return S 24 ┋ ┋