Vim: Find lines longer than current line

Vim isn't just for editing source code. It's also a pretty good data editor.

Sometimes I'm editing dirty fixed-width data files, and some lines are incorrectly a bit too long because one or two fields overflowed. It's easy to search for lines that are too long, once you know how long lines should be. Say your lines should be 1000 characters; search like this:

/^.\{1001}

Now all the longer lines are highlighted (assuming :set hls).

That's tedious to type though. Put your cursor on a non-overflowing line and call this function, and Vim will find all the lines that are too long, and move you to the first one:

function! FindLongerLines()
    let @/ = '^.\{' . col('$') . '}'
    silent! norm n$
endfunction

That mess about manually setting @/ is because of this somewhat unfortunate fact (from :help :function):

        The last used search pattern and the redo command "."
        will not be changed by the function.  This also
        implies that the effect of |:nohlsearch| is undone
        when the function returns.

That is, using something like norm / inside functions doesn't affect the last-remembered search once the function returns, but that's exactly what we want to happen.

June 21, 2012 @ 3:29 AM PDT
Cateogory: Programming
Tags: Vim

Happy Day Against DRM

Books are 50% off at O'Reilly today, using code DRMFREE. (This includes my book, Clojure Programming, by the way...) I'm a bit late with this, given the offer expires in 9 hours, but there's still time.

Whether you want to buy books today or not, it's worth pointing out that today is International Day Against DRM!

Day Against DRM

May 04, 2012 @ 6:23 AM PDT
Cateogory: Rants

cursorcolumn / cursorline slowdown

The cursorcol and cursorline options in Vim are great. Enabling them, and setting up your syntax highlighting correctly, will highlight the line and column that contains the cursor, drawing a sort of "crosshairs", to let you find the cursor easily.

This is especially useful when editing non-sourcecode files, like giant fixed-with data files. Or when you need to keep switching your attention back and forth from Vim to something else; the visual cue to draw your eyes back to the cursor can be useful to prevent a mental page fault.

Cursor crosshairs

Great. However, the help info for cursorcolumn says this, in part:

    Highlight the screen column of the cursor with CursorColumn
    |hl-CursorColumn|.  Useful to align text.  Will make screen redrawing
    slower.

"Will make screen redrawing slower" is an understatement, unfortunately. Over the past who-knows-how-long, I've noticed Vim slowing to a crawl when editing certain files, mostly big Ruby files. Moving the cursor around or scrolling the window became pretty painful. I could never quite figure out why, but today I got sick of it, and eventually found an old message on the Vim mailing list explaining the problem.

Apparently when you have cursorcolumn or cursorline enabled, the whole screen is redrawn every time you move the cursor. That explains a lot. When I disabled these options, editing complex Ruby files once again achieved notepad.exe-level speed.

I guess there's this:

function! CursorPing()
    set cursorline cursorcolumn
    redraw
    sleep 50m
    set nocursorline nocursorcolumn
endfunction

nmap <C-Space> :call CursorPing()<CR>

This will flash the cursor crosshairs for 50 milliseconds when I hit CTRL+Space in normal mode. Better than nothing.

April 30, 2012 @ 8:48 AM PDT
Cateogory: Programming
Tags: Vim

Split page vertically in CSS (minus pixels)

I was designing an online database application recently. The layout I wanted was, I thought, fairly simple:

  • N pixel header at the top
  • The rest of the page split vertically into two panes
  • Each pane should scroll independently

Super easy to do in CSS, right? Of course not! You can't do this:

#header {  height: 50px; }

#panels {  height: 100% - 50px; }

#top, #bottom { overflow: auto; }

This is because (of course) you can't do simple arithmetic in CSS.

I can't think of a reason why it's not supported. My browser knows the height of the window at any given point in time. The browser can surely subtract two numbers. If someone knows of a solid reason why we can't do this in CSS, please clue me in.

I can think of many reasons why I would want to do it though. The above use case is just one of them.

I really dislike resorting to this (which does work, as seen here):

#header {  height: 50px; }

#panels {
    position: absolute;
    top: 50px;
    left: 0px;
    right: 0px;
    bottom: 0px;
}

#top, #bottom { overflow: auto; }

Whenever I start using absolute positioning, I know something went off the rails somewhere.

The worst part isn't that CSS doesn't support this, it's that even if CSS did suddenly support it, I couldn't use it until sometime in 2023 when all the major browsers implemented it and everyone using the old browsers switched or died of old age.

April 23, 2012 @ 2:43 PM PDT
Cateogory: Programming

I don't have cancer

2011 was an interesting year. A year of firsts!

  • I worked on my first book, Clojure Programming (soon to be released, in fine bookstores near you).
  • I bought my first house.
  • The first of my maternal grandparents died.

Hmm, kind of took a turn for the worst there. Then, one fine sunny day in 2011, sitting at my favorite pub, enjoying my favorite beer, I started coughing up blood. Another first!

April 04, 2012 @ 7:29 AM PDT
Cateogory: Rants
Tags: Rant

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 @ 7:07 AM PDT
Cateogory: Programming
Tags: Ruby, Vim

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 @ 10:22 AM 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 @ 8:14 AM 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 @ 2: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 @ 8:21 AM PDT
Cateogory: Programming
Tags: Emacs, Vim, Undo