forked from tools/josh
1
0
Fork 0
This commit is contained in:
Florine W. Dekker 2019-11-10 16:52:58 +01:00
parent 2d077c6599
commit 5f632fb692
Signed by: FWDekker
GPG Key ID: B1B567AF58D6EE0F
4 changed files with 53 additions and 41 deletions

View File

@ -1,6 +1,6 @@
{
"name": "fwdekker.com",
"version": "1.8.7",
"version": "1.8.8",
"description": "The source code of [my personal website](https://fwdekker.com/).",
"author": "Felix W. Dekker",
"repository": {

View File

@ -322,7 +322,7 @@ export class Commands {
return mappings
.map(([source, destination]) => {
try {
this.fileSystem.copy(source, destination, input.hasAnyOption("r", "R", "recursive"));
this.fileSystem.copy(source, destination, input.hasAnyOption("-r", "-R", "--recursive"));
return 0;
} catch (error) {
streams.err.writeLine(`cp: ${error.message}`);
@ -340,7 +340,7 @@ export class Commands {
private echo(input: InputArgs, streams: StreamSet): number {
const message = input.args.join(" ").replace("hunter2", "*******");
if (input.hasAnyOption("n", "newline"))
if (input.hasAnyOption("-n", "--newline"))
streams.out.write(message);
else
streams.out.writeLine(message);
@ -436,7 +436,7 @@ export class Commands {
.sortAlphabetically(it => it, true)
.forEach(name => {
const node = nodes[name];
if (!input.hasAnyOption("a", "A", "all") && name.startsWith("."))
if (!input.hasAnyOption("-a", "-A", "--all") && name.startsWith("."))
return;
if (node instanceof Directory)
@ -474,7 +474,7 @@ export class Commands {
.map(arg => Path.interpret(this.environment.get("cwd"), arg))
.map(path => {
try {
this.fileSystem.add(path, new Directory(), input.hasAnyOption("p", "parents"));
this.fileSystem.add(path, new Directory(), input.hasAnyOption("-p", "--parents"));
return 0;
} catch (error) {
streams.err.writeLine(`mkdir: ${error.message}`);
@ -508,7 +508,7 @@ export class Commands {
private open(input: InputArgs, streams: StreamSet): number {
const path = Path.interpret(this.environment.get("cwd"), input.args[0]);
const target = input.hasAnyOption("b", "blank") ? "_blank" : "_self";
const target = input.hasAnyOption("-b", "--blank") ? "_blank" : "_self";
const node = this.fileSystem.get(path);
if (node === undefined) {
@ -559,18 +559,18 @@ export class Commands {
try {
const target = this.fileSystem.get(path);
if (target === undefined) {
if (input.hasAnyOption("f", "force"))
if (input.hasAnyOption("-f", "--force"))
return 0;
streams.err.writeLine(`rm: The file '${path}' does not exist.`);
return -1;
}
if (target instanceof Directory) {
if (!input.hasAnyOption("r", "R", "recursive")) {
if (!input.hasAnyOption("-r", "-R", "--recursive")) {
streams.err.writeLine(`rm: '${path}' is a directory.`);
return -1;
}
if (path.toString() === "/" && !input.hasAnyOption("no-preserve-root")) {
if (path.toString() === "/" && !input.hasAnyOption("--no-preserve-root")) {
streams.err.writeLine("rm: Cannot remove root directory.");
return -1;
}

View File

@ -105,20 +105,20 @@ export class InputParser {
if (key === "")
break;
options[key] = value;
options[`--${key}`] = value;
} else {
const keys = argsParts[0].substr(1);
if (keys === "")
break;
if (keys.length === 1) {
options[keys] = value;
options[`-${keys}`] = value;
} else {
if (value !== null)
throw new IllegalArgumentError("Cannot assign value to multiple short options.");
for (const key of keys)
options[key] = value;
options[`-${key}`] = value;
}
}
}

View File

@ -36,31 +36,31 @@ describe("input parser", () => {
describe("options", () => {
describe("short options", () => {
it("assigns null to a parameter-less short option", () => {
expect(parser.parse("command -o").options).to.have.own.property("o", null);
expect(parser.parse("command -o").options).to.have.own.property("-o", null);
});
it("assigns null to each parameter-less short option", () => {
const options = parser.parse("command -o -p").options;
expect(options).to.have.own.property("o", null);
expect(options).to.have.own.property("p", null);
expect(options).to.have.own.property("-o", null);
expect(options).to.have.own.property("-p", null);
});
it("assigns null to each parameter-less short option in a group", () => {
const options = parser.parse("command -op").options;
expect(options).to.have.own.property("o", null);
expect(options).to.have.own.property("p", null);
expect(options).to.have.own.property("-o", null);
expect(options).to.have.own.property("-p", null);
});
it("assigns the given value to a short option", () => {
expect(parser.parse("command -o=value").options).to.have.own.property("o", "value");
expect(parser.parse("command -o=value").options).to.have.own.property("-o", "value");
});
it("assigns the given value containing a space to a short option", () => {
expect(parser.parse(`command -o="val ue"`).options).to.have.own.property("o", "val ue");
expect(parser.parse(`command -o="val ue"`).options).to.have.own.property("-o", "val ue");
});
it("assigns an empty string to a short option", () => {
expect(parser.parse("command -o= -p").options).to.have.own.property("o", "");
expect(parser.parse("command -o= -p").options).to.have.own.property("-o", "");
});
it("does not assign a value to grouped short options", () => {
@ -68,77 +68,89 @@ describe("input parser", () => {
});
it("stops parsing options if a short option name contains a space", () => {
expect(parser.parse(`command "-opt ion" -p`).options).to.not.have.own.property("p");
expect(parser.parse(`command "-opt ion" -p`).options).to.not.have.own.property("-p");
});
it("stops parsing options if a short option-like negative number is given", () => {
expect(parser.parse(`command -2 -p`).options).to.not.have.own.property("p");
expect(parser.parse(`command -2 -p`).options).to.not.have.own.property("-p");
});
it("continues parsing options if the value of a short option is a number", () => {
expect(parser.parse(`command -a=2 -p`).options).to.have.own.property("a", "2");
expect(parser.parse(`command -a=2 -p`).options).to.have.own.property("-a", "2");
});
it("considers an assignment to an empty short option to be an argument", () => {
expect(parser.parse("command -=value -p").options).to.not.have.own.property("p");
expect(parser.parse("command -=value -p").options).to.not.have.own.property("-p");
});
it("considers a short option surrounded by quotes as any other option", () => {
const options = parser.parse(`command -o "-p"`).options;
expect(options).to.have.own.property("o", null);
expect(options).to.have.own.property("p", null);
expect(options).to.have.own.property("-o", null);
expect(options).to.have.own.property("-p", null);
});
});
describe("long options", () => {
it("assigns null to a parameter-less long option", () => {
expect(parser.parse("command --option").options).to.have.own.property("option", null);
expect(parser.parse("command --option").options).to.have.own.property("--option", null);
});
it("assigns null to each parameter-less long option", () => {
const options = parser.parse("command --optionA --optionB").options;
expect(options).to.have.own.property("optionA", null);
expect(options).to.have.own.property("optionB", null);
expect(options).to.have.own.property("--optionA", null);
expect(options).to.have.own.property("--optionB", null);
});
it("assigns the given value to a long option", () => {
expect(parser.parse("command --option=value").options).to.have.own.property("option", "value");
expect(parser.parse("command --option=value").options).to.have.own.property("--option", "value");
});
it("assigns the given value containing a space to a long option", () => {
expect(parser.parse(`command --option="val ue"`).options).to.have.own.property("option", "val ue");
expect(parser.parse(`command --option="val ue"`).options).to.have.own.property("--option", "val ue");
});
it("stops parsing options if a long option name contains a space", () => {
expect(parser.parse(`command "--opt ion" -p`).options).to.not.have.own.property("p");
expect(parser.parse(`command "--opt ion" -p`).options).to.not.have.own.property("-p");
});
it("stops parsing options if a long option-like negative number is given", () => {
expect(parser.parse(`command --2 -p`).options).to.not.have.own.property("p");
expect(parser.parse(`command --2 -p`).options).to.not.have.own.property("-p");
});
it("continues parsing options if the value of a long option is a number", () => {
expect(parser.parse(`command --a=2 -p`).options).to.have.own.property("a", "2");
expect(parser.parse(`command --a=2 -p`).options).to.have.own.property("--a", "2");
});
it("considers an assignment to an empty long option to be an argument", () => {
const options = parser.parse("command --=value -p").options;
expect(options).to.not.have.own.property("p");
expect(options).to.not.have.own.property("-p");
});
it("considers a long option surrounded by quotes as any other option", () => {
const options = parser.parse(`command -o "--p"`).options;
expect(options).to.have.own.property("o", null);
expect(options).to.have.own.property("p", null);
expect(options).to.have.own.property("-o", null);
expect(options).to.have.own.property("--p", null);
});
});
it("distinguishes between short and long options", () => {
const options = parser.parse("command -s --long").options;
expect(options).to.not.have.own.property("s", null);
expect(options).to.have.own.property("-s", null);
expect(options).to.not.have.own.property("--s", null);
expect(options).to.not.have.own.property("long", null);
expect(options).to.not.have.own.property("-long", null);
expect(options).to.have.own.property("--long", null);
});
it("stops parsing options after the first non-option", () => {
expect(parser.parse("command -o=value arg -p").options).to.not.have.own.property("p");
expect(parser.parse("command -o=value arg -p").options).to.not.have.own.property("-p");
});
it("stops parsing options after --", () => {
expect(parser.parse("command -- -p").options).to.not.have.own.property("p");
expect(parser.parse("command -- -p").options).to.not.have.own.property("-p");
});
});
@ -201,7 +213,7 @@ describe("input parser", () => {
it("should find the writing redirect target if placed at the end", () => {
const inputArgs = parser.parse("command -o=p arg1 > file");
expect(inputArgs.options).to.deep.equal({o: "p"});
expect(inputArgs.options).to.deep.equal({"-o": "p"});
expect(inputArgs.args).to.have.members(["arg1"]);
expect(inputArgs.redirectTarget).to.have.members(["write", "file"]);
});
@ -215,7 +227,7 @@ describe("input parser", () => {
it("should find the redirect target if placed in between options", () => {
const inputArgs = parser.parse("command -o=p >> file --ba=ba arg2");
expect(inputArgs.redirectTarget).to.have.members(["append", "file"]);
expect(inputArgs.options).to.deep.equal({o: "p", ba: "ba"});
expect(inputArgs.options).to.deep.equal({"-o": "p", "--ba": "ba"});
});
it("should ignore the redirect target if inside quotation marks", () => {