neovim: swap out a filetype plugin in place of tree-sitter-nix-shell for handling #!nix-shell scripts
This commit is contained in:
@@ -4,7 +4,9 @@ moduleArgs@{ lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
plugins = import ./plugins.nix moduleArgs;
|
||||
plugin-packages = builtins.map (p: p.plugin) plugins;
|
||||
plugin-packages = builtins.filter (x: x != null) (
|
||||
builtins.map (p: p.plugin or null) plugins
|
||||
);
|
||||
plugin-configs = lib.concatMapStrings (p:
|
||||
lib.optionalString
|
||||
(p ? config) (
|
||||
|
78
hosts/common/programs/neovim/nix_shell.lua
Normal file
78
hosts/common/programs/neovim/nix_shell.lua
Normal file
@@ -0,0 +1,78 @@
|
||||
-- add to ~/.vimrc to enable file-type detection for `nix-shell` scripts,
|
||||
-- e.g. files with `#!nix-shell -i python3 -p python3 -p ...` are recognized as `python` files
|
||||
|
||||
-- see <https://neovim.io/doc/user/lua.html#vim.filetype.add()>
|
||||
vim.filetype.add {
|
||||
pattern = {
|
||||
['.*'] = {
|
||||
function(path, bufnr)
|
||||
function test_for_nix_shell_shebang(maybe_hashbang)
|
||||
local bang_payload = string.match(maybe_hashbang, '^#!(.*)$')
|
||||
if not bang_payload then
|
||||
return false -- not a shebang
|
||||
end
|
||||
-- look for `nix-shell` _as its own word_ anywhere in the shebang line
|
||||
for word in string.gmatch(bang_payload, "[^ ]+") do
|
||||
if word == "nix-shell" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- extract `$interpreter` from some `#!nix-shell -i $interpreter ...` line
|
||||
function parse_nix_shell(maybe_nix_shell)
|
||||
local shell_payload = string.match(maybe_nix_shell, "^#!nix%-shell(.*)$")
|
||||
|
||||
if not shell_payload then
|
||||
return
|
||||
end
|
||||
|
||||
local interpreters = {}
|
||||
local context = nil
|
||||
for word in string.gmatch(shell_payload, "[^ ]+") do
|
||||
if context == "-i" then
|
||||
table.insert(interpreters, word)
|
||||
context = nil
|
||||
elseif word == "-i" then
|
||||
context = "-i"
|
||||
end
|
||||
-- this parser doesn't consider _all_ nix flags, and especially things like quotes, etc.
|
||||
-- just keep your nix-shell lines simple...
|
||||
end
|
||||
|
||||
return interpreters[1]
|
||||
end
|
||||
|
||||
function filetype_from_interpreter(i)
|
||||
if string.match(i, "^python") then
|
||||
-- python3, python2.7, etc
|
||||
return "python"
|
||||
else
|
||||
-- very common for interpreter name to be the same as filetype
|
||||
return i
|
||||
end
|
||||
end
|
||||
|
||||
-- docs: <https://neovim.io/doc/user/api.html#nvim_buf_get_lines()>
|
||||
-- nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing})
|
||||
-- `start` and `end` are inclusive
|
||||
local first_few_lines = vim.api.nvim_buf_get_lines(bufnr, 0, 5, false)
|
||||
local maybe_hashbang = first_few_lines[1] or ''
|
||||
|
||||
if not test_for_nix_shell_shebang(maybe_hashbang) then
|
||||
return
|
||||
end
|
||||
|
||||
-- search for `#!nix-shell -i $interpreter ...` anywhere in the first few lines of the file
|
||||
for _, line in ipairs(first_few_lines) do
|
||||
local interpreter = parse_nix_shell(line)
|
||||
if interpreter then
|
||||
return filetype_from_interpreter(interpreter)
|
||||
end
|
||||
end
|
||||
end,
|
||||
-- high priority, to overrule vim's native detection (which gives ft=nix to all nix-shell files)
|
||||
{ priority = math.huge },
|
||||
},
|
||||
},
|
||||
}
|
@@ -194,7 +194,18 @@ with pkgs.vimPlugins;
|
||||
# nvim-treesitter ships its own queries which may be distinct from e.g. helix.
|
||||
# the queries aren't included when i ship the grammar in this manner.
|
||||
# maybe check: <https://github.com/nvim-treesitter/nvim-treesitter/wiki/Extra-modules-and-plugins> ?
|
||||
pkgs.tree-sitter-nix-shell
|
||||
#
|
||||
# however: tree-sitter for `#!nix-shell` is the WRONG APPROACH.
|
||||
# - because it works via "injection"s, i don't get proper LSP integration.
|
||||
# i.e. no undefined variable checks, or language-aware function completions
|
||||
# upstream vim showed interest in a similar approach as mine, but w/o the tree-sitter integration:
|
||||
# - <https://groups.google.com/g/vim_dev/c/c-VXsJu-EKA>
|
||||
# this likely still has the same problem w.r.t. LSP integration.
|
||||
# vim-nix project also has a solution:
|
||||
# - <https://github.com/LnL7/vim-nix/pull/51>
|
||||
# this overrides the active filetype, so likely *is* what i want.
|
||||
# and i've implemented my own pure-lua .vimrc integration further below
|
||||
# pkgs.tree-sitter-nix-shell
|
||||
]);
|
||||
type = "lua";
|
||||
config = ''
|
||||
@@ -228,6 +239,11 @@ with pkgs.vimPlugins;
|
||||
vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
|
||||
'';
|
||||
}
|
||||
{
|
||||
# detect `#!nix-shell -i $interpreter ...` files as filetype=$interpreter
|
||||
type = "lua";
|
||||
config = builtins.readFile ./nix_shell.lua;
|
||||
}
|
||||
{
|
||||
# show commit which last modified text under the cursor.
|
||||
# trigger with `:GitMessenger` or `<Leader>gm` (i.e. `\gm`)
|
||||
|
Reference in New Issue
Block a user