nvim windows support + multicursors
This commit is contained in:
1 parent
b6968a10b3
commit
93c97e65e2
10 files changed
+778
-24
No files matched your search
+20
-13
@@ -113,19 +113,26 @@ vim.api.nvim_create_autocmd("FileType", {
|
||||
})
|
||||
|
||||
-- SSH Clipboard Support (OSC 52)
|
||||
vim.g.clipboard = {
|
||||
name = 'OSC 52',
|
||||
copy = {
|
||||
['+'] = require('vim.ui.clipboard.osc52').copy('+'),
|
||||
['*'] = require('vim.ui.clipboard.osc52').copy('*'),
|
||||
},
|
||||
paste = {
|
||||
-- We now return BOTH the text and the register type ('v', 'V', or '^V')
|
||||
-- This restores native p and P line-wise behavior
|
||||
['+'] = function() return { vim.fn.getreg('"', 1, true), vim.fn.getregtype('"') } end,
|
||||
['*'] = function() return { vim.fn.getreg('"', 1, true), vim.fn.getregtype('"') } end,
|
||||
},
|
||||
}
|
||||
-- Skipped on native Windows: Neovim's own clipboard provider (win32yank,
|
||||
-- bundled with the Windows builds) works there for both the terminal and
|
||||
-- Neovide, whereas OSC 52 can't work at all in Neovide (it isn't a
|
||||
-- terminal). Over SSH you'd be running the Linux config on the remote
|
||||
-- machine anyway.
|
||||
if vim.fn.has('win32') == 0 then
|
||||
vim.g.clipboard = {
|
||||
name = 'OSC 52',
|
||||
copy = {
|
||||
['+'] = require('vim.ui.clipboard.osc52').copy('+'),
|
||||
['*'] = require('vim.ui.clipboard.osc52').copy('*'),
|
||||
},
|
||||
paste = {
|
||||
-- We now return BOTH the text and the register type ('v', 'V', or '^V')
|
||||
-- This restores native p and P line-wise behavior
|
||||
['+'] = function() return { vim.fn.getreg('"', 1, true), vim.fn.getregtype('"') } end,
|
||||
['*'] = function() return { vim.fn.getreg('"', 1, true), vim.fn.getregtype('"') } end,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
-- GENERAL KEYMAPS --
|
||||
|
||||
|
||||
@@ -82,6 +82,9 @@ local function shared_lib_ext()
|
||||
end
|
||||
return '.so'
|
||||
end
|
||||
local function exe_ext()
|
||||
return vim.loop.os_uname().sysname == 'Windows_NT' and '.exe' or ''
|
||||
end
|
||||
local function fixture_lib_path()
|
||||
return build_dir() .. '/tests/' .. shared_lib_prefix() .. 'dynlib_test_fixture' .. shared_lib_ext()
|
||||
end
|
||||
@@ -97,7 +100,7 @@ local configurations = {
|
||||
type = 'codelldb',
|
||||
request = 'launch',
|
||||
program = function()
|
||||
return build_dir() .. '/tests/test_dynamic_library'
|
||||
return build_dir() .. '/tests/test_dynamic_library' .. exe_ext()
|
||||
end,
|
||||
args = function()
|
||||
return { fixture_lib_path() }
|
||||
@@ -112,7 +115,7 @@ local configurations = {
|
||||
type = 'codelldb',
|
||||
request = 'launch',
|
||||
program = function()
|
||||
return build_dir() .. '/demo/example_host'
|
||||
return build_dir() .. '/demo/example_host' .. exe_ext()
|
||||
end,
|
||||
args = function()
|
||||
return { demo_plugin_path() }
|
||||
@@ -127,7 +130,7 @@ local configurations = {
|
||||
type = 'codelldb',
|
||||
request = 'launch',
|
||||
program = function()
|
||||
return build_dir() .. '/demo/example_host'
|
||||
return build_dir() .. '/demo/example_host' .. exe_ext()
|
||||
end,
|
||||
args = function()
|
||||
local path = vim.fn.input('Plugin path: ', demo_plugin_path(), 'file')
|
||||
|
||||
@@ -23,7 +23,7 @@ return {
|
||||
dashboard.button("r", " Recent Files", "<cmd>Telescope oldfiles<CR>"),
|
||||
dashboard.button("w", " Live Grep", "<cmd>Telescope live_grep<CR>"),
|
||||
dashboard.button("e", " New File", "<cmd>ene<CR>"),
|
||||
dashboard.button("c", " Edit Config", "<cmd>edit ~/.config/nvim/init.lua<CR>"),
|
||||
dashboard.button("c", " Edit Config", "<cmd>edit " .. vim.fn.fnameescape(vim.fs.normalize(vim.fn.stdpath("config")) .. "/init.lua") .. "<CR>"),
|
||||
dashboard.button("q", " Quit", "<cmd>qa<CR>"),
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +62,16 @@ return {
|
||||
-- plain text in connections.json here, password included -- leave the
|
||||
-- password out of the URL and put it in ~/.my.cnf's [client] section
|
||||
-- if that bothers you (the mariadb client reads it from there).
|
||||
-- (On Windows that means %LOCALAPPDATA%\db_ui -- Neovim itself uses
|
||||
-- %LOCALAPPDATA%\nvim and %LOCALAPPDATA%\nvim-data there, so it's
|
||||
-- outside both of those too.)
|
||||
local data_home = vim.env.XDG_DATA_HOME
|
||||
if not data_home or data_home == "" then
|
||||
data_home = vim.env.HOME .. "/.local/share"
|
||||
if vim.fn.has("win32") == 1 then
|
||||
data_home = vim.env.LOCALAPPDATA or (vim.env.USERPROFILE .. "\\AppData\\Local")
|
||||
else
|
||||
data_home = vim.env.HOME .. "/.local/share"
|
||||
end
|
||||
end
|
||||
vim.g.db_ui_save_location = data_home .. "/db_ui"
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
return {
|
||||
-- Multiple cursors (multicursor.nvim). Add cursors, then use Vim
|
||||
-- normally -- motions, operators, insert mode, macros and undo all act
|
||||
-- on every cursor at once. Esc collapses back to one cursor.
|
||||
--
|
||||
-- The key layout below deliberately differs from the plugin's README
|
||||
-- example, which would collide with this config: <leader>n/s/S/x clash
|
||||
-- with the <leader>s* "Splits" group, and bare <Up>/<Down> are normal
|
||||
-- cursor movement. Instead, the everyday actions sit on Ctrl keys
|
||||
-- (VS Code-style), and the rest live under a <leader>m "Multicursor"
|
||||
-- group (registered in which-key.lua) so they show up in the popup.
|
||||
--
|
||||
-- <leader>m is NOT also bound to the plugin's own `operator` action
|
||||
-- (which its README suggests) -- that would make every <leader>m...
|
||||
-- key ambiguous. `ga{motion}` (below) covers the same ground.
|
||||
{
|
||||
"jake-stewart/multicursor.nvim",
|
||||
branch = "1.0",
|
||||
event = "VeryLazy",
|
||||
config = function()
|
||||
local mc = require("multicursor-nvim")
|
||||
mc.setup()
|
||||
|
||||
local set = vim.keymap.set
|
||||
|
||||
-- Add cursors: above / below the main cursor.
|
||||
set({ "n", "x" }, "<C-Up>", function() mc.lineAddCursor(-1) end, { desc = "Add cursor above" })
|
||||
set({ "n", "x" }, "<C-Down>", function() mc.lineAddCursor(1) end, { desc = "Add cursor below" })
|
||||
|
||||
-- Add cursors: at the next / previous match of the word under the
|
||||
-- cursor, or of the visual selection (like Ctrl+D in VS Code).
|
||||
set({ "n", "x" }, "<C-n>", function() mc.matchAddCursor(1) end, { desc = "Add cursor at next match" })
|
||||
set({ "n", "x" }, "<C-p>", function() mc.matchAddCursor(-1) end, { desc = "Add cursor at previous match" })
|
||||
|
||||
-- Add cursors with the mouse: Ctrl+click adds or removes one, and
|
||||
-- Ctrl+drag adds a column of them. (If your terminal swallows
|
||||
-- Ctrl+click, use <C-q> below instead.)
|
||||
set("n", "<C-LeftMouse>", mc.handleMouse, { desc = "Add/remove cursor" })
|
||||
set("n", "<C-LeftDrag>", mc.handleMouseDrag)
|
||||
set("n", "<C-LeftRelease>", mc.handleMouseRelease)
|
||||
|
||||
-- Disable the cursors so only the main one moves; while disabled,
|
||||
-- pressing this again drops a cursor at the main cursor's position.
|
||||
-- Move, press, move, press... places cursors anywhere. <Esc>
|
||||
-- re-enables them. (Shadows Neovim's <C-q> alias for <C-v>;
|
||||
-- <C-v> itself is untouched.)
|
||||
set({ "n", "x" }, "<C-q>", mc.toggleCursor, { desc = "Toggle cursor (place / disable)" })
|
||||
|
||||
-- `gaip` adds a cursor on every line of a paragraph (any motion or
|
||||
-- text object works); in Visual mode, on every selected line.
|
||||
set({ "n", "x" }, "ga", mc.addCursorOperator, { desc = "Add cursors over motion" })
|
||||
|
||||
-- Visual mode: insert at the start / append at the end of every
|
||||
-- selected line, like a block-selection I/A but for any selection.
|
||||
set("x", "I", mc.insertVisual, { desc = "Insert on each selected line" })
|
||||
set("x", "A", mc.appendVisual, { desc = "Append on each selected line" })
|
||||
|
||||
-- <leader>m group (see which-key.lua).
|
||||
set({ "n", "x" }, "<leader>ms", function() mc.matchSkipCursor(1) end, { desc = "Skip next match" })
|
||||
set({ "n", "x" }, "<leader>mS", function() mc.matchSkipCursor(-1) end, { desc = "Skip previous match" })
|
||||
set({ "n", "x" }, "<leader>mj", function() mc.lineSkipCursor(1) end, { desc = "Skip line below" })
|
||||
set({ "n", "x" }, "<leader>mk", function() mc.lineSkipCursor(-1) end, { desc = "Skip line above" })
|
||||
set({ "n", "x" }, "<leader>ma", mc.matchAllAddCursors, { desc = "Add cursors at ALL matches" })
|
||||
set("n", "<leader>mr", mc.restoreCursors, { desc = "Restore cleared cursors" })
|
||||
|
||||
-- Mappings in a keymap layer only exist while there is more than
|
||||
-- one cursor, so they can overlap with ordinary mappings.
|
||||
mc.addKeymapLayer(function(layerSet)
|
||||
-- Make a different cursor the main one.
|
||||
layerSet({ "n", "x" }, "<leader>mh", mc.prevCursor, { desc = "Previous cursor" })
|
||||
layerSet({ "n", "x" }, "<leader>ml", mc.nextCursor, { desc = "Next cursor" })
|
||||
|
||||
-- Drop the main cursor, keeping the rest.
|
||||
layerSet({ "n", "x" }, "<leader>mx", mc.deleteCursor, { desc = "Delete main cursor" })
|
||||
|
||||
-- Treat all the cursors as one sequence: 1, 2, 3, ... down the
|
||||
-- column. Kept in the layer so Vim's own Visual-mode g<C-a> /
|
||||
-- g<C-x> are untouched when there is only one cursor.
|
||||
layerSet({ "n", "x" }, "g<C-a>", mc.sequenceIncrement, { desc = "Increment as sequence" })
|
||||
layerSet({ "n", "x" }, "g<C-x>", mc.sequenceDecrement, { desc = "Decrement as sequence" })
|
||||
|
||||
-- Esc: re-enable disabled cursors, otherwise collapse to one. This
|
||||
-- shadows the global <Esc> (clear search highlight) while the
|
||||
-- layer is active, so it does that too.
|
||||
layerSet("n", "<Esc>", function()
|
||||
vim.cmd.nohlsearch()
|
||||
if not mc.cursorsEnabled() then
|
||||
mc.enableCursors()
|
||||
else
|
||||
mc.clearCursors()
|
||||
end
|
||||
end, { desc = "Collapse cursors" })
|
||||
end)
|
||||
|
||||
-- Cursor look. `reverse` stays visible on any background (this
|
||||
-- theme is transparent in the terminal), and a theme change would
|
||||
-- otherwise wipe these, so they're re-applied on ColorScheme.
|
||||
local function set_highlights()
|
||||
local hl = vim.api.nvim_set_hl
|
||||
hl(0, "MultiCursorCursor", { reverse = true })
|
||||
hl(0, "MultiCursorVisual", { link = "Visual" })
|
||||
hl(0, "MultiCursorSign", { link = "SignColumn" })
|
||||
hl(0, "MultiCursorMatchPreview", { link = "Search" })
|
||||
hl(0, "MultiCursorDisabledCursor", { reverse = true })
|
||||
hl(0, "MultiCursorDisabledVisual", { link = "Visual" })
|
||||
hl(0, "MultiCursorDisabledSign", { link = "SignColumn" })
|
||||
end
|
||||
set_highlights()
|
||||
vim.api.nvim_create_autocmd("ColorScheme", { callback = set_highlights })
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -1,3 +1,48 @@
|
||||
-- Recursive copy used by the gM mapping below. Unix keeps using `cp -r`
|
||||
-- (unchanged behavior); Windows has no `cp`, so it gets an equivalent
|
||||
-- written against libuv. One difference there: if the destination
|
||||
-- directory already exists, contents are merged into it rather than the
|
||||
-- source being nested inside it, which is what `cp -r` would do.
|
||||
-- Returns true on success, or false plus an error message.
|
||||
local function copy_path(src, dest)
|
||||
if vim.fn.has("win32") == 0 then
|
||||
local result = vim.fn.system({ "cp", "-r", src, dest })
|
||||
return vim.v.shell_error == 0, result
|
||||
end
|
||||
|
||||
local uv = vim.uv or vim.loop
|
||||
local function copy(s, d)
|
||||
local stat = uv.fs_stat(s)
|
||||
if not stat then
|
||||
return false, "no such file or directory: " .. s
|
||||
end
|
||||
if stat.type == "directory" then
|
||||
local made, mkerr = uv.fs_mkdir(d, 493) -- 0755
|
||||
if not made then
|
||||
local existing = uv.fs_stat(d)
|
||||
if not (existing and existing.type == "directory") then
|
||||
return false, mkerr
|
||||
end
|
||||
end
|
||||
local handle = uv.fs_scandir(s)
|
||||
while handle do
|
||||
local name = uv.fs_scandir_next(handle)
|
||||
if not name then
|
||||
break
|
||||
end
|
||||
local ok, err = copy(s .. "/" .. name, d .. "/" .. name)
|
||||
if not ok then
|
||||
return false, err
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
local ok, err = uv.fs_copyfile(s, d)
|
||||
return ok and true or false, err
|
||||
end
|
||||
return copy(src, dest)
|
||||
end
|
||||
|
||||
return {
|
||||
-- NvimTree (On the right)
|
||||
{
|
||||
@@ -198,9 +243,9 @@ return {
|
||||
-- instead of surfacing cp's raw "same file" error.
|
||||
vim.notify("Skipped " .. base .. ": pattern didn't match, and destination is the same as source", vim.log.levels.WARN)
|
||||
else
|
||||
local result = vim.fn.system({ "cp", "-r", node.absolute_path, dest_path })
|
||||
if vim.v.shell_error ~= 0 then
|
||||
vim.notify("Copy failed for " .. base .. ": " .. result, vim.log.levels.ERROR)
|
||||
local copied, result = copy_path(node.absolute_path, dest_path)
|
||||
if not copied then
|
||||
vim.notify("Copy failed for " .. base .. ": " .. tostring(result), vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,8 +9,18 @@ return {
|
||||
-- built in (paths, directory contents, and history) with zero
|
||||
-- config -- accept with -> or <End>. This only affects terminals
|
||||
-- opened from Neovim; your system login shell is untouched.
|
||||
--
|
||||
-- Windows: fish has no native Windows build, so the terminal
|
||||
-- launches PowerShell 7 (pwsh) instead -- it has the same kind of
|
||||
-- grey inline prediction (PSReadLine, from command history) on by
|
||||
-- default -- falling back to Windows PowerShell 5.1 if pwsh isn't
|
||||
-- installed. setup_neovim.ps1 installs pwsh.
|
||||
local shell = "fish"
|
||||
if vim.fn.has("win32") == 1 then
|
||||
shell = vim.fn.executable("pwsh") == 1 and "pwsh" or "powershell"
|
||||
end
|
||||
require("toggleterm").setup({
|
||||
shell = "fish",
|
||||
shell = shell,
|
||||
})
|
||||
vim.keymap.set('n', '<leader>tf', '<cmd>ToggleTerm direction=float<cr>', { desc = "Floating Terminal" })
|
||||
vim.keymap.set('n', '<leader>th', '<cmd>ToggleTerm direction=horizontal<cr>', { desc = "Bottom Terminal" })
|
||||
|
||||
@@ -14,6 +14,7 @@ return {
|
||||
{ "<leader>c", group = "Comments" },
|
||||
{ "<leader>f", group = "Find / Grep" },
|
||||
{ "<leader>l", group = "LSP" },
|
||||
{ "<leader>m", group = "Multicursor" },
|
||||
{ "<leader>o", group = "OOP" },
|
||||
{ "<leader>s", group = "Splits" },
|
||||
{ "<leader>t", group = "Terminal" },
|
||||
|
||||
Reference in new issue
Block a user