Ranger

· software · geek ·

It’s nearly Christmas, and what could be more festive than writing about a command-line file manager? I’m pretty sure that I’ve tried Ranger before, but at that point it was early in its development, and I had a few issues with it. I was reminded of it again by Dr Bunsen, and decided to give it another go. It’s available via homebrew, so you can install it with a simple brew install ranger. I also chose to install some of the optional dependencies: highlight, poppler and w3m, of which more later.

Ranger is a command-line file manager that operates over three columns, a bit like the Mac Finder. The middle column shows you your current selection, the left column is the parent directory of the selected file, and the right column optionally shows a preview of certain kinds of files. What I really like about Ranger (over similar file managers like Midnight Commander), is that it uses Vim-style keybindings by default. So you can navigate up and down the file tree, copy, cut and paste files in exactly the same way as Vim. Even those bindings that don’t have a direct counterpart in Vim make sense and feel very natural if you are a Vim user. I think this is the first command-line file manager that feels almost as natural as using Finder.

The ability to preview files is the other big benefit of Ranger. It will show you the content of text files in the right-hand column by default, but if you install highlight, it will use syntax colouring to do so, which is a very nice touch that I find helpful. Similarly, if you have w3m installed, it will show you a bare-bones rendered version of HTML files, which again helps readability, without having to open up a browser to view the file. Finally, poppler (which includes pdf2text) allows you to preview a plain text version of PDF files, something that works remarkably well on mostly text-based PDF files. You can even use img2txt to render a coloured ASCII art version of your image files, but that felt a bit over the top1.

The power doesn’t stop there, because you can write commands (in Python) and bind keystrokes in the config files to automate certain tasks. For example, I wrote a little keybinding to open the selected file in Marked (to render and preview Markdown files):

map mm shell -fs open -a 'Marked 2.app' %s

So in Ranger, I need only hit mm and the selected file opens in Marked.

I should say that Ranger includes some very powerful filtering, searching and marking commands, as well as bookmarking of directories, so it’s easy to chain these together with any external tools to process files, in a similar way to using shell commands in Vim.

Speaking of Vim, I was thinking that it would be nice to be able to use Ranger from within Vim rather than have to rely on Vim’s own file manager which is less powerful, when I came across this article by Thibault Duplessis. He includes a function that you put in your .vimrc which provides a command for launching Ranger within Vim, passing it a temporary file to write to, which is deleted when you write the file you are editing. It’s a bit difficult to explain because it begins to sound a bit like a geeky Matryoshka doll, but what you see when you hit the keybinding is that Ranger appears, you select a file to edit (which then opens in Vim), and then when you write the file and quit, you end up back where you were in Vim when you called Ranger. It’s magic, trust me. I had to modify the command a little, because the Mac version of mktemp evidently has some different switches and options to the Linux one, but this works for me:

function! Ranger()
    " Get a temp file name without creating it
    let tmpfile = substitute(system('mktemp -u -t ranger'), '\n', '', '')
    " Launch ranger, passing it the temp file name
    silent exec '!RANGER_RETURN_FILE='.tmpfile.' ranger'
    " If the temp file has been written by ranger
    if filereadable(tmpfile)
        " Get the selected file name from the temp file
        let filetoedit = system('cat '.tmpfile)
        exec 'edit '.filetoedit
        call delete(tmpfile)
    endif
    redraw!
endfunction

nmap <leader>r :call Ranger()<cr()

If you spend a bit of time in a Terminal, I really recommend trying out Ranger and seeing if it suits you. It’s a mark of how much I like it that I’ve let it occupy its own window in tmux by default.


  1. I’m trying to avoid saying ‘pointless’, as I’m sure some people might find it useful. ↩︎