Use rustc --print sysroot for default sources

Previously, we were used /usr/share/doc/rust{,-doc}/html as a default
source, assuming that it would contain the standard library
documentation.  This is true if the user installed the Rust
documentation manually or using a package manager.  If they use rustup
instead, the documentation is placed in a subdirectory of ~/.rustup.

With this patch, we call `rustc --print sysroot` to determine the
installation directory of the currently activated Rust toolchain –
either the system Rust installation or a Rust installation managed by
rustup.  We then use `$(sysroot)/share/doc/…` as a default path for the
standard library documentation (with /usr as a fallback if the call to
rustc does not return a valid path).
This commit is contained in:
Robin Krahl 2020-07-25 19:06:27 +02:00
parent 4d7c7d4eab
commit 64dd5a55ae
No known key found for this signature in database
GPG Key ID: 8E9B0870524F69D8
3 changed files with 44 additions and 20 deletions

View File

@ -5,6 +5,11 @@ SPDX-License-Identifier: MIT
# Changelog for rusty-man
## Unreleased
- Use `rustc --print sysroot` to determine the Rust installation directory
instead of always using `/usr`.
## v0.1.2 (2020-07-25)
This patch release adds basic logging output and a new `-e`/`--examples` option

View File

@ -31,17 +31,17 @@ You dont have to specificy the full item name:
$ rusty-man NodeRef
```
If the documentation is not placed in `./target/doc` or
`/usr/share/doc/rust{,-doc}/html`, you have to manually set the source path
using the `-s`/`--source` option:
If the documentation is not placed in `./target/doc` or the Rust installation
directory, you have to manually set the source path using the `-s`/`--source`
option:
```
$ rusty-man --source ~/.rustup/toolchains/stable-*/share/doc/html io::Error
$ rusty-man --source my/other/crate/target/doc io::Error
```
If there are multiple matches for the keyword, rusty-man will show you a list
of all matching items:
```
$ rusty-man --source ~/.rustup/toolchains/stable-*/share/doc/rust/html u8
$ rusty-man --source my/other/crate/target/doc u8
Found mulitple matches for u8 select one of:
[ 0 ] core::u8: The 8-bit unsigned integer type.

View File

@ -6,8 +6,9 @@
//! rusty-man opens the documentation for a given keyword. It performs these steps to find the
//! documentation for an item:
//! 1. The sources, currently only local directories, are loaded, see the `load_sources` funnction
//! and the `source` module. Per default, we look for documentation in `/usr/share/doc` and in
//! `./target/doc`.
//! and the `source` module. Per default, we look for documentation in the directory
//! `share/doc/rust{,-doc}/html` relative to the Rust installation path (`rustc --print sysroot`
//! or `usr`) and in `./target/doc`.
//! 2. We split the keyword `{crate}::{item}` into the crate and the item and try to find the crate
//! in one of the sources see the `find_crate` function.
//! 3. If we found a crate, we look up the item in the `all.html` file of the crate and load the
@ -50,8 +51,9 @@ use structopt::StructOpt;
/// rusty-man reads the HTML documentation generated by rustdoc and displays a documentation item.
/// Make sure to run `cargo doc` before using rusty-man. Per default, rusty-man looks up
/// documentation in the ./target/doc directory relative to the current working directory and in
/// the system documentation directories (/usr/share/doc/rust{,-doc}/html). Use the -s/--source
/// option if you want to read the documentation from a different directory.
/// the system documentation directories (share/doc/rust{,-doc}/html relative to the Rust sysroot,
/// see `rustc --print sysroot`, or /usr). Use the -s/--source option if you want to read the
/// documentation from a different directory.
///
/// rusty-man tries to find an item that exactly matches the given keyword. If it doesnt find an
/// exact match, it reads the search indexes of all available sources and tries to find a partial
@ -74,8 +76,9 @@ struct Opt {
/// Do not search the default documentation sources
///
/// If this option is not set, rusty-man appends `/usr/share/doc/rust{,-doc}/html` and
/// `target/doc` to the list of sources if they exist.
/// If this option is not set, rusty-man appends `$sysroot/share/doc/rust{,-doc}/html` and
/// `target/doc` to the list of sources if they exist. `$sysroot` is the output of `rustc
/// --print sysroot` or `/usr` if that command does not output a valid path.
#[structopt(long)]
no_default_sources: bool,
@ -124,12 +127,6 @@ fn main() -> anyhow::Result<()> {
}
}
const DEFAULT_SOURCES: &[&str] = &[
"/usr/share/doc/rust/html",
"/usr/share/doc/rust-doc/html",
"./target/doc",
];
/// Load all sources given as a command-line argument and, if enabled, the default sources.
fn load_sources(
sources: &[String],
@ -138,10 +135,9 @@ fn load_sources(
let mut vec: Vec<Box<dyn source::Source>> = Vec::new();
if load_default_sources {
for s in DEFAULT_SOURCES {
let path: &path::Path = s.as_ref();
for path in get_default_sources() {
if path.is_dir() {
vec.push(source::get_source(path)?);
vec.push(source::get_source(&path)?);
} else {
log::info!(
"Ignoring default source '{}' because it does not exist",
@ -161,6 +157,29 @@ fn load_sources(
Ok(vec)
}
fn get_default_sources() -> Vec<path::PathBuf> {
let mut default_sources: Vec<path::PathBuf> = Vec::new();
let sysroot = get_sysroot().unwrap_or_else(|| path::PathBuf::from("/usr"));
default_sources.push(sysroot.join("share/doc/rust/html"));
default_sources.push(sysroot.join("share/doc/rust-doc/html"));
default_sources.push(path::PathBuf::from("./target/doc"));
default_sources
}
fn get_sysroot() -> Option<path::PathBuf> {
std::process::Command::new("rustc")
.arg("--print")
.arg("sysroot")
.output()
.ok()
.filter(|o| o.status.success())
.and_then(|o| String::from_utf8(o.stdout).ok())
.map(|s| s.trim().into())
}
/// Find the documentation for an item with the given name (exact matches only).
fn find_doc(
sources: &[Box<dyn source::Source>],