Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

goto definition for a file path #557

Open
crabdancing opened this issue Jul 30, 2024 · 9 comments
Open

goto definition for a file path #557

crabdancing opened this issue Jul 30, 2024 · 9 comments
Labels
enhancement New feature or request idea-approved Proposed idea is approved by at least 1 maintainers

Comments

@crabdancing
Copy link

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.

@crabdancing crabdancing changed the title GOTO file path LSP 'go to' a file path Jul 30, 2024
@inclyc
Copy link
Member

inclyc commented Jul 30, 2024

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.

@crabdancing
Copy link
Author

crabdancing commented Jul 30, 2024

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.

@inclyc inclyc added the enhancement New feature or request label Jul 30, 2024
@inclyc
Copy link
Member

inclyc commented Jul 30, 2024

I see, seems to be reasonable to integrate it.

@inclyc inclyc added the idea-approved Proposed idea is approved by at least 1 maintainers label Jul 30, 2024
@crabdancing
Copy link
Author

crabdancing commented Jul 30, 2024

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.

@inclyc
Copy link
Member

inclyc commented Jul 31, 2024

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.

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.

@inclyc inclyc changed the title LSP 'go to' a file path goto definition for a file path Jul 31, 2024
@crabdancing
Copy link
Author

Thanks for that! I really appreciate it. ^w^

@Brisingr05
Copy link

(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:

2024-08-08_09-29-25.mp4

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";
      };
    };
  }
}

@crabdancing
Copy link
Author

crabdancing commented Aug 9, 2024

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.

@crabdancing
Copy link
Author

crabdancing commented Aug 9, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request idea-approved Proposed idea is approved by at least 1 maintainers
Projects
None yet
Development

No branches or pull requests

3 participants