yank_notification: show line numbers. Clipboard copy notification to have line counts. Fix: Paste clipboard over selection

This commit is contained in:
psychhim
2025-10-09 03:26:44 +05:30
parent 7c56ba0821
commit 009b3aa8c0
4 changed files with 70 additions and 17 deletions

View File

@@ -1,6 +1,9 @@
vim.g.mapleader = ' ' vim.g.mapleader = ' '
vim.g.maplocalleader = ' ' vim.g.maplocalleader = ' '
-- Load yank notification with line counts
require 'yank_notification'
-- [[ Install `lazy.nvim` plugin manager ]] -- [[ Install `lazy.nvim` plugin manager ]]
-- https://github.com/folke/lazy.nvim -- https://github.com/folke/lazy.nvim
-- `:help lazy.nvim.txt` for more info -- `:help lazy.nvim.txt` for more info

View File

@@ -1,10 +1,17 @@
local M = {} local M = {}
function M.trim_clipboard() function M.trim_clipboard()
-- Get the content of the '+' register
local content = vim.fn.getreg '+' local content = vim.fn.getreg '+'
-- Remove single trailing newline if present -- Remove single trailing newline if present
content = content:gsub('\n$', '') content = content:gsub('\n$', '')
-- Update '+' and '*' registers
vim.fn.setreg('+', content) vim.fn.setreg('+', content)
vim.fn.setreg('*', content) vim.fn.setreg('*', content)
vim.notify('Copied selection to clipboard', vim.log.levels.INFO) -- Count the number of lines copied
local line_count = select(2, content:gsub('\n', '')) + 1 -- Number of newlines + 1
-- Notification with line count
local plural = line_count == 1 and '' or 's'
vim.notify(string.format('Copied %d line%s to clipboard', line_count, plural), vim.log.levels.INFO)
end end
return M return M

View File

@@ -165,39 +165,59 @@ vim.keymap.set('x', 'Y', [["+y<esc>:lua require("copy_to_clipboard_fix").trim_cl
-- [[ Paste from clipboard with line count ]] -- [[ Paste from clipboard with line count ]]
local function paste_from_clipboard() local function paste_from_clipboard()
-- Get clipboard lines
local lines = vim.fn.getreg('+', 1, true) local lines = vim.fn.getreg('+', 1, true)
local line_count = #lines
if vim.tbl_isempty(lines) then if vim.tbl_isempty(lines) then
return return
end end
local line_count = #lines
local mode = vim.fn.mode() local mode = vim.fn.mode()
if mode == 'v' or mode == 'V' or mode == '\22' then if mode == 'v' or mode == 'V' or mode == '\22' then
local selection_linewise = (mode == 'V') -- Visual mode: replace selection with clipboard
-- Force register type local start_line = vim.fn.line 'v'
if selection_linewise and #lines == 1 then local start_col = vim.fn.col 'v'
-- Make clipboard linewise to force newline after paste local end_line = vim.fn.line '.'
vim.fn.setreg('+', table.concat(lines, '\n'), 'l') local end_col = vim.fn.col '.'
else if start_line > end_line or (start_line == end_line and start_col > end_col) then
-- Otherwise characterwise is fine start_line, end_line = end_line, start_line
vim.fn.setreg('+', table.concat(lines, '\n'), 'c') start_col, end_col = end_col, start_col
end end
-- Delete selection without affecting clipboard -- Determine register type
local reg_type
if #lines > 1 or (end_line - start_line + 1) > 1 then
reg_type = 'l' -- linewise
else
reg_type = 'c' -- characterwise
end
vim.fn.setreg('"', vim.fn.getreg '+', reg_type)
-- Delete selection into blackhole and paste from unnamed (clipboard)
vim.cmd 'normal! "_dP' vim.cmd 'normal! "_dP'
-- Move cursor to end of pasted text -- Move cursor to end of pasted text
vim.cmd 'normal! `]' local buf = vim.api.nvim_get_current_buf()
local last_line = start_line + #lines - 1
local last_col
if reg_type == 'l' then
local line_content = vim.api.nvim_buf_get_lines(buf, last_line - 1, last_line, false)[1]
last_col = #line_content
else
local first_line = vim.api.nvim_buf_get_lines(buf, start_line - 1, start_line, false)[1]
last_col = start_col - 1 + #lines[1]
end
vim.api.nvim_win_set_cursor(0, { last_line, last_col })
-- Exit visual mode -- Exit visual mode
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Esc>', true, false, true), 'n', true) vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Esc>', true, false, true), 'n', true)
else else
-- Normal mode: paste before cursor -- Normal mode: paste before cursor
vim.api.nvim_put(lines, 'c', false, true) vim.api.nvim_put(lines, 'c', false, true)
end end
-- Notify with line count -- Notify line count
vim.schedule(function() vim.defer_fn(function()
vim.notify(line_count .. ' line' .. (line_count > 1 and 's' or '') .. ' pasted from clipboard', vim.log.levels.INFO) local plural = line_count > 1 and 's' or ''
end) vim.notify(line_count .. ' line' .. plural .. ' pasted from clipboard', vim.log.levels.INFO)
end, 0)
end end
vim.keymap.set('n', '<leader>P', paste_from_clipboard, { desc = 'Paste from clipboard before cursor' }) vim.keymap.set('n', '<leader>P', paste_from_clipboard, { desc = 'Paste from clipboard before cursor' })
vim.keymap.set('x', '<leader>P', paste_from_clipboard, { desc = 'Paste from clipboard over selection' }) vim.keymap.set('x', '<leader>P', paste_from_clipboard, { desc = 'Paste clipboard over selection' })
-- [[ Paste Neovim yanks ]] -- [[ Paste Neovim yanks ]]
-- In Normal Mode before cursor inline -- In Normal Mode before cursor inline

23
lua/yank_notification.lua Normal file
View File

@@ -0,0 +1,23 @@
local M = {}
vim.api.nvim_create_autocmd('TextYankPost', {
pattern = '*',
callback = function()
local content = vim.fn.getreg '"'
if not content or content == '' then
return
end
-- Split by newline
local lines = vim.split(content, '\n', true)
-- Remove trailing empty line if present
if lines[#lines] == '' then
table.remove(lines, #lines)
end
local line_count = #lines
vim.schedule(function()
local plural = line_count == 1 and '' or 's'
vim.notify(string.format('Yanked %d line%s', line_count, plural), vim.log.levels.INFO)
end)
end,
})
return M