From fe48f5aab6364be704c34fbbde1d34fb3ff477c7 Mon Sep 17 00:00:00 2001
From: Alex
Date: Tue, 15 Feb 2022 21:28:54 -0800
Subject: [PATCH 01/18] Copy generate_container_preview as
generate_container_count
This just prints the container's number of children, while keeping the
opening/closing characters. So:
foo: [ 2 ]
bar: { 3 }
---
src/lineprinter.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/src/lineprinter.rs b/src/lineprinter.rs
index d2df366..41068d4 100644
--- a/src/lineprinter.rs
+++ b/src/lineprinter.rs
@@ -796,6 +796,78 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
Ok(num_printed)
}
+ // similar to generate_container_preview, except it only prints the count
+ // of the number of children:
+ // - number of key-val pairs in a hash, ie "{ 3 }"
+ // - number of items in an array, ie "[ 2 ]"
+ fn generate_container_count(
+ &mut self,
+ flatjson: &FlatJson,
+ row: &Row,
+ mut available_space: isize,
+ quoted_object_keys: bool,
+ ) -> Result {
+ debug_assert!(row.is_opening_of_container());
+
+ // Minimum amount of space required == 3: […]
+ if available_space < 3 {
+ return Ok(0);
+ }
+
+ let container_type = row.value.container_type().unwrap();
+ let mut num_printed = 0;
+
+ // Print opening character, either "[" or "{"
+ self.highlight_str(
+ container_type.open_str(),
+ Some(self.value_range.start),
+ highlighting::PREVIEW_STYLES,
+ )?;
+
+ num_printed += 1;
+
+ let mut next_sibling = row.first_child();
+ let mut count:usize = 0;
+ while let OptionIndex::Index(child) = next_sibling {
+ next_sibling = flatjson[child].next_sibling;
+ count += 1;
+ }
+
+ // Print count with spaces around it: " N "
+ self.highlight_str(
+ " ",
+ Some(self.value_range.start+num_printed),
+ highlighting::PREVIEW_STYLES
+ )?;
+ num_printed += 1;
+
+ let count_as_str = count.to_string();
+ let count_length = count_as_str.len();
+ self.highlight_str(
+ &count_as_str,
+ Some(self.value_range.start+num_printed),
+ highlighting::PREVIEW_STYLES
+ )?;
+ num_printed += count_length;
+
+ self.highlight_str(
+ " ",
+ Some(self.value_range.start+num_printed),
+ highlighting::PREVIEW_STYLES
+ )?;
+ num_printed += 1;
+
+ // Print closing char, "]" or "}"
+ self.highlight_str(
+ container_type.close_str(),
+ Some(self.value_range.end - 1),
+ highlighting::PREVIEW_STYLES,
+ )?;
+ num_printed += 1;
+
+ Ok(num_printed)
+ }
+
// {a…: …, …}
//
// [a, …]
From 6eedd029af27358fe67c22d6ed29ec167183c404 Mon Sep 17 00:00:00 2001
From: Alex
Date: Tue, 15 Feb 2022 21:09:20 -0800
Subject: [PATCH 02/18] Fix `cargo build` error
```
$ cargo build
Compiling jless v0.7.1 (/...)
error[E0308]: mismatched types
--> src/lineprinter.rs:765:12
|
765 | Ok(num_printed)
| ^^^^^^^^^^^ expected `isize`, found `usize`
|
help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
|
765 | Ok(num_printed.try_into().unwrap())
| ++++++++++++++++++++
```
I'm not sure why this error only showed up after my changes. I haven't
changed the type of `num_printed`, and I've only changed it by calling
`+=` on it a few extra times.
---
src/lineprinter.rs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lineprinter.rs b/src/lineprinter.rs
index 41068d4..8e4bb73 100644
--- a/src/lineprinter.rs
+++ b/src/lineprinter.rs
@@ -2,6 +2,7 @@ use std::collections::hash_map::Entry;
use std::fmt;
use std::iter::Peekable;
use std::ops::Range;
+use std::convert::TryInto;
use regex::Regex;
@@ -804,8 +805,7 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
&mut self,
flatjson: &FlatJson,
row: &Row,
- mut available_space: isize,
- quoted_object_keys: bool,
+ mut available_space: isize
) -> Result {
debug_assert!(row.is_opening_of_container());
@@ -865,7 +865,7 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
)?;
num_printed += 1;
- Ok(num_printed)
+ Ok(num_printed.try_into().unwrap())
}
// {a…: …, …}
From 8c82925088de6c14c1512fd599599f662db1c85d Mon Sep 17 00:00:00 2001
From: Alex
Date: Tue, 15 Feb 2022 21:52:51 -0800
Subject: [PATCH 03/18] Add `JsonViewer.preview`, and have
`fill_in_container_preview` read it
This is modeled exactly after the existing `JsonViewer.mode`, down to
its arg handling and toggling.
---
src/app.rs | 3 ++-
src/lineprinter.rs | 36 +++++++++++++++++++++++-------------
src/options.rs | 9 +++++++++
src/screenwriter.rs | 1 +
src/viewer.rs | 21 ++++++++++++++++++++-
5 files changed, 55 insertions(+), 15 deletions(-)
diff --git a/src/app.rs b/src/app.rs
index 2ad2f01..ef36acc 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -49,7 +49,7 @@ impl App {
Err(err) => return Err(format!("Unable to parse input: {:?}", err)),
};
- let mut viewer = JsonViewer::new(flatjson, opt.mode);
+ let mut viewer = JsonViewer::new(flatjson, opt.mode, opt.preview);
viewer.scrolloff_setting = opt.scrolloff;
let screen_writer =
@@ -233,6 +233,7 @@ impl App {
Key::Char('G') | Key::End => Some(Action::FocusBottom),
Key::Char('%') => Some(Action::FocusMatchingPair),
Key::Char('m') => Some(Action::ToggleMode),
+ Key::Char('p') => Some(Action::TogglePreview),
Key::Char('<') => {
self.screen_writer
.decrease_indentation_level(self.viewer.flatjson.2 as u16);
diff --git a/src/lineprinter.rs b/src/lineprinter.rs
index 8e4bb73..5fcda59 100644
--- a/src/lineprinter.rs
+++ b/src/lineprinter.rs
@@ -13,6 +13,7 @@ use crate::terminal;
use crate::terminal::{Color, Style, Terminal};
use crate::truncatedstrview::TruncatedStrView;
use crate::viewer::Mode;
+use crate::viewer::Preview;
// # Printing out individual lines
//
@@ -195,6 +196,7 @@ pub enum LineValue<'a> {
pub struct LinePrinter<'a, 'b, 'c> {
pub mode: Mode,
+ pub preview: Preview,
pub terminal: &'c mut dyn Terminal,
pub node_depth: usize,
@@ -685,23 +687,31 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
available_space -= 1;
}
- let quoted_object_keys = self.mode == Mode::Line;
- let mut used_space =
- self.generate_container_preview(flatjson, row, available_space, quoted_object_keys)?;
+ let mut used_space = 0;
+
+ if self.preview == Preview::Full {
+ let quoted_object_keys = self.mode == Mode::Line;
+ used_space =
+ self.generate_container_preview(flatjson, row, available_space, quoted_object_keys)?;
- if self.trailing_comma {
- used_space += 1;
if self.trailing_comma {
- self.highlight_str(
- ",",
- Some(self.value_range.end),
- (
- &highlighting::DEFAULT_STYLE,
- &highlighting::SEARCH_MATCH_HIGHLIGHTED,
- ),
- )?;
+ used_space += 1;
+ if self.trailing_comma {
+ self.highlight_str(
+ ",",
+ Some(self.value_range.end),
+ (
+ &highlighting::DEFAULT_STYLE,
+ &highlighting::SEARCH_MATCH_HIGHLIGHTED,
+ ),
+ )?;
+ }
}
}
+ else {
+ used_space =
+ self.generate_container_count(flatjson, row, available_space)?;
+ }
Ok(used_space)
}
diff --git a/src/options.rs b/src/options.rs
index eba1dbb..2cee8c0 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -3,6 +3,7 @@ use std::path::PathBuf;
use clap::Parser;
use crate::viewer::Mode;
+use crate::viewer::Preview;
/// A pager for JSON data
#[derive(Debug, Parser)]
@@ -21,6 +22,14 @@ pub struct Opt {
#[clap(short, long, arg_enum, hide_possible_values = true, default_value_t = Mode::Data)]
pub mode: Mode,
+ /// Initial preview of container nodes. In full mode (--preview full;
+ /// the default), containers will be rendered as much as they can be in
+ /// the width of the terminal. In count mode (--preview count), only
+ /// the child node count will be rendered. This can be toggled by
+ /// pressing 'p'.
+ #[clap(short, long, arg_enum, hide_possible_values = true, default_value_t = Preview::Full)]
+ pub preview: Preview,
+
/// Number of lines to maintain as padding between the currently
/// focused row and the top or bottom of the screen. Setting this to
/// a large value will keep the focused in the middle of the screen
diff --git a/src/screenwriter.rs b/src/screenwriter.rs
index 7a5e0dd..a040a26 100644
--- a/src/screenwriter.rs
+++ b/src/screenwriter.rs
@@ -275,6 +275,7 @@ impl ScreenWriter {
let mut line = lp::LinePrinter {
mode: viewer.mode,
+ preview: viewer.preview,
terminal: &mut self.terminal,
node_depth: row.depth,
diff --git a/src/viewer.rs b/src/viewer.rs
index 2fed3b8..b046b70 100644
--- a/src/viewer.rs
+++ b/src/viewer.rs
@@ -9,6 +9,12 @@ pub enum Mode {
Data,
}
+#[derive(PartialEq, Eq, Copy, Clone, Debug, ArgEnum)]
+pub enum Preview {
+ Full,
+ Count,
+}
+
const DEFAULT_SCROLLOFF: u16 = 3;
pub struct JsonViewer {
@@ -26,10 +32,11 @@ pub struct JsonViewer {
// Access the functional value via .scrolloff().
pub scrolloff_setting: u16,
pub mode: Mode,
+ pub preview: Preview,
}
impl JsonViewer {
- pub fn new(flatjson: FlatJson, mode: Mode) -> JsonViewer {
+ pub fn new(flatjson: FlatJson, mode: Mode, preview: Preview) -> JsonViewer {
JsonViewer {
flatjson,
top_row: 0,
@@ -38,6 +45,7 @@ impl JsonViewer {
dimensions: TTYDimensions::default(),
scrolloff_setting: DEFAULT_SCROLLOFF,
mode,
+ preview,
}
}
}
@@ -96,6 +104,7 @@ pub enum Action {
ExpandNodeAndSiblings,
ToggleMode,
+ TogglePreview,
ResizeViewerDimensions(TTYDimensions),
}
@@ -137,6 +146,7 @@ impl JsonViewer {
// TODO: custom window management here
self.toggle_mode();
}
+ Action::TogglePreview => self.toggle_preview(),
Action::ResizeViewerDimensions(dims) => self.dimensions = dims,
}
@@ -178,6 +188,7 @@ impl JsonViewer {
Action::CollapseNodeAndSiblings => true,
Action::ExpandNodeAndSiblings => true,
Action::ToggleMode => false,
+ Action::TogglePreview => false,
Action::ResizeViewerDimensions(_) => true,
_ => false,
}
@@ -197,6 +208,7 @@ impl JsonViewer {
| Action::MoveFocusedLineToCenter
| Action::MoveFocusedLineToBottom
| Action::ToggleMode
+ | Action::TogglePreview
| Action::ResizeViewerDimensions(_)
)
}
@@ -586,6 +598,13 @@ impl JsonViewer {
}
}
+ fn toggle_preview(&mut self) {
+ self.preview = match self.preview {
+ Preview::Full => Preview::Count,
+ Preview::Count => Preview::Full,
+ }
+ }
+
fn scrolloff(&self) -> u16 {
self.scrolloff_setting.min((self.dimensions.height - 1) / 2)
}
From 1e6dbc1574dba4f348fcc8fb897a5a1f183fdf2c Mon Sep 17 00:00:00 2001
From: Alex
Date: Wed, 16 Feb 2022 09:04:30 -0800
Subject: [PATCH 04/18] Reduce complexity of `generate_container_count`
Rather than calling `highlight_str` a bunch, use `format!` to assemble
the string. This also removes the need to `use std::convert::TryInto`,
since I'm `as isize`ing everywhere. It also respects and updates
`available_space`, though I'm not quite sure if a string as short as
this should do so.
---
src/lineprinter.rs | 61 +++++++++++++++-------------------------------
1 file changed, 19 insertions(+), 42 deletions(-)
diff --git a/src/lineprinter.rs b/src/lineprinter.rs
index 5fcda59..1fb531e 100644
--- a/src/lineprinter.rs
+++ b/src/lineprinter.rs
@@ -2,7 +2,6 @@ use std::collections::hash_map::Entry;
use std::fmt;
use std::iter::Peekable;
use std::ops::Range;
-use std::convert::TryInto;
use regex::Regex;
@@ -824,18 +823,6 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
return Ok(0);
}
- let container_type = row.value.container_type().unwrap();
- let mut num_printed = 0;
-
- // Print opening character, either "[" or "{"
- self.highlight_str(
- container_type.open_str(),
- Some(self.value_range.start),
- highlighting::PREVIEW_STYLES,
- )?;
-
- num_printed += 1;
-
let mut next_sibling = row.first_child();
let mut count:usize = 0;
while let OptionIndex::Index(child) = next_sibling {
@@ -843,39 +830,29 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
count += 1;
}
- // Print count with spaces around it: " N "
- self.highlight_str(
- " ",
- Some(self.value_range.start+num_printed),
- highlighting::PREVIEW_STYLES
- )?;
- num_printed += 1;
-
- let count_as_str = count.to_string();
- let count_length = count_as_str.len();
- self.highlight_str(
- &count_as_str,
- Some(self.value_range.start+num_printed),
- highlighting::PREVIEW_STYLES
- )?;
- num_printed += count_length;
+ let container_type = row.value.container_type().unwrap();
+ let mut count_str = format!(
+ "{} {} {}",
+ container_type.open_str(),
+ count.to_string(),
+ container_type.close_str()
+ );
+ if count_str.len() as isize > available_space {
+ count_str = format!(
+ "{}…{}",
+ container_type.open_str(),
+ container_type.close_str()
+ );
+ }
self.highlight_str(
- " ",
- Some(self.value_range.start+num_printed),
+ &count_str,
+ Some(self.value_range.start),
highlighting::PREVIEW_STYLES
)?;
- num_printed += 1;
-
- // Print closing char, "]" or "}"
- self.highlight_str(
- container_type.close_str(),
- Some(self.value_range.end - 1),
- highlighting::PREVIEW_STYLES,
- )?;
- num_printed += 1;
-
- Ok(num_printed.try_into().unwrap())
+ let len = count_str.len() as isize;
+ available_space -= len;
+ Ok(len)
}
// {a…: …, …}
From f7e2c0b4adba9a0180ff9e1b8aac229664997b89 Mon Sep 17 00:00:00 2001
From: Alex
Date: Wed, 16 Feb 2022 10:14:15 -0800
Subject: [PATCH 05/18] Remove `preview` from `JsonViewer::new`, set it
elsewhere
This is used in lots of places, so it's not worth changing every single
call to `::new()` just to add `preview`. Just set it right after `::new`
in app.rs and let it default everywhere else.
---
src/app.rs | 3 ++-
src/viewer.rs | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/app.rs b/src/app.rs
index ef36acc..d853ac7 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -49,7 +49,8 @@ impl App {
Err(err) => return Err(format!("Unable to parse input: {:?}", err)),
};
- let mut viewer = JsonViewer::new(flatjson, opt.mode, opt.preview);
+ let mut viewer = JsonViewer::new(flatjson, opt.mode);
+ viewer.preview = opt.preview;
viewer.scrolloff_setting = opt.scrolloff;
let screen_writer =
diff --git a/src/viewer.rs b/src/viewer.rs
index b046b70..37f2043 100644
--- a/src/viewer.rs
+++ b/src/viewer.rs
@@ -36,7 +36,7 @@ pub struct JsonViewer {
}
impl JsonViewer {
- pub fn new(flatjson: FlatJson, mode: Mode, preview: Preview) -> JsonViewer {
+ pub fn new(flatjson: FlatJson, mode: Mode) -> JsonViewer {
JsonViewer {
flatjson,
top_row: 0,
@@ -45,7 +45,7 @@ impl JsonViewer {
dimensions: TTYDimensions::default(),
scrolloff_setting: DEFAULT_SCROLLOFF,
mode,
- preview,
+ preview: Preview::Full,
}
}
}
From a9a42258b512112e864656329720cffad5fe8ae0 Mon Sep 17 00:00:00 2001
From: Alex
Date: Wed, 16 Feb 2022 10:16:50 -0800
Subject: [PATCH 06/18] Add test for `generate_container_count`
This involved adding an extra string to `generate_container_count`,
because Rust has weird memory rules around str::len() that was causing
the returned value to get stuck based on the initial assigned value of
`count_str`, rather than its final value. Or something, I don't know.
---
src/lineprinter.rs | 100 ++++++++++++++++++++++++++++++++++++++-------
1 file changed, 85 insertions(+), 15 deletions(-)
diff --git a/src/lineprinter.rs b/src/lineprinter.rs
index 1fb531e..3062267 100644
--- a/src/lineprinter.rs
+++ b/src/lineprinter.rs
@@ -831,28 +831,37 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
}
let container_type = row.value.container_type().unwrap();
- let mut count_str = format!(
+ let count_str = format!(
"{} {} {}",
container_type.open_str(),
count.to_string(),
container_type.close_str()
);
+ let short_str = format!(
+ "{}…{}",
+ container_type.open_str(),
+ container_type.close_str()
+ );
- if count_str.len() as isize > available_space {
- count_str = format!(
- "{}…{}",
- container_type.open_str(),
- container_type.close_str()
- );
+ if count_str.len() as isize <= available_space {
+ self.highlight_str(
+ &count_str,
+ Some(self.value_range.start),
+ highlighting::PREVIEW_STYLES
+ )?;
+ let len = count_str.len() as isize;
+ available_space -= len;
+ return Ok(len)
}
- self.highlight_str(
- &count_str,
- Some(self.value_range.start),
- highlighting::PREVIEW_STYLES
- )?;
- let len = count_str.len() as isize;
- available_space -= len;
- Ok(len)
+ else {
+ self.highlight_str(
+ &short_str,
+ Some(self.value_range.start),
+ highlighting::PREVIEW_STYLES
+ )?;
+ available_space -= 3;
+ return Ok(3)
+ }
}
// {a…: …, …}
@@ -1113,6 +1122,7 @@ mod tests {
fn default_line_printer(terminal: &mut dyn Terminal) -> LinePrinter {
LinePrinter {
mode: Mode::Data,
+ preview: Preview::Full,
terminal,
node_depth: 0,
depth: 0,
@@ -1564,6 +1574,66 @@ mod tests {
Ok(())
}
+ #[test]
+ fn test_generate_countainer_count() -> std::fmt::Result {
+ let json_arr = r#"[1,2,3] "#;
+ let json_obj = r#"{"a":1, "b":2}"#;
+ // 012345678901234 (14 chars)
+ let fj_arr = parse_top_level_json(json_arr.to_owned()).unwrap();
+ let fj_obj = parse_top_level_json(json_obj.to_owned()).unwrap();
+
+ let mut term = TextOnlyTerminal::new();
+ let mut line: LinePrinter = LinePrinter {
+ value_range: &(0..json_obj.len()),
+ preview: Preview::Count,
+ ..default_line_printer(&mut term)
+ };
+
+ for (available_space, used_space, expected) in vec![
+ (14, 5, r#"[ 3 ]"#),
+ (4, 3, r#"[…]"#),
+ (2, 0, r#""#),
+ ]
+ .into_iter()
+ {
+ let used =
+ line.generate_container_count(&fj_arr, &fj_arr[0], available_space)?;
+ assert_eq!(
+ expected,
+ line.terminal.output(),
+ "expected preview with {} available columns (used up {} columns)",
+ available_space,
+ UnicodeWidthStr::width(line.terminal.output()),
+ );
+ assert_eq!(used_space, used);
+
+ line.terminal.clear_output();
+ }
+
+ for (available_space, used_space, expected) in vec![
+ (14, 5, r#"{ 2 }"#),
+ (4, 3, r#"{…}"#),
+ (2, 0, r#""#),
+ ]
+ .into_iter()
+ {
+ let used =
+ line.generate_container_count(&fj_obj, &fj_obj[0], available_space)?;
+ assert_eq!(
+ expected,
+ line.terminal.output(),
+ "expected preview with {} available columns (used up {} columns)",
+ available_space,
+ UnicodeWidthStr::width(line.terminal.output()),
+ );
+ assert_eq!(used_space, used);
+
+ line.terminal.clear_output();
+ }
+
+ Ok(())
+ }
+
#[test]
fn test_generate_array_preview() -> fmt::Result {
let json = r#"[1, {"x": true}, null, "hello", true]"#;
From 8ab2644631f3c5a02aa79fb6d8d80911c71f1958 Mon Sep 17 00:00:00 2001
From: Alex
Date: Wed, 16 Feb 2022 13:45:55 -0800
Subject: [PATCH 07/18] Add "none" as an option to `preview`
This renders nothing, as it's been requested in a couple other Github
issues. Toggling now goes `full (default)` --> `count` --> `none`, then
repeats.
---
src/lineprinter.rs | 3 +++
src/options.rs | 5 +++--
src/viewer.rs | 4 +++-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/lineprinter.rs b/src/lineprinter.rs
index 3062267..4777a8d 100644
--- a/src/lineprinter.rs
+++ b/src/lineprinter.rs
@@ -707,6 +707,9 @@ impl<'a, 'b, 'c> LinePrinter<'a, 'b, 'c> {
}
}
}
+ else if self.preview == Preview::None {
+ used_space = 0;
+ }
else {
used_space =
self.generate_container_count(flatjson, row, available_space)?;
diff --git a/src/options.rs b/src/options.rs
index 2cee8c0..54f5eb8 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -25,8 +25,9 @@ pub struct Opt {
/// Initial preview of container nodes. In full mode (--preview full;
/// the default), containers will be rendered as much as they can be in
/// the width of the terminal. In count mode (--preview count), only
- /// the child node count will be rendered. This can be toggled by
- /// pressing 'p'.
+ /// the child node count will be rendered. In none mode (--preview none),
+ /// no preview will be rendered at all. This can be toggled by pressing
+ /// 'p'.
#[clap(short, long, arg_enum, hide_possible_values = true, default_value_t = Preview::Full)]
pub preview: Preview,
diff --git a/src/viewer.rs b/src/viewer.rs
index 37f2043..422f8b8 100644
--- a/src/viewer.rs
+++ b/src/viewer.rs
@@ -13,6 +13,7 @@ pub enum Mode {
pub enum Preview {
Full,
Count,
+ None,
}
const DEFAULT_SCROLLOFF: u16 = 3;
@@ -601,7 +602,8 @@ impl JsonViewer {
fn toggle_preview(&mut self) {
self.preview = match self.preview {
Preview::Full => Preview::Count,
- Preview::Count => Preview::Full,
+ Preview::Count => Preview::None,
+ Preview::None => Preview::Full,
}
}
From 8ad349d0b720e6cfef9927f6037a3579bfd11a15 Mon Sep 17 00:00:00 2001
From: Alex
Date: Thu, 17 Feb 2022 10:18:39 -0800
Subject: [PATCH 08/18] Update jless.help and usage.html
---
docs/usage.html | 40 ++++++++++++++++++++++++++++++++++++++++
src/jless.help | 6 ++++++
2 files changed, 46 insertions(+)
diff --git a/docs/usage.html b/docs/usage.html
index 65da7fc..18bb178 100644
--- a/docs/usage.html
+++ b/docs/usage.html
@@ -344,6 +344,46 @@
Data Mode vs. Line Mode
In line mode you can press % when focused on an open or close delimiter of an object or array to jump to its matching pair.
+
Changing preview of child nodes
+
+
+ The way JLess displays previews can be changed, either by passing --preview or -p with one of: full (the default), count, or none. By pressing p, you can cycle between these three.
+