Posts tagged "Emacs"urn:www-greghendershott-com:Emacs2020-02-24T00:00:00ZThe Big Switcheroourn:www-greghendershott-com:-2020-02-the-big-switcheroo.html2020-02-24T00:00:00Z2020-02-24T00:00:00ZGreg Hendershott
<div>
<article>
<header>
<h1>The Big Switcheroo</h1>
<p class="date-and-tags">
<time datetime="2020-02-24" pubdate="true">2020-02-24</time> :: <span class="tags"><a href="/tags/Racket.html">Racket</a>, <a href="/tags/Emacs.html">Emacs</a></span></p></header>
<p>In my <a href="/2020/02/using-drracket-check-syntax-in-racket-mode.html">previous post</a> I talked about how Racket Mode now will often want the back end command server, before actually needing a live REPL — but it has to start a REPL anyway. This was bothering me. So I went on to address that. Doing so entailed reversing the I/O model for the back end. As a bonus, that set up fairly short strokes to supporting multiple REPLs.</p><!-- more-->
<p>In the beginning, Racket Mode was a thin wrapper around <code>xrepl</code>. As a result, it used a <code>comint-mode</code> buffer to start Racket, and the REPL stdin/stdout was connected to the <code>comint-mode</code> buffer. The back end also started a little TCP server; connecting to that established the I/O for commands.</p>
<p>This was mostly fine, especially when <code>racket-run</code> tended to be the first command you would use.</p>
<p>However it might take a second or two for the TCP server to be ready to accept connections. As a result, the front end either needed to block (boo!) or use an Emacs timer to retry at, say, one second intervals until success. That meant some extra complexity. More basically, it meant more delay until a command request and response could occur.</p>
<h1 id="flip">Flip</h1>
<p>So I decided to flip that around. Now, the stdin/stdout of the back end process is the command request/response channel. The same format of sexpr command requests and responses are sent — they just happen to go over ports that are stdin/stdout instead of TCP ports. The TCP server is for creating a REPL session, if/when that is desired. Make a TCP connection, read a session ID, et voila you have a new REPL session. The back end <code>parameterize</code>s the REPL’s <code>current-{input
output error}-mode</code> to the TCP ports. And fortunately, <code>comint-mode</code> makes it as easy to connect the buffer to I/O from a TCP connection, as to stdin/stdout of a process.</p>
<p>The other thing is, a process can have only one stdin/stdout. But of course it can accept multiple TCP connections. Now that we use the latter for REPL I/O, this removes a basic barrier to an old feature request: Supporting multiple REPLs would now be possible.</p>
<p>Of course “possible” is different than “implemented and working correctly”. So at first I focused mainly on the back end: Make sure that it wasn’t using global variables when it could use per-thread parameters, for things related to the REPL. Add a lookup table from unique REPL session IDs to information about each REPL session. Have the front end obtain the session ID and supply it later with commands — but otherwise, for now, the front end still just created one REPL session at a time.</p>
<h1 id="multiple-repls">Multiple REPLs</h1>
<p>After some time to get that working, I wanted to tackle supporting multiple REPLs in the front end. For a day or two, I procrastinated. I <em>really</em> did not want to write a bunch of “ceremonial” code related to REPL sessions. I did not want some whole UI for that, complete with more code and bugs.</p>
<p>I’m glad I hesitated, because I realized something simple. Emacs already has the concept that variable values can be global to all buffers — but also can be set so that a buffer has its own, local value.</p>
<p>So, assume a variable <code>racket-repl-buffer-name</code>. It only has meaning for a <code>racket-mode</code> buffer. It means, “what is the name of the <code>racket-repl-mode</code> buffer that commands like <code>racket-run</code> should use”. Initially such a variable could have a global value, <code>*Racket REPL*</code>. That default is the status quo behavior: All edit buffers take turns sharing the same, one and only REPL buffer.</p>
<p>Now, what if a <code>racket-mode</code> buffer for <code>foo.rkt</code> did a <code>(setq-local
racket-repl-buffer-name "*Racket REPL foo.rkt*")</code>? Now commands issued with that buffer selected would use (creating if necessary) a REPL buffer of <em>that</em> name. If every edit buffer did this, you’d have one REPL per edit buffer (much like DrRacket).</p>
<p>You could also imagine wanting edit buffers for files that are in the same <code>projectile</code> project, to share a REPL buffer: “One REPL per project”. OK: <code>setq-local</code> their <code>racket-repl-buffer-name</code> to some common name that includes the project name or root directory.</p>
<p>And so that is the mechanism I went with. A customization variable <code>racket-repl-buffer-name-function</code> points to a function that will set the <code>racket-repl-buffer-name</code> variable value for a <code>racket-mode</code> edit buffer when it is created. I defined three such functions, for the three strategies described above. And best of all, as a user you can supply your own such function.</p>
<p>I also added a <code>kill-buffer-hook</code>: When you kill a <code>racket-mode</code> edit buffer, and it is the last one using a <code>racket-repl-mode</code> buffer, we <code>y-or-n-prompt</code> offering to kill the REPL buffer, too. I figure that will help keep things cleaner, especially for the case where people want 1:1 edit:REPL buffers.</p>
<p>As a result, there is no Big UI about “sessions”. There are just edit buffers, and names of the REPL buffer(s) each should use. Because it rides directly on Emacs semantics for variables and buffers, there is non-trivial code that I did not need to write — and “out of sync” bugs that I could not create.</p>
<h1 id="that-cleaving-feeling">That cleaving feeling</h1>
<p>Of course there are <em>some</em> bugs lurking, about which I don’t yet know. Someday I’ll probably feel discouraged about this code, for reasons I don’t yet know. A lot of programming “innovation” amounts to trading an old set of problems for a new set. Sometimes the new problems aren’t better, they just feel better, at first, because novelty.</p>
<p>All stipulated and admitted. Even so, I <em>also</em> feel this was one of those situations where, finally, I saw a way to define a problem so that it aligns with the material I had to work with: Just a few gentle taps, and the material cleaves along the lines I need and want. That is a pretty awesome feeling. While it lasts.</p>
<h1 id="availability">Availability</h1>
<p>The stuff I’m describing in this blog post initially lived on a <code>new-comm</code> branch. I did just merge it back to the <code>check-syntax</code> branch. It’s <em>not</em> yet merged to <code>master</code>. I’m still reviewing documentation, dogfooding, and such. I’m coming up on two full months working on this, so, I’d like to merge to <code>master</code> in the near future.</p>
<footer></footer></article></div>Using check-syntax in Racket Modeurn:www-greghendershott-com:-2020-02-using-drracket-check-syntax-in-racket-mode.html2020-02-14T00:00:00Z2020-02-14T00:00:00ZGreg Hendershott
<div>
<article>
<header>
<h1>Using check-syntax in Racket Mode</h1>
<p class="date-and-tags">
<time datetime="2020-02-14" pubdate="true">2020-02-14</time> :: <span class="tags"><a href="/tags/Racket.html">Racket</a>, <a href="/tags/Emacs.html">Emacs</a></span></p></header>
<p>During most of January and into February, I’ve been working full-time to have <a href="https://github.com/greghendershott/racket-mode/">Racket Mode</a> make better use of <a href="https://docs.racket-lang.org/drracket-tools/Accessing_Check_Syntax_Programmatically.html">drracket/check-syntax</a> analysis of fully-expanded code. I’m pretty excited by it.</p><!-- more-->
<p>Consider this little Racket program:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="kn">#lang </span><span class="nn">racket/base</span>
<span class="p">(</span><span class="n">push-the-red-button!</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">f</span> <span class="n">x</span><span class="p">)</span>
<span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">x</span> <span class="mi">1</span><span class="p">))</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/module.html#(form._((quote._~23~25kernel)._module))" style="color: inherit">module</a></span> <span class="n">m</span> <span class="n">typed/racket/base</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" style="color: inherit">define</a></span> <span class="p">(</span><span class="n">g</span> <span class="n">x</span><span class="p">)</span>
<span class="nb"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#(def._((quote._~23~25kernel)._+))" style="color: inherit">+</a></span> <span class="n">x</span> <span class="mi">1</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>A few things to note:</p>
<ul>
<li>
<p>The file module has a side-effecting expression <code>(push-the-red-button!)</code>. Every time the file is evaluated a.k.a. “run”, this expression is evaluated.</p></li>
<li>
<p>The file module language is <code>racket/base</code>.</p></li>
<li>
<p>The submodule <code>m</code> language is <code>typed/racket/base</code>.</p></li></ul>
<h1 id="status-quo">Status quo</h1>
<p>Traditionally Racket Mode has required you to <code>racket-run</code> a file in order for some handy features to be available, because it can use the namespace resulting from <code>module->namespace</code> to support those features. This reflects its origins as a wrapper around <code>xrepl</code>. It retained that basic approach even as it grew beyond <code>xrepl</code>.</p>
<p>For instance it uses <code>namespace-mapped-symbols</code> to obtain a list of completion candidates. If it needs to get you documentation, it can synthesize a suitable identifier from a string using <code>namespace-symbol->identifier</code>. It can give such an identifier to <code>xref-binding->definition-tag</code>, and in turn give that result to <code>xref-tag->path+anchor</code>, and get the appropriate help topic.</p>
<p>Likewise the visit-definition feature can use the namespace to make the correct identifier to give to <code>identifier-binding</code>, which tells you where the binding was defined.</p>
<p>Racket Mode lets you run, not just the outermost, file’s module, but specific submodules — the innermost module around point. So when you run the <code>m</code> module, the namespace is inside that submodule. Therefore features work as you’d expect. For example help will be for Typed Racket’s <code>define</code>, and visit-definition will go to the source for that <code>define</code>.</p>
<p>This all works fine, with one drawback: You must <code>racket-run</code> the edit buffer to get results. (And if you make changes, you must run it again to get updated results.) This is a speed bump, especially when exploring many Racket files. It would be nice to open the file, and just visit definitions or get help — without needing to run each file. That can be slow. Worse, what about side-effects like <code>push-the-red-button!</code>?</p>
<p>Also, I knew at least a few people who use Racket Mode pretty much solely as an editing mode. In other words, they use <code>racket-mode</code> to edit .rkt files, but they rarely or never use <code>racket-run</code> and <code>racket-repl-mode</code>. Maybe <code>racket-mode</code> should be simpler and more lightweight — maybe some new minor mode should augment it with the “extras” for those who want them. This is a typical Emacs approach: A major mode handles a basic set of functionality, and one or more minor modes optionally enhance it.</p>
<h1 id="check-syntax">Check Syntax</h1>
<p>The Dr Racket IDE has a “Check Syntax” feature, which works solely by expanding a module — but <em>not</em> evaluating a.k.a. “running” it — and analyzing that fully-expanded syntax.</p>
<p>The acronym REPL — read, eval, print, loop? The “E” actually covers a few steps: expand, compile, evaluate. More like “RECEPL”.</p>
<p>A program in fully-expanded form looks like Racket “assembly language”. It is tedious to read, as a human. But a few key forms like <code>define-values</code>, <code>define-syntaxes</code>, and <code>#%require</code>, provide a lot of very useful information about bindings — things defined in that module or imported from another.<sup><a href="#using-drracket-check-syntax-in-racket-mode-footnote-1-definition" name="using-drracket-check-syntax-in-racket-mode-footnote-1-return">1</a></sup></p>
<p>The great news is that the <a href="https://docs.racket-lang.org/drracket-tools/Accessing_Check_Syntax_Programmatically.html">drracket/check-syntax</a> library exposes the analysis Dr Racket does to create annotations for the source buffer. I was able to leverage this to get most of what I wanted to do.</p>
<p>In a few cases, I need to extend this. For example, I wanted <em>all</em> local, module, and imported definitions to be available as completion candidates. The library produces annotations for the arrows Dr Racket draws between definitions and uses. If something is defined but not used? You can’t draw an arrow from something to nothing. Therefore it doesn’t produce an annotation. So the set of definitions in arrow annotations isn’t sufficient. Fortunately there is also a “mouseover text” annotation such as “N bound occurrence(s)”.<sup><a href="#using-drracket-check-syntax-in-racket-mode-footnote-2-definition" name="using-drracket-check-syntax-in-racket-mode-footnote-2-return">2</a></sup> So, a way to get all module and local definitions is to look for all such annotations — those are your definitions. As for imported definitions, I needed to walk the fully-expanded syntax myself, looking for <code>#%require</code> and its subforms that filter and rename what is imported, and do such filters/renames on <code>module->exports</code> lists. Although that didn’t take five minutes to figure out and debug, it wasn’t too bad.</p>
<p>Some of the work involved other issues. By far the slowest part isn’t the analysis of expanded code, it is getting that expanded code: <code>expand</code> can be non-trivial for languages like Typed Racket. For other reasons Racket Mode already maintained a cache of <code>file -> expanded syntax</code>. I needed that to also handle <code>(path-string code-string) -> expanded syntax</code>, for the case of unsaved buffer text. And as a result, I needed to make my own, cache-aware wrapper like <code>show-content</code> around <code>make-traversal</code>.</p>
<p>I also enhanced the back end command server to support the idea of cancelling a command already in progress. That way when we get a new request to analyze updated source, we can cancel any analysis possibly still running for the old, “stale” text.</p>
<h1 id="front-end">Front end</h1>
<p>How about the “front end”, implemented in Emacs Lisp?</p>
<p>Racket Mode already had a <code>racket-check-syntax-mode</code> minor mode. However it made the buffer read-only. You could navigate, and rename bindings, but you had to quit the mode to resume normal free-form editing. Also it didn’t attempt to unify the UX with normal commands to visit definitions, see help, and so on.</p>
<p>Instead, I wanted to this be something that — as in Dr Racket — runs automatically in the background on a read/write buffer. After you make some changes, and after some short idle delay, a new analysis kicks off. When its results are ready, the buffer annotations and completion candidates are refreshed. Annotations are done using Emacs text properties, and in the case of defs and uses which refer to each other, use Emacs <em>markers</em> so they remain valid after most edits. When there are syntax errors, those are annotated, but previous completion candidates are retained.</p>
<p>Although we can’t draw graphical arrows, we can highlight definitions and uses when point moves over them, using <code>cursor-sensor-mode</code> (which is a minor mode a user can disable if they find this slow or distracting).</p>
<p>Initially I still called this <code>racket-check-syntax-mode</code>. But (a) that’s pretty verbose, and (b) checking your syntax for mistakes is not most of the benefit. Really, it is a static analysis of expanded code that helps you explore and explain. With all those “exp” prefixes, plus an inclination for an even shorter name, I settled on <code>racket-xp-mode</code>.</p>
<p>At this point I’ll simply quote the documentation string for <code>racket-xp-mode</code> and show some screen shots:</p>
<blockquote>
<p>racket-xp-mode is an interactive function defined in racket-xp.el.</p>
<p><strong>Documentation</strong></p>
<p>A minor mode that analyzes expanded code to explain and explore.</p>
<p>This minor mode is an optional enhancement to racket-mode edit buffers. Like any minor mode, you can turn it on or off for a specific buffer. If you always want to use it, put the following code in your Emacs init file:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">require</span> <span class="ss">'racket-xp</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">'racket-mode-hook</span> <span class="nf">#'</span><span class="nv">racket-xp-mode</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Note: This mode won’t do anything unless/until the Racket Mode back end is running. It will try to start the back end automatically. You do <em>not</em> need to racket-run the buffer you are editing.</p>
<p>This mode uses the drracket/check-syntax package to analyze fully-expanded programs, without needing to evaluate a.k.a. “run” them. The resulting analysis provides information for:</p>
<ul>
<li>
<p>Visually annotating bindings — local or imported definitions and references to them.</p></li>
<li>
<p>Completion candidates.</p></li>
<li>
<p>Defintions’ source and documentation.</p></li></ul>
<p>When point is on a definition or use, related items are highlighted using racket-xp-def-face and racket-xp-use-face — instead of drawing arrows as in Dr Racket — and “mouse over”. Information is displayed using the function(s) in the hook variable racket-show-functions; it is also available when hovering the mouse cursor. Note: If you find these features too distracting and/or slow, you may disable cursor-sensor-mode. The remaining features discussed below will still work.</p>
<p>You may also use commands to navigate among a definition and its uses, or to rename a local definitions and all its uses.</p>
<p>In the following little example, not only does drracket/check-syntax distinguish the various “x” bindings, it understands the two different imports of “define”:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="kn">#lang </span><span class="nn">racket/base</span>
<span class="p">(</span><span class="k">define</span> <span class="n">x</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">x</span>
<span class="p">(</span><span class="k">let</span> <span class="p">([</span><span class="n">x</span> <span class="n">x</span><span class="p">])</span>
<span class="p">(</span><span class="nb">+</span> <span class="n">x</span> <span class="mi">1</span><span class="p">))</span>
<span class="p">(</span><span class="k">module</span> <span class="n">m</span> <span class="n">typed/racket/base</span>
<span class="p">(</span><span class="k">define</span> <span class="n">x</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">x</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>The function racket-xp-complete-at-point is added to the variable completion-at-point-functions. Note that in this case, it is not smart about submodules; identifiers are assumed to be definitions from the file’s module or its imports. In addition to supplying completion candidates, it supports the ":company-location" property to inspect the definition of a candidate and the ":company-doc-buffer" property to view its documentation.</p>
<p>When you edit the buffer, existing annotations are retained; their positions are updated to reflect the edit. Annotations for new or deleted text are not requested until after racket-xp-after-change-refresh-delay seconds. The request is made asynchronously so that Emacs will not block — for moderately complex source files, it can take some seconds simply to fully expand them, as well as a little more time for the drracket/check-syntax analysis. When the results are ready, all annotations for the buffer are completely refreshed.</p>
<p>You may also set racket-xp-after-change-refresh-delay to nil and use the racket-xp-annotate command manually.</p>
<p>The mode line changes to reflect the current status of annotations, and whether or not you had a syntax error.</p>
<p>If you have one or more syntax errors, use the standard next-error command and key bindings to navigate among them. Although most languages will stop after the first syntax error, some like Typed Racket will try to collect and report multiple errors.</p>
<p>Tip: This mode follows the convention that a minor mode may only use a prefix key consisting of “C-c” followed by a punctuation key. As a result, racket-xp-control-c-hash-keymap is bound to “C-c #” by default. Although you might find this awkward to type, remember that as an Emacs user, you are free to bind this map to a more convenient prefix, and/or bind any individual commands directly to whatever keys you prefer.</p>
<pre><code>C-c # . racket-xp-visit-definition
C-c # g racket-xp-annotate
C-c # j racket-xp-next-definition
C-c # k racket-xp-previous-definition
C-c # n racket-xp-next-use
C-c # p racket-xp-previous-use
C-c # r racket-xp-rename
C-c C-. racket-xp-describe
C-c C-d racket-xp-documentation
M-. racket-xp-visit-definition</code></pre></blockquote>
<figure><img src="/img/check-syntax.gif" width="100%" />
<figcaption>Animatation of check-syntax screen shots</figcaption></figure>
<p>Keep in mind that almost everything can be customized using defined faces or variables. Information like “1 bound occurrence” or error messages can be configured to be shown using the echo area (as in these screen shots), a header line, a <code>pos-tip</code> tooltip, and/or whatever custom function you want to supply.<sup><a href="#using-drracket-check-syntax-in-racket-mode-footnote-3-definition" name="using-drracket-check-syntax-in-racket-mode-footnote-3-return">3</a></sup></p>
<p>It was particularly fun when things were working well enough that I could use <code>racket-xp-mode</code> to more quickly explore and better understand some of the <a href="https://docs.racket-lang.org/drracket-tools/Accessing_Check_Syntax_Programmatically.html">drracket/check-syntax</a> code — as well as my own.</p>
<h1 id="taking-stock">Taking stock</h1>
<p>What remained was to step back and look at the <code>racket-mode</code> major mode (in hindsight maybe better-named <code>racket-edit-mode</code>), now optionally enhanced by <code>racket-xp-mode</code>, as well as the <code>racket-repl-mode</code> major mode.</p>
<p>What should live where, what should change, and what should remain the same?</p>
<p>After all, the old way of using the namespace from a run program, is actually still useful and quite appropriate for the REPL. You can run a program, then go into the REPL, and <code>define</code> and <code>require</code> all sorts of things. It still makes send to have that live namespace answer questions like “What are your symbols for completion candiates?” or “Which <code>define</code> is this, exactly, and where is its help or definition source?”. It is nice that you no longer <em>must</em> run your program, but if you <em>have</em> run it, and you’re in the REPL buffer… when in Rome.</p>
<p>So I realized there were a few commands — visit-definition, describe, help, completions — where there should be two flavors. One provided by <code>racket-xp-mode</code> and another provided by <code>racket-repl-mode</code> still working the “old” way. For example the old <code>racket-visit-definition</code> is effectively just moved/renamed to <code>racket-repl-visit-definition</code>.</p>
<p>At a lower level, also, there were some functions where I wrapped both flavors in a single back end command with a “how” argument: Use the <code>current-namespace</code> from <code>module->namespace</code>, or, use the namespace and module lexical context for some given path? (The latter covers cases where there exists no annotation, or the user has typed some arbitrary text, and we want to synthesize an identifier.)</p>
<h1 id="automatically-starting-the-back-end">Automatically starting the back end</h1>
<p>One other note. Racket Mode consists of an Emacs front end, obviously, and also a back end command server written in Racket. Although <code>racket-xp-mode</code> does <em>not</em> need to <code>racket-run</code> any .rkt buffer, it <em>does</em> need to talk to the back end server. Today that still means that a <code>racket-repl-mode</code> buffer is created. It just stays in the background, and it needn’t be running any particular file — but it must be open.<sup><a href="#using-drracket-check-syntax-in-racket-mode-footnote-4-definition" name="using-drracket-check-syntax-in-racket-mode-footnote-4-return">4</a></sup></p>
<p>When <code>racket-xp-mode</code> needs the back end, it will try to start it if not already running. This made me nervous, because auto-starting in the past led to some bugs, especially when something needed a command response to continue: Emacs could sometimes get stuck at a “starting…” or “waiting for…” message. You could
<kbd>C-g</kbd> out of that, usually. But it sucked. I had a think and realized the key was to make everything “asynchronous” with explicit continuations. I’d already replaced many uses of <code>racket--cmd/await</code> with <code>racket--cmd/async</code> — which takes a completion callback a.k.a. continuation procedure. I replaced even more. And also, I realized that starting the command server should itself be asynchronous. And so any <code>racket--cmd/async</code> that can’t happen yet, is pushed onto a list of continuations to be run eventually by the “connected to command server” continuation when it is called. Meanwhile, Emacs remains unblocked. Although I am not going to jinx this by declaring “mission accomplished!”, and some bugs may lurk, I’ve tried to be diligent in thinking through race conditions. I feel like this approach at least simplifies what needs to be considered.</p>
<h1 id="availability">Availability</h1>
<p>As I write this, I have 100+ commits still on a <code>check-syntax</code> branch — not yet merged to <code>master</code> or available from MELPA.</p>
<p>If you’re feeling brave or curious, feel free to try it out! I’ve been dogfooding it a fair amount. I’m still finding and fixing edge cases, but I think it’s stable enough to understand the basic experience.</p>
<div class="footnotes">
<ol>
<li id="using-drracket-check-syntax-in-racket-mode-footnote-1-definition" class="footnote-definition">
<p>The outermost <code>module</code> form also gets a syntax-property with the lexical context inside the module, including imports. As a result, you can synthesize an identifer using that as the first argument to <code>datum->syntax</code>, and then do the same things with that identifier you could with one from <code>namespace-symbol->identifer</code>, in order to support features like visit-definition or help, where the user has supplied some arbitrary string. <a href="#using-drracket-check-syntax-in-racket-mode-footnote-1-return">↩</a></p></li>
<li id="using-drracket-check-syntax-in-racket-mode-footnote-2-definition" class="footnote-definition">
<p>And if you want to find <em>unused</em> imported and locally-defined definitions, they’ll have a “mouseover” annotation, “no bound occurrences”. <a href="#using-drracket-check-syntax-in-racket-mode-footnote-2-return">↩</a></p></li>
<li id="using-drracket-check-syntax-in-racket-mode-footnote-3-definition" class="footnote-definition">
<p>It’s also shown when you hover the mouse pointer. If you use a mouse with Emacs, I won’t judge you. <em>*coughs*</em>. <a href="#using-drracket-check-syntax-in-racket-mode-footnote-3-return">↩</a></p></li>
<li id="using-drracket-check-syntax-in-racket-mode-footnote-4-definition" class="footnote-definition">
<p>Perhaps in the future that will change — especially if Racket Mode ever supports multiple REPLs open at once. In that case, starting the back end will be an independent first step, things like <code>racket-run</code> will create one or more REPLs, and the I/O for the comint buffers will be a network stream instead of stdin/stdout. <a href="#using-drracket-check-syntax-in-racket-mode-footnote-4-return">↩</a></p></li></ol></div>
<footer></footer></article></div>Supporting multi-inurn:www-greghendershott-com:-2019-04-supporting-multi-in.html2019-04-25T00:00:00Z2019-04-25T00:00:00ZGreg Hendershott
<div>
<article>
<header>
<h1>Supporting multi-in</h1>
<p class="date-and-tags">
<time datetime="2019-04-25" pubdate="true">2019-04-25</time> :: <span class="tags"><a href="/tags/Racket.html">Racket</a>, <a href="/tags/Emacs.html">Emacs</a></span></p></header>
<p>In <a href="https://github.com/greghendershott/racket-mode/">racket-mode</a> I improved support for the <code><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/require..rkt)._multi-in))" style="color: inherit">multi-in</a></code> form provided by <code>racket/require</code>.</p><!-- more-->
<h1 id="what-is-brush-racketmulti-in">What is <code><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/require..rkt)._multi-in))" style="color: inherit">multi-in</a></code>?</h1>
<p>Instead of:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">net/uri-codec</span>
<span class="n">net/url</span>
<span class="n">racket/contract</span>
<span class="n">racket/format</span>
<span class="n">racket/string</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>You can say:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">racket/require</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/require..rkt)._multi-in))" style="color: inherit">multi-in</a></span> <span class="n">net</span> <span class="p">(</span><span class="n">uri-codec</span> <span class="n">url</span><span class="p">))</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/require..rkt)._multi-in))" style="color: inherit">multi-in</a></span> <span class="n">racket</span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/attaching-contracts-to-values.html#(form._((lib._racket/contract/private/base..rkt)._contract))" style="color: inherit">contract</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((quote._~23~25kernel)._format))" style="color: inherit">format</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string))" style="color: inherit">string</a></span><span class="p">)))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>One detail: The <code>racket/require</code> must appear before any <code>multi-in</code> forms. Any sorting must make an exception for this.</p>
<h1 id="what-are-the-racket-tidy-trim-base-requires-commands">What are the <code>racket-{tidy trim base}-requires</code> commands?</h1>
<ul>
<li>
<p><code>racket-tidy-requires</code> gathers multiple <code>require</code> forms into one. Within that, it groups phase level sub-forms such as <code>for-syntax</code>. Finally it sorts absolute module paths like <code>foo</code> before relative paths like <code>"foo.rkt"</code>, and sorts each of those alphabetically.</p></li>
<li>
<p><code>racket-trim-requires</code> uses the <code>show-requires</code> function from <code>macro-debugger/analysis/check-requires</code> to analyze requires and delete any unused. Also it tidies.</p></li>
<li>
<p><code>racket-base-requires</code> uses the analysis to change a <code>#lang racket</code> file to <code>#lang racket/base</code>, adding requires as necessary. Also it trims and tidies.</p></li></ul>
<h1 id="what-are-the-changes">What are the changes?</h1>
<ol>
<li>
<p>Sorting makes sure to keep <code>racket/require</code> first.</p></li>
<li>
<p>If <code>racket/require</code> is present in the original <code>require</code> form(s), then <code>multi-in</code> is used when tidying.</p></li>
<li>
<p>Any analysis that says requires should be removed, should handle <code>multi-in</code> forms.</p></li></ol>
<p>Essentially, the commands first “expand” or “explode” <code>multi-in</code> forms to individual requires, do any analysis and modifications, then try to “unexpand” or “implode” them back again.<sup><a href="#supporting-multi-in-footnote-1-definition" name="supporting-multi-in-footnote-1-return">1</a></sup></p>
<p>All together, these changes close issues <a href="https://github.com/greghendershott/racket-mode/issues/355">355</a>, <a href="https://github.com/greghendershott/racket-mode/issues/356">356</a>, and <a href="https://github.com/greghendershott/racket-mode/issues/369">369</a>.</p>
<h2 id="example-without-racketrequire">Example without <code>racket/require</code></h2>
<p>Here’s an example where <code>racket/require</code> is <em>not</em> in the original <code>require</code> forms:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="kn">#lang </span><span class="nn">racket</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">net/url</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">net/uri-codec</span><span class="p">)</span>
<span class="c1">;; Just some expressions using imported definitions</span>
<span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-join))" style="color: inherit">string-join</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/format..rkt)._~7ea))" style="color: inherit">~a</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._get-pure-port))" style="color: inherit">get-pure-port</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/uri-codec.html#(def._((lib._net/uri-codec..rkt)._uri-decode))" style="color: inherit">uri-decode</a></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/match.html#(form._((lib._racket/match..rkt)._match-define))" style="color: inherit">match-define</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="mi">1</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>After
<kbd>M-x</kbd> <code>racket-base-requires</code>:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="kn">#lang </span><span class="nn">racket/base</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">net/uri-codec</span>
<span class="n">net/url</span>
<span class="n">racket/format</span>
<span class="n">racket/match</span>
<span class="n">racket/string</span><span class="p">)</span>
<span class="c1">;; Just some expressions using imported definitions</span>
<span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-join))" style="color: inherit">string-join</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/format..rkt)._~7ea))" style="color: inherit">~a</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._get-pure-port))" style="color: inherit">get-pure-port</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/uri-codec.html#(def._((lib._net/uri-codec..rkt)._uri-decode))" style="color: inherit">uri-decode</a></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/match.html#(form._((lib._racket/match..rkt)._match-define))" style="color: inherit">match-define</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="mi">1</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<h2 id="example-with-racketrequire">Example with <code>racket/require</code></h2>
<p>Here’s an example where <code>racket/require</code> <em>is</em> in the original <code>require</code> forms:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="kn">#lang </span><span class="nn">racket</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">racket/require</span><span class="p">)</span> <span class="c1">;new</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">net/url</span><span class="p">)</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">net/uri-codec</span><span class="p">)</span>
<span class="c1">;; Just some expressions using imported definitions</span>
<span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-join))" style="color: inherit">string-join</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/format..rkt)._~7ea))" style="color: inherit">~a</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._get-pure-port))" style="color: inherit">get-pure-port</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/uri-codec.html#(def._((lib._net/uri-codec..rkt)._uri-decode))" style="color: inherit">uri-decode</a></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/match.html#(form._((lib._racket/match..rkt)._match-define))" style="color: inherit">match-define</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="mi">1</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>After
<kbd>M-x</kbd> <code>racket-base-requires</code>:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6
7
8</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="kn">#lang </span><span class="nn">racket/base</span>
<span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" style="color: inherit">require</a></span> <span class="n">racket/require</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/require..rkt)._multi-in))" style="color: inherit">multi-in</a></span> <span class="n">net</span> <span class="p">(</span><span class="n">uri-codec</span> <span class="n">url</span><span class="p">))</span>
<span class="p">(</span><span class="n"><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/require..rkt)._multi-in))" style="color: inherit">multi-in</a></span> <span class="n">racket</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((quote._~23~25kernel)._format))" style="color: inherit">format</a></span> <span class="k"><a href="http://docs.racket-lang.org/reference/match.html#(form._((lib._racket/match..rkt)._match))" style="color: inherit">match</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string))" style="color: inherit">string</a></span><span class="p">)))</span>
<span class="c1">;; Just some expressions using imported definitions</span>
<span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/string..rkt)._string-join))" style="color: inherit">string-join</a></span> <span class="nb"><a href="http://docs.racket-lang.org/reference/strings.html#(def._((lib._racket/format..rkt)._~7ea))" style="color: inherit">~a</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._get-pure-port))" style="color: inherit">get-pure-port</a></span> <span class="n"><a href="http://docs.racket-lang.org/net/uri-codec.html#(def._((lib._net/uri-codec..rkt)._uri-decode))" style="color: inherit">uri-decode</a></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/match.html#(form._((lib._racket/match..rkt)._match-define))" style="color: inherit">match-define</a></span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._list))" style="color: inherit">list</a></span> <span class="mi">1</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<div class="footnotes">
<ol>
<li id="supporting-multi-in-footnote-1-definition" class="footnote-definition">
<p>Not everything survives a round-trip, exactly. A Cartesian product like <code>(multi-in (a b) (c d))</code> will end up as a <code>(multi-in a (c d))</code> and a <code>(multi-in b (c d))</code> — equivalent but not as concise. <a href="#supporting-multi-in-footnote-1-return">↩</a></p></li></ol></div>
<footer></footer></article></div>racket-modeurn:www-greghendershott-com:-2018-10-racket-mode.html2018-10-03T04:00:00Z2018-10-03T04:00:00ZGreg Hendershott
<div>
<article>
<header>
<h1>racket-mode</h1>
<p class="date-and-tags">
<time datetime="2018-10-03" pubdate="true">2018-10-03</time> :: <span class="tags"><a href="/tags/Racket.html">Racket</a>, <a href="/tags/Emacs.html">Emacs</a></span></p></header>
<p>Even though it’s been one of my most time-consuming projects, I’ve hardly blogged about <a href="https://github.com/greghendershott/racket-mode">racket-mode</a> — an <a href="https://www.gnu.org/software/emacs/">Emacs</a> major mode for <a href="https://www.racket-lang.org">Racket</a>. To change that, here’s a post giving an overview of how racket-mode works, as well as a look at how it might grow someday.</p><!-- more-->
<h1 id="cast-of-characters">Cast of characters</h1>
<p>racket-mode consists of two main parts:</p>
<ul>
<li>
<p>An <a href="https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html">Emacs Lisp</a> “front end”. This implements various major and minor modes, the main two of which are:</p>
<ul>
<li>
<p><code>racket-mode</code> for editing <code>.rkt</code> files</p></li>
<li>
<p><code>racket-repl-mode</code> for a REPL</p></li></ul></li>
<li>A Racket “back end”. This is a <code>racket</code> process that runs the back end code, which in turn runs your program and implements “commands”, as discussed below.</li></ul>
<p>This mix of Emacs Lisp and Racket code is delivered as an Emacs package (e.g. via <a href="https://melpa.org">MELPA</a>), where the Racket files come along for the ride.<sup><a href="#racket-mode-footnote-1-definition" name="racket-mode-footnote-1-return">1</a></sup></p>
<h1 id="crossing-the-chasm">Crossing the chasm</h1>
<p>The Emacs front end (“client”) sends command requests to the Racket back end (“server”) which sends command responses. Exactly <em>how</em> this happens is the aspect of racket-mode that has changed the most over the years.</p>
<h2 id="historical">Historical</h2>
<p>The very earliest version of racket-mode was a very thin wrapper around <a href="https://docs.racket-lang.org/xrepl/">XREPL</a>, which lets you enter commands prefixed by a comma<sup><a href="#racket-mode-footnote-2-definition" name="racket-mode-footnote-2-return">2</a></sup> like <code>,enter <filename></code>. So racket-mode would mostly just <code>comint-send-string</code> a few of these commands (invisibly type them into the buffer on your behalf).</p>
<p>But.</p>
<ul>
<li>
<p>What if the user’s program does <code>read</code> or <code>read-line</code>? If we send commands to the back end, the user’s program will get them.</p></li>
<li>
<p>Later, command <em>responses</em> became more important. For example, racket-mode’s <code>racket-describe</code> command returns HTML (from Racket’s documentation) to be shown in an Emacs buffer. Well, occasionally the HTML might contain something like <code>"\ndiv>"</code> — breaking code trying to read a response up to the next REPL prompt.</p></li></ul>
<p>Long story short: If you like edge cases, you’ll love multiplexing textual command I/O with user program I/O. That approach is an easy way to start casually. But it’s actually easier long-term to move the command I/O “out-of-band”, when possible. It sucks to demux.</p>
<h2 id="today">Today</h2>
<p>Early Summer 2018 I again changed how command requests and responses work.</p>
<p>The Racket back end starts a TCP “command server”, and the Emacs front end connects to it.</p>
<p>Although the connection method is TCP, the protocol isn’t HTTP. Instead, the command server:</p>
<ul>
<li>
<p>Accepts a single TCP connection at a time (multiple requests and responses are sent over the one connection)</p></li>
<li>
<p>Uses a subset of valid Emacs Lisp s-expressions for requests and responses.</p></li></ul>
<p>Command requests are <code>(nonce command param ...)</code>.</p>
<p>A thread is spun off to handle each request, so that a long-running command won’t block others. The <code>nonce</code> supplied with the request is returned with the response, so that the client can match the response with the request.<sup><a href="#racket-mode-footnote-3-definition" name="racket-mode-footnote-3-return">3</a></sup></p>
<p>Command responses are either <code>(nonce 'ok sexp ...+)</code> or <code>(nonce 'error
"message")</code>.</p>
<p>Here’s a code snippet to give a rough sense of the commands:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/match.html#(form._((lib._racket/match..rkt)._match))" style="color: inherit">match</a></span> <span class="n">sexpr</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">run</span> <span class="o">,</span><span class="n">what</span> <span class="o">,</span><span class="n">mem</span> <span class="o">,</span><span class="n">pp?</span> <span class="o">,</span><span class="n">ctx</span> <span class="o">,</span><span class="n">args</span> <span class="o">,</span><span class="n">dbg</span><span class="p">)</span> <span class="p">(</span><span class="n">run</span> <span class="n">what</span> <span class="n">mem</span> <span class="n">pp?</span> <span class="n">ctx</span> <span class="n">args</span> <span class="n">dbg</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">path+md5</span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/pairs.html#(def._((quote._~23~25kernel)._cons))" style="color: inherit">cons</a></span> <span class="p">(</span><span class="k"><a href="http://docs.racket-lang.org/reference/if.html#(form._((lib._racket/private/letstx-scheme..rkt)._or))" style="color: inherit">or</a></span> <span class="n">path</span> <span class="o">'</span><span class="ss">top</span><span class="p">)</span> <span class="n">md5</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">syms</span><span class="p">)</span> <span class="p">(</span><span class="n">syms</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">def</span> <span class="o">,</span><span class="n">str</span><span class="p">)</span> <span class="p">(</span><span class="n">find-definition</span> <span class="n">str</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">mod</span> <span class="o">,</span><span class="n">sym</span><span class="p">)</span> <span class="p">(</span><span class="n">find-module</span> <span class="n">sym</span> <span class="n">maybe-mod</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">describe</span> <span class="o">,</span><span class="n">str</span><span class="p">)</span> <span class="p">(</span><span class="n">describe</span> <span class="n">str</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">doc</span> <span class="o">,</span><span class="n">str</span><span class="p">)</span> <span class="p">(</span><span class="n">doc</span> <span class="n">str</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">type</span> <span class="o">,</span><span class="n">v</span><span class="p">)</span> <span class="p">(</span><span class="n">type</span> <span class="n">v</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">macro-stepper</span> <span class="o">,</span><span class="n">str</span> <span class="o">,</span><span class="n">into-base?</span><span class="p">)</span> <span class="p">(</span><span class="n">macro-stepper</span> <span class="n">str</span> <span class="n">into-base?</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">macro-stepper/next</span><span class="p">)</span> <span class="p">(</span><span class="n">macro-stepper/next</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">requires/tidy</span> <span class="o">,</span><span class="n">reqs</span><span class="p">)</span> <span class="p">(</span><span class="n">requires/tidy</span> <span class="n">reqs</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">requires/trim</span> <span class="o">,</span><span class="n">path-str</span> <span class="o">,</span><span class="n">reqs</span><span class="p">)</span> <span class="p">(</span><span class="n">requires/trim</span> <span class="n">path-str</span> <span class="n">reqs</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">requires/base</span> <span class="o">,</span><span class="n">path-str</span> <span class="o">,</span><span class="n">reqs</span><span class="p">)</span> <span class="p">(</span><span class="n">requires/base</span> <span class="n">path-str</span> <span class="n">reqs</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">find-collection</span> <span class="o">,</span><span class="n">str</span><span class="p">)</span> <span class="p">(</span><span class="n">find-collection</span> <span class="n">str</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">get-profile</span><span class="p">)</span> <span class="p">(</span><span class="n">get-profile</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">get-uncovered</span><span class="p">)</span> <span class="p">(</span><span class="n">get-uncovered</span> <span class="n">path</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">check-syntax</span> <span class="o">,</span><span class="n">path-str</span><span class="p">)</span> <span class="p">(</span><span class="n">check-syntax</span> <span class="n">path-str</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss"><a href="http://docs.racket-lang.org/reference/eval.html#(def._((quote._~23~25kernel)._eval))" style="color: inherit">eval</a></span> <span class="o">,</span><span class="n">v</span><span class="p">)</span> <span class="p">(</span><span class="n">eval-command</span> <span class="n">v</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">repl-submit?</span> <span class="o">,</span><span class="n">str</span> <span class="o">,</span><span class="n">eos?</span><span class="p">)</span> <span class="p">(</span><span class="n">repl-submit?</span> <span class="n">submit-pred</span> <span class="n">str</span> <span class="n">eos?</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">debug-eval</span> <span class="o">,</span><span class="n">src</span> <span class="o">,</span><span class="n">l</span> <span class="o">,</span><span class="n">c</span> <span class="o">,</span><span class="n">p</span> <span class="o">,</span><span class="n">code</span><span class="p">)</span> <span class="p">(</span><span class="n">debug-eval</span> <span class="n">src</span> <span class="n">l</span> <span class="n">c</span> <span class="n">p</span> <span class="n">code</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">debug-resume</span> <span class="o">,</span><span class="n">v</span><span class="p">)</span> <span class="p">(</span><span class="n">debug-resume</span> <span class="n">v</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss">debug-disable</span><span class="p">)</span> <span class="p">(</span><span class="n">debug-disable</span><span class="p">)]</span>
<span class="p">[</span><span class="o">`</span><span class="p">(</span><span class="ss"><a href="http://docs.racket-lang.org/reference/Exiting.html#(def._((quote._~23~25kernel)._exit))" style="color: inherit">exit</a></span><span class="p">)</span> <span class="p">(</span><span class="nb"><a href="http://docs.racket-lang.org/reference/Exiting.html#(def._((quote._~23~25kernel)._exit))" style="color: inherit">exit</a></span><span class="p">)])</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>This approach also makes it reasonably simple for the Emacs Lisp front end to issue some commands “asynchronously”. In fact the lowest-level command function is async:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="k">defvar</span> <span class="nv">racket--cmd-nonce->callback</span> <span class="p">(</span><span class="nf">make-hash-table</span> <span class="nb">:test</span> <span class="ss">'eq</span><span class="p">)</span>
<span class="s">"A hash from nonce to callback function."</span><span class="p">)</span>
<span class="p">(</span><span class="k">defvar</span> <span class="nv">racket--cmd-nonce</span> <span class="mi">0</span>
<span class="s">"Increments for each command request we send."</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">racket--cmd/async-raw</span> <span class="p">(</span><span class="nv">command-sexpr</span> <span class="kp">&optional</span> <span class="nv">callback</span><span class="p">)</span>
<span class="s">"Send COMMAND-SEXPR and return. Later call CALLBACK with the response sexp.</span>
<span class="s">If CALLBACK is not supplied or nil, defaults to </span><span class="ss">`ignore'</span><span class="s">."</span>
<span class="p">(</span><span class="nv">racket--repl-ensure-buffer-and-process</span> <span class="no">nil</span><span class="p">)</span>
<span class="p">(</span><span class="nv">racket--cmd-connect-finish</span><span class="p">)</span>
<span class="p">(</span><span class="nb">cl-incf</span> <span class="nv">racket--cmd-nonce</span><span class="p">)</span>
<span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="k">and</span> <span class="nv">callback</span>
<span class="p">(</span><span class="nv">not</span> <span class="p">(</span><span class="nf">equal</span> <span class="nv">callback</span> <span class="nf">#'</span><span class="nv">ignore</span><span class="p">)))</span>
<span class="p">(</span><span class="nf">puthash</span> <span class="nv">racket--cmd-nonce</span> <span class="nv">callback</span> <span class="nv">racket--cmd-nonce->callback</span><span class="p">))</span>
<span class="p">(</span><span class="nf">process-send-string</span> <span class="nv">racket--cmd-proc</span>
<span class="p">(</span><span class="nf">format</span> <span class="s">"%S\n"</span> <span class="p">(</span><span class="nf">cons</span> <span class="nv">racket--cmd-nonce</span>
<span class="nv">command-sexpr</span><span class="p">))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Code that doesn’t need to examine error responses can use a simplified wrapper:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">defun</span> <span class="nv">racket--cmd/async</span> <span class="p">(</span><span class="nv">command-sexpr</span> <span class="kp">&optional</span> <span class="nv">callback</span><span class="p">)</span>
<span class="s">"You probably want to use this instead of </span><span class="ss">`racket--cmd/async-raw'</span><span class="s">.</span>
<span class="s">CALLBACK is only called for 'ok responses, with (ok v ...)</span>
<span class="s">unwrapped to (v ...). 'error responses are handled here."</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">buf</span> <span class="p">(</span><span class="nf">current-buffer</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">racket--cmd/async-raw</span>
<span class="nv">command-sexpr</span>
<span class="p">(</span><span class="k">if</span> <span class="nv">callback</span>
<span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">response</span><span class="p">)</span>
<span class="p">(</span><span class="nb">pcase</span> <span class="nv">response</span>
<span class="p">(</span><span class="o">`</span><span class="p">(</span><span class="nv">ok</span> <span class="o">,</span><span class="nv">v</span><span class="p">)</span> <span class="p">(</span><span class="nb">with-current-buffer</span> <span class="nv">buf</span> <span class="p">(</span><span class="nf">funcall</span> <span class="nv">callback</span> <span class="nv">v</span><span class="p">)))</span>
<span class="p">(</span><span class="o">`</span><span class="p">(</span><span class="ne">error</span> <span class="o">,</span><span class="nv">m</span><span class="p">)</span> <span class="p">(</span><span class="nf">message</span> <span class="s">"%s"</span> <span class="nv">m</span><span class="p">))</span>
<span class="p">(</span><span class="nv">v</span> <span class="p">(</span><span class="nf">message</span> <span class="s">"Unknown command response: %S"</span> <span class="nv">v</span><span class="p">))))</span>
<span class="nf">#'</span><span class="nv">ignore</span><span class="p">))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Code that needs to wait synchronously for a response can use another wrapper:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">defun</span> <span class="nv">racket--cmd/await</span> <span class="p">(</span><span class="nv">command-sexpr</span><span class="p">)</span>
<span class="s">"Send COMMAND-SEXPR. Await and return an 'ok response value, or raise </span><span class="ss">`error'</span><span class="s">."</span>
<span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">awaiting</span> <span class="ss">'RACKET-REPL-AWAITING</span><span class="p">)</span>
<span class="p">(</span><span class="nv">response</span> <span class="nv">awaiting</span><span class="p">))</span>
<span class="p">(</span><span class="nv">racket--cmd/async-raw</span> <span class="nv">command-sexpr</span>
<span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">v</span><span class="p">)</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">response</span> <span class="nv">v</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">with-timeout</span> <span class="p">(</span><span class="nv">racket-command-timeout</span>
<span class="p">(</span><span class="ne">error</span> <span class="s">"racket-command process timeout"</span><span class="p">))</span>
<span class="p">(</span><span class="k">while</span> <span class="p">(</span><span class="nf">eq</span> <span class="nv">response</span> <span class="nv">awaiting</span><span class="p">)</span>
<span class="p">(</span><span class="nf">accept-process-output</span> <span class="no">nil</span> <span class="mf">0.001</span><span class="p">))</span>
<span class="p">(</span><span class="nb">pcase</span> <span class="nv">response</span>
<span class="p">(</span><span class="o">`</span><span class="p">(</span><span class="nv">ok</span> <span class="o">,</span><span class="nv">v</span><span class="p">)</span> <span class="nv">v</span><span class="p">)</span>
<span class="p">(</span><span class="o">`</span><span class="p">(</span><span class="ne">error</span> <span class="o">,</span><span class="nv">m</span><span class="p">)</span> <span class="p">(</span><span class="ne">error</span> <span class="s">"%s"</span> <span class="nv">m</span><span class="p">))</span>
<span class="p">(</span><span class="nv">v</span> <span class="p">(</span><span class="ne">error</span> <span class="s">"Unknown command response: %S"</span> <span class="nv">v</span><span class="p">))))))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>In other words, asynchronous is the baseline. Synchronous is the special case where the callback <code>setq</code>s the response and the main Emacs thread polls for it.</p>
<h1 id="what-does-it-mean-to-run-a-file">What does it mean to “run” a file</h1>
<p>The main command is <code>run</code>, which causes it to run a specific <code>.rkt</code> file. “Run” means something similar to what it does in <a href="https://docs.racket-lang.org/drracket/index.html">DrRacket</a>: <code>dynamic-require</code> a relative module path and use <code>module->namespace</code> so that you are “inside” the module and can see all its module-level definitions (even those it does not <code>provide</code>). Then it does a <code>read-eval-print-loop</code>, which is the REPL you see in the <code>racket-repl-mode</code> buffer.</p>
<p>Importantly, each run uses a fresh custodian and namespace. Therefore each run discards any changes you made only in the REPL and “resets” you to a namespace corresponding to the <code>.rkt</code> file. In other words, the single source of truth is your source file.</p>
<p>One handy nuance: If, when you run, point<sup><a href="#racket-mode-footnote-4-definition" name="racket-mode-footnote-4-return">4</a></sup> is inside a submodule at any depth, you enter that submodule. So for example you can put point within a <code>(module+ test ___)</code> form and
<kbd>C-c C-c</kbd>. Not only will this run your tests, the REPL will be “inside” the <code>test</code> submodule so you can explore and experiment more. Or you can run a <code>main</code>, or any other, submodule.</p>
<p>Of course there are many wrinkles:</p>
<ul>
<li>
<p>In some cases we “instrument” the module to support features like profiling, test coverage, or step debugging.</p></li>
<li>
<p>We look for and run <code>configure-runtime</code>s or <code>get-info</code>s supplied by a <code>#lang</code>.</p></li>
<li>
<p>We warn when a <code>#lang</code> doesn’t supply <code>#%top-interaction</code>.</p></li>
<li>
<p>We load <code>racket/gui</code> lazily. (That way, you don’t get a pointless GUI frame window while working on textual programs.)</p></li>
<li>
<p>We maybe set up custom print handlers to use pretty-print.</p></li>
<li>
<p>If the file contains syntax errors, we try to distill it to a “skeleton” of things that create runtime, module-level bindings, i.e. <code>require</code>s and <code>define</code>s. You can think of this as replacing all <code>(define id rhs)</code> with <code>(define id (void))</code>. Why? That way, we get a namespace with the definition identifiers available to things like auto-complete.</p></li>
<li>
<p>And on and on.</p></li></ul>
<h1 id="summer-two-step">Summer two step</h1>
<p>Over the summer of 2018, I added a couple features under the theme of “stepping”.</p>
<h2 id="macro-step-expander">Macro step expander</h2>
<p>A new <code>racket-stepper-mode</code> presents a consistent <code>diff -U 3</code> format UI for both:</p>
<ul>
<li>
<p><code>expand-once</code>-ing expressions</p></li>
<li>
<p>whole-file expansion using <a href="https://docs.racket-lang.org/macro-debugger/index.html#(mod-path._macro-debugger%2Fstepper-text)"><code>macro-debugger/stepper-text</code></a> (although the UI is not as ambitious as the fantastic macro stepper in DrRacket)</p></li></ul>
<p>Whole-file expansion potentially can take many seconds. So this is an example where it’s good to have the ability for command responses to come as an asynchronous callback. Emacs isn’t “frozen” while waiting.</p>
<h2 id="step-debugger">Step debugger</h2>
<p>Also new is an interactive step debugger. I won’t repeat the <a href="https://github.com/greghendershott/racket-mode/commit/2b1c7d476dc71b1707fd5222f963ab6509e50805">commit message</a> or the <a href="https://github.com/greghendershott/racket-mode/blob/master/Reference.md#racket-debug-mode">documentation</a> here. I’ll just mention that, as the commit message says, I had started to work on this several years ago but decided not to merge it. The new async command protocol was one factor that made it easier. Also, by labeling it “experimental”, I was less worried should it turn out to be too much hassle to support long-term.</p>
<p>I’m curious to see how much people actually use it. I’ve found that I want an interactive debugger <em>much</em> less often writing mostly functional Racket than I did when writing imperative C/C++. With Racket, a step debugger feels more like a nice-to-have than a must-have. Even so, while working in Emacs Lisp for racket-mode, sometimes I have found <a href="https://www.gnu.org/software/emacs/manual/html_node/eintr/edebug.html"><code>edebug</code></a> to be handy. So we’ll see.</p>
<p><img src="/img/racket-mode-step-debugger.gif" alt="racket-mode step debugger" class="screenshot" /></p>
<h1 id="future">Future</h1>
<p>Modulo bugs and some UX refinements, I’d say that racket-mode has reached the point where it’s a pretty good "#lang-racket-mode". That is, it’s pretty good for working with s-expression <code>#lang</code>s like <code>racket</code>, <code>racket/base</code>, <code>typed/racket</code>, and so on.</p>
<p>However it does not attempt to be a “racket-is-a-programming-language-programming-language-mode” like DrRacket. Maybe that is where it should head next. If so, I’m aware of three main areas, only one of which is done.</p>
<h2 id="submitted-for-your-approval-in-the-repl-zone">Submitted for your approval, in the REPL zone</h2>
<p>A <code>#lang</code> may supply a <a href="https://docs.racket-lang.org/tools/lang-languages-customization.html#%28elem._drracket~3asubmit-predicate%29"><code>drracket:submit-predicate</code></a> to say whether some chunk of text is a complete expression. In other words, when a user hits
<kbd>ENTER</kbd> in the REPL, should this be sent for evaluation, or, simply insert a newline and wait for them to supply more?</p>
<p>As of a couple months ago, racket-mode does actually look for and use this.</p>
<h2 id="syntax-highlighting">Syntax highlighting</h2>
<p>“Font-lock” is what Emacs calls the process of changing the appearance of text — such as syntax highlighting for programming modes. Mostly this is done via regular expressions, although an arbitrary function can be supplied to do both fancier matching and altering.</p>
<p>Traditionally font-lock distinguishes between language elements that are “keywords” vs. “builtins”. When it comes to Racket, this is sort of a weird distinction that I handled <a href="https://github.com/greghendershott/racket-mode/blob/4440f34bc892ce6ad1036b2123e5f6010872423d/racket/keywords.rkt#L5-L36">ad hoc</a>.</p>
<p>DrRacket takes a different approach. Each <code>#lang</code> may supply a <a href="https://docs.racket-lang.org/tools/lang-languages-customization.html#%28part._.Syntax_.Coloring%29"><code>color-lexer</code></a>. Clearly this is the Correct Way.</p>
<p>And yet. One great way to make Emacs feel sluggish is to do font-lock poorly. To-date, I’ve been worried about the performance of trying to use <code>color-lexer</code>s, which are <a href="https://docs.racket-lang.org/framework/Color.html"><code>color:text<%></code></a> interfaces. How will this perform marshaled over the TCP connection? Will this force racket-mode to use <code>racket/gui</code> always, instead of only when user programs need it?</p>
<h2 id="indentation">Indentation</h2>
<p>Similarly, racket-mode could someday use a <code>#lang</code>-supplied <a href="https://docs.racket-lang.org/tools/lang-languages-customization.html#(part._.Indentation)"><code>drracket:indentation</code></a> — and similarly, naive indentation can bring Emacs to its knees.</p>
<p>Currently racket-mode indents using Emacs Lisp that is mostly hardcoded with special handling for known macros<sup><a href="#racket-mode-footnote-5-definition" name="racket-mode-footnote-5-return">5</a></sup> in some popular <code>#lang</code>s.</p>
<p>I say “mostly hardcoded” because it <em>is</em> extensible in the tradition of lisp-mode and scheme-mode: racket-mode looks for a <a href="https://github.com/greghendershott/racket-mode/blob/master/Reference.md#racket-indent-line"><code>'racket-indent-function</code></a> property on an Emacs Lisp symbol of the same name as the Racket macro. racket-mode sets up some of these itself. You can add your own in your Emacs init file:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nf">put</span> <span class="ss">'racket-macro-name</span> <span class="ss">'racket-indent-function</span> <span class="nv">indent-value</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>You can also do this using Emacs <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html">Directory Variables</a> or in <code>.rkt</code> files using Emacs <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html#Specifying-File-Variables">File Variables</a>. An example of the latter setting up indentation for some <a href="https://docs.racket-lang.org/sql/index.html"><code>sql</code></a> package syntax:</p>
<div class="brush: racket">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4
5
6</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="c1">;; Local Variables:</span>
<span class="c1">;; eval: (put 'insert 'racket-indent-function 'defun)</span>
<span class="c1">;; eval: (put 'update 'racket-indent-function 'defun)</span>
<span class="c1">;; eval: (put 'delete 'racket-indent-function 'defun)</span>
<span class="c1">;; eval: (put 'select 'racket-indent-function 'defun)</span>
<span class="c1">;; End:</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Although this works, it’s not ideal.</p>
<p>So it would be nice for racket-mode to use a <code>#lang</code>-supplied <a href="https://docs.racket-lang.org/tools/lang-languages-customization.html#(part._.Indentation)"><code>drracket:indentation</code></a>.</p>
<p>However, even that doesn’t seem enough: Not just a full-blown <code>#lang</code>, but really <em>any</em> library module — like <code>sql</code> — ought to be able to specify indent for special syntax.</p>
<p>So I don’t yet know a good story for rich indentation that is both complete and performant.</p>
<h1 id="conclusion">Conclusion</h1>
<p>Hopefully this gives you some overview of how racket-mode works, as well as what it currently does or does not attempt to do, and why.</p>
<div class="footnotes">
<ol>
<li id="racket-mode-footnote-1-definition" class="footnote-definition">
<p>Another approach would be to split it into an Emacs package and a Racket package. This would have various pros and cons. I think the main disadvantage is that users would need both to update to stay in sync. When using CIDER for Clojure I found this a little troublesome. <a href="#racket-mode-footnote-1-return">↩</a></p></li>
<li id="racket-mode-footnote-2-definition" class="footnote-definition">
<p>Since <code>,</code> is reader shorthand for <code>unquote</code>, which is only valid inside a <code>quasiquote</code>, this is a clever way to distinguish a command from a valid Racket expression. <a href="#racket-mode-footnote-2-return">↩</a></p></li>
<li id="racket-mode-footnote-3-definition" class="footnote-definition">
<p>The nonce needn’t be a cryptographically secure random number, just unique; an increasing integer is fine. <a href="#racket-mode-footnote-3-return">↩</a></p></li>
<li id="racket-mode-footnote-4-definition" class="footnote-definition">
<p>“Point” is Emacs’ name for what you might call the cursor or caret. <a href="#racket-mode-footnote-4-return">↩</a></p></li>
<li id="racket-mode-footnote-5-definition" class="footnote-definition">
<p>As far as I can tell, the convention is that function applications should be indented consistently — only macro invocations might use custom indent. <a href="#racket-mode-footnote-5-return">↩</a></p></li></ol></div>
<footer></footer></article></div>Please scrollurn:www-greghendershott-com:-2017-03-please-scroll.html2017-03-08T22:00:00Z2017-03-08T22:00:00ZGreg Hendershott
<div>
<article>
<header>
<h1>Please scroll</h1>
<p class="date-and-tags">
<time datetime="2017-03-08" pubdate="true">2017-03-08</time> :: <span class="tags"><a href="/tags/Racket.html">Racket</a>, <a href="/tags/Emacs.html">Emacs</a></span></p></header>
<p>Recently I got more time to catch up on <a href="https://github.com/greghendershott/racket-mode">racket-mode</a>. I improved two things that happen to fit one theme — an extraordinarily advanced UX concept I call, “scrolling down to the point of interest.”</p><!-- more-->
<h2 id="visit-definition">Visit definition</h2>
<p>In racket-mode you can
<kbd>M-.</kbd> (press
<kbd>Alt</kbd> and
<kbd>period</kbd>) to visit the definition of a Racket identifier.</p>
<p>There is no Racket library function that supports this, exactly. The <a href="http://docs.racket-lang.org/reference/stxcmp.html#%28def._%28%28quote._~23~25kernel%29._identifier-binding%29%29"><code>identifier-binding</code></a> function gives you a filename, but not a position within. And actually, it gives you <em>two</em> filenames (and identifier symbols), because the location and symbol of the <em>definition</em> might differ from the location and symbol under which it is <em>provided</em>.</p>
<p>I’ve also found it can be tricky when something is renamed more than once — for example both renamed and wrapped in a contract. Of the three (or more) names involved, <code>identifier-binding</code> will return only two. For example in <code>(provide (contract-out [rename orig new
contract]))</code> it reports (1) the contract wrapper’s generated identifier and (2) <code>new</code> — but <em>not</em> (3) <code>orig</code>. Unfortunately the definition of <code>orig</code> is our desired destination.</p>
<p>So, I need to treat <code>identifier-binding</code> as a valuable head start — but maybe not the real answer.</p>
<p>I need to check each file and try to find the identifier within. This isn’t a job for regular expression; the name might not appear textually at the definition site (think of <code>define</code>-er macros). Instead I read the file as syntax and walk it. Sometimes it makes sense to search the syntax after it has been fully-expanded. Sometimes it helps to walk it unexpanded, looking for some special forms, for example the “rename” variant of <code>contract-out</code>.</p>
<p>If after all that, we can’t find the position, racket-mode plops you at the start of the file.</p>
<p>The change I made was to reduce the chance of that happening. Details in the <a href="https://github.com/greghendershott/racket-mode/commit/c50cd48edc74348bd89b09661ea325dac12fcb48">commit</a> message and diff.</p>
<h2 id="view-documentation">View documentation</h2>
<p>In racket-mode you can
<kbd>C-c C-d</kbd> to view Racket’s HTML documentation in your default web browser. It should (a) open the correct page and (b) scroll to the item on that page. Unfortunately (b) didn’t always happen on macOS. Under certain conditions, macOS is reluctant to open <code>file:</code> URLs <em>and</em> scroll down to the anchor/fragment (the bit after the <code>#</code> in the URL).</p>
<div class="brush: sh">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="c1"># Will open the default browser to the top of the define.html page</span>
<span class="c1"># but not scroll down to the define-values item:</span>
$ open <span class="s1">'file:///Applications/Racket_v6.7/doc/reference/define.html#%28form._%28%28quote._~23~25kernel%29._define-values%29%29'</span>
<span class="c1"># Ditto</span>
$ osascript -e <span class="s1">'open location "file:///Applications/Racket_v6.7/doc/reference/define.html#%28form._%28%28quote._~23~25kernel%29._define-values%29%29"'</span>
<span class="c1"># But this works!</span>
$ osascript -e <span class="s1">'tell application "chrome" to open location "file:///Applications/Racket_v6.7/doc/reference/define.html#%28form._%28%28quote._~23~25kernel%29._define-values%29%29"'</span>
<span class="c1"># Well, you also want the "activate" at the end:</span>
$ osascript -e <span class="s1">'tell application "chrome" to open location "file:///Applications/Racket_v6.7/doc/reference/define.html#%28form._%28%28quote._~23~25kernel%29._define-values%29%29" activate'</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Interestingly the generic <code>open</code> seems to work fine for <code>http:</code>. Also fine if a <code>file:</code> location is under your home directory instead of <code>/Applications</code>. Because security?<sup><a href="#please-scroll-footnote-1-definition" name="please-scroll-footnote-1-return">1</a></sup> Anyway, this is probably why Racket developers and power users haven’t noticed, if they’re building Racket (and its docs) from HEAD.</p>
<p>So I can use <code>osascript</code> if I know the default browser. How do I know that? Ugh. OK. This information seems to reside in <code>Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist</code>. Read the JSON, find the correct entry, grab the <code>browser</code> part of <code>com.company.browser</code>, and hopefully we’re good.</p>
<h2 id="pontification">Pontification</h2>
<p>Computer science mostly isn’t science.</p>
<p>Software engineering mostly isn’t engineering.</p>
<p>Sometimes success is simply scrolling.</p>
<div class="footnotes">
<ol>
<li id="please-scroll-footnote-1-definition" class="footnote-definition">
<p>Security theater? I don’t see why it’s safe to load a page, but risky to scroll to an anchor in it? I also don’t see why <code>/Applications</code> is more risky than your home dir — much less some rando <code>http:</code> location? <a href="#please-scroll-footnote-1-return">↩</a></p></li></ol></div>
<footer></footer></article></div>Emacs Themesurn:www-greghendershott-com:-2017-02-emacs-themes.html2017-02-08T05:00:00Z2017-02-08T05:00:00ZGreg Hendershott
<div>
<article>
<header>
<h1>Emacs Themes</h1>
<p class="date-and-tags">
<time datetime="2017-02-08" pubdate="true">2017-02-08</time> :: <span class="tags"><a href="/tags/Emacs.html">Emacs</a></span></p></header>
<p>Until a few months ago I didn’t use Emacs <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Custom-Themes.html">themes</a>. A <code>custom-set-faces</code> form in my init file gradually accumulated face specs like a lint-roller.</p>
<p>Then I started to use <a href="https://melpa.org/#/solarized-theme">Solarized</a>. Mostly light, sometimes dark. Switching between them using
<kbd>M-x load-theme</kbd> worked fine.</p>
<p>Later I liked the look of <a href="https://melpa.org/#/material-theme">Material</a>. Although too high-contrast to use full-time, it works well in certain situations.</p>
<p>After I installed it I had two annoyances:</p>
<ol>
<li>
<p>I didn’t love the 3D “button” look it gives org-mode headings. Must tweak.</p></li>
<li>
<p>Switching between the Solarized and Material themes using <code>load-theme</code> definitely did <em>not</em> work well: If the old theme defined a face, but the new theme did not, the old face would remain in effect. So for example I might switch to Material then back to Solarized, and get a weird mix of mostly Solarized but with Material org headings.</p></li></ol>
<p>Here’s what I’m doing to address both issues.</p><!-- more-->
<h2 id="multiple-themes">Multiple themes</h2>
<p>What I didn’t understand at first is that Emacs supports many themes enabled simultaneously. The variable <code>custom-enabled-themes</code> is plural, a list. As a result, <code>load-theme</code> doesn’t mean “use this one theme” — it means, “layer this theme on top of those already enabled”.</p>
<p>If want just one theme at a time? I must first <code>disable-theme</code> each currently-enabled theme. A little function/command:<sup><a href="#emacs-themes-footnote-1-definition" name="emacs-themes-footnote-1-return">1</a></sup></p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">defun</span> <span class="nv">gh/disable-all-themes</span> <span class="p">()</span>
<span class="p">(</span><span class="k">interactive</span><span class="p">)</span>
<span class="p">(</span><span class="nf">mapc</span> <span class="nf">#'</span><span class="nv">disable-theme</span> <span class="nv">custom-enabled-themes</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>So fine, but, now I need to issue two commands. Give me convenience or give me death.</p>
<p>One idea would be to make a new <code>gh/load-theme</code> command that composes <code>gh/disable-all-themes</code> and <code>load-theme</code>. But will I remember to
<kbd>M-x</kbd> <em>that</em> instead?</p>
<p>Another idea would be to advise <code>load-theme</code> so I can continue doing
<kbd>M-x load-theme</kbd>.</p>
<p>I did that. As a bonus, such advice can also provide a kind of “theme hooks” feature — a way to call a function after a specific theme is loaded.</p>
<h2 id="emacs-init-file">Emacs init file</h2>
<p>Here are some snippets from my <code>~/.emacs.d/init.el</code>.</p>
<h3 id="advice-and-hooks">Advice and hooks</h3>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="c1">;;; Theme hooks</span>
<span class="p">(</span><span class="k">defvar</span> <span class="nv">gh/theme-hooks</span> <span class="no">nil</span>
<span class="s">"((theme-id . function) ...)"</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">gh/add-theme-hook</span> <span class="p">(</span><span class="nv">theme-id</span> <span class="nv">hook-func</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'gh/theme-hooks</span> <span class="p">(</span><span class="nf">cons</span> <span class="nv">theme-id</span> <span class="nv">hook-func</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">gh/load-theme-advice</span> <span class="p">(</span><span class="nv">f</span> <span class="nv">theme-id</span> <span class="kp">&optional</span> <span class="nv">no-confirm</span> <span class="nv">no-enable</span> <span class="kp">&rest</span> <span class="nv">args</span><span class="p">)</span>
<span class="s">"Enhances </span><span class="ss">`load-theme'</span><span class="s"> in two ways:</span>
<span class="s">1. Disables enabled themes for a clean slate.</span>
<span class="s">2. Calls functions registered using </span><span class="ss">`gh/add-theme-hook'</span><span class="s">."</span>
<span class="p">(</span><span class="nb">unless</span> <span class="nv">no-enable</span>
<span class="p">(</span><span class="nv">gh/disable-all-themes</span><span class="p">))</span>
<span class="p">(</span><span class="k">prog1</span>
<span class="p">(</span><span class="nf">apply</span> <span class="nv">f</span> <span class="nv">theme-id</span> <span class="nv">no-confirm</span> <span class="nv">no-enable</span> <span class="nv">args</span><span class="p">)</span>
<span class="p">(</span><span class="nb">unless</span> <span class="nv">no-enable</span>
<span class="p">(</span><span class="nb">pcase</span> <span class="p">(</span><span class="nf">assq</span> <span class="nv">theme-id</span> <span class="nv">gh/theme-hooks</span><span class="p">)</span>
<span class="p">(</span><span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="nv">_</span> <span class="o">.</span> <span class="o">,</span><span class="nv">f</span><span class="p">)</span> <span class="p">(</span><span class="nf">funcall</span> <span class="nv">f</span><span class="p">))))))</span>
<span class="p">(</span><span class="nv">advice-add</span> <span class="ss">'load-theme</span>
<span class="nb">:around</span>
<span class="nf">#'</span><span class="nv">gh/load-theme-advice</span><span class="p">)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<h3 id="packages">Packages</h3>
<p>Now my configuration of each theme package can add a theme hook to make tweaks.</p>
<p>I manage package install and config in my init file using the wonderful <a href="https://melpa.org/#/use-package">use-package</a>.</p>
<p>My personal preferences for Material:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">use-package</span> <span class="nv">material-theme</span>
<span class="nb">:ensure</span> <span class="no">t</span>
<span class="nb">:defer</span> <span class="no">t</span>
<span class="nb">:init</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">gh/material-theme-hook</span> <span class="p">()</span>
<span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'which-key-key-face</span> <span class="no">nil</span> <span class="nb">:foreground</span>
<span class="p">(</span><span class="nv">face-attribute</span> <span class="ss">'error</span> <span class="nb">:foreground</span><span class="p">))</span>
<span class="p">(</span><span class="nb">loop</span> <span class="nv">for</span> <span class="nv">n</span> <span class="nv">from</span> <span class="mi">1</span> <span class="nv">to</span> <span class="mi">8</span>
<span class="nb">do</span> <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="p">(</span><span class="nf">intern-soft</span> <span class="p">(</span><span class="nf">format</span> <span class="s">"org-level-%s"</span> <span class="nv">n</span><span class="p">))</span>
<span class="no">nil</span>
<span class="nb">:height</span> <span class="ss">'unspecified</span>
<span class="nb">:background</span> <span class="ss">'unspecified</span>
<span class="nb">:box</span> <span class="ss">'unspecified</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">gh/add-theme-hook</span> <span class="ss">'material</span> <span class="nf">#'</span><span class="nv">gh/material-theme-hook</span><span class="p">)</span>
<span class="p">(</span><span class="nv">gh/add-theme-hook</span> <span class="ss">'material-light</span> <span class="nf">#'</span><span class="nv">gh/material-theme-hook</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>And for Solarized:</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">use-package</span> <span class="nv">solarized</span>
<span class="nb">:ensure</span> <span class="nv">solarized-theme</span>
<span class="nb">:defer</span> <span class="no">t</span>
<span class="nb">:init</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">gh/solarized-theme-hook</span> <span class="p">()</span>
<span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'font-lock-constant-face</span> <span class="no">nil</span> <span class="nb">:weight</span> <span class="ss">'normal</span><span class="p">)</span>
<span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'font-lock-function-name-face</span> <span class="no">nil</span> <span class="nb">:weight</span> <span class="ss">'bold</span><span class="p">)</span>
<span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'which-key-key-face</span> <span class="no">nil</span> <span class="nb">:foreground</span>
<span class="p">(</span><span class="nv">face-attribute</span> <span class="ss">'error</span> <span class="nb">:foreground</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">gh/add-theme-hook</span> <span class="ss">'solarized-dark</span> <span class="nf">#'</span><span class="nv">gh/solarized-theme-hook</span><span class="p">)</span>
<span class="p">(</span><span class="nv">gh/add-theme-hook</span> <span class="ss">'solarized-light</span> <span class="nf">#'</span><span class="nv">gh/solarized-theme-hook</span><span class="p">)</span>
<span class="nb">:config</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">solarized-use-variable-pitch</span> <span class="no">nil</span>
<span class="nv">solarized-use-less-bold</span> <span class="no">t</span>
<span class="nv">solarized-use-more-italic</span> <span class="no">nil</span>
<span class="nv">solarized-distinct-doc-face</span> <span class="no">t</span>
<span class="nv">solarized-high-contrast-mode-line</span> <span class="no">t</span>
<span class="c1">;; I find different font sizes irritating.</span>
<span class="nv">solarized-height-minus-1</span> <span class="mf">1.0</span>
<span class="nv">solarized-height-plus-1</span> <span class="mf">1.0</span>
<span class="nv">solarized-height-plus-2</span> <span class="mf">1.0</span>
<span class="nv">solarized-height-plus-3</span> <span class="mf">1.0</span>
<span class="nv">solarized-height-plus-4</span> <span class="mf">1.0</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<h2 id="hydra">Hydra</h2>
<p>Finally, let’s use the <a href="https://melpa.org/#/hydra">hydra</a> package …</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre>1
2
3
4</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nb">use-package</span> <span class="nv">hydra</span>
<span class="nb">:ensure</span> <span class="no">t</span>
<span class="nb">:config</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">hydra-lv</span> <span class="no">nil</span><span class="p">)</span> <span class="c1">;use echo area)</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>… to make it easy to switch among themes with a single key press …</p>
<div class="brush: elisp">
<table class="sourcetable">
<tbody>
<tr>
<td class="linenos">
<div class="linenodiv">
<pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td>
<td class="code">
<div class="source">
<pre><span></span><span class="p">(</span><span class="nv">defhydra</span> <span class="nv">gh/themes-hydra</span> <span class="p">(</span><span class="nb">:hint</span> <span class="no">nil</span> <span class="nb">:color</span> <span class="nv">pink</span><span class="p">)</span>
<span class="s">"</span>
<span class="s">Themes</span>
<span class="s">^Solarized^ ^Material^ ^Other^</span>
<span class="s">----------------------------------------------------</span>
<span class="s">_s_: Dark _m_: Dark _z_: Zenburn _DEL_: none</span>
<span class="s">_S_: Light _M_: Light</span>
<span class="s">"</span>
<span class="p">(</span><span class="s">"s"</span> <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'solarized-dark</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="s">"S"</span> <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'solarized-light</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="s">"m"</span> <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'material</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="s">"M"</span> <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'material-light</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="s">"z"</span> <span class="p">(</span><span class="nv">load-theme</span> <span class="ss">'zenburn</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="s">"DEL"</span> <span class="p">(</span><span class="nv">gh/disable-all-themes</span><span class="p">))</span>
<span class="p">(</span><span class="s">"RET"</span> <span class="no">nil</span> <span class="s">"done"</span> <span class="nb">:color</span> <span class="nv">blue</span><span class="p">))</span>
<span class="p">(</span><span class="nv">bind-keys</span> <span class="p">(</span><span class="s">"C-c w t"</span> <span class="o">.</span> <span class="nv">gh/themes-hydra/body</span><span class="p">))</span>
</pre></div>
</td></tr></tbody></table>
</div>
<p>Incidentally I bind this hydra to
<kbd>C-c w t</kbd> following an idea I saw in <a href="https://github.com/lunaryorn/.emacs.d/blob/master/init.el#L302-L427">lunaryorn’s init file</a>:</p>
<ol>
<li>
<p>Use <code>bind-keys</code> (from <code>use-package</code>) to put commands on
<kbd>C-c</kbd> prefixes, with an additional prefix key to group related commands. So for example window-related commands have a
<kbd>C-c w</kbd> prefix.</p></li>
<li>
<p>Use <a href="https://melpa.org/#/which-key"><code>which-key</code></a> to label prefixes and bindings.</p></li></ol>
<p>Anyway, the upshot is I can type
<kbd>C-c w t</kbd>, then keep pressing single hydra keys to switch among themes. Upon finding the optimal mood management, tap
<kbd>RETURN</kbd> to exit the hydra.</p>
<div class="footnotes">
<ol>
<li id="emacs-themes-footnote-1-definition" class="footnote-definition">
<p>In my init file I do the customary thing: Prefix identifiers with my initials and a slash: <code>gh/</code>. <a href="#emacs-themes-footnote-1-return">↩</a></p></li></ol></div>
<footer></footer></article></div>