I’m stuck on Stage #EP2.
I’ve tried testing locally with this registered specification script:
#!/usr/bin/env python3
print("add")
print("commit")
print("branch")
print("cat-file")
print("remote")
print("rebase")
print("reset")
print("stash")
print("status")
# this file is in /tmp/sc
and ran this command complete -C /tmp/sc git to store the script path in a Hashmap.
Things seem to work as I see my output:
Compiling codecrafters-shell v0.1.0 (/home/skhuong/rnd/simsh)
Finished `release` profile [optimized] target(s) in 1.14s
$ complete -C /tmp/sc git
$ complete -p git
complete -C '/tmp/sc' git
$ git re
rebase remote reset
$ git sta
stash status
$ git sta
However, it couldn’t pass the test and what’s weird to me is the error message:
[tester::#EP2] Expected argv[3] to be "git", found ""
Based on previous stage, argv[3] supposed to be the prefix—not the command—ain’t it?
Here are my logs:
[compile] Compiling codecrafters-shell v0.1.0 (/app)
[compile] Finished `release` profile [optimized] target(s) in 2.31s
[compile] Moved ./.codecrafters/run.sh → ./your_program.sh
[compile] Compilation successful.
Debug = true
[tester::#EP2] Running tests for Stage #EP2 (Programmable Completion - Multiple completer candidates)
[tester::#EP2] Running ./your_program.sh
[your-program] $ complete -C /tmp/dog/multiCandidateEnvCompleter git
[tester::#EP2] ✓ Registered command-based completion
[tester::#EP2] Typed "git sta"
[your-program] $ git sta
[tester::#EP2] ✓ Prompt line matches "$ git sta"
[tester::#EP2] Pressed "<TAB>" (expecting bell to ring)
[tester::#EP2] ✓ Received bell
[tester::#EP2] Pressed "<TAB>" (expecting "stash status" as completion options)
[tester::#EP2] Didn't find expected line.
[tester::#EP2] Expected: "stash status"
[tester::#EP2] Received: "" (no line received)
[tester::#EP2] Errors from the completer script:
[tester::#EP2] ✓ Arguments are of length 4 (including program name)
[tester::#EP2] ✓ Expected value of argv[1] found
[tester::#EP2] ✓ Expected value of argv[2] found
[tester::#EP2] Expected argv[3] to be "git", found ""
[tester::#EP2] ✓ Expected value of environment variable COMP_LINE found
[tester::#EP2] ✓ Expected value of environment variable COMP_POINT found
[tester::#EP2] Test failed
And here’s a snippet of my code:
use rustyline::completion::Pair;
use std::collections::HashMap;
use std::io::{BufRead, BufReader};
use std::process::{Command, Stdio};
use crate::parser;
pub fn get_completions_from_registered_spec(
line: &str,
pos: usize,
path: &String,
) -> Option<(usize, Vec<Pair>)> {
let args = parser::command_input_parser(line).0;
let command = args[0].clone();
let mut subcommand = String::new();
let mut prefix = String::new();
if args.len() > 3 {
if let Some(arg) = args.last() {
prefix = arg.clone();
subcommand = args[args.len() - 2].clone();
}
} else if args.len() == 3 {
subcommand = args[1].clone();
prefix = args[2].clone();
} else if args.len() == 2 {
prefix = args[1].clone();
}
let is_line_ends_with_space = line.ends_with(" ");
let mut vars = HashMap::<String, String>::new();
vars.insert("COMP_LINE".to_string(), line.to_string());
vars.insert("COMP_POINT".to_string(), pos.to_string());
let mut child = Command::new(path)
.envs(vars)
.args(vec![command, prefix.clone(), subcommand])
.stdout(Stdio::piped())
.spawn()
.expect("Failed to execute completion script");
let mut completions: Vec<String> = vec![];
if let Some(stdout) = child.stdout.take() {
let reader = BufReader::new(stdout);
for line_from_reader in reader.lines() {
if let Ok(completion) = line_from_reader
&& completion.starts_with(prefix.as_str())
{
completions.push(completion);
}
}
}
let pos = pos
- if is_line_ends_with_space {
0
} else {
prefix.len()
};
if completions.len() > 0 {
return Some((
pos,
completions
.iter()
.map(|completion| Pair {
display: completion.clone(),
replacement: format!("{} ", completion.clone()),
})
.collect(),
));
}
None
}
Could anyone please hlep?
Here is my repo if you need to check other file: simsh/src/completion/get_completions_from_registered_spec.rs at main · skuong/simsh · GitHub
Thanks in advance
