From f0f0758cdffc4944c01dd100233872ec1a26e092 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 21:56:12 +0800 Subject: [PATCH 01/12] custom plugins --- lua/custom/plugins/00-init.lua | 435 ++++++++++++++++++++ lua/custom/plugins/01-functions.lua | 375 +++++++++++++++++ lua/custom/plugins/01-opts.lua | 133 ++++++ lua/custom/plugins/50-git.lua | 236 +++++++++++ lua/custom/plugins/51-navigation.lua | 77 ++++ lua/custom/plugins/52-terminal.lua | 56 +++ lua/custom/plugins/53-window.lua | 23 ++ lua/custom/plugins/55-startup.lua | 13 + lua/custom/plugins/56-jupyter-plugin.lua | 4 + lua/custom/plugins/57-jupyter-setup.lua | 150 +++++++ lua/custom/plugins/97-setup-plugins.lua | 127 ++++++ lua/custom/plugins/98-bookmarks.lua | 1 + lua/custom/plugins/99-keymaps.lua | 489 +++++++++++++++++++++++ lua/custom/plugins/blank.lua | 1 + lua/custom/plugins/readme.md | 96 +++++ 15 files changed, 2216 insertions(+) create mode 100644 lua/custom/plugins/00-init.lua create mode 100644 lua/custom/plugins/01-functions.lua create mode 100644 lua/custom/plugins/01-opts.lua create mode 100644 lua/custom/plugins/50-git.lua create mode 100644 lua/custom/plugins/51-navigation.lua create mode 100644 lua/custom/plugins/52-terminal.lua create mode 100644 lua/custom/plugins/53-window.lua create mode 100644 lua/custom/plugins/55-startup.lua create mode 100644 lua/custom/plugins/56-jupyter-plugin.lua create mode 100644 lua/custom/plugins/57-jupyter-setup.lua create mode 100644 lua/custom/plugins/97-setup-plugins.lua create mode 100644 lua/custom/plugins/98-bookmarks.lua create mode 100644 lua/custom/plugins/99-keymaps.lua create mode 100644 lua/custom/plugins/blank.lua create mode 100644 lua/custom/plugins/readme.md diff --git a/lua/custom/plugins/00-init.lua b/lua/custom/plugins/00-init.lua new file mode 100644 index 00000000000..2c47f053e8e --- /dev/null +++ b/lua/custom/plugins/00-init.lua @@ -0,0 +1,435 @@ +vim.deprecate = function() end + +-- You can add your own plugins here or in other files in this directory! +-- I promise not to create any merge conflicts in this directory :) +-- +-- See the kickstart.nvim README for more information +return { + { + 'HakonHarnes/img-clip.nvim', + event = 'VeryLazy', + opts = {}, + keys = { + { 'p', 'PasteImage', desc = 'Paste image from system clipboard' }, + }, + }, + { + 'nvim-neo-tree/neo-tree.nvim', + version = '*', + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended + 'MunifTanjim/nui.nvim', + }, + cmd = 'Neotree', + keys = { + { '\\', ':Neotree reveal', desc = 'NeoTree reveal', silent = true }, + }, + opts = { + filesystem = { + window = { + mappings = { + [''] = 'close_window', + }, + }, + }, + }, + }, + { + 'nvim-treesitter/nvim-treesitter-context', + event = 'VeryLazy', + config = function() + require('treesitter-context').setup { + enable = true, + max_lines = 3, + trim_scope = 'outer', + } + end, + }, + { + 'folke/flash.nvim', + event = 'VeryLazy', + opts = {}, + keys = { + { + 's', + mode = { 'n', 'x', 'o' }, + function() + require('flash').jump() + end, + desc = 'Flash', + }, + { + 'S', + mode = { 'n', 'x', 'o' }, + function() + require('flash').treesitter() + end, + desc = 'Flash Treesitter', + }, + { + 'r', + mode = 'o', + function() + require('flash').remote() + end, + desc = 'Remote Flash', + }, + { + 'R', + mode = { 'o', 'x' }, + function() + require('flash').treesitter_search() + end, + desc = 'Treesitter Search', + }, + { + '', + mode = { 'c' }, + function() + require('flash').toggle() + end, + desc = 'Toggle Flash Search', + }, + }, + }, + { + 'echasnovski/mini.statusline', + event = 'VeryLazy', + config = function() + require('mini.statusline').setup { use_icons = vim.g.have_nerd_font } + end, + }, + { + 'yokowasis/emmet-vim', + init = function() + vim.g.user_emmet_settings = { + typescriptreact = { + attribute_name = { + ['class'] = 'class', -- override className -> class + }, + }, + } + end, + }, + { + 'jake-stewart/multicursor.nvim', + branch = '1.0', + config = function() + local mc = require 'multicursor-nvim' + mc.setup() + + local set = vim.keymap.set + + -- Add or skip cursor above/below the main cursor. + -- set({"n", "x"}, "", function() mc.lineAddCursor(-1) end) + -- set({ 'n', 'x' }, '', function() + -- mc.lineAddCursor(1) + -- end) + -- set({"n", "x"}, "", function() mc.lineSkipCursor(-1) end) + -- set({"n", "x"}, "", function() mc.lineSkipCursor(1) end) + + -- Add or skip adding a new cursor by matching word/selection + set({ 'n', 'x' }, '', function() + mc.matchAddCursor(1) + end) + -- set({ 'n', 'x' }, 's', function() + -- mc.matchSkipCursor(1) + -- end) + -- set({ 'n', 'x' }, 'N', function() + -- mc.matchAddCursor(-1) + -- end) + -- set({ 'n', 'x' }, 'S', function() + -- mc.matchSkipCursor(-1) + -- end) + + -- Add and remove cursors with control + left click. + set('n', '', mc.handleMouse) + set('n', '', mc.handleMouseDrag) + set('n', '', mc.handleMouseRelease) + + -- Disable and enable cursors. + set({ 'n', 'x' }, '', mc.toggleCursor) + + -- Mappings defined in a keymap layer only apply when there are + -- multiple cursors. This lets you have overlapping mappings. + mc.addKeymapLayer(function(layerSet) + -- Select a different cursor as the main one. + -- layerSet({ 'n', 'x' }, '', mc.prevCursor) + -- layerSet({ 'n', 'x' }, '', mc.nextCursor) + + -- Delete the main cursor. + layerSet({ 'n', 'x' }, 'x', mc.deleteCursor) + + -- Enable and clear cursors using escape. + layerSet('n', '', function() + if not mc.cursorsEnabled() then + mc.enableCursors() + else + mc.clearCursors() + end + end) + end) + + -- Customize how cursors look. + 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, + }, + { + 'rachartier/tiny-inline-diagnostic.nvim', + event = 'VeryLazy', -- Or `LspAttach` + priority = 1000, -- needs to be loaded in first + config = function() + require('tiny-inline-diagnostic').setup() + vim.diagnostic.config { virtual_text = false } -- Only if needed in your configuration, if you already have native LSP diagnostics + end, + }, + { + 'echasnovski/mini.indentscope', + event = 'VeryLazy', + config = function() + require('mini.indentscope').setup { + symbol = '│', + options = { try_as_border = true }, + } + end, + }, + + { + 'NickvanDyke/opencode.nvim', + dependencies = { 'folke/snacks.nvim' }, + ---@type opencode.Config + opts = { + -- Your configuration, if any + }, + -- stylua: ignore + keys = { + { 'ot', function() require('opencode').toggle() end, desc = 'Toggle embedded opencode', }, + { 'oa', function() require('opencode').ask() end, desc = 'Ask opencode', mode = 'n', }, + { 'oa', function() require('opencode').ask('@selection: ') end, desc = 'Ask opencode about selection', mode = 'v', }, + { 'op', function() require('opencode').select_prompt() end, desc = 'Select prompt', mode = { 'n', 'v', }, }, + { 'on', function() require('opencode').command('session_new') end, desc = 'New session', }, + { 'oy', function() require('opencode').command('messages_copy') end, desc = 'Copy last message', }, + { '', function() require('opencode').command('messages_half_page_up') end, desc = 'Scroll messages up', }, + { '', function() require('opencode').command('messages_half_page_down') end, desc = 'Scroll messages down', }, + }, + }, + { + 'olimorris/codecompanion.nvim', + tag = 'v17.33.0', -- Pin to stable version to avoid breaking changes + dependencies = { + 'ravitemer/mcphub.nvim', + 'nvim-lua/plenary.nvim', + 'nvim-treesitter/nvim-treesitter', + }, + }, + -- { + -- 'MeanderingProgrammer/render-markdown.nvim', + -- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, + -- ft = { 'markdown', 'codecompanion' }, + -- }, + { + 'echasnovski/mini.diff', + config = function() + local diff = require 'mini.diff' + diff.setup { + -- Enable git source + source = diff.gen_source.git(), + view = { + style = 'sign', -- Show git changes in sign column + signs = { add = '+', change = '~', delete = '-' }, + }, + } + end, + }, + { + 'MagicDuck/grug-far.nvim', + config = function() + require('grug-far').setup { + headerMaxWidth = 80, + } + end, + cmd = 'GrugFar', + keys = { + { 'S', 'GrugFar', desc = 'Search and Replace (grug-far)' }, + { + 'sw', + function() + require('grug-far').grug_far { prefills = { search = vim.fn.expand '' } } + end, + desc = 'Search current word', + }, + { + 'sf', + function() + require('grug-far').grug_far { prefills = { paths = vim.fn.expand '%' } } + end, + desc = 'Search in current file', + }, + }, + }, + { + 'folke/noice.nvim', + event = 'VeryLazy', + opts = { + lsp = { + progress = { + enabled = false, + }, + hover = { + enabled = false, + }, + signature = { + enabled = false, + }, + -- override markdown rendering so that **cmp** and other plugins use **Treesitter** + override = { + -- ['vim.lsp.util.convert_input_to_markdown_lines'] = true, + -- ['vim.lsp.util.stylize_markdown'] = true, + -- ['cmp.entry.get_documentation'] = true, -- requires hrsh7th/nvim-cmp + }, + }, + -- you can enable a preset for easier configuration + presets = { + bottom_search = true, -- use a classic bottom cmdline for search + command_palette = true, -- position the cmdline and popupmenu together + long_message_to_split = true, -- long messages will be sent to a split + inc_rename = false, -- enables an input dialog for inc-rename.nvim + lsp_doc_border = false, -- add a border to hover docs and signature help + }, + views = { + mini = { + size = { + width = 'auto', + height = 'auto', + }, + border = { + style = 'rounded', + }, + win_options = { + winblend = 10, + }, + }, + }, + }, + dependencies = { + 'MunifTanjim/nui.nvim', + }, + }, + { + 'luckasRanarison/tailwind-tools.nvim', + name = 'tailwind-tools', + build = ':UpdateRemotePlugins', + dependencies = { + 'nvim-treesitter/nvim-treesitter', + 'nvim-telescope/telescope.nvim', -- optional + 'neovim/nvim-lspconfig', -- optional + }, + opts = {}, -- your configuration + }, + { + 'supermaven-inc/supermaven-nvim', + config = function() + require('supermaven-nvim').setup { + keymaps = { + accept_suggestion = '', + accept_word = '<>', + }, + } + end, + }, + { + 'kristijanhusak/vim-dadbod-ui', + dependencies = { + { 'tpope/vim-dadbod', lazy = true }, + { 'kristijanhusak/vim-dadbod-completion', ft = { 'sql', 'mysql', 'plsql' }, lazy = true }, -- Optional + }, + cmd = { + 'DBUI', + 'DBUIToggle', + 'DBUIAddConnection', + 'DBUIFindBuffer', + }, + init = function() + -- Your DBUI configuration + vim.g.db_ui_use_nerd_fonts = 1 + end, + }, + -- colorschemes + -- { + -- 'ribru17/bamboo.nvim', + -- lazy = false, + -- priority = 1000, + -- config = function() + -- require('bamboo').setup { + -- -- optional configuration here + -- code_style = { + -- comments = { + -- italic = false, + -- }, + -- conditionals = { + -- italic = false, + -- }, + -- keywords = { + -- italic = false, + -- }, + -- functions = { + -- italic = false, + -- }, + -- namespaces = { + -- italic = false, + -- }, + -- parameters = { + -- italic = false, + -- }, + -- strings = { + -- italic = false, + -- }, + -- variables = { + -- italic = false, + -- }, + -- }, + -- highlights = { + -- -- Remove underlines from tag-related groups + -- ['htmlLink'] = { fg = '$blue' }, + -- ['@markup.link.label.html'] = { fg = '$blue' }, + -- ['@string.special.url.html'] = { fg = '$orange' }, + -- -- TSX/JSX related + -- ['@_jsx_element.tsx'] = { fg = '$blue' }, + -- ['@_jsx_element'] = { fg = '$blue' }, + -- ['@none.tsx'] = { fg = '$blue' }, + -- ['@spell.tsx'] = { fg = '$blue' }, + -- ['@markup.link.label.tsx'] = { fg = '$blue' }, + -- -- JavaScript/JSX related + -- ['@_jsx_element.javascript'] = { fg = '$blue' }, + -- ['@none.javascript'] = { fg = '$blue' }, + -- ['@spell.javascript'] = { fg = '$blue' }, + -- ['@markup.link.label.javascript'] = { fg = '$blue' }, + -- }, + -- } + -- require('bamboo').load() + -- end, + -- }, + -- { 'Mofiqul/dracula.nvim' }, + { + 'thesimonho/kanagawa-paper.nvim', + lazy = false, + priority = 1000, + opts = {}, + config = function() + vim.cmd 'colorscheme kanagawa-paper-ink' + end, + }, + -- { + -- 'rose-pine/neovim', + -- name = 'rose-pine', + -- config = function() end, + -- }, +} diff --git a/lua/custom/plugins/01-functions.lua b/lua/custom/plugins/01-functions.lua new file mode 100644 index 00000000000..491d4a1324f --- /dev/null +++ b/lua/custom/plugins/01-functions.lua @@ -0,0 +1,375 @@ +-- Notification function for job output +function notif(jobid, data, event, timeout, notifid) + if type(data) == 'number' then + return + end + + local output = table.concat(data, '\n') + if output ~= '' then + vim.notify(output, vim.log.levels.WARN, { + title = 'Notification', + timeout = timeout or 5000, + }) + end +end + +function CompileAndRun() + local filetype = GetFileType() + + -- Get full folder path of the current buffer + local folder_path = vim.fn.expand '%:p:h' + + -- get full path up to "labs" folder + local labs_fullfolder = folder_path:match '(.+labs)' + + -- Get the filename (with extension) of the current buffer + local filename_with_extension = vim.fn.expand '%:t' + + -- Get the filename without the extension + local filename_without_extension = vim.fn.expand '%:t:r' + + -- Get the file extension of the current buffer + local file_extension = vim.fn.fnamemodify(filename_with_extension, ':e') + + if file_extension == 'cjs' or file_extension == 'mjs' then + filetype = 'javascript' + elseif file_extension == 'md' then + filetype = 'markdown' + end + + local iste = true + + if filetype == 'cpp' then + vim.cmd( + ':tabnew | te g++ --std=c++17 ' + .. folder_path + .. '/' + .. filename_with_extension + .. ' -o ' + .. folder_path + .. '/' + .. filename_without_extension + .. '.out' + .. ' && ' + .. folder_path + .. '/' + .. filename_without_extension + .. '.out' + ) + elseif filetype == 'javascript' then + vim.cmd(':tabnew | te node ' .. folder_path .. '/' .. filename_with_extension) + elseif file_extension == 'py' then + vim.cmd(':tabnew | te python ' .. folder_path .. '/' .. filename_with_extension) + elseif filetype == 'typescript' then + vim.cmd(':tabnew | te ts-node ' .. folder_path .. '/' .. filename_with_extension) + elseif filetype == 'shell' then + vim.cmd(':tabnew | te bash ' .. folder_path .. '/' .. filename_with_extension) + else + vim.notify('Filetype ' .. filetype .. ' not supported for compile and run') + return + end + + if iste then + vim.api.nvim_feedkeys('i', 'n', true) + end +end + +-- livegrep search +function customSearchGrep() + local extension = vim.fn.input 'Enter File Extension (*): ' + local dirs = vim.fn.input 'Enter Search Directories (.): ' + + -- if escape is pressed, return + if extension == '' and dirs == '' then + return + end + + if extension == '' then + extension = '*' + end + if dirs == '' then + dirs = '.' + end + + vim.cmd('Telescope live_grep glob_pattern=*.{' .. extension .. '} search_dirs=' .. dirs) +end + +function SearchAndReplace(search, replace) + -- make sure search is not empty + if search == '' then + return + end + + local command = ':%s/' .. search .. '/' .. replace .. '/g' + local termcodes = vim.api.nvim_replace_termcodes(command, true, true, true) + vim.api.nvim_feedkeys(termcodes, 'n', true) +end + +function NextJSNewPage(pagename) + local page_path = 'src/app/pages/' .. pagename .. '/page.tsx' + local page_content = {} + page_content[#page_content + 1] = [["use client"]] + page_content[#page_content + 1] = [[import type { NextPage } from "next";]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[const Test: NextPage<{ someProps: string }> = (props) => {]] + page_content[#page_content + 1] = [[ return <>Hello Test;]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export default Test;]] + vim.fn.mkdir('src/app/pages/' .. pagename, 'p') + vim.fn.writefile(page_content, page_path) + vim.cmd('e ' .. page_path) +end + +function NextJSNewApiGet(pagename) + local page_path = 'src/app/api/' .. pagename .. '/route.ts' + local page_content = {} + page_content[#page_content + 1] = [[import { NextRequest, NextResponse } from "next/server";]] + page_content[#page_content + 1] = [[// export const runtime = "edge";]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const OPTIONS = async () => {]] + page_content[#page_content + 1] = [[ return NextResponse.json({]] + page_content[#page_content + 1] = [[ status: "ok",]] + page_content[#page_content + 1] = [[ });]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const GET = async (]] + page_content[#page_content + 1] = [[ req: NextRequest,]] + page_content[#page_content + 1] = [[ { params }: { params: { [s: string]: string } }]] + page_content[#page_content + 1] = [[) => {]] + page_content[#page_content + 1] = [[ try {]] + page_content[#page_content + 1] = [[ const url = new URL(req.url);]] + page_content[#page_content + 1] = [[ const {} = params ? params : {};]] + page_content[#page_content + 1] = [[ const searchParams = new URLSearchParams(url.search);]] + page_content[#page_content + 1] = [[ const test = searchParams.get("test");]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[ return NextResponse.json({ status: "ok", test });]] + page_content[#page_content + 1] = [[ } catch (error) {]] + page_content[#page_content + 1] = [[ return NextResponse.json({ err: (error as any).toString() });]] + page_content[#page_content + 1] = [[ }]] + page_content[#page_content + 1] = [[};]] + vim.fn.mkdir('src/app/api/' .. pagename, 'p') + vim.fn.writefile(page_content, page_path) + vim.cmd('e ' .. page_path) +end + +function NextJSNewApiPost(pagename) + local page_path = 'src/app/api/' .. pagename .. '/route.ts' + local page_content = {} + page_content[#page_content + 1] = [[import { NextRequest, NextResponse } from "next/server";]] + page_content[#page_content + 1] = [[// export const runtime = "edge";]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const OPTIONS = async () => {]] + page_content[#page_content + 1] = [[ return NextResponse.json({]] + page_content[#page_content + 1] = [[ status: "ok",]] + page_content[#page_content + 1] = [[ });]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const POST = async (]] + page_content[#page_content + 1] = [[ req: NextRequest,]] + page_content[#page_content + 1] = [[ { params }: { params: { [s: string]: string } }]] + page_content[#page_content + 1] = [[) => {]] + page_content[#page_content + 1] = [[ try {]] + page_content[#page_content + 1] = [[ const body = await req.json();]] + page_content[#page_content + 1] = [[ const {}: { [key: string]: string } = body;]] + page_content[#page_content + 1] = [[ const {} = params;]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[ return NextResponse.json({ status: "ok", body });]] + page_content[#page_content + 1] = [[ } catch (error) {]] + page_content[#page_content + 1] = [[ return NextResponse.json({ err: (error as any).toString() });]] + page_content[#page_content + 1] = [[ }]] + page_content[#page_content + 1] = [[};]] + vim.fn.mkdir('src/app/api/' .. pagename, 'p') + vim.fn.writefile(page_content, page_path) + vim.cmd('e ' .. page_path) +end + +function SvelteKitNewPage(pagename) + local page_path = 'src/routes/' .. pagename .. '/+page.svelte' + local page_content = {} + vim.fn.mkdir('src/routes/' .. pagename, 'p') + vim.fn.writefile(page_content, page_path) + vim.cmd('e ' .. page_path) +end + +function SvelteKitNewAPIPost(pagename) + local page_path = 'src/routes/api/' .. pagename .. '/+server.ts' + local page_content = {} + page_content[#page_content + 1] = [[import { json } from "@sveltejs/kit";]] + page_content[#page_content + 1] = [[import type { RequestHandler } from "./$types";]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[const headers = {]] + page_content[#page_content + 1] = [[ "Access-Control-Allow-Origin": "*",]] + page_content[#page_content + 1] = [[ "Access-Control-Allow-Methods": "GET,HEAD,PUT,PATCH,POST,DELETE",]] + page_content[#page_content + 1] = [[ "Access-Control-Allow-Headers": "Content-Type,authorization",]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const OPTIONS: RequestHandler = () => {]] + page_content[#page_content + 1] = [[ return new Response("", {]] + page_content[#page_content + 1] = [[ status: 200,]] + page_content[#page_content + 1] = [[ headers,]] + page_content[#page_content + 1] = [[ });]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[export const POST: RequestHandler = async ({ request, cookies }) => {]] + page_content[#page_content + 1] = [[ const { something } = await request.json();]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[ return json({ something }, { status: 200, headers });]] + page_content[#page_content + 1] = [[};]] + vim.fn.mkdir('src/routes/api/' .. pagename, 'p') + vim.fn.writefile(page_content, page_path) + vim.cmd('e ' .. page_path) +end + +function SvelteKitNewAPIGet(pagename) + local page_path = 'src/routes/api/' .. pagename .. '/+server.ts' + local page_content = {} + page_content[#page_content + 1] = [[import { json } from "@sveltejs/kit";]] + page_content[#page_content + 1] = [[import type { RequestHandler } from "./$types";]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[const headers = {]] + page_content[#page_content + 1] = [[ "Access-Control-Allow-Origin": "*",]] + page_content[#page_content + 1] = [[ "Access-Control-Allow-Methods": "GET,HEAD,PUT,PATCH,POST,DELETE",]] + page_content[#page_content + 1] = [[ "Access-Control-Allow-Headers": "Content-Type,authorization",]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const OPTIONS: RequestHandler = () => {]] + page_content[#page_content + 1] = [[ return new Response("", {]] + page_content[#page_content + 1] = [[ status: 200,]] + page_content[#page_content + 1] = [[ headers,]] + page_content[#page_content + 1] = [[ });]] + page_content[#page_content + 1] = [[};]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[export const GET: RequestHandler = ({ url, params }) => {]] + page_content[#page_content + 1] = [[ const q = url.searchParams.get("q");]] + page_content[#page_content + 1] = [[ // const slug = params.slug;]] + page_content[#page_content + 1] = [[ const number = Math.floor(Math.random() * 6) + 1;]] + page_content[#page_content + 1] = [[]] + page_content[#page_content + 1] = [[ return json({ number }, {status:200, headers});]] + page_content[#page_content + 1] = [[};]] + vim.fn.mkdir('src/routes/api/' .. pagename, 'p') + vim.fn.writefile(page_content, page_path) + vim.cmd('e ' .. page_path) +end + +-- NPM +function Npm_install() + local package_lock_exists = vim.fn.filereadable 'package-lock.json' == 1 + local yarn_lock_exists = vim.fn.filereadable 'yarn.lock' == 1 + local pnpm_lock_exists = vim.fn.filereadable 'pnpm-lock.yaml' == 1 + if package_lock_exists then + RunCommandInNewTab 'npm install --legacy-peer-deps' + elseif yarn_lock_exists then + RunCommandInNewTab 'yarn' + elseif pnpm_lock_exists then + RunCommandInNewTab 'pnpm install' + else + RunCommandInNewTab 'npm install --legacy-peer-deps' + end +end + +function GetFileType() + local filename = vim.fn.expand '%:t' + local extension = vim.fn.fnamemodify(filename, ':e') + + if extension == 'js' or extension == 'jsx' then + return 'javascript' + elseif extension == 'ts' or extension == 'tsx' then + return 'typescript' + elseif extension == 'cpp' or extension == 'c' then + return 'cpp' + elseif extension == 'sh' then + return 'shell' + else + return 'unknown' + end +end + +function fileExists(fileName) + local file = io.open(fileName, 'r') + if file then + file:close() + return true + else + return false + end +end + +function BuildAndNotify() + vim.notify('Building Project...', vim.log.levels.INFO, { + title = 'NPM', + timeout = 36000000, + }) + + vim.fn.jobstart('npm run build', { + on_stdout = function(id, data, e) + notif(id, data, e, 4000) + end, + on_stderr = function(id, data, e) + notif(id, data, e, 4000) + end, + on_exit = function(id, data, e) + notif(id, data, e, 4000) + end, + }) +end + +function RunCommandInNewTab(command) + vim.cmd(':-1tabnew | te ' .. command) +end + +function RunCommandAndNotify(command, timeout, title) + if timeout == nil then + timeout = 5000 -- 5 seconds instead of 10 hours! + end + if title == nil then + title = 'Run Command' + end + vim.notify(title, vim.log.levels.INFO, { + title = title, + timeout = timeout, + }) + + vim.fn.jobstart(command, { + on_stdout = function(id, data, e) + notif(id, data, e, 4000) + end, + on_stderr = function(id, data, e) + notif(id, data, e, 4000) + end, + on_exit = function(id, data, e) + notif(id, data, e, 4000) + end, + }) +end + +function CloseHiddenBuffers() + local all_buffers = vim.api.nvim_list_bufs() + local visible_buffers = {} + local closed_count = 0 + + -- Get all visible buffers from all tabs and windows + for _, tabpage in ipairs(vim.api.nvim_list_tabpages()) do + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tabpage)) do + local buf = vim.api.nvim_win_get_buf(win) + visible_buffers[buf] = true + end + end + + -- Close buffers that are not visible in any window + for _, buf in ipairs(all_buffers) do + if not visible_buffers[buf] and vim.api.nvim_buf_is_loaded(buf) then + local buf_name = vim.api.nvim_buf_get_name(buf) + if buf_name ~= '' and not vim.api.nvim_buf_get_option(buf, 'modified') then + vim.api.nvim_buf_delete(buf, { force = false }) + closed_count = closed_count + 1 + end + end + end + + vim.notify('Closed ' .. closed_count .. ' hidden buffers', vim.log.levels.INFO, { + title = 'Buffer Cleanup', + timeout = 2000, + }) +end + +return {} diff --git a/lua/custom/plugins/01-opts.lua b/lua/custom/plugins/01-opts.lua new file mode 100644 index 00000000000..b862f7cc97d --- /dev/null +++ b/lua/custom/plugins/01-opts.lua @@ -0,0 +1,133 @@ +-- noswap +vim.o.swapfile = false +vim.o.guifont = 'JetBrainsMono Nerd Font Mono:h15:sb' +vim.o.list = false + +-- disable spell for pandoc +vim.api.nvim_set_var('pandoc#spell#enabled', 0) + +-- markdown multi table format +vim.g.table_mode_corner_corner = '+' +vim.g.table_mode_header_fillchar = '=' + +-- markdown bullet and numbering indent +vim.o.breakindentopt = 'list:-1' + +-- lsp border +vim.o.winborder = 'rounded' + +sysname = vim.loop.os_uname().sysname +isWindows = sysname == 'Windows_NT' +isMac = sysname == 'Darwin' +isLinux = sysname == 'Linux' + +-- neovide auto focus +if vim.g.neovide then + vim.defer_fn(function() + vim.cmd 'NeovideFocus' + end, 200) + + if isWindows then + -- new neovide window in Windows + vim.keymap.set('n', '', ':silent !neovide', { + desc = 'Python', + noremap = true, + silent = true, + }) + vim.keymap.set('i', '', ':silent !neovide', { + desc = 'Python', + noremap = true, + silent = true, + }) + else + -- new neovide window in MACOS + vim.keymap.set('n', '', ':silent !neovide', { + desc = 'Python', + noremap = true, + silent = true, + }) + vim.keymap.set('i', '', ':silent !neovide', { + desc = 'Python', + noremap = true, + silent = true, + }) + end +else + -- new nvim-qt window in Android + vim.keymap.set('n', '', ':silent !nvim-qt', { + desc = 'Python', + noremap = true, + silent = true, + }) +end + +if isWindows then + vim.g.python3_host_prog = 'C:\\Users\\yokow\\miniforge3\\envs\\labs\\python.exe' +end + +-- independent clipboard +vim.opt.clipboard = '' + +-- set autoindent expandtab tabstop=2 shiftwidth=2 +vim.o.autoindent = true +vim.o.expandtab = true +vim.o.tabstop = 2 +vim.o.shiftwidth = 2 +vim.o.smartindent = true + +vim.o.foldlevel = 20 + +vim.opt.confirm = true +vim.g.have_nerd_font = true + +-- Enable line numbers (both absolute and relative) +vim.wo.relativenumber = true + +-- "Keep it Centered +-- Create nnoremap mappings +vim.api.nvim_set_keymap('n', 'n', 'nzzzv', { + noremap = true, + silent = true, +}) +vim.api.nvim_set_keymap('n', 'N', 'Nzzzv', { + noremap = true, + silent = true, +}) +vim.o.hlsearch = true + +vim.api.nvim_set_keymap('n', 'cpr', ':CphReceive', { + noremap = true, + silent = false, + desc = '[C]ompetitive [P]rogramming [R]eceive', +}) + +vim.api.nvim_set_keymap('n', 'cpt', ':CphTest', { + noremap = true, + silent = false, + desc = '[C]ompetitive [P]rogramming [T]est', +}) + +-- save Cursor +vim.cmd [[ + autocmd BufReadPost * + \ if @% !~# '\.git[\/\\]COMMIT_EDITMSG$' && + \ line("'\"") > 1 && + \ line("'\"") <= line("$") | + \ exe "normal! g`\"" | + \ endif +]] + +vim.o.encoding = 'utf-8' + +vim.g.markdown_fenced_languages = { 'html', 'python', 'lua', 'vim', 'typescript', 'javascript' } + +-- session options +vim.opt.sessionoptions = { + 'buffers', -- save all loaded buffers + 'curdir', -- save current directory + 'tabpages', -- save tab pages + 'winsize', -- save window sizes + 'terminal', -- save terminal state +} + +return {} diff --git a/lua/custom/plugins/50-git.lua b/lua/custom/plugins/50-git.lua new file mode 100644 index 00000000000..ed8e71af354 --- /dev/null +++ b/lua/custom/plugins/50-git.lua @@ -0,0 +1,236 @@ +-- "Git Mapping +function GitPullAndNotify() + vim.notify('Pull Processing...', vim.log.levels.INFO, { + title = 'Git', + timeout = 5000, -- 5 seconds instead of 10 hours + }) + + vim.fn.jobstart('git fetch --all && git pull --rebase', { + on_stdout = function(id, data, e) + notif(id, data, e, 4000) + end, + on_stderr = function(id, data, e) + notif(id, data, e, 4000) + end, + on_exit = function(id, data, e) + notif(id, data, e, 4000) + end, + }) +end + +function GitPushAndNotify() + vim.notify('Push Processing...', vim.log.levels.INFO, { + title = 'Git', + timeout = 5000, -- 5 seconds instead of 10 hours + }) + + vim.fn.jobstart('git pull --rebase && git push', { + on_stdout = function(id, data, e) + notif(id, data, e, 4000) + end, + on_stderr = function(id, data, e) + notif(id, data, e, 4000) + end, + on_exit = function(id, data, e) + notif(id, data, e, 4000) + end, + }) +end + +function OpenGitStatus() + -- Check if neogit is already open + local neogit_open = false + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + local name = vim.api.nvim_buf_get_name(buf) + if name:match 'NeogitStatus' then + neogit_open = true + vim.api.nvim_buf_delete(buf, { force = true }) + break + end + end + + if not neogit_open then + vim.cmd [[Neotree close]] + vim.cmd [[Neogit]] + end +end + +function CreateBranchAndPush(branchName) + RunCommandAndNotify('git checkout -b ' .. branchName .. ' && git push -u origin ' .. branchName) +end + +vim.keymap.set('n', '', OpenGitStatus, { + desc = '[G]it [S]tatus', +}) + +function GitCommit(commitMessage) + RunCommandAndNotify('git add . && git commit -m "' .. commitMessage .. '"') +end + +function RevertToCommitUnderCursor() + local commit = vim.fn.expand '' + + if commit == nil or commit == '' then + print 'No word under cursor.' + return + end + + local answer = vim.fn.input("Reset to commit '" .. commit .. "' and force push? (yes/no): ") + + if answer ~= 'yes' then + print 'Cancelled.' + return + end + + local cmd = string.format('git reset --hard %s && git push --force', commit) + RunCommandInNewTab(cmd) +end + +function UndoCommit() + local n = vim.fn.input 'Enter number of commits to undo: ' + RunCommandAndNotify('git reset --soft HEAD~' .. n) +end + +vim.keymap.set('n', 'gx', UndoCommit, { desc = 'Discard changes in last commit (Undo Commit)' }) +vim.keymap.set('n', 'gr', RevertToCommitUnderCursor, { desc = 'Reset HEAD to commit under cursor + force push' }) + +vim.keymap.set('n', 'ga', function() + local branchName = vim.fn.input 'Enter commit message: ' + if branchName == '' then + return + end + + CreateBranchAndPush(branchName) +end, { + desc = '[G]it [A]dd Branch', + noremap = true, + silent = false, +}) + +vim.keymap.set('n', 'gc', function() + local commitMessage = vim.fn.input 'Enter commit message: ' + if commitMessage == '' then + return + end + + GitCommit(commitMessage) +end, { + desc = '[G]it [C]ommit', + noremap = true, + silent = false, +}) + +vim.keymap.set('n', 'gh', ':Telescope git_bcommits', { + desc = '[G]it File [H]istory', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'gp', GitPushAndNotify, { + desc = '[G]it [P]ush', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'gu', GitPullAndNotify, { + desc = '[G]it P[u]ll', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'gd', 'Neogit diff', { + desc = '[G]it [D]iff', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'gb', 'Neogit branch', { + desc = '[G]it [B]ranch', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'gv', 'DiffviewOpen', { + desc = '[G]it [V]iew Diff (current file)', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'gl', ':Telescope git_commits', { + desc = '[G]it [L]og', + noremap = true, + silent = true, +}) + +vim.api.nvim_create_user_command('GitInitPush', function() + local username = 'yokowasis' + local repo = vim.fn.fnamemodify(vim.loop.cwd(), ':t') + if repo == '' then + print 'Could not determine repository name from current directory' + return + end + local remote = 'https://github.com/' .. username .. '/' .. repo .. '.git' + local cmd = 'git init && git add . && git commit -m "Initial commit" && git branch -M main && gh repo create ' + .. repo + .. ' --private --source=. --remote=origin --push' + vim.cmd('terminal ' .. cmd) +end, {}) + +vim.keymap.set('n', 'gi', ':GitInitPush', { + desc = '[G]it [I]nit and Push', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'coo', function() + -- Get current line and extract branch name, then checkout with neogit + local line = vim.api.nvim_get_current_line() + local branch = line:match 'origin/(.+)' + if branch then + vim.cmd('Neogit branch checkout ' .. branch) + else + vim.notify('No origin branch found on current line', vim.log.levels.WARN) + end +end, { + desc = 'Checkout Origin Branch', + noremap = true, + silent = true, +}) + +return { + { + 'NeogitOrg/neogit', + dependencies = { + 'nvim-lua/plenary.nvim', -- required + 'sindrets/diffview.nvim', -- optional - for diff view + 'nvim-telescope/telescope.nvim', -- optional - for telescope integration + }, + config = function() + require('neogit').setup { + -- Neogit configuration + integrations = { + telescope = true, + diffview = true, + }, + sections = { + untracked = { + folded = false, + }, + unstaged = { + folded = false, + }, + staged = { + folded = false, + }, + }, + } + + -- Branch-specific keymaps + vim.keymap.set('n', 'gb', 'Neogit branch', { + desc = '[G]it [B]ranch menu', + noremap = true, + silent = true, + }) + end, + }, +} diff --git a/lua/custom/plugins/51-navigation.lua b/lua/custom/plugins/51-navigation.lua new file mode 100644 index 00000000000..a6fca5dcaae --- /dev/null +++ b/lua/custom/plugins/51-navigation.lua @@ -0,0 +1,77 @@ +-- Smart buffer delete function (for ) +local function smart_buffer_delete() + local buffers = vim.fn.getbufinfo { buflisted = 1 } + local listed_buffers = {} + + -- Count only listed buffers (exclude help, quickfix, etc.) + for _, buf in ipairs(buffers) do + if buf.listed == 1 then + table.insert(listed_buffers, buf) + end + end + + -- If this is the last buffer, quit Neovim + if #listed_buffers <= 1 then + vim.cmd 'quit' + else + vim.cmd 'bdelete' + end +end + +-- "Tab Navigation +vim.keymap.set('n', '', ':tabnew', { + desc = 'New Tab', + noremap = true, + silent = true, +}) +vim.keymap.set('n', 'tn', ':-1tabnew', { + desc = 'New Tab To The Left', + noremap = true, + silent = true, +}) +vim.keymap.set('n', '', ':tabnext', { + desc = 'Next Tab', + noremap = true, + silent = true, +}) +vim.keymap.set('n', '', ':tabprevious', { + desc = 'Previous Tab', + noremap = true, + silent = true, +}) +vim.keymap.set('n', '', ':tabclose', { + desc = 'Close Tab', + noremap = true, + silent = true, +}) + +-- Window splitting +vim.keymap.set('n', 'sv', ':vsplit', { + desc = '[S]plit [V]ertical', + noremap = true, + silent = true, +}) +vim.keymap.set('n', 'sh', ':split', { + desc = '[S]plit [H]orizontal', + noremap = true, + silent = true, +}) +vim.keymap.set('n', 'sq', 'q', { + desc = '[S]plit [Q]uit Window', + noremap = true, + silent = true, +}) + +-- nerdtree +vim.keymap.set('n', '', ':Neotree reveal', { + desc = 'Show File Explorer', + noremap = true, + silent = true, +}) +vim.keymap.set('i', '', ':Neotree reveal', { + desc = 'Show File Explorer', + noremap = true, + silent = true, +}) + +return {} diff --git a/lua/custom/plugins/52-terminal.lua b/lua/custom/plugins/52-terminal.lua new file mode 100644 index 00000000000..a5d28637a89 --- /dev/null +++ b/lua/custom/plugins/52-terminal.lua @@ -0,0 +1,56 @@ +TerminalShell = '' + +if isWindows then + vim.cmd [[command! SaveInitVim :tabnew | exe ':te git -C '. stdpath("config") .' add . & git -C ' . stdpath("config") . ' commit -m save & git -C ' . stdpath("config") . ' push']] + vim.cmd [[command! SaveGlobalSnippets :tabnew | exe ':te git -C '. stdpath("config") .'/../../../git/friendly-snippets add . & git -C '. stdpath("config") .'/../../../git/friendly-snippets commit -m save & git -C '. stdpath("config") .'/../../../git/friendly-snippets push']] + vim.cmd [[command! LoadGlobalSnippets :tabnew | exe ':te git -C '. stdpath("config") .'/../../../git/friendly-snippets pull']] + + TerminalShell = 'pwsh' +else + vim.cmd [[command! SaveInitVim :tabnew | exe ':te git -C '. stdpath("config") .' add . && git -C ' . stdpath("config") . ' commit -m save && git -C ' . stdpath("config") . ' push']] + vim.cmd [[command! SaveGlobalSnippets :tabnew | exe ':te git -C ~/git/friendly-snippets add . && git -C ~/git/friendly-snippets commit -m save && git -C ~/git/friendly-snippets push']] + vim.cmd [[command! LoadGlobalSnippets :tabnew | exe ':te git -C ~/git/friendly-snippets pull']] + + TerminalShell = 'bash' +end + +vim.cmd [[command! LoadInitVim :tabnew | exe ':te git -C '. stdpath("config") .' pull' ]] +vim.cmd [[command! EditInitVim :tabnew | exe 'edit '. stdpath('config').'/lua/custom/plugins/00-init.lua']] +vim.cmd [[command! EditSnippets :lua require("luasnip.loaders").edit_snippet_files()]] + +-- open terminal +vim.keymap.set('n', '``', ':horizontal terminal ' .. TerminalShell .. 'J-----', { + desc = 'Open Terminal', + noremap = false, + silent = true, +}) + +-- vertical terminal +vim.keymap.set('n', '`v', 'v:terminal ' .. TerminalShell .. '', { + desc = 'Open Terminal [V]ertical', + noremap = false, + silent = true, +}) + +-- close terminal +vim.keymap.set('t', '`', ':q', { + desc = '', + noremap = true, + silent = true, +}) + +-- switch window +vim.keymap.set('t', '', '', { + desc = '', + noremap = true, + silent = true, +}) + +-- esc to normal mode in terminal +vim.keymap.set('t', '', '', { + desc = '', + noremap = true, + silent = true, +}) + +return {} diff --git a/lua/custom/plugins/53-window.lua b/lua/custom/plugins/53-window.lua new file mode 100644 index 00000000000..7126e687ec0 --- /dev/null +++ b/lua/custom/plugins/53-window.lua @@ -0,0 +1,23 @@ +-- "RESIZE WINDOW +vim.keymap.set('n', '.', ':vertical resize -10', { + desc = '', + noremap = true, + silent = true, +}) +vim.keymap.set('n', ',', ':vertical resize +5', { + desc = '', + noremap = true, + silent = true, +}) +vim.keymap.set('n', "'", ':horizontal resize -5', { + desc = '', + noremap = true, + silent = true, +}) +vim.keymap.set('n', ';', ':horizontal resize +2', { + desc = '', + noremap = true, + silent = true, +}) + +return {} diff --git a/lua/custom/plugins/55-startup.lua b/lua/custom/plugins/55-startup.lua new file mode 100644 index 00000000000..17894e949e9 --- /dev/null +++ b/lua/custom/plugins/55-startup.lua @@ -0,0 +1,13 @@ +if vim.fn.argc() == 0 then + vim.defer_fn(function() + local session_name = vim.fn.fnamemodify(vim.fn.getcwd(), ':t') .. '.vim' + local session_path = vim.fn.expand('~/' .. session_name) + if vim.fn.filereadable(session_path) == 1 then + vim.cmd('silent! source ' .. vim.fn.fnameescape(session_path)) + vim.notify('Session loaded: ' .. session_name, vim.log.levels.INFO) + vim.cmd 'silent! GuessIndent' + end + end, 300) -- Delay the session load by 100ms +end + +return {} diff --git a/lua/custom/plugins/56-jupyter-plugin.lua b/lua/custom/plugins/56-jupyter-plugin.lua new file mode 100644 index 00000000000..09de851909e --- /dev/null +++ b/lua/custom/plugins/56-jupyter-plugin.lua @@ -0,0 +1,4 @@ +return { + 'Vigemus/iron.nvim', +} + diff --git a/lua/custom/plugins/57-jupyter-setup.lua b/lua/custom/plugins/57-jupyter-setup.lua new file mode 100644 index 00000000000..f5f1ce67f4c --- /dev/null +++ b/lua/custom/plugins/57-jupyter-setup.lua @@ -0,0 +1,150 @@ +-- setup iron nvim + +local iron = require 'iron.core' +local view = require 'iron.view' +local common = require 'iron.fts.common' + +iron.setup { + config = { + -- Whether a repl should be discarded or not + scratch_repl = true, + -- Your repl definitions come here + repl_definition = { + sh = { + -- Can be a table or a function that + -- returns a table (see below) + command = { 'zsh' }, + }, + python = { + command = { 'python3' }, -- or { "ipython", "--no-autoindent" } + format = common.bracketed_paste_python, + block_dividers = { '# %%', '#%%' }, + env = { PYTHON_BASIC_REPL = '1' }, --this is needed for python3.13 and up. + }, + }, + -- set the file type of the newly created repl to ft + -- bufnr is the buffer id of the REPL and ft is the filetype of the + -- language being used for the REPL. + repl_filetype = function(bufnr, ft) + return ft + -- or return a string name such as the following + -- return "iron" + end, + -- Send selections to the DAP repl if an nvim-dap session is running. + dap_integration = true, + -- How the repl window will be displayed + -- See below for more information + repl_open_cmd = view.bottom(40), + + -- repl_open_cmd can also be an array-style table so that multiple + -- repl_open_commands can be given. + -- When repl_open_cmd is given as a table, the first command given will + -- be the command that `IronRepl` initially toggles. + -- Moreover, when repl_open_cmd is a table, each key will automatically + -- be available as a keymap (see `keymaps` below) with the names + -- toggle_repl_with_cmd_1, ..., toggle_repl_with_cmd_k + -- For example, + -- + -- repl_open_cmd = { + -- view.split.vertical.rightbelow("%40"), -- cmd_1: open a repl to the right + -- view.split.rightbelow("%25") -- cmd_2: open a repl below + -- } + }, + -- Iron doesn't set keymaps by default anymore. + -- You can set them here or manually add keymaps to the functions in iron.core + keymaps = { + toggle_repl = 'rr', -- toggles the repl open and closed. + -- If repl_open_command is a table as above, then the following keymaps are + -- available + -- toggle_repl_with_cmd_1 = "rv", + -- toggle_repl_with_cmd_2 = "rh", + restart_repl = 'jr', -- calls `IronRestart` to restart the repl + send_motion = 'sc', + visual_send = 'sc', + send_file = 'ja', + send_line = 'sl', + send_paragraph = 'sp', + send_until_cursor = 'su', + send_mark = 'sm', + send_code_block = 'sb', + send_code_block_and_move = 'sn', + mark_motion = 'mc', + mark_visual = 'mc', + remove_mark = 'md', + cr = 's', + interrupt = 's', + exit = 'jq', + clear = 'jl', + }, + -- If the highlight is on, you can change how it looks + -- For the available options, check nvim_set_hl + highlight = { + italic = true, + }, + ignore_blank_lines = true, -- ignore blank lines when sending visual select lines +} + +-- iron also has a list of commands, see :h iron-commands for all available commands +vim.keymap.set('n', 'rf', 'IronFocus') +vim.keymap.set('n', 'rh', 'IronHide') + +local function send_cell() + local iron = require 'iron.core' + + local buf = vim.api.nvim_get_current_buf() + local cursor = vim.api.nvim_win_get_cursor(0)[1] -- 1-based + local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + + local start_line = 1 + local end_line = #lines + + -- search upward for previous "# %%" + for i = cursor, 1, -1 do + if lines[i]:match '^# %%%%' then + start_line = i + 1 + break + end + end + + -- search downward for next "# %%" + for i = cursor + 1, #lines do + if lines[i]:match '^# %%%%' then + end_line = i - 1 + break + end + end + + if start_line > end_line then + return + end + + -- collect lines of the cell + local cell_lines = vim.api.nvim_buf_get_lines(buf, start_line - 1, end_line, false) + + -- send to REPL + iron.send(nil, cell_lines) +end + +-- keymaps + +vim.keymap.set('n', 'jm', 'i# %%', { + noremap = true, + silent = false, + desc = '[J]upyter Create [M]ark', +}) + +vim.keymap.set('n', 'ji', ':vsplit:IronReplHere', { + noremap = true, + silent = false, + desc = '[J]upyter [I]nit', +}) + +vim.keymap.set('v', 'jv', ":lua require('iron.core').visual_send()", { + noremap = true, + silent = false, + desc = '[J]upyter [V]isual Send', +}) + +vim.keymap.set('n', 'jj', send_cell, { desc = 'Iron: send current # %% cell' }) + +return {} diff --git a/lua/custom/plugins/97-setup-plugins.lua b/lua/custom/plugins/97-setup-plugins.lua new file mode 100644 index 00000000000..9dd10d83995 --- /dev/null +++ b/lua/custom/plugins/97-setup-plugins.lua @@ -0,0 +1,127 @@ +local ls = require 'luasnip' +ls.config.set_config { + store_selection_keys = '', +} +ls.filetype_extend('svelte', { 'typescript', 'html' }) + +require('luasnip.loaders.from_vscode').lazy_load { + paths = { '~/git/friendly-snippets' }, +} + +vim.keymap.set({ 'i', 's' }, '', function() + if require('luasnip').choice_active() then + require('luasnip').change_choice(1) + end +end, { desc = 'LuaSnip: next choice' }) + +vim.keymap.set({ 'i', 's' }, '', function() + if require('luasnip').choice_active() then + require('luasnip').change_choice(-1) + end +end, { desc = 'LuaSnip: previous choice' }) + +-- close window with x if it's not a main window +vim.api.nvim_create_autocmd('FileType', { + pattern = { 'checkhealth', 'fugitive*', 'git', 'help', 'lspinfo', 'netrw', 'notify', 'qf', 'query' }, + callback = function() + vim.keymap.set('n', 'x', vim.cmd.close, { + desc = 'Close the current buffer', + buffer = true, + }) + end, +}) + +-- Folding settings +vim.opt.foldmethod = 'indent' + +require('nvim-treesitter.install').compilers = { 'clang', 'gcc', 'zig' } + +-- save folded state +local viewdir = vim.fn.stdpath 'state' .. '/view' + +vim.o.viewdir = viewdir +vim.o.viewoptions = 'cursor,folds' -- only save cursor + folds (not options, etc.) + +-- Create the view directory if it doesn't exist +vim.fn.mkdir(viewdir, 'p') + +vim.api.nvim_create_augroup('remember_folds', { clear = true }) +vim.api.nvim_create_autocmd('BufWinLeave', { + group = 'remember_folds', + pattern = '*', + callback = function() + vim.cmd 'silent! mkview' + end, +}) +vim.api.nvim_create_autocmd('BufWinEnter', { + group = 'remember_folds', + pattern = '*', + callback = function() + vim.cmd 'silent! loadview' + end, +}) + +require('guess-indent').setup {} +require('conform').setup { + formatters = { + ['pretty-php'] = { + prepend_args = { '-s2' }, + }, + }, +} + +-- Setup clangd with system preference (if system clangd is available and preferred) +-- This will override the main lspconfig setup with additional arguments +local has_system_clangd = vim.fn.executable('clangd') == 1 +local prefer_system_clangd = true -- Set to false if you want to use Mason's clangd + +if has_system_clangd and prefer_system_clangd then + require('lspconfig').clangd.setup { + cmd = { 'clangd', '--background-index' }, + } +end + +require('codecompanion').setup { + adapters = { + http = { + my_custom_openai = function() + return require('codecompanion.adapters').extend('openai_compatible', { + name = 'my_custom_openai', + formatted_name = 'Custom OpenAI', + env = { + api_key = 'OPENAI_API_KEY', + url = 'https://chatgpt-api.sg.app.web.id', + chat_url = '/v1/chat/completions', + models_endpoint = '/v1/models', + }, + schema = { + model = { + order = 1, + mapping = 'parameters', + type = 'enum', + desc = 'ID of the model to use', + default = 'gpt-4o', + choices = { 'gpt-4o', 'gpt-4o-mini', 'gpt-3.5-turbo' }, + }, + }, + }) + end, + }, + acp = { + gemini_cli = function() + local adapter = require 'codecompanion.adapters.acp.gemini_cli' + return require('codecompanion.adapters.acp').new(adapter) + end, + }, + }, + strategies = { + chat = { + adapter = 'my_custom_openai', + }, + inline = { + adapter = 'my_custom_openai', + }, + }, +} + +return {} diff --git a/lua/custom/plugins/98-bookmarks.lua b/lua/custom/plugins/98-bookmarks.lua new file mode 100644 index 00000000000..a564707544f --- /dev/null +++ b/lua/custom/plugins/98-bookmarks.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/custom/plugins/99-keymaps.lua b/lua/custom/plugins/99-keymaps.lua new file mode 100644 index 00000000000..b6716888624 --- /dev/null +++ b/lua/custom/plugins/99-keymaps.lua @@ -0,0 +1,489 @@ +-- Create a mapping for compiling and running code +vim.keymap.set('n', 'cr', CompileAndRun, { + noremap = true, + silent = false, + desc = '[C]ompile and [R]un', +}) + +-- emmet +vim.api.nvim_set_keymap('i', '', '(emmet-expand-abbr)', { + noremap = true, + silent = true, +}) + +-- "Copy Paste from OS Clipboard +vim.keymap.set('v', '', '"+p:silent! %s/\\r//g', { + desc = '[P]aste from system clipboard', + noremap = true, + silent = true, +}) +vim.keymap.set('n', '', '"+p:silent! %s/\\r//g', { + desc = '[P]aste from system clipboard', + noremap = true, + silent = true, +}) +vim.keymap.set('i', '', '"+p:silent! %s/\\r//ga', { + desc = '[P]aste from system clipboard', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', '', '"+p:silent! %s/\\r//g', { + desc = '[P]aste from system clipboard', + noremap = true, + silent = true, +}) +vim.keymap.set('i', '', '*:silent! %s/\\r//g', { + desc = '[P]aste from system clipboard', + noremap = true, + silent = true, +}) + +vim.keymap.set('x', '', '"+y', { + desc = '[Y]ank to system clipboard', + noremap = true, + silent = true, +}) +vim.keymap.set('x', '', '"+y', { + desc = '[Y]ank to system clipboard', + noremap = true, + silent = true, +}) + +-- Map Ctrl+S to save +vim.keymap.set('n', '', ':w', { + desc = '[^s] Save Current File', + noremap = true, + silent = true, +}) +vim.keymap.set('i', '', ':wa', { + desc = '[^s] Save Current File', + noremap = true, + silent = true, +}) + +-- "Toggle Wrap +vim.keymap.set('n', 'ww', ':set wrap!', { + desc = '[W]ord [W]rap', + noremap = true, + silent = true, +}) + +-- +-- "keep visual mode after indent +vim.keymap.set('v', '>', '>gv', { + desc = '', + noremap = true, + silent = true, +}) + +vim.keymap.set('v', '<', '', '"_d', { + desc = 'Black Hole Delete', + noremap = true, + silent = true, +}) +vim.keymap.set('x', '', '"_d', { + desc = 'Black Hole Delete', + noremap = true, + silent = true, +}) + +-- telescope keymap +vim.keymap.set('n', '?', ':Telescope keymaps', { + desc = 'Show Keymaps', + noremap = true, + silent = true, +}) + +-- macos arrow navigation +vim.api.nvim_set_keymap('', '', '', { + noremap = true, +}) +vim.api.nvim_set_keymap('', '', '', { + noremap = true, +}) + +vim.api.nvim_set_keymap('i', '', 'b', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('i', '', 'w', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('x', '', 'b', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('x', '', 'w', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('n', '', 'b', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('n', '', 'w', { + noremap = true, + silent = false, +}) + +-- macos, neovide, alacritty terminal +vim.api.nvim_set_keymap('i', '', '"*pa', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('n', '', '"*p', { + noremap = true, + silent = false, +}) + +vim.api.nvim_set_keymap('n', '', '', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('n', '', '', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('i', '', '', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('i', '', '', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('x', '', '', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('x', '', '', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('n', '', 'gg', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('n', '', 'G', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('i', '', 'gg', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('i', '', 'G', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('x', '', 'gg', { + noremap = true, + silent = false, +}) +vim.api.nvim_set_keymap('x', '', 'G', { + noremap = true, + silent = false, +}) + +vim.keymap.set('n', '', ':w', { + desc = '[^s] Save Current File', + noremap = true, + silent = true, +}) +vim.keymap.set('i', '', ':wa', { + desc = '[^s] Save Current File', + noremap = true, + silent = true, +}) + +-- npm / yarn operation +vim.keymap.set('n', 'rb', function() + RunCommandAndNotify 'npm run build' +end, { + noremap = true, + silent = false, + desc = '[R]un [B]uild', +}) +vim.keymap.set('n', 'rd', function() + RunCommandInNewTab 'npm run dev' +end, { + noremap = true, + silent = false, + desc = '[R]un [D]ev', +}) +vim.keymap.set('n', 'ri', Npm_install, { + noremap = true, + silent = false, + desc = '[R]un npm [I]nstall', +}) +vim.keymap.set('n', 'rl', function() + RunCommandInNewTab 'five-server' +end, { + noremap = true, + silent = false, + desc = '[R]un npm [L]ive Server', +}) + +-- clear highlight after search by pressing return +vim.api.nvim_set_keymap('n', 'cl', ':noh:%s/\r//g', { + noremap = true, + silent = true, + desc = '[C][l]ear Search and NewLine Character', +}) + +-- cd to current directory +vim.api.nvim_set_keymap('n', 'cd', ':cd %:p:h:pwd', { + noremap = true, + silent = false, + desc = '[C]hange [D]irectory to current file', +}) + +-- Session +vim.api.nvim_set_keymap('n', 'sel', ":execute 'source ' . fnameescape(expand('~/' . fnamemodify(getcwd(), ':t') . '.vim'))", { + noremap = true, + silent = false, + desc = '[Se]ssion [L]oad', +}) + +vim.api.nvim_set_keymap('n', 'nq', ":execute 'mksession! ' . fnameescape(expand('~/' . fnamemodify(getcwd(), ':t') . '.vim')):qa!", { + noremap = true, + silent = false, + desc = '[N]vim [Q]uit', +}) + +-- vim signature help +vim.keymap.set('n', 'k', vim.lsp.buf.signature_help, { + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'sne', ':EditSnippets', { + noremap = true, + silent = false, + desc = '[Sn]ippets [E]dit', +}) + +vim.keymap.set('n', 'snf', ':%s/"/\\\\"/gggVG10>gg0v_y:%s/0/\\":%s/\\n/\\",\\r:%s/\\n\\",/\\r\\"\\",', { + noremap = true, + silent = false, + desc = '[Sn]ippets [F]ormat', +}) + +-- Noice Notification +vim.keymap.set('n', 'snn', ':NoiceAll', { + noremap = true, + silent = false, + desc = '[S]how [N]oice [N]otification', +}) + +-- auto format +vim.keymap.set('n', 'fmf', 'gg=G', { + noremap = true, + silent = false, + desc = '[F]ormat [M]anual [F]ormat', +}) + +-- Search and Replace +vim.keymap.set('n', 'sar', ':%s///g', { + noremap = true, + silent = false, + desc = '[S]earch [A]nd [R]eplace', +}) + +-- Search and Replace +vim.keymap.set('v', 'sar', '"zy:%s/z//g', { + noremap = true, + silent = false, + desc = '[S]earch [A]nd [R]eplace', +}) + +-- Search and Replace with Number of rows +vim.keymap.set('v', 'san', function() + -- Get the selected text + vim.cmd 'normal! "zy' + local selected = vim.fn.getreg 'z' + + -- Ask for number of rows + local rows = vim.fn.input 'Number of rows to affect: ' + if rows == '' then + print 'Operation cancelled' + return + end + + -- Get current line number + local current_line = vim.fn.line '.' + local end_line = current_line + tonumber(rows) - 1 + + -- Generate the command but don't execute it + local cmd = ':' .. current_line .. ',' .. end_line .. 's/' .. vim.fn.escape(selected, '/') .. '//g' + vim.fn.feedkeys(cmd .. vim.api.nvim_replace_termcodes('', true, false, true)) +end, { + noremap = true, + silent = false, + desc = '[S]earch [A]nd Replace with [N]umber of rows starting from current line', +}) + +-- Search and Visual Replace +vim.keymap.set('v', 'svr', ':s/"//g', { + noremap = true, + silent = false, + desc = '[S]earch And [V]isual [R]eplace', +}) + +-- Search and Visual Replace +vim.keymap.set('v', 'sk', ':s/\\(.*\\)/\\1/g', { + noremap = true, + silent = false, + desc = '[S]earch [K]irby', +}) + +vim.keymap.set('n', 'fnp', function() + NextJSNewPage(vim.fn.input 'Enter Page Name: ') +end, { + noremap = true, + silent = false, + desc = 'New [P]age', +}) +vim.keymap.set('n', 'fnr', function() + NextJSNewApiPost(vim.fn.input 'Enter Route Name: ') +end, { + noremap = true, + silent = false, + desc = 'New API [R]oute POST', +}) +vim.keymap.set('n', 'fng', function() + NextJSNewApiGet(vim.fn.input 'Enter Route Name: ') +end, { + noremap = true, + silent = false, + desc = 'New [G]et Route', +}) +vim.keymap.set('n', 'fsp', function() + SvelteKitNewPage(vim.fn.input 'Enter Page Name: ') +end, { + noremap = true, + silent = false, + noremap = true, + silent = false, + desc = 'New [P]age', +}) +vim.keymap.set('n', 'fsr', function() + SvelteKitNewAPIPost(vim.fn.input 'Enter Route Name: ') +end, { + noremap = true, + silent = false, + desc = 'New Post [R]oute', +}) +vim.keymap.set('n', 'fsg', function() + SvelteKitNewAPIGet(vim.fn.input 'Enter Route Name: ') +end, { + noremap = true, + silent = false, + desc = 'New [G]et Route', +}) + +vim.keymap.set( + 'n', + '', + function() + SearchAndReplace(vim.fn.input 'Enter Search Term: ', vim.fn.input 'Enter Replace Term: ') + end, + -- ":%s/vim.fn.input('Enter Search Term: ')/vim.fn.input('Enter Replace Term: ')/g", + { + noremap = true, + silent = false, + desc = '[S]earch and [R]eplace', + } +) + +vim.keymap.set('n', 'sg', ':Telescope live_grep', { + desc = '[S]earch by [G]rep', + noremap = true, + silent = false, +}) + +vim.keymap.set('n', 'sc', customSearchGrep, { + desc = '[S]earch by [G]rep [C]ustom', + noremap = true, + silent = false, +}) + +-- close other windows except this one +vim.keymap.set('n', 'x', ':on', { + desc = 'Close all other windows', + noremap = true, + silent = true, +}) + +vim.keymap.set('n', 'rr', ':e!', { + noremap = true, + silent = false, + desc = '[R]eload [R]esource', +}) + +vim.keymap.set('n', 'rp', ':LspRestart', { + noremap = true, + silent = false, + desc = '[R]eload LS[P]', +}) + +-- code companion +vim.keymap.set('n', 'ct', ':CodeCompanionChat', { + noremap = true, + silent = false, + desc = '[C]odeCompanion [T]alk', +}) +vim.keymap.set('n', 'cc', ':CodeCompanion #{buffer} ', { + noremap = true, + silent = false, + desc = '[C]ode [C]ompanion', +}) +vim.keymap.set('v', 'cc', ':CodeCompanion ', { + noremap = true, + silent = false, + desc = '[C]ode [C]ompanion', +}) + +vim.keymap.set('n', 'fc', function() + vim.fn.setreg('+', vim.fn.expand '%:p') + print('Copied filename to clipboard: ' .. vim.fn.expand '%:p') +end, { + noremap = true, + silent = true, + desc = '[F]ile [C]opy current file path to clipboard', +}) + +vim.keymap.set('n', 'fe', function() + os.execute 'explorer.exe .' +end, { + noremap = true, + silent = true, + desc = '[F]ile [E]xplorer on current file folder', +}) + +vim.keymap.set('n', 'gd', require('telescope.builtin').lsp_definitions, { noremap = true, silent = true }) + +-- Close all hidden/background buffers +vim.keymap.set('n', 'bo', CloseHiddenBuffers, { + noremap = true, + silent = false, + desc = '[B]uffer [O]nly - Close all hidden buffers', +}) + +-- "Database Toggle UI" +vim.keymap.set('n', 'db', ':DBUIToggle', { + desc = '[D]ata[b]ase', + noremap = true, + silent = true, +}) + +return {} diff --git a/lua/custom/plugins/blank.lua b/lua/custom/plugins/blank.lua new file mode 100644 index 00000000000..a564707544f --- /dev/null +++ b/lua/custom/plugins/blank.lua @@ -0,0 +1 @@ +return {} diff --git a/lua/custom/plugins/readme.md b/lua/custom/plugins/readme.md new file mode 100644 index 00000000000..6a3423892ae --- /dev/null +++ b/lua/custom/plugins/readme.md @@ -0,0 +1,96 @@ +# Neovim Setup and Notes + +## TODO + +The very first thing you should do is to run the command `:Tutor` in Neovim. + +## Notes + +### SNIPPET/LSP + +- Trigger with ``. +- For `TM_SELECTED_TEXT`, block the text and then ``. +- Move between choices with `` and ``. +- Move between placeholder with `` and ``. + +### Copilot + +- Trigger with ``. + +--- + +## Setup Instructions + +### General + +- Install required Python packages: + ```bash + pip install pynvim neovim + ``` + +### Paste Image + +- Install Pillow: + ```bash + pip install pillow + ``` + +### Jupyter Setup + +1. Set up a Conda environment. +2. Install the following packages: + ```bash + pip install ipykernel jupytext pynvim jupyter_client cairosvg plotly kaleido pyperclip nbformat + ``` + +### Install All Dependencies + +- Run the following command: + ```bash + pip install pynvim neovim pillow ipykernel jupytext pynvim jupyter_client cairosvg plotly kaleido pyperclip nbformat + :UpdateRemotePlugins + ``` + +### Windows Specific + +- Copy the `rplugin.vim` file: + ```bash + cp ./rplugin.vim C:\Users\yokow\AppData\Local\nvim-data/rplugin.vim + ``` + +### Initialization + +1. Add environment to Molten (e.g., `labs`): + ```bash + python -m ipykernel install --user --name labs --display-name labs + ``` +2. Initialize Jupyter Labs: + ```bash + jupyter kernel --kernel=labs + ``` + +--- + +## iTerm2 Setup + +- Keybindings: + - `#s` -> `` + - `!Up` -> `` + - `#Up` -> `` + - `!Down` -> `` + - `#Down` -> `` + - `#Left` -> `` + - `#Right` -> `` + +--- + +## Lemonade Setup + +- Install Lemonade: + ```bash + go install github.com/lemonade-command/lemonade@latest + ``` +- Start the Lemonade server: + ```bash + ~/go/bin/lemonade server + ``` From 1a6d9acc8c69c4deeaf29d1530348dd892a176ff Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:04:20 +0800 Subject: [PATCH 02/12] options --- init.lua | 8 ++-- init.lua.bak | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 init.lua.bak diff --git a/init.lua b/init.lua index 3593ca2e194..2efb0515d4e 100644 --- a/init.lua +++ b/init.lua @@ -91,7 +91,7 @@ vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' -- Set to true if you have a Nerd Font installed and selected in the terminal -vim.g.have_nerd_font = false +vim.g.have_nerd_font = true -- [[ Setting options ]] -- See `:help vim.o` @@ -114,7 +114,9 @@ vim.o.showmode = false -- Schedule the setting after `UiEnter` because it can increase startup-time. -- Remove this option if you want your OS clipboard to remain independent. -- See `:help 'clipboard'` -vim.schedule(function() vim.o.clipboard = 'unnamedplus' end) +vim.schedule(function() + -- vim.opt.clipboard = 'unnamedplus' +end) -- Enable break indent vim.o.breakindent = true @@ -923,7 +925,7 @@ require('lazy').setup({ -- This is the easiest way to modularize your config. -- -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - -- { import = 'custom.plugins' }, + { import = 'custom.plugins' }, -- -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` -- Or use telescope! diff --git a/init.lua.bak b/init.lua.bak new file mode 100644 index 00000000000..6c6d42bd327 --- /dev/null +++ b/init.lua.bak @@ -0,0 +1,109 @@ +--[[ + +===================================================================== +==================== READ THIS BEFORE CONTINUING ==================== +===================================================================== +======== .-----. ======== +======== .----------------------. | === | ======== +======== |.-""""""""""""""""""-.| |-----| ======== +======== || || | === | ======== +======== || KICKSTART.NVIM || |-----| ======== +======== || || | === | ======== +======== || || |-----| ======== +======== ||:Tutor || |:::::| ======== +======== |'-..................-'| |____o| ======== +======== `"")----------------(""` ___________ ======== +======== /::::::::::| |::::::::::\ \ no mouse \ ======== +======== /:::========| |==hjkl==:::\ \ required \ ======== +======== '""""""""""""' '""""""""""""' '""""""""""' ======== +======== ======== +===================================================================== +===================================================================== + +What is Kickstart? + + Kickstart.nvim is *not* a distribution. + + Kickstart.nvim is a starting point for your own configuration. + The goal is that you can read every line of code, top-to-bottom, understand + what your configuration is doing, and modify it to suit your needs. + + Once you've done that, you can start exploring, configuring and tinkering to + make Neovim your own! That might mean leaving Kickstart just the way it is for a while + or immediately breaking it into modular pieces. It's up to you! + + If you don't know anything about Lua, I recommend taking some time to read through + a guide. One possible example which will only take 10-15 minutes: + - https://learnxinyminutes.com/docs/lua/ + + After understanding a bit more about Lua, you can use `:help lua-guide` as a + reference for how Neovim integrates Lua. + - :help lua-guide + - (or HTML version): https://neovim.io/doc/user/lua-guide.html + +Kickstart Guide: + + TODO: The very first thing you should do is to run the command `:Tutor` in Neovim. + + If you don't know what this means, type the following: + - + - : + - Tutor + - + + (If you already know the Neovim basics, you can skip this step.) + + Once you've completed that, you can continue working through **AND READING** the rest + of the kickstart init.lua. + + Next, run AND READ `:help`. + This will open up a help window with some basic information + about reading, navigating and searching the builtin help documentation. + + This should be the first place you go to look when you're stuck or confused + with something. It's one of my favorite Neovim features. + + MOST IMPORTANTLY, we provide a keymap "sh" to [s]earch the [h]elp documentation, + which is very useful when you're not exactly sure of what you're looking for. + + I have left several `:help X` comments throughout the init.lua + These are hints about where to find more information about the relevant settings, + plugins or Neovim features used in Kickstart. + + NOTE: Look for lines like this + + Throughout the file. These are for you, the reader, to help you understand what is happening. + Feel free to delete them once you know what you're doing, but they should serve as a guide + for when you are first encountering a few different constructs in your Neovim config. + +If you experience any errors while trying to install kickstart, run `:checkhealth` for more info. + +I hope you enjoy your Neovim journey, +- TJ + +P.S. You can delete this when you're done too. It's your config now! :) +--]] + +-- Set as the leader key +-- See `:help mapleader` +-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used) +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' + +-- Set to true if you have a Nerd Font installed and selected in the terminal +vim.g.have_nerd_font = true + +-- [[ Setting options ]] +require 'options' + +-- [[ Basic Keymaps ]] +require 'keymaps' + +-- [[ Install `lazy.nvim` plugin manager ]] +require 'lazy-bootstrap' + +-- [[ Configure and install plugins ]] +require 'lazy-plugins' + +-- The line beneath this is called `modeline`. See `:help modeline` +-- vim: ts=2 sts=2 sw=2 et From 1b1c05e4f406b3340484b0a96b24112c7674f6e8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:07:04 +0800 Subject: [PATCH 03/12] keymaps --- init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 2efb0515d4e..3528f582610 100644 --- a/init.lua +++ b/init.lua @@ -197,7 +197,7 @@ vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagn -- -- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping -- or just use to exit terminal mode -vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' }) +-- vim.keymap.set('t', '', '', { desc = 'Exit terminal mode' }) -- TIP: Disable arrow keys in normal mode -- vim.keymap.set('n', '', 'echo "Use h to move!!"') From 24080f2a07582e09b3d33bf2666e10b7a9a90c58 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:13:57 +0800 Subject: [PATCH 04/12] telscope --- init.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index 3528f582610..b21217de284 100644 --- a/init.lua +++ b/init.lua @@ -389,7 +389,16 @@ require('lazy').setup({ require('telescope').setup { -- You can put your default mappings / updates / etc. in here -- All the info you're looking for is in `:help telescope.setup()` - -- + defaults = { + file_ignore_patterns = { + 'node_modules', + 'package-lock.json', + 'yarn.lock', + 'pnpm-lock.yaml', + 'lazy-lock.json', + }, + mappings = {}, + }, -- defaults = { -- mappings = { -- i = { [''] = 'to_fuzzy_refine' }, From 77c38f1eb1d61485638e26811a8f9dc1b4a6c7d2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:40:15 +0800 Subject: [PATCH 05/12] lsp --- init.lua | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index b21217de284..fa5b68fd8d9 100644 --- a/init.lua +++ b/init.lua @@ -516,6 +516,9 @@ require('lazy').setup({ 'saghen/blink.cmp', }, config = function() + -- Configuration: Set to true to prefer system clangd over Mason + local prefer_system_clangd = true + -- Brief aside: **What is LSP?** -- -- LSP is an initialism you've probably heard, but might not understand what it is. @@ -609,6 +612,22 @@ require('lazy').setup({ end, }) + -- Disable hover capability from Ruff if using with ty + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }), + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + if client == nil then + return + end + if client.name == 'ruff' then + -- Disable hover in favor of ty + client.server_capabilities.hoverProvider = false + end + end, + desc = 'LSP: Disable hover capability from Ruff', + }) + -- Enable the following language servers -- Feel free to add/remove any LSPs that you want here. They will automatically be installed. -- See `:help lsp-config` for information about keys and how to configure @@ -616,7 +635,14 @@ require('lazy').setup({ local servers = { -- clangd = {}, -- gopls = {}, - -- pyright = {}, + -- ty for Python type checking and hover documentation + ty = { + settings = { + ty = { + -- ty language server settings go here + }, + }, + }, -- rust_analyzer = {}, -- -- Some languages (like typescript) have entire language plugins that can be useful: @@ -624,6 +650,9 @@ require('lazy').setup({ -- -- But for many setups, the LSP (`ts_ls`) will work just fine -- ts_ls = {}, + -- + -- Ruff LSP for Python linting and formatting + ruff = {}, stylua = {}, -- Used to format Lua code @@ -664,17 +693,77 @@ require('lazy').setup({ -- :Mason -- -- You can press `g?` for help in this menu. + -- + -- You can add other tools here that you want Mason to install + -- for you, so that they are available from within Neovim. + + -- Detect system capabilities + local is_termux = vim.fn.has 'unix' == 1 and vim.fn.executable 'termux-info' == 1 + local has_system_clangd = vim.fn.executable 'clangd' == 1 + local use_system_clangd = prefer_system_clangd and has_system_clangd + + -- List of tools to install via Mason local ensure_installed = vim.tbl_keys(servers or {}) + + -- Extend with common tools vim.list_extend(ensure_installed, { - -- You can add other tools here that you want Mason to install + 'stylua', + 'tailwindcss', + 'prettierd', + 'html', + 'intelephense', + 'pretty-php', + -- 'pylsp', + 'svelte', + 'vtsls', + 'gofumpt', + 'gopls', + 'shfmt', + 'rust-analyzer', + 'ruff', }) + -- Only include clangd if not in Termux and system clangd preference allows it + if not is_termux and not use_system_clangd then + vim.list_extend(ensure_installed, { + 'clangd', + 'clang-format', + }) + elseif not is_termux then + -- Still install clang-format via Mason even when using system clangd + vim.list_extend(ensure_installed, { + 'clang-format', + }) + end + require('mason-tool-installer').setup { ensure_installed = ensure_installed } for name, server in pairs(servers) do vim.lsp.config(name, server) vim.lsp.enable(name) end + + -- Setup clangd LSP conditionally - prefer system clangd if configured and available + local clangd_cmd = (use_system_clangd or is_termux) and { 'clangd' } or nil + + require('lspconfig').clangd.setup { + cmd = clangd_cmd, + } + + require('mason-lspconfig').setup { + ensure_installed = {}, -- explicitly set to an empty table (Kickstart populates installs via mason-tool-installer) + automatic_installation = false, + handlers = { + function(server_name) + local server = servers[server_name] or {} + -- This handles overriding only values explicitly passed + -- by the server configuration above. Useful when disabling + -- certain features of an LSP (for example, turning off formatting for ts_ls) + server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) + require('lspconfig')[server_name].setup(server) + end, + }, + } end, }, From d130d5241b30a6821ad7b2c7cb5cd4decdb29a4d Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:42:22 +0800 Subject: [PATCH 06/12] conform --- init.lua | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/init.lua b/init.lua index fa5b68fd8d9..4d3a3f7a913 100644 --- a/init.lua +++ b/init.lua @@ -773,7 +773,7 @@ require('lazy').setup({ cmd = { 'ConformInfo' }, keys = { { - 'f', + 'ff', function() require('conform').format { async = true, lsp_format = 'fallback' } end, mode = '', desc = '[F]ormat buffer', @@ -783,15 +783,16 @@ require('lazy').setup({ ---@type conform.setupOpts opts = { notify_on_error = false, - format_on_save = function(bufnr) + format_after_save = function(bufnr) -- Disable "format_on_save lsp_fallback" for languages that don't -- have a well standardized coding style. You can add additional -- languages here or re-enable it for the disabled ones. - local disable_filetypes = { c = true, cpp = true } + local disable_filetypes = {} if disable_filetypes[vim.bo[bufnr].filetype] then return nil else return { + async = true, timeout_ms = 500, lsp_format = 'fallback', } @@ -804,6 +805,29 @@ require('lazy').setup({ -- -- You can use 'stop_after_first' to run the first available formatter from the list -- javascript = { "prettierd", "prettier", stop_after_first = true }, + javascript = { 'prettierd' }, + typescript = { 'prettierd' }, + javascriptreact = { 'prettierd' }, + typescriptreact = { 'prettierd' }, + scss = { 'prettierd' }, + pandoc = { 'prettierd' }, + markdown = { 'prettierd' }, + json = { 'prettierd' }, + css = { 'prettierd' }, + yml = { 'prettierd' }, + html = { 'prettierd' }, + php = { 'pretty-php' }, + cpp = { 'clang_format' }, + sh = { 'shfmt' }, + go = { 'gofumpt' }, + python = { + -- To fix auto-fixable lint errors + 'ruff_fix', + -- To run the Ruff formatter + 'ruff_format', + -- To organize the imports + 'ruff_organize_imports', + }, }, }, }, From 4c2f34b6899a772b4589a3aa73bc7bf9cdcc8fdc Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:45:31 +0800 Subject: [PATCH 07/12] blink --- init.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/init.lua b/init.lua index 4d3a3f7a913..854c51b10cb 100644 --- a/init.lua +++ b/init.lua @@ -888,6 +888,14 @@ require('lazy').setup({ -- -- See :h blink-cmp-config-keymap for defining your own keymap preset = 'default', + [''] = { 'accept', 'fallback' }, + [''] = { + function(cmp) + cmp.show { providers = { 'lsp' } } + end, + }, + [''] = { 'fallback' }, + [''] = { 'fallback' }, -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps From 7c070a47e4873c9e8066b2e7f55b94ae964fbc8d Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:53:55 +0800 Subject: [PATCH 08/12] treesitter --- init.lua | 57 ++++++++++++++++++++++++++++++++------------------------ test.jsx | 9 +++++++++ test.py | 1 + test.tsx | 9 +++++++++ 4 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 test.jsx create mode 100644 test.py create mode 100644 test.tsx diff --git a/init.lua b/init.lua index 854c51b10cb..78bb09df949 100644 --- a/init.lua +++ b/init.lua @@ -933,28 +933,6 @@ require('lazy').setup({ }, }, - { -- You can easily change to a different colorscheme. - -- Change the name of the colorscheme plugin below, and then - -- change the command in the config to whatever the name of that colorscheme is. - -- - -- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`. - 'folke/tokyonight.nvim', - priority = 1000, -- Make sure to load this before all the other start plugins. - config = function() - ---@diagnostic disable-next-line: missing-fields - require('tokyonight').setup { - styles = { - comments = { italic = false }, -- Disable italics in comments - }, - } - - -- Load the colorscheme here. - -- Like many other themes, this one has different styles, and you could load - -- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'. - vim.cmd.colorscheme 'tokyonight-night' - end, - }, - -- Highlight todo, notes, etc in comments { 'folke/todo-comments.nvim', @@ -982,7 +960,17 @@ require('lazy').setup({ -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren -- - sd' - [S]urround [D]elete [']quotes -- - sr)' - [S]urround [R]eplace [)] ['] - require('mini.surround').setup() + require('mini.surround').setup { + mappings = { + add = 'ra', -- Add surrounding in Normal and Visual modes + delete = 'rd', -- Delete surrounding + find = 'rf', -- Find surrounding (to the right) + find_left = 'rF', -- Find surrounding (to the left) + highlight = 'rh', -- Highlight surrounding + replace = 'rr', -- Replace surrounding + update_n_lines = 'rn', -- Update `n_lines` + }, + } -- Simple and easy statusline. -- You could remove this setup call if you don't like it, @@ -1009,7 +997,28 @@ require('lazy').setup({ branch = 'main', -- [[ Configure Treesitter ]] See `:help nvim-treesitter-intro` config = function() - local parsers = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' } + local parsers = { + 'jsx', + 'tsx', + 'javascript', + 'typescript', + 'rust', + 'zig', + 'bash', + 'c', + 'cpp', + 'python', + 'vimdoc', + 'vim', + 'lua', + 'php', + 'html', + 'svelte', + 'markdown', + 'markdown_inline', + 'yaml', + 'json', + } require('nvim-treesitter').install(parsers) vim.api.nvim_create_autocmd('FileType', { callback = function(args) diff --git a/test.jsx b/test.jsx new file mode 100644 index 00000000000..418f65fde66 --- /dev/null +++ b/test.jsx @@ -0,0 +1,9 @@ +const Component = (props) => { + return ( + <> +

Hello Mantap

+ + ); +}; + +export default Component; diff --git a/test.py b/test.py new file mode 100644 index 00000000000..8cde7829c17 --- /dev/null +++ b/test.py @@ -0,0 +1 @@ +print("hello world") diff --git a/test.tsx b/test.tsx new file mode 100644 index 00000000000..f2bdcdde590 --- /dev/null +++ b/test.tsx @@ -0,0 +1,9 @@ +const Component = (props) => { + return ( + <> +

Hello World

+ + ); +}; + +export default Component; From aa573a0d05e07ac186a6529047f3a98bb966800e Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:55:11 +0800 Subject: [PATCH 09/12] done --- init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index 78bb09df949..e566f56898a 100644 --- a/init.lua +++ b/init.lua @@ -1053,10 +1053,10 @@ require('lazy').setup({ -- Here are some example plugins that I've included in the Kickstart repository. -- Uncomment any of the lines below to enable them (you will need to restart nvim). -- - -- require 'kickstart.plugins.debug', + require 'kickstart.plugins.debug', -- require 'kickstart.plugins.indent_line', -- require 'kickstart.plugins.lint', - -- require 'kickstart.plugins.autopairs', + require 'kickstart.plugins.autopairs', -- require 'kickstart.plugins.neo-tree', -- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommend keymaps From 6aa85cc985bafdfbd9a96d7cbe13de250081cb1b Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 6 Mar 2026 22:55:28 +0800 Subject: [PATCH 10/12] fix error --- lua/custom/plugins/99-keymaps.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/lua/custom/plugins/99-keymaps.lua b/lua/custom/plugins/99-keymaps.lua index b6716888624..cd21e42fb0c 100644 --- a/lua/custom/plugins/99-keymaps.lua +++ b/lua/custom/plugins/99-keymaps.lua @@ -370,8 +370,6 @@ end, { vim.keymap.set('n', 'fsp', function() SvelteKitNewPage(vim.fn.input 'Enter Page Name: ') end, { - noremap = true, - silent = false, noremap = true, silent = false, desc = 'New [P]age', From 7d410f88e678681bbccb562db0b87f0fef2a65fb Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 7 Mar 2026 07:04:51 +0800 Subject: [PATCH 11/12] nvim dap --- lua/kickstart/plugins/debug.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lua/kickstart/plugins/debug.lua b/lua/kickstart/plugins/debug.lua index 7e58905e830..d4a5d633dd4 100644 --- a/lua/kickstart/plugins/debug.lua +++ b/lua/kickstart/plugins/debug.lua @@ -25,6 +25,33 @@ return { -- Add your own debuggers here 'leoluz/nvim-dap-go', + + -- Virtual text support for nvim-dap + { + 'theHamsta/nvim-dap-virtual-text', + opts = { + enabled = true, + enabled_commands = true, + highlight_changed_variables = true, + highlight_new_as_changed = false, + show_stop_reason = true, + commented = false, + only_first_definition = true, + all_references = false, + clear_on_continue = false, + display_callback = function(variable, buf, stackframe, node, options) + if options.virt_text_pos == 'inline' then + return ' = ' .. variable.value:gsub("%s+", " ") + else + return variable.name .. ' = ' .. variable.value:gsub("%s+", " ") + end + end, + virt_text_pos = vim.fn.has 'nvim-0.10' == 1 and 'inline' or 'eol', + all_frames = false, + virt_lines = false, + virt_text_win_col = nil + }, + }, }, keys = { -- Basic debugging keymaps, feel free to change to your liking! From c35ede75e0305f62eaf6a0eee1b01852dc6bcd5d Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 15 Mar 2026 09:36:56 +0000 Subject: [PATCH 12/12] save --- lua/custom/plugins/99-keymaps.lua | 64 +++++++++++++------------------ 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/lua/custom/plugins/99-keymaps.lua b/lua/custom/plugins/99-keymaps.lua index cd21e42fb0c..2e0f922db5b 100644 --- a/lua/custom/plugins/99-keymaps.lua +++ b/lua/custom/plugins/99-keymaps.lua @@ -206,16 +206,12 @@ vim.keymap.set('i', '', ':wa', { }) -- npm / yarn operation -vim.keymap.set('n', 'rb', function() - RunCommandAndNotify 'npm run build' -end, { +vim.keymap.set('n', 'rb', function() RunCommandAndNotify 'npm run build' end, { noremap = true, silent = false, desc = '[R]un [B]uild', }) -vim.keymap.set('n', 'rd', function() - RunCommandInNewTab 'npm run dev' -end, { +vim.keymap.set('n', 'rd', function() RunCommandInNewTab 'npm run dev' end, { noremap = true, silent = false, desc = '[R]un [D]ev', @@ -225,9 +221,7 @@ vim.keymap.set('n', 'ri', Npm_install, { silent = false, desc = '[R]un npm [I]nstall', }) -vim.keymap.set('n', 'rl', function() - RunCommandInNewTab 'five-server' -end, { +vim.keymap.set('n', 'rl', function() RunCommandInNewTab 'five-server' end, { noremap = true, silent = false, desc = '[R]un npm [L]ive Server', @@ -272,10 +266,22 @@ vim.keymap.set('n', 'sne', ':EditSnippets', { desc = '[Sn]ippets [E]dit', }) -vim.keymap.set('n', 'snf', ':%s/"/\\\\"/gggVG10>gg0v_y:%s/0/\\":%s/\\n/\\",\\r:%s/\\n\\",/\\r\\"\\",', { - noremap = true, - silent = false, - desc = '[Sn]ippets [F]ormat', +-- "Snippet Format" +vim.keymap.set('n', 'snf', function() + local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) + + for i, line in ipairs(lines) do + line = line:gsub('\\', '\\\\') -- escape backslashes + line = line:gsub('"', '\\"') -- escape quotes + line = line:gsub("%$", "\\\\$") + line = line:gsub("\\\\\\\\", "\\\\\\\\\\\\") + + lines[i] = '"' .. line .. '",' + end + + vim.api.nvim_buf_set_lines(0, 0, -1, false, lines) +end, { + desc = '[Sn]ippet [F]ormat', }) -- Noice Notification @@ -346,44 +352,32 @@ vim.keymap.set('v', 'sk', ':s/\\(.*\\)/\\1/gfnp', function() - NextJSNewPage(vim.fn.input 'Enter Page Name: ') -end, { +vim.keymap.set('n', 'fnp', function() NextJSNewPage(vim.fn.input 'Enter Page Name: ') end, { noremap = true, silent = false, desc = 'New [P]age', }) -vim.keymap.set('n', 'fnr', function() - NextJSNewApiPost(vim.fn.input 'Enter Route Name: ') -end, { +vim.keymap.set('n', 'fnr', function() NextJSNewApiPost(vim.fn.input 'Enter Route Name: ') end, { noremap = true, silent = false, desc = 'New API [R]oute POST', }) -vim.keymap.set('n', 'fng', function() - NextJSNewApiGet(vim.fn.input 'Enter Route Name: ') -end, { +vim.keymap.set('n', 'fng', function() NextJSNewApiGet(vim.fn.input 'Enter Route Name: ') end, { noremap = true, silent = false, desc = 'New [G]et Route', }) -vim.keymap.set('n', 'fsp', function() - SvelteKitNewPage(vim.fn.input 'Enter Page Name: ') -end, { +vim.keymap.set('n', 'fsp', function() SvelteKitNewPage(vim.fn.input 'Enter Page Name: ') end, { noremap = true, silent = false, desc = 'New [P]age', }) -vim.keymap.set('n', 'fsr', function() - SvelteKitNewAPIPost(vim.fn.input 'Enter Route Name: ') -end, { +vim.keymap.set('n', 'fsr', function() SvelteKitNewAPIPost(vim.fn.input 'Enter Route Name: ') end, { noremap = true, silent = false, desc = 'New Post [R]oute', }) -vim.keymap.set('n', 'fsg', function() - SvelteKitNewAPIGet(vim.fn.input 'Enter Route Name: ') -end, { +vim.keymap.set('n', 'fsg', function() SvelteKitNewAPIGet(vim.fn.input 'Enter Route Name: ') end, { noremap = true, silent = false, desc = 'New [G]et Route', @@ -392,9 +386,7 @@ end, { vim.keymap.set( 'n', '', - function() - SearchAndReplace(vim.fn.input 'Enter Search Term: ', vim.fn.input 'Enter Replace Term: ') - end, + function() SearchAndReplace(vim.fn.input 'Enter Search Term: ', vim.fn.input 'Enter Replace Term: ') end, -- ":%s/vim.fn.input('Enter Search Term: ')/vim.fn.input('Enter Replace Term: ')/g", { noremap = true, @@ -460,9 +452,7 @@ end, { desc = '[F]ile [C]opy current file path to clipboard', }) -vim.keymap.set('n', 'fe', function() - os.execute 'explorer.exe .' -end, { +vim.keymap.set('n', 'fe', function() os.execute 'explorer.exe .' end, { noremap = true, silent = true, desc = '[F]ile [E]xplorer on current file folder',