atlas.engineer.atom.xml - sfeed_tests - sfeed tests and RSS and Atom files
(HTM) git clone git://git.codemadness.org/sfeed_tests
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
atlas.engineer.atom.xml (200408B)
---
1 <?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Nyxt Browser</title><link href="https://nyxt.atlas.engineer" /><link rel="self" href="https://nyxt.atlas.engineer/feed" /><updated>2003-12-13T18:30:02Z</updated><author><name>Atlas Engineer LLC</name></author><id>urn:uuid:c888f647-4c80-3284-8a1b-72c820f5e4d7</id><entry><id>urn:uuid:bb7836ba-30a9-3d29-a062-36082bb03e02</id><updated>2020-10-20T00:00:00.00+00:00</updated><title>Release 2 Pre Release 3</title><link href="https://nyxt.atlas.engineer/article/release-2-pre-release-3.org" /><content type="html"><!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="generator" content="pandoc" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
7 <title>Nyxt 2 Pre-release 3</title>
8 <style type="text/css">
9 code{white-space: pre-wrap;}
10 span.smallcaps{font-variant: small-caps;}
11 span.underline{text-decoration: underline;}
12 div.column{display: inline-block; vertical-align: top; width: 50%;}
13 </style>
14 <!--[if lt IE 9]>
15 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
16 <![endif]-->
17 </head>
18 <body>
19 <header>
20 <h1 class="title">Nyxt 2 Pre-release 3</h1>
21 </header>
22 <p>We are happy to announce the third pre-release of Nyxt version 2.0.0. If you missed the previous pre-release announcement, see <a href="https://nyxt.atlas.engineer/article/release-2-pre-release-2.org">here</a>.</p>
23 <p>Nyxt 2 is a massive overhaul of the Nyxt 1 series. A lot of effort has been geared towards improving the code quality under the hood which should reflect on the overall user experience with better performance, increased stability and better accessibility.</p>
24 <p>This is a test release for everyone to try out before the final release. It contains experimental features and some parts are still unfinished. Please feel free to share your feedback on our <a href="https://github.com/atlas-engineer/nyxt/issues">GitHub issue tracker</a>!</p>
25 <p>Notable highlights:</p>
26 <ul>
27 <li><p>New <code>import-bookmarks-from-html</code> command. Easily import your bookmarks from other browsers into Nyxt. (Thanks to <span class="citation" data-cites="kssytsrk">@kssytsrk</span> via GitHub.)</p></li>
28 <li><p>New <code>reduce-tracking-mode</code>. Reduce your online fingerprint.</p></li>
29 <li><p>New <code>reduce-to-buffer</code> command deletes buffers and lists them on a page. Useful for offloading inactive buffers and sending/saving a group of buffers.</p></li>
30 <li><p>New <code>toggle-toolbars</code> command hides/shows the visibility of the status area and the echo area.</p></li>
31 <li><p>New <code>execute-extended-command</code> command. You can now execute commands and interactively supply required, optional, and keyword parameters.</p></li>
32 <li><p><code>download-hint-url</code> now supports multiple selections. That means that you can download a set of links at once.</p></li>
33 <li><p>Quicklisp-based Lisp package manager. See the <code>list-systems</code>, <code>load-system</code> and <code>add-distribution</code> commands.</p></li>
34 <li><p>New <code>input-edit-mode</code>. You can now use commands like <code>cursor-forwards-word</code> in a HTML input buffer via <code>input-edit-mode</code>.</p></li>
35 <li><p>Added many bookmarklets (Javascripts utilities):</p>
36 <ul>
37 <li><p>color-internal-external-links</p></li>
38 <li><p>urls-as-link-text</p></li>
39 <li><p>hide-visited-urls</p></li>
40 <li><p>toggle-checkboxes</p></li>
41 <li><p>view-password-field-contents</p></li>
42 <li><p>show-hidden-form-elements</p></li>
43 <li><p>enlarge-textareas</p></li>
44 <li><p>show-textbox-character-count</p></li>
45 <li><p>highlight-regexp</p></li>
46 <li><p>zoom-images-in</p></li>
47 <li><p>zoom-images-out</p></li>
48 <li><p>sort-table</p></li>
49 <li><p>number-table-rows</p></li>
50 <li><p>number-lines</p></li>
51 <li><p>transpose-tables</p></li>
52 <li><p>remove-color</p></li>
53 <li><p>remove-images</p></li>
54 <li><p>hue-shift-positive</p></li>
55 <li><p>hue-shift-negative</p></li>
56 <li><p>increase-brightness</p></li>
57 <li><p>decrease-brightness</p></li>
58 <li><p>invert-color</p></li>
59 </ul></li>
60 </ul>
61 <p>For the complete change list, please consult the <a href="https://github.com/atlas-engineer/nyxt/blob/2-pre-release-2/documents/CHANGELOG.org#2-pre-release-2">CHANGELOG.org</a> file.</p>
62 <p>We hope you enjoy these new features, and that they help make you more productive. Thanks for reading :-)</p>
63 <h1 id="screenshots">Screenshots</h1>
64 <h2 id="reduce-to-buffer">Reduce to Buffer</h2>
65 <p><img src="../static/image/article/reduce-to-buffer-select.png" /></p>
66 <p><img src="../static/image/article/reduced-buffers.png" /></p>
67 <h2 id="bookmarklet-demonstration">Bookmarklet Demonstration</h2>
68 <p>Below is a demonstration of a coloring internal / external links uniquely.</p>
69 <p><img src="../static/image/article/color-internal-external.png" /></p>
70 <h2 id="load-system">Load System</h2>
71 <p>Quicklisp is neatly integrated into Nyxt allowing you to load and browse systems available.</p>
72 <p><img src="../static/image/article/load-system.png" /></p>
73 </body>
74 </html>
75 </content></entry><entry><id>urn:uuid:247f6507-f4eb-3728-a1ca-df77e2bb8218</id><updated>2020-10-08T00:00:00.00+00:00</updated><title>Bookmarklets</title><link href="https://nyxt.atlas.engineer/article/bookmarklets.org" /><content type="html"><!DOCTYPE html>
76 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
77 <head>
78 <meta charset="utf-8" />
79 <meta name="generator" content="pandoc" />
80 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
81 <title>Bookmarklets for better browsing</title>
82 <style type="text/css">
83 code{white-space: pre-wrap;}
84 span.smallcaps{font-variant: small-caps;}
85 span.underline{text-decoration: underline;}
86 div.column{display: inline-block; vertical-align: top; width: 50%;}
87 </style>
88 <style type="text/css">
89 a.sourceLine { display: inline-block; line-height: 1.25; }
90 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
91 a.sourceLine:empty { height: 1.2em; position: absolute; }
92 .sourceCode { overflow: visible; }
93 code.sourceCode { white-space: pre; position: relative; }
94 div.sourceCode { margin: 1em 0; }
95 pre.sourceCode { margin: 0; }
96 @media screen {
97 div.sourceCode { overflow: auto; }
98 }
99 @media print {
100 code.sourceCode { white-space: pre-wrap; }
101 a.sourceLine { text-indent: -1em; padding-left: 1em; }
102 }
103 pre.numberSource a.sourceLine
104 { position: relative; }
105 pre.numberSource a.sourceLine:empty
106 { position: absolute; }
107 pre.numberSource a.sourceLine::before
108 { content: attr(data-line-number);
109 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
110 border: none; pointer-events: all;
111 -webkit-touch-callout: none; -webkit-user-select: none;
112 -khtml-user-select: none; -moz-user-select: none;
113 -ms-user-select: none; user-select: none;
114 padding: 0 4px; width: 4em;
115 color: #aaaaaa;
116 }
117 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
118 div.sourceCode
119 { }
120 @media screen {
121 a.sourceLine::before { text-decoration: underline; }
122 }
123 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
124 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
125 code span.at { color: #7d9029; } /* Attribute */
126 code span.bn { color: #40a070; } /* BaseN */
127 code span.bu { } /* BuiltIn */
128 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
129 code span.ch { color: #4070a0; } /* Char */
130 code span.cn { color: #880000; } /* Constant */
131 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
132 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
133 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
134 code span.dt { color: #902000; } /* DataType */
135 code span.dv { color: #40a070; } /* DecVal */
136 code span.er { color: #ff0000; font-weight: bold; } /* Error */
137 code span.ex { } /* Extension */
138 code span.fl { color: #40a070; } /* Float */
139 code span.fu { color: #06287e; } /* Function */
140 code span.im { } /* Import */
141 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
142 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
143 code span.op { color: #666666; } /* Operator */
144 code span.ot { color: #007020; } /* Other */
145 code span.pp { color: #bc7a00; } /* Preprocessor */
146 code span.sc { color: #4070a0; } /* SpecialChar */
147 code span.ss { color: #bb6688; } /* SpecialString */
148 code span.st { color: #4070a0; } /* String */
149 code span.va { color: #19177c; } /* Variable */
150 code span.vs { color: #4070a0; } /* VerbatimString */
151 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
152 </style>
153 <!--[if lt IE 9]>
154 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
155 <![endif]-->
156 </head>
157 <body>
158 <header>
159 <h1 class="title">Bookmarklets for better browsing</h1>
160 </header>
161 <p>Bookmarklets are a feature in Nyxt that allow you to quickly create and consume snippets of JavaScript.</p>
162 <p>Wikipedia provides a succinct introduction and historical context:</p>
163 <blockquote>
164 <p>A bookmarklet is a bookmark stored in a web browser that contains JavaScript commands that add new features to the browser. Bookmarklets are unobtrusive JavaScripts stored as the URL of a bookmark in a web browser or as a hyperlink on a web page. Bookmarklets are usually JavaScript programs.</p>
165 </blockquote>
166 <p>Unlike in typical browsers, bookmarklets are not second-class citizens relegated to bookmarks- they are first-class commands! Because of their status in Nyxt, you can:</p>
167 <ul>
168 <li>bind snippets of JavaScript to a hotkey</li>
169 <li>chain JavaScript snippets in your workflows/command invokations</li>
170 <li>save snippets of JavaScript for later use</li>
171 </ul>
172 <p>Defining bookmarklets in Nyxt is straightforward:</p>
173 <div class="sourceCode" id="bookmarklet example" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="bookmarklet example-1" data-line-number="1">(define-bookmarklet-command color-internal-external-links</a>
174 <a class="sourceLine" id="bookmarklet example-2" data-line-number="2"> <span class="st">&quot;Color internal links red, external links blue, and in-page links orange.&quot;</span></a>
175 <a class="sourceLine" id="bookmarklet example-3" data-line-number="3"> <span class="st">&quot;(function(){var i,x; ...&quot;</span>)</a></code></pre></div>
176 <p>You provide:</p>
177 <ol>
178 <li>A name for your bookmarklet, this corresponds to its function/command</li>
179 <li>A documentation string describing what the bookmarklet does</li>
180 <li>Any JavaScript code you would like to run</li>
181 </ol>
182 <p>… and that's it!</p>
183 <p>We've included a collection of Bookmarklets we think would be useful in our <code>bookmarklets.lisp</code> file. They include commands to:</p>
184 <ul>
185 <li><code>color-internal-external-links</code>: Color internal links red, external links blue, and in-page links orange.</li>
186 <li><code>urls-as-link-text</code>: Changes the text of links to match their absolute URLs.</li>
187 <li><code>hide-visited-urls</code>: Hide visited URLs.</li>
188 <li><code>toggle-checkboxes</code>: Toggle all checkboxes.</li>
189 <li><code>view-password-field-contents</code>: View passwords on page.</li>
190 <li><code>show-hidden-form-elements</code>: Show hidden form elements.</li>
191 <li><code>enlarge-textareas</code>: Increase height of all text areas by 5 vertical lines.</li>
192 <li><code>show-textbox-character-count</code>: Displays a running count of the characters in each textbox.</li>
193 <li><code>highlight-regexp</code>: Highlights each match for a regular expression.</li>
194 <li><code>zoom-images-in</code>: Zoom images in.</li>
195 <li><code>zoom-images-out</code>: Zoom images out.</li>
196 <li><code>sort-table</code>: Sort a table alphabetically.</li>
197 <li><code>number-table-rows</code>: Add numbers to table rows.</li>
198 <li><code>number-lines</code>: Numberlines in plaintext documents and PRE tags.</li>
199 <li><code>transpose-tables</code>: Transpose all table row and columns.</li>
200 <li><code>remove-color</code>: Remove color from web pages.</li>
201 <li><code>remove-images</code>: Remove images from web pages.</li>
202 <li><code>hue-shift-positive</code>: Shift the colors of the web page with a positive hue.</li>
203 <li><code>hue-shift-negative</code>: Shift the colors of the web page with a negative hue.</li>
204 <li><code>increase-brightness</code>: Increase the brightness of the web page.</li>
205 <li><code>decrease-brightness</code>: Decrease the brightness of the web page.</li>
206 <li><code>invert-color</code>: Invert the color of the web page.</li>
207 </ul>
208 <p>The currently provided bookmarklets were sourced from <a href="https://www.squarefree.com/bookmarklets/">Jesse Ruderman's public domain works</a>.</p>
209 <p>A great illustration of how useful bookmarklets can be is shown below. We start with the Wikipedia page for Salmon.</p>
210 <p><img src="../static/image/article/sort-table-before.png" /></p>
211 <p>After executing our <code>sort-table</code> bookmarklet, every single table has a header above it that we can use to sort the elements in the table alphabetically, by column.</p>
212 <p><img src="../static/image/article/sort-table-after.png" /></p>
213 <p>We were then able to click and sort by &quot;Scientific Name&quot;.</p>
214 <p>We hope you enjoy using these bookmarklets and find many more to add to your collection!</p>
215 <p>Thanks for reading :-)</p>
216 </body>
217 </html>
218 </content></entry><entry><id>urn:uuid:6780ffb8-9047-310a-9441-50c296c7e6f7</id><updated>2020-10-02T00:00:00.00+00:00</updated><title>Class Based Functional Configuration</title><link href="https://nyxt.atlas.engineer/article/class-based-functional-configuration.org" /><content type="html"><!DOCTYPE html>
219 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
220 <head>
221 <meta charset="utf-8" />
222 <meta name="generator" content="pandoc" />
223 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
224 <title>Class-based, functional configuration</title>
225 <style type="text/css">
226 code{white-space: pre-wrap;}
227 span.smallcaps{font-variant: small-caps;}
228 span.underline{text-decoration: underline;}
229 div.column{display: inline-block; vertical-align: top; width: 50%;}
230 </style>
231 <style type="text/css">
232 a.sourceLine { display: inline-block; line-height: 1.25; }
233 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
234 a.sourceLine:empty { height: 1.2em; position: absolute; }
235 .sourceCode { overflow: visible; }
236 code.sourceCode { white-space: pre; position: relative; }
237 div.sourceCode { margin: 1em 0; }
238 pre.sourceCode { margin: 0; }
239 @media screen {
240 div.sourceCode { overflow: auto; }
241 }
242 @media print {
243 code.sourceCode { white-space: pre-wrap; }
244 a.sourceLine { text-indent: -1em; padding-left: 1em; }
245 }
246 pre.numberSource a.sourceLine
247 { position: relative; }
248 pre.numberSource a.sourceLine:empty
249 { position: absolute; }
250 pre.numberSource a.sourceLine::before
251 { content: attr(data-line-number);
252 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
253 border: none; pointer-events: all;
254 -webkit-touch-callout: none; -webkit-user-select: none;
255 -khtml-user-select: none; -moz-user-select: none;
256 -ms-user-select: none; user-select: none;
257 padding: 0 4px; width: 4em;
258 color: #aaaaaa;
259 }
260 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
261 div.sourceCode
262 { }
263 @media screen {
264 a.sourceLine::before { text-decoration: underline; }
265 }
266 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
267 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
268 code span.at { color: #7d9029; } /* Attribute */
269 code span.bn { color: #40a070; } /* BaseN */
270 code span.bu { } /* BuiltIn */
271 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
272 code span.ch { color: #4070a0; } /* Char */
273 code span.cn { color: #880000; } /* Constant */
274 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
275 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
276 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
277 code span.dt { color: #902000; } /* DataType */
278 code span.dv { color: #40a070; } /* DecVal */
279 code span.er { color: #ff0000; font-weight: bold; } /* Error */
280 code span.ex { } /* Extension */
281 code span.fl { color: #40a070; } /* Float */
282 code span.fu { color: #06287e; } /* Function */
283 code span.im { } /* Import */
284 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
285 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
286 code span.op { color: #666666; } /* Operator */
287 code span.ot { color: #007020; } /* Other */
288 code span.pp { color: #bc7a00; } /* Preprocessor */
289 code span.sc { color: #4070a0; } /* SpecialChar */
290 code span.ss { color: #bb6688; } /* SpecialString */
291 code span.st { color: #4070a0; } /* String */
292 code span.va { color: #19177c; } /* Variable */
293 code span.vs { color: #4070a0; } /* VerbatimString */
294 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
295 </style>
296 <!--[if lt IE 9]>
297 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
298 <![endif]-->
299 </head>
300 <body>
301 <header>
302 <h1 class="title">Class-based, functional configuration</h1>
303 </header>
304 <p>One of the strongest assets of Nyxt is its configurability: anything in the Common Lisp code base can be changed and extended.</p>
305 <p>While technically possible, it proved practically difficult to design a system that users could easily leverage. We were in dire need of a configuration framework that would accompany and empower the user beyond the capabilities of pure Lisp.</p>
306 <h1 id="case-study-emacs">Case study: Emacs</h1>
307 <p>The <a href="https://www.gnu.org/software/emacs/">Emacs</a> text editor is a model of extensible computer applications. Its legendary customizability has given birth to thousand of extensions.</p>
308 <p>Nyxt draws much from Emacs when it comes to extensibility, namely, by allowing the user to reprogram everything from their configuration file.</p>
309 <p>When Emacs was designed in the 1980s, it's likely that the developers didn't expect third-party extensions would play a significant role in the Emacs community. Nor did they expect, I suppose, that someday hardcore fans would use Emacs for everything, including their <a href="https://github.com/ch11ng/exwm">window manager</a>.</p>
310 <p>It isn't all perfect though. Emacs customizability comes with its load of limits, and it's common to read stories of &quot;configuration bankruptcy&quot; – a term coined to mean a user is overwhelmed by the complexity of their own configuration.</p>
311 <p>A frequent source of Emacs bankruptcy is inherent to its architecture: state. The state consistency of Emacs is one of its biggest weaknesses since much of its configuration is based on unguarded global values. This can lead to hard-to-debug configurations and conflicts between extensions.</p>
312 <h1 id="what-we-need">What we need</h1>
313 <p>With Nyxt, we envision the growth of a community and, hopefully, a vibrant library of third-party extensions! At the same time, we realize that the global state of Emacs is a limiting factor that must be fixed from the root, lest we reach a point of no return.</p>
314 <p>Starting from a configurability similar to Emacs (also using a Lisp language), here follows our specification:</p>
315 <ul>
316 <li><p>All configurable original values should be accessible at any time.</p></li>
317 <li><p>Default values should be configurable at any time (from the configuration file but also while running the browser).</p></li>
318 <li><p>Third-party packages should be able to offer customized core settings, or even settings for other third-party packages.</p></li>
319 <li><p>Any option or set of options should be reversible to a previous state (not just the original value). In particular, this would allow the user the switch themes and disable themes (something that does not work well in Emacs).</p></li>
320 <li><p>Sets of options should be composable. In particular, the user should be able to apply two option sets, choosing which one takes precedence.</p></li>
321 </ul>
322 <h1 id="initial-attempts">Initial attempts</h1>
323 <p>Common Lisp comes with a very powerful object-orientated system: <a href="https://en.wikipedia.org/wiki/Common_Lisp_Object_System">CLOS</a>. We figured out that we should leverage it since it does most of the heavy lifting when it comes to structuring data.</p>
324 <p>Almost all the data in Nyxt is structured into classes. Thus, configuring an option amounts to configuring a class <em>slot</em> (sometimes called an <em>attribute</em> in other languages).</p>
325 <p>The first obvious strategy that comes to mind is to make the slot default value point to a global variable which the user can customize:</p>
326 <div class="sourceCode" id="cb1" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb1-1" data-line-number="1">(<span class="kw">defvar</span><span class="fu"> *default-modes* </span>&#39;(web-mode base-mode))</a>
327 <a class="sourceLine" id="cb1-2" data-line-number="2">(<span class="kw">defvar</span><span class="fu"> *search-engines* </span>(<span class="kw">list</span> (<span class="kw">make-instance</span> &#39;search-engine</a>
328 <a class="sourceLine" id="cb1-3" data-line-number="3"> :shortcut <span class="st">&quot;wiki&quot;</span></a>
329 <a class="sourceLine" id="cb1-4" data-line-number="4"> :search-url <span class="st">&quot;https://en.wikipedia.org/w/index.php?search=~a&quot;</span></a>
330 <a class="sourceLine" id="cb1-5" data-line-number="5"> :fallback-url <span class="st">&quot;https://en.wikipedia.org/&quot;</span>)))</a>
331 <a class="sourceLine" id="cb1-6" data-line-number="6"></a>
332 <a class="sourceLine" id="cb1-7" data-line-number="7">(define-class buffer ()</a>
333 <a class="sourceLine" id="cb1-8" data-line-number="8"> ((default-modes *default-modes*)</a>
334 <a class="sourceLine" id="cb1-9" data-line-number="9"> <span class="co">;; More slots...</span></a>
335 <a class="sourceLine" id="cb1-10" data-line-number="10"> (search-engines *search-engines*)))</a></code></pre></div>
336 <p>The drawbacks are obvious:</p>
337 <ul>
338 <li>We need as many &quot;default&quot; variables as we have slots. This is a burden to maintain and prone to errors.</li>
339 <li>Being globals, replacing them means altering the global state, which opens the door for inconsistencies in the global state (the same problem as Emacs).</li>
340 <li>Changes to variables are irreversible: there is no way to access the previous state or the original state (unless it was saved manually).</li>
341 </ul>
342 <p>This approach is not sustainable. We need a better way. In particular, we wanted to follow a more &quot;functional&quot; paradigm (in the sense of <a href="https://en.wikipedia.org/wiki/Functional_programming">functional programming</a>) – without seeking purity.</p>
343 <p>CLOS is complex and powerful. Some parts are left unspecified. We initially thought we could leverage this hole in the specs to our advantage.</p>
344 <ol>
345 <li><p>We first tried to set the slot default value directly by leveraging the introspection library <code>closer-mop</code>. It worked with the <a href="http://www.sbcl.org/">SBCL</a> compiler but was not portable and very brittle, it was particularly difficult to handle inheritance correctly.</p></li>
346 <li><p>We tried to replace the class definition directly, for instance</p>
347 <div class="sourceCode" id="cb2" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb2-1" data-line-number="1">(<span class="kw">setf</span> (<span class="kw">find-class</span> &#39;buffer) (<span class="kw">find-class</span> &#39;my-buffer))</a></code></pre></div>
348 <p>This hack works as long as there is no inheritance. The new definition won't propagate to its children which results in inconsistent class definitions. This is too confusing and hard to maintain.</p></li>
349 <li><p>Use <code>closer-mop:ensure-class</code> to redefine the class as above. This would trigger the CLOS internals to update all the child classes, thus fixing the inheritance issue. Problem: How do we redefine a single slot without rewriting the code for all slots? Using the above <code>buffer</code> example, if we write</p>
350 <div class="sourceCode" id="cb3" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb3-1" data-line-number="1">(define-class buffer () <span class="co">; New definition.</span></a>
351 <a class="sourceLine" id="cb3-2" data-line-number="2"> ((default-modes &#39;(new modes))))</a></code></pre></div>
352 <p>it would define a new <code>buffer</code> class without any slot but the <code>default-modes</code>. It seems there is no good way to say &quot;insert the rest of original slots here&quot;.</p></li>
353 </ol>
354 <h1 id="class-composition">Class composition</h1>
355 <p>In computer science, it can be considered good practice to use composition instead of inheritance for increased flexibility and less complexity. This is what led us to implement what we call &quot;user classes&quot;: slot-less classes that only inherit from a list of classes, namely the original class followed by the specialized classes. To clarify, let's consider this example with the <code>buffer</code> class:</p>
356 <div class="sourceCode" id="cb4" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb4-1" data-line-number="1">(define-class buffer ()</a>
357 <a class="sourceLine" id="cb4-2" data-line-number="2"> ((default-modes *default-modes*)</a>
358 <a class="sourceLine" id="cb4-3" data-line-number="3"> <span class="co">;; More slots...</span></a>
359 <a class="sourceLine" id="cb4-4" data-line-number="4"> (search-engines *search-engines*)))</a>
360 <a class="sourceLine" id="cb4-5" data-line-number="5"></a>
361 <a class="sourceLine" id="cb4-6" data-line-number="6">(define-class user-buffer (buffer))</a></code></pre></div>
362 <p>Whenever we want to instantiate a buffer, we call</p>
363 <div class="sourceCode" id="cb5" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb5-1" data-line-number="1">(<span class="kw">make-instance</span> &#39;user-buffer)</a></code></pre></div>
364 <p>Why is this interesting? Because now you can safely redefine the user class without touching the original <code>buffer</code> class:</p>
365 <div class="sourceCode" id="cb6" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb6-1" data-line-number="1">(define-class my-buffer ()</a>
366 <a class="sourceLine" id="cb6-2" data-line-number="2"> ((default-modes &#39;(my-mode web-mode base-mode))))</a>
367 <a class="sourceLine" id="cb6-3" data-line-number="3"></a>
368 <a class="sourceLine" id="cb6-4" data-line-number="4">(define-class user-buffer (my-buffer buffer))</a></code></pre></div>
369 <p>Our user-buffer override now inherits from <code>my-buffer</code> and <code>buffer</code>. Parent classes are ordered by priority, with the highest priority being first. This means that <code>user-buffer</code> will use the <code>default-modes</code> slot from <code>my-buffer</code> and the rest of its slots from <code>buffer</code>.</p>
370 <p>This resolves our problem statement: no globals (beside <code>user-buffer</code>), we keep access to the original value, we compose all settings and we can revert any change. Indeed, should you decide you want to remove the defaults of <code>my-buffer</code>, you can redefine <code>user-buffer</code> without it.</p>
371 <p>Even though the syntax is relatively light, we offer the <code>define-configuration</code> helper macro:</p>
372 <div class="sourceCode" id="cb7" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb7-1" data-line-number="1">(define-configuration buffer</a>
373 <a class="sourceLine" id="cb7-2" data-line-number="2"> ((search-engines (<span class="kw">append</span> my-search-engines %slot-default))</a>
374 <a class="sourceLine" id="cb7-3" data-line-number="3"> (bookmarks-path (<span class="kw">make-instance</span> &#39;bookmarks-data-path</a>
375 <a class="sourceLine" id="cb7-4" data-line-number="4"> :basename <span class="st">&quot;~/personal/bookmarks.lisp.gpg&quot;</span>))))</a></code></pre></div>
376 <p>This macro comes with some benefits:</p>
377 <ul>
378 <li><p>It's shorter and easier to write, the user class is automatically updated for you.</p></li>
379 <li><p>It displays a warning when the slot name is unknown, which is convenient for catching typos.</p></li>
380 <li><p>It binds <code>%slot-default</code> to the default value of the class slot which enables convenient modification. This allows the user to automatically adapt the new default to new versions of Nyxt.</p></li>
381 </ul>
382 <h1 id="conclusions-and-thoughts">Conclusions and thoughts</h1>
383 <p>Our approach is both powerful and flexible. The user has the ability to change <em>any</em> value at runtime – without risk of corrupting global state. Each buffer, or any other class instantiated objects, can be safely manipulated and reverted without fear of repercussion.</p>
384 <p>We would like to encourage other programs and programmers to empower their users using similar techniques. Give users the tools they need to adapt and modify their programs to suit their workflow!</p>
385 <p>A tool that works for the 80% is great when you are doing common work, but when you are doing extraordinary work, that extra 20% makes the difference.</p>
386 <p>Thanks for reading :-)</p>
387 </body>
388 </html>
389 </content></entry><entry><id>urn:uuid:1860537e-3dde-31ba-9488-05c128041508</id><updated>2020-09-24T00:00:00.00+00:00</updated><title>Release 2 Pre Release 2</title><link href="https://nyxt.atlas.engineer/article/release-2-pre-release-2.org" /><content type="html"><!DOCTYPE html>
390 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
391 <head>
392 <meta charset="utf-8" />
393 <meta name="generator" content="pandoc" />
394 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
395 <title>Nyxt 2 Pre-release 2</title>
396 <style type="text/css">
397 code{white-space: pre-wrap;}
398 span.smallcaps{font-variant: small-caps;}
399 span.underline{text-decoration: underline;}
400 div.column{display: inline-block; vertical-align: top; width: 50%;}
401 </style>
402 <!--[if lt IE 9]>
403 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
404 <![endif]-->
405 </head>
406 <body>
407 <header>
408 <h1 class="title">Nyxt 2 Pre-release 2</h1>
409 </header>
410 <p>We are happy to announce the second pre-release of Nyxt version 2.0.0. If you missed the previous pre-release announcement, see <a href="https://nyxt.atlas.engineer/article/release-2-pre-release-1.org">here</a>.</p>
411 <p>Nyxt 2 is a massive overhaul of the Nyxt 1 series. A lot of effort has been geared towards improving the code quality under the hood which should reflect on the overall user experience with better performance, increased stability and better accessibility.</p>
412 <p>This is a test release for everyone to try out before the final release. It contains experimental features and some parts are still unfinished. Please feel free to share your feedback on our <a href="https://github.com/atlas-engineer/nyxt/issues">GitHub issue tracker</a>!</p>
413 <p>Notable highlights:</p>
414 <ul>
415 <li><p>New startup page.</p></li>
416 <li><p>New &quot;common settings&quot; page. A button was added to configure any slot in the class description buffers. See <a href="https://nyxt.atlas.engineer/article/common-settings.org">this article</a> for more details.</p></li>
417 <li><p>New <code>nosound-mode</code> to mute individual buffers.</p></li>
418 <li><p>New <code>search-selection</code> command.</p>
419 <p>It allows to query the highlighted text with a given search engine. It is particularly useful for dictionaries.</p></li>
420 <li><p>Puny-encoded URLs are now human-readable.</p></li>
421 <li><p>The <code>M-i</code> binding toggles the transparency of element hints.</p></li>
422 <li><p>New session dumping commands, namely <code>store-session-by-name</code>, <code>restore-session-by-name</code> and <code>replace-session-by-name</code>.</p></li>
423 </ul>
424 <p>For the complete change list, please consult the <a href="https://github.com/atlas-engineer/nyxt/blob/2-pre-release-2/documents/CHANGELOG.org#2-pre-release-2">CHANGELOG.org</a> file.</p>
425 <p>We hope you enjoy these new features, and that they help make you more productive. Thanks for reading :-)</p>
426 <h1 id="screenshots">Screenshots</h1>
427 <h2 id="new-startup-page">New startup page</h2>
428 <p><img src="../static/image/article/help-page.png" /></p>
429 <h2 id="new-graphical-settings-page">New graphical settings page</h2>
430 <p><img src="../static/image/article/common-settings.png" /></p>
431 </body>
432 </html>
433 </content></entry><entry><id>urn:uuid:1be4caf5-78dc-39a6-b342-431bc5ce476a</id><updated>2020-09-23T00:00:00.00+00:00</updated><title>Common Settings</title><link href="https://nyxt.atlas.engineer/article/common-settings.org" /><content type="html"><!DOCTYPE html>
434 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
435 <head>
436 <meta charset="utf-8" />
437 <meta name="generator" content="pandoc" />
438 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
439 <title>Common Settings and Easy Configuration</title>
440 <style type="text/css">
441 code{white-space: pre-wrap;}
442 span.smallcaps{font-variant: small-caps;}
443 span.underline{text-decoration: underline;}
444 div.column{display: inline-block; vertical-align: top; width: 50%;}
445 </style>
446 <style type="text/css">
447 a.sourceLine { display: inline-block; line-height: 1.25; }
448 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
449 a.sourceLine:empty { height: 1.2em; position: absolute; }
450 .sourceCode { overflow: visible; }
451 code.sourceCode { white-space: pre; position: relative; }
452 div.sourceCode { margin: 1em 0; }
453 pre.sourceCode { margin: 0; }
454 @media screen {
455 div.sourceCode { overflow: auto; }
456 }
457 @media print {
458 code.sourceCode { white-space: pre-wrap; }
459 a.sourceLine { text-indent: -1em; padding-left: 1em; }
460 }
461 pre.numberSource a.sourceLine
462 { position: relative; }
463 pre.numberSource a.sourceLine:empty
464 { position: absolute; }
465 pre.numberSource a.sourceLine::before
466 { content: attr(data-line-number);
467 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
468 border: none; pointer-events: all;
469 -webkit-touch-callout: none; -webkit-user-select: none;
470 -khtml-user-select: none; -moz-user-select: none;
471 -ms-user-select: none; user-select: none;
472 padding: 0 4px; width: 4em;
473 color: #aaaaaa;
474 }
475 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
476 div.sourceCode
477 { }
478 @media screen {
479 a.sourceLine::before { text-decoration: underline; }
480 }
481 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
482 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
483 code span.at { color: #7d9029; } /* Attribute */
484 code span.bn { color: #40a070; } /* BaseN */
485 code span.bu { } /* BuiltIn */
486 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
487 code span.ch { color: #4070a0; } /* Char */
488 code span.cn { color: #880000; } /* Constant */
489 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
490 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
491 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
492 code span.dt { color: #902000; } /* DataType */
493 code span.dv { color: #40a070; } /* DecVal */
494 code span.er { color: #ff0000; font-weight: bold; } /* Error */
495 code span.ex { } /* Extension */
496 code span.fl { color: #40a070; } /* Float */
497 code span.fu { color: #06287e; } /* Function */
498 code span.im { } /* Import */
499 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
500 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
501 code span.op { color: #666666; } /* Operator */
502 code span.ot { color: #007020; } /* Other */
503 code span.pp { color: #bc7a00; } /* Preprocessor */
504 code span.sc { color: #4070a0; } /* SpecialChar */
505 code span.ss { color: #bb6688; } /* SpecialString */
506 code span.st { color: #4070a0; } /* String */
507 code span.va { color: #19177c; } /* Variable */
508 code span.vs { color: #4070a0; } /* VerbatimString */
509 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
510 </style>
511 <!--[if lt IE 9]>
512 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
513 <![endif]-->
514 </head>
515 <body>
516 <header>
517 <h1 class="title">Common Settings and Easy Configuration</h1>
518 </header>
519 <p>Common settings and easy configuration recently landed in Nyxt! Now it is possible to set the value of any class/slot from the UI! You don't need to know any Lisp.</p>
520 <p>When you first start Nyxt, our new <code>*help*</code> page presents you with some helpful buttons to click on:</p>
521 <p><img src="../static/image/article/help-page.png" /></p>
522 <p>If you click on <code>Common settings</code>, you'll be presented with a simple menu where you can select your favorite keybinding scheme, home page URL, and zoom level.</p>
523 <p><img src="../static/image/article/common-settings.png" /></p>
524 <p>Your settings will automatically be saved and reloaded whenever you start Nyxt!</p>
525 <p>Don't worry about overwriting changes to your <code>init.lisp</code> file, these changes are automatically stored in a separate <code>auto-config.lisp</code> file. This file is loaded <strong>before</strong> your <code>init.lisp</code> file so that you can always override any configuration.</p>
526 <p>Here's what would be appended to your <code>auto-config.lisp</code> file if you clicked on <code>Use Emacs</code> in the common settings screen.</p>
527 <div class="sourceCode" id="configuration" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="configuration-1" data-line-number="1">(DEFINE-CONFIGURATION WEB-BUFFER</a>
528 <a class="sourceLine" id="configuration-2" data-line-number="2"> ((DEFAULT-MODES &#39;(EMACS-MODE CERTIFICATE-EXCEPTION-MODE WEB-MODE BASE-MODE))))</a></code></pre></div>
529 <p>No magic. Transparent, straightforward Lisp.</p>
530 <p>Beyond customization of common settings, we've added the ability to customize any class or slot from the <code>describe-slot</code> and <code>describe-class</code> commands.</p>
531 <p>Below you can see an example of how we can customize a class:</p>
532 <p><img src="../static/image/article/describe-class.png" /></p>
533 <p>Every single slot marked with <code>Configure</code> will allow you to input whatever value you like. Anything that is introspectable is customizable!</p>
534 <p>Let's run through an example: let's change the height of our status buffer.</p>
535 <p>First you would find the slot that you are interested in, in this case the status buffer height slot.</p>
536 <p><img src="../static/image/article/describe-slot-status-buffer-query.png" /></p>
537 <p>Then you would view the current value, the default form, and the documentation. From this screen, you can press <code>Configure</code>. After pressing <code>Configure</code>, you will be prompted for a new value. Input any valid value you would like.</p>
538 <p><img src="../static/image/article/configure-slot-value.png" /></p>
539 <p>After you supply your new value, any new windows (even after restarting Nyxt) will utilize the new value for the status buffer height! That's it!</p>
540 <p><img src="../static/image/article/configure-result.png" /></p>
541 <p>Please note: configuration changes only affect new instances of an object, not existing ones.</p>
542 <p>Thanks for reading :-)</p>
543 </body>
544 </html>
545 </content></entry><entry><id>urn:uuid:3066e4f1-b97c-3501-921d-88eb1c410795</id><updated>2020-09-14T00:00:00.00+00:00</updated><title>Fosdem Presentation</title><link href="https://nyxt.atlas.engineer/article/fosdem-presentation.org" /><content type="html"><!DOCTYPE html>
546 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
547 <head>
548 <meta charset="utf-8" />
549 <meta name="generator" content="pandoc" />
550 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
551 <title>FOSDEM Presentation</title>
552 <style type="text/css">
553 code{white-space: pre-wrap;}
554 span.smallcaps{font-variant: small-caps;}
555 span.underline{text-decoration: underline;}
556 div.column{display: inline-block; vertical-align: top; width: 50%;}
557 </style>
558 <!--[if lt IE 9]>
559 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
560 <![endif]-->
561 </head>
562 <body>
563 <header>
564 <h1 class="title">FOSDEM Presentation</h1>
565 </header>
566 <p>On February 2nd, 2020, we had the privilege of attending FOSDEM where we were able to present a lightning talk about Nyxt (Next, at the time).</p>
567 <p>Nyxt has progressed a lot since then, but we still find it very interesting. Enjoy :-)</p>
568 <p><a href="../static/video/fosdem-presentation.mp4">FOSDEM Video</a></p>
569 <p>To see the FOSDEM URL for this presentation please click here: <a href="https://archive.fosdem.org/2020/schedule/event/next_web_browser/" class="uri">https://archive.fosdem.org/2020/schedule/event/next_web_browser/</a></p>
570 </body>
571 </html>
572 </content></entry><entry><id>urn:uuid:fe2e6b09-ab2f-382f-ba00-49856422b91d</id><updated>2020-10-16T00:00:00.00+00:00</updated><title>Auto Mode</title><link href="https://nyxt.atlas.engineer/article/auto-mode.org" /><content type="html"><!DOCTYPE html>
573 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
574 <head>
575 <meta charset="utf-8" />
576 <meta name="generator" content="pandoc" />
577 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
578 <meta name="author" content="Artyom Bologov" />
579 <title>auto-mode will take care of your VPN when you forget!</title>
580 <style type="text/css">
581 code{white-space: pre-wrap;}
582 span.smallcaps{font-variant: small-caps;}
583 span.underline{text-decoration: underline;}
584 div.column{display: inline-block; vertical-align: top; width: 50%;}
585 </style>
586 <style type="text/css">
587 a.sourceLine { display: inline-block; line-height: 1.25; }
588 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
589 a.sourceLine:empty { height: 1.2em; position: absolute; }
590 .sourceCode { overflow: visible; }
591 code.sourceCode { white-space: pre; position: relative; }
592 div.sourceCode { margin: 1em 0; }
593 pre.sourceCode { margin: 0; }
594 @media screen {
595 div.sourceCode { overflow: auto; }
596 }
597 @media print {
598 code.sourceCode { white-space: pre-wrap; }
599 a.sourceLine { text-indent: -1em; padding-left: 1em; }
600 }
601 pre.numberSource a.sourceLine
602 { position: relative; }
603 pre.numberSource a.sourceLine:empty
604 { position: absolute; }
605 pre.numberSource a.sourceLine::before
606 { content: attr(data-line-number);
607 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
608 border: none; pointer-events: all;
609 -webkit-touch-callout: none; -webkit-user-select: none;
610 -khtml-user-select: none; -moz-user-select: none;
611 -ms-user-select: none; user-select: none;
612 padding: 0 4px; width: 4em;
613 color: #aaaaaa;
614 }
615 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
616 div.sourceCode
617 { }
618 @media screen {
619 a.sourceLine::before { text-decoration: underline; }
620 }
621 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
622 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
623 code span.at { color: #7d9029; } /* Attribute */
624 code span.bn { color: #40a070; } /* BaseN */
625 code span.bu { } /* BuiltIn */
626 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
627 code span.ch { color: #4070a0; } /* Char */
628 code span.cn { color: #880000; } /* Constant */
629 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
630 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
631 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
632 code span.dt { color: #902000; } /* DataType */
633 code span.dv { color: #40a070; } /* DecVal */
634 code span.er { color: #ff0000; font-weight: bold; } /* Error */
635 code span.ex { } /* Extension */
636 code span.fl { color: #40a070; } /* Float */
637 code span.fu { color: #06287e; } /* Function */
638 code span.im { } /* Import */
639 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
640 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
641 code span.op { color: #666666; } /* Operator */
642 code span.ot { color: #007020; } /* Other */
643 code span.pp { color: #bc7a00; } /* Preprocessor */
644 code span.sc { color: #4070a0; } /* SpecialChar */
645 code span.ss { color: #bb6688; } /* SpecialString */
646 code span.st { color: #4070a0; } /* String */
647 code span.va { color: #19177c; } /* Variable */
648 code span.vs { color: #4070a0; } /* VerbatimString */
649 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
650 </style>
651 <!--[if lt IE 9]>
652 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
653 <![endif]-->
654 </head>
655 <body>
656 <header>
657 <h1 class="title">auto-mode will take care of your VPN when you forget!</h1>
658 <p class="author">Artyom Bologov</p>
659 </header>
660 <p>Your Internet privacy routine can be simple or complicated, ritualistic or conscious, but it's always this – <em>routine</em>. It helps you to leave less data for other people to exploit… Until you forget!</p>
661 <p>While browsers and extensions offer some options- like blocklisting the websites you want your VPN to be turned on, or even remembering settings domain-wise, it's usually not scalable and transferable between different extensions. It's hard to learn ten different mechanisms and use them everyday to preserve your privacy.</p>
662 <p>That's where Nyxt's new <code>auto-mode</code> can help you. It remembers the modes you enable and disable for different URLs and reapplies them automatically.</p>
663 <h1 id="how-to-use-it">How to use it?</h1>
664 <p>Just add <code>auto-mode</code> to your buffer <code>default-modes</code>:</p>
665 <div class="sourceCode" id="cb1" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb1-1" data-line-number="1">(define-configuration buffer</a>
666 <a class="sourceLine" id="cb1-2" data-line-number="2"> ((default-modes (<span class="kw">append</span> &#39;(auto-mode) %slot-default))))</a></code></pre></div>
667 <p>Now, if you navigate to a web page, enable <code>proxy-mode</code>, and execute <code>save-non-default-modes-for-future-visits</code>, <code>proxy-mode</code> will be automatically reapplied when you vist again. Your rules can be activated on the main domain of a website, any of its subdomains, or even on specific pages, depending on what you input. In addition to reapplying modes, <code>auto-mode</code> will automatically deactivate modes when they are no longer relevant.</p>
668 <p>If you get back to the page you saved <code>proxy-mode</code> for, it will be enabled and you'll access the page with a new IP, without any action on your part. Easy, huh? That's what <code>auto-mode</code> will do for you all the time. It will remember your modes and enable them right when you need them!</p>
669 <h1 id="this-command-is-hard-to-type-is-there-an-alternative">This command is hard to type! Is there an alternative?</h1>
670 <p>If you don't want to type in the long <code>save-non-default-...</code> command name (even though it's fuzzy-completed), there's an option for you! Just enable chatty prompting on mode toggles that <code>auto-mode</code> has as a configuration variable:</p>
671 <div class="sourceCode" id="cb2" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb2-1" data-line-number="1">(define-configuration nyxt/auto-mode:auto-mode</a>
672 <a class="sourceLine" id="cb2-2" data-line-number="2"> ((nyxt/auto-mode:prompt-on-mode-toggle <span class="kw">t</span>)))</a></code></pre></div>
673 <p>It's simple and convenient. Say, you open some web page and enable <code>proxy-mode</code>. That's what you'll see:</p>
674 <p><img src="../static/image/article/auto-mode-permanent.png" /></p>
675 <p>If you answer &quot;yes&quot;, you'll be prompted for a URL to save this mode for, as in <code>save-non-default-modes-for-future-visits</code>. The rule will be created in the same way, but you won't need to call any command – <code>auto-mode</code> will ask you about saving modes when you toggle them.</p>
676 <h1 id="how-do-i-change-the-auto-mode-rules">How do I change the auto-mode rules?</h1>
677 <p>There are two ways:</p>
678 <ul>
679 <li>you can browse your usual websites and use <code>auto-mode</code> to re-save the modes you enable, or</li>
680 <li>you can edit the file that <code>auto-mode</code> saves all the rules in.</li>
681 </ul>
682 <p>The rules file is stored in <code>~/.local/share/nyxt/auto-mode-rules.lisp</code>. (You can redefine it to use a different path and even to use GPG-encryption!) This file is made exactly in a way that enables you to easily edit it!</p>
683 <p>When you open it, you'll be presented with a header explaining all the formatting of <code>auto-mode</code> rules, so you won't ever be lost! Here are the shortened rules:</p>
684 <ul>
685 <li>Every rule is delimited by a newline.</li>
686 <li>Rules can have test, <code>:excluded</code> modes, <code>:included</code> modes and they can be <code>:exact-p</code>.
687 <ul>
688 <li>Test is the first thing in the rule. It relies on <code>match-*</code> functions heavily, so you can look up their documentation with Nyxt's <code>describe-function</code> and use them however you want!</li>
689 <li><code>:included</code> modes are the ones that will always be enabled when the URL matches this rule.</li>
690 <li><code>:excluded</code> modes will be always disabled when this rule matches.</li>
691 <li><code>:exact-p</code> denotes whether you want <em>exactly this list of modes</em> to be enabled for this rule or you just want to enable/disable the listed modes in addition to the present ones. See the documentation of <code>save-exact-modes-for-future-visits</code> for more information.</li>
692 </ul></li>
693 </ul>
694 <p>That's almost everything you need to know to create new rules and edit the existing ones!</p>
695 <h1 id="what-about-other-uses-of-auto-mode">What about other uses of <code>auto-mode</code>?</h1>
696 <p>Maybe you like <code>noscript-mode</code> and <code>noimage-mode</code>, because they speed up browsing, at the cost of breaking some sites. <code>auto-mode</code> is the perfect solution for this kind of problems: simply disable <code>noscript-mode</code> or <code>noimage-mode</code> when required and your preferences will be remembered!</p>
697 <p><code>auto-mode</code> is about toggling modes, so anything that can be represented as mode can be automated by it! The more modes there are, the more powerful <code>auto-mode</code> will become, so don't hesitate to use it and create new modes to automate your Internet routine!</p>
698 <p>Thanks for reading :-)</p>
699 </body>
700 </html>
701 </content></entry><entry><id>urn:uuid:d452421c-46dd-3132-a2f3-89fa0a4633f0</id><updated>2020-09-02T00:00:00.00+00:00</updated><title>Release 2 Pre Release 1</title><link href="https://nyxt.atlas.engineer/article/release-2-pre-release-1.org" /><content type="html"><!DOCTYPE html>
702 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
703 <head>
704 <meta charset="utf-8" />
705 <meta name="generator" content="pandoc" />
706 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
707 <title>Nyxt 2 Pre-release 1</title>
708 <style type="text/css">
709 code{white-space: pre-wrap;}
710 span.smallcaps{font-variant: small-caps;}
711 span.underline{text-decoration: underline;}
712 div.column{display: inline-block; vertical-align: top; width: 50%;}
713 </style>
714 <!--[if lt IE 9]>
715 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
716 <![endif]-->
717 </head>
718 <body>
719 <header>
720 <h1 class="title">Nyxt 2 Pre-release 1</h1>
721 </header>
722 <p>If the above title was confusing, don't worry, you're not alone :-). We are happy to announce the first pre-release of Nyxt version 2.0.0.</p>
723 <p>Nyxt 2 is a massive overhaul of the Nyxt 1 series. A lot of effort has been geared towards improving the code quality under the hood which should reflect on the overall user experience with better performance, increased stability and better accessibility.</p>
724 <p>This is a test release for everyone to try out before the final release. It contains experimental features and some parts are still unfinished. Please feel free to share your feedback on our <a href="https://github.com/atlas-engineer/nyxt/issues">GitHub issue tracker</a>!</p>
725 <p>Notable highlights:</p>
726 <ul>
727 <li>Use the new <code>auto-mode</code> to automatically load a configured set of modes for matching URLs and predicates. For instance, Nyxt can automatically enable proxy-mode when navigating to Wikipedia and disable it otherwise.</li>
728 <li>Use the new <code>autofill</code> command to insert predefined or computed content in text fields, such as the current date. You can use this to speed up filling of forms.</li>
729 <li>Support for <code>data-profiles</code>. Data profiles help you customize data separation easily and flexibly, e.g. a &quot;work&quot; instance of Nyxt may use different cookies but the same bookmarks as the &quot;personal&quot; instance.</li>
730 <li>New <code>--script</code> command line option that can be used in shabangs to write &quot;Nyxt scripts.&quot;</li>
731 <li>New <code>lisp-repl</code> command to evaluate Lisp, introspect and modify Nyxt while it's running, from the browser itself!</li>
732 <li>Built-in <code>tutorial</code> and <code>manual</code> commands.</li>
733 <li>New documentation commands: <code>describe-function</code>, <code>describe-slot</code>, <code>describe-class</code>, <code>describe-key</code>, <code>describe-bindings</code>. These commands allow you to quickly introspect any part of Nyxt.</li>
734 <li>Improved macOS performance with support for Quartz renderer. No more dependency on XQuartz.</li>
735 <li>No more D-Bus. We've moved to direct web renderer bindings (leveraging the CFFI library), and the responsiveness of the Nyxt interface is better than ever!</li>
736 <li>Built-in spell checker/suggestions.</li>
737 </ul>
738 <p>For the complete change list, please consult the <a href="https://github.com/atlas-engineer/nyxt/blob/14ad9eb1d835950257d031e78126625546ebe996/documents/CHANGELOG.org#2-pre-release-1">CHANGELOG.org</a> file.</p>
739 <p>We hope you enjoy these new features, and that they help make you more productive. Thanks for reading :-)</p>
740 <h1 id="screenshots">Screenshots</h1>
741 <h2 id="autofills">Autofills</h2>
742 <p>Use Autofills to conveniently fill in data:</p>
743 <p><img src="../static/image/animation/auto-fill.gif" /></p>
744 <h2 id="clipboard-history">Clipboard history</h2>
745 <p>Remember all of your clipboard history:</p>
746 <p><img src="../static/image/animation/paste-ring.gif" /></p>
747 <h2 id="intelligent-bookmark-search">Intelligent bookmark search</h2>
748 <p>Use compound queries with <code>AND</code> and <code>OR</code> to find your bookmarks!</p>
749 <p><img src="../static/image/bookmark.png" /></p>
750 <h2 id="built-in-repl">Built-in REPL</h2>
751 <p>Use the built-in REPL to program your browser on the fly.</p>
752 <p><img src="../static/image/animation/lisp-repl.gif" /></p>
753 <h2 id="powerful-link-hinting">Powerful link hinting</h2>
754 <p>Use link hinting to quickly jump around. You can jump to a link by its URL, title, or two/three letter shortcut.</p>
755 <p><img src="../static/image/animation/link-hint.gif" /></p>
756 </body>
757 </html>
758 </content></entry><entry><id>urn:uuid:7c15c026-c66c-3fb8-9964-3c01564b5509</id><updated>2020-08-31T00:00:00.00+00:00</updated><title>Debconf Presentation</title><link href="https://nyxt.atlas.engineer/article/debconf-presentation.org" /><content type="html"><!DOCTYPE html>
759 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
760 <head>
761 <meta charset="utf-8" />
762 <meta name="generator" content="pandoc" />
763 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
764 <title>DebConf Presentation</title>
765 <style type="text/css">
766 code{white-space: pre-wrap;}
767 span.smallcaps{font-variant: small-caps;}
768 span.underline{text-decoration: underline;}
769 div.column{display: inline-block; vertical-align: top; width: 50%;}
770 </style>
771 <!--[if lt IE 9]>
772 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
773 <![endif]-->
774 </head>
775 <body>
776 <header>
777 <h1 class="title">DebConf Presentation</h1>
778 </header>
779 <p>This year we got to participate in the virtual Debconf lightning talks! We enjoyed making a short little demonstration of Nyxt, and we hope you like it too!</p>
780 <p><a href="../static/video/debconf-compressed.mp4">DebConf Video</a></p>
781 <p>Thanks for watching :-)</p>
782 </body>
783 </html>
784 </content></entry><entry><id>urn:uuid:5c0223a5-454b-3675-b412-1ad387e8456b</id><updated>2020-08-26T00:00:00.00+00:00</updated><title>Release 1.3.3</title><link href="https://nyxt.atlas.engineer/article/release-1.3.3.org" /><content type="html"><!DOCTYPE html>
785 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
786 <head>
787 <meta charset="utf-8" />
788 <meta name="generator" content="pandoc" />
789 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
790 <title>Nyxt release 1.3.3</title>
791 <style type="text/css">
792 code{white-space: pre-wrap;}
793 span.smallcaps{font-variant: small-caps;}
794 span.underline{text-decoration: underline;}
795 div.column{display: inline-block; vertical-align: top; width: 50%;}
796 </style>
797 <!--[if lt IE 9]>
798 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
799 <![endif]-->
800 </head>
801 <body>
802 <header>
803 <h1 class="title">Nyxt release 1.3.3</h1>
804 </header>
805 <p>After another short but intense development cycle, we are happy to announce the availability of <a href="http://next.atlas.engineer/">Nyxt</a> version 1.3.3!</p>
806 <p>This version brings outstanding and unique features (again!). It is also easier to install on GNU/Linux thanks to a Debian package. Please see all installation options on the <a href="https://next.atlas.engineer/download">download page</a>.</p>
807 <h1 id="new-features">New features</h1>
808 <h2 id="multiple-input-selection">Multiple input selection</h2>
809 <p>Until now, Nyxt's prompt was able to ask the user for <em>one</em> choice among a list (with fuzzy completion). Now, for commands that support it, the user can select <strong>multiple candidates</strong> and apply an action on all of them (for example, to delete many buffers at once). We can <strong>filter and narrow</strong> the selection with a text input, and we can select all the visible candidates or unselect the current ones.</p>
810 <p>The default bindings are:</p>
811 <ul>
812 <li><p><code>C-SPACE</code> to toggle the mark of an entry.</p></li>
813 <li><p><code>M-a</code> to mark all visible entries.</p></li>
814 <li><p><code>M-u</code> to unmark all visible entries.</p></li>
815 </ul>
816 <p>Furthermore, when the input is changed and the candidates are re-filtered, the selection is not altered, even if the marked elements are not visible. We can <strong>add-up the selections</strong>.</p>
817 <p>For example, if we have several Wikipedia and Stack Overflow pages open, and we want to close them, we can do the following:</p>
818 <ul>
819 <li><p>Press <code>C-x k</code> (Emacs bindings) or <code>d</code> (vim bindings) or call <code>M-x delete-buffer</code>.</p></li>
820 <li><p>In the list of current buffers, type &quot;wikip&quot; and witness the list will shrink down. Type <code>M-a</code> to mark all the Wikipedia buffers.</p></li>
821 <li><p>Erase the input and filter with <code>stack</code>, press <code>M-a</code> again.</p></li>
822 <li><p>Press <code>Enter</code>.</p></li>
823 </ul>
824 <img src="/static/image/multiple-selection.gif" align="center"/>
825 <p>How efficient is that!?</p>
826 <p>Of course should you wish, you always have the possibility to write your own <code>delete-lots-of-buffers</code> command :-)</p>
827 <h2 id="bookmarks-tags-and-compound-queries">Bookmarks, tags and compound queries</h2>
828 <p>Now with Nyxt, you can <strong>tag your bookmarks</strong> and filter them with <strong>compound selectors</strong>.</p>
829 <p>When you bookmark a new page (<code>C-m s</code> or <code>m M</code> vi-mode or <code>M-x
830 bookmark-page</code>), you are asked for a list of space-separated tags.</p>
831 <img src="/static/image/bookmark-sea-turtle.png" align="center"/>
832 <p>When about to open a bookmark (<code>C-m o</code>, <code>m o</code>, <code>M-x set-url-from-bookmark</code>), you can fuzzy-filter the list and <em>also</em> filter them with tag selectors: use <code>+</code>, <code>-</code> or start a compound selector with <code>(</code> in which you can use <code>and</code>, <code>or</code> and <code>not</code>.</p>
833 <p>Examples:</p>
834 <pre class="example"><code>+lisp -blog
835 +blog (or lisp emacs)
836 +foo -bar (or (and john doe) (not (and tic tac)))
837 </code></pre>
838 <p>Additionally, the bookmarks are now <strong>saved in text format</strong>, more precisely, in s-expressions. You can easily read and edit them with another tool of your choice. In fact, we have <a href="https://github.com/tviti/next-cfg">a user who syncs them to a Github repository</a> already.</p>
839 <h2 id="password-manager">Password manager</h2>
840 <p>Nyxt 1.3.3 provides a password manager interface to <a href="https://keepassxc.org/">KeepassXC</a> or <a href="https://www.passwordstore.org/">Pass</a>.</p>
841 <p>See the commands <code>save-new-password</code> and <code>copy-password</code>.</p>
842 <p>Credits go to Solomon Bloch (<span class="citation" data-cites="noogie13">@noogie13</span>).</p>
843 <h2 id="session-persistence">Session persistence</h2>
844 <p>The user session is now automatically persisted. Close Nyxt, and find all your buffers open on subsequent starts.</p>
845 <p>You can also quit without saving it with <code>M-x quit-after-clearing-session</code>, or program Nyxt to adapt it to your liking. Maybe with <a href="https://next.atlas.engineer/article/hooks.org">hooks</a> this time.</p>
846 <h2 id="clone-git-repositories">Clone Git repositories</h2>
847 <p>Nyxt 1.3.3 introduces the <code>vcs-clone</code> (alias <code>git-clone</code>) command to clone Git repositories to disk. It asks for the destination and then runs asynchronously. It has a few configuration options, see the <a href="https://github.com/atlas-engineer/next/blob/master/documents/MANUAL.org">manual</a>.</p>
848 <p>We see this new command as a simple preview of what is possible with Nyxt, as we can interface with the host system rather easily. We are excited to work more on developer helpers in the future, and to see what you'll come up with.</p>
849 <h2 id="download-videos">Download videos</h2>
850 <p>Another utility is the new <code>download-video</code> command, which will download the video at the current URL. It is at the moment a wrapper around the <a href="http://ytdl-org.github.io/youtube-dl/">youtube-dl</a> program, which you must first install.</p>
851 <p>After the download, you can open your video with the <code>open-file</code> command (<code>C-x C-f</code>).</p>
852 <p>See the manual for more documentation and configuration options.</p>
853 <h2 id="reopen-closed-tabs">Reopen closed tabs</h2>
854 <p>The new command <code>reopen-buffer</code> (bound to <code>C-/</code>, or <code>u</code> with VI bindings) will ask for a buffer from the most recently closed ones. It supports <strong>multiple selection</strong>. And <code>reopen-last-buffer</code> will work without a prompt.</p>
855 <p>Credits go to <code>4t0m</code>.</p>
856 <h2 id="faster-and-improved-fuzzy-completion">Faster and improved fuzzy completion</h2>
857 <p>Our minibuffer can now match against typos and has much improved performance (no more hang after some 15 input characters…).</p>
858 <p>The rules are as follows:</p>
859 <ul>
860 <li><p>When any of the input strings does not match any candidate, Nyxt will try to match against possible typos.</p></li>
861 <li><p>When any of the input strings matches exactly</p></li>
862 </ul>
863 <p>Example in <code>execute-command</code> (<code>M-x</code>):</p>
864 <ul>
865 <li><p><code>buffer</code> would filter out all commands that don't contain the string &quot;buffer&quot;.</p></li>
866 <li><p><code>swt buffer</code> would do as above, then try its best to guess which of the remaining commands matches &quot;swt&quot; more.</p></li>
867 </ul>
868 <h2 id="view-the-buffer-history-as-a-tree">View the buffer history (as a tree)</h2>
869 <p>Early versions of Nyxt have supported tree based history. However, until now, visualizing the whole history tree has been difficult.</p>
870 <p>Nyxt 1.3.3 introduces the command <code>buffer-history-tree</code> to view it in HTML:</p>
871 <img src="/static/image/history-tree.png" align="center"/>
872 <p>The keys <code>C-b</code> and <code>C-f</code> (<code>history-backwards</code> and <code>history-forwards</code>) are the &quot;usual&quot; ones. <code>M-b</code> and <code>M-f</code> (<code>history-backwards-query</code> and <code>history-forwards-query</code>) show the buffer history and ask for an url.</p>
873 <p>There is also <code>history-all-query</code> (<code>C-M-b</code>) that is self-explanatory and <code>history-forwards-maybe-query</code> that will &quot;do the right thing&quot;, that is, ask for input only if there is ambiguity.</p>
874 <h2 id="new-command-line-argument-no-init">New command line argument: –no-init</h2>
875 <p>The command line argument <code>--no-init</code> or <code>-Q</code> will allow you to start Nyxt without loading your init file.</p>
876 <h1 id="changes-in-configuration-settings-alias-functional-configuration-system">Changes in configuration settings (alias &quot;functional configuration system&quot;)</h1>
877 <p>A new style of configuration is available allowing for a &quot;functional&quot; style of configuration. To know more about it, check out our <a href="https://github.com/atlas-engineer/next/issues/419">discussion on GitHub</a>.</p>
878 <h1 id="whats-next">What's next ?</h1>
879 <p>We have a ton of ideas, as you certainly will the second you try Nyxt. We worked on it full time on our own resources for the last few months, however, they are limited. We might need to look for a real job. We don't see ourselves doing so much again if we can only devote a fraction of our time to it. That's why we launched the Indiegogo campaign. You are warmly invited to join in to make it a success (even with a small donation, the number of participants is also meaningful to us). Thank you!</p>
880 <p><a href="https://www.indiegogo.com/projects/next-browser-v1-4-0/x/13474269#/" class="uri">https://www.indiegogo.com/projects/next-browser-v1-4-0/x/13474269#/</a></p>
881 <p>If you'd like to become a sponsor, or if you need some help to getting started hacking in Nyxt, you can contact us at <code>hello@atlas.engineer</code>.</p>
882 <p>Find out more about Nyxt:</p>
883 <ul>
884 <li>The <a href="https://github.com/atlas-engineer/next/blob/master/documents/MANUAL.org">manual</a>.</li>
885 <li>Our <a href="https://github.com/atlas-engineer/next/wiki">wiki</a>.</li>
886 <li>Our <a href="https://www.reddit.com/r/next_browser/">subreddit</a>.</li>
887 <li>#nyxt-browser on Freenode IRC.</li>
888 </ul>
889 </body>
890 </html>
891 </content></entry><entry><id>urn:uuid:a28b1781-1134-3bd4-9521-62518145d772</id><updated>2020-08-26T00:00:00.00+00:00</updated><title>Autofills</title><link href="https://nyxt.atlas.engineer/article/autofills.org" /><content type="html"><!DOCTYPE html>
892 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
893 <head>
894 <meta charset="utf-8" />
895 <meta name="generator" content="pandoc" />
896 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
897 <title>Autofills</title>
898 <style type="text/css">
899 code{white-space: pre-wrap;}
900 span.smallcaps{font-variant: small-caps;}
901 span.underline{text-decoration: underline;}
902 div.column{display: inline-block; vertical-align: top; width: 50%;}
903 </style>
904 <!--[if lt IE 9]>
905 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
906 <![endif]-->
907 </head>
908 <body>
909 <header>
910 <h1 class="title">Autofills</h1>
911 </header>
912 <p>Autofills are a feature in Nyxt that allow you to compose and fill in forms as rapidly as possible. Typical autofill functionality includes inputting 'remembered' information such as your username, address or telephone number. This is useful, but can be further expanded.</p>
913 <p><img src="../static/image/article/typical-autofill.png" /></p>
914 <p>In Nyxt, autofills are dynamic, and context sensitive. In addition to being able to 'remember' data, autofills can also compute data. This is because autofills can be functions.</p>
915 <p>An example of a dynamic autofill can be a requirement to fill in the current date on a form. Instead of manually retrieving and copying the date, you can have an autofill automatically input the date in whatever format you wish.</p>
916 <p><img src="../static/image/article/nyxt-autofill.png" /></p>
917 <p>Beyond simple workflows of inputting a single element, autofills can be used in a more advanced fashion. Imagine that you are working on a customer support ticket. Typically, you have a template for messages:</p>
918 <pre id="template" class="language"><code>Dear customer W,
919
920 We&#39;ve received your information about problem X, and we are working on
921 a solution. We anticipate we&#39;ll have more information for you by date
922 Y.
923
924 thank you for continued patience,
925
926 signed, Z
927 </code></pre>
928 <p>Instead of writing this information out all the time, you could have an autofill that prompts you for the values of W, X, Y, and Z to automatically compose your customer response messages.</p>
929 <p>To find out more about autofills and how to configure them in Nyxt, please see <code>describe-slot</code>, <code>autofills</code>.</p>
930 <p>We hope you enjoy using Nyxt's autofills!</p>
931 <p>Thanks for reading :-)</p>
932 </body>
933 </html>
934 </content></entry><entry><id>urn:uuid:04aca7fd-0782-3bbc-ba3b-861032d80b0d</id><updated>2020-07-24T00:00:00.00+00:00</updated><title>Element Hints</title><link href="https://nyxt.atlas.engineer/article/element-hints.org" /><content type="html"><!DOCTYPE html>
935 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
936 <head>
937 <meta charset="utf-8" />
938 <meta name="generator" content="pandoc" />
939 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
940 <title>Element Hints</title>
941 <style type="text/css">
942 code{white-space: pre-wrap;}
943 span.smallcaps{font-variant: small-caps;}
944 span.underline{text-decoration: underline;}
945 div.column{display: inline-block; vertical-align: top; width: 50%;}
946 </style>
947 <!--[if lt IE 9]>
948 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
949 <![endif]-->
950 </head>
951 <body>
952 <header>
953 <h1 class="title">Element Hints</h1>
954 </header>
955 <p>Element hints are a feature in Nyxt that allow you to interact with elements on a web page. Unlike traditional methods of doing so (mouse), element hints are entirely keyboard driven.</p>
956 <p><img src="../static/image/article/element-hint.png" /></p>
957 <p>Element hints work like this:</p>
958 <ol>
959 <li>You press a keybinding.</li>
960 <li>A series of hints appear on the page, and in the Minibuffer as a list.</li>
961 <li>Using the Minibuffer you select which hint you would like to navigate to/interact with.</li>
962 <li>When you're ready, you submit your input, and Nyxt will navigate to and/or interact with the selected element hint/s.</li>
963 </ol>
964 <p>Importantly, because the element hints are available in the Minibuffer, Nyxt element hints can be selected by URL, hint, or title!</p>
965 <p>Beyond link navigation, element hints can be used to do a variety of things:</p>
966 <ol>
967 <li>copy a URL</li>
968 <li>jump to a URL</li>
969 <li>open a URL in a background buffer</li>
970 <li>open a URL in a new buffer</li>
971 <li>click a button</li>
972 <li>submit a form</li>
973 </ol>
974 <p>Like other commands, element hints can accept multiple inputs (when applicable). For example, a user can simultaneously open up several matching element hints in new buffers:</p>
975 <p><img src="../static/image/article/element-hint-multiple-select.png" /></p>
976 <p>We hope you enjoy using Nyxt's advanced element hints!</p>
977 <p>Thanks for reading :-)</p>
978 </body>
979 </html>
980 </content></entry><entry><id>urn:uuid:dd1beb7f-3100-3502-bc57-fed4c39d55f0</id><updated>2020-07-15T00:00:00.00+00:00</updated><title>Reading Line</title><link href="https://nyxt.atlas.engineer/article/reading-line.org" /><content type="html"><!DOCTYPE html>
981 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
982 <head>
983 <meta charset="utf-8" />
984 <meta name="generator" content="pandoc" />
985 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
986 <title>Reading Lines</title>
987 <style type="text/css">
988 code{white-space: pre-wrap;}
989 span.smallcaps{font-variant: small-caps;}
990 span.underline{text-decoration: underline;}
991 div.column{display: inline-block; vertical-align: top; width: 50%;}
992 </style>
993 <!--[if lt IE 9]>
994 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
995 <![endif]-->
996 </head>
997 <body>
998 <header>
999 <h1 class="title">Reading Lines</h1>
1000 </header>
1001 <p>Reading lines are a new feature available in Nyxt. Reading lines solve the problem of picking up back where you left off within a document. When reading physical documents, people will often use their finger or a sticky note for this purpose. In Nyxt, the reading line is a digital equivalent of a sticky note/marker. You can use reading lines on long pages, or when switching applications to easily resume reading.</p>
1002 <p>Here's what they look like:</p>
1003 <p><img src="../static/image/article/reading-line.png" /></p>
1004 <p>As can be seen, the reading line is a horizontally drawn gray bar. You can move this bar up and down the page, and the focus of the window will follow. You can even navigate away from the reading line and jump back to it:</p>
1005 <p><img src="../static/image/article/jump-to-reading-line.png" /></p>
1006 <p>When you are done investigating whatever else you were looking at, you can jump back to where you left off.</p>
1007 <p><img src="../static/image/article/return-to-reading-line.png" /></p>
1008 <p>Thanks for reading :-)</p>
1009 </body>
1010 </html>
1011 </content></entry><entry><id>urn:uuid:253ccf45-8df4-3d03-b912-dfcec6c48677</id><updated>2020-06-23T00:00:00.00+00:00</updated><title>Next Nyxt Rename</title><link href="https://nyxt.atlas.engineer/article/next-nyxt-rename.org" /><content type="html"><!DOCTYPE html>
1012 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1013 <head>
1014 <meta charset="utf-8" />
1015 <meta name="generator" content="pandoc" />
1016 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1017 <title>Next-&gt;Nyxt Project Rename</title>
1018 <style type="text/css">
1019 code{white-space: pre-wrap;}
1020 span.smallcaps{font-variant: small-caps;}
1021 span.underline{text-decoration: underline;}
1022 div.column{display: inline-block; vertical-align: top; width: 50%;}
1023 </style>
1024 <!--[if lt IE 9]>
1025 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1026 <![endif]-->
1027 </head>
1028 <body>
1029 <header>
1030 <h1 class="title">Next-&gt;Nyxt Project Rename</h1>
1031 </header>
1032 <h1 id="next-has-a-new-name">Next has a new name!</h1>
1033 <p>Hello everybody, we are happy to announce that Next has a new name, Nyxt!</p>
1034 <h1 id="why-the-new-name">Why the new name?</h1>
1035 <p>There are a couple of reasons why we've decided to change the name. Listed below are some of our reasons (unordered):</p>
1036 <ul>
1037 <li>Next is a word in English, making it hard to find related resources via search engines</li>
1038 <li>Nyxt is the Greek goddess of the night, making it consistent with the parent organization name, Atlas</li>
1039 <li>Nyxt is a relatively unique spelling which will result in few false positives</li>
1040 </ul>
1041 <p>We hope you like the new name! Thanks for reading :-)</p>
1042 </body>
1043 </html>
1044 </content></entry><entry><id>urn:uuid:3172379f-fe4d-3ce3-9406-c52fc912d30d</id><updated>2020-06-03T00:00:00.00+00:00</updated><title>Release 1.5.0</title><link href="https://nyxt.atlas.engineer/article/release-1.5.0.org" /><content type="html"><!DOCTYPE html>
1045 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1046 <head>
1047 <meta charset="utf-8" />
1048 <meta name="generator" content="pandoc" />
1049 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1050 <title>Next release 1.5.0</title>
1051 <style type="text/css">
1052 code{white-space: pre-wrap;}
1053 span.smallcaps{font-variant: small-caps;}
1054 span.underline{text-decoration: underline;}
1055 div.column{display: inline-block; vertical-align: top; width: 50%;}
1056 </style>
1057 <!--[if lt IE 9]>
1058 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1059 <![endif]-->
1060 </head>
1061 <body>
1062 <header>
1063 <h1 class="title">Next release 1.5.0</h1>
1064 </header>
1065 <p>We are happy to announce the release of Next version 1.5.0!</p>
1066 <ul>
1067 <li><p>Add <code>certificate-whitelist-mode</code>. (Thanks to Alexander Egorenkov.)</p>
1068 <p>This mode temporarily authorizes invalid certificates for the current buffer (e.g. TLS certificates).</p>
1069 <p>The mode can also be enabled for all buffers with a custom whitelist so that the whitelisting is remembered across sessions.</p></li>
1070 <li><p>Add <code>enable-hook-handler</code> and <code>disable-hook-handler</code> commands.</p>
1071 <p>This is particularly convenient to temporarily disable hooks that are set in the <code>init.lisp</code> file.</p></li>
1072 <li><p>Overhaul buffer search to behave in a Helm/Ivy fashion.</p></li>
1073 <li><p>Add <code>search-buffers</code> command to search across the given buffers. (Thanks to Chris Bøg.)</p></li>
1074 <li><p>Add <code>delete-other-buffers</code> command. (Thanks to Chris Bøg.)</p></li>
1075 <li><p>Sort buffer by last-access time.</p>
1076 <p>In particular, the latest buffer buffer will be popped when deleting the current buffer.</p></li>
1077 <li><p>Display log messages in <code>*Messages*</code> buffer. (Thanks to Bruno Cichon.)</p></li>
1078 <li><p>Show source location with <code>command-inspect</code>. (Thanks to Bruno Cichon.)</p></li>
1079 <li><p>Fix define-mode when there is no docstring. (Thanks to Chris Bøg.)</p></li>
1080 <li><p>Fix tab-insert on candidates.</p></li>
1081 <li><p>Rename &quot;link-hint&quot; to &quot;element-hint&quot;.</p></li>
1082 <li><p>Fix updating echo area on buffer change.</p></li>
1083 </ul>
1084 <h1 id="about-next">About Next</h1>
1085 <p>Next is a keyboard-oriented, extensible web-browser designed for power users. The application has familiar key-bindings (<a href="https://en.wikipedia.org/wiki/Emacs">Emacs</a>, <a href="https://en.wikipedia.org/wiki/Vim_(text_editor)">VI</a>), is fully configurable and extensible in Lisp, and has powerful features for productive professionals.</p>
1086 <p><a href="https://next.atlas.engineer/download">Download it here!</a></p>
1087 </body>
1088 </html>
1089 </content></entry><entry><id>urn:uuid:2e1fe75f-a1c9-3263-ab5e-b142dd019b3a</id><updated>2020-06-03T00:00:00.00+00:00</updated><title>Release 1.4.0</title><link href="https://nyxt.atlas.engineer/article/release-1.4.0.org" /><content type="html"><!DOCTYPE html>
1090 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1091 <head>
1092 <meta charset="utf-8" />
1093 <meta name="generator" content="pandoc" />
1094 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1095 <title>Next release 1.4.0</title>
1096 <style type="text/css">
1097 code{white-space: pre-wrap;}
1098 span.smallcaps{font-variant: small-caps;}
1099 span.underline{text-decoration: underline;}
1100 div.column{display: inline-block; vertical-align: top; width: 50%;}
1101 </style>
1102 <!--[if lt IE 9]>
1103 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1104 <![endif]-->
1105 </head>
1106 <body>
1107 <header>
1108 <h1 class="title">Next release 1.4.0</h1>
1109 </header>
1110 <p>We are happy to announce the release of Next version 1.4.0!</p>
1111 <ul>
1112 <li><p>CLOS-style configuration. This simplifies setting the default slots of the various classes (<code>buffer</code>, <code>window</code>, <code>interface</code>, <code>minibuffer</code>, etc.). In particular, the user-specialized (or extension-specialized) classes can in turn be composed to form a new specialized classes.</p></li>
1113 <li><p>Revamped hook system. (Backward incompatible.) Hooks are now simpler to use but also more powerful. In particular, handlers can be typed and composed. See the manual for examples.</p></li>
1114 <li><p>Link hints: Add fuzzy-completion over titles and URLs.</p></li>
1115 <li><p>New <code>--eval</code> command line argument.</p></li>
1116 <li><p>New delete-all-buffers command.</p></li>
1117 <li><p>Open directories, music and videos directly from Next.</p></li>
1118 <li><p>VCS: More checks and notifications.</p></li>
1119 <li><p>Complete search-engine names with Tab.</p></li>
1120 <li><p>Display package in <code>execute-command</code> candidate list.</p></li>
1121 <li><p>New <code>+platform-port-command+</code> global.</p></li>
1122 <li><p>More minibuffer default bindings. Bind <code>C-Right</code>, <code>C-Left</code>, <code>Home</code>, <code>End</code> in the minibuffer.</p></li>
1123 <li><p>Remove history duplicates.</p></li>
1124 <li><p>Scroll page with an offset by default.</p>
1125 Offset is configurable in the <code>page-scroll-ratio</code> buffer slot.</li>
1126 <li><p>New command line parameter <code>--session</code> to skip loading the previous session.</p></li>
1127 <li><p>Password manager fixes. (Thanks to Rune Juhl Jacobsen.)</p></li>
1128 <li><p>Bug fixes:</p>
1129 <ul>
1130 <li><p>Don't reload page when there is no history change.</p></li>
1131 <li><p>Omit extra space in search engine queries.</p></li>
1132 <li><p>Show if new or current buffer in <code>set-url</code> prompt (Thanks to Rune Juhl Jacobsen).</p></li>
1133 <li><p>Fix minibuffer performance hog.</p></li>
1134 <li><p>Fix element hint performance.</p></li>
1135 <li><p>Buttons hints can now be followed.</p></li>
1136 <li><p>Fix element hint rendered offscreen on a scaled display.</p></li>
1137 </ul></li>
1138 </ul>
1139 <h1 id="about-next">About Next</h1>
1140 <p>Next is a keyboard-oriented, extensible web-browser designed for power users. The application has familiar key-bindings (<a href="https://en.wikipedia.org/wiki/Emacs">Emacs</a>, <a href="https://en.wikipedia.org/wiki/Vim_(text_editor)">VI</a>), is fully configurable and extensible in Lisp, and has powerful features for productive professionals.</p>
1141 <p><a href="https://next.atlas.engineer/download">Download it here!</a></p>
1142 </body>
1143 </html>
1144 </content></entry><entry><id>urn:uuid:e353ecec-c03c-349e-8b0d-6862015f9557</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>The Nyxt Thesis</title><link href="https://nyxt.atlas.engineer/article/the-nyxt-thesis.org" /><content type="html"><!DOCTYPE html>
1145 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1146 <head>
1147 <meta charset="utf-8" />
1148 <meta name="generator" content="pandoc" />
1149 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1150 <title>The Nyxt Thesis</title>
1151 <style type="text/css">
1152 code{white-space: pre-wrap;}
1153 span.smallcaps{font-variant: small-caps;}
1154 span.underline{text-decoration: underline;}
1155 div.column{display: inline-block; vertical-align: top; width: 50%;}
1156 </style>
1157 <!--[if lt IE 9]>
1158 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1159 <![endif]-->
1160 </head>
1161 <body>
1162 <header>
1163 <h1 class="title">The Nyxt Thesis</h1>
1164 </header>
1165 <h1 id="why-should-i-care-who-is-nyxt-for">Why should I care? Who is Nyxt for?</h1>
1166 <ul>
1167 <li>Have you ever felt frustrated looking for a tab?</li>
1168 <li>Have you ever been annoyed at the default, unchangable behavior of your browser?</li>
1169 <li>Have you ever felt that your work-flows could greatly benefit from some simple keyboard macros or automation?</li>
1170 <li>Do all web browsers feel the same?</li>
1171 <li>Are you interested in optimizing and being more efficient?</li>
1172 </ul>
1173 <p>If any of the above resonates with you, you should know that it doesn't have to be this way. We believe that you should be able to:</p>
1174 <ol>
1175 <li>Find the information you need, and find it quickly.</li>
1176 <li>Work efficiently, focus on the task at hand instead of navigating some dumbed-down point and click UI.</li>
1177 <li>Adjust every single detail and nuance of your web browser to suit your work-flow.</li>
1178 <li>Have unlimited power over your environment.</li>
1179 </ol>
1180 <h1 id="what-is-nyxt-what-is-the-solution">What is Nyxt? What is the solution?</h1>
1181 <p>Nyxt is a new type of web browser that gives the user full control over its behavior. Literally any part of Nyxt is reprogrammable. You can fire up a compiled version of Nyxt, drop into a <a href="https://en.wikipedia.org/wiki/REPL">REPL</a>, and immediately begin hacking and changing the behavior of your browser.</p>
1182 <p>Out of the box Nyxt ships with extensions that are designed to make you faster at navigating the Internet. For instance, consider a task that you do hundreds of times per day- switching tabs. In a normal browser, you have to go through your tabs one by one until you find what you need. In Nyxt, simply type a fuzzy search string describing the tab you are looking for, and Nyxt will let you jump to it instantly.</p>
1183 <p>All the source code for Nyxt is available to you under a <a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3 clause license</a>. Do with it whatever you want, inspect it, modify it, and make Nyxt your own.</p>
1184 <h1 id="what-is-the-mission-of-nyxt">What is the mission of Nyxt?</h1>
1185 <p>The mission of Nyxt is to enable people to be as productive as possible. We don't place barriers upon the users of Nyxt. We allow people to get stuff done, their way.</p>
1186 <p>Nyxt is about freedom. You should have the freedom to modify and change the tool you use to adapt to your particular needs, to enable yourself to be more productive.</p>
1187 <p>Modern day scientists, engineers, philosophers, artists, and others spend increasingly more time on the Internet. Current tools hinder access to Internet-based resources. Nyxt, instead of hindering, empowers. In turn, this hopefully makes the world a better place.</p>
1188 <h1 id="whats-the-problem-with-current-browsers">What's the problem with current browsers?</h1>
1189 <p>The problem with current browsers is that they are engaged in what is known as the browser war. The browser war is one of focusing entirely on performance, and attaining the largest user base possible.</p>
1190 <p>How to get a large user base? Make a product that is as simple as possible. That is why major browsers today are constraind in their UI designs by paradigms invented by Netscape and Internet Explorer in the late 90s.</p>
1191 <h2 id="why-do-browsers-care-about-market-share">Why do browsers care about market share?</h2>
1192 <p>Market share is power. If Chrome unilaterally decided to implement a new standard, other, smaller browsers would be forced to follow suite. Otherwise, their users would get messages such as &quot;Sorry, this website doesn't support your browser, please download Chrome&quot;.</p>
1193 <p>Furthermore, the business models of browsers, particularly Chrome, is centered around gathering and selling your data. That is why they want as <em>many</em> users as possible. They don't care about you, they just want your data to sell to advertisers.</p>
1194 <h1 id="how-can-i-participate">How can I participate?</h1>
1195 <p>You can try Nyxt now by visiting the download page linked above! We hope you enjoy it and you'll join us on our mission! Thanks for reading :)</p>
1196 </body>
1197 </html>
1198 </content></entry><entry><id>urn:uuid:f38b35f9-20ef-3e58-af5e-fd71f1260a8a</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Release 1.3.4</title><link href="https://nyxt.atlas.engineer/article/release-1.3.4.org" /><content type="html"><!DOCTYPE html>
1199 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1200 <head>
1201 <meta charset="utf-8" />
1202 <meta name="generator" content="pandoc" />
1203 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1204 <title>Nyxt release 1.3.4</title>
1205 <style type="text/css">
1206 code{white-space: pre-wrap;}
1207 span.smallcaps{font-variant: small-caps;}
1208 span.underline{text-decoration: underline;}
1209 div.column{display: inline-block; vertical-align: top; width: 50%;}
1210 </style>
1211 <!--[if lt IE 9]>
1212 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1213 <![endif]-->
1214 </head>
1215 <body>
1216 <header>
1217 <h1 class="title">Nyxt release 1.3.4</h1>
1218 </header>
1219 <p>We are happy to announce the release of Nyxt version 1.3.4!</p>
1220 <p>This is a minor bug-fix release:</p>
1221 <ul>
1222 <li><p>Display number of (marked) candidates in minibuffer.</p></li>
1223 <li><p>Improve fuzzy search performance and relevance.</p></li>
1224 <li><p>Swap <code>C-x k</code> and <code>C-x C-k</code> bindings to match Emacs' behaviour.</p></li>
1225 <li><p>Fix platform port lookup failure on startup when looked up in PATH.</p></li>
1226 <li><p>Fix <strong>default-hostlist</strong> path in pre-compiled binaries.</p></li>
1227 <li><p>Fix compound tags lookup for bookmarks.</p></li>
1228 <li><p>Fix history update on Javascript-loaded pages (e.g. GitHub).</p></li>
1229 </ul>
1230 <h1 id="about-nyxt">About Nyxt</h1>
1231 <p>Nyxt is a keyboard-oriented, extensible web-browser designed for power users. The application has familiar key-bindings (<a href="https://en.wikipedia.org/wiki/Emacs">Emacs</a>, <a href="https://en.wikipedia.org/wiki/Vim_(text_editor)">VI</a>), is fully configurable and extensible in Lisp, and has powerful features for productive professionals.</p>
1232 <p><a href="https://next.atlas.engineer/download">Download it here!</a></p>
1233 </body>
1234 </html>
1235 </content></entry><entry><id>urn:uuid:97bf83da-7b34-378b-bba8-f4e7eabff0b5</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Campaign Reminder</title><link href="https://nyxt.atlas.engineer/article/campaign-reminder.org" /><content type="html"><!DOCTYPE html>
1236 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1237 <head>
1238 <meta charset="utf-8" />
1239 <meta name="generator" content="pandoc" />
1240 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1241 <title>Only 10 days left to back the Nyxt browser crowdfunding campaign!</title>
1242 <style type="text/css">
1243 code{white-space: pre-wrap;}
1244 span.smallcaps{font-variant: small-caps;}
1245 span.underline{text-decoration: underline;}
1246 div.column{display: inline-block; vertical-align: top; width: 50%;}
1247 </style>
1248 <!--[if lt IE 9]>
1249 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1250 <![endif]-->
1251 </head>
1252 <body>
1253 <header>
1254 <h1 class="title">Only 10 days left to back the Nyxt browser crowdfunding campaign!</h1>
1255 </header>
1256 <p><a href="https://next.atlas.engineer">Nyxt</a> is a productivity focused, infinitely extensible power-browser. It comes with Emacs / VI bindings and is completely programmable. You can transform it any way you like!</p>
1257 <p>In just the last months, we've released three new versions! Lots of exciting features, from hooks to continuous improvements to the &quot;minibuffer&quot; (a.k.a. the &quot;power bar&quot;) to empower the users in a never-ending quest to fuzzy-searching everything!</p>
1258 <p>The project has been seriously taking off these last couple of weeks. We would like to thank our <a href="https://github.com/atlas-engineer/next/">27 contributors</a>, and all the users and testers that asked for new features, suggested improvements or reported bugs. Thanks!</p>
1259 <h1 id="so-what-exactly-can-you-do-with-nyxt">So what exactly can you do with Nyxt?</h1>
1260 <ul>
1261 <li><p>Go blazing fast when browsing the web! For starters, Nyxt is keyboard driven and has fuzzy-completion everywhere.</p></li>
1262 <li><p>You can write <strong>new commands for anything you want</strong>. You have the full power of the programming language at hand, without <em>restricting you to a browser's API</em>. Some examples: You can <code>git-clone</code> the current URL's repository, download Youtube videos and fuzzy-search for local files with <code>open-file</code>.</p></li>
1263 <li><p>You can <a href="https://next.atlas.engineer/article/hooks.org">write <strong>hooks</strong></a> to extend your browsing experience. Write a function that is called when a given network event happens, or slightly modify the behaviour of built-in commands to fit your needs – <em>perfectly</em>.</p></li>
1264 </ul>
1265 <ul>
1266 <li><p>Every tab history is saved as a tree, meaning you don't lose any page when going back. Want an outlook of your whole history? Call the <code>buffer-history-tree</code> command!</p>
1267 <p><img src="../static/image/history-tree.png" /></p></li>
1268 <li><p>Press the <code>M-.</code> key to get a list of the page headers, fuzzy-search them and go straight to them.</p></li>
1269 </ul>
1270 <p>And much more, as you would expect from your daily driver: adblocking, proxy and Tor support, Javascript blocker, etc.</p>
1271 <h1 id="we-need-your-support">We need your support!</h1>
1272 <p>Nyxt is being developed by a small team of computer scientists with a passion for changing the world of browsers. We rely on your support to keep development going!</p>
1273 <p>Last month we started a <a href="https://www.indiegogo.com/projects/next-browser-v1-4-0#/">crowdfunding campaign</a> so that we can get to work on the next version. The campaign is ending on <strong>Friday, October 4th</strong>, and we've still got a long way to go. Only your support can help us go forward, every $1 helps!</p>
1274 <p>We are also actively looking for people who would like to sponsor/be sponsored by us. If you are interested, get in touch by writing at <code>hello@atlas.engineer</code>.</p>
1275 <h1 id="interested-in-whats-coming-next">Interested in what's coming next?</h1>
1276 <ul>
1277 <li><p>Per-domain CSS (e.g. a Dark Mode)</p></li>
1278 <li><p>Bluring the lines between a browser, a text editor and a file manager</p></li>
1279 <li><p>A sandboxed REPL for online code snippets</p></li>
1280 <li><p>Overpowered bookmarks</p></li>
1281 <li><p>A widget library for third-party authors</p></li>
1282 <li><p>Explorable features thanks to embedded documentation and live introspection</p></li>
1283 <li><p>Minibuffer multiselection (or &quot;delete fuzzy-matched buffers in one go&quot;, etc.)</p></li>
1284 <li><p>Seamless integration with decentralized internet protocols such as IPFS, Dat and Zeronet</p></li>
1285 <li><p>WebKitGTK sandboxing</p></li>
1286 <li><p>Session persistence (or &quot;reopen previously open buffers on restart&quot;)</p></li>
1287 <li><p>Enhanced and configurable adblocking</p></li>
1288 <li><p>Status bar</p></li>
1289 <li><p>Third-party / User extension support</p></li>
1290 <li><p>More programmable hooks for everything!</p></li>
1291 <li><p>Improved macOS support</p></li>
1292 </ul>
1293 <p>Thank you for reading, and thanks in advance for your support! ;)</p>
1294 </body>
1295 </html>
1296 </content></entry><entry><id>urn:uuid:0592ea73-0e97-3f77-a7b1-bab7fc390636</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Release 1.3.2</title><link href="https://nyxt.atlas.engineer/article/release-1.3.2.org" /><content type="html"><!DOCTYPE html>
1297 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1298 <head>
1299 <meta charset="utf-8" />
1300 <meta name="generator" content="pandoc" />
1301 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1302 <title>Nyxt release 1.3.2</title>
1303 <style type="text/css">
1304 code{white-space: pre-wrap;}
1305 span.smallcaps{font-variant: small-caps;}
1306 span.underline{text-decoration: underline;}
1307 div.column{display: inline-block; vertical-align: top; width: 50%;}
1308 </style>
1309 <!--[if lt IE 9]>
1310 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1311 <![endif]-->
1312 </head>
1313 <body>
1314 <header>
1315 <h1 class="title">Nyxt release 1.3.2</h1>
1316 </header>
1317 <p>We are happy to announce the release of Nyxt version 1.3.2!</p>
1318 <p>This version includes several cool new features:</p>
1319 <ul>
1320 <li><p>&quot;Hooks&quot; let you insert your own code before of after network events and commands, such as automatic download of Youtube videos or auto-switch to old.reddit.com! To read more about hooks, see our updated article here: <a href="https://nyxt.atlas.engineer/article/hooks.org" class="uri">https://nyxt.atlas.engineer/article/hooks.org</a>.</p></li>
1321 <li><p>A new <code>open-file</code> command. This allows you to open up any file locally on your machine.</p></li>
1322 <li><p>A <code>paste-from-ring</code> command that allows you to fuzzy-search and paste from the clipboard ring of <em>all</em> previously copied/pasted text.</p></li>
1323 </ul>
1324 <p>Last month we started a crowdfunding campaign, so if you like what we are doing feel free to support us by chipping in!</p>
1325 <p><a href="https://www.indiegogo.com/projects/nyxt-browser-v1-4-0#/" class="uri">https://www.indiegogo.com/projects/nyxt-browser-v1-4-0#/</a></p>
1326 <p>Thanks for reading and supporting us! You can read the full change log <a href="https://github.com/atlas-engineer/next/blob/1.3.1/documents/CHANGELOG.org">here</a>.</p>
1327 <h1 id="whats-next">What's next?</h1>
1328 <p>We have many new and exciting features in the pipeline that we could release shortly!</p>
1329 <ul>
1330 <li><p>A high quality macOS port, with complete GTK parity(!), for improved performance, distribution, and stability. This means a single app bundle that you can simply download and run.</p></li>
1331 <li><p>Minibuffer multi-selection (or &quot;delete fuzzy-matched buffers in one go&quot;, etc.).</p></li>
1332 <li><p>Session persistence (or &quot;reopen previously open buffers up restart&quot;).</p></li>
1333 <li><p>Status bar.</p></li>
1334 <li><p>WebKitGTK native sandboxing.</p></li>
1335 <li><p>Per-domain CSS (e.g. a Dark Mode).</p></li>
1336 <li><p>Smart searching across all tabs.</p></li>
1337 <li><p>Jump to heading all tabs.</p></li>
1338 <li><p>Package manager.</p></li>
1339 <li><p>Add support for per-tab proxy and Tor support.</p></li>
1340 <li><p>Add an integrated password manager.</p></li>
1341 <li><p>Add built-in editor.</p></li>
1342 <li><p>Allow Nyxt to call out to an external editor to fill in the contents of a particular text field.</p></li>
1343 <li><p>Switch from SQLite to a text based format, allowing bookmarks to be viewed and synced more easily with any external tool.</p></li>
1344 </ul>
1345 <p>Thanks for reading!</p>
1346 <h1 id="about-nyxt">About Nyxt</h1>
1347 <p>Nyxt is a keyboard-oriented, extensible web-browser designed for power users. The application has familiar key-bindings (<a href="https://en.wikipedia.org/wiki/Emacs">Emacs</a>, <a href="https://en.wikipedia.org/wiki/Vim_(text_editor)">VI</a>), is fully configurable and extensible in Lisp, and has powerful features for productive professionals.</p>
1348 <p><a href="https://next.atlas.engineer/download">Download it here!</a></p>
1349 </body>
1350 </html>
1351 </content></entry><entry><id>urn:uuid:5f991ce4-326a-3e33-8db7-d6f0f660a459</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Release 1.3.1</title><link href="https://nyxt.atlas.engineer/article/release-1.3.1.org" /><content type="html"><!DOCTYPE html>
1352 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1353 <head>
1354 <meta charset="utf-8" />
1355 <meta name="generator" content="pandoc" />
1356 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1357 <title>Nyxt release 1.3.1</title>
1358 <style type="text/css">
1359 code{white-space: pre-wrap;}
1360 span.smallcaps{font-variant: small-caps;}
1361 span.underline{text-decoration: underline;}
1362 div.column{display: inline-block; vertical-align: top; width: 50%;}
1363 </style>
1364 <style type="text/css">
1365 a.sourceLine { display: inline-block; line-height: 1.25; }
1366 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
1367 a.sourceLine:empty { height: 1.2em; position: absolute; }
1368 .sourceCode { overflow: visible; }
1369 code.sourceCode { white-space: pre; position: relative; }
1370 div.sourceCode { margin: 1em 0; }
1371 pre.sourceCode { margin: 0; }
1372 @media screen {
1373 div.sourceCode { overflow: auto; }
1374 }
1375 @media print {
1376 code.sourceCode { white-space: pre-wrap; }
1377 a.sourceLine { text-indent: -1em; padding-left: 1em; }
1378 }
1379 pre.numberSource a.sourceLine
1380 { position: relative; }
1381 pre.numberSource a.sourceLine:empty
1382 { position: absolute; }
1383 pre.numberSource a.sourceLine::before
1384 { content: attr(data-line-number);
1385 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
1386 border: none; pointer-events: all;
1387 -webkit-touch-callout: none; -webkit-user-select: none;
1388 -khtml-user-select: none; -moz-user-select: none;
1389 -ms-user-select: none; user-select: none;
1390 padding: 0 4px; width: 4em;
1391 color: #aaaaaa;
1392 }
1393 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
1394 div.sourceCode
1395 { }
1396 @media screen {
1397 a.sourceLine::before { text-decoration: underline; }
1398 }
1399 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
1400 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
1401 code span.at { color: #7d9029; } /* Attribute */
1402 code span.bn { color: #40a070; } /* BaseN */
1403 code span.bu { } /* BuiltIn */
1404 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
1405 code span.ch { color: #4070a0; } /* Char */
1406 code span.cn { color: #880000; } /* Constant */
1407 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
1408 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
1409 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
1410 code span.dt { color: #902000; } /* DataType */
1411 code span.dv { color: #40a070; } /* DecVal */
1412 code span.er { color: #ff0000; font-weight: bold; } /* Error */
1413 code span.ex { } /* Extension */
1414 code span.fl { color: #40a070; } /* Float */
1415 code span.fu { color: #06287e; } /* Function */
1416 code span.im { } /* Import */
1417 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
1418 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
1419 code span.op { color: #666666; } /* Operator */
1420 code span.ot { color: #007020; } /* Other */
1421 code span.pp { color: #bc7a00; } /* Preprocessor */
1422 code span.sc { color: #4070a0; } /* SpecialChar */
1423 code span.ss { color: #bb6688; } /* SpecialString */
1424 code span.st { color: #4070a0; } /* String */
1425 code span.va { color: #19177c; } /* Variable */
1426 code span.vs { color: #4070a0; } /* VerbatimString */
1427 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
1428 </style>
1429 <!--[if lt IE 9]>
1430 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1431 <![endif]-->
1432 </head>
1433 <body>
1434 <header>
1435 <h1 class="title">Nyxt release 1.3.1</h1>
1436 </header>
1437 <p>We are happy to announce the release of Nyxt version 1.3.1!</p>
1438 <p>This version includes important bug fixes, an improved minibuffer experience, better support for various platforms (D-Bus should be handled properly), not forgetting that Nyxt is back to the official Guix repository! (This should make it easier to install Nyxt on any OS running a Linux kernel.)</p>
1439 <p>A screenshot of the minibuffer with fuzzy-matching on the URLs <span class="underline">and</span> titles of the buffers:</p>
1440 <p><img src="../static/image/nyxt-1.3.1-minibuffer.png" /></p>
1441 <p>On the community level, we've overhauled our article/blog page <a href="https://nyxt.atlas.engineer/articles" class="uri">https://nyxt.atlas.engineer/articles</a>, with the aim of regularly publishing articles on our progress, along various Nyxt hacks and configuration tips.</p>
1442 <p>We've also added a news feed where you can follow us: <a href="https://nyxt.atlas.engineer/feed" class="uri">https://nyxt.atlas.engineer/feed</a>.</p>
1443 <p>Thanks!</p>
1444 <h1 id="rest-of-the-change-log">Rest of the <a href="https://github.com/atlas-engineer/next/blob/1.3.1/documents/CHANGELOG.org">change log</a></h1>
1445 <ul>
1446 <li><p>Print page title in buffer list.</p>
1447 <p>And the title is matched when fuzzy-searching a buffer!</p></li>
1448 <li><p>Improved minibuffer performance: it now shows up instantly.</p></li>
1449 <li><p>Open external links in new buffer by default.</p>
1450 <p>This can be configured by setting <code>(open-external-link-in-new-window-p
1451 *interface*)</code> to the desired boolean.</p></li>
1452 <li><p>Return to last created buffer when deleting buffer.</p>
1453 <p>When killing the last created buffer, we were brought back to the first one, so usually the help buffer. This is now fixed, we stay at the previous last created buffer, as expected.</p></li>
1454 <li>Minibuffer <code>M-backspace</code> improvements.
1455 <ul>
1456 <li>In the minibuffer, using <code>M-backspace</code> to delete a word didn't respect white spaces. It is fixed.</li>
1457 <li>Its behaviour was also too different than other common tools, like Firefox. Now:
1458 <ul>
1459 <li>it deletes the trailing word delimiter;</li>
1460 <li>it removes all trailing delimiters <em>plus</em> one word.</li>
1461 </ul></li>
1462 </ul></li>
1463 <li><p>Add keypad bindings</p></li>
1464 <li><p>Nyxt is back to the Guix official channel</p>
1465 <p>The Nyxt Guix channel can be safely removed from your <code>~/.config/guix/channels.scm</code> before running a <code>guix pull</code>.</p></li>
1466 <li><p>Mouse <code>button2</code> (middle click) opens a URL in a new buffer/window.</p></li>
1467 <li><p>Automatically fall back to a local D-Bus session if none can be used.</p></li>
1468 <li><p>Fix platform port log file path on Guix.</p>
1469 <p>It is now properly set to <code>~/.local/share/nyxt/nyxt-gtk-webkit.log</code> by default.</p></li>
1470 <li><p>Fix ignored search engine prefix in minibuffer input.</p></li>
1471 <li><p>Fix browsed URLs not being added to history.</p>
1472 <p>Yes, this is better for a daily usage :)</p></li>
1473 <li><p>Fix crash when proxy-mode was added to the list of default modes.</p>
1474 <p>You can now add this to your <code>~/.config/nyxt/init.lisp</code> to open pages in proxy-mode by default:</p>
1475 <div class="sourceCode" id="cb1" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb1-1" data-line-number="1">(<span class="kw">setf</span> (get-default &#39;proxy-mode &#39;server-address) <span class="st">&quot;socks5://localhost:1080&quot;</span>)</a>
1476 <a class="sourceLine" id="cb1-2" data-line-number="2">(add-to-default-list &#39;proxy-mode &#39;buffer &#39;default-modes)</a></code></pre></div>
1477 <p>Thanks to <span class="citation" data-cites="MasterCsquare">@MasterCsquare</span>.</p></li>
1478 <li><p>More bug fixes (special thanks to Solomon Bloch, <span class="citation" data-cites="goose121">@goose121</span>, Sean Farley, <span class="citation" data-cites="glacambre">@glacambre</span>).</p></li>
1479 <li><p>Developer changes:</p>
1480 <ul>
1481 <li><p>The Makefile automatically updates the Quicklisp distribution.</p>
1482 <p>Nyxt uses its own installation path for the Quicklisp dependencies, it doesn't mesh with your existing <code>~/quicklisp/local-projects</code>. Now you can follow git master without the surprise of a library missing a function.</p></li>
1483 <li><p>Remove cl-string-match and cl-strings dependencies.</p>
1484 <p>Now we mostly rely on <a href="https://github.com/vindarel/cl-str/issues">str</a> and <a href="https://edicl.github.io/cl-ppcre/">cl-ppcre</a>.</p></li>
1485 </ul></li>
1486 </ul>
1487 <h1 id="whats-next">What's next?</h1>
1488 <p>We have many new and exciting features in the pipeline that we should release shortly:</p>
1489 <ul>
1490 <li>a <strong><strong>password manager</strong></strong>,</li>
1491 <li>a <strong><strong>kill ring</strong></strong>,</li>
1492 <li>the possibility to quickly <strong><strong>open any file with fuzzy search</strong></strong>,</li>
1493 <li>new minibuffer improvements, such as <strong><strong>multi-selection</strong></strong>,</li>
1494 <li><strong><strong>session persistence</strong></strong>,</li>
1495 <li>hooks (for modes, commands, startup, network events, etc.) allowing per-domain customization.</li>
1496 </ul>
1497 <p>Thanks for reading!</p>
1498 <h1 id="about-nyxt">About Nyxt</h1>
1499 <p>Nyxt is a keyboard-oriented, extensible web-browser designed for power users. The application has familiar key-bindings (<a href="https://en.wikipedia.org/wiki/Emacs">Emacs</a>, <a href="https://en.wikipedia.org/wiki/Vim_(text_editor)">VI</a>), is fully configurable and extensible in Lisp, and has powerful features for productive professionals.</p>
1500 <p><a href="https://next.atlas.engineer/download">Download it here!</a></p>
1501 </body>
1502 </html>
1503 </content></entry><entry><id>urn:uuid:5a8f7f01-bdf7-3518-b4f8-1a8fec128799</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Emacs Hacks</title><link href="https://nyxt.atlas.engineer/article/emacs-hacks.org" /><content type="html"><!DOCTYPE html>
1504 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1505 <head>
1506 <meta charset="utf-8" />
1507 <meta name="generator" content="pandoc" />
1508 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1509 <title>Emacs Hacks</title>
1510 <style type="text/css">
1511 code{white-space: pre-wrap;}
1512 span.smallcaps{font-variant: small-caps;}
1513 span.underline{text-decoration: underline;}
1514 div.column{display: inline-block; vertical-align: top; width: 50%;}
1515 </style>
1516 <style type="text/css">
1517 a.sourceLine { display: inline-block; line-height: 1.25; }
1518 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
1519 a.sourceLine:empty { height: 1.2em; position: absolute; }
1520 .sourceCode { overflow: visible; }
1521 code.sourceCode { white-space: pre; position: relative; }
1522 div.sourceCode { margin: 1em 0; }
1523 pre.sourceCode { margin: 0; }
1524 @media screen {
1525 div.sourceCode { overflow: auto; }
1526 }
1527 @media print {
1528 code.sourceCode { white-space: pre-wrap; }
1529 a.sourceLine { text-indent: -1em; padding-left: 1em; }
1530 }
1531 pre.numberSource a.sourceLine
1532 { position: relative; }
1533 pre.numberSource a.sourceLine:empty
1534 { position: absolute; }
1535 pre.numberSource a.sourceLine::before
1536 { content: attr(data-line-number);
1537 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
1538 border: none; pointer-events: all;
1539 -webkit-touch-callout: none; -webkit-user-select: none;
1540 -khtml-user-select: none; -moz-user-select: none;
1541 -ms-user-select: none; user-select: none;
1542 padding: 0 4px; width: 4em;
1543 color: #aaaaaa;
1544 }
1545 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
1546 div.sourceCode
1547 { }
1548 @media screen {
1549 a.sourceLine::before { text-decoration: underline; }
1550 }
1551 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
1552 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
1553 code span.at { color: #7d9029; } /* Attribute */
1554 code span.bn { color: #40a070; } /* BaseN */
1555 code span.bu { } /* BuiltIn */
1556 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
1557 code span.ch { color: #4070a0; } /* Char */
1558 code span.cn { color: #880000; } /* Constant */
1559 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
1560 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
1561 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
1562 code span.dt { color: #902000; } /* DataType */
1563 code span.dv { color: #40a070; } /* DecVal */
1564 code span.er { color: #ff0000; font-weight: bold; } /* Error */
1565 code span.ex { } /* Extension */
1566 code span.fl { color: #40a070; } /* Float */
1567 code span.fu { color: #06287e; } /* Function */
1568 code span.im { } /* Import */
1569 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
1570 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
1571 code span.op { color: #666666; } /* Operator */
1572 code span.ot { color: #007020; } /* Other */
1573 code span.pp { color: #bc7a00; } /* Preprocessor */
1574 code span.sc { color: #4070a0; } /* SpecialChar */
1575 code span.ss { color: #bb6688; } /* SpecialString */
1576 code span.st { color: #4070a0; } /* String */
1577 code span.va { color: #19177c; } /* Variable */
1578 code span.vs { color: #4070a0; } /* VerbatimString */
1579 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
1580 </style>
1581 <!--[if lt IE 9]>
1582 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1583 <![endif]-->
1584 </head>
1585 <body>
1586 <header>
1587 <h1 class="title">Emacs Hacks</h1>
1588 </header>
1589 <h1 id="nyxt-interfaces">Nyxt interfaces</h1>
1590 <p>Nyxt can be controlled from an external program via SWANK. For instance, Emacs with <a href="https://github.com/slime/slime">SLIME</a> makes it possible to hack Nyxt while it's running.</p>
1591 <p>But what about the other way around? Can we use Nyxt to manipulate other programs? Sure we can! Nyxt is a full-blown Common Lisp program that can leverage all of Common Lisp power to interact with foreign programs via Unix sockets, XML-RPC, you name it.</p>
1592 <p>An interesting example is that of Emacs, since it can be hacked live with Elisp, a language very similar to Common Lisp. In the following article, Nyxt will generate Elisp code to hack Emacs live!</p>
1593 <h1 id="youtube-dl-with-emacs">Youtube-dl with Emacs</h1>
1594 <p><a href="https://yt-dl.org">Youtube-dl</a> is a great program for downloading audio and video files from a ridiculous number of websites.</p>
1595 <p>That said, we would like to make it more convenient than constantly copy-pasting to a shell. Besides, naively calling <code>youtube-dl</code> from Nyxt is not so convenient since we lack feedback or interactivity with the running subprocess.</p>
1596 <p>We could derive our own Youtube-dl extension for Nyxt so that we would have a buffer showing progress of multiple downloads and allowing for interactivity. However, until someone works on the extension, let's see what others have been doing so far.</p>
1597 <p>Chris Wellon wrote <a href="https://github.com/skeeto/youtube-dl-emacs/">a great Emacs extension</a>, which sadly, only works for Youtube. This won't stop us! Here is our poor man's universal interface to Youtube-dl to supplement the aforementioned extension:</p>
1598 <div class="sourceCode" id="cb1" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb1-1" data-line-number="1">(<span class="kw">defun</span><span class="fu"> youtube-dl-url </span>(&amp;optional url)</a>
1599 <a class="sourceLine" id="cb1-2" data-line-number="2"> <span class="st">&quot;Run &#39;youtube-dl&#39; over the URL.</span></a>
1600 <a class="sourceLine" id="cb1-3" data-line-number="3"><span class="st">If URL is nil, use URL at point.&quot;</span></a>
1601 <a class="sourceLine" id="cb1-4" data-line-number="4"> (interactive)</a>
1602 <a class="sourceLine" id="cb1-5" data-line-number="5"> (<span class="kw">setq</span> url (<span class="kw">or</span> url (thing-at-point-url-at-point)))</a>
1603 <a class="sourceLine" id="cb1-6" data-line-number="6"> (<span class="kw">let</span> ((eshell-buffer-name <span class="st">&quot;*youtube-dl*&quot;</span>)</a>
1604 <a class="sourceLine" id="cb1-7" data-line-number="7"> (<span class="kw">directory</span> (cl-loop for dir in &#39;(<span class="st">&quot;~/Videos&quot;</span> <span class="st">&quot;~/Downloads&quot;</span>)</a>
1605 <a class="sourceLine" id="cb1-8" data-line-number="8"> <span class="kw">when</span> (file-directory-p dir)</a>
1606 <a class="sourceLine" id="cb1-9" data-line-number="9"> <span class="kw">return</span> (expand-file-name dir)</a>
1607 <a class="sourceLine" id="cb1-10" data-line-number="10"> finally <span class="kw">return</span> <span class="st">&quot;.&quot;</span>))</a>
1608 <a class="sourceLine" id="cb1-11" data-line-number="11"> (eshell)</a>
1609 <a class="sourceLine" id="cb1-12" data-line-number="12"> (<span class="kw">when</span> (eshell-interactive-process)</a>
1610 <a class="sourceLine" id="cb1-13" data-line-number="13"> (eshell <span class="kw">t</span>))</a>
1611 <a class="sourceLine" id="cb1-14" data-line-number="14"> (eshell-interrupt-process)</a>
1612 <a class="sourceLine" id="cb1-15" data-line-number="15"> (insert (<span class="kw">format</span> <span class="st">&quot;cd &#39;%s&#39; &amp;&amp; youtube-dl &quot;</span> <span class="kw">directory</span>) url)</a>
1613 <a class="sourceLine" id="cb1-16" data-line-number="16"> (eshell-send-input)))</a></code></pre></div>
1614 <p>The above snippet opens a dedicated <code>*youtube-dl*</code> Eshell buffer so that we can track download progress from there, as well as stack multiple video downloads.</p>
1615 <p>With that set up, now we can add the following snippet to our <code>nyxt/init.lisp</code>:</p>
1616 <div class="sourceCode" id="cb2" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb2-1" data-line-number="1">(<span class="kw">defun</span><span class="fu"> eval-in-emacs </span>(&amp;<span class="kw">rest</span> s-exps)</a>
1617 <a class="sourceLine" id="cb2-2" data-line-number="2"> <span class="st">&quot;Evaluate S-EXPS with emacsclient.&quot;</span></a>
1618 <a class="sourceLine" id="cb2-3" data-line-number="3"> (<span class="kw">let</span> ((s-exps-string (cl-strings:replace-all</a>
1619 <a class="sourceLine" id="cb2-4" data-line-number="4"> (<span class="kw">write-to-string</span></a>
1620 <a class="sourceLine" id="cb2-5" data-line-number="5"> `(<span class="kw">progn</span> ,@s-exps) <span class="bu">:case</span> :downcase)</a>
1621 <a class="sourceLine" id="cb2-6" data-line-number="6"> <span class="co">;; Discard the package prefix.</span></a>
1622 <a class="sourceLine" id="cb2-7" data-line-number="7"> <span class="st">&quot;nyxt::&quot;</span> <span class="st">&quot;&quot;</span>)))</a>
1623 <a class="sourceLine" id="cb2-8" data-line-number="8"> (<span class="kw">format</span> <span class="va">*error-output*</span> <span class="st">&quot;Sending to Emacs:~%~a~%&quot;</span> s-exps-string)</a>
1624 <a class="sourceLine" id="cb2-9" data-line-number="9"> (uiop:run-program</a>
1625 <a class="sourceLine" id="cb2-10" data-line-number="10"> (<span class="kw">list</span> <span class="st">&quot;emacsclient&quot;</span> <span class="st">&quot;--eval&quot;</span> s-exps-string))))</a>
1626 <a class="sourceLine" id="cb2-11" data-line-number="11"></a>
1627 <a class="sourceLine" id="cb2-12" data-line-number="12">(define-command youtube-dl-current-page ()</a>
1628 <a class="sourceLine" id="cb2-13" data-line-number="13"> <span class="st">&quot;Download a video in the currently open buffer.&quot;</span></a>
1629 <a class="sourceLine" id="cb2-14" data-line-number="14"> (with-result (url (buffer-get-url))</a>
1630 <a class="sourceLine" id="cb2-15" data-line-number="15"> (eval-in-emacs</a>
1631 <a class="sourceLine" id="cb2-16" data-line-number="16"> (<span class="kw">if</span> (<span class="kw">search</span> <span class="st">&quot;youtu&quot;</span> url)</a>
1632 <a class="sourceLine" id="cb2-17" data-line-number="17"> `(<span class="kw">progn</span> (youtube-dl ,url) (youtube-dl-list))</a>
1633 <a class="sourceLine" id="cb2-18" data-line-number="18"> `(youtube-dl-url ,url)))))</a>
1634 <a class="sourceLine" id="cb2-19" data-line-number="19"></a>
1635 <a class="sourceLine" id="cb2-20" data-line-number="20">(define-key <span class="st">&quot;C-c d&quot;</span> &#39;youtube-dl-current-page)</a></code></pre></div>
1636 <p>We define a helper function <code>eval-in-emacs</code> which sends a bunch of formatted s-expressions to Emacs. This requires the Emacs daemon, either by starting Emacs with <code>emacs --daemon</code> or by running <code>M-x server-start</code> from an Emacs instance.</p>
1637 <p>The <code>youtube-dl-current-page</code> command tests whether the current URL is Youtube, in which case we use Chris Wellons' <code>youtube-dl</code> extension, or else we rely on the Eshell version we wrote in our Emacs config.</p>
1638 <h1 id="org-mode-and-org-capture">Org-mode and Org-capture</h1>
1639 <p><a href="https://orgmode.org/">Org-mode</a> is a great extension for Emacs for note taking (and so much more). It has a feature called &quot;org-capture&quot; which, on a key press, will store some contextual information to your agenda, so that later Org will remind you to refer to it again.</p>
1640 <p>This can be useful for a web browser: You'd like to mark this page and let Org remind you to read it later? Nothing easier! And off we go to add the following snippet to our Emacs init file:</p>
1641 <div class="sourceCode" id="cb3" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb3-1" data-line-number="1">(add-to-list</a>
1642 <a class="sourceLine" id="cb3-2" data-line-number="2"> &#39;org-capture-templates</a>
1643 <a class="sourceLine" id="cb3-3" data-line-number="3"> `(<span class="st">&quot;w&quot;</span> <span class="st">&quot;Web link&quot;</span> entry (file+headline ,(<span class="kw">car</span> org-agenda-files) <span class="st">&quot;Links&quot;</span>)</a>
1644 <a class="sourceLine" id="cb3-4" data-line-number="4"> <span class="st">&quot;* %?%a</span><span class="sc">\n</span><span class="st">:SCHEDULED: %(org-insert-time-stamp (org-read-date nil t </span><span class="sc">\&quot;</span><span class="st">+1d</span><span class="sc">\&quot;</span><span class="st">))</span><span class="sc">\n</span><span class="st">&quot;</span>))</a></code></pre></div>
1645 <p>The above snippet does quite a few things, so let's analyze it carefully:</p>
1646 <ul>
1647 <li><p>The first <code>&quot;w&quot;</code> is the key binding to insert a web link when Org mode asks which capture to perform. You can add several capture templates with different key bindings to perform different actions.</p></li>
1648 <li><p><code>(file+headline ,(car org-agenda-files) &quot;Links&quot;)</code> tells Org where to insert to result. Here we chose the &quot;Links&quot; headline in our first agenda file.</p></li>
1649 <li><p><code>%a</code> is the Org URL of the page we are going to pass from Nyxt.</p></li>
1650 <li><p>The rest is arbitrary. Here we schedule the reading to the day after (<code>+1d</code> in the time-stamp).</p></li>
1651 </ul>
1652 <p>See <code>org-capture-templates</code> documentation for more details.</p>
1653 <p>Now to our <code>nyxt/init.lisp</code>:</p>
1654 <div class="sourceCode" id="cb4" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb4-1" data-line-number="1">(define-command org-capture ()</a>
1655 <a class="sourceLine" id="cb4-2" data-line-number="2"> <span class="st">&quot;Org-capture current page.&quot;</span></a>
1656 <a class="sourceLine" id="cb4-3" data-line-number="3"> (with-result* ((url (buffer-get-url))</a>
1657 <a class="sourceLine" id="cb4-4" data-line-number="4"> (title (buffer-get-title)))</a>
1658 <a class="sourceLine" id="cb4-5" data-line-number="5"> (eval-in-emacs</a>
1659 <a class="sourceLine" id="cb4-6" data-line-number="6"> `(org-link-set-parameters</a>
1660 <a class="sourceLine" id="cb4-7" data-line-number="7"> <span class="st">&quot;nyxt&quot;</span></a>
1661 <a class="sourceLine" id="cb4-8" data-line-number="8"> :store (<span class="kw">lambda</span> ()</a>
1662 <a class="sourceLine" id="cb4-9" data-line-number="9"> (org-store-link-props</a>
1663 <a class="sourceLine" id="cb4-10" data-line-number="10"> <span class="bu">:type</span> <span class="st">&quot;nyxt&quot;</span></a>
1664 <a class="sourceLine" id="cb4-11" data-line-number="11"> :link ,url</a>
1665 <a class="sourceLine" id="cb4-12" data-line-number="12"> :description ,title)))</a>
1666 <a class="sourceLine" id="cb4-13" data-line-number="13"> `(org-capture))))</a>
1667 <a class="sourceLine" id="cb4-14" data-line-number="14"></a>
1668 <a class="sourceLine" id="cb4-15" data-line-number="15">(define-key <span class="st">&quot;C-c C-t&quot;</span> &#39;org-capture)</a></code></pre></div>
1669 <p>This is similar to the example in the previous section. Note that we are passing multiple s-expressions to Emacs, they will all be wrapped into a single <code>(progn ...)</code> and Emacs will evaluate everything in one go.</p>
1670 <p>Happy hacking!</p>
1671 </body>
1672 </html>
1673 </content></entry><entry><id>urn:uuid:5a163163-5c04-3d7d-98fa-3c6f39a66674</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Technical Design</title><link href="https://nyxt.atlas.engineer/article/technical-design.org" /><content type="html"><!DOCTYPE html>
1674 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1675 <head>
1676 <meta charset="utf-8" />
1677 <meta name="generator" content="pandoc" />
1678 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1679 <title>Technical Design</title>
1680 <style type="text/css">
1681 code{white-space: pre-wrap;}
1682 span.smallcaps{font-variant: small-caps;}
1683 span.underline{text-decoration: underline;}
1684 div.column{display: inline-block; vertical-align: top; width: 50%;}
1685 </style>
1686 <!--[if lt IE 9]>
1687 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1688 <![endif]-->
1689 </head>
1690 <body>
1691 <header>
1692 <h1 class="title">Technical Design</h1>
1693 </header>
1694 <h1 id="requirements-of-a-browser">Requirements of a browser</h1>
1695 <p>A web browser is made of a few major components:</p>
1696 <ul>
1697 <li>A graphical user interface (GUI), written in, say Cocoa or GTK.</li>
1698 <li>A renderer (e.g. Gecko or WebKit).</li>
1699 <li>A controller (the glue code, which includes user configuration and interaction).</li>
1700 </ul>
1701 <h1 id="the-current-landscape-of-browsers">The current landscape of browsers</h1>
1702 <p>The graphical user interface can be a prominent part of the experience for browsers targeting a larger audience like Firefox or Safari. On the contrary, browsers targeting power-users tend to make minimal use of the toolkit, leaving most of the screen real-estate to the renderer.</p>
1703 <p>A renderer can be extremely difficult to write, so most browsers end up reusing an existing one, mostly without change. WebKit knows some success among power-user browsers.</p>
1704 <p>Last but not least, the controllers are mostly divided into two groups that correlate those of the graphical user interfaces: when predominantly &quot;user-friendly&quot;, the controller will often be an obscure, unhackable blackbox; when targeting power users, it will often be configurable with INI-style config files, or sometimes even an interpreted language such as Python or Lua.</p>
1705 <h1 id="the-poor-state-of-language-bindings-for-gui-toolkits">The poor state of language bindings for GUI toolkits</h1>
1706 <p>Initially, Nyxt was 100% written in Common Lisp, which means that the GUI toolkit had to be driven by language bindings.</p>
1707 <p>Indeed, the most common GUI toolkits are written in C or a variant of C, and as such if we want to use a different language, we need some form of translation between our language and the library language. Those language bindings can be tedious and difficult to write. For the ones that are developed to the point of being stable enough to be useful, they might not fully cover the library nonetheless, which means that some important features will be missing.</p>
1708 <p>Common Lisp has a rather complete Cocoa-binding library, but it mostly works with <a href="https://ccl.clozure.com/">Clozure CL</a> and not so well with other Common Lisp compilers.</p>
1709 <p>Sadly, the GTK bindings are not in a shape that is enough to fulfill our needs. We've tried to get Nyxt running with CL-CFFI-GTK on GNU/Linux for many months, to no avail.</p>
1710 <p>It turns out that this is not an isolated issue. Because of the complexity of GUI toolkits and how challenging it is to write bindings for various languages, there might not be a single language out there in which we can program complex graphical user interfaces that works well enough on all platforms.</p>
1711 <h1 id="split-process-design-a-cure-for-portable-interfaces">Split-process design: A cure for portable interfaces</h1>
1712 <p>Nyxt is all about the controller. Its selling point is to be infinitely extensible, so we really needed to write it in Lisp.</p>
1713 <p>The GUI toolkit and the renderer are only secondary. If we can't get all three components to work together in Lisp, then couldn't we just get the GUI and the renderer to work in a separate piece of software written in their native language?</p>
1714 <p>Then we would have only one thing left: the controller, manipulating the GUI and the renderer via some <a href="https://en.wikipedia.org/wiki/Remote_procedure_call">RPC</a> protocols. This way, we would get both the GUI and the renderer out of the way and solve both the language and the portability issue once and for all.</p>
1715 <h2 id="choosing-an-rpc-protocol">Choosing an RPC protocol</h2>
1716 <p>We chose XML-RPC, mostly because we had to choose one of the many options. XML-RPC is simple, wildly supported, old and stable.</p>
1717 <p>It operates very simply: the server registers a set of callbacks to execute when receiving a <em>method name</em>. The client sends an HTTP request whose body is a simple XML document with just two entries: the <em>method name</em> and its parameters, if any.</p>
1718 <p>While XML is more verbose (and arguably uglier) than JSON, it does not matter much because even from a developer's perspective we never get to look at the XML part. It's all handled by the XML-RPC clients and servers.</p>
1719 <p>XML-RPC can be used over HTTP sockets, and this is what we do. This comes with a nice side effect: we don't even need to run the separate parts on the same machine, they can be connected remotely over the Internet!</p>
1720 <h2 id="implementation-the-platform-port-and-the-lisp-core">Implementation: The platform port and the Lisp core</h2>
1721 <p>We've implemented two processes:</p>
1722 <ul>
1723 <li><p>The Lisp core which is a regular Common Lisp application firing up an XML-RPC server on startup.</p></li>
1724 <li><p>The &quot;platform port&quot;, which does three things:</p>
1725 <ul>
1726 <li>all the GUI parts,</li>
1727 <li>all the web rendering,</li>
1728 <li>and it also fires up its own XML-RPC server which responds to a set of specific requests.</li>
1729 </ul></li>
1730 </ul>
1731 <p>The Lisp core and the platform port are both XML-RPC clients and servers, because they both independently need to send messages to the other party.</p>
1732 <p>For instance, whenever the user presses a key, say <code>C-l</code>, it is intercepted by the GUI toolkit and sent over to the Lisp core. From there, the Lisp core checks whether it knows the binding or not. If not, it sends a response to the GUI telling it to forward the binding the other handlers in the application (a key like <code>space</code> would then scroll the page in the web view). If the binding is recognized, then the Lisp core calls the associated function, which in turn might send a new message to the GUI (in the case of <code>C-l</code>, it would tell the GUI to open the minibuffer).</p>
1733 <p>The platform port is very minimalist, it only needs to know how to perform a few simple tasks such as making a new window, instantiating rendering views and, importantly, evaluate JavaScript. Thanks to this last feature, it is possible to query arbitrary information from a web page (e.g. its title), manipulate it (e.g. add link hints), but also generate user interface elements, such as a prompt with completion, a status bar, etc.</p>
1734 <p>Since the Lisp core can generate JavaScript (with a Lisp syntax thanks to <a href="https://common-lisp.net/project/parenscript/">Parenscript</a>) and parse the result, possibilities become endless for the Lisp core, without even having to add features to the platform port.</p>
1735 <p>Indeed, once a platform port has been made to work, there is no more need to touch its code base. All future development can happen on the Lisp side!</p>
1736 <h1 id="benefits-of-a-split-process-design">Benefits of a split-process design</h1>
1737 <h2 id="high-level-browser-library">High-level browser library</h2>
1738 <p>In the end, the platform port is just a graphical user interface and some web rendering queries grouped together. That's it. For less than 1000 lines of C or Objective-C code, we have a fully working browser interface.</p>
1739 <p>Which means that from a programmer's point of view, this is possibly the simplest working example of a fully-functional web browser interface with a clear, minimal list of all the features required by the <em>controller</em>.</p>
1740 <h2 id="native-look-feel">Native <em>look &amp; feel</em></h2>
1741 <p>A nice consequence of the separation between the platform port and the controller is that it allows us to provides excellent user experience on any possible platform.</p>
1742 <h2 id="multiple-renderer-support">Multiple renderer support</h2>
1743 <p>Another cool side effect of this approach and that it is by design very <em>natural</em> to add support for extra web renderers.</p>
1744 <p>For the initial release, we've opted for WebKit for a few reasons:</p>
1745 <ul>
1746 <li><p>It's easy enough to embed into a project, possibly more than Gecko or Blink.</p></li>
1747 <li><p>It works well on all platforms and has both Cocoa and GTK support.</p></li>
1748 <li><p>In 2018, it's a call against the pressing monopoly of Blink. We wouldn't be too happy, would Internet ever become driven by a unique renderer whose development is not particularly community-oriented, while being subject to some arbitrary corporate policies.</p></li>
1749 </ul>
1750 <h2 id="robustness-and-security">Robustness and security</h2>
1751 <p>Because the platform port is so minimal, it is much easier to maintain and to fix bugs.</p>
1752 <p>The security-sensitive part, i.e. the renderer, is contained into a relatively simple executable. It's possible to start this executable within a container, so that security issues with the renderer (or, who knows, with the GUI toolkit) won't ever reach beyond the boundaries of the RPC calls.</p>
1753 <h2 id="resistance-to-web-renderer-api-breakages">Resistance to web renderer API breakages</h2>
1754 <p>Last but not least, our design means that the web renderer is no longer a critical dependency.</p>
1755 <p>Many times in the past, it happened that a web renderer API would break the backward compatibility, thus breaking all web browsers depending on it in the process.</p>
1756 <p>When WebKit 2.0 came out, many WebKit-1-based browsers became obsolete. Rewriting them was so much work that many of them were simply abandoned.</p>
1757 <p>More recently, it happened again with Firefox' extensions when XUL was dropped. Not only the extensions, but also <a href="http://www.conkeror.org/">Conkeror</a>, which was a full-fledged browser written in XUL and became obsolete from one day to the next.</p>
1758 <p>With our split-process design, should a web renderer break, we would only have to update or rewrite a platform port. Thus we get the guarantee that the Lisp core and all the community-written extensions will never break.</p>
1759 </body>
1760 </html>
1761 </content></entry><entry><id>urn:uuid:c61f3aed-0d4b-38e0-8456-af5a396fddf8</id><updated>2020-10-20T00:00:00.00+00:00</updated><title>Hooks</title><link href="https://nyxt.atlas.engineer/article/hooks.org" /><content type="html"><!DOCTYPE html>
1762 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1763 <head>
1764 <meta charset="utf-8" />
1765 <meta name="generator" content="pandoc" />
1766 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1767 <title>Hooks in practice</title>
1768 <style type="text/css">
1769 code{white-space: pre-wrap;}
1770 span.smallcaps{font-variant: small-caps;}
1771 span.underline{text-decoration: underline;}
1772 div.column{display: inline-block; vertical-align: top; width: 50%;}
1773 </style>
1774 <style type="text/css">
1775 a.sourceLine { display: inline-block; line-height: 1.25; }
1776 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
1777 a.sourceLine:empty { height: 1.2em; position: absolute; }
1778 .sourceCode { overflow: visible; }
1779 code.sourceCode { white-space: pre; position: relative; }
1780 div.sourceCode { margin: 1em 0; }
1781 pre.sourceCode { margin: 0; }
1782 @media screen {
1783 div.sourceCode { overflow: auto; }
1784 }
1785 @media print {
1786 code.sourceCode { white-space: pre-wrap; }
1787 a.sourceLine { text-indent: -1em; padding-left: 1em; }
1788 }
1789 pre.numberSource a.sourceLine
1790 { position: relative; }
1791 pre.numberSource a.sourceLine:empty
1792 { position: absolute; }
1793 pre.numberSource a.sourceLine::before
1794 { content: attr(data-line-number);
1795 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
1796 border: none; pointer-events: all;
1797 -webkit-touch-callout: none; -webkit-user-select: none;
1798 -khtml-user-select: none; -moz-user-select: none;
1799 -ms-user-select: none; user-select: none;
1800 padding: 0 4px; width: 4em;
1801 color: #aaaaaa;
1802 }
1803 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
1804 div.sourceCode
1805 { }
1806 @media screen {
1807 a.sourceLine::before { text-decoration: underline; }
1808 }
1809 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
1810 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
1811 code span.at { color: #7d9029; } /* Attribute */
1812 code span.bn { color: #40a070; } /* BaseN */
1813 code span.bu { } /* BuiltIn */
1814 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
1815 code span.ch { color: #4070a0; } /* Char */
1816 code span.cn { color: #880000; } /* Constant */
1817 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
1818 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
1819 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
1820 code span.dt { color: #902000; } /* DataType */
1821 code span.dv { color: #40a070; } /* DecVal */
1822 code span.er { color: #ff0000; font-weight: bold; } /* Error */
1823 code span.ex { } /* Extension */
1824 code span.fl { color: #40a070; } /* Float */
1825 code span.fu { color: #06287e; } /* Function */
1826 code span.im { } /* Import */
1827 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
1828 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
1829 code span.op { color: #666666; } /* Operator */
1830 code span.ot { color: #007020; } /* Other */
1831 code span.pp { color: #bc7a00; } /* Preprocessor */
1832 code span.sc { color: #4070a0; } /* SpecialChar */
1833 code span.ss { color: #bb6688; } /* SpecialString */
1834 code span.st { color: #4070a0; } /* String */
1835 code span.va { color: #19177c; } /* Variable */
1836 code span.vs { color: #4070a0; } /* VerbatimString */
1837 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
1838 </style>
1839 <!--[if lt IE 9]>
1840 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
1841 <![endif]-->
1842 </head>
1843 <body>
1844 <header>
1845 <h1 class="title">Hooks in practice</h1>
1846 </header>
1847 <p>Update: This article was updated for Nyxt 2 for which the hook system has been completely rewritten.</p>
1848 <h1 id="using-hooks-to-smart-program-your-browser">Using hooks to smart-program your browser</h1>
1849 <p>Hooks are a great way to extend a workflow by triggering actions upon events. Simply put, a hook is an object that holds a list of <em>handlers</em>, which are functions called when the hook is <em>run</em> at a precisely defined point in the program.</p>
1850 <p>In the world of a web browser, there are a ton of events: page loaded, DOM available, page rendered, etc. In addition to the events fired off by normal processing of web pages there are a large set of events which include actions by the user: tab deleted, page bookmarked, command called, mode enabled, etc.</p>
1851 <p>In Nyxt, all these events are <em>hookable</em>.</p>
1852 <p>Hooking into the events fired off by the browser or by the user allows the creation of extendable and tailored workflows.</p>
1853 <h1 id="the-nyxt-hook-system">The Nyxt hook system</h1>
1854 <p>Many hooks are as such executed at different points in Nyxt:</p>
1855 <ul>
1856 <li><p><strong>Global</strong> hooks, such as the <code>*after-init-hook*</code> hook, which is run after the browser has been initialized.</p></li>
1857 <li><p><strong>Window</strong> and <strong>buffer</strong> related hooks (before and after creation, before and after the page is loaded, etc.).</p></li>
1858 <li><p><strong>Modes</strong> hooks (before and after a mode is enabled or disabled).</p></li>
1859 <li><p>&quot;Before&quot; and &quot;after&quot; <strong>command</strong> hooks.</p></li>
1860 </ul>
1861 <p>For the full list, run <code>describe-variable</code> and <code>describe-slot</code> over the names ending with <code>-hook</code>.</p>
1862 <h2 id="practical-examples">Practical examples</h2>
1863 <p>Let's consider a practical example. If you want to force the redirection of a domain to another, you can use the <code>request-resource-hook</code> to change the URL and return a new one. In the example below, we make sure we always visit <code>old.reddit.com</code> instead of the new Reddit interface:</p>
1864 <div class="sourceCode" id="cb1" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb1-1" data-line-number="1">(<span class="kw">defun</span><span class="fu"> old-reddit-handler </span>(request-data)</a>
1865 <a class="sourceLine" id="cb1-2" data-line-number="2"> (<span class="kw">let</span> ((uri (url request-data)))</a>
1866 <a class="sourceLine" id="cb1-3" data-line-number="3"> (<span class="kw">setf</span> (url request-data)</a>
1867 <a class="sourceLine" id="cb1-4" data-line-number="4"> (<span class="kw">if</span> (<span class="kw">search</span> <span class="st">&quot;reddit.com&quot;</span> (quri:uri-host uri))</a>
1868 <a class="sourceLine" id="cb1-5" data-line-number="5"> (<span class="kw">progn</span></a>
1869 <a class="sourceLine" id="cb1-6" data-line-number="6"> (<span class="kw">setf</span> (quri:uri-host uri) <span class="st">&quot;old.reddit.com&quot;</span>)</a>
1870 <a class="sourceLine" id="cb1-7" data-line-number="7"> (log:info <span class="st">&quot;Switching to old Reddit: ~s&quot;</span> (object-display uri))</a>
1871 <a class="sourceLine" id="cb1-8" data-line-number="8"> uri)</a>
1872 <a class="sourceLine" id="cb1-9" data-line-number="9"> uri)))</a>
1873 <a class="sourceLine" id="cb1-10" data-line-number="10"> request-data)</a>
1874 <a class="sourceLine" id="cb1-11" data-line-number="11"></a>
1875 <a class="sourceLine" id="cb1-12" data-line-number="12">(define-configuration buffer</a>
1876 <a class="sourceLine" id="cb1-13" data-line-number="13"> ((request-resource-hook</a>
1877 <a class="sourceLine" id="cb1-14" data-line-number="14"> (<span class="kw">reduce</span> #&#39;hooks:add-hook</a>
1878 <a class="sourceLine" id="cb1-15" data-line-number="15"> (<span class="kw">mapcar</span> #&#39;make-handler-resource (<span class="kw">list</span> #&#39;old-reddit-handler))</a>
1879 <a class="sourceLine" id="cb1-16" data-line-number="16"> <span class="bu">:initial-value</span> %slot-default))))</a></code></pre></div>
1880 <p>You can ask Nyxt to automatically enable or disable modes depending on the URL, for instance, you can toggle the proxy mode per domain, which can be very convenient if you would like to, say, disable Tor for some resource intensive domains.</p>
1881 <p>Another cool example would be automatically downloading any YouTube video we visit:</p>
1882 <div class="sourceCode" id="cb2" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb2-1" data-line-number="1">(<span class="kw">defvar</span><span class="fu"> +youtube-dl-command+ </span><span class="st">&quot;youtube-dl&quot;</span></a>
1883 <a class="sourceLine" id="cb2-2" data-line-number="2"> <span class="st">&quot;Path to the &#39;youtube-dl&#39; program.&quot;</span>)</a>
1884 <a class="sourceLine" id="cb2-3" data-line-number="3"></a>
1885 <a class="sourceLine" id="cb2-4" data-line-number="4">(<span class="kw">defun</span><span class="fu"> auto-yt-dl-handler </span>(request-data)</a>
1886 <a class="sourceLine" id="cb2-5" data-line-number="5"> <span class="st">&quot;Download a Youtube URL asynchronously to /tmp/videos/.</span></a>
1887 <a class="sourceLine" id="cb2-6" data-line-number="6"><span class="st">Videos are downloaded with `+youtube-dl-command+&#39;.&quot;</span></a>
1888 <a class="sourceLine" id="cb2-7" data-line-number="7"> (<span class="kw">let</span> ((url (url request-data)))</a>
1889 <a class="sourceLine" id="cb2-8" data-line-number="8"> (<span class="kw">if</span> (<span class="kw">and</span> url</a>
1890 <a class="sourceLine" id="cb2-9" data-line-number="9"> (<span class="kw">member</span> (quri:uri-domain url) &#39;(<span class="st">&quot;youtube.com&quot;</span> <span class="st">&quot;youtu.be&quot;</span>)</a>
1891 <a class="sourceLine" id="cb2-10" data-line-number="10"> <span class="bu">:test</span> #&#39;string=)</a>
1892 <a class="sourceLine" id="cb2-11" data-line-number="11"> (<span class="kw">string=</span> (quri:uri-path url) <span class="st">&quot;/watch&quot;</span>))</a>
1893 <a class="sourceLine" id="cb2-12" data-line-number="12"> (<span class="kw">progn</span></a>
1894 <a class="sourceLine" id="cb2-13" data-line-number="13"> (echo <span class="st">&quot;Youtube: downloading ~a&quot;</span> url)</a>
1895 <a class="sourceLine" id="cb2-14" data-line-number="14"> (uiop:launch-program (<span class="kw">list</span> +youtube-dl-command+ (quri:render-uri url) <span class="st">&quot;-o&quot;</span> <span class="st">&quot;/tmp/videos/%(title)s.%(ext)s&quot;</span>))</a>
1896 <a class="sourceLine" id="cb2-15" data-line-number="15"> <span class="co">;; Return nil to cancel the page load.</span></a>
1897 <a class="sourceLine" id="cb2-16" data-line-number="16"> <span class="kw">nil</span>)</a>
1898 <a class="sourceLine" id="cb2-17" data-line-number="17"> request-data)))</a>
1899 <a class="sourceLine" id="cb2-18" data-line-number="18"></a>
1900 <a class="sourceLine" id="cb2-19" data-line-number="19">(define-configuration buffer</a>
1901 <a class="sourceLine" id="cb2-20" data-line-number="20"> ((request-resource-hook</a>
1902 <a class="sourceLine" id="cb2-21" data-line-number="21"> (<span class="kw">reduce</span> #&#39;hooks:add-hook</a>
1903 <a class="sourceLine" id="cb2-22" data-line-number="22"> (<span class="kw">mapcar</span> #&#39;make-handler-resource (<span class="kw">list</span> #&#39;auto-yt-dl-handler))</a>
1904 <a class="sourceLine" id="cb2-23" data-line-number="23"> <span class="bu">:initial-value</span> %slot-default))))</a></code></pre></div>
1905 <p>Adjust it to your taste!</p>
1906 <h2 id="all-user-commands-have-hooks">All user commands have hooks</h2>
1907 <p>One feature that makes Nyxt unique is the ability to extend commands exposed to the user.</p>
1908 <p>Because the Common Lisp language allows it, one could replace a command definition by another function. This is however not the recommended approach, most notably because it could break the built-in behavior.</p>
1909 <p>We can then use the &quot;before&quot; and &quot;after&quot; hooks to extend the built-in commands. It is as simple as defining a new function with no parameters:</p>
1910 <div class="sourceCode" id="cb3" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb3-1" data-line-number="1">(<span class="kw">defun</span><span class="fu"> post-bookmark-hook </span>()</a>
1911 <a class="sourceLine" id="cb3-2" data-line-number="2"> <span class="co">;; Your bookmark synchronization code...</span></a>
1912 <a class="sourceLine" id="cb3-3" data-line-number="3"> (log:info <span class="st">&quot;Let&#39;s sync the bookmarks!&quot;</span>))</a></code></pre></div>
1913 <p>and adding it to the list of hooks:</p>
1914 <div class="sourceCode" id="cb4" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="cb4-1" data-line-number="1">(hooks:add-hook bookmark-url-after-hook (hooks:make-handler-void #&#39;post-bookmark-hook))</a></code></pre></div>
1915 <p>And voila!</p>
1916 <h1 id="conclusions">Conclusions</h1>
1917 <p>In summary, hooks present a very simple and effective mechanism to chain behavior in your workflows. We are looking forward to seeing what you can create with them!</p>
1918 <p>For more about details on the hook internals and advanced usage, see our <a href="https://nyxt.atlas.engineer/article/hooks-implementation.org">other article</a>.</p>
1919 <p>Thanks for reading!</p>
1920 </body>
1921 </html>
1922 </content></entry><entry><id>urn:uuid:fb160a1c-75ad-3af8-aa3d-05e9799e388f</id><updated>2020-06-02T00:00:00.00+00:00</updated><title>Command Line Programs</title><link href="https://nyxt.atlas.engineer/article/command-line-programs.org" /><content type="html"><!DOCTYPE html>
1923 <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
1924 <head>
1925 <meta charset="utf-8" />
1926 <meta name="generator" content="pandoc" />
1927 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
1928 <title>Command Line Programs</title>
1929 <style type="text/css">
1930 code{white-space: pre-wrap;}
1931 span.smallcaps{font-variant: small-caps;}
1932 span.underline{text-decoration: underline;}
1933 div.column{display: inline-block; vertical-align: top; width: 50%;}
1934 </style>
1935 <style type="text/css">
1936 a.sourceLine { display: inline-block; line-height: 1.25; }
1937 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
1938 a.sourceLine:empty { height: 1.2em; position: absolute; }
1939 .sourceCode { overflow: visible; }
1940 code.sourceCode { white-space: pre; position: relative; }
1941 div.sourceCode { margin: 1em 0; }
1942 pre.sourceCode { margin: 0; }
1943 @media screen {
1944 div.sourceCode { overflow: auto; }
1945 }
1946 @media print {
1947 code.sourceCode { white-space: pre-wrap; }
1948 a.sourceLine { text-indent: -1em; padding-left: 1em; }
1949 }
1950 pre.numberSource a.sourceLine
1951 { position: relative; }
1952 pre.numberSource a.sourceLine:empty
1953 { position: absolute; }
1954 pre.numberSource a.sourceLine::before
1955 { content: attr(data-line-number);
1956 position: absolute; left: -5em; text-align: right; vertical-align: baseline;
1957 border: none; pointer-events: all;
1958 -webkit-touch-callout: none; -webkit-user-select: none;
1959 -khtml-user-select: none; -moz-user-select: none;
1960 -ms-user-select: none; user-select: none;
1961 padding: 0 4px; width: 4em;
1962 color: #aaaaaa;
1963 }
1964 pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
1965 div.sourceCode
1966 { }
1967 @media screen {
1968 a.sourceLine::before { text-decoration: underline; }
1969 }
1970 code span.al { color: #ff0000; font-weight: bold; } /* Alert */
1971 code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
1972 code span.at { color: #7d9029; } /* Attribute */
1973 code span.bn { color: #40a070; } /* BaseN */
1974 code span.bu { } /* BuiltIn */
1975 code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
1976 code span.ch { color: #4070a0; } /* Char */
1977 code span.cn { color: #880000; } /* Constant */
1978 code span.co { color: #60a0b0; font-style: italic; } /* Comment */
1979 code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
1980 code span.do { color: #ba2121; font-style: italic; } /* Documentation */
1981 code span.dt { color: #902000; } /* DataType */
1982 code span.dv { color: #40a070; } /* DecVal */
1983 code span.er { color: #ff0000; font-weight: bold; } /* Error */
1984 code span.ex { } /* Extension */
1985 code span.fl { color: #40a070; } /* Float */
1986 code span.fu { color: #06287e; } /* Function */
1987 code span.im { } /* Import */
1988 code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
1989 code span.kw { color: #007020; font-weight: bold; } /* Keyword */
1990 code span.op { color: #666666; } /* Operator */
1991 code span.ot { color: #007020; } /* Other */
1992 code span.pp { color: #bc7a00; } /* Preprocessor */
1993 code span.sc { color: #4070a0; } /* SpecialChar */
1994 code span.ss { color: #bb6688; } /* SpecialString */
1995 code span.st { color: #4070a0; } /* String */
1996 code span.va { color: #19177c; } /* Variable */
1997 code span.vs { color: #4070a0; } /* VerbatimString */
1998 code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
1999 </style>
2000 <!--[if lt IE 9]>
2001 <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
2002 <![endif]-->
2003 </head>
2004 <body>
2005 <header>
2006 <h1 class="title">Command Line Programs</h1>
2007 </header>
2008 <h1 id="running-programs-in-nyxt">Running Programs in Nyxt</h1>
2009 <p>Nyxt gives you the power to extend its capabilities by invoking other programs. This allows you to chain Lisp functions and operations with any programs of your choosing.</p>
2010 <h1 id="a-practical-example-download-youtube-videos">A Practical Example: Download Youtube Videos</h1>
2011 <p>Let's consider the following situation: you are watching a Youtube video, but wait! You have somewhere to be! Why not download the video so you can watch it on the train where your internet access will be limited? Sounds good right? Let's see what options there are.</p>
2012 <p>A quick search on the internet reveals a very convenient program called <a href="https://github.com/rg3/youtube-dl/">youtube-dl</a>. Youtube-dl is invoked via the command line like this: <code>youtube-dl &quot;url-to-download&quot;</code>. Of course there are other flags and arguments, but let's consider the simplest case.</p>
2013 <p>You could simply copy the URL and paste it into the terminal. That's not really cool though. Let's automate it:</p>
2014 <div class="sourceCode" id="youtube-dl" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="youtube-dl-1" data-line-number="1">(define-command youtube-dl-current-page ()</a>
2015 <a class="sourceLine" id="youtube-dl-2" data-line-number="2"> <span class="st">&quot;Download a Youtube video in the currently open buffer.&quot;</span></a>
2016 <a class="sourceLine" id="youtube-dl-3" data-line-number="3"> (with-result (url (buffer-get-url))</a>
2017 <a class="sourceLine" id="youtube-dl-4" data-line-number="4"> (uiop:run-program</a>
2018 <a class="sourceLine" id="youtube-dl-5" data-line-number="5"> (<span class="kw">list</span> <span class="st">&quot;youtube-dl&quot;</span> url))))</a></code></pre></div>
2019 <p>Just like that! Instant Youtube downloader script. If you want, bind it to a keybinding:</p>
2020 <div class="sourceCode" id="youtube-dl-keybinding" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="youtube-dl-keybinding-1" data-line-number="1">(define-key <span class="st">&quot;C-c d&quot;</span> &#39;youtube-dl-current-page)</a></code></pre></div>
2021 <p>Now whenever you want to download a Youtube video simply &quot;C-c d&quot; and you'll have it on your computer!</p>
2022 <h1 id="shell-mode">&quot;Shell&quot; Mode</h1>
2023 <p>That was cool, but it doesn't really show the true power of Nyxt. An example that is more illustrative is a very basic &quot;shell&quot; implementation. It is not really a shell because it doesn't have variables, piping, or anything else a shell really has, but it can run programs.</p>
2024 <p>Simply put: shell mode is an extension for running simple one-liner shell commands and seeing the output. There is no history or variables. Use <code>C-x s</code> to enter <code>*shell-mode*</code> and <code>c</code> to enter a command and <code>k</code> to clear the command output.</p>
2025 <div class="sourceCode" id="shell-mode" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><a class="sourceLine" id="shell-mode-1" data-line-number="1">(define-mode shell-mode ()</a>
2026 <a class="sourceLine" id="shell-mode-2" data-line-number="2"> <span class="st">&quot;A basic shell prompt.&quot;</span></a>
2027 <a class="sourceLine" id="shell-mode-3" data-line-number="3"> ((keymap-schemes</a>
2028 <a class="sourceLine" id="shell-mode-4" data-line-number="4"> :initform</a>
2029 <a class="sourceLine" id="shell-mode-5" data-line-number="5"> (<span class="kw">let</span> ((<span class="kw">map</span> (make-keymap)))</a>
2030 <a class="sourceLine" id="shell-mode-6" data-line-number="6"> (define-key :keymap <span class="kw">map</span></a>
2031 <a class="sourceLine" id="shell-mode-7" data-line-number="7"> <span class="st">&quot;c&quot;</span> &#39;run-shell-command</a>
2032 <a class="sourceLine" id="shell-mode-8" data-line-number="8"> <span class="st">&quot;k&quot;</span> &#39;clear-shell)</a>
2033 <a class="sourceLine" id="shell-mode-9" data-line-number="9"> (<span class="kw">list</span> :emacs <span class="kw">map</span></a>
2034 <a class="sourceLine" id="shell-mode-10" data-line-number="10"> :vi-normal <span class="kw">map</span>)))))</a>
2035 <a class="sourceLine" id="shell-mode-11" data-line-number="11"></a>
2036 <a class="sourceLine" id="shell-mode-12" data-line-number="12">(define-parenscript clear-shell-output ()</a>
2037 <a class="sourceLine" id="shell-mode-13" data-line-number="13"> (<span class="kw">setf</span> (ps:chain document body inner-h-t-m-l) <span class="st">&quot;&quot;</span>))</a>
2038 <a class="sourceLine" id="shell-mode-14" data-line-number="14"></a>
2039 <a class="sourceLine" id="shell-mode-15" data-line-number="15">(define-command clear-shell (shell-mode)</a>
2040 <a class="sourceLine" id="shell-mode-16" data-line-number="16"> <span class="st">&quot;Clear the output in the shell buffer.&quot;</span></a>
2041 <a class="sourceLine" id="shell-mode-17" data-line-number="17"> (rpc-buffer-evaluate-javascript</a>
2042 <a class="sourceLine" id="shell-mode-18" data-line-number="18"> *interface* (active-buffer *interface*)</a>
2043 <a class="sourceLine" id="shell-mode-19" data-line-number="19"> (clear-shell-output)))</a>
2044 <a class="sourceLine" id="shell-mode-20" data-line-number="20"></a>
2045 <a class="sourceLine" id="shell-mode-21" data-line-number="21">(define-parenscript append-output (output)</a>
2046 <a class="sourceLine" id="shell-mode-22" data-line-number="22"> (<span class="kw">setf</span> (ps:chain document body inner-h-t-m-l)</a>
2047 <a class="sourceLine" id="shell-mode-23" data-line-number="23"> (ps:chain document body inner-h-t-m-l</a>
2048 <a class="sourceLine" id="shell-mode-24" data-line-number="24"> (concat (ps:lisp</a>
2049 <a class="sourceLine" id="shell-mode-25" data-line-number="25"> (<span class="kw">format</span> <span class="kw">nil</span> <span class="st">&quot;&lt;pre&gt;&lt;code&gt;~a&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&quot;</span> output))))))</a>
2050 <a class="sourceLine" id="shell-mode-26" data-line-number="26"></a>
2051 <a class="sourceLine" id="shell-mode-27" data-line-number="27">(define-command run-shell-command (shell-mode)</a>
2052 <a class="sourceLine" id="shell-mode-28" data-line-number="28"> <span class="st">&quot;Run a shell command.&quot;</span></a>
2053 <a class="sourceLine" id="shell-mode-29" data-line-number="29"> (with-result</a>
2054 <a class="sourceLine" id="shell-mode-30" data-line-number="30"> (input (read-from-minibuffer</a>
2055 <a class="sourceLine" id="shell-mode-31" data-line-number="31"> (minibuffer *interface*)</a>
2056 <a class="sourceLine" id="shell-mode-32" data-line-number="32"> :input-prompt <span class="st">&quot;Run in shell:&quot;</span>))</a>
2057 <a class="sourceLine" id="shell-mode-33" data-line-number="33"> (rpc-buffer-evaluate-javascript</a>
2058 <a class="sourceLine" id="shell-mode-34" data-line-number="34"> *interface* (active-buffer *interface*)</a>
2059 <a class="sourceLine" id="shell-mode-35" data-line-number="35"> (append-output</a>
2060 <a class="sourceLine" id="shell-mode-36" data-line-number="36"> <span class="bu">:output</span></a>
2061 <a class="sourceLine" id="shell-mode-37" data-line-number="37"> (uiop:run-program input :force-shell <span class="kw">t</span> <span class="bu">:output</span> :string)))))</a>
2062 <a class="sourceLine" id="shell-mode-38" data-line-number="38"></a>
2063 <a class="sourceLine" id="shell-mode-39" data-line-number="39">(define-command shell ()</a>
2064 <a class="sourceLine" id="shell-mode-40" data-line-number="40"> <span class="st">&quot;Open a shell buffer.&quot;</span></a>
2065 <a class="sourceLine" id="shell-mode-41" data-line-number="41"> (set-active-buffer *interface* (make-buffer <span class="bu">:name</span> <span class="st">&quot;*shell*&quot;</span> :default-modes &#39;(shell-mode))))</a>
2066 <a class="sourceLine" id="shell-mode-42" data-line-number="42"></a>
2067 <a class="sourceLine" id="shell-mode-43" data-line-number="43">(define-key <span class="st">&quot;C-x s&quot;</span> #&#39;shell)</a></code></pre></div>
2068 <p>Within 40 lines of Lisp we've managed to make a completely new mode that allows us to execute commands, view the output on screen, and even clear the screen.</p>
2069 <h1 id="the-take-away">The Take Away</h1>
2070 <p>Nyxt can be extended with any program of any type as long as it accepts some form of IPC. This means that you can chain any process you want on your computer. Of course, this application has bounds of reason, you shouldn't imagine that Nyxt will turn into your system shell, process manager- even though it could.</p>
2071 <p>Thanks for reading!</p>
2072 </body>
2073 </html>
2074