-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(complete): Support multi-path-element prefix completion #6261
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
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to add duplicate coverage
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some of the test organization is suspect |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1443,6 +1443,201 @@ pos-c | |
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn suggest_multi_path_element_prefix() { | ||
| let mut cmd = Command::new("dynamic") | ||
| .arg( | ||
| clap::Arg::new("input") | ||
| .long("input") | ||
| .short('i') | ||
| .value_hint(clap::ValueHint::AnyPath), | ||
| ); | ||
|
|
||
| let testdir = snapbox::dir::DirRoot::mutable_temp().unwrap(); | ||
| let testdir_path = testdir.path().unwrap(); | ||
|
|
||
| // Create a nested directory structure | ||
| fs::create_dir_all(testdir_path.join("target/debug/incremental")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join("target/release")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join("tests")).unwrap(); | ||
| fs::write(testdir_path.join("target/debug/binary"), "").unwrap(); | ||
|
|
||
| // 1. Single-component abbreviation: standard prefix matching still works | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input tar[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str!["target/"] | ||
| ); | ||
|
|
||
| // 2. Two-component abbreviation: "tar/de" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input tar/de[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 3. Full abbreviated path: "tar/de/inc" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input tar/de/inc[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 4. Abbreviated path to a file: "tar/de/bin" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input tar/de/bin[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 5. Multiple matches for last component: "tar/re" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input tar/re[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 6. Single char per component: "t/d/i" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input t/d/i[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn suggest_multi_path_element_prefix_edge_cases() { | ||
| let mut cmd = Command::new("dynamic") | ||
| .arg( | ||
| clap::Arg::new("input") | ||
| .long("input") | ||
| .short('i') | ||
| .value_hint(clap::ValueHint::AnyPath), | ||
| ); | ||
|
|
||
| let testdir = snapbox::dir::DirRoot::mutable_temp().unwrap(); | ||
| let testdir_path = testdir.path().unwrap(); | ||
|
|
||
| // Create directory structure | ||
| fs::create_dir_all(testdir_path.join("target/debug/incremental")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join("target/release")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join("tests")).unwrap(); | ||
| fs::write(testdir_path.join("target/debug/binary"), "").unwrap(); | ||
|
|
||
| // 7. Non-existent abbreviated path: no match, should return empty | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input foo/bar/baz[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 8. Empty input: should list top-level directory contents (normal behavior) | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input [TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![[r#" | ||
| . | ||
| target/ | ||
| tests/ | ||
| "#]] | ||
| ); | ||
|
|
||
| // 9. Trailing slash on abbreviated component: "tar/" tries to list contents of | ||
| // non-existent "tar/" directory, falls back to abbreviated matching | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input tar/[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 10. Single component with no slash: normal prefix completion, no abbreviation needed | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input targ[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str!["target/"] | ||
| ); | ||
|
|
||
| // 11. Path with "./" prefix: doesn't work without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input ./tar/de[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // 12. Ambiguous first component: doesn't work without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input t/d[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn suggest_multi_path_element_prefix_existing_paths() { | ||
| let mut cmd = Command::new("dynamic") | ||
| .arg( | ||
| clap::Arg::new("input") | ||
| .long("input") | ||
| .short('i') | ||
| .value_hint(clap::ValueHint::AnyPath), | ||
| ); | ||
|
|
||
| let testdir = snapbox::dir::DirRoot::mutable_temp().unwrap(); | ||
| let testdir_path = testdir.path().unwrap(); | ||
|
|
||
| // Create directory structure | ||
| fs::create_dir_all(testdir_path.join("target/debug/incremental")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join("target/release")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join("tests")).unwrap(); | ||
| fs::write(testdir_path.join("target/debug/binary"), "").unwrap(); | ||
|
|
||
| // 13. Normal full path completion: "target/" lists contents of target/ | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input target/[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![[r#" | ||
| target/debug/ | ||
| target/release/ | ||
| "#]] | ||
| ); | ||
|
|
||
| // 14. Normal file completion within a real directory path | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input target/debug/bin[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str!["target/debug/binary"] | ||
| ); | ||
|
|
||
| // 15. Normal full path prefix completion still works | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input target/de[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str!["target/debug/"] | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn suggest_multi_path_element_prefix_hidden_files() { | ||
| let mut cmd = Command::new("dynamic") | ||
| .arg( | ||
| clap::Arg::new("input") | ||
| .long("input") | ||
| .short('i') | ||
| .value_hint(clap::ValueHint::AnyPath), | ||
| ); | ||
|
|
||
| let testdir = snapbox::dir::DirRoot::mutable_temp().unwrap(); | ||
| let testdir_path = testdir.path().unwrap(); | ||
|
|
||
| // Create directory structure with hidden directories | ||
| fs::create_dir_all(testdir_path.join(".config/nvim/lua")).unwrap(); | ||
| fs::create_dir_all(testdir_path.join(".cache/downloads")).unwrap(); | ||
| fs::write(testdir_path.join(".config/nvim/init.lua"), "").unwrap(); | ||
|
|
||
| // Hidden directory abbreviated paths: ".c/n" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input .c/n[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
|
||
| // Hidden directory deep abbreviated paths: ".c/n/l" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input .c/n/l[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
|
|
||
| // Hidden directory abbreviated path to file: ".c/n/i" doesn't match without abbreviated path support | ||
| assert_data_eq!( | ||
| complete!(cmd, "--input .c/n/i[TAB]", current_dir = Some(testdir_path)), | ||
| snapbox::str![""] | ||
| ); | ||
| } | ||
|
|
||
| fn complete(cmd: &mut Command, args: impl AsRef<str>, current_dir: Option<&Path>) -> String { | ||
| let input = args.as_ref(); | ||
| let mut args = vec![std::ffi::OsString::from(cmd.get_name())]; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing test cases: