<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jless - Command Line JSON Viewer</title>
<meta name="og:title" content="jless - Command Line JSON Viewer" />
<meta name="og:image" content="https://pauljuliusmartinez.github.io/assets/logo/text-logo-with-mascot-social.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:creator" content="@CodeIsTheEnd" />
<link rel="icon" href="./assets/logo/mascot.svg" type="image/svg+xml">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;700&family=Roboto+Slab:wght@800&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; }
body {
margin: 0 auto;
padding: 16px;
max-width: 800px;
background-color: #f4f4f8;
font-family: 'Fira Sans', sans-serif;
font-size: 22px;
}
header {
display: flex;
align-items: center;
flex-direction: column;
}
#text-logo-with-mascot {
margin: 0 auto;
max-width: min(540px, 100%);
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Roboto Slab', serif;
font-weight: 700;
}
nav h3 { text-align: center; }
nav {
display: flex;
justify-content: space-evenly;
font-family: 'Roboto Slab', serif;
font-weight: 700;
}
nav a {
color: black;
}
.code-block {
border: 1px solid black;
border-radius: 4px;
padding: 8px;
width: 100%;
overflow-x: auto;
background-color: #eeeeee;
white-space: pre;
font-family: monospace;
font-size: 16px;
}
.code-block .prefix {
user-select: none;
}
code {
position: relative;
top: -2px;
display: inline-block;
border: 1px solid black;
border-radius: 4px;
margin: 0 2px;
padding: 2px 4px;
background-color: #eeeeee;
font-size: 16px;
}
footer {
display: flex;
flex-direction: column;
align-items: center;
font-size: 14px;
}
footer img {
width: max(25%, 160px);
}
@media (max-width: 540px) {
body {
font-size: 19px;
}
}
</style>
</head>
<body>
<header>
<img id="text-logo-with-mascot" src="./assets/logo/text-logo-with-mascot.svg">
<h2>jless — a command-line JSON viewer</h3>
</header>
<nav>
<a href="./">About</a>
<a href="./usage.html">User Guide</a>
<a href="./releases.html">Releases</a>
<a href="https://github.com/PaulJuliusMartinez/jless">GitHub</a>
</nav>
<h2 id="usage">Usage</h2>
<p>
JLess can read files directly, or read JSON data from standard input:
</p>
<div class="code-block"><span class="prefix">$ </span>curl https://api.github.com/repos/PaulJuliusMartinez/jless/commits -o commits.json
<span class="prefix">$ </span>jless commits.json
<span class="prefix">$ </span>cat commits.json | jless</div>
<p>
JLess can handle newline-delimited JSON, so feel free to pipe in the output from <a href="https://stedolan.github.io/jq/">jq</a> or some dense log files.
</p>
<h2 id="commands">Commands</h2>
<p>
JLess has a large suite of vim-inspired commands. Commands prefixed by <i>count</i> may be preceded by a number <code>N</code>, which will perform a command a given number of times.
</p>
<ul>
<li><code>q</code>, <code>Ctrl-C</code>, <code>:quit</code>, <code>:exit</code> Exit JLess; don't worry, it's not as hard as exiting vim.
<li><code>:help</code>, <code>F1</code> Show the help page.
</ul>
<h3 id="moving">Moving</h3>
<ul>
<li>
<i>count</i>
<code>j</code>,
<code>DownArrow</code>,
<code>Ctrl-n</code>,
<code>Enter</code>,
<code>Space</code> Move focus down one line (or <code>N</code> lines).
</li>
<li>
<i>count</i>
<code>k</code>,
<code>UpArrow</code>,
<code>Ctrl-p</code>,
<code>Backspace</code> Move focus up one line (or <code>N</code> lines).
</li>
<li>
<code>h</code>,
<code>LeftArrow</code> When focused on an expanded object or array, collapse the object or array. Otherwise, move focus to the parent of the focused node.
</li>
<li>
<code>H</code> Focus the parent of the focused node without collapsing the focused node.
</li>
<li>
<code>l</code>,
<code>RightArrow</code> When focused on a collapsed object or array, expand the object or array. When focused on an expanded object or array, move focus to the first child. When focused on non-container values, does nothing.
</li>
<li>
<i>count</i>
<code>J</code> Move to the focused node's next sibling 1 or <code>N</code> times.
</li>
<li>
<i>count</i>
<code>K</code> Move to the focused node's previous sibling 1 or <code>N</code> times.
</li>
<li>
<i>count</i>
<code>w</code> Move forward until the next change in depth 1 or <code>N</code> times.
</li>
<li>
<i>count</i>
<code>b</code> Move backwards until the next change in depth 1 or <code>N</code> times.
</li>
<li>
<i>count</i>
<code>PageDown</code> Move down by one window's height or <code>N</code> windows' heights.
</li>
<li>
<i>count</i>
<code>PageUp</code> Move up by one window's height or <code>N</code> windows' heights.
</li>
<li>
<i>count</i>
<code>0</code>, <code>^</code> Move to the first sibling of the focused node's parent.
</li>
<li>
<i>count</i>
<code>$</code> Move to the last sibling of the focused node's parent.
</li>
<li>
<i>count</i>
<code>g</code>, <code>Home</code> Focus the first line in the input.
</li>
<li>
<i>count</i>
<code>G</code>, <code>End</code> Focus the last line in the input.
</li>
<li>
<i>count</i>
<code>c</code> Collapse the focused node and all its siblings.
</li>
<li>
<i>count</i>
<code>e</code> Expand the focused node and all its siblings.
</li>
</ul>
<h3 id="scrolling">Scrolling</h3>
<ul>
<li>
<i>count</i>
<code>Ctrl-e</code> Scroll down one line (or <code>N</code> lines).
</li>
<li>
<i>count</i>
<code>Ctrl-y</code> Scroll up one line (or <code>N</code> lines).
</li>
<li>
<code>zz</code> Move the focused node to the center of the screen.
</li>
<li>
<code>zt</code> Move the focused node to the top of the screen.
</li>
<li>
<code>zb</code> Move the focused node to the bottom of the screen.
</li>
<li>
<i>count</i>
<code>.</code> Scroll a truncated value one character to the right (or <code>N</code> characters).
</li>
<li>
<i>count</i>
<code>,</code> Scroll a truncated value one character to the left (or <code>N</code> characters).
</li>
<li>
<code>;</code> Scroll a truncated value all the way to the end, or, if already at the end, back to the start.
</li>
<li>
<i>count</i>
<code><</code> Decrease the indentation of every line by one (or <code>N</code>) tabs.
</li>
<li>
<i>count</i>
<code>></code> Increase the indentation of every line by one (or <code>N</code>) tabs.
</li>
</ul>
<h3 id="search">Search</h3>
<p>
jless supports full-text search over the input JSON.
</p>
<ul>
<li>
<code>/pattern</code> Search forward for the given pattern.
</li>
<li>
<code>?pattern</code> Search forward for the given pattern.
</li>
<li>
<i>count</i>
<code>*</code> Move to the next occurrence of the object key on the focused line (or move forward <code>N</code> occurrences)
</li>
<li>
<i>count</i>
<code>#</code> Move to the previous occurrence of the object key on the focused line (or move backwards <code>N</code> occurrences)
</li>
<li>
<i>count</i>
<code>n</code> Move in the search direction to the next match (or forward <code>N</code> matches).
</li>
<li>
<i>count</i>
<code>N</code> Move in the opposite of the search direction to the previous match (or previous <code>N</code> matches).
</li>
</ul>
<p>
Searching uses "smart case" by default. If the input pattern doesn't contain any capital letters, a case insensitive search will be performed. If there are any capital letters, it will be case sensitive. You can force a case-sensitive search by appending <code>/s</code> to your query.
</p>
<p>
A trailing slash will be removed from a pattern; to search for a pattern ending in <code>/</code> (or <code>/s</code>), just add another <code>/</code> to the end.
</p>
<p>
Search patterns are interpreted as mostly standard regular expressions, with one exception. Because JSON data contains many square and curly brackets (<code>[]{}</code>), these characters do <i>not</i> take on their usual meanings (specifying characters classes and repetition counts respectively) and are instead interpreted literally.
</p>
<p>
To use character classes or repetition counts, escape these characters with a backslash.
</p>
<p>
Some examples:
<p>
<ul>
<li><code>/[1, 2, 3]</code> matches an array: <code>[1, 2, 3]</code></li>
<li><code>/\[bch\]at</code> matches <code>bat</code>, <code>cat</code> or <code>hat</code></li>
<li><code>/{}</code> matches an empty object <code>{}</code></li>
<li><code>/(ha)\{2,3}</code> matches <code>haha</code> or <code>hahaha</code></li>
</ul>
<p>
For exhaustive documentation of the supported regular expression syntax, check out the
<a href="https://docs.rs/regex/latest/regex/index.html#syntax">
documentation of the underlying regex engine:
</a>.
</p>
<h3 id="search-input">Search Input</h3>
<p>
The search is <i>not</i> performed over the original input, but over a single-line pretty formatted version of the input JSON. Consider the following two ways to format an equivalent JSON blob:
</p>
<div class="code-block">{"a":1,"b":true,"c":[null,{},[],"hello"]}
{
"a": 1,
"b": true,
"c": [
null,
{},
[],
"hello"
]
}</div>
<p>
jless will create an internal representation formatted as follows:
</p>
<div class="code-block">{ "a": 1, "b": true, "c": [null, {}, [], "hello"] }</div>
<p>
(No spaces inside empty objects or arrays, one space inside objects with values, no spaces inside array square brackets, no space between an object key and ':', one space after the ':', and one space after commas separating object entries and array elements.)
</p>
<p>
Searching will be performed over this internal representation so that patterns can include multiple elements without worrying about newlines or the exact input format.
</p>
<p>
When the input is newline-delimited JSON, an actual newline will separate each top-level JSON element in the internal representation.
</p>
<p>
<h3 id="data-mode-vs-line-mode">Data Mode vs. Line Mode</h3>
</p>
<p>
JLess starts in "data" mode, which displays the JSON data in a more streamlined fashion: no closing delimiters for objects or arrays, no trailing commas, no quotes around object keys that are valid identifiers in JavaScript. It also shows single-line previews of objects and arrays, and array indexes before array elements. Note that when using full-text search, object keys will still be surrounded by quotes.
</p>
<p>
By pressing <code>m</code>, you can switch jless to "line" mode, which displays the input as pretty printed JSON.
</p>
<p>
In line mode you can press <code>%</code> when focused on an open or close delimiter of an object or array to jump to its matching pair.
</p>
<footer>
<img src="./assets/logo/mascot-rocket.svg">
<div style="margin-top: 24px">
Created by <a href="https://twitter.com/CodeIsTheEnd">CodeIsTheEnd</a>.
</div>
</footer>
</body>
</html>