Pages

Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Wednesday, August 17, 2011

Tab completes my life

Sorry for the somewhat awkward title. I just couldn't resist the geeky pun, and couldn't come up with a better phrase to express it. Hope you got the short message from the title. Also please forgive the awful (or awesome?) prose below. I've always wanted to write a post like this :)

Having been a happy Linux user for the past year-and-a-half, I respect the art of command line-fu. The most useful, yet simple, trick in the bag of the CLI ninja is, of course, the all-powerful Tab key. In one stroke - literally - it can help him type even the longest of commands with minimal key presses. I just love going ..<Tab>..<Tab>..<Tab><Enter> on my terminal, commands flowing at the speed of thought.

Now I'm so used to it, I expect it to be present everywhere - my browser, my text editor, in git commands, in the python interactive interpreter. Basically, I expect my computer to do its job - that is, helping me out while I try to do mine. That does not happen easily, however. So I set out on a quest - to try to have some form of Tab-completion in as many programs as possible. Below, I chronicle my journey, for the benefit of the traveller seeking the same end :-

The Switch from Bash to Zsh:
All Linuxes come with the same default shell: bash. However, there's another shell out there - zsh - which is little known, but extremely powerful. It's the first step from CLI apprentice to CLI productivity master. There are some excellent plugins available for zsh which add tab completion for many commands like git, pip, gem, and kill along with some bonuses. It'll also help you out with many other small things, like ignoring case and correcting spelling mistakes.

If you're thinking to try out zsh, I'd recommend installing Oh My Zsh! first thing after you install zsh itself. It'll make it much easier to set up zsh to your liking, replete with themes, plugins, and aliases. Also, as it turns out, the $RPS1 environment variable, along with the git support in Oh My Zsh!, pretty much renders my alternative (and very useful) bash prompt obsolete.

The Text Editor:
Since I'm a die-hard Emacs user, this section's a bit biased. For Emacs, I use Auto Complete Mode. It's fairly easy to setup, and blazing fast once you get used to it. Note that this is not code completion, it's simple, cross-buffer word completion, so it'll suggest words based on what's in the rest of the buffer, or in other open buffers. I find this better than code completion for the simple reason that code completion would require me to install separate plugins for each language I use, while on the other hand, word completion is universally effective, if not as accurate. Heck, it even works in comments. Combine that with YASnippet, and you'll find yourself with one finger on the Tab key nearly perpetually, and code flowing from your fingers.

Oh, and let's not forget ido-mode. It's the coolest, dead-simplest Emacs plugin ever.

For Vim users who feel left out, a quick Google search yields this.

The Interactive Interpreters (Python and Ruby):
I hated it when I fired up python the first time and it didn't offer Tab-completion. I later understood that since whitespace is significant in Python, completion is not enabled by default in the interpreter (or the Python REPL, in purist-speak). I figured spaces could be used for indentation just as easily as tabs, so I enabled completion using this .pythonrc. It's not like I miss tabs for indentation now.

Coming to irb (the Ruby interpreter), you can have Tab-completion and syntax highlighting in it using the wirble gem and a .irbrc. Pretty straight forward, supremely effective, no down-sides.

The Browser:
Not much to say here. Probably the only thing you can Tab-complete in a browser is URLs, which the latest versions of Firefox and Chrome already do, anyway (it's not true, CLI-style tab-completion; just passable). If you want word completion too and you're on a recent version of Firefox, use this addon. Or, if you're using an older Firefox version, you could try this one.


Here ended my quest. Let your chronicles and criticisms be outlined in the comments below.

Sunday, July 3, 2011

Beautiful code == poetry

This post is long and a little on the non-technical side, but I think the implications are very relevant to the readers. You might be somewhat pissed that I'm not talking about how sweet jQuery is, but here goes.

How many of us programmers just drool over clean, self-documenting code? I do. I literally strive to have my code look like elegant poetry, so much so that I spend a good portion of my time refactoring. Some might call that over-the-top. I call it an eye for detail. I believe code is like literature; you have to write it in a way so that others (and more importantly a future you) can immediately understand what you mean without getting bogged down with pathetic, obscure syntax or poor style. After all, code is not meant to be "write-once". Moreover, a few years down the line, you want to be able to look back on your code and say, "Whoa. I used to write amazing code even back then".

I try to take extreme care about naming my functions in just the right way. So whenever I read it later on, I know exactly what it does. I won't say I'm very good at it, but I believe I'm getting better.

The language syntax is crucial to how readable the code is. That is one thing Ruby does well. Let's see a contrived example:

a = [1, 2, 3] + [4, 5, 6] - [5]   # = [1, 2, 3, 4, 6]
b = "blah"
return true if a.include? 4 and not b.empty?

Another thing Ruby is good at: Domain Specific Languages (DSLs). They're an attempt to make non-geeks write code to get stuff done easily. As an example, consider this: rocket scientists are good at space-talk, but bad at writing code. What if we could create a program which exposes an API that looks like rocket science? It doesn't get any cooler. The scientist doesn't need to know Ruby, only the API. He can think in terms of space shuttles and takeoff times and things like that. For example, a rocket science DSL in Ruby might allow a rocket scientist to write stuff like:

shuttle.fill_tank 50   # tank up 50 liters
shuttle.launch_after 3 if shuttle.prepared? # 3... 2... 1... go!

You might say, "Wait a sec. Isn't that your regular object-oriented code?". Yes, but normally we create that for ourselves. A DSL's API is meant to be used by the users to write code.

A related example comes to mind. The other day my friend and I were working on a DSL for access control in a web application, which controls what user gets to access what part of the application. The most important thing in a DSL, as you might've noticed, is the API. Everything else is secondary. We needed to name a function which would take a condition, and a result to be returned if the condition was met. We thought up names like make_rule, but we weren't satisfied. After some brainstorming, we came up with an API like this one:

given :condition => user.admin?, :return => true

I feel the function name given is the most important thing in this API. It conveys the purpose unambiguously and reads like natural English. Any other name would've made it confusing or misleading. And remember again, some John Doe titled "Maintainer" at a company is going to be using this API directly, without being good at Ruby, that's why the nomenclature is so very important.

If you're more of a JavaScript guy, you should check out CoffeeScript. It's "a little language that compiles into JavaScript", with and Ruby and Python-inspired syntax. Imagine being able to write stuff like the following and have it run as JavaScript:

volume = 10 if band isnt SpinalTap
letTheWildRumpusBegin() unless answer is no

I've presented my (rather long) case. Let the comments fly.

UPDATE: We're finally done with the access control DSL, and the API now looks like this:

given :condition => { :controller.is => :admin, :action.not.in => [:create, :show] },
      :return => true

isn't that beautiful? :)

----
If you like this article, consider following me and Rajat on Twitter.