emacs/var/elfeed/db/data/2c/2cef45cd9712201a711c4fa21fa54fed3d12543f
2022-01-03 12:49:32 -06:00

89 lines
10 KiB
Plaintext

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="author" content="By Pierre Neidhardt" />
<title>Prompt buffer: an overpowered user experience</title>
<style type="text/css">
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<header>
<h1 class="title">Prompt buffer: an overpowered user experience</h1>
<p class="author">By Pierre Neidhardt</p>
</header>
<p>Have you ever felt frustrated using a popular browser when you couldn't do something as simple as &quot;close all Wikipedia tabs&quot; or &quot;download all pictures on this page&quot;?</p>
<p>This frustration is behind one of the fundamental ideas that gave birth to Nyxt: provide the user with a powerful, non-limiting interactive experience. The UI (user interface) should never get in the way. Quite the opposite, actually, it should empower the user by allowing them to quickly search, filter and process anything, from web page content to UI elements.</p>
<p>With this in mind, we've decided to put interactivity at the center of Nyxt. This is how the <em>prompt buffer</em> came to fruition:</p>
<p><img src="../static/image/article/prompt-buffer-set-url.png" /></p>
<p>We didn't want to repeat Emacs' mistake: its original &quot;prompt&quot; is so limited that it couldn't contain the frustration of its power users. This gave birth to a flock of alternative prompts, from <a href="https://emacs-helm.github.io/helm/">Helm</a> to <a href="https://oremacs.com/swiper/">Ivy</a>. Because of this, the Emacs community is now split between various interfaces, with loads of extensions that only work with one but not the other.</p>
<p>By providing an original framework that strives at being as powerful and flexible as possible, we hope to satisfy all possible needs and keep the community stuck together with a consistent user experience.</p>
<h1 id="what-is-the-prompt-buffer">What is the prompt buffer?</h1>
<p>The prompt buffer is a universal input area for Nyxt. You can think of it like an 'omnibox', but with more features and power beyond simply setting the URL.</p>
<p>Our prompt buffer is heavily inspired by <a href="https://emacs-helm.github.io/helm/">Emacs helm</a>, but without the technical debt. Indeed, much of the logic is contained in a small cleanly separated <a href="https://github.com/atlas-engineer/nyxt/tree/2-pre-release-7/libraries/prompter">prompter</a> library. (For the technically minded, the library is short of 1500 lines of Lisp code.)</p>
<h1 id="features">Features</h1>
<p>Let's review what makes the prompt buffer special.</p>
<h2 id="live-narrowing-and-fuzzy-searching.">Live narrowing and fuzzy-searching.</h2>
<p>Let's walk through an example of setting the URL:</p>
<p>Run <code>set-url</code> (bound to <code>C-l</code> by default, or click on the URL in the status area).</p>
<p>When you begin typing, you'll instantly note that <em>suggestions</em> update in real time.</p>
<p>Suggestions are filtered and sorted by fuzzy (non-exact) matching. There are several phases one can customize to filter/modify/redisplay suggestions to one's liking.</p>
<p>When you see the suggestion you like, select it (for instance with the up/down arrow keys) and press <code>return</code>.</p>
<h2 id="multiple-sources">Multiple sources</h2>
<p>So far so good, we've seen something similar to what the URL bar in many browser does.</p>
<p>That's where the familiarity ends and where the special side of the prompt buffer starts to shine!</p>
<p>Let's start with a simple frustration: why does the bar search known URLs only in the history instead of collecting all the known URLs from various sources? Why should I use a different bar to search my bookmarks for instance?</p>
<p>Well, the prompt buffer addresses this!</p>
<p>Notice how <code>set-url</code> suggestions are split by <em>sources</em>, such as &quot;New URL or search query&quot; or &quot;Global history&quot;. You can jump between sources with <code>C-pagedown</code> and <code>C-pageup</code>.</p>
<p>One of the most powerful design aspects of the prompt buffer is that sources can be reused in any prompt. Not only is it elegant from a programming perspective, but it's also beneficial to the end users since it allows them to easily customize <em>what</em> suggestions will be listed in any prompt.</p>
<p>For instance, you could easily customize the <code>set-url</code> prompt to remove the bookmark source, and add it to another prompt.</p>
<p>More on this in the <a href="./prompt-buffer-customization.org">Prompt buffer customization</a> article.</p>
<h2 id="multiple-actions">Multiple actions</h2>
<p>Say you call <code>set-url</code> and select a URL, but only then you decide to rather open it in a new buffer. With a regular prompt, you'd be forced to quit it, run the right UI element or command, find and select the URL again. This can quickly get cumbersome.</p>
<p>No problem with the prompt buffer: By pressing <code>M-return</code> after selecting the desired URL, you're a prompted with a list of possible actions you can run!</p>
<p><img src="../static/image/article/prompt-set-url-actions.png" /></p>
<p>Another benefit of actions is that it composes features. For instance, if we didn't have multiple-action support and if we wanted all the <em>N</em> URL-opening commands to have a way to open the result in a new buffer, we would need to define <em>N</em> more commands that would do the same as the original ones, only to open the result in a new buffer.</p>
<p>Without loss of generality, this means that for <em>P</em> actions common to <em>N</em> commands, we need <em>N*(P-1)</em> additional commands.</p>
<p>With support for multiple actions, the original <em>N</em> commands are enough!</p>
<p>Each source has its own set of <em>actions</em>. Technically, an action is any Lisp function run against the selection. More on this in the <em>Prompt buffer customization</em> article.</p>
<h2 id="multiple-selections">Multiple selections</h2>
<p>In the introduction, I hinted at the frustration of not being able to &quot;delete all Wikipedia buffers&quot;. So how do we solve this problem? The answer is simple: by marking the filtered suggestions.</p>
<p>Run <code>delete-buffer</code> for instance.</p>
<p><img src="../static/image/article/prompt-select-multiple.png" /></p>
<p>Notice that the prompt is followed by <code>[2/3]</code>, with <code>3</code> being the number of suggestions, and <code>2</code> the number of current <em>marks</em>. This means that you can &quot;mark&quot; (in other words, &quot;select&quot;) multiple suggestions with <code>C-space</code> by default.</p>
<p>Conveniently, marking automatically moves to the next suggestion, so you can keep <code>C-space</code> pressed to mark multiple elements in a row (press <code>shift-space</code> to mark backwards).</p>
<p>To list all marking keys, press <code>f1 b</code> and type <code>mark</code>.</p>
<p>The mark commands are togglers, so marking an already marked suggestion removes the mark.</p>
<p>Upon pressing <code>return</code>, all the marks are deleted.</p>
<p>Note that if you've marked at least one suggestion and if the current selection is not on a mark, it will <em>not</em> be applied in the resulting action. (In this particular example, it won't be deleted.)</p>
<p>Press <code>M-a</code> to mark all suggestions of a source. <code>M-u</code> to unmark all. If you want to apply an action on all elements save a few ones, it's more efficient to mark all elements first, then type some input to match the elements you want to unmark.</p>
<p>Let's answer our original question: to delete all Wikipedia buffers, run <code>delete-buffer</code>, type Wikipedia, press <code>M-a</code> to select all suggestions, make sure you remove non-Wikipedia mismatches and confirm the deletion with <code>return</code>!</p>
<h2 id="suggestion-attributes-and-togglable-column-display">Suggestion attributes and togglable column display</h2>
<p>The URL bar in popular browser display the URL and its associated title, but often that's it. What if you wanted to know more details about the URLs, such as the last time you accessed it? What about other pieces of data, such as bookmarks with their tags?</p>
<p>The prompt buffer tackles this problem by offering an extensible tabular display.</p>
<p><img src="../static/image/article/prompt-execute-command.png" /></p>
<p>When you run <code>execute-command</code> you'll notice that it displays multiple <em>attribute</em> columns by default. You can customize which attributes to display with <code>toggle-attributes-display</code> (<code>C-]</code> by default).</p>
<p>Only visible columns are matched against the user input. Thus, hiding some columns is an easy way to match against a specific one.</p>
<h2 id="follow-mode">&quot;Follow mode&quot;</h2>
<p>Some sources have a &quot;follow action&quot;, that is, an action that's run on the selection when it's changed, without closing the prompt.</p>
<p>This is convenient to run actions that may act as a preview or perform some other preprocessing.</p>
<p>For instance, <code>switch-buffer</code> has a default follow action which temporarily switches the current buffer to the one that's selected. Upon quit, the original buffer is restored.</p>
<h2 id="resumable-prompts">Resumable prompts</h2>
<p>Each prompt session is automatically recorded and can be resumed with <code>resume-prompt</code>.</p>
<p>This is particularly useful, say, to resume a search.</p>
<p><img src="../static/image/article/prompt-resume-command.png" /></p>
<h1 id="conclusion">Conclusion</h1>
<p>We hope you enjoy these new features, and that they help make you more productive.</p>
<p>Thanks for reading :-)</p>
</body>
</html>