Ubuntu 13.04 Microphone Issues for Lenovo

Posted in Uncategorized on May 24th, 2013 by Yubin – 5 Comments

The Microphone is Not Working!

After recently formatting my Linux partition and reinstalling Ubuntu, I ran into a host of problems that I vaguely remembered solving the last time I did this. In order to prevent history from repeating itself (once more), I decided to document one of the most crucial issues that I encountered: the microphone not working. As a person working from home, I’m often participating in conference calls on my laptop which requires microphone input! Sadly, this morning, when I tried to join a reading group discussion, I found that my newly formatted laptop lacked microphone capabilites. I ended up having to resort to my phone (the primitive horrors!). I spent a good hour fumbling around trying to remember what I did the last time I had this issue, and without further ado, I present my solution!


Step 1. Start gstreamer-properties in a terminal and select ALSA as the default input plugin.
Step 2. Start alsamixer in a terminal, hit F5 to show all devices
Step 3. Use the left and right arrow keys to move to various devices and for all input related devices, use the Q key to increase the volume for the left channel and the C key to turn down the right channel to 0. (If your device says MM, then it is muted! Use M to unmute the device.) Alternatively, you can use E and Z to use the right channel volume instead. All that matters is that one channel is at a reasonable volume and the other channel is at 0.

The reason why this works is that microphones are monochannel, and the default settings for the ALSA has two channels for microphone devices, which means that the sounds cancels itself out. By decreasing one side of the channel to zero, you prevent this cancellation and get a working microphone!

Short post, but hopefully this is useful for somebody else in the future as well.

Tmux Copy Buffer and X Clipboard Integration over SSH

Posted in likes, tech on October 10th, 2012 by Yubin – 1 Comment

Recently, I parted ways with screen and started using tmux as my primary terminal multiplexer. Although I know some staunch screen loyalists, in my opinion, tmux is screen’s sexier cousin. It’s prettier, more modern, and highly scriptable. (Also, it doesn’t do that lame thing that screen does where if you open up a program like vim and exit it, the program’s dead husk hovers above your new blinking $ like some vengeful ghost.) Best yet, the man page for tmux is extremely readable and configuration file syntax is actually sane. Combined with the extremely helpful community of people on the mailing lists, I’m glad to say I am now more proficient with tmux in a week than I ever was with screen.

One of the features that I used the most from my previous configuration in screen was the ability to copy the screen buffer into the X clipboard for a hands-free work flow when I need to paste to a spreadsheet etc. As a highly-trained engineer, I figured out how to duplicate this behaviour by consulting Google:

# place into .tmux.conf
# copy tmux's selection buffer into the primary X selection with PREFIX+CTRL+Y
bind-key c-y run "tmux show-buffer | xsel -i"
# copy primary X selection into tmux's selection buffer with PREFIX+CTRL+P
bind-key c-p run "xsel -o | tmux load-buffer -"
# Note: xsel is a handy little program for scripting the X selections; 
# people who like to use xclip instead can just replace xsel with xclip.

The Tmux Re-attach Problem

The above snippet worked wonderfully… that is, until I logged out of the SSH session to the remote cluster I was connected to from work and re-logged into it from my home machine and attached back to my tmux session. To cut a long story (of pitiful thrashing about) short, I discovered this was due to a stale $DISPLAY variable value.

When you SSH into a machine using -X (or -Y for trusted forwarding), the $DISPLAY variable in your shell is set, so that X knows where to connect and send the UI. Let’s say you logged into your machine and checked your shell for the $DISPLAY.

$ echo $DISPLAY

Now, when you start (or attach to) a tmux session, any new shell panes or windows created during this SSH session will take this $DISPLAY variable value.

$ tmux # start a new tmux session
within tmux session$ echo $DISPLAY

However, old windows and panes in an existing tmux session will have an old $DISPLAY copied from whatever SSH session you created them in.

$ tmux a # attach to existing tmux session
within tmux session$ echo $DISPLAY
localhost:15.0 # Wrong!

The Solution that You Think Should Fix It

Of course, we can fix the stale value by issuing the following command (you need to do this for each shell pane/window):

within tmux session$ export DISPLAY=localhost:10.0 # or the correct DISPLAY value
within tmux session$ tmux show-buffer | xsel -i # works on commandline!

However, if you try your CTRL+C binding, you’ll find that it still does not work. This is because the background shell in tmux will have a stale value for $DISPLAY, same as old windows and panes! Since the background shell is the environment that all your key binding commands run in, your binding won’t work until the $DISPLAY variable value is fixed in the background shell.

The Actual Solution

Alright, I’ll stop teasing you. Here’s the shell script that will fix the stale variable in all of your tmux sessions.

#! /bin/sh
# Yubin totally wrote this one herself
# Run this script outside of tmux!
for name in `tmux ls -F '#{session_name}'`; do
  tmux setenv -g -t $name DISPLAY $DISPLAY #set display for all sessions

This little script will correct the background shell’s $DISPLAY variable value for all tmux sessions found on the host. Stick this in the .bashrc of your remote host, and then you’ll never have to worry about stale background shell display variables again. :)

P.S. I want to note quickly here that stale $DISPLAY variables cause problems for vim as well. You might find that if you try to open vim from a stale shell window in tmux (or screen), it’ll hang for a very long time. This is because vim is trying to connect to a non-existent X server. The “Solution that You Think Should Fix It” actually is the real solution for this particular issue. Just export the correct $DISPLAY value and try opening vim again. It should work like a charm.

Recipe for Korean BBQ Meat Dipping Sauce

Posted in cooking, likes on May 11th, 2012 by Yubin – 18 Comments

Everybody loves Korean BBQ. If you don’t know what that is, I suggest you find a friend to immediately to rectify the situation—it’s fresh meat grilled table-side and traditionally eaten in a lettuce wrap with delicious sauces. What’s not to love?

In a departure from the usual technical blogging topics, I decided to share my secret Korean BBQ sauce recipes passed down to me from my mother through the generations (not really, I trial’d-and-error’d most of them). When I do Korean BBQ at home, I will serve all three sauces. The directions for all three recipes is “put integredients in a bowl; mix well.”

Chili Paste Sauce

This one is completely legit. My mom taught me how to make this and I’ve received countless compliments on it. It’s absolutely wonderful with meats of all kinds and a key component of the lettuce wrap. Onion is the secret ingredient; do not leave it out!

1 Tbsp Pepper paste
1 Tbsp Soy bean paste
1 Tsp Sesame oil
1/2 Tsp Minced garlic
1 Tsp Fresh onion juice (grated or blended)

Dipping Sauce

This recipe was painstakingly developed through many trial-and-error sessions and heavy in-depth research on Naver.com. It’s very light, and I prefer to make a rather large batch and drop my just-off-the-grill-still-sizzling meat into a pool of this to cool it down.  Also, the onion slivers will soak up the flavour of the sauce after a while and become an excellent addition to the lettuce wrap. I like this with chadol (paper-thin beef brisket) or pork belly.

1 Tbsp Soy sauce
3 Tbsp Water
1 Tbsp White cooking wine
1/2 Tbsp Vinegar
1 Tsp Sugar
1/2 Tsp Mustard powder
1/2 Tbsp Slivers of onion

Sesame Oil Sauce

Not my favourite, but my fiancé loves it. Better for beef than pork belly in my opinion, as pork belly has plenty of oil on its own.

2 Tbsp Sesame oil
1/2 Tsp Salt
Dash of finely ground black pepper

CppUnit Assertion Traits with Strings

Posted in indifferent, tech on March 7th, 2012 by Yubin – 3 Comments

When I posted an entry in my blog today, I came across this draft of a blog entry that was created in July 28th, 2009. I honestly have no idea why I didn’t post it or what prompted the post in the first place. Also, I’m fairly certain that the code snippet below was something I found while Googling and unfortunately don’t know the author. In any case, here is the resurrected post.

I recently discovered assertion traits while writing some unit tests in C++. If you ever wanted to use the CPP_ASSERTION macros with char* (c strings), the following code bit may come in handy:

namespace CppUnit {
 struct assertion_traits<char*>   // specialization for the std::string type
   static bool equal( char* const& x, char* const& y )
     if (!x || !y) {
       return !x && !y;
     return strcmp(x, y) == 0;
   static std::string toString( char* const& x )
     if (!x) return "\"\"";
     // adds quote around the string to see whitespace
     std::string text = '"' + string(x) + '"';
     OStringStream ost;
     ost << text;
     return ost.str();

Graduate students, Git was made for you!

Posted in likes, tech on March 6th, 2012 by Yubin – 4 Comments

This past Friday, I was feeling particularly unproductive, so I decided to take the day off and learn something new because I am secretly terrified of technologically falling behind while sequestered in academia. So, I decided to take this new-fangled Git thing for a spin. It is possibly—

The. Best. Thing. Ever.

Now, I’ve heard many of my friends wax eloquent about Git (it does SVN better than SVN, branching and merging is amazing etc. etc.), but none of it had really swayed me in the past. Hopefully, the chronicle of my love story will reach people in situations similar to myself and lead them to discover the sheer joy that is Git.

The Story

Ever since I started as a graduate student in CMU, I had a problem. My research group has a powerful remote cluster, which is where I do my primary development. And as my fellow graduate students will know, “development” in academia mostly consists of hacking together a series of scripts the night before the weekly meeting with your advisor. Oftentimes, you have no idea if the script you are writing right now would ever be used again. When this is combined with the fact that the user directories in the cluster are backed up nightly, it becomes a very strong deterrent against setting up an initial SVN repository to version control your code. (At most I’ll only lose a day’s worth of work, right??)

Afterwards, even when you realize that your script is something you will be improving and using frequently, the overhead for setting up a SVN repo is discouraging. You would have to move your script folder to a temporary name, create a new repo, check out the repo, move your scripts to the new directory, add the files, and then check it in. (Oh well, everything’s backed up nightly, it’ll be okay, probably maybe.)

So long story short, I have scripts that are several hundred lines long all over my directory in the research cluster, many of which are critical, none of which are version controlled. Basically, I spent the past 6 months trying really hard to ignore that panicky little voice in the back of my head that’s been whispering, “ohgodohgod I hope I never need an older version of this file ohgodohgod.

In comes Git riding—no, flying in on a pegasus-unicorn-fire-breathing-dragon-gryphon wearing, I don’t know, whatever awesome version control systems wear.

“Fear not!” It says. “All you need to do is—”

git init && git add . && git commit

“What?” I say, dazzled. “That’s it? Now everything in my directory is version controlled? Oh Git, you are so handsome and amazing—”


Anyway, yes. That’s it. Now everything in your directory is version controlled.

Furthermore, Git solves another one of my problems very neatly; occasionally, the research cluster suffers from latency issues and vim responds unbearably slow. Up until now, I just grit my teeth and bore it, but now I can easily just git pull the directory down to my local machine and continue my work happily. The only tricky part here is that the repository I pulled from has a working files in it, a so-called “non-bare” repository. Therefore, after I’m done my changes, instead of pushing directly to master, I push to a branch instead and merge the changes afterwards. So, to recap, this is what my workflow under high-latency looks like:

remote$ git commit -a
local$ git clone username@remote:/path/to/git/dir
<hackity hack hack>
local$ git commit -a
local$ git push origin master:local-master
remote$ git merge local-master

Easy peasy. Fellow grad students, use Git and revel in its glory.

Liberate your Kindle eBooks. Remove DRM!

Posted in books, dislikes on June 6th, 2011 by Yubin – 1 Comment

I finally caved and bought a Kindle.

I’ve been thinking about it for years but I held back because it was a pricy gadget (at the time) and I was concerned about eBook DRM. However, a few months ago I had a lengthy travel to the States and I decided, ‘to hell with it,’ and bought a Kindle to accompany me on my plane flight. Now that I have been using for a few months, I can safely assert that it is one of the best purchases I’ve made in terms of ease and frequency of use. (I’ll spare you of any further I <3 Kindle gushing.)

However, recently I remembered why I hesitated to buy the Kindle in the first place: DRM. I was talking to a friend of mine who is interning at Kobo and their new touch edition Kobo came up in conversation. My thought process at that point went something like this:

The wave of blind rage actually made me conversationally unresponsive for a moment. When I got back home, I immediately set out to rectify this horrendous injustice. Turns out, it is actually so easy for you to remove DRM. This is how.

Free your eBooks from oppression, a 10 min guide

  1. Download the latest DRM tools package and unpack it
  2. Download, install, and run calibre
  3. Install the DRM tools plugin:
    1. Preferences -> Plugins (under the Advanced section)
    2. “Add a new plugin”
    3. Navigate to where you unpacked the plugins and select a .zip file to add
    4. Repeat above for all five .zip archives
  4. Configure the plugins:
    1. Click on “K4PC, K4MAC, Kindle Mobi and Topz DeDRM” plugin and click “Customize”
    2. Add your Kindle serial number in the field. This can be found in the Settings page on your Kindle, accessible by the Menu button from the home screen. The serial number is case sensitive.
  5. Connect your Kindle via USB
  6. Given a minute, calibre will detect your Kindle and will appear in the top menu bar as “Device”. Click “Device”
  7. Select all books you wish to liberate, right click and either “Add books to library” or “Save to disk”

The steps for other DRM schemes such as the Barnes & Noble and Adobe are similar and can be found at the Stream Recorder forums.

Commentary on DRM

Now that you have read the useful part about this post, here is some ranting about DRM; feel free to skip past to the end.

I don’t understand why people think that eBook DRM is a good idea. I don’t claim any knowledge of how authors feel about this whole debacle, but I do know how I feel about it as a consumer.

It blows. Hard.

Amazon and Barnes & Noble would tie me exclusively to their devices and software with no recourse if their DRM format becomes obsolete. Also, what if my Kindle failed and I had to go back to reading on my Nintendo DS, the only portable electronic device I own? In fact, I know exactly what I would do, because I have been doing it for years; I would pirate my books.

I just want publishers to know that they have been losing my business for years because of DRM. I would have gladly shelled out some bucks if the books I wanted were available in a free format which I could use to convert to plain text files. (Or even better, offered in plain text in addition to ePubs and PDFs!) I love supporting the authors who wrote my books and the publishers who made it possible for me to find them. I want publishers to know that they would have lost my business again if circumventing DRM didn’t turn out to be so easy.

I want them to know that they should just get rid of the damn thing.

Implementing an Algorithm for Generating Power Sets

Posted in likes, tech on August 24th, 2010 by Yubin – 4 Comments

I have recently started learning Haskell, after years of telling myself that I should pick up a functional language. I decided to embark on this journey with Real World Haskell, an O’Reilly book that is freely available online in an extremely convenient HTML format. The book has numerous exercises, and as I was working through them, I marvelled at the ease of list manipulation in Haskell. For example, one of the earlier exercises in the book was implementing the Graham Scan algorithm for computing convex hulls. This took me 26 lines including comments and blank lines—and this was before I knew about map or folds.

The sheer conciseness of Haskell for list manipulation tasks made me want to revisit a problem I encountered on my last work term: generating power sets. To explain briefly, the power set of a set is the set of all its possible subsets; for example, the power set of \(\{1, 2, 3\}\) is \(\{\{\}, \{1\}, \{2\}, \{3\}, \{1, 2\}, \{1, 3\}, \{2, 3\}, \{1, 2, 3\}\}\).

The algorithm I used was based the recursive algorithm given in the Wikipedia page for power set, which I will explain here for those of you who are lazy. This recursive definition of the power set says that the power set of an empty set \(S = \{\}\) is \(PS(S) = \{ \{\} \}\), a set containing an empty set. For a non-empty set \(S\), take one element, say \(x\), out of the set, and find \(PS(S – x)\). Then, for each set in \(PS(S – x)\), add \(x\) to the set, and denote this new set of sets as \(A\). Then, \(PS(S) = \{ PS(S – x) \cup A \}\).

My Java implementation of generating power sets was an iterative version of the above algorithm, and looked like this:

import java.util.*;
import java.util.*;
class Powerset {
  public static <T> List<List<T>> powerset(Collection<T> list) {
    List<List<T>> ps = new ArrayList<List<T>>();
    ps.add(new ArrayList<T>());   // start with the empty set
    // for every item in the original list
    for (T item : list) {
      List<List<T>> newPs = new ArrayList<List<T>>();
      for (List<T> subset : ps) {
        // copy all of the current powerset's subsets
        // plus the subsets appended with the current item
        List<T> newSubset = new ArrayList<T>(subset);
      // powerset is now powerset of list.subList(0, list.indexOf(item)+1)
      ps = newPs;
    return ps;

And now, for my Haskell implementation:

ps = foldr (\xss x -> xss ++ map (x:) xss) [[]]

For those of you who are unfamiliar with Haskell syntax, I make use of map, a lambda function (indicated by the backslash), and fold, also known as reduce or inject. Finally, to save some extra characters, I also make use of Haskell’s automatic currying. Now, if I scrunch in the unnecessary whitespace and use single letter variables, it is 31 characters.

ps=foldr(\x y->y++map(x:)y)[[]]

Hurrah for Haskell!

P. S. Upon finding out that Ruby also has fold (called inject), I also implemented power set in Ruby, which is also fairly short with some whitespace scrunching:

def ps(xs)

A Small Appreciation of Wikipedia

Posted in likes on March 17th, 2010 by Yubin – 1 Comment

…and all of you who contribute to its content

I’ve always appreciated Wikipedia.org; it’s a part of my daily life, and I use it for both work and entertainment. (Wiki-chaining, anyone?) However, recently, I had the opportunity the appreciate Wikipedia in a new way: a direct contribution to new, original knowledge. Let me back up a bit to tell you more.

I have had the great opportunity to intern in a research position at a start-up this term. Naturally, I read quite a few research papers as part of my work; because I work in a semantic web technology start-up, many of the papers I read are related to information retrieval and text classification. As I was reading, I noted that one of the foremost resources that researchers used was WordNet, a lexical database created at Princeton. This did not come as a surprise—WordNet is this amazing high-quality research tool prepared by people with fancy PhDs.

What did surprise me, however, was how often the same researchers used Wikipedia in the same project—and not just for a source of text data. Wikipedia is often used for things like query expansion and discovering concept hierarchies. Wikipedia, this project that was created by millions of ordinary people with no expert quality control, was being used as much as WordNet! In fact, a quick preliminary search on “Wikipedia” and “WordNet” in the ACM Digital Library yields 3242 results for Wikipedia and 2889 results for WordNet.

So I thank you, Wikipedia, and I thank you, contributor, for creating this incredible repository of information that not only disseminates existing knowledge, but helps create new knowledge as well.

On Half-Finished Blog Posts

Posted in dislikes on March 16th, 2010 by Yubin – 3 Comments


Visitors to my blog probably have noted that it has not been updated in nearly a year. This is not because I could not find topics to write about. On the contrary, I currently have no less than four half-finished posts and another topic idea or two floating around in my head. The question you would naturally ask at this point is, “Yubin, why the heck do you have so many unfinished blog posts?” And that, my dear reader, is what this entry endeavours to explain.

A rambling exposition about my personality

Here, I will pause for a quick warning: in order to fully answer the question posed in the introduction, I will be delving into a (likely boring) exploration of several facets of my personality. (Skip to the TLDR; section if you get annoyed.)

First, my hobbies and interests come and go in fiery, but short-lived bursts of passion. Apart from a select few subjects of interest, I often pick up strange hobbies and abandon them in a blink of an eye. For example, a few years back I decided, out of the blue, to learn heraldry. Yes, that’s right; I wanted to learn how to blazon a coat of arms. It was a phase that lasted for a month or so, in which I learned to read simple shields, and in particular, learned the blazon of the University of Waterloo’s coat of arms:

Or, on a chevron Sable between three lions rampant Gules a chevronel Argent.

Nifty, huh?

I went through similar phases with learning the International Phonetic Alphabet and trying my hands at American Sign Language (har har) to name two others. In any case, you get the point. I become bored easily. And when it comes to blogging, this does not play with a second facet of my personality: perfectionism.

When I wrote my first post, things were pretty easy; it was a technical topic without the need for a lot of prose, so I did not feel the need to revisit my sentences and edit for flow and grammar. However, my subsequent topics were quite the opposite. I found myself revising over and over again after barely typing a paragraph.

I should probably mention here that I dislike poorly written blog posts. If you’re passionate enough about a topic to write a fairly long article about it, I believe you should try your best to do it justice. Naturally, I apply this rule to myself, hence the endless revisions. And thus, the recipe for a slew of half-finished posts is complete.

Because I read my own ideas and my own words again and again as I revise to perfect my post, voila–I get bored of them before I even finish a first draft.  And what’s this? Am I getting bored with this post like all the others? I think I am. Well, there you have it.


I kept revising my blog posts while writing, leading me to become bored of the topic before I finished the post. I’ll try to do better.


The only reason why this post isn’t in the “half-finished blog posts” pile with the rest of them is because I decided to end the post when I got bored. So really, I guess in a sense it is half-finished. How appropriate. I also apologize for the poor flow and rambling quality of the post. As I’ve said, I’ll try to do better.

Vim tips: stuff I wish I knew when I first started

Posted in likes, tech, vim on July 15th, 2009 by Yubin – 26 Comments


I tried very hard to make the title short. Obviously, I didn’t quite make it.

The Stuff

Before Vim, there was darkness. Well, actually, there was a whole hodgepodge of text editors I used for programming. This includes Netbeans (for Java), a brief affair with UltraEdit, and on one regrettable night, Notepad. I discovered Vim in my second year at the University of Waterloo at the insistence of a friend and a computer science professor. I sharply recall muddling my way through vimtutor, struggling to remember the strange new keystrokes that seemed unintuitive at the time. (Why y for yank instead of c for copy?) However, after a few weeks and some regular expressions later, I confessed true love and haven’t looked back since.

Now, although vimtutor is a real handy introduction, I have since found out that Vim is so, so very much more. Here is a list of some neat Vim features that (probably) aren’t in vimtutor that I wish I knew about back when I first started using vim.

Increment and Decrement Numbers

Used in normal mode, CTRL-A increments and CTRL-X decrements the first numerical value on the line. Consider the following file:
This is file #7!
Open the file and type CTRL-A. You’ll see that #7 turned into #8. But, try the same in this file:
This is file #07!
#07 turns into #010 instead. This is because Vim considers any number preceded by 0 to be octal (unless it contains an 8 or 9). Similarly, any number prefixed by 0x is considered hexadecimal. If you wish to change this behaviour and increment 07 to 08, you need to change the nrformats setting, which specifies what Vim considers a numerical value. Type the following to see your nrformats setting:
:set nrformats
By default, nrformats should be set to octal,hex. To avoid 07 being understood as an octal number:
:set nrformats=hex
Now, 07 should be incremented to 08. It may intrigue you to know that another possible value for nrformats is alpha. If included, Vim will increment or decrement single alphabetic characters–quite handy when creating lists with alphabetical indices such as a), b), etc.

Record and Reuse Complex Actions

Typed in normal mode, q allows you to record complex actions and save them in a register for later use. It’s very useful in situations where regular expressions cannot handle the job, or where it could, but would be too complicated. This is easier to explain with an example, so let us consider the following situation.

You have an XML parsing application that parses XML files in the form of:
  <document docid="00001" \>
  <document docid="00002" \>

You would like to test your application with a large input file that has a thousand documents. You could write a quick script to generate this file; however, there is no need. Vim can do this for you! First, :set nrformats=hex. Then, starting with the above file, type the following sequence of keystrokes in normal mode:

Wow, what just happened? It’s like magic, right? This is what you did.

  • gg – Go to top of file
  • jj – Go two lines down
  • qr – Begin recording actions, storing them in the r register
  • yyp<CTRL-A> – Copy the current line and paste it, then increment the number in the new line. (This is the action you are recording!)
  • q – Stop recording
  • 998@r - Replay the actions at register r, 998 times

Basically, by typing qr in normal mode, you begin to record every keystroke you make into register r until you type q in normal mode again. Typing @r will play the recorded keystrokes. There are, of course, many other registers than r. You can replace r with any number between 0-9, any upper or lowercase alphabet, or " (that is, [0-9a-zA-Z"] in regex). I personally like to use the q register, so I type qq to start recording and @q to use the action.

Split Windows

Nowadays, most people have nice, large monitors that can support much more than the 80 character columns of the screens of old. To take full advantage of this wonderful hardware, split your Vim windows! Try this:

Vim should have opened a new file buffer by splitting the screen in half. Neat, right? You can also split screen horizontally with :new. If you want edit the same buffer in the new window, you can do this with :vsplit and :split. (This is often handy when you have a large file and you want to look at two different places at once.)

You will notice that when Vim splits a window vertically, it opens the new window to the left of the old one. Personally, this behaviour bothered me. If you think likewise, you can add the following to your .vimrc:
set splitright

Similarly, horizontal windows appear above the old window, and this can be changed by :set splitbelow.

In order to navigate between the windows, try the following commands:

  • CTRL-W CTRL-W - Go to the next window; if you do this repeatedly, it will cycle through all the windows on the screen
  • CTRL-W h - Go to the window left of the current one
  • CTRL-W l - Go to the window right of the current one
  • CTRL-W k - Go to the window above the current one
  • CTRL-W j - Go to the window below the current one

When windows first open, Vim will distribute the screen real estate evenly between the old and new. However, you may want to change this around afterwards. Here are some useful commands:

  • CTRL-W _ - Give all vertical space to the current window; e.g. vertical expansion
  • CTRL-W | - Give all horizontal space to current window; e.g. horizontal expansion
  • CTRL-W = - Evenly distribute space for all windows
  • CTRL-W + - Increase current window height
  • CTRL-W - - Decrease current window height
  • CTRL-W > - Increase current window width
  • CTRL-W < - Decrease current window width

I use the first three commands in this list frequently still, but there are better ways to fiddle with the window height and width--I'll talk about this in section Using the Mouse. For more on windows, try :help windows.

Tabbed Windows

Although Vim has buffers for editing multiple files, I prefer a more visual way of interacting with my opened files. Thus, I use tabbed windows, a feature supported by Vim since version 7. Here is a quick cheat sheet of commonly used commands:

  • :tabnew - Open a new tab window
  • :tabe - Used like :e, but opens in a new tab
  • CTRL-<PgUp> - Go to the next tab on the right
  • CTRL-<PgDn> - Go to the next tab on the left
  • :tabdo command - Applies command to all opened tabs. (e.g. :tabe %s/old/new/g)

For more on tabs, type :help tab-page.

Using the Mouse

Shortly after learning about tabs and split windows, I found that I started spawning multiple tabs, each with multiple split windows in any given Vim session. I thought to myself, hey, wouldn't it be great if I can use my mouse cursor to resize the window partitions and click on tabs? Also, I secretly missed the option of using the scroll wheel and mouse clicks to browse code. It turns out, Vim lets you do all these things. Simply add the following to your .vimrc.
set mouse=a


Paste Mode

If you have ever spent long minutes fixing indentation issues that occurred when you copied code like this:
void nestedMethod() {
  for (int i = 0; i < 5; i++) {
    //more nested code

And pasted it into Vim resulting in this:
void nestedMethod() {
    for (int i = 0; i < 5; i++) {
          //more nested code

This will be welcome news. Next time, :set paste before entering insert mode to paste indented text. Your status bar will show INSERT (paste) and your pasted text will retain its original indentation.

Of course, setting and disabling paste can get tiresome, which is why Vim allows you to map a key that will perform this function. Add the following to your .vimrc file:
set pastetoggle=<F2>

After you restart Vim (or :so $MYVIMRC), you will be able to use <F2> to toggle paste mode on and off.

Navigating Long Lines that Wrap

You run into a file with really long lines. Cursing the fool that created this file, you irritably :set wrap to see the entire line:
This is a really long line with wrapping text. This is a really long line that wraps. This is a really long line that wraps. This is a really long line that wraps. This is a really long line that wraps.
Next line.

Of course, when you hit j from the beginning of the file, it jumps to Next line. instead of the next display line that contains the wrapped text. You swear in mind-bending frustration. Does this sound familiar? Have no fear, gj is here! gk and gj are like k and j, except they move by display line rather than actual lines. Add the following lines to your .vimrc:
nnoremap k gk
nnoremap j gj
nnoremap gk k
nnoremap gj j

This will non-recursively map k to gk, vice versa, and similarly with j in normal mode only. What this means is that now k and j will move by display line. If you want to move by physical lines, use gk and gj instead.

Other Tips

Text Objects
Vim has a series of selection commands that start with "i", which stands for "inner". These are very useful when programming. For example, yiB will copy the inner block of code bounded by { and }. ci" will delete text within "", and put the cursor in insert mode. These commands work in visual mode as well; if you enter visual mode and type ib, it will select all characters within ( and ). For more on these, :help text-objects.
Useful Motion Commands
Next time you need to go to the top of a long method or a loop, try [{. This will bring you to the previous unmatched {. Vim has a whole slew of useful motions like [{, including motions for parenthesis and c-style comments. Read :help various-motions, and you won't be disappointed.
Code Folding
Like IDEs such as Eclipse, Vim can be made to fold code for easier browsing in large files. There is an excellent introduction to code folding at :help usr_28.txt.
Browsing Code Intelligently
Vim can be made to work with ctags or cscope. Ctags is a utility that will index all the "tags" in given source files and allow you to jump from the usage of the tag (which can be a method, variable, class, etc.) to its definition. Cscope is a little more elaborate to set up, but it is much more powerful. There are already detailed tutorials for setting up ctags/cscope, so I will forgo duplicating existing work. Quick Googling turns up this page for ctags and this page for cscope.
Search Commands
Vim has some special search commands besides / and :s that are quite handy. * is my personal favourite; used in normal mode, it will search for the word under the cursor, respecting word boundaries. That is, *ing Fred will not match Frederik. # is a similar search command that will search backwards instead of forwards. As you can imagine, they're great at searching for occurrences of variables or functions. Another favourite of mine is gd, which means go to local declaration. When used on a local variable, Vim will find and jump to its declaration. It's not perfect, but surprisingly accurate. Few another variations on these commands can be found at :help search-commands.


Wow, that was longer than I expected. And yes, I did get lazy at the end. I think the post is plenty long as it is. Hope it was useful!