Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mophy committed Sep 28, 2019
0 parents commit 0a95c33
Show file tree
Hide file tree
Showing 20 changed files with 5,392 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"env": {
"test": {
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"targets": {
"node": "current"
}
}
]
],
"plugins": [
[
"@babel/plugin-transform-modules-commonjs",
{
"spec": true
}
]
]
}
}
}
38 changes: 38 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"extends": [
"airbnb-base",
"plugin:jest/recommended"
],
"plugins": [
"import",
"jest"
],
"env": {
"node": true,
"jest/globals": true
},
"globals": {
"using": true
},
"rules": {
"indent": ["error", 4, { "SwitchCase": 1 }],
"padded-blocks": ["error", { "classes": "always" }],
"no-underscore-dangle": 0,
"consistent-return": ["error", { "treatUndefinedAsUnspecified": true }],
"no-void": 0,
"class-methods-use-this": 0,
"one-var": 0,
"one-var-declaration-per-line": 0,
"max-len": ["error", { "code": 120 }],
"no-use-before-define": ["error", { "functions": false }],
"object-curly-newline": ["error", { "multiline": true }],
"prefer-destructuring": 0,
"no-param-reassign": 0,
"curly": ["error", "multi"],
"nonblock-statement-body-position": ["error", "any"],
"prefer-const": 0,
"no-else-return": 0,
"import/prefer-default-export": 0,
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }]
}
}
66 changes: 66 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

# ide
.idea/
47 changes: 47 additions & 0 deletions main/argument-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Arguments } from './arguments';
import { Argument } from './argument';
import { Tokenizer } from './tokenizer';
import { Schemas } from './schemas';

export class ArgumentParser {

constructor(schemas) {
this.schemas = new Schemas(schemas);
}

parse(commandLine) {
this.createDefaultArguments();
this.tokenizeCommandLine(commandLine);
this.parseTokens();
return this.args;
}

createDefaultArguments() {
this.args = new Arguments(this.schemas.map(this.createArgument));
}

createArgument(schema) {
return new Argument(schema.flag, schema.type.default());
}

tokenizeCommandLine(commandLine) {
this.tokens = new Tokenizer(commandLine);
}

parseTokens() {
while (this.tokens.hasMore()) this.parseToken();
}

parseToken() {
let flag = this.tokens.nextFlag();
let schema = this.schemas.find(flag);
let value = this.nextValue(schema.type, flag);
this.args.set(flag, value);
}

nextValue(type, flag) {
let value = type.needValue() ? this.tokens.nextValue(flag) : undefined;
return type.convert(value, flag);
}

}
8 changes: 8 additions & 0 deletions main/argument.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class Argument {

constructor(flag, value) {
this.flag = flag;
this.value = value;
}

}
19 changes: 19 additions & 0 deletions main/arguments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export class Arguments {

constructor(items) {
this.items = items;
}

find(flag) {
return this.items.find(item => item.flag === flag);
}

get(flag) {
return this.find(flag).value;
}

set(flag, value) {
this.find(flag).value = value;
}

}
15 changes: 15 additions & 0 deletions main/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function unknownFlagError(flag) {
throw new Error(`Unknown flag: -${flag}`);
}

export function invalidIntegerError(flag, value) {
throw new Error(`Invalid integer of flag -${flag}: ${value}`);
}

export function unexpectedValueError(token) {
throw new Error(`Unexpected value: ${token}`);
}

export function valueNotSpecifiedError(flag) {
throw new Error(`Value not specified of flag -${flag}`);
}
34 changes: 34 additions & 0 deletions main/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { IntegerListArgumentType } from './types/integer-list-argument-type';
import { BooleanArgumentType } from './types/boolean-argument-type';
import { StringArgumentType } from './types/string-argument-type';
import { IntegerArgumentType } from './types/integer-argument-type';
import { StringListArgumentType } from './types/string-list-argument-type';

class Schema {

constructor(flag, type) {
this.flag = flag;
this.type = type;
}

}

export function BooleanSchema(flag) {
return new Schema(flag, BooleanArgumentType);
}

export function StringSchema(flag) {
return new Schema(flag, StringArgumentType);
}

export function IntegerSchema(flag) {
return new Schema(flag, IntegerArgumentType);
}

export function StringListSchema(flag) {
return new Schema(flag, StringListArgumentType);
}

export function IntegerListSchema(flag) {
return new Schema(flag, IntegerListArgumentType);
}
19 changes: 19 additions & 0 deletions main/schemas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { unknownFlagError } from './errors';

export class Schemas {

constructor(items) {
this.items = items;
}

find(flag) {
let found = this.items.find(item => item.flag === flag);
if (!found) unknownFlagError(flag);
return found;
}

map(cb) {
return this.items.map(item => cb(item));
}

}
24 changes: 24 additions & 0 deletions main/tokenizer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { unexpectedValueError, valueNotSpecifiedError } from './errors';

export class Tokenizer {

constructor(commandLine) {
this.tokens = commandLine.split(' ').filter(t => t.length);
}

hasMore() {
return this.tokens.length > 0;
}

nextFlag() {
let token = this.tokens.shift();
if (!token.startsWith('-')) unexpectedValueError(token);
return token.substring(1);
}

nextValue(flag) {
if (!this.tokens.length) valueNotSpecifiedError(flag);
return this.tokens.shift();
}

}
7 changes: 7 additions & 0 deletions main/types/argument-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export class ArgumentType {

static needValue() {
return true;
}

}
17 changes: 17 additions & 0 deletions main/types/boolean-argument-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ArgumentType } from './argument-type';

export class BooleanArgumentType extends ArgumentType {

static default() {
return false;
}

static convert() {
return true;
}

static needValue() {
return false;
}

}
15 changes: 15 additions & 0 deletions main/types/integer-argument-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { invalidIntegerError } from '../errors';
import { ArgumentType } from './argument-type';

export class IntegerArgumentType extends ArgumentType {

static default() {
return 0;
}

static convert(value, flag) {
if (!value.match(/^[-]?\d+$/)) invalidIntegerError(flag, value);
return parseInt(value, 10);
}

}
10 changes: 10 additions & 0 deletions main/types/integer-list-argument-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ListArgumentType } from './list-argument-type';
import { IntegerArgumentType } from './integer-argument-type';

export class IntegerListArgumentType extends ListArgumentType {

static itemClass() {
return IntegerArgumentType;
}

}
19 changes: 19 additions & 0 deletions main/types/list-argument-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ArgumentType } from './argument-type';

export class ListArgumentType extends ArgumentType {

static default() {
return [];
}

static convert(value, flag) {
return value.split(',')
.map(this.convertItem(flag));
}

static convertItem(flag) {
return value => this.itemClass()
.convert(value, flag);
}

}
13 changes: 13 additions & 0 deletions main/types/string-argument-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ArgumentType } from './argument-type';

export class StringArgumentType extends ArgumentType {

static default() {
return '';
}

static convert(value) {
return value;
}

}
Loading

0 comments on commit 0a95c33

Please sign in to comment.