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

programs.nix-index: add common-not-found support for Fish #272

Closed
wants to merge 3 commits into from

Conversation

malob
Copy link
Contributor

@malob malob commented Jan 17, 2021

Works like a charm for me!

❯ dot
The program 'dot' is currently not installed. It is provided by
several packages. You can install it by typing one of the following:
  nix-env -iA nixpkgs.graphviz_2_32.out
  nix-env -iA nixpkgs.graphviz-nox.out
  nix-env -iA nixpkgs.graphviz.out

@LnL7
Copy link
Owner

LnL7 commented Jan 28, 2021

I don't know much about fish, but I think the fish integration uses foreign-env/babelfish to interact with standard shell scripts. Might also be relevant here, would be great of somebody that actually uses fish could take a look.

@malob
Copy link
Contributor Author

malob commented Jan 29, 2021

So, as far as I can tell, foreign-env isn't an option in this case (though it's totally possible I'm missing something and there is a way to use it).

With #270 now merged, it should be possible to add something like the following to the nix-index module's config, to get this working:

programs.fish.interactiveShellInit = mkIf config.programs.fish.useBabelfish ''
  function __fish_command_not_found_handler --on-event="fish_command_not_found"
    command_not_found_handle $argv
  end
'';

Unfortunately, it appears that currently babelfish fails when parsing the command-not-found.sh script (see #282). So until a fix gets implemented upstream, that doesn't seem to be an option. Also if/when that happens, unless programs.fish switches to using babelfish by default, adding this feature will still require an alternative implementation for those that don't have programs.fish.useBabelfish enabled.

Maybe others like @kevingriffin, @bouk, or @toonn, might have ideas on the best way to move this forward?

@toonn
Copy link
Contributor

toonn commented Jan 29, 2021

I think the simplest way forward is to petition the project to include a fish version of the handler too, shelling out to bash probably introduces a noticeable delay.

I'd also prefer if this was easy to disable. I don't personally use such hooks.

@malob
Copy link
Contributor Author

malob commented Jan 30, 2021

I think the simplest way forward is to petition the project to include a fish version of the handler too, shelling out to bash probably introduces a noticeable delay.

There's currently and issue about that on the nix-index repo, however I'm not sure it will go anywhere: nix-community/nix-index#126

In this case, It doesn't look like shelling out to Bash is having any noticeable effect. Here are the results of a quick benchmark I just ran:

hyperfine --ignore-failure --show-output --runs 50 --export-markdown results.md \
  --command-name Sourcing \
    "bash -c 'source command-not-found.sh; command_not_found_handle dot'" \
  --command-name Direct \ 
    'command_not_found_handle dot'
Command Mean [ms] Min [ms] Max [ms] Relative
Sourcing 224.5 ± 5.7 217.5 247.0 1.01 ± 0.04
Direct 222.7 ± 7.4 214.9 248.6 1.00

I'd also prefer if this was easy to disable. I don't personally use such hooks.

So, the only thing programs.nix-index.enable = true does aside from adding pkgs.nix-index to environment.systemPackages is configuring the command-not-found shell hook. As such, there's no reason for someone to use this module unless they want the hook. I definitely agree that if there was some other reason to use this module aside from the hook, that an option to enable/disable the hook would be the right call.

@malob
Copy link
Contributor Author

malob commented Jan 30, 2021

As some additional context, in the benchmark in my previous comment, most of the execution time is actually time it takes to show the output. Removing the --show-output flag from the benchmark gives us the time it takes to run the two without including the time it took to print the output.

Command Mean [ms] Min [ms] Max [ms] Relative
Sourcing 3.0 ± 0.4 2.5 4.8 28.47 ± 51.94
Direct 0.1 ± 0.2 0.0 1.9 1.00

So, at least on my system, shelling out to Bash, sourcing, then running the function adds about 3ms on average.

@toonn
Copy link
Contributor

toonn commented Jan 30, 2021

Note that my performance remark is inconsequential if it's barely noticeable anyway.
But aren't you basically benchmarking the same thing twice? I.e., starting bash, sourcing the script, running the function v. running the script, which will use bash because of the shebang? The performance difference would be between shelling out to bash and a native fish implementation. Though if the nix-index binary accounts for most of the time anyway the point is moot.

If this is the only reason to enable the module I agree a flag's not necessary.

@malob
Copy link
Contributor Author

malob commented Feb 1, 2021

Note that my performance remark is inconsequential if it's barely noticeable anyway.

Totally.

But aren't you basically benchmarking the same thing twice? I.e., starting bash, sourcing the script, running the function v. running the script, which will use bash because of the shebang? The performance difference would be between shelling out to bash and a native fish implementation.

Sorry, I think I might not have been very clear about what I'm comparing with the benchmark, or at least trying to compare. I claim (though it's possible of course that I'm confused/wrong) that what I'm comparing with that benchmark, is the difference between,

  • the time it takes to run command_not_found_handle once it's already been sourced by the shell and is thus available to run as a command from the prompt; and
  • the time it takes to spawn a Bash sub-shell, source the command-not-found.sh script, then run the command_not_found_handle command.

I think this is the relevant comparison since, in the absence of there being a native Fish implementation (or using Babelfish to create one from the current version), the only way for Fish to run the command is the run it inside a sub-shell that supports the current implementation (the workaround I implemented here). It seems to me like the key question when trying to figure out whether this workaround incurs a significant performance penalty, is to look at how much longer it takes to spawn a new bash shell, source the script, and run the command, compared to just running the command directly.

To do that, I ran hyperfine from Bash, after running export -f command_not_found_handle (which is already available in my Bash environment) so that the sh shell that hyperfine spawns would have the command available in it's environment (unless asked to do otherwise, hyperfine runs the given command in an sh shell).

Though if the nix-index binary accounts for most of the time anyway the point is moot.

Just to clarify. It's my understanding that the only difference between the two versions of the benchmarks I posted is whether the output of the commands is printed to the terminal or not. Both benchmarks are running the command. So it's actually the case that running the command takes a negligible amount of time, and the bulk of the time is taken up waiting for the terminal to render the output (I'm using Kitty).

(Edit: Actually, it's not the terminal rendering, I ran the first benchmark again piping the output of both commands to /dev/null, and got a similar result. Though, regardless that doesn't change the fact that the difference between the two commands run in either version of the benchmark is negligible.)

@malob
Copy link
Contributor Author

malob commented Feb 1, 2021

With #282 now resolved with the latest version of Babelfish, I've updated the PR accordingly, so that it uses the Fish native command that Babelfish creates, if programs.fish.useBabelFish is enabled, and falls back to the workaround otherwise.

@malob
Copy link
Contributor Author

malob commented Aug 30, 2022

Gonna close this since it's been open for a while now, and I don't care very much about it.

@malob malob closed this Aug 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants