The Rube Goldberg-esque complexity of the JavaScript ecosystem has been a well-trodden trope for years. So it has been very refreshing to spend some time playing with Bun in late 2023. It's oversold as a "drop-in Node replacement", as many compatibility issues remain, but the speed and simplicity is a breath of fresh air. Bun's pace of development is truly impressive, too, and despite the lack of a sustainable funding model, it's been so fun to use that I'm considering moving a few projects from Node to Bun this year.
Of course LLMs were a fascinating topic in 2023. Simon Willison's blog was, and continues to be, an engineering generalist's essential reading on the topic. ML is very far from my circle of competence but it's been fun to learn about a new field that is deep and fascinating.
Regular readers of the blog (are there any?) will be familiar with my annual vanity metric– number of books read in the year. Even as I smashed my previous record this year, I realized how pointless and counter-productive this number is, given I retain very little of what I read. For 2024 my goal is to take a full page of notes for 20 high-quality books. I did this for only 9 books last year.
Retention issues aside, I enjoyed quite a few reads this year. Favourites were:
Last year I wrote down some nifty indieweb tech that I thought would be cool to explore on this site, and predictably, none of those things came to fruition. One day, maybe. As usual I didn't really write anything here, though I did do a little blogging elsewhere. A few people even told me those posts were useful, which, if true, is probably a first for me.
]]>Last year I built a customizable pdf planner and calendar for my reMarkable 2 with a Google Form, TypeScript, and considerable duct tape and spit polish. This year I kept plugging away at it, and the response certainly exceeded my expectations. Scott Hanselman gave me an early Christmas present and the project made the top 10 of HN the next day. More improvents and some related projects are in the hopper for 2023!
Tried out some new technologies this year and rather enjoyed them. Each of these should probably get their own post at some point, but for now I'll just say that I award my coveted seal of approval to:
Chewed through an even 50 books this year. Less than one per week; I must be slipping. Favourites were:
Somehow I had never listened to Vulfpeck before this year. They're a fun band; I enjoyed going through their back catalogue and associated acts like The Fearless Flyers.
Did pretty much nothing with the ol' personal website this year. With the surge in interest in federated web tech (thanks to Twitter's implosion), I'm regaining interest in sprucing up this site with Webmentions and other "indieweb" tech. To that end, I'm liberating an old list of links that have laid dormant in my Gmail tasks sidebar for eons, in case they're useful:
I resisted the impulse to rewrite this content-free site again, so that's a positive for the year at least. NextJS is still definitely a good fit for the low-maintenance static deploy that I favor, but if I ever dabble in the indieweb tech above, I might give Remix a spin here as well.
]]>I remain enamored with my reMarkable 2 after 14 months of daily use. The large-eInk-screen-with-low-latency-pen-input device really feels like a new medium with a ton of untapped potential. My recreational coding time this year was dedicated to enhancing my reMarkable’s utility. I built:
That reMarkable day-planner took on a life of its own after sharing it on reddit, and for the first time I made a little income from a side project. Not enough to pay even a single month’s rent, mind you, but it’s still been enormously satisfying to receive the positive feedback and email from satisfied customers. You can, and should, order your own custom planner at hyperpaper.me. I hope to write up a post at some point with "lessons learned" from putting this out there.
I read 57 books this year (gotta keep sharing my personal vanity metric). Favourites were:
My favourite links on Pinboard over the year:
I am an old man, so it’s rare for a new album to trigger both intense anticipation and thorough enjoyment. But An Evening with Silk Sonic absolutely knocked it out of the park for me. It was easily my favourite new album in years, and if you enjoy vintage R&B/funk/soul you need to check it out.
I inexplicably re-built this site for a second straight year. For those keeping track at home, the
technology arc has been Jekyll on GitHub Pages
-> 11ty on Netlify
-> NextJS on Cloudflare Pages
. NextJS was a project I wanted to explore, and I really enjoy how it abstracts away the usual
webpack/babel/typescript config shenanigans for you. Would recommend, so far.
I wrote a single post, which is actually enough to exceed my average throughput over the past 5 years (!). Hope to see you again in 2022.
]]>Neovim 0.5 is really a game changer in a lot of ways, and its impact on my setup has been significant. Native LSP support and treesitter integration are two of the exciting headline features, but in my mind, the biggest game-changer is the first-class support for scripting everything in Lua. Many of the plugins I've migrated below are fully implemented in Lua, and it's amazing to think that the community is just getting started in harnessing a "proper", and much faster, built-in scripting language.
Then: gitgutter
Now: gitsigns
Gitgutter served me well for a very long time! However, with gitsigns the VCS feedback appears much, much faster, and that was reason enough for me to switch. I also prefer its more understated use of the sign column.
Then: Syntastic
Now: nvim-lspconfig
I have to give a shout out to ALE and coc-nvim, two great projects that I used for long stretches over the last five years. But as far as I'm concerned, Neovim's built-in LSP integration is absolutely the future in this space. I'd been cautiously kicking its tires before it was stable in 0.5, and ended up switching earlier than I'd anticipated thanks to the phenomenal performance increase over coc.nvim.
Then: vim-polyglot
Now: nvim-treesitter
Another performance-related switch here, based on a new feature in Neovim 0.5. I have only scratched the surface of what the treesitter integration has to offer, but am also excited about features like language-aware text objects. Again, the future in Neovim is really bright now that these tools are in the hands of an active development community.
Then: ???
Now: nvim-compe
Hard to believe I used vim for years without decent autocomplete. Sorry, vim curmudgeons, but modern editors have raised the stakes here, and the built-in Omnicomplete just doesn't measure up anymore. nvim-compe is snappy (thanks in part to Lua) and has a configurable list of sources (including, most notably, neovim's LSP client). I don't quite have the snippet support set up to my liking yet, but in every other respect it's been a great experience so far.
Then: Ctrlp.vim
Now: fzf.vim
Looking at the list of file finders in the original post was quite a trip down memory lane. Again, I switched to fzf eons ago, and I think the killer feature for me, besides the speed, was having the same file searching available in the shell. There are fancier new options available like telescope.nvim, but after a cursory exploration I've decided I'm quite happy with my trusty FZF setup.
Then: Ags.vim
Now: CtrlSF
I've been using CtrlSF for ages as well, as a UI for grepping across a project (via the spectacularly fast ripgrep). It's modeled on Sublime Text's project search, supports editing multiple files via search results, and is fairly customizable.
My full init.vim is up on GitHub, with a few other miscellaneous plugins and supporting config. Notably, I've started moving some of my more involved keybindings and supporting functions to lua modules. I'm still far from a Lua ninja, but compared to vimscript, making these kinds of customizations is significantly easier.
To some readers, spending years customizing a text editor probably seems frivolous, an extravagant waste of time. Why not just use VS Code? I can understand that perspective, but also derive a deep satisfaction every time I'm able to sculpt the digital environment where I spend hours each day in a way that fits my brain better. I'm very much looking forward to further exploring the new sculpting tools in Neovim 0.5.
]]>I'm not going to spend too much time re-immersing myself in that dumpster-fire-of-a-year, but what follows is the usual listicle of the books, tech, and miscellaneous stuff that helped me get through it.
For most of 2020, there wasn't a lot to do but hunker down and read. Fortunately for me, this is how I spend most of my free time already. Some of the books I most enjoyed:
You may have noticed above that like every other programmer and their dog, I spent a little time with Rust recently. While the language is too low-level for my current needs and tastes, I was impressed and inspired by its tooling and the deep integration of typed functional programming idioms in the language. Dipping my toes in was a great learning experience and I expect that I'll return to it at some point. Maybe lifetimes and the borrow checker will "click" for me next time.
Most of my other programming endeavors have been in TypeScript for the last 18 months. The language is still adding interesting features and I still feel like there is more to learn. For UI work, I'm quite satisfied with TypeScript/React/Apollo.
From time to time I add a top
tag on Pinboard to items that I particularly like (they show up as
bigger circles on my homepage's beeswarm chart). The ones I tagged in 2020 were:
Have I ever mentioned here that I'm a big ol' board game nerd? Before the current restrictions on social gatherings were in place, I had a lot of fun gathering with friends and family for the odd game night. I don't record new games or plays, so some of these are probably from 2019, but below are some of the "new" games I've most enjoyed recently:
I moved this site from Jekyll to Eleventy this year, but that was pretty much the extent of the effort I put into it. I certainly appreciate the dramatic improvement in build speed, but otherwise it was a mostly lateral move. After playing around with NextJS a few months ago (and being quite impressed), I'm already considering another migration. These technology changes are pointless, low-impact projects, but they're also decent ways to kick the tires on new technology and learn a few things.
]]>If you look solely at the spec sheet, the reMarkable 2 (aka RM2) is a pretty underwhelming product. Monochromatic screen. Meagre feature set. Underpowered CPU. No third-party apps, audio, backlight, or Bluetooth. As a distraction-free reading/writing/organization niche device, some of those are anti-features, but others would improve the product, depending on what your primary use case is. I would be remiss if I didn't mention another important downside– the RM2 is freaking expensive! I preordered the RM2, which knocked a few hundred bucks off the current list price, but if I was considering the purchase today, I would have a hard time justifying it.
I've been using the RM2 primarily as an notetaking device (its raison d'étre) and e-reader. Anyone who's worked with me in an office can probably remember messy piles of post-it notes on my desk; I've always found notetaking and sketching to be extremely helpful as thinking aids, and being able to mix digital organization with analog-style tactile immediacy with the RM2 has been a big win. The writing experience on the device is very good, and that's undoubtedly what most people are going to be purchasing it for.
As an e-reader, the RM2 is more of a mixed bag. The e-ink screen is gentle on the eyes, and the 10.3” screen is a near-perfect size for the technical books (nicely formatted PDFs) that I've been accumulating over the years. The refresh rate is good enough, though noticeable, and it's great to have all of the same annotation tools for books that are available for notetaking. The flip side is that the reading software is inexcusably limited. There's no way to see a list of pages with annotations, bookmark a page for later (!), or follow pdf links. It's mindboggling that after several years of developing the reMarkable software, these features are absent, but they update the software semi-regularly so I hold out hopes that they might get added later.
The hardware design of the reMarkable2 is undoubtedly it's strongest point. Not only is the RM2 svelte and solid, both the tablet and the pen have wonderful physical textures, which make handling and using the device a really pleasing tactile experience. The magnets that keep the pen and folio connected to the tablet are strong and give a satisfying "click" as the pieces snap together.
For the technically inclined, the RM2 is also surprisingly open. It runs Linux and you can ssh in as root to modify files and install (not officially supported) software and hacks. I have yet to try the "hacks" but it appears to paper over some of the more frustrating limitations of the stock UI.
Overall, I haven't been this smitten with a piece of hardware since the iPhone 3G (my first smartphone, over a decade ago). Despite its warts, the reMarkable 2 is now an essential part of my workflow and I would dearly miss it if something happened to it.
A lot of reviews directly compare the RM2 to an iPad, but the experience with each device is markedly different. To me placing them in the same category is almost nonsensical, though they're both nominally "tablets".
My kids really enjoy the RM2 as well. It's been a great motivator to practice their writing, but it physically pains me to see (and hear!) how much pressure they apply with the stylus (see nib wear, below)
Nib wear was a concern of mine before getting the RM2, as it looked like regularly replacing the nibs had the potential to add a significant recurring cost. As I was writing this post, I just replaced my first nib, after 6 weeks with the device. It seems the amount of pressure you apply when writing is a major factor in how quickly you'll go through nibs, and if not for my kids’ aggressive use, I think the nibs would each likely last over two months.
reMarkable also has a Chrome extension that lets you send articles to the device via their cloud service. It's pretty limited (images don't make the journey to the tablet if you use the default epub document export), but reading long form content is so much better on the RM2 vs a laptop that I find myself using it frequently.
If you're interested in the reMarkable, you really need to check out the reviews from My Deep Guide on Youtube. They're probably the most in-depth and unbiased reviews of a product I've ever seen, and will go a long way to help understand if the RM2 would be a good fit for you.
I jumped on the TypeScript hype train in 2019 and have been pretty impressed with it so far. After spending the better parts of 2 years using Flow, it was increasingly feeling like a dead end. By comparison, TypeScript has a massive (and growing) community, fantastic developer tooling, and decent documentation.
After tinking with OCaml/Reason for the last few years, I definitely miss variants (TS enums are a pale substitute) and pattern matching. But TS seems to be the most pragmatic typed frontend language around right now– 80% of the type safety with 20% of the effort required to get up and running with the more ironclad but obscure alternatives. It's also infinitely more employable, which is a little bit of a bonus.
Another language I spent a little bit of time with in 2019 is Lua. I'd previously messed with it a bit for use with Hammerspoon, but this year Neovim got first-class Lua support so I've been playing with it a lot more. Being able to script Vim without VimScript (ugh) or remote plugins is a treat!
At the start of the year I set out a list of 12 books that had been lingering on my shelves (physical or virtual) for years. Because I impulsively check out a lot of books from the library, it came down to the last week, but I managed to read them all. In decreasing order of my enjoyment, they were:
In total I read 59 books, which is pretty solid. Actually, it might be the most I've ever read in a calendar year. Other standouts read in 2019 included:
As I age, I find it progressively more challenging to find new music that resonates with me. So I was really excited to find Tiny Desk Concerts this year. The videos cover a wide set of genres, and the artists and sound quality are consistently awesome. My favourite video so far is the one featuring Joey Alexander, and I had the good fortune to see him in concert this year. It was the best show I've seen in years– he melted my face off!
This personal site got a fresh coat of paint late in the year, and I almost got a real blog post out, but not quite. With my flagging enthusiasm for posting here and the visceral cringe I get when reading my old posts, I periodically wonder if keeping this site up is worthwhile. But independent blogs are a somewhat imperiled medium, and one that I get a lot of value from. I want to do my part, however tiny, at contributing to the ecosystem. Here's to renewing it for another year!
]]>I will keep this post brief as at this point I forget most of the details of 2018. However the big theme was moving cities for the first time in my adult life. After many years in Vancouver, we picked up and moved to Victoria in August.
The “Why I'm leaving Vancouver” blogpost is a well-worn trope by now, but I will continue to resist the urge to indulge. I was hesitant about the move myself, but with several months of hindsight it has been a great change. Victoria is extremely bikeable, there's less rain, and the laid-back vibe suits my disposition well.
After considered it for many years, the move gave me the opportunity to dive into remote work. Once I worked out the kinks in my workspace and daily routine (perhaps fodder for a future post), I'm pleased to say that I've really enjoy it. I was already spoiled with a short walking commute in Vancouver, but the flexibility of schedule and proximity to family is hard to beat.
Open source and on-the-side coding took a backseat to “real life” priorities this year. I continued to monitor the ReasonML ecosystem, hoping its community would take off and I could justify pitching it seriously at work (hasn't happened yet). Work kept me busy and I was able to focus on helping build a large frontend app (React/Redux/etc).
I still managed to read a fair bit this year (56 books!). Here were my favourites:
I started doing some light journalling. It's been helpful at times to get thoughts out of my head and onto the page. Clearly it hasn't translated to increased blog output yet though!
]]>It was ReasonML, hands down. Last year I kept close tabs on this fledgling "language" (it's really just a toolset around the venerable OCaml), and was richly rewarded. The community is incredibly friendly, and there is so much neat stuff to learn by diving into a typed functional language. I wrote a canvas-based game, started working on some (very incomplete) d3 bindings, and am kicking around a few more small projects for fun. I will definitely be spending a lot more time with Reason this year!
I previously wrote up my review of the UI design course that I took early in 2017. While I don't do any design day-to-day, I'm really enjoyed continuing to pick at this hobby, and dipping back into the course videos and homework from time to time. If you are an analytically inclined person looking to gain some design skills, I still highly endorse it!
After chewing through 45 books last year, I think might have hit a new personal high score. Looking through the list, only of few of them were truly exceptional:
I started taking to baking bread. Flour Water Salt Yeast was inspiring, and breadmaking is a wonderfully tactile counterpoint to my usual computer-based hobbies. After a half dozen mildly successful attempts at sourdough, I'm now working on mastering a more basic white bread. The plan is to work up through pre-ferments and then back to regularly baking sourdough.
Also in the kitchen, I joined the cult of the Instant Pot. I'm only a few months in, but it does seem like a really useful gadget.
Still going through a bit of a dry spell as far as discovering new music goes. But while going through Stevie Wonder's classic period, albums, I finally found Fulfillingness's First Finale, which is now one of my all-time favourite records.
]]>The following is my take of the Learn UI Design video course. I paid for access to the course when it was in alpha last year. As the course is accepting new students soon, and I haven't seen too many longer-form reviews online, I thought this post might be helpful to anyone who's considering the course, but not sure if it's right for them.
As a programmer, I've always been drawn to the visual side of my field. I vividly remember making my first game (pong in Python!) and how amazing it was to watch things move crudely around the screen. Later on I worked at a small startup that didn't have a full-time designer, and acutely felt the pain of trying to put together styles and imagery that didn't look awful. As easy as some people make it look, designing user interfaces is a full-time craft, and unraveling its secrets is a challenge for most of us.
Despite chewing through countless articles and books over the years, passable design skills remained elusive for me. While some of these resources were excellent, at best they only gave me familiarity with concepts and terminology. Whenever I tried to actually build something visual, I got the same uninspired (or just plain ugly) results.
I subscribed to Erik Kennedy's email list after reading one of his excellent Medium posts, as he communicated design concepts in a way that made things "click" a bit easier for me. So naturally when he announced his online design course I was very interested. I signed up for Learn UI Design about a year ago, near the end of the first batch of students.
Learn UI Design is a hands-on video course, with an accompanying Slack channel for discussion and feedback. I won't rehash the syllabus here– you can a clear overview from the website. The videos are extensive (18+ hours in total), well produced, and easy to follow. Each topic is dealt with thoroughly, and I can't remember finishing a video and feeling like anything had been skipped over. My only (minor) complaint is that I'd love to see a few more subjects added, like animation basics, and maybe some UX topics. Erik is still adding new content over time, so it's possible the scope could widen a bit in the future.
If you like Erik's teaching style from his Medium posts, you'll find it translates well to the videos. Maybe it's the cynical programmer in me, but a lot of design instruction out there comes across as overly artsy or "hand wavey". Erik's style is the opposite– very direct and pragmatic.
The Slack channel is a really helpful component of the course as well. When I signed up I thought it was kind of a "throw in", but being active there is pretty integral to getting the most value out of the course. Besides the general banter and tips, posting homework solutions there for feedback has been really helpful. I'm a perfectionist and I hate putting my work "out there" when I'm not confident in it (every blog post here is a struggle), so this was tough for me at first. But the other students have been really friendly and helpful, and Erik's direct feedback has been invaluable. The level of feedback and mentorship he provides each student is really commendable.
Remember how I said the course has two main components? There is also a third part that I think is perhaps the most important of all: the homework. Looking back at my previous attempts at learning design, my biggest mistake was not getting enough reps in with the concepts I was reading about. Most videos in the course come with one or more related homework assignments, so you can apply your new knowledge right away. Maybe the idea of homework makes you recoil in horror, but if you're serious about levelling up your skills, you need to do the work to get there.
My personal favourite course section is the one on colour– an area that has historically been my achilles heel. Erik does a great job of explaining why HSB is vastly more useful than RGB for design work, and presents lots of useful tricks and heuristics. Other highlights for me are the videos on grids, imagery, spacing, and alignment.
One "meta" takeaway from the course is the importance of iterating on your work. Erik specifically talks about the importance of iteration early in the videos, and applying this lesson pays dividends as you complete the rest of the coursework. Trying to find multiple solutions to problems and tweaking as you go not only makes your designs better, it's also applicable to many other creative disciplines.
Is Learn UI Design the best way possible to learn UI design? I don't know; I haven't tried every course or method, and the answer probably depends on your background and personality. But I can confidently say that nothing I've watched or read has been remotely as helpful for me personally, so I highly recommend it. My recommendation comes with the caveat that you should plan to spend at least 3 hours weekly (ideally 5+) working on the course to get the best results. There's a lot of material and I found it's important to immerse yourself and keep your momentum going.
A year after joining, I still get a lot of value out of the Slack channel, and I have referred back to the videos numerous times (the course gives you lifetime access). There were a few new videos added last week that I still need to catch up on. Anyways, I hope this review has been helpful and gives you a feel for the course. I'm @af on the Slack channel and hope to see your work there soon!
]]>Calling envalid "my" library is no longer accurate, as the last few months have brought contributions from several others. In particular @SimenB contributed most of the new code that culminated in this latest major release 👏.
I've never really described envalid's features in detail here, but briefly, here are some of the things it handles for you out of the box:
process.env
are converted to a useful format centrally, rather than all across your
appdotenv
package, so you can drop your development/testing default values in
a .env
file instead of hardcoding them somewhere.env.isDev
, env.isProduction
, and env.isTest
to replace the if (process.env.NODE_ENV === 'production')
checks that tend to get strewn about.Two nice little additions are the use of prettier
for code formatting and new host
and port
validators. In my experience, hosts and ports are extremely common env vars so it's nice to have
some extra validation baked in for these.
The major (and only breaking) change is to envalid's "strict mode", which gives you some extra guarantees about your validated environment object. In v4, strict mode will throw if you try to set, or even access, an invalid property on your environment object. If the mistake was a simple typo, envalid will helpfully suggest a related property that you may have meant.
The following (contrived) example shows how this helps in practice. Note how well it works when destructuring your env imports– the errors happen at startup time, rather than later on during the execution of your server route.
// Oops! I forgot a 'T' in there.
// But in v4.x envalid will throw instead of returning `undefined`
const { STRIPE_SECRE_KEY } = require('path/to/my/env/object')
app.get('/customer/info', (req, res) => {
const stripe = require('stripe')(STRIPE_SECRE_KEY)
stripe.customers.retrieve(req.user.customerId)
.then(customer => res.json(customer))
})
It feels like envalid is "mostly done", but I probably would have said the same thing three months ago, before all of the features above landed. It's exciting to see adoption pick up (currently just a shade under 10k monthly downloads) and lots of great community feedback and contributions. Here are a few random ideas I've thought of that might be useful in the future:
If you have any other ideas, please drop by the envalid issue tracker!
]]>I wrote a rambling post about how I was cautiously optimistic about GraphQL shortly after it was released. This year I finally took it for a spin on a project at work, and so far I've been very impressed. We are using Apollo as our GraphQL client, and it too has been a real treat. I hope to dive into this a bit more in a future post, but these two technologies have taken a lot of the pain out of writing network APIs and building isomorphic/universal web apps.
In other news, I spent some time learning the basics of Haskell, which was certainly a mind-bending experience. Rather than becoming a proficient Haskell programmer, I wanted to become more conversant about higher-level functional programming concepts. This year I might try dipping into OCaml or its new variant Reason to further my journey.
I didn't make many open source contributions this year, but two projects of mine did get some love. Envalid, my environment variable validation library, got a complete rewrite to a much saner API. apollo-local-query is a new, tiny library to make server rendering with the aforementioned Apollo a bit easier.
I don't have any specific goals for open source this year, but I do have a skunkworks project that I revisit every couple of months. Maybe this year I'll sharpen it into a more "serious" project.
Of the ~40 books I read this year there were five standouts. I don't generally read new non-programming books so I was surprised that three of them were actually released in 2016.
My investment in this blog was basically non-existent in 2016, and I'm ok with that. Till next time!
]]>Useful as they may be, without discipline env vars can turn into a liability - acting as chunks of mutable global state sprinkled throughout your program. Here we'll look at three env var usage antipatterns that are commonly seen in web apps.
Environment variables are a type of input to your program, and as such should be treated with suspicion and care. While malicious inputs are generally unlikely in this case, if you expect a number or an email address and that expectation is not met, it's best to throw an error as soon as possible, ideally at deploy time. This makes the runtime behavior of your app much more predictable and eliminates some of the guesswork of configuring your app for others.
While validating inputs from the environment is an essential first step, as always it's important to keep things DRY. This means your logic for accessing and validating an env var should be contained in a single place, and not duplicated wherever the variable is accessed. Ideally all direct contact with, and validation of, env vars should happen in a single place in your program. This also makes it easier to see at a glance what your program's configuration dependencies are.
From the program's perspective, environment variables are a form of global state. Global state is not inherently bad if it remains static, but once it changes it becomes a rich breeding ground for bugs and unexpected behavior. By wrapping env var access in a read-only data structure, you can side-step these pitfalls and increase the predictability of your code.
The antipatterns above are applicable to any language or framework. A pattern I've found useful for sidestepping these issues is to centralize all environment accesses through a single module that does nothing else. When written in a declarative way, this module also serves as a form of executable documentation for anyone deploying the app. The rest of your code can import this module and use it as an immutable map of verified environment attributes.
For nodejs programs, I maintain and use envalid, which provides an implementation of this approach, and should effectively mitigate the env vars footguns described above.
]]>I can't think of a year in recent memory where I learned so many new technologies. It’s no exaggeration that my tools of choice are now completely different than they were just 3 years ago. Of course the rate of churn in the front-end world has been a frequent topic of lamentation this year, but generally I welcome all of the great new ideas and libraries that we have to choose from. Here are my top picks from 2015:
Finally, a variant of Flux that just feels right. I love how beautifully simple the APIs are, and there’s a really great community and ecosystem sprouting up around Redux. Watch the conference talk on how it came to be, and the really excellent tutorial videos.
It seems a lot of people are moving from JSHint to ESLint, and it’s easy to see why: style checking, pluggable rules, and a really active ecosystem make it by far the best JavaScript linter going forward.
Webpack takes a lot of heat (often deserved) for being a beast to configure, but there really isn’t anything comparable for transforming and bundling web assets. And once you experience HMR for JavaScript and CSS, writing a web app any other way feels painfully archaic.
I was definitely playing catch-up on this one, but 2015 was finally the year that browser support for CSS's Flexbox made its widespread use feasible. If you write CSS and haven’t jumped in yet, check out how much easier it’ll make your life.
I moved from Vim to Neovim this year as my main editor, and it has been remarkably stable for such an ambitious young project. If you use Vim and aren‘t on an Amiga, I definitely recommend switching, if only for the async command support (check out Neomake).
Since November, I have been spending a lot of time with react-native. While it is still raw in a lot of ways (particularly the docs), it is already an incredibly powerful platform for building mobile apps. I am constantly stunned by
Looking back on the 39 books I read, there were surprisingly few technical ones last year. Of the half dozen tech books, CSS Secrets was by far the best. If you have some experience with CSS, I very highly recommend it. There were a few non-technical standouts as well:
One of my goals for the year was to write a few more things on this blog. While I missed the goal of one entry per month, I eked out 8, still far above my usual rate. Though I'm not particularly proud of anything I wrote, I am glad that I managed to force some pieces out, just to get the practice. There are no blog-related goals for 2016, so we’ll see what happens.
]]>I've personally felt this pain on more than one occasion. Excited to try out a new idea, I bring up my text editor only to realize that I can't remember how to configure webpack. Or Babel 6 changed a bunch of things that I haven't learned yet, but a library I want to use depends on it. And on and on. These tooling-related roadblocks can quickly kill the enthusiasm for an idea.
The discussion around this issue started by considering the experience of beginners, but soon many more experienced developers voiced their frustrations with the current state of webapp tooling. Clearly, both groups of developers are struggling with this, but their needs are dramatically different.
For those new to web development, we really need to keep the number of suggested tools and technologies to a minimum. That means no Babel, no JSX, no Webpack, no Flux/Redux. Before you use these tools you need to understand them. And before you can understand them, you have to experience the pain points they exist to solve.
A single html file with inline CSS and JS is a great starting point for a beginner. They can save it locally, instantly use any text editor or environment that they are comfortable with, and easily publish with something like Surge.
Of course, using a single html file goes against several web development best practices, but that is completely irrelevant for a beginner. The emphasis should be on facilitating learning, not conforming to every best practice out of the gate.
For more seasoned developers, part of the problem is the tooling we use (webpack, babel, etc), once experienced, provide ergonomics that are hard to do without. I never want to start a project without hot reloading again. It's also increasingly annoying to eschew ES6 features or write CSS without a preprocessor. If you use JSX, there's another thing that imposes a build step on your project. These luxuries trap us in increasingly intricate tooling setups, yet for all but the most trivial prototypes, I think they provide a net benefit over the lifetime of a project.
It seems people often suggest boilerplates as a solution to the problem. If someone has already gone to the trouble of setting up all these components together, why not just pull that in and build on top? Indeed, boilerplates seem to be growing in popularity and (even more so) in number. However, once you need to deviate from the boilerplate's built-in conventions, you need to descend into its constituent tools, sometimes learning them from scratch.
If you're a web developer by trade, I think a build-your-own-boilerplate approach makes the most sense. Instead of cargo-culting someone else's boilerplate project, take the time to learn your tools thoroughly, set up a boilerplate that you can quickly clone and extend, and use that for your projects.
With one command your boilerplate should ideally:
package.json
(or the equivalent for your ecosystem of choice)Hello world
output right awayIn theory, setting this up should be a one-time cost, paying interest every time you start a new project. In practice, however, our tools change rapidly and there will always be temptations to add new libraries and upgrade to the latest and greatest. Resist! You should really only need to update your boilerplate a few times a year.
]]>It’s hard to imagine now, but the frontend community’s initial response to React was pretty lukewarm (at least from where I was sitting). David’s post made a lot of people sit up and take notice. I don’t think it’s coincidence that interest in React began to really take off shortly thereafter. React’s benefits are pretty well documented by now, but its widespread adoption was never a given.
While certainly not a new idea, immutable data structures only seemed to "catch on" in the front-end world since Om’s release. Now popular libraries like Immutable.js give them a more familiar JavaScript API, and they’re even being proposed for inclusion in a future version of EcmaScript.
Another technique popularized by Om is placing all application state in a single object. Easy undo/redo and backup/restore are its most commonly cited benefits, but I'm curious to see what else it makes possible as more people explore this idea. Omniscient and Redux (among others) have brought it to JavaScript, and the latter is currently seeing an explosion in popularity.
In late 2013 it seemed like most people were pretty happy writing MVC*-ish* apps in JavaScript. The Om blog post was one of the first pieces I saw that not only gave a cogent argument against it, but also presented a reasonable alternative. A few months later, Flux was released. The breaking of the MVC monoculture has allowed a lot of diverse ideas to flourish, which has been both fascinating and illuminating. Let’s hope it continues for a while yet.
]]>There’s one area of our work that we often don’t think to automate, but which can yield immense time savings: the way we interact with the GUI on our desktops. Even if you spend the majority of your time in one terminal window, I’m willing to bet you frequently switch over to your web browser and/or music app.
If you’re on a Mac, this is where Hammerspoon comes in. This strangely named app gives you a Lua API for a boatload of common desktop and application operations. Here’s a quick list of what I use it for:
Global hotkeys for most commonly used applications, to avoid the Cmd-Tab
,
Cmd-Tab
, Cmd-Tab
, Cmd-Tab
dance to get to a certain app. Getting
to iTerm is always Ctrl-2
, regardless of when it was last in focus.
Basically, this is a simple substitute for a window manager. With one global keystroke, you can resize a window however you like, send it to a different screen, or snap it to a grid that you have predefined.
Volume/muting, in a way that is more customizable than the default OS controls.
Having global hotkeys for music is a godsend. No app (or mental context) switching is necessary when you're deeply concentrating on something else.
Hammerspoon’s API docs have a full list of everything that’s available. Even after using it for several months, there’s a lot there that I wasn’t aware of new features are being added constantly. My dotfiles are a pretty simple starting point if you’re not sure how to jump in.
I highly recommend checking out Hammerspoon. It’s a robust and extremely powerful automation tool for areas that you didn’t know you wanted to automate. Using it has also been a great introduction to Lua, which seems like a nice little language. If you come across novel applications for Hammerspoon, please let me know. I’m always looking to expand the ways I use it.
]]>If you're a Canadian and haven't been hiding under a rock, you're probably aware there's an election coming up. When we're not hearing about candidates peeing in mugs or how Bill C-51 reflects the teachings of Jesus, we're knee-deep in speculation over who's going to be in power later this fall.
Unless you support the Conservative party (full disclosure: I do not), there's a good chance you've lamented the "vote splitting" of the left, and the tactical/strategic voting that seems necessary to prevent Conservative (CPC) rule.
The spectre of vote splitting is invoked countless times in the run-up to each election, but we rarely get a chance to see how it actually impacts the results. Meanwhile, the poll numbers we see in the press are almost always the nation-wide popular vote, which give no insight into what's happening at the riding level. Since our first-past-the-post voting system means our elections are really hundreds of separate contests, it's complicated and counterintuitive to see how changes in popular vote translate to movement in seats.
I took an interest in this topic and built a data visualization that allows you to modify the popular vote in the 2011 election and see how it would have affected the results. You can also zoom in and click on ridings to see how each of them would have played out with your changes, or look at the absolute best case of strategic voting in 2011.
Some pointers on using the visualization:
Before drawing any conclusions, it's important to stress that its data is limited to the 2011 election. This year's election has 30 new ridings to consider, many existing boundary lines redrawn, and polls that look very different than they did four years ago. In summary, you really can't extrapolate too confidently from the 2011 results to today. However, many of the trends and party strongholds remain the same in 2015, and gaining a better understanding of past results is still useful in revealing the dynamics of our democracy.
The Green party is the party most frequently accused of siphoning off votes that could be used to defeat the Conservatives. With the visualization we can see that even if all 2011 Green voters voted for the second-place NDP, or voted perfectly strategically, we would have still ended up with a Conservative government, and still a majority in the first case. This lends some credence to Elizabeth May's rebuttal that the Greens did not split the vote appreciably. But could it be different this year with the top three parties closer in the polls?
If you played around with some of the Green vote scenarios above, you may have noticed that transfering their votes to the Liberals instead would have cost the CPC an extra five seats. This highlights a pattern: even though the NDP finished second in seats in 2011, the Liberals were actually in more close contests with the Conservatives and may stand to steal more seats from them. This may partially explain why most of the CPC's attack ads to date have focused on Trudeau and not Mulcair, despite the NDP's strength in the polls for much of the campaign.
There were actually only a handful of ridings where the Conservatives and NDP were in close competition with each other in 2011. That's why if you are looking to vote strategically, choosing the top non-CPC party in the popular vote numbers may be counterproductive; you're much better off looking at riding-by-riding polls and supporting whoever has the best chance of knocking off the Conservatives in your district.
One thing that's clear from running through different scenarios is that if the Conservatives lost support to the Liberals as current polls indicate may be happening, they'd be in trouble in many swing ridings across the country.
At the same time, their strongholds in the prairies appear to be very safe in some ridings they collected upwards of 80% of the vote in 2011. There has been speculation that the NDP's victory in the Alberta provincial election may presage a shift in the federal election, but it seems unlikely and the current polls don't support that theory either.
From trying out various scenarios, it seems there are three major classes of ridings for the would-be strategic voter to consider:
If you were to go back in time to re-cast your ballot in 2011, it seems clear that the majority of ridings are of type A or B. If you lived in one of them, you wouldn't need to worry about vote splitting at all, and should vote for the party that best aligns with your values. However, in the ridings that are shaping up to be battlegrounds, you may want to vote strategically, with the help of VoteTogether and the current polls in your riding.
A few more things that deserve attention for October 2015:
On a final note, the source code for the visualization is available. Please file an issue on Github if you have any suggestions for improvement.
]]>Web developers are a fickle bunch, and the massive churn in the world of web frameworks is well documented. So what's far more interesting than React's popularity is the way it's changed how we think about front-end web applications. React's key features are great encapsulation through components, and declarative UI, rather than directly manipulating global state (ie. the DOM). React's virtual DOM is generally considered to be its key feature, but in reality it's an implementation detail that powers these two breakthroughs.
A few weeks ago, Facebook released the initial spec and reference implementation for GraphQL, a new way to do data transfer between servers and app/web clients. Just as React and Flux challenged our assumptions that MVC was the preferred (only?) way to write clean frontend applications, GraphQL now puts REST in the crosshairs.
REST has turned into a bit of a sacred cow among web developers. It's generally considered "the right way" to do data exchange between servers and web UIs, and what we've lost with this uncritical attitude is a more nuanced understanding of REST's tradeoffs for the systems we're building. Furthermore, most of us are pretty low on the Richardson Maturity Model, so you can argue that often we're not even doing REST correctly. How many REST APIs have you written that actually use hypermedia to link and expose affordances between your resources?
I highly recommend reading Facebook's GraphQL introduction, as it does a fantastic job of enumerating the problems with REST for the increasingly complex and performance-sensitive systems we're building today. It also lists issues with the "Ad Hoc Endpoints" that many of us build and erroneously call "REST APIs".
One of the promising things about GraphQL is that it's not tied to HTTP at all– this is great for two reasons. First, it means you should also be able to use it with other transports like Websockets or TCP. Secondly, HTTP has always been pretty awkward for representing application semantics. If you've ever agonized over the correct response code for an error condition in a REST API, you've experienced this first-hand. It shouldn't be surprising that a protocol designed for document delivery is not an ideal fit for the wide variety of things we do with APIs and web applications today.
GraphQL is still extremely young as a public project, so it's hard to tell if it will live up to its promise. Like any technology, it will have its pain points, but at the moment only people inside of Facebook are intimately aware of them. It's also clearly still at the "technical preview" stage, and some critical things like mutations (ie. writes to your data) are still not fully fleshed out in the documentation. Things should really ramp up when Facebook releases Relay, a client-side JavaScript framework they've been teasing that's designed to integrate tightly with GraphQL. It's projected to drop some time in the next month and I'm really looking forward to digging in, so we can get a wider look into GraphQL's potential.
The JavaScript community has a history of piling on those who advocate semicolon-free code (although the tide does seem to be turning of late). For a long time, I was in the pro-; camp. While semicolon-free code has always looked easier to read and “cleaner” to my eyes, why would you seemingly invite bugs into your software for such a small aesthetic benefit? Also, Douglas Crockford forbade them (his views are apparently still a primary factor in the style choices of many JavaScript developers).
Before getting into the crux of my argument, I must concede that if you write your
JavaScript without trailing semicolons, you need to make a habit of adding them to
the start of the line in
two specific cases
– when you begin your line with a [
or a (
. Otherwise in some cases JavaScript
will interpret those characters as the start of array indexing or function invocation,
respectively.
Anyways, I was experimenting with semicolon-free JS on a side project a few months ago when I tripped up and forgot the two edge cases above. What I saw caused me to swear off trailing semicolons for all future projects. It looked something like this:
The screenshot above shows JSHint catching the two aforementioned cases where omitting trailing semicolons could cause a bug in JavaScript. The beauty in this example is that this feedback happened instantly in my editor (via syntastic in Neovim).
If you don't have a linter making these (and other) automated checks for you before you check in, a) you're missing out, and b) please refrain from lecturing others on programming style and code quality. If you do have linting checks in place, you can skip trailing semicolons. It's up to you, but with today's tooling support for JavaScript, code "quality" and robustness should not factor into your decision.
Further / reading / on / semicolons. Also, for a good time, read this entire thread
Postscript: There are a few more contrived cases where ASI can bite you, but in my experience they're not worth worrying about:
function thisIsTerrible() {
return // ASI would strike here; returns `undefined`
{
foo: 'bar'
}
}
Seriously, who writes code like this? Oh yeah, and JSHint will catch this too.
]]>It would be irresponsible to discuss Vim plugins without first imploring the reader to spend a lot of time with plain Vim first. You will get far more out of plugins once you have a firm grasp on Vim's fundamental actions, motions, and overall editing philosophy. By far the best resource I've found so far is Practical Vim, by Drew Neil. It is well worth your money and time if you're serious about Vim. His Vimcasts video series is also excellent.
Before you start messing around with plugins, it is imperative that you choose and install a Vim plugin manager. Dealing with installing, upgrading, and deleting Vim plugins by hand will leave you in a world of pain. It's one of the things about Vim that is really terrible out of the box. Fortunately, there are quite a few good plugin managers out there, and I use and strongly recommend NeoBundle. Its killer feature is the ability to pin each of your plugin dependencies to a specific Git commit– as far as I know, none of the alternatives do this. Pinning to a commit keeps your plugin installs repeatable, and also gives you more flexibility since you aren't limited to in pinning only to tagged versions.
See also: pathogen, vundle, vim-plug
After using vanilla Vim for a while, navigating between and launching files can still be a pain point. Probably the most popular plugin for addressing this is the mighty ctrlp.vim. It does the project-wide fuzzy file matching you may have come to expect from Textmate or Sublime, as well as fast MRU and buffer switching. I use all 3 modes dozens of times daily, and ctrlp is probably my most indispensible plugin. If there's a downside, it's that ctrlp hasn't seen an update in almost two years, but there is an actively developed fork that might be worth checking out.
Another common use case is searching file contents within your project. I've just started using Ags.vim for this, which uses the excellent silver searcher tool under the covers. It's really fast and makes navigating the results easy. I've used a few other plugins for this, but Ags seems to hit the sweet spot for me.
See also: Ack.vim, Command-T, FuzzyFinder, Unite.vim
Comprehensive, up-to-date syntax highlighting is a must for any programmer. vim-polyglot gives you great syntax highlighting for a ton of different languages, while minimizing the increased startup time from having them all installed.
Also, getting quick feedback on errors as you type saves a ton of debugging time, especially if you're writing in a dynamic programming language. Syntastic runs linters and other checkers as you save your code for quick feedback. It does cause some lag with slower linters (looking at you, JSHint), but that's a limitation of Vim's purely synchronous APIs, and despite this it's still more than worth your time.
Fugitive is the ultimate plugin for
git integration. I've had it installed for years and have still barely scratched
the surface of all the things it does. For a taste, install it and enter :Gblame
or :Gdiff
while editing a file with changes. :Gmove
and :Gremove
are very
handy as well, but I haven't yet absorbed any of the other commands into my
workflow yet.
Another nice tool is gitgutter, which shows which lines of the current file have been added/removed/modified in the "gutter" to the left of Vim's line numbers. It seems like a small utility, but I could honestly not go back to editing without this information available at a glance. It also enables the following key mappings in my vimrc, which allow me to jump to the closest modified "hunk" in the current file, without needing to know anything about where that is. Super handy!
map <C-j> :GitGutterNextHunk<CR>
map <C-k> :GitGutterPrevHunk<CR>
Some other plugins I use and recommend (but am too lazy to write about further) include:
You can see the full list near the top of my vimrc.
I confess to being somewhat of a plugin junkie, so this post is really just a snapshot of where my setup is now. I'm sure things will be a little different in a year's time. If you share the same tweaker's mentality, I recommend following usevim and the vim subreddit, which are generally how I keep tabs on the Vim community. Also, the Neovim project is making great progress, and I'm excited to see how its Lua support and async capabilities will impact the plugin landscape going forward.
]]>I read 40 books last year, with the following standouts:
I was well on track to discover exactly zero new music last year, until R&B legend D’Angelo came back from the dead to release Black Messiah in late December. While it's definitely not at Voodoo's level, I enjoy the new album, and at least it gave me something fresh to listen to. Looking forward to actively seeking out new music again in 2015.
In 2014 it was time to learn a few technologies I'd had my eye on for a while:
At the end of the year I had a few things to show for my efforts:
I'm also working on a Web Audio-related side project that will hopefully see the light of day at some point.
Work was steady for 2014. A highlight was definitely implementing a few data visualisations with d3 (dataviz was obviously a major theme for the year).
Nada.
Very little.
So it turns out there wasn't too much to write about (here) for 2014. My life last year was dominated by non-programming concerns, and was overall pretty damn intense and stressful. I begin 2015 refreshed, and extremely thankful for a lot of things in my life. One of my goals for the new year is to write here a little more– stay tuned for more questionable ramblings.
]]>The main contenders for terminal IRC seem to be irssi and WeeChat. I went with WeeChat, since it seemed to be the more modern and actively maintained of the two. Both are popular options, and you probably can't go wrong with irssi either. Even though WeeChat is allegedly the more “user-friendly” client, I encountered some bumps getting it set up on OS X (Yosemite)– hence this post. A lot of what I learned was cribbed from the WeeChat quickstart guide, so I highly recommend reading through it if, like me, you're just getting started.
Below is a screenshot of what you'll end up with at the end of this post. Note that I'm using custom terminal colours, so YMMV on that front. Also, the culmination of my experimentation is on github if you want to skip these ramblings.
If you're interested in a command-line IRC program for OS X, I'm going to assume you have Homebrew installed, or at least know how to get it. Install WeeChat with:
brew install weechat --with-perl --with-python
The --with-perl --with-python
flags are important if you want to use WeeChat
scripts, since most of the popular ones are written
in one of those two languages. You can also add --with-lua
and --with-ruby
if you think you'll need plugins from those languages.
You start WeeChat, predictably enough, by entering weechat
in your terminal
app of choice. After that, things can be a bit bewildering. The first time run doesn't give
you any hints for how to connect to a server, configure the program, or
do much of anything. The magic command to get you started is /help
. This lists
the available commands used to interact with WeeChat. Each command should be
prefixed with a /
, and you can (and should) run /help {command}
to get more
information about the important ones.
A few essential commands and hotkeys:
/quit
exits WeeChat/set
is used to read & write your WeeChat configuration. The contents of
/help set
is one of the first things you should read as a new WeeChat user./save
saves your current configuration to various config files, in
~/.weechat
by default. Out of the box, WeeChat also saves your up-to-date
configuration any time you exit the program./close
closes the current "buffer". If you're familiar with vim, WeeChat's
concept of buffers is similar. Otherwise, just assume that a buffer maps
one-to-one to a connected IRC channel for now./join {channel}
joins an IRC channel (once you're connected to a server;
more on that in the next section).Freenode is where the majority of programming IRC talk happens, so let's connect to it. WeeChat comes with basic Freenode configuration out of the box, which is nice and convenient. I'm going to assume you have a Freenode account (or will connect without one); registering there is outside the scope of this post.
You can run /set irc.server.freenode.*
to see all of the available freenode
settings. I configured the following settings (substitute your own values where
applicable):
/set irc.server.freenode.addresses chat.freenode.net/7000
/set irc.server.freenode.autoconnect on
/set irc.server.freenode.autojoin {comma-separated list of channels to join}
/set irc.server.freenode.nicks {nicks to use}
/set irc.server.freenode.sasl_password {your freenode password}
/set irc.server.freenode.sasl_username {your freenode username}
/set irc.server.freenode.ssl on
/set irc.server.freenode.ssl_dhkey_size 1024
I'm a little fuzzy on whether SASL authentication helps much if you're already connecting over SSL, but I turned it on anyways. This post has more information on that.
Once you've entered these settings, /quit
and restart WeeChat, and on the next
startup WeeChat should try and auto-connect to Freenode.
One glitch I hit pretty early was that OS X apparently doesn't ship with the SSL CA certificates needed to connect to Freenode over SSL. Of course, you could leave SSL off, but after following the news for the last few years, that just seems irresponsible. The error message I got looked like this:
gnutls: connected using 1024-bit Diffie-Hellman shared secret exchange
gnutls: receiving 2 certificates
- certificate[1] info:
- subject `OU=Domain Control Validated,OU=Gandi Standard Wildcard SSL,CN=*.freenode.net', issuer `C=FR,O=GANDI SAS,CN=Gandi Standard SSL CA', RSA key 2048
bits, signed using RSA-SHA1, activated `2014-01-13 00:00:00 UTC', expires `2015-01-14 23:59:59 UTC', SHA-1 fingerprint `a0fde217de32fae602fe67409697e15ac06f0286'
- certificate[2] info:
- subject `C=FR,O=GANDI SAS,CN=Gandi Standard SSL CA', issuer `C=US,ST=UT,L=Salt Lake City,O=The USERTRUST
Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Hardware', RSA key 2048 bits, signed using RSA-SHA1, activated `2008-10-23 00:00:00 UTC', expires `2020-05-30
10:48:38 UTC', SHA-1 fingerprint `a9f79883a075ce82d20d274d1368e876140d33b3'
gnutls: peer's certificate is NOT trusted
gnutls: peer's certificate issuer is unknown
irc: TLS handshake failed
irc: error: Error in the certificate.
irc: reconnecting to server in 10 seconds
The WeeChat FAQ has an entry on
this, but
the curl-ca-bundle
package it mentions doesn't seem to be available in homebrew.
Instead, you can follow this gist to
install the CA bundle that you need. Update: on OS X 10.11 and later, follow the
instructions in this comment
instead
Back in WeeChat, the following command will point to the CA file that you just created:
/set weechat.network.gnutls_ca_file "/usr/share/curl/ca-bundle.crt"
Now restart WeeChat and it should finally connect to Freenode successfully!
If you followed the connection instructions above, your IRC password is now
stored in plain text in your WeeChat config file, which is, um, not ideal.
Fortunately, WeeChat has the /secure
command, which lets you store sensitive
information in an encrypted local file, and will prompt you
for a password to unlock it on startup. The user guide has a nice
section on using this
feature.
You can customize and extend WeeChat by installing various "scripts". It comes with
a built-in script manager (try /help script
), and tons of
scripts are available for installation. As mentioned
earlier, you need to have support for a plugin's language (generally perl or
python) compiled in for them to be installable.
The buffers.pl and iset.pl plugins are essential. Assuming you built WeeChat with perl support, you can install them with the following commands:
/script install buffers.pl
/script autoload buffers.pl
/script install iset.pl
/script autoload iset.pl
Buffers.pl gives you an always-visible list of the buffers that you have open
(in my opinion this should be built-in to WeeChat). You can tweak it a bit if
you want, but it works great out of the box. iset is a nice UI for interactively
editing your WeeChat configuration, rather than entering verbose /set
commands
every time you want to change something. Install it and read /help iset
for more
details.
The other scripts I've found useful so far are:
urlgrab.py
- lists and opens urls from your IRC buffersnotification_center.py
-
uses OS X's native notifitions to alert you to IRC highlights and private messagescolorize_nicks.py
- colours IRC nicknames in the messages themselvesHere's a miscellaneous list of other stuff I recommend looking into:
Customizing the WeeChat UI colours. For example, the following colour tweaks made things a bit more readable for me:
/set weechat.bar.title.color_bg black
/set weechat.bar.status.color_bg black
Filtering out join/leaves. In many IRC channels the actual conversation can
be drowned out by tons of join and leave messages. WeeChat has a nice way of
intelligently filtering these out as needed; run
/filter add irc_smart * irc_smart_filter *
to activate it.
WeeChat lets you easily customize your keyboard hotkeys. I'm a complete hotkey
junkie, so this is one of my favourite features. Read /help key
for more info.
It's only been two weeks, but I'm really enjoying WeeChat so far. For the first
time, having IRC open feels natural and unobtrusive to my workflow. While the
initial learning curve can be quite steep, once you understand how things are
laid out WeeChat is really fun to explore and customize. My weechat
config is online if you
want to crib some settings. And if you have questions or need help, #weechat
on freenode is a great place to ask.
My first, and most “successful” project, djangbone is a REST API library for Django. I was learning Backbone.js at the time (this was in 2011), and wanted to write some backend APIs that worked with Backbone's conventions. Djangbone is intentionally minimalistic, but also pretty extensible and you can create a pretty useful API very quickly.
I've been pleasantly surprised by how much attention Djangbone received. I put it on Django packages early on, and that seemed to get it some traction. As of this writing, it's still the 4th most popular API library there, ranked by GitHub stars.
Another project that received a bit of traction, backprop is a Backbone plugin that helps you use JavaScript's properties on your models.
Even though properties are pretty commonly used in Python, they
don't seem to have found much uptake in JavaScript-land since being introduced in
ES5.
I always thought that was a shame, and replacing Backbone's somewhat ugly model.get('name')
for property access seemed like a perfect fit for them. On top of that, backprop lets
you define lightweight schemas (eg. type coercions and default values) along with
your property definitions.
littledom was a fun pedagogical exercise– it apes a subset of jQuery's DOM manipulation API. I learned a lot while writing this and peeking into the internals of jQuery and Zepto. It's also come in handy for a couple of small side-projects where jQuery felt like overkill.
[shamus] is a project automation/watcher desktop application. It's a node-webkit app that runs pre-defined tasks when files in a (recursively) watched directory change. I've found it really useful for running unit tests, linters, and build tools and receiving near-instant feedback without jumping between apps. However, since I'm now using tmux pretty heavily, I haven't fired shamus up lately. I'd like to try making a curses-based version to run in a tmux pane at some point, that could be pretty useful too!
d3 is a library that had been on my radar for a long time, but I'd never sat down and built something with it. Earlier this year I finally took the plunge and built a little unit visualization for one of my favourite video games, OpenRA. I still have reservations about the resulting design, but it was a fun learning exercise. If you're familiar with OpenRA, you should check it out.
A fun little game I made a few
years back. One of my first experiments with <canvas>
, this is a clone of
a Flash game that I found incredibly addictive. My nephew seemed to really like
my version and told me he played it a lot, which I thought was
pretty great. If I remember correctly, my high score is around 6300...
There are a few other odds and ends on my GitHub profile, (including my dotfiles and this web site). I have a stack of open source ideas I'd like to get to, but finding the time has really been a challenge of late (for very good reasons).
]]>Completed 38 books (not bad). Favourites included:
Overall not bad, but there was some personal stuff that put a damper on 2013 for me. Bring on the New Year!
]]>Using the <esc>
key (or <C-[>
for that matter) to exit Insert mode
is quite a stretch on standard qwerty keyboards. Since vim usage
involves making this mode switch constantly, this is a big annoyance.
It must be a weird manifestation of OCD, but no matter which program I’m
using, I compulsively save my work after almost any edit. In vim, this means
hitting :w<CR>
to make sure the current buffer is saved.
That is a lot of keystrokes to go through every few seconds!
My favourite vim mapping addresses both of these problems, and has made editing much more pleasant.
The first step is to remap our awful CapsLock key to pull double-duty: when
pressed, it works as an <esc>
keypress, and when held down while pressing
another key, it works as a <Ctrl>
modifier key. I picked up this trick from
Steve Losh’s awesomely comprehensive blog post on keyboard customization,
and it has served me very well for the last year. It uses KeyRemap4MacBook,
but I’m sure similar programs exist for Linux and Windows.
With that mapping in place, an <esc>
key is very conveniently located next
to the left pinky finger, so getting out of vim's Insert mode is now a snap.
To address the compulsive :w<CR>
problem, I’ve set up custom bindings in Vim
so that every time I hit <esc>
, (in Insert or Normal mode) the buffer is
automatically saved. The mappings (in my .vimrc file) look like this:
{% highlight vim %} inoremap :w autocmd InsertLeave * nnoremap :w {% endhighlight %}
The second mapping is a bit of a hack, and will only work after you’ve spent
some time in Insert mode. However, using just nnoremap <esc> <esc>:w<CR>
caused weird problems when opening a file for the first time. If anyone has a
more elegant way to handle the Normal mode mapping, I’d love to hear it!
I’ve just started revisiting my dotfiles, cleaning them up, and putting them on GitHub. Thought this trick might come in handy for anyone else who has the same annoyances when getting started with vim.
]]>One of the things I asked myself any time I considered setting up a personal site is “why”? I think I finally have a few answers to that question. First off, working on the web platform for the last 7 years and still not having any kind of personal online space is a bit embarrassing. While most of my posts here will probably be software/technology related, the occasional non-technical article will probably find its way here as well.
A second reason for the site is that I’ve noticed my written communication skills have really deteriorated over time. I haven’t really written anything longer than 4 paragraphs since university, and anytime you abandon a skill for that long, atrophy is inevitable.
Finally, I’m hoping to “reset” the way that I communicate online somewhat. I’ve used Facebook and Twitter for a few years, and I think writing exclusively in media of their ilk dulls your brain a bit. After the shutdown of Google Reader, there has been small renaissance in feed reader software, so it’s good to see that people are still interested in life beyond 140 characters. That’s where I am hoping to spend more of my time online.
So hopefully this has been a reasonable defence of this site’s existence. I’m sort of re-learning how to write, and trying to find a voice, so it will probably be ugly for a while. Anyways, this site’s source and posts are all open source on github so if you see anything wrong, or have any suggestions, let me know. If you are interested in keeping tabs on what I post, an Atom feed is available.
]]>