xplr/en/print.html

2934 lines
181 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>xplr book</title>
<meta name="robots" content="noindex" />
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="A hackable, minimal, fast TUI file explorer">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="quickstart.html"><strong aria-hidden="true">2.</strong> Quickstart</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="install.html"><strong aria-hidden="true">2.1.</strong> Install</a></li><li class="chapter-item expanded "><a href="post-install.html"><strong aria-hidden="true">2.2.</strong> Post Install</a></li></ol></li><li class="chapter-item expanded "><a href="configuration.html"><strong aria-hidden="true">3.</strong> Configuration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="general-config.html"><strong aria-hidden="true">3.1.</strong> General Config</a></li><li class="chapter-item expanded "><a href="modes.html"><strong aria-hidden="true">3.2.</strong> Modes</a></li><li class="chapter-item expanded "><a href="message.html"><strong aria-hidden="true">3.3.</strong> Message</a></li><li class="chapter-item expanded "><a href="layouts.html"><strong aria-hidden="true">3.4.</strong> Layouts</a></li><li class="chapter-item expanded "><a href="node_types.html"><strong aria-hidden="true">3.5.</strong> Node Types</a></li><li class="chapter-item expanded "><a href="style.html"><strong aria-hidden="true">3.6.</strong> Style</a></li><li class="chapter-item expanded "><a href="sorting.html"><strong aria-hidden="true">3.7.</strong> Sorting</a></li><li class="chapter-item expanded "><a href="filtering.html"><strong aria-hidden="true">3.8.</strong> Filtering</a></li><li class="chapter-item expanded "><a href="column-renderer.html"><strong aria-hidden="true">3.9.</strong> Column Renderer</a></li></ol></li><li class="chapter-item expanded "><a href="default-key-bindings.html"><strong aria-hidden="true">4.</strong> Default Key Bindings</a></li><li class="chapter-item expanded "><a href="plugin.html"><strong aria-hidden="true">5.</strong> Plugin</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="installing-plugins.html"><strong aria-hidden="true">5.1.</strong> Installing Plugins</a></li><li class="chapter-item expanded "><a href="writing-plugins.html"><strong aria-hidden="true">5.2.</strong> Writing Plugins</a></li><li class="chapter-item expanded "><a href="awesome-plugins.html"><strong aria-hidden="true">5.3.</strong> Awesome Plugins</a></li></ol></li><li class="chapter-item expanded "><a href="integration.html"><strong aria-hidden="true">6.</strong> Integration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="awesome-integrations.html"><strong aria-hidden="true">6.1.</strong> Awesome Integrations</a></li></ol></li><li class="chapter-item expanded "><a href="todo.html"><strong aria-hidden="true">7.</strong> TODO</a></li><li class="chapter-item expanded "><a href="alternatives.html"><strong aria-hidden="true">8.</strong> Alternatives</a></li><li class="chapter-item expanded "><a href="upgrade-guide.html"><strong aria-hidden="true">9.</strong> Upgrade Guide</a></li><li class="chapter-item expanded "><a href="community.html"><strong aria-hidden="true">10.</strong> Community</a></li><li class="chapter-item expanded "><a href="contribute.html"><strong aria-hidden="true">11.</strong> Contribute</a></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">xplr book</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/sayanarijit/xplr" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="introduction"><a class="header" href="#introduction">Introduction</a></h1>
<p>xplr is a terminal UI based file explorer that aims to increase our terminal
productivity by being a flexible, interactive orchestrator for the ever growing
awesome command-line utilities that work with the file-system.</p>
<p>To achieve its goal, xplr strives to be a fast, minimal and more importantly,
hackable file explorer.</p>
<p>xplr is not meant to be a replacement for the standard shell commands or the
GUI file managers. Rather, it aims to integrate them all and expose an
intuitive, scriptable, keyboard controlled, real-time visual interface, also
being an ideal candidate for further integration, enabling the users to achieve
insane terminal productivity.</p>
<h2 id="features"><a class="header" href="#features">Features</a></h2>
<h3 id="hackable"><a class="header" href="#hackable">Hackable</a></h3>
<p>xplr is built with configurability in mind. So it allows you to perform a vast
set of operations and make it behave just the way you want.</p>
<p>A few things you can do with the xplr configuration</p>
<ul>
<li><a href="layouts.html">Hack the layout</a></li>
<li><a href="modes.html">Hack the key bindings</a></li>
<li><a href="awesome-plugins.html">Extend with plugins</a></li>
</ul>
<h2 id="fast"><a class="header" href="#fast">Fast</a></h2>
<p>Although speed is not the primary concern, xplr is already fast enough so that
you can take it out for a walk into your <code>node_modules</code> or <code>/nix/store</code> any
time you want. I currently
<a href="https://github.com/sayanarijit/xplr/tree/main/benches">measure the most commonly used operations</a>
and I have seen it improve significantly over time, and it's only the start.</p>
<p><strong>Tip:</strong> A quick and easy way to optimize UI rendering is reducing the number
of columns in the table.</p>
<p><strong>Note:</strong> If you feel xplr is not behaving at its optimal, this is probably
because I am waiting for someone to complain. I want to avoid optimizing things
I don't need to, because optimization often requires either complexity or
feature sacrifice or both.</p>
<h2 id="minimalist"><a class="header" href="#minimalist">Minimalist</a></h2>
<p>xplr prefers to stay minimal, both in terms of features and binary size, but
just like speed, minimalism isn't as aggressively pursued as configurability.
If adding some feature, lines of code, or a dependency allows the users to be a
little more productive or allows xplr to be a little more configurable, it will
be considered. But of-course, the <code>bulk vs productivity gain per user</code> balance
will also be considered in the decision-making.</p>
<h2 id="other-features"><a class="header" href="#other-features">Other features</a></h2>
<ul>
<li><a href="https://github.com/sayanarijit/xplr/discussions/183">Embedded LuaJIT</a> for
portability and extensibility.</li>
<li><strong>Switchable recover mode:</strong> Saves you from doing unwanted things when in a
hurry.</li>
<li><strong>Sane (vim-like) defaults:</strong>
<ul>
<li>Use <code>h</code>, <code>j</code>, <code>k</code>, <code>l</code> or arrow keys
for basic navigation.</li>
<li>Go to top using <code>g</code> <code>g</code>, and bottom using <code>G</code>.</li>
<li>Travel history using <code>ctrl-o</code> and <code>ctrl-i</code>.</li>
<li>Go to home directory using <code>~</code>.</li>
<li>Enter search mode with <code>/</code> or <code>ctrl-f</code>.</li>
<li>Go to absolute index (e.g. <code>4</code>) using <code>4</code> <code>enter</code> or
<code>:</code> <code>4</code> <code>enter</code>.</li>
<li>Go to relative index (e.g. <code>4</code> <code>down</code>) using <code>4</code> <code>down</code> or
<code>:</code> <code>4</code> <code>down</code>.</li>
<li>Follow symlink using <code>g</code> <code>f</code>.</li>
<li>Open in GUI using <code>g</code> <code>x</code>.</li>
<li>Spawn terminal using <code>:</code> <code>!</code>.</li>
<li>Toggle selection using <code>v</code> or <code>space</code>.</li>
<li>Toggle select all using <code>V</code> or <code>ctrl-a</code>.</li>
<li>Clear selections using <code>ctrl-u</code>.</li>
</ul>
</li>
<li><strong>Separate keys for navigation:</strong> navigation keys are separated from the
action keys (e.g. file opening action) to avoid mistakenly performing
unwanted actions while navigating.</li>
<li><strong>Always visible panels</strong> to save you brain cycles:
<ul>
<li>Selection list.</li>
<li>Help menu.</li>
<li>Input &amp; logs.</li>
<li>Filter and sort pipeline.</li>
</ul>
</li>
<li><strong>Batch creation:</strong> Create multiple files and directories without repeating
keys.</li>
<li><strong>Batch sort &amp; filter:</strong> Apply sorters and filters in without repeating keys.</li>
<li><strong>Custom file properties:</strong> Display custom file properties with custom colors
in the table using Lua functions.</li>
<li><strong>Input buffer:</strong> Read user input using the built-in input buffer with
customizable behavior.</li>
<li><strong>Switchable layouts:</strong> Switch layouts dynamically without leaving <code>xplr</code>.</li>
<li><strong>Saved locations:</strong> Never lose context when traveling back and forth
directories.</li>
<li><strong>Auto refresh state:</strong> Auto refresh app state when the <code>$PWD</code> changes.</li>
<li><strong>Manually refresh UI</strong> when other apps mess it up.</li>
<li><strong>FIFO-based previews:</strong> Easy to manage FIFO file that can be used to
<a href="https://github.com/sayanarijit/xplr/pull/229">integrate with previewers</a>.</li>
<li><strong>Different quit options:</strong>
<ul>
<li>Quit with success without any output (<code>q</code>).</li>
<li>Quit with success and the result printed on stdout (<code>enter</code>).</li>
<li>Quit with success and the present working directory printed on stdout
(<code>:</code> <code>q</code> <code>p</code>).</li>
<li>Quit with success and the path under focus printed on stdout
(<code>:</code> <code>q</code> <code>f</code>).</li>
<li>Quit with success and the selection printed on stdout
(<code>:</code> <code>q</code> <code>s</code>).</li>
<li>Quit with failure (<code>ctrl-c</code>).</li>
</ul>
</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="quickstart"><a class="header" href="#quickstart">Quickstart</a></h1>
<p>Nice to you have here! Let's quickly start our xplr journey with the
following steps:</p>
<ul>
<li><a href="install.html">Install</a></li>
<li><a href="post-install.html">Post Install</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="try-in-docker"><a class="header" href="#try-in-docker">Try in Docker</a></h1>
<p>If you prefer to try it before installing, here's the snipper for your
convenience.</p>
<pre><code class="language-bash">docker run -w / -it --rm ubuntu sh -uec '
apt-get update -y
apt-get install -y wget tar vim
wget https://github.com/sayanarijit/xplr/releases/latest/download/xplr-linux.tar.gz
tar -xzvf xplr-linux.tar.gz
./xplr
'
</code></pre>
<h1 id="install"><a class="header" href="#install">Install</a></h1>
<p>You can install xplr using one of the following ways. Each has their own
advantages and limitations.</p>
<p>For example, the <a href="install.html#direct-download">Direct Download</a>, <a href="install.html#from-a-hrefhttpscratesiocratesxplrcratesioa">From crates.io</a>, and
<a href="install.html#build-from-source">Build From Source</a> methods allow the users to install the latest possible
version of xplr, but they have one common drawback - the user will need to keep
an eye on the releases, and manually upgrade xplr when a new version is
available.</p>
<p>One way to keep an eye on the releases is to
<a href="https://github.com/sayanarijit/xplr/watchers">watch the repository</a>.</p>
<h2 id="community-maintained-repositories"><a class="header" href="#community-maintained-repositories">Community Maintained Repositories</a></h2>
<p>xplr can be installed from one of the following community maintained
repositories:</p>
<p><a href="https://repology.org/project/xplr/versions"><img src="https://repology.org/badge/vertical-allrepos/xplr.svg" alt="packaging status" /></a></p>
<h3 id="arch-linux"><a class="header" href="#arch-linux">Arch Linux</a></h3>
<h4 id="a-hrefhttpsarchlinuxorgpackagescommunityx86_64xplrofficial-community-repoa"><a class="header" href="#a-hrefhttpsarchlinuxorgpackagescommunityx86_64xplrofficial-community-repoa"><a href="https://archlinux.org/packages/community/x86_64/xplr">Official Community Repo</a></a></h4>
<pre><code>sudo pacman -S xplr
</code></pre>
<h4 id="a-hrefhttpsaurarchlinuxorgpackageso0sebnkxplroutdatedsbnsoapp50do_searchgoaura"><a class="header" href="#a-hrefhttpsaurarchlinuxorgpackageso0sebnkxplroutdatedsbnsoapp50do_searchgoaura"><a href="https://aur.archlinux.org/packages/?O=0&amp;SeB=n&amp;K=xplr&amp;outdated=&amp;SB=n&amp;SO=a&amp;PP=50&amp;do_Search=Go">AUR</a></a></h4>
<p>Binary version:</p>
<pre><code>paru -S xplr-bin
</code></pre>
<p>Git version:</p>
<pre><code>paru -S xplr-git
</code></pre>
<h3 id="void-linux"><a class="header" href="#void-linux">Void Linux</a></h3>
<h4 id="a-hrefhttpsgithubcomshubham-cppvoid-pkg-templatesvoid-templates-by-shubhama"><a class="header" href="#a-hrefhttpsgithubcomshubham-cppvoid-pkg-templatesvoid-templates-by-shubhama"><a href="https://github.com/shubham-cpp/void-pkg-templates">void-templates by shubham</a></a></h4>
<h3 id="nixos"><a class="header" href="#nixos">Nix(OS)</a></h3>
<h4 id="a-hrefhttpsgithubcomnixosnixpkgsblobmasterpkgsapplicationsmiscxplrnixpkgsa"><a class="header" href="#a-hrefhttpsgithubcomnixosnixpkgsblobmasterpkgsapplicationsmiscxplrnixpkgsa"><a href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/xplr">Nixpkgs</a></a></h4>
<pre><code>nix-env -f https://github.com/NixOS/nixpkgs/tarball/master -iA xplr
</code></pre>
<h3 id="macos"><a class="header" href="#macos">macOS</a></h3>
<h4 id="a-hrefhttpsportsmacportsorgportxplrmacportsa"><a class="header" href="#a-hrefhttpsportsmacportsorgportxplrmacportsa"><a href="https://ports.macports.org/port/xplr">MacPorts</a></a></h4>
<pre><code>sudo port selfupdate
sudo port install xplr
</code></pre>
<h4 id="a-hrefhttpsformulaebrewshformulaxplrhomebrewa"><a class="header" href="#a-hrefhttpsformulaebrewshformulaxplrhomebrewa"><a href="https://formulae.brew.sh/formula/xplr">Homebrew</a></a></h4>
<p>Stable branch:</p>
<pre><code>brew install xplr
</code></pre>
<p>HEAD branch:</p>
<pre><code>brew install --head xplr
</code></pre>
<h3 id="freebsd"><a class="header" href="#freebsd">FreeBSD</a></h3>
<h4 id="a-hrefhttpscgitfreebsdorgportsplainmiscxplrportsa"><a class="header" href="#a-hrefhttpscgitfreebsdorgportsplainmiscxplrportsa"><a href="https://cgit.freebsd.org/ports/plain/misc/xplr/">ports</a></a></h4>
<pre><code>pkg install xplr
</code></pre>
<p>Or</p>
<pre><code>cd /usr/ports/misc/xplr
make install clean
</code></pre>
<h3 id="netbsd"><a class="header" href="#netbsd">NetBSD</a></h3>
<h4 id="a-hrefhttpspkgsrcsesysutilsxplrpkgsrca"><a class="header" href="#a-hrefhttpspkgsrcsesysutilsxplrpkgsrca"><a href="https://pkgsrc.se/sysutils/xplr">pkgsrc</a></a></h4>
<pre><code>pkgin install xplr
</code></pre>
<p>Or</p>
<pre><code>cd /usr/pkgsrc/sysutils/xplr
make install
</code></pre>
<h2 id="direct-download"><a class="header" href="#direct-download">Direct Download</a></h2>
<p>One can directly download the standalone binary from the
<a href="https://github.com/sayanarijit/xplr/releases">releases</a>.</p>
<p>Currently, the following options are available for direct download:</p>
<ul>
<li><a href="https://github.com/sayanarijit/xplr/releases/latest/download/xplr-linux.tar.gz">Linux</a></li>
<li><a href="https://github.com/sayanarijit/xplr/releases/latest/download/xplr-macos.tar.gz">macOS</a></li>
</ul>
<p>Command-line instructions:</p>
<pre><code class="language-bash">platform=&quot;linux&quot; # or &quot;macos&quot;
# Download
wget https://github.com/sayanarijit/xplr/releases/latest/download/xplr-$platform.tar.gz
# Extract
tar xzvf xplr-$platform.tar.gz
# Place in $PATH
sudo mv xplr /usr/local/bin/
</code></pre>
<h2 id="from-a-hrefhttpscratesiocratesxplrcratesioa"><a class="header" href="#from-a-hrefhttpscratesiocratesxplrcratesioa">From <a href="https://crates.io/crates/xplr">crates.io</a></a></h2>
<p>Prerequisites:</p>
<ul>
<li><a href="https://www.rust-lang.org/tools/install">Rust toolchain</a>,</li>
<li><a href="https://gcc.gnu.org/">gcc</a></li>
<li><a href="https://www.gnu.org/software/make/">make</a></li>
</ul>
<p>Command-line instructions:</p>
<pre><code class="language-bash">cargo install --locked --force xplr
</code></pre>
<h2 id="build-from-source"><a class="header" href="#build-from-source">Build From Source</a></h2>
<p>Prerequisites:</p>
<ul>
<li><a href="https://git-scm.com/">git</a></li>
<li><a href="https://www.rust-lang.org/tools/install">Rust toolchain</a></li>
<li><a href="https://gcc.gnu.org/">gcc</a></li>
<li><a href="https://www.gnu.org/software/make/">make</a></li>
</ul>
<p>Command-line instructions:</p>
<pre><code class="language-bash"># Clone the repository
git clone https://github.com/sayanarijit/xplr.git
cd xplr
# Build
cargo build --locked --release --bin xplr
# Place in $PATH
sudo cp target/release/xplr /usr/local/bin/
</code></pre>
<h2 id="android"><a class="header" href="#android">Android</a></h2>
<h3 id="a-hrefhttpstermuxcomtermuxa"><a class="header" href="#a-hrefhttpstermuxcomtermuxa"><a href="https://termux.com/">Termux</a></a></h3>
<p><a href="https://gifyu.com/image/tF2D"><img src="https://s3.gifyu.com/images/xplr-termuxfd3c398d3cf4bcbc.md.jpg" alt="xplr-termuxfd3c398d3cf4bcbc.md.jpg" /></a></p>
<blockquote>
<p>Please note that xplr isn't heavily tested on Termux, hence things might
need a little tweaking and fixing for a smooth usage experience.</p>
</blockquote>
<ul>
<li>
<p>Install build dependencies</p>
<pre><code class="language-bash">pkg install rustc cargo make
</code></pre>
</li>
<li>
<p>Install <code>xplr</code></p>
<pre><code class="language-bash">cargo install --locked --force xplr
</code></pre>
</li>
<li>
<p>Setup storage</p>
<pre><code class="language-bash">termux-setup-storage
</code></pre>
</li>
<li>
<p>Setup config and runtime dir</p>
<pre><code class="language-bash">export XDG_CONFIG_HOME=&quot;$PWD/storage/.config&quot;
export XDG_RUNTIME_DIR=&quot;$PWD/storage/run&quot;
mkdir -p &quot;$XDG_CONFIG_HOME&quot; &quot;$XDG_RUNTIME_DIR&quot;
</code></pre>
</li>
<li>
<p>Run</p>
<pre><code class="language-bash">~/.cargo/bin/xplr
</code></pre>
</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="post-install"><a class="header" href="#post-install">Post Install</a></h1>
<p>Once <a href="install.html">installed</a>, use the following steps to setup and run xplr.</p>
<h2 id="create-the-customizable-config-file"><a class="header" href="#create-the-customizable-config-file">Create the customizable config file</a></h2>
<pre><code class="language-bash">mkdir -p ~/.config/xplr
version=&quot;$(xplr | grep ^version: | cut -d' ' -f 2)&quot;
# When the app loads, press `#`
echo version = '&quot;'${version:?}'&quot;' &gt; ~/.config/xplr/init.lua
</code></pre>
<p>Then
<strong><a href="https://github.com/sayanarijit/xplr/blob/main/src/init.lua">copy from here</a></strong>
and remove / comment out what you don't want to customize.</p>
<blockquote>
<p><strong>Note:</strong> You don't generally need to create the config file. You can use the
default configuration for basic operations. However, creating the config file
is recommended because the project is in its early stage and the defaults
might change. Creating the config file will save you from unexpected behavior
when you <a href="upgrade-guide.html">upgrade</a>.
Also, the default configuration is meant to be overwritten to suit your
workflow.</p>
</blockquote>
<h2 id="run"><a class="header" href="#run">Run</a></h2>
<pre><code>xplr
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="configuration"><a class="header" href="#configuration">Configuration</a></h1>
<p>xplr can be configured using <a href="https://www.lua.org/">Lua</a> via a special file
named <code>init.lua</code>
(<a href="https://github.com/sayanarijit/xplr/blob/main/src/init.lua">example</a>), which
can be placed in <code>~/.config/xplr/</code> (user specific) or <code>/etc/xplr/</code> (global)
depending on the use case.</p>
<p>When a user specific configuration is available, the global configuration file
will be ignored.</p>
<p>However, it's also possible to place the file anywhere, with any name and use
the command-line argument <code>-c</code> / <code>--config</code> to specify its path explicitely. In
that case, both <code>~/.config/xplr/init.lua</code> and <code>/etc/xplr/init.lua</code> will be
ignored.</p>
<h2 id="how-config-is-loaded"><a class="header" href="#how-config-is-loaded">How Config Is Loaded</a></h2>
<p>When xplr loads, it first executes the built-in
<a href="https://github.com/sayanarijit/xplr/blob/main/src/init.lua">init.lua</a> to set
the default values, which is then overwritten by another config file, if found
using the following lookup order:</p>
<p><strong>--config /path/to/init.lua</strong> &gt; <strong>~/.config/xplr/init.lua</strong> &gt; <strong>/etc/xplr/init.lua</strong></p>
<h2 id="config"><a class="header" href="#config">config</a></h2>
<p>The xplr configuration, exposed as <code>xplr.config</code> Lua API contains the
following fields:</p>
<ul>
<li><a href="general-config.html">general</a></li>
<li><a href="modes.html">modes</a></li>
<li><a href="layouts.html">layouts</a></li>
<li><a href="node_types.html">node_types</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="general-config"><a class="header" href="#general-config">General Config</a></h1>
<p>This configuration is exposed via the <code>xplr.config.general</code> API. It contains
the following fields:</p>
<h2 id="enable_mouse"><a class="header" href="#enable_mouse">enable_mouse</a></h2>
<p>Type: boolean</p>
<p>Set it to <code>true</code> enable scrolling using mouse.</p>
<h2 id="show_hidden"><a class="header" href="#show_hidden">show_hidden</a></h2>
<p>Type: boolean</p>
<p>Set it to <code>true</code> to show hidden files.</p>
<h2 id="read_only"><a class="header" href="#read_only">read_only</a></h2>
<p>Type: boolean</p>
<p>Set it to <code>true</code> to use only a subset of selected operations that forbids
executing commands or performing write operations on the file-system.</p>
<h2 id="enable_recover_mode"><a class="header" href="#enable_recover_mode">enable_recover_mode</a></h2>
<p>Type: boolean</p>
<p>Set it to <code>true</code> if you want to enable a safety feature that will save you from
yourself when you type recklessly.</p>
<h2 id="cursorformat"><a class="header" href="#cursorformat">cursor.format</a></h2>
<p>Type: nullable string</p>
<p>This is the shape of the cursor visible when the input buffer contains some string.</p>
<h2 id="cursorstyle"><a class="header" href="#cursorstyle">cursor.style</a></h2>
<p>Type: <a href="style.html">Style</a></p>
<p>Style of the cursor.</p>
<h2 id="initial_layout"><a class="header" href="#initial_layout">initial_layout</a></h2>
<p>Type: string</p>
<p>The name of one of the <a href="layouts.html">layout</a> to use when xplr loads.</p>
<h2 id="initial_mode"><a class="header" href="#initial_mode">initial_mode</a></h2>
<p>Type: string</p>
<p>The name of one of the <a href="modes.html">mode</a> to use when xplr loads.</p>
<h2 id="initial_sorting"><a class="header" href="#initial_sorting">initial_sorting</a></h2>
<p>Type: list of <a href="sorting.html#node-sorter-applicable">Node Sorter Applicable</a></p>
<p>Initial group if sorters applied to the nodes list in the table.</p>
<h2 id="tablestyle"><a class="header" href="#tablestyle">table.style</a></h2>
<p>Type: <a href="style.html">Style</a></p>
<p>Default style of the table.</p>
<h2 id="tablecol_spacing"><a class="header" href="#tablecol_spacing">table.col_spacing</a></h2>
<p>Type: nullable integer</p>
<p>Default spacing of the columns in the table.</p>
<h2 id="tablecol_widths"><a class="header" href="#tablecol_widths">table.col_widths</a></h2>
<p>Type: nullable list of <a href="layouts.html#constraint">Constraint</a></p>
<p>Width of each column in the table.</p>
<h2 id="tableheaderheight"><a class="header" href="#tableheaderheight">table.header.height</a></h2>
<p>Type: nullable integer</p>
<p>Height of the table header.</p>
<h2 id="tableheaderstyle"><a class="header" href="#tableheaderstyle">table.header.style</a></h2>
<p>Type: <a href="style.html">Style</a></p>
<p>Style of table header.</p>
<h2 id="tableheadercols"><a class="header" href="#tableheadercols">table.header.cols</a></h2>
<p>Type: List of column configuration</p>
<p>Each column config contains <code>format</code> field (string) and <code>style</code> field
(<a href="style.html">Style</a>), that define the content and style of header.</p>
<h2 id="tablerowheight"><a class="header" href="#tablerowheight">table.row.height</a></h2>
<p>Type: nullable integer</p>
<p>Height of each row in the table.</p>
<h2 id="tablerowstyle"><a class="header" href="#tablerowstyle">table.row.style</a></h2>
<p>Type: <a href="style.html">Style</a></p>
<p>Style of table rows.</p>
<h2 id="tablerowcols"><a class="header" href="#tablerowcols">table.row.cols</a></h2>
<p>Type: List of column configuration</p>
<p>Each column config contains <code>format</code> field (string) and <code>style</code> field
(<a href="style.html">Style</a>).</p>
<p>However, unlike <a href="general-config.html#tableheadercols">table.header.cols</a>, the <code>format</code> field here
points to a <a href="column-renderer.html">column renderer function</a>.</p>
<h2 id="tabletree"><a class="header" href="#tabletree">table.tree</a></h2>
<p>Type: List of tree configuration</p>
<p>It expects a list of three items. The first component of the tree, then the
middle components, and finally the last component of the tree.</p>
<p>Each item requires the <code>format</code> field which is a string, and the <code>style</code> field,
which is the <a href="style.html">Style</a> object.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.general.table.tree = {
{ format = &quot;├─&quot;, style = { add_modifiers = { &quot;Bold&quot; }, bg = nil, fg = &quot;Blue&quot;, sub_modifiers = nil } },
{ format = &quot;├─&quot;, style = { add_modifiers = { &quot;Bold&quot; }, bg = nil, fg = &quot;Blue&quot;, sub_modifiers = nil } },
{ format = &quot;╰─&quot;, style = { add_modifiers = { &quot;Bold&quot; }, bg = nil, fg = &quot;Blue&quot;, sub_modifiers = nil } },
}
</code></pre>
<p>TODO: Continue documentation.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="modes"><a class="header" href="#modes">Modes</a></h1>
<p>xplr is a modal file explorer. That means the users switch between different
modes, each containing a different set of key bindings to avoid clashes. Users
can switch between these modes at run-time.</p>
<p>The modes can be configured using the <code>xplr.config.modes</code> Lua API.</p>
<p>It contains the following fields:</p>
<ul>
<li><a href="modes.html#builtin">builtin</a></li>
<li><a href="modes.html#custom">custom</a></li>
</ul>
<h2 id="builtin"><a class="header" href="#builtin">builtin</a></h2>
<p>Type: mapping of string and <a href="modes.html#mode">Mode</a></p>
<p>This is exposed by the <code>xplr.config.modes.builtin</code> API.</p>
<p>xplr by default provides the following builtin modes:</p>
<ul>
<li>default</li>
<li>recover</li>
<li>selection_ops</li>
<li>create</li>
<li>create_directory</li>
<li>create_file</li>
<li>number</li>
<li>go_to</li>
<li>rename</li>
<li>delete</li>
<li>action</li>
<li>search</li>
<li>filter</li>
<li>relative_path_does_contain</li>
<li>relative_path_does_not_contain</li>
<li>sort</li>
<li>switch_layout</li>
<li>quit</li>
</ul>
<p>Visit the <a href="default-key-bindings.html">Default Key Bindings</a> to see what each mode
does.</p>
<h2 id="custom"><a class="header" href="#custom">custom</a></h2>
<p>Type: mapping of string and <a href="modes.html#mode">Mode</a></p>
<p>This is exposed by the <code>xplr.config.modes.custom</code> API.</p>
<p>It allows the users to define custom modes.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.modes.custom.example = {
name = &quot;example&quot;,
key_bindings = {
on_key = {
enter = {
help = &quot;default mode&quot;,
messages = {
&quot;PopMode&quot;,
{ SwitchModeBuiltin = &quot;default&quot; }
}
}
}
}
}
xplr.config.general.initial_mode = &quot;example&quot;
-- when you load xplr, you should be in the &quot;example&quot; mode,
-- pressing &quot;enter&quot; should take you to the &quot;default&quot; mode.
</code></pre>
<h2 id="mode"><a class="header" href="#mode">Mode</a></h2>
<p>A mode contains the following information:</p>
<ul>
<li><a href="modes.html#name">name</a></li>
<li><a href="modes.html#help">help</a></li>
<li><a href="modes.html#extra_help">extra_help</a></li>
<li><a href="modes.html#key_bindings">key_bindings</a></li>
<li><a href="modes.html#layout">layout</a></li>
</ul>
<h3 id="name"><a class="header" href="#name">name</a></h3>
<p>Type: string</p>
<p>This is the name of the mode visible in the help menu.</p>
<h3 id="help"><a class="header" href="#help">help</a></h3>
<p>Type: nullable string</p>
<p>If specified, the help menu will display this instead of the auto generated
mappings.</p>
<h3 id="extra_help"><a class="header" href="#extra_help">extra_help</a></h3>
<p>Type: nullable string</p>
<p>If specified, the help menu will display this along-side the auto generated
help menu.</p>
<h3 id="key_bindings"><a class="header" href="#key_bindings">key_bindings</a></h3>
<p>Type: <a href="modes.html#key-bindings">Key Bindings</a></p>
<p>The key bindings available in that mode.</p>
<h3 id="layout"><a class="header" href="#layout">layout</a></h3>
<p>Type: nullable <a href="layouts.html#Layout">Layout</a></p>
<p>If specified, this layout will be used to render the UI.</p>
<h2 id="key-bindings"><a class="header" href="#key-bindings">Key Bindings</a></h2>
<p>Key bindings define how each keyboard input will be handled in a specific mode.</p>
<p>See the <a href="default-key-bindings.html">default key bindings</a> for example.</p>
<p>Key bindings contains the following information:</p>
<ul>
<li><a href="modes.html#on_key">on_key</a></li>
<li><a href="modes.html#on_alphabet">on_alphabet</a></li>
<li><a href="modes.html#on_number">on_number</a></li>
<li><a href="modes.html#on_special_character">on_special_character</a></li>
<li><a href="modes.html#default">default</a></li>
</ul>
<h3 id="on_key"><a class="header" href="#on_key">on_key</a></h3>
<p>Type: mapping of <a href="modes.html#key">Key</a> to nullable <a href="modes.html#action">Action</a></p>
<p>Defines what to do when a specific key is pressed.</p>
<h3 id="on_alphabet"><a class="header" href="#on_alphabet">on_alphabet</a></h3>
<p>Type: nullable <a href="modes.html#action">Action</a></p>
<p>An action to perform if the keyboard input is an alphabet and is not mapped via
the <a href="modes.html#on_key">on_key</a> field.</p>
<h3 id="on_number"><a class="header" href="#on_number">on_number</a></h3>
<p>Type: nullable <a href="modes.html#action">Action</a></p>
<p>An action to perform if the keyboard input is a number and is not mapped via
the <a href="modes.html#on_key">on_key</a> field.</p>
<h3 id="on_special_character"><a class="header" href="#on_special_character">on_special_character</a></h3>
<p>Type: nullable <a href="modes.html#action">Action</a></p>
<p>An action to perform if the keyboard input is a special character and is not
mapped via the <a href="modes.html#on_key">on_key</a> field.</p>
<h3 id="default"><a class="header" href="#default">default</a></h3>
<p>Type: nullable <a href="modes.html#action">Action</a></p>
<p>Default action to perform in case of a keyboard input not mapped via any of the
<a href="modes.html#on_key">on_key</a>, <a href="modes.html#on_alphabet">on_alphabet</a>, <a href="modes.html#on_number">on_number</a> or
<a href="modes.html#on_special_character">on_special_character</a> field.</p>
<h2 id="key"><a class="header" href="#key">Key</a></h2>
<p>A key can be one of the following:</p>
<ul>
<li>0, 1, ... 9</li>
<li>a, b, ... z</li>
<li>A, B, ... Z</li>
<li>f1, f2, ... f12</li>
<li>ctrl-a, ctrl-b, ... ctrl-z</li>
<li>alt-a, alt-b, ... alt-z</li>
<li>backspace</li>
<li>left</li>
<li>right</li>
<li>up</li>
<li>down</li>
<li>home</li>
<li>end</li>
<li>page-up</li>
<li>page-down</li>
<li>back-tab</li>
<li>delete</li>
<li>insert</li>
<li>enter</li>
<li>tab</li>
<li>esc</li>
</ul>
<p>And finally, the special characters - including space (<code>&quot; &quot;</code>).</p>
<h2 id="action"><a class="header" href="#action">Action</a></h2>
<p>An action contains the following information:</p>
<ul>
<li>help</li>
<li><a href="modes.html#messages">messages</a></li>
</ul>
<h3 id="help-1"><a class="header" href="#help-1">help</a></h3>
<p>Type: nullable string</p>
<p>Description of what it does. If unspecified, it will be excluded from the help
menu.</p>
<h3 id="messages"><a class="header" href="#messages">messages</a></h3>
<p>Type: A list of <a href="message.html">Message</a> to send.</p>
<p>The list of messages to send when a key is pressed.</p>
<h2 id="tutorial-adding-a-new-mode"><a class="header" href="#tutorial-adding-a-new-mode">Tutorial: Adding a New Mode</a></h2>
<p>Assuming xplr is <a href="install.html">installed</a> and <a href="post-install.html">setup</a>, let's
add our own mode to integrate xplr with <a href="https://github.com/junegunn/fzf">fzf</a>.</p>
<p>We'll call it <code>fzxplr</code> mode.</p>
<p>First, let's add a custom mode called <code>fzxplr</code>, and map the key <code>F</code> to an
action that will call <code>fzf</code> to search and focus on a file or enter into a
directory.</p>
<pre><code class="language-lua">xplr.config.modes.custom.fzxplr = {
name = &quot;fzxplr&quot;,
key_bindings = {
on_key = {
F = {
help = &quot;search&quot;,
messages = {
{
BashExec = [===[
PTH=$(cat &quot;${XPLR_PIPE_DIRECTORY_NODES_OUT:?}&quot; | awk -F/ '{print $NF}' | fzf)
if [ -d &quot;$PTH&quot; ]; then
echo ChangeDirectory: &quot;'&quot;${PWD:?}/${PTH:?}&quot;'&quot; &gt;&gt; &quot;${XPLR_PIPE_MSG_IN:?}&quot;
else
echo FocusPath: &quot;'&quot;${PWD:?}/${PTH:?}&quot;'&quot; &gt;&gt; &quot;${XPLR_PIPE_MSG_IN:?}&quot;
fi
]===]
},
&quot;PopMode&quot;,
},
},
},
default = {
messages = {
&quot;PopMode&quot;,
},
},
},
}
</code></pre>
<p>As you can see, the key <code>F</code> in mode <code>fzxplr</code> (the name can be anything)
executes a script in <code>bash</code>.</p>
<p><code>BashExec</code>, <code>PopMode</code>, <code>SwitchModeBuiltin</code>, <code>ChangeDirectory</code> and <code>FocusPath</code>
are <a href="message.html">messages</a>, <code>$XPLR_PIPE_MSG_IN</code>,
<code>$XPLR_PIPE_DIRECTORY_NODES_OUT</code> are
<a href="message.html#environment-variables">environment variables</a> exported by <code>xplr</code>
before executing the command. They contain the path to the
<a href="message.html#input-pipe">input</a> and <a href="message.html#output-pipes">output</a> pipes that
allows external tools to interact with <code>xplr</code>.</p>
<p>Now that we have our new mode ready, let's add an entry point to this mode via
the <code>default</code> mode.</p>
<pre><code class="language-lua">xplr.config.modes.builtin.default.key_bindings.on_key[&quot;F&quot;] = {
help = &quot;fzf mode&quot;,
messages = {
{ SwitchModeCustom = &quot;fzxplr&quot; },
},
}
</code></pre>
<p>Now let's try out the new <code>xplr</code>-<code>fzf</code> integration.</p>
<p><a href="https://gifyu.com/image/tW86"><img src="https://s3.gifyu.com/images/xplr-fzf.gif" alt="xplr-fzf.gif" /></a></p>
<hr />
<p>Visit <a href="awesome-plugins.html">Awesome Plugins</a> for more <a href="awesome-plugins.html#integration">integration</a> options.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="message"><a class="header" href="#message">Message</a></h1>
<p>You can think of xplr as a server. Just like web servers listen to HTTP
requests, xplr listens to <a href="message.html#full-list-of-messages">messages</a>.</p>
<p>You can send these messages to an xplr session in the following ways:</p>
<ul>
<li>Via <a href="modes.html#key-bindings">key bindings</a></li>
<li>Via <a href="message.html#lua-function-calls">Lua function calls</a></li>
<li>Via shell command using the <a href="message.html#input-pipe">input pipe</a></li>
</ul>
<h2 id="format"><a class="header" href="#format">Format</a></h2>
<p>To send messages using the <a href="modes.html#key-bindings">key bindings</a> or
<a href="message.html#lua-function-calls">Lua function calls</a>, messages are represented in
<a href="https://www.lua.org/">Lua</a> syntax. For example:</p>
<ul>
<li>&quot;Quit&quot;</li>
<li>{ FocusPath = &quot;/path/to/file&quot; }</li>
<li>{ Call = { command = &quot;bash&quot;, args = { &quot;-c&quot;, &quot;read -p test&quot; } } }</li>
</ul>
<p>However, to send messages using the <a href="message.html#input-pipe">input pipe</a>, they need to be
represented using
<a href="http://yaml.org/">YAML</a> (or <a href="https://www.json.org">JSON</a>) syntax. For example:</p>
<ul>
<li>Quit</li>
<li>FocusPath: &quot;/path/to/file&quot;</li>
<li>Call: { command: bash, args: [&quot;-c&quot;, &quot;read -p test&quot;] }</li>
</ul>
<h2 id="full-list-of-messages"><a class="header" href="#full-list-of-messages">Full List of Messages</a></h2>
<h3 id="explorepwd"><a class="header" href="#explorepwd">&quot;ExplorePwd&quot;</a></h3>
<p><strong>YAML:</strong> <code>ExplorePwd</code></p>
<p>Explore the present working directory and register the filtered nodes.
This operation is expensive. So, try to avoid using it too often.</p>
<h3 id="explorepwdasync"><a class="header" href="#explorepwdasync">&quot;ExplorePwdAsync&quot;</a></h3>
<p><strong>YAML:</strong> <code>ExplorePwdAsync</code></p>
<p>Explore the present working directory and register the filtered nodes asynchronously.
This operation happens asynchronously. That means, the xplr directory buffers won't be updated
immediately. Hence, it needs to be used with care and probably with special checks in place.
To explore <code>$PWD</code> synchronously, use <code>ExplorePwd</code> instead.</p>
<h3 id="exploreparentsasync"><a class="header" href="#exploreparentsasync">&quot;ExploreParentsAsync&quot;</a></h3>
<p><strong>YAML:</strong> <code>ExploreParentsAsync</code></p>
<p>Explore the present working directory along with its parents and register the filtered nodes.
This operation happens asynchronously. That means, the xplr directory buffers won't be updated
immediately. Hence, it needs to be used with care and probably with special checks in place.
To explore just the <code>$PWD</code> synchronously, use <code>ExplorePwd</code> instead.</p>
<h3 id="refresh"><a class="header" href="#refresh">&quot;Refresh&quot;</a></h3>
<p><strong>YAML:</strong> <code>Refresh</code></p>
<p>Refresh the UI.
But it will not re-explore the directory if the working directory is the same.
If there is some change in the working directory and you want to re-explore it,
use the <code>Explore</code> message instead.
Also, it will not clear the screen. Use <code>ClearScreen</code> for that.</p>
<h3 id="clearscreen"><a class="header" href="#clearscreen">&quot;ClearScreen&quot;</a></h3>
<p><strong>YAML:</strong> <code>ClearScreen</code></p>
<p>Clears the screen.</p>
<h3 id="focusnext"><a class="header" href="#focusnext">&quot;FocusNext&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusNext</code></p>
<p>Focus next node.</p>
<h3 id="-focusnextbyrelativeindex--int-"><a class="header" href="#-focusnextbyrelativeindex--int-">{ FocusNextByRelativeIndex = int }</a></h3>
<p><strong>YAML:</strong> <code>FocusNextByRelativeIndex: int</code></p>
<p>Focus on the <code>n</code>th node relative to the current focus where <code>n</code> is a given value.</p>
<p><strong>YAML Example:</strong> <code>FocusNextByRelativeIndex: 2</code></p>
<p><strong>Lua Example:</strong> <code>{ FocusNextByRelativeIndex = 2 }</code></p>
<h3 id="focusnextbyrelativeindexfrominput"><a class="header" href="#focusnextbyrelativeindexfrominput">&quot;FocusNextByRelativeIndexFromInput&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusNextByRelativeIndexFromInput</code></p>
<p>Focus on the <code>n</code>th node relative to the current focus where <code>n</code> is read from
the input buffer.</p>
<h3 id="focusprevious"><a class="header" href="#focusprevious">&quot;FocusPrevious&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusPrevious</code></p>
<p>Focus on the previous item.</p>
<h3 id="-focuspreviousbyrelativeindex--int-"><a class="header" href="#-focuspreviousbyrelativeindex--int-">{ FocusPreviousByRelativeIndex = int }</a></h3>
<p><strong>YAML:</strong> <code>FocusPreviousByRelativeIndex: int</code></p>
<p>Focus on the <code>-n</code>th node relative to the current focus where <code>n</code> is a given value.</p>
<p><strong>YAML Example:</strong> <code>FocusPreviousByRelativeIndex: 2</code></p>
<p><strong>Lua Example:</strong> <code>{ FocusPreviousByRelativeIndex = 2 }</code></p>
<h3 id="focuspreviousbyrelativeindexfrominput"><a class="header" href="#focuspreviousbyrelativeindexfrominput">&quot;FocusPreviousByRelativeIndexFromInput&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusPreviousByRelativeIndexFromInput</code></p>
<p>Focus on the <code>-n</code>th node relative to the current focus where <code>n</code> is read from
the input buffer.</p>
<h3 id="focusfirst"><a class="header" href="#focusfirst">&quot;FocusFirst&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusFirst</code></p>
<p>Focus on the first node.</p>
<h3 id="focuslast"><a class="header" href="#focuslast">&quot;FocusLast&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusLast</code></p>
<p>Focus on the last node.</p>
<h3 id="-focuspath--string-"><a class="header" href="#-focuspath--string-">{ FocusPath = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>FocusPath: string</code></p>
<p>Focus on the given path.</p>
<p><strong>YAML Example:</strong> <code>FocusPath: /path/to/file</code></p>
<p><strong>Lua Example:</strong> <code>{ FocusPath = &quot;/path/to/file&quot; }</code></p>
<h3 id="focuspathfrominput"><a class="header" href="#focuspathfrominput">&quot;FocusPathFromInput&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusPathFromInput</code></p>
<p>Focus on the path read from input buffer.</p>
<h3 id="-focusbyindex--int-"><a class="header" href="#-focusbyindex--int-">{ FocusByIndex = int }</a></h3>
<p><strong>YAML:</strong> <code>FocusByIndex: int</code></p>
<p>Focus on the absolute <code>n</code>th node where <code>n</code> is a given value.</p>
<p><strong>YAML Example:</strong> <code>FocusByIndex: 2</code></p>
<p><strong>Lua Example:</strong> <code>{ FocusByIndex = 2 }</code></p>
<h3 id="focusbyindexfrominput"><a class="header" href="#focusbyindexfrominput">&quot;FocusByIndexFromInput&quot;</a></h3>
<p><strong>YAML:</strong> <code>FocusByIndexFromInput</code></p>
<p>Focus on the absolute <code>n</code>th node where <code>n</code> is read from the input buffer.</p>
<h3 id="-focusbyfilename--string-"><a class="header" href="#-focusbyfilename--string-">{ FocusByFileName = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>FocusByFileName: string</code></p>
<p>Focus on the file by name from the present working directory.</p>
<p><strong>YAML Example:</strong> <code>FocusByFileName: filename.ext</code></p>
<p><strong>Lua Example:</strong> <code>{ FocusByFileName = &quot;filename.ext&quot; }</code></p>
<h3 id="-changedirectory--string-"><a class="header" href="#-changedirectory--string-">{ ChangeDirectory = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>ChangeDirectory: string</code></p>
<p>Change the present working directory ($PWD)</p>
<p><strong>YAML Example:</strong> <code>ChangeDirectory: /path/to/directory</code></p>
<p><strong>Lua Example:</strong> <code>{ ChangeDirectory = &quot;/path/to/directory&quot; }</code></p>
<h3 id="enter"><a class="header" href="#enter">&quot;Enter&quot;</a></h3>
<p><strong>YAML:</strong> <code>Enter</code></p>
<p>Enter into the currently focused path if it's a directory.</p>
<h3 id="back"><a class="header" href="#back">&quot;Back&quot;</a></h3>
<p><strong>YAML:</strong> <code>Back</code></p>
<p>Go back to the parent directory.</p>
<h3 id="lastvisitedpath"><a class="header" href="#lastvisitedpath">&quot;LastVisitedPath&quot;</a></h3>
<p><strong>YAML:</strong> <code>LastVisitedPath</code></p>
<p>Go to the last path visited.</p>
<h3 id="nextvisitedpath"><a class="header" href="#nextvisitedpath">&quot;NextVisitedPath&quot;</a></h3>
<p><strong>YAML:</strong> <code>NextVisitedPath</code></p>
<p>Go to the next path visited.</p>
<h3 id="followsymlink"><a class="header" href="#followsymlink">&quot;FollowSymlink&quot;</a></h3>
<p><strong>YAML:</strong> <code>FollowSymlink</code></p>
<p>Follow the symlink under focus to its actual location.</p>
<h3 id="-bufferinput--string-"><a class="header" href="#-bufferinput--string-">{ BufferInput = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>BufferInput(String)</code></p>
<p>Append/buffer the given string into the input buffer.</p>
<p><strong>YAML Example:</strong> <code>BufferInput: foo</code></p>
<p><strong>Lua Example:</strong> <code>{ BufferInput = &quot;foo&quot; }</code></p>
<h3 id="bufferinputfromkey"><a class="header" href="#bufferinputfromkey">&quot;BufferInputFromKey&quot;</a></h3>
<p><strong>YAML:</strong> <code>BufferInputFromKey</code></p>
<p>Append/buffer the characted read from a keyboard input into the
input buffer.</p>
<h3 id="-setinputbuffer--string-"><a class="header" href="#-setinputbuffer--string-">{ SetInputBuffer = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SetInputBuffer: string</code></p>
<p>Set/rewrite the input buffer with the given string.
When the input buffer is not-null (even if empty string)
it will show in the UI.</p>
<p><strong>YAML Example:</strong> <code>SetInputBuffer: foo</code></p>
<p><strong>Lua Example:</strong> <code>{ SetInputBuffer = &quot;foo&quot; }</code></p>
<h3 id="removeinputbufferlastcharacter"><a class="header" href="#removeinputbufferlastcharacter">&quot;RemoveInputBufferLastCharacter&quot;</a></h3>
<p><strong>YAML:</strong> <code>RemoveInputBufferLastCharacter</code></p>
<p>Remove input buffer's last character.</p>
<h3 id="removeinputbufferlastword"><a class="header" href="#removeinputbufferlastword">&quot;RemoveInputBufferLastWord&quot;</a></h3>
<p><strong>YAML:</strong> <code>RemoveInputBufferLastWord</code></p>
<p>Remove input buffer's last word.</p>
<h3 id="resetinputbuffer"><a class="header" href="#resetinputbuffer">&quot;ResetInputBuffer&quot;</a></h3>
<p><strong>YAML:</strong> <code>ResetInputBuffer</code></p>
<p>Reset the input buffer back to null. It will not show in the UI.</p>
<h3 id="-switchmode--string-"><a class="header" href="#-switchmode--string-">{ SwitchMode = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchMode: string</code></p>
<p>Switch input <a href="modes.html#mode">mode</a>.
It clears the input buffer.</p>
<blockquote>
<p><strong>NOTE:</strong> To be specific about which mode to switch to, use <code>SwitchModeBuiltin</code> or
<code>SwitchModeCustom</code> instead.</p>
</blockquote>
<p><strong>YAML Example:</strong> <code>SwitchMode: default</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchMode = &quot;default&quot; }</code></p>
<h3 id="-switchmodekeepinginputbuffer--string-"><a class="header" href="#-switchmodekeepinginputbuffer--string-">{ SwitchModeKeepingInputBuffer = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchModeKeepingInputBuffer: string</code></p>
<p>Switch input <a href="modes.html#mode">mode</a>.
It keeps the input buffer.</p>
<blockquote>
<p><strong>NOTE:</strong> To be specific about which mode to switch to, use
<code>SwitchModeBuiltinKeepingInputBuffer</code> or
<code>SwitchModeCustomKeepingInputBuffer</code> instead.</p>
</blockquote>
<p><strong>YAML Example:</strong> <code>SwitchModeKeepingInputBuffer: default</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchModeKeepingInputBuffer = &quot;default&quot; }</code></p>
<h3 id="-switchmodebuiltin--string-"><a class="header" href="#-switchmodebuiltin--string-">{ SwitchModeBuiltin = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchModeBuiltin: string</code></p>
<p>Switch to a <a href="modes.html#builtin">builtin mode</a>.
It clears the input buffer.</p>
<p><strong>YAML Example:</strong> <code>SwitchModeBuiltin: default</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchModeBuiltin = &quot;default&quot; }</code></p>
<h3 id="-switchmodebuiltinkeepinginputbuffer--string-"><a class="header" href="#-switchmodebuiltinkeepinginputbuffer--string-">{ SwitchModeBuiltinKeepingInputBuffer = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchModeBuiltinKeepingInputBuffer: string</code></p>
<p>Switch to a <a href="modes.html#builtin">builtin mode</a>.
It keeps the input buffer.</p>
<p><strong>YAML Example:</strong> <code>SwitchModeBuiltinKeepingInputBuffer: default</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchModeBuiltinKeepingInputBuffer = &quot;default&quot; }</code></p>
<h3 id="-switchmodecustom--string-"><a class="header" href="#-switchmodecustom--string-">{ SwitchModeCustom = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchModeCustom: string</code></p>
<p>Switch to a <a href="modes.html#custom">custom mode</a>.
It clears the input buffer.</p>
<p><strong>YAML Example:</strong> <code>SwitchModeCustom: my_custom_mode</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchModeCustom = &quot;my_custom_mode&quot; }</code></p>
<h3 id="-switchmodecustomkeepinginputbuffer--string-"><a class="header" href="#-switchmodecustomkeepinginputbuffer--string-">{ SwitchModeCustomKeepingInputBuffer = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchModeCustom: string</code></p>
<p>Switch to a <a href="modes.html#custom">custom mode</a>.
It keeps the input buffer.</p>
<p><strong>YAML Example:</strong> <code>SwitchModeCustomKeepingInputBuffer: my_custom_mode</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchModeCustomKeepingInputBuffer = &quot;my_custom_mode&quot; }</code></p>
<h3 id="popmode"><a class="header" href="#popmode">&quot;PopMode&quot;</a></h3>
<p><strong>YAML:</strong> <code>PopMode</code></p>
<p>Pop the last mode from the history and switch to it.
It clears the input buffer.</p>
<h3 id="popmodekeepinginputbuffer"><a class="header" href="#popmodekeepinginputbuffer">PopModeKeepingInputBuffer</a></h3>
<p><strong>YAML:</strong> <code>PopModeKeepingInputBuffer</code></p>
<p>Pop the last mode from the history and switch to it.
It keeps the input buffer.</p>
<h3 id="-switchlayout--string-"><a class="header" href="#-switchlayout--string-">{ SwitchLayout = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchLayout: string</code></p>
<p>Switch <a href="layouts.html#layout">layout</a>.</p>
<blockquote>
<p><strong>NOTE:</strong> To be specific about which layout to switch to, use <code>SwitchLayoutBuiltin</code> or
<code>SwitchLayoutCustom</code> instead.</p>
</blockquote>
<p><strong>YAML Example:</strong> <code>SwitchLayout: default</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchLayout = &quot;default&quot; }</code></p>
<h3 id="-switchlayoutbuiltin--string-"><a class="header" href="#-switchlayoutbuiltin--string-">{ SwitchLayoutBuiltin = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchLayoutBuiltin: string</code></p>
<p>Switch to a <a href="layouts.html#builtin">builtin layout</a>.</p>
<p><strong>YAML Example:</strong> <code>SwitchLayoutBuiltin: default</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchLayoutBuiltin = &quot;default&quot; }</code></p>
<h3 id="-switchlayoutcustom--string-"><a class="header" href="#-switchlayoutcustom--string-">{ SwitchLayoutCustom = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SwitchLayoutCustom: string</code></p>
<p>Switch to a <a href="layouts.html#custom">custom layout</a>.</p>
<p><strong>YAML Example:</strong> <code>SwitchLayoutCustom: my_custom_layout</code></p>
<p><strong>Lua Example:</strong> <code>{ SwitchLayoutCustom = &quot;my_custom_layout&quot; }</code></p>
<h3 id="-call--string-"><a class="header" href="#-call--string-">{ Call = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>Call: string</code></p>
<p>Call a shell command with the given arguments.
Note that the arguments will be shell-escaped.
So to read the variables, the <code>-c</code> option of the shell
can be used.
You may need to pass <code>ExplorePwd</code> depening on the expectation.</p>
<p><strong>YAML Example:</strong> <code>Call: { command: bash, args: [&quot;-c&quot;, &quot;read -p test&quot;] }</code></p>
<p><strong>Lua Example:</strong> <code>{ Call = { command = &quot;bash&quot;, args = { &quot;-c&quot;, &quot;read -p test&quot; } } }</code></p>
<h3 id="-callsilently--string-"><a class="header" href="#-callsilently--string-">{ CallSilently = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>CallSilently: string</code></p>
<p>Like <code>Call</code> but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive.</p>
<p><strong>YAML Example:</strong> <code>CallSilently: { command: tput, args: [&quot;bell&quot;] }</code></p>
<p><strong>Lua Example:</strong> <code>{ CallSilently = { command = &quot;tput&quot;, args = { &quot;bell&quot; } } }</code></p>
<h3 id="-calllua--string-"><a class="header" href="#-calllua--string-">{ CallLua = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>CallLua: string</code></p>
<p>Call a Lua function.
A <a href="message.html#calllua-argument"><code>CallLuaArg</code></a> object will be passed to the
<a href="message.html#lua-function-calls">function</a> as argument.
The function can optionally return a list of messages for xplr to handle
after the executing the function.</p>
<p><strong>YAML Example:</strong> <code>CallLua: custom.some_custom_funtion</code></p>
<p><strong>Lua Example:</strong> <code>{ CallLua = &quot;custom.some_custom_funtion&quot; }</code></p>
<h3 id="-callluasilently--string-"><a class="header" href="#-callluasilently--string-">{ CallLuaSilently = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>CallLuaSilently: string</code></p>
<p>Like <code>CallLua</code> but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive.</p>
<p><strong>YAML Example:</strong> <code>CallLuaSilently: custom.some_custom_function</code></p>
<p><strong>Lua Example:</strong> <code>{ CallLuaSilently = &quot;custom.some_custom_function&quot; }</code></p>
<h3 id="-bashexec--string-"><a class="header" href="#-bashexec--string-">{ BashExec = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>BashExec: string</code></p>
<p>An alias to <code>Call: {command: bash, args: [&quot;-c&quot;, &quot;{string}&quot;], silent: false}</code>
where <code>{string}</code> is the given value.</p>
<p><strong>YAML Example:</strong> <code>BashExec: &quot;read -p test&quot;</code></p>
<p><strong>Lua Example:</strong> <code>{ BashExec = &quot;read -p test&quot; }</code></p>
<h3 id="-bashexecsilently--string-"><a class="header" href="#-bashexecsilently--string-">{ BashExecSilently = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>BashExecSilently(String)</code></p>
<p>Like <code>BashExec</code> but without the flicker. The stdin, stdout
stderr will be piped to null. So it's non-interactive.</p>
<p><strong>YAML Example:</strong> <code>BashExecSilently: &quot;tput bell&quot;</code></p>
<p><strong>Lua Example:</strong> <code>{ BashExecSilently = &quot;tput bell&quot; }</code></p>
<h3 id="select"><a class="header" href="#select">&quot;Select&quot;</a></h3>
<p><strong>YAML:</strong> <code>Select</code></p>
<p>Select the focused node.</p>
<h3 id="selectall"><a class="header" href="#selectall">&quot;SelectAll&quot;</a></h3>
<p><strong>YAML:</strong> <code>SelectAll</code></p>
<p>Select all the visible nodes.</p>
<h3 id="-selectpath--string-"><a class="header" href="#-selectpath--string-">{ SelectPath = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>SelectPath: string</code></p>
<p>Select the given path.</p>
<p><strong>YAML Example:</strong> <code>SelectPath: /path/to/file</code></p>
<p><strong>Lua Example:</strong> <code>{ SelectPath = &quot;/path/to/file&quot; }</code></p>
<h3 id="unselect"><a class="header" href="#unselect">&quot;UnSelect&quot;</a></h3>
<p><strong>YAML:</strong> <code>UnSelect</code></p>
<p>Unselect the focused node.</p>
<h3 id="unselectall"><a class="header" href="#unselectall">&quot;UnSelectAll&quot;</a></h3>
<p><strong>YAML:</strong> <code>UnSelectAll</code></p>
<p>Unselect all the visible nodes.</p>
<h3 id="-unselectpath--string-"><a class="header" href="#-unselectpath--string-">{ UnSelectPath = &quot;string)&quot; }</a></h3>
<p><strong>YAML:</strong> <code>UnSelectPath: string</code></p>
<p>UnSelect the given path.</p>
<p><strong>YAML Example:</strong> <code>UnSelectPath: /path/to/file</code></p>
<p><strong>Lua Example:</strong> <code>{ UnSelectPath = &quot;/path/to/file&quot; }</code></p>
<h3 id="toggleselection"><a class="header" href="#toggleselection">&quot;ToggleSelection&quot;</a></h3>
<p><strong>YAML:</strong> <code>ToggleSelection</code></p>
<p>Toggle selection on the focused node.</p>
<h3 id="toggleselectall"><a class="header" href="#toggleselectall">&quot;ToggleSelectAll&quot;</a></h3>
<p><strong>YAML:</strong> <code>ToggleSelectAll</code></p>
<p>Toggle between select all and unselect all.</p>
<h3 id="-toggleselectionbypath--string-"><a class="header" href="#-toggleselectionbypath--string-">{ ToggleSelectionByPath = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>ToggleSelectionByPath: string</code></p>
<p>Toggle selection by file path.</p>
<p><strong>YAML Example:</strong> <code>ToggleSelectionByPath: /path/to/file</code></p>
<p><strong>Lua Example:</strong> <code>{ ToggleSelectionByPath = &quot;/path/to/file&quot; }</code></p>
<h3 id="clearselection"><a class="header" href="#clearselection">&quot;ClearSelection&quot;</a></h3>
<p><strong>YAML:</strong> <code>ClearSelection</code></p>
<p>Clear the selection.</p>
<h3 id="-addnodefilter---filter--a-hreffilteringhtmlfilterfiltera-input--string-"><a class="header" href="#-addnodefilter---filter--a-hreffilteringhtmlfilterfiltera-input--string-">{ AddNodeFilter = { filter = <a href="filtering.html#filter">Filter</a>, input = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>AddNodeFilter: { filter = Filter, input = string }</code></p>
<p>Add a <a href="filtering.html">filter</a> to exclude nodes while exploring directories.</p>
<p><strong>YAML Example:</strong> <code>AddNodeFilter: { filter: RelativePathDoesStartWith, input: foo }</code></p>
<p><strong>Lua Example:</strong> <code>{ AddNodeFilter = { filter = &quot;RelativePathDoesStartWith&quot;, input = &quot;foo&quot; } }</code></p>
<h3 id="-removenodefilter---filter--a-hreffilteringhtmlfilterfiltera-input--string-"><a class="header" href="#-removenodefilter---filter--a-hreffilteringhtmlfilterfiltera-input--string-">{ RemoveNodeFilter = { filter = <a href="filtering.html#filter">Filter</a>, input = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>RemoveNodeFilter: { filter = Filter, input = string</code></p>
<p>Remove an existing <a href="filtering.html">filter</a>.</p>
<p><strong>YAML Example:</strong> <code>RemoveNodeFilter: { filter: RelativePathDoesStartWith, input: foo }</code></p>
<p><strong>Lua Example:</strong> <code>{ RemoveNodeFilter: { filter: &quot;RelativePathDoesStartWith&quot;, input: &quot;foo&quot; } }</code></p>
<h3 id="-togglenodefilter---filter--a-hreffilteringhtmlfilterfiltera-input--string-"><a class="header" href="#-togglenodefilter---filter--a-hreffilteringhtmlfilterfiltera-input--string-">{ ToggleNodeFilter = { filter = <a href="filtering.html#filter">Filter</a>, input = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>ToggleNodeFilter: { filter = Filter, input = string }</code></p>
<p>Remove a <a href="filtering.html">filter</a> if it exists, else, add a it.</p>
<p><strong>YAML Example:</strong> <code>ToggleNodeFilter: { filter: RelativePathDoesStartWith, input: foo }</code></p>
<p><strong>Lua Example:</strong> <code>{ ToggleNodeFilter = { filter = &quot;RelativePathDoesStartWith&quot;, input = &quot;foo&quot; } }</code></p>
<h3 id="-addnodefilterfrominput--a-hreffilteringhtmlfilterfiltera-"><a class="header" href="#-addnodefilterfrominput--a-hreffilteringhtmlfilterfiltera-">{ AddNodeFilterFromInput = <a href="filtering.html#filter">Filter</a> }</a></h3>
<p><strong>YAML:</strong> <code>AddNodeFilterFromInput: Filter</code></p>
<p>Add a node <a href="filtering.html">filter</a> reading the input from the buffer.</p>
<p><strong>YAML Example:</strong> <code>AddNodeFilterFromInput: RelativePathDoesStartWith</code></p>
<p><strong>Lua Example:</strong> <code>{ AddNodeFilterFromInput = &quot;RelativePathDoesStartWith&quot; }</code></p>
<h3 id="-removenodefilterfrominput--a-hreffilteringhtmlfilterfiltera-"><a class="header" href="#-removenodefilterfrominput--a-hreffilteringhtmlfilterfiltera-">{ RemoveNodeFilterFromInput = <a href="filtering.html#filter">Filter</a> }</a></h3>
<p><strong>YAML:</strong> <code>RemoveNodeFilterFromInput: Filter</code></p>
<p>Remove a node <a href="filtering.html">filter</a> reading the input from the buffer.</p>
<p><strong>YAML Example:</strong> <code>RemoveNodeFilterFromInput: RelativePathDoesStartWith</code></p>
<p><strong>Lua Example:</strong> <code>{ RemoveNodeFilterFromInput = &quot;RelativePathDoesStartWith&quot; }</code></p>
<h3 id="removelastnodefilter"><a class="header" href="#removelastnodefilter">&quot;RemoveLastNodeFilter&quot;</a></h3>
<p><strong>YAML:</strong> <code>RemoveLastNodeFilter</code></p>
<p>Remove the last node <a href="filtering.html">filter</a>.</p>
<h3 id="resetnodefilters"><a class="header" href="#resetnodefilters">&quot;ResetNodeFilters&quot;</a></h3>
<p><strong>YAML:</strong> <code>ResetNodeFilters</code></p>
<p>Reset the node <a href="filtering.html">filters</a> back to the default configuration.</p>
<h3 id="clearnodefilters"><a class="header" href="#clearnodefilters">&quot;ClearNodeFilters&quot;</a></h3>
<p><strong>YAML:</strong> <code>ClearNodeFilters</code></p>
<p>Clear all the node <a href="filtering.html">filters</a>.</p>
<h3 id="-addnodesorter---sorter--a-hrefsortinghtmlsortersortera-reverse--bool--"><a class="header" href="#-addnodesorter---sorter--a-hrefsortinghtmlsortersortera-reverse--bool--">{ AddNodeSorter = { sorter = <a href="sorting.html#sorter">Sorter</a>, reverse = bool } }</a></h3>
<p><strong>YAML:</strong> <code>AddNodeSorter: { sorter: Sorter, reverse = bool }</code></p>
<p>Add a <a href="sorting.html#sorter">sorter</a> to sort nodes while exploring directories.</p>
<p><strong>YAML Example:</strong> <code>AddNodeSorter: { sorter: ByRelativePath, reverse: false }</code></p>
<p><strong>YAML Example:</strong> <code>{ AddNodeSorter = { sorter = &quot;ByRelativePath&quot;, reverse = false } }</code></p>
<h3 id="-removenodesorter--a-hrefsortinghtmlsortersortera-"><a class="header" href="#-removenodesorter--a-hrefsortinghtmlsortersortera-">{ RemoveNodeSorter = <a href="sorting.html#sorter">Sorter</a> }</a></h3>
<p><strong>YAML:</strong> <code>RemoveNodeSorter: Sorter</code></p>
<p>Remove an existing <a href="sorting.html#sorter">sorter</a>.</p>
<p><strong>YAML Example:</strong> <code>RemoveNodeSorter: ByRelativePath</code></p>
<p><strong>Lua Example:</strong> <code>{ RemoveNodeSorter = &quot;ByRelativePath&quot; }</code></p>
<h3 id="-reversenodesorter--a-hrefsortinghtmlsortersortera-"><a class="header" href="#-reversenodesorter--a-hrefsortinghtmlsortersortera-">{ ReverseNodeSorter = <a href="sorting.html#sorter">Sorter</a> }</a></h3>
<p><strong>YAML:</strong> <code>ReverseNodeSorter: Sorter</code></p>
<p>Reverse a node <a href="sorting.html#sorter">sorter</a>.</p>
<p><strong>YAML Example:</strong> <code>ReverseNodeSorter: ByRelativePath</code></p>
<p><strong>Lua Example:</strong> <code>{ ReverseNodeSorter = &quot;ByRelativePath&quot; }</code></p>
<h3 id="-togglenodesorter---sorter--a-hrefsortinghtmlsortersortera-reverse--bool--"><a class="header" href="#-togglenodesorter---sorter--a-hrefsortinghtmlsortersortera-reverse--bool--">{ ToggleNodeSorter = { sorter = <a href="sorting.html#sorter">Sorter</a>, reverse = bool } }</a></h3>
<p><strong>YAML:</strong> <code>ToggleNodeSorter: { sorter: Sorter, reverse = bool }</code></p>
<p>Remove a <a href="sorting.html#sorter">sorter</a> if it exists, else, add a it.</p>
<p><strong>YAML Example:</strong> <code>ToggleSorterSorter: {sorter: ByRelativePath, reverse: false }</code></p>
<p><strong>Lua Example:</strong> <code>{ ToggleSorterSorter: { sorter = &quot;ByRelativePath&quot;, reverse = false } }</code></p>
<h3 id="reversenodesorters"><a class="header" href="#reversenodesorters">&quot;ReverseNodeSorters&quot;</a></h3>
<p><strong>YAML:</strong> <code>ReverseNodeSorters</code></p>
<p>Reverse the node <a href="sorting.html#sorter">sorters</a>.</p>
<h3 id="removelastnodesorter"><a class="header" href="#removelastnodesorter">&quot;RemoveLastNodeSorter&quot;</a></h3>
<p><strong>YAML:</strong> <code>RemoveLastNodeSorter</code></p>
<p>Remove the last node <a href="sorting.html#sorter">sorter</a>.</p>
<h3 id="resetnodesorters"><a class="header" href="#resetnodesorters">&quot;ResetNodeSorters&quot;</a></h3>
<p><strong>YAML:</strong> <code>ResetNodeSorters</code></p>
<p>Reset the node <a href="sorting.html#sorter">sorters</a> back to the default configuration.</p>
<h3 id="clearnodesorters"><a class="header" href="#clearnodesorters">&quot;ClearNodeSorters&quot;</a></h3>
<p><strong>YAML:</strong> <code>ClearNodeSorters</code></p>
<p>Clear all the node <a href="sorting.html#sorter">sorters</a>.</p>
<h3 id="enablemouse"><a class="header" href="#enablemouse">&quot;EnableMouse&quot;</a></h3>
<p><strong>YAML:</strong> <code>EnableMouse</code></p>
<p>Enable mouse</p>
<h3 id="disablemouse"><a class="header" href="#disablemouse">&quot;DisableMouse&quot;</a></h3>
<p><strong>YAML:</strong> <code>DisableMouse</code></p>
<p>Disable mouse</p>
<h3 id="togglemouse"><a class="header" href="#togglemouse">&quot;ToggleMouse&quot;</a></h3>
<p><strong>YAML:</strong> <code>ToggleMouse</code></p>
<p>Toggle mouse</p>
<h3 id="-startfifo--string-"><a class="header" href="#-startfifo--string-">{ StartFifo = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>StartFifo: string</code></p>
<p>Start piping the focused path to the given fifo path</p>
<p><strong>YAML Example:</strong> <code>StartFifo: /tmp/xplr.fifo</code></p>
<p><strong>Lua Example:</strong> <code>{ StartFifo = &quot;/tmp/xplr.fifo }</code></p>
<h3 id="stopfifo"><a class="header" href="#stopfifo">&quot;StopFifo&quot;</a></h3>
<p><strong>YAML:</strong> <code>StopFifo</code></p>
<p>Close the active fifo and stop piping.</p>
<h3 id="-togglefifo--string-"><a class="header" href="#-togglefifo--string-">{ ToggleFifo = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>ToggleFifo: string</code></p>
<p>Toggle betwen {Start|Stop}Fifo</p>
<p><strong>YAML Example:</strong> <code>ToggleFifo: /path/to/fifo</code></p>
<p><strong>Lua Example:</strong> <code>{ ToggleFifo = &quot;/path/to/fifo&quot; }</code></p>
<h3 id="-loginfo--string-"><a class="header" href="#-loginfo--string-">{ LogInfo = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>LogInfo: string</code></p>
<p>Log information message.</p>
<p><strong>YAML Example:</strong> <code>LogInfo: launching satellite</code></p>
<p><strong>Lua Example:</strong> <code>{ LogInfo = &quot;launching satellite&quot; }</code></p>
<h3 id="-logsuccess--string-"><a class="header" href="#-logsuccess--string-">{ LogSuccess = &quot;String&quot; }</a></h3>
<p><strong>YAML:</strong> <code>LogSuccess: string</code></p>
<p>Log a success message.</p>
<p><strong>YAML Example:</strong> <code>LogSuccess: satellite reached destination</code>.</p>
<p><strong>Lua Example:</strong> <code>{ LogSuccess = &quot;satellite reached destination&quot; }</code>.</p>
<h3 id="-logwarning--string-"><a class="header" href="#-logwarning--string-">{ LogWarning = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>LogWarning: string</code></p>
<p>Log an warning message.</p>
<p><strong>YAML Example:</strong> <code>LogWarning: satellite is heating</code></p>
<p><strong>Lua Example:</strong> <code>{ LogWarning = &quot;satellite is heating&quot; }</code></p>
<h3 id="-logerror--string-"><a class="header" href="#-logerror--string-">{ LogError = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>LogError: string</code></p>
<p>Log an error message.</p>
<p><strong>YAML Example:</strong> <code>LogError: satellite crashed</code></p>
<p><strong>Lua Example:</strong> <code>{ LogError = &quot;satellite crashed&quot; }</code></p>
<h3 id="quit"><a class="header" href="#quit">&quot;Quit&quot;</a></h3>
<p><strong>YAML:</strong> <code>Quit</code></p>
<p>Quit with returncode zero (success).</p>
<h3 id="printpwdandquit"><a class="header" href="#printpwdandquit">&quot;PrintPwdAndQuit&quot;</a></h3>
<p><strong>YAML:</strong> <code>PrintPwdAndQuit</code></p>
<p>Print $PWD and quit.</p>
<h3 id="printfocuspathandquit"><a class="header" href="#printfocuspathandquit">&quot;PrintFocusPathAndQuit&quot;</a></h3>
<p><strong>YAML:</strong> <code>PrintFocusPathAndQuit</code></p>
<p>Print the path under focus and quit. It can be empty string if there's nothing to focus.</p>
<h3 id="printselectionandquit"><a class="header" href="#printselectionandquit">&quot;PrintSelectionAndQuit&quot;</a></h3>
<p><strong>YAML:</strong> <code>PrintSelectionAndQuit</code></p>
<p>Print the selected paths and quit. It can be empty is no path is selected.</p>
<h3 id="printresultandquit"><a class="header" href="#printresultandquit">&quot;PrintResultAndQuit&quot;</a></h3>
<p><strong>YAML:</strong> <code>PrintResultAndQuit</code></p>
<p>Print the selected paths if it's not empty, else, print the focused node's path.</p>
<h3 id="printappstateandquit"><a class="header" href="#printappstateandquit">&quot;PrintAppStateAndQuit&quot;</a></h3>
<p><strong>YAML:</strong> <code>PrintAppStateAndQuit</code></p>
<p>Print the state of application in YAML format. Helpful for debugging or generating
the default configuration file.</p>
<h3 id="-debug--string-"><a class="header" href="#-debug--string-">{ Debug = &quot;string&quot; }</a></h3>
<p><strong>YAML:</strong> <code>Debug: string</code></p>
<p>Write the application state to a file, without quitting. Also helpful for debugging.</p>
<p><strong>YAML Example:</strong> <code>Debug: /path/to/file</code></p>
<p><strong>Lua Example:</strong> <code>{ Debug = &quot;/path/to/file&quot; }</code></p>
<h3 id="terminate"><a class="header" href="#terminate">&quot;Terminate&quot;</a></h3>
<p><strong>YAML:</strong> <code>Terminate</code></p>
<p>Terminate the application with a non-zero return code.</p>
<h2 id="lua-function-calls"><a class="header" href="#lua-function-calls">Lua Function Calls</a></h2>
<p>xplr allows users to define lua functions using the <code>xplr.fn.custom</code> Lua API.</p>
<p>These functions can be called using messages like <code>CallLua</code>, <code>CallLuaSilently</code>.</p>
<p>When called the function receives a <a href="message.html#calllua-argument">special argument</a> that
contains some useful information. The function can optionally return a list of
messages which will be handled by xplr.</p>
<h3 id="calllua-argument"><a class="header" href="#calllua-argument">CallLua Argument</a></h3>
<p>This is a special argument passed to the lua functions when called using the
<code>CallLua</code>, <code>CallLuaSilently</code> messages.</p>
<p>It contains the following information:</p>
<ul>
<li><a href="message.html#version">version</a></li>
<li><a href="message.html#config">config</a></li>
<li><a href="message.html#pwd">pwd</a></li>
<li><a href="message.html#focused_node">focused_node</a></li>
<li><a href="message.html#directory_buffer">directory_buffer</a></li>
<li><a href="message.html#selection">selection</a></li>
<li><a href="message.html#mode">mode</a></li>
<li><a href="message.html#layout">layout</a></li>
<li><a href="message.html#input_buffer">input_buffer</a></li>
<li><a href="message.html#pid">pid</a></li>
<li><a href="message.html#session_path">session_path</a></li>
<li><a href="message.html#explorer_config">explorer_config</a></li>
<li><a href="message.html#history">history</a></li>
<li><a href="message.html#last_modes">last_modes</a></li>
</ul>
<h3 id="version"><a class="header" href="#version">version</a></h3>
<p>Type: string</p>
<p>xplr version. Can be used to test compatibility.</p>
<h3 id="config-1"><a class="header" href="#config-1">config</a></h3>
<p>Type: <a href="configuration.html#config">Config</a></p>
<p>The loaded configuration.</p>
<h3 id="pwd"><a class="header" href="#pwd">pwd</a></h3>
<p>Type: string</p>
<p>The present working directory/</p>
<h3 id="focused_node"><a class="header" href="#focused_node">focused_node</a></h3>
<p>Type: nullable <a href="message.html#node">Node</a></p>
<p>The node under focus.</p>
<h3 id="directory_buffer"><a class="header" href="#directory_buffer">directory_buffer</a></h3>
<p>Type: nullable <a href="message.html#directorybuffer">DirectoryBuffer</a></p>
<p>The directory buffer being rendered.</p>
<h3 id="selection"><a class="header" href="#selection">selection</a></h3>
<p>Type: list of selected <a href="message.html#node">Node</a>s</p>
<p>The selected nodes.</p>
<h3 id="mode-1"><a class="header" href="#mode-1">mode</a></h3>
<p>Type: <a href="modes.html#mode">Mode</a></p>
<p>Current mode.</p>
<h3 id="layout-1"><a class="header" href="#layout-1">layout</a></h3>
<p>Type: <a href="layouts.html#layout">Layout</a></p>
<p>Current layout.</p>
<h3 id="input_buffer"><a class="header" href="#input_buffer">input_buffer</a></h3>
<p>Type: nullable string</p>
<p>The input buffer.</p>
<h3 id="pid"><a class="header" href="#pid">pid</a></h3>
<p>Type: integer</p>
<p>The xplr session PID.</p>
<h3 id="session_path"><a class="header" href="#session_path">session_path</a></h3>
<p>Type: string</p>
<p>The session path.</p>
<h3 id="explorer_config"><a class="header" href="#explorer_config">explorer_config</a></h3>
<p><a href="https://docs.rs/xplr/latest/xplr/app/struct.ExplorerConfig.html">TODO</a></p>
<h3 id="history"><a class="header" href="#history">history</a></h3>
<p>Type: <a href="message.html#history-1">History</a></p>
<h3 id="last_modes"><a class="header" href="#last_modes">last_modes</a></h3>
<p>Type: list of <a href="modes.html#mode">Mode</a></p>
<p>Last modes, not popped yet.</p>
<h3 id="parent"><a class="header" href="#parent">parent</a></h3>
<p>Type: string</p>
<p>The parent path of the node.</p>
<h3 id="relative_path"><a class="header" href="#relative_path">relative_path</a></h3>
<p>Type: string</p>
<p>The path relative to the parent, i.e. the file/directory name with extension.</p>
<h3 id="absolute_path"><a class="header" href="#absolute_path">absolute_path</a></h3>
<p>Type: string</p>
<p>The absolute path (without resolving symlinks) of the node.</p>
<h3 id="extension"><a class="header" href="#extension">extension</a></h3>
<p>Type: string</p>
<p>The extension of the node.</p>
<h3 id="is_symlink"><a class="header" href="#is_symlink">is_symlink</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a symlink.</p>
<h3 id="is_broken"><a class="header" href="#is_broken">is_broken</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a broken symlink.</p>
<h3 id="is_dir"><a class="header" href="#is_dir">is_dir</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a directory.</p>
<h3 id="is_file"><a class="header" href="#is_file">is_file</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a file.</p>
<h3 id="is_readonly"><a class="header" href="#is_readonly">is_readonly</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is real-only.</p>
<h3 id="mime_essence"><a class="header" href="#mime_essence">mime_essence</a></h3>
<p>Type: string</p>
<p>The mime type of the node. For e.g. <code>text/csv</code>, <code>image/jpeg</code> etc.</p>
<h3 id="size"><a class="header" href="#size">size</a></h3>
<p>Type: integer</p>
<p>The size of the exact node. The size of a directory won't be calculated
recursively.</p>
<h3 id="human_size"><a class="header" href="#human_size">human_size</a></h3>
<p>Type: string</p>
<p>Like size but in human readable format.</p>
<h3 id="permissions"><a class="header" href="#permissions">permissions</a></h3>
<p>Type: <a href="column-renderer.html#permission">Permission</a></p>
<p>The <a href="column-renderer.html#permission">permissions</a> applied to the node.</p>
<h3 id="canonical"><a class="header" href="#canonical">canonical</a></h3>
<p>Type: nullable <a href="column-renderer.html#resolved-node-metadata">Resolved Node Metadata</a></p>
<p>If the node is a symlink, it will hold information about the symlink resolved
node. Else, it will hold information the actual node. It the symlink is broken,
it will be null.</p>
<h3 id="symlink"><a class="header" href="#symlink">symlink</a></h3>
<p>Type: nullable <a href="column-renderer.html#resolved-node-metadata">Resolved Node Metadata</a></p>
<p>If the node is a symlink and is not broken, it will hold information about the
symlink resolved node. However, it will never hold information about the actual
node. It will instead be null.</p>
<h3 id="node"><a class="header" href="#node">Node</a></h3>
<p>A node contains the following fields:</p>
<ul>
<li><a href="message.html#parent">parent</a></li>
<li><a href="message.html#relative_path">relative_path</a></li>
<li><a href="message.html#absolute_path">absolute_path</a></li>
<li><a href="message.html#extension">extension</a></li>
<li><a href="message.html#is_symlink">is_symlink</a></li>
<li><a href="message.html#is_broken">is_broken</a></li>
<li><a href="message.html#is_dir">is_dir</a></li>
<li><a href="message.html#is_file">is_file</a></li>
<li><a href="message.html#is_readonly">is_readonly</a></li>
<li><a href="message.html#mime_essence">mime_essence</a></li>
<li><a href="message.html#size">size</a></li>
<li><a href="message.html#human_size">human_size</a></li>
<li><a href="message.html#permissions">permissions</a></li>
<li><a href="message.html#canonical">canonical</a></li>
<li><a href="message.html#symlink">symlink</a></li>
</ul>
<h3 id="directorybuffer"><a class="header" href="#directorybuffer">DirectoryBuffer</a></h3>
<p>Directory buffer contains the following fields:</p>
<ul>
<li><a href="message.html#parent">parent</a></li>
<li><a href="message.html#nodes">nodes</a></li>
<li><a href="message.html#total">total</a></li>
<li><a href="message.html#focus">focus</a></li>
</ul>
<h4 id="parent-1"><a class="header" href="#parent-1">parent</a></h4>
<p>Type: string</p>
<p>The parent path of the node.</p>
<h4 id="nodes"><a class="header" href="#nodes">nodes</a></h4>
<p>Type: list of <a href="message.html#node">Node</a>s</p>
<p>A list of visible nodes.</p>
<h4 id="total"><a class="header" href="#total">total</a></h4>
<p>Type: int</p>
<p>The count of nodes being rendered.</p>
<h4 id="focus"><a class="header" href="#focus">focus</a></h4>
<p>Type: int</p>
<p>The index of the node under focus. It can be <code>0</code> even when there's no node to
focus on.</p>
<h3 id="history-1"><a class="header" href="#history-1">History</a></h3>
<p>History contains the following fields:</p>
<ul>
<li><a href="message.html#loc">loc</a></li>
<li><a href="message.html#paths">paths</a></li>
</ul>
<h4 id="loc"><a class="header" href="#loc">loc</a></h4>
<p>Type: int</p>
<p>Location of the current path in history.</p>
<h4 id="paths"><a class="header" href="#paths">paths</a></h4>
<p>Type: list of string</p>
<p>Visited paths.</p>
<h3 id="example-using-lua-function-calls"><a class="header" href="#example-using-lua-function-calls">Example: Using Lua Function Calls</a></h3>
<pre><code class="language-lua">-- Define the function
xplr.fn.custom.ask_name_and_greet = function(app)
print(&quot;What's your name?&quot;)
local name = io.read()
local greeting = &quot;Hello &quot; .. name .. &quot;!&quot;
local message = greeting .. &quot; You are inside &quot; .. app.pwd
return {
{ LogSuccess = message },
}
end
-- Map the function to a key (space)
xplr.config.modes.builtin.default.key_bindings.on_key.space = {
help = &quot;ask name and greet&quot;,
messages = {
{ CallLua = &quot;custom.ask_name_and_greet&quot; }
}
}
-- Now, when you press &quot;space&quot; in default mode, you will be prompted for your
-- name. Enter your name to receive a nice greeting and to know your location.
</code></pre>
<h2 id="environment-variables-and-pipes"><a class="header" href="#environment-variables-and-pipes">Environment Variables and Pipes</a></h2>
<p>Alternative to <code>CallLua</code>, <code>CallLuaSilently</code> messages that call Lua functions,
there are <code>Call</code>, <code>CallSilently</code>, <code>BashExec</code>, <code>BashExecSilently</code> messages
that call shell commands.</p>
<p>However, unlike the Lua functions, these shell commands have to read the useful
information and send messages via environment variables and temporary files
called &quot;pipe&quot;s. These environment variables and files are only available when
a command is being executed.</p>
<p>Visit the <a href="modes.html#tutorial-adding-a-new-mode"><strong>fzf integration tutorial</strong></a>
for example.</p>
<h3 id="environment-variables"><a class="header" href="#environment-variables">Environment variables</a></h3>
<p>To see the environment variables, invoke the shell by typing <code>:!</code> in default
mode and run the following command:</p>
<pre><code>env | grep ^XPLR_
</code></pre>
<p>You will see something like:</p>
<pre><code>XPLR_FOCUS_INDEX=0
XPLR_MODE=action to
XPLR_PIPE_SELECTION_OUT=/run/user/1000/xplr/session/122278/pipe/selection_out
XPLR_INPUT_BUFFER=
XPLR_PIPE_GLOBAL_HELP_MENU_OUT=/run/user/1000/xplr/session/122278/pipe/global_help_menu_out
XPLR_PID=122278
XPLR_PIPE_MSG_IN=/run/user/1000/xplr/session/122278/pipe/msg_in
XPLR_PIPE_LOGS_OUT=/run/user/1000/xplr/session/122278/pipe/logs_out
XPLR_PIPE_RESULT_OUT=/run/user/1000/xplr/session/122278/pipe/result_out
XPLR_PIPE_HISTORY_OUT=/run/user/1000/xplr/session/122278/pipe/history_out
XPLR_FOCUS_PATH=/home/sayanarijit/Documents/GitHub/xplr/docs/en/book
XPLR_SESSION_PATH=/run/user/1000/xplr/session/122278
XPLR_APP_VERSION=0.14.3
XPLR_PIPE_DIRECTORY_NODES_OUT=/run/user/1000/xplr/session/122278/pipe/directory_nodes_out
</code></pre>
<p>The environment variables starting with <code>XPLR_PIPE_</code> are the temporary files
called &quot;pipe&quot;s.</p>
<h4 id="input-pipe"><a class="header" href="#input-pipe">Input pipe</a></h4>
<p>Current there is only one input pipe.</p>
<ul>
<li><a href="message.html#xplr_pipe_msg_in">XPLR_PIPE_MSG_IN</a></li>
</ul>
<h4 id="output-pipes"><a class="header" href="#output-pipes">Output pipes</a></h4>
<p><code>XPLR_PIPE_*_OUT</code> are the output pipes that contain data which cannot be
exposed directly via environment variables, like multi-line string.</p>
<ul>
<li><a href="message.html#xplr_pipe_selection_out">XPLR_PIPE_SELECTION_OUT</a></li>
<li><a href="message.html#xplr_pipe_global_help_menu_out">XPLR_PIPE_GLOBAL_HELP_MENU_OUT</a></li>
<li><a href="message.html#xplr_pipe_logs_out">XPLR_PIPE_LOGS_OUT</a></li>
<li><a href="message.html#xplr_pipe_result_out">XPLR_PIPE_RESULT_OUT</a></li>
<li><a href="message.html#xplr_pipe_history_out">XPLR_PIPE_HISTORY_OUT</a></li>
<li><a href="message.html#xplr_pipe_directory_nodes_out">XPLR_PIPE_DIRECTORY_NODES_OUT</a></li>
</ul>
<h4 id="xplr_pipe_msg_in"><a class="header" href="#xplr_pipe_msg_in">XPLR_PIPE_MSG_IN</a></h4>
<p>Append new-line delimited messages to this pipe in <a href="https://www.yaml.org">YAML</a>
(or <a href="https://www.json.org">JSON</a>) syntax. These messages will be read and
handled by xplr after the command execution.</p>
<h4 id="xplr_pipe_selection_out"><a class="header" href="#xplr_pipe_selection_out">XPLR_PIPE_SELECTION_OUT</a></h4>
<p>New-line delimited list of selected paths.</p>
<h4 id="xplr_pipe_global_help_menu_out"><a class="header" href="#xplr_pipe_global_help_menu_out">XPLR_PIPE_GLOBAL_HELP_MENU_OUT</a></h4>
<p>The full help menu.</p>
<h4 id="xplr_pipe_logs_out"><a class="header" href="#xplr_pipe_logs_out">XPLR_PIPE_LOGS_OUT</a></h4>
<p>New-line delimited list of logs.</p>
<h4 id="xplr_pipe_result_out"><a class="header" href="#xplr_pipe_result_out">XPLR_PIPE_RESULT_OUT</a></h4>
<p>New-line delimited result (selected paths if any, else the focused path)</p>
<h4 id="xplr_pipe_history_out"><a class="header" href="#xplr_pipe_history_out">XPLR_PIPE_HISTORY_OUT</a></h4>
<p>New-line delimited list of last visited paths (similar to jump list in vim).</p>
<h4 id="xplr_pipe_directory_nodes_out"><a class="header" href="#xplr_pipe_directory_nodes_out">XPLR_PIPE_DIRECTORY_NODES_OUT</a></h4>
<p>New-line delimited list of paths, filtered and sorted as displayed in the
<a href="layouts.html#table">files table</a>.</p>
<h3 id="example-using-environment-variables-and-pipes"><a class="header" href="#example-using-environment-variables-and-pipes">Example: Using Environment Variables and Pipes</a></h3>
<pre><code class="language-lua">xplr.config.modes.builtin.default.key_bindings.on_key.space = {
help = &quot;ask name and greet&quot;,
messages = {
{
BashExec = [===[
echo &quot;What's your name?&quot;
read name
greeting=&quot;Hello $name!&quot;
message=&quot;$greeting You are inside $PWD&quot;
echo LogSuccess: '&quot;'$message'&quot;' &gt;&gt; &quot;${XPLR_PIPE_MSG_IN:?}&quot;
]===]
}
}
}
-- Now, when you press &quot;space&quot; in default mode, you will be prompted for your
-- name. Enter your name to receive a nice greeting and to know your location.
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="layouts"><a class="header" href="#layouts">Layouts</a></h1>
<h4 id="example-defining-custom-layout"><a class="header" href="#example-defining-custom-layout">Example: Defining Custom Layout</a></h4>
<p><a href="https://gifyu.com/image/1X38"><img src="https://s6.gifyu.com/images/layout.png" alt="layout.png" /></a></p>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
Horizontal = {
config = {
margin = 1,
horizontal_margin = 2,
vertical_margin = 3,
constraints = {
{ Percentage = 50 },
{ Percentage = 50 },
}
},
splits = {
&quot;Table&quot;,
&quot;HelpMenu&quot;,
}
}
}
</code></pre>
<p>xplr layouts define the structure of the UI, i.e. how many panel we see,
placement and size of the panels, how they look etc.</p>
<p>This is configuration exposed via the <code>xplr.config.layouts</code> API. It contains
the following fields:</p>
<ul>
<li><a href="layouts.html#builtin">builtin</a></li>
<li><a href="layouts.html#custom">custom</a></li>
</ul>
<p>The users can switch between these layouts at run-time.</p>
<h2 id="builtin-1"><a class="header" href="#builtin-1">builtin</a></h2>
<p>Type: mapping of string and <a href="layouts.html#layout">Layout</a></p>
<p>This is exposed by the <code>xplr.config.layouts.builtin</code> API.</p>
<p>xplr by default provides the following builtin layouts:</p>
<ul>
<li><a href="layouts.html#default">default</a></li>
<li><a href="layouts.html#no_help">no_help</a></li>
<li><a href="layouts.html#no_selection">no_selection</a></li>
<li><a href="layouts.html#no_help_no_selection">no_help_no_selection</a></li>
</ul>
<h3 id="default-1"><a class="header" href="#default-1">default</a></h3>
<p>Type: <a href="layouts.html#layout">Layout</a></p>
<p>This is the default layout we see when we run xplr.</p>
<h3 id="no_help"><a class="header" href="#no_help">no_help</a></h3>
<p>Type: <a href="layouts.html#layout">Layout</a></p>
<p>This layout hides the help menu.</p>
<h3 id="no_selection"><a class="header" href="#no_selection">no_selection</a></h3>
<p>Type: <a href="layouts.html#layout">Layout</a></p>
<p>This layout hides the selection panel.</p>
<h3 id="no_help_no_selection"><a class="header" href="#no_help_no_selection">no_help_no_selection</a></h3>
<p>Type: <a href="layouts.html#layout">Layout</a></p>
<p>This layout hides both the help menu and the selection panel.</p>
<h2 id="custom-1"><a class="header" href="#custom-1">custom</a></h2>
<p>Type: mapping of string and <a href="layouts.html#layout">Layout</a></p>
<p>This is exposed by the <code>xplr.config.layouts.custom</code> API.</p>
<p>It allows the users to define any custom layout.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.layouts.custom.example = &quot;Nothing&quot;
xplr.config.general.initial_layout = &quot;example&quot;
-- when you load xplr, you should see a blank screen
</code></pre>
<h2 id="layout-2"><a class="header" href="#layout-2">Layout</a></h2>
<p>A layout can be one of the following:</p>
<ul>
<li><a href="layouts.html#nothing">&quot;Nothing&quot;</a></li>
<li><a href="layouts.html#table">&quot;Table&quot;</a></li>
<li><a href="layouts.html#inputandlogs">&quot;InputAndLogs&quot;</a></li>
<li><a href="layouts.html#selection">&quot;Selection&quot;</a></li>
<li><a href="layouts.html#helpmenu">&quot;HelpMenu&quot;</a></li>
<li><a href="layouts.html#sortandfilter">&quot;SortAndFilter&quot;</a></li>
<li>{ <a href="layouts.html#custom-content">CustomContent</a> = { <a href="layouts.html#title">title</a>, <a href="layouts.html#body">body</a> }</li>
<li>{ <a href="layouts.html#horizontal">Horizontal</a> = { <a href="layouts.html#layout-config">config</a>, <a href="layouts.html#splits">splits</a> }</li>
<li>{ <a href="layouts.html#vertical">Vertical</a> = { <a href="layouts.html#layout-config">config</a>, <a href="layouts.html#splits">splits</a> }</li>
</ul>
<h3 id="nothing"><a class="header" href="#nothing">Nothing</a></h3>
<p>This layout contains a blank panel.</p>
<h3 id="table"><a class="header" href="#table">Table</a></h3>
<p>This layout contains the table displaying the files and directories in the
current directory.</p>
<h3 id="inputandlogs"><a class="header" href="#inputandlogs">InputAndLogs</a></h3>
<p>This layout contains the panel displaying the input prompt and logs.</p>
<h3 id="selection-1"><a class="header" href="#selection-1">Selection</a></h3>
<p>This layout contains the panel displaying the selected paths.</p>
<h3 id="helpmenu"><a class="header" href="#helpmenu">HelpMenu</a></h3>
<p>This layout contains the panel displaying the help menu for the current mode in
real-time.</p>
<h3 id="sortandfilter"><a class="header" href="#sortandfilter">SortAndFilter</a></h3>
<p>This layout contains the panel displaying the pipeline of sorters and filters
applied of the list of paths being displayed.</p>
<h3 id="horizontal"><a class="header" href="#horizontal">Horizontal</a></h3>
<p>This is a special layout that splits the panel into two horizontal parts.</p>
<p>It contains the following information:</p>
<ul>
<li><a href="layouts.html#layout-config">config</a></li>
<li><a href="layouts.html#splits">splits</a></li>
</ul>
<h3 id="vertical"><a class="header" href="#vertical">Vertical</a></h3>
<p>This is a special layout that splits the panel into two vertical parts.</p>
<p>It contains the following information:</p>
<ul>
<li><a href="layouts.html#layout-config">config</a></li>
<li><a href="layouts.html#splits">splits</a></li>
</ul>
<h2 id="layout-config"><a class="header" href="#layout-config">Layout Config</a></h2>
<p>A layout config contains the following information:</p>
<ul>
<li><a href="layouts.html#margin">margin</a></li>
<li><a href="layouts.html#horizontal_margin">horizontal_margin</a></li>
<li><a href="layouts.html#vertical_margin">vertical_margin</a></li>
<li><a href="layouts.html#constraints">constraints</a></li>
</ul>
<h3 id="margin"><a class="header" href="#margin">margin</a></h3>
<p>Type: nullable integer</p>
<p>The width of the margin in all direction.</p>
<h3 id="horizontal_margin"><a class="header" href="#horizontal_margin">horizontal_Margin</a></h3>
<p>Type: nullable integer</p>
<p>The width of the horizontal margins. Overwrites the <a href="layouts.html#margin">margin</a> value.</p>
<h3 id="vertical_margin"><a class="header" href="#vertical_margin">vertical_Margin</a></h3>
<p>Type: nullable integer</p>
<p>The width of the vertical margins. Overwrites the <a href="layouts.html#margin">margin</a> value.</p>
<h3 id="constraints"><a class="header" href="#constraints">constraints</a></h3>
<p>Type: nullable list of <a href="layouts.html#constraint">Constraint</a></p>
<p>The constraints applied on the layout.</p>
<h2 id="constraint"><a class="header" href="#constraint">Constraint</a></h2>
<p>A constraint can be one of the following:</p>
<ul>
<li>{ Percentage = int }</li>
<li>{ Ratio = { int, int } }</li>
<li>{ Length = { int }</li>
<li>{ LengthLessThanScreenHeight = int }</li>
<li>{ LengthLessThanScreenWidth = int }</li>
<li>{ LengthLessThanLayoutHeight = int }</li>
<li>{ LengthLessThanLayoutWidth = int }</li>
<li>{ Max = int }</li>
<li>{ MaxLessThanScreenHeight = int }</li>
<li>{ MaxLessThanScreenWidth = int }</li>
<li>{ MaxLessThanLayoutHeight = int }</li>
<li>{ MaxthLessThanLayoutWidth = int }</li>
<li>{ Min = int }</li>
<li>{ MinLessThanScreenHeight = int }</li>
<li>{ MinLessThanScreenWidth = int }</li>
<li>{ MinLessThanLayoutHeight = int }</li>
<li>{ MinLessThanLayoutWidth = int }</li>
</ul>
<p>TODO: document each constraint.</p>
<h2 id="splits"><a class="header" href="#splits">splits</a></h2>
<p>Type: list of <a href="layouts.html#layout">Layout</a></p>
<p>The list of child layouts to fit into the parent layout.</p>
<h2 id="custom-content"><a class="header" href="#custom-content">Custom Content</a></h2>
<p>Custom content is a special layout to render something custom.
It contains the following information:</p>
<ul>
<li><a href="layouts.html#title">title</a></li>
<li><a href="layouts.html#body">body</a></li>
</ul>
<h3 id="title"><a class="header" href="#title">title</a></h3>
<p>Type: nullable string</p>
<p>The title of the panel.</p>
<h3 id="body"><a class="header" href="#body">body</a></h3>
<p>Type: <a href="layouts.html#content-body">Content Body</a></p>
<p>The body of the panel.</p>
<h2 id="content-body"><a class="header" href="#content-body">Content Body</a></h2>
<p>Content body can be one of the following:</p>
<ul>
<li><a href="layouts.html#static-paragraph">StaticParagraph</a></li>
<li><a href="layouts.html#dynamic-paragraph">DynamicParagraph</a></li>
<li><a href="layouts.html#static-list">StaticList</a></li>
<li><a href="layouts.html#dynamic-list">DynamicList</a></li>
<li><a href="layouts.html#static-table">StaticTable</a></li>
<li><a href="layouts.html#dynamic-table">DynamicTable</a></li>
</ul>
<h3 id="static-paragraph"><a class="header" href="#static-paragraph">Static Paragraph</a></h3>
<p>A paragraph to render. It contains the following fields:</p>
<ul>
<li><strong>render</strong> (string): The string to render.</li>
</ul>
<h4 id="example-render-a-custom-static-paragraph"><a class="header" href="#example-render-a-custom-static-paragraph">Example: Render a custom static paragraph</a></h4>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
CustomContent = {
title = &quot;custom title&quot;,
body = {
StaticParagraph = { render = &quot;custom body&quot; },
},
},
}
</code></pre>
<h3 id="dynamic-paragraph"><a class="header" href="#dynamic-paragraph">Dynamic Paragraph</a></h3>
<p>A <a href="layouts.html#content-renderer">Lua function</a> to render a custom paragraph.
It contains the following fields:</p>
<ul>
<li><strong>render</strong> (string): The <a href="layouts.html#content-renderer">lua function</a> that returns the paragraph to
render.</li>
</ul>
<h4 id="example-render-a-custom-dynamic-paragraph"><a class="header" href="#example-render-a-custom-dynamic-paragraph">Example: Render a custom dynamic paragraph</a></h4>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
CustomContent = {
title = &quot;custom title&quot;,
body = { DynamicParagraph = { render = &quot;custom.render_layout&quot; } },
},
}
xplr.fn.custom.render_layout = function(ctx)
return ctx.app.pwd
end
</code></pre>
<h3 id="static-list"><a class="header" href="#static-list">Static List</a></h3>
<p>A list to render. It contains the following fields:</p>
<ul>
<li><strong>render</strong> (list of string): The list to render.</li>
</ul>
<h4 id="example-render-a-custom-static-list"><a class="header" href="#example-render-a-custom-static-list">Example: Render a custom static list</a></h4>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
CustomContent = {
title = &quot;custom title&quot;,
body = {
StaticList = { render = { &quot;1&quot;, &quot;2&quot;, &quot;3&quot; } },
},
},
}
</code></pre>
<h3 id="dynamic-list"><a class="header" href="#dynamic-list">Dynamic List</a></h3>
<p>A <a href="layouts.html#content-renderer">Lua function</a> to render a custom list.
It contains the following fields:</p>
<ul>
<li><strong>render</strong> (string): The <a href="layouts.html#content-renderer">lua function</a> that returns the list to render.</li>
</ul>
<h4 id="example-render-a-custom-dynamic-list"><a class="header" href="#example-render-a-custom-dynamic-list">Example: Render a custom dynamic list</a></h4>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
CustomContent = {
title = &quot;custom title&quot;,
body = { DynamicList = { render = &quot;custom.render_layout&quot; } },
},
}
xplr.fn.custom.render_layout = function(ctx)
return ctx.app.history.paths
end
</code></pre>
<h3 id="static-table"><a class="header" href="#static-table">Static Table</a></h3>
<p>A table to render. It contains the following fields:</p>
<ul>
<li><strong>widths</strong> (list of <a href="layouts.html#constraint">Constraint</a>): Width of the columns.</li>
<li><strong>col_spacing</strong> (nullable int): Spacing between columns. Defaults to 1.</li>
<li><strong>render</strong> (list of list of string): The rows and columns to render.</li>
</ul>
<h4 id="example-render-a-custom-static-table"><a class="header" href="#example-render-a-custom-static-table">Example: Render a custom static table</a></h4>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
CustomContent = {
title = &quot;custom title&quot;,
body = {
StaticTable = {
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
col_spacing = 1,
render = {
{ &quot;a&quot;, &quot;b&quot; },
{ &quot;c&quot;, &quot;d&quot; },
},
},
},
},
}
</code></pre>
<h3 id="dynamic-table"><a class="header" href="#dynamic-table">Dynamic Table</a></h3>
<p>A <a href="layouts.html#content-renderer">Lua function</a> to render a custom table.
It contains the following fields:</p>
<ul>
<li><strong>widths</strong> (list of <a href="layouts.html#constraint">Constraint</a>): Width of the columns.</li>
<li><strong>col_spacing</strong> (nullable int): Spacing between columns. Defaults to 1.</li>
<li><strong>render</strong> (string): The <a href="layouts.html#content-renderer">lua function</a> that returns the table to render.</li>
</ul>
<h4 id="example-render-a-custom-dynamic-table"><a class="header" href="#example-render-a-custom-dynamic-table">Example: Render a custom dynamic table</a></h4>
<pre><code class="language-lua">xplr.config.layouts.builtin.default = {
CustomContent = {
title = &quot;custom title&quot;,
body = {
DynamicTable = {
widths = {
{ Percentage = 50 },
{ Percentage = 50 },
},
col_spacing = 1,
render = &quot;custom.render_layout&quot;,
},
},
},
}
xplr.fn.custom.render_layout = function(ctx)
return {
{ &quot;&quot;, &quot;&quot; },
{ &quot;Layout height&quot;, tostring(ctx.layout_size.height) },
{ &quot;Layout width&quot;, tostring(ctx.layout_size.width) },
{ &quot;&quot;, &quot;&quot; },
{ &quot;Screen height&quot;, tostring(ctx.screen_size.height) },
{ &quot;Screen width&quot;, tostring(ctx.screen_size.width) },
}
end
</code></pre>
<h2 id="content-renderer"><a class="header" href="#content-renderer">Content Renderer</a></h2>
<p>It is a Lua function that receives <a href="layouts.html#content-renderer-argument">a special argument</a> as input and
returns some output that can be rendered in the UI. It is used to render
content body for the custom dynamic layouts.</p>
<h2 id="content-renderer-argument"><a class="header" href="#content-renderer-argument">Content Renderer Argument</a></h2>
<p>It contains the following information:</p>
<ul>
<li><a href="layouts.html#size">layout_size</a></li>
<li><a href="layouts.html#size">screen_size</a></li>
<li><a href="message.html#calllua-argument">app</a></li>
</ul>
<h2 id="size-1"><a class="header" href="#size-1">Size</a></h2>
<p>It contains the following information:</p>
<ul>
<li>x</li>
<li>y</li>
<li>height</li>
<li>width</li>
</ul>
<p>Every field is of integer type.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="node-types"><a class="header" href="#node-types">Node Types</a></h1>
<p>This configuration defines how to deal with different kinds of nodes (files,
directories, symlinks etc.) in a directory.</p>
<p>This can be configured using the <code>xplr.config.node_types</code> Lua API.</p>
<p>It contains the following fields:</p>
<ul>
<li><a href="node_types.html#directory">directory</a></li>
<li><a href="node_types.html#file">file</a></li>
<li><a href="node_types.html#symlink">symlink</a></li>
<li><a href="node_types.html#mime_essence">mime_essence</a></li>
<li><a href="node_types.html#extension">extension</a></li>
<li><a href="node_types.html#special">special</a></li>
</ul>
<p>One node can fall into multiple categories. For example, a node can have the
extension <code>md</code>, and be a <code>file</code>. In that case, the properties from the more
specific category i.e. extension will be used.</p>
<p>The priority is:</p>
<p><strong>special</strong> &gt; <strong>extension</strong> &gt; <strong>mime_essence</strong> &gt; <strong>symlink</strong> &gt; <strong>file</strong> &gt; <strong>directory</strong></p>
<h3 id="directory"><a class="header" href="#directory">directory</a></h3>
<p>Type: <a href="node_types.html#nodetype-config">NodeType Config</a></p>
<p>Properties related to directories are defined here.</p>
<p>Contains the following fields:</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.directory.meta.icon = &quot;&quot;
xplr.config.node_types.directory.style.add_modifiers = { &quot;Bold&quot; }
</code></pre>
<h3 id="file"><a class="header" href="#file">file</a></h3>
<p>Type: <a href="node_types.html#nodetype-config">NodeType Config</a></p>
<p>Properties related to regular files are defined here.</p>
<p>Contains the following fields:</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.file.meta.icon = &quot;&quot;
xplr.config.node_types.file.style.fg = &quot;White&quot;
</code></pre>
<h3 id="symlink-1"><a class="header" href="#symlink-1">symlink</a></h3>
<p>Type: <a href="node_types.html#nodetype-config">NodeType Config</a></p>
<p>Properties related to symlink are defined here.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.symlink.meta.icon = &quot;&quot;
xplr.config.node_types.symlink.style.add_modifiers = { &quot;Italic&quot; }
</code></pre>
<h3 id="mime_essence-1"><a class="header" href="#mime_essence-1">mime_essence</a></h3>
<p>Type: mapping of mime-type and mapping of mime-subtype and <a href="node_types.html#nodetype-config">NodeType Config</a></p>
<p>Properties related to files with specific mime types are defined here.</p>
<p>It is possible to use the wildcard <code>*</code> to match all mime subtypes. It will be
overwritten by the more specific sub types that are defined.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.mime_essence = {
application = {
-- application/*
[&quot;*&quot;] = { meta = { icon = &quot;a&quot; } }
-- application/pdf
pdf = { meta = { icon = &quot;&quot; } },
-- application/zip
zip = { meta = { icon = &quot;&quot;} },
},
}
</code></pre>
<h3 id="extension-1"><a class="header" href="#extension-1">extension</a></h3>
<p>Type: mapping of extension and <a href="node_types.html#nodetype-config">NodeType Config</a></p>
<p>Properties related to files with specific extension are defined here.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.extension.md = { meta = { icon = &quot;&quot; } }
xplr.config.node_types.extension.rs = { meta = { icon = &quot;🦀&quot; } }
</code></pre>
<h3 id="special"><a class="header" href="#special">special</a></h3>
<p>Type: mapping of name and <a href="node_types.html#nodetype-config">NodeType Config</a></p>
<p>Properties related to files and directories with special names are defined
here.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.special[&quot;Cargo.toml&quot;] = { meta = { icon = &quot;&quot; } }
xplr.config.node_types.special[&quot;Downloads&quot;] = { meta = { icon = &quot;&quot; } }
</code></pre>
<h2 id="nodetype-config"><a class="header" href="#nodetype-config">NodeType Config</a></h2>
<p>A node-type config contains the following fields:</p>
<ul>
<li><a href="node_types.html#meta">meta</a></li>
<li><a href="style.html">style</a></li>
</ul>
<h3 id="meta"><a class="header" href="#meta">meta</a></h3>
<p>Type: mapping of string and string</p>
<p>A meta field can contain custom metadata about a node. By default, the &quot;icon&quot;
metadata is set for the <a href="node_types.html#directory">directory</a>, <a href="node_types.html#file">file</a>, and
<a href="node_types.html#symlink">symlink</a> nodes.</p>
<p>Example:</p>
<pre><code class="language-lua">xplr.config.node_types.file = {
meta = {
icon = &quot;f&quot;,
foo = &quot;bar&quot;,
}
}
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="style"><a class="header" href="#style">Style</a></h1>
<p>A style object contains the following information:</p>
<ul>
<li><a href="style.html#fg">fg</a></li>
<li><a href="style.html#bg">bg</a></li>
<li><a href="style.html#add_modifiers">add_modifiers</a></li>
<li><a href="style.html#sub_modifiers">sub_modifiers</a></li>
</ul>
<h3 id="fg"><a class="header" href="#fg">fg</a></h3>
<p>Type: nullable <a href="style.html#color">Color</a></p>
<p>The foreground color.</p>
<h3 id="bg"><a class="header" href="#bg">bg</a></h3>
<p>Type: nullable <a href="style.html#color">Color</a></p>
<p>The background color.</p>
<h3 id="add_modifiers"><a class="header" href="#add_modifiers">add_modifiers</a></h3>
<p>Type: nullable list of <a href="style.html#modifier">Modifier</a></p>
<p>Modifiers to add.</p>
<h3 id="sub_modifiers"><a class="header" href="#sub_modifiers">sub_modifiers</a></h3>
<p>Type: nullable list of <a href="style.html#modifier">Modifier</a></p>
<p>Modifiers to remove.</p>
<h2 id="color"><a class="header" href="#color">Color</a></h2>
<p>Color can be one of the following:</p>
<ul>
<li>&quot;Reset&quot;</li>
<li>&quot;Black&quot;</li>
<li>&quot;Red&quot;</li>
<li>&quot;Green&quot;</li>
<li>&quot;Yellow&quot;</li>
<li>&quot;Blue&quot;</li>
<li>&quot;Magenta&quot;</li>
<li>&quot;Cyan&quot;</li>
<li>&quot;Gray&quot;</li>
<li>&quot;DarkGray&quot;</li>
<li>&quot;LightRed&quot;</li>
<li>&quot;LightGreen&quot;</li>
<li>&quot;LightYellow&quot;</li>
<li>&quot;LightBlue&quot;</li>
<li>&quot;LightMagenta&quot;</li>
<li>&quot;LightCyan&quot;</li>
<li>&quot;White&quot;</li>
<li>{ Rgb = { int, int, int } }</li>
<li>{ Indexed = int }</li>
</ul>
<h2 id="modifier"><a class="header" href="#modifier">Modifier</a></h2>
<p>Modifier can be one of the following:</p>
<ul>
<li>&quot;Bold&quot;</li>
<li>&quot;Dim&quot;</li>
<li>&quot;Italic&quot;</li>
<li>&quot;Underlined&quot;</li>
<li>&quot;SlowBlink&quot;</li>
<li>&quot;RapidBlink&quot;</li>
<li>&quot;Reversed&quot;</li>
<li>&quot;Hidden&quot;</li>
<li>&quot;CrossedOut&quot;</li>
</ul>
<h2 id="example"><a class="header" href="#example">Example</a></h2>
<pre><code class="language-lua">xplr.config.general.cursor.style.fg = &quot;Red&quot;
xplr.config.general.cursor.style.bg = { Rgb = { 100, 150, 200 } }
xplr.config.general.cursor.style.add_modifiers = { &quot;Bold&quot;, &quot;Italic&quot; }
xplr.config.general.cursor.style.sub_modifiers = { &quot;Hidden&quot; }
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="sorting"><a class="header" href="#sorting">Sorting</a></h1>
<p>xplr supports sorting paths by different properties. The sorting mechanism
works like a pipeline, which in visible in the <code>Sort &amp; filter</code> panel.</p>
<p>Example:</p>
<pre><code>size↑ [i]rel↓ [c]dir↑ [c]file↑ sym↑
</code></pre>
<p>This line means that the nodes visible in the table will be first sorted by
it's size, then by case insensitive relative path, then by the
canonical (symlink resolved) type of the node, and finally by whether or not
the node is a symlink.</p>
<p>The arrows denote the order.</p>
<p>Each part of this pipeline is called <a href="sorting.html#node-sorter-applicable">Node Sorter Applicable</a>.</p>
<h2 id="node-sorter-applicable"><a class="header" href="#node-sorter-applicable">Node Sorter Applicable</a></h2>
<p>It contains the following information:</p>
<ul>
<li><a href="sorting.html#sorter">sorter</a></li>
<li><a href="sorting.html#reverse">reverse</a></li>
</ul>
<h3 id="sorter"><a class="header" href="#sorter">sorter</a></h3>
<p>A sorter can be one of the following:</p>
<ul>
<li>&quot;ByRelativePath&quot;</li>
<li>&quot;ByIRelativePath&quot;</li>
<li>&quot;ByExtension&quot;</li>
<li>&quot;ByIsDir&quot;</li>
<li>&quot;ByIsFile&quot;</li>
<li>&quot;ByIsSymlink&quot;</li>
<li>&quot;ByIsBroken&quot;</li>
<li>&quot;ByIsReadonly&quot;</li>
<li>&quot;ByMimeEssence&quot;</li>
<li>&quot;BySize&quot;</li>
<li>&quot;ByCanonicalAbsolutePath&quot;</li>
<li>&quot;ByICanonicalAbsolutePath&quot;</li>
<li>&quot;ByCanonicalExtension&quot;</li>
<li>&quot;ByCanonicalIsDir&quot;</li>
<li>&quot;ByCanonicalIsFile&quot;</li>
<li>&quot;ByCanonicalIsReadonly&quot;</li>
<li>&quot;ByCanonicalMimeEssence&quot;</li>
<li>&quot;ByCanonicalSize&quot;</li>
<li>&quot;BySymlinkAbsolutePath&quot;</li>
<li>&quot;ByISymlinkAbsolutePath&quot;</li>
<li>&quot;BySymlinkExtension&quot;</li>
<li>&quot;BySymlinkIsDir&quot;</li>
<li>&quot;BySymlinkIsFile&quot;</li>
<li>&quot;BySymlinkIsReadonly&quot;</li>
<li>&quot;BySymlinkMimeEssence&quot;</li>
<li>&quot;BySymlinkSize&quot;</li>
</ul>
<p>TODO: document each</p>
<h3 id="reverse"><a class="header" href="#reverse">reverse</a></h3>
<p>Type: boolean</p>
<p>It defined the direction of the order.</p>
<h2 id="example-1"><a class="header" href="#example-1">Example</a></h2>
<pre><code class="language-lua">xplr.config.general.initial_sorting = {
{ sorter = &quot;ByCanonicalIsDir&quot;, reverse = true },
{ sorter = &quot;ByIRelativePath&quot;, reverse = false },
}
</code></pre>
<p>This snippet defines the initial sorting logic to be applied when xplr loads.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="filtering"><a class="header" href="#filtering">Filtering</a></h1>
<p>xplr supports filtering paths by different properties. The filtering mechanism
works like a pipeline, which in visible in the <code>Sort &amp; filter</code> panel.</p>
<p>Example:</p>
<pre><code>rel!^. [i]abs=~abc [i]rel!~xyz
</code></pre>
<p>This line means that the nodes visible on the table will first be filtered by
the condition: <em>relative path does not start with <code>.</code></em>, then by the condition:
<em>absolute path contains <code>abc</code> (case insensitive)</em>, and finally by the
condition: <em>relative path does not contain <code>xyz</code></em> (case insensitive).</p>
<p>Each part of this pipeline is called <a href="filtering.html#node-filter-applicable">Node Filter Applicable</a>.</p>
<h2 id="node-filter-applicable"><a class="header" href="#node-filter-applicable">Node Filter Applicable</a></h2>
<p>It contains the following information:</p>
<ul>
<li><a href="filtering.html#filter">filter</a></li>
<li><a href="filtering.html#input">input</a></li>
</ul>
<h3 id="filter"><a class="header" href="#filter">filter</a></h3>
<p>A filter can be one of the following:</p>
<ul>
<li>&quot;RelativePathIs&quot;</li>
<li>&quot;RelativePathIsNot&quot;</li>
<li>&quot;IRelativePathIs&quot;</li>
<li>&quot;IRelativePathIsNot&quot;</li>
<li>&quot;RelativePathDoesStartWith&quot;</li>
<li>&quot;RelativePathDoesNotStartWith&quot;</li>
<li>&quot;IRelativePathDoesStartWith&quot;</li>
<li>&quot;IRelativePathDoesNotStartWith&quot;</li>
<li>&quot;RelativePathDoesContain&quot;</li>
<li>&quot;RelativePathDoesNotContain&quot;</li>
<li>&quot;IRelativePathDoesContain&quot;</li>
<li>&quot;IRelativePathDoesNotContain&quot;</li>
<li>&quot;RelativePathDoesEndWith&quot;</li>
<li>&quot;RelativePathDoesNotEndWith&quot;</li>
<li>&quot;IRelativePathDoesEndWith&quot;</li>
<li>&quot;IRelativePathDoesNotEndWith&quot;</li>
<li>&quot;AbsolutePathIs&quot;</li>
<li>&quot;AbsolutePathIsNot&quot;</li>
<li>&quot;IAbsolutePathIs&quot;</li>
<li>&quot;IAbsolutePathIsNot&quot;</li>
<li>&quot;AbsolutePathDoesStartWith&quot;</li>
<li>&quot;AbsolutePathDoesNotStartWith&quot;</li>
<li>&quot;IAbsolutePathDoesStartWith&quot;</li>
<li>&quot;IAbsolutePathDoesNotStartWith&quot;</li>
<li>&quot;AbsolutePathDoesContain&quot;</li>
<li>&quot;AbsolutePathDoesNotContain&quot;</li>
<li>&quot;IAbsolutePathDoesContain&quot;</li>
<li>&quot;IAbsolutePathDoesNotContain&quot;</li>
<li>&quot;AbsolutePathDoesEndWith&quot;</li>
<li>&quot;AbsolutePathDoesNotEndWith&quot;</li>
<li>&quot;IAbsolutePathDoesEndWith&quot;</li>
<li>&quot;IAbsolutePathDoesNotEndWith&quot;</li>
</ul>
<p>TODO: document each</p>
<h3 id="input"><a class="header" href="#input">input</a></h3>
<p>Type: string</p>
<p>The input for the condition.</p>
<h2 id="example-2"><a class="header" href="#example-2">Example:</a></h2>
<pre><code class="language-lua">ToggleNodeFilter = {
filter = &quot;RelativePathDoesNotStartWith&quot;,
input = &quot;.&quot;
}
</code></pre>
<p>Here, <code>ToggleNodeFilter</code> is a <a href="message.html">message</a> that adds or removes
(toggles) the filter applied.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="column-renderer"><a class="header" href="#column-renderer">Column Renderer</a></h1>
<p>A column renderer is a Lua function that receives a <a href="column-renderer.html#table-renderer-argument">special argument</a> and
returns a string that will be displayed in each specific field of the
<a href="layouts.html#table">files table</a>.</p>
<p>xplr by default provides the following column renderers:</p>
<ul>
<li><code>xplr.fn.builtin.fmt_general_table_row_cols_0</code></li>
<li><code>xplr.fn.builtin.fmt_general_table_row_cols_1</code></li>
<li><code>xplr.fn.builtin.fmt_general_table_row_cols_2</code></li>
<li><code>xplr.fn.builtin.fmt_general_table_row_cols_3</code></li>
<li><code>xplr.fn.builtin.fmt_general_table_row_cols_4</code></li>
</ul>
<p>You can either overwrite these functions, or create new functions in
<code>xplr.fn.custom</code> and point to them.</p>
<p>Terminal colors are supported.</p>
<h2 id="table-renderer-argument"><a class="header" href="#table-renderer-argument">Table Renderer Argument</a></h2>
<p>The special argument contains the following fields</p>
<ul>
<li><a href="column-renderer.html#parent">parent</a></li>
<li><a href="column-renderer.html#relative_path">relative_path</a></li>
<li><a href="column-renderer.html#absolute_path">absolute_path</a></li>
<li><a href="column-renderer.html#extension">extension</a></li>
<li><a href="column-renderer.html#is_symlink">is_symlink</a></li>
<li><a href="column-renderer.html#is_broken">is_broken</a></li>
<li><a href="column-renderer.html#is_dir">is_dir</a></li>
<li><a href="column-renderer.html#is_file">is_file</a></li>
<li><a href="column-renderer.html#is_readonly">is_readonly</a></li>
<li><a href="column-renderer.html#mime_essence">mime_essence</a></li>
<li><a href="column-renderer.html#size">size</a></li>
<li><a href="column-renderer.html#human_size">human_size</a></li>
<li><a href="column-renderer.html#permissions">permissions</a></li>
<li><a href="column-renderer.html#canonical">canonical</a></li>
<li><a href="column-renderer.html#symlink">symlink</a></li>
<li><a href="column-renderer.html#index">index</a></li>
<li><a href="column-renderer.html#relative_index">relative_index</a></li>
<li><a href="column-renderer.html#is_before_focus">is_before_focus</a></li>
<li><a href="column-renderer.html#is_after_focus">is_after_focus</a></li>
<li><a href="column-renderer.html#tree">tree</a></li>
<li><a href="column-renderer.html#prefix">prefix</a></li>
<li><a href="column-renderer.html#suffix">suffix</a></li>
<li><a href="column-renderer.html#is_selected">is_selected</a></li>
<li><a href="column-renderer.html#is_focused">is_focused</a></li>
<li><a href="column-renderer.html#total">total</a></li>
<li><a href="meta">meta</a></li>
</ul>
<h3 id="parent-2"><a class="header" href="#parent-2">parent</a></h3>
<p>Type: string</p>
<p>The parent path of the node.</p>
<h3 id="relative_path-1"><a class="header" href="#relative_path-1">relative_path</a></h3>
<p>Type: string</p>
<p>The path relative to the parent, i.e. the file/directory name with extension.</p>
<h3 id="absolute_path-1"><a class="header" href="#absolute_path-1">absolute_path</a></h3>
<p>Type: string</p>
<p>The absolute path (without resolving symlinks) of the node.</p>
<h3 id="extension-2"><a class="header" href="#extension-2">extension</a></h3>
<p>Type: string</p>
<p>The extension of the node.</p>
<h3 id="is_symlink-1"><a class="header" href="#is_symlink-1">is_symlink</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a symlink.</p>
<h3 id="is_broken-1"><a class="header" href="#is_broken-1">is_broken</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a broken symlink.</p>
<h3 id="is_dir-1"><a class="header" href="#is_dir-1">is_dir</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a directory.</p>
<h3 id="is_file-1"><a class="header" href="#is_file-1">is_file</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is a file.</p>
<h3 id="is_readonly-1"><a class="header" href="#is_readonly-1">is_readonly</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is real-only.</p>
<h3 id="mime_essence-2"><a class="header" href="#mime_essence-2">mime_essence</a></h3>
<p>Type: string</p>
<p>The mime type of the node. For e.g. <code>text/csv</code>, <code>image/jpeg</code> etc.</p>
<h3 id="size-2"><a class="header" href="#size-2">size</a></h3>
<p>Type: integer</p>
<p>The size of the exact node. The size of a directory won't be calculated
recursively.</p>
<h3 id="human_size-1"><a class="header" href="#human_size-1">human_size</a></h3>
<p>Type: string</p>
<p>Like <a href="column-renderer.html#size">size</a> but in human readable format.</p>
<h3 id="permissions-1"><a class="header" href="#permissions-1">permissions</a></h3>
<p>Type: <a href="column-renderer.html#permission">Permission</a></p>
<p>The <a href="column-renderer.html#permission">permissions</a> applied to the node.</p>
<h3 id="canonical-1"><a class="header" href="#canonical-1">canonical</a></h3>
<p>Type: nullable <a href="column-renderer.html#resolved-node-metadata">Resolved Node Metadata</a></p>
<p>If the node is a symlink, it will hold information about the symlink resolved
node. Else, it will hold information the actual node. It the symlink is broken,
it will be null.</p>
<h3 id="symlink-2"><a class="header" href="#symlink-2">symlink</a></h3>
<p>Type: nullable <a href="column-renderer.html#resolved-node-metadata">Resolved Node Metadata</a></p>
<p>If the node is a symlink and is not broken, it will hold information about the
symlink resolved node. However, it will never hold information about the actual
node. It will instead be null.</p>
<h3 id="index"><a class="header" href="#index">index</a></h3>
<p>Type: integer</p>
<p>Index (starting from 0) of the node.</p>
<h3 id="relative_index"><a class="header" href="#relative_index">relative_index</a></h3>
<p>Type: integer</p>
<p>Relative index from the focused node (i.e. 0th node).</p>
<h3 id="is_before_focus"><a class="header" href="#is_before_focus">is_before_focus</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is before the focused node.</p>
<h3 id="is_after_focus"><a class="header" href="#is_after_focus">is_after_focus</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is after the focused node.</p>
<h3 id="tree"><a class="header" href="#tree">tree</a></h3>
<p>Type: string</p>
<p>The <a href="general-config.html#tabletree">tree component</a> based on the node's index.</p>
<h3 id="prefix"><a class="header" href="#prefix">prefix</a></h3>
<p>Type: string</p>
<p>The prefix applicable for the node.</p>
<h3 id="suffix"><a class="header" href="#suffix">suffix</a></h3>
<p>Type: string</p>
<p>The suffix applicable for the node.</p>
<h3 id="is_selected"><a class="header" href="#is_selected">is_selected</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is selected.</p>
<h3 id="is_focused"><a class="header" href="#is_focused">is_focused</a></h3>
<p>Type: boolean</p>
<p><code>true</code> if the node is under focus.</p>
<h3 id="total-1"><a class="header" href="#total-1">total</a></h3>
<p>Type: integer</p>
<p>The total number of the nodes.</p>
<h3 id="meta-1"><a class="header" href="#meta-1">meta</a></h3>
<p>Type: mapping of string and string</p>
<p>The applicable <a href="node_types.html#meta">meta object</a> for the node.</p>
<h2 id="permission"><a class="header" href="#permission">Permission</a></h2>
<p>Permission contains the following fields:</p>
<ul>
<li>user_read</li>
<li>user_write</li>
<li>user_execute</li>
<li>group_read</li>
<li>group_write</li>
<li>group_execute</li>
<li>other_read</li>
<li>other_write</li>
<li>other_execute</li>
<li>sticky</li>
<li>setgid</li>
<li>setuid</li>
</ul>
<p>Each field holds a boolean value.</p>
<h2 id="resolved-node-metadata"><a class="header" href="#resolved-node-metadata">Resolved Node Metadata</a></h2>
<p>It contains the following fields.</p>
<ul>
<li><a href="column-renderer.html#absolute_path">absolute_path</a></li>
<li><a href="column-renderer.html#extension">extension</a></li>
<li><a href="column-renderer.html#is_dir">is_dir</a></li>
<li><a href="column-renderer.html#is_file">is_file</a></li>
<li><a href="column-renderer.html#is_readonly">is_readonly</a></li>
<li><a href="column-renderer.html#mime_essence">mime_essence</a></li>
<li><a href="column-renderer.html#size">size</a></li>
<li><a href="column-renderer.html#human_size">human_size</a></li>
</ul>
<h2 id="example-customizing-table-renderer"><a class="header" href="#example-customizing-table-renderer">Example: Customizing Table Renderer</a></h2>
<pre><code class="language-lua">xplr.fn.custom.fmt_simple_column = function(m)
return m.prefix .. m.relative_path .. m.suffix
end
xplr.config.general.table.header.cols = {
{ format = &quot; path&quot; }
}
xplr.config.general.table.row.cols = {
{ format = &quot;custom.fmt_simple_column&quot; }
}
xplr.config.general.table.col_widths = {
{ Percentage = 100 }
}
-- With this config, you should only see a single column displaying the
-- relative paths.
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="default-key-bindings"><a class="header" href="#default-key-bindings">Default Key Bindings</a></h1>
<p>The default key binding is inspired by <a href="https://www.vim.org/">vim</a> and slightly
overlaps with <a href="https://github.com/jarun/nnn/">nnn</a>, but it's supposed to be
customized as per user requirements.</p>
<p>When you press <code>?</code> in <a href="default-key-bindings.html#default">default mode</a>, you can see the complete list
of <a href="modes.html">modes</a> and the key mappings for each mode.</p>
<h3 id="default-2"><a class="header" href="#default-2">default</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>.</td><td></td><td>show hidden</td></tr>
<tr><td>/</td><td>ctrl-f</td><td>search</td></tr>
<tr><td>:</td><td></td><td>action</td></tr>
<tr><td>?</td><td></td><td>global help menu</td></tr>
<tr><td>G</td><td></td><td>go to bottom</td></tr>
<tr><td>V</td><td>ctrl-a</td><td>select/unselect all</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-i</td><td>tab</td><td>next visited path</td></tr>
<tr><td>ctrl-o</td><td></td><td>last visited path</td></tr>
<tr><td>ctrl-r</td><td></td><td>refresh screen</td></tr>
<tr><td>ctrl-u</td><td></td><td>clear selection</td></tr>
<tr><td>ctrl-w</td><td></td><td>switch layout</td></tr>
<tr><td>d</td><td></td><td>delete</td></tr>
<tr><td>down</td><td>j</td><td>down</td></tr>
<tr><td>enter</td><td></td><td>quit with result</td></tr>
<tr><td>f</td><td></td><td>filter</td></tr>
<tr><td>g</td><td></td><td>go to</td></tr>
<tr><td>h</td><td>left</td><td>back</td></tr>
<tr><td>k</td><td>up</td><td>up</td></tr>
<tr><td>l</td><td>right</td><td>enter</td></tr>
<tr><td>q</td><td></td><td>quit</td></tr>
<tr><td>r</td><td></td><td>rename</td></tr>
<tr><td>s</td><td></td><td>sort</td></tr>
<tr><td>space</td><td>v</td><td>toggle selection</td></tr>
<tr><td>~</td><td></td><td>go home</td></tr>
<tr><td>[0-9]</td><td></td><td>input</td></tr>
</tbody></table>
<h3 id="recover"><a class="header" href="#recover">recover</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>esc</td><td></td><td>escape</td></tr>
</tbody></table>
<h3 id="filter-1"><a class="header" href="#filter-1">filter</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>R</td><td></td><td>relative does not contain</td></tr>
<tr><td>backspace</td><td></td><td>remove last filter</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-r</td><td></td><td>reset filters</td></tr>
<tr><td>ctrl-u</td><td></td><td>clear filters</td></tr>
<tr><td>enter</td><td>esc</td><td>done</td></tr>
<tr><td>r</td><td></td><td>relative does contain</td></tr>
</tbody></table>
<h3 id="number"><a class="header" href="#number">number</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>down</td><td>j</td><td>to down</td></tr>
<tr><td>enter</td><td></td><td>to index</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
<tr><td>k</td><td>up</td><td>to up</td></tr>
<tr><td>[0-9]</td><td></td><td>input</td></tr>
</tbody></table>
<h3 id="go-to"><a class="header" href="#go-to">go to</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
<tr><td>f</td><td></td><td>follow symlink</td></tr>
<tr><td>g</td><td></td><td>top</td></tr>
<tr><td>x</td><td></td><td>open in gui</td></tr>
</tbody></table>
<h3 id="search"><a class="header" href="#search">search</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-n</td><td>down</td><td>down</td></tr>
<tr><td>ctrl-p</td><td>up</td><td>up</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>enter</td><td>esc</td><td>focus</td></tr>
<tr><td>left</td><td></td><td>back</td></tr>
<tr><td>right</td><td></td><td>enter</td></tr>
<tr><td>tab</td><td></td><td>toggle selection</td></tr>
</tbody></table>
<h3 id="selection-ops"><a class="header" href="#selection-ops">selection ops</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>c</td><td></td><td>copy here</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
<tr><td>m</td><td></td><td>move here</td></tr>
<tr><td>x</td><td></td><td>open in gui</td></tr>
</tbody></table>
<h3 id="action-to"><a class="header" href="#action-to">action to</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>!</td><td></td><td>shell</td></tr>
<tr><td>c</td><td></td><td>create</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>e</td><td></td><td>open in editor</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
<tr><td>l</td><td></td><td>logs</td></tr>
<tr><td>m</td><td></td><td>toggle mouse</td></tr>
<tr><td>q</td><td></td><td>quit options</td></tr>
<tr><td>s</td><td></td><td>selection operations</td></tr>
<tr><td>[0-9]</td><td></td><td>go to index</td></tr>
</tbody></table>
<h3 id="create"><a class="header" href="#create">create</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>d</td><td></td><td>create directory</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
<tr><td>f</td><td></td><td>create file</td></tr>
</tbody></table>
<h3 id="create-file"><a class="header" href="#create-file">create file</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>enter</td><td></td><td>create file</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<h3 id="create-directory"><a class="header" href="#create-directory">create directory</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>enter</td><td></td><td>create directory</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<h3 id="rename"><a class="header" href="#rename">rename</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>enter</td><td></td><td>rename</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<h3 id="delete"><a class="header" href="#delete">delete</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>D</td><td></td><td>force delete</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>d</td><td></td><td>delete</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<h3 id="sort"><a class="header" href="#sort">sort</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>!</td><td></td><td>reverse sorters</td></tr>
<tr><td>E</td><td></td><td>by canonical extension reverse</td></tr>
<tr><td>M</td><td></td><td>by canonical mime essence reverse</td></tr>
<tr><td>N</td><td></td><td>by node type reverse</td></tr>
<tr><td>R</td><td></td><td>by relative path reverse</td></tr>
<tr><td>S</td><td></td><td>by size reverse</td></tr>
<tr><td>backspace</td><td></td><td>remove last sorter</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-r</td><td></td><td>reset sorters</td></tr>
<tr><td>ctrl-u</td><td></td><td>clear sorters</td></tr>
<tr><td>e</td><td></td><td>by canonical extension</td></tr>
<tr><td>enter</td><td>esc</td><td>done</td></tr>
<tr><td>m</td><td></td><td>by canonical mime essence</td></tr>
<tr><td>n</td><td></td><td>by node type</td></tr>
<tr><td>r</td><td></td><td>by relative path</td></tr>
<tr><td>s</td><td></td><td>by size</td></tr>
</tbody></table>
<h3 id="filter-2"><a class="header" href="#filter-2">filter</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>R</td><td></td><td>relative does not contain</td></tr>
<tr><td>backspace</td><td></td><td>remove last filter</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-r</td><td></td><td>reset filters</td></tr>
<tr><td>ctrl-u</td><td></td><td>clear filters</td></tr>
<tr><td>enter</td><td>esc</td><td>done</td></tr>
<tr><td>r</td><td></td><td>relative does contain</td></tr>
</tbody></table>
<h3 id="relative-path-does-contain"><a class="header" href="#relative-path-does-contain">relative path does contain</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>enter</td><td></td><td>apply filter</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<h3 id="relative-path-does-not-contain"><a class="header" href="#relative-path-does-not-contain">relative path does not contain</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>backspace</td><td></td><td>remove last character</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>ctrl-u</td><td></td><td>remove line</td></tr>
<tr><td>ctrl-w</td><td></td><td>remove last word</td></tr>
<tr><td>enter</td><td></td><td>apply filter</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<h3 id="switch-layout"><a class="header" href="#switch-layout">switch layout</a></h3>
<table><thead><tr><th>key</th><th>remaps</th><th>action</th></tr></thead><tbody>
<tr><td>1</td><td></td><td>default</td></tr>
<tr><td>2</td><td></td><td>no help menu</td></tr>
<tr><td>3</td><td></td><td>no selection panel</td></tr>
<tr><td>4</td><td></td><td>no help or selection</td></tr>
<tr><td>ctrl-c</td><td></td><td>terminate</td></tr>
<tr><td>esc</td><td></td><td>cancel</td></tr>
</tbody></table>
<div style="break-before: page; page-break-before: always;"></div><h1 id="plugin"><a class="header" href="#plugin">Plugin</a></h1>
<p>xplr supports pluggable Lua modules that can be used to easily configure or
extend xplr UI and functionalities.</p>
<ul>
<li><a href="installing-plugins.html">Installing Plugins</a></li>
<li><a href="writing-plugins.html">Writing Plugins</a></li>
<li><a href="awesome-plugins.html">Awesome Plugins</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="installing-plugins"><a class="header" href="#installing-plugins">Installing Plugins</a></h1>
<p>Until we get a cool plugin manager, let's install plugins manually using the
following procedure:</p>
<ul>
<li>
<p>Add the following line in <code>~/.config/xplr/init.lua</code></p>
<pre><code class="language-lua">package.path = os.getenv(&quot;HOME&quot;) .. '/.config/xplr/plugins/?/src/init.lua'
</code></pre>
</li>
<li>
<p>Clone the plugin</p>
<pre><code class="language-bash">mkdir -p ~/.config/xplr/plugins
git clone https://github.com/sayanarijit/material-landscape2.xplr ~/.config/xplr/plugins/material-landscape2
</code></pre>
</li>
<li>
<p>Require the module in <code>~/.config/xplr/init.lua</code></p>
<pre><code class="language-lua">require(&quot;material-landscape2&quot;).setup()
-- The setup arguments might differ for different plugins.
-- Visit the project README for setup instructions.
</code></pre>
</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="writing-plugins"><a class="header" href="#writing-plugins">Writing Plugins</a></h1>
<p>Anyone who can write <a href="https://www.lua.org">Lua</a> code, can write xplr plugins.</p>
<p>Just follow the instructions and best practices:</p>
<h2 id="naming"><a class="header" href="#naming">Naming</a></h2>
<p>xplr plugins are named using hiphen (<code>-</code>) separated words that may also include
integers. They will be plugged using the <code>require()</code> function in Lua.</p>
<h2 id="structure"><a class="header" href="#structure">Structure</a></h2>
<p>A minimal plugin should confirm to the following structure:</p>
<pre><code>plugin-name
├── README.md
└── src
└── init.lua
</code></pre>
<p>You can also use
<a href="https://github.com/sayanarijit/plugin-template1.xplr">this template</a>.</p>
<h3 id="readmemd"><a class="header" href="#readmemd">README.md</a></h3>
<p>This is where you document what the plugin does, how to use it, etc.</p>
<h3 id="srcinitlua"><a class="header" href="#srcinitlua">src/init.lua</a></h3>
<p>This file is executed to load the plugin. It should expose a <code>setup()</code>
function, which will be used by the users to setup the plugin.</p>
<p>Example:</p>
<pre><code class="language-lua">local function setup(args)
local xplr = xplr
-- do stuff with xplr
end
return { setup = setup }
</code></pre>
<h2 id="publishing"><a class="header" href="#publishing">Publishing</a></h2>
<p>When publishing plugins on GitHub or other repositories, it's a best practice
to append <code>.xplr</code> to the name to make them distinguishable. Similar to the
<code>*.nvim</code> naming convention for <a href="https://neovim.io">Neovim</a> plugins.</p>
<p>Finally, after publishing, don't hesitate to
<a href="https://github.com/sayanarijit/xplr/discussions/categories/show-and-tell">let us know</a>.</p>
<h2 id="examples"><a class="header" href="#examples">Examples</a></h2>
<p>Visit <a href="awesome-plugins.html">Awesome Plugins</a> for xplr plugin examples.</p>
<h2 id="also-see"><a class="header" href="#also-see">Also See</a></h2>
<ul>
<li><a href="modes.html#tutorial-adding-a-new-mode">Tutorial: Adding a New Mode</a></li>
<li><a href="message.html#example-using-environment-variables-and-pipes">Example: Using Environment Variables and Pipes</a></li>
<li><a href="message.html#example-using-lua-function-calls">Example: Using Lua Function Calls</a></li>
<li><a href="column-renderer.html#example-customizing-table-renderer">Example: Customizing Table Renderer</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="awesome-plugins"><a class="header" href="#awesome-plugins">Awesome Plugins</a></h1>
<p>Here's a list of awesome xplr plugins that you might want to check out. If none
of the following plugins work for you, it's very easy to
<a href="./writing-plugins.html">write your own</a>.</p>
<h2 id="categories"><a class="header" href="#categories">Categories</a></h2>
<ul>
<li><a href="awesome-plugins.html#extension">Extension</a></li>
<li><a href="awesome-plugins.html#integration">Integration</a></li>
<li><a href="awesome-plugins.html#theme">Theme</a></li>
</ul>
<h2 id="extension-3"><a class="header" href="#extension-3">Extension</a></h2>
<ul>
<li><a href="https://github.com/sayanarijit/comex.xplr"><strong>comex.xplr</strong></a> One xplr plugin to compress and extract them all.</li>
<li><a href="https://github.com/sayanarijit/command-mode.xplr"><strong>command-mode.xplr</strong></a> The missing command mode for xplr.</li>
<li><a href="https://github.com/prncss-xyz/type-to-nav.xplr"><strong>type-to-nav.xplr</strong></a> Inspired by <a href="https://github.com/jarun/nnn/wiki/concepts#type-to-nav">nnn's type-to-nav mode</a> for xplr,
with some tweaks.</li>
</ul>
<h2 id="integration"><a class="header" href="#integration">Integration</a></h2>
<ul>
<li><a href="https://github.com/sayanarijit/alacritty.xplr"><strong>alacritty.xplr</strong></a> <a href="https://github.com/alacritty/alacritty">Alacritty</a> integration for xplr.</li>
<li><a href="https://github.com/sayanarijit/dragon.xplr"><strong>dragon.xplr</strong></a> Drag and drop files using <a href="https://github.com/mwh/dragon">dragon</a>.</li>
<li><a href="https://github.com/sayanarijit/dua-cli.xplr"><strong>dua-cli.xplr</strong></a> Get the disk usage using <a href="https://github.com/Byron/dua-cli">dua-cli</a> with selection
support.</li>
<li><a href="https://github.com/sayanarijit/fzf.xplr"><strong>fzf.xplr</strong></a> Fuzzy search using <a href="https://github.com/junegunn/fzf">fzf</a> to focus on a file or enter
into a directory.</li>
<li><a href="https://github.com/sayanarijit/nvim-ctrl.xplr"><strong>nvim-ctrl.xplr</strong></a> Send files to running Neovim sessions using
<a href="https://github.com/chmln/nvim-ctrl">nvim-ctrl</a>.</li>
<li><a href="https://github.com/dtomvan/paste-rs.xplr"><strong>paste-rs.xplr</strong></a> Use this plugin to paste your files to
<a href="https://paste.rs">paste.rs</a>, and open/delete them later using <a href="https://github.com/junegunn/fzf">fzf</a>.</li>
<li><a href="https://github.com/sayanarijit/preview-tabbed.xplr"><strong>preview-tabbed.xplr</strong></a> Preview paths using suckless <a href="https://tools.suckless.org/tabbed/">tabbed</a> and
<a href="https://github.com/jarun/nnn/blob/master/plugins/preview-tabbed">nnn preview-tabbed</a>.</li>
<li><a href="https://github.com/sayanarijit/qrcp.xplr"><strong>qrcp.xplr</strong></a> Send and receive files via QR code using <a href="https://github.com/claudiodangelis/qrcp">qrcp</a>.</li>
<li><a href="https://github.com/sayanarijit/trash-cli.xplr"><strong>trash-cli.xplr</strong></a> Trash files and directories using <a href="https://github.com/andreafrancia/trash-cli">trash-cli</a>.</li>
<li><a href="https://github.com/sayanarijit/xargs.xplr"><strong>xargs.xplr</strong></a> Batch execute commands on the focused or selected files
using <code>xargs</code>.</li>
<li><a href="https://github.com/sayanarijit/xclip.xplr"><strong>xclip.xplr</strong></a> Copy and paste with system clipboard using <a href="https://github.com/astrand/xclip">xclip</a>.</li>
<li><a href="https://github.com/sayanarijit/zoxide.xplr"><strong>zoxide.xplr</strong></a> Change directory using the <a href="https://github.com/ajeetdsouza/zoxide">zoxide</a> database.</li>
</ul>
<h2 id="theme"><a class="header" href="#theme">Theme</a></h2>
<ul>
<li><a href="https://github.com/sayanarijit/material-landscape.xplr"><strong>material-landscape.xplr</strong></a> Material Landscape</li>
<li><a href="https://github.com/sayanarijit/material-landscape2.xplr"><strong>material-landscape2.xplr</strong></a> Material Landscape 2</li>
<li><a href="https://github.com/sayanarijit/zentable.xplr"><strong>zentable.xplr</strong></a> A clean, distraction free xplr table UI</li>
<li><a href="https://github.com/prncss-xyz/icons.xplr"><strong>icons.xplr</strong></a> An icon theme for xplr.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="integration-1"><a class="header" href="#integration-1">Integration</a></h1>
<p>xplr is designed to integrate well with other tools and commands. It can be
used as a file picker or a pluggable file manager.</p>
<ul>
<li><a href="awesome-integrations.html">Awesome Integrations</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="awesome-integrations"><a class="header" href="#awesome-integrations">Awesome Integrations</a></h1>
<p>Here's a list of awesome xplr integrations that you might want to check out.</p>
<p>If none of the following integrations work for you, you can create your own and
<a href="https://github.com/sayanarijit/xplr/discussions/categories/show-and-tell">let us know</a>.</p>
<h2 id="categories-1"><a class="header" href="#categories-1">Categories</a></h2>
<ul>
<li><a href="awesome-integrations.html#editor">Editor</a></li>
<li><a href="awesome-integrations.html#shell">Shell</a></li>
<li><a href="awesome-integrations.html#security-tools">Security Tools</a></li>
</ul>
<h2 id="editor"><a class="header" href="#editor">Editor</a></h2>
<ul>
<li><a href="https://github.com/voldikss/vim-floaterm#xplr"><strong>vim-floaterm</strong></a> xplr integrated in vim-floaterm (Neo)vim plugin.</li>
<li><a href="https://github.com/fhill2/xplr.nvim"><strong>xplr.nvim</strong></a> Opens xplr inside nvim, and hosts a msgpack client inside xplr.</li>
<li><a href="https://github.com/sayanarijit/xplr.vim"><strong>xplr.vim</strong></a> Pick files in Vim using xplr.</li>
</ul>
<h2 id="shell"><a class="header" href="#shell">Shell</a></h2>
<ul>
<li><a href="https://github.com/romkatv/powerlevel10k/blob/191d1b89e325ee3b6d2d75a394654aaf4f077a7c/internal/p10k.zsh#L4756-L4768"><strong>powerlevel10k</strong></a> Powerlevel10k prompt for xplr shell.</li>
</ul>
<h2 id="security-tools"><a class="header" href="#security-tools">Security Tools</a></h2>
<ul>
<li><a href="https://github.com/orhun/gpg-tui#importreceive"><strong>gpg-tui</strong></a> Import GPG certificates using xplr.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="todo"><a class="header" href="#todo">TODO</a></h1>
<ul>
<li><input disabled="" type="checkbox" checked=""/>
Saner key bindings.</li>
<li><input disabled="" type="checkbox" checked=""/>
Pipes.</li>
<li><input disabled="" type="checkbox" checked=""/>
Native search &amp; filter.</li>
<li><input disabled="" type="checkbox" checked=""/>
Create, copy, move, delete files directly.</li>
<li><input disabled="" type="checkbox" checked=""/>
logging support.</li>
<li><input disabled="" type="checkbox" checked=""/>
Version compatibility instructions.</li>
<li><input disabled="" type="checkbox" checked=""/>
Implement CLI arguments.</li>
<li>~Add support for tabs and/or panes (non native)~ <a href="https://github.com/sayanarijit/xplr/wiki/Hacks#spawn-multiple-sessions-in-different-windows">hacked</a> | <a href="https://github.com/sayanarijit/xplr/discussions/15">discussion</a></li>
<li>~Implement bookmarks.~ <a href="https://github.com/sayanarijit/xplr/wiki/Hacks#bookmark">hacked</a></li>
<li><input disabled="" type="checkbox" checked=""/>
Add sorting support.</li>
<li><input disabled="" type="checkbox" checked=""/>
Add filter support.</li>
<li><input disabled="" type="checkbox" checked=""/>
File previews.</li>
<li><input disabled="" type="checkbox" checked=""/>
Implement plugins support (or some way to easily share configuration).</li>
<li><input disabled="" type="checkbox" checked=""/>
Bigger (and better) help menu.</li>
<li><input disabled="" type="checkbox" checked=""/>
Offline docs.</li>
<li><input disabled="" type="checkbox"/>
Support for background services</li>
<li><input disabled="" type="checkbox" checked=""/>
~Customize~ switch UI at run-time.</li>
<li><input disabled="" type="checkbox"/>
More tests and benchmarks.</li>
<li><input disabled="" type="checkbox"/>
Measure code coverage.</li>
<li><input disabled="" type="checkbox"/>
Improve the <a href="https://github.com/sayanarijit/xplr.vim">vim plugin</a>.</li>
<li><input disabled="" type="checkbox"/>
Cleanup, refactor, optimize.</li>
</ul>
<p><a href="https://github.com/sayanarijit/xplr/discussions/2">add more</a></p>
<p>Like this project so far? <strong><a href="contribute.html">Please consider contributing</a>.</strong></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="alternatives"><a class="header" href="#alternatives">Alternatives</a></h1>
<p>These are the alternative TUI/CLI file managers/explorers you might want to check out (in no particular order).</p>
<ul>
<li><a href="https://github.com/jarun/nnn/">nnn</a></li>
<li><a href="https://github.com/vifm/vifm">vifm</a></li>
<li><a href="https://github.com/ranger/ranger">ranger</a></li>
<li><a href="https://github.com/gokcehan/lf">lf</a></li>
<li><a href="https://github.com/kamiyaa/joshuto">joshuto</a></li>
<li><a href="https://github.com/dylanaraps/fff">fff</a></li>
<li><a href="https://github.com/MidnightCommander/mc">mc</a></li>
<li><a href="https://github.com/Canop/broot">broot</a></li>
<li><a href="https://github.com/rabite0/hunter">hunter</a></li>
<li><a href="https://git.2f30.org/noice/">noice</a></li>
<li><a href="https://github.com/pasqu4le/clifm">clifm</a></li>
<li><a href="https://github.com/leo-arch/clifm">clifm</a> (non curses)</li>
</ul>
<p><a href="community.html">add more</a></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="upgrade-guide"><a class="header" href="#upgrade-guide">Upgrade Guide</a></h1>
<p>When you upgrade xplr, you might see an error like this</p>
<pre><code>Incompatible script version in: /home/sayanarijit/.config/xplr/init.lua. The script version is: 0.9.0, the required version is: 0.10.1. Visit https://github.com/sayanarijit/xplr/wiki/Upgrade-Guide
</code></pre>
<p>All you need to do is follow the <a href="upgrade-guide.html#instructions">instructions</a> starting from
your config version, all the way to the required version.</p>
<details>
<summary>Expand for more information</summary>
<p>With every update, we either implement a <code>major</code> breaking change (e.g.
deprecating or replacing messages), or a <code>minor</code> feature addition (e.g. adding
new messages) or <code>patch</code>, fixes, and optimization (e.g. performance
optimization).</p>
<p>Knowing that we use the <code>{major}.{minor}.{patch}</code> versioning format,</p>
<ul>
<li>Major version mismatch are generally incompatible. xplr will fail
with error.</li>
<li>Minor version upgrades (not downgrades) and patch fixes are backwards
compatible. You might get notified by log a message which you can disable by
updating the version in your config file.</li>
<li>However, if the config file has a higher value for the minor version
than the app, then also xplr will fail with error, suggesting you
to visit this page.
Though in that case, you will be downgrading your config file based on your
app version.</li>
</ul>
<p>e.g.</p>
<ul>
<li><code>1.0.0</code> -&gt; <code>1.0.x</code>: Bug fix (fully compatible).</li>
<li><code>1.0.0</code> -&gt; <code>1.x.x</code>: Only backwards compatible. You can't generally use for
e.g. <code>app-1.0.0</code> with <code>config-1.1.0</code>. But vice versa is fine.</li>
<li><code>1.0.0</code> -&gt; <code>x.x.x</code>: Not compatible at all.</li>
</ul>
<p>Note that until we're <code>v1</code>, we'll be using the <code>{minor}</code> version number as
<code>{major}</code>, and the <code>{patch}</code> fix number as <code>{minor}</code> to determine
compatibility.</p>
</details>
<h3 id="instructions"><a class="header" href="#instructions">Instructions</a></h3>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0147v0147a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0150v0150a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0147v0147a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0150v0150a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.14.7">v0.14.7</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.15.0">v0.15.0</a></a></h4>
<ul>
<li>Added <code>CustomContent</code> as layout option that can be used to render custom
paragraphs, lists and tables. Both static and dynamic.</li>
<li>Added support for optionally defining custom layouts for different modes.</li>
<li>Added <code>xplr.config.general.focus_selection_ui</code> to highlight selected files
under focus differently than files under focus that are not selected.</li>
<li>Added <code>PopModeKeepingInputBuffer</code>, and SwitchMode alternatives to allow
switching to different modes without resetting the input buffer.</li>
<li>Removed <code>config</code> field from <code>CallLuaArg</code> as it's already available globally
as <code>xplr.config</code>.</li>
<li>Fixed a bug which caused xplr to misbehave when used with specific tools and
environment (e.g. neovim, fzf, zsh4humans etc.).</li>
<li>Recover mode will be disabled by default.
i.e. <code>xplr.config.general.disable_recover_mode</code> has been deprecated. Use
<code>xplr.config.general.enable_recover_mode</code> instead.</li>
<li>Library users please refer to the latest API docs and examples.</li>
<li>New homepage: https://xplr.dev</li>
</ul>
<p><sub>Like this project so far? <strong><a href="contribute.html">Please consider contributing</a></strong>.</sub></p>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0137v0137a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0147v0147a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0137v0137a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0147v0147a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.13.7">v0.13.7</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.14.7">v0.14.7</a></a></h4>
<ul>
<li>macOS users need to place their config file (<code>init.lua</code>) in
<code>$HOME/.config/xplr/</code> or <code>/etc/xplr/</code>.</li>
<li>Library users please refer to the latest API docs.</li>
<li>Check out the new messages: <code>{Start|Stop|Toggle}Fifo</code>. These enable support
for <a href="https://github.com/sayanarijit/xplr/pull/229#issue-662426960">FIFO based file previews</a>.</li>
<li>You can disable the recover mode using <code>config.general.disable_recover_mode = true</code>.</li>
<li>Try running <code>xplr --help</code>. Yes, CLI has been implemented.</li>
<li>Since version <code>v0.14.3</code>, <code>StartFifo</code> and <code>ToggleFifo</code> will write to the FIFO
path when called. So, there's no need to pipe the focus path explicitely.</li>
<li>Since version <code>v0.14.3</code>, general config <code>xplr.config.start_fifo</code> is available
which can be set to a file path to start a fifo when xplr starts.</li>
<li>Since version <code>v0.14.4</code>, <code>$XPLR_SESSION_PATH</code> can be used to dump session
related data.</li>
<li>Since version <code>v0.14.6</code>, the <code>-C</code> or <code>--extra-config</code> CLI argument is
available.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0121v0121a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0137v0137a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0121v0121a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0137v0137a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.12.1">v0.12.1</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.13.7">v0.13.7</a></a></h4>
<ul>
<li>Lua functions called using <a href="https://docs.rs/xplr/latest/xplr/app/enum.ExternalMsg.html#variant.CallLua"><code>CallLua</code></a> and <a href="https://docs.rs/xplr/latest/xplr/app/enum.ExternalMsg.html#variant.CallLuaSilently"><code>CallLuaSilently</code></a> messages will receive <a href="https://docs.rs/xplr/latest/xplr/app/struct.CallLuaArg.html"><code>CallLuaArg</code></a> object as the function argument (instead of the <a href="https://docs.rs/xplr/latest/xplr/app/struct.App.html"><code>App</code></a> object).</li>
<li>Each <code>node_types</code> config will inherit defaults from matching less specifig <code>node_types</code> config and overwrite them.</li>
<li>Since version <code>v0.13.2</code>, you don't need to use/send <code>Refresh</code> anymore. It will be auto-handled by xplr.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0111v0111a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0121v0121a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0111v0111a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0121v0121a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.11.1">v0.11.1</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.12.1">v0.12.1</a></a></h4>
<ul>
<li><code>xplr.config.node_types.mime_essence</code> has split into type and subtype. Hence, instead of <code>xplr.config.node_types.mime_essence[&quot;text/plain&quot;] = ..</code> use <code>xplr.config.node_types.mime_essence[&quot;text&quot;] = { plain = .. }</code>.</li>
<li>You can also define <code>xplr.config.node_types.mime_essence[&quot;text&quot;][&quot;*&quot;]</code> that will match all text types (<code>text/*</code>).</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0102v0102a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0111v0111a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0102v0102a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0111v0111a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.10.2">v0.10.2</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.11.1">v0.11.1</a></a></h4>
<ul>
<li><code>remaps:</code> has been removed to avoid confusion. Use lua assignments instead.
For e.g.
<pre><code>xplr.config.modes.builtin.default.key_bindings.on_key[&quot;v&quot;] = xplr.config.modes.builtin.default.key_bindings.on_key.space
</code></pre>
</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv091v091a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0102v0102a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv091v091a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0102v0102a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.9.1">v0.9.1</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.10.2">v0.10.2</a></a></h4>
<ul>
<li><a href="https://github.com/sayanarijit/xplr/blob/85696ded7a/src/config.yml"><code>config.yml</code></a> has been fully replaced with <a href="https://github.com/sayanarijit/xplr/blob/main/src/init.lua"><code>init.lua</code></a>. If you have a lot of customization in your <code>config.yml</code>, <a href="https://github.com/sayanarijit/xplr-yml2lua">xplr-yml2lua</a> can help you with migrating it to <code>init.lua</code>.</li>
<li><code>Handlebars</code> templates has been replaced with <a href="https://github.com/sayanarijit/xplr/blob/bfdb7736b99bc3c5ae53e7d621ba0e7ca2299b14/src/init.lua#L2005-L2064">Lua functions</a>. You can either remove the customizations or overwrite the functions accordingly.</li>
<li>Added new messages <code>CallLua</code> and <code>CallLuaSilently</code> to call lua functions. The app state will be passed as input to the functions, and the returned messages will be handled by xplr. <code>CallLua</code> and <code>CallLuaSilently</code> are more flexible (and probably faster) alternatives to <code>Call</code>, <code>CallSilently</code>, <code>BashExec</code> and <code>BashExecSilently</code>. <a href="https://github.com/sayanarijit/xplr/pull/177#issue-650643573">e.g.</a></li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv090v090a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv091v091a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv090v090a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv091v091a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.9.0">v0.9.0</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.9.1">v0.9.1</a></a></h4>
<ul>
<li>You can now set <code>remaps: {key: null}</code> to un-map a key.</li>
<li><code>gx</code> will open the item under focus.</li>
<li>New key map <code>:sx</code> will open the selected items.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv080v080a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv090v090a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv080v080a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv090v090a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.8.0">v0.8.0</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.9.0">v0.9.0</a></a></h4>
<p>Your previous config should mostly work fine. However, in case you are using <code>SwitchMode</code> heavily in your custom config, follow along.</p>
<ul>
<li>Introduced new message <code>PopMode</code>. You might want to use this message instead of <code>SwitchMode*</code> when returning back to the previous mode.</li>
<li>After using (the group of) <code>PopMode</code> and <code>SwitchMode*</code> messages, you are now required to <code>Refresh</code> manually to avoid the UI lag.</li>
<li>Pressing any invalid key will now lead you to the <code>recover</code> mode and will protect you from typing further invalid keys. Press <code>esc</code> to escape the <code>recover</code> mode.</li>
<li>Introduced new message <code>LogWarning</code>, similar to other <code>Log*</code> messages.</li>
<li>Creating files and directories has been optimized for batch creation.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv072v072a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv080v080a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv072v072a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv080v080a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.7.2">v0.7.2</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.8.0">v0.8.0</a></a></h4>
<p>If you have made changes to the config file,</p>
<ul>
<li>Replace message <code>Explore</code> with <code>ExplorePwd</code> or <code>ExplorePwdAsync</code> or probably <code>ExploreParentsAsync</code>.</li>
<li>Pipe <code>$XPLR_PIPE_FOCUS_OUT</code> has been removed. Use <code>$XPLR_FOCUS_PATH</code> env var instead.</li>
<li>You might want to review your path escaping logics. For e.g. use <code>echo FocusPath: &quot;'&quot;$PWD&quot;'&quot; &gt;&gt; $PIPE</code> instead of <code>echo &quot;FocusPath: $PWD&quot; &gt;&gt; $PIPE</code>.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv070v070a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv072v072a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv070v070a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv072v072a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.7.0">v0.7.0</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.7.2">v0.7.2</a></a></h4>
<ul>
<li>Just update the <code>version</code> in your config file.</li>
<li>For version &gt;= <code>v0.7.1</code>, you might want to free up or remap the <code>tab</code> key in <code>search</code> mode to enable easy selection during search.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv060v060a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv070v070a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv060v060a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv070v070a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.6.0">v0.6.0</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.7.0">v0.7.0</a></a></h4>
<p>If you haven't made any changes in the config file, you should be fine just updating the version number. Else,</p>
<ul>
<li>You can make the <code>Table: ...</code>, <code>InputAndLogs: ...</code> layout values null and define the common properties in the <code>general.panel_ui</code> instead.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0513v0513a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv060v060a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0513v0513a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv060v060a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.5.13">v0.5.13</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.6.0">v0.6.0</a></a></h4>
<p>If you haven't made any changes in the config file, you should be fine just updating the version number. Else,</p>
<ul>
<li>Rename <code>add_modifier: {bits: 1}</code> to <code>add_modifiers: [Bold]</code>, <code>sub_modifier: {bits: 1}</code> to <code>sub_modifiers: [Bold]</code> and so on.</li>
<li>Rename <code>percentage: 10</code> to <code>Percentage: 10</code>, <code>ratio: 1</code> to <code>Ratio: 1</code> and so on.</li>
<li>You might want to free up or remap the <code>ctrl-w</code> key binding in <code>default</code> mode to enable layout switching.</li>
</ul>
<p>Optionally, checkout this new theme to learn more about what's new.</p>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv050v050a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0513v0513a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv050v050a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0513v0513a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.5.0">v0.5.0</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.5.13">v0.5.13</a></a></h4>
<ul>
<li>Just update the <code>version</code> in your config file.</li>
<li>For versions &gt;= <code>v0.5.8</code>, you can set <code>$OPENER</code> env var to declare a global GUI file opener (to open files using keys <code>gx</code>).</li>
<li>You might also want to update other mappings to handle files with names starting with <code>-</code> (hiphen). For example, instead of <code>rm ${filename}</code> use <code>rm -- ${filename}</code>. Same goes for <code>cp</code>, <code>mv</code>, <code>cat</code>, <code>touch</code> etc.</li>
<li>For version &gt;= <code>v0.5.13</code>, you might want to use the more specific <code>SwitchModeBuiltin</code> and <code>SwitchModeCustom</code> messages instead of the general <code>SwitchMode</code> message.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv043v043a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv050v050a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv043v043a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv050v050a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.4.3">v0.4.3</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.5.0">v0.5.0</a></a></h4>
<p>If you haven't have any changes in the config file, you should be fine just updating the version number.</p>
<p>Else do the following</p>
<ul>
<li>Replace <code>{RelativePathIs, case_sensitive: true}</code> with <code>RelativePathIs</code>.</li>
<li>Replace <code>{RelativePathIs, case_sensitive: false}</code> with <code>IRelativePathIs</code>.</li>
<li>Do the same with other filters you are using.</li>
<li>You might want to update your <code>backspace</code> handling to use the <code>RemoveInputBufferLastCharacter</code> message.</li>
<li>You might want to free-up <code>f</code>, <code>s</code>, <code>ctrl-r</code> and <code>ctrl-u</code> key bindings in the default mode, or remap them.</li>
<li>You might want to use the new UI variables.</li>
<li>Update your config version to <code>v0.5.0</code>.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv042v042a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv043v043a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv042v042a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv043v043a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.4.2">v0.4.2</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.4.3">v0.4.3</a></a></h4>
<p>If you have customized <code>general.table.row.cols</code>, you might want to <a href="https://github.com/sayanarijit/xplr/blob/af1cda5762/src/config.yml#L46-L48">update it</a> to use the new variables with better symlink support.</p>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv041v041a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv042v042a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv041v041a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv042v042a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.4.1">v0.4.1</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.4.2">v0.4.2</a></a></h4>
<p>In case you have mapped the keys <code>q</code>, <code>ctrl-i</code> and <code>ctrl-o</code>, you may want to revisit the default mode key bindings and remap accordingly to use the new functionalities.</p>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0313v0313a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv041v041a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0313v0313a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv041v041a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.3.13">v0.3.13</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.4.1">v0.4.1</a></a></h4>
<p>A lot has changed (apologies). But I promise from now on, upgrading will be much less painful (thanks to <a href="https://github.com/maximbaz">@maximbaz</a>'s valuable <a href="https://github.com/sayanarijit/xplr/issues/45#issue-854447104">inputs</a> and <a href="https://github.com/sayanarijit/xplr/pull/47">code reviews</a>).</p>
<p>So, to start with the upgrade, let's remove everything from your config file except the <code>version</code> field and your custom modifications. If <code>version</code> is the only thing remaining, update it to <code>v0.4.1</code> and you are done.</p>
<p>Else, do the following</p>
<ul>
<li>Rename <code>general.focused_ui</code> to <code>general.focus_ui</code> (<a href="https://github.com/sayanarijit/xplr/blob/055c1083d6/src/config.yml#L124">see here</a>).</li>
<li>Rename <code>filetypes</code> to <code>node_types</code>. (<a href="https://github.com/sayanarijit/xplr/blob/055c1083d6/src/config.yml#L145">see here</a>)</li>
<li>Rename <code>custom</code> field to <code>meta</code>. (<a href="https://github.com/sayanarijit/xplr/blob/055c1083d6/src/config.yml#L154-L155">see here</a>)</li>
<li>Move <code>icon</code> to <code>meta.icon</code>. (<a href="https://github.com/sayanarijit/xplr/blob/055c1083d6/src/config.yml#L45">see here</a>)</li>
<li>Rename <code>normal_ui</code> to <code>default_ui</code>. (<a href="https://github.com/sayanarijit/xplr/blob/055c1083d6/src/config.yml#L114">see here</a>)</li>
<li>Split <code>modes</code> into <code>modes.builtin</code> and <code>modes.custom</code> (<a href="https://github.com/sayanarijit/xplr/blob/055c1083d6/src/config.yml#L180-L181">see here</a>). Migrate your custom modes to <code>modes.custom</code>. And copy only the changes in the in-built modes in <code>modes.builtin</code>.</li>
<li>Finally, update the <code>version</code> to <code>v0.4.1</code>.</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv038v038a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0313v0313a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv038v038a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv0313v0313a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.3.8">v0.3.8</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.3.13">v0.3.13</a></a></h4>
<p>Your current config should work fine. However, you might want to replace some <code>Call</code> and <code>BashExec</code> messages with <code>CallSilently</code> and <code>BashExecSilently</code> to remove the flickering of the screen.</p>
<p>If you haven't made any changes to the configuration, you can delete and regenerate it.</p>
<p>Else, do the following</p>
<ul>
<li>Check the new default config by temporarily removing your current config (with backup) and dumping the new config.</li>
<li>Search for <code>Call</code> and <code>BashExec</code> in the new config.</li>
<li>Compare and probably replace the associated actions in your current config</li>
</ul>
<h4 id="a-hrefhttpsgithubcomsayanarijitxplrreleasestagv030v030a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv038v038a"><a class="header" href="#a-hrefhttpsgithubcomsayanarijitxplrreleasestagv030v030a---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv038v038a"><a href="https://github.com/sayanarijit/xplr/releases/tag/v0.3.0">v0.3.0</a> -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.3.8">v0.3.8</a></a></h4>
<p>Your current config should work fine. However, you might want to replace some <code>ResetNodeFilters</code> messages with <code>RemoveNodeFilter</code> and <code>RemoveNodeFilterFromInput</code> to get a better search and filter experience.</p>
<p>If you haven't made any changes to the configuration, you can delete and regenerate it.</p>
<p>Else, do the following</p>
<ul>
<li>Check the new default config by temporarily removing your current config (with backup) and dumping the new config.</li>
<li>Search for <code>RemoveNodeFilterFromInput</code> in the new config.</li>
<li>Compare and probably replace the associated actions in your current config.</li>
</ul>
<h4 id="v0214---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv030v030a"><a class="header" href="#v0214---a-hrefhttpsgithubcomsayanarijitxplrreleasestagv030v030a">v0.2.14 -&gt; <a href="https://github.com/sayanarijit/xplr/releases/tag/v0.3.0">v0.3.0</a></a></h4>
<p>If you haven't made any changes to the configuration, you can delete and regenerate it.</p>
<p>Else do the following:</p>
<ul>
<li><code>$XPLR_APP_YAML</code> has been removed. You can use <code>Debug</code> to export the app state.</li>
<li><code>$XPLR_RESULT</code> has been ported to file <code>$XPLR_PIPE_RESULT_OUT</code>. Use <code>cat</code> instead of <code>echo</code>, <code>&lt;</code> instead of <code>&lt;&lt;&lt;</code> etc.</li>
<li><code>$XPLR_GLOBAL_HELP_MENU</code> has been ported to
file <code>$XPLR_PIPE_GLOBAL_HELP_MENU_OUT</code>. Use <code>cat</code> instead of <code>echo</code>, <code>&lt;</code> instead of <code>&lt;&lt;&lt;</code> etc.</li>
<li><code>$XPLR_DIRECTORY_NODES</code> has been ported to
file <code>$XPLR_PIPE_DIRECTORY_NODES_OUT</code>. Use <code>cat</code> instead of <code>echo</code>, <code>&lt;</code> instead of <code>&lt;&lt;&lt;</code> etc.</li>
<li><code>$XPLR_LOGS</code> has been ported to file <code>$XPLR_PIPE_LOGS_OUT</code>. Use <code>cat</code> instead of <code>echo</code>, <code>&lt;</code> instead of <code>&lt;&lt;&lt;</code> etc.</li>
<li><code>$XPLR_PIPE_RESULT</code> has been ported to file <code>$XPLR_PIPE_RESULT_OUT</code>. Use <code>cat</code> instead of <code>echo</code>, <code>&lt;</code> instead of <code>&lt;&lt;&lt;</code> etc.</li>
<li>Finally, update the <code>version</code> in your config file.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="community"><a class="header" href="#community">Community</a></h1>
<p>Building an active community of awesome people and learning stuff together is
one of my reasons to publish this tool and maintain it. Hence, please feel free
to reach out via your preferred way.</p>
<ul>
<li>Real-time chat lovers can <a href="https://discord.gg/JmasSPCcz3"><strong>join our discord channel</strong></a>.</li>
<li>Forum discussion veterans can <a href="https://github.com/sayanarijit/xplr/discussions"><strong>start a new GitHub discussion</strong></a>.</li>
</ul>
<p>BTW I like Miyazaki and Shinkai works.</p>
<div style="break-before: page; page-break-before: always;"></div><p>If you like xplr, and want to contribute, that would be really awesome.</p>
<p>You can contribute to this project in the following ways</p>
<ul>
<li>
<p>Contribute your time and expertise (read <a href="https://github.com/sayanarijit/xplr/blob/main/CONTRIBUTING.md">CONTRIBUTING.md</a> for instructions).</p>
<ul>
<li><strong>Developers:</strong> You can help me improve my code, fix things, implement features etc.</li>
<li><strong>Repository maintainers:</strong> You can save the users from the pain of managing xplr in their system manually.</li>
<li><strong>Code Reviewers:</strong> Teach me your ways of code.</li>
<li><strong>Designers:</strong> You can make the logo even more awesome, donate stickers and blog post worthy pictures.</li>
<li><strong>Bloggers, YouTubers &amp; broadcasters:</strong> You can help spread the word. </li>
</ul>
</li>
<li>
<p>Contribute by donating.</p>
<ul>
<li>You can <a href="https://opencollective.com/xplr">fuel me with coins of encouragement</a> or <a href="https://ko-fi.com/sayanarijit">buy me a coffee</a>.</li>
</ul>
</li>
</ul>
<p>For further queries or concern related to <code>xplr</code>, <a href="community.html">just ask us</a>.</p>
<h3 id="backers"><a class="header" href="#backers">Backers</a></h3>
<p><a href="https://opencollective.com/xplr#backer"><img src="https://opencollective.com/xplr/tiers/backer.svg?width=890" /></a></p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>