• Stars
    star
    1,844
  • Rank 25,170 (Top 0.5 %)
  • Language
    Lua
  • License
    MIT License
  • Created almost 3 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Neovim plugin to improve the default vim.ui interfaces

Dressing.nvim

With the release of Neovim 0.6 we were given the start of extensible core UI hooks (vim.ui.select and vim.ui.input). They exist to allow plugin authors to override them with improvements upon the default behavior, so that's exactly what we're going to do.

It is a goal to match and not extend the core Neovim API. All options that core respects will be respected, and we will not accept any custom parameters or options in the functions. Customization will be done entirely using a separate configuration method.

Requirements

Neovim 0.8.0+ (for earlier versions, use the nvim-0.7 or nvim-0.5 branch)

Screenshots

vim.input replacement (handling a LSP rename)

Screenshot from 2021-12-09 17-36-16

vim.select (telescope)

Screenshot from 2021-12-02 19-46-01

vim.select (fzf)

Screenshot from 2021-12-02 19-46-54

vim.select (nui)

Screenshot from 2021-12-02 19-47-56

vim.select (built-in)

Screenshot from 2021-12-04 17-14-32

Installation

dressing.nvim supports all the usual plugin managers

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

Configuration

If you're fine with the defaults, you're good to go after installation. If you want to tweak, call this function:

require('dressing').setup({
  input = {
    -- Set to false to disable the vim.ui.input implementation
    enabled = true,

    -- Default prompt string
    default_prompt = "Input:",

    -- Can be 'left', 'right', or 'center'
    title_pos = "left",

    -- When true, <Esc> will close the modal
    insert_only = true,

    -- When true, input will start in insert mode.
    start_in_insert = true,

    -- These are passed to nvim_open_win
    anchor = "SW",
    border = "rounded",
    -- 'editor' and 'win' will default to being centered
    relative = "cursor",

    -- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
    prefer_width = 40,
    width = nil,
    -- min_width and max_width can be a list of mixed types.
    -- min_width = {20, 0.2} means "the greater of 20 columns or 20% of total"
    max_width = { 140, 0.9 },
    min_width = { 20, 0.2 },

    buf_options = {},
    win_options = {
      -- Window transparency (0-100)
      winblend = 10,
      -- Disable line wrapping
      wrap = false,
      -- Indicator for when text exceeds window
      list = true,
      listchars = "precedes:…,extends:…",
      -- Increase this for more context when text scrolls off the window
      sidescrolloff = 0,
    },

    -- Set to `false` to disable
    mappings = {
      n = {
        ["<Esc>"] = "Close",
        ["<CR>"] = "Confirm",
      },
      i = {
        ["<C-c>"] = "Close",
        ["<CR>"] = "Confirm",
        ["<Up>"] = "HistoryPrev",
        ["<Down>"] = "HistoryNext",
      },
    },

    override = function(conf)
      -- This is the config that will be passed to nvim_open_win.
      -- Change values here to customize the layout
      return conf
    end,

    -- see :help dressing_get_config
    get_config = nil,
  },
  select = {
    -- Set to false to disable the vim.ui.select implementation
    enabled = true,

    -- Priority list of preferred vim.select implementations
    backend = { "telescope", "fzf_lua", "fzf", "builtin", "nui" },

    -- Trim trailing `:` from prompt
    trim_prompt = true,

    -- Options for telescope selector
    -- These are passed into the telescope picker directly. Can be used like:
    -- telescope = require('telescope.themes').get_ivy({...})
    telescope = nil,

    -- Options for fzf selector
    fzf = {
      window = {
        width = 0.5,
        height = 0.4,
      },
    },

    -- Options for fzf-lua
    fzf_lua = {
      -- winopts = {
      --   height = 0.5,
      --   width = 0.5,
      -- },
    },

    -- Options for nui Menu
    nui = {
      position = "50%",
      size = nil,
      relative = "editor",
      border = {
        style = "rounded",
      },
      buf_options = {
        swapfile = false,
        filetype = "DressingSelect",
      },
      win_options = {
        winblend = 10,
      },
      max_width = 80,
      max_height = 40,
      min_width = 40,
      min_height = 10,
    },

    -- Options for built-in selector
    builtin = {
      -- These are passed to nvim_open_win
      anchor = "NW",
      border = "rounded",
      -- 'editor' and 'win' will default to being centered
      relative = "editor",

      buf_options = {},
      win_options = {
        -- Window transparency (0-100)
        winblend = 10,
        cursorline = true,
        cursorlineopt = "both",
      },

      -- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
      -- the min_ and max_ options can be a list of mixed types.
      -- max_width = {140, 0.8} means "the lesser of 140 columns or 80% of total"
      width = nil,
      max_width = { 140, 0.8 },
      min_width = { 40, 0.2 },
      height = nil,
      max_height = 0.9,
      min_height = { 10, 0.2 },

      -- Set to `false` to disable
      mappings = {
        ["<Esc>"] = "Close",
        ["<C-c>"] = "Close",
        ["<CR>"] = "Confirm",
      },

      override = function(conf)
        -- This is the config that will be passed to nvim_open_win.
        -- Change values here to customize the layout
        return conf
      end,
    },

    -- Used to override format_item. See :help dressing-format
    format_item_override = {},

    -- see :help dressing_get_config
    get_config = nil,
  },
})

Highlights

A common way to adjust the highlighting of just the dressing windows is by providing a winhighlight option in the config. See :help winhighlight for more details. Example:

require('dressing').setup({
  input = {
    winhighlight = 'NormalFloat:DiagnosticError'
  }
})

Advanced configuration

For each of the input and select configs, there is an option get_config. This can be a function that accepts the opts parameter that is passed in to vim.select or vim.input. It must return either nil (to no-op) or config values to use in place of the global config values for that module.

For example, if you want to use a specific configuration for code actions:

require('dressing').setup({
  select = {
    get_config = function(opts)
      if opts.kind == 'codeaction' then
        return {
          backend = 'nui',
          nui = {
            relative = 'cursor',
            max_width = 40,
          }
        }
      end
    end
  }
})

Notes for plugin authors

TL;DR: you can customize the telescope vim.ui.select implementation by passing telescope into opts.

The vim.ui hooks are a great boon for us because we can now assume that users will have a reasonable UI available for simple input operations. We no longer have to build separate implementations for each of fzf, telescope, ctrlp, etc. The tradeoff is that vim.ui.select is less customizable than any of these options, so if you wanted to have a preview window (like telescope supports), it is no longer an option.

My solution to this is extending the opts that are passed to vim.ui.select. You can add a telescope field that will be passed directly into the picker, allowing you to customize any part of the UI. If a user has both dressing and telescope installed, they will get your custom picker UI. If either of those are not true, the selection UI will gracefully degrade to whatever the user has configured for vim.ui.select.

An example of usage:

vim.ui.select({'apple', 'banana', 'mango'}, {
  prompt = "Title",
  telescope = require("telescope.themes").get_cursor(),
}, function(selected) end)

For now this is available only for the telescope backend, but feel free to request additions.

Alternative and related projects

  • telescope-ui-select - provides a vim.ui.select implementation for telescope
  • fzf-lua - provides a vim.ui.select implementation for fzf
  • nvim-fzy - fzf alternative that also provides a vim.ui.select implementation (#13)
  • guihua.lua - multipurpose GUI library that provides vim.ui.select and vim.ui.input implementations
  • nvim-notify - doing pretty much the same thing but for vim.notify
  • nui.nvim - provides common UI components for plugin authors. The wiki has examples of how to build your own vim.ui interfaces.

More Repositories

1

oil.nvim

Neovim file explorer: edit your filesystem like a buffer
Lua
3,907
star
2

conform.nvim

Lightweight yet powerful formatter plugin for Neovim
Lua
3,073
star
3

aerial.nvim

Neovim plugin for a code outline window
Lua
1,711
star
4

overseer.nvim

A task runner and job management plugin for Neovim
Lua
1,193
star
5

pypicloud

S3-backed pypi server implementation
Python
505
star
6

vim-arduino

Vim plugin for compiling and uploading arduino sketches
Vim Script
345
star
7

quicker.nvim

Improved UI and workflow for the Neovim quickfix
Lua
321
star
8

stickybuf.nvim

Neovim plugin for locking a buffer to a window
Lua
246
star
9

resession.nvim

A replacement for mksession with a better API
Lua
226
star
10

gkeep.nvim

Google Keep integration for Neovim
Python
193
star
11

dql

A SQL-ish language for DynamoDB
Python
149
star
12

flywheel

Object mapper for Amazon's DynamoDB
Python
128
star
13

profile.nvim

lua profiler for nvim
Lua
126
star
14

qf_helper.nvim

A collection of improvements for the quickfix buffer
Lua
97
star
15

pypicloud-docker

Docker image for pypicloud
Shell
86
star
16

dotfiles

Lua
57
star
17

godot_parser

Python library for parsing Godot scene files
Python
54
star
18

pair-ls

Editor-agnostic remote pair programming
TypeScript
28
star
19

three.nvim

Neovim plugin for working with buffers, windows, and tabs
Lua
21
star
20

nvim-typecheck-action

Github action for typechecking a neovim plugin
Lua
17
star
21

pair-ls.nvim

Neovim plugin for pair-ls
Lua
14
star
22

dynamo3

Python 3 compatible library for DynamoDB
Python
13
star
23

gitstack

A utility for stacking branches and github pull requests
Python
12
star
24

pyramid_webpack

Pyramid extension for managing assets with Webpack
Python
10
star
25

vim-vscode-snippets

A collection of vscode snippets for vim
Python
9
star
26

nvim_doc_tools

Python scripts for Neovim documentation generation
Python
7
star
27

pyramid_duh

Utilities that you'll want for nearly every pyramid app
Python
6
star
28

Battlecode-Server-Tester

Distributed testing tool for the MIT Battlecode competition
Java
3
star
29

parseargs

Bash utility for parsing commandline arguments
Shell
2
star
30

pike

Asset pipeline and make tool
Go
2
star
31

pair-ls-vscode

VS Code extension for pair-ls
TypeScript
2
star
32

eat_your_vegetables

An organizational wrapper around celery
Python
2
star
33

bluepill

A command line utility for working inside docker containers
Python
2
star
34

pore

Command line full-text search
Rust
2
star
35

flow-coverage.nvim

Neovim plugin to display flow type coverage information
Lua
2
star
36

stevearc

1
star
37

stevetags

Little website for tagging Dropbox files
Python
1
star