<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <generator uri="http://jekyllrb.com" version="4.1.1">Jekyll</generator>
  
  
  <link href="http://leonard.io/blog/feed.xml" rel="self" type="application/atom+xml" />
  <link href="http://leonard.io/blog/" rel="alternate" type="text/html" hreflang="en" />
  <updated>2020-09-01T09:56:35+02:00</updated>
  <id>http://leonard.io/blog//</id>

  
    <title type="html">Leonard Ehrenfried’s notebook</title>
  

  
    <subtitle>Minimal, responsive Jekyll theme for hackers.</subtitle>
  

  
    <author>
        <name>Leonard Ehrenfried</name>
      
      
    </author>
  

  
  
    <entry xml:lang="de">
      
      <title type="html">Itron Openway mit Volkszähler</title>
      
      
      <link href="http://leonard.io/blog/2020/08/itron-openway-volkszaehler/" rel="alternate" type="text/html" title="Itron Openway mit Volkszähler" />
      
      <published>2020-08-31T00:00:00+02:00</published>
      <updated>2020-08-31T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2020/08/itron-openway-volkszaehler</id>
      <content type="html" xml:base="http://leonard.io/blog/2020/08/itron-openway-volkszaehler/">&lt;p&gt;Vor einer Weile hat mich mein Vater gebeten ihm zu helfen herauszufinden wie
viel Strom seiner neuen Photovoltaikanlage er an seinen Energieanbieter
verschenkt, wenn er sie ins Netz einspeist.&lt;/p&gt;

&lt;p&gt;Das hat mich in die Welt der Home Automation eingeführt und ich will meine 
Ergebnisse hier ein wenig dokumentieren.&lt;/p&gt;

&lt;h3 id=&quot;hardware&quot;&gt;Hardware&lt;/h3&gt;

&lt;p&gt;Mein Vater hat von der EnBW einen Zähler bekommen, der auf der Vorderseite
als “Itron Openway 3Hz” bezeichnet wird. Leider konnte ich online recht wenig
über dieses Modell finden und vermute das ist irgendeine Sonderedition.&lt;/p&gt;

&lt;h3 id=&quot;software&quot;&gt;Software&lt;/h3&gt;

&lt;p&gt;Manuel Wortmann hat einen &lt;a href=&quot;https://www.manuel-wortmann.de/875/stromzaehler-as1440-stadtwerke-osnabrueck-auslesen/&quot;&gt;sehr guten Post&lt;/a&gt; über sein Setup geschrieben und
ich bin dieser Anleitung gefolgt.&lt;/p&gt;

&lt;p&gt;Hier die Kurzversion:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://shop.weidmann-elektronik.de/index.php?page=product&amp;amp;info=24&quot;&gt;Weidmann Optokopf&lt;/a&gt; kaufen&lt;/li&gt;
  &lt;li&gt;Raspberry Pi kaufen&lt;/li&gt;
  &lt;li&gt;Volkszähler-Image auf RasPi installieren&lt;/li&gt;
  &lt;li&gt;D0-Schnittstelle (optische Datenausgabe) am Zähler aktivieren&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vzlogger&lt;/code&gt; konfigurieren&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;datenausgabe-über-optische-schnittstelle&quot;&gt;Datenausgabe über optische Schnittstelle&lt;/h3&gt;

&lt;p&gt;Um Daten aus dem Itron auszulesen muss die optische Schnittstelle mittels Taschenlampe
und PIN-Eingabe aktiviert werden. Ziel ist es das Gerät in den “Info On” Modus, was
dann auch im Display steht, zu setzen. Das ist eine sehr fummelige Angelegenheit und ist im
Handbuch des Herstellers und in &lt;a href=&quot;https://shop.weidmann-elektronik.de/media/files_public/ef65a5f91f3dabc8252faaababd91b30/Freischaltung_D0_Schnittstelle.pdf&quot;&gt;der des Weidmann Optokopfes&lt;/a&gt; 
beschrieben.&lt;/p&gt;

&lt;h3 id=&quot;eigenheiten&quot;&gt;Eigenheiten&lt;/h3&gt;
&lt;p&gt;Um den den Channel anzulegen, habe ich auch nicht den MySQL-Client benutzt, sondern
die Volkszähler-UI. Hierbei ist es wichtig als Typen “El. Energie (Leistungswerte))” auszuwählen.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/volkszaehler-leistungsstaende.png&quot; alt=&quot;Volkszähler Setup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Die Konfiguration des &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vzlogger&lt;/code&gt; für den Itron Openway ist ein wenig anders als beim von Manuel beschriebenen Modell.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Die Datenausgabe des Stromzählers muss nicht initialisiert werden. Wenn das Gerät auf “Info On”-Modus ist,
werden die Lichtumpulse alle Sekunde ausgegeben.&lt;/li&gt;
  &lt;li&gt;Die Daten sind im sml-Protokoll kodiert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Das Gerät liefert zwei Werte pro Datenpaket:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;den klassischen Zählerstand, also eine immerzu steigende Zahl&lt;/li&gt;
  &lt;li&gt;den aktuellen Verbrauch&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mein Vater war an letzerem interessiert und um diese Daten via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vzlogger&lt;/code&gt;
an die Volkszähler-Middleware zu schicken, habe ich folgende &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vzlogger.conf&lt;/code&gt;-Datei benutzt:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;retry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;daemon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;verbosity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;log&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/log/vzlogger.log&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;index&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;buffer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;meters&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;enabled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;device&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/dev/ttyUSB0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;protocol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;aggtime&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&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;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;aggfixedinterval&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;baudrate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;parity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;8n1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;duplicates&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uuid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;${von der UI generierte UUID}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;middleware&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://localhost/middleware.php&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;identifier&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1-0:16.7.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;aggmode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In dieser Konfiguration wird der Zählerstand nicht weiterverabeitet. Solltest Du an diesem
interessiert sein, dann erhöhe die &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;verbosity&lt;/code&gt; auf 15 und schau’ Dir die Werte und
deren ID im Log an. Dafür könntest Du einen zweiten Channel anlegen und auch diese Werte
aufzeichnen.&lt;/p&gt;

&lt;h3 id=&quot;foto-des-fertigen-setups&quot;&gt;Foto des fertigen Setups&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/itron-openway.jpg&quot; alt=&quot;Itron Openway&quot; /&gt;&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="itron" />
      
        <category term="openway" />
      
        <category term="volkszaehler" />
      

      
        <summary type="html">Vor einer Weile hat mich mein Vater gebeten ihm zu helfen herauszufinden wie viel Strom seiner neuen Photovoltaikanlage er an seinen Energieanbieter verschenkt, wenn er sie ins Netz einspeist.</summary>
      

      
      
    </entry>
  
  
  
    <entry xml:lang="de">
      
      <title type="html">A reproducible benchmark for sbt</title>
      
      
      <link href="http://leonard.io/blog/2017/11/a-reproducible-benchmark-for-sbt/" rel="alternate" type="text/html" title="A reproducible benchmark for sbt" />
      
      <published>2017-11-12T00:00:00+01:00</published>
      <updated>2017-11-12T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2017/11/a-reproducible-benchmark-for-sbt</id>
      <content type="html" xml:base="http://leonard.io/blog/2017/11/a-reproducible-benchmark-for-sbt/">&lt;p&gt;A few weeks ago sbt version 1.0.0 has been released. One of the big ticket
items in this release has been an improved incremental compiler that needs
to compile less and therefore is faster. Slow builds are a common complaint
for Scala developers so this generated a lot of excitement.&lt;/p&gt;

&lt;p&gt;In reality however, build times in version 1.0.0 have not seen any improvement
but rather a significant slow down. While the incremental compiler itself
&lt;em&gt;is&lt;/em&gt; faster, other areas of sbt have seen a sudden worseing of performance.
This has been reflected in a &lt;a href=&quot;https://github.com/sbt/zinc/pull/452&quot;&gt;flurry&lt;/a&gt; of 
&lt;a href=&quot;https://github.com/sbt/zinc/pull/371&quot;&gt;Github tickets&lt;/a&gt; and discussions on the
Gitter channel.&lt;/p&gt;

&lt;p&gt;The sbt core developers have been understandably reluctant to merge in spurious
pull requests by the community without evidence that they really improve
performance beyond a simple micro benchmark.&lt;/p&gt;

&lt;p&gt;The Scala compiler, for example, has a solid &lt;a href=&quot;https://developer.lightbend.com/blog/2017-06-12-faster-scala-compiler/#benchmarking&quot;&gt;performance benchmark&lt;/a&gt; 
suite that is run on every commit and gives immediate feedback about proposed changes.&lt;/p&gt;

&lt;p&gt;Something along these lines is needed for sbt, too.&lt;/p&gt;

&lt;p&gt;Since there doesn’t seem to be anything around yet, I took upon me to write 
one.&lt;/p&gt;

&lt;h2 id=&quot;methodology&quot;&gt;Methodology&lt;/h2&gt;

&lt;p&gt;I took an sbt project provided by &lt;a href=&quot;https://github.com/fommil&quot;&gt;Sam Halliday&lt;/a&gt; that 
had pathologically bad performance.&lt;/p&gt;

&lt;p&gt;The problem with this project is its very large classpath and many
submodules - it contains almost no source code itself!
Before compilation even starts a large amount of time is spent on checking
if classpath entries have changed.&lt;/p&gt;

&lt;p&gt;Around this test repository wrote a little bit of tooling for executing and timing
sbt commands and running them with various sbt versions.&lt;/p&gt;

&lt;p&gt;The benchmark sets sbt up to download all the required dependencies before the 
actual task under benchmark in order to ensure fairness. It then benchmark
tasks with various sbt versions and measures execution times.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;The timing results are as follows:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;command&lt;/th&gt;
      &lt;th&gt;sbt 0.13.16&lt;/th&gt;
      &lt;th&gt;sbt 1.0.3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;startup&lt;/td&gt;
      &lt;td&gt;37 seconds&lt;/td&gt;
      &lt;td&gt;45 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;compile once&lt;/td&gt;
      &lt;td&gt;89 seconds&lt;/td&gt;
      &lt;td&gt;129 seconds&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;compile twice&lt;/td&gt;
      &lt;td&gt;107 seconds&lt;/td&gt;
      &lt;td&gt;189 seconds&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The results are clear: sbt 1.0.0 has seen a substantial slowdown - at
least for this particular use case.&lt;/p&gt;

&lt;p&gt;In case you’re wondering, these benchmarks were run on a 2015 Macbook Pro with
a 2.9 GHz Intel Core i5 and 16 GB of RAM.&lt;/p&gt;

&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;/h2&gt;

&lt;p&gt;I’m planning on tracking and comparing the performance of future sbt versions.
In particular, 1.0.4 is going to be released very soon and has some performance
improvement patches.&lt;/p&gt;

&lt;p&gt;The benchmark can also be extended with more test case to give insights into a
wide range of performance scenarios. Contributions are very welcome!&lt;/p&gt;

&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/leonardehrenfried/sbt-performance-benchmark&quot;&gt;Benchmark repository on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/leonardehrenfried/sbt-performance-benchmark/blob/master/reports/large-classpath-2017-11-10T23:09:08.604Z.json&quot;&gt;Raw results in JSON format&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/cakesolutions/sbt-cake/tree/sbt-perf-regression&quot;&gt;Original performance regression demo repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="scala" />
      
        <category term="sbt" />
      
        <category term="benchmark" />
      

      
        <summary type="html">A few weeks ago sbt version 1.0.0 has been released. One of the big ticket items in this release has been an improved incremental compiler that needs to compile less and therefore is faster. Slow builds are a common complaint for Scala developers so this generated a lot of excitement.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Snake case keys in Circe</title>
      
      
      <link href="http://leonard.io/blog/2017/11/snake-case-with-circe/" rel="alternate" type="text/html" title="Snake case keys in Circe" />
      
      <published>2017-11-10T00:00:00+01:00</published>
      <updated>2017-11-10T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2017/11/snake-case-with-circe</id>
      <content type="html" xml:base="http://leonard.io/blog/2017/11/snake-case-with-circe/">&lt;p&gt;How to combine Circe’s semi-automatic derivation with snake case keys took me a little
while to find out.&lt;/p&gt;

&lt;p&gt;You will need to add the circe module: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;io.circe&quot; %% &quot;circe-generic-extras&quot; % &quot;0.8.0&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the code:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io.circe.generic.extras.Configuration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io.circe.generic.extras.semiauto._&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io.circe.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Snaky&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someProperty&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Snaky&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;customConfig&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Configuration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Configuration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;withSnakeCaseKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;withDefaults&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;snakyEncoder&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Snaky&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;n&quot;&gt;deriveEncoder&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;snakyDecoder&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Snaky&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;n&quot;&gt;deriveDecoder&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="scala" />
      
        <category term="json" />
      
        <category term="circe" />
      

      
        <summary type="html">How to combine Circe’s semi-automatic derivation with snake case keys took me a little while to find out.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Running a task on startup in sbt 1.0</title>
      
      
      <link href="http://leonard.io/blog/2017/10/running-a-command-on-startup-in-sbt-1/" rel="alternate" type="text/html" title="Running a task on startup in sbt 1.0" />
      
      <published>2017-10-27T00:00:00+02:00</published>
      <updated>2017-10-27T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2017/10/running-a-command-on-startup-in-sbt-1</id>
      <content type="html" xml:base="http://leonard.io/blog/2017/10/running-a-command-on-startup-in-sbt-1/">&lt;p&gt;If you want to run a task on startup in sbt 0.13 you’d probably do something
like this:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;onLoad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Global&lt;/span&gt; &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;Command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;project server&quot;&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;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compose&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;onLoad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Global&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This changes into the the subproject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; after sbt has loaded.&lt;/p&gt;

&lt;p&gt;In sbt 1.0 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Command.process&lt;/code&gt; has been removed and to achieve the same thing, 
you now have to do this:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;onLoad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Global&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~=&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;nf&quot;&gt;andThen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;project server&quot;&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;o&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="scala" />
      
        <category term="sbt" />
      

      
        <summary type="html">If you want to run a task on startup in sbt 0.13 you’d probably do something like this:</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Gitlab CI caching for sbt projects</title>
      
      
      <link href="http://leonard.io/blog/2017/05/gitlab-ci-caching-for-sbt-projects/" rel="alternate" type="text/html" title="Gitlab CI caching for sbt projects" />
      
      <published>2017-05-01T00:00:00+02:00</published>
      <updated>2017-05-01T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2017/05/gitlab-ci-caching-for-sbt-projects</id>
      <content type="html" xml:base="http://leonard.io/blog/2017/05/gitlab-ci-caching-for-sbt-projects/">&lt;p&gt;Compiling and testing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt; projects on hosted CI platfroms like Travis and Gitlab CI is dominated by downloading
the required dependencies from Maven Central.&lt;/p&gt;

&lt;p&gt;Oftentimes you have four to five minutes of downloading and less than one minute of compiling and testing.&lt;/p&gt;

&lt;p&gt;Some offer a feature which is supposed to speed up these always-the-same download tasks by caching
the dependencies in an S3 bucket.&lt;/p&gt;

&lt;p&gt;Caching dependencies for Scala in Travis is relatively straight forward however I couldn’t find an example
to do this for Gitlab CI. After a bit of trial and error I figured it out.&lt;/p&gt;

&lt;p&gt;Here is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitlab-ci.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# some parts originally from https://github.com/randm-ch/units-of-information/blob/master/.gitlab-ci.yml&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;hseeberger/scala-sbt:8u141-jdk_2.12.3_1.0.2&quot;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;SBT_OPTS&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dsbt.global.base=sbt-cache/sbtboot&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dsbt.boot.directory=sbt-cache/boot&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-Dsbt.ivy.home=sbt-cache/ivy&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;COURSIER_CACHE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sbt-cache/coursier&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#only needed if you use coursier&lt;/span&gt;


&lt;span class=&quot;na&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# if you want to have a separate cache per branch, uncomment the next line&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# key: &quot;$CI_BUILD_REF_NAME&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;untracked&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sbt-cache/ivy/cache&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sbt-cache/boot&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sbt-cache/sbtboot&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sbt-cache/target&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sbt-cache/coursier&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#only needed if you use coursier&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;stages&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;test&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sbt test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sometimes it takes a few times for it to actually work so just commit it and try it more than once.&lt;/p&gt;

&lt;p&gt;Edit 2017-09-20: I updated the directories and the base image slightly.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="scala" />
      
        <category term="sbt" />
      
        <category term="gitlab" />
      

      
        <summary type="html">Compiling and testing sbt projects on hosted CI platfroms like Travis and Gitlab CI is dominated by downloading the required dependencies from Maven Central.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">An in depth guide to deploying to Maven Central with sbt</title>
      
      
      <link href="http://leonard.io/blog/2017/01/an-in-depth-guide-to-deploying-to-maven-central/" rel="alternate" type="text/html" title="An in depth guide to deploying to Maven Central with sbt" />
      
      <published>2017-01-15T00:00:00+01:00</published>
      <updated>2017-01-15T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2017/01/an-in-depth-guide-to-deploying-to-maven-central</id>
      <content type="html" xml:base="http://leonard.io/blog/2017/01/an-in-depth-guide-to-deploying-to-maven-central/">&lt;p&gt;So, you’ve written a library or program in Java or Scala (or any other JVM language) and want to deploy it so that others can use
it without configuring extra repos? Just deploy it to Maven Central! This repository of code artifacts and their metadata
is &lt;em&gt;the&lt;/em&gt; place to publish your code as virtually all JVM build systems pull their dependencies from there.&lt;/p&gt;

&lt;p&gt;I published my first artifact to Maven Central with Maven (the tool, not the repository format) in 2011 and back then it was
an extremely complicated process.&lt;/p&gt;

&lt;p&gt;In 2016 I did it again with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mvn&lt;/code&gt; and was pleasantly surprised about how much the process had been streamlined.&lt;/p&gt;

&lt;p&gt;In this blog post I’m going into detail about how to deploy an artifact with sbt.&lt;/p&gt;

&lt;h3 id=&quot;sonatype&quot;&gt;Sonatype&lt;/h3&gt;

&lt;p&gt;Only very few projects deploy to Maven Central directly. Most small projects these days deploy to Maven Central via the
&lt;a href=&quot;http://central.sonatype.org/pages/ossrh-guide.html&quot;&gt;Sonatype Repository&lt;/a&gt;. This in turn then syncs with Maven Central.&lt;/p&gt;

&lt;p&gt;There is an &lt;a href=&quot;http://www.scala-sbt.org/release/docs/Using-Sonatype.html&quot;&gt;official guide&lt;/a&gt; on how to do that with sbt but
we are going to use a couple of plugins so we don’t have to use the confusing UI of the Sonatype Repository. (At least it was confusing
when I used it last in ~2011.)&lt;/p&gt;

&lt;h3 id=&quot;sbt-setup&quot;&gt;sbt setup&lt;/h3&gt;

&lt;p&gt;Add the following plugins to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project/plugins.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;addSbtPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.xerial.sbt&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sbt-sonatype&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.3&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;addSbtPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;com.jsuereth&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sbt-pgp&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.1.1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and the following keys to your project settings in your main &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// POM settings for Sonatype&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;organization&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;com.example&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;homepage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/username/projectname&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scmInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ScmInfo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/username/projectname&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;s&quot;&gt;&quot;git@github.com:username/projectname.git&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;developers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Developer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;s&quot;&gt;&quot;User Name&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;s&quot;&gt;&quot;mail@username.de&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/username&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;licenses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Apache-2.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.apache.org/licenses/LICENSE-2.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;publishMavenStyle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Add sonatype repository settings&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;publishTo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isSnapshot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Opts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;sonatypeSnapshots&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Opts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;sonatypeStaging&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Obviously replace the placeholder values appropriately.&lt;/p&gt;

&lt;h3 id=&quot;gpg-keys&quot;&gt;GPG keys&lt;/h3&gt;

&lt;p&gt;In order to be on Maven Central your artifacts have to be signed with PGP. If you already have a PGP key, great! If not create one with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sbt pgp-cmd gen-key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then deploy this key to a key server&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pgp-cmd send-key ${keyname} hkp://pool.sks-keyservers.net
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are a few key servers around the internet and every few hours they syncronise with
each other so eventually all keys will be on all servers. Sonatype and Maven/Ivy clients
will validate the signature on the artifact with your public key to make sure it is exactly what you have published.&lt;/p&gt;

&lt;h3 id=&quot;sonatype-account&quot;&gt;Sonatype account&lt;/h3&gt;

&lt;p&gt;You need to make an account at the Sonatype repo: &lt;a href=&quot;https://issues.sonatype.org/secure/Signup!default.jspa&quot;&gt;https://issues.sonatype.org/secure/Signup!default.jspa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They usually takes a few hours to respond and will ask you if you own the domain of your group id. If you don’t then maybe
use the domain of the provider where you host the code such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;com.github.username&lt;/code&gt; as your group id.&lt;/p&gt;

&lt;p&gt;After a while the ticket will be closed and you’ll be told that you now can publish into your group id.&lt;/p&gt;

&lt;h3 id=&quot;configure-credentials&quot;&gt;Configure credentials&lt;/h3&gt;

&lt;p&gt;Create a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.sbt/(sbt-version)/sonatype.sbt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Set Sonatype account information (user name and password) in the global sbt settings. To protect your password,
never commit this file to your SCM.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Credentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Sonatype Nexus Repository Manager&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;oss.sonatype.org&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;(Sonatype user name)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;(Sonatype password)&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;publishing&quot;&gt;Publishing&lt;/h3&gt;

&lt;p&gt;Once you have the permission to upload you can simply run&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sbt publishSigned
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will sign and upload your artifact to Sonatype’s staging repository. If you want you can test this release first by adding the repo to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sbt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’re happy with the release and want to push to Maven Central run&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sbt sonatypeRelease
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This promotes the release to be ready for synching to Maven Central. It usually takes a few hours before it will show up in http://search.maven.org/ but the actual sync job runs every hour or so.&lt;/p&gt;

&lt;p&gt;Now head over to the &lt;a href=&quot;https://search.maven.org/&quot;&gt;Maven search&lt;/a&gt; to check out your artifact.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="scala" />
      
        <category term="scalajs" />
      

      
        <summary type="html">So, you’ve written a library or program in Java or Scala (or any other JVM language) and want to deploy it so that others can use it without configuring extra repos? Just deploy it to Maven Central! This repository of code artifacts and their metadata is the place to publish your code as virtually all JVM build systems pull their dependencies from there.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">First impressions of ScalaJS</title>
      
      
      <link href="http://leonard.io/blog/2015/08/scalajs-first-impressions/" rel="alternate" type="text/html" title="First impressions of ScalaJS" />
      
      <published>2015-08-08T00:00:00+02:00</published>
      <updated>2015-08-08T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2015/08/scalajs-first-impressions</id>
      <content type="html" xml:base="http://leonard.io/blog/2015/08/scalajs-first-impressions/">&lt;p&gt;My last couple of projects have mostly been written in Scala and I’ve really
started too love the language as I became better and better at it. Once you’ve
fully experienced the joy of proper type safety, you can’t go back.&lt;/p&gt;

&lt;p&gt;However, these days Scala is confined mostly to the server. Since my current
contract also involves a rather large frontend component I also occassionally
have to write JavaScript. Don’t get me wrong, I’m not some hapless backend
code slinger dipping his toes into the browser world. Years ago I used the
language a lot and I’m quite competent at it. However after writing a lot of
Scala, JS’s weak types really grind on you: they make refactoring
really difficult and you discover many problems, which a compiler would tell
you much earlier, at runtime. :/&lt;/p&gt;

&lt;p&gt;Help is at hand: EPFL (where Martin Odersky is a professor) is developing
&lt;a href=&quot;http://www.scala-js.org/&quot;&gt;ScalaJS&lt;/a&gt;, which compiles Scala to JavaScript.
This weekend I took it for a spin and here are my observations.
(Mind you, this isn’t a thorough review but rather a
rough-and-ready stream of consciousness.)&lt;/p&gt;

&lt;h3 id=&quot;nice-integration-with-sbt&quot;&gt;Nice integration with sbt&lt;/h3&gt;

&lt;p&gt;You can keep using your build system and IDE. Everything worked out-of-the-box.&lt;/p&gt;

&lt;h3 id=&quot;compiler&quot;&gt;Compiler&lt;/h3&gt;

&lt;p&gt;The compilation process is not slower than the compiler that targets the JVM.
However, the Scala compiler &lt;em&gt;is&lt;/em&gt; quite slow but you get used to it because it
really helps you during development. Those sweet, sweet types are great!&lt;/p&gt;

&lt;p&gt;The compiler produces unreadable code which will make debugging harder.
&lt;del&gt;I’ve read that source maps are available, but I haven’t been able to make them work
yet.&lt;/del&gt; Source maps do work and can help you debugging!&lt;/p&gt;

&lt;h3 id=&quot;community&quot;&gt;Community&lt;/h3&gt;

&lt;p&gt;It’s rather small, but that shouldn’t surprise you since ScalaJS has only
come out of beta a few weeks ago. You should expect to write stuff yourself
because it doesn’t exist yet.&lt;/p&gt;

&lt;h3 id=&quot;libraries-and-frameworks&quot;&gt;Libraries and frameworks&lt;/h3&gt;

&lt;p&gt;This is currently a weak spot. Obviously, you can use the fantastic Scala
core library which to me is one of the main appeals. I haven’t found out how
easy it is to get third party libraries like, say, Joda-Time working.&lt;/p&gt;

&lt;p&gt;On the DOM side, there is the nice &lt;a href=&quot;https://github.com/lihaoyi/scalatags/&quot;&gt;scalatags&lt;/a&gt;
which makes writing HTML typesafe but other than there isn’t all that much
around.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://groups.google.com/forum/#!topic/scala-js/OErQmI2FQRQ&quot;&gt;community seems to be split&lt;/a&gt;
between people wanting to wrap native JS frameworks like React and others
wanting to write stuff from scratch in pure Scala.&lt;/p&gt;

&lt;p&gt;I think we will see a lot of experimentation of approaches and many new
frameworks popping up and eventually dieing. This isn’t something that worries
me a lot since this is the way that really make a community thrive. Yes, it
does cause fragmentation to a certain degree but I feel that it’s a price worth
paying for finding the best ideas and practises.&lt;/p&gt;

&lt;h3 id=&quot;file-size&quot;&gt;File size&lt;/h3&gt;

&lt;p&gt;In short: it’s acceptable. With fast optimisation my dummy app clocked in at
~600kb. A full optimisation brought that down to around 140kb. Really large
apps probably will be a few MB, but that’s not something unheard off with
apps written in native JS, too.&lt;/p&gt;

&lt;h3 id=&quot;in-summary&quot;&gt;In summary&lt;/h3&gt;

&lt;p&gt;I’m very excited about ScalaJS and I think it’s very promising. It gets
a lot of things right and people are working on the things that aren’t so
great yet.&lt;/p&gt;

&lt;p&gt;I might sound like a fanboy, but most things coming out of the Scala ecosystem
these days are very high quality and this is no exception.&lt;/p&gt;

&lt;p&gt;If you can tolerate a little technological immaturity and don’t mind being an
early adopter, I would seriously consider ScalaJS for you next frontend project.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="scala" />
      
        <category term="scalajs" />
      

      
        <summary type="html">My last couple of projects have mostly been written in Scala and I’ve really started too love the language as I became better and better at it. Once you’ve fully experienced the joy of proper type safety, you can’t go back.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Setting sbt memory options</title>
      
      
      <link href="http://leonard.io/blog/2015/06/setting-sbt-memory-options/" rel="alternate" type="text/html" title="Setting sbt memory options" />
      
      <published>2015-06-04T00:00:00+02:00</published>
      <updated>2015-06-04T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2015/06/setting-sbt-memory-options</id>
      <content type="html" xml:base="http://leonard.io/blog/2015/06/setting-sbt-memory-options/">&lt;p&gt;If you’ve been working on a bigger Scala project you will probably have
experienced that SBT consumers a rather large amount of memory and can crash
with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutOfMemoryError Metaspace&lt;/code&gt;. There is a lot of advise floating around
the web that tells you to set your memory options in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SBT_OPTS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I learned  that this is only partially true.&lt;/p&gt;

&lt;p&gt;What I found out about sbt-launcher version 0.13.8 (the most recent version
at the time of writing) is that setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Xmx&lt;/code&gt; and friends in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SBT_OPTS&lt;/code&gt; does
indeed result in them being added to the command line arguments but then they
are overwritten.&lt;/p&gt;

&lt;p&gt;The resulting command line invocation looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/usr/bin/java -XX:+CMSClassUnloadingEnabled -Xmx1500M -XX:MaxMetaspaceSize=512m -Xms1024m -Xmx1024m -XX:ReservedCodeCacheSize=128m -XX:MaxMetaspaceSize=256m -jar /usr/local/Cellar/sbt/0.13.8/libexec/sbt-launch.jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Xmx&lt;/code&gt; is set twice because the sbt launcher script blindly
prepends the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$SBT_OPTS&lt;/code&gt; to the incovation.&lt;/p&gt;

&lt;p&gt;If you put the setting into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$JAVA_OPTS&lt;/code&gt; then the sbt launcher intelligently
parses them but I wanted the memory settings to apply to sbt only and not other
Java applications.&lt;/p&gt;

&lt;p&gt;The solution I came up with in the end is to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-mem&lt;/code&gt; paramter of sbt
directly.&lt;/p&gt;

&lt;p&gt;I’ve set the following alias&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alias sbt=&quot;sbt -mem 1500&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This sets the heap space to 1.5 GB and the MaxMetaspace to 512 MB.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="java" />
      
        <category term="sbt" />
      
        <category term="xmx" />
      
        <category term="xms" />
      

      
        <summary type="html">If you’ve been working on a bigger Scala project you will probably have experienced that SBT consumers a rather large amount of memory and can crash with a OutOfMemoryError Metaspace. There is a lot of advise floating around the web that tells you to set your memory options in $SBT_OPTS.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Make Maven treat warning as errors</title>
      
      
      <link href="http://leonard.io/blog/2014/02/treat-java-warnings-as-errors-with-maven/" rel="alternate" type="text/html" title="Make Maven treat warning as errors" />
      
      <published>2014-02-28T00:00:00+01:00</published>
      <updated>2014-02-28T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2014/02/treat-java-warnings-as-errors-with-maven</id>
      <content type="html" xml:base="http://leonard.io/blog/2014/02/treat-java-warnings-as-errors-with-maven/">&lt;p&gt;I like compiler warnings and I think a nicely linted code base really improves
code hygiene and keeps standards high. Rather than relying on some post-compile
script or a tool like Sonar I prefer the compiler to throw an error when it
encouters something that we defined as a code smell. In other words, I want
it to treat warnings as errors.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;javac&lt;/code&gt; can do exactly that with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-Werror&lt;/code&gt; flag but using it in Maven took 
me a little while to find out. To enable it in your Maven builds, use the
following XML:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
&lt;span class=&quot;nt&quot;&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-compiler-plugin&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;source&amp;gt;&lt;/span&gt;1.7&lt;span class=&quot;nt&quot;&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;target&amp;gt;&lt;/span&gt;1.7&lt;span class=&quot;nt&quot;&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;compilerArguments&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;Werror&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;Xlint:all&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/compilerArguments&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="javac" />
      
        <category term="werror" />
      
        <category term="maven" />
      

      
        <summary type="html">I like compiler warnings and I think a nicely linted code base really improves code hygiene and keeps standards high. Rather than relying on some post-compile script or a tool like Sonar I prefer the compiler to throw an error when it encouters something that we defined as a code smell. In other words, I want it to treat warnings as errors.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Find out who the maintainer of a Debian/Ubuntu package is</title>
      
      
      <link href="http://leonard.io/blog/2014/02/find-out-debian-ubuntu-package-maintainer/" rel="alternate" type="text/html" title="Find out who the maintainer of a Debian/Ubuntu package is" />
      
      <published>2014-02-11T00:00:00+01:00</published>
      <updated>2014-02-11T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2014/02/find-out-debian-ubuntu-package-maintainer</id>
      <content type="html" xml:base="http://leonard.io/blog/2014/02/find-out-debian-ubuntu-package-maintainer/">&lt;p&gt;Run the following command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dpkg-query &lt;span class=&quot;nt&quot;&gt;-W&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'${Maintainer}'&lt;/span&gt; coreutils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Obviously, replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;coreutils&lt;/code&gt; with the package you’re interested in.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="ubuntu" />
      
        <category term="debian" />
      

      
        <summary type="html">Run the following command:</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Removing 200s from an Apache access log</title>
      
      
      <link href="http://leonard.io/blog/2013/10/removing-200-from-apache-access-log/" rel="alternate" type="text/html" title="Removing 200s from an Apache access log" />
      
      <published>2013-10-25T00:00:00+02:00</published>
      <updated>2013-10-25T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2013/10/removing-200-from-apache-access-log</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/10/removing-200-from-apache-access-log/">&lt;p&gt;At work we use Splunk to do log analysis of our frontend Apache which acts as
a simple proxy to the application servers. I quite like Splunk but we were
hitting our quota quite frequently when we started to include our access log
to the indexed files.&lt;/p&gt;

&lt;p&gt;We noticed that the vast majority of our entries in the access log had &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;200&lt;/code&gt;
response statuses. We’re actually not that interested in all these 200s and
it would greatly reduce our Splunk usage if we could filter them all out.
What we could have done is to just use the normal access log and then have a
cronjob grep out all the 400s and 500s but that didn’t seem very elegant. I
wanted a solution without an intermediate step.&lt;/p&gt;

&lt;p&gt;Apache has a feature called conditional logging, however it can’t be used to
filter by response code.&lt;/p&gt;

&lt;p&gt;On the other hand I found out about piped logs. The idea is that you just
pipe the log to another process which in turn can do any log processing and
filtering you want.&lt;/p&gt;

&lt;p&gt;I chose a combination of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; and Apache’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotatelogs&lt;/code&gt;. To use it, put
the following in your Apache configuration:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;LogFormat&lt;/span&gt; &quot;%s %h %l %u %t \&quot;%r\&quot; %b&quot; splunk
&lt;span class=&quot;nc&quot;&gt;CustomLog&lt;/span&gt; &quot;|stdbuf -o0 /bin/grep --invert-match '^200' | /usr/sbin/rotatelogs /var/log/apache2/splunk-access.log 86400&quot; splunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first line defines a log format with the nickname &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;splunk&lt;/code&gt;. In this format
we put the response code (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%s&lt;/code&gt;) at the beginning of the log file so we can
grep for it easily.&lt;/p&gt;

&lt;p&gt;The second one is where the action starts. The pipe (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt;) indicates that it is
a piped log. Next we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdbuf -o0&lt;/code&gt; to disable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdin&lt;/code&gt; buffering which makes
it a pain to test this setup. You can skip this in production if you want to.&lt;/p&gt;

&lt;p&gt;Next we hand over to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; and remove all lines that start with the string
200.&lt;/p&gt;

&lt;p&gt;Finally we pass the data on to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotatelogs&lt;/code&gt; which rotates the log once a day
and gzipps those older 24 hours. Read the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotatelogs&lt;/code&gt;
&lt;a href=&quot;http://httpd.apache.org/docs/2.2/programs/rotatelogs.html&quot;&gt;manual&lt;/a&gt;
for many more configuration settings.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="apache" />
      
        <category term="log" />
      

      
        <summary type="html">At work we use Splunk to do log analysis of our frontend Apache which acts as a simple proxy to the application servers. I quite like Splunk but we were hitting our quota quite frequently when we started to include our access log to the indexed files.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">ack2 package for Ubuntu 12.04</title>
      
      
      <link href="http://leonard.io/blog/2013/10/ack2-package-for-ubuntu-1204-precise/" rel="alternate" type="text/html" title="ack2 package for Ubuntu 12.04" />
      
      <published>2013-10-15T00:00:00+02:00</published>
      <updated>2013-10-15T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2013/10/ack2-package-for-ubuntu-1204-precise</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/10/ack2-package-for-ubuntu-1204-precise/">&lt;p&gt;Ubuntu 12.04 Precise Pengolin ships with version 1.96 of
&lt;a href=&quot;http://beyondgrep.com&quot;&gt;ack&lt;/a&gt; which has been superseded by the much improved
version 2. Read the &lt;a href=&quot;http://beyondgrep.com/ack-2.0/&quot;&gt;ack homepage&lt;/a&gt; if you want
to find out what is new in ack 2.&lt;/p&gt;

&lt;p&gt;Since I’m now using Ubuntu on my work computer I have built a Debian/Ubuntu
package and uploaded it to a PPA. This makes installing ack2 really easy on
Ubuntu 12.04.&lt;/p&gt;

&lt;p&gt;If you want to install it do the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo add-apt-repository ppa:leonard-ehrenfried/ack2
sudo apt-get update
sudo apt-get install ack-grep
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Afterwards, ack will be available as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ack-grep&lt;/code&gt; (there is another program in
the Ubuntu repositories using the name ack).&lt;/p&gt;

&lt;p&gt;Since I share my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; between OS X and Linux I’ve aliased it as follows:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Linux&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;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ack-grep&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      

      
        <summary type="html">Ubuntu 12.04 Precise Pengolin ships with version 1.96 of ack which has been superseded by the much improved version 2. Read the ack homepage if you want to find out what is new in ack 2.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Unit testing Javascript UIs</title>
      
      
      <link href="http://leonard.io/blog/2013/08/testing-javascript-uis/" rel="alternate" type="text/html" title="Unit testing Javascript UIs" />
      
      <published>2013-08-19T00:00:00+02:00</published>
      <updated>2013-08-19T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2013/08/testing-javascript-uis</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/08/testing-javascript-uis/">&lt;p&gt;&lt;em&gt;NB: Javascript is quite popular on the server-side now as well. This article
however concerns itself exclusively with JS in the browser.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the last 5 years Javascript has come a very long way. When I started out as
a (browser) Javascript developer people smiled when I called myself that.
I was patronised and thought of as a lesser programmer, a pixel pusher. To be
fair there was some truth to it as widgets often broke.&lt;/p&gt;

&lt;p&gt;Times have changed. Interactive websites are at the heart of a lot of
businesses and no longer an afterthought tacked on after the “real” development
has been completed.&lt;/p&gt;

&lt;p&gt;But still, there is a large holdout who think of browser programming with
Javascript as a foolish activity and not a serious developer’s job.&lt;/p&gt;

&lt;p&gt;Today I chatted to a friend about this and have started to develop at theory
why that might be. I think it has partially something to do with how Javascript
testing was done in the browser.&lt;/p&gt;

&lt;h3 id=&quot;js-and-html&quot;&gt;JS and HTML&lt;/h3&gt;

&lt;p&gt;On traditional web apps it worked mostly like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The server spits out HTML which is the baseline and users should be able to
use the app/website even with JS disabled&lt;/li&gt;
  &lt;li&gt;Javascript then takes the exitisting HTML and applies some transformation on
it, rendering it more interactive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This meant that the widgets the frontend developers built were really hard to
test, due to the fact that HTML and JS were largely separated.
The widget expected a certain kind of HTML to operate on and if this structure
wasn’t there, mostly the JS widget would just not work.&lt;/p&gt;

&lt;p&gt;Activating one of these widgets would often work something like this&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.my-widget&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;datepicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and this would assume a DOM structure which would look something like this&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my-widget&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dropdown&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;components&quot;&gt;Components&lt;/h3&gt;

&lt;p&gt;But a new style of programming the DOM, fuelled by the rise of client-side MVC
frameworks like Backbone, came into being: the UI became parcelled up into
components, views or whatever you might want to call them.
This meant that a frontend developer wouldn’t have to build a certain
HTML structure and then call some jQuery plugin on it.&lt;/p&gt;

&lt;p&gt;Instead, the HTML isn’t rendered on the server but the component you are trying
to build comes with its own HTML. Rather than the above you would do something 
like this:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DatepickerView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rendered&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.my-widget&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rendered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Can you spot the difference here? The component itself brings its own HTML
to the table instead of manipulating some globally available DOM.&lt;/p&gt;

&lt;h3 id=&quot;how-is-this-different&quot;&gt;How is this different?&lt;/h3&gt;

&lt;p&gt;If we write our UI widgets in this style testing is rather easy. Before, if
you wanted to really test your JS you had to test both the HTML the server
produced &lt;em&gt;as well&lt;/em&gt; as the widget code that operated on it. That would mean to
somehow also build up the entire context of the server-side templating
language and render a full response.&lt;/p&gt;

&lt;p&gt;Whilst before you were never quite sure that the HTML you produced was matching
the expectations the JS had, it is now rather easy to assert against the widget.&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;rendered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clickCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;p&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This new-found engineering rigour means that JS code can be as easily tested
as server side code, if not easier. What has made the difference is
the coupling of JS with the HTML it operates on (and produces).
In my opinion, that’s the qualitative distinction.&lt;/p&gt;

&lt;p&gt;In fact, if all your server produces is JSON asserting against that becomes
easy too. You no longer have to do some DOM gymnastics to find out if your
server has generated the correct response: just parse the JSON and assert
against that.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Nowadays, JS-heavy projects are thought of as API clients to the server that
produces JSON. This has enabled a style of frontend development that takes
raw data as its input and not data mixed with a sprinkling of presentation
layer. I think that this is a good thing. Frontend developers are now
writing programs, apps and no longer just spice up your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;select&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="javascript" />
      
        <category term="testing" />
      
        <category term="html" />
      

      
        <summary type="html">NB: Javascript is quite popular on the server-side now as well. This article however concerns itself exclusively with JS in the browser.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">How to test a Play framework project on Travis CI</title>
      
      
      <link href="http://leonard.io/blog/2013/07/testing-a-play-framework-project-on-travis-ci/" rel="alternate" type="text/html" title="How to test a Play framework project on Travis CI" />
      
      <published>2013-07-02T00:00:00+02:00</published>
      <updated>2013-07-02T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2013/07/testing-a-play-framework-project-on-travis-ci</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/07/testing-a-play-framework-project-on-travis-ci/">&lt;p&gt;Setting up a Travis CI build job for a Play project isn’t quite as
straightforward as I had hoped. There are some guides floating around the
web telling you to download the binary distribution and execute that.&lt;/p&gt;

&lt;p&gt;I, however, found that it is easier, quicker and cleaner to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt;
command that comes preinstalled with the Travis VMs if you set the language to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala&lt;/code&gt;. (The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;play&lt;/code&gt; command is just a thin wrapper around &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt&lt;/code&gt; anyway.)&lt;/p&gt;

&lt;p&gt;What it boils down to is this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;scala&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2.10.0&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sbt test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will also need to make sure that you have specified at least version
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.12.3&lt;/code&gt; of sbt in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.properties&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sbt.version=0.12.3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I found that with earlier sbt versions I would get a weird error whereby a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slf4j-api&lt;/code&gt; dependency couldn’t be resolved.&lt;/p&gt;

&lt;h3 id=&quot;using-the-play-command&quot;&gt;Using the play command&lt;/h3&gt;

&lt;p&gt;Today I also got a second variation working by downloading the Play zip
distribution and running that.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;scala&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PLAY_VERSION=2.1.1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;wget http://downloads.typesafe.com/play/${PLAY_VERSION}/play-${PLAY_VERSION}.zip&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;unzip -q play-${PLAY_VERSION}.zip&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;play-${PLAY_VERSION}/play test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This takes a little longer but runs the tests in the way a developer is
advised by the Play documentation to do it. I think either way is fine.&lt;/p&gt;

&lt;p&gt;You must make absolutely sure that you are using the same Play version in
your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;travis.yml&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;play-sbt-plugin&lt;/code&gt; in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sbt&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;a href=&quot;https://github.com/commercetools/sphere-snowflake&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commercetools/sphere-snowflake&lt;/code&gt;&lt;/a&gt;
is an example Github repository of a Play project being tested on Travis.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="play" />
      
        <category term="testing" />
      
        <category term="ci" />
      

      
        <summary type="html">Setting up a Travis CI build job for a Play project isn’t quite as straightforward as I had hoped. There are some guides floating around the web telling you to download the binary distribution and execute that.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Starting WEBBrick with logging disabled</title>
      
      
      <link href="http://leonard.io/blog/2013/06/starting-webrick-with-no-logging/" rel="alternate" type="text/html" title="Starting WEBBrick with logging disabled" />
      
      <published>2013-06-19T00:00:00+02:00</published>
      <updated>2013-06-19T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2013/06/starting-webrick-with-no-logging</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/06/starting-webrick-with-no-logging/">&lt;p&gt;Today I had to start a little web server that prints out the HTTP requests
received and I used Ruby’s WEBBrick for that.&lt;/p&gt;

&lt;p&gt;The trouble is that it has its own logging built in that interfered with what
I was trying to log.&lt;/p&gt;

&lt;p&gt;Here is how you disable logging completely:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;dev_null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;WEBrick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/dev/null&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;WEBrick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;HTTPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:Port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:Logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:AccessLog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dev_null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="ruby" />
      
        <category term="webbrick" />
      

      
        <summary type="html">Today I had to start a little web server that prints out the HTTP requests received and I used Ruby’s WEBBrick for that.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Editing Scala with vim</title>
      
      
      <link href="http://leonard.io/blog/2013/04/editing-scala-with-vim/" rel="alternate" type="text/html" title="Editing Scala with vim" />
      
      <published>2013-04-05T00:00:00+02:00</published>
      <updated>2013-04-05T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2013/04/editing-scala-with-vim</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/04/editing-scala-with-vim/">&lt;p&gt;Even though it hurts my brain a little bit, learning Scala has been
a pleasurable part of my job lately. It definitely isn’t for the
faint-hearted but it has taught me a lot about thinking precisely about
the topics of immutability and shared state. The functional mindset forces
you to think mainly about input and output of functions and this training,
I feel, makes me a better programmer even when programming in a language other than Scala.&lt;/p&gt;

&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;
&lt;p&gt;I’m not really an IDE lover, quite the opposite, but I have started taking
a shine to the comforts that Intelli-J is offering when writing Java.&lt;/p&gt;

&lt;p&gt;I was happy to see that Intelli-J has a plugin for Scala development and have
been using that for the last couple of months. Sadly, the plugin is really,
really slow which makes it pretty unusable to me.&lt;/p&gt;

&lt;p&gt;There is no question that the language is beautiful but the tools aren’t.&lt;/p&gt;

&lt;h3 id=&quot;enter-vim&quot;&gt;Enter vim&lt;/h3&gt;

&lt;p&gt;I’m already using vim for everything other than Java so I hunted around the
web in order to find plugins. I’ve been quite satisfied with the
following combination.&lt;/p&gt;

&lt;p&gt;###&lt;a href=&quot;https://github.com/derekwyatt/vim-scala&quot;&gt;vim-scala&lt;/a&gt;
Obviously, you will need syntax highlighting and this plugin provides that.&lt;/p&gt;

&lt;p&gt;###&lt;a href=&quot;https://github.com/Shougo/neocomplcache&quot;&gt;neocomplcache&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The built-in vim autocomplete isn’t great for Scala but the &lt;a href=&quot;https://github.com/Shougo/neocomplcache&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;neocomplcache&lt;/code&gt;&lt;/a&gt; plugin
makes typing out long Scala class or package names easier. There is no
semantic analysis behind it so all this plugin does is string matching but
I was very surprised to realise that this takes you a long way. To me at least
it is adequate.&lt;/p&gt;

&lt;h3 id=&quot;ctags&quot;&gt;ctags&lt;/h3&gt;

&lt;p&gt;In order to enable jump-to-source navigation you need to configure ctags to
index scala files. You can do that by adding the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.ctags&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;--langdef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;scala
&lt;span class=&quot;nt&quot;&gt;--langmap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;scala:.scala
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;?[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;class[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\4&lt;/span&gt;/c,classes/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;?[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;object[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\4&lt;/span&gt;/c,objects/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;?[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*case&lt;/span&gt; class[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\6&lt;/span&gt;/c,case classes/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;?[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*case&lt;/span&gt; object[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\4&lt;/span&gt;/c,case objects/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;?[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;trait[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\4&lt;/span&gt;/t,traits/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\1&lt;/span&gt;/T,types/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy|private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;a-z]&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;def[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\4&lt;/span&gt;/m,methods/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy|private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;val[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\3&lt;/span&gt;/l,constants/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;((&lt;/span&gt;abstract|final|sealed|implicit|lazy|private[^ &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;|protected&lt;span class=&quot;o&quot;&gt;)[&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\t&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;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;var[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\3&lt;/span&gt;/l,variables/
&lt;span class=&quot;nt&quot;&gt;--regex-scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/^[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;package[ &lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;a-zA-Z0-9_.]+&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;/&lt;span class=&quot;se&quot;&gt;\1&lt;/span&gt;/p,packages/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After having done that you need to run ctags from the root of your project
directory with something like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ctags &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--exclude&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;target &lt;span class=&quot;nt&quot;&gt;--exclude&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;vendor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default vim will only look for the tags file in the directory of the file
open in the current buffer. If you want vim do move up the directory hierarchy
until it has found the file add this to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;tags&lt;/span&gt;;/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, if you move the cursor over a type name and press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-]&lt;/code&gt; you will jump
to the definition of the type. That’s pretty nifty!&lt;/p&gt;

&lt;p&gt;If you want to go back to where you were before the jump press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-T&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sorting-of-imports&quot;&gt;Sorting of imports&lt;/h3&gt;

&lt;p&gt;Based on feedback from a collegue who was complaining that my imports always
look messy I have &lt;a href=&quot;https://github.com/derekwyatt/vim-scala/pull/24&quot;&gt;contributed a command&lt;/a&gt;
 to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim-scala&lt;/code&gt; plugin which automatically sorts your import statements.&lt;/p&gt;

&lt;p&gt;You can invoke the command with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:SortScalaImports&lt;/code&gt; and there are two modes
on how your imports could be sorted. By default the command goes through
the import groups (which are defined as separated by a newline) and orders
them alphabetically. This is useful for when you prefer to sort your import
into groups yourself like this:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Utility imports&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.me&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.them&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Concurrency imports&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;akka....&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scala...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;spray....&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Domain imports&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.me.data....&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.me.data....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second mode can be enabled by setting the following in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vimrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:scala_sort_across_groups&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will take &lt;em&gt;all&lt;/em&gt; of your imports and puts them into 3 different groups:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Java/Scala core libraries&lt;/li&gt;
  &lt;li&gt;3rd party libraries&lt;/li&gt;
  &lt;li&gt;First party code, a.k.a your own&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What is considered first party code can be configured by setting the a regex.
I have set it to this, which is for a standard Play app:&lt;/p&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:scala_first_party_namespaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\(controllers\|views\|models\|util\|de.\)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The result of the sort looks like this:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.text.SimpleDateFormat&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Currency&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Calendar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scala.collection.JavaConversions._&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scala.util.Random&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;play.api._&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;play.api.mvc._&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;controllers.Secured._&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;de.mycompany.useful.library.Class&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;util._&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="vim" />
      
        <category term="scala" />
      
        <category term="ctags" />
      

      
        <summary type="html">Even though it hurts my brain a little bit, learning Scala has been a pleasurable part of my job lately. It definitely isn’t for the faint-hearted but it has taught me a lot about thinking precisely about the topics of immutability and shared state. The functional mindset forces you to think mainly about input and output of functions and this training, I feel, makes me a better programmer even when programming in a language other than Scala.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">My 2009 dissertation using GATE</title>
      
      
      <link href="http://leonard.io/blog/2013/01/my-dissertation-using-gate/" rel="alternate" type="text/html" title="My 2009 dissertation using GATE" />
      
      <published>2013-01-29T00:00:00+01:00</published>
      <updated>2013-01-29T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2013/01/my-dissertation-using-gate</id>
      <content type="html" xml:base="http://leonard.io/blog/2013/01/my-dissertation-using-gate/">&lt;p&gt;Not quite 4 years ago I left university after having graduated with a degree
in computer science. I did fairly well on my final dissertation and have
been meaning to publish it for quite some time but never actually came round
to it.&lt;/p&gt;

&lt;p&gt;The reason that publishing this popped back into my mind was that last week
a colleague and I got chatting about a friend of his. The friend is also wanting
to write a thesis on natural language processing and I said that I can pass on
mine.&lt;/p&gt;

&lt;p&gt;My dissertation is titled &lt;em&gt;Automatic extraction and categorisation of
bicycle items for sale on an internet bulletin board&lt;/em&gt; and its focus is
on natural language processing using the software &lt;a href=&quot;http://gate.ac.uk/&quot;&gt;GATE&lt;/a&gt;
which is/was developed at the University of Sheffield.&lt;/p&gt;

&lt;p&gt;If you want to read it you can head over to
&lt;a href=&quot;https://docs.google.com/file/d/0B8fpFPFuEud6MExRcGJmVDhBc3M/edit&quot;&gt;the document on Google Drive&lt;/a&gt;.
From there you can download the original PDF on the top left corner.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="nlp" />
      
        <category term="java" />
      
        <category term="dissertation" />
      

      
        <summary type="html">Not quite 4 years ago I left university after having graduated with a degree in computer science. I did fairly well on my final dissertation and have been meaning to publish it for quite some time but never actually came round to it.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Handlebars array access</title>
      
      
      <link href="http://leonard.io/blog/2012/11/handlebars-array-access/" rel="alternate" type="text/html" title="Handlebars array access" />
      
      <published>2012-11-27T00:00:00+01:00</published>
      <updated>2012-11-27T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2012/11/handlebars-array-access</id>
      <content type="html" xml:base="http://leonard.io/blog/2012/11/handlebars-array-access/">&lt;p&gt;I keep forgetting and regoogling this and apparently it isn’t documented anywhere
I could find it, so I’m going to write it down hoping that Google will
help spread the word.&lt;/p&gt;

&lt;h3 id=&quot;so-how-do-i-access-an-array-in-a-handlebar-template&quot;&gt;So, how do I access an array in a Handlebar template?&lt;/h3&gt;

&lt;p&gt;The syntax is the following: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{{ array.[index] }}&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;an-example-from-an-app-im-building-right-now&quot;&gt;An example from an app I’m building right now&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;img-container pull-left&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ #if imageURLs.length }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ imageURLs.[0] }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  {{ else }}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://placehold.it/130x130&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;img-polaroid&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  {{ /if }}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="javascript" />
      
        <category term="html" />
      

      
        <summary type="html">I keep forgetting and regoogling this and apparently it isn’t documented anywhere I could find it, so I’m going to write it down hoping that Google will help spread the word.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Tools for the discerning front end developer</title>
      
      
      <link href="http://leonard.io/blog/2012/11/tools-for-the-discerning-frontend-developer/" rel="alternate" type="text/html" title="Tools for the discerning front end developer" />
      
      <published>2012-11-25T00:00:00+01:00</published>
      <updated>2012-11-25T00:00:00+01:00</updated>
      <id>http://leonard.io/blog/2012/11/tools-for-the-discerning-frontend-developer</id>
      <content type="html" xml:base="http://leonard.io/blog/2012/11/tools-for-the-discerning-frontend-developer/">&lt;h3 id=&quot;pro-forma-preamble&quot;&gt;Pro-forma preamble&lt;/h3&gt;

&lt;p&gt;Working as a web developer and doing a lot of frontend work, over the years I have collected a rather nice tool belt (if I may say so) of things that make me more productive. Today I’d like to share some of these.&lt;/p&gt;

&lt;h3 id=&quot;javascript&quot;&gt;Javascript&lt;/h3&gt;

&lt;h3 id=&quot;grunt&quot;&gt;Grunt&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://lh6.googleusercontent.com/-rC0dC5mG4Pk/UJgVyx8ORJI/AAAAAAAAIQw/Q4M0-N92Q08/s288/logo.png&quot; alt=&quot;Grunt logo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One of my more recent discoveries is a JavaScript build tool called &lt;a href=&quot;http://gruntjs.com/&quot;&gt;grunt&lt;/a&gt;. Even though I guess you could use it to build node modules, it is really meant for frontend coding tasks. If you’ve ever written your own scripts to glue together &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jshint&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uglify&lt;/code&gt;, file concatenation and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; and wondered if there is a better way, grunt can help you. It is ideal not only for those things but has plugins for virtually everything like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CoffeeScript, including on-the-fly compilation if a file is modified&lt;/li&gt;
  &lt;li&gt;CSS Compression&lt;/li&gt;
  &lt;li&gt;LessCSS compilation&lt;/li&gt;
  &lt;li&gt;Live Reload of a website without browser plugins (more about this in the next section)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, there is a bewildering array of JS build tools (Jake, Cake, Yeoman, Buildr, custom ant scripts… the list goes on) but I found grunt so far the most pleasurable to use. Go try it out.&lt;/p&gt;

&lt;h3 id=&quot;grunt-live-reload-plugin&quot;&gt;&lt;a href=&quot;https://github.com/webxl/grunt-reload&quot;&gt;Grunt Live Reload plugin&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Frankly, this is like magic. What this enables you to do is to hit save in your favourite text editor and have this automatically trigger a refresh of the page you are working on. And all of that without even installing a browser extension. The way this works is by injecting a little snippet of JavaScript into the page which in turn opens a Websocket connection to the development server which watches for changes on the file system. Here is an example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grunt.js&lt;/code&gt; file to achieve this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;grunt&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;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;lint&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;na&quot;&gt;all&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;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;js/*.js&lt;/span&gt;&lt;span class=&quot;dl&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;na&quot;&gt;less&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;na&quot;&gt;style&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;na&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;style.less&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;style.css&lt;/span&gt;&lt;span class=&quot;dl&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;na&quot;&gt;watch&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;na&quot;&gt;files&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;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;*.less&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;*.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;less reload&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;reload&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;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;proxy&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;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8000&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;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadNpmTasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;grunt-contrib-less&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadNpmTasks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;grunt-reload&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;grunt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;server reload watch&lt;/span&gt;&lt;span class=&quot;dl&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;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Who knew that development could be fun with tools like this?&lt;/p&gt;

&lt;h3 id=&quot;css-reload-bookmarklet&quot;&gt;CSS reload bookmarklet&lt;/h3&gt;

&lt;p&gt;If you don’t need the whole live reload setup or are maybe using a web framework which doesn’t play nice with grunt you can use Paul Irish’s &lt;a href=&quot;http://paulirish.com/2008/how-to-iterate-quickly-when-debugging-css/&quot;&gt;CSS reload bookmarklet&lt;/a&gt;. This simply iterates over all the stylesheets in the document and adds a fake parameter with a timestamp value to their URL causing them to be reloaded. The timestamp also takes care of any caching issues.&lt;/p&gt;

&lt;p&gt;Chrome doesn’t allow bookmarklets to be invoked with a keyboard shortcut but I found the following trick to be able to kinda-simulate a shortcut: You need to bind the bookmarklet to a custom search, which in turn can be triggered by a one-letter keyword.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh5.googleusercontent.com/-_Whl1sZppio/UJgbghpKQwI/AAAAAAAAIRA/h-aeCDdn3-w/s674/Screen%2520Shot%25202012-11-05%2520at%252021.02.27.png&quot; alt=&quot;Setting a &amp;quot;shortcut&amp;quot; to a bookmarklet in Chrome by abusing a saved search&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In order to do this, create a new search, paste the bookmarklet Javascript URL into the URL field, give it a name and a one letter keyword (I have given it the letter ‘r’). Now you can jump to the URL bar with ⌘ + L, then type R and hit enter and voila, your CSS is reloaded without you having to refresh the entire page.&lt;/p&gt;

&lt;h3 id=&quot;cdnjs&quot;&gt;&lt;a href=&quot;http://cdnjs.com/&quot;&gt;cdnjs&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;This free, community-curated CDN hosts Javascript libraries like Backbone, moment.js and various popular jQuery plugins. Using this has the double advantage of not polluting your source tree with third-party libraries as well as speeding up your page load by spreading the load onto multiple servers.&lt;/p&gt;

&lt;p&gt;An added bonus: They support SPDY for extra-parallel download for enabled browsers. You can also add a library you need to the CDN by submitting a pull request. I’ve done that a few times and Ryan and Thomas have always been quick and &lt;em&gt;very&lt;/em&gt; friendly.&lt;/p&gt;

&lt;h3 id=&quot;twitter-bootstrap-related&quot;&gt;Twitter Bootstrap related&lt;/h3&gt;

&lt;h3 id=&quot;bootswatch&quot;&gt;&lt;a href=&quot;http://bootswatch.com/&quot;&gt;Bootswatch&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;If you can’t stand the default look of Bootstrap anymore go and check out this nice selection of themes for Bootstrap.&lt;/p&gt;

&lt;h3 id=&quot;bootstrap-form-builder&quot;&gt;&lt;a href=&quot;http://bootstrap-forms.heroku.com/&quot;&gt;Bootstrap Form Builder&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://lh6.googleusercontent.com/-Od5fO3TehO4/UJgTx4eGJUI/AAAAAAAAIQo/Z4zslSr1aOw/s481/Screen%2520Shot%25202012-11-05%2520at%252020.29.45.png&quot; alt=&quot;Bootstrap Form Builder&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you’re building a lot of forms with Bootstrap, you probably want to check out this little app. It gives you a nice UI for building them.&lt;/p&gt;

&lt;h3 id=&quot;bootsnipp&quot;&gt;&lt;a href=&quot;http://bootsnipp.com/&quot;&gt;Bootsnipp&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;If it isn’t forms specifically you’re building, Bootsnipp gives you small snippets of readymade Bootstrap components and examples of what you could build with Bootstrap.&lt;/p&gt;

&lt;h3 id=&quot;bootstrapcdn&quot;&gt;&lt;a href=&quot;http://www.bootstrapcdn.com/&quot;&gt;BootstrapCDN&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Are you tired of re-adding Bootstrap’s CSS file to your repositories over and over or using Github as a static asset server? As the name suggests this free CDN hosts Bootstrap for you. My favourite feature are the hosted versions of Bootswatch.&lt;/p&gt;

&lt;h3 id=&quot;misc&quot;&gt;Misc.&lt;/h3&gt;

&lt;h3 id=&quot;fontello&quot;&gt;&lt;a href=&quot;http://fontello.com/&quot;&gt;Fontello&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Remember the days when you had to pester your designer for small icon PNGs (most likely in plain as well as mouseover/active variations)? Thank God we have icon fonts now! The only downside is that selecting an icon character and inserting it into your HTML is quite a bit of work and may involve special programs for font managements.&lt;/p&gt;

&lt;p&gt;Fontello is a web app that has made it its mission to take away the pain from using icon fonts. They have collected a hand full of very popular icon fonts (&lt;a href=&quot;http://www.entypo.com/&quot;&gt;Entypo&lt;/a&gt;, for example), have given each icon character a simple, descriptive name and make this all available as single webfont file (in all formats you’ll ever need) plus a handy stylesheet. This lets you create icons by simply applying a CSS class to an element, just as it is done in Twitter Bootstrap.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh5.googleusercontent.com/-fj4HRCQhhxQ/UJgkMDywG3I/AAAAAAAAIRU/H5NWQF-UcEA/s229/Screen%2520Shot%25202012-11-05%2520at%252021.39.53.png&quot; alt=&quot;Fontello&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you suggest this in your team, your designer will love you as this frees her/him up to do actual design. Other benefits are that you can style your icons with CSS and have a lot less HTTP requests during page load.&lt;/p&gt;

&lt;h3 id=&quot;json-formatting&quot;&gt;JSON formatting&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://stedolan.github.com/jq/&quot;&gt;jq&lt;/a&gt; is pretty nice tool for querying a JSON document but if all you need is a pretty printer you can pipe your JSON through a built in python module with the following one-liner:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'{&quot;foo&quot;: &quot;lorem&quot;, &quot;bar&quot;: &quot;ipsum&quot;}'&lt;/span&gt; | python &lt;span class=&quot;nt&quot;&gt;-mjson&lt;/span&gt;.tool&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I have this aliased in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.profile&lt;/code&gt; to jsonpretty with a&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;jsonpretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'python -mjson.tool'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;ack---better-than-grep&quot;&gt;&lt;a href=&quot;http://betterthangrep.com/&quot;&gt;ack&lt;/a&gt; - better than grep&lt;/h3&gt;

&lt;p&gt;If the project-wide full text search of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$FAVOURITE_IDE&lt;/code&gt; sucks, and lets be honest they all do, and grep is just a little too awkward to use then take a look at ack. It has changed the way I explore and navigate source trees. Ack is designed to search through large source code trees, searches recursively by default and excludes stuff you definitely don’t want to search like git and temp folders.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh3.googleusercontent.com/-R7dPtGgbuvQ/UJlzS4QCrlI/AAAAAAAAIRk/EnSQkgHQPy0/s471/Screen%2520Shot%25202012-11-06%2520at%252021.29.07.png&quot; alt=&quot;Grepping with ack&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Even though it is currently still in alpha state, I’m using version 2.0 for a couple of months now without any issues. Ack 2 removes the limitation of having to keep a whitelist of files to be searched and includes all text files by default. Another thing which wasn’t possible in ack 1 but is in 2 is including file names without dots (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt;). If you want to install ack 2.0 alpha through homebrew, I have prepared a recipe for you. Just do a&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install https://raw.github.com/leonardehrenfried/ack2-compiled/master/ack2.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;testing-regular-expressions&quot;&gt;Testing regular expressions&lt;/h3&gt;
&lt;p&gt;To me it was a real eye opener when I discovered visual regex tools. They
shorten the feedback loop drastically and make reasoning about them a lot
easier (even though it still often takes a few moments to fully wrap your head
around what is happening.)&lt;/p&gt;

&lt;p&gt;My current favourite for doing that using the JS regex syntax is
an obscure tool called &lt;a href=&quot;http://www.gethifi.com/tools/regex&quot;&gt;Hifi Regex Tester&lt;/a&gt;.
Even though its usability isn’t too great (too many colours!) it is the only
one that I have found which displays match groups.&lt;/p&gt;

&lt;p&gt;If you can live without match groups, &lt;a href=&quot;http://refiddle.com/&quot;&gt;refiddle&lt;/a&gt; feels a
lot more modern and tidied up.&lt;/p&gt;

&lt;h3 id=&quot;your-favourites&quot;&gt;Your favourites&lt;/h3&gt;

&lt;p&gt;If you liked this little list, how about you letting me know about other
productivity enhancers?&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="development" />
      
        <category term="tools" />
      

      
        <summary type="html">Pro-forma preamble</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Slides for my talk at CocoaHeads Berlin</title>
      
      
      <link href="http://leonard.io/blog/2012/10/slides-for-my-talk-at-cocoaheads-berlin/" rel="alternate" type="text/html" title="Slides for my talk at CocoaHeads Berlin" />
      
      <published>2012-10-18T00:00:00+02:00</published>
      <updated>2012-10-18T00:00:00+02:00</updated>
      <id>http://leonard.io/blog/2012/10/slides-for-my-talk-at-cocoaheads-berlin</id>
      <content type="html" xml:base="http://leonard.io/blog/2012/10/slides-for-my-talk-at-cocoaheads-berlin/">&lt;p&gt;Yesterday I gave a talk at Cocoaheads Berlin, which is the iOS/OS X developers user group here. The talk was titled “CocoaPods - Sane library management for Xcode”.&lt;/p&gt;

&lt;p&gt;If you are interested in reading &lt;a href=&quot;http://lenni.info/talks/cocoapods/&quot;&gt;my HTML slide deck&lt;/a&gt;, I’ve made them available online.&lt;/p&gt;

&lt;p&gt;Here is the same thing in a little embedded viewer:&lt;/p&gt;

&lt;iframe src=&quot;http://www.slideshare.net/slideshow/embed_code/14779558&quot; width=&quot;476&quot; height=&quot;400&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Leonard Ehrenfried</name>
          
          
        </author>
      

      

      
        <category term="cocoheads" />
      
        <category term="Mixed" />
      
        <category term="slides" />
      
        <category term="talk" />
      

      
        <summary type="html">Yesterday I gave a talk at Cocoaheads Berlin, which is the iOS/OS X developers user group here. The talk was titled “CocoaPods - Sane library management for Xcode”.</summary>
      

      
      
    </entry>
  
  
</feed>
