Initial commit

This commit is contained in:
Steven Arcangeli 2021-12-02 17:43:52 -08:00 committed by Steven Arcangeli
commit 7f6cf7fb80
22 changed files with 1039 additions and 0 deletions

4
.github/pre-commit vendored Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
set -e
luacheck .
stylua --check .

87
.github/update_readme.py vendored Executable file
View file

@ -0,0 +1,87 @@
#!/usr/bin/env python
import os
import os.path
import re
from typing import List
HERE = os.path.dirname(__file__)
ROOT = os.path.abspath(os.path.join(HERE, os.path.pardir))
README = os.path.join(ROOT, "README.md")
DOC = os.path.join(ROOT, "doc", "dressing.txt")
def indent(lines: List[str], amount: int) -> List[str]:
ret = []
for line in lines:
if amount >= 0:
ret.append(" " * amount + line)
else:
space = re.match(r"[ \t]+", line)
if space:
ret.append(line[min(abs(amount), space.span()[1]) :])
else:
ret.append(line)
return ret
def replace_section(file: str, start_pat: str, end_pat: str, lines: List[str]) -> None:
prefix_lines: List[str] = []
postfix_lines: List[str] = []
file_lines = prefix_lines
found_section = False
with open(file, "r", encoding="utf-8") as ifile:
inside_section = False
for line in ifile:
if inside_section:
if re.match(end_pat, line):
inside_section = False
file_lines = postfix_lines
file_lines.append(line)
else:
if not found_section and re.match(start_pat, line):
inside_section = True
found_section = True
file_lines.append(line)
if inside_section or not found_section:
raise Exception(f"could not find file section {start_pat}")
all_lines = prefix_lines + lines + postfix_lines
with open(file, "w", encoding="utf-8") as ofile:
ofile.write("".join(all_lines))
def read_section(filename: str, start_pat: str, end_pat: str) -> List[str]:
lines = []
with open(filename, "r", encoding="utf-8") as ifile:
inside_section = False
for line in ifile:
if inside_section:
if re.match(end_pat, line):
break
lines.append(line)
elif re.match(start_pat, line):
inside_section = True
return lines
def main() -> None:
"""Update the README"""
config_file = os.path.join(ROOT, "lua", "dressing", "config.lua")
opt_lines = read_section(config_file, r"^\s*local default_config =", r"^}$")
replace_section(README, r"^require\('dressing'\)\.setup", r"^}\)$", opt_lines)
replace_section(
DOC, r"^\s*require\('dressing'\)\.setup", r"^\s*}\)$", indent(opt_lines, 4)
)
get_config_lines = read_section(DOC, r"^dressing.get_config", "^===")
for i, line in enumerate(get_config_lines):
if re.match(r"^\s*>$", line):
get_config_lines[i] = "```lua\n"
break
get_config_lines.append("```\n")
replace_section(README, r"^## Custom config", r"^#", indent(get_config_lines, -4))
if __name__ == "__main__":
main()

32
.github/workflows/lint.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Lint
on: [push, pull_request]
jobs:
luacheck:
name: Luacheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Prepare
run: |
sudo apt-get update
sudo add-apt-repository universe
sudo apt install luarocks -y
sudo luarocks install luacheck
- name: Run Luacheck
run: luacheck .
stylua:
name: StyLua
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Stylua
uses: JohnnyMorganz/stylua-action@1.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --check .

25
.github/workflows/update-readme.yml vendored Normal file
View file

@ -0,0 +1,25 @@
name: Update README
on: push
jobs:
update-readme:
name: Update README
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Update README
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_MSG: |
[docgen] Update README.md
skip-checks: true
run: |
git config user.email "actions@github"
git config user.name "Github Actions"
git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
python .github/update_readme.py
git add README.md
# Only commit and push if we have changes
git diff --quiet && git diff --staged --quiet || (git commit -m "${COMMIT_MSG}"; git push origin HEAD:${GITHUB_REF})

41
.gitignore vendored Normal file
View file

@ -0,0 +1,41 @@
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

16
.luacheckrc Normal file
View file

@ -0,0 +1,16 @@
max_comment_line_length = false
codes = true
exclude_files = {
"tests/",
}
ignore = {
"212", -- Unused argument
"631", -- Line is too long
"122", -- Setting a readonly global
}
read_globals = {
"vim",
}

3
.stylua.toml Normal file
View file

@ -0,0 +1,3 @@
column_width = 100
indent_type = "Spaces"
indent_width = 2

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Steven Arcangeli
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

180
README.md Normal file
View file

@ -0,0 +1,180 @@
# Dressing.nvim
With the release of Neovim 0.6 we were given the start of extensible core UI
hooks ([vim.ui.select](https://github.com/neovim/neovim/pull/15771) and
[vim.ui.input](https://github.com/neovim/neovim/pull/15959)). 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](#configuration) method.
## Requirements
Neovim 0.5+
On versions prior to 0.6, this plugin will act as a polyfill for `vim.ui`
## Installation
dressing.nvim supports all the usual plugin managers
<details>
<summary>Packer</summary>
```lua
require('packer').startup(function()
use {'stevearc/dressing.nvim'}
end)
```
</details>
<details>
<summary>Paq</summary>
```lua
require "paq" {
{'stevearc/dressing.nvim'};
}
```
</details>
<details>
<summary>vim-plug</summary>
```vim
Plug 'stevearc/dressing.nvim'
```
</details>
<details>
<summary>dein</summary>
```vim
call dein#add('stevearc/dressing.nvim')
```
</details>
<details>
<summary>Pathogen</summary>
```sh
git clone --depth=1 https://github.com/stevearc/dressing.nvim.git ~/.vim/bundle/
```
</details>
<details>
<summary>Neovim native package</summary>
```sh
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
```
</details>
## Configuration
If you're fine with the defaults, you're good to go after installation. If you
want to tweak, call this function:
```lua
require('dressing').setup({
input = {
-- Default prompt string
default_prompt = "➤ ",
-- These are passed to nvim_open_win
anchor = "SW",
relative = "cursor",
row = 0,
col = 0,
border = "rounded",
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
prefer_width = 40,
max_width = nil,
min_width = 20,
-- see :help dressing_get_config
get_config = nil,
},
select = {
-- Priority list of preferred vim.select implementations
backend = { "telescope", "fzf", "builtin", "nui" },
-- Options for telescope selector
telescope = {},
-- Options for fzf selector
fzf = {
width = 0.5,
height = 0.4,
},
-- Options for nui Menu
nui = {
position = "50%",
size = nil,
relative = "editor",
border = {
style = "rounded",
},
max_width = 80,
max_height = 40,
},
-- Options for built-in selector
builtin = {
-- These are passed to nvim_open_win
anchor = "NW",
relative = "cursor",
row = 0,
col = 0,
border = "rounded",
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
width = nil,
max_width = 0.8,
min_width = 40,
height = nil,
max_height = 0.9,
min_height = 10,
},
-- see :help dressing_get_config
get_config = nil,
},
})
```
## Custom config per usage
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:
```lua
require('dressing').setup({
select = {
get_config = function(opts)
if opts.kind == 'codeaction' then
return {
backend = 'nui',
nui = {
relative = 'cursor',
max_width = 40,
}
}
end
end
}
})
```
## Similar projects
* [nvim-notify](https://github.com/rcarriga/nvim-notify) - doing pretty much the
same thing but for `vim.notify`
* [nui.nvim](https://github.com/MunifTanjim/nui.nvim) - provides common UI
components for plugin authors

20
autoload/dressing.vim Normal file
View file

@ -0,0 +1,20 @@
func! dressing#prompt_confirm(text) abort
call v:lua.dressing_prompt_confirm(a:text)
endfunc
func! dressing#prompt_cancel() abort
lua dressing_prompt_cancel()
endfunc
function! dressing#fzf_run(labels, options, window) abort
call fzf#run({
\ 'source': a:labels,
\ 'sink': funcref('dressing#fzf_choice'),
\ 'options': a:options,
\ 'window': a:window,
\ })
endfunction
function! dressing#fzf_choice(label) abort
call v:lua.dressing_fzf_choice(a:label)
endfunction

102
doc/dressing.txt Normal file
View file

@ -0,0 +1,102 @@
*dressing.txt*
*Dressing* *dressing* *dressing.nvim*
===============================================================================
CONFIGURATION *dressing-configuration*
Configure dressing.nvim by calling the setup() function.
>
require('dressing').setup({
input = {
-- Default prompt string
default_prompt = "➤ ",
-- These are passed to nvim_open_win
anchor = "SW",
relative = "cursor",
row = 0,
col = 0,
border = "rounded",
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
prefer_width = 40,
max_width = nil,
min_width = 20,
-- see :help dressing_get_config
get_config = nil,
},
select = {
-- Priority list of preferred vim.select implementations
backend = { "telescope", "fzf", "builtin", "nui" },
-- Options for telescope selector
telescope = {},
-- Options for fzf selector
fzf = {
width = 0.5,
height = 0.4,
},
-- Options for nui Menu
nui = {
position = "50%",
size = nil,
relative = "editor",
border = {
style = "rounded",
},
max_width = 80,
max_height = 40,
},
-- Options for built-in selector
builtin = {
-- These are passed to nvim_open_win
anchor = "NW",
relative = "cursor",
row = 0,
col = 0,
border = "rounded",
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
width = nil,
max_width = 0.8,
min_width = 40,
height = nil,
max_height = 0.9,
min_height = 10,
},
-- see :help dressing_get_config
get_config = nil,
},
})
dressing.get_config() *dressing_get_config()*
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
}
})
===============================================================================
vim:ft=help:et:ts=2:sw=2:sts=2:norl

6
doc/tags Normal file
View file

@ -0,0 +1,6 @@
Dressing dressing.txt /*Dressing*
dressing dressing.txt /*dressing*
dressing-configuration dressing.txt /*dressing-configuration*
dressing.nvim dressing.txt /*dressing.nvim*
dressing.txt dressing.txt /*dressing.txt*
dressing_get_config() dressing.txt /*dressing_get_config()*

92
lua/dressing/config.lua Normal file
View file

@ -0,0 +1,92 @@
local default_config = {
input = {
-- Default prompt string
default_prompt = "",
-- These are passed to nvim_open_win
anchor = "SW",
relative = "cursor",
row = 0,
col = 0,
border = "rounded",
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
prefer_width = 40,
max_width = nil,
min_width = 20,
-- see :help dressing_get_config
get_config = nil,
},
select = {
-- Priority list of preferred vim.select implementations
backend = { "telescope", "fzf", "builtin", "nui" },
-- Options for telescope selector
telescope = {},
-- Options for fzf selector
fzf = {
window = {
width = 0.5,
height = 0.4,
},
},
-- Options for nui Menu
nui = {
position = "50%",
size = nil,
relative = "editor",
border = {
style = "rounded",
},
max_width = 80,
max_height = 40,
},
-- Options for built-in selector
builtin = {
-- These are passed to nvim_open_win
anchor = "NW",
relative = "cursor",
row = 0,
col = 0,
border = "rounded",
-- These can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
width = nil,
max_width = 0.8,
min_width = 40,
height = nil,
max_height = 0.9,
min_height = 10,
},
-- see :help dressing_get_config
get_config = nil,
},
}
local M = vim.deepcopy(default_config)
M.update = function(opts)
local newconf = vim.tbl_deep_extend("force", default_config, opts or {})
for k, v in pairs(newconf) do
M[k] = v
end
end
M.get_mod_config = function(key, ...)
if not M[key].get_config then
return M[key]
end
local conf = M[key].get_config(...)
if conf then
return vim.tbl_deep_extend("force", M[key], conf)
else
return M[key]
end
end
return M

18
lua/dressing/init.lua Normal file
View file

@ -0,0 +1,18 @@
local config = require("dressing.config")
local M = {}
M.setup = function(opts)
config.update(opts)
end
M.patch = function()
-- For Neovim before 0.6
if not vim.ui then
vim.ui = {}
end
vim.ui.input = require("dressing.input")
vim.ui.select = require("dressing.select")
end
return M

83
lua/dressing/input.lua Normal file
View file

@ -0,0 +1,83 @@
local global_config = require("dressing.config")
local util = require("dressing.util")
local function clear_callbacks()
_G.dressing_prompt_confirm = function() end
_G.dressing_prompt_cancel = function() end
_G.dressing_prompt_hl = function() end
end
clear_callbacks()
return function(opts, on_confirm)
vim.validate({
on_confirm = { on_confirm, "function", false },
})
opts = opts or {}
local config = global_config.get_mod_config("input", opts)
local bufnr = vim.api.nvim_create_buf(false, true)
local prompt = opts.prompt or config.default_prompt
local width = util.calculate_width(config.prefer_width + vim.api.nvim_strwidth(prompt), config)
local winopt = {
relative = config.relative,
anchor = config.anchor,
row = config.row,
col = config.col,
border = config.border,
width = width,
height = 1,
zindex = 150,
style = "minimal",
}
local winnr = vim.api.nvim_open_win(bufnr, true, winopt)
vim.api.nvim_buf_set_option(bufnr, "buftype", "prompt")
vim.api.nvim_buf_set_option(bufnr, "swapfile", false)
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
vim.fn.prompt_setprompt(bufnr, prompt)
_G.dressing_prompt_confirm = function(text)
clear_callbacks()
vim.api.nvim_win_close(winnr, true)
on_confirm(text)
end
_G.dressing_prompt_cancel = function()
clear_callbacks()
vim.api.nvim_win_close(winnr, true)
on_confirm(nil)
end
if opts.highlight then
_G.dressing_prompt_hl = function()
local text = vim.api.nvim_buf_get_lines(bufnr, 0, 1, true)[1]
local ns = vim.api.nvim_create_namespace("DressingHl")
local highlights
if type(opts.highlight) == "function" then
highlights = opts.highlight(text)
else
highlights = vim.fn[opts.highlight](text)
end
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
for _, highlight in ipairs(highlights) do
local start = highlight[1]
local stop = highlight[2]
local group = highlight[3]
vim.api.nvim_buf_add_highlight(bufnr, ns, group, 0, start, stop)
end
end
vim.cmd([[
autocmd TextChanged <buffer> lua dressing_prompt_hl()
autocmd TextChangedI <buffer> lua dressing_prompt_hl()
]])
end
-- Would prefer to use v:lua directly here, but it doesn't work :(
vim.fn.prompt_setcallback(bufnr, "dressing#prompt_confirm")
vim.fn.prompt_setinterrupt(bufnr, "dressing#prompt_cancel")
vim.cmd([[
autocmd BufLeave <buffer> call dressing#prompt_cancel()
]])
vim.cmd("startinsert!")
if opts.default then
vim.fn.feedkeys(opts.default)
end
_G.dressing_prompt_hl()
end

View file

@ -0,0 +1,74 @@
local util = require("dressing.util")
local M = {}
M.is_supported = function()
return true
end
local _callback = function() end
local _items = {}
local function clear_callback()
_callback = function() end
_items = {}
end
M.select = function(config, items, opts, on_choice)
_callback = function(item, idx)
clear_callback()
on_choice(item, idx)
end
_items = items
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_option(bufnr, "swapfile", false)
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
local lines = {}
local max_width = 1
for _, item in ipairs(items) do
local line = opts.format_item(item)
max_width = math.max(max_width, vim.api.nvim_strwidth(line))
table.insert(lines, line)
end
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
vim.api.nvim_buf_set_option(bufnr, "modifiable", false)
local winopt = {
relative = config.relative,
anchor = config.anchor,
row = config.row,
col = config.col,
border = config.border,
width = util.calculate_width(max_width, config),
height = util.calculate_height(#lines, config),
zindex = 150,
style = "minimal",
}
local winnr = vim.api.nvim_open_win(bufnr, true, winopt)
vim.api.nvim_win_set_option(winnr, "cursorline", true)
if vim.fn.exists("&cursorlineopt") ~= 0 then
vim.api.nvim_win_set_option(winnr, "cursorlineopt", "both")
end
local function map(lhs, rhs)
vim.api.nvim_buf_set_keymap(bufnr, "n", lhs, rhs, { silent = true, noremap = true })
end
map("<CR>", [[<cmd>lua require('dressing.select.builtin').choose()<CR>]])
map("<C-c>", [[<cmd>lua require('dressing.select.builtin').cancel()<CR>]])
map("<Esc>", [[<cmd>lua require('dressing.select.builtin').cancel()<CR>]])
vim.cmd([[
autocmd BufLeave <buffer> lua require('dressing.select.builtin').cancel()
]])
end
M.choose = function()
local cursor = vim.api.nvim_win_get_cursor(0)
local idx = cursor[1]
_callback(_items[idx], idx)
vim.api.nvim_win_close(0, true)
end
M.cancel = function()
vim.api.nvim_win_close(0, true)
_callback(nil, nil)
end
return M

View file

@ -0,0 +1,36 @@
local M = {}
M.is_supported = function()
return vim.fn.exists("*fzf#run") ~= 0
end
local function clear_callback()
_G.dressing_fzf_choice = function() end
_G.dressing_fzf_cancel = function() end
end
clear_callback()
M.select = function(config, items, opts, on_choice)
local labels = {}
for i, item in ipairs(items) do
table.insert(labels, string.format("%d: %s", i, opts.format_item(item)))
end
_G.dressing_fzf_cancel = function()
clear_callback()
on_choice(nil, nil)
end
_G.dressing_fzf_choice = function(label)
clear_callback()
local colon = string.find(label, ":")
local lnum = tonumber(string.sub(label, 1, colon - 1))
local item = items[lnum]
on_choice(item, lnum)
end
vim.fn["dressing#fzf_run"](labels, string.format('--prompt="%s"', opts.prompt), config.window)
-- fzf doesn't have a cancel callback, so we have to make one.
-- the defer_fn is so that we can process the confirm event first
vim.cmd([[autocmd BufLeave <buffer> lua vim.defer_fn(function() dressing_fzf_cancel() end, 5)]])
end
return M

View file

@ -0,0 +1,39 @@
local global_config = require("dressing.config")
local function get_backend(config)
local backends = config.backend
if type(backends) ~= "table" then
backends = { backends }
end
for _, backend in ipairs(backends) do
local ok, mod = pcall(require, string.format("dressing.select.%s", backend))
if ok and mod.is_supported() then
return mod, backend
end
end
return require("dressing.select.builtin"), "builtin"
end
return function(items, opts, on_choice)
vim.validate({
items = { items, "table", false },
on_choice = { on_choice, "function", false },
})
opts = opts or {}
local config = global_config.get_mod_config("select", opts)
opts.prompt = opts.prompt or "Select one of:"
opts.format_item = opts.format_item or tostring
local backend, name = get_backend(config)
backend.select(config[name], items, opts, on_choice)
-- for i, item in pairs(items) do
-- table.insert(choices, string.format("%d: %s", i, format_item(item)))
-- end
-- local choice = vim.fn.inputlist(choices)
-- if choice < 1 or choice > #items then
-- on_choice(nil, nil)
-- else
-- on_choice(items[choice], choice)
-- end
end

View file

@ -0,0 +1,55 @@
local M = {}
M.is_supported = function()
return pcall(require, "nui.menu")
end
M.select = function(config, items, opts, on_choice)
local Menu = require("nui.menu")
local event = require("nui.utils.autocmd").event
local lines = {}
for i, item in ipairs(items) do
table.insert(lines, Menu.item(opts.format_item(item), { value = item, idx = i }))
end
local border = vim.deepcopy(config.border)
border.text = {
top = opts.prompt,
top_align = "center",
}
local menu = Menu({
position = config.position,
size = config.size,
relative = config.relative,
border = border,
buf_options = {
swapfile = false,
},
win_options = {
winblend = 10,
},
enter = true,
}, {
lines = lines,
max_width = config.max_width,
max_height = config.max_height,
keymap = {
focus_next = { "j", "<Down>", "<Tab>" },
focus_prev = { "k", "<Up>", "<S-Tab>" },
close = { "<Esc>", "<C-c>" },
submit = { "<CR>" },
},
on_close = function()
on_choice(nil, nil)
end,
on_submit = function(item)
on_choice(item.value, item.idx)
end,
})
menu:mount()
menu:on(event.BufLeave, menu.menu_props.on_close, { once = true })
end
return M

View file

@ -0,0 +1,58 @@
local M = {}
M.is_supported = function()
return pcall(require, "telescope")
end
M.select = function(config, items, opts, on_choice)
local themes = require("telescope.themes")
local actions = require("telescope.actions")
local state = require("telescope.actions.state")
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local conf = require("telescope.config").values
local entry_maker = function(item)
local formatted = opts.format_item(item)
return {
display = formatted,
ordinal = formatted,
value = item,
}
end
local picker_opts = themes.get_dropdown({
previewer = false,
})
pickers.new(picker_opts, {
prompt_title = opts.prompt,
finder = finders.new_table({
results = items,
entry_maker = entry_maker,
}),
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
local selection = state.get_selected_entry()
actions._close(prompt_bufnr, false)
local idx = nil
for i, item in ipairs(items) do
if item == selection.value then
idx = i
break
end
end
on_choice(selection.value, idx)
end)
actions.close:replace(function()
actions._close(prompt_bufnr, false)
on_choice(nil, nil)
end)
return true
end,
}):find()
end
return M

46
lua/dressing/util.lua Normal file
View file

@ -0,0 +1,46 @@
local M = {}
local function is_float(value)
local _, p = math.modf(value)
return p ~= 0
end
local function calc_float(value, max_value)
if value and is_float(value) then
return math.min(max_value, value * max_value)
else
return value
end
end
local function calculate_dim(desired_size, size, min_size, max_size, total_size)
local ret = calc_float(size, total_size)
if not ret then
ret = calc_float(desired_size, total_size)
end
ret = math.min(ret, calc_float(max_size, total_size) or total_size)
ret = math.max(ret, calc_float(min_size, total_size) or 1)
return math.floor(ret)
end
M.calculate_width = function(desired_width, config)
return calculate_dim(
desired_width,
config.width,
config.min_width,
config.max_width,
vim.o.columns
)
end
M.calculate_height = function(desired_height, config)
return calculate_dim(
desired_height,
config.height,
config.min_height,
config.max_height,
vim.o.lines - vim.o.cmdheight
)
end
return M

1
plugin/dressing.lua Normal file
View file

@ -0,0 +1 @@
require("dressing").patch()