<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[_habnablog]]></title>
  <link href="http://blog.habnab.it/atom.xml" rel="self"/>
  <link href="http://blog.habnab.it/"/>
  <updated>2014-04-13T14:12:12-04:00</updated>
  <id>http://blog.habnab.it/</id>
  <author>
    <name><![CDATA[_Harold Abnabit]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Python Packages and You]]></title>
    <link href="http://blog.habnab.it/blog/2013/07/21/python-packages-and-you/"/>
    <updated>2013-07-21T12:29:00-04:00</updated>
    <id>http://blog.habnab.it/blog/2013/07/21/python-packages-and-you</id>
    <content type="html"><![CDATA[<p>Jean-Paul Calderone wrote <a href="http://as.ynchrono.us/2007/12/filesystem-structure-of-python-project_21.html">an excellent blog post</a> on the right way to
structure a python project. This post will build on that post by covering
concrete examples of how to write imports, how to distribute your package, and
what not to do.</p>

<!-- more -->


<p>As an example, we&rsquo;ll be looking at my own project, <a href="https://github.com/habnabit/passacre">passacre</a>. There is a
python package called <code>passacre</code> immediately in the root of the project
(i.e. not in a <code>lib</code> or <code>src</code> directory). Here&rsquo;s what&rsquo;s inside it:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>passacre/__init__.py
</span><span class='line'>passacre/__main__.py
</span><span class='line'>passacre/application.py
</span><span class='line'>passacre/config.py
</span><span class='line'>passacre/generator.py
</span><span class='line'>passacre/multibase.py
</span><span class='line'>passacre/test/__init__.py
</span><span class='line'>passacre/test/test_application.py
</span><span class='line'>passacre/test/test_config.py
</span><span class='line'>passacre/test/test_generator.py
</span><span class='line'>passacre/test/test_multibase.py
</span><span class='line'>passacre/test/util.py
</span><span class='line'>passacre/util.py</span></code></pre></td></tr></table></div></figure>


<h2>Intra-package imports</h2>

<p>There is exactly one way code in your package should be importing other code
inside your package, and that&rsquo;s with <em>absolute imports</em>.</p>

<h3>Basic imports</h3>

<p>So, in this code, <code>passacre.config</code> needs to import some things from
<code>passacre.multibase</code>. The import looks like this:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">passacre.multibase</span> <span class="kn">import</span> <span class="n">MultiBase</span>
</span></code></pre></td></tr></table></div></figure>


<p>Note that the import uses the fully-qualified name of the module,
<code>passacre.multibase</code>. This is important for two reasons:</p>

<ol>
<li>It makes your code very explicit in what you&rsquo;re importing.</li>
<li>Your code will continue to work in the future. There&rsquo;s a very, very old
method of doing imports (&ldquo;implicit relative imports&rdquo;) wherein one would
write <code>from multibase import Multibase</code> instead, but this is
<a href="http://www.python.org/dev/peps/pep-0328/">gone in python 3</a>. It <a href="http://bugs.python.org/issue14494">should&rsquo;ve been removed from python 2.7</a>, but
unfortunately, <a href="http://mail.python.org/pipermail/python-dev/2010-April/099607.html">they forgot to do it</a>.</li>
</ol>


<p>There is another style of imports also covered in <a href="http://www.python.org/dev/peps/pep-0328/">PEP 328</a>, wherein the
code would look instead look like this:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">.multibase</span> <span class="kn">import</span> <span class="n">MultiBase</span>
</span></code></pre></td></tr></table></div></figure>


<p>I&rsquo;ll only mention explicit relative imports once more in this post; I very much
prefer the look of absolute imports, but this is primarily an issue of style.</p>

<h3>Test module imports</h3>

<p><code>passacre</code> also comes with a test suite in the <code>passacre.test</code> submodule. These
tests necessarily have to import the passacre code to test it. Here&rsquo;s what the
<code>passacre.test.test_multibase</code> module does to import <code>passacre.multibase</code>:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">passacre.multibase</span> <span class="kn">import</span> <span class="n">MultiBase</span>
</span></code></pre></td></tr></table></div></figure>


<p>&ldquo;But wait! That&rsquo;s the same as before!&rdquo; you cry. Since the fully-qualified
module name is always the same, <em>the imports are also always the same</em>. This is
another advantage of absolute imports&mdash;you always know exactly what you&rsquo;re
getting.</p>

<h3>Sibling subpackage imports</h3>

<p>For demonstration purposes, we&rsquo;ll pretend that there&rsquo;s another subpackage
<code>passacre.test2</code> that contains even more tests. Here&rsquo;s the imaginary addition
to the package structure:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>passacre/test2/__init__.py
</span><span class='line'>passacre/test2/test_multibase.py</span></code></pre></td></tr></table></div></figure>


<p>This <code>test_multibase</code> module needs to use some utility function from
<code>passacre.test.util</code>, so it imports the function:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">passacre.test.util</span> <span class="kn">import</span> <span class="n">excinfo_arg_0</span>
</span></code></pre></td></tr></table></div></figure>


<p>Using absolute imports means that it doesn&rsquo;t matter where in the project a
module is when you try to import another module. Python will always look up the
module to import from the root of your package.</p>

<h3>Shadowed standard library module imports</h3>

<p>Something I&rsquo;m <em>sure</em> everyone has done at some point in their python career is
name a module the same as a module in the standard library. If I wanted a
<code>passacre.socket</code> module that used the standard library <code>socket</code> module,
<code>import socket</code> should give me the standard library module instead of
<code>passacre.socket</code>. <a href="http://www.python.org/dev/peps/pep-0328/">PEP 328</a> covers this too by adding a <code>__future__</code>
feature <code>absolute_import</code>, which is on by default in python 3.0 and higher.</p>

<p>Activating <code>absolute_import</code> has exactly one effect: disabling implicit
relative imports. Since <code>__future__</code> features only affect the module enabling
them, I can simply add <code>from __future__ import absolute_import</code> to
<code>passacre/socket.py</code> and any <code>import socket</code> calls in it will import the
standard library <code>socket</code> module.</p>

<h2>Distribution</h2>

<p>Once your package has some code in it that can run, you&rsquo;ll probably want to let
other people use your package as well.</p>

<h3><code>setup.py</code></h3>

<p><code>setup.py</code> is your package&rsquo;s entry point into <a href="http://docs.python.org/2/distutils/">distutils</a> or
<a href="http://pythonhosted.org/setuptools/">setuptools</a>. Every package should have one, as that&rsquo;s how your code gets
put into the right place for your users. I won&rsquo;t go too much into detail in how
to use them; the links above are for tutorials which will explain how to get
started.</p>

<p>My own rule of thumb is to use distutils unless I absolutely require a feature
from setuptools. Some people will say to always use setuptools, and that&rsquo;s okay
too.</p>

<h3>Executable scripts</h3>

<p><a href="http://as.ynchrono.us/2007/12/filesystem-structure-of-python-project_21.html">Jean-Paul&rsquo;s post</a> recommends putting python scripts in the <code>bin</code> directory
of your project root. This is fine advice, but there are newer methods which
mean you don&rsquo;t need a <code>bin</code> directory at all.</p>

<p>First, there&rsquo;s <code>__main__.py</code>. This is not quite the same as an executable
script, but it allows a package to be executed via <code>python -m</code>. For example,
<code>passacre/__main__.py</code> means that one can execute <code>python -m passacre</code> and the
<code>__main__.py</code> file will be executed. <a href="http://www.python.org/dev/peps/pep-0338/">PEP 338</a> has more details on exactly
how this works.</p>

<p><code>passacre/__main__.py</code> is fairly small:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">passacre.application</span> <span class="kn">import</span> <span class="n">main</span>
</span><span class='line'><span class="n">main</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>Since <code>__main__.py</code> is executed directly, the actual main function should live
elsewhere if you actually want to be able to test it. This way, test code can
<em>also</em> <code>from passacre.application import main</code> and be able to call that
function.</p>

<p><code>python -m</code> is not limited to executing packages. For times when you want to
quickly run some module that has an <code>if __name__ == '__main__':</code> block in it,
you can use <code>python -m passacre.thatmodule</code>. Importantly, this will ensure that
python recognizes your whole package, which means that your imports won&rsquo;t fail.</p>

<p>Sometimes a project wants explicit binaries instead of requiring their users to
use <code>python -m</code>. For this case, setuptools has <a href="http://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation">automatic script creation</a>.
Here&rsquo;s an excerpt from passacre&rsquo;s <code>setup.py</code> file:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
</span><span class='line'>
</span><span class='line'><span class="c"># [...]</span>
</span><span class='line'>
</span><span class='line'><span class="n">setup</span><span class="p">(</span>
</span><span class='line'>    <span class="c"># [...]</span>
</span><span class='line'>    <span class="n">entry_points</span><span class="o">=</span><span class="p">{</span>
</span><span class='line'>        <span class="s">&#39;console_scripts&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s">&#39;passacre = passacre.application:main&#39;</span><span class="p">],</span>
</span><span class='line'>    <span class="p">},</span>
</span><span class='line'><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>(The actual <code>setup.py</code> uses <a href="http://pythonhosted.org/setuptools/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies">extras</a>, but that&rsquo;s not important for this blog
post.)</p>

<p>This <code>console_scripts</code> definition makes a <code>passacre</code> executable that does the
same thing as the <code>__main__.py</code> script did: imports the <code>main</code> function from
<code>passacre.application</code> and calls it.</p>

<p>Using distutils or setuptools to generate and/or install your python scripts is
important&mdash;as a part of the install process, the shebang line (e.g.
<code>#!/usr/bin/env python</code>) will be <em>rewritten</em> to use the python that ran
<code>setup.py</code>. So, if someone does <code>/usr/local/bin/python2.6 setup.py install</code>,
<code>passacre</code> will start with <code>#!/usr/local/bin/python2.6</code>.</p>

<p>Additionally, <code>python -m</code> and automatic script creation can be used beautifully
together&mdash;a project can have a <code>scripts</code> subpackage containing one module for
every executable script. For example, <code>passacre_generate</code> could be
<code>passacre_generate = passacre.scripts.generate:main</code> and also contain:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
</span><span class='line'>    <span class="n">main</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>For projects with a lot of scripts, this is a good organization method to keep
the scripts separate from the more library-ish code.</p>

<h2>Documentation</h2>

<p>Please have some, especially if you&rsquo;re distributing your package. Docstrings
are a good start, but a tutorial written with <a href="http://sphinx-doc.org/">sphinx</a> and/or a <code>README</code>
with usage examples goes a long way.</p>

<h2>Common pitfalls</h2>

<h3>Don&rsquo;t directly run modules inside packages</h3>

<p>Seriously. Never ever <em>ever</em> do this. What I mean specifically is doing <code>python
passacre/__main__.py</code>, or <code>python passacre/test/test_application.py</code>, or
anything else that starts with <code>python passacre/</code>. This will prevent python
from knowing where the root of your package is, and so absolute imports and
explicit relative imports will fail, or not import the code you think it should
be importing.</p>

<p>If you think you have to do this, <strong>you&rsquo;re wrong</strong>. Instead, you probably want
to use <code>python -m</code>, or <a href="http://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation">generate an executable script to run</a>, or
<a href="http://pytest.org/">use a test runner</a>. If you don&rsquo;t think any of those cover your use case,
leave a comment and I&rsquo;ll show you a better method.</p>

<h3>Don&rsquo;t set <code>PYTHONPATH</code> to try to make it go</h3>

<p>If you think you have to set <code>PYTHONPATH</code>, you&rsquo;ve probably fallen victim to the
first pitfall and are trying to execute a module directly. With proper package
layout and proper imports, you won&rsquo;t need to set <code>PYTHONPATH</code> to run your code.</p>

<h3>Don&rsquo;t modify <code>sys.path</code> from code in your package</h3>

<p>Like modifying <code>PYTHONPATH</code>, but worse because it&rsquo;s easier to affect other
people using your code. <strong>Never</strong> do this, as it <strong>will</strong> break and make people
trying to use your code very annoyed.</p>

<h3>Don&rsquo;t make your project root a package</h3>

<p>Your project root should <em>contain</em> a python package, not be a package itself.
If you do this, your <code>setup.py</code> will be very confusing (or not work at all) and
it will be very difficult to run your code.</p>

<h2>Conclusion</h2>

<p>Really, writing a python package isn&rsquo;t hard. The rules above are very simple
and will lead to simple, easy-to-read-and-understand python code.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[emacsclient and TRAMP]]></title>
    <link href="http://blog.habnab.it/blog/2013/06/25/emacsclient-and-tramp/"/>
    <updated>2013-06-25T07:47:00-04:00</updated>
    <id>http://blog.habnab.it/blog/2013/06/25/emacsclient-and-tramp</id>
    <content type="html"><![CDATA[<p>For quite a while now, I&rsquo;ve done a large amount of my text editing in emacs
over ssh using <a href="http://www.emacswiki.org/emacs/TrampMode">TRAMP</a>. It&rsquo;s <em>extremely</em> convenient to be able to run one
instance of emacs locally instead of spawning an editor remotely and
interacting with it over ssh. I&rsquo;ve tried using <a href="http://fuse.sourceforge.net/sshfs.html">sshfs</a> in the past, but it&rsquo;s
never worked well for me in the general case. But, this isn&rsquo;t a post about
justifying my choices.</p>

<p>The other crucial part of my local emacs setup has been <a href="http://www.emacswiki.org/emacs/EmacsClient">emacsclient</a>. Setting
my local <code>$EDITOR</code> to emacsclient means that I could, for example, run <code>git
commit</code> in a terminal and edit the commit message without having to spawn a
<em>new</em> emacs instance. Instead, emacsclient tells the existing emacs what files
to edit, and waits until emacs says it&rsquo;s done with them.</p>

<p>Until just yesterday, there was a major flaw in my setup: I couldn&rsquo;t activate
my local emacs instance through emacsclient on a remote host. This meant that
<code>$EDITOR</code> had to be set to something that spawned an editor on the remote host,
which was becoming increasingly frustrating.</p>

<!-- more -->


<p>In the past I&rsquo;d tried doing things like using an ssh tunnel to forward the
emacsclient connections from the remote host to my local machine, but
emacsclient doesn&rsquo;t anticipate this case. The emacsclient protocol is very
simple: ASCII commands delimited with line feeds. So, for example:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ emacsclient /foo/bar
</span><span class='line'># and this sends (approximately):
</span><span class='line'>-auth some-gunk-here
</span><span class='line'>-dir /foo -file /foo/bar</span></code></pre></td></tr></table></div></figure>


<p>The problem is that this is being sent to your <em>local</em> emacs, which then tries
to load the <em>local</em> <code>/foo/bar</code>. A TRAMP path is in the form of (approximately)
<code>/ssh:example.com:/foo/bar</code>, so if only this could be prepended, emacs could
deal with it!</p>

<p>In my most recent investigation of the problem, I found <a href="http://snarfed.org/emacsclient_in_tramp_remote_shells">Ryan Barrett&rsquo;s
implementation</a>, which was <em>most</em> of what I wanted. Except,</p>

<ol>
<li><p>It wasn&rsquo;t automatic. It&rsquo;s really convenient to be able to have TRAMP dump
the appropriate authentication file onto the server as soon as a connection
is made without having to connect using a special function.</p></li>
<li><p>It was relying on emacsclient sending a <code>-tty</code> argument in a specific
format, and then using the TRAMP prefix of the <em>current buffer</em>. In practice
this means you have to have your frontmost buffer a file open on the remote
server, and <em>only then</em> can you use emacsclient on that remote server.</p></li>
</ol>


<p>I started to hack on it, but I was still affected by the same original problem:
emacsclient doesn&rsquo;t know about TRAMP. The default implementation doesn&rsquo;t even
have a way of specifying additional data to be sent over the wire. With the
simplicity of the emacsclient protocol, it started looking like writing my own
would be the simplest choice.</p>

<p>So, I put together some elisp to write out a special client authentication file
that would also include the TRAMP prefix and a shell script that would parse it
and write commands using nc. My elisp implementation borrows code from Ryan
Barrett&rsquo;s (and thank you for getting me started with this!) but goes a bit
farther. The full workflow is like this:</p>

<ol>
<li><p>Update your <code>.emacs</code> to load and configure the elisp.</p></li>
<li><p>Update your <code>.profile</code> to set <code>$EDITOR</code> to the <code>emacsclient.sh</code> script and
tell it where the authentication file is.</p></li>
<li><p>Open a TRAMP connection from your local emacs to write out the
authentication file.</p></li>
<li><p>Go hog wild.</p></li>
<li><p>Repeat only steps 3-5.</p></li>
</ol>


<p>Here are the versions of <code>emacsclient.sh</code> and <code>remote-emacsclient.el</code> as of
2013-06-25:</p>

<figure class='code'><figcaption><span> (emacsclient.sh)</span> <a href='http://blog.habnab.it/downloads/code/remote-emacsclient/emacsclient.sh'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="c">#!/bin/sh</span>
</span><span class='line'><span class="nv">nowait</span><span class="o">=</span>0
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$1&quot;</span> <span class="o">=</span> <span class="s2">&quot;-n&quot;</span> <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nv">nowait</span><span class="o">=</span>1
</span><span class='line'>    <span class="nb">shift</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$#&quot;</span> -eq 0 <span class="o">]</span>; <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nb">echo</span> <span class="s2">&quot;no files specified&quot;</span>
</span><span class='line'>    <span class="nb">exit </span>0
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'><span class="o">[</span> -e <span class="s2">&quot;$remote_emacs_auth&quot;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">client_host</span><span class="o">=</span><span class="k">$(</span>sed -n 1p <span class="s2">&quot;$remote_emacs_auth&quot;</span><span class="k">)</span>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> -z <span class="s2">&quot;$client_host&quot;</span> <span class="o">]</span> <span class="o">||</span> ! nc -z <span class="nv">$client_host</span>; <span class="k">then</span>
</span><span class='line'><span class="k">    </span><span class="nb">echo</span> <span class="s2">&quot;no emacs server&quot;</span>
</span><span class='line'>    sleep 1
</span><span class='line'>    <span class="nb">exec </span>emacs <span class="s2">&quot;$@&quot;</span>
</span><span class='line'><span class="k">fi</span>
</span><span class='line'>
</span><span class='line'>quote <span class="o">()</span> <span class="o">{</span>
</span><span class='line'>    sed <span class="s1">&#39;s:&amp;:\&amp;\&amp;:g;s:-:\&amp;-:g;s: :\&amp;_:g&#39;</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'>quoteline <span class="o">()</span> <span class="o">{</span>
</span><span class='line'>    <span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;$1&quot;</span> | quote
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'>unquote <span class="o">()</span> <span class="o">{</span>
</span><span class='line'>    sed <span class="s1">&#39;s:&amp;&amp;:\&amp;:g;s:&amp;-:-:g;s:&amp;_: :g;s:&amp;n:\</span>
</span><span class='line'><span class="s1">:g&#39;</span>
</span><span class='line'><span class="o">}</span>
</span><span class='line'>
</span><span class='line'><span class="nv">client_auth</span><span class="o">=</span><span class="k">$(</span>sed -n 2p <span class="s2">&quot;${remote_emacs_auth}&quot;</span><span class="k">)</span>
</span><span class='line'><span class="nv">tramp_prefix</span><span class="o">=</span><span class="k">$(</span>sed -n 3p <span class="s2">&quot;${remote_emacs_auth}&quot;</span><span class="k">)</span>
</span><span class='line'><span class="nv">args</span><span class="o">=</span><span class="k">$(</span><span class="nb">printf</span> <span class="s2">&quot;%s\n%s\n&quot;</span> <span class="s2">&quot;${client_auth}&quot;</span> <span class="s2">&quot;-dir ${tramp_prefix}${quoted_pwd}&quot;</span><span class="k">)</span>
</span><span class='line'><span class="o">[</span> <span class="s2">&quot;${nowait}&quot;</span> !<span class="o">=</span> 0 <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nv">args</span><span class="o">=</span><span class="s2">&quot;${args} -nowait&quot;</span>
</span><span class='line'><span class="nv">quoted_pwd</span><span class="o">=</span><span class="k">$(</span>quoteline <span class="s2">&quot;$(pwd)&quot;</span><span class="k">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">for </span>file; <span class="k">do</span>
</span><span class='line'><span class="k">    </span><span class="nv">quoted_file</span><span class="o">=</span><span class="k">$(</span>quoteline <span class="s2">&quot;${file}&quot;</span><span class="k">)</span>
</span><span class='line'>    <span class="k">case</span> <span class="s2">&quot;${file}&quot;</span> in
</span><span class='line'>        +*<span class="o">)</span> <span class="nv">argument</span><span class="o">=</span><span class="s2">&quot;-position ${quoted_file}&quot;</span>;;
</span><span class='line'>        /*<span class="o">)</span> <span class="nv">argument</span><span class="o">=</span><span class="s2">&quot;-file ${tramp_prefix}${quoted_file}&quot;</span>;;
</span><span class='line'>        *<span class="o">)</span>  <span class="nv">argument</span><span class="o">=</span><span class="s2">&quot;-file ${tramp_prefix}${quoted_pwd}/${quoted_file}&quot;</span>;;
</span><span class='line'>    <span class="k">esac</span>
</span><span class='line'><span class="k">    </span><span class="nv">args</span><span class="o">=</span><span class="s2">&quot;${args} ${argument}&quot;</span>
</span><span class='line'><span class="k">done</span>
</span><span class='line'>
</span><span class='line'><span class="nb">printf</span> <span class="s2">&quot;%s\n&quot;</span> <span class="s2">&quot;${args}&quot;</span> | nc <span class="nv">$client_host</span> | unquote
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span> (remote-emacsclient.el)</span> <a href='http://blog.habnab.it/downloads/code/remote-emacsclient/remote-emacsclient.el'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
</pre></td><td class='code'><pre><code class='common-lisp'><span class='line'><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;tramp</span><span class="p">)</span>
</span><span class='line'><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;tramp-sh</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="k">setq</span> <span class="nv">server-use-tcp</span> <span class="no">t</span><span class="p">)</span>
</span><span class='line'><span class="p">(</span><span class="nv">server-start</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nb">defun</span> <span class="nv">put-alist</span> <span class="p">(</span><span class="nv">key</span> <span class="nv">value</span> <span class="nv">alist</span><span class="p">)</span>
</span><span class='line'>  <span class="s">&quot;Set cdr of an element (KEY . ...) in ALIST to VALUE and return ALIST.</span>
</span><span class='line'><span class="s">If there is no such element, create a new pair (KEY . VALUE) and</span>
</span><span class='line'><span class="s">return a new alist whose car is the new pair and cdr is ALIST.&quot;</span>
</span><span class='line'>  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">elm</span> <span class="p">(</span><span class="nb">assoc</span> <span class="nv">key</span> <span class="nv">alist</span><span class="p">)))</span>
</span><span class='line'>    <span class="p">(</span><span class="k">if</span> <span class="nv">elm</span>
</span><span class='line'>        <span class="p">(</span><span class="k">progn</span>
</span><span class='line'>          <span class="p">(</span><span class="nv">setcdr</span> <span class="nv">elm</span> <span class="nv">value</span><span class="p">)</span>
</span><span class='line'>          <span class="nv">alist</span><span class="p">)</span>
</span><span class='line'>      <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">key</span> <span class="nv">value</span><span class="p">)</span> <span class="nv">alist</span><span class="p">))))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nb">defun</span> <span class="nv">update-tramp-emacs-server-port-forward</span> <span class="p">(</span><span class="nv">method-name</span><span class="p">)</span>
</span><span class='line'>  <span class="s">&quot;Update the specified TRAMP&#39;s method to forward the Emacs</span>
</span><span class='line'><span class="s"> server port to the local host. This lets emacsclient on the</span>
</span><span class='line'><span class="s"> remote host open files in the local Emacs server.&quot;</span>
</span><span class='line'>  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nc">method</span> <span class="p">(</span><span class="nb">assoc</span> <span class="nv">method-name</span> <span class="nv">tramp-methods</span><span class="p">))</span>
</span><span class='line'>         <span class="p">(</span><span class="nv">ssh-args</span> <span class="p">(</span><span class="nb">cadr</span> <span class="p">(</span><span class="nb">assoc</span> <span class="ss">&#39;tramp-login-args</span> <span class="nc">method</span><span class="p">))))</span>
</span><span class='line'>    <span class="p">(</span><span class="nv">put-alist</span> <span class="ss">&#39;tramp-login-args</span>
</span><span class='line'>      <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nv">put-alist</span> <span class="s">&quot;-R&quot;</span> <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">port</span>
</span><span class='line'>                                   <span class="p">(</span><span class="nv">process-contact</span> <span class="nv">server-process</span> <span class="ss">:service</span><span class="p">)))</span>
</span><span class='line'>        <span class="c1">;; put-alist makes a dotted pair for the key/value, but tramp-methods</span>
</span><span class='line'>        <span class="c1">;; needs a normal list, so put the value inside a list so that the</span>
</span><span class='line'>        <span class="c1">;; second part of the dotted pair (ie the cdr) is a list, which</span>
</span><span class='line'>        <span class="c1">;; converts it from a dotted pair into a normal list.</span>
</span><span class='line'>                              <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s:127.0.0.1:%s&quot;</span> <span class="nv">port</span> <span class="nv">port</span><span class="p">)))</span>
</span><span class='line'>                       <span class="nv">ssh-args</span><span class="p">))</span>
</span><span class='line'>      <span class="nc">method</span><span class="p">)))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nb">defun</span> <span class="nv">tramp-make-tramp-file-name-from-vec</span> <span class="p">(</span><span class="nv">vec</span> <span class="nv">file</span><span class="p">)</span>
</span><span class='line'>  <span class="s">&quot;Convenience function for making a TRAMP path, since this</span>
</span><span class='line'><span class="s">apparently didn&#39;t already exist.&quot;</span>
</span><span class='line'>  <span class="p">(</span><span class="nv">tramp-make-tramp-file-name</span>
</span><span class='line'>    <span class="p">(</span><span class="nv">tramp-file-name-method</span> <span class="nv">vec</span><span class="p">)</span>
</span><span class='line'>    <span class="p">(</span><span class="nv">tramp-file-name-user</span> <span class="nv">vec</span><span class="p">)</span>
</span><span class='line'>    <span class="p">(</span><span class="nv">tramp-file-name-host</span> <span class="nv">vec</span><span class="p">)</span>
</span><span class='line'>    <span class="nv">file</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nv">defcustom</span> <span class="nv">tramp-default-remote-emacsclient-auth-file</span>
</span><span class='line'>  <span class="s">&quot;~/.emacs.d/remote-server&quot;</span>
</span><span class='line'>  <span class="s">&quot;Default remote path at which to save the remote emacsclient</span>
</span><span class='line'><span class="s">authentication file. This can be a string or nil to disable</span>
</span><span class='line'><span class="s">saving an authentication file.</span>
</span><span class='line'>
</span><span class='line'><span class="s">The authentication file is similar to the one written out by the</span>
</span><span class='line'><span class="s">emacsclient TCP server, except it includes the prefix used for</span>
</span><span class='line'><span class="s">the TRAMP connection to the remote server.&quot;</span>
</span><span class='line'>  <span class="ss">:group</span> <span class="ss">&#39;tramp</span>
</span><span class='line'>  <span class="ss">:type</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">choice</span> <span class="p">(</span><span class="nv">const</span> <span class="no">nil</span><span class="p">)</span> <span class="nb">string</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nv">defcustom</span> <span class="nv">tramp-remote-emacsclient-auth-file-alist</span> <span class="no">nil</span>
</span><span class='line'>  <span class="s">&quot;The remote emacsclient authentication file path to use for</span>
</span><span class='line'><span class="s">specific host/user pairs. This is an alist of items (HOST USER</span>
</span><span class='line'><span class="s">PATH). The first matching item specifies the path to use for a</span>
</span><span class='line'><span class="s">connection which does not specify a method. HOST and USER are</span>
</span><span class='line'><span class="s">regular expressions or nil, which is interpreted as a regular</span>
</span><span class='line'><span class="s">expression which always matches. If no entry matches, the</span>
</span><span class='line'><span class="s">variable `tramp-default-remote-emacsclient-auth-file&#39; takes</span>
</span><span class='line'><span class="s">effect.</span>
</span><span class='line'>
</span><span class='line'><span class="s">If the connection does not specify the user, lookup is done using</span>
</span><span class='line'><span class="s">the empty string for the user name.</span>
</span><span class='line'>
</span><span class='line'><span class="s">See `tramp-default-remote-emacsclient-auth-file&#39; for an</span>
</span><span class='line'><span class="s">explanation of the auth file path.&quot;</span>
</span><span class='line'>  <span class="ss">:group</span> <span class="ss">&#39;tramp</span>
</span><span class='line'>  <span class="ss">:type</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">repeat</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nv">choice</span> <span class="ss">:tag</span> <span class="s">&quot;Host regexp&quot;</span> <span class="nv">regexp</span> <span class="p">(</span><span class="nv">const</span> <span class="no">nil</span><span class="p">))</span>
</span><span class='line'>             <span class="p">(</span><span class="nv">choice</span> <span class="ss">:tag</span> <span class="s">&quot;User regexp&quot;</span> <span class="nv">regexp</span> <span class="p">(</span><span class="nv">const</span> <span class="no">nil</span><span class="p">))</span>
</span><span class='line'>             <span class="p">(</span><span class="nv">choice</span> <span class="ss">:tag</span> <span class="s">&quot;emacsclient auth path&quot;</span> <span class="nb">string</span> <span class="p">(</span><span class="nv">const</span> <span class="no">nil</span><span class="p">)))))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nb">defun</span> <span class="nv">tramp-get-remote-emacsclient-auth-file</span> <span class="p">(</span><span class="nv">vec</span><span class="p">)</span>
</span><span class='line'>  <span class="s">&quot;Determine the full TRAMP path for the remote emacsclient</span>
</span><span class='line'><span class="s">authentication file, given a connection vector.&quot;</span>
</span><span class='line'>  <span class="p">(</span><span class="k">let</span>
</span><span class='line'>      <span class="p">((</span><span class="nv">auth-file</span>
</span><span class='line'>        <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">choices</span> <span class="nv">tramp-remote-emacsclient-auth-file-alist</span><span class="p">)</span>
</span><span class='line'>              <span class="p">(</span><span class="nv">host</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">tramp-file-name-host</span> <span class="nv">vec</span><span class="p">)</span> <span class="s">&quot;&quot;</span><span class="p">))</span>
</span><span class='line'>              <span class="p">(</span><span class="nv">user</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">tramp-file-name-user</span> <span class="nv">vec</span><span class="p">)</span> <span class="s">&quot;&quot;</span><span class="p">))</span>
</span><span class='line'>              <span class="nv">lfile</span> <span class="nv">item</span> <span class="nv">matched</span><span class="p">)</span>
</span><span class='line'>          <span class="p">(</span><span class="nv">while</span> <span class="nv">choices</span>
</span><span class='line'>            <span class="p">(</span><span class="k">setq</span> <span class="nv">item</span> <span class="p">(</span><span class="nb">pop</span> <span class="nv">choices</span><span class="p">))</span>
</span><span class='line'>            <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nv">string-match</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">0</span> <span class="nv">item</span><span class="p">)</span> <span class="s">&quot;&quot;</span><span class="p">)</span> <span class="nv">host</span><span class="p">)</span>
</span><span class='line'>                       <span class="p">(</span><span class="nv">string-match</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">1</span> <span class="nv">item</span><span class="p">)</span> <span class="s">&quot;&quot;</span><span class="p">)</span> <span class="nv">user</span><span class="p">))</span>
</span><span class='line'>              <span class="p">(</span><span class="k">setq</span> <span class="nv">lfile</span> <span class="p">(</span><span class="nb">nth</span> <span class="mi">2</span> <span class="nv">item</span><span class="p">)</span>
</span><span class='line'>                    <span class="nv">choices</span> <span class="no">nil</span>
</span><span class='line'>                    <span class="nv">matched</span> <span class="no">t</span><span class="p">)))</span>
</span><span class='line'>          <span class="p">(</span><span class="k">if</span> <span class="nv">matched</span> <span class="nv">lfile</span> <span class="nv">tramp-default-remote-emacsclient-auth-file</span><span class="p">))))</span>
</span><span class='line'>    <span class="p">(</span><span class="k">if</span> <span class="nv">auth-file</span>
</span><span class='line'>        <span class="p">(</span><span class="nv">tramp-make-tramp-file-name-from-vec</span> <span class="nv">vec</span> <span class="nv">auth-file</span><span class="p">))))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nb">defun</span> <span class="nv">tramp-save-remote-emacsclient-auth-file</span> <span class="p">(</span><span class="k">&amp;optional</span> <span class="nv">vec</span><span class="p">)</span>
</span><span class='line'>  <span class="s">&quot;Write the remote emacsclient authentication file for a given</span>
</span><span class='line'><span class="s">connection buffer, or, if used interactively, for the TRAMP</span>
</span><span class='line'><span class="s">connection of the current buffer.&quot;</span>
</span><span class='line'>  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
</span><span class='line'>  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">vec</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">vec</span> <span class="p">(</span><span class="nv">tramp-dissect-file-name</span> <span class="nv">default-directory</span><span class="p">))))</span>
</span><span class='line'>    <span class="p">(</span><span class="nv">condition-case</span> <span class="nv">err</span>
</span><span class='line'>        <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">auth-file</span> <span class="p">(</span><span class="nv">tramp-get-remote-emacsclient-auth-file</span> <span class="nv">vec</span><span class="p">))</span>
</span><span class='line'>              <span class="p">(</span><span class="nv">server</span> <span class="p">(</span><span class="nv">process-contact</span> <span class="nv">server-process</span> <span class="ss">:local</span><span class="p">)))</span>
</span><span class='line'>          <span class="p">(</span><span class="k">if</span> <span class="nv">auth-file</span>
</span><span class='line'>              <span class="p">(</span><span class="nv">with-temp-file</span> <span class="nv">auth-file</span>
</span><span class='line'>                <span class="p">(</span><span class="nv">insert</span>
</span><span class='line'>                 <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;127.0.0.1 %d\n&quot;</span> <span class="p">(</span><span class="nb">elt</span> <span class="nv">server</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">server</span><span class="p">)</span> <span class="mi">1</span><span class="p">)))</span>
</span><span class='line'>                 <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;-auth %s\n&quot;</span> <span class="p">(</span><span class="nv">process-get</span> <span class="nv">server-process</span> <span class="ss">:auth-key</span><span class="p">))</span>
</span><span class='line'>                 <span class="p">(</span><span class="nv">server-quote-arg</span> <span class="p">(</span><span class="nv">tramp-make-tramp-file-name-from-vec</span> <span class="nv">vec</span> <span class="s">&quot;&quot;</span><span class="p">))</span>
</span><span class='line'>                 <span class="s">&quot;\n&quot;</span><span class="p">))</span>
</span><span class='line'>            <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">called-interactively-p</span> <span class="ss">&#39;any</span><span class="p">)</span>
</span><span class='line'>              <span class="p">(</span><span class="nv">message</span> <span class="s">&quot;No remote emacsclient auth file for %s&quot;</span>
</span><span class='line'>                       <span class="nv">default-directory</span><span class="p">))))</span>
</span><span class='line'>      <span class="p">(</span><span class="kt">file-error</span> <span class="p">(</span><span class="nv">message</span> <span class="s">&quot;error saving remote emacsclient auth: %s&quot;</span> <span class="nv">err</span><span class="p">)))))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nv">defadvice</span> <span class="nv">tramp-open-connection-setup-interactive-shell</span>
</span><span class='line'>  <span class="p">(</span><span class="nv">after</span> <span class="nv">copy-server-file-by-tramp</span> <span class="p">(</span><span class="nv">proc</span> <span class="nv">vec</span><span class="p">)</span> <span class="nv">activate</span><span class="p">)</span>
</span><span class='line'>  <span class="s">&quot;Automatically write out a remote emacsclient auth file after a</span>
</span><span class='line'><span class="s">successful connection.&quot;</span>
</span><span class='line'>  <span class="p">(</span><span class="nv">tramp-save-remote-emacsclient-auth-file</span> <span class="nv">vec</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="p">(</span><span class="nb">provide</span> <span class="ss">&#39;remote-emacsclient</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The most up-to-date versions of each will be in <a href="https://github.com/habnabit/dotfiles">my dotfiles repository</a>. For
convenience, here are links to the files within the repository:
<a href="https://github.com/habnabit/dotfiles/blob/master/emacsclient.sh">emacsclient.sh</a> and <a href="https://github.com/habnabit/dotfiles/blob/master/emacs.d/remote-emacsclient.el">remote-emacsclient.el</a>.</p>

<p>Configuration is pretty straightforward. In my local <code>.emacs</code> file,
<code>(server-start)</code> got changed to:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='common-lisp'><span class='line'><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;remote-emacsclient</span><span class="p">)</span>
</span><span class='line'><span class="p">(</span><span class="nv">update-tramp-emacs-server-port-forward</span> <span class="nv">tramp-default-method</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>update-tramp-emacs-server-port-forward</code> function takes a <a href="http://www.gnu.org/software/emacs/manual/html_node/tramp/External-methods.html">TRAMP method</a>
and updates the ssh arguments to that method to include a <code>-R</code> flag forwarding
remote TCP connections to the local server. It&rsquo;s probably not necessary to call
it for any TRAMP method other than your default.</p>

<p>By default <em>every</em> new server connection will leave an authentication file.
This can be tuned with the <code>tramp-default-remote-emacsclient-auth-file</code> and
<code>tramp-remote-emacsclient-auth-file-alist</code> variables. The former can be set to
<code>nil</code> to disable auth file creation by default. The latter is in the same form
as the <code>tramp-default-method-alist</code> variable for specifying the location of the
auth file by host and/or by user.</p>

<p>And in my <code>.zshrc</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>: <span class="k">${</span><span class="nv">remote_emacs_auth</span><span class="p">:=</span><span class="s2">&quot;$HOME/.emacs.d/remote-server&quot;</span><span class="k">}</span>; <span class="nb">export </span>remote_emacs_auth
</span><span class='line'><span class="nb">export </span><span class="nv">EDITOR</span><span class="o">=</span><span class="s2">&quot;$HOME/.dotfiles/emacsclient.sh&quot;</span>
</span><span class='line'><span class="nb">alias </span><span class="nv">emacs</span><span class="o">=</span><span class="s2">&quot;$HOME/.dotfiles/emacsclient.sh -n&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>$remote_emacs_auth</code>&rsquo;s default mirrors <code>remote-emacsclient.el</code>&rsquo;s default of
writing the auth file to <code>~/.emacs.d/remote-server</code>. Since <code>emacsclient.sh</code> is
(for me, by default) checked out in <code>~/.dotfiles</code> and set executable, this is
all that&rsquo;s required to use it as an editor. As an added bonus, the <code>emacs</code>
alias lets me type <code>emacs somefile</code> over ssh to open <code>somefile</code> in my local
emacs.</p>

<p>There&rsquo;s only two caveats (that I&rsquo;m aware of (I&rsquo;ve only tried the <code>scp</code>, <code>ssh</code>,
and <code>scpc</code> tramp methods with this so far)):</p>

<ol>
<li><p>Since the authentication key changes every time emacs is started, you <em>must</em>
open a new tramp connection to a server before emacsclient will be able to
speak to your local emacs. I haven&rsquo;t found a good solution to this other
than forcing the authentication key to always be the same (bad) or making
emacs reconnect to everything whenever you start it (worse).</p></li>
<li><p>There&rsquo;s no detection of when the server is restarted. Restarting the server
in a running emacs <em>also</em> changes the authentication key. Making a new tramp
connection isn&rsquo;t required in this case; there&rsquo;s a
<code>tramp-save-remote-emacsclient-auth-file</code> function that can be run
interactively. Running it will write a new auth file for the connection
corresponding to the current buffer.</p></li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[AMP and StartTLS]]></title>
    <link href="http://blog.habnab.it/blog/2012/05/28/amp-and-starttls/"/>
    <updated>2012-05-28T22:46:00-04:00</updated>
    <id>http://blog.habnab.it/blog/2012/05/28/amp-and-starttls</id>
    <content type="html"><![CDATA[<p>Recently, I&rsquo;ve been hacking on a thing which has been using <a href="http://twistedmatrix.com/">Twisted</a>&rsquo;s <a href="http://twistedmatrix.com/documents/current/api/twisted.protocols.amp.html">AMP</a>
for making remote calls. I&rsquo;ve developed a bit of a fetish for SSL client
certificates, so I was hoping to use that for authenticating clients. AMP does
have <a href="http://twistedmatrix.com/documents/current/api/twisted.protocols.amp.StartTLS.html">STARTTLS</a> support builtin, but I couldn&rsquo;t find any examples! Here&rsquo;s what
I found and figured out, for future hackers:</p>

<!-- more -->


<h2>Always initiate from the client</h2>

<p>Until <a href="http://tm.tl/5690">a bug in Twisted</a> is resolved, only the client will be able to
successfully initiate the StartTLS. Here&rsquo;s a full runnable example.</p>

<figure class='code'><figcaption><span> (basic.py)</span> <a href='http://blog.habnab.it/downloads/code/amp-starttls/basic.py'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='py'><span class='line'><span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">protocol</span><span class="p">,</span> <span class="n">reactor</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">twisted.protocols</span> <span class="kn">import</span> <span class="n">amp</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">twisted.python</span> <span class="kn">import</span> <span class="n">log</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">sys</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">SupCommand</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">Command</span><span class="p">):</span>
</span><span class='line'>    <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ServerProtocol</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">AMP</span><span class="p">):</span>
</span><span class='line'>    <span class="nd">@SupCommand.responder</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">sup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>        <span class="n">log</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&#39;got sup&#39;</span><span class="p">)</span>
</span><span class='line'>        <span class="k">return</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ServerFactory</span><span class="p">(</span><span class="n">protocol</span><span class="o">.</span><span class="n">ServerFactory</span><span class="p">):</span>
</span><span class='line'>    <span class="n">protocol</span> <span class="o">=</span> <span class="n">ServerProtocol</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ClientProtocol</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">AMP</span><span class="p">):</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">connectionMade</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>        <span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">callRemote</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">StartTLS</span><span class="p">)</span>
</span><span class='line'>        <span class="n">d</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="k">lambda</span> <span class="n">ign</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">callRemote</span><span class="p">(</span><span class="n">SupCommand</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ClientFactory</span><span class="p">(</span><span class="n">protocol</span><span class="o">.</span><span class="n">ClientFactory</span><span class="p">):</span>
</span><span class='line'>    <span class="n">protocol</span> <span class="o">=</span> <span class="n">ClientProtocol</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;client&#39;</span><span class="p">:</span>
</span><span class='line'>    <span class="n">reactor</span><span class="o">.</span><span class="n">connectTCP</span><span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">9991</span><span class="p">,</span> <span class="n">ClientFactory</span><span class="p">())</span>
</span><span class='line'><span class="k">elif</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;server&#39;</span><span class="p">:</span>
</span><span class='line'>    <span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">9991</span><span class="p">,</span> <span class="n">ServerFactory</span><span class="p">())</span>
</span><span class='line'>
</span><span class='line'><span class="n">log</span><span class="o">.</span><span class="n">startLogging</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">)</span>
</span><span class='line'><span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Using client certificates isn&rsquo;t hard</h2>

<p>Specifying which certificate to use for both peers requires only minor
modifications. Here&rsquo;s another runnable example, assuming you have an <code>ssl.pem</code>
file.</p>

<figure class='code'><figcaption><span> (client-cert.py)</span> <a href='http://blog.habnab.it/downloads/code/amp-starttls/client-cert.py'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
</pre></td><td class='code'><pre><code class='py'><span class='line'><span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">protocol</span><span class="p">,</span> <span class="n">reactor</span><span class="p">,</span> <span class="n">ssl</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">twisted.protocols</span> <span class="kn">import</span> <span class="n">amp</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">twisted.python</span> <span class="kn">import</span> <span class="n">log</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">sys</span>
</span><span class='line'>
</span><span class='line'><span class="n">cert</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">PrivateCertificate</span><span class="o">.</span><span class="n">loadPEM</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">&#39;ssl.pem&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span><span class='line'><span class="n">certParams</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;tls_localCertificate&#39;</span><span class="p">:</span> <span class="n">cert</span><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">SupCommand</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">Command</span><span class="p">):</span>
</span><span class='line'>    <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ServerProtocol</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">AMP</span><span class="p">):</span>
</span><span class='line'>    <span class="nd">@SupCommand.responder</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">sup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>        <span class="n">log</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&#39;got sup&#39;</span><span class="p">)</span>
</span><span class='line'>        <span class="k">return</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'>    <span class="nd">@amp.StartTLS.responder</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">startTLS</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>        <span class="k">return</span> <span class="n">certParams</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ServerFactory</span><span class="p">(</span><span class="n">protocol</span><span class="o">.</span><span class="n">ServerFactory</span><span class="p">):</span>
</span><span class='line'>    <span class="n">protocol</span> <span class="o">=</span> <span class="n">ServerProtocol</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ClientProtocol</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">AMP</span><span class="p">):</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">connectionMade</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>        <span class="n">d</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">callRemote</span><span class="p">(</span><span class="n">amp</span><span class="o">.</span><span class="n">StartTLS</span><span class="p">,</span> <span class="o">**</span><span class="n">certParams</span><span class="p">)</span>
</span><span class='line'>        <span class="n">d</span><span class="o">.</span><span class="n">addCallback</span><span class="p">(</span><span class="k">lambda</span> <span class="n">ign</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">callRemote</span><span class="p">(</span><span class="n">SupCommand</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ClientFactory</span><span class="p">(</span><span class="n">protocol</span><span class="o">.</span><span class="n">ClientFactory</span><span class="p">):</span>
</span><span class='line'>    <span class="n">protocol</span> <span class="o">=</span> <span class="n">ClientProtocol</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;client&#39;</span><span class="p">:</span>
</span><span class='line'>    <span class="n">reactor</span><span class="o">.</span><span class="n">connectTCP</span><span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mi">9991</span><span class="p">,</span> <span class="n">ClientFactory</span><span class="p">())</span>
</span><span class='line'><span class="k">elif</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;server&#39;</span><span class="p">:</span>
</span><span class='line'>    <span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">9991</span><span class="p">,</span> <span class="n">ServerFactory</span><span class="p">())</span>
</span><span class='line'>
</span><span class='line'><span class="n">log</span><span class="o">.</span><span class="n">startLogging</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">)</span>
</span><span class='line'><span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>ssl.pem</code> must include both the certificate and the key. Though the example
doesn&rsquo;t demonstrate it, certificate authorities to use can also be specified
using the <code>tls_verifyAuthorities</code> parameter (see the API docs for <a href="http://twistedmatrix.com/documents/current/api/twisted.protocols.amp.StartTLS.html">StartTLS</a>).</p>
]]></content>
  </entry>
  
</feed>
