Skip to content

Commit 9bdf6b0

Browse files
authored
feat: print target and package names formatted as file hyperlinks (#15405)
Resolves #15401 Here is an example of the feature in [kitty](https://sw.kovidgoyal.net/kitty/) `0.40.1` with the following config set in `~/.config/kitty/kitty.conf` ```conf underline_hyperlinks always show_hyperlink_targets yes allow_hyperlinks yes # ... ``` ![cargo-target-file-hyperlik-kitty-showcase](https://github.com/user-attachments/assets/04155d5a-a254-4e80-a35e-a02cc4671ae4) Tested on `uname -a`: ``` Linux nixos 6.14.0 #1-NixOS SMP PREEMPT_DYNAMIC Mon Mar 24 14:02:41 UTC 2025 x86_64 GNU/Linux ``` Terminals tested with: - [x] [kitty](https://sw.kovidgoyal.net/kitty/) `0.40.1` - [x] [ghostty](https://ghostty.org/) `1.1.4-6f1b22a-nix` ![image](https://github.com/user-attachments/assets/afeb250f-009b-429a-8854-6c3053449f9e) - [x] [alacritty](https://alacritty.org/index.html) `0.15.1` ![image](https://github.com/user-attachments/assets/9742cd72-13e5-4e90-8ece-dd101553e5cc) - [x] VScode's version `1.98` integrated terminal aka. [xterm.js](https://xtermjs.org/) ![image](https://github.com/user-attachments/assets/f02ce77a-18e4-47dd-b428-7b82bc013021) The following `cargo` invocations will have their output be modified by this change: ```shell cargo run # If multiple binaries are defined in the manifest and [package.default-bin] is not defined cargo run --bin cargo run --example cargo run --package cargo build --bin cargo build --example cargo build --package cargo test --test cargo test --bench ``` In addition I have done a slight refactor to have the printed indent of targets and packages be the same by using a shared constant named `const ITEM_INDENT: &str = " ";` This is my first PR to the cargo codebase, so I am not familiar with what is expected in terms of test for a feature such as this. <!-- Thanks for submitting a pull request 🎉! Here are some tips for you: * If this is your first contribution, read "Cargo Contribution Guide" first: https://doc.crates.io/contrib/ * Run `cargo fmt --all` to format your code changes. * Small commits and pull requests are always preferable and easy to review. * If your idea is large and needs feedback from the community, read how: https://doc.crates.io/contrib/process/#working-on-large-features * Cargo takes care of compatibility. Read our design principles: https://doc.crates.io/contrib/design.html * When changing help text of cargo commands, follow the steps to generate docs: https://github.com/rust-lang/cargo/tree/master/src/doc#building-the-man-pages * If your PR is not finished, set it as "draft" PR or add "WIP" in its title. * It's ok to use the CI resources to test your PR, but please don't abuse them. ### What does this PR try to resolve? Explain the motivation behind this change. A clear overview along with an in-depth explanation are helpful. You can use `Fixes #<issue number>` to associate this PR to an existing issue. ### How should we test and review this PR? Demonstrate how you test this change and guide reviewers through your PR. With a smooth review process, a pull request usually gets reviewed quicker. If you don't know how to write and run your tests, please read the guide: https://doc.crates.io/contrib/tests ### Additional information Other information you want to mention in this PR, such as prior arts, future extensions, an unresolved problem, or a TODO list. -->
2 parents c7be060 + 33ee639 commit 9bdf6b0

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

src/cargo/util/workspace.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ use anyhow::bail;
77
use cargo_util::paths::normalize_path;
88
use cargo_util::ProcessBuilder;
99
use std::fmt::Write;
10+
use std::path::Path;
1011
use std::path::PathBuf;
1112

13+
const ITEM_INDENT: &str = " ";
14+
1215
fn get_available_targets<'a>(
1316
filter_fn: fn(&Target) -> bool,
1417
ws: &'a Workspace<'_>,
1518
options: &'a CompileOptions,
16-
) -> CargoResult<Vec<&'a str>> {
19+
) -> CargoResult<Vec<(&'a str, &'a Path)>> {
1720
let packages = options.spec.get_packages(ws)?;
1821

1922
let mut targets: Vec<_> = packages
@@ -24,7 +27,12 @@ fn get_available_targets<'a>(
2427
.iter()
2528
.filter(|target| filter_fn(target))
2629
})
27-
.map(Target::name)
30+
.map(|target| {
31+
(
32+
target.name(),
33+
target.src_path().path().expect("Target is not a `Metabuild` but one of `Bin` | `Test` | `Bench` | `ExampleBin`")
34+
)
35+
})
2836
.collect();
2937

3038
targets.sort();
@@ -48,8 +56,10 @@ fn print_available_targets(
4856
writeln!(output, "No {} available.", plural_name)?;
4957
} else {
5058
writeln!(output, "Available {}:", plural_name)?;
51-
for target in targets {
52-
writeln!(output, " {}", target)?;
59+
let mut shell = ws.gctx().shell();
60+
for (name, src_path) in targets {
61+
let link = shell.err_file_hyperlink(src_path);
62+
writeln!(output, "{ITEM_INDENT}{link}{}{link:#}", name)?;
5363
}
5464
}
5565
bail!("{}", output)
@@ -58,7 +68,7 @@ fn print_available_targets(
5868
pub fn print_available_packages(ws: &Workspace<'_>) -> CargoResult<()> {
5969
let packages = ws
6070
.members()
61-
.map(|pkg| pkg.name().as_str())
71+
.map(|pkg| (pkg.name().as_str(), pkg.manifest_path()))
6272
.collect::<Vec<_>>();
6373

6474
let mut output = "\"--package <SPEC>\" requires a SPEC format value, \
@@ -72,8 +82,10 @@ pub fn print_available_packages(ws: &Workspace<'_>) -> CargoResult<()> {
7282
writeln!(output, "No packages available.")?;
7383
} else {
7484
writeln!(output, "Possible packages/workspace members:")?;
75-
for package in packages {
76-
writeln!(output, " {}", package)?;
85+
let mut shell = ws.gctx().shell();
86+
for (name, manifest_path) in packages {
87+
let link = shell.err_file_hyperlink(manifest_path);
88+
writeln!(output, "{ITEM_INDENT}{link}{}{link:#}", name)?;
7789
}
7890
}
7991
bail!("{}", output)

0 commit comments

Comments
 (0)