Skip to content

Commit

Permalink
Add description() and action() methods for commands
Browse files Browse the repository at this point in the history
  • Loading branch information
siokas committed Mar 23, 2020
1 parent 2c8d646 commit 052a7e8
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 85 deletions.
12 changes: 6 additions & 6 deletions AppDetailAccessors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,27 @@ export default class AppDetailAccessors {
}
}

get name(): string {
get app_name(): string {
return this._app_name;
}

set name(name: string) {
set app_name(name: string) {
this._app_name = name;
}

get description(): string {
get app_description(): string {
return this._app_description;
}

set description(description: string) {
set app_description(description: string) {
this._app_description = description;
}

get version(): string {
get app_version(): string {
return this._app_version;
}

set version(version: string) {
set app_version(version: string) {
this._app_version = version;
}
}
60 changes: 40 additions & 20 deletions Command.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
import { stripDashes, containsBrackets } from "./helpers.ts";

export default class Command {
private _value: string;
private _description: string;
private _is_required: boolean;
private _letter_command: string | undefined;
private _word_command: string | undefined;
private _type: "command" | "option";
private options: {
value: string;
description: string;
is_required: boolean;
type: "command" | "option";
action: Function;
};

require_command_value: boolean = false;

constructor(
value: string,
description: string,
is_required?: boolean,
type?: "command" | "option"
options: {
value: string;
description?: string;
is_required?: boolean;
type?: "command" | "option";
action?: Function;
}
) {
this._value = value;
this._description = description;
this._is_required = is_required || false;
this._type = type || "option";
this.options = Object.assign({
description: "",
is_required: false,
type: "option",
action: () => {}
}, options);

if (!this.options.value) {
throw new ReferenceError("You have to specify the command");
}

if (this._type == "option") {
if (this.options.type == "option") {
this.generateOption();
} else {
this.generateCommand();
}
}

private generateCommand() {
let splitedValue = this._value.split(" ");
let splitedValue = this.options.value.split(" ");

switch (splitedValue.length) {
case 1:
Expand All @@ -46,7 +58,7 @@ export default class Command {
}

private generateOption() {
let splitedValue = this._value.split(" ");
let splitedValue = this.options.value.split(" ");

switch (splitedValue.length) {
case 1:
Expand Down Expand Up @@ -75,19 +87,19 @@ export default class Command {
}

get value(): string {
return this._value;
return this.options.value;
}

set value(value: string) {
this._value = value;
this.options.value = value;
}

get description(): string {
return this._description;
return this.options.description;
}

set description(description: string) {
this._description = description;
this.options.description = description;
}

get letter_command(): string | undefined {
Expand All @@ -106,7 +118,15 @@ export default class Command {
this._word_command = word_command;
}

get action(): Function {
return this.options.action;
}

set action(callback: Function) {
this.options.action = callback;
}

get type(): "command" | "option" {
return this._type;
return this.options.type;
}
}
70 changes: 55 additions & 15 deletions Denomander.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,19 @@ export default class Denomander extends AppDetailAccessors {
private available_commands: Array<Command> = [];
private available_options: Array<Command> = [];
private available_default_options: Array<Command> = [];
private available_actions: Array<Command> = [];
private available_on_commands: Array<OnCommand> = [];
private temp_on_commands: Array<TempOnCommand> = [];
[key: string]: any

private version_command: Command = new Command(
"-V --version",
"Print the current version"
);
private help_command: Command = new Command(
"-h --help",
"Print command line options (currently set)"
);
private version_command: Command = new Command({
value: "-V --version",
description: "Print the current version"
});
private help_command: Command = new Command({
value: "-h --help",
description: "Print command line options (currently set)"
});

private isHelpConfigured: Boolean = false;
private isVersionConfigured: Boolean = false;
Expand Down Expand Up @@ -62,36 +63,63 @@ export default class Denomander extends AppDetailAccessors {
}

option(value: string, description: string): Denomander {
this.commands.push(new Command(value, description));
this.available_options.push(new Command(value, description));
this.commands.push(new Command({ value, description }));
this.available_options.push(new Command({ value, description }));

return this;
}

requiredOption(value: string, description: string): Denomander {
let command = new Command(value, description, true);
let command: Command | undefined = new Command(
{ value, description, is_required: true }
);
this.commands.push(command);
this.available_requiredOptions.push(command);

return this;
}

command(value: string, description: string): Denomander {
let new_command = new Command(value, description, false, "command");
command(value: string, description?: string): Denomander {
let new_command: Command | undefined = new Command({
value,
description,
type: "command"
});
this.commands.push(new_command);
this.available_commands.push(new_command);

return this;
}

description(description: string): Denomander {
let command: Command | undefined = this.commands.slice(-1)[0];

if (command) {
command.description = description;
}

return this;
}

action(callback: Function): Denomander {
let command: Command | undefined = this.commands.slice(-1)[0];

if (command) {
command.action = callback;
this.available_actions.push(command);
}

return this;
}

on(arg: string, callback: Function): Denomander {
this.temp_on_commands.push({ arg, callback });

return this;
}

setHelp(command: string, description: string): Denomander {
this.help_command = new Command(command, description);
this.help_command = new Command({ value: command, description });

let new_available_default_options = removeCommandFromArray(
this.commands,
Expand All @@ -111,7 +139,7 @@ export default class Denomander extends AppDetailAccessors {
description: string
): Denomander {
this.version = version;
this.version_command = new Command(command, description);
this.version_command = new Command({ value: command, description });

let new_available_default_options = removeCommandFromArray(
this.commands,
Expand Down Expand Up @@ -297,6 +325,18 @@ export default class Denomander extends AppDetailAccessors {
console.log("v" + this.version);
}

this.available_actions.forEach((command: Command) => {
if (isCommandInArgs(command, this._args)) {
if (command.action.length == 0) {
command.action();
} else if (command.action.length == 1) {
command.action(this[command.word_command!]);
} else {
throw new Error("Too much parameters");
}
}
});

return this;
}

Expand Down
61 changes: 49 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,61 @@ let program = new Denomander(
);
```

There are three option types: __commands__, __options__ and __required options__. To set an option just call the corresponding method passing __a) the sort and the long flag__ seperated by space and __b) the description__
There are three option types: __commands__, __options__ and __required options__.

### Options
To set an option just call the **option()** method passing __a) the sort and the long flag__ seperated by space and __b) the description__. The value can be accessed as properties.

```javascript
program
.command("new [name]", "Generate a new file")
.option("-a --address", "Define the address")
.option("-p --port", "Define the port")
.requiredOption("-s --server", "Server Name")
.parse(Deno.args);

if(program.address){
server.name = program.server;
let port = program.port || "8000";
console.log(`Server run on ${program.address}:${port}`);
}
```

if(program.port){
s = serve({ port: program.port });
}
### Required Options
The implementation of required option is exactly same as the optional option but you have to call the **requiredOption()** method instead.

if(program.new){
console.log("Creating the file " + program.new);
}
```javascript
program
.option("-a --address", "Define the address")
.requiredOption("-p --port", "Define the port")
.parse(Deno.args);

// The port is required so it must have a value
let address = program.address || "localhost";
console.log(`Server run on ${address}:${program.port}`);
```

### Commands
There are two ways to implement the command options. The first is to use an action handler by calling the **action()** method immediately after the command definition passing the callback function and the second is with custom one-line implementation.

#### Action Handler
```javascript
program
.command("clone [foldername]")
.description("clone a repo")
.action((foldername) => {
console.log("The repo is cloned into: " + foldername);
});

program.parse(Deno.args);
```

#### Custom Implementation
```javascript
program.command("serve", "Start the server");

if(program.serve){
console.log("The server has started...");
}

program.parse(Deno.args);
```

### Option to change default commands (help, version)
Expand Down Expand Up @@ -95,7 +129,8 @@ program.parse(args);
- [X] program.on() method
- [ ] Custom option processing
- [X] Option to change default commands (help, version)
- [ ] description(), action() methods
- [X] description(), action() methods
- [ ] Multiple short flags (-abc)

## Used

Expand All @@ -108,8 +143,10 @@ program.parse(args);
* 0.1.0
* Initial Commit
* Change Command of Default Options [help, version]
* 0.2.0
* Custom help and version (program.on() method)
* 0.2.0
* Add description() and action() methods for commands


## Meta

Expand Down
20 changes: 10 additions & 10 deletions appDetailAccessors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import { assertEquals, test } from "./test_deps.ts";
import AppDetailAccessors from "./AppDetailAccessors.ts";

test(function app_detail_accessors() {
let app = new AppDetailAccessors();
assertEquals(app.name, "My App"); // Default app name if not provided in constructor
assertEquals(app.description, "My Description"); // Default description if not provided in constructor
assertEquals(app.version, "0.0.1"); // Default version if not provided in constructor
let program = new AppDetailAccessors();
assertEquals(program.app_name, "My App"); // Default app name if not provided in constructor
assertEquals(program.app_description, "My Description"); // Default description if not provided in constructor
assertEquals(program.app_version, "0.0.1"); // Default version if not provided in constructor

app.name = "New Name";
assertEquals(app.name, "New Name");
program.app_name = "New Name";
assertEquals(program.app_name, "New Name");

app.description = "New Description";
assertEquals(app.description, "New Description");
program.app_description = "New Description";
assertEquals(program.app_description, "New Description");

app.version = "2.5.0";
assertEquals(app.version, "2.5.0");
program.app_version = "2.5.0";
assertEquals(program.app_version, "2.5.0");
});
Loading

0 comments on commit 052a7e8

Please sign in to comment.