goto definition for a file path
Is your feature request related to a problem? Please describe.
It's awkward to navigate between related source files (e.g., source files that import other source files).
Describe the solution you'd like
LSP go-to on file path would ideally open that path.
Describe alternatives you've considered
I've tried to setup multi-LSP support and have nil do it, but it doesn't seem to work.
Additional context
In nil, if you 'go to' a path, it will open that file path. E.g., 'go to ./module.nix' will open ./module.nix. After switching to nixd, I am loving a lot of the cross-file analysis, but I really miss being able to hop between source files.
Did you mean "go to definition" for file paths?
AFAIK, Ctrl + Click works as a part of "documentLink" on vscode, I guess your editor may not provide such linking.
Yeah, I believe 'go to definition' is what it is. In Helix, it triggered when I hit g d, which is probably the exact same thing as Ctrl+Click in VSCode. The nixlang-relevant part of my config for Helix (setup via home-manager) is as follows:
languages = {
language-server.nixd = {
command = "nixd";
formatting = {
command = ["alejandra"];
};
options.nixos = {
expr = "(builtins.getFlake \"/etc/nixos\").nixosConfigurations.core.options";
};
};
language = [
{
name = "nix";
auto-format = true;
language-servers = ["nixd" "nil"];
formatter.command = "${pkgs.alejandra}/bin/alejandra";
}
];
};
If I select g d on an import path, it just says No definition found.
I see, seems to be reasonable to integrate it.
If it helps, I looked into it and figured out how to get a log of the Helix LSP thread's interactions with nixd. The output is here.
As a point of comparison, here is Helix interacting with nil to open a file by path via go-to-definition.
If it helps, I looked into it and figured out how to get a log of the Helix LSP thread's interactions with
nixd. The output is here.As a point of comparison, here is Helix interacting with
nilto open a file by path via go-to-definition.
Thanks for the detailed information; Acked. I also wanted to note that the feature document link behaves differently across editors. In vscode, document links become Ctrl + Click-able, which conflicts with the goto definition shortcut. That's why I didn't initially include it, as this project was primarily tested on vscode.
However, I believe it's important to enhance the user experience across all editors, so I'm happy to add this feature.
Thanks for that! I really appreciate it. ^w^
(Please let me know if I'm misunderstanding the issue):
In Helix, g f is "Goto files/URLs in selections" and g d is "Goto definition". In the video I press g f followed by g d:
https://github.com/user-attachments/assets/446be114-eab6-4961-89de-20961f7f2802
Relevant snippet from HM config for Helix:
languages = {
language = [
{
name = "nix";
auto-format = true;
language-servers = [ "nixd" ];
formatter.command = "nixfmt";
}
];
language-server = {
nixd = {
command = "nixd";
config = {
nixpkgs.expr = "import (builtins.getFlake \"/home/brisingr05/nixos-config\").inputs.nixpkgs { }";
formatting.command = [ "nixfmt" ]; # Currently doesn't work
options.nixos.expr = "(builtins.getFlake \"/home/brisingr05/nixos-config\").nixosConfigurations.hpaio.options";
};
};
}
}
That's nifty, @Brisingr05! I actually was just thinking of g f as a fuzzy finder opener, since that's what it does if no file path is selected in the editor.
Regardless, the concern still remains. Other editors will seemingly often roll the go-to-file and go-to-definition logic into a single user-facing action, but Helix does not. In Helix, you would need to train separate reflexes for both use cases. This is unpleasant if you're used to nil, which is able to trigger opening the file path on g d.
I also believe there is a logical separation here, too. g f will work on arbitrary strings/tokens. I hit g f on "24.05" and it will happily open a nonsense myworkdirectory/24.05 file that was never even a path by Nix's reckoning. This makes accidents easy and workflow unpleasant. Go-to-definition ought to have no such issue. If I see a ./mythingy.nix import, I ought to be able to jump to that as if it were an invocation of a previously declared variable, with the 'declaration' being the file in the path. If I hit g d on a string, however, it would not go to that file path because that is not the lang server's understanding of the token. This is a more correctness focused approach.
This also has precedence as a more 'intelligent' go-to-file behavior (as opposed to the raw behavior) -- which is why I'd prefer to keep my muscle memory trained on g d instead of g f for things like module/include paths.
E.g., in Rust, if you g d on mod mymodule. rust-analyzer + helix will take you to src/mymodule.rs, not just a file named mymodule. If you try using g f, it will just dump you in a nonexistent mymodule file. This sort of thing makes it my opinion that g f ought to be a last resort, rather than the recommended solution for this use case. g d has more universally intelligent behavior that can adapt itself to different languages.
Just tested it, and it also works in clang in the context of C projects.
g d in Helix takes you to definition for e.g. #include <stdio.h>. I think it's reasonable to say that this behavior is fairly well standardized, at least for static analysis of systems programming languages. :P
Edit:
It also works for Bash!
Hitting g d on ./bash2.sh in the context of source ./bash2.sh opens bash2.sh. Notably, this happens even if I hit g d on the source part. If I hit g f on the source token, it just dumps me in a nonexistent file named source. Notably, am using bash-language-server for this test.