Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ isMaximal: {

tailwind.enable = false;
svelte.enable = false;
vue.enable = false;

# Nim LSP is broken on Darwin and therefore
# should be disabled by default. Users may still enable
Expand Down
4 changes: 4 additions & 0 deletions docs/manual/release-notes/rl-0.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
- Fix `vim.tabline.nvimBufferline` where `setupOpts.options.hover` requires
`vim.opt.mousemoveevent` to be set.

[miaapancake](https://github.com/miaapancake)

- Add vue language support.

[thamenato](https://github.com/thamenato):

- Attempt to adapt nvim-treesitter to (breaking) Nixpkgs changes. Some
Expand Down
1 change: 1 addition & 0 deletions modules/plugins/languages/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ in {
./yaml.nix
./ruby.nix
./just.nix
./vue.nix

# This is now a hard deprecation.
(mkRenamedOptionModule ["vim" "languages" "enableLSP"] ["vim" "lsp" "enable"])
Expand Down
24 changes: 22 additions & 2 deletions modules/plugins/languages/ts.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.types) enum package bool;
inherit (lib) optional;
inherit (lib.types) enum bool;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (lib.nvim.lua) toLuaObject;
Expand All @@ -21,14 +22,26 @@
servers = let
ts_ls = {
cmd = [(getExe pkgs.typescript-language-server) "--stdio"];
init_options = {hostInfo = "neovim";};
init_options = {
hostInfo = "neovim";
plugins =
[]
++ (optional config.vim.languages.vue.lsp.enable
{
name = "@vue/typescript-plugin";
location = "${pkgs.vue-language-server}/lib/language-tools/packages/language-server";
languages = ["vue"];
configNamespace = "typescript";
});
};
filetypes = [
"javascript"
"javascriptreact"
"javascript.jsx"
"typescript"
"typescriptreact"
"typescript.tsx"
"vue"
];
root_markers = ["tsconfig.json" "jsconfig.json" "package.json" ".git"];
handlers = {
Expand Down Expand Up @@ -63,6 +76,13 @@
},
})
end, {})

-- make sure that vue-language-server handles semantic tokens when we are in a vue file
if vim.bo.filetype == 'vue' then
client.server_capabilities.semanticTokensProvider.full = false
else
client.server_capabilities.semanticTokensProvider.full = true
end
end
'';
};
Expand Down
177 changes: 177 additions & 0 deletions modules/plugins/languages/vue.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
config,
pkgs,
lib,
...
}: let
inherit (builtins) attrNames;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.meta) getExe;
inherit (lib.types) enum listOf;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (lib.nvim.types) mkGrammarOption diagnostics;

cfg = config.vim.languages.vue;

defaultServers = ["vue_ls"];
servers = {
vue_ls = {
cmd = [(getExe pkgs.vue-language-server) "--stdio"];
filetypes = ["vue"];
root_markers = [
"tsconfig.json"
"jsconfig.json"
"package.json"
".git"
];
on_init = mkLuaInline ''
-- forward typescript blocks to ts_ls or vtsls depending on which is available first
function(client)
client.handlers['tsserver/request'] = function(_, result, context)
local ts_clients = vim.lsp.get_clients({ bufnr = context.bufnr, name = 'ts_ls' })
local clients = {}

vim.list_extend(clients, ts_clients)

if #clients == 0 then
vim.notify('Could not find `vtsls` or `ts_ls` lsp client, `vue_ls` would not work without it.', vim.log.levels.ERROR)
return
end
local ts_client = clients[1]

local param = unpack(result)
local id, command, payload = unpack(param)
ts_client:exec_cmd({
title = 'vue_request_forward', -- You can give title anything as it's used to represent a command in the UI, `:h Client:exec_cmd`
command = 'typescript.tsserverRequest',
arguments = {
command,
payload,
},
}, { bufnr = context.bufnr }, function(_, r)
local response = r and r.body
-- TODO: handle error or response nil here, e.g. logging
-- NOTE: Do NOT return if there's an error or no response, just return nil back to the vue_ls to prevent memory leak
local response_data = { { id, response } }

---@diagnostic disable-next-line: param-type-mismatch
client:notify('tsserver/response', response_data)
end)
end
end
'';
};
};
defaultFormat = ["prettier"];
formats = {
prettier = {
command = getExe pkgs.nodePackages.prettier;
options.ft_parsers.vue = "vue";
};
};
defaultDiagnosticsProvider = ["eslint_d"];
diagnosticsProviders = {
eslint_d = let
pkg = pkgs.eslint_d;
in {
package = pkg;
config = {
cmd = getExe pkg;
required_files = [
"eslint.config.js"
"eslint.config.mjs"
".eslintrc"
".eslintrc.json"
".eslintrc.js"
".eslintrc.yml"
];
};
};
};
formatType =
enum (attrNames formats);
Comment on lines +93 to +94

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this type is wrong and errors when evaluating, since you expect a single value, but you're setting a list above.
see here:
https://github.com/miaapancake/nvf/blob/533135a95d147110e581da686975cd0312e4aac6/modules/plugins/languages/vue.nix#L67-L73

Looking at what you've been setting in defaultFormat above, you probably want this:

Suggested change
formatType =
enum (attrNames formats);
formatType =
nonEmptyListOf (enum (attrNames formats));

in {
_file = ./vue.nix;
options.vim.languages.vue = {
enable = mkEnableOption "Vue language support";

treesitter = {
enable = mkEnableOption "Vue treesitter" // {default = config.vim.languages.enableTreesitter;};

vuePackage = mkGrammarOption pkgs "vue";
};

lsp = {
enable = mkEnableOption "Vue LSP support" // {default = config.vim.lsp.enable;};

servers = mkOption {
type = listOf (enum (attrNames servers));
default = defaultServers;
description = "Vue LSP server to use";
};
};

format = {
enable = mkEnableOption "Vue formatting" // {default = config.vim.languages.enableFormat;};

type = mkOption {
type = formatType;
default = defaultFormat;
description = "Vue formatter to use";
};
};

extraDiagnostics = {
enable = mkEnableOption "extra Vue diagnostics" // {default = config.vim.languages.enableExtraDiagnostics;};

types = diagnostics {
langDesc = "Vue";
inherit diagnosticsProviders;
inherit defaultDiagnosticsProvider;
};
};
};

config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.vuePackage];
})

(mkIf cfg.lsp.enable {
vim.lsp.servers =
mapListToAttrs (n: {
name = n;
value = servers.${n};
})
cfg.lsp.servers;
})

(mkIf cfg.format.enable {
vim.formatter.conform-nvim = {
enable = true;
setupOpts = {
formatters_by_ft.vue = cfg.format.type;
formatters =
mapListToAttrs (name: {
inherit name;
value = formats.${name};
})
cfg.format.type;
};
};
})

(mkIf cfg.extraDiagnostics.enable {
vim.diagnostics.nvim-lint = {
enable = true;
linters_by_ft.vue = cfg.extraDiagnostics.types;
linters =
mkMerge (map (name: {${name} = diagnosticsProviders.${name}.config;})
cfg.extraDiagnostics.types);
};
})
]);
}
Loading