Shuffle lines in Vim

In a pinch, I needed to randomize the order of a few thousand lines of plain text. In Linux you can just pipe the file through sort, even right inside Vim:

:%!sort -R

But I was stuck on Windows. And I don't know how to randomize a file in native Vim script. But doing it in Ruby is pretty easy, and luckily, Vim has awesome Ruby support. Tne minutes' work and a few peeks at :h ruby and we have a successful, working kludge:

function! ShuffleLines()
ruby << EOF
    buf = VIM::Buffer.current
    firstnum =  VIM::evaluate('a:firstline')
    lastnum = VIM::evaluate('a:lastline')
    lines = []
    firstnum.upto(lastnum) do |lnum|
      lines << buf[lnum]
    end
    lines.shuffle!
    firstnum.upto(lastnum) do |lnum|
      buf[lnum] = lines[lnum-firstnum]
    end
EOF
endfunction

2011-07-07 23:32 - Edited to remove a superfluous line.

2011-07-09 21:33 - Wrong parameter for sort, oops.

July 07, 2011 @ 2:07 PM PDT
Cateogory: Programming
Tags: Vim, Ruby

Keyword Arguments: Ruby, Clojure, Common Lisp

And suddenly I return to blogging, rising from the ashes like some kind of zombie phoenix. Turns out writing a book is a good absorber of time, like some sort of heavy-duty temporal paper towel. Now that I've gotten the terrible similes out of my system, let's talk about keyword arguments, one of my favorite features in any language that supports them.

Ruby, Clojure, and Common Lisp are all languages I enjoy to some degree, and they all have keyword arguments. Let's explore how keyword args differ in those languages.

June 24, 2011 @ 5:22 PM PDT
Cateogory: Programming
Tags: Lisp, Ruby, Clojure

org-mode is awesome

I've seen org-mode for Emacs mentioned very frequently around the interwebs, so it went into my mental queue of topics to learn. It finally bubbled to the top this week, so I took a look.

Organizer? Nah.

As an organizer/calendar, well, I doubt I'll need it. Enforced use of MS Outlook is mandated by work. My Post-it-notes-all-over-my-desk method of organization will also continue to serve me well.

There are some nice agenda-related shortcuts that are probably worth using though, like typing C-c . to enter a datestamp, like <2011-01-20 Thu>. Then you can increment or decrement it one year/month/day at a time via S-up and S-down. I like this.

Plaintext editor? Yes!

As a plaintext outline and table editor... wow. org-mode rocks. Do you know how many hours of my life could have been saved by having a good ASCII table/bullet-list editor? org-mode lines everything up and keeps it all nice and neat for you.

You can also make plaintext check boxes and check/uncheck them. And you can insert hyperlinks and footnotes, and click them to open web pages or jump back and forth between footnote and reference.

There are ways to collapse and expand outlines, search for items and only display those items, and so on. The documentation for org-mode is very clear and took me less than an hour to read through. All-in-all a pleasant experience.

* Agenda
** Things to learn
1. [X] Clojure
2. [X] org-mode (see [fn:diagram1])
3. [ ] Haskell
4. [ ] Japanese
   1. [X] Hiragana
   2. [X] Katakana
   3. [ ] Kanji
5. [ ] The true meaning of friendship

* Footnotes
[fn:diagram1]

| Task                              | Annoyance (1-10) |
|-----------------------------------+------------------|
| Making ASCII tables by hand       |              9.5 |
| Making ASCII bullet lists by hand |              7.2 |
| Using org-mode                    |              0.4 |

It looks nice plastered into my blog, but you don't get a real idea of how many cool things you can do with it until you open it in Emacs and start shuffling items around, bumping them up/down a level in headlines, creating properly-numbered bullet items with one key, and seeing the columns in the table auto-resize as you type.

I also highly recommend putting (setq org-startup-indented t) into .emacs to make everything look pretty on-screen. It still saves as the simple plaintext above, but it looks like this in Emacs:

org-mode

I can definitely see using org-mode for TODO files in some of my projects. (You can mark entries as TODO (just by typing TODO in front), and then toggle between TODO/DONE via C-c C-t.) I can also see using it as a general-purpose note-taker.

org-mode also has a mobile version for iPhone and Android, synced via WebDAV or Dropbox, so you can org-mode on your phone while you're driving to the grocery store1. Again I don't really need this, but there it is.

The joy of plaintext

Plaintext is awesome.

It's the universal file format. It's readable and writeable by scripting langauges, terminals, text editors, IDEs, word processors, web browsers, even lowly humans.

Plaintext's one shortcoming is its lack of structure. It's just a bunch of letters. It doesn't have a color, it doesn't have a style, it doesn't line up into columns without a lot of effort. There's nothing stopping you from opening a parenthesized list and forgetting the closing paren.

Computers don't care about these problems, but humans are bad at producting plaintext by hand, and bad at editing it once it's produced. Our clumsy, stumpy fingers and inconsistent, chaotic brains can't handle the freedom.

Emacs (and Vim) are awesome because they let you do magical things to plaintext. They enforce structure. They provide shortcuts so you can get your plainext right the first time.

[ ] is just two braces and a space, but org-mode lets me hit C-c C-c and turn the space into an X. This may seem banal, hardly worth caring about, but add to this shortcut thousands upon thousands of others. Things like org-mode, or paredit, or all of Vim's built-in magic... it all adds up to something wonderful.

And best of all, you always still have the option of manually keyboarding over and typing that X between the braces yourself. It's still just plaintext underneath. So you end up with the best of both worlds.

  1. I do not recommend using org-mode while driving, for public safety reasons.

January 20, 2011 @ 4:14 PM PST
Cateogory: Programming

2010 in review

Another year down the drain. A good year, in the end.

2010 Geek Achievements

  1. Wrote some code...
    • cow-blog - The engine running this blog.
    • oyako - Clojure ORM library.
    • gaka - CSS compiler for Clojure
  2. Finished a huge project for work, my first AJAX-y web app (in Rails). That was fun, albeit stressful.
  3. Learned a lot of git.
  4. Learned a lot of Clojure.
  5. Learned a lot of Emacs.
  6. Learned a lot of Javascript.
  7. Learned a lot of PostgreSQL. It's good to be free of MySQL.
  8. Switched to ZSH. This was a good switch.
  9. Tried to learn a lot of Japanese, but kind of fizzled out at the end of the year.
  10. Alllllllmost got a Clojure gold badge on Stack Overflow. I'll get it soon though. Not losing any sleep over it either way.
  11. Read a lot of books. The best: probably Feynman's books of anecdotes.
  12. Blogged a bit. Got an article in Hacker Monthly. Was flamed repeatedly. Learned a lot in the process.

2010 Non-Geek Achievements

  1. Immigrated to Canada. A good move, without a doubt.
  2. Lost 25ish lbs. :)
  3. Learned how to cook better.
  4. My most important achievement from 2010 is actually non-geek: I finally obtained a bit of an offline social life. This is not an easy task for one such as myself.
  5. Continued to learn to appreciate good beer. Longwood Dunkelweizen, mmm.

2010 Failures

  1. Did not blog enough.1
  2. Did not write enough code.1
  3. Missed the first Clojure Conj. Maybe next year.
  4. Re-gained 10ish lbs. :( 2

Plans for 2011

  1. Re-lose 25ish pounds. I'd like to reach the weight I had in college.
  2. Finish my rewrite of oyako. I have ambitious plans for it, if I can just find the time.
  3. Finish my rewrite of cow-blog to match oyako.
  4. Keep working on the RPG my wife and I are creating (in Clojure).
  5. Attend the next Clojure Conj, I hope.
  6. Learn more Clojure.
  7. Learn Haskell? Trying and failing to learn Haskell has become somewhat of a tradition, no sense stopping now.
  8. Learn all 2000+ jouyou kanji by the end of the year.
  9. Supar sekrit projekt. But I haven't signed the contract for it yet so I won't talk about it until I do.
  10. Maintain social life at acceptable levels.
  11. Buy a house.

I feel like I have solid plans for completing each of these things. Blogging more often and finishing oyako are high on my list of priorities. I expect 2011 to be my most productive year to date.

  1. See also, non-geek achievement #4, "Obtained social life".

  2. See also non-geek achievement #3, "Learned how to cook better".

January 05, 2011 @ 10:10 AM PST
Cateogory: Rants
Tags: 2010, Clojure

Vim undo tree visualization

I wrote previously about an awsome plugin to give Emacs Vim-style undo trees.

Vim's undo trees are the best thing since sliced bread, but the interface for browsing through the tree is not pleasant. The Emacs undo-tree library has a way to visualize the tree and move through it with your keyboard, which solves this problem.

But now, thanks to Steve Losh, Vim has an undo-tree visualizer too. Delicious. Though it's still beta and promises to eat your babies, it seems to work pretty well. I think the diff view of the changes for the undo is a really good idea.

Thus continues the eternal Vim/Emacs arms race.

Vim undo tree

October 18, 2010 @ 3:21 PM PDT
Cateogory: Programming
Tags: Vim, Emacs, Undo

Productivity Booster

I came up with a great way to increase my productivity recently. You need a locally-running Apache server for this to work most effectively.

First you need to set up a redirect for 404 requests to localhost. On my system I determined that DocumentRoot is /srv/http, so I set this up in /etc/httpd/conf/httpd.conf:

<Directory "/srv/http">
    AllowOverride All
</Directory>

Next I edited /srv/http/.htaccess to redirect 404's to a main index page:

ErrorDocument 404 /index.html

Then I created /srv/http/index.html:

<html>
    <head>
        <title>GET BACK TO WORK, YOU HOBO</title>
        <style type="text/css">
            html {
                background: #f00;
            }
            h1 {
                color: #0f0;
                font-family: sans-serif;
                text-align: center;
                margin-top: 100px;
                font-size: 64pt;
            }
        </style>
    </head>
    <body>
        <h1>GET BACK TO WORK, YOU HOBO</h1>
    </body>
</html>

Almost done; the final step is to edit /etc/hosts:

127.0.0.1 reddit.com www.reddit.com slashdot.org news.ycombinator.com

Now I see this. Image hidden behind a link to spare the eyes of my readers.

If this doesn't work, you could try making the background color flash quickly between red and green, or add a background MIDI and some animated GIFs.

October 08, 2010 @ 3:09 PM PDT
Cateogory: Linux

iPad? More like iAd. Vertisements.

Via Slashdot, it seems soon you may be able to subscribe to newspapers on the iPad in the near future.

Sure. Why pay $10 for a paper copy of something when you can pay the same $10 for a likely-DRM'ed copy that can only be read on a $500 portable computer?

In all honesty though, instant delivery, lack of clutter, "take it anywhere", being able to archive issues indefinitely, text search... those features might be worth the money, if it was a really good newspaper/magazine.

But wait, there's more.

The Cupertino company has agreed to provide an opt-in function for subscribers to allow Apple to share with publishers their information, which includes vital data that news organizations use to attract advertisers, industry sources say.

...

While the leap into the digital tablet market comes with short-term problems for newspapers, the iPad and future tablets will provide a new digital palette for publications to create sophisticated and lucrative ads, said Needham & Co. analyst Charles Wolf.

"I would say it's a risk, but I would argue it's a short-term risk," Wolf said. "If you can put animation and multimedia into ads, that will greatly enhance reader views. I am certain of that."

So as I understand it, first I buy a $500 gadget. Then I pay for a newspaper subscription. Then a bunch of companies want me to give them personal information about myself, so they can share it amongst themselves. And then I have to view ads.

Animated ads.

The only thing better would be if the iPad also woke you up at 4AM and tried to sell you life insurance. Maybe Apple would let me install a free ad-blocker script for my news reader though. It is my hardware, after all... pfffft, yeah, I could't keep going with a straight face.

And thus my desire to get an iPad, kind-of sort-of building over the past couple of months, once again flatlines.

September 16, 2010 @ 6:43 PM PDT
Cateogory: Rants

Git info in your ZSH Prompt

Recently I discovered vcs_info recently. This nicely replaces the horrible hack I was using previously to show current Git status. vcs_info works with VCSes besides Git, and it handles some of the magic and keeps your .zshrc clean, so those are nice benefits.

I used some Unicode to display colored circles. Green if there are staged changes, yellow if there are unstaged changes, and red if there are new untracked-yet-unignored files. Below is a picture.

I like this because I'm constantly forgetting to git add newly-created files. Then I have to add them and amend my commit, and so on. I like a prompt that reminds me that new files showed up that need to be added or ignored.

Code:

autoload -Uz vcs_info

zstyle ':vcs_info:*' stagedstr '%F{28}●'
zstyle ':vcs_info:*' unstagedstr '%F{11}●'
zstyle ':vcs_info:*' check-for-changes true
zstyle ':vcs_info:(sv[nk]|bzr):*' branchformat '%b%F{1}:%F{11}%r'
zstyle ':vcs_info:*' enable git svn
precmd () {
    if [[ -z $(git ls-files --other --exclude-standard 2> /dev/null) ]] {
        zstyle ':vcs_info:*' formats ' [%F{green}%b%c%u%F{blue}]'
    } else {
        zstyle ':vcs_info:*' formats ' [%F{green}%b%c%u%F{red}●%F{blue}]'
    }

    vcs_info
}

setopt prompt_subst
PROMPT='%F{blue}%n@%m %c${vcs_info_msg_0_}%F{blue} %(?/%F{blue}/%F{red})%% %{$reset_color%}'

Picture:

ZSH and Git

Limitations

As you can see in the screenshot, when you have a brand new Git repo (no commits yet), vcs_info fails to show you that there are files staged. It works OK after you have at least one commit though.

vcs_info doesn't (yet?) handle showing untracked files. So I hacked a function to support it.

Finding a good Unicode symbol that displays nicely in monospace font was annoying. If I ever change fonts, I'll likely have to pick a new symbol. It also doesn't display too well in a real tty. Or over SSH when using Putty. So I may have to scrap the stoplights and use plus-signs or something. Sigh.

September 10, 2010 @ 1:31 PM PDT
Cateogory: Linux
Tags: ZSH, Git

Vim :ruby and :rubydo scope

Note to self. In old Vim (tested in 7.2.320), I could do this:

:ruby x='foo'
:rubydo $_=x

Now every line in the file says foo. But in Vim 7.3 I get an error:

NameError: undefined local variable or method `x' for main:Object

The scoping rules for Ruby in Vim must have changed somewhere along the line. I was abusing this feature to do some handy things, so this is sad.

A workaround is to use global variables in Ruby instead. So this still works:

:ruby $x='foo'
:rubydo $_=$x

Phew.

August 31, 2010 @ 10:40 AM PDT
Cateogory: Programming
Tags: Vim, Ruby

Emacs undo trees

I've said it before: undo in Emacs is horrible. On the other hand, undo in Vim is awesome.

But this is true no longer. Now there are undo trees for Emacs! Yes, this news is so important I had to italicize and bold it. It's like Emacs has been punching me in the face for years, and today I got it to stop. I never thought I'd see the day.

And it works great too. You can even view the tree visually and navigate it with the cursor keys, which is a step up on what Vim offers out of the box.

Emacs undo trees

In other news, Vim 7.3 is out and it now has persistent undo across reloads. It's like an arms race, and gleeful hackers reap the benefits.

August 17, 2010 @ 2:06 PM PDT
Cateogory: Programming
Tags: Vim, Emacs, Undo