<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>achinghead.com</title>
  <link href="http://achinghead.com/atom.xml" rel="self"/>
  <link href="http://achinghead.com/"/>
  <updated>2011-04-06T22:38:40Z</updated>
  <id>http://achinghead.com/</id>
  <author>
    <name>Waylan Limberg</name>
    <email>waylan@gmail.com</email>
  </author>

  
  <entry>
    <title>Syntax Highlighting on the Web</title>
    <link href="http://achinghead.com/syntax-highlighting-web.html"/>
    <updated>2010-01-30T00:00:00Z</updated>
    <id>http://achinghead.com/MjAxMC0wMS0zMC1zeW50YXgtaGlnaGxpZ2h0aW5nLXdlYg==</id>
    <content type="html">&lt;p&gt;Years ago I starting using &lt;a href=&#34;http://daringfireball.net/projects/markdown/&#34;&gt;Markdown&lt;/a&gt; to markup text on this site. And
as is often the case today, I would include various code snippets in my posts. I
wanted those snippets to be highlighted like I saw on others sites (mostly
&lt;a href=&#34;http://trac.edgewall.org/&#34;&gt;Trac&lt;/a&gt; instances at the time) and whatever text editor I may have been using.
As I soon learned, this is a &lt;a href=&#34;http://web.archive.org/web/20030407072903/http://www.paranoidfish.org/notes/2003/03/17/1845&#34;&gt;problem&lt;/a&gt; that many people have had various
levels of success with for some time.&lt;/p&gt;
&lt;h3 id=&#34;the_background&#34;&gt;The Background&lt;/h3&gt;
&lt;p&gt;Of course, Trac was written in &lt;a href=&#34;http://python.org&#34;&gt;Python&lt;/a&gt; and I like working with Python so I
thought I&#39;d dig in and see if I could borrow from their code. It is a open
source project after all. Well, after a few false starts trying to piece
together their code, I finally came across something (not in the code itself)
that told me they were using a third part package which name escapes me now. The
package had horrible documentation and a little searching confirmed that most
people had as little success getting it to work as I did. I believe Trac has
since abandoned that package for a newer one which had not yet been released
when this was all going on.&lt;/p&gt;
&lt;p&gt;This lack of a good syntax highlighter for Python sent me on a search through
various possible solutions. In the course of that search, I learned a lot and
much of my opinions discussed below are drawn from that experience. I should
also note that the second &lt;a href=&#34;http://www.freewisdom.org/projects/python-markdown/&#34;&gt;Python-Markdown&lt;/a&gt; extension I ever released &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; rel=&#34;footnote&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
was the &lt;a href=&#34;http://www.freewisdom.org/projects/python-markdown/CodeHilite&#34;&gt;CodeHilite&lt;/a&gt; extension. In it&#39;s earliest form it called a command
line script which is available on most any Linux distributions and extracted and
slightly modified a snippet of html from the returned result do be included in a
Markdown document. It worked, but each snippet in a blog post would generate
another call to an external process and slow rendering down that much more.&lt;/p&gt;
&lt;p&gt;I looked at other solutions in various other languages and almost switched back
to PHP for some of the nice libraries offered in that language (i.e.:
&lt;a href=&#34;http://qbnz.com/highlighter/index.php&#34;&gt;GeSHi&lt;/a&gt;). I also looked at Ruby, but it was brand new at the time and didn&#39;t
have much in the way of third party libraries.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; rel=&#34;footnote&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; I also found an interesting
JavaScript project called dp.SyntaxHighlighter. It had a few quirks, so I
wasn&#39;t sold on it, but I did see it&#39;s value so I built my extension with a
setting to either use the command line script or to spit out the wonky html
necessary for the JavaScript library to work (I believe it required a specially
classed or otherwise labeled textarea). Then, almost immediately after I
released my first version of the Python-Markdown extension, I came across the
newly released &lt;a href=&#34;http://pygments.org/&#34;&gt;Pygments&lt;/a&gt; library. I almost immediately added Pygments as a
third highlighting option and soon thereafter abandoned the others, leaving
Pygments as the sole highlighting library. A short time later, I was asked to
join the Python-Markdown project and didn&#39;t spend much time on syntax
highlighting for quite a while.&lt;/p&gt;
&lt;p&gt;Before finding Pygments, I looked at starting my own library among other
things. At the time a syntax parser was a &lt;del&gt;little&lt;/del&gt; &lt;ins&gt;lot&lt;/ins&gt; over
my head, but I did find many examples that highlighted Python code. I even got
my own variation working with little trouble. If I recall correctly, it was the
first backend I built for my extension. However, I abandoned it before public 
release as it is one thing to get Python to tokenize Python code&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; rel=&#34;footnote&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, but quite
another to get it to tokenize anything else. At the time I was writing more
about HTML/CSS than about Python, so this was a non-option.&lt;/p&gt;
&lt;h3 id=&#34;numbering_lines&#34;&gt;Numbering Lines&lt;/h3&gt;
&lt;p&gt;Another issue besides tokenizing the code into its various parts (keywords,
variables, integers, strings, comments, etc.), is line numbering. Some may argue
that this is an unnecessary feature, but try reading a tutorial as a beginner
about how to understand some snippet of code, and if the author doesn&#39;t have an
easy way to indicate which line in the code he&#39;s talking about, you could easily
get lost. Besides, it makes it easy for commenters to point to the exact error
they found in your code (Hey, it&#39;s not my fault you didn&#39;t test the code you&#39;re
writing about).&lt;/p&gt;
&lt;p&gt;Even today it&#39;s not uncommon to find lines of code broken up into table rows.
One row per line of code, with two columns, the first being the line number and
the second containing the actual code. With proper styling it looks nice, but
now try to select the code to copy and past into your editor. Oops, you got the
line numbers as well. Now you have to go back and delete the line number, the
punctuation following it (usually a period) and any white space added in without
messing up indentation and the like. The same problem presents itself with a
standard ordered list. Fortunately, that was solved a long time ago by
&lt;a href=&#34;http://web.archive.org/web/20021006003116/webweaver.org/dan/css/corners/with_borders.html&#34;&gt;Dan Loda&lt;/a&gt;, &lt;a href=&#34;http://web.archive.org/web/20021021220639/http://development.incutio.com/simon/numbered-code-experiment.html&#34;&gt;Simon Willison&lt;/a&gt; (both via the Way Back Machine), and
&lt;a href=&#34;http://www.1976design.com/blog/archive/2004/07/29/redesign-tag-transform/&#34;&gt;Dustan Orchard&lt;/a&gt; (scroll about half-way down that page). The trick is to style
your &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; so that the line numbers are displayed but don&#39;t get copied.&lt;/p&gt;
&lt;p&gt;Interestingly, modern highlighters such as Pygments still have not solved this
problem. Pygments specifically still uses a table, of only one row and two
columns. The first column contains all the line numbers with line breaks in a
single cell and the second column contains all the lines of code, again with
line breaks in a single cell. Assuming your styling is correct, the line
numbers in the first column should line up with the corresponding lines in
column two. Unfortunately, I have seen many sites where this is broken.
Strangely, it seems to be more of a problem on longer snippets, so the site
designer probably didn&#39;t catch it on his short test examples while adjusting
the styling to fit his site. On some very long snippets, the line numbers
actually end short of the number of lines. While, this allows one to select and
copy the code within one table cell and avoid getting line numbers, it simply is
not an acceptable solution. Someone really should write a new formatter for
Pygments that uses the much better ordered-list.&lt;/p&gt;
&lt;p&gt;One of the downsides of the ordered-list solution to line numbering is that if
the client has CSS turned off, the user will still get line numbers when
copying and pasting. But, how often does a user have CSS turned off and
JavaScript still on? I would guess not often enough to be a concern. Today a
number of JavaScript libraries exist which do the syntax highlighting and line
numbering themselves -- no server side code needed. So, in cases where CSS and 
JavaScript are disabled, the JavaScript will never run and the code blocks will
remain in their plain, unadulterated state ready for copying and pasting line
number free.&lt;/p&gt;
&lt;h3 id=&#34;the_un-styled_source&#34;&gt;The Un-Styled Source&lt;/h3&gt;
&lt;p&gt;But there is something else interesting about Dustan Orchard&#39;s solution. Even
if the line numbers were still a problem when it came to copying and pasting, a
link is provided to download each snippet as a separate file in its original
plain text form -- no line numbers anywhere. Unfortunately, for Dustan this
means each snippet needs to be in a separate file on his server. His code then
parses the post and finds each instance of his custom markup, determines where
the source file is, reads it from the file system, and inserts it into his HTML
line by line before sereving it. Not ideal. Besides, I am working with Markdown
where the snippets are inline with the body of text and simply marked as code
blocks according to Markdown&#39;s syntax. How am I going to serve each snippet
separately, especially when I have multiple snippets in one document. I&#39;m sure
it&#39;s possible, but not really worth the effort in my opinion.&lt;/p&gt;
&lt;p&gt;I suppose one could include two copies of the snippet in the HTML document; one
styled and one not. Then with a little JavaScript, the user could toggle back
and forth between the two. But if your using JavaScript, there&#39;s a better
option. &lt;/p&gt;
&lt;p&gt;Consider the project that I believe started life as that wonky
dp.SyntaxHighlighter library I spoke of earlier: &lt;a href=&#34;http://code.google.com/p/syntaxhighlighter/&#34;&gt;SyntaxHighlighter&lt;/a&gt;. I
realize the link goes to an old abandoned version of the project, but go take a
look at the sample provided in the summary there. Notice the extra links at the
top of the screen capture? If it wasn&#39;t just an image, clicking on them would
reveal that they are links, one of which gives you the option to &#34;view plain&#34;
code. The &lt;a href=&#34;http://alexgorbatchev.com/wiki/SyntaxHighlighter&#34;&gt;newer version&lt;/a&gt; of the project gives you the same option as a little
pop-up when you hover your mouse over the block of code, as does the
&lt;a href=&#34;http://startbigthinksmall.wordpress.com/2008/10/30/beautyofcode-jquery-plugin-for-syntax-highlighting/&#34;&gt;jQuery plugin&lt;/a&gt; adaptation of the library which actually outputs valid HTML.
Personally, I like the old styling better, but that should be customizable.&lt;/p&gt;
&lt;p&gt;The point is that this is only possible with JavaScript. As the server is
sending the document with the plain code wrapped in &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; and/or &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;
tags, the code will display fine in browsers with CSS and/or JavaScript turned
off. However, with JavaScript enabled, we get the pretty version. However, as
we already have the original plain text version available client-side, its easy
to have JavaScript open a little pop-up window that displays the plain-text
code. While pop-ups are generally to be avoided, they are only used here when
specifically activated by the end user and they serve a useful purpose in this
context. I would imagine the end user could think that the plain code has
actually been fetched from the server as a separate file like Dustan Orchard&#39;s 
site does. Except, the code displays instantaneously without the delay of a
request. And there&#39;s no dance involved in including two versions and figuring
out which one to display and which one to hide by default. I suspect that&#39;s why
at least one such JavaScript library (&lt;a href=&#34;http://softwaremaniacs.org/soft/highlight/en/&#34;&gt;Highlight.js&lt;/a&gt;) markets itself as
working specifically with Markdown.&lt;/p&gt;
&lt;h3 id=&#34;the_state_of_javascript_libraries&#34;&gt;The State of JavaScript Libraries&lt;/h3&gt;
&lt;p&gt;Like the server-side libraries, many of these JavaScript libraries accept
patches for additional languages or even have a mechanism for adding your own
extensions (&lt;a href=&#34;http://shjs.sourceforge.net/&#34;&gt;SHJS&lt;/a&gt; provides an interesting solution for this). Really, you
have little to loose and much to gain by using them. A quick Google search
turned up this &lt;a href=&#34;http://www.webdesignbooth.com/9-useful-javascript-syntax-highlighting-scripts/&#34;&gt;list of nine&lt;/a&gt; JavaScript libraries currently out there (not
counting SHJS mentioned earlier). Unfortunately, it appears that only two of
those (&lt;a href=&#34;http://pradador.com/code/lighterjs/&#34;&gt;Lighter.js&lt;/a&gt; and &lt;a href=&#34;http://code.google.com/p/jquery-chili-js/&#34;&gt;Chili&lt;/a&gt;) actually have solved the
line-numbers-in-copy-and-paste problem. Actually, most of them don&#39;t even
support line numbering, but those that do all have a solution of one kind or
another.&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; rel=&#34;footnote&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; The worst part is, all of the libraries that generate line numbers
are jQuery or MooTools extensions. I&#39;d really like a standalone solution that
actually output valid HTML (that last bit disqualifies SyntaxHighlighter).&lt;/p&gt;
&lt;p&gt;Another problem is that each of those JavaScript libraries uses a slightly
different syntax to determine what code blocks are to be highlighted and what
language to highlight them as. In other words, a library like Markdown can&#39;t
just output all its code blocks using one format and expect it to work with any
JavaScript syntax highlighting library. And that&#39;s a problem.&lt;/p&gt;
&lt;h3 id=&#34;the_sad_conclusion&#34;&gt;The Sad Conclusion&lt;/h3&gt;
&lt;p&gt;Something that may seem to be missing from this analysis is a good look at
libraries in languages other than Python and JavaScript. While that may be worth
doing, it&#39;s beside the point really. Suppose you find a good library in language
X, but are forced to develop a project in language Y (perhaps due to
client/employer demands). Now that library is rather useless -- unless that
library happens to be in JavaScript and is not a plugin for a specific
JavaScript framework you also happen not to be using on this particular project.
I simply used the state of Python libraries above as examples
because that is what I am most familiar with. However, I have experienced the
same usability problems and annoyances on various sites developed on all sorts
of platforms. While we have come a long way, it is evident that we still have a
long way to go.&lt;/p&gt;
&lt;p&gt;So, yes, I think JavaScript libraries for syntax highlighting on the web are
the way of the future. I don&#39;t expect to be putting much effort into
server-side solutions from here-on-out. Any efforts will be directed primarily
at the client-side offerings out there. Hopefully we can make them better.&lt;/p&gt;
&lt;div class=&#34;footnote&#34;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;The &lt;a href=&#34;http://www.freewisdom.org/projects/python-markdown/WikiLinks&#34;&gt;first extension&lt;/a&gt; I released publicly was a simple little thing
that converted WikiLinks to links. It simply served as a means to better
understand Python-Markdown&#39;s extension API. I had actually started the core
of my highlighting extension before the wikilink extension was thought of.&amp;#160;&lt;a href=&#34;#fnref:1&#34; rev=&#34;footnote&#34; title=&#34;Jump back to footnote 1 in the text&#34;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Ruby has since gained a few libraries since then. Two being
&lt;a href=&#34;http://ultraviolet.rubyforge.org/&#34;&gt;Ultraviolet&lt;/a&gt; and &lt;a href=&#34;http://22bits.exofire.net/browse/code/colourcode&#34;&gt;ColourCode&lt;/a&gt;, both of which I know nothing about.&amp;#160;&lt;a href=&#34;#fnref:2&#34; rev=&#34;footnote&#34; title=&#34;Jump back to footnote 2 in the text&#34;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;For those who don&#39;t know, the Python tokenizer is callable from Python
code. It will return a list of tokens which you can easily iterate over and
build a bunch of appropriately styled spans for syntax highlighted Python
code on the web.&amp;#160;&lt;a href=&#34;#fnref:3&#34; rev=&#34;footnote&#34; title=&#34;Jump back to footnote 3 in the text&#34;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Actually that is not entirely true. For example, while Google&#39;s own
library (&lt;a href=&#34;http://code.google.com/p/google-code-prettify/&#34;&gt;google-code-prettify&lt;/a&gt;) does not directly support line numbers,
they suggest a rather lousy workaround on their &lt;a href=&#34;http://google-code-prettify.googlecode.com/svn/trunk/README.html&#34;&gt;FAQs&lt;/a&gt; page (second to
last FAQ). Ugh.&amp;#160;&lt;a href=&#34;#fnref:4&#34; rev=&#34;footnote&#34; title=&#34;Jump back to footnote 4 in the text&#34;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
  </entry>
  
  <entry>
    <title>Python-Markdown Tutorial Part 2: Changing Bold and Italics</title>
    <link href="http://achinghead.com/python-markdown-changing-bold-italics.html"/>
    <updated>2009-07-12T00:00:00Z</updated>
    <id>http://achinghead.com/MjAwOS0wNy0xMi1weXRob24tbWFya2Rvd24tY2hhbmdpbmctYm9sZC1pdGFsaWNz</id>
    <content type="html">&lt;p&gt;In &lt;a href=&#34;/python-markdown-adding-insert-delete.html&#34;&gt;part 1&lt;/a&gt;, we created a Python-Markdown extension which implements a new 
syntax for defining &lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;del&amp;gt;&lt;/code&gt; tags. Now we need to alter Markdown&#39;s 
existing syntax for bold and italics. As a reminder, your new syntax should 
look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;no-highlight&#34;&gt;Two hyphens for --delete--.
Two underscores for &lt;strong&gt;insert&lt;/strong&gt;.
Two asterisks for &lt;strong&gt;strong&lt;/strong&gt;.
Two slashes for //emphasis//.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we need to define our new regular expressions. We can just use the same
expressions from last time with a few modifications.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;STRONG_RE = r&#39;(**)(.&lt;em&gt;?)**&#39;
EMPH_RE = r&#39;(//)(.&lt;/em&gt;?)//&#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to insert these into the markdown parser. However, unlike with ins and del, we need to override the existing inline patterns. A quick look at the
&lt;a href=&#34;http://gitorious.org/python-markdown/mainline/blobs/master/markdown/__init__.py#line276&#34;&gt;source&lt;/a&gt; indicates that strong and emphasis are currently implemented with 
four inline patterns; &#34;strong&#34;, &#34;emphasis&#34;, &#34;emphasis2&#34; and &#34;strong_em&#34;.&lt;/p&gt;
&lt;p&gt;Let&#39;s override &#34;strong&#34; first.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        ...
        # Create new strong pattern
        strong_tag = markdown.inlinepatterns.SimpleTagPattern(STRONG_RE, &#39;strong&#39;)
        # Override existing strong pattern
        md.inlinepatterns[&#39;strong&#39;] = strong_tag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that rather than &#34;add&#34;ing a new pattern before or after an existing 
pattern, we simple reassigned the value of a pattern named &#34;strong&#34;. This is
because the old pattern named &#34;strong&#34; already existed and we don&#39;t need to 
change its location in the parser. So we simply assign a new pattern instance 
to it.&lt;/p&gt;
&lt;p&gt;We can do the same for emphasis:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        ...
        emph_tag = markdown.inlinepatterns.SimpleTagPattern(EMPH_RE, &#39;emphasis&#39;)
        md.inlinepatterns[&#39;emphasis&#39;] = emph_tag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we have two old patterns left, &#34;strong_em&#34; and &#34;emphasis2&#34;. &#34;Emphasis2&#34;
was just a special case so that underscored_words were not mistaken for 
emphasis, but as our new syntax required double underscores, it&#39;s not needed any
more. Therefore, we can delete it. The same applies for strong_em. With the old 
syntax, due to both strong and emphasis using the same characters, a special 
case was needed to match the two nested together (i.e.: &lt;code&gt;***like this***&lt;/code&gt;). 
Again this isn&#39;t needed. We can delete the two in the same way we would delete 
dict items:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        ...
        del md.inlinepatterns[&#39;strong_em&#39;]
        del md.inlinepatterns[&#39;emphasis2&#39;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That should do it. For completeness, the entire extension should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import markdown

DEL_RE = r&#39;(--)(.&lt;em&gt;?)--&#39;
INS_RE = r&#39;(&lt;strong&gt;)(.*?)&lt;/strong&gt;&#39;
STRONG_RE = r&#39;(**)(.&lt;/em&gt;?)**&#39;
EMPH_RE = r&#39;(//)(.*?)//&#39;

class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        del_tag = markdown.inlinepatterns.SimpleTagPattern(DEL_RE, &#39;del&#39;)
        md.inlinepatterns.add(&#39;del&#39;, del_tag, &#39;&amp;gt;not_strong&#39;)
        ins_tag = markdown.inlinepatterns.SimpleTagPattern(INS_RE, &#39;ins&#39;)
        md.inlinepatterns.add(&#39;ins&#39;, ins_tag, &#39;&amp;gt;del&#39;)
        strong_tag = markdown.inlinepatterns.SimpleTagPattern(STRONG_RE, &#39;strong&#39;)
        md.inlinepatterns[&#39;strong&#39;] = strong_tag
        emph_tag = markdown.inlinepatterns.SimpleTagPattern(EMPH_RE, &#39;emphasis&#39;)
        md.inlinepatterns[&#39;emphasis&#39;] = emph_tag
        del md.inlinepatterns[&#39;strong_em&#39;]
        del md.inlinepatterns[&#39;emphasis2&#39;]

def makeExtension(configs=None):
    return MyExtension(configs=configs)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In part 3 (coming soon) we&#39;ll combine all four of those patterns into one new
pattern. Yes, that means we&#39;ll be writing our own InlinePattern class.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title> Python-Markdown Tutorial Part 1: Adding InlinePatterns Insert and Delete</title>
    <link href="http://achinghead.com/python-markdown-adding-insert-delete.html"/>
    <updated>2009-06-24T00:00:00Z</updated>
    <id>http://achinghead.com/MjAwOS0wNi0yNC1weXRob24tbWFya2Rvd24tYWRkaW5nLWluc2VydC1kZWxldGU=</id>
    <content type="html">&lt;p&gt;A &lt;a href=&#34;http://six.pairlist.net/pipermail/markdown-discuss/2009-June/001591.html&#34;&gt;recent question&lt;/a&gt; on the &lt;a href=&#34;http://six.pairlist.net/mailman/listinfo/markdown-discuss&#34;&gt;markdown-discuss&lt;/a&gt; mailing list resulted in some
suggestions for an extension to &lt;a href=&#34;http://www.freewisdom.org/projects/python-markdown/&#34;&gt;Python-Markdown&lt;/a&gt;. I was able to point Simon
to the &lt;a href=&#34;http://www.freewisdom.org/projects/python-markdown/Writing_Extensions&#34;&gt;documentation&lt;/a&gt; for writing extensions, but it occurs to me that that 
document could be a little overwhelming for a first-timer. Especially when all
he needs is to alter the behavior of a few inline patterns.&lt;/p&gt;
&lt;p&gt;So, without further ado, I present a tutorial which steps through creating a
Python-Markdown Extension which incorporates something similar to Simon&#39;s
suggestion.&lt;/p&gt;
&lt;p&gt;First, we need to establish the syntax we will be implementing. While Simon&#39;s 
suggestion would work as is, I&#39;m more inclined to implement a slight variation
which follows the &lt;a href=&#34;http://txt2tags.sourceforge.net/userguide/BoldItalicUnderlineStrike.html#6_5&#34;&gt;prior art&lt;/a&gt; of the &lt;a href=&#34;http://txt2tags.sourceforge.net/index.html&#34;&gt;txt2tags&lt;/a&gt; project. Interestingly, the
&lt;a href=&#34;http://www.wikicreole.org/&#34;&gt;CREOLE&lt;/a&gt; project more-or-less adopted this same syntax and has an interesting 
&lt;a href=&#34;http://www.wikicreole.org/wiki/BoldAndItalicsReasoning&#34;&gt;explanation&lt;/a&gt; of the reasoning behind their community based decision. While I
may not agree with all their reasoning, I do like the idea that in each instance
double characters are used for markup. That way, there&#39;s less chance of a single
character needing to be escaped - both for the machine and human reader. So, the
syntax looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;no-highlight&#34;&gt;Two hyphens for --strike--.
Two underscores for &lt;strong&gt;underline&lt;/strong&gt;.
Two asterisks for &lt;strong&gt;bold&lt;/strong&gt;.
Two slashes for //italic//.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first step is to create the boilerplate code that will be required by any
Python-Markdown Extension.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import markdown

class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        # Insert code here to change markdown&#39;s behavior.
        pass

def makeExtension(configs=None):
    return MyExtension(configs=configs)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save the above code as &lt;code&gt;mdx_myextension.py&lt;/code&gt;. Now, obviously, that code doesn&#39;t
really do anything useful, but now that we have it in place, we can actually 
start implementing our new syntax.&lt;/p&gt;
&lt;p&gt;To start, let&#39;s implement the one part of that syntax that doesn&#39;t overlap with
Markdown&#39;s standard syntax; the &lt;code&gt;--strike--&lt;/code&gt; syntax. I&#39;m actually going to call 
it &#34;del&#34; (delete) rather than &#34;strike&#34; as the html generated will be the &lt;code&gt;&amp;lt;del&amp;gt;&lt;/code&gt;
tag.&lt;/p&gt;
&lt;p&gt;The first step is to write a regular expression to match the del syntax.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;DEL_RE = r&#39;(--)(.*?)--&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, there are probably a few things I should explain about that. First, you may
note that the first set of hyphens (&lt;code&gt;(--)&lt;/code&gt;) are grouped in parentheses. This is 
because we will be using a generic pattern class provided by Python-Markdown.
Specifically, the &lt;code&gt;SimpleTextPattern&lt;/code&gt; which expects the text content to be found
in &lt;code&gt;group(3)&lt;/code&gt; of the regular expression. As the entire text (including markup)
will be in &lt;code&gt;group(1)&lt;/code&gt;, we add the extra group to force the content we want into
&lt;code&gt;group(3)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Second, you may want to note that the content is matched using a non-greedy 
match &lt;code&gt;(.*?)&lt;/code&gt;. Otherwise, everything between the first occurrence and the last 
would all be placed inside one &lt;code&gt;&amp;lt;del&amp;gt;&lt;/code&gt; tag, which we do not want.&lt;/p&gt;
&lt;p&gt;So, let&#39;s incorporate our regular expression into Markdown:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;DEL_RE = r&#39;(--)(.*?)--&#39;

class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        # Create the del pattern
        del_tag = markdown.inlinepatterns.SimpleTagPattern(DEL_RE, &#39;del&#39;)
        # Insert del pattern into markdown parser
        md.inlinepatterns.add(&#39;del&#39;, del_tag, &#39;&amp;gt;not_strong&#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you noticed, we added two lines. The first line creates an instance of a
&lt;code&gt;SimpleTagPattern&lt;/code&gt;. This generic pattern class takes two arguments; the 
regular expression to match against (in this case &lt;code&gt;DEL_RE&lt;/code&gt;), and the name of 
the tag to insert the text of &lt;code&gt;group(3)&lt;/code&gt; into (&#34;del&#34;).&lt;/p&gt;
&lt;p&gt;The second line adds our new pattern to the Markdown parser. In the event that 
it is not obvious, the &lt;code&gt;extendMarkdown&lt;/code&gt; method of any &lt;code&gt;markdown.Extension&lt;/code&gt; class is passed two arguments; &#34;md&#34; and &#34;md_globals&#34;. &#34;md&#34; is actually the instance
of the Markdown class. This allows you to alter anything you want in the class
from your extension. In this case, we are adding a new inline pattern named 
&#34;del&#34;, using our pattern instance &lt;code&gt;del_tag&lt;/code&gt; after the pattern named 
&#34;not_strong&#34; (thus the &lt;code&gt;&#39;&amp;gt;not_strong&#39;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Now let&#39;s test our new extension. Open a python interpreter in the same 
directory as you saved your file (&#34;mdx_myextension.py&#34;) and try the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;gt;&amp;gt;&amp;gt; import markdown
&amp;gt;&amp;gt;&amp;gt; markdown.markdown(&#39;foo --deleted-- bar&#39;, [&#39;myextension&#39;])
u&#39;&amp;lt;p&amp;gt;foo &amp;lt;del&amp;gt;deleted&amp;lt;/del&amp;gt; bar&amp;lt;/p&amp;gt;&#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that we passed in &#34;myextension&#34; as an extension name. Markdown 
automatically appended &#34;mdx_&#34; to the name and tried to import it. As long as
the file is on your PYTHONPATH, Markdown will find it and load the extension.&lt;/p&gt;
&lt;p&gt;Let&#39;s add our syntax for underline, or as I&#39;m referring to it &lt;code&gt;__ins__&lt;/code&gt; for the &lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;DEL_RE = r&#39;(--)(.*?)--&#39;
INS_RE = r&#39;(&lt;strong&gt;)(.*?)&lt;/strong&gt;&#39;

class MyExtension(markdown.Extension):
    def extendMarkdown(self, md, md_globals):
        del_tag = markdown.inlinepatterns.SimpleTagPattern(DEL_RE, &#39;del&#39;)
        md.inlinepatterns.add(&#39;del&#39;, del_tag, &#39;&amp;gt;not_strong&#39;)
        ins_tag = markdown.inlinepatterns.SimpleTagPattern(INS_RE, &#39;ins&#39;)
        md.inlinepatterns.add(&#39;ins&#39;, ins_tag, &#39;&amp;gt;del&#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That should be self explanatory. We simply created a new pattern which matches
our &#34;ins&#34; syntax and added it after the &#34;del&#34; pattern. What&#39;s interesting about 
this is that we do not even need to alter the existing bold syntax (&lt;code&gt;__bold__&lt;/code&gt;)
as our pattern has been inserted into the parser before the existing bold 
pattern (named &#34;strong&#34;). Therefore, by the time that the &#34;strong&#34; pattern gets
to run, our extension has already identified the double underscores as inserts,
so there&#39;s no match against the &#34;strong&#34; pattern.&lt;/p&gt;
&lt;p&gt;Therefore, if all we wanted to implement was ins and del syntax we are done - 
well, except maybe giving it a decent name. Go ahead and test it out. That 
being the case, we&#39;ll stop here, and pick up with &lt;a href=&#34;/python-markdown-changing-bold-italics.html&#34;&gt;Part 2&lt;/a&gt; &lt;del&gt;(coming soon)&lt;/del&gt; where
we implement the new bold and italic syntax which replaces Markdown&#39;s 
existing syntax.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Nosetests, Generators and Descriptions</title>
    <link href="http://achinghead.com/nosetests-generators-descriptions.html"/>
    <updated>2009-06-12T00:00:00Z</updated>
    <id>http://achinghead.com/MjAwOS0wNi0xMi1ub3NldGVzdHMtZ2VuZXJhdG9ycy1kZXNjcmlwdGlvbnM=</id>
    <content type="html">&lt;p&gt;I&#39;ve recently been playing around with the &lt;a href=&#34;http://somethingaboutorange.com/mrl/projects/nose/&#34;&gt;nose&lt;/a&gt; testing framework for Python. It&#39;s pretty slick! With the various hooks for plugins, one can make it work pretty much however one wants. And what I especially like is support for generators.&lt;/p&gt;
&lt;p&gt;That is, given a iterable of some kind, a test function can yield a series of tests. In my case, I actually am walking a directory structure and returning a separate test for each data file. Via a plugin, I&#39;m even able to customize the output of these specific tests to alter the failure reports by removing unhelpful information and/or otherwise making them more useful. However, even with all this power, giving a meaningful name to each generated test is less than straightforward. There&#39;s even a &lt;a href=&#34;http://code.google.com/p/python-nose/issues/detail?id=244&#34;&gt;bug report&lt;/a&gt; regarding the issue.&lt;/p&gt;
&lt;p&gt;To illustrate, let&#39;s look at a simple nose test function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def test_foo():
    &#34;&#34;&#34; Test Foo &#34;&#34;&#34;
    assert False, &#39;Foo failed&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run that test and you&#39;ll get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F
======================================================================
FAIL: Test Foo
----------------------------------------------------------------------
Traceback (most recent call last):
  File &#34;/usr/lib/python2.5/site-packages/nose-0.11.0-py2.5.egg/nose/case.py&#34;, line 183, in runTest
    self.test(*self.arg)
  File &#34;/home/waylan/tmp/nose/test_foo.py&#34;, line 3, in test_foo
    assert False, &#34;Foo failed&#34;
AssertionError: Foo failed

----------------------------------------------------------------------
Ran 1 test in 0.014s

FAILED (failures=1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, as with Unittest, the description was pulled from the doc string. Alternatively, we could set a description attribute on the test:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test_foo.description = &#39;Test Foo&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far so good. But now let&#39;s move on to generators. A basic generator would look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def run_bar(n):
    assert False, &#39;Test %d failed&#39; % n

def test_bar():
    for n in range(2):
        yield run_bar, n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output from running this test:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FF
======================================================================
FAIL: test_foo.test_bar(0,)
----------------------------------------------------------------------
Traceback (most recent call last):
  File &#34;/usr/lib/python2.5/site-packages/nose-0.11.0-py2.5.egg/nose/case.py&#34;, line 183, in runTest
    self.test(*self.arg)
  File &#34;/home/waylan/tmp/nose/test_foo.py&#34;, line 8, in run_bar
    assert False, &#39;Test %d failed&#39; % n
AssertionError: Test 0 failed

======================================================================
FAIL: test_foo.test_bar(1,)
----------------------------------------------------------------------
Traceback (most recent call last):
  File &#34;/usr/lib/python2.5/site-packages/nose-0.11.0-py2.5.egg/nose/case.py&#34;, line 183, in runTest
    self.test(*self.arg)
  File &#34;/home/waylan/tmp/nose/test_foo.py&#34;, line 8, in run_bar
    assert False, &#39;Test %d failed&#39; % n
AssertionError: Test 1 failed

----------------------------------------------------------------------
Ran 2 tests in 0.014s

FAILED (failures=2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, in this simple case, test names like &lt;code&gt;test_foo.test_bar(1,)&lt;/code&gt; are not that bad. But start passing more complex arguments to your tests and things get ugly real fast. In my case, I&#39;m passing a long string containing a file&#39;s absolute path as well as a ConfigParser instance. Ugh. &lt;/p&gt;
&lt;p&gt;Oh, and if your wondering why I didn&#39;t just use doc strings; that would simply give every test the same description, which isn&#39;t very helpful. The first (and seemingly obvious solution) would be to use the description attribute. Something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def test_bar():
    for n in range(2):
        run_bar.description = &#39;Test bar with %d&#39; % n
        yield run_bar, n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But, alas, every test now takes on the name of the very last test run! What!?! With some thought, I realized that every test was using the same instance of the test function. Therefore, by the time the report was generated, all the tests had already run, and the description attribute was always going to be for the last run test.&lt;/p&gt;
&lt;p&gt;Ah, but, if each test uses a different instance of the test, then perhaps the description of each test could be unique. So, I made the test function a callable class and set the description on each instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class RunBaz:
    def __init__(self, n):
        self.description = &#39;Test baz with %d&#39; % n
    def __call__(self, n):
        assert False, &#39;%d failed&#39; % n

def test_baz():
    for n in range(2):
        yield RunBaz(n), n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sure enough, it works!:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;FF
======================================================================
FAIL: Test baz with 0
----------------------------------------------------------------------
Traceback (most recent call last):
  File &#34;/usr/lib/python2.5/site-packages/nose-0.11.0-py2.5.egg/nose/case.py&#34;, line 183, in runTest
    self.test(*self.arg)
  File &#34;/home/waylan/tmp/nose/test_foo.py&#34;, line 18, in __call__
    assert False, &#39;%d failed&#39; % n
AssertionError: 0 failed

======================================================================
FAIL: Test baz with 1
----------------------------------------------------------------------
Traceback (most recent call last):
  File &#34;/usr/lib/python2.5/site-packages/nose-0.11.0-py2.5.egg/nose/case.py&#34;, line 183, in runTest
    self.test(*self.arg)
  File &#34;/home/waylan/tmp/nose/test_foo.py&#34;, line 18, in __call__
    assert False, &#39;%d failed&#39; % n
AssertionError: 1 failed

----------------------------------------------------------------------
Ran 2 tests in 0.018s

FAILED (failures=2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, the need to pass the arguments into the test twice (&lt;code&gt;yield RunBaz(n), n&lt;/code&gt;) is not very DRY. This would certainly work if the description needs to be built with more than just the arguments passed in for running the test. However, if we only need to use the arguments, we can make it a little simpler:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class RunBaz:
    def __call__(self, n):
        self.description = &#39;Test baz with %d&#39; % n
        assert False, &#39;%d failed&#39; % n

def test_baz():
    for n in range(2):
        yield RunBaz(), n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just set &lt;code&gt;self.description&lt;/code&gt; right in the &lt;code&gt;__call__&lt;/code&gt; method. &lt;del&gt;The output is exactly the same as before&lt;/del&gt; &lt;ins&gt;Upon further testing, it appears that this method does not work. Every test gets the name of the last test run for the same reason explained earlier&lt;/ins&gt;.&lt;/p&gt;
&lt;p&gt;But, now I see someone has recently described a &lt;a href=&#34;http://code.google.com/p/python-nose/issues/detail?id=244#c1&#34;&gt;workaround&lt;/a&gt; in the bug report that uses functools&#39; &lt;a href=&#34;http://docs.python.org/library/functools.html#functools.partial&#34;&gt;partial&lt;/a&gt; method, which essentially does the same thing. &lt;/p&gt;
&lt;p&gt;Sigh. &lt;/p&gt;
&lt;p&gt;However, it appears that functools was only added to the standard library in Python 2.5. As I need to support earlier versions of Python, I guess my work was not all in vain. The important thing here is that generated tests in nose can have unique descriptions using a variety of methods. Pick whichever method meets your needs.&lt;/p&gt;
&lt;p&gt;Now go write some generated tests with helpful descriptions.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Git, Interactive Rebase and Ubuntu</title>
    <link href="http://achinghead.com/git-interactive-rebase-and-ubuntu.html"/>
    <updated>2008-12-12T00:00:00Z</updated>
    <id>http://achinghead.com/MjAwOC0xMi0xMi1naXQtaW50ZXJhY3RpdmUtcmViYXNlLWFuZC11YnVudHU=</id>
    <content type="html">&lt;p&gt;As mentioned &lt;a href=&#34;http://achinghead.com/archive/83/installing-multiple-versions-python/&#34;&gt;previously&lt;/a&gt;, I have a Ubuntu VirtualBox VM set up for all my python development. As we use &lt;a href=&#34;http://git.or.cz/&#34;&gt;Git&lt;/a&gt; for &lt;a href=&#34;http://www.freewisdom.org/projects/python-markdown/&#34;&gt;Python-Markdown&lt;/a&gt;, I installed Git via Ubuntu/Debian&#39;s package manager with a simple &lt;code&gt;sudo aptitude install git&lt;/code&gt; -- or so I thought:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;waylan@dev:~$ git
bash: git: command not found
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh, right! The &lt;a href=&#34;http://packages.ubuntu.com/gutsy/git&#34;&gt;git package&lt;/a&gt; has nothing to do with Git. I have to use &lt;a href=&#34;http://packages.ubuntu.com/gutsy/git-core&#34;&gt;git-core&lt;/a&gt;: &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo aptitude install git-core
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, now that I had Git installed, I went on my way, hacking on code and committing each step of the way. Whoops, I just committed an incomplete patch. Oh well, I&#39;ll commit the missing pieces separately, and use interactive rebase to squash the two commits. Hmm, what do I put for a commit message? Oh, who cares, it&#39;s a throw-away message anyway... And then I am horrified to discover that the version of Git I have is as 1.5.2.5 but interactive rebase wasn&#39;t added until 1.5.3. Therefore, Python-Markdown has commits like &lt;a href=&#34;http://gitorious.org/projects/python-markdown/repos/mainline/commits/b443efad9ae25f8f8ab421907d71c2b87e3b095a&#34;&gt;this&lt;/a&gt; and &lt;a href=&#34;http://gitorious.org/projects/python-markdown/repos/mainline/commits/971d605e2e1d0652b5ea161fe0c35a40d9685e5c&#34;&gt;this&lt;/a&gt;. Grrr.&lt;/p&gt;
&lt;p&gt;Curiously, my primary machine has a new version of Git installed. Oh, right. Apt is broken on that machine (I haven&#39;t bothered to debug it yet) and I had to manually download and install Git there. I might as well do the same on my dev VM. So, I go to the Git site, and to my delight, they host &lt;a href=&#34;http://www.backports.org/debian/pool/main/g/git-core&#34;&gt;deb files&lt;/a&gt; of the most recent builds of Git.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget http://www.backports.org/debian/pool/main/g/git-core/git-core_1.5.6.5-1~bpo40+1_i386.deb
sudo dpkg --install git-core_1.5.6.5-1~bpo40+1_i386.deb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s better. I type &lt;code&gt;git rebase -i HEAD~5&lt;/code&gt; and my editor opens with the last five commits (&lt;code&gt;HEAD~5&lt;/code&gt;) listed along with some helpful instructions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pick 358decd A few more tweaks to extension loading. We don&#39;t test trying to load non-existant or broken extensions often enough. This should handle things better.
pick b443efa foo
pick 971d605 Revert &#34;foo&#34;
pick c669bf0 One more tweak to extension loading.
pick d6711cf Normalized stripTopLevelTags to be consistant regardless of any whitespace. For example, this would allow an extension to remove/replace &#39;Prettify&#39; treeprocessor with something that added more or less whitespace without adverse effects.

# Rebase c1f4bc1..d6711cf onto c1f4bc1
#
# Commands:
#  pick = use commit
#  edit = use commit, but stop for amending
#  squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The instructions are pretty self explainitory. So I edit the file like so and save it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pick 358decd A few more tweaks to extension loading. We don&#39;t test trying to load non-existant or broken extensions often enough. This should handle things better.
squash c669bf0 One more tweak to extension loading.
pick d6711cf Normalized stripTopLevelTags to be consistant regardless of any whitespace. For example, this would allow an extension to remove/replace &#39;Prettify&#39; treeprocessor with something that added more or less whitespace without adverse effects.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The rebase runs with one more stop in the editor for me to edit the commit message. After saving that, the logs are now fixed up all nice and pretty. To bad I had pushed those changes public before the rebase. Now that others have cloned the bad commits, their clones will never merge properly with the fixed one. Oh well, at least I have the tools in place to avoid doing that again.&lt;/p&gt;
&lt;p&gt;One other cool (undocumented) feature of interactive rebase is that if you reorder the commits, they will be reordered in the log as well. In the event that the rebase runs into a conflict (which could easily happen when reordering) it will pause, allow you to fix the conflict and continue with the command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git rebase --continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is one of the reasons I really like Git. As a distributed system, I can commit locally, edit/reorder/remove/combine those commits however I like and only when I am happy with everything, push those commits to a public repo for the world to see. Yes, that means I don&#39;t push after each commit -- only after a feature is complete.&lt;/p&gt;</content>
  </entry>
  

</feed>
