Handle Multiple completions stage at build your own shell challenge

I’m stuck on Stage #Multiple completions #wh6.

I’ve tried to solve it by out the bell characters where there is no match or when there are multiple matches and I return the hits from the commands to let the user see the possible choices.

Here are my logs:

[compile] Moved ./.codecrafters/run.sh → ./your_program.sh
[compile] Compilation successful.
[tester::#WH6] Running tests for Stage #WH6 (Command Completion - Multiple completions)
[tester::#WH6] [setup] export PATH=/tmp/ant:$PATH
[tester::#WH6] [setup] export PATH=/tmp/owl:$PATH
[tester::#WH6] [setup] export PATH=/tmp/dog:$PATH
[tester::#WH6] [setup] Available executables:
[tester::#WH6] [setup] - xyz_owl
[tester::#WH6] [setup] - xyz_pig
[tester::#WH6] [setup] - xyz_dog
[tester::#WH6] Running ./your_program.sh
[tester::#WH6] ✓ Received prompt ($ )
[tester::#WH6] Typed "xyz_"
[your-program] $ xyz_
[tester::#WH6] ✓ Prompt line matches "$ xyz_"
[tester::#WH6] Pressed "<TAB>" (expecting bell to ring)
[tester::#WH6] ✓ Received bell
[tester::#WH6] Pressed "<TAB>" (expecting "xyz_dog  xyz_owl  xyz_pig" as completion options)
[your-program] xyz_dog   xyz_pig   xyz_owl
[tester::#WH6] ^ Line does not match expected value.
[tester::#WH6] Expected: "xyz_dog  xyz_owl  xyz_pig"
[tester::#WH6] Received: "xyz_dog   xyz_pig   xyz_owl"
[your-program] 
[your-program] $ xyz_
[tester::#WH6] Test failed

And here’s a snippet of my code:
this is the code of my `main.js` file and for the rest of the code I will put the link of github repo

const readline = require("readline");
const { execFileSync } = require('node:child_process');

const { isExist } = require('./utils/isExit');
const { isBuiltInCommand } = require("./utils/isBuiltInCommand");
const { isExecutable } = require("./utils/isExecutable");
const { getExecutableFiles } = require("./utils/getExecutableFiles");
const { handleBuiltInCommands } = require("./utils/handleBuiltInCommands");
const { handleQuotes } = require("./utils/handleQuotes");
const { isExternalCommand } = require("./utils/isExternalCommand");
const { handleExternalCommands } = require("./utils/handleExternalCommands");

const rl = readline.createInterface({
	input: process.stdin,
	output: process.stdout,
	prompt: "$ ",
	completer: (line) => {
		const executables = getExecutableFiles();
		const commands = ['echo ', 'exit ', ...executables.map(cmd => cmd + ' ')];
		const hits = commands.filter((cmd) => cmd.startsWith(line));
		if (hits.length === 0 || hits.length > 1) {
			process.stdout.write('\u0007');
		}
		return [hits.length ? hits : commands, line];
	}
});

rl.prompt();
rl.on('line', (input) => {
	if (input.trim()) {
		let [command, ...args] = handleQuotes(input);

		if (isBuiltInCommand(command)) {
			handleBuiltInCommands(command, args);
		} else if (isExternalCommand(command)) {
			handleExternalCommands(command, args);
		} else {
			let { state, data } = isExecutable(command);
			if (state) {
				let output = execFileSync(command, args);
				process.stdout.write(output.toString());
			} else {
				console.log(`${input}: command not found`);
			}
		}
	}
	rl.prompt();
})

Hey @MostafaEdrees11, there might be several issues at play here, but the main one is that the completion candidates should be sorted before being displayed.

[tester::#WH6] Expected: “xyz_dog xyz_owl xyz_pig”
[tester::#WH6] Received: “xyz_dog xyz_pig xyz_owl”

Let me know if you’d like further clarification.

I sort the hits before I return them but there is still a problem because completer function insert a new line after printing the hits and before the prompt

[tester::#WH6] Typed “xyz_”

[your-program] $ xyz_

[tester::#WH6] ✓ Prompt line matches “$ xyz_”

[tester::#WH6] Pressed “” (expecting bell to ring)

[tester::#WH6] ✓ Received bell

[tester::#WH6] Pressed “” (expecting “xyz_ant  xyz_dog  xyz_rat” as completion options)

[your-program] xyz_ant   xyz_dog   xyz_rat

[tester::#WH6] 3 matching completion options found

[your-program]

[tester::#WH6] ^ Line does not match expected value.

[tester::#WH6] Expected: “$ xyz_”

[tester::#WH6] Received: “” (empty line)

[your-program] $ xyz_

[tester::#WH6] Test failed

@MostafaEdrees11 That looks like a quirk of node’s readline library. A possible workaround is to suppress the library’s default completion output for multiple candidates and print the completion candidates yourself instead.