-- LSP und Treesitter Konfiguration local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) -- Mason für einfache LSP-Installation require('mason').setup() require('mason-lspconfig').setup({ ensure_installed = { -- Sprachen 'lua_ls', -- Lua 'pyright', -- Python 'ruff', -- Python Linter 'ts_ls', -- TypeScript/JavaScript -- 'vue-language-server', -- Vue 'intelephense', -- PHP 'html', -- HTML 'cssls', -- CSS 'yamlls', -- YAML 'jsonls', -- JSON 'docker_compose_language_service', -- Docker Compose 'dockerls', -- Dockerfile 'gopls', }, }) -- LSP-Server konfigurieren local lspconfig = require('lspconfig') -- Lua lspconfig.lua_ls.setup({ capabilities = capabilities, }) -- TypeScript (inkl. React) lspconfig.ts_ls.setup({ capabilities = capabilities, }) -- Typescript-Tools für bessere TS/JS Unterstützung require("typescript-tools").setup({ settings = { -- Für NestJS, React und andere TS-Frameworks tsserver_file_preferences = { importModuleSpecifierPreference = "relative", }, }, }) -- Python lspconfig.pyright.setup({ capabilities = capabilities, }) -- PHP/Symfony lspconfig.intelephense.setup({ capabilities = capabilities, settings = { intelephense = { stubs = { "apache", "bcmath", "bz2", "calendar", "Core", "curl", "date", "dba", "dom", "fileinfo", "filter", "ftp", "gd", "gettext", "hash", "iconv", "imap", "intl", "json", "ldap", "libxml", "mbstring", "mysqli", "mysqlnd", "oci8", "openssl", "pcntl", "pcre", "PDO", "pdo_mysql", "pdo_pgsql", "pdo_sqlite", "pgsql", "Phar", "posix", "pspell", "readline", "Reflection", "session", "shmop", "SimpleXML", "snmp", "soap", "sockets", "sodium", "SPL", "sqlite3", "standard", "superglobals", "sysvmsg", "sysvsem", "sysvshm", "tidy", "tokenizer", "xml", "xmlreader", "xmlrpc", "xmlwriter", "xsl", "Zend OPcache", "zip", "zlib", "wordpress", "symfony" }, }, }, }) -- Go lspconfig.gopls.setup({ capabilities = capabilities, settings = { gopls = { analyses = { unusedparams = true, }, staticcheck = true, gofumpt = true, -- Strengere Formatierung als gofmt usePlaceholders = true, completeUnimported = true, experimentalPostfixCompletions = true, }, }, }) -- YAML mit Schema-Unterstützung lspconfig.yamlls.setup({ capabilities = capabilities, settings = { yaml = { schemas = require('schemastore').yaml.schemas(), }, }, }) -- JSON mit Schema-Unterstützung lspconfig.jsonls.setup({ capabilities = capabilities, settings = { json = { schemas = require('schemastore').json.schemas(), validate = { enable = true }, }, }, }) -- Treesitter-Konfiguration für Syntax-Highlighting require('nvim-treesitter.configs').setup({ ensure_installed = { "lua", "vim", "vimdoc", "json", "yaml", "html", "css", "javascript", "typescript", "tsx", "php", "python", "vue", "dockerfile", "markdown", "regex", "bash", "go", }, highlight = { enable = true }, indent = { enable = true }, }) -- Autocomplete-Konfiguration local cmp = require('cmp') local luasnip = require('luasnip') cmp.setup({ snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, }, window = { completion = cmp.config.window.bordered(), documentation = cmp.config.window.bordered(), }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete(), [''] = cmp.mapping.confirm({ select = true }), [''] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_next_item() elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump() else fallback() end end, { 'i', 's' }), [''] = cmp.mapping(function(fallback) if cmp.visible() then cmp.select_prev_item() elseif luasnip.jumpable(-1) then luasnip.jump(-1) else fallback() end end, { 'i', 's' }), }), sources = cmp.config.sources({ { name = 'nvim_lsp' }, { name = 'luasnip' }, { name = 'buffer' }, { name = 'path' }, }), }) -- Einfache benutzerdefinierte Snippets (optional) -- Hier ein Beispiel für ein paar einfache Snippets local snippets_path = vim.fn.stdpath("config") .. "/snippets" if vim.fn.isdirectory(snippets_path) == 0 then vim.fn.mkdir(snippets_path, "p") end -- Füge einige nützliche Snippets hinzu luasnip.add_snippets("python", { luasnip.snippet("def", { luasnip.text_node("def "), luasnip.insert_node(1, "function_name"), luasnip.text_node("("), luasnip.insert_node(2, "args"), luasnip.text_node("):\n\t"), luasnip.insert_node(0), }), }) luasnip.add_snippets("typescript", { luasnip.snippet("fn", { luasnip.text_node("function "), luasnip.insert_node(1, "name"), luasnip.text_node("("), luasnip.insert_node(2, "params"), luasnip.text_node(") {\n\t"), luasnip.insert_node(0), luasnip.text_node("\n}"), }), }) luasnip.add_snippets("go", { luasnip.snippet("func", { luasnip.text_node("func "), luasnip.insert_node(1, "name"), luasnip.text_node("("), luasnip.insert_node(2, "params"), luasnip.text_node(") "), luasnip.insert_node(3, "returnType"), luasnip.text_node(" {\n\t"), luasnip.insert_node(0), luasnip.text_node("\n}"), }), luasnip.snippet("if", { luasnip.text_node("if "), luasnip.insert_node(1, "condition"), luasnip.text_node(" {\n\t"), luasnip.insert_node(0), luasnip.text_node("\n}"), }), }) -- Code-Formatierung require("conform").setup({ formatters_by_ft = { javascript = { "prettier" }, typescript = { "prettier" }, javascriptreact = { "prettier" }, typescriptreact = { "prettier" }, vue = { "prettier" }, json = { "prettier" }, yaml = { "prettier" }, html = { "prettier" }, css = { "prettier" }, php = { "php_cs_fixer" }, python = { "black" }, lua = { "stylua" }, go = { "gofumpt" }, }, }) -- Formatierung beim Speichern vim.api.nvim_create_autocmd("BufWritePre", { pattern = "*", callback = function() require("conform").format({ async = false, lsp_fallback = true }) end, }) -- Einstellungen für die Diagnostik (Fehleranzeige) vim.diagnostic.config({ virtual_text = { format = function(diagnostic) local icon = "→ " if diagnostic.severity == vim.diagnostic.severity.ERROR then icon = "✗ " elseif diagnostic.severity == vim.diagnostic.severity.WARN then icon = "⚠ " elseif diagnostic.severity == vim.diagnostic.severity.INFO then icon = "ℹ " elseif diagnostic.severity == vim.diagnostic.severity.HINT then icon = "➤ " end return icon .. diagnostic.message end }, signs = true, -- Symbole in der Randspalte anzeigen underline = true, -- Problematischen Code unterstreichen update_in_insert = false, severity_sort = true, float = { border = "rounded", source = "always", }, }) -- Tastenkombinationen für Diagnostik vim.keymap.set('n', 'cd', vim.diagnostic.open_float, { desc = 'Fehlerdetails anzeigen' }) vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Vorheriger Fehler' }) vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Nächster Fehler' }) vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Fehler in Liste anzeigen' })