init.lua
lua/autocmd.lua
lua/colorscheme.lua
lua/command.lua
lua/dmacro.lua
lua/fcitx5.lua
lua/ftplugin.lua
lua/fzf.lua
lua/gitlens.lua
lua/lsp.lua
lua/map.lua
lua/opt.lua
lua/plugindata.lua
lua/plugin.lua
lua/snippet.lua
lua/submode.lua
lua/ui.lua
lua/utils.lua
lua/wrapwin.lua
lua/ftplugin/asm.lua
lua/ftplugin/c.lua
lua/ftplugin/cmake.lua
lua/ftplugin/cpp.lua
lua/ftplugin/fish.lua
lua/ftplugin/go.lua
lua/ftplugin/haskell.lua
lua/ftplugin/java.lua
lua/ftplugin/lua.lua
lua/ftplugin/makefile.lua
lua/ftplugin/nix.lua
lua/ftplugin/nu.lua
lua/ftplugin/rust.lua
lua/ftplugin/scheme.lua
lua/ftplugin/tex.lua
lua/ftplugin/typst.lua
lua/ftplugin/yaml.lua
lua/ftplugin/zig.lua

==> init.lua <==
-- overwrite superfluous paths
vim.opt.runtimepath = '~/.config/nvim,~/.local/share/nvim/runtime,~/.local/lib/nvim'

local clibpath = vim.fn.stdpath('config') .. '/lib/?.so'
package.cpath = package.cpath .. ';' .. clibpath

require 'autocmd'
require 'dmacro'
require 'fcitx5'
require 'ftplugin'
require 'gitlens'
require 'opt'
require 'plugin'
require 'colorscheme'
require 'ui'

==> lua/autocmd.lua <==
local au = vim.api.nvim_create_autocmd
local map = vim.keymap.set

function Treesitter_config()
	local prefix = vim.env.HOME .. '/.local/share/nvim/runtime/queries/'
	if #vim.o.filetype > 0 and vim.uv.fs_stat(prefix .. vim.o.filetype) then
		vim.treesitter.start()
	end
end

au({ 'VimEnter' }, {
    callback = function()
        local session = vim.env.HOME .. '/.cache/nvim/session.vim'
        if vim.uv.fs_stat(session) then
            vim.cmd.source(session)
            vim.fs.rm(session)
        end
    end
})

au({ 'UIEnter' }, {
	callback = function()
		require 'map'
        vim.cmd.rshada()
        if (vim.fn.argc() == 0) then
            vim.cmd.term('nu')
        else
            vim.cmd.normal 'g`"'
        end
	end
})

au({ 'FileType' }, {
	callback = Treesitter_config
})

au({ 'CmdLineEnter' }, {
	callback = function()
		require 'cdtrack'
	end,
    once = true
})

au({ 'TextYankPost' }, {
	callback = function()
		if vim.v.event.regname == '' then
			vim.fn.setreg(vim.v.event.operator, vim.fn.getreg())
		end
	end
})

au({ 'CmdWinEnter' }, {
	callback = function()
		map('n', '<ESC>', '<cmd>q!<CR>', { buffer = true })
		vim.bo.filetype = 'vim'
	end
})

au({ 'BufWinEnter' }, {
	pattern = 'COMMIT_EDITMSG',
	callback = function()
		for i, s in ipairs(vim.fn.systemlist('git diff --cached')) do
			vim.fn.append(i - 1, '# ' .. s)
		end
	end
})

au({ 'BufWritePre' }, {
	callback = function()
		local dir = vim.fn.expand('<afile>:p:h')
		local f = io.open(dir, 'r')
		if f then
			f:close()
			return
		end
		vim.fn.mkdir(dir, 'p')
	end
})

au({ 'VimLeave' }, { command = 'wshada' })

==> lua/colorscheme.lua <==
local NITSC = {
	green = '#07d101',
	blue = '#00bfff',
	cream = '#edf0e0',
	bush = '#f584c6',
	red = '#f85624',
	brick = '#d8916e',
	navy = '#0047ab',
	gray = '#c0c0c0',
	greenyellow = '#adff2f',
	electriclime = '#ccff00',
	forest = '#228b22',
	cherry = '#ffb7c5',
	gold = '#ffd700',
}

---@param group string
---@param opts table
local function hi(group, opts)
	vim.api.nvim_set_hl(0, group, opts)
end

hi('Normal', { bg = 'None' })
hi('NormalNC', { bg = 'None' })
hi('SignColumn', { bg = 'None' })
hi('CursorLine', { bg = 'none' })
hi('CursorLineNR', { fg = NITSC.red, bg = 'none', bold = true })
hi('CursorLineNC', { bg = 'none' })
hi('LineNr', { fg = NITSC.navy, bg = 'none' })
hi('StatusLine', { bg = 'none' })
hi('StatusLineNC', { bg = 'none' })
hi('LspInlayHint', { fg = 'DarkCyan' })
hi('Visual', { bg = NITSC.blue })
hi('PmenuSel', { fg = NITSC.gold, bg = NITSC.blue })
hi('Search', { fg = NITSC.cream })
hi('CurSearch', { fg = NITSC.forest, bg = NITSC.cream })
hi('Substitute', { fg = NITSC.cream })
hi('WinSeparator', { fg = NITSC.blue })

hi('Boolean', { fg = NITSC.blue })
hi('Comment', { fg = NITSC.gray })
hi('Constant', { fg = NITSC.bush })
hi('Statement', { fg = NITSC.green, bold = true })
hi('KeyWord', { fg = NITSC.cream, bold = true })
hi('PreProc', { fg = NITSC.brick })
hi('Identifier', { fg = NITSC.greenyellow, bold = true })
hi('Special', { fg = NITSC.blue })
hi('String', { fg = NITSC.cherry })
hi('Type', { fg = NITSC.blue, bold = true })
hi('Number', { fg = NITSC.gold })
hi('Todo', { fg = NITSC.navy, bg = NITSC.cream, bold = true })
hi('Operator', { fg = NITSC.cream })
hi('Function', { fg = NITSC.gold })
hi('SpecialChar', { fg = NITSC.bush })
hi('Delimiter', { fg = NITSC.cream })

hi('@variable', { fg = NITSC.electriclime })
hi('@variable.parameter', { italic = true })

==> lua/command.lua <==
local command = vim.api.nvim_create_user_command

command('M', function(opts)
	local args = table.concat(opts.fargs, ' ')
	vim.cmd.term('man ' .. args .. '| bat -p -l man')
	vim.cmd.startinsert()
end, {
	nargs = '*',
	bar = true,
})

command('W', function(opts)
	vim.cmd.term('w3m ' .. opts.fargs[1])
	vim.cmd.startinsert()
end, {
	nargs = 1,
	bar = true
})

command('H', function(opts)
	vim.cmd('tab h ' .. opts.fargs[1])

	require 'wrapwin'.open_wrapwin()
end, {
	nargs = 1,
	complete = 'help'
})

command('VS', function(_)
	require 'wrapwin'.open_wrapwin()
end, {
	nargs = 0,
})

==> lua/dmacro.lua <==
local dmacro_key = '<C-T>'
local clear_key = '<C-S-T>'
local key_log = ''
local prev_macro = nil

---@param kl string
---@return string
local function guess_macro(kl)
	for i = #kl / 2, #kl do
		local curspan = kl:sub(i)
		local srchspan = kl:sub(1, i - 1)
		local start, fin = srchspan:find(curspan, 1, true)
		if start and fin then
			prev_macro = srchspan:sub(start)
			return srchspan:sub(fin + 1)
		end
	end
	return ''
end

---@param typed string
local function key_logger(_, typed)
	local readable_keycode = vim.fn.keytrans(typed)
	if readable_keycode == dmacro_key then return end

	key_log = key_log .. readable_keycode
	if #key_log > 100 then
		key_log = key_log:sub(#key_log - 100)
	end
	prev_macro = nil
end

vim.on_key(key_logger)
vim.keymap.set({ 'i', 'n', 'v', 'o', 'c', 't' }, dmacro_key, function()
	vim.api.nvim_input(prev_macro or guess_macro(key_log))
end)
vim.keymap.set({ 'i', 'n', 'v', 'o', 'c', 't' }, clear_key, function()
	key_log = ''
end)

==> lua/fcitx5.lua <==
local IM_cmd = 'fcitx5-remote'
local toggle_IM = { IM_cmd, '-t' }
local was_IM_enabled = false -- was im enabled in previous insert mode

---@return boolean
local function get_IM_status()
	return vim.system({ IM_cmd }):wait().stdout:sub(1, 1) == '2'
end

local function toggle_IM_status()
	if was_IM_enabled then vim.system(toggle_IM) end
end

vim.api.nvim_create_autocmd('InsertEnter', { callback = toggle_IM_status })

vim.api.nvim_create_autocmd('InsertLeave', {
	callback = function()
		was_IM_enabled = get_IM_status()
		toggle_IM_status()
	end
})

==> lua/ftplugin.lua <==
local au = vim.api.nvim_create_autocmd
local snip = require 'snippet'

--- evaluate code selected in visual mode
---@param cmd string[]
local function quickeval(cmd)
	local range = require 'utils'.get_visual_selection()
	local begin = range.start
	local last = range.last

	begin[1] = begin[1] - 1
	last[1] = last[1] - 1
	last[2] = last[2] + 1

	local content = vim.api.nvim_buf_get_text(0, begin[1], begin[2], last[1], last[2], {})

	local tmpfilename = '/tmp/nvim-ftplugin.' .. vim.fn.expand('%:e')
	local file = assert(io.open(tmpfilename, 'w'))
	for _, line in ipairs(content) do
		file:write(line .. '\n')
	end
	file:close()

	vim.cmd('vert term ' .. cmd .. tmpfilename)
	vim.cmd.startinsert()
end

au('FileType', {
	callback = function(ev)
		local ft = ev.match
		local ok, ftp = pcall(require, 'ftplugin.' .. ft)
		if not ok then return end

		if ftp.lsp then
			ftp.lsp.on_attach = require 'lsp'.on_attach
			vim.loop.new_async(vim.schedule_wrap(function()
				vim.lsp.start(ftp.lsp)
			end)):send()
		end
		if ftp.quickeval_cmd then
			vim.keymap.set('v', 'x', function()
				quickeval(ftp.quickeval_cmd)
			end)
		end
		if ftp.callback then
			ftp.callback()
		end
		if ftp.snippet then
			snip.setup_keymap()
			for _, sn in ipairs(ftp.snippet) do
				snip.set_snip(sn)
			end
		end
	end
})

==> lua/fzf.lua <==
---@param directory string
---@param files table
---@return table
local function get_files_recursive(directory, files)
	local curdir = vim.env.PWD
	local directory_files = vim.fn.readdir(directory)
	local ignored_dirs = { '.', '..', '.git', 'build', 'bin', 'plugins' }
	for _, file in ipairs(directory_files) do
		local full_path = directory .. '/' .. file
		if vim.fn.isdirectory(full_path) ~= 0 and not vim.tbl_contains(ignored_dirs, file) then
			get_files_recursive(full_path, files)
		else
			table.insert(files, full_path:sub(#curdir + 2))
		end
	end
	return files
end

local file_cache = nil

vim.api.nvim_create_user_command('F',
	function(opts)
		vim.cmd.tabnew(opts.fargs[1])
	end,
	{
		nargs = 1,
		bar = true,
		complete = function(trigger)
			if not file_cache then
				file_cache = get_files_recursive(vim.env.PWD, {})
			end
			if #trigger > 0 then
				return vim.fn.matchfuzzy(file_cache, trigger)
			else
				return file_cache
			end
		end
	})

==> lua/gitlens.lua <==
local map = vim.keymap.set
local api = vim.api

local function printBlameText()
	local currFile = vim.fn.expand('%')
	local line = api.nvim_win_get_cursor(0)
	local blame = vim.fn.system(string.format('git blame -c -L %d,%d %s', line[1], line[1], currFile))
    local hash = string.match(blame, '%S+')
	if hash == '00000000' then
		Text = 'Not Committed Yet'
	else
		local cmd = 'git show ' .. hash .. " --format='%an | %ar | %s' | head -n 1"
		Text = vim.fn.system(cmd):sub(1, -2)
		if Text:find('fatal') then
			Text = 'Not Committed Yet'
		end
	end
	print(Text)
end

map('n', '\\b', printBlameText)

==> lua/lsp.lua <==
M = {}

vim.keymap.set('n', '=', vim.lsp.buf.format)
vim.keymap.set('n', '^h', function()
	vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled())
end)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition)
vim.keymap.set('n', 'grh', vim.lsp.buf.hover)

vim.diagnostic.config({ virtual_text = true })
vim.lsp.document_color.enable(true, 0, { style = 'virtual' })

function M.on_attach(client, bufnr)
    local chars = {}
    for i = 32, 126 do table.insert(chars, string.char(i)) end
    client.server_capabilities.completionProvider.triggerCharacters = chars
	vim.lsp.completion.enable(true, client.id, bufnr, {
		autotrigger = true,
		convert = function(item)
			return { abbr = item.label:gsub('%b()', '') }
		end
	})
end

return M

==> lua/map.lua <==
local map = vim.keymap.set
local submode = require 'submode'
vim.g.mapleader = ' '

local function smart_gf()
	local fpath = vim.fn.expand('<cfile>')
	if fpath:sub(1, 8) == 'https://' then
		vim.cmd.term('w3m ' .. fpath)
		vim.cmd.startinsert()
	else
		vim.cmd.normal 'gF'
	end
end

-- consider indentation
local function smart_i()
	if vim.fn.getline('.'):match('^ *$') then
		vim.api.nvim_input '"_cc'
	else
		-- vim.api.nvim_input 'i' -- freeze
		vim.cmd.startinsert()
	end
end

map('n', '<BS>', '<C-b>')
map('n', '<Delete>', '<C-f>')
map('n', '<C-S-e>', '5<C-e>')
map('n', '<C-S-y>', '5<C-y>')
map('n', 'i', smart_i)
map('n', 'S', 'c^')
map('n', 'Q', 'ZZ', { noremap = true })
map('n', 'ZZ', function()
    vim.cmd.mksession(vim.env.HOME .. '/.cache/nvim/session.vim')
    vim.cmd.wqa()
end)
map('n', 'G', '')
map('n', 'GG', 'G')
map('n', 'gk', '25k')
map('n', 'gj', '25j')
map('n', 'gf', smart_gf)
map('n', 'gb', vim.cmd.bnext)
map('n', 'gB', vim.cmd.bprev)
map('n', '^n', function() vim.o.number = not vim.o.number end)
map('n', '^r', function() vim.o.relativenumber = not vim.o.relativenumber end)
map('n', '^s', function() vim.o.spell = not vim.o.spell end)
map('n', '<C-z>', ':w<CR><C-z>')
map('n', 'zS', vim.show_pos)
map({ 'n', 'v' }, 'q;', 'q:')
map({ 'n', 'o', 'v' }, 'K', '5k')
map({ 'n', 'o', 'v' }, 'J', '5j')
map({ 'n', 'v' }, 'x', '"_d')
map({ 'n', 'v' }, 'X', '"_D')
map({ 'n', 'v' }, ']]', '<C-]>')
map({ 'n', 'v' }, '<Leader>y', [["+y]])
map({ 'n', 'v' }, '<Leader>Y', [["+Y]])
map({ 'n', 'v' }, '<Leader>d', [["_d]])
map({ 'n', 'v', 'o' }, 'gl', '$l')
map({ 'n', 'v', 'o' }, 'gh', '^')
map({ 'n', 'v', 'o' }, ']b', '])')
map({ 'n', 'v', 'o' }, '[b', '[(')
map({ 'n', 'v', 'o' }, ']B', ']}')
map({ 'n', 'v', 'o' }, '[B', '[{')

map('i', '<Esc>', '<Right><Esc>')

map('v', '<C-k>', ":m '<-2<CR>gv=gv")
map('v', '<C-j>', ":m '>+1<CR>gv=gv")
map('v', 'v', '<C-v>')
map('v', 'aa', 'VggoG')

map('o', '.', 'i>')
map('o', 'iq', "i'")
map('o', 'iQ', 'i"')
map('o', 'aq', "a'")
map('o', 'aQ', 'a"')
map('o', 'i<Space>', 'iW')
map('o', 'a<Space>', 'aW')

map('t', '<C-\\>', '<C-\\><C-n>')

submode.set_submode_keymap('n', 'g', {
	{ key = 't' },
	{ key = 'T' },
	{ key = 'e' },
	{ key = 'E' },
	{ key = 'J' },
})
submode.set_submode_keymap('n', 'd', {
	{ key = 'h' },
	{ key = 'l' },
})
submode.set_submode_keymap('n', '<C-w>', {
	{ key = '>' },
	{ key = '<' },
	{ key = '+' },
	{ key = '-' },
	{ key = 'h' },
	{ key = 'j' },
	{ key = 'k' },
	{ key = 'l' },
})

submode.set_submode_keymap('n', 'z', {
	{ key = '<Space>', run_when = { entering = '<C-f>', repeating = '<C-f>' } },
	{ key = 'b',       run_when = { entering = '<C-b>', repeating = '<C-b>' } },
})

-- When pressed once, it does not move, but registers the word at the cursor position in the / register.
submode.set_submode_keymap('n', '*', {
	{ key = '*', run_when = { entering = '#*', repeating = '*' } },
})
submode.set_submode_keymap('n', '#', {
	{ key = '#', run_when = { entering = '*#', repeating = '#' } },
})

submode.acceleration_key('n', 'j')
submode.acceleration_key('n', 'k')
submode.acceleration_key('n', 'h')
submode.acceleration_key('n', 'l')

local function safe_cabbrev(lhs, rhs)
	vim.cmd('cabbrev <expr> ' ..
		lhs .. ' (getcmdtype() ==# ":" && getcmdline() ==# "' .. lhs .. '") ? "' .. rhs .. '" : "' .. lhs .. '"')
end

safe_cabbrev('r', 'lua require')
safe_cabbrev('l', 'lua')
vim.cmd 'cabbrev api vim.api'

==> lua/opt.lua <==
local o = vim.opt

o.autoread = true
o.autowrite = true
o.complete = 'w,i,d,kspell'
o.completeopt = 'menuone,preinsert,noselect,popup,fuzzy'
o.cursorline = true
o.expandtab = true
o.foldmethod = 'manual'
o.fillchars = { stl = ' ', stlnc = ' ' }
o.gdefault = true
o.guicursor = 'n-v-c-sm:block,i-ci-ve:ver25-blinkwait1000-blinkoff300-blinkon1000,t:block-TermCursor'
o.guifont = 'PlemolJP35 Console NF:h8'
o.helplang = 'ja,en'
o.hidden = true
o.ignorecase = true
o.hlsearch = false
o.incsearch = false
o.laststatus = 0
o.mouse = ''
o.number = false
o.paragraphs = ''
o.path = '.,,,**'
o.ruler = false
o.scrolloff = 10
o.shada = ''
o.shell = '/run/current-system/sw/bin/zsh'
o.shiftwidth = 4
o.showcmd = false
o.showmode = false
o.showtabline = 0
o.signcolumn = 'yes'
o.smartcase = true
o.smartindent = true
o.statusline = ' '
o.tabstop = 4
o.termguicolors = true
o.textwidth = 0
o.timeout = false
o.undodir = vim.fn.stdpath('data') .. '/undo'
o.undofile = true
o.wildmenu = true
o.wrap = false

vim.g.copilot_filetypes = { gitcommit = true, yaml = true, markdown = true }

if vim.g.neovide then
	vim.g.neovide_hide_mouse_when_typing = true
	vim.g.neovide_opacity = 1.0
	vim.g.transparency = 1.0
	vim.g.neovide_text_gamma = 0
	vim.g.neovide_text_contrast = 0.0
	vim.g.terminal_color_0  = '#171717' -- black
	vim.g.terminal_color_1  = '#d81765' -- normal red
	vim.g.terminal_color_2  = '#97d01a' -- normal green
	vim.g.terminal_color_3  = '#ffa800' -- normal yellow
	vim.g.terminal_color_4  = '#16b1fb' -- normal blue
	vim.g.terminal_color_5  = '#ff2491' -- normal magenta
	vim.g.terminal_color_6  = '#0fdcb6' -- normal cyan
	vim.g.terminal_color_7  = '#ebebeb' -- light gray
	vim.g.terminal_color_8  = '#88757c' -- dark gray
	vim.g.terminal_color_9  = '#ff0000' -- bright red
	vim.g.terminal_color_10 = '#76b639' -- bright green
	vim.g.terminal_color_11 = '#f7b125' -- bright yellow
	vim.g.terminal_color_12 = '#289cd5' -- bright blue
	vim.g.terminal_color_13 = '#ff2491' -- bright magenta
	vim.g.terminal_color_14 = '#0a9b81' -- bright cyan
	vim.g.terminal_color_15 = '#f8f8f8' -- white
end

==> lua/plugindata.lua <==
local map = vim.keymap.set

return {
    ['folke/flash.nvim'] = {
        modname = 'flash',
        opts = {},
        callback = function()
            local flash = require 'flash'
            flash.toggle(true)
        end
    },
    ['gbprod/substitute.nvim'] = {
        modname = 'substitute',
        callback = function()
            local sub = require 'substitute'
            map('n', 's', sub.operator)
            map('n', 'ss', sub.line)
            map('n', 'S', sub.eol)
            map('x', 's', sub.visual)
        end
    },
    ['kylechui/nvim-surround'] = {
        modname = 'nvim-surround',
        opts = {},
    },
    ['stevearc/oil.nvim'] = {
        modname = 'oil',
        opts = {
            columns = {
                'icon',
                'permission',
                'size',
                'mtime'
            },
        },
        callback = function()
            map('n', '^o', require 'oil'.toggle_float)
        end,
        dependencies = { 'nvim-tree/nvim-web-devicons' }
    },
    ['vim-jp/vimdoc-ja'] = {},
    ['vim-jp/nvimdoc-ja'] = {},
    ['altermo/ultimate-autopair.nvim'] = {
        modname = 'ultimate-autopair',
        opts = {
            fastwarp = {
                rmap = '<A-y>',
                rcmap = '<A-y>',
            },
            tabout = {
                multi = true,
                enable = true,
                hopout = true,
            },
            bs = {
                indent_ignore = true,
            },
            space2 = {
                enable = true,
            },
            extensions = {
                fly = {
                    multiline = true,
                    enable = true
                },
            }
        },
    },
    ['utilyre/sentiment.nvim'] = {
        modname = 'sentiment',
        opts = {},
        callback = function()
            vim.g.loaded_matchparen = 1
        end
    },
    ['nvim-tree/nvim-web-devicons'] = {},
    ['niuiic/core.nvim'] = {},
    ['niui/track.nvim'] = {
        modname = 'track',
        opts = {},
        callback = function()
            local track = require 'track'
            local markfile = vim.fn.stdpath('data') .. '/marks/mark.json'
            map('n', 'ma', track.add_mark)
            map('n', 'mA', track.add_flow)
            map('n', 'md', track.delete_mark)
            map('n', 'mD', track.delete_flow)
            map('n', 'mu', track.update_mark)
            map('n', 'mU', track.update_flow)
            map('n', 'ms', function() track.store_marks(markfile) end)
            track.restore_marks(markfile)
        end,
        dependencies = {
            'nvim-lua/plenary.nvim',
            'nvim-telescope/telescope.nvim',
            'niuiic/core.nvim',
        },
    },
    ['nvim-lua/plenary.nvim'] = {},
    ['nvim-telescope/telescope.nvim'] = {
        modname = 'telescope',
        opts = {},
        dependencies = {
            'nvim-lua/plenary.nvim',
        },
    },
    ['hadronized/hop.nvim'] = {
        modname = 'hop',
        opts = {},
        callback = function()
            local hop = require 'hop'
            map({ 'n', 'v', 'o' }, 'gw', hop.hint_words)
            map({ 'n', 'v', 'o' }, 'ga', hop.hint_anywhere)
        end
    },
    ['zbirenbaum/copilot.lua'] = {
        modname = 'copilot',
        opts = {
            suggestion = {
                enabled = true,
                auto_trigger = false,
                keymap = {
                    accept = '<C-S-y>',
                    next = '<C-S-n>',
                    prev = '<C-S-p>',
                    dismiss = '<C-S-e>',
                }
            },
            filetypes = {
                gitcommit = true
            }
        },
        callback = function()
            map('n', '^a', require 'copilot.suggestion'.toggle_auto_trigger)
        end
    },
    ['nvim-treesitter/nvim-treesitter'] = {
        modname = 'nvim-treesitter',
        opts = { ensure_installed = 'all' },
    },
    ['SmiteshP/nvim-navic'] = {
        modname = 'nvim-navic',
        opts = {
            lsp = { auto_attach = true },
            highlight = true
        }
    },
    ['SmiteshP/nvim-navbuddy'] = {
        modname = 'nvim-navbuddy',
        opts = {
            lsp = { auto_attach = true },
            highlight = true
        },
        dependencies = {
            'SmiteshP/nvim-navic',
            'MunifTanjim/nui.nvim'
        }
    },
    ['MunifTanjim/nui.nvim'] = {
        modname = 'nui',
    },
    ['andersevenrud/nvim_context_vt'] = {
        modname = 'nvim_context_vt',
        opts = {
            enabled = true,
        },
    },
    ['sphamba/smear-cursor.nvim'] = {
        modname = 'smear_cursor',
        opts = {},
    },
}

==> lua/plugin.lua <==
local au = vim.api.nvim_create_autocmd
local map = vim.keymap.set

local pluginOptions = require 'plugindata'

---@param plugname string
function Load_plugin(plugname)
	if pluginOptions[plugname] then
        local url = 'https://github.com/' .. plugname
        local modname = pluginOptions[plugname].modname
		local opts = pluginOptions[plugname].opts
		local callback = pluginOptions[plugname].callback
		local dependencies = pluginOptions[plugname].dependencies
		if dependencies then
			for _, dep in ipairs(dependencies) do
				Load_plugin(dep)
			end
		end
        vim.pack.add({ url })
		if opts and modname then require(modname).setup(opts) end
		if callback then callback() end
		pluginOptions[plugname] = nil
	end
end

au({ 'UIEnter' }, {
	callback = function()
		Load_plugin 'folke/flash.nvim'
		Load_plugin 'gbprod/substitute.nvim'
		Load_plugin 'kylechui/nvim-surround'
		Load_plugin 'andersevenrud/nvim_context_vt'
	end
})

local function Load_cmdln()
	require 'command'
	require 'fzf'
	Load_plugin 'vim-jp/vimdoc-ja'
	Load_plugin 'vim-jp/nvimdoc-ja'
	Load_plugin 'stevearc/oil.nvim'
end

local cmdlnc = { ':', '/', '?' }
for _, c in ipairs(cmdlnc) do
	map({ 'n', 'v', }, c, function()
		Load_cmdln()
		for _, cc in ipairs(cmdlnc) do
			vim.keymap.del({ 'n', 'v' }, cc)
		end
		vim.fn.feedkeys(c)
	end)
end

map('n', '^a', function()
	Load_plugin 'zbirenbaum/copilot.lua'
	local sug = require 'copilot.suggestion'
	map('n', '^a', sug.toggle_auto_trigger)
	sug.toggle_auto_trigger()
end)

map('n', 'g/', function()
	Load_plugin 'nvim-telescope/telescope.nvim'
	local tb = require 'telescope.builtin'
	map('n', 'g/', tb.live_grep)
	tb.live_grep()
end)

map('n', 'm', function()
	Load_plugin 'niuiic/track.nvim'
	vim.keymap.del('n', 'm')
	vim.fn.feedkeys 'm'
end)

map('n', '<A-n>', function()
	Load_plugin 'SmiteshP/nvim-navbuddy'
	map('n', '<A-n>', vim.cmd.Navbuddy)
	vim.cmd.Navbuddy()
end)

au({ 'InsertEnter', 'CmdlineEnter' }, {
	once = true,
	callback = function()
		if vim.bo.filetype ~= 'markdown' then Load_plugin 'altermo/ultimate-autopair.nvim' end
	end
})

au({ 'CursorMoved' }, {
	once = true,
	callback = function()
		Load_plugin 'mini.indentscope'
		Load_plugin 'utilyre/sentiment.nvim'
		Load_plugin 'hadronized/hop.nvim'
		-- if not vim.g.neovide and vim.env.TERM ~= 'xterm-kitty' then
		-- 	Load_Plugin 'sphamba/smear-cursor.nvim'
		-- end
	end
})

==> lua/snippet.lua <==
local mysnip = {}
local map = vim.keymap.set
M = {}

function M.set_snip(sn)
	mysnip[sn.abbr] = sn.snip
end

function M.setup_keymap()
	map('i', '<Tab>', function()
		local curpos = vim.api.nvim_win_get_cursor(0);
		if curpos[2] == 0 then return '<Tab>' end
		local newpos = { curpos[1], curpos[2] - 1 }
		vim.api.nvim_win_set_cursor(0, newpos)
		local cword = vim.fn.expand('<cword>')
		local snip = mysnip[cword]
		if snip then
			return '<Esc>ciw<cmd>lua vim.snippet.expand"' .. snip:gsub('\n', '\\n') .. '"<CR>'
		end

		vim.api.nvim_win_set_cursor(0, curpos)
		if vim.snippet.active({ direction = 1 }) then
			return '<cmd>lua vim.snippet.jump(1)'
		else
			return '<Tab>'
		end
	end, { expr = true })

	map({ 'i', 's' }, '<S-Tab>', function()
		if vim.snippet.active({ direction = -1 }) then
			vim.snippet.jump(-1)
		else
			return '<S-Tab>'
		end
	end, { expr = true })
end

return M

==> lua/submode.lua <==
M = {}

---@param str string
---@return string
local function make_uniq(str)
	return '<Plug>(' .. str .. ')'
end

local function isfun(any)
	return type(any) == 'function'
end

local function map(mode, lhs, rhs, remap)
	vim.keymap.set(mode, lhs, rhs, { expr = isfun(rhs), remap = remap })
end

---@class Autos
---@field entering (fun(): string?|string)?
---@field repeating (fun(): string?|string)?
---@field leaving (fun(): string?|string)? (reserved)

---@class Follower
---@field key string
---@field run_when Autos?

---@param mode string|string[]
---@param leader string
---@param followers Follower[]
function M.set_submode_keymap(mode, leader, followers)
	local uniqid = make_uniq(leader)
	local uniqprefix = uniqid .. leader
	for _, follower in ipairs(followers) do
		local key = leader .. follower.key
		local run_when = follower.run_when or {}

		local get_rhs = function(any)
			if not any then
				return key .. uniqprefix
			elseif type(any) == 'string' then
				return any .. uniqprefix
			elseif isfun(any) then
				return function()
					return (any() or '') .. uniqprefix
				end
			end
		end

		map(mode, key, get_rhs(run_when.entering), true)
		map(mode, uniqprefix .. follower.key, get_rhs(run_when.repeating), true)
	end

	map(mode, uniqprefix, '', true)
end

---@class AccOpts
---@field base number?
---@field thre number?

---@param mode string|string[]
---@param key string
---@param callback (fun(): string?)?
---@param opts AccOpts?
function M.acceleration_key(mode, key, callback, opts)
	local uniqid = make_uniq(key)
	local count ---@type number
	local base = opts and opts.base or 2
	local thre = opts and opts.thre or 3

	vim.keymap.set(mode, key, function()
		if vim.v.count > 0 then
			return key
		end

		count = 1

		if callback then
			return (callback() or '') .. uniqid
		end

		return key .. uniqid
	end, { expr = true })

	vim.keymap.set(mode, uniqid .. key, function()
		local speed = math.pow(base, math.floor(count / thre))
		count = count + 1

		if callback then
			return speed .. (callback() or key) .. uniqid
		end

		return speed .. key .. uniqid
	end, { expr = true })

	vim.keymap.set(mode, uniqid, '<Nop>')
end

return M

==> lua/ui.lua <==
local extui = require 'vim._extui'

extui.enable({
    enable = true
})

==> lua/utils.lua <==
M = {}

function M.get_visual_selection()
  local vpos = vim.fn.getpos('v')
  local begin_pos = {  vpos[2],  vpos[3] - 1 }
  local end_pos = vim.api.nvim_win_get_cursor(0)
  if begin_pos[1] < end_pos[1] or begin_pos[1] == end_pos[1] and begin_pos[2] <= end_pos[2] then
    return { start = begin_pos, last = end_pos }
  else
    return { start = end_pos, last = begin_pos }
  end
end

return M

==> lua/wrapwin.lua <==
M = {}

function M.open_wrapwin()
	local curwin = vim.api.nvim_tabpage_get_win(0)
	local newwin = vim.api.nvim_open_win(0, false, { split = 'left' })
	local winheight = vim.api.nvim_win_get_height(0)
	local winbot = vim.fn.line('w$')
	local targetline = winbot + math.floor(winheight / 2) - 1

	-- scroll new window page forward
	vim.api.nvim_win_set_cursor(0, { targetline, 1 })
	vim.cmd.normal 'zz'

	-- enable scrollbind for both
	vim.o.scrollbind = true
	vim.api.nvim_tabpage_set_win(0, newwin)
	vim.o.scrollbind = true

	-- delete only new window
	vim.keymap.set('n', '<C-c>', function()
		vim.api.nvim_win_close(newwin, false)
		vim.keymap.set('n', 'Q', 'ZZ')
	end, { buffer = true })

	-- delete both of windows
	vim.keymap.set('n', 'Q', function()
		vim.api.nvim_win_close(newwin, false)
		vim.api.nvim_tabpage_set_win(0, curwin)
		vim.cmd.quit()
	end, { buffer = true })

	vim.keymap.set('n', '<C-f>', '2<C-f>', { buffer = true })
	vim.keymap.set('n', '<C-b>', '2<C-b>', { buffer = true })
	vim.keymap.set('n', '<C-d>', '<C-f>', { buffer = true })
	vim.keymap.set('n', '<C-u>', '<C-b>', { buffer = true })
end

return M

==> lua/ftplugin/asm.lua <==
return {
	lsp = {
		name = 'asm-lsp',
		cmd = { 'asm-lsp' }
	}
}

==> lua/ftplugin/c.lua <==
return {
	lsp = {
		name = 'clangd',
		cmd = { 'clangd' }
	},
	quickeval_cmd = 'clang-repl --summary-file=',
	snippet = {
		{ abbr = 'in',   snip = '#include <$1.h>\n$0' },
		{ abbr = 'i',    snip = 'if ($1) {\n  $2\n}\n$0' },
		{ abbr = 'f',    snip = 'for ($1; $2; $3) {\n  $4\n}\n$0' },
		{ abbr = 's',    snip = 'switch ($1) {\n  $2\n}\n$0' },
		{ abbr = 'c',    snip = 'case $1:\n  $0' },
		{ abbr = 'w',    snip = 'while ($1) {\n  $2\n}\n$0' },
		{ abbr = 'd',    snip = '#define $0' },
		{ abbr = 'p',    snip = 'printf("$1", $2);\n$0' },
		{ abbr = 'call', snip = '$1($2);\n$0' },
	},
	callback = function()
		vim.bo.expandtab = true
		vim.bo.shiftwidth = 2
		vim.bo.tabstop = 2
		vim.cmd 'iabbrev and &&'
		vim.cmd 'iabbrev or \\|\\|'
		vim.cmd 'iabbrev not !'
	end
}

==> lua/ftplugin/cmake.lua <==
return {
	lsp = {
		name = 'cmake-ls',
		cmd = { 'cmake-language-server' }
	}
}

==> lua/ftplugin/cpp.lua <==
return require 'ftplugin.c'

==> lua/ftplugin/fish.lua <==
return {
	lsp = {
		name = 'fish-lsp',
		cmd = { 'fish-lsp', 'start' }
	}
}

==> lua/ftplugin/go.lua <==
return {
	lsp = {
		name = 'gopls',
		cmd = { 'gopls' }
	}
}

==> lua/ftplugin/haskell.lua <==
return {
    lsp = {
        name = 'haskell',
        cmd = { 'haskell-language-server-wrapper' }
    }
}

==> lua/ftplugin/java.lua <==
return {
    lsp = {
        name = 'java-language-server',
        cmd = { 'java-language-server' }
    }
}

==> lua/ftplugin/lua.lua <==
return {
	lsp = {
		name = 'lua-ls',
		cmd = { 'lua-language-server' },
		root_dir = vim.fn.stdpath('config')
	},
	snippet = {
		{ abbr = 'i', snip = 'if $1 then\n\t$2\nend\n$0' },
		{ abbr = 'f', snip = 'for $1 in $2 do\n\t$3\nend\n$0' },
		{ abbr = 'fn', snip = 'function $1($2)\n\t$3\nend\n$0' },
		{ abbr = 'l', snip = 'function($1)\n\t$2\nend\n$0' },
	}
}

==> lua/ftplugin/makefile.lua <==
return {
	quickeval_cmd = 'make -n -f ',
	snippet = {
		{ abbr = 'target', snip = '$1: $2\n\t$0' },
		{ abbr = 'p', snip = '.PHONY: $1' },
	}
}

==> lua/ftplugin/nix.lua <==
return {
    lsp = {
        name = 'nixd',
        cmd = { 'nixd' }
    }
}

==> lua/ftplugin/nu.lua <==
return {
	lsp = {
		name = 'nu',
		cmd = { 'nu', '--lsp' }
	}
}

==> lua/ftplugin/rust.lua <==
return {
	lsp = {
		name = 'rust-analyzer',
		cmd = { 'rust-analyzer' }
	},
	snippet = {
		{ abbr = 'i', snip = 'if $1 {\n\t$2\n}\n$0' },
		{ abbr = 'f', snip = 'for $1 in $2 {\n\t$3\n}\n$0' },
		{ abbr = 'w', snip = 'while $1 {\n\t$2\n}\n$0' },
		{ abbr = 'm', snip = 'match $1 {\n\t$2\n}\n$0' },
		{ abbr = 'p', snip = '$1 => $2,\n$0' },
		{ abbr = 'fn', snip = 'fn $1($2) {\n\t$3\n}\n$0' },
		{ abbr = 'fnr', snip = 'fn $1($2) -> $3 {\n\t$4\n}\n$0' },
	}
}

==> lua/ftplugin/scheme.lua <==
return {
	quickeval_cmd = 'scheme',
	snippet = {
		{ abbr = 'i', snip = '(if ${1:cond}\n  ${2:true}\n  ${3:false})' },
		{ abbr = 'fn', snip = '(define $1 (lambda ($2)\n  $3))' },
	},
	callback = function()
		vim.bo.expandtab = true
		vim.bo.shiftwidth = 2
		vim.bo.tabstop = 2
	end
}

==> lua/ftplugin/tex.lua <==
return {
	lsp = {
		name = 'texlab',
		cmd = { 'texlab' }
	},
	snippet = {
		{
			abbr = '!',
			snip = [[\\documentclass[uplatex, dvipdfmx, a4paper]{ltjsarticle}
\\usepackage{}
\\title{$1}
\\author{$2}
\\date{}

\\begin{document}
\\maketitle
\\newpage
$0
\\end{document}]]
		},
		{ abbr = 'b', snip = '\\\\begin{${1:env}}\n$2\n\\\\end{${1:env}}\n$0' },
		{ abbr = 's', snip = '\\\\section{$1}\n$0' },
		{ abbr = 'sb', snip = '\\\\subsection{$1}\n$0' },
	}
}

==> lua/ftplugin/typst.lua <==
return {
	lsp = {
		name = 'tinymist',
		cmd = { 'tinymist' }
	}
}

==> lua/ftplugin/yaml.lua <==
return {
	lsp = {
		name = 'yaml-ls',
		cmd = { 'yaml-language-server' }
	}
}

==> lua/ftplugin/zig.lua <==
return {
	lsp = {
		name = 'zls-prime',
		cmd = { 'zls-prime' }
	},
	snippet = {
		{ abbr = 'i', snip = 'if ($1) {\n    $2\n}\n$0' },
		{ abbr = 'f', snip = 'for ($1) |$2| {\n    $3\n}\n$0' },
		{ abbr = 'w', snip = 'while ($1) {\n    $2\n}\n$0' },
		{ abbr = 'fn', snip = 'fn $1($2) $3 {\n    $4\n}\n$0' },
		{ abbr = 's', snip = 'switch ($1) {\n    $2\n}\n$0' },
		{ abbr = 'p', snip = '$1 => $2,\n$0' },
		{ abbr = 't', snip = 'test "$1" {\n    $2\n}' },
	},
	callback = function()
		vim.bo.expandtab = true
		vim.bo.shiftwidth = 4
		vim.bo.tabstop = 4
	end
}