<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Atomized &#187; directory-local-variables</title>
	<atom:link href="http://atomized.org/tag/directory-local-variables/feed/" rel="self" type="application/rss+xml" />
	<link>http://atomized.org</link>
	<description>Fragmenting reality.</description>
	<lastBuildDate>Mon, 23 May 2011 23:46:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Emacs 23: Easier directory-local variables</title>
		<link>http://atomized.org/2009/05/emacs-23-easier-directory-local-variables/</link>
		<comments>http://atomized.org/2009/05/emacs-23-easier-directory-local-variables/#comments</comments>
		<pubDate>Wed, 06 May 2009 00:12:48 +0000</pubDate>
		<dc:creator>Ian</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[directory-local-variables]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://atomized.org/?p=554</guid>
		<description><![CDATA[I’ve been using directory-local-variables for a while now, and written about them before I currently have two problems with DLV: It takes a lot of code to set anything. Here’s a very simple example that makes all files opened under a subdirectory read-only: (dir-locals-set-class-variables 'read-only '((nil . ((buffer-read-only t))))) (dir-locals-set-directory-class "~/Library/Preferences" 'read-only nil) Many of [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been using directory-local-variables for a while now, and <a href="http://atomized.org/2009/01/emacs-23-directory-local-variables/">written about them before</a></p>
<p>I currently have two problems with DLV:</p>
<ol>
<li>It takes a lot of code to set anything. Here’s a very simple example that makes all files opened under a subdirectory read-only:
<pre language="emacs-lisp">
(dir-locals-set-class-variables 'read-only
                                '((nil . ((buffer-read-only t)))))
(dir-locals-set-directory-class "~/Library/Preferences" 'read-only nil)
    </pre>
</li>
<li>Many of my variables need to be set to paths of files within the base directory. As an example, <code>phpunit-program</code> needs to be <code>$ROOT/bin/phpunit</code>. This doesn’t map well onto the class/directory split of DLV; I have to define a class for every directory, since the values are dependent on the path. You also end up duplicating a lot of long paths inside the directory-class.</li>
</ol>
<p>Here’s my current solution, <code>dir-locals</code>.</p>
<pre language="emacs-lisp">
(defmacro absolute-dirname (path)
  "Return the directory name portion of a path.

If PATH is local, return it unaltered.
If PATH is remote, return the remote diretory portion of the path."
  `(cond ((tramp-tramp-file-p ,path)
          (elt (tramp-dissect-file-name ,path) 3))
         (t ,path)))

(defmacro dir-locals (dir vars)
       "Set local variables for a directory.

DIR is the base diretory to set variables on.

VARS is an alist of variables to set on files opened under DIR,
in the same format as `dir-locals-set-class-variables' expects."
       `(let ((name (intern (concat "dir-locals-"
                                    ,(md5 (expand-file-name dir)))))
              (base-dir ,dir)
              (base-abs-dir ,(absolute-dirname dir)))
          (dir-locals-set-class-variables name ,vars)
          (dir-locals-set-directory-class ,dir name nil)))
</pre>
<p>It takes two arguments, a directory and a list of variables. The directory-class is autogenerated, so you don’t need to worry about it. Here’s how you’d use it:</p>
<pre language="emacs-lisp">
(dir-locals "~/Projects/hello-world"
            '((nil . ((user-mail-address . "ian@foo.com")))))
</pre>
<p><em>Much</em> better.</p>
<p>Within your varible list, you have two special variables you can use: <code>base-dir</code> and <code>base-abs-dir</code>. These contain the root of the directory the variables apply to, and the local directory part of that, respectively.</p>
<p>We need this because of the way Emacs invokes processes. If you’re visiting a remote file, Emacs will spawn external processes on the remote system. To set a DLV for a remote file, the root needs to be in the form <code>/ssh:user@host:/path/to/root</code>. If you try to invoke a program like that, it won’t work; you need just the directory part of the path, and this is what’s available in <code>base-abs-dir</code>.</p>
<p>On the other hand, if you want per-project TAGS files, you’ll need the full path to the remote system.</p>
<p> Here’s how you’d use it:</p>
<pre langauge="emacs-lisp">
(dir-locals "~/Projects/hello-world"
            `((nil . ((user-mail-address . "ian@foo.com")
                      (tags-table-list . '(,(concat base-dir "/TAGS.gz")))))
              (php-mode . ((phpunit-program . ,(concat base-abs-dir
                                                       "/bin/phpunit"))))))
</pre>
<p>The important thing to note here is the different syntax used for the variables. Rather than using a regular quote, we use a backquote, and a comma where the special variables are used.</p>
<p>And that’s that. Now I have one-(or two-)line setting of variables, with access to the base directory.</p>
]]></content:encoded>
			<wfw:commentRss>http://atomized.org/2009/05/emacs-23-easier-directory-local-variables/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

