<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Blog | Allie Jones</title><description>RSS feed for alliejon.es/blog</description><link>https://alliejon.es/</link><language>en-us</language><item><title>Migrating from MAMP to Homebrew</title><link>https://alliejon.es/blog/2013/02/15/migrating-from-mamp-to-a-homebrew-based-setup/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/02/15/migrating-from-mamp-to-a-homebrew-based-setup/</guid><pubDate>Fri, 15 Feb 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been using &lt;a href=&quot;http://www.mamp.info/&quot;&gt;MAMP&lt;/a&gt; (the free version, not MAMP Pro) on my local machine for development and testing for a long time, mostly out of laziness. &lt;a href=&quot;http://www.fuelphp.com/&quot;&gt;FuelPHP&lt;/a&gt;&apos;s &lt;code&gt;oil&lt;/code&gt; utility does not work well with MAMP&apos;s MySQL, however, so today I decided it was finally time to switch to using homebrew-installed MySQL and PHP and OSX 10.8&apos;s included Apache.&lt;/p&gt;
&lt;p&gt;It was generally painless (I used &lt;a href=&quot;http://blog.stevenlu.com/2012/10/12/moving-away-from-mamp-and-into-homebrew/&quot;&gt;these instructions&lt;/a&gt; and &lt;a href=&quot;http://coolestguyplanettech.com/downtown/install-and-configure-apache-mysql-php-and-phpmyadmin-osx-108-mountain-lion&quot;&gt;this blog post&lt;/a&gt; about enabling Apache on Mountain Lion) but I didn&apos;t want to have to recreate all of my local databases. Some Googling only turned up the location of MAMP Pro&apos;s database files. I found the files for regular MAMP at &lt;code&gt;/Applications/MAMP/db/mysql/&lt;/code&gt; and moved them to &lt;code&gt;/usr/local/var/mysql/&lt;/code&gt; and everything was good to go.&lt;/p&gt;
&lt;p&gt;While researching this, I also came across &lt;a href=&quot;http://eddmann.com/posts/the-ultimate-mamp-setup-hands-down/&quot;&gt;this blog post&lt;/a&gt; explaining a setup that automatically makes each folder in your &lt;code&gt;Sites&lt;/code&gt; directory available at &lt;code&gt;&amp;lt;foldername&amp;gt;.dev&lt;/code&gt; and set that up as well. It&apos;s awesome. No more editing my hosts file and Apache config!&lt;/p&gt;
</content:encoded></item><item><title>A new blog</title><link>https://alliejon.es/blog/2013/02/15/new-blog/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/02/15/new-blog/</guid><pubDate>Fri, 15 Feb 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of my recent personal goals has been to get more comfortable with writing about technical and programming topics. Starting a new blog seemed like a good way to practice this.&lt;/p&gt;
&lt;p&gt;So naturally I got totally sidetracked by choosing the right platform, trying to port over my portfolio to a new format and agonizing over what kind of design it should have ... which is why I haven&apos;t actually written anything, despite intending to for months now.&lt;/p&gt;
&lt;p&gt;However, for the next three months I am fortunate enough to be attending &lt;a href=&quot;http://www.hackerschool.com/&quot;&gt;Hacker School&lt;/a&gt;, where I have the freedom to learn about whatever cool and interesting programming topics I want---things I should definitely write about! So no more procrastination; Octopress&apos; default template it is.&lt;/p&gt;
&lt;p&gt;I&apos;ve been in New York and at Hacker School for a week now and so far things have been awesome. More thoughts on that later!&lt;/p&gt;
</content:encoded></item><item><title>JavaScript function statements vs. function expressions</title><link>https://alliejon.es/blog/2013/02/19/javascript-function-statements-vs-function-expressions/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/02/19/javascript-function-statements-vs-function-expressions/</guid><pubDate>Tue, 19 Feb 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I was talking about JavaScript scope today (and how, when first learning the language, I assumed JS had block rather than functional scope and was often confused). That reminded me of a seemingly-strange Javascript behavior I had discovered previously.&lt;/p&gt;
&lt;p&gt;When declaring functions, this works:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function two() {
  one();
}
two();
function one() {
  console.log(&quot;one!&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this does not (throwing the error &lt;code&gt;one is not a function&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var two = function () {
  one();
};
two();
var one = function () {
  console.log(&quot;one!&quot;);
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(I had trouble finding a concise way to describe these two methods of creating a function, but &lt;em&gt;JavaScript: The Good Parts&lt;/em&gt; enlightened me: function statements and function expressions.)&lt;/p&gt;
&lt;p&gt;This behavior happens because when JavaScript initially parses a file, it evaluates all of the function statements first, before executing anything. So a named function (a function statement) is always available before any code is executed, regardless of where the function appears in a file. An anonymous function assigned to a variable is only available after the variable is defined and assigned the function.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://danielmendel.github.com&quot;&gt;Daniel Mendel&lt;/a&gt;, fellow Hacker Schooler, talked through this with me and also wrote &lt;a href=&quot;http://danielmendel.github.com/blog/2013/02/20/cool-stuff-i-learned-doing-code-review/&quot;&gt;a blog post about it&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>HS Project: Makefolio</title><link>https://alliejon.es/blog/2013/03/01/hs-project-makefolio/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/03/01/hs-project-makefolio/</guid><pubDate>Fri, 01 Mar 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For my first project at Hacker School, I decided to build a static site generator for portfolios. (Wondering what a static site generator is? Here&apos;s a &lt;a href=&quot;http://www.odopod.com/blog/introduction-static-website-generators/&quot;&gt;pretty good explanation&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;I have attempted to migrate &lt;a href=&quot;http://alliejon.es/&quot;&gt;my portfolio&lt;/a&gt; to a few different static site generators without success. (I think the one I got farthest with was &lt;a href=&quot;http://laktek.github.com/punch/&quot;&gt;Punch&lt;/a&gt;, but I still ran into trouble.) My format of mostly images with a small amount of text was just not the sort of the website most generators&apos; authors had in mind, so trying to shoehorn my existing website into their format was difficult.&lt;/p&gt;
&lt;p&gt;Writing a site generator that handled collections of images well seemed like both a way to solve my problem and a perfectly-sized challenge. I wasn&apos;t totally sure how to accomplish it, but I had a general idea and a specific end goal in mind: being able to generate my current site using the tool I would write.&lt;/p&gt;
&lt;h2&gt;My goals&lt;/h2&gt;
&lt;h3&gt;Get more comfortable with Ruby&lt;/h3&gt;
&lt;p&gt;Prior to this project, I&apos;d written enough Ruby to know that I liked it, but hadn&apos;t built anything substantial. This was a great way to get more familar with the language (especially without the added complexity of Rails). Having other Hacker Schoolers review my code and suggest more Ruby-like ways to do things was incredibly helpful too.&lt;/p&gt;
&lt;h3&gt;Gain more experience structuring applications&lt;/h3&gt;
&lt;p&gt;Most of my previous programming experience involved working with pre-existing frameworks, and I want more experience making the structural decisions neccessary when building software from (mostly) scratch.&lt;/p&gt;
&lt;h3&gt;Try test-driven development&lt;/h3&gt;
&lt;p&gt;I think I&apos;m a convert! Though I felt like I was spending far too much time writing tests and trying to understand Rspec at the beginning of the project, by the mid-point I was so glad I had taken the time to write them. It felt great to be able to dramatically refactor things and know I hadn&apos;t broken everything. (A big benefit to my other goal of getting more experience organizing my code!)&lt;/p&gt;
&lt;h3&gt;Better understand how templating works&lt;/h3&gt;
&lt;p&gt;I have more to do on this one. I used basic ERB templates, but I can&apos;t say I really understand what is happening when I pass a Ruby &lt;code&gt;Binding&lt;/code&gt; object to a template. Something to investigate further.&lt;/p&gt;
&lt;h2&gt;Other things I learned&lt;/h2&gt;
&lt;p&gt;This was the first time I&apos;ve tried to write a thorough README for something I&apos;ve made, and I was surprised at how well it clarified what I wanted Makefolio to do. Multiple features and improvements occurred to me as I was writing. (I now have a better appreciation of Amazon&apos;s &lt;a href=&quot;http://www.allthingsdistributed.com/2006/11/working_backwards.html&quot;&gt;press release first&lt;/a&gt; method of product development!)&lt;/p&gt;
</content:encoded></item><item><title>Opening the box: things I learned while learning about sockets</title><link>https://alliejon.es/blog/2013/03/21/opening-box/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/03/21/opening-box/</guid><pubDate>Thu, 21 Mar 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the pieces of advice we were given at the beginning of Hacker School was &quot;open the box&quot;---that is, don&apos;t blindly use things in your programming projects without any idea of how they work. Don&apos;t gloss over things you don&apos;t understand, take the time to learn more about them. Feeling encouraged to really deepen your level of understanding (and having the time to do so!) is one of the best things about Hacker School&apos;s focus on learning and becoming a better programmer.&lt;/p&gt;
&lt;p&gt;One of my Hacker School goals is to fill in the gaps and fuzzy patches in my understanding of the web stack and how the Web works. Towards that end, this week I read through Jesse Storimer&apos;s &lt;a href=&quot;http://workingwithtcpsockets.com/&quot;&gt;Working with TCP Sockets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I kept track of all of the unfamiliar topics I found myself investigating further while reading through the book and writing my own code based on his examples. I&apos;d probably never finish this post if I wrote out explanations of each of these things, but even just the list is interesting.&lt;/p&gt;
&lt;h3&gt;Things I learned while learning about sockets&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;the TCP urgent flag (that no one ever uses)&lt;/li&gt;
&lt;li&gt;some of the differences between the MRI, JRuby and Rubinius implementations of Ruby&lt;/li&gt;
&lt;li&gt;Ruby functions that were new to me: &lt;code&gt;pack&lt;/code&gt;, &lt;code&gt;unpack&lt;/code&gt;, &lt;code&gt;exit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;C&apos;s fixed-width integer data type&lt;/li&gt;
&lt;li&gt;binary representation of text&lt;/li&gt;
&lt;li&gt;the concepts big-endian and little-endian&lt;/li&gt;
&lt;li&gt;4 bits (half a byte) is a &apos;nibble&apos; (Cute.)&lt;/li&gt;
&lt;li&gt;the difference between threads and processes&lt;/li&gt;
&lt;li&gt;the FTP specification&lt;/li&gt;
&lt;li&gt;POSIX signals (and capturing them in Ruby scripts)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the same vein as this, &lt;a href=&quot;http://www.sashalaundy.com&quot;&gt;Sasha Laundy&lt;/a&gt; has a great &lt;a href=&quot;http://blog.sashalaundy.com/blog/2013/03/25/on-rakefiles-and-rabbit-holes/&quot;&gt;post about how she learned all kinds of things while trying to fix a bug in Octopress&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Missing dependencies with Heroku, Python and pip</title><link>https://alliejon.es/blog/2013/03/28/dependencies-heroku-python-pip/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/03/28/dependencies-heroku-python-pip/</guid><pubDate>Thu, 28 Mar 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been experimenting with some machine learning techniques after &lt;a href=&quot;http://www.hilarymason.com/&quot;&gt;Hilary Mason&lt;/a&gt; spoke about it to Hacker School last week. I&apos;ll save discussing exactly what I&apos;ve been working on for another post, but I&apos;ve been programming in Python to take advantage of the libraries available to assist with the math involved.&lt;/p&gt;
&lt;p&gt;I want to build some web applications based on my scripts, so I&apos;ve been working on a bare-bones Flask app to provide their results in &lt;code&gt;json&lt;/code&gt; format. Getting a server running on EC2 proved beyond my sysadmin abilities and patience at the moment, so I decided to deploy to Heroku instead.&lt;/p&gt;
&lt;p&gt;My script uses the &lt;code&gt;hcluster&lt;/code&gt; library, which depends on &lt;code&gt;numpy&lt;/code&gt;, and this is where I ran into trouble. When I pushed my application to Heroku, it would attempt to install the packages in &lt;code&gt;pip&lt;/code&gt;&apos;s &lt;code&gt;requirements.txt&lt;/code&gt;. &lt;code&gt;hcluster&lt;/code&gt; would fail to install because it couldn&apos;t find &lt;code&gt;numpy&lt;/code&gt;, even if &lt;code&gt;pip&lt;/code&gt; had already attempted to install &lt;code&gt;numpy&lt;/code&gt; (or so I thought). This happened regardless of the order of the packages in the requirements file.&lt;/p&gt;
&lt;p&gt;The solution turned out to be removing &lt;code&gt;hcluster&lt;/code&gt; from &lt;code&gt;requirements.txt&lt;/code&gt; temporarily, pushing to Heroku so &lt;code&gt;numpy&lt;/code&gt; would be installed successfully, then restoring &lt;code&gt;hcluster&lt;/code&gt; to &lt;code&gt;requirements.txt&lt;/code&gt; and pushing again. Not the most elegant fix, but it worked. &lt;a href=&quot;http://stackoverflow.com/questions/11797688/matplotlib-requirements-with-%60pip%60-install-in-virtualenv&quot;&gt;This StackOverflow question&lt;/a&gt; about a different library pointed me towards this solution.&lt;/p&gt;
&lt;p&gt;It turns out that &lt;code&gt;pip&lt;/code&gt; first runs each module&apos;s &lt;code&gt;setup.py&lt;/code&gt;, then installs. (So I thought &lt;code&gt;numpy&lt;/code&gt; was being installed first, but it actually wasn&apos;t.) Apparently checking for module dependencies in the setup script is an incorrect use of &lt;code&gt;setup.py&lt;/code&gt;, but it seems like &lt;code&gt;hcluster&lt;/code&gt; isn&apos;t the only library to do so. There&apos;s also &lt;a href=&quot;https://github.com/pypa/pip/issues/25&quot;&gt;a Github issue&lt;/a&gt; for &lt;code&gt;pip&lt;/code&gt; that provides more context.&lt;/p&gt;
</content:encoded></item><item><title>SPACEJUMP</title><link>https://alliejon.es/blog/2013/03/31/spacejump/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/03/31/spacejump/</guid><pubDate>Sun, 31 Mar 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A Hacker School facilitator recommended Michal Zalewski&apos;s &lt;em&gt;The Twisted Web&lt;/em&gt; to me, and I&apos;ve really been enjoying it. I&apos;d say it&apos;s the most entertaining highly technical book I&apos;ve ever read, and it is densely packed with great information about how the Web works.&lt;/p&gt;
&lt;p&gt;However, I was reading it this afternoon and was distracted from its more substantial content by an offhand comment about the HTTP SPACEJUMP method. I was offline right then (thanks, laundromat with crappy cell reception) and couldn&apos;t look up its actual use, but it seemed like a charming Easter egg in the HTTP protocol.&lt;/p&gt;
&lt;p&gt;Sadly, SPACEJUMP has nothing to do with astronauts as I was imagining. It was intended for &lt;a href=&quot;http://www.w3.org/Protocols/HTTP/Methods/SpaceJump.html&quot;&gt;something like an image map&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;m a little disappointed. &lt;a href=&quot;http://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol&quot;&gt;HTTP response code 418 (I&apos;m a teapot)&lt;/a&gt; will have to remain my favorite bit of web protocol silliness.&lt;/p&gt;
</content:encoded></item><item><title>Use your Github code as a website background</title><link>https://alliejon.es/blog/2013/03/31/use-your-github-code-as-a-website-background/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/03/31/use-your-github-code-as-a-website-background/</guid><pubDate>Sun, 31 Mar 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been thinking about the best way to add my Hacker School projects to my portfolio. Prior to the past six weeks, I haven&apos;t written much code I could share publicly, and most of my projects included enough design that it wasn&apos;t difficult to create a representative screenshot. That&apos;s not the case with everything I&apos;m working on now.&lt;/p&gt;
&lt;p&gt;Displaying the source code itself seemed like a good possible solution---maybe not &lt;em&gt;quite&lt;/em&gt; as interesting as images, but not bad. But I didn&apos;t want to have to copy and paste code or clutter up my HTML with what would be essentially decorative text.&lt;/p&gt;
&lt;h2&gt;The final product&lt;/h2&gt;
&lt;p&gt;&amp;lt;pre class=&quot;codepen&quot; data-height=&quot;300&quot; data-type=&quot;result&quot; data-href=&quot;vExdA&quot; data-user=&quot;alliejones&quot; data-safe=&quot;true&quot;&amp;gt;&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;a href=&quot;https://codepen.io/alliejones/pen/vExdA&quot;&amp;gt;Check out this Pen!&amp;lt;/a&amp;gt;&amp;lt;/pre&amp;gt;
&amp;lt;script async src=&quot;https://codepen.io/assets/embed/ei.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;h2&gt;Loading the source code&lt;/h2&gt;
&lt;p&gt;My first thought was to use a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag, similar to the way JavaScript templates can be embedded in a page. Something like this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;text&quot; src=&quot;/path/to/code.rb&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That doesn&apos;t work, however. JavaScript can&apos;t access the script tag&apos;s contents unless the code is embedded in the page, rather than linked, so I&apos;d still have to copy and paste. (There may be other problems with this approach, too, but I didn&apos;t pursue it any further.)&lt;/p&gt;
&lt;p&gt;I then realized that Github has an API, and most of my code is already hosted there, so I wouldn&apos;t even have to do any extra work to make the source accessible. Perfect.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://developer.github.com/v3/&quot;&gt;Github&apos;s API&lt;/a&gt; supports &lt;a href=&quot;http://en.wikipedia.org/wiki/JSONP&quot;&gt;JSONP&lt;/a&gt;, so you can access it via JavaScript from any domain. (I just learned recently that jQuery includes support for JSONP AJAX requests. It handles the callback function for you so that a JSONP request can be treated like a normal AJAX request.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$.getJSON(
  &quot;https://api.github.com/repos/alliejones/makefolio/contents/lib/makefolio/project.rb?callback=?&quot;,
  function (response) {
    var code = Base64.decode(response.data.content);
    $(&quot;div&quot;).attr(&quot;data-code&quot;, code); // see below
  }
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The one complication is that the file contents are base-64 encoded in Github&apos;s response, so I had to find &lt;a href=&quot;https://github.com/dankogai/js-base64/&quot;&gt;a JavaScript base-64 decoding library that supported utf-8&lt;/a&gt;. (Only Firefox has built in functions to encode/decode base-64 data, and even it &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/DOM/window.btoa#Unicode_Strings&quot;&gt;requires a workaround for utf-8&lt;/a&gt;.)&lt;/p&gt;
&lt;h2&gt;Getting it on the page with CSS&lt;/h2&gt;
&lt;p&gt;Using a pseudo-element seemed like the best approach in this case, since I&apos;m creating a largely decorative effect and trying to avoid having to change the structure of my HTML.&lt;/p&gt;
&lt;p&gt;By combining the &lt;code&gt;attr()&lt;/code&gt; &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/CSS/attr&quot;&gt;CSS expression&lt;/a&gt;, CSS generated content and a &lt;a href=&quot;http://html5doctor.com/html5-custom-data-attributes/&quot;&gt;custom data attribute&lt;/a&gt;, you can set the contents of a pseudo element to pretty much any text.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;attr()&lt;/code&gt; is applied to a pseudo-element, its context is the pseudo-element&apos;s parent element, so the data attribute should be set on the original, content-containing element. The custom data attribute doesn&apos;t even need to exist in the HTML---it can be added via jQuery, as I&apos;m doing in my AJAX request callback.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$(&quot;div&quot;).attr(&quot;data-code&quot;, code);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(An aside: jQuery includes a &lt;a href=&quot;http://api.jquery.com/data/&quot;&gt;&lt;code&gt;data&lt;/code&gt;&lt;/a&gt; function that can be used to &lt;em&gt;access&lt;/em&gt; custom data attributes that have been set on HTML elements, but using that function to &lt;em&gt;set&lt;/em&gt; custom data doesn&apos;t update the DOM, so it won&apos;t work in this case.)&lt;/p&gt;
&lt;p&gt;With a few additional CSS properties to set the appropriate monospaced font and place our background text behind the actual content, this is ready for whatever additional styling you might like to add.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;div {
  position: relative;
}

div:after {
  content: attr(data-code);
  font-family: monospace;
  top: 0;
  left: 0;
  max-height: 100%;
  max-width: 100%;
  overflow: hidden;
  position: absolute;
  white-space: pre;
  z-index: -1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It isn&apos;t possible to have syntax highlighted code with this particular CSS approach, because the &lt;code&gt;content&lt;/code&gt; property only supports plain text. I&apos;m okay with single-color code in this case, and didn&apos;t want to deal with integrating a code highlighting library as well, but you could probably wrangle something by adding the extra HTML elements containing your highlighted code to the page via JavaScript.&lt;/p&gt;
&lt;h2&gt;Additional considerations&lt;/h2&gt;
&lt;h3&gt;Don&apos;t use Github as a CDN&lt;/h3&gt;
&lt;p&gt;The first version of my sample on Codepen was broken in Chrome Canary for a reason unrelated to what I was ultimately trying to achieve. Out of laziness, I was linking to a base-64 decoding library hosted on &lt;code&gt;raw.github.com&lt;/code&gt;, and Canary refused to load it.&lt;/p&gt;
&lt;p&gt;Github serves raw source code files with the MIME type of &lt;code&gt;text/plain&lt;/code&gt; and the HTTP header &lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt;. That header was new to me, but it is basically a request from the server that browsers accept the MIME type specified, rather than trying to guess what type of file they may be receiving. The end result is that browsers that respect the &lt;code&gt;nosniff&lt;/code&gt; header won&apos;t execute JavaScript code sent as &lt;code&gt;text/plain&lt;/code&gt;. (Github does this because they&apos;d prefer you didn&apos;t hotlink to raw source code in a repository, which seems pretty reasonable.)&lt;/p&gt;
&lt;p&gt;This is a recent change in Canary that will eventually make its way to Chrome. IE already supports &lt;code&gt;nosniff&lt;/code&gt; and Firefox is planning to do so. There&apos;s &lt;a href=&quot;https://code.google.com/p/chromium/issues/detail?id=180007&quot;&gt;a Chromium issue&lt;/a&gt; that explains further.&lt;/p&gt;
&lt;h3&gt;Browser support and accessibility&lt;/h3&gt;
&lt;p&gt;Browser support for this isn&apos;t bad (Webkit, Firefox, IE 10), though since the source code is loaded asynchronously (and therefore doesn&apos;t block the page from rendering) and this is really just a cool detail rather than critical content, it degrades nicely in older browsers.&lt;/p&gt;
&lt;p&gt;Github&apos;s API is only available over HTTPS, so some browsers may refuse to make the AJAX request if the initiating page was loaded over HTTP. (This may be why it doesn&apos;t work in earlier versions of IE, but I&apos;m not sure.)&lt;/p&gt;
&lt;p&gt;CSS generated content is printed by default, so the code should probably be hidden in a print stylesheet. Apparently &lt;a href=&quot;http://www.456bereastreet.com/archive/201205/css_generated_content_and_screen_readers/&quot;&gt;screenreaders&apos; behavior with pseudo-elements&lt;/a&gt; varies widely, so I&apos;m not sure what the best solution to that would be.&lt;/p&gt;
</content:encoded></item><item><title>Getting started with Grunt</title><link>https://alliejon.es/blog/2013/04/04/getting-started-with-grunt/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/04/04/getting-started-with-grunt/</guid><pubDate>Thu, 04 Apr 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I love &lt;a href=&quot;http://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt;. I wouldn&apos;t want to work on a JavaScript project much bigger than a file or two without it, now that I&apos;ve realized how much time and hassle it saves me.&lt;/p&gt;
&lt;p&gt;But getting started using it involves a lot of friction. Even though I&apos;m familiar with the tool I still drag my feet setting it up on a new project.&lt;/p&gt;
&lt;p&gt;Yesterday, so that I would no longer have this problem, I created a template Gruntfile for myself. It contains the tasks I use on nearly every project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JavaScript linting (with JSHint)&lt;/li&gt;
&lt;li&gt;file concatenation and compression (using Uglify)&lt;/li&gt;
&lt;li&gt;file watching (so that I don&apos;t have to invoke Grunt manually every time I change a file)&lt;/li&gt;
&lt;li&gt;Growl notifications for warnings and errors (so you don&apos;t have to waste screen space keeping your terminal visible)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the exception of Growl, these are all official Grunt packages.&lt;/p&gt;
&lt;p&gt;This would be a great starter configuration for someone new to Grunt, and once you have this setup working it is easy to find and add new tasks. Using it is pretty straightforward, but I&apos;ll explain the important details below. (I&apos;ve also saved this file &lt;a href=&quot;https://gist.github.com/alliejones/5306809&quot;&gt;as a gist&lt;/a&gt; if you want to save your own changes.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module.exports = function (grunt) {
  var defaultTasks = [&quot;jshint&quot;, &quot;concat&quot;, &quot;uglify&quot;]; // used for watch as well

  var files = [
    /* your source files */
  ];

  grunt.initConfig({
    jshint: { all: files.concat([&quot;Gruntfile.js&quot;]) },

    concat: {
      all: {
        src: files,
        dest: &quot;project.all.js&quot;,
      },
    },

    uglify: {
      all: { files: { &quot;project.min.js&quot;: files } },
    },

    watch: {
      all: {
        files: files,
        tasks: defaultTasks,
        options: { debounceDelay: 250 },
      },
    },
  });

  grunt.loadNpmTasks(&quot;grunt-contrib-concat&quot;);
  grunt.loadNpmTasks(&quot;grunt-contrib-uglify&quot;);
  grunt.loadNpmTasks(&quot;grunt-contrib-watch&quot;);
  grunt.loadNpmTasks(&quot;grunt-contrib-jshint&quot;);

  grunt.registerTask(&quot;default&quot;, defaultTasks);

  var growl = require(&quot;growl&quot;);

  [&quot;warn&quot;, &quot;fatal&quot;].forEach(function (level) {
    grunt.util.hooker.hook(grunt.fail, level, function (opt) {
      growl(opt.name, {
        title: opt.message,
        image: &quot;Console&quot;,
      });
    });
  });
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A note: These instructions assume you are using OSX.&lt;/p&gt;
&lt;h3&gt;Requirements&lt;/h3&gt;
&lt;p&gt;Grunt requires &lt;a href=&quot;http://nodejs.org/&quot;&gt;Node.js and npm&lt;/a&gt; to be installed (npm, Node&apos;s package manager, is included in the Node installer).&lt;/p&gt;
&lt;p&gt;Grunt comes in two parts, one that only needs to be installed once and a second that is installed for each project.&lt;/p&gt;
&lt;p&gt;The first time you set up Grunt, you should run &lt;code&gt;npm -g install grunt-cli&lt;/code&gt;. This makes the &lt;code&gt;grunt&lt;/code&gt; command available on your system. (&lt;a href=&quot;http://gruntjs.com/getting-started#how-the-cli-works&quot;&gt;More information here&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Then, from the root directory of the project you&apos;d like to use Grunt with, run the following to install the packages you need via npm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install grunt
npm install grunt-contrib-concat
npm install grunt-contrib-uglify
npm install grunt-contrib-watch
npm install grunt-contrib-jshint
npm install growl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Growl notifications also require that Growl be installed, as well as the Growl command line tool &lt;code&gt;growlnotify&lt;/code&gt; (&lt;a href=&quot;http://growl.info/downloads#generaldownloads&quot;&gt;downloadable here&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;Configuration&lt;/h3&gt;
&lt;p&gt;You should save the Gruntfile to your project&apos;s root directory with the filename &lt;code&gt;Gruntfile.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Gruntfiles are just JavaScript, so you can use variables and functions as you normally would. I&apos;ve set up this Gruntfile so that you only have to specify the locations of your project&apos;s JavaScript files once, at the top of the file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var files = [&quot;main.js&quot;, &quot;src/**/*.js&quot;];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This array of file paths will be passed to each Grunt task automatically. Grunt supports glob paths as well (so &lt;code&gt;src/**/*.js&lt;/code&gt; will include every file with the extension &lt;code&gt;.js&lt;/code&gt; in any subfolder of &lt;code&gt;src&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If you need specify files in a more particular fashion, the &lt;a href=&quot;http://gruntjs.com/configuring-tasks#files&quot;&gt;supported syntax&lt;/a&gt; is extremely flexible and powerful, but I rarely find myself needing that much complexity.&lt;/p&gt;
&lt;p&gt;To actually use the tasks you&apos;ve configured, run &lt;code&gt;grunt watch&lt;/code&gt; from the root directory of your project. Your JavaScript files will be automatically checked for errors, concatenated and minified each time you modify a file, and your JavaScript build process will be much less tedious!&lt;/p&gt;
</content:encoded></item><item><title>Full-bleed images with TCPDF</title><link>https://alliejon.es/blog/2013/06/07/full-bleed-images-with-tcpdf/</link><guid isPermaLink="true">https://alliejon.es/blog/2013/06/07/full-bleed-images-with-tcpdf/</guid><pubDate>Fri, 07 Jun 2013 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The current PHP project I&apos;m working on needs to generate PDFs, and I&apos;m using the &lt;a href=&quot;http://www.tcpdf.org/&quot;&gt;TCPDF class&lt;/a&gt; to do so. TCPDF, while powerful, has &lt;a href=&quot;http://www.tcpdf.org/doc/code/classTCPDF.html&quot;&gt;documentation&lt;/a&gt; that is ... not very user-friendly, to put it mildly.&lt;/p&gt;
&lt;p&gt;I ran into problems trying to display an SVG file as a full-bleed image (that is, I didn&apos;t want white space between the edges of the PDF document and the image). I would set the document size and the SVG display size to the same values, and set the document margins to zero, and yet, infuriatingly, my SVG file would display just &lt;em&gt;slightly&lt;/em&gt; smaller than the full page size.&lt;/p&gt;
&lt;p&gt;After some searching and experimentation, I found another margin property that needed to be changed. To remove &lt;em&gt;all&lt;/em&gt; of the margins on a TCPDF-generated PDF file, you need to set the bottom margin of each page via the &lt;code&gt;setPageOrientation&lt;/code&gt; method as well as &lt;code&gt;setMargins&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The bottom margin was creating whitespace on the file&apos;s right edge as well, because the SVG file was maintaining its original aspect ratio.&lt;/p&gt;
&lt;p&gt;The full code to remove all of the margins on the page was this (the header and footer also have to be disabled):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
$pdf = new TCPDF(/* ... */);
$pdf-&amp;gt;setPrintHeader(false);
$pdf-&amp;gt;setPrintFooter(false);
$pdf-&amp;gt;setMargins(0, 0, 0, true);
$pdf-&amp;gt;setPageOrientation(&apos;&apos;, false, 0);
// the third argument above is the bottom margin size
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>The old year and the new one</title><link>https://alliejon.es/blog/2014/01/19/the-old-year-and-the-new-one/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/01/19/the-old-year-and-the-new-one/</guid><pubDate>Sun, 19 Jan 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2013 was probably the most eventful year I&apos;ve had in my post-school life: in the space of ten days this past August, I got married, moved to a new (big!) city and started a new job as a &quot;real&quot; programmer.&lt;/p&gt;
&lt;p&gt;Though it seems implausible even to me, I didn&apos;t have any of these things planned at the beginning of 2013. I applied to Hacker School on a whim around New Year&apos;s 2012, and deciding to attend set all of these things in motion. (Well, that, and the Rhode Island legislature finally getting their act together on gay marriage.)&lt;/p&gt;
&lt;p&gt;I never did write a substantial Hacker School reflection post, but I am without question a better and more confident programmer, I have a bunch of new friends &lt;em&gt;and&lt;/em&gt; my new job (at &lt;a href=&quot;http://www.photoshelter.com/&quot;&gt;Photoshelter&lt;/a&gt;) makes me much happier every day. I&apos;d definitely call that as a success.&lt;/p&gt;
&lt;p&gt;I&apos;m not one to talk about my personal life on the internet much (at least now that the livejournal chronicling my teenage years is gone, hah), but beyond all of the awesome tech-related things that I accomplished this year, getting to marry my favorite person was still the best.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I expect 2014 will be a little quieter, and I&apos;m more than content with that, but I have put some thought into things I&apos;d like to do this year. I&apos;m being not-particularly-ambitious in the hopes I&apos;ll be more likely to actually accomplish everything.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Finish reading and working through &lt;em&gt;The Elements of Computing Systems&lt;/em&gt; (aka &lt;a href=&quot;http://www.nand2tetris.org/&quot;&gt;nand2tetris&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Work through at least a few chapters of &lt;a href=&quot;http://mitpress.mit.edu/sicp/&quot;&gt;SICP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Build some toy projects with &lt;a href=&quot;http://angularjs.org/&quot;&gt;AngularJS&lt;/a&gt; and &lt;a href=&quot;http://facebook.github.io/react/&quot;&gt;React&lt;/a&gt;, and possibly give Clojure/ClojureScript a try&lt;/li&gt;
&lt;li&gt;Blog more (I&apos;m doing a friendly blog-post-a-week competition, starting this week, so I hope it will help!)&lt;/li&gt;
&lt;li&gt;More generally, do more substantial things and fewer bite-size things (e.g.: less Twitter, more books; less tiny iOS puzzle games, more getting through the huge backlog of things I would like to play ...)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was thinking along these lines before I stumbled upon this blog post, but Michael Lopp&apos;s essay &lt;a href=&quot;http://randsinrepose.com/archives/the-builders-high/&quot;&gt;The Builder&apos;s High&lt;/a&gt; is a more eloquent explanation of my fuzzier thoughts.&lt;/p&gt;
</content:encoded></item><item><title>An art school lesson</title><link>https://alliejon.es/blog/2014/02/02/an-art-school-lesson/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/02/02/an-art-school-lesson/</guid><pubDate>Sun, 02 Feb 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The first studio class I attended my first week of college was three-dimensional design. I was extremely nervous, and things started strangely. The professor was absent, and had left a TA who instructed each student to each choose an art postcard from a collection pinned to the wall, with no further guidelines.&lt;/p&gt;
&lt;p&gt;Once everyone in the class had chosen a postcard, we were told our assignment was to recreate these paintings in three dimensions. Newspaper and tape were distributed. We had a few hours to put together a rough proposal of our ideas for how to build our projects.&lt;/p&gt;
&lt;p&gt;I can&apos;t remember the artist or title of painting I chose, though they were all abstract or stylized in some way that made translating the image to three dimensions challenging.&lt;/p&gt;
&lt;p&gt;What I do remember is what the professor said to me once I had hesitantly presented my idea to him: &quot;That looks great. But you should make it twice that size.&quot; A simple suggestion, but an intimidating one for me--I hardly knew how I was going to build this project at all, let alone at a large scale. But he was the professor, so I took his advice.&lt;/p&gt;
&lt;p&gt;There wasn&apos;t much for me to do after that except start working, so I did. What I realized is that you don&apos;t have to know how the entire thing is going to come together when you begin something: just start with a small part, learn as you go, and build from there. It wasn&apos;t completely smooth sailing, but my project turned out great, and I felt awesome about making something much more ambitious than I thought I could.&lt;/p&gt;
&lt;p&gt;I still think about that experience often when I am starting something new. &quot;Great, but make it bigger!&quot; isn&apos;t useful advice for everyone, but for me, as a person who tends to be more pragmatic and conservative than I need to be, it makes a big difference.&lt;/p&gt;
&lt;p&gt;I don&apos;t make ambitious art projects as often anymore, but I find &quot;make it bigger!&quot; applies well to programming, too.&lt;/p&gt;
&lt;p&gt;When I started &lt;a href=&quot;https://github.com/alliejones/doodler&quot;&gt;my collaborative drawing app&lt;/a&gt;, I barely knew how any of the parts would work. Handling real-time events seemed intimidating, and so did working with TCP sockets. But I figured I could learn enough to build a tiny terminal-based chat, and I did. Once that existed, rewriting what I had using EventMachine seemed straightforward, and then it didn&apos;t seem so difficult to switch to using websockets instead.&lt;/p&gt;
&lt;p&gt;Setting a goal that seemed slightly scary and working towards it a small piece at a time got me much farther than I would have thought I could at the beginning. An excellent thing to remember any time a new programming task or skill seems daunting.&lt;/p&gt;
</content:encoded></item><item><title>Javascript: String.replace()</title><link>https://alliejon.es/blog/2014/02/09/javascript-string-replace/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/02/09/javascript-string-replace/</guid><pubDate>Sun, 09 Feb 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve always used &lt;code&gt;String.replace()&lt;/code&gt; in Javascript pretty much like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;Some &amp;lt;foo&amp;gt;&quot;.replace(&quot;&amp;lt;foo&amp;gt;&quot;, &quot;bar&quot;);
// &apos;Some bar&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or with a regular expression if I was feeling fancy or the pattern to match was more complex:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;Some &amp;lt;foo&amp;gt;&quot;.replace(/&amp;lt;\w+&amp;gt;/, &quot;bar&quot;);
// &apos;Some bar&apos;

&quot;Some &amp;lt;baz&amp;gt; and a bit of &amp;lt;foo&amp;gt;&quot;.replace(/&amp;lt;\w+&amp;gt;/g, &quot;bar&quot;);
// &apos;Some bar and a bit of bar&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What I didn&apos;t realize until this week is that you can also &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter&quot;&gt;pass a callback function&lt;/a&gt; to &lt;code&gt;replace()&lt;/code&gt;, which makes it possible to perform more complicated (and also possibly easier to follow) manipulation of the matched portions of the string before they&apos;re replaced.&lt;/p&gt;
&lt;p&gt;You could even use this to create a super simple (and, sure, probably inadvisable) templating system:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var variables = { foo: &quot;one&quot;, bar: &quot;two&quot;, baz: &quot;sea&quot; };
var template = &quot;{{foo}} if by land, {{bar}} if by {{baz}}&quot;;

template.replace(/\{\{(\w+)\}\}/g, function (match, group, offset, string) {
  return variables[group];
});
// &apos;one if by land, two if by sea&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The function is called once for each match within the string, and each parenthesized group in the match gets passed as a parameter to the callback function (which does mean the number of function parameters is variable, based on how many groups you have in your regular expression). Here I&apos;ve used grouping to pull out the variable name inside the &lt;code&gt;&amp;amp;lcub;&amp;amp;lcub; &amp;amp;rcub;&amp;amp;rcub;&lt;/code&gt; delimiters and use it as an object property.&lt;/p&gt;
&lt;p&gt;Not a Javascript feature I will use every day, but definitely one that will come in handy occasionally (and most likely be much cleaner than whatever code I might have written without it).&lt;/p&gt;
</content:encoded></item><item><title>The best games I&apos;ve played recently</title><link>https://alliejon.es/blog/2014/02/16/the-best-games-ive-played-recently/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/02/16/the-best-games-ive-played-recently/</guid><pubDate>Sun, 16 Feb 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Though I will happily play a typical AAA-style video game when an appealing one comes along, most of my gaming time recently has been spent playing casual puzzle games and more experimental things, so I&apos;ve divided my list into those categories.&lt;/p&gt;
&lt;h2&gt;Puzzles&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://asherv.com/threes/&quot;&gt;Threes&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;iOS&lt;/em&gt;&lt;br /&gt;
Beautiful design, simple rules and surprisingly deep strategy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.blendoku.com/&quot;&gt;Blendoku&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;iOS, Android&lt;/em&gt;&lt;br /&gt;
Crossword puzzles that use colors instead of words. Like color theory excercises turned into a surprisingly fun game.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.enjoysudoku.com/&quot;&gt;Enjoy Sudoku&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;iOS, Android, OSX&lt;/em&gt;&lt;br /&gt;
This isn&apos;t a particularly attractive version of Sudoku, but it&apos;s become my favorite. It&apos;s the only Sudoku app I&apos;ve found that helps you learn more complex solving strategies.&lt;/p&gt;
&lt;h2&gt;Experimental Narratives&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://mrgan.com/blackbar/&quot;&gt;Blackbar&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;iOS, Android&lt;/em&gt;&lt;br /&gt;
A game told through censored letters. Puzzling out what words have been blacked out to advance through the story is surprisingly compelling.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://simogo.com/games/device6/&quot;&gt;Device 6&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;iOS&lt;/em&gt;&lt;br /&gt;
A beautifully designed short story turned into a puzzle game. Sometimes frustrating, but interesting and clever. The developer Simogo&apos;s other game &lt;a href=&quot;http://simogo.com/games/yearwalk/&quot;&gt;Year Walk&lt;/a&gt; is very different in presentation (more like an adventure game) but also worthwhile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.brothersthegame.com/&quot;&gt;Brothers: A Tale of Two Sons&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;PC, PS3, XBox&lt;/em&gt;&lt;br /&gt;
An interesting take on tightly tying a game&apos;s control scheme and story: you play both title characters at once, controlling one brother with each analog stick. I loved the dark-but-beautiful fairy tale setting, and though the plot was a little heavy-handed it was still affecting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.aksysgames.com/999/&quot;&gt;999: 9 Hours, 9 Persons, 9 Doors&lt;/a&gt;&lt;/strong&gt;  &lt;em&gt;3DS&lt;/em&gt;&lt;br /&gt;
A visual novel and escape-the-room game hybrid. The plot is ridiculous, but I found the game enjoyably suspenseful and creepy regardless.&lt;/p&gt;
</content:encoded></item><item><title>Thoughts on debugging JavaScript, part one</title><link>https://alliejon.es/blog/2014/02/23/thoughts-on-debugging-javascript/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/02/23/thoughts-on-debugging-javascript/</guid><pubDate>Sun, 23 Feb 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Spending the past few months becoming familiar with a large and complex JavaScript codebase has been a learning experience. I have had a few tearing-my-hair-out moments of frustration, but I&apos;ve also become a much more systematic debugger. In the hopes it might be helpful, and also to clarify these things for myself, here are some notes on the topic.&lt;/p&gt;
&lt;p&gt;It turns out I have a lot of feelings about browser devtools, so that&apos;s going to be Part One. Part Two will be less specific to debugging JavaScript in the browser, and hopefully more generally applicable.&lt;/p&gt;
&lt;h2&gt;Befriend your developer tools&lt;/h2&gt;
&lt;p&gt;Seriously. There are so many useful things hiding in there you probably haven&apos;t discovered yet. I&apos;m not such a devotee that I &lt;a href=&quot;http://remysharp.com/2013/07/18/my-workflow-v3-full-coding-stack/&quot;&gt;use the devtools as my editor&lt;/a&gt; (maybe someday), but I do pretty much always have them open while I&apos;m working.&lt;/p&gt;
&lt;p&gt;I prefer the Chrome tools, mostly arbitrarily, but Safari and Firefox have very similar features. CodeSchool has a free &lt;a href=&quot;http://discover-devtools.codeschool.com/&quot;&gt;Chrome devtools course&lt;/a&gt; that&apos;s helpful for getting started.&lt;/p&gt;
&lt;p&gt;In my own debugging, I use the Elements, Network and Console panels most heavily (learning the profiling tools better is on my to-do list).&lt;/p&gt;
&lt;p&gt;I think the Elements panel is pretty straightforward and self-explantory, but the Network and Console panels have a lot of hidden functionality you might be unfamiliar with. (And I&apos;m sure they are plenty more things I haven&apos;t discovered yet either.)&lt;/p&gt;
&lt;h3&gt;Network&lt;/h3&gt;
&lt;p&gt;The Network panel is useful for answering questions like, &quot;Did this ajax request even happen?&quot; or &quot;What data did I just post to the server?&quot;.&lt;/p&gt;
&lt;p&gt;Clicking on a filename in the Name column will open a detail pane with lots of information about your request. It is usually hidden by the expanded-by-default Request Headers section, but the form data passed with the request (something I often want to check) is recorded here. Viewing the server&apos;s response (helpfully under that Response tab) can be useful when debugging too.&lt;/p&gt;
&lt;p&gt;Also, I&apos;m filtering the requests by type in this screenshot, limiting it to only ajax/XHR requests. This helps a lot with finding the actual requests you&apos;re interested in, since I don&apos;t particularly care about images if I&apos;m trying to figure out why an ajax request is broken.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It took me far too long to realize that if you hover over the filename in the Initiator column, you can view a stack trace that shows where an ajax request came from. So here&apos;s a screenshot of that, too, so you don&apos;t have to discover it accidentally like I did.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Console&lt;/h3&gt;
&lt;p&gt;I use the console a lot for trying out and troubleshooting small pieces of code, but it can also be useful if you&apos;re trying to understand an unfamiliar codebase.&lt;/p&gt;
&lt;p&gt;If there is a class (or jQuery plugin, or whatever) whose behavior seems mysterious, trying to use it and poking around in its properties from the console can often help clarify things. (If the class in question is inside a module or otherwise out of scope, I&apos;ll edit the code temporarily to set it as a property of &lt;code&gt;window&lt;/code&gt;, so it will be accessible from the console.)&lt;/p&gt;
&lt;h3&gt;Extras&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;debugger&lt;/code&gt; &lt;a href=&quot;https://developers.google.com/chrome-developer-tools/docs/console#setting_breakpoints_in_javascript&quot;&gt;keyword&lt;/a&gt; is incredibly useful, and often better than using &lt;code&gt;console.log&lt;/code&gt; (though I use that often, too) or trying to set breakpoints in large files. It will pause code execution wherever you put it, allowing you to see the current state of the application and step through what is happening.&lt;/p&gt;
&lt;p&gt;When paused in the debugger, the &quot;Continue to here&quot; option can be useful for jumping into callback functions (which can be tricky or tedious to do otherwise). That option is available by right-clicking on the line number you&apos;d like to stop at.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;console.trace&lt;/code&gt; can also come in handy. It is similar to &lt;code&gt;console.log&lt;/code&gt;, but prints a stack trace to the console instead of its passed arguments.&lt;/p&gt;
&lt;p&gt;More thoughts (and less devtools nerdery) next week!&lt;/p&gt;
</content:encoded></item><item><title>Thoughts on debugging JavaScript, part two</title><link>https://alliejon.es/blog/2014/03/02/thoughts-on-debugging-javascript-part-two/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/03/02/thoughts-on-debugging-javascript-part-two/</guid><pubDate>Sun, 02 Mar 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Link } from &quot;gatsby&quot;;&lt;/p&gt;
&lt;p&gt;Following up my &lt;a href=&quot;/blog/2014/02/23/thoughts-on-debugging-javascript/&quot;&gt;dev tools lovefest&lt;/a&gt;, I have some more advice on debugging JavaScript, including some approaches I find helpful and editor features worth learning. First, some strategy:&lt;/p&gt;
&lt;h2&gt;Develop a theory&lt;/h2&gt;
&lt;p&gt;Starting the process of tracking down a bug can be overwhelming if you&apos;re working on code you&apos;re unfamiliar with, either because you&apos;ve never seen it before or because you wrote it months ago and have completely forgotten about its details. It is easy (for me, anyway) to feel paralyzed by not even knowing how things were &lt;em&gt;intended&lt;/em&gt; to work or how all of the pieces fit together, let alone what component is now causing problems.&lt;/p&gt;
&lt;p&gt;One approach I find helpful in this situation is to invent a theory about what&apos;s causing the bug, and attempt to confirm or disprove that specific explanation. I say &quot;invent&quot; because, while a plausible theory helps, pretty much any reasonable one will suggest some concrete details of the code you need to investigate.&lt;/p&gt;
&lt;p&gt;For example, say I&apos;ve been given a bug where a particular widget in the application isn&apos;t rendering. My first theory might be, &quot;Maybe the ajax request to the API isn&apos;t returning data in the correct format&quot;, or &quot;I wonder if the render function isn&apos;t getting called for some reason&quot;, or &quot;My coworker made some changes to the template function recently, something weird could be happening there&quot;.&lt;/p&gt;
&lt;p&gt;The point isn&apos;t to guess correctly on the first try, but instead to start digging through the low-level details of the code. It is much easier to do that with a working theory that suggests specific questions like, &quot;Where in this code does the widget&apos;s render function get called?&quot; or &quot;What data format is this widget expecting?&quot;. You might not have been (probably weren&apos;t, even) right, but in finding that out you&apos;ve learned a lot about how everything works, and you&apos;re better positioned to develop your next theory, which will likely be more accurate.&lt;/p&gt;
&lt;p&gt;A bonus benefit of this approach is that as you continue to use it and your familiarity with the code you&apos;re working on increases, your intuition about what is causing a bug improves, and your first guess &lt;em&gt;will&lt;/em&gt; be right more often.&lt;/p&gt;
&lt;h2&gt;Break things&lt;/h2&gt;
&lt;p&gt;The code you&apos;re working on is (I sincerely hope) under version control, which is awesome, because it means you&apos;re free to break everything in your quest to fix things. Restoring order afterwards is as easy as running &lt;code&gt;git reset&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When I first started working on a production application with a team of other developers, I was afraid to touch core parts of the code, because &lt;em&gt;what if I ruined everything?!&lt;/em&gt; But don&apos;t be timid—just because committing that change would break all kinds of things doesn&apos;t mean you can&apos;t do it in your development environment.&lt;/p&gt;
&lt;p&gt;When you&apos;re learning a complicated system, it can really help a lot to sprinkle around &lt;code&gt;console.log&lt;/code&gt;s with abandon, or comment out a critical function call just to see what fails. Sometimes I will comment out everything and try to &quot;rebuild&quot; it by re-enabling components piece-by-piece, to better understand how the parts work together and depend on each other.&lt;/p&gt;
&lt;p&gt;As a caveat, this does require some knowledge of which parts of your dev environment might be shared or not revertable (there may be things you really shouldn&apos;t mess with, like a shared database), but my point stands.&lt;/p&gt;
&lt;h2&gt;Use a linter&lt;/h2&gt;
&lt;p&gt;Save yourself from losing hours of your life to typos and hard-to-spot errors (&lt;a href=&quot;http://trailingcomma.com/&quot;&gt;IE trailing comma bug&lt;/a&gt;, anybody?) and let a linter find them for you.&lt;/p&gt;
&lt;p&gt;I use Sublime Text with the &lt;a href=&quot;https://github.com/victorporof/Sublime-JSHint&quot;&gt;Sublime-JSHint package&lt;/a&gt; to show lint errors as I type. (This also saves a lot of time I&apos;d otherwise spend reloading the app I&apos;m working on only to get a syntax error because I forgot a curly brace.) But you use whatever works for you and your editor of choice.&lt;/p&gt;
&lt;p&gt;Running JSHint on an older codebase or one without consistent style conventions for the first time might make you want to cry, but persevere. You don&apos;t have to fix every single warning just because it&apos;s there. (I say this for my own benefit as much as yours, trust me. I also suggest making a very lenient &lt;code&gt;.jshintrc&lt;/code&gt; that disables the rules that are more like style preferences and only checks the likely-to-cause-bugs ones.)&lt;/p&gt;
&lt;p&gt;The first time JSHint finds a case statement that&apos;s falling through accidentally or a variable that&apos;s being unintentionally reused and causing mysterious problems, it will totally be worth it.&lt;/p&gt;
&lt;h2&gt;Learn your editor&lt;/h2&gt;
&lt;p&gt;As previously established in the first installment of this advice, I love nerding out over tools, and this is another instance of that. But learning how to move around a large codebase quickly is ridiculously helpful when debugging, and well worth the time spent learning some of the intricacies of your editor.&lt;/p&gt;
&lt;p&gt;My editor of choice is Sublime Text 3 in Vintage mode (yay vim keybindings), and these are the commands I use all the time while debugging. I&apos;m including the Sublime shortcuts for these since I know them, but most editors probably have similar features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fuzzy file matching&lt;/strong&gt;  &lt;code&gt;Cmd-P&lt;/code&gt;&lt;br /&gt;
Look up a file based on a partial filepath. Saves so much time when you&apos;re looking for &lt;code&gt;SomeWidgetView.js&lt;/code&gt; but you&apos;re not entirely sure where in the repo it lives.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Function search&lt;/strong&gt;  &lt;code&gt;Cmd-P&lt;/code&gt;, then type &lt;code&gt;@&lt;/code&gt;&lt;br /&gt;
List all of the functions in a file (and search them, if you start typing a function name after the &lt;code&gt;@&lt;/code&gt;). A good way to get an overview of a giant file you&apos;re unfamiliar with.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Search within a file, jump to a line number&lt;/strong&gt;  &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;gg&amp;lt;line&amp;gt;&lt;/code&gt; (specific to Vintage mode)&lt;br /&gt;
Become familiar enough with these that they&apos;re automatic, so that answering a question like, &quot;Huh, where else does this function get used?&quot; or looking at the line with a syntax error is frictionless.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go to definition&lt;/strong&gt;  &lt;code&gt;Opt-Cmd-↓&lt;/code&gt;&lt;br /&gt;
Jump right to the definition of a function. I&apos;ve had mixed results as far as this actually working in ST, but it saves a lot of digging when it does.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Leave a path behind you&lt;/h2&gt;
&lt;p&gt;Once you&apos;ve spent twenty minutes puzzling out exactly &lt;em&gt;what&lt;/em&gt; data that &lt;code&gt;getData()&lt;/code&gt; function retrieves and why, do future debuggers a favor and leave a comment documenting your findings. If making another person&apos;s task much easier in the future isn&apos;t motivating enough, consider that the person debugging next time is very likely to be you (especially now that you&apos;ve become the dev who fixed a bug in this code most recently). Or that if you can&apos;t finish this task today, you might have to figure this out again when you come back to the code tomorrow.&lt;/p&gt;
&lt;p&gt;If another dev gives you a helpful explanation of how a library works or lets you know about a quirk of the framework on IRC or via email, take a minute to clean it up and post it on the dev wiki or wherever other devs can access it. It doesn&apos;t require a lot of time and it is definitely worth it.&lt;/p&gt;
</content:encoded></item><item><title>Run your own mini Heroku with Dokku</title><link>https://alliejon.es/blog/2014/03/09/run-your-own-mini-heroku-with-dokku/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/03/09/run-your-own-mini-heroku-with-dokku/</guid><pubDate>Sun, 09 Mar 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I find building toy projects much more fun if I can get them on the internet to show them off to people. Having things that only run on my local machine just isn&apos;t the same. When you&apos;re using technology newer or more complicated than the LAMP stack, though, deploying things to a server can be a challenging (at least if your patience for being a sysadmin is as limited as mine).&lt;/p&gt;
&lt;p&gt;Heroku is a popular choice for painlessly getting small projects online, but I&apos;m difficult and the 30 second start up time for rarely used sites on the free tier annoys me, and I&apos;m not ready to pay $30 or so a month to host a toy project.&lt;/p&gt;
&lt;p&gt;During my Hacker School batch I got my &lt;a href=&quot;http://drawtogether.by.alliejon.es/&quot;&gt;multiuser drawing app&lt;/a&gt; running on a $5/month &lt;a href=&quot;https://www.digitalocean.com/&quot;&gt;Digital Ocean&lt;/a&gt; droplet, but configuring Nginx to work with Node and websockets pushed the limits of my sysadmin skills and patience.&lt;/p&gt;
&lt;p&gt;However, Digital Ocean offers many different preconfigured server images, and I recent set up a droplet with their Dokku image. It has turned out to be perfect for getting small projects online without too much work and I love it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/progrium/dokku&quot;&gt;Dokku&lt;/a&gt; is basically a tiny Heroku clone written in bash. It uses Heroku buildpacks to compile projects, so if your application runs on Heroku it should run on Dokku. Once your Dokku server is running, adding and deploying a new project is as easy as doing this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git remote add mywebsite dokku@mywebsite.com:myproject
git push mywebsite master
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once everything finishes building, your project will be running at &lt;code&gt;myproject.mywebsite.com&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;If this seems appealing, there are a bunch of good tutorials for getting started, and the Dokku docs are also helpful. This is what I did, and the resources I used:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set up a subdomain with wildcard DNS&lt;/strong&gt;&lt;br /&gt;
I had to work around my hosting a bit for this: I was using &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech&lt;/a&gt;, where this blog is hosted, for DNS, but they don&apos;t support wildcard subdomains. However, &lt;a href=&quot;https://www.gandi.net/&quot;&gt;Gandi&lt;/a&gt;, where I registered my goofy domain hack address in the first place, does. After switching my DNS over, I was able to point &lt;code&gt;alliejon.es&lt;/code&gt; here, while &lt;code&gt;by.alliejon.es&lt;/code&gt; (and &lt;code&gt;*.by.alliejon.es&lt;/code&gt;) point to my Digital Ocean server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Digital Ocean droplet using their &lt;a href=&quot;https://www.digitalocean.com/community/articles/how-to-use-the-digitalocean-dokku-application&quot;&gt;Dokku tutorial&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;
(DO has a lot of really great beginner articles on server setup besides this one that are worth looking through, too.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deploy my own application&lt;/strong&gt;&lt;br /&gt;
I had tested the Dokku setup with Heroku&apos;s sample node application (as suggested by the tutorial above), and that worked great, but my first attempt at deploying &lt;a href=&quot;http://drawtogether.by.alliejon.es/&quot;&gt;drawtogether&lt;/a&gt; just led to mysterious 500 errors. So, a tip: don&apos;t forget to add a Procfile to your project repository so Dokku actually knows how to run your application. Once I figured that out, everything worked perfectly with no additional configuration on my part. Awesome!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All told, even with my DNS fiddling, a lot of googling because I was wondering if websockets would work out of the box (they do) and forgetting to create a Procfile, it only took me a few hours to get everything running. Definitely worth it for simple deployment with git and inexpensive project hosting.&lt;/p&gt;
</content:encoded></item><item><title>Seven Databases in Seven Weeks: Installing Erlang and Riak 1.0.2 on OSX 10.9</title><link>https://alliejon.es/blog/2014/03/14/seven-databases-in-seven-weeks-installing-erlang-and-riak-1-dot-0-2-on-osx-10-dot-9-mavericks/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/03/14/seven-databases-in-seven-weeks-installing-erlang-and-riak-1-dot-0-2-on-osx-10-dot-9-mavericks/</guid><pubDate>Fri, 14 Mar 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been reading and working through &lt;a href=&quot;http://pragprog.com/book/rwdata/seven-databases-in-seven-weeks&quot;&gt;Seven Databases in Seven Weeks&lt;/a&gt; lately, but when I got to the chapter on &lt;a href=&quot;http://basho.com/riak/&quot;&gt;Riak&lt;/a&gt; this week I ran into a problem: the latest version of Riak (1.4.8 as of right now) is different enough that I couldn&apos;t follow the book&apos;s tutorial, and installing the older version of Riak used to write the examples turned out to be a little bit of a challenge.&lt;/p&gt;
&lt;p&gt;Since I did figure it out eventually, here is an explanation of how I got Riak 1.0.2 running on my Mavericks machine. The main issue (as far as I can tell, though I am far from an expert on this stuff) is that these older versions of Erlang and Riak don&apos;t compile correctly with clang, which is the default C++ compiler for OSX 10.9. So you have to install gcc instead, and make sure Erlang and Riak are built using that.&lt;/p&gt;
&lt;p&gt;To start, I installed gcc via &lt;a href=&quot;http://brew.sh/&quot;&gt;homebrew&lt;/a&gt;: &lt;code&gt;brew install apple-gcc42&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then I basically followed &lt;a href=&quot;http://docs.basho.com/riak/1.3.0/tutorials/installation/Installing-Erlang/#Install-using-kerl&quot;&gt;Basho&apos;s instructions for installing Erlang via kerl&lt;/a&gt;. I did have to change a few things, so I&apos;ve documented the whole process in this post, but most of this came from their docs.&lt;/p&gt;
&lt;p&gt;First install &lt;a href=&quot;https://github.com/spawngrid/kerl&quot;&gt;kerl&lt;/a&gt;, which is basically like virtualenv or rvm for Erlang.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -O https://raw.github.com/spawngrid/kerl/master/kerl
chmod a+x kerl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then create a &lt;code&gt;~/.kerlrc&lt;/code&gt; file containing this configuration, so that Erlang will be compiled using gcc instead of clang (the rest of the build settings are as suggested by Basho&apos;s docs).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;KERL_CONFIGURE_OPTIONS=&quot;CC=gcc-4.2 --disable-hipe --enable-smp-support
                        --enable-threads --enable-kernel-poll
                        --enable-darwin-64bit&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can tell kerl to build, install and activate Erlang. Version R14B03 is the latest one that will work with Riak 1.0.2. (FYI, this version of Riak is not compatible with Erlang R14B04, which I learned the tedious way.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./kerl build R14B03 r14b03
./kerl install r14b03 ~/erlang/r14b03
. ~/erlang/r14b03/activate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With Erlang installed, you&apos;re ready to set up Riak. You can &lt;a href=&quot;https://github.com/basho/riak/archive/riak-1.0.2.zip&quot;&gt;download the Riak 1.0.2 source from Github&lt;/a&gt;. Riak won&apos;t build correctly with clang either, so you need to specify gcc when compiling again. (I&apos;m not sure that running &lt;code&gt;make rel&lt;/code&gt; is neccessary here, but that&apos;s what I did.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CC=gcc-4.2 make rel
CC=gcc-4.2 make devrel
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now (whew!) you should have a functional old version of Riak, and you can get back to learning about databases.&lt;/p&gt;
</content:encoded></item><item><title>Adding syntax highlighting to knitting patterns</title><link>https://alliejon.es/blog/2014/03/23/adding-syntax-highlighting-to-knitting-patterns/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/03/23/adding-syntax-highlighting-to-knitting-patterns/</guid><pubDate>Sun, 23 Mar 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A few weeks ago a coworker sent me &lt;a href=&quot;http://www.cs4fn.org/regularexpressions/knitters.php&quot;&gt;Karen Shoop&apos;s awesome essay about the similarities between knitting patterns and regular expressions&lt;/a&gt;. While thinking about that, as well the as the knitting chart generator I&apos;m going to make someday, really, it occurred to me that syntax highlighting knitting patterns could be genuinely useful. So I tried it!&lt;/p&gt;
&lt;p&gt;If you&apos;re not familiar with knitting patterns, they use a semi-standardized set of symbols and shorthand to record exactly how to recreate a particular texture or garment. The pattern will tell you things like how many stitches you need, what sort of stich to make and when and how to add or remove stitches.&lt;/p&gt;
&lt;p&gt;For example, here&apos;s the top of a sock I&apos;m working on. The top of the cuff looks different than the rest, which is the result of a different pattern of stitches. (There are two kinds of stitches in knitting, knit and purl, though they are really the same stitch flipped 180 degrees—the back of a knit stitch looks like a purl stitch, and vice versa.)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The knitting pattern abbreviation for the cuff (at the top of the photo) is this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k1 p1 until end of round
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That translates to &quot;knit one stitch, then purl one stitch, then knit, then purl ... until you get back to where you started&quot;. (This sock is being knit as a tube, hence &quot;round&quot;.)&lt;/p&gt;
&lt;p&gt;Instructions for the lower part of the sock are like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k3 p1 until end of round
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Almost the same, but with a different ratio of knits and purls, which makes a different texture.&lt;/p&gt;
&lt;p&gt;For another example, here&apos;s a closeup of a hat I made. Same two stitches, but in more complicated patterns:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;A section of that hat&apos;s texture (the diagonal stripes) would be transcribed like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;k2, p2 to end of round.
k1, (p2, k2) to 3 sts before end of round, p2, k1
(p2, k2) to end of round
p1, (k2, p2) to 3 sts before end of round, k2, p1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So you can see how that starts to get more challenging to read and follow. (The parentheses indicate a series of stitches you should repeat.)&lt;/p&gt;
&lt;p&gt;Wikipedia has &lt;a href=&quot;http://en.wikipedia.org/wiki/Knitting_abbreviations&quot;&gt;an interesting taxonomy of the kinds of knitting abbreviations&lt;/a&gt;, but that didn&apos;t seem like the most practical way to highlight the different portions of knitting pattern instructions. Instead I thought about the things that most often cause me to make an error while following a pattern, the parts that should be more distinct from each other while reading. I came up with this list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which kind of stitch to make (knit or purl)&lt;/li&gt;
&lt;li&gt;portions of the pattern that repeat&lt;/li&gt;
&lt;li&gt;adding or removing stitches&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wasn&apos;t really interested in writing my own syntax highlighter (yet, anyway), so I used &lt;a href=&quot;http://prismjs.com/&quot;&gt;Prism.js&lt;/a&gt; and wrote my own knitting pattern language definition, giving each of those pattern features their own distinct color. (And, in a neat circling back around to the essay I linked to at the beginning of this post, I used regular expressions to do so!)&lt;/p&gt;
&lt;p&gt;Here&apos;s the more complicated pattern from above, this time with syntax highlighting:&lt;/p&gt;
&lt;p&gt;&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-knitting&quot;&amp;gt;k2, p2 to end of round.
k1, (p2, k2) to 3 sts before end of round, p2, k1
(p2, k2) to end of round
p1, (k2, p2) to 3 sts before end of rnd, k2, p1
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;/p&gt;
&lt;p&gt;Much easier to read, I think!&lt;/p&gt;
&lt;p&gt;For another, more complicated, example, here&apos;s a portion of &lt;a href=&quot;http://www.knitty.com/ISSUEss14/PATTfiftyfifty.php&quot;&gt;this lace tank top pattern&lt;/a&gt;. This pattern includes increasing and decreasing stitches (the abbreviations in teal and yellow), and repeated instructions (in orange).&lt;/p&gt;
&lt;p&gt;&amp;lt;pre&amp;gt;&amp;lt;code class=&quot;language-knitting&quot;&amp;gt;k2, p2 to end of round.
Rnd 1: K1, *k4, sl1, k1, sl1, k5; rep from * to last st, k1.
Rnd 2: K1, *k3, k2tog, yo, k1, yo, ssk, k4; rep from * to last st, k1.
Rnd 3: K1, *(k3, sl1) twice, k4; rep from * to last st, k1.
Rnd 4: K1, *k2, k2tog, yo, k3, yo, ssk, k3; rep from * to last st, k1.
Rnd 5: K1, *k2, sl1, k5, sl1, k3; rep from * to last st, k1.
Rnd 6: K1, *k1, k2tog, yo, k5, yo, ssk, k2; rep from * to last st, k1.
Rnd 7: K1, *(k1, sl1, k2, sl1) twice, k2; rep from * to last st, k1.
Rnd 8: K1, *k2tog, yo, k1, yo, ssk, k1; rep from * to last st, k1.
Rnd 9: K1, *sl1, k3, k1tbl, sl1, k4, sl1, k1; rep from * to last st, k1.
Rnd 10: K2tog, *yo, k3, yo, sl1, k2tog, psso; rep from * to last 6 sts, yo, k3, yo, ssk, k1.
Rnds 11-12: Knit.
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;ve put my (pretty simple) language definition &lt;a href=&quot;https://github.com/alliejones/prism-knitting&quot;&gt;up on Github&lt;/a&gt;, if you&apos;re interested in trying it out. I&apos;m sure there is room for improvement in the regexes I&apos;ve written, though this was definitely a great way to get practice with writing more complex ones than I typically do.&lt;/p&gt;
</content:encoded></item><item><title>&quot;Girly&quot; games, programming, and the fractal gender binary</title><link>https://alliejon.es/blog/2014/03/30/girly-games-programming-and-the-fractal-gender-binary/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/03/30/girly-games-programming-and-the-fractal-gender-binary/</guid><pubDate>Sun, 30 Mar 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week &lt;a href=&quot;http://www.gog.com/&quot;&gt;GOG&lt;/a&gt; had the &lt;a href=&quot;http://en.wikipedia.org/wiki/Creatures_%28artificial_life_series%29&quot;&gt;Creatures series of video games&lt;/a&gt; on sale, and I couldn&apos;t resist getting a copy that would run on my current computer and spending an evening immersed in gaming nostalgia.&lt;/p&gt;
&lt;p&gt;As a kid and a teenager, I was fortuate enough to have easy access to the family computer (and later my own machine), and I spent many happy hours raising imaginary animals, figuring out how to access the alt.games.creatures newsgroup, downloading game add-ons and trying to build my own.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I was similarly fascinated with the &lt;a href=&quot;http://en.wikipedia.org/wiki/Petz&quot;&gt;Petz games&lt;/a&gt;, and loved breeding strange hybrid animals and trying my hand at editing the files that defined the appearance of the cats and dogs in the game. (If you want to see some amazing examples of the game being pushed to its limits, &lt;a href=&quot;http://petzventures.tumblr.com/&quot;&gt;this tumblr&lt;/a&gt; is hilarious.) I learned how to build websites in part so I could share the things I had made.&lt;/p&gt;
&lt;p&gt;Then I discovered &lt;a href=&quot;http://en.wikipedia.org/wiki/Online_text-based_role-playing_game&quot;&gt;MU*s&lt;/a&gt;, which, besides being ridiculously fun, greatly improved my writing ability and introduced me to friends I still have, over a decade later.&lt;/p&gt;
&lt;p&gt;Looking back, I am amazed at all of the technological skills I learned in the context of playing these games I loved, that I would otherwise have been too intimidated to try. Editing Petz breeds required using a hex editor and reading documentation from others who had reverse-engineered the file format. MU*s had their own &lt;a href=&quot;http://en.wikipedia.org/wiki/Message_Parsing_Interpreter&quot;&gt;Lisp-like&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/MUF_%28programming_language%29&quot;&gt;Forth-based&lt;/a&gt; programming languages that I learned to use, as well as many admin commands inspired by UNIX. (Not that I realized that, at the time. The first time I used &lt;code&gt;chmod&lt;/code&gt; on a web server many years later I was startled that it was familiar!)&lt;/p&gt;
&lt;p&gt;What also amazes me is that I did all these things, and yet never really considered myself the kind of person who could be a programmer. I was nerdy, sure, but programming was this lofty skill that I was sure was probably beyond me.&lt;/p&gt;
&lt;p&gt;It is hard to say now exactly why I felt that way (and I certainly don&apos;t remember ever being explicity discouraged from liking technology or having a career in it), but it seems likely to me in retrospect that I knew these were &quot;girly&quot; games, and my activities were not things &quot;real&quot; people who were into technology would do. People who became programmers wrote Quake mods, not custom breedfiles so they could have horses in their virtual pet game.&lt;/p&gt;
&lt;p&gt;I think this Sociological Images post by Lisa Wade on &lt;a href=&quot;http://thesocietypages.org/socimages/2010/01/07/the-fractal-nature-of-the-gender-binary-or-blue-vs-turquoise/&quot;&gt;the fractal nature of the gender binary&lt;/a&gt; provides an interesting framework for thinking about this[^1]. Playing games and creating your own add-ons for them is stereotyped as a masculine activity. But within that category there are more and less feminine games. First person shooters? Masculine (and, thus, cooler). Virtual pets? Feminine (and so not as cool). Even text-based RPGs, a very specific and tiny subcategory of games, have gender stereotypes: MUDs (which have stats and combat systems) are for dudes, while MUCKs (which are largely for free-form roleplay) have many more female players (or so everyone assumed when I played them, I&apos;m not sure if it was actually true).&lt;/p&gt;
&lt;p&gt;Even now that I &lt;em&gt;am&lt;/em&gt; a programmer (and let&apos;s pretend I didn&apos;t feel a tiny bit hesitant saying that), this fractal nature of the gendering of things---and so also their relative value---reappears. Front-end web development seems to attract a greater proportion of women (though I admit I can&apos;t find hard data on this), and I don&apos;t think it is a coincidence &lt;a href=&quot;http://www.quora.com/Startups/Why-are-front-end-developers-so-high-in-demand-at-startups-if-front-end-development-is-relatively-easier-than-other-fields-of-engineering?share=1&quot;&gt;it is considered &quot;easier&quot; than other programming specialties&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don&apos;t really have a neat conclusion to these thoughts, except that gender and the ways we categorize the world are complicated, and we still have a lot of work to do to make everyone feel welcome in technology (and everywhere else).&lt;/p&gt;
&lt;p&gt;[^1]: Just to be clear, I think that assuming gender is binary sucks (besides being, oh, totally inaccurate), and I wish things weren&apos;t socially classified this way. But these assumptions definitely exist.&lt;/p&gt;
</content:encoded></item><item><title>Adventures in knitting machine hacking</title><link>https://alliejon.es/blog/2014/12/02/adventures-in-knitting-machine-hacking/</link><guid isPermaLink="true">https://alliejon.es/blog/2014/12/02/adventures-in-knitting-machine-hacking/</guid><pubDate>Tue, 02 Dec 2014 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My love of combining technology and textiles is well-documented already, so it is likely unsurprising I&apos;ve had my eye on knitting machine hacks for a while.&lt;/p&gt;
&lt;p&gt;Knitting machines are strange beasts. The most common ones, the machines I am familiar with, were made by Brother in the 70s and 80s for home knitters and are no longer manufactured. In &lt;a href=&quot;http://www.risd.edu/academics/textiles/&quot;&gt;college&lt;/a&gt; I took two semesters of knitting classes[^1] that used them, and they are odd and finicky and it isn&apos;t surprising they never quite caught on. They make fabric much faster than hand-knitting, but they also require a lot of skill to operate and they really aren&apos;t anything close to automatic.&lt;/p&gt;
&lt;p&gt;You can still do a lot of neat things with them, though, and they are a much more accessible textile-making tool than many of the others I learned to use. (Maybe someday I&apos;ll have my own loom for weaving, but that seems pretty unlikely to happen while I live in a New York apartment.)&lt;/p&gt;
&lt;p&gt;As far as hacks go, &lt;a href=&quot;https://learn.adafruit.com/electroknit&quot;&gt;Becky Stern&apos;s&lt;/a&gt; is probably the most well-known, but I found this disclaimer pretty intimidating[^2] (and I can use knitting machines and Python already!):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Working with these machines is very difficult. Before you begin, look at your life, and what choices brought you to this point. Are you proficient at using the knitting machine&apos;s normal functions? Can you read and run Python scripts? Have you ever done any serial communication between your computer and another device before? If you answered &quot;no&quot; to any of these questions, work on these skills first before attempting to follow this guide.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I don&apos;t have any hardware skills, and tackling a modification to an expensive knitting machine as a first project seems likely to end poorly.&lt;/p&gt;
&lt;p&gt;Happily, some enterprising German hackers made an alternative knitting machine hack that seemed more approachable to my intimidated-by-hardware self. &lt;a href=&quot;http://ayab-knitting.com/&quot;&gt;All Yarns Are Beautiful&lt;/a&gt; designed an Arduino shield that interfaces with electronic Brother machines. Even better, the process is nondestructive and reversible, &lt;em&gt;and&lt;/em&gt; it supports a less expensive model than the 930e used in the Adafruit hack.&lt;/p&gt;
&lt;p&gt;A few weeks ago I finally decided I wanted to make my own hacked machine, despite my fear I would buy all these parts and ultimately get nowhere. I got lucky and found a Brother 910 with a broken card reader on EBay. The 910 originally read patterns off of mylar cards, which meant the pattern functions were unusable, but made it perfect for my purposes---the AYAB Arduino replaces that component completely.&lt;/p&gt;
&lt;p&gt;This week the machine and the shield arrived, and I&apos;ve made a lot of progress! I&apos;ve been keeping notes and will be following up this post with others about the whole process. (And, hopefully, some finished products!)&lt;/p&gt;
&lt;p&gt;If you&apos;d like to see a Brother 910 in action, I found &lt;a href=&quot;http://www.marthastewart.com/article/karen-allen-fiber-arts#ooid=tucG9lMjpDBHTAjkgKVoOjIbbCJFL5KT&quot;&gt;this cool video of Karen Allen demonstrating how she uses one to make sweaters&lt;/a&gt;. (Though she&apos;s using the original card reader for patterns, she&apos;s done some knit hacking too! I&apos;ve never seen someone use two carriages at once to knit with that many colors.)&lt;/p&gt;
&lt;p&gt;[^1]: How cool is it you can study this in college? I still think it&apos;s amazing. (Probably moreso now that I am not fighting with knitting machines at 2am though, hah.)
[^2]: Having now attempted this project, I will say the disclaimer isn&apos;t &lt;em&gt;wrong&lt;/em&gt; exactly, but I think you can do fine with two skills out of three. I would say one of those skills should be using a knitting machine, though, since they can be tricky enough on their own without the complication of a hack.&lt;/p&gt;
</content:encoded></item><item><title>Knitting machine hacking: flashing the Arduino firmware</title><link>https://alliejon.es/blog/2015/01/25/knitting-machine-hacking-flashing-the-arduino-firmware/</link><guid isPermaLink="true">https://alliejon.es/blog/2015/01/25/knitting-machine-hacking-flashing-the-arduino-firmware/</guid><pubDate>Sun, 25 Jan 2015 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Wondering what this is about? See &lt;a href=&quot;/blog/2014/12/02/adventures-in-knitting-machine-hacking/&quot;&gt;the introduction&lt;/a&gt; to my knitting machine hacking adventures.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Successfully flashing the firmware on my Arduino so I could use my AYAB shield took a bit of fiddling, especially because I&apos;m running OSX instead of Linux.&lt;/p&gt;
&lt;p&gt;I&apos;ll list the straightforward (as I can manage) steps that actually worked first, for anyone else trying to do this, and the messy narrative version afterwards (since that&apos;s the fun/infuriating part!).&lt;/p&gt;
&lt;p&gt;If you use these instructions and run into problems, or have suggestions for improvements, please get in touch! I&apos;m happy to help though I&apos;m far from expert in these things (so while I hope these instructions won&apos;t mess up your Arduino, I definitely can&apos;t promise that). This is what worked for me, though.&lt;/p&gt;
&lt;h2&gt;How to install AYAB Arduino firmware on OSX&lt;/h2&gt;
&lt;p&gt;AYAB comes with a Python-based GUI, but I couldn&apos;t get it to run successfully on my OSX machine, and it isn&apos;t neccessary for flashing the Arduino firmware anyway. These instructions explain how to get the firmware image and use &lt;code&gt;avrdude&lt;/code&gt; to flash the firmware from the command line.&lt;/p&gt;
&lt;p&gt;I did this on OSX Yosemite (10.10) but my guess is it would work fine on any relatively recent version of OSX.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install &lt;code&gt;avrdude&lt;/code&gt; 5.x (I used 5.11.1 specifically)&lt;/strong&gt;&lt;br /&gt;
Homebrew only has a formula for &lt;code&gt;avrdude&lt;/code&gt; 6.x, but if you don&apos;t want to build &lt;code&gt;avrdude&lt;/code&gt; yourself, an older version is downloadable from Objective Development as part of their CrossPack toolkit. You need the &lt;code&gt;2012-11-28&lt;/code&gt; release. Here is a &lt;a href=&quot;http://www.obdev.at/downloads/crosspack/CrossPack-AVR-20121128.dmg&quot;&gt;direct link to the dmg file&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Download or clone &lt;a href=&quot;https://bitbucket.org/chris007de/ayab-apparat/&quot;&gt;the AYAB software repo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find and edit &lt;code&gt;avrdude.conf&lt;/code&gt; or download a corrected version&lt;/strong&gt;
The &lt;code&gt;avrdude&lt;/code&gt; config provided by AYAB won&apos;t work when used on a computer without parallel ports (which I&apos;m pretty sure means any modern Mac).&lt;/p&gt;
&lt;p&gt;I put the &lt;a href=&quot;https://gist.github.com/alliejones/022b9d3cc422bdc8bf36&quot;&gt;modified version I used&lt;/a&gt; on Github if you&apos;d like to download it.&lt;/p&gt;
&lt;p&gt;Alternately, to edit it yourself, find the config file in the repo at &lt;code&gt;/plugins/ayab_plugin/firmware/avrdude.conf&lt;/code&gt;. Do a search and replace on this file, replacing any instances of &lt;code&gt;par;&lt;/code&gt; with &lt;code&gt;serbb;&lt;/code&gt;. (Thanks to &lt;a href=&quot;http://forum.arduino.cc/index.php?topic=49229.0&quot;&gt;this Arduino forum post&lt;/a&gt; for this fix.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find &lt;code&gt;firmware.hex&lt;/code&gt; in the AYAB repo&lt;/strong&gt;&lt;br /&gt;
The path relative to the AYAB repo root directory is &lt;code&gt;/software/python/ayab/plugins/ayab_plugin/firmware/[KNITTING MACHINE MODEL]/[ARDUINO TYPE]/firmware.hex&lt;/code&gt;. You&apos;ll need to pick the directories that match your knitting machine and Arudino. There are different files for the different combinations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Determine which USB port your Arduino is connected to&lt;/strong&gt;
Your Arduino needs to be connected to your computer via the USB cable for this command to work (and for the firmware flashing you will be doing shortly!).
Running &lt;code&gt;ls /dev/tty.usbmodem*&lt;/code&gt; should show you the correct serial port. (I think this is dependent on your OS version and Arduino model, so you may have to do a bit of Googling if this specific command doesn&apos;t work.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Actually flash your firmware!&lt;/strong&gt;&lt;br /&gt;
Now you should have collected all of the information you&apos;ll need. Here&apos;s the avrdude command to run: &lt;code&gt;avrdude -v -p atmega328p -C &quot;[PATH TO AVRDUDE.CONF]&quot; -c arduino -P [ARDUINO SERIAL PORT] -b115200 -D -Uflash:w:&quot;[PATH TO FIRMWARE.HEX]&quot;:i&lt;/code&gt;
A note: I have an Arduino Uno, and you &lt;em&gt;may&lt;/em&gt; have to change the &lt;code&gt;-p atmega328p&lt;/code&gt; too if you&apos;re using an Arduino Mega, but I&apos;m not sure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So if all goes well, avrdude should do its thing and flash the firmware, and you&apos;re ready to install your AYAB shield, yay!&lt;/p&gt;
&lt;h2&gt;How I figured all this out&lt;/h2&gt;
&lt;p&gt;In short: trial and error and a lot of Googling. (As with so many things!)&lt;/p&gt;
&lt;p&gt;My previous Arduino experiments have been at the &quot;making an LED blink&quot; level, just to give you an idea of my familiarity with hardware things (and to explain all my fumbling around).&lt;/p&gt;
&lt;p&gt;I started by trying to get the AYAB GUI to run on OSX, since it has a firmware flashing utility built in, but after an hour or so of fiddling with Python dependencies and trying to figure out how to install what it was was missing, I decided this wasn&apos;t going to be a very productive direction.&lt;/p&gt;
&lt;p&gt;Instead, I set up a Linux VM using Parallels (though I bet you could use VirtualBox for this too) and installed the GUI in that. This was much less painful and following the AYAB-provided instructions seemed to work.&lt;/p&gt;
&lt;p&gt;This turned out to not be the case with the firmware flashing utility, however. The main part of the application, which you use to control the knitting machine once everything is set up, worked fine. But trying to run the firmware utility just gave me an error.&lt;/p&gt;
&lt;p&gt;I&apos;m not sure if using a virtual machine for firmware flashing would have worked, because I never got that far. Using &lt;code&gt;pip&lt;/code&gt; to install AYAB (as per the instructions) doesn&apos;t seem to install the &lt;code&gt;avrdude&lt;/code&gt; utility the GUI runs behind the scenes, so it fails to do anything.&lt;/p&gt;
&lt;p&gt;I figured this out from error messages in the debugging console that opens with the GUI, once I realized the console was actually providing me with useful information.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;avrdude&lt;/code&gt; &lt;em&gt;does&lt;/em&gt; seem to be in the repo, so I spent a while trying to manually copy it to the right directory so that the AYAB GUI could find it, but for whatever reason I couldn&apos;t get this to work. While I was trying this, though, I realized that the console error messages also showed me exactly what the GUI was trying to do for me, which was run &lt;code&gt;avrdude&lt;/code&gt; with a bunch of arguments.&lt;/p&gt;
&lt;p&gt;A little bit of research into what &lt;code&gt;avrdude&lt;/code&gt; does (since I&apos;d never heard of it before) confirmed that running it was probably all I needed to do, and showed me what files from the AYAB repo I needed. (The command the GUI runs is the one I provide above in the step-by-step directions.)&lt;/p&gt;
&lt;p&gt;And so I saved a copy of that command, and tried installing &lt;code&gt;avrdude&lt;/code&gt; on OSX! (OSX because I&apos;m not a very efficient Linux user, and I was worried the virtual machine stuff would mess things up.)&lt;/p&gt;
&lt;p&gt;Homebrew&apos;s version of &lt;code&gt;avrdude&lt;/code&gt; didn&apos;t like the config file from the AYAB repo, and then I realized that the &lt;code&gt;avrdude&lt;/code&gt; version provided by AYAB was 5.x and Homebrew&apos;s was 6.x---that seemed likely to be source of the problem. Since the &lt;code&gt;avrdude.conf&lt;/code&gt; file was huge and I wasn&apos;t entirely sure which parts were relevant or really what it was doing at all, I guessed it would be easier to try and find an older, compatible version rather than update the config for the new version.&lt;/p&gt;
&lt;p&gt;After rummaging through a bunch of tutorials and search results and seeing if I could build an 5.x version of &lt;code&gt;avrdude&lt;/code&gt; from source (nope) I eventually found the old version of CrossPack I linked to in my instructions.&lt;/p&gt;
&lt;p&gt;Now I had a running, hopefully-compatible version of &lt;code&gt;avrdude&lt;/code&gt;! So close! And yet still not quite there apparently!&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;avrdude&lt;/code&gt; with all the right (I hoped) arguments and file paths gave me the mysterious errors &lt;code&gt;parallel port access not available in this configuration&lt;/code&gt; and &lt;code&gt;programmer type not specified&lt;/code&gt;. Googling those errors turned up &lt;a href=&quot;http://forum.arduino.cc/index.php?topic=49229.0&quot;&gt;this forum post&lt;/a&gt; which seemed to describe exactly the problem I was having (and my laptop certainly doesn&apos;t have a parallel port), so I tried the suggested solution.&lt;/p&gt;
&lt;p&gt;And with that last change, it worked! &lt;code&gt;avrdude&lt;/code&gt; ran for a minute or two and then I had a newly-flashed Arduino.&lt;/p&gt;
&lt;p&gt;In retrospect, it is hilarious that I thought &quot;just&quot; buying an Arduino shield for my knitting machine might be too simple a project, and I wouldn&apos;t feel very accomplished getting it to work. Definitely not the case! I felt pretty damn victorious by the time I was done with this part of the process.&lt;/p&gt;
&lt;p&gt;Next up: installing the Arduino in the knitting machine and the moment of truth!&lt;/p&gt;
</content:encoded></item><item><title>Knitting machine hacking: putting it all together</title><link>https://alliejon.es/blog/2015/05/29/knitting-machine-hacking-putting-it-all-together/</link><guid isPermaLink="true">https://alliejon.es/blog/2015/05/29/knitting-machine-hacking-putting-it-all-together/</guid><pubDate>Fri, 29 May 2015 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Previous knitting machine hacking posts: &lt;a href=&quot;/blog/2014/12/02/adventures-in-knitting-machine-hacking&quot;&gt;introduction&lt;/a&gt;, &lt;a href=&quot;/blog/2015/01/25/knitting-machine-hacking-flashing-the-arduino-firmware/&quot;&gt;flashing the Arduino firmware&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Thankfully, after the complicated process I went through getting my Arduino set up to work with the AYAB shield, actually connecting everything to the knitting machine was straightforward!&lt;/p&gt;
&lt;p&gt;The video from AYAB showing how to open up your knitting machine and connect your Arduino is great and very clear. I had to snip a cable tie to get enough slack in some of the cables and remove a plastic clip from one of the connectors to get it to fit when connected to the shield, but it all worked out fine.&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe src=&quot;//player.vimeo.com/video/99870358&quot; class=&quot;w-full aspect-video&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;p&gt;Since my knitting machine has a broken card reader anyway, I didn&apos;t bother keeping it. I did keep the plastic outer case, but removed the electronics and display, which were just attached with a few screws. The empty space created is big enough to fit the Arduino and shield (though I have to disconnect some cables from the Arduino), which makes it much easier to store everything.&lt;/p&gt;
&lt;p&gt;I was dying to find out if this was all going to work and I couldn&apos;t find documentation for the command line control utility (though I&apos;ve since figured it out), so I used the AYAB GUI running in an Ubuntu virtual machine[^1].&lt;/p&gt;
&lt;p&gt;It took a bit of experimentation to get the knitting process initialized correctly, but it totally worked! I was &lt;a href=&quot;https://twitter.com/gredaline/status/539516636483833856&quot;&gt;ridiculously excited&lt;/a&gt; at this point, as you might imagine. (And yes, I did need a &lt;a href=&quot;http://diananatters.blogspot.com/2011/03/ways-to-improve-your-knitting-fix-your.html&quot;&gt;new sponge bar&lt;/a&gt; for my machine, which is very often the case with used knitting machines. Thankfully I had a spare!)&lt;/p&gt;
&lt;p&gt;I did a lot of testing and experimenting without yarn as I was getting the hang of using the AYAB GUI. You don&apos;t need to have yarn in the machine to test the needle controls---you can run the empty carriage back and forth to try out the process first.&lt;/p&gt;
&lt;p&gt;Two things to note about the GUI that I figured out through trial and error: it only supports PNGs (as far as I can tell? JPGs are included in the example files, but they did&apos;t work for me), and the file width needs to be smaller than the number of needles you&apos;ve selected to work with.&lt;/p&gt;
&lt;h2&gt;It works! Actual knitting!&lt;/h2&gt;
&lt;p&gt;Here it is, video evidence of my newly-hacked knitting machine in action. (Also including a cameo from my cat Abe, who loves all things yarn-y and was very curious about this strange noisy machine.)&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe class=&quot;w-full aspect-video&quot; src=&quot;https://www.youtube.com/embed/o-TDBhz8wz8&quot; frameborder=&quot;0&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;In case you couldn&apos;t quite see what I knitted at the end of the video, here&apos;s the source image (scaled up significantly; there is one pixel for each stitch so the original is 50 pixels wide):&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And the finished product:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;What&apos;s next&lt;/h2&gt;
&lt;p&gt;Since I wrote most of this post (in February, whoops) I&apos;ve acquired a ribber for my knitting machine, which is a second set of needles that creates a lot more possibilities for knitting images into fabric.&lt;/p&gt;
&lt;p&gt;I&apos;d also really like to write my own GUI for my machine, probably in Node with a web interface. I have some UI ideas brewing ...&lt;/p&gt;
&lt;p&gt;[^1]: This worked fine using Parallels on my Mac; the only configuration neccessary is to tell Parallels to &quot;pass through&quot; the Arduino&apos;s USB port to the VM from the Devices menu.&lt;/p&gt;
</content:encoded></item><item><title>Smoother remote live demos with OBS</title><link>https://alliejon.es/blog/2020/10/30/smoother-remote-live-demos-with-obs/</link><guid isPermaLink="true">https://alliejon.es/blog/2020/10/30/smoother-remote-live-demos-with-obs/</guid><pubDate>Fri, 30 Oct 2020 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Like the rest of the world, I&apos;ve been doing a lot more communication over video chat in 2020. I&apos;ve had remote teammates for a long time, so not much has changed with how I communicate with coworkers. My volunteering, however, feels totally different: for the past few years I have helped teach web development to high school students through &lt;a href=&quot;https://codenation.org/&quot;&gt;CodeNation&lt;/a&gt;, and this is the first school year the class has been entirely over video rather than in-person in a classroom.&lt;/p&gt;
&lt;p&gt;Teaching effectively requires a lot of skill, and teaching remotely feels even more challenging! (I hope this isn&apos;t news to anyone.) Technology can&apos;t fix most of the challenges, but I still couldn&apos;t resist experimenting with my setup to make presenting and coding remotely a little easier. I went into this thinking I was just indulging myself in some fun yak-shaving, but I was pleasantly surprised at how little fuss a better setup required, so I&apos;m documenting it here in case other folks find it useful! (And though I&apos;ve been using it for teaching so far, this may end up upping my work presentation standards too ...)&lt;/p&gt;
&lt;p&gt;My goal was to make it easy to switch between slides in presentation mode and a code editor (&lt;a href=&quot;https://glitch.com/&quot;&gt;Glitch&lt;/a&gt; in the browser, in my case, but this would work just as well for a standalone program) without having to share my entire screen. This means I can keep a class schedule, presenter notes, the meeting chat and whatever else visible on my own screen without showing them to everyone. I&apos;m not dealing with audio setup here because it&apos;s not neccessary in Zoom; you can continue to use your regular webcam and audio.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://obsproject.com/&quot;&gt;OBS&lt;/a&gt; (yes, the same program Twitch streamers use) makes this pretty easy! And while I haven&apos;t even scratched the surface of all the fancy things you can do with OBS, once you have this set up it should be straightforward to experiment with fancier things. I&apos;m assuming you&apos;re using OSX and presenting over Zoom in these instructions, but the general approach should work for other OSes and conferencing software too.&lt;/p&gt;
&lt;p&gt;There are only a few setup steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install OBS and a virtual camera plugin&lt;/li&gt;
&lt;li&gt;Configure your &quot;scenes&quot; (the different sections of your screen you&apos;d like to display)&lt;/li&gt;
&lt;li&gt;Share the virtual camera in Zoom&lt;/li&gt;
&lt;li&gt;Present!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Installing OBS&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://obsproject.com/&quot;&gt;Download OBS from the project&apos;s website&lt;/a&gt; and install it.&lt;/p&gt;
&lt;p&gt;OBS for Windows comes with a virtual camera plugin pre-installed, but you need to download a separate plugin for OSX. I used &lt;a href=&quot;https://github.com/johnboiles/obs-mac-virtualcam&quot;&gt;obs-mac-virtualcam&lt;/a&gt;. Download the latest &lt;code&gt;.pkg&lt;/code&gt; file from the &lt;a href=&quot;https://github.com/johnboiles/obs-mac-virtualcam/releases&quot;&gt;releases page&lt;/a&gt; and install it as well.&lt;/p&gt;
&lt;p&gt;When you start OBS for the first time, it will ask you about what preset settings you&apos;d like. You can cancel out of this window, it doesn&apos;t really matter for this setup.&lt;/p&gt;
&lt;h3&gt;Set up your scenes&lt;/h3&gt;
&lt;p&gt;OBS lets you combine a bunch of different input sources into one video output. For this simple setup (switching between two application windows) you only need to use &quot;window capture&quot;, but it&apos;s worth experimenting with some of the other options! You can display the output of a specific web URL or add a nice background image or webcam feed pretty easily.&lt;/p&gt;
&lt;p&gt;To add a new scene:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure the &quot;Scenes&quot; tab is selected (you should see this in the lower left of the OBS interface by default).&lt;/li&gt;
&lt;li&gt;Click the &quot;+&quot; button and name your scene something that makes sense to you (I usually pick something like &quot;Slides&quot; and &quot;Browser&quot;).&lt;/li&gt;
&lt;li&gt;Then click the &quot;Sources&quot; tab, click &quot;+&quot; again and select &quot;Window Capture&quot; from the dropdown.&lt;/li&gt;
&lt;li&gt;Choose &quot;Create new&quot; and then, in the &quot;Properties&quot; dialog that opens, choose the window you want for your first scene.&lt;br /&gt;
If you can&apos;t tell windows apart from their titles, selecting a window will show you a preview. If you just see a list of windows named &quot;void&quot; or it seems like things are missing, you may need to &lt;a href=&quot;https://support.apple.com/guide/mac-help/control-access-to-screen-recording-on-mac-mchld6aa7d23/mac&quot;&gt;grant OBS access to screen recording&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Click &quot;OK&quot;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the main OBS window, you can now manually drag and resize the window capture to make it a custom size. If you just want this one window, I find it easier to right click on the preview and select &quot;Tranform &amp;gt; Fit to screen&quot; to automatically make the whole capture visible and as big as possible.&lt;/p&gt;
&lt;p&gt;For your second scene (and any additional scenes), repeat these steps to create a new scene and a new window capture.&lt;/p&gt;
&lt;h3&gt;Use the virtual camera in Zoom&lt;/h3&gt;
&lt;p&gt;To connect OBS to your meeting software, you can use a &quot;virtual camera&quot;. This feature needs to be turned on in OBS: go to the &quot;Tools&quot; menu and select &quot;Start Virtual Camera&quot;. (If it says &quot;Stop Virtual Camera&quot; the camera is already on, and you don&apos;t need to do anything. If you don&apos;t see either option, double-check that you&apos;ve installed the virtual camera plugin.)&lt;/p&gt;
&lt;p&gt;You don&apos;t need to do anything else in OBS! Don&apos;t worry about the &quot;Start Streaming&quot; or &quot;Start Recording&quot; buttons; you just need the virtual camera on to send OBS output to Zoom.&lt;/p&gt;
&lt;p&gt;Zoom works particularly well with this setup because you can share the output of a second camera while keeping your regular webcam unchanged. Zoom provides &lt;a href=&quot;https://support.zoom.us/hc/en-us/articles/201362153-Sharing-your-screen-content-or-second-camera&quot;&gt;more detailed instructions if you&apos;d like them&lt;/a&gt;, but the short version is: in the dialog that opens when you click the &quot;Share Screen&quot; button in a meeting, select &quot;Advanced&quot; and then &quot;Content from 2nd Camera&quot;. Click the &quot;Switch camera&quot; button to the virtual camera output if you don&apos;t see it right away.&lt;/p&gt;
&lt;h3&gt;Present!&lt;/h3&gt;
&lt;p&gt;You should be good to go switching between your different scenes! As you&apos;re presenting, select the scene/window you&apos;d like to share from the Sources tab in the OBS window and it will update the camera output.&lt;/p&gt;
&lt;p&gt;I experimented with using the &lt;a href=&quot;https://obsproject.com/forum/resources/advanced-scene-switcher.395/&quot;&gt;Advanced Scene Switcher plugin&lt;/a&gt; to switch between scenes when I moused over the window associated with each scene, but in the end that felt too fussy (and despite moving my mouse very carefully it was still easy to accidentally switch scenes when I didn&apos;t intend to). I think OBS also has a lot of other built-in automatic scene switching options you could potentially use, but for this not-very-complicated setup manual switching seems simplest.&lt;/p&gt;
</content:encoded></item><item><title>Building Javascript SSR for Etsy.com</title><link>https://alliejon.es/blog/2021/11/04/building-javascript-ssr-for-etsy-com/</link><guid isPermaLink="true">https://alliejon.es/blog/2021/11/04/building-javascript-ssr-for-etsy-com/</guid><pubDate>Thu, 04 Nov 2021 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In 2021 I architected and then tech led the implementation of Etsy&apos;s server-side rendered Javascript infrastructure. We used &lt;a href=&quot;https://preactjs.com/&quot;&gt;Preact&lt;/a&gt; and the &lt;a href=&quot;https://jasonformat.com/islands-architecture/&quot;&gt;islands architecture&lt;/a&gt;, which let us create a smooth developer experience without sacrificing our frontend performance.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.etsy.com/codeascraft/mobius-adopting-jsx-while-prioritizing-user-experience&quot;&gt;I wrote about it in detail on the Etsy Engineering blog Code as Craft.&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Modernizing legacy codebases with Marianne Belotti</title><link>https://alliejon.es/blog/2022/11/08/modernizing-legacy-codebases/</link><guid isPermaLink="true">https://alliejon.es/blog/2022/11/08/modernizing-legacy-codebases/</guid><pubDate>Tue, 08 Nov 2022 16:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As part of Etsy&apos;s &lt;a href=&quot;https://www.etsy.com/codeascraft/events&quot;&gt;Code as Craft talk series&lt;/a&gt;, I spoke with &lt;a href=&quot;https://www.bellotti.tech/&quot;&gt;Marianne Belotti&lt;/a&gt; about our experiences wrangling with legacy code. It was a really fun conversation, and I&apos;d highly recommend her book &lt;a href=&quot;https://nostarch.com/kill-it-fire&quot;&gt;Kill It with Fire&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe src=&quot;https://player.vimeo.com/video/769079692?h=df3616f6ee&quot; class=&quot;w-full aspect-video&quot; frameborder=&quot;0&quot; allow=&quot;fullscreen; picture-in-picture&quot; allowfullscreen title=&quot;Modernizing legacy codebases with Marianne Belotti&quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
</content:encoded></item></channel></rss>