/oil.nvim

Neovim file explorer: edit your filesystem like a buffer

Primary LanguageLuaMIT LicenseMIT

oil.nvim

A vim-vinegar like file explorer that lets you edit your filesystem like a normal Neovim buffer.

oil.demo.mp4

Requirements

Installation

oil.nvim supports all the usual plugin managers

Packer
require('packer').startup(function()
    use {
      'stevearc/oil.nvim',
      config = function() require('oil').setup() end
    }
end)
Paq
require "paq" {
    {'stevearc/oil.nvim'};
}
vim-plug
Plug 'stevearc/oil.nvim'
dein
call dein#add('stevearc/oil.nvim')
Pathogen
git clone --depth=1 https://github.com/stevearc/oil.nvim.git ~/.vim/bundle/
Neovim native package
git clone --depth=1 https://github.com/stevearc/oil.nvim.git \
  "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/pack/oil/start/oil.nvim

Quick start

Add the following to your init.lua

require("oil").setup()

Then open a directory with nvim .. Use <CR> to open a file/directory, and - to go up a directory. Otherwise, just treat it like a normal buffer and make changes as you like. Remember to :w when you're done to actually perform the actions.

If you want to mimic the vim-vinegar method of navigating to the parent directory of a file, add this keymap:

vim.keymap.set("n", "-", require("oil").open, { desc = "Open parent directory" })

You can open a directory with :edit <path> or :Oil <path>. To open oil in a floating window, do :Oil --float <path>.

Options

require("oil").setup({
  -- Id is automatically added at the beginning, and name at the end
  -- See :help oil-columns
  columns = {
    "icon",
    -- "permissions",
    -- "size",
    -- "mtime",
  },
  -- Window-local options to use for oil buffers
  win_options = {
    wrap = false,
    signcolumn = "no",
    cursorcolumn = false,
    foldcolumn = "0",
    spell = false,
    list = false,
    conceallevel = 3,
    concealcursor = "n",
  },
  -- Restore window options to previous values when leaving an oil buffer
  restore_win_options = true,
  -- Skip the confirmation popup for simple operations
  skip_confirm_for_simple_edits = false,
  -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap
  -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true })
  -- Additionally, if it is a string that matches "action.<name>",
  -- it will use the mapping at require("oil.action").<name>
  -- Set to `false` to remove a keymap
  keymaps = {
    ["g?"] = "actions.show_help",
    ["<CR>"] = "actions.select",
    ["<C-s>"] = "actions.select_vsplit",
    ["<C-h>"] = "actions.select_split",
    ["<C-p>"] = "actions.preview",
    ["<C-c>"] = "actions.close",
    ["<C-l>"] = "actions.refresh",
    ["-"] = "actions.parent",
    ["_"] = "actions.open_cwd",
    ["`"] = "actions.cd",
    ["~"] = "actions.tcd",
    ["g."] = "actions.toggle_hidden",
  },
  -- Set to false to disable all of the above keymaps
  use_default_keymaps = true,
  view_options = {
    -- Show files and directories that start with "."
    show_hidden = false,
  },
  -- Configuration for the floating window in oil.open_float
  float = {
    -- Padding around the floating window
    padding = 2,
    max_width = 0,
    max_height = 0,
    border = "rounded",
    win_options = {
      winblend = 10,
    },
  },
  adapters = {
    ["oil://"] = "files",
    ["oil-ssh://"] = "ssh",
  },
  -- When opening the parent of a file, substitute these url schemes
  remap_schemes = {
    ["scp://"] = "oil-ssh://",
    ["sftp://"] = "oil-ssh://",
  },
})

Adapters

Oil does all of its filesystem interaction through an adapter abstraction. In practice, this means that oil can be used to view and modify files in more places than just the local filesystem, so long as the destination has an adapter implementation.

Note that file operations work across adapters. This means that you can use oil to copy files to/from a remote server using the ssh adapter just as easily as you can copy files from one directory to another on your local machine.

SSH

This adapter allows you to browse files over ssh, much like netrw. To use it, simply open a buffer using the following name template:

nvim oil-ssh://[username@]hostname[:port]/[path]

This should look familiar. In fact, if you replace oil-ssh:// with sftp://, this is the exact same url format that netrw uses.

While this adapter effectively replaces netrw for directory browsing, it still relies on netrw for file editing. When you open a file from oil, it will use the scp://host/path/to/file.txt format that triggers remote editing via netrw.

API

get_entry_on_line(bufnr, lnum)

get_entry_on_line(bufnr, lnum): nil|oil.Entry
Get the entry on a specific line (1-indexed)

Param Type Desc
bufnr integer
lnum integer

get_cursor_entry()

get_cursor_entry(): nil|oil.Entry
Get the entry currently under the cursor

discard_all_changes()

discard_all_changes()
Discard all changes made to oil buffers

set_columns(cols)

set_columns(cols)
Change the display columns for oil

Param Type Desc
cols oil.ColumnSpec[]

get_current_dir()

get_current_dir(): nil|string
Get the current directory

open_float(dir)

open_float(dir)
Open oil browser in a floating window

Param Type Desc
dir nil|string When nil, open the parent of the current buffer, or the cwd if current buffer is not a file

open(dir)

open(dir)
Open oil browser for a directory

Param Type Desc
dir nil|string When nil, open the parent of the current buffer, or the cwd if current buffer is not a file

close()

close()
Restore the buffer that was present when oil was opened

select(opts)

select(opts)
Select the entry under the cursor

Param Type Desc
opts table
vertical boolean Open the buffer in a vertical split
horizontal boolean Open the buffer in a horizontal split
split "aboveleft"|"belowright"|"topleft"|"botright" Split modifier
preview boolean Open the buffer in a preview window

save(opts)

save(opts)
Save all changes

Param Type Desc
opts nil|table
confirm nil|boolean Show confirmation when true, never when false, respect skip_confirm_for_simple_edits if nil

setup(opts)

setup(opts)
Initialize oil

Param Type Desc
opts nil|table

FAQ

Q: Why "oil"?

A: From the vim-vinegar README, a quote by Drew Neil:

Split windows and the project drawer go together like oil and vinegar

Vinegar was taken. Let's be oil. Plus, I think it's pretty slick ;)

Q: Why would I want to use oil vs any other plugin?

A:

  • You like to use a netrw-like view to browse directories (as opposed to a file tree)
  • AND you want to be able to edit your filesystem like a buffer
  • AND you want to perform cross-directory actions. AFAIK there is no other plugin that does this.

If you don't need those features specifically, check out the alternatives listed below

Q: Why write another plugin yourself instead of adding functionality to one that already exists?

A: Because I am a maniac control freak.

Q: What are some alternatives?

A:

  • vim-vinegar: The granddaddy. This made me fall in love with single-directory file browsing. I stopped using it when I encountered netrw bugs and performance issues.
  • defx.nvim: What I switched to after vim-vinegar. Much more flexible and performant, but requires python and the API is a little hard to work with.
  • dirbuf.nvim: The first plugin I encountered that let you edit the filesystem like a buffer. Never used it because it can't do cross-directory edits.
  • lir.nvim: What I used prior to writing this plugin. Similar to vim-vinegar, but with better Neovim integration (floating windows, lua API).
  • vim-dirvish: Never personally used, but well-established, stable, simple directory browser.
  • vidir: Never personally used, but might be the first plugin to come up with the idea of editing a directory like a buffer.

There's also file trees like neo-tree and nvim-tree, but they're really a different category entirely.