<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>chrispoole.com</title>
  <link href="http://chrispoole.com/atom.xml" rel="self"/>
  <link href="http://chrispoole.com"/>
  <updated>2012-01-12T14:01:10+00:00</updated>
  <id>http://chrispoole.com</id>
  <author>
    <name>Chris Poole</name>
  </author>
  
    <entry>
      <title>Quick Man Page Lookup</title>
      <link href="http://chrispoole.com/article/quick-man-page-lookup"/>
      <updated>2011-10-24T00:00:00+01:00</updated>
      <id>http://chrispoole.com/article/quick-man-page-lookup</id>
      <content type="html">&lt;p&gt;I often find myself wanting to look up an option in a unix &lt;code&gt;man&lt;/code&gt; page. This is a
little function I wrote to save myself some typing. It’ll also successfully find
text that’s written in bold font in the manual, which simple grepping will not
do.&lt;/p&gt;

&lt;p&gt;Put it in your &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt; file. I’ve tested it with &lt;code&gt;zsh&lt;/code&gt; on Mac OS X
Snow Leopard.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;gman &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
    man -- &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; | col -bx | &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;        &lt;/span&gt;grep -Em2 -- &lt;span class=&quot;s2&quot;&gt;&amp;quot;^ +$1&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;        if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; -lt 0 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;            &lt;/span&gt;grep -C&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;#-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; -- &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;            &lt;/span&gt;grep -A&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; -- &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt; | more
    &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Invoke it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gman (program name) [search term] [[-]num]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;example-usage&quot;&gt;Example usage&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;gman grep&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Prints rough usage of the command &lt;code&gt;grep&lt;/code&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;pre&gt;&lt;code&gt;grep, egrep, fgrep - print lines matching a pattern
grep [options] PATTERN [FILE...]
&lt;/code&gt;&lt;/pre&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;gman grep -o&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Prints lines matching &lt;code&gt;-o&lt;/code&gt; in &lt;code&gt;grep&lt;/code&gt;’s man page, usually explaining how to use
it&lt;/dd&gt;
  &lt;dd&gt;There’s no need to add &lt;code&gt;--&lt;/code&gt; before the search term&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;gman grep -o 3&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Same as above, showing the next 3 lines after each matching line&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;gman grep -o -3&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Show 3 lines around each matching line&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;gman bash '!!' -20&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Quickly check the &lt;em&gt;event designators&lt;/em&gt; section of the bash manual&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;The output is passed to &lt;code&gt;more&lt;/code&gt;, the pager program, so longer results won’t
simply disappear off your screen.&lt;/p&gt;
</content>
    </entry>
  
    <entry>
      <title>Send reddit Saved Links to Pinboard</title>
      <link href="http://chrispoole.com/project/reddit-pinboard"/>
      <updated>2011-08-01T00:00:00+01:00</updated>
      <id>http://chrispoole.com/project/reddit-pinboard</id>
      <content type="html">&lt;p&gt;This is a simple python&lt;sup id=&quot;fnref:py-installed&quot;&gt;&lt;a href=&quot;#fn:py-installed&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; script to send saved links from &lt;a href=&quot;http://reddit.com&quot;&gt;reddit&lt;/a&gt;
to &lt;a href=&quot;http://pinboard.in&quot;&gt;Pinboard&lt;/a&gt;. They get added to your &lt;em&gt;unread&lt;/em&gt; pile. It may be useful if reddit
ever goes down.&lt;/p&gt;

&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;/h3&gt;

&lt;p&gt;Download &lt;a href=&quot;/downloads/reddit_save_to_pinboard&quot;&gt;the script&lt;/a&gt; here.&lt;/p&gt;

&lt;p&gt;Go to your &lt;a href=&quot;http://www.reddit.com/prefs/&quot;&gt;reddit preferences&lt;/a&gt;, and under &lt;em&gt;content options&lt;/em&gt;, tick
&lt;em&gt;enable private RSS feeds&lt;/em&gt;. Then visit your &lt;a href=&quot;http://www.reddit.com/prefs/feeds/&quot;&gt;private RSS feeds page&lt;/a&gt; and
grab the link for the RSS feed for &lt;em&gt;your saved links&lt;/em&gt;&lt;sup id=&quot;fnref:other-links&quot;&gt;&lt;a href=&quot;#fn:other-links&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Use the RSS feed link when calling the script from the shell:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;reddit_save_to_pinboard &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;-t&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;saved links feed url&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;pinboard username&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                             &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;pinboard password&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If no password is given, it’ll ask you for it. For example, here’s what I type
in:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;reddit_save_to_pinboard &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://www.reddit.com/saved.rss?feed=deadbeef18284e0c2c421&amp;amp;user=chrispoole&amp;quot;&lt;/span&gt; chrispoole mypinboardpassword
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;further-information&quot;&gt;Further information&lt;/h3&gt;

&lt;p&gt;Each link is given two tags: &lt;code&gt;reddit&lt;/code&gt;, and that link’s subreddit name.&lt;/p&gt;

&lt;p&gt;By default, the Pinboard link is the submitted URL, with a link to the reddit
comments page as the Pinboard comment.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/pinboard.png&quot; alt=&quot;Screenshot of the output in pinboard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you like to use the reddit toolbar, use the &lt;code&gt;-t&lt;/code&gt; option, which sets the
toolbar link as the main Pinboard link, and adds the submitted URL in the
comments. If you want to retain the usual behaviour of this script but still use
the reddit toolbar for regular browsing, just don’t add the &lt;code&gt;-t&lt;/code&gt; option.&lt;/p&gt;

&lt;h3 id=&quot;dependencies&quot;&gt;Dependencies&lt;/h3&gt;

&lt;p&gt;You’ll need three modules that don’t come with Python by default:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;BeautifulSoup&lt;/li&gt;
  &lt;li&gt;FeedParser&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mgan59/python-pinboard&quot;&gt;Python-Pinboard&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BeautifulSoup&lt;sup id=&quot;fnref:soup&quot;&gt;&lt;a href=&quot;#fn:soup&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; and FeedParser are available on &lt;code&gt;pypi&lt;/code&gt;, using &lt;code&gt;pip&lt;/code&gt;. If
you’re getting the error &lt;code&gt;ImportError: pinboard module required.&lt;/code&gt;, put the file
&lt;code&gt;pinboard.py&lt;/code&gt; (from the Python-Pinboard page) in the same directory as this
script.&lt;/p&gt;

&lt;h3 id=&quot;change-log&quot;&gt;Change log&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;em&gt;20111118&lt;/em&gt;&lt;/dt&gt;
  &lt;dd&gt;Major refactor, fixing a reddit toolbar issue on the way.&lt;/dd&gt;
  &lt;dt&gt;&lt;em&gt;20111111&lt;/em&gt;&lt;/dt&gt;
  &lt;dd&gt;Reverse reddit feed entries so they match order shown on Pinboard.&lt;/dd&gt;
&lt;/dl&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:py-installed&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://python.org&quot;&gt;Python&lt;/a&gt; comes as standard on Mac OS X, and many popular distributions of GNU/Linux.&lt;a href=&quot;#fnref:py-installed&quot; rev=&quot;footnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:other-links&quot;&gt;
      &lt;p&gt;It also works with the &lt;em&gt;liked&lt;/em&gt; links (and others), if that’s what you want.&lt;a href=&quot;#fnref:other-links&quot; rev=&quot;footnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:soup&quot;&gt;
      &lt;p&gt;If you’re getting BeautifulSoup import errors, use the latest stable
release: &lt;code&gt;pip install BeautifulSoup==3.2.0&lt;/code&gt;.&lt;a href=&quot;#fnref:soup&quot; rev=&quot;footnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
  
    <entry>
      <title>Notes on My Backup Strategy: The Voldemort Approach</title>
      <link href="http://chrispoole.com/article/backup-strategy"/>
      <updated>2011-08-01T00:00:00+01:00</updated>
      <id>http://chrispoole.com/article/backup-strategy</id>
      <content type="html">&lt;p&gt;Along with many others, I keep an increasing amount of memories and important
documents on my computer. I don’t want to lose any of it. Here are my thoughts
on backup systems, along with justifications:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Use multiple physical devices&lt;/dt&gt;
  &lt;dd&gt;Any drive or medium can and will fail.&lt;/dd&gt;
  &lt;dd&gt;I don’t trust a drive mechanism to work perfectly for the length of time I
care about the data it holds, because it probably won’t.&lt;/dd&gt;
  &lt;dd&gt;The same applies to NAS arrays and the like; one drive controller means a
single point of failure.&lt;/dd&gt;
  &lt;dt&gt;Use multiple physical locations&lt;/dt&gt;
  &lt;dd&gt;Fire and theft can occur, so offsite backups just make good sense.&lt;/dd&gt;
  &lt;dt&gt;Use multiple programs to do the backup&lt;/dt&gt;
  &lt;dd&gt;Tablets and paper have proven to last quite a long time. Software programs
haven’t. So that I don’t put all my eggs in one basket, use a few different
programs so that if I find some corruption in a backup when I come to restore,
it may not be there in other backups from other programs.&lt;/dd&gt;
  &lt;dt&gt;Don’t use proprietary container formats&lt;/dt&gt;
  &lt;dd&gt;Along the same lines are the previous item, proprietary formats that only a
few people know the blueprints to probably won’t last. Free, open formats
stand a better chance.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h3 id=&quot;backup-programs&quot;&gt;Backup programs&lt;/h3&gt;

&lt;p&gt;I use &lt;em&gt;Time Machine&lt;/em&gt; with my Mac, along with &lt;a href=&quot;http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html&quot;&gt;SuperDuper!&lt;/a&gt;. Time Machine is
great for restoring the odd file, but SuperDuper! is essential if you care about
minimal downtime when a hard drive fails. It could take hours to restore from a
Time Machine backup, but (assuming you’re using SuperDuper! to backup to the
same drive type as your main internal drive), you can just swap the drives out
and keep working immediately.&lt;/p&gt;

&lt;p&gt;Both programs simply copy files using the standard filesystem for storage: there
are no weird storage containers to open first. Assuming you can still read the
filesystem (usually &lt;em&gt;HFS+&lt;/em&gt; for current Macs) and the format of the file you’re
wanting, everything should be fine.&lt;/p&gt;

&lt;p&gt;For offsite backups and other small backups, I use &lt;a href=&quot;http://duplicity.nongnu.org/&quot;&gt;Duplicity&lt;/a&gt;. I run it using a
wrapper I wrote, &lt;a href=&quot;/project/horcrux&quot;&gt;Horcrux&lt;/a&gt;. It uses the &lt;em&gt;tar&lt;/em&gt; file format, along with &lt;a href=&quot;http://www.gnupg.org/&quot;&gt;GnuPG&lt;/a&gt;
for encryption. It also allows for incremental backups, so a full backup only
needs to be completed periodically. Horcrux makes it easy to quickly create new
backups using common arguments and options for Duplicity.&lt;/p&gt;

&lt;p&gt;This kind of backup workflow leads me to keep small backups of essential files
on many devices and drives, just in case, hence why I call my Duplicity wrapper
Horcrux.&lt;/p&gt;

</content>
    </entry>
  
    <entry>
      <title>Simple Python Completion Source for Auto-Complete</title>
      <link href="http://chrispoole.com/project/ac-python"/>
      <updated>2011-08-01T00:00:00+01:00</updated>
      <id>http://chrispoole.com/project/ac-python</id>
      <content type="html">&lt;p&gt;This is a plugin for &lt;a href=&quot;http://www.emacswiki.org/emacs/AutoComplete&quot;&gt;Auto-Complete&lt;/a&gt; (in Emacs) which provides a quick, simple
completion source for available python symbols.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/emacs-python-ac.png&quot; alt=&quot;Auto-Complete in action.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can of course use rope (with &lt;a href=&quot;http://rope.sourceforge.net/ropemacs.html&quot;&gt;ropemacs&lt;/a&gt;), but on Mac OS X this is incredibly
slow (typically taking 10 seconds to start a new python buffer), and using rope
just for symbol completion is a bit like cracking a nut with a sledge hammer.&lt;/p&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/downloads/ac-python.el&quot;&gt;Download the plugin here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Setup Auto-Complete in the usual fashion, and make sure it gets loaded for
python buffers. Then, place &lt;code&gt;ac-python.el&lt;/code&gt; in your load-path, and add&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;cl&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;ac-python&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;to your .emacs file (after loading Auto-Complete).&lt;/p&gt;

&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;/h3&gt;

&lt;p&gt;Python symbols will be completed by Auto-Complete, once Emacs learns about these
symbols. This is the short-coming of the plugin, but it’s a small price to pay.&lt;/p&gt;

&lt;p&gt;To teach Emacs about symbols in imported modules, Emacs needs to execute the
Python source. This can be accomplished with &lt;code&gt;python-send-buffer&lt;/code&gt; for example,
often bound to &lt;code&gt;C-c C-c&lt;/code&gt;. If a python process is already running, this is
essentially instantaneous.&lt;/p&gt;

&lt;p&gt;It works with both &lt;a href=&quot;http://www.emacswiki.org/emacs/ProgrammingWithPythonDotEl&quot;&gt;python.el&lt;/a&gt; and &lt;a href=&quot;https://launchpad.net/python-mode&quot;&gt;python-mode.el&lt;/a&gt;.&lt;/p&gt;

</content>
    </entry>
  
    <entry>
      <title>Horcrux: A Wrapper for Duplicity</title>
      <link href="http://chrispoole.com/project/horcrux"/>
      <updated>2011-07-14T00:00:00+01:00</updated>
      <id>http://chrispoole.com/project/horcrux</id>
      <content type="html">&lt;p&gt;&lt;a href=&quot;http://duplicity.nongnu.org/&quot;&gt;Duplicity&lt;/a&gt; is a backup program that allows you to store encrypted backups offsite
while also allowing for incremental updates.&lt;/p&gt;

&lt;p&gt;I take &lt;a href=&quot;/article/backup-strategy&quot;&gt;the &lt;em&gt;Voldemort&lt;/em&gt; approach to backups&lt;/a&gt;, backing up mostly
the same stuff to several different places, hence using similar options with
&lt;a href=&quot;http://duplicity.nongnu.org/&quot;&gt;Duplicity&lt;/a&gt;. To make this use case easier, I wrote Horcrux, a wrapper for
Duplicity’s most commonly-used options. It also includes functionality to check
a restored backup to periodically ensure your backups are working.&lt;/p&gt;

&lt;p&gt;After a simple setup, you’ll be able to run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux auto offsite1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to backup selected files and directories as part of your &lt;em&gt;offsite1&lt;/em&gt; backup. If
you want to add a new backup, the setup is minimal, and you can run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux auto offsite2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Both backups keep separate caches and use separate log files. They can backup
different files and directories, and to different locations.&lt;/p&gt;

&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/downloads/horcrux&quot;&gt;Download Horcrux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Place it in your &lt;code&gt;PATH&lt;/code&gt; somewhere, usually &lt;code&gt;~/bin&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;first-run&quot;&gt;First run&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;horcrux&lt;/code&gt; with no arguments. It’ll tell you that it’s created a file,
&lt;code&gt;~/.horcrux/horcrux.conf&lt;/code&gt;. This is the global configuration file, which’ll be
consulted for each backup. Open this file in your favourite text editor and edit
the options (perhaps only the source directory and the encryption key ID).&lt;/p&gt;

&lt;p&gt;Note that if you add a sign key (a good idea) and you use a subkey, you should
give the subkey’s ID, not the ID of your main key. If you give the main key, the
backup will still work (since gpg will choose your signing key automatically),
but upon restore Duplicity will complain that the backup files have been signed
with a different key.&lt;/p&gt;

&lt;p&gt;The source directory is the directory containing the files and directories to be
backed up. Each backup will then consult an exclude file, which will tell
Duplicity which files should be ignored, and which should be part of the backup.&lt;/p&gt;

&lt;h3 id=&quot;basic-usage&quot;&gt;Basic usage&lt;/h3&gt;

&lt;p&gt;Horcrux is run from the command line with the following syntax:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux [options] operation backup_name [restore path]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;options&lt;/code&gt; and &lt;code&gt;restore path&lt;/code&gt; are optional, but you must always tell Horcrux what
you want it to do (the operation), and the name of the backup. The backup name
can use most characters (letters, numbers, etc.) but &lt;em&gt;should not use hyphens&lt;/em&gt;.&lt;/p&gt;

&lt;h4 id=&quot;configuration-setup&quot;&gt;Configuration setup&lt;/h4&gt;

&lt;p&gt;Each backup run by Horcrux has a name and an exclude file. For example, let’s
create a backup called &lt;em&gt;offsite1&lt;/em&gt;. Create the following two files in the
&lt;code&gt;~/.horcrux&lt;/code&gt; directory:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;offsite1-config&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;offsite1-exclude&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The config file should contain at least one variable: the destination path. If
you’re backing up to a directory on a remote server somewhere, &lt;em&gt;offsite1-config&lt;/em&gt;
might look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;destination_path=&quot;rsync://username@your_server//home/username/backup/&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The URL follows the definitions allowed as described in &lt;a href=&quot;http://duplicity.nongnu.org/duplicity.1.html&quot;&gt;Duplicity’s man
page&lt;/a&gt;. You can also override variables set in the global configuration file; this
is useful to be able to change the source directory or encryption key for one
specific backup, for example. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;offsite1-exclude&lt;/em&gt; file also follows the syntax explains in Duplicity’s man
page. Assuming the source directory is &lt;code&gt;$HOME/&lt;/code&gt;, it looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;**/.DS_Store
+ /Users/username/.emacs
+ /Users/username/emacs
+ /Users/username/bin
+ /Users/username/.git*
+ /Users/username/.ssh
+ /Users/username/.zsh*
+ /Users/username/.horcrux
+ /Users/username/Documents/**/*.md
+ /Users/username/Documents/**/*.css
**/*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Duplicity likes the exclude syntax to use absolute path names, hence the
redundancy here. Items starting with a &lt;code&gt;+&lt;/code&gt; are to be included. Those without are
to be excluded. The above lines will cause Duplicity to ignore any &lt;em&gt;.DS_Store&lt;/em&gt;
files (used by Mac OS X to store icon information in the Finder), then include
several files and directories. Any &lt;code&gt;.css&lt;/code&gt; files in any directory within my
&lt;em&gt;Documents&lt;/em&gt; directory will get backed up, as will the &lt;em&gt;.horcrux&lt;/em&gt; directory, my
&lt;em&gt;emacs&lt;/em&gt; directory, and several files and directories starting with &lt;em&gt;.zsh&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Duplicity stores a local cache of changes in &lt;code&gt;~/.cache/duplicity&lt;/code&gt; by
default. If your source directory is the root of your home directory (the
Horcrux default), then make sure you exclude this directory. I add the following
line to some of my exclude files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;**/*[Cc]ache*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will ensure that Duplicity excludes files and directories with the word
&lt;em&gt;cache&lt;/em&gt; in it, which also includes &lt;code&gt;~/.cache&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;your-first-backup&quot;&gt;Your first backup&lt;/h4&gt;

&lt;p&gt;Now you should be ready to make your first backup. Duplicity first produces a
full backup, and from then on can make incremental backups (i.e., only uploading
the changed bits, to save time and space). To do this automatically, run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux auto offsite1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All output sent to the screen will also be put in a log file in &lt;code&gt;~/.horcrux&lt;/code&gt;
with the appropriate name. It’ll be compressed with &lt;code&gt;bzip2&lt;/code&gt;, or &lt;code&gt;pbzip2&lt;/code&gt; if
available.&lt;/p&gt;

&lt;p&gt;If at any point you want to check the names of options to use, you can run
&lt;code&gt;horcrux help&lt;/code&gt; or &lt;code&gt;horcrux -h&lt;/code&gt;.&lt;/p&gt;

&lt;h5 id=&quot;zero-configuration-for-local-drives&quot;&gt;Zero configuration for local drives&lt;/h5&gt;

&lt;p&gt;You might have a few external USB drives to use for backups, each of which have
the directory &lt;em&gt;backup&lt;/em&gt; inside them, so for each one you’d add&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;destination_path=&quot;file:///Volumes/drive_name/backup/&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;destination_path=&quot;file:///media/drive_name/backup/&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to its configuration file&lt;sup id=&quot;fnref:zero&quot;&gt;&lt;a href=&quot;#fn:zero&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; (assuming you’re using the same name for both
the drive and the backup). In this case, there’s no need to have a configuration
file at all. Horcrux will automatically look for such a directory, and if it
exists, will use this as the destination path&lt;sup id=&quot;fnref:dest&quot;&gt;&lt;a href=&quot;#fn:dest&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you connect a drive called &lt;em&gt;offsite2&lt;/em&gt;, and add a directory
&lt;em&gt;backup&lt;/em&gt;, you can then add an exclude file &lt;em&gt;offsite2-exclude&lt;/em&gt; to your Horcrux
directory, and the backup files will automatically be sent to
&lt;code&gt;/Volumes/offsite2/backup&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;operations&quot;&gt;Operations&lt;/h3&gt;

&lt;p&gt;Horcrux supports the following operations:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;code&gt;auto&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Full backup if no filesets or last full backup is old (default 360 days), else
incremental.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;check&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Check md5 hashes of files in a restored fileset against local fileset.&lt;/dd&gt;
  &lt;dd&gt;Requires &lt;a href=&quot;http://md5deep.sourceforge.net/&quot;&gt;md5deep&lt;/a&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;clean&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Clean local caches, removing files no longer needed.&lt;/dd&gt;
  &lt;dd&gt;Maps to &lt;code&gt;duplicity cleanup --extra-clean --force&lt;/code&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;full&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Perform full backup.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;inc&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Perform incremental backup.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;list&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;List files backed up in fileset.&lt;/dd&gt;
  &lt;dd&gt;Maps to &lt;code&gt;duplicity list-current-files&lt;/code&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Remove filesets, leaving latest n (default 3) full+inc filesets.&lt;/dd&gt;
  &lt;dd&gt;Maps to &lt;code&gt;duplicity remove-all-but-n-full n --force&lt;/code&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;restore&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Restore certain files/directories or complete filesets.&lt;/dd&gt;
  &lt;dd&gt;Maps to &lt;code&gt;duplicity restore&lt;/code&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;status&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Check collection status on fileset.&lt;/dd&gt;
  &lt;dd&gt;Maps to &lt;code&gt;duplicity collection-status&lt;/code&gt;.&lt;/dd&gt;
  &lt;dt&gt;&lt;code&gt;verify&lt;/code&gt;&lt;/dt&gt;
  &lt;dd&gt;Verify a backup. Not as thorough as &lt;code&gt;check&lt;/code&gt;.&lt;/dd&gt;
  &lt;dd&gt;Maps to &lt;code&gt;duplicity verify&lt;/code&gt;.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Running &lt;code&gt;full&lt;/code&gt; will force a full backup; if &lt;code&gt;auto&lt;/code&gt; is passed, Duplicity will
choose this method if it doesn’t find a “recent” fileset at the backup
destination&lt;sup id=&quot;fnref:recent&quot;&gt;&lt;a href=&quot;#fn:recent&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, otherwise it’ll run an incremental backup.&lt;/p&gt;

&lt;h4 id=&quot;restoring-a-backup&quot;&gt;Restoring a backup&lt;/h4&gt;

&lt;p&gt;You can restore certain files from your backups, or certain directories, or
the entire fileset. To do the latter, create a directory where you want to
restore to, and then run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux restore offsite1 /Some/restore/directory
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The backup &lt;em&gt;offsite1&lt;/em&gt; will then be restored to &lt;code&gt;/Some/restore/directory&lt;/code&gt;. You’ll
be prompted for your GPG passphrase by Duplicity.&lt;/p&gt;

&lt;p&gt;If you want to restore a certain file or directory, use the &lt;code&gt;-f&lt;/code&gt; option:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux -f somefile.txt restore offsite1 ~/restore_directory/somefile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The file &lt;code&gt;~/restore_directory/somefile.txt&lt;/code&gt; will be written with the contents of
&lt;code&gt;somefile.txt&lt;/code&gt; from your backup. This file named with &lt;code&gt;-f&lt;/code&gt; is relative to the
source directory of the backup.&lt;/p&gt;

&lt;h5 id=&quot;restoring-from-a-certain-time&quot;&gt;Restoring from a certain time&lt;/h5&gt;

&lt;p&gt;You can use the &lt;code&gt;-t&lt;/code&gt; option to restore a file or directory from a certain time
(assuming this time is between the first backup date and now). The following
syntax is used:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;YYYY-MM-DD, or interval using characters s, m, h, D, W, M, or Y. 1h78m, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, a file could be restored from 2 weeks ago using&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux -t 2W -f somefile.txt restore offsite1 ~/restore_directory/somefile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, this time format is shown in the output from &lt;code&gt;horcrux help&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;checking-a-backup&quot;&gt;Checking a backup&lt;/h4&gt;

&lt;p&gt;This is a feature that isn’t provided by &lt;a href=&quot;http://duplicity.nongnu.org/&quot;&gt;duplicity&lt;/a&gt;. It ensures that a restored
backup is exactly the same as the local files that the backup is based
on. Alternatively, it’ll show you exactly what files have been changed. It’s
useful if you want to periodically check your backups.&lt;/p&gt;

&lt;p&gt;First, you need to restore your backup to a directory. Then, run the command&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux check offsite1 /Some/restore/directory
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;http://md5deep.sourceforge.net/&quot;&gt;md5deep&lt;/a&gt; will run through all files in the restore directory, and then compare
the md5 hashes of each file with its equivalent in the backup’s source
directory. If just one byte of a file is different its hash will also be
different, and this will be recorded. The list of changed files will be stored
in &lt;code&gt;~/.horcrux/offsite1-changed-hashes.log.bz2&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;removing-old-backup-filesets&quot;&gt;Removing old backup filesets&lt;/h4&gt;

&lt;p&gt;Performing a full backup followed by a few incremental backups produces the
following structure on the backup side:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- full 1
    - incremental 1
    - incremental 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we then force a full backup then perform a few incremental backups, we’ll end
up with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- full 1
    - incremental 1
    - incremental 2
- full 2
    - incremental 3
    - incremental 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Future incremental backups (included those started by the &lt;code&gt;auto&lt;/code&gt; operation) will
be attached to &lt;em&gt;full 2&lt;/em&gt;. If space is at a premium, the old backup chains can be
removed using the &lt;code&gt;remove&lt;/code&gt; operation. By default it’ll leave 3 chains, but this
can be changed either globally in &lt;code&gt;~/.horcrux/horcrux.conf&lt;/code&gt; or for a particular
backup using the &lt;code&gt;-c&lt;/code&gt; option. If we run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux -c1 remove offsite1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;for the above backup, the result will be&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- full 2
    - incremental 3
    - incremental 4
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;options&quot;&gt;Options&lt;/h3&gt;

&lt;p&gt;Horcrux supports a number of options that can be used to change an option from
the default. For example, perhaps you want to increase the verbosity of output
from the default of 5 to the maximum of 9. You would run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;horcrux -v9 auto offsite1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are a number of possible options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;-a&lt;/code&gt;: use gpg-agent&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-c&lt;/code&gt;: number of full filesets to leave during remove operation&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-f&lt;/code&gt;: file to restore&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-h&lt;/code&gt;: show help (this text)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-k&lt;/code&gt;: encryption key&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-i&lt;/code&gt;: signing key&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-n&lt;/code&gt;: dry run&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-o&lt;/code&gt;: make auto operation run full backup if older than some time&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-s&lt;/code&gt;: backup source&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-t&lt;/code&gt;: time to restore file or directory from&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-v&lt;/code&gt;: verbosity&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-z&lt;/code&gt;: volume size in MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you run &lt;code&gt;horcrux help&lt;/code&gt; then you’ll be reminded of these options, together
with their current values (as set in &lt;code&gt;~/.horcrux/horcrux.conf&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;frequently-asked-questions&quot;&gt;Frequently asked questions&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;em&gt;I want to check what will happen before I run a backup&lt;/em&gt;&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;Use the dry run option, giving a command like &lt;code&gt;horcrux -n auto offsite1&lt;/code&gt;.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;You could also use the &lt;code&gt;paramtest&lt;/code&gt; operation, to very quickly check what
parameters will be passed to Duplicity.&lt;/dd&gt;
  &lt;dt&gt;&lt;em&gt;I want to backup to the same place, but with different names&lt;/em&gt;&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;I backup to a home server. Locally it has an address &lt;code&gt;192.168.1.2&lt;/code&gt;, but
outside of my home network it has another address provided by &lt;a href=&quot;http://www.dyndns.com/&quot;&gt;DynDNS&lt;/a&gt;.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;
    &lt;p&gt;Use multiple configuration files, one for each location, with names like
&lt;em&gt;offsite3-local-config&lt;/em&gt; and &lt;em&gt;offsite3-remote-config&lt;/em&gt;. In each one specify the
correct &lt;code&gt;destination_path&lt;/code&gt;.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;
    &lt;p&gt;Since it’s actually the same backup, it’ll just use the same exclude file as
usual, &lt;em&gt;offsite3-exclude&lt;/em&gt;.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;
    &lt;p&gt;Run the backup as either &lt;code&gt;horcrux auto offsite3-local&lt;/code&gt; or &lt;code&gt;horcrux auto
offsite3-remote&lt;/code&gt;. The correct configuration file will be loaded.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;
    &lt;p&gt;All output will go into the same log file as usual, and the same local cache
will be used.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dt&gt;&lt;em&gt;I want to backup locally first, then upload somewhere&lt;/em&gt;&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;Create your &lt;em&gt;backup-config&lt;/em&gt; file as usual, but also create a file called
&lt;em&gt;backup-local-config&lt;/em&gt; (for example). In this second file, make sure the backup
destination is set to a local drive; the former file can still have a remote
path.&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;
    &lt;p&gt;Backup using &lt;code&gt;horcrux auto backup-local&lt;/code&gt;, and then use &lt;code&gt;scp&lt;/code&gt;, &lt;code&gt;rsync&lt;/code&gt;, or
whatever, to copy these files to the remote destination. You can run &lt;code&gt;horcrux
auto backup&lt;/code&gt; from then on. I often run something like this to maximise my
upload bandwidth:&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;local_backup_dir
find . -name &lt;span class=&quot;s1&quot;&gt;&amp;#39;*.gpg&amp;#39;&lt;/span&gt; -print0 | xargs -0I&lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; -n1 -P8 rsync -avhP &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    your.remote.server:backup
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;reporting-bugs&quot;&gt;Reporting bugs&lt;/h3&gt;

&lt;p&gt;Please send me email to &lt;a href=&quot;&amp;#109;&amp;#097;&amp;#105;&amp;#108;&amp;#116;&amp;#111;:&amp;#099;&amp;#104;&amp;#114;&amp;#105;&amp;#115;&amp;#064;&amp;#099;&amp;#104;&amp;#114;&amp;#105;&amp;#115;&amp;#112;&amp;#111;&amp;#111;&amp;#108;&amp;#101;&amp;#046;&amp;#099;&amp;#111;&amp;#109;&quot;&gt;&amp;#116;&amp;#104;&amp;#101;&amp;#032;&amp;#117;&amp;#115;&amp;#117;&amp;#097;&amp;#108;&amp;#032;&amp;#097;&amp;#100;&amp;#100;&amp;#114;&amp;#101;&amp;#115;&amp;#115;&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;requirements&quot;&gt;Requirements&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://duplicity.nongnu.org/&quot;&gt;duplicity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;bzip2 or &lt;a href=&quot;http://compression.ca/pbzip2/&quot;&gt;pbzip2&lt;/a&gt; (to compress log files)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://md5deep.sourceforge.net/&quot;&gt;md5deep&lt;/a&gt; (for the &lt;code&gt;verify&lt;/code&gt; operation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;change-log&quot;&gt;Change log&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;em&gt;20110718&lt;/em&gt;&lt;/dt&gt;
  &lt;dd&gt;Add support for gpg-agent with &lt;code&gt;-a&lt;/code&gt; and &lt;code&gt;use_agent&lt;/code&gt; in horcrux.conf.&lt;/dd&gt;
  &lt;dd&gt;Check for &lt;em&gt;backup&lt;/em&gt; directory in &lt;code&gt;/media/drive_name&lt;/code&gt; as well as
&lt;code&gt;/Volumes/drive_name&lt;/code&gt;.&lt;/dd&gt;
  &lt;dd&gt;Produce more output with &lt;code&gt;paramtest&lt;/code&gt; operation (for debugging).&lt;/dd&gt;
&lt;/dl&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:zero&quot;&gt;
      &lt;p&gt;This feature assumes Mac OS X or another unix system where files are
mounted in &lt;code&gt;/media&lt;/code&gt;, such as Ubuntu.&lt;a href=&quot;#fnref:zero&quot; rev=&quot;footnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:dest&quot;&gt;
      &lt;p&gt;See variable &lt;code&gt;backup_basename&lt;/code&gt; in &lt;em&gt;horcrux.conf&lt;/em&gt;.&lt;a href=&quot;#fnref:dest&quot; rev=&quot;footnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:recent&quot;&gt;
      &lt;p&gt;See variable &lt;code&gt;full_if_old&lt;/code&gt; in &lt;em&gt;horcrux.conf&lt;/em&gt;. By default it’s 360 days.&lt;a href=&quot;#fnref:recent&quot; rev=&quot;footnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
  
    <entry>
      <title>How to Backup Your Pinboard Bookmarks</title>
      <link href="http://chrispoole.com/article/pinboard-backup"/>
      <updated>2011-06-01T00:00:00+01:00</updated>
      <id>http://chrispoole.com/article/pinboard-backup</id>
      <content type="html">&lt;p&gt;I’ve been using &lt;a href=&quot;http://pinboard.in&quot;&gt;Pinboard&lt;/a&gt; for several months now. It allows me view my
bookmarks on different devices, and it grabs articles and links from my
&lt;a href=&quot;http://instapaper.com&quot;&gt;Instapaper&lt;/a&gt; and &lt;a href=&quot;http://twitter.com&quot;&gt;Twitter&lt;/a&gt; accounts.&lt;/p&gt;

&lt;p&gt;If the bookmarks stored by Pinboard are important to you though, you shouldn’t
trust Pinboard to back them up for you. This is a simple &lt;code&gt;bash&lt;/code&gt; script to backup
your Pinboard bookmarks to your local machine.&lt;/p&gt;

&lt;p&gt;Assuming you have &lt;code&gt;curl&lt;/code&gt; installed on your unix-like system, add the following
to a file in your &lt;code&gt;PATH&lt;/code&gt; (&lt;code&gt;~/bin&lt;/code&gt; is the usual location), and change the
username, password and backup directory values:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash -&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cookies.txt
&lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;johnsmith
&lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hunter2
&lt;span class=&quot;nv&quot;&gt;backup_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;$HOME/&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Backing up Pinboard bookmarks... &amp;quot;&lt;/span&gt;

curl -s -d &lt;span class=&quot;s2&quot;&gt;&amp;quot;username=$username&amp;amp;password=$password&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;https://pinboard.in/auth/&amp;#39;&lt;/span&gt; -c &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; &amp;gt; /dev/null 2&amp;gt;&amp;amp;1

curl -s -L -b &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; -c &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;https://pinboard.in/export/format:html/&amp;#39;&lt;/span&gt; | bzip2 -c &amp;gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;$backup_dir&amp;quot;&lt;/span&gt;/pinboard-bookmarks-&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date &lt;span class=&quot;s2&quot;&gt;&amp;quot;+%Y%m%d%H%M&amp;quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;.htm.bz2

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; -f &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;rm &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt;;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Remove Pinboard bookmark backup files older than 14 days&lt;/span&gt;
find &lt;span class=&quot;s2&quot;&gt;&amp;quot;$backup_dir&amp;quot;&lt;/span&gt; -name &lt;span class=&quot;s1&quot;&gt;&amp;#39;pinboard-bookmarks-*.htm.bz2&amp;#39;&lt;/span&gt; -type f -mtime &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    +14 -maxdepth 1 -print0 | xargs -0I&lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; rm &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Done.\n&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;what-it-does&quot;&gt;What it does&lt;/h3&gt;

&lt;p&gt;Firstly, &lt;code&gt;curl&lt;/code&gt; visits the login page, entering your username and password, and
grabbing the token that Pinboard returns, keeping it in the cookie jar.&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;curl&lt;/code&gt; sends a &lt;code&gt;GET&lt;/code&gt; request to the page holding your bookmarks for
export. I’ve chosen the &lt;code&gt;html&lt;/code&gt; format, a legacy Netscape format that’s
understood by lots of other services, but you could change this to &lt;code&gt;json&lt;/code&gt; or
&lt;code&gt;xml&lt;/code&gt;. Before saving the bookmarks into a file (here, in my backup directory,
but change this to suit your taste), it’s passed through &lt;code&gt;bzip2&lt;/code&gt; to compress the
information to save space.&lt;/p&gt;

&lt;p&gt;Finally, old backup files are removed.&lt;/p&gt;

</content>
    </entry>
  
    <entry>
      <title>How to Backup Your Instapaper Links</title>
      <link href="http://chrispoole.com/article/instapaper-backup"/>
      <updated>2011-06-01T00:00:00+01:00</updated>
      <id>http://chrispoole.com/article/instapaper-backup</id>
      <content type="html">&lt;p&gt;&lt;a href=&quot;http://instapaper.com&quot;&gt;Instapaper&lt;/a&gt; saves interesting articles you come across, so you can read them at
a later date. Best of all, there’s a nice iPhone and iPad client, making reading
longer articles a pleasure.&lt;/p&gt;

&lt;p&gt;Here’s how to backup your links on a unix-like system (including Mac OS
X):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash -&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;john@example.com&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hunter2&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;form_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;df7dfg7dfg7df89g
&lt;span class=&quot;nv&quot;&gt;backup_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;$HOME/&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cookies.txt
&lt;span class=&quot;nv&quot;&gt;login_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;https://www.instapaper.com/user/login&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;export_page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;https://www.instapaper.com/export/html&amp;#39;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Backing up Instapaper... &amp;quot;&lt;/span&gt;

curl -s -d &lt;span class=&quot;s2&quot;&gt;&amp;quot;username=$username&amp;amp;password=$password&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$login_page&lt;/span&gt; -c &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; &amp;gt; /dev/null 2&amp;gt;&amp;amp;1

curl -s -b &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; -d &lt;span class=&quot;s2&quot;&gt;&amp;quot;form_key=$form_key&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$export_page&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -c &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; | bzip2 -c &amp;gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;$backup_dir&amp;quot;&lt;/span&gt;/instapaper-&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;date &lt;span class=&quot;s2&quot;&gt;&amp;quot;+%Y%m%d%H%M&amp;quot;&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;.htm.bz2

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; -f &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;    &lt;/span&gt;rm &lt;span class=&quot;nv&quot;&gt;$cookies&lt;/span&gt;;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Remove Instapaper backup files older than 14 days&lt;/span&gt;
find &lt;span class=&quot;s2&quot;&gt;&amp;quot;$backup_dir&amp;quot;&lt;/span&gt; -name &lt;span class=&quot;s1&quot;&gt;&amp;#39;instapaper-*.htm.bz2&amp;#39;&lt;/span&gt; -type f &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -mtime +14 -maxdepth 1 -print0 | xargs -0I&lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; rm &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Done.\n&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Add your username and password, and then in your browser, view the source code
to &lt;a href=&quot;http://www.instapaper.com/u&quot;&gt;your Instapaper page&lt;/a&gt;, and search for &lt;code&gt;form_key&lt;/code&gt;. It’ll have some strange
value like the above. Replace the dummy value in the script with the value for
your &lt;code&gt;form_key&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;/h3&gt;

&lt;p&gt;Once this script is in an executable file, it can be called (manually or by cron
or similar) to create a compressed backup file (currently in &lt;code&gt;$HOME/&lt;/code&gt;). Backups
older than 14 days will also get removed.&lt;/p&gt;

</content>
    </entry>
  
    <entry>
      <title>Wordpress Breadcrumbs</title>
      <link href="http://chrispoole.com/project/breadcrumbs"/>
      <updated>2004-01-01T00:00:00+00:00</updated>
      <id>http://chrispoole.com/project/breadcrumbs</id>
      <content type="html">&lt;p&gt;This PhP script implements a breadcrumbs menu (see example below), which should
work out of the box with Wordpress.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/breadcrumbs.png&quot; alt=&quot;Example of breadcrumbs&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/*&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt; * quick and dirty breadcrumb menu&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt; * initially designed for wordpress&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt; */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CPbreadcrumbs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$CPtheFullUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$_SERVER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;REQUEST_URI&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$CPurlArray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPtheFullUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPtext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPurlArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$CPdir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$CPi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CPj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$CPdir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CPurlArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$CPtext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CPurlArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$CPi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPurlArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;amp;raquo; &amp;lt;a href=&amp;quot;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$CPdir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;quot;&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;-&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CPtext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;/a&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;wp_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;CPbreadcrumbs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;span class=&quot;x&quot; /&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To use it, just put that block of code into your Wordpress file where you want
the menu to appear.&lt;/p&gt;

&lt;p&gt;If you don’t use Wordpress but still want to use this, you may have to change
&lt;code&gt;REQUEST_URI&lt;/code&gt; at the start of the script to &lt;code&gt;PHP_SELF&lt;/code&gt;. And then at the bottom,
change &lt;code&gt;wp_title()&lt;/code&gt; to be a function that gives the title of the current page.&lt;/p&gt;
</content>
    </entry>
  
    <entry>
      <title>CSS Hacks</title>
      <link href="http://chrispoole.com/article/hacks"/>
      <updated>2003-01-01T00:00:00+00:00</updated>
      <id>http://chrispoole.com/article/hacks</id>
      <content type="html">&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;

&lt;p&gt;OK, so you’re happily writing some CSS for your structured X/HTML. You get some
nice effects in IE6, then test the page in Mozilla and find that widths are
different, and you have all sorts of problems. Or, you get it working in
Mozilla, try it in IE, and it doesn’t work.&lt;/p&gt;

&lt;p&gt;Usually, it’s due to different (and incorrect) box models. Mozilla tends to
display the CSS as it should be, but it does have the odd bug in it’s
system. IE5 and IE5.5 have some CSS problems, and so some things would look
different in these browsers compared to what they look like in, say, IE6.  So,
we want our CSS to look similar in these browsers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Internet Explorer 5/5.5 &lt;/li&gt;
  &lt;li&gt;Internet Explorer 6+ &lt;/li&gt;
  &lt;li&gt;Mozilla/Netscape 6&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have combined IE5 and IE5.5 above as they both suffer from very similar CSS
issues. IE6 has fixed a lot of problems, but it’s still far from
perfect. Mozilla is very, very good, but as it has a different (and more
correct) box model, it often renders the CSS differently to IE6. Note that
Netscape 6 uses the same Gecko engine, and is infact just an earlier version of
the current Mozilla release.&lt;/p&gt;

&lt;p&gt;There are a couple of little CSS &lt;em&gt;hacks&lt;/em&gt; that can be used to make the same
(fairly simple) CSS work in all of the above browsers.&lt;/p&gt;

&lt;h3 id=&quot;ie555-css-parser-bug&quot;&gt;IE5/5.5 CSS parser bug&lt;/h3&gt;

&lt;p&gt;At first sight, a CSS parser bug seems to be a nightmare. However, it can be a
blessing in disguise sometimes. If you add the following properties to your
definitions:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;voice-family&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;voice-family&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:inherit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then the parser will close that CSS rule. Suppose you wanted to show the ‘hand’
cursor for an element other than a link (let’s say an image tag). You could do
this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pointer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is the valid value of the cursor definition to use. However, IE5/5.5
doesn’t use that value. They instead use the value &lt;code&gt;hand&lt;/code&gt;. So, you could do the
following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;But then, any other browsers (IE6, Mozilla etc.) would then not get a ‘hand’
cursor (as they use the valid value).  You can take advantage of the IE5/5.5
parser bug by doing the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;voice-family&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;nt&quot;&gt;voice-family&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
  &lt;span class=&quot;nt&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So, IE5/5.5 reads the first definition of this rule for the image tag. It makes
a ‘hand’ cursor show when your mouse moves over images. Then, it reads the next
two lines, and ends the rule with a &lt;code&gt;}&lt;/code&gt; (as it should). It does’t even read the
last rule.&lt;/p&gt;

&lt;p&gt;IE6 or Mozilla comes along, and reads the first definiton of the rule. It
changes the cursor to the &lt;code&gt;hand&lt;/code&gt; value.  However, as this is not a correct value
in these browsers, it still shows the basic arrow. It then reads what we know as
the IE5/5.5 parser bug. It is not affected by this bug, and keeps reading. The
CSS that makes up the &lt;em&gt;hack&lt;/em&gt; that we are creating also does not affect the style
of the image element (or any element for that matter).  So, it then gets to the
final definition, and sets the value of the &lt;code&gt;cursor&lt;/code&gt; definition to
&lt;code&gt;pointer&lt;/code&gt;. Now, a hand is shown in all browsers.&lt;/p&gt;

&lt;p&gt;There you have it. You have a way of separating IE5/5.5 definitions from IE6 and
Mozilla definitions.  All browsers will show a ‘hand’ cursor now.  Job done :-)&lt;/p&gt;

&lt;h3 id=&quot;ie6-support&quot;&gt;IE6 support&lt;/h3&gt;

&lt;p&gt;Even though Microsoft added a lot more when they created IE6, it still isn’t as
good as Mozilla for its CSS support.  Using the above method, we can separate
IE5/5.5 from all the newer browsers.  However, what if we want to separate IE6
from the other new browsers (that may render the CSS differently)?&lt;/p&gt;

&lt;p&gt;We simply take advantage of IE6’s lack of proper support, and confuse it a
little.  Say we do this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nf&quot;&gt;#myElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100px&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;But due to different box models, borders etc.  in Mozilla it becomes too long
(it seems to infact be 110px).  We can do this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nf&quot;&gt;#myElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100px&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#myElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;90px&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;IE6 will read the first rule, and set the width of my element to the value of
100px.  It then reads the next rule, but the &lt;code&gt;html&amp;gt;body&lt;/code&gt; part of the selector
confuses it. Naturally, it skips the definitions in that rule.&lt;/p&gt;

&lt;p&gt;Mozilla comes along, sets the width the 100px, as IE6 did.  However, Mozilla
supports more CSS, and so understands the selector for the next rule.  So, it
changes the width to 90px.  This will fix the width problems we have been
having.&lt;/p&gt;

&lt;p&gt;Please, try to code your CSS without using any of these &lt;em&gt;hacks&lt;/em&gt;. However, if you
really, really need to use a &lt;em&gt;hack&lt;/em&gt; to get it working better in another browser,
then do so. It certainly beats using JavaScript to detect the browser, then load
a custom stylesheet from there!&lt;/p&gt;
</content>
    </entry>
  
    <entry>
      <title>DOM Image Rollover</title>
      <link href="http://chrispoole.com/project/domroll"/>
      <updated>2003-01-01T00:00:00+00:00</updated>
      <id>http://chrispoole.com/project/domroll</id>
      <content type="html">&lt;p&gt;The good old image rollover, revamped for ease of use. No JavaScript knowledge
required!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/downloads/dom_image_rollover_hover/dom_image_rollover_hover.htm&quot;&gt;Demo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/downloads/dom_image_rollover_hover.zip&quot;&gt;Download&lt;/a&gt; (with instructions)&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
  
    <entry>
      <title>Introduction to CSS</title>
      <link href="http://chrispoole.com/article/css-intro"/>
      <updated>2003-01-01T00:00:00+00:00</updated>
      <id>http://chrispoole.com/article/css-intro</id>
      <content type="html">&lt;p&gt;Before continuing with the tutorials, please understand that you need a good
knowledge of X/HTML before going on to learn CSS. This is assumed in these
tutorials.&lt;/p&gt;

&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;

&lt;p&gt;CSS stands for &lt;em&gt;Cascading Style Sheets&lt;/em&gt;, and is an on-going
recommendation set by &lt;a href=&quot;http://w3.org&quot; title=&quot;World Wide Web Consortium&quot;&gt;the W3C&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is a pretty simple language, to define how elements on your page (like a link
or a paragraph of text) are displayed to the visitor. The CSS is normally put
into a &lt;em&gt;style sheet&lt;/em&gt;, but can be added as an extra attribute to single
elements (tags) in your X/HTML. I would recommend not using the latter method of
using CSS, and stick to using it as part of a proper style sheet.&lt;/p&gt;

&lt;p&gt;A style sheet can be written in an external text file (in a program such as
Windows Notepad), like you may do with your X/HTML. This file can then be
linked into your X/HTML, on any number of pages. This creates an instant major
advantage to web developers: you can change only one file (the external CSS
style sheet), and your entire site will change. That reason alone is good enough
to stop coding all your styling information in the markup.&lt;/p&gt;

&lt;p&gt;You can have more than one external style sheet in your documents. Maybe you
want one sheet for the colors, one for the positioning of your elements,
etc. It’s really up to you as a designer :)&lt;/p&gt;

&lt;h3 id=&quot;what-cascading-means-to-you&quot;&gt;What cascading means to you&lt;/h3&gt;

&lt;p&gt;If you have more than one style sheet, the &lt;em&gt;CSS parser&lt;/em&gt; of the browser
will read the first sheet, then the second, etc. If you have the same thing
defined in more than once place, the first thing will be replaced by the
second. More on this later.&lt;/p&gt;

&lt;h3 id=&quot;how-to-use-css&quot;&gt;How to use CSS&lt;/h3&gt;

&lt;p&gt;As a good designer, you want your pages to follow the same structure, i.e. menu
top-left, title top-center, etc. This makes it easier for your visitors to
browser round your site, and also makes it nice and simple to update your site.&lt;/p&gt;

&lt;p&gt;You also need good structure to be able to take full advantage of CSS. This
means &lt;a href=&quot;http://validator.w3.org&quot; title=&quot;Validate your website!&quot;&gt;valid X/HTML&lt;/a&gt;. Apart
from improving other aspects of your document, valid markup helps enormously if
you’re planning on having the bulk of your site styled by CSS.&lt;/p&gt;

&lt;h3 id=&quot;where-to-put-the-css&quot;&gt;Where to put the CSS&lt;/h3&gt;

&lt;p&gt;As explained above, the CSS can be in any of three places:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In a style sheet as part of the X/HTML document &lt;/li&gt;
  &lt;li&gt;In an additional attribute for almost any element&lt;/li&gt;
  &lt;li&gt;In an external style sheet&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;as-part-of-the-xhtml-document&quot;&gt;As part of the X/HTML document&lt;/h4&gt;

&lt;p&gt;You put the CSS code in the HEAD of your document, in between the following
tags:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;CSS&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;stuff&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;here&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Of course, the code applies to elements in that document only.&lt;/p&gt;

&lt;h4 id=&quot;the-style-attribute&quot;&gt;The style attribute&lt;/h4&gt;

&lt;p&gt;If you wish to add some style to one particular element only, you can use this
method. I do not use it however as it goes against my principal to separate the
style of a document from it’s structure (i.e. to separate the CSS from the
X/HTML). Here it is anyway:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;index.htm&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CSS stuff here&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;example&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;tag&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h4 id=&quot;external-style-sheet&quot;&gt;External style sheet&lt;/h4&gt;

&lt;p&gt;This is my chosen method, and the chosen method of many people, for it’s sheer
convenience in site building.&lt;/p&gt;

&lt;p&gt;Simply create a blank text file in Notepad, and start typing your CSS. No
X/HTML tags required. Call it something like &lt;em&gt;style.css&lt;/em&gt;. Anything you
like, as long as it has the &lt;em&gt;.css&lt;/em&gt; file extension. Then, to add it to
your X/HTML document, put this in the HEAD of your document:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;style.css&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You can add more to that tag, but that’s out of scope of this basic
tutorial. The above tag is also for a XHTML document, having &lt;code&gt;/&lt;/code&gt; at the end
of it. Remove that for an HTML document, obviously.&lt;/p&gt;

&lt;h3 id=&quot;one-more-thing&quot;&gt;One more thing!&lt;/h3&gt;

&lt;p&gt;Just a little addition to this basics tutorial. Bear in mind that whitespace is
ignored by the CSS parsers, so you can format your CSS code any way you like, to
make it more readable to you :-)&lt;/p&gt;
</content>
    </entry>
  
</feed>
