Showing the current Vim file as a proxy icon in the Terminal.app title bar

First published

In OS X Lion, the built-in Terminal gained the ability to display a proxy icon representing the current file or directory in its title bar, in keeping with other document-based applications like TextEdit. The proxy icon can be dragged into other applications as a Finder icon would, or right-clicked or Ctrl-clicked on to bring up a menu showing the item’s location in the filesystem.

The default Bash configuration in applicable versions of OS X takes advantage of this feature to show the current working directory:

Behind the scenes, this is accomplished by watching for an ANSI control sequence, similarly to how the window title is set in xterm-compatible emulators. Terminal.app actually supports two separate sequences for changing the proxy icon, with slightly different semantics. One is for files, and is indicated by the digit 6 in its escape sequence:

^[]6;file://host/path/to/file^G

The other is for directories, and is indicated by the digit 7:

^[]7;file://host/path/to/directory^G

Here, ^[ is the escape character, and ^G is the bell character. In the example above, the default /etc/bashrc adjusts PROMPT_COMMAND to output a directory reporting sequence whenever the prompt is displayed.1

With this knowledge, it’s easy to get Vim to report its current file by adapting its existing window title functionality to use the new control sequence. We can do this with the .vimrc commands shown below. Note that here ^[ and ^G are literal control characters, which must be entered in Vim as Ctrl-V Esc and Ctrl-V Ctrl-G, respectively.

set title
set t_ts=^[]6;
set t_fs=^G
set titlestring=%{bufname('%')==''?'':'file://'.hostname().expand('%:p:gs/\ /%20/')}
set titlelen=0

The first line tells Vim to automatically manage the window title. We then modify the t_ts and t_fs variables to use the file reporting control sequences instead of the standard title escapes.

The titlestring is rather gnarly, so let’s break it down. The %{...} quoting is used to tell Vim to execute the code inside as Vimscript, and yield its result. We then determine whether the current buffer has a name. If not, we’re editing a document that hasn’t yet been saved to disk, and therefore Vim should report an empty filename. This causes Terminal.app to fall back on the current working directory.

Otherwise, we contruct a file: URI pointing to the file we have open, using its path and the computer’s hostname.2 The expand function call gives us the current filename (%), expanded to an absolute path (:p), with all spaces replaced by the URI-encoded sequence %20 (:gs/ /%20/). Note that we have to escape the space with a backslash in order to keep Vim from thinking that we’re trying to set the value of a second variable on the same line.

Lastly, we tell Vim not to truncate the reported filename by setting titlelen to 0, indicating no length limit.

Once that’s done, restart Vim, and voilà.

Figuring out how to do this for text editors that I don’t use is left as an exercise for the reader. Happy hacking!

  1. This feature is also what enables Terminal.app to open new tabs and windows in the same working directory as the current one. GNOME Terminal began using this implementation in version 3.8, replacing a rather hairy method for detecting the working directory that could sometimes deadlock the whole terminal process. ↩︎

  2. The hostname is used to prevent Terminal.app from showing proxy icons for reported file and directory names on remote computers accessed through, e.g., SSH. ↩︎