Compare commits

...

13 Commits

Author SHA1 Message Date
hyzen
8e0d7b2eec Fix: alpha not showed in new tabs if nvim started with a filename in command, i.e nvim file.txt 2026-07-01 04:07:02 +05:30
hyzen
38afffe094 Fix: replace_with_custom_snippets.lua breaking the original repo folder 2026-06-30 16:41:06 +05:30
hyzen
a33b196aca Fix: comment on tabs over spaces 2026-06-29 14:17:50 +05:30
hyzen
af8e71910c Fix: LuaSnip dependency block 2026-06-29 14:13:26 +05:30
hyzen
7df4ce3c03 Update: replace_snippets wait 2026-06-28 23:10:57 +05:30
hyzen
602735a0f4 Fix: update_kickestend.lua origin check for local commits 2026-06-28 23:05:50 +05:30
hyzen
0e08afd339 Update: which-key healthcheck notification 2026-06-28 22:58:53 +05:30
hyzen
25f8a5cd15 Fix: tabline 2026-06-28 22:05:14 +05:30
hyzen
cc449aec74 Remove: dead code 2026-06-28 21:55:35 +05:30
hyzen
5f8e087d8a Fix: buffer_deleted.lua 2026-06-28 21:30:55 +05:30
hyzen
bbc14c3c9d Fix: double q exit visual mode 2026-06-28 21:05:35 +05:30
hyzen
fbf75ac3ed Remove: dead code 2026-06-27 20:48:34 +05:30
hyzen
e713e93426 Update: alpha opens in every new tab 2026-06-27 20:41:58 +05:30
10 changed files with 149 additions and 131 deletions

View File

@@ -8,9 +8,6 @@ vim.g.loaded_netrwPlugin = 1
-- keymaps.lua -- keymaps.lua
require 'keymaps' require 'keymaps'
-- Copy custom snippets from custom_friendly_snippets folder
require 'replace_with_custom_snippets'
-- :UpdateKickestEnd command to safely update KickestEnd.nvim config from origin/master -- :UpdateKickestEnd command to safely update KickestEnd.nvim config from origin/master
require 'update_kickestend' require 'update_kickestend'
@@ -39,14 +36,14 @@ vim.opt.rtp:prepend(lazypath)
-- You can also configure plugins after the setup call, -- You can also configure plugins after the setup call,
-- as they will be available in your neovim runtime. -- as they will be available in your neovim runtime.
-- Disables which-key healthcheck notifications -- Disables which-key healthcheck notification
do do
local orig_notify = vim.notify local orig_notify = vim.notify
vim.notify = function(msg, ...) vim.notify = function(msg, level, ...)
if type(msg) == 'string' and msg:match 'which%-key' then if type(msg) == 'string' and msg:match 'issues reported with your' and msg:match 'which%-key' then
return -- ignore WhichKey health messages return
end end
return orig_notify(msg, ...) return orig_notify(msg, level, ...)
end end
end end
@@ -138,8 +135,7 @@ require('lazy').setup({
event = 'InsertEnter', event = 'InsertEnter',
dependencies = { dependencies = {
-- Snippet Engine & its associated nvim-cmp source -- Snippet Engine & its associated nvim-cmp source
'L3MON4D3/LuaSnip', { 'L3MON4D3/LuaSnip', dependencies = { 'rafamadriz/friendly-snippets' } },
dependencies = { 'rafamadriz/friendly-snippets' },
'saadparwaiz1/cmp_luasnip', 'saadparwaiz1/cmp_luasnip',
-- Adds LSP completion capabilities -- Adds LSP completion capabilities
'hrsh7th/cmp-nvim-lsp', 'hrsh7th/cmp-nvim-lsp',
@@ -326,7 +322,7 @@ vim.o.completeopt = 'menuone,noselect'
vim.o.termguicolors = true vim.o.termguicolors = true
-- Tabs and indentation -- Tabs and indentation
vim.o.expandtab = false -- use spaces instead of tabs vim.o.expandtab = false -- use tabs instead of spaces
vim.o.shiftwidth = 4 -- number of spaces for autoindent vim.o.shiftwidth = 4 -- number of spaces for autoindent
vim.o.softtabstop = 0 -- number of spaces per Tab in insert mode vim.o.softtabstop = 0 -- number of spaces per Tab in insert mode
vim.o.tabstop = 4 -- number of spaces a Tab counts for vim.o.tabstop = 4 -- number of spaces a Tab counts for

View File

@@ -1,7 +1,45 @@
-- Manages Alpha refresh when switching and preserves ASCII art -- Manages Alpha refresh when switching and preserves ASCII art
-- Temporarily unlist other buffers so alpha.start(true) isn't skipped
-- when other tabs have real files open, then restore them after.
-- Also bypass argc()>0, which alpha's own should_skip_alpha() checks
-- first -- this stays true for the whole session if nvim was launched
-- as `nvim file.txt`, blocking alpha.start(true) everywhere afterward.
_G.alpha_tab_ascii = {} _G.alpha_tab_ascii = {}
local function force_alpha_start()
local alpha_loaded, alpha = pcall(require, 'alpha')
if not alpha_loaded then
return
end
local curbuf = vim.api.nvim_get_current_buf()
local restore = {}
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
if buf ~= curbuf and vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_option(buf, 'buflisted') then
table.insert(restore, buf)
vim.api.nvim_buf_set_option(buf, 'buflisted', false)
end
end
local orig_argc = vim.fn.argc
vim.fn.argc = function(...)
return 0
end
local ok = pcall(alpha.start, true)
vim.fn.argc = orig_argc
if not ok then
vim.notify('Failed to start Alpha', vim.log.levels.ERROR)
end
for _, buf in ipairs(restore) do
if vim.api.nvim_buf_is_valid(buf) then
vim.api.nvim_buf_set_option(buf, 'buflisted', true)
end
end
end
_G.force_alpha_start = force_alpha_start
local last_tab_count = #vim.api.nvim_list_tabpages() local last_tab_count = #vim.api.nvim_list_tabpages()
-- Save ASCII art -- Save ASCII art
@@ -46,7 +84,7 @@ vim.api.nvim_create_autocmd('TabEnter', {
local dashboard_loaded, dashboard = pcall(require, 'alpha.themes.dashboard') local dashboard_loaded, dashboard = pcall(require, 'alpha.themes.dashboard')
if not dashboard_loaded then if not dashboard_loaded then
vim.cmd 'enew' vim.cmd 'enew'
alpha.start(true) force_alpha_start()
return return
end end
@@ -57,7 +95,7 @@ vim.api.nvim_create_autocmd('TabEnter', {
end end
vim.cmd 'enew' vim.cmd 'enew'
alpha.start(true) force_alpha_start()
end) end)
end end
end, end,
@@ -67,9 +105,14 @@ vim.api.nvim_create_autocmd('TabEnter', {
vim.api.nvim_create_autocmd('TabClosed', { vim.api.nvim_create_autocmd('TabClosed', {
pattern = '*', pattern = '*',
callback = function() callback = function()
local closed_tab = tonumber(vim.fn.expand '<afile>') local live_tabs = {}
if closed_tab then for _, tab in ipairs(vim.api.nvim_list_tabpages()) do
_G.alpha_tab_ascii[closed_tab] = nil live_tabs[tab] = true
end
for cached_tab, _ in pairs(_G.alpha_tab_ascii) do
if not live_tabs[cached_tab] then
_G.alpha_tab_ascii[cached_tab] = nil
end
end end
end, end,
}) })

View File

@@ -5,6 +5,19 @@ local M = {}
-- List of buffer names or filetypes to skip (UndoTree, Neo-tree, etc.) -- List of buffer names or filetypes to skip (UndoTree, Neo-tree, etc.)
local skip_buffers = { 'undotree', 'neo-tree' } local skip_buffers = { 'undotree', 'neo-tree' }
-- getftime() returns -1 for both never-existed and deleted files
local confirmed_existed = {}
vim.api.nvim_create_autocmd({ 'BufReadPost', 'BufWritePost' }, {
callback = function(args)
confirmed_existed[args.buf] = true
end,
})
vim.api.nvim_create_autocmd('BufDelete', {
callback = function(args)
confirmed_existed[args.buf] = nil
end,
})
-- Helper function to determine if a buffer should be skipped in future -- Helper function to determine if a buffer should be skipped in future
local function should_skip(buf) local function should_skip(buf)
if not vim.api.nvim_buf_is_valid(buf) then if not vim.api.nvim_buf_is_valid(buf) then
@@ -44,10 +57,9 @@ local function rename_deleted_buffers()
local bufname = vim.api.nvim_buf_get_name(buf) local bufname = vim.api.nvim_buf_get_name(buf)
if bufname ~= '' and vim.fn.filereadable(bufname) == 0 then if bufname ~= '' and vim.fn.filereadable(bufname) == 0 then
-- Skip buffers for files that have never been written (new files), -- Skip never-written new files, but not deleted ones
-- regardless of whether they have unsaved (modified) content
local ftime = vim.fn.getftime(bufname) local ftime = vim.fn.getftime(bufname)
if ftime == -1 then if ftime == -1 and not confirmed_existed[buf] then
goto continue goto continue
end end
@@ -70,6 +82,9 @@ local function rename_deleted_buffers()
vim.api.nvim_buf_set_option(buf, 'buflisted', false) vim.api.nvim_buf_set_option(buf, 'buflisted', false)
vim.api.nvim_buf_set_name(buf, new_name) vim.api.nvim_buf_set_name(buf, new_name)
vim.api.nvim_buf_set_option(buf, 'buflisted', true) vim.api.nvim_buf_set_option(buf, 'buflisted', true)
-- Prevent accidental :w from creating this file on disk
vim.api.nvim_buf_set_option(buf, 'buftype', 'nofile')
vim.api.nvim_buf_set_option(buf, 'modifiable', false)
end end
end end
end end
@@ -85,8 +100,8 @@ vim.api.nvim_create_autocmd({ 'FocusGained', 'BufEnter' }, {
if should_skip(buf) then if should_skip(buf) then
return return
end end
-- Force Neovim to check external changes -- Restrict to current buffer; checktime with no arg checks all
vim.cmd 'checktime' vim.cmd('checktime ' .. buf)
rename_deleted_buffers() rename_deleted_buffers()
end, end,
}) })

View File

@@ -23,10 +23,13 @@ function M.tabline()
local label = i .. ': ' .. vim.fn.fnamemodify(bufname, ':t') .. modified local label = i .. ': ' .. vim.fn.fnamemodify(bufname, ':t') .. modified
-- truncate/pad to fixed tab_width -- truncate/pad to fixed tab_width
if #label > tab_width - 2 then if vim.fn.strwidth(label) > tab_width - 2 then
label = label:sub(1, tab_width - 3) .. '' while vim.fn.strwidth(label) > tab_width - 3 and #label > 0 do
label = label:sub(1, -2)
end
label = label .. ''
end end
label = label .. string.rep(' ', tab_width - #label) label = label .. string.rep(' ', tab_width - vim.fn.strwidth(label))
tabs[i] = (i == current_tab and '%#TabLineSel#' or '%#TabLine#') .. label tabs[i] = (i == current_tab and '%#TabLineSel#' or '%#TabLine#') .. label
end end

View File

@@ -117,7 +117,7 @@ vim.keymap.set('n', '<leader>th', '<Cmd>vsplit | wincmd l | terminal<CR>i', { no
vim.keymap.set('n', '<Leader>e', function() vim.keymap.set('n', '<Leader>e', function()
vim.cmd 'tabnew' -- create a new tab vim.cmd 'tabnew' -- create a new tab
vim.cmd 'enew' -- create a new empty buffer in it vim.cmd 'enew' -- create a new empty buffer in it
require('alpha').start(true) -- open Alpha dashboard in this new tab _G.force_alpha_start() -- opens Alpha
end, { noremap = true, silent = true, desc = 'Create a new tab' }) end, { noremap = true, silent = true, desc = 'Create a new tab' })
-- [[ Horizontal split with new empty buffer below ]] -- [[ Horizontal split with new empty buffer below ]]
@@ -242,14 +242,12 @@ local function smart_save(force_save_as)
return return
end end
end end
-- Preserve cursor position and undo history -- Preserve cursor position
local old_buf = vim.api.nvim_get_current_buf() local old_buf = vim.api.nvim_get_current_buf()
local cursor_pos = vim.api.nvim_win_get_cursor(0) local cursor_pos = vim.api.nvim_win_get_cursor(0)
local undo_history = vim.fn.getbufinfo(old_buf)[1].changedtick
vim.cmd('edit ' .. vim.fn.fnameescape(filename)) vim.cmd('edit ' .. vim.fn.fnameescape(filename))
vim.cmd 'filetype detect' vim.cmd 'filetype detect'
vim.api.nvim_win_set_cursor(0, cursor_pos) vim.api.nvim_win_set_cursor(0, cursor_pos)
vim.cmd 'undojoin'
vim.api.nvim_buf_delete(old_buf, { force = true }) vim.api.nvim_buf_delete(old_buf, { force = true })
end end
print('Saved as ' .. filename) print('Saved as ' .. filename)
@@ -744,4 +742,17 @@ for i = 32, 126 do
end, { noremap = true, expr = true, silent = true }) end, { noremap = true, expr = true, silent = true })
end end
end end
vim.keymap.set({ 'i', 'v', 't' }, 'q', q_double_escape, { noremap = true, expr = true, silent = true }) -- Insert/terminal mode:
vim.keymap.set({ 'i', 't' }, 'q', q_double_escape, { noremap = true, expr = true, silent = true })
-- Visual mode:
vim.keymap.set('v', 'q', function()
local ok, nr = pcall(vim.fn.getchar)
if not ok then
return ''
end
local nextchar = type(nr) == 'number' and vim.fn.nr2char(nr) or nr
if nextchar == 'q' then
return vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
end
return 'q' .. nextchar
end, { noremap = true, expr = true, silent = true })

View File

@@ -126,7 +126,6 @@ return {
end end
-- Reuse empty buffer in current tab -- Reuse empty buffer in current tab
local wins = vim.api.nvim_tabpage_list_wins(0) local wins = vim.api.nvim_tabpage_list_wins(0)
local empty_buf = nil
for _, win in ipairs(wins) do for _, win in ipairs(wins) do
if vim.api.nvim_win_is_valid(win) then if vim.api.nvim_win_is_valid(win) then
local buf = vim.api.nvim_win_get_buf(win) local buf = vim.api.nvim_win_get_buf(win)
@@ -165,11 +164,8 @@ return {
end end
end end
end end
if empty_buf then -- No reusable window found, open in a new tab
vim.cmd('edit ' .. vim.fn.fnameescape(path)) vim.cmd('tabnew ' .. vim.fn.fnameescape(path))
else
vim.cmd('tabnew ' .. vim.fn.fnameescape(path))
end
-- Always close Neo-tree window if open -- Always close Neo-tree window if open
for _, win in ipairs(vim.api.nvim_list_wins()) do for _, win in ipairs(vim.api.nvim_list_wins()) do
if vim.api.nvim_win_is_valid(win) then if vim.api.nvim_win_is_valid(win) then

View File

@@ -121,7 +121,45 @@ return {
local cmp = require 'cmp' local cmp = require 'cmp'
local luasnip = require 'luasnip' local luasnip = require 'luasnip'
require('luasnip.loaders.from_vscode').lazy_load() require('luasnip.loaders.from_vscode').lazy_load()
--require('luasnip.loaders.from_vscode').lazy_load({ paths = { "~/.config/nvim/my_snippets" } }) do
local parser = require 'luasnip.util.parser'
local custom_dir = vim.fn.stdpath 'config' .. '/custom_friendly_snippets'
local handle = vim.loop.fs_scandir(custom_dir)
if handle then
while true do
local name, ftype = vim.loop.fs_scandir_next(handle)
if not name then
break
end
if ftype == 'file' and name:match '%.json$' then
local filetype = name:gsub('%.json$', '')
local lines_ok, lines = pcall(vim.fn.readfile, custom_dir .. '/' .. name)
if lines_ok then
local decode_ok, data = pcall(vim.json.decode, table.concat(lines, '\n'))
if decode_ok and type(data) == 'table' then
local snippets = {}
for snip_name, snip in pairs(data) do
local prefixes = type(snip.prefix) == 'table' and snip.prefix or { snip.prefix }
local body = type(snip.body) == 'table' and table.concat(snip.body, '\n') or snip.body
for _, prefix in ipairs(prefixes) do
local parse_ok, parsed =
pcall(parser.parse_snippet, { trig = prefix, name = snip_name, desc = snip.description }, body)
if parse_ok then
table.insert(snippets, parsed)
end
end
end
luasnip.add_snippets(filetype, snippets, { default_priority = 2000 })
else
vim.notify('Failed to decode custom snippet file: ' .. name, vim.log.levels.ERROR)
end
else
vim.notify('Failed to read custom snippet file: ' .. name, vim.log.levels.ERROR)
end
end
end
end
end
luasnip.config.setup {} luasnip.config.setup {}
cmp.setup { cmp.setup {
snippet = { snippet = {

View File

@@ -311,19 +311,8 @@ return {
require('telescope.builtin').git_files { require('telescope.builtin').git_files {
attach_mappings = function(_, map) attach_mappings = function(_, map)
map('n', 'q', actions.close) map('n', 'q', actions.close)
local actions = require 'telescope.actions' map('i', '<CR>', smart_open)
local action_state = require 'telescope.actions.state' map('n', '<CR>', smart_open)
local function open_smart(prompt_bufnr)
local entry = action_state.get_selected_entry()
if not entry then
return
end
pcall(actions.close, prompt_bufnr)
smart_open(prompt_bufnr)
end
map('i', '<CR>', open_smart)
map('n', '<CR>', open_smart)
return true return true
end, end,
} }

View File

@@ -1,79 +0,0 @@
local uv = vim.loop
local home = uv.os_homedir()
-- Detect OS and base path of friendly-snippets
local function get_friendly_snippets_base_path()
local os_name = uv.os_uname().sysname
if os_name == 'Windows_NT' then
return home .. '\\.local\\share\\nvim\\lazy\\friendly-snippets\\snippets\\'
else
return home .. '/.local/share/nvim/lazy/friendly-snippets/snippets/'
end
end
local target_base = get_friendly_snippets_base_path()
local custom_snippets_dir = vim.fn.stdpath 'config' .. '/custom_friendly_snippets/'
-- Read all files in custom_snippets_dir
local function get_custom_snippet_files()
local handle = uv.fs_scandir(custom_snippets_dir)
if not handle then
vim.notify('Custom snippets folder not found: ' .. custom_snippets_dir, vim.log.levels.ERROR)
return {}
end
local files = {}
while true do
local name, type = uv.fs_scandir_next(handle)
if not name then
break
end
if type == 'file' then
table.insert(files, name)
end
end
return files
end
-- Replace each snippet file
local function replace_snippets()
local files = get_custom_snippet_files()
for _, filename in ipairs(files) do
local source_path = custom_snippets_dir .. filename
local target_path = target_base .. filename
local source_file = io.open(source_path, 'r')
if not source_file then
vim.notify('Failed to read: ' .. source_path, vim.log.levels.ERROR)
goto continue
end
local source_content = source_file:read '*a'
source_file:close()
-- Read target content (if exists)
local target_content = ''
local target_file = io.open(target_path, 'r')
if target_file then
target_content = target_file:read '*a'
target_file:close()
end
-- Only update if different
if source_content ~= target_content then
-- Create backup if not exists
local backup_path = target_path .. '.bak'
if not uv.fs_stat(backup_path) and target_content ~= '' then
local backup_file = io.open(backup_path, 'w')
if backup_file then
backup_file:write(target_content)
backup_file:close()
else
vim.notify('Failed to create backup: ' .. backup_path, vim.log.levels.ERROR)
end
end
local output = io.open(target_path, 'w')
if output then
output:write(source_content)
output:close()
vim.notify('Updated snippet: ' .. filename, vim.log.levels.INFO)
else
vim.notify('Failed to write: ' .. target_path, vim.log.levels.ERROR)
end
end
::continue::
end
end
replace_snippets()

View File

@@ -27,15 +27,21 @@ vim.api.nvim_create_user_command('UpdateKickestEnd', function()
local origin_master = vim.fn.systemlist({ 'git', '-C', config_path, 'rev-parse', 'origin/master' })[1] local origin_master = vim.fn.systemlist({ 'git', '-C', config_path, 'rev-parse', 'origin/master' })[1]
local is_uptodate = (head == origin_master) local is_uptodate = (head == origin_master)
-- Check for local commits not yet pushed to origin/master -- a
local ahead_count = tonumber(vim.fn.systemlist({ 'git', '-C', config_path, 'rev-list', '--count', 'origin/master..HEAD' })[1]) or 0
local has_unpushed_commits = ahead_count > 0
-- Skip update if nothing to do -- Skip update if nothing to do
if not dirty and is_uptodate then if not dirty and is_uptodate then
vim.notify('KickestEnd.nvim is already up-to-date with origin/master.', vim.log.levels.INFO) vim.notify('KickestEnd.nvim is already up-to-date with origin/master.', vim.log.levels.INFO)
return return
end end
-- If there are local changes or untracked files, confirm overwrite -- If there are local changes, untracked files, or unpushed commits, confirm overwrite
if dirty then if dirty or has_unpushed_commits then
local answer = vim.fn.input 'Local changes or new files detected! Overwrite and delete them? (y/N): ' local prompt = dirty and 'Local changes or new files detected! Overwrite and delete them? (y/N): '
or string.format('%d local commit(s) not on origin/master will be lost! Continue? (y/N): ', ahead_count)
local answer = vim.fn.input(prompt)
if answer:lower() ~= 'y' then if answer:lower() ~= 'y' then
vim.notify('Update cancelled to preserve your modifications.', vim.log.levels.WARN) vim.notify('Update cancelled to preserve your modifications.', vim.log.levels.WARN)
return return