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 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!
-
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. ↩︎
-
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. ↩︎