Skip to content

Commit 72e90fa

Browse files
committed
feat: Add custom completer for cargo remove <TAB>
1 parent aed94a8 commit 72e90fa

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

src/bin/cargo/commands/remove.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ pub fn cli() -> clap::Command {
2525
.required(true)
2626
.num_args(1..)
2727
.value_name("DEP_ID")
28-
.help("Dependencies to be removed")])
28+
.help("Dependencies to be removed")
29+
.add(clap_complete::ArgValueCandidates::new(
30+
get_direct_dependencies_pkg_name_candidates,
31+
))])
2932
.arg_dry_run("Don't actually write the manifest")
3033
.arg_silent_suggestion()
3134
.next_help_heading("Section")

src/cargo/util/command_prelude.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::core::compiler::{
22
BuildConfig, CompileKind, MessageFormat, RustcTargetData, TimingOutput,
33
};
44
use crate::core::resolver::{CliFeatures, ForceAllTargets, HasDevUnits};
5+
use crate::core::Dependency;
56
use crate::core::{profiles::Profiles, shell, Edition, Package, Target, TargetKind, Workspace};
67
use crate::ops::lockfile::LOCKFILE_NAME;
78
use crate::ops::registry::RegistryOrIndex;
@@ -23,8 +24,10 @@ use cargo_util_schemas::manifest::RegistryName;
2324
use cargo_util_schemas::manifest::StringOrVec;
2425
use clap::builder::UnknownArgumentValueParser;
2526
use home::cargo_home_with_cwd;
27+
use indexmap::IndexSet;
28+
use itertools::Itertools;
2629
use semver::Version;
27-
use std::collections::HashMap;
30+
use std::collections::{HashMap, HashSet};
2831
use std::ffi::{OsStr, OsString};
2932
use std::path::Path;
3033
use std::path::PathBuf;
@@ -1404,6 +1407,56 @@ fn get_packages() -> CargoResult<Vec<Package>> {
14041407
Ok(packages)
14051408
}
14061409

1410+
pub fn get_direct_dependencies_pkg_name_candidates() -> Vec<clap_complete::CompletionCandidate> {
1411+
let (current_package_deps, all_package_deps) = match get_dependencies_from_metadata() {
1412+
Ok(v) => v,
1413+
Err(_) => return Vec::new(),
1414+
};
1415+
1416+
let current_package_deps_package_names = current_package_deps
1417+
.into_iter()
1418+
.map(|dep| dep.package_name().to_string())
1419+
.sorted();
1420+
let all_package_deps_package_names = all_package_deps
1421+
.into_iter()
1422+
.map(|dep| dep.package_name().to_string())
1423+
.sorted();
1424+
1425+
let mut package_names_set = IndexSet::new();
1426+
package_names_set.extend(current_package_deps_package_names);
1427+
package_names_set.extend(all_package_deps_package_names);
1428+
1429+
package_names_set
1430+
.into_iter()
1431+
.map(|name| name.into())
1432+
.collect_vec()
1433+
}
1434+
1435+
fn get_dependencies_from_metadata() -> CargoResult<(Vec<Dependency>, Vec<Dependency>)> {
1436+
let cwd = std::env::current_dir()?;
1437+
let gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);
1438+
let ws = Workspace::new(&find_root_manifest_for_wd(&cwd)?, &gctx)?;
1439+
let current_package = ws.current().ok();
1440+
1441+
let current_package_dependencies = ws
1442+
.current()
1443+
.map(|current| current.dependencies())
1444+
.unwrap_or_default()
1445+
.to_vec();
1446+
let all_other_packages_dependencies = ws
1447+
.members()
1448+
.filter(|&member| Some(member) != current_package)
1449+
.flat_map(|pkg| pkg.dependencies().into_iter().cloned())
1450+
.collect::<HashSet<_>>()
1451+
.into_iter()
1452+
.collect::<Vec<_>>();
1453+
1454+
Ok((
1455+
current_package_dependencies,
1456+
all_other_packages_dependencies,
1457+
))
1458+
}
1459+
14071460
pub fn new_gctx_for_completions() -> CargoResult<GlobalContext> {
14081461
let cwd = std::env::current_dir()?;
14091462
let mut gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);

0 commit comments

Comments
 (0)