NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.02k stars 14.03k forks source link

ruby: documentation is missing #154283

Open csabahenk opened 2 years ago

csabahenk commented 2 years ago

Issue description

The *.ri documentation is not generated (or shipped) with the build, so ri(1), the standard doc cli for Ruby, is not displaying the documentation for core / stdlib APIs. (Nb. Ruby has a docSupport opion, which is true by default.) This is true for all versions shipped by nixpkgs.

Steps to reproduce

Actual:

$ ri Hash
Nothing known about Hash

Expected:

$ ri Hash
= Hash < Object                                                                                                                                                                                                                                                                                                               

------------------------------------------------------------------------
= Includes:
Enumerable (from ruby core)

(from ruby core)                                                                                                                                                                                                                                                                                                              
------------------------------------------------------------------------
A Hash maps each of its unique keys to a specific value.
...

Technical details

$ nix-shell -p nix-info --run "nix-info -m"
 - host os: `Linux 5.10.89, NixOS, 21.11 (Porcupine)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3.16`
 - channels(root): `"nixos-21.11.335037.e67c94a1adb"`
 - channels(csaba): `""`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`

The posix path for the Ruby *.ri files is /usr/share/ri/\<ruby version>/system (eg. documentation of the Hash class, that was looked for in the above example, should reside at /usr/share/ri/\<ruby version>/system/Hash/cdesc-Hash.ri). /usr/share/ri does not exist in the Nix ruby packages.

I checked for the effect of the docSupport option; only difference I see is that if it's enabled, the /usr/share/ruby/doc directory is created, otherwise it's not (and it's left empty even in the former case). I don't know of any reliance of the Ruby ecosystem on /usr/share/ruby/doc (all I know is that some distros chose to place some package miscellany in it, like LICENSE). Documentation in Ruby world means *.ri.

I tried to locate *.ri files via nix-index / nix-locate (maybe they are slated to some other package?), but even that does not give anything either.

csabahenk commented 2 years ago

Hi @alyssais, I see that your commits 6ffb5079b285a8db67856cb3ea43bfbb08310eb5 547b5b7a73e8a780b6438cf1128388dbc51b002e basically fix this issue so maybe this could be closed. Was your effort linked to or motivated by the current issue, or it's an independent efffort? Is there an issue where your work was tracked?

However, one thing is not clear, how to make ri documentation available with nix-env? nix-env -i -A ruby.devdoc does not make the trick.

nepella commented 2 years ago

I think the reason that Ri can find the documentation when Ruby.devdoc is loaded with a Nix-shell but not when it's installed in the user profile or system-wide is that, from Nix-shell, Ruby.devdoc adds ${ruby.devdoc}/lib/ruby/site_ruby to the RUBYLIB environment variable. With that set, Ruby loads ${ruby.devdoc}/lib/ruby/site_ruby/rbconfig.rb on startup, which sets the Ruby variable RbConfig::CONFIG["ridir"] to point at the documentation directory.

I'd love to know how to solve this properly, but this worked for me:

# Inside `home.packages` (or `environment.systemPackages`):
(let
  ruby = ruby_3_0;
  rubyWithPkgs = ruby.withPackages (p: with p; [
    nokogiri
    pry
  ]);
in stdenvNoCC.mkDerivation {
  name = "${ruby.name}-with-packages-and-docs";
  nativeBuildInputs = [ makeWrapper ];
  buildCommand = ''
    for i in ${rubyWithPkgs}/bin/*; do
        makeWrapper "$i" $out/bin/$(basename "$i") \
            --set RUBYLIB ${ruby.devdoc}/lib/ruby/site_ruby
    done

    ln -s ${ruby}/nix-support $out/nix-support
  '';
  preferLocalBuild = true;
  allowSubstitutes = false;
})

That also makes documentation available from within Pry.

If the Ruby derivation didn't split out the documentation into a separate output, this wouldn't be a problem. I played with overriding it to install the documentation in the primary output, but that required uglier code and defeated the binary cache. I'm likely missing something here, but it seems to me that breaking Ruby's documentation to save a mere 11 MB is not a good trade.

NNBnh commented 1 year ago

Hello, is there a quick fix to get ruby's documentations on my machine?

csabahenk commented 1 year ago

@NNBnh

nix-shell -p ruby_3_1 ruby_3_1.devdoc

works for me.

chasevasic commented 1 year ago

Hey, any reason why this has not been fixed? If I have enabled development docs in my system flake, I should not need to enter a nix shell for system-wide applications to access them without modifying environment vars or using my own shims. For example, using neovim with a ruby LSP, I cannot see yard docs even though they are in my system closure, unless I modify environment variables or run it inside a nix shell.

pjones commented 9 months ago

It's surprisingly difficult to get a development environment where Ruby docs and installed gem docs are available. Here is a flake that I'm currently using:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  };

  outputs = { self, nixpkgs }:
    let
      supportedSystems = [
        "x86_64-linux"
      ];

      # Function to generate a set based on supported systems:
      forAllSystems = f:
        nixpkgs.lib.genAttrs supportedSystems (system: f system);

      # Attribute set of nixpkgs for each system:
      nixpkgsFor = forAllSystems (system:
        import nixpkgs { inherit system; });

      # Which version of Ruby are we using?
      ruby = pkgs: pkgs.ruby_3_3;

      # Function to force installation of documentation for the given
      # Ruby Gem:
      withDocs = map (gem: gem.override {
        document = [ "ri" ];
      });

      rubyWithPackages = pkgs:
        (ruby pkgs).withPackages (ps:
          with ps;
          withDocs [
            rubocop
            minitest
          ]);
    in
    {
      devShells = forAllSystems (system:
        let pkgs = nixpkgsFor.${system}; in
        {
          default = pkgs.mkShell {
            buildInputs = with pkgs; [
              (rubyWithPackages pkgs)
              (ruby pkgs).devdoc
            ];
          };
        });
    };
}

@marsam Do you have any suggestions on how to improve this? Is there a better way to get Ruby docs into the current environment?