1

Regenerate nvim config

This commit is contained in:
2024-06-02 03:29:20 +02:00
parent 75eea0c030
commit ef2e28883d
5576 changed files with 604886 additions and 503 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Daniel Nägele
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.

View File

@ -0,0 +1,252 @@
# telescope-undo.nvim
Visualize your undo tree and fuzzy-search changes in it. For those days where committing early and
often doesn't work out.
![screenshot](https://user-images.githubusercontent.com/4604331/208297854-df5a104a-2fc1-4411-9f5f-5e40454d8dac.png)
## Usage
After invoking `telescope-undo` you can browse the current buffer's undo tree in a text-based tree
representation by using telescope's `move_selection_next/previous` actions. These are mapped to
arrow keys or `<C-n>,<C-p>` by default. Inserted text is fuzzy matched against the additions and
deletions in each undo state in your undo tree and the finder will limit the results accordingly.
While this obviously breaks the tree visuals, you can freely search in your undo states. The
previewer will always show the diff of the current selection with some context according to the
config or your `scrolloff` value.
If you have found the undo state you were looking for, you can use `<C-cr>` or `<C-r>` to revert to
that state. If you'd rather not change your whole buffer, you can use `<cr>` to yank the additions
of this undo state into your default register (use `<S-cr>` or `<C-y>` to yank the deletions).
## Installation
Install with your favorite Neovim package manager.
As part of your Telescope plugin spec for [lazy.nvim](https://github.com/folke/lazy.nvim):
```lua
{
"nvim-telescope/telescope.nvim",
dependencies = {
"nvim-lua/plenary.nvim",
"debugloop/telescope-undo.nvim",
},
config = function()
require("telescope").setup({
-- the rest of your telescope config goes here
extensions = {
undo = {
-- telescope-undo.nvim config, see below
},
-- other extensions:
-- file_browser = { ... }
},
})
require("telescope").load_extension("undo")
-- optional: vim.keymap.set("n", "<leader>u", "<cmd>Telescope undo<cr>")
end,
},
```
If you prefer standalone Lazy plugin specs (my personal recommendation), here's how you do that with
some more options as an example:
```lua
{
"debugloop/telescope-undo.nvim",
dependencies = { -- note how they're inverted to above example
{
"nvim-telescope/telescope.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
},
},
keys = {
{ -- lazy style key map
"<leader>u",
"<cmd>Telescope undo<cr>",
desc = "undo history",
},
},
opts = {
-- don't use `defaults = { }` here, do this in the main telescope spec
extensions = {
undo = {
-- telescope-undo.nvim config, see below
},
-- no other extensions here, they can have their own spec too
},
},
config = function(_, opts)
-- Calling telescope's setup from multiple specs does not hurt, it will happily merge the
-- configs for us. We won't use data, as everything is in it's own namespace (telescope
-- defaults, as well as each extension).
require("telescope").setup(opts)
require("telescope").load_extension("undo")
end,
},
```
Invoke using:
```viml
" Directly by calling it through Telescope's extension interface:
" using lua
:lua require("telescope").extensions.undo.undo()
" using custom options for just this call
:lua require("telescope").extensions.undo.undo({ side_by_side = true })
" using legacy Vim script
:Telescope undo
" Using the optional mapping:
" using lua
:lua vim.keymap.set("n", "<leader>u", "<cmd>Telescope undo<cr>")
" using legacy Vim script
:nmap <leader>u <cmd>Telescope undo<cr>
```
## Configuration
The available configuration values are:
* `use_delta`, which controls whether [delta](https://github.com/dandavison/delta) is used for fancy
diffs in the preview section. If set to false, `telescope-undo` will not use `delta` even when
available and fall back to a plain diff with treesitter highlights.
* `use_custom_command`, which can be used to use an *unsupported* diff tool other than `delta`
* `side_by_side`, which tells `delta` to render diffs side-by-side. Thus, requires `delta` to be
used. Be aware that `delta` always uses its own configuration, so it might be that you're getting
the side-by-side view even if this is set to false.
* `diff_context_lines`, defaults to your scrolloff value.
* `entry_format`, defaults to `"state #$ID, $STAT, $TIME""`, which contains the three supported
variables.
* `time_format`, defaults to "" for a timeago-style representation. Can be set to a [Lua date format
string](https://www.lua.org/pil/22.1.html).
* `saved_only`, defaults to false, but can be used to limit shown undo states to those that have
been saved to disk.
Further, the undo telescope should accept any of the usual telescope attributes as well as the
special `theme` key which auto-extends the telescope theme *on top* of any of your explicitly
provided config. Of course, you might also want to remap some of the default keys.
This is what the defaults look like with some additional explanations:
```lua
opts = {
extensions = {
undo = {
use_delta = true,
use_custom_command = nil, -- setting this implies `use_delta = false`. Accepted format is: { "bash", "-c", "echo '$DIFF' | delta" }
side_by_side = false,
diff_context_lines = vim.o.scrolloff,
entry_format = "state #$ID, $STAT, $TIME",
time_format = "",
saved_only = false,
},
},
},
```
The full list will always be available in the code providing the defaults
[here](https://github.com/debugloop/telescope-undo.nvim/blob/main/lua/telescope/_extensions/undo.lua#L6).
My personal recommendation is the following, which maximizes the width of the preview to enable
side-by-side diffs:
```lua
opts = {
extensions = {
undo = {
side_by_side = true,
layout_strategy = "vertical",
layout_config = {
preview_height = 0.8,
},
},
},
}
```
## Mappings
By default, the following mappings are enabled.
```lua
require("telescope").setup({
extensions = {
undo = {
mappings = {
i = {
["<cr>"] = require("telescope-undo.actions").yank_additions,
["<S-cr>"] = require("telescope-undo.actions").yank_deletions,
["<C-cr>"] = require("telescope-undo.actions").restore,
-- alternative defaults, for users whose terminals do questionable things with modified <cr>
["<C-y>"] = require("telescope-undo.actions").yank_deletions,
["<C-r>"] = require("telescope-undo.actions").restore,
},
n = {
["y"] = require("telescope-undo.actions").yank_additions,
["Y"] = require("telescope-undo.actions").yank_deletions,
["u"] = require("telescope-undo.actions").restore,
},
},
},
},
})
```
> [!IMPORTANT]
> Note how above example uses the call to telescope's `setup()`. This is due to the fact that
> directly requiring these actions needs `telescope-undo` to be available already, which it is not
> inside lazy's `opts` key when using above "standalone" spec. See the next example for how to do it
> inside `opts`.
There is one more mapping available, `yank_larger`. This yanks either the additions or the deletions
based on their line count, with the additions winning in case of a tie. This is how you configure
this mapping, or remap any of the default actions for that matter:
```lua
opts = {
extensions = {
undo = {
mappings = {
-- Wrapping the actions inside a function prevents the error due to telescope-undo being not
-- yet loaded.
i = {
["<cr>"] = function(bufnr)
return require("telescope-undo.actions").yank_larger(bufnr)
end,
},
n = {
["y"] = function(bufnr)
return require("telescope-undo.actions").yank_larger(bufnr)
end,
},
},
},
},
}
```
If you wish to disable one of the default mappings, just set it to `false`.
```lua
opts = {
extensions = {
undo = {
mappings = {
i = {
["<C-y>"] = false,
},
},
},
},
}
```
## Contributions
Suggestions, issues and patches are very much welcome. There are some TODOs sprinkeled into the code
that need addressing, but could also use some input and opinions.

View File

@ -0,0 +1,84 @@
local actions = require("telescope.actions")
local actions_state = require("telescope.actions.state")
local function _get_default_register()
local clipboardFlags = vim.split(vim.api.nvim_get_option("clipboard"), ",")
if vim.tbl_contains(clipboardFlags, "unnamedplus") then
return "+"
end
if vim.tbl_contains(clipboardFlags, "unnamed") then
return "*"
end
return '"'
end
-- TODO maybe provide actions for the following:
-- * yank to arbitrary registers
-- * open state in new file
-- * rewind to last saved state
-- * goto lastest undo state
-- * something with git staging?
local myactions = {}
-- these actions are returning named functions with the prompt_bufnr en-closured so that their metatable contains a name that telescope which-key can use
myactions.restore = function(prompt_bufnr)
local function restore()
-- makes the selected undo state the buffers current state
local entry = actions_state.get_selected_entry()
if entry ~= nil then
vim.api.nvim_buf_call(entry.value.bufnr, function()
vim.cmd("undo " .. entry.value.seq)
end)
actions.close(prompt_bufnr)
end
end
return restore
end
myactions.yank_deletions = function(prompt_bufnr)
local function yank_deletions()
-- yanks the deletions from the currently selected undo state into the default register
local entry = actions_state.get_selected_entry()
if entry ~= nil then
vim.fn.setreg(_get_default_register(), entry.value.deletions, (#entry.value.deletions > 1) and "V" or "v")
actions.close(prompt_bufnr)
return entry.value.deletions
end
end
return yank_deletions
end
myactions.yank_additions = function(prompt_bufnr)
local function yank_additions()
-- yanks the additions from the currently selected undo state into the default register
local entry = actions_state.get_selected_entry()
if entry ~= nil then
vim.fn.setreg(_get_default_register(), entry.value.additions, (#entry.value.additions > 1) and "V" or "v")
actions.close(prompt_bufnr)
return entry.value.additions
end
end
return yank_additions
end
myactions.yank_larger = function(prompt_bufnr)
local function yank_larger()
-- yanks the additions from the currently selected undo state into the default register
local entry = actions_state.get_selected_entry()
if entry == nil then
return
end
if #entry.value.additions >= #entry.value.deletions then
vim.fn.setreg(_get_default_register(), entry.value.additions, (#entry.value.additions > 1) and "V" or "v")
actions.close(prompt_bufnr)
return entry.value.additions
else
vim.fn.setreg(_get_default_register(), entry.value.deletions, (#entry.value.deletions > 1) and "V" or "v")
actions.close(prompt_bufnr)
return entry.value.deletions
end
end
return yank_larger
end
return myactions

View File

@ -0,0 +1,172 @@
local finders = require("telescope.finders")
local pickers = require("telescope.pickers")
local conf = require("telescope.config").values
require("telescope-undo.previewer")
require("telescope-undo.actions")
require("telescope-undo.lua-timeago")
local function _traverse_undotree(opts, entries, level)
local undolist = {}
-- create diffs for each entry in our undotree
for i = #entries, 1, -1 do
if opts.saved_only ~= nil and opts.saved_only and entries[i].save == nil then
goto continue
end
-- grab the buffer as it is after this iteration's undo state
vim.cmd("silent undo " .. entries[i].seq)
local buffer_after_lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) or {}
local buffer_after = table.concat(buffer_after_lines, "\n")
-- grab the buffer as it is after this undo state's parent
vim.cmd("silent undo")
local buffer_before_lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) or {}
local buffer_before = table.concat(buffer_before_lines, "\n")
-- build diff header so that delta can go ahead and syntax highlight
local filename = vim.fn.expand("%")
local header = filename .. "\n--- " .. filename .. "\n+++ " .. filename .. "\n"
-- do the diff using our internal diff function
local diff = vim.diff(buffer_before, buffer_after, {
algorithm = "patience",
ctxlen = opts.diff_context_lines or 0,
})
-- extract data for yanking and searching
local ordinal = ""
local additions = {}
local deletions = {}
for line in (diff .. "\n"):gmatch("(.-)\n") do
if line:sub(1, 1) == "+" then
local content = line:sub(2, -1)
table.insert(additions, content)
ordinal = ordinal .. content
elseif line:sub(1, 1) == "-" then
local content = line:sub(2, -1)
table.insert(deletions, content)
ordinal = ordinal .. content
end
end
-- use the data we just created to feed into our finder later
table.insert(undolist, {
seq = entries[i].seq, -- save state number, used in display and to restore
alt = level, -- current level, i.e. how deep into alt branches are we, used to graph
first = i == #entries, -- whether this is the first node in this branch, used to graph
time = entries[i].time, -- save state time, used in display
ordinal = ordinal, -- a long string of all additions and deletions, used for search
diff = header .. diff, -- the proper diff, used for preview
additions = additions, -- all additions, used to yank a result
deletions = deletions, -- all deletions, used to yank a result
bufnr = vim.api.nvim_get_current_buf(), -- for which buffer this telescope was invoked, used to restore
})
-- descend recursively into alternate histories of undo states
if entries[i].alt ~= nil then
local alt_undolist = _traverse_undotree(opts, entries[i].alt, level + 1)
-- pretend these results are our results
for _, elem in pairs(alt_undolist) do
table.insert(undolist, elem)
end
end
::continue::
end
return undolist
end
local function build_undolist(opts)
-- save our current cursor
local cursor = vim.api.nvim_win_get_cursor(0)
-- get all diffs
local ut = vim.fn.undotree()
-- TODO: maybe use this opportunity to limit the number of root nodes we process overall, to ensure good performance
local undolist = _traverse_undotree(opts, ut.entries, 0)
-- restore everything after all diffs have been created
-- BUG: `gi` (last insert location) is being killed by our method, we should save that as well
vim.cmd("silent undo " .. ut.seq_cur)
vim.api.nvim_win_set_cursor(0, cursor)
return undolist
end
local M = {}
M.undo = function(opts)
if not vim.api.nvim_buf_get_option(0, "modifiable") then
print("telescope-undo.nvim: Current buffer is not modifiable.")
return
end
opts = opts or {}
pickers
.new(opts, {
prompt_title = "Undo History",
finder = finders.new_table({
results = build_undolist(opts),
entry_maker = function(undo)
local order = require("telescope.config").values.sorting_strategy
-- TODO: show a table instead of a list
if #undo.additions + #undo.deletions == 0 then
-- skip empty changes, vim has these sometimes...
return nil
end
-- the following prefix should work out to this graph structure:
-- state #1
-- └─state #2
-- state #3
-- ├─state #4
-- └─state #5
-- state #6
-- ├─state #7
-- ┆ ├─state #8
-- ┆ └─state #9
-- └─state #10
local prefix = ""
if undo.alt > 0 then
prefix = string.rep("", undo.alt - 1)
if undo.first then
local corner = order == "ascending" and "" or ""
prefix = prefix .. corner .. ""
else
prefix = prefix .. "├╴"
end
end
local diffstat = ""
if #undo.additions > 0 then
diffstat = "+" .. #undo.additions
end
if #undo.deletions > 0 then
if diffstat ~= "" then
diffstat = diffstat .. " "
end
diffstat = "-" .. #undo.deletions
end
local formatted_time = opts.time_format == "" and timeago(undo.time) or os.date(opts.time_format, undo.time)
return {
value = undo,
display = prefix
.. opts.entry_format:gsub("$ID", undo.seq):gsub("$STAT", diffstat):gsub("$TIME", formatted_time),
ordinal = undo.ordinal,
}
end,
}),
previewer = get_previewer(opts),
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr, map)
for _, mode in pairs({ "i", "n" }) do
for key, get_action in pairs(opts.mappings[mode] or {}) do
map(mode, key, get_action(prompt_bufnr))
end
end
-- TODO: provide means to filter for time frames
return true -- include defaults as well
end,
})
:find()
end
return M

View File

@ -0,0 +1,72 @@
-- This file is subject to LGPL-2.1 and installed from:
-- https://github.com/f-person/lua-timeago
--
-- TODO: Understand lua require weirdness and properly include this as a git submodule
local language = {
justnow = "just now",
minute = { singular = "a minute ago", plural = "minutes ago" },
hour = { singular = "an hour ago", plural = "hours ago" },
day = { singular = "a day ago", plural = "days ago" },
week = { singular = "a week ago", plural = "weeks ago" },
month = { singular = "a month ago", plural = "months ago" },
year = { singular = "a year ago", plural = "years ago" },
}
local function round(num)
return math.floor(num + 0.5)
end
function timeago(time)
local now = os.time()
local diff_seconds = os.difftime(now, time)
if diff_seconds < 45 then
return language.justnow
end
local diff_minutes = diff_seconds / 60
if diff_minutes < 1.5 then
return language.minute.singular
end
if diff_minutes < 59.5 then
return round(diff_minutes) .. " " .. language.minute.plural
end
local diff_hours = diff_minutes / 60
if diff_hours < 1.5 then
return language.hour.singular
end
if diff_hours < 23.5 then
return round(diff_hours) .. " " .. language.hour.plural
end
local diff_days = diff_hours / 24
if diff_days < 1.5 then
return language.day.singular
end
if diff_days < 7.5 then
return round(diff_days) .. " " .. language.day.plural
end
local diff_weeks = diff_days / 7
if diff_weeks < 1.5 then
return language.week.singular
end
if diff_weeks < 4.5 then
return round(diff_weeks) .. " " .. language.week.plural
end
local diff_months = diff_days / 30
if diff_months < 1.5 then
return language.month.singular
end
if diff_months < 11.5 then
return round(diff_months) .. " " .. language.month.plural
end
local diff_years = diff_days / 365.25
if diff_years < 1.5 then
return language.year.singular
end
return round(diff_years) .. " " .. language.year.plural
end

View File

@ -0,0 +1,57 @@
local previewers = require("telescope.previewers")
local is_wsl = (function()
local output = vim.fn.systemlist("uname -r")
return not not string.find(output[1] or "", "WSL")
end)()
function get_previewer(opts)
if opts.use_custom_command ~= nil then
return previewers.new_termopen_previewer({
get_command = function(entry, status)
local difftext = entry.value.diff:gsub("'", [['"'"']])
local shlexed = {}
for i, part in ipairs(opts.use_custom_command) do
shlexed[i] = part:gsub("$DIFF", difftext)
end
return shlexed
end,
})
end
local has_powershell = vim.fn.executable("powershell") == 1
local has_bash = vim.fn.executable("bash") == 1
if opts.use_delta and not is_wsl and (has_powershell or has_bash) and vim.fn.executable("delta") == 1 then
return previewers.new_termopen_previewer({
get_command = function(entry, status)
local append = ""
if opts.side_by_side == true then
append = append .. " -s"
end
if has_powershell then
return {
"powershell",
"-Command",
"echo '" .. entry.value.diff:gsub([[']], [['']]) .. "' | delta" .. append,
}
elseif has_bash then
return {
"bash",
"-c",
"echo '" .. entry.value.diff:gsub("'", [['"'"']]) .. "' | delta" .. append,
-- HACK: check out this escape method -----^
}
end
end,
})
else
return previewers.new_buffer_previewer({
-- this is not the prettiest preview...
define_preview = function(self, entry, status)
vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, true, vim.split(entry.value.diff, "\n"))
require("telescope.previewers.utils").highlighter(
self.state.bufnr,
"diff",
{ preview = { treesitter = { enable = {} } } }
)
end,
})
end
end

View File

@ -0,0 +1,57 @@
local has_telescope, telescope = pcall(require, "telescope")
if not has_telescope then
error("telescope_undo.nvim requires telescope.nvim - https://github.com/nvim-telescope/telescope.nvim")
end
-- full list of available config items and their defaults
local defaults = {
use_delta = true,
use_custom_command = nil, -- should be in this format: { "bash", "-c", "echo '$DIFF' | delta" }
side_by_side = false,
diff_context_lines = vim.o.scrolloff,
entry_format = "state #$ID, $STAT, $TIME",
time_format = "",
saved_only = false,
mappings = {
i = {
["<cr>"] = require("telescope-undo.actions").yank_additions,
["<S-cr>"] = require("telescope-undo.actions").yank_deletions,
["<C-cr>"] = require("telescope-undo.actions").restore,
-- alternative defaults, for users whose terminals do questionable things with modified <cr>
["<C-y>"] = require("telescope-undo.actions").yank_deletions,
["<C-r>"] = require("telescope-undo.actions").restore,
},
n = {
["y"] = require("telescope-undo.actions").yank_additions,
["Y"] = require("telescope-undo.actions").yank_deletions,
["u"] = require("telescope-undo.actions").restore,
},
},
}
local M = {
exports = {},
}
M.exports.undo = function(config)
config = vim.tbl_deep_extend("force", M.config, config or {})
if config.theme then
config = require("telescope.themes")["get_" .. config.theme](config)
end
require("telescope-undo").undo(config)
end
M.setup = function(extension_config, telescope_config)
M.config = vim.tbl_deep_extend("force", defaults, extension_config)
-- Remove default keymaps that have been disabled by the user.
for _, mode in ipairs({ "i", "n" }) do
M.config.mappings[mode] = vim.tbl_map(function(val)
return val ~= false and val or nil
end, M.config.mappings[mode])
end
if M.config["side_by_side"] and not M.config["use_delta"] then
error("telescope_undo.nvim: setting side_by_side but not use_delta will have no effect")
end
end
return telescope.register_extension(M)

View File

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