Skip to content

Commit

Permalink
fix: Completions of paths with spaces and single quotes (#20)
Browse files Browse the repository at this point in the history
* fix: completions of paths with spaces
  • Loading branch information
domsleee authored Mar 6, 2024
1 parent c8689a1 commit ccbdc57
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 3 deletions.
2 changes: 1 addition & 1 deletion resource/completions.nu
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
def "nu-complete git branches" [] {
^git branch | lines | each { |line| $line | str replace '\* ' "" | str trim }
^git branch | lines | each { |line| $line | str replace '* ' "" | str trim }
}

def "nu-complete git switchable branches" [] {
Expand Down
13 changes: 12 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,24 @@ fn complete(root_args: &RootArgs, complete_args: &CompleteArgs) -> Result<(), st
let suggestions = completer.complete(arg_str, arg_str.len());
let suggestion_strings: Vec<String> = suggestions
.iter()
.map(|x| x.value.clone().split(' ').last().unwrap().to_string())
.map(|x| maybe_process_path(&x.value.clone().to_string()))
.collect();

println!("{}", suggestion_strings.join("\n"));
Ok(())
}

fn maybe_process_path(arg: &str) -> String {
if arg.len() > 1 && arg.starts_with('`') && arg.ends_with('`') {
// replace the start and end backticks with single quotes
// also replace all single quotes with double single quote
let replaced_single_quotes = &arg[1..arg.len() - 1].replace('\'', "''");
return format!("'{replaced_single_quotes}'",);
}

arg.to_string()
}

fn get_string_from_files(root_args: &RootArgs) -> String {
match &root_args.file_override {
Some(file_override) => fs::read_to_string(file_override)
Expand Down
45 changes: 44 additions & 1 deletion tests/test_complete_git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,49 @@ fn test_complete_nongit_command(shell: &str) {
let res = testenv
.run_with_profile("Invoke-TabComplete 'burrito -'")
.unwrap();
let lines = res.stdout.lines().map(|x| x.unwrap()).collect_vec();
let lines: Vec<String> = res.stdout.lines().map(|x| x.unwrap()).collect_vec();
assert_that!(lines).contains("--hello-there".to_string());
}

#[apply(shell_to_use)]
fn test_file_completion_edgecases(shell: &str) -> std::io::Result<()> {
assert_file_completion(
shell,
"myfile with spaces.txt",
"'myfile with spaces.txt'",
"my",
)?;
assert_file_completion(
shell,
"myfilewith'quote.txt",
"'myfilewith''quote.txt'",
"my",
)?;
assert_file_completion(
shell,
"myfile with ' quote spaces.txt",
"'myfile with '' quote spaces.txt'",
"my",
)?;

// seems broken in nushell?
// assert_file_completion(shell, "myfilewith`backtick.txt", "'myfilewith`backtick.txt'", "my")?;

Ok(())
}

fn assert_file_completion(
shell: &str,
filename: &str,
expected: &str,
completion: &str,
) -> std::io::Result<()> {
let testenv = TestEnv::new(shell);
std::fs::write(testenv.temp_dir.path().join(filename), "AAA")?;
let res = testenv
.run_with_profile(&format!("Invoke-TabComplete 'git add {completion}'"))
.unwrap();
let lines: Vec<String> = res.stdout.lines().map(|x| x.unwrap()).collect_vec();
assert_that!(lines).is_equal_to(vec![expected.to_string()]);
Ok(())
}

0 comments on commit ccbdc57

Please sign in to comment.