<?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>Gregory Grubbs &#187; tramp</title>
	<atom:link href="http://gregorygrubbs.com/tag/tramp/feed/" rel="self" type="application/rss+xml" />
	<link>http://gregorygrubbs.com</link>
	<description>Attention in software development</description>
	<lastBuildDate>Mon, 12 Jul 2010 17:35:34 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Emacs Power: remote servers and shell commands</title>
		<link>http://gregorygrubbs.com/wordpress/emacs-power-remote-servers-and-shell-commands/</link>
		<comments>http://gregorygrubbs.com/wordpress/emacs-power-remote-servers-and-shell-commands/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 17:26:40 +0000</pubDate>
		<dc:creator>Gregory Grubbs</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[geekhood]]></category>
		<category><![CDATA[power]]></category>
		<category><![CDATA[remote server]]></category>
		<category><![CDATA[secure shell]]></category>
		<category><![CDATA[tramp]]></category>

		<guid isPermaLink="false">http://gregorygrubbs.com/?p=372</guid>
		<description><![CDATA[
Emacs file and directory browsing 
Emacs has Dired, a great method for browsing directories; especially in combination with ido-mode, I prefer it to Windows Explorer, OS X Finder, Gnome Nautilus, or anything else I&#8217;ve used over the decades to browse file systems. You can quickly begin entering paths, and Dired helps you with directory and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://flickr.com/photos/16230215@N08/2898797929" title="Come Together"><img src="http://farm4.static.flickr.com/3282/2898797929_f209eeb4a4.jpg" /></a></p>
<h4 id="sec-1">Emacs file and directory browsing </h4>
<p>Emacs has Dired, a great method for browsing directories; especially in combination with ido-mode, I prefer it to Windows Explorer, OS X Finder, Gnome Nautilus, or anything else I&#8217;ve used over the decades to browse file systems. You can quickly begin entering paths, and Dired helps you with directory and file name completion.<br />
<span id="more-372"></span></p>
<p>  As you browse directories, emacs lets you bookmark any path you may visit again. A very cool feature of emacs is the wide variety of shell-based modes: shell, term, interactive SQL, version control, recursive grep, and more.  When you are looking at a Dired buffer and invoke any of those commands, the shell is started in the directory you are looking at.</p>
<h4 id="sec-2">TRAMP: powerful remote file server access </h4>
<p>An emacs user will eventually discover that Dired becomes even more powerful with the built-in power of TRAMP (Transparent Remote (file) Access, Multiple Protocol).  This extends directory path syntax to include FTP, SSH, Rsync and other protocols for accessing remote files.</p>
<p>  An example of accessing a remote file on my development server <code>smeagol</code> from my laptop:</p>
<pre class="example">/ssh:gregj@smeagol:work/client1/web/index.php
</pre>
<p>  A directory on an FTP server is accessed the same way:</p>
<pre class="example">/ftp:ftpuser@ftp.example.com:
</pre>
<p>  Even sudo is considered a &#8216;protocol&#8217;; so to gain root access without leaving the comfort of your emacs session, use</p>
<pre class="example">/sudo::/etc/hosts
</pre>
<p>  Emacs even helps you browse remote servers, providing the same name completion you get on your local directories.</p>
<h4 id="sec-1">The amazing combo of TRAMP and shell commands</h4>
<p>  As wonderful as all this is, we are still in the realm of &#8220;mere&#8221; GUI editors that can browse remote servers. But we are dealing with emacs, the superset of all editors, so we expect even more.</p>
<p>  Imagine we are looking at a directory on a remote server at <code>/ssh:myuser@remote.com:web/public_html</code>, and decide to type</p>
<pre class="example">M-x shell
</pre>
<p>  What happens? Why, emacs looks at our current directory, sees that it is a TRAMP remote path, and just does the Right Thing&trade;: in this case, invokes ssh, sets the directory on the remote server to ~myuser/web/public_html, and sets us at the shell prompt.</p>
<p>  Similarly, if we invoke version control (<code>vc-dir</code>, for example), or recursive grep (<code>rgrep</code>), or most other shell-based commands, emacs will open a secure shell first, then run the vc command (<code>svn</code>, <code>git</code>, etc) or <code>grep</code> <b>on the remote server!!</b> So for example, if I innocently invoke <code>rgrep</code> at the root of a remote WordPress installation, the grep command looks through all the files from the remote server. If on the other hand I were accessing the server using something like <a href="http://fuse.sourceforge.net/sshfs.html">SSHFS</a>, all those files would be transferred to my local machine first and then searched!</p>
<h4 id="sec-3">Some examples </h4>
<p>  I&#8217;ll save my favorite uses of this magic called Dired with TRAMP for last.  I often need to access a development system or a live WordPress installation remotely. To access the SQL client, I found I often had to browse for the WordPress config file, open it, search for the database access info, open a SQL session using <code>M-x sql-mysql</code> and fill in all the prompts to authenticate to the MySQL server.  It&#8217;s great that emacs with TRAMP starts a shell on the remote machine, and initiates the mysql client on that machine.  But emacs allows you to do damn near anything you can imagine, so I realized I could write a function that does the following:</p>
<ol>
<li>
	Looks for wp-config.php in the current directory
  </li>
<li>
	If not found, moves up a directory until it either finds the file or reaches the root of the filesystem
  </li>
<li>
	If found, opens the config file and parses the database authentication parameters
  </li>
<li>
	Feeds those parameters to the sql-mysql function and
  </li>
<li>
	plops me into the MySQL prompt all logged in and ready to go!</p>
</li>
</ol>
<p>Another example: my iPod Touch has an SSH server running on it (don&#8217;t ask me how it got there). I have discovered that many apps use SQLite to store their data.  I have been losing weight lately, and have been using the excellent <a href="http://www.loseit.com/">Lose It!</a> app to track my meals and exercise.  The app gives me nice weekly summaries of my caloric intake, but does not give a weekly summary of my aerobic exercise.  Here&#8217;s how I get that information now:</p>
<ol>
<li>
	I have a nice bookmark to the Lose It! application directory at<br />
	<code>/scpc:mobile@172.16.17.118:/var/mobile/Applications/C6503545-700B-4395-9C8B-FE5B75CF6CD8/</code>,<br />
	so I hit the Return key on that bookmark and wait for Dired to show me the files there.
  </li>
<li>
	Browse to the Documents directory, wherein is stored the database for my personal history
  </li>
<li>
	Invoke <code>M-x sql-sqlite</code> and enter the database file <code>UserDatabaseV1.sql</code> (using dabbrev as a shortcut)
  </li>
<li>
	Wait for the SQLite prompt to appear, and run a lovely little SQL query using a YASnippets shortcut: </p>
</li>
</ol>
<pre class="src src-sql"><span style="color: #a020f0;">SELECT</span> <span style="color: #228b22;">date</span>(<span style="color: #0000ff;">'2001-01-01'</span>, <span style="color: #0000ff;">'+'</span> || <span style="color: #228b22;">Date</span> || <span style="color: #0000ff;">' day'</span>, <span style="color: #0000ff;">'-1 day'</span>, <span style="color: #0000ff;">'weekday 1'</span>, <span style="color: #0000ff;">'-7 day'</span>) <span style="color: #a020f0;">AS</span> Weekdate, strftime(<span style="color: #0000ff;">'%W'</span>,<span style="color: #228b22;">date</span>(<span style="color: #0000ff;">'2001-01-01'</span>, <span style="color: #0000ff;">'+'</span> || <span style="color: #228b22;">Date</span> || <span style="color: #0000ff;">' day'</span>, <span style="color: #0000ff;">'-1 day'</span>)) <span style="color: #a020f0;">AS</span> Week,   ExerciseName, ExerciseCategoryId, <span style="color: #da70d6;">SUM</span>(Minutes), <span style="color: #da70d6;">SUM</span>(CaloriesBurned)   <span style="color: #a020f0;">FROM</span> ExerciseLogEntries  <span style="color: #a020f0;">GROUP</span> <span style="color: #a020f0;">BY</span> Week;
</pre>
<h4 id="sec-4">Summary </h4>
<p>I hope that this post gives an idea of the power of TRAMP on emacs.  It should at least explain the occasional ecstatic post you may see from your geekier tweeps.</p>
<p>As a bonus, here&#8217;s what the above examples look like in use: it&#8217;s unbelievable how fast emacs makes you after a quick 15 years of study.</p>
<p><object width="640" height="505"><param name="movie" value="http://www.youtube.com/v/UjPasLGWzD0&#038;hl=en&#038;fs=1&#038;color1=0x5d1719&#038;color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/UjPasLGWzD0&#038;hl=en&#038;fs=1&#038;color1=0x5d1719&#038;color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"></embed></object></p>
<p>  And here&#8217;s my emacs lisp code that opens up a SQL prompt for any WordPress installation.  To use, eval the code and invoke <code>M-x gjg/sql-mysql-wordpress</code></p>
<pre class="src src-emacs-lisp">(<span style="color: #a020f0;">defun</span> <span style="color: #0000ff;">gjg/parse-wp-config-db</span> (wpconfig-path)
  <span style="color: #0000ff;">"Read in and parse the DB settings from a WordPress config file; binds 'global' vars for use by sql-mode"</span>
  (<span style="color: #a020f0;">save-excursion</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">will restore current buffer and default dir afterwards
  </span>    (set-buffer (get-buffer-create (generate-new-buffer-name <span style="color: #0000ff;">" wp-config.php"</span>)))
  (insert-file-contents wpconfig-path)
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">in regex: subexpr 1 is variable name, subexpr 3 is value: DB_{HOST,NAME,PASSWORD,USER}
  </span>    (<span style="color: #a020f0;">while</span> (search-forward-regexp <span style="color: #0000ff;">"define\s*(\s*['\"]</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">(</span><span style="color: #0000ff;">DB_</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">(</span><span style="color: #0000ff;">HOST</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">|</span><span style="color: #0000ff;">NAME</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">|</span><span style="color: #0000ff;">PASSWORD</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">|</span><span style="color: #0000ff;">USER</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">)</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">)</span><span style="color: #0000ff;">['\"]\s*,\s*['\"]</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">(</span><span style="color: #0000ff;">[</span><span style="color: #0000ff;">^</span><span style="color: #0000ff;">'\"]*</span><span style="color: #0000ff; font-weight: bold;">\\</span><span style="color: #0000ff; font-weight: bold;">)</span><span style="color: #0000ff;">['\"]\s*)"</span> (point-max) 42   )
  (<span style="color: #a020f0;">cond</span>
  ((equal <span style="color: #0000ff;">"DB_HOST"</span> (match-string-no-properties 1))
  (setq sql-server (match-string-no-properties 3)))
  ((equal <span style="color: #0000ff;">"DB_NAME"</span> (match-string-no-properties 1))
  (setq sql-database (match-string-no-properties 3)))
  ((equal <span style="color: #0000ff;">"DB_PASSWORD"</span> (match-string-no-properties 1))
  (setq sql-password (match-string-no-properties 3)))
  ((equal <span style="color: #0000ff;">"DB_USER"</span> (match-string-no-properties 1))
  (setq sql-user (match-string-no-properties 3)))))
  (kill-buffer )))

  (<span style="color: #a020f0;">defun</span> <span style="color: #0000ff;">gjg/sql-mysql-wordpress</span> ()
  <span style="color: #0000ff;">"Find WordPress config file in current tree, log into WP database if found."</span>
  (interactive)
  (<span style="color: #a020f0;">let</span> ((mypath (locate-dominating-file default-directory <span style="color: #0000ff;">"wp-config.php"</span>)))
  (<span style="color: #a020f0;">if</span> mypath
  (<span style="color: #a020f0;">progn</span>
  (gjg/parse-wp-config-db (concat mypath <span style="color: #0000ff;">"wp-config.php"</span>))
  (pop-to-buffer (sql-connect-mysql))
  (setq sql-interactive-product 'mysql)
  (setq sql-buffer (current-buffer))
  (sql-interactive-mode)
  (<span style="color: #a020f0;">let*</span> ((match (string-match (nth 0 tramp-file-name-structure) mypath))
  (myformat (<span style="color: #a020f0;">if</span> (eq nil match)
  (format <span style="color: #0000ff;">" WordPress: local; %s; dbhost %s "</span>
  mypath
  sql-server
  )
  (format <span style="color: #0000ff;">" WordPress: Remote %s@%s %s; dbhost %s "</span>
  (match-string (nth 2 tramp-file-name-structure) mypath)
  (match-string (nth 3 tramp-file-name-structure) mypath)
  (match-string (nth 4 tramp-file-name-structure) mypath)
  sql-server))))
  (setq header-line-format myformat))
  )
  (message <span style="color: #0000ff;">"Did not find wp-config.php in current path"</span>))
  ))
</pre>
<p> LocalWords:  Dired emacs SQL Rsync smeagol pre rgrep WordPress MySQL iPod<br />
 LocalWords:  SQLite</p>
]]></content:encoded>
			<wfw:commentRss>http://gregorygrubbs.com/wordpress/emacs-power-remote-servers-and-shell-commands/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
