Skip to content

Commit

Permalink
fix: empty strings were ignored (#195)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryooooooga authored Dec 17, 2023
1 parent e0386dd commit c987b89
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 23 deletions.
16 changes: 12 additions & 4 deletions mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1265,8 +1265,11 @@ Deno.test("copy test", async () => {
"cp: target 'non-existent' is not a directory\n",
);

assertEquals(await getStdErr($`cp "" ""`), "cp: missing file operand\n");
assertStringIncludes(await getStdErr($`cp ${file1} ""`), "cp: missing destination file operand after");
assertEquals(await getStdErr($`cp`), "cp: missing file operand\n");
assertStringIncludes(await getStdErr($`cp ${file1}`), "cp: missing destination file operand after");

assertEquals(await getStdErr($`cp`), "cp: missing file operand\n");
assertStringIncludes(await getStdErr($`cp ${file1}`), "cp: missing destination file operand after");

// recursive test
destDir.join("sub_dir").mkdirSync();
Expand Down Expand Up @@ -1331,8 +1334,8 @@ Deno.test("move test", async () => {
"mv: target 'non-existent' is not a directory\n",
);

assertEquals(await getStdErr($`mv "" ""`), "mv: missing operand\n");
assertStringIncludes(await getStdErr($`mv ${file1} ""`), "mv: missing destination file operand after");
assertEquals(await getStdErr($`mv`), "mv: missing operand\n");
assertStringIncludes(await getStdErr($`mv ${file1}`), "mv: missing destination file operand after");
});
});

Expand Down Expand Up @@ -1648,6 +1651,11 @@ Deno.test("ensure KillSignalController readme example works", async () => {
assert(endTime - startTime < 1000);
});

Deno.test("should support empty quoted string", async () => {
const output = await $`echo '' test ''`.text();
assertEquals(output, " test ");
});

function ensurePromiseNotResolved(promise: Promise<unknown>) {
return new Promise<void>((resolve, reject) => {
promise.then(() => reject(new Error("Promise was resolved")));
Expand Down
44 changes: 25 additions & 19 deletions src/shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,10 +838,11 @@ async function evaluateWord(word: Word, context: Context) {
return result.join(" ");
}

async function evaluateWordParts(wordParts: WordPart[], context: Context) {
async function evaluateWordParts(wordParts: WordPart[], context: Context, quoted = false) {
// not implemented mostly, and copying from deno_task_shell
const result: string[] = [];
let currentText = "";
let hasQuoted = false;
for (const stringPart of wordParts) {
let evaluationResult: string | undefined = undefined;
switch (stringPart.kind) {
Expand All @@ -852,8 +853,9 @@ async function evaluateWordParts(wordParts: WordPart[], context: Context) {
evaluationResult = context.getVar(stringPart.value); // value is name
break;
case "quoted": {
const text = (await evaluateWordParts(stringPart.value, context)).join(" ");
const text = (await evaluateWordParts(stringPart.value, context, true)).join("");
currentText += text;
hasQuoted = true;
continue;
}
case "command":
Expand All @@ -862,26 +864,30 @@ async function evaluateWordParts(wordParts: WordPart[], context: Context) {
}

if (evaluationResult != null) {
const parts = evaluationResult.split(" ")
.map((t) => t.trim())
.filter((t) => t.length > 0);
if (parts.length > 0) {
// append the first part to the current text
currentText += parts[0];

// store the current text
result.push(currentText);

// store all the rest of the parts
result.push(...parts.slice(1));

// use the last part as the current text so it maybe
// gets appended to in the future
currentText = result.pop()!;
if (quoted) {
currentText += evaluationResult;
} else {
const parts = evaluationResult.split(" ")
.map((t) => t.trim())
.filter((t) => t.length > 0);
if (parts.length > 0) {
// append the first part to the current text
currentText += parts[0];

// store the current text
result.push(currentText);

// store all the rest of the parts
result.push(...parts.slice(1));

// use the last part as the current text so it maybe
// gets appended to in the future
currentText = result.pop()!;
}
}
}
}
if (currentText.length !== 0) {
if (hasQuoted || currentText.length !== 0) {
result.push(currentText);
}
return result;
Expand Down

0 comments on commit c987b89

Please sign in to comment.