From f7c03f82f1c2b0fc54bce04f56f7231927e91c91 Mon Sep 17 00:00:00 2001 From: Timo Hocker Date: Mon, 15 Jun 2020 11:56:33 +0200 Subject: [PATCH] split interactive source --- lib/Option.ts | 14 ++++ lib/Sources/ArgSource.ts | 2 +- lib/Sources/ConfigSource.ts | 2 +- lib/Sources/EnvSource.ts | 2 +- lib/Sources/Interactive/ArraySubSource.ts | 19 ++++++ lib/Sources/Interactive/BooleanSubSource.ts | 19 ++++++ .../Interactive/InteractiveSubSource.ts | 28 ++++++++ lib/Sources/Interactive/PresetSubSource.ts | 28 ++++++++ lib/Sources/Interactive/StringSubSource.ts | 27 ++++++++ lib/Sources/InteractiveSource.ts | 67 ++++--------------- lib/Sources/OptionSource.ts | 15 ----- 11 files changed, 150 insertions(+), 73 deletions(-) create mode 100644 lib/Sources/Interactive/ArraySubSource.ts create mode 100644 lib/Sources/Interactive/BooleanSubSource.ts create mode 100644 lib/Sources/Interactive/InteractiveSubSource.ts create mode 100644 lib/Sources/Interactive/PresetSubSource.ts create mode 100644 lib/Sources/Interactive/StringSubSource.ts diff --git a/lib/Option.ts b/lib/Option.ts index 5bfa899..37156c9 100644 --- a/lib/Option.ts +++ b/lib/Option.ts @@ -34,6 +34,20 @@ class OptionValue { public constructor (type_validation: TypeValidation) { this.type_validation = type_validation; } + + public async assign_arg ( + opt: Option, + value: unknown + ): Promise { + try { + this.value = await this.type_validation.to_type (value); + this.filled = true; + } + catch (e) { + if (typeof opt.error_callback !== 'undefined') + opt.error_callback (opt.name, value, e); + } + } } export { Option, OptionValue }; diff --git a/lib/Sources/ArgSource.ts b/lib/Sources/ArgSource.ts index 46265e9..03a4cc8 100644 --- a/lib/Sources/ArgSource.ts +++ b/lib/Sources/ArgSource.ts @@ -45,6 +45,6 @@ export class ArgSource extends OptionSource { ) return; - await this.assign_arg (opt, val, argv[opt.name]); + await val.assign_arg (opt, argv[opt.name]); } } diff --git a/lib/Sources/ConfigSource.ts b/lib/Sources/ConfigSource.ts index 62e40fd..59ceac9 100644 --- a/lib/Sources/ConfigSource.ts +++ b/lib/Sources/ConfigSource.ts @@ -64,6 +64,6 @@ export class ConfigSource extends OptionSource { const keys = Object.keys (data); if (keys.includes (opt.name)) - await this.assign_arg (opt, val, data[opt.name]); + await val.assign_arg (opt, data[opt.name]); } } diff --git a/lib/Sources/EnvSource.ts b/lib/Sources/EnvSource.ts index d9fddf3..c705bc4 100644 --- a/lib/Sources/EnvSource.ts +++ b/lib/Sources/EnvSource.ts @@ -25,6 +25,6 @@ export class EnvSource extends OptionSource { return; } - await this.assign_arg (opt, val, process.env[opt.env]); + await val.assign_arg (opt, process.env[opt.env]); } } diff --git a/lib/Sources/Interactive/ArraySubSource.ts b/lib/Sources/Interactive/ArraySubSource.ts new file mode 100644 index 0000000..fc798cb --- /dev/null +++ b/lib/Sources/Interactive/ArraySubSource.ts @@ -0,0 +1,19 @@ +import { List } from 'enquirer'; +import { InteractiveSubSource } from './InteractiveSubSource'; + +export class ArraySubSource extends InteractiveSubSource { + protected condition ():boolean { + return this.val.type_validation.option_type === 'array'; + } + + protected async run ():Promise { + await this.val.assign_arg ( + this.opt, + await new List ({ + message: this.get_message (), + default: this.opt.default + }) + .run () + ); + } +} diff --git a/lib/Sources/Interactive/BooleanSubSource.ts b/lib/Sources/Interactive/BooleanSubSource.ts new file mode 100644 index 0000000..fc92c0f --- /dev/null +++ b/lib/Sources/Interactive/BooleanSubSource.ts @@ -0,0 +1,19 @@ +import { Confirm } from 'enquirer'; +import { InteractiveSubSource } from './InteractiveSubSource'; + +export class BooleanSubSource extends InteractiveSubSource { + protected condition ():boolean { + return this.val.type_validation.option_type === 'boolean'; + } + + protected async run ():Promise { + await this.val.assign_arg ( + this.opt, + await new Confirm ({ + message: this.get_message (), + default: this.opt.default + }) + .run () + ); + } +} diff --git a/lib/Sources/Interactive/InteractiveSubSource.ts b/lib/Sources/Interactive/InteractiveSubSource.ts new file mode 100644 index 0000000..02c9830 --- /dev/null +++ b/lib/Sources/Interactive/InteractiveSubSource.ts @@ -0,0 +1,28 @@ +import { OptionValue, Option } from '../../Option'; + +export abstract class InteractiveSubSource { + protected val: OptionValue; + protected opt: Option; + + protected abstract condition():boolean; + protected abstract async run():Promise; + + public constructor ( + val:OptionValue, + opt:Option + ) { + this.val = val; + this.opt = opt; + } + + public async parse ():Promise { + if (this.condition ()) + await this.run (); + } + + protected get_message (): string { + return typeof this.opt.message === 'undefined' + ? `input ${this.opt.name}` + : this.opt.message; + } +} diff --git a/lib/Sources/Interactive/PresetSubSource.ts b/lib/Sources/Interactive/PresetSubSource.ts new file mode 100644 index 0000000..18cc052 --- /dev/null +++ b/lib/Sources/Interactive/PresetSubSource.ts @@ -0,0 +1,28 @@ +import { AutoComplete } from 'enquirer'; +import { StringOptionConfig } from '../../SubConfigs'; +import { InteractiveSubSource } from './InteractiveSubSource'; + +export class PresetSubSource extends InteractiveSubSource { + protected condition ():boolean { + return [ + 'string', + 'file', + 'folder', + 'path' + ].includes (this.val.type_validation.option_type) + && typeof (this.opt as StringOptionConfig).preset !== 'undefined'; + } + + protected async run ():Promise { + await this.val.assign_arg ( + this.opt, + await new AutoComplete ({ + message: this.get_message (), + default: this.opt.default, + choices: (this.opt as StringOptionConfig).preset, + limit: 10 + }) + .run () + ); + } +} diff --git a/lib/Sources/Interactive/StringSubSource.ts b/lib/Sources/Interactive/StringSubSource.ts new file mode 100644 index 0000000..cf16f66 --- /dev/null +++ b/lib/Sources/Interactive/StringSubSource.ts @@ -0,0 +1,27 @@ +import { Input } from 'enquirer'; +import { StringOptionConfig } from '../../SubConfigs'; +import { InteractiveSubSource } from './InteractiveSubSource'; + +export class StringSubSource extends InteractiveSubSource { + protected condition ():boolean { + return [ + 'string', + 'file', + 'folder', + 'path', + 'number' + ].includes (this.val.type_validation.option_type) + && typeof (this.opt as StringOptionConfig).preset === 'undefined'; + } + + protected async run ():Promise { + await this.val.assign_arg ( + this.opt, + await new Input ({ + message: this.get_message (), + default: this.opt.default + }) + .run () + ); + } +} diff --git a/lib/Sources/InteractiveSource.ts b/lib/Sources/InteractiveSource.ts index fe090d3..cb16756 100644 --- a/lib/Sources/InteractiveSource.ts +++ b/lib/Sources/InteractiveSource.ts @@ -7,11 +7,13 @@ /* eslint-disable no-console */ /* eslint-disable no-process-exit */ -import { Confirm, Input, List, AutoComplete } from 'enquirer'; import { ErrorCallback } from '../ErrorCallback'; import { Option, OptionValue } from '../Option'; -import { StringOptionConfig } from '../SubConfigs'; import { OptionSource } from './OptionSource'; +import { ArraySubSource } from './Interactive/ArraySubSource'; +import { BooleanSubSource } from './Interactive/BooleanSubSource'; +import { PresetSubSource } from './Interactive/PresetSubSource'; +import { StringSubSource } from './Interactive/StringSubSource'; export class InteractiveSource extends OptionSource { private _exit_on_interrupt: boolean; @@ -24,62 +26,17 @@ export class InteractiveSource extends OptionSource { this._exit_on_interrupt = exit_on_interrupt; } - private get_message (opt: Option): string { - return typeof opt.message === 'undefined' - ? `input ${opt.name}` - : opt.message; - } - private async prompt (opt: Option, val:OptionValue): Promise { if (val.filled) return; - let value = null; - const { option_type } = val.type_validation; - const { preset } = opt as StringOptionConfig; - if ( - option_type === 'string' - || option_type === 'file' - || option_type === 'folder' - || option_type === 'path' - || option_type === 'number' - ) { - if (typeof preset === 'undefined') { - value = await new Input ({ - message: this.get_message (opt), - default: opt.default - }) - .run (); - } - else { - value = await new AutoComplete ({ - message: this.get_message (opt), - default: opt.default, - choices: preset, - limit: 10 - }) - .run (); - } - } - if ( - option_type === 'boolean' - ) { - value = await new Confirm ({ - message: this.get_message (opt), - default: opt.default - }) - .run (); - } - if (option_type === 'array') { - value = await new List ({ - message: this.get_message (opt), - default: opt.default - }) - .run (); - } - if (value === null) - return; - - await this.assign_arg (opt, val, value); + await new StringSubSource (val, opt) + .parse (); + await new PresetSubSource (val, opt) + .parse (); + await new BooleanSubSource (val, opt) + .parse (); + await new ArraySubSource (val, opt) + .parse (); } public async parse (opt: Option, val:OptionValue): Promise { diff --git a/lib/Sources/OptionSource.ts b/lib/Sources/OptionSource.ts index 9a4f742..78fba35 100644 --- a/lib/Sources/OptionSource.ts +++ b/lib/Sources/OptionSource.ts @@ -16,19 +16,4 @@ export abstract class OptionSource { public constructor (error_callback?: ErrorCallback) { this.error_callback = error_callback; } - - protected async assign_arg ( - opt: Option, - val: OptionValue, - value: unknown - ): Promise { - try { - val.value = await val.type_validation.to_type (value); - val.filled = true; - } - catch (e) { - if (typeof this.error_callback !== 'undefined') - this.error_callback (opt.name, value, e); - } - } }