jless 0.7.1

A command-line JSON viewer
<!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>&lt;</code> Decrease the indentation of every line by one (or <code>N</code>) tabs.
      </li>
      <li>
        <i>count</i>
        <code>&gt;</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>