Skip to content

Commit f4efaa9

Browse files
committed
updates
1 parent 0b10f06 commit f4efaa9

File tree

7 files changed

+299
-58
lines changed

7 files changed

+299
-58
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ tags
22
test.sh
33
.luarc.json
44
nvim
5+
.swp
6+
.undo

CLAUDE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Neovim Configuration Guidelines
2+
3+
## Commands
4+
- Format code: `<leader>f` or `:Format`
5+
- Toggle autoformat: `:KickstartFormatToggle`
6+
- LSP actions: `<leader>la` (code action), `<leader>ln` (rename)
7+
- Search files: `<leader>t` (find files), `<leader>F` (live grep)
8+
- Test commands: None defined (add when implementing tests)
9+
10+
## Style Guidelines
11+
- **Formatting**: Uses formatter.nvim (stylua for Lua, eslint_d for TS/Vue)
12+
- **Indentation**: 2 spaces (ts=2 sts=2 sw=2)
13+
- **Imports**: Follow lazy.nvim plugin structure for new plugins
14+
- **Plugin Structure**: Use `lua/custom/plugins/*.lua` with return table format
15+
- **Naming**: Follow existing conventions (lowercase, underscore_case)
16+
- **Error Handling**: Use LSP diagnostics (`<leader>e` to view, `[d`/`]d` to navigate)
17+
- **File Organization**: Single plugin per file in `lua/custom/plugins/`
18+
- **Leader Key**: `,` is defined as both leader and localleader
19+
20+
## Conventions
21+
- Use Lua for all configuration
22+
- Follow kickstart.nvim modular approach for new features
23+
- Add new plugins in `lua/custom/plugins/` directory

init.lua

Lines changed: 237 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ if not vim.loop.fs_stat(lazypath) then
5959
}
6060
end
6161
vim.opt.rtp:prepend(lazypath)
62+
vim.opt.spelllang = 'en_us'
63+
vim.opt.spell = true
64+
65+
local prefix = vim.env.XDG_CONFIG_HOME or vim.fn.expand("~/.config")
66+
67+
vim.opt.undodir = { prefix .. "/nvim/.undo//"}
68+
69+
vim.opt.backupdir = {prefix .. "/nvim/.backup//"}
70+
71+
vim.opt.directory = { prefix .. "/nvim/.swp//"}
6272

6373
-- [[ Configure plugins ]]
6474
-- NOTE: Here is where you install your plugins.
@@ -486,9 +496,34 @@ vim.defer_fn(function()
486496
}
487497
end, 0)
488498

499+
-- Helper function to manually stop unwanted language servers in Deno projects
500+
local function force_stop_ts_servers_for_deno(bufnr)
501+
local fname = vim.api.nvim_buf_get_name(bufnr or 0)
502+
if require('lspconfig').util.root_pattern("deno.json", "deno.jsonc")(fname) then
503+
-- We're in a Deno project, stop any non-Deno TS servers
504+
for _, client in pairs(vim.lsp.get_clients({bufnr = bufnr})) do
505+
if client.name ~= "denols" and (
506+
client.name == "tsserver" or
507+
client.name == "typescript" or
508+
client.name == "ts_ls" or
509+
client.name == "volar" or
510+
client.name == "eslint") then
511+
client.stop()
512+
vim.notify("Force-stopped " .. client.name .. " in Deno project", vim.log.levels.INFO)
513+
end
514+
end
515+
end
516+
end
517+
518+
-- Create a command to manually force stop unwanted servers
519+
vim.api.nvim_create_user_command('ForceStopTsServers', function()
520+
force_stop_ts_servers_for_deno()
521+
vim.notify("Manually stopped non-Deno language servers", vim.log.levels.INFO)
522+
end, { desc = 'Force stop non-Deno TS language servers' })
523+
489524
-- [[ Configure LSP ]]
490525
-- This function gets run when an LSP connects to a particular buffer.
491-
local on_attach = function(_, bufnr)
526+
local on_attach = function(client, bufnr)
492527
-- NOTE: Remember that lua is a real programming language, and as such it is possible
493528
-- to define small helper and utility functions so you don't have to repeat yourself
494529
-- many times.
@@ -526,27 +561,51 @@ local on_attach = function(_, bufnr)
526561
end, '[W]orkspace [L]ist Folders')
527562

528563
-- Create a command `:Format` local to the LSP buffer
529-
--vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
530-
-- vim.lsp.buf.format()
531-
--end, { desc = 'Format current buffer with LSP' })
564+
vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
565+
vim.lsp.buf.format()
566+
end, { desc = 'Format current buffer with LSP' })
567+
568+
-- For Deno projects, we want to force-stop non-Deno servers immediately
569+
force_stop_ts_servers_for_deno(bufnr)
570+
571+
-- If the client is denols, stop other TS servers
572+
if client.name == "denols" then
573+
local active_clients = vim.lsp.get_clients({bufnr = bufnr})
574+
for _, client_ in pairs(active_clients) do
575+
if client_.id ~= client.id and (
576+
client_.name == "tsserver" or
577+
client_.name == "typescript" or
578+
client_.name == "ts_ls" or
579+
client_.name == "volar" or
580+
client_.name == "eslint") then
581+
client_.stop()
582+
vim.notify("Stopped " .. client_.name .. " when Deno LSP attached", vim.log.levels.INFO)
583+
end
584+
end
585+
end
532586
end
533587

534588
-- document existing key chains
535-
require('which-key').register {
536-
['<leader>c'] = { name = '[C]ode', _ = 'which_key_ignore' },
537-
['<leader>g'] = { name = '[G]it', _ = 'which_key_ignore' },
538-
['<leader>h'] = { name = 'Git [H]unk', _ = 'which_key_ignore' },
539-
['<leader>r'] = { name = '[R]ename', _ = 'which_key_ignore' },
540-
['<leader>s'] = { name = '[S]earch', _ = 'which_key_ignore' },
541-
['<leader>t'] = { name = '[T]oggle', _ = 'which_key_ignore' },
542-
['<leader>w'] = { name = '[W]orkspace', _ = 'which_key_ignore' },
543-
}
544-
-- register which-key VISUAL mode
545-
-- required for visual <leader>hs (hunk stage) to work
546-
require('which-key').register({
547-
['<leader>'] = { name = 'VISUAL <leader>' },
548-
['<leader>h'] = { 'Git [H]unk' },
549-
}, { mode = 'v' })
589+
require('which-key').add(
590+
{
591+
{ "<leader>c", group = "[C]ode" },
592+
{ "<leader>c_", hidden = true },
593+
{ "<leader>g", group = "[G]it" },
594+
{ "<leader>g_", hidden = true },
595+
{ "<leader>h", group = "Git [H]unk" },
596+
{ "<leader>h_", hidden = true },
597+
{ "<leader>r", group = "[R]ename" },
598+
{ "<leader>r_", hidden = true },
599+
{ "<leader>s", group = "[S]earch" },
600+
{ "<leader>s_", hidden = true },
601+
{ "<leader>t", group = "[T]oggle" },
602+
{ "<leader>t_", hidden = true },
603+
{ "<leader>w", group = "[W]orkspace" },
604+
{ "<leader>w_", hidden = true },
605+
{ "<leader>", group = "VISUAL <leader>", mode = "v" },
606+
{ "<leader>h", desc = "Git [H]unk", mode = "v" },
607+
}
608+
)
550609

551610
-- mason-lspconfig requires that these setup functions are called in this order
552611
-- before setting up the servers.
@@ -561,15 +620,36 @@ require('mason-lspconfig').setup()
561620
--
562621
-- If you want to override the default filetypes that your language server will attach to you can
563622
-- define the property 'filetypes' to the map in question.
623+
564624
local servers = {
565625
-- clangd = {},
566626
-- gopls = {},
567-
-- pyright = {},
627+
pyright = {},
568628
rust_analyzer = {},
569-
tsserver = {},
570-
volar = {},
629+
-- Official typescript server
630+
tsserver = {
631+
filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
632+
},
633+
-- Alternative typescript server (appears in your LspInfo as ts_ls)
634+
typescript = {
635+
filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact' },
636+
},
637+
-- eslint = {
638+
-- workingDirectory = { mode = 'location' },
639+
-- },
640+
denols = {
641+
filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx", "json", "jsonc" },
642+
},
643+
--volar = {
644+
-- filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
645+
-- -- root_dir = require('lspconfig').util.root_pattern("src/App.vue"),
646+
-- init_options = {
647+
-- vue = {
648+
-- hybridMode = true,
649+
-- },
650+
-- },
651+
--},
571652
html = { filetypes = { 'html', 'twig', 'hbs' } },
572-
573653
lua_ls = {
574654
Lua = {
575655
workspace = { checkThirdParty = false },
@@ -594,14 +674,142 @@ mason_lspconfig.setup {
594674
ensure_installed = vim.tbl_keys(servers),
595675
}
596676

677+
-- Create autocommand group for our Deno-related commands
678+
local deno_augroup = vim.api.nvim_create_augroup('denols_force_stop', { clear = true })
679+
680+
-- Add autocmd to force stop non-Deno servers when entering a buffer
681+
vim.api.nvim_create_autocmd('BufEnter', {
682+
group = deno_augroup,
683+
callback = function(args)
684+
-- Small delay to ensure all servers have had a chance to attach
685+
vim.defer_fn(function()
686+
force_stop_ts_servers_for_deno(args.buf)
687+
end, 100)
688+
end,
689+
})
690+
691+
-- Helper function to check if in a Deno project
692+
local function is_deno_project(fname)
693+
local deno_root = require('lspconfig').util.root_pattern("deno.json", "deno.jsonc")(fname)
694+
return deno_root ~= nil
695+
end
696+
597697
mason_lspconfig.setup_handlers {
598698
function(server_name)
599-
require('lspconfig')[server_name].setup {
600-
capabilities = capabilities,
601-
on_attach = on_attach,
602-
settings = servers[server_name],
603-
filetypes = (servers[server_name] or {}).filetypes,
604-
}
699+
if server_name == "denols" then
700+
require('lspconfig')[server_name].setup {
701+
capabilities = capabilities,
702+
on_attach = on_attach,
703+
settings = servers[server_name],
704+
filetypes = (servers[server_name] or {}).filetypes,
705+
root_dir = require('lspconfig').util.root_pattern("deno.json", "deno.jsonc"),
706+
-- This will prevent other TS LSP servers from starting when denols is active
707+
single_file_support = false,
708+
}
709+
elseif server_name == "tsserver" then
710+
require('lspconfig')[server_name].setup {
711+
capabilities = capabilities,
712+
on_attach = function(client, bufnr)
713+
-- Check if we're in a Deno project, if so stop the client immediately
714+
local fname = vim.api.nvim_buf_get_name(bufnr)
715+
if is_deno_project(fname) then
716+
client.stop()
717+
vim.notify("Prevented tsserver in Deno project", vim.log.levels.INFO)
718+
return
719+
end
720+
on_attach(client, bufnr)
721+
end,
722+
settings = servers[server_name],
723+
filetypes = (servers[server_name] or {}).filetypes,
724+
-- Explicitly avoid attaching in Deno projects
725+
root_dir = function(fname)
726+
if is_deno_project(fname) then
727+
return nil -- Don't attach tsserver in Deno projects
728+
end
729+
return require('lspconfig').util.root_pattern("package.json", "tsconfig.json", "jsconfig.json")(fname)
730+
end,
731+
}
732+
elseif server_name == "typescript" or server_name == "ts_ls" then
733+
require('lspconfig')[server_name].setup {
734+
capabilities = capabilities,
735+
on_attach = function(client, bufnr)
736+
-- Check if we're in a Deno project, if so stop the client immediately
737+
local fname = vim.api.nvim_buf_get_name(bufnr)
738+
if is_deno_project(fname) then
739+
client.stop()
740+
vim.notify("Prevented ts_ls in Deno project", vim.log.levels.INFO)
741+
return
742+
end
743+
on_attach(client, bufnr)
744+
end,
745+
settings = servers[server_name],
746+
filetypes = (servers[server_name] or {}).filetypes,
747+
-- Explicitly avoid attaching in Deno projects
748+
root_dir = function(fname)
749+
if is_deno_project(fname) then
750+
return nil -- Don't attach typescript/ts_ls in Deno projects
751+
end
752+
return require('lspconfig').util.root_pattern("package.json", "tsconfig.json", "jsconfig.json")(fname)
753+
end,
754+
}
755+
elseif server_name == "volar" then
756+
require('lspconfig')[server_name].setup {
757+
capabilities = capabilities,
758+
on_attach = function(client, bufnr)
759+
-- Check if we're in a Deno project, if so stop the client immediately
760+
local fname = vim.api.nvim_buf_get_name(bufnr)
761+
if is_deno_project(fname) then
762+
client.stop()
763+
vim.notify("Prevented volar in Deno project", vim.log.levels.INFO)
764+
return
765+
end
766+
on_attach(client, bufnr)
767+
end,
768+
settings = servers[server_name],
769+
filetypes = (servers[server_name] or {}).filetypes,
770+
init_options = {
771+
vue = {
772+
hybridMode = true,
773+
},
774+
},
775+
-- Explicitly avoid attaching in Deno projects
776+
root_dir = function(fname)
777+
if is_deno_project(fname) then
778+
return nil -- Don't attach volar in Deno projects
779+
end
780+
return require('lspconfig').util.root_pattern("package.json")(fname)
781+
end,
782+
}
783+
elseif server_name == "eslint" then
784+
require('lspconfig')[server_name].setup {
785+
capabilities = capabilities,
786+
on_attach = function(client, bufnr)
787+
-- Check if we're in a Deno project, if so stop the client immediately
788+
local fname = vim.api.nvim_buf_get_name(bufnr)
789+
if is_deno_project(fname) then
790+
client.stop()
791+
vim.notify("Prevented eslint in Deno project", vim.log.levels.INFO)
792+
return
793+
end
794+
on_attach(client, bufnr)
795+
end,
796+
settings = servers[server_name],
797+
-- Explicitly avoid attaching in Deno projects
798+
root_dir = function(fname)
799+
if is_deno_project(fname) then
800+
return nil -- Don't attach eslint in Deno projects
801+
end
802+
return require('lspconfig').util.root_pattern(".eslintrc.js", ".eslintrc.cjs", ".eslintrc.yaml", ".eslintrc.yml", ".eslintrc.json")(fname)
803+
end,
804+
}
805+
else
806+
require('lspconfig')[server_name].setup {
807+
capabilities = capabilities,
808+
on_attach = on_attach,
809+
settings = servers[server_name],
810+
filetypes = (servers[server_name] or {}).filetypes,
811+
}
812+
end
605813
end,
606814
}
607815

0 commit comments

Comments
 (0)