From 1a84577a108e192b18af0180b8a28ea28fdc2d03 Mon Sep 17 00:00:00 2001 From: "Leo Lee (DEVDIV)" Date: Fri, 6 Feb 2015 16:04:01 -0800 Subject: [PATCH] moved taco logic from taco-utils to taco moved resources out from help module to resources.json --- src/taco-cli/bin/taco | 2 +- src/taco-cli/cli/commands.json | 58 +++------------- src/taco-cli/cli/cordova.ts | 13 ++-- src/taco-cli/cli/create.ts | 20 ++++-- src/taco-cli/cli/help.ts | 59 +++++++++++----- src/taco-cli/cli/taco.ts | 47 +++++++------ src/taco-cli/resources/en/resources.json | 13 +++- src/taco-utils/taco-utils.ts | 86 ++++++++++++++---------- src/typings/taco-utils.d.ts | 47 ++++++++++--- 9 files changed, 198 insertions(+), 147 deletions(-) diff --git a/src/taco-cli/bin/taco b/src/taco-cli/bin/taco index 02a316cd..41f03cb0 100644 --- a/src/taco-cli/bin/taco +++ b/src/taco-cli/bin/taco @@ -1,4 +1,4 @@ #!/usr/bin/env node var taco = require('./../cli/taco'); -taco(); +taco.run(); diff --git a/src/taco-cli/cli/commands.json b/src/taco-cli/cli/commands.json index 1f973457..c1d739ec 100644 --- a/src/taco-cli/cli/commands.json +++ b/src/taco-cli/cli/commands.json @@ -2,59 +2,23 @@ "create": { "synopsis": " [ID] [NAME] [options]", "modulePath": "../cli/create", - "description": "Create a Cordova project", + "description": "[command.create.description]", "args": [ - { "name": "PATH", "description": "Where to create the project" }, - { "name": "ID", "description": "Package ID for the project" }, - { "name": "NAME", "description": "Human readable app name" } + { "name": "PATH", "description": "[command.create.description]" }, + { "name": "ID", "description": "[command.create.args.path]" }, + { "name": "NAME", "description": "[command.create.args.name]" } ], "options": [ - { "name": "--kit ", "description": "Use the specified Cordova Dev Kit for this project rather than the default. Use \"taco kit list\" to see a list of available Kits." }, - { "name": "--template ", "description": "Use an alternate project template instead of blank." }, - { "name": "--cli ", "description": "Use a version of the Cordova CLI rather than a Cordova Dev Kit." }, - { "name": "--copy-from|src ", "description": "Use custom www assets instead using a template." }, - { "name": "--link-to ", "description": "Symlink to custom www assets without creating a copy." } - ] - }, - "plugin": { - "Synopsis" : "", - "modulePath": "../cli/cordova", - "description": "Add/remove a plugin", - "args": [ - { "name": "[command]", "description": "add or remove" }, - { "name": "", "description": "name of the plugin" } + { "name": "--kit ", "description": "[command.create.options.kit]" }, + { "name": "--template ", "description": "[command.create.options.template]" }, + { "name": "--cli ", "description": "[command.create.options.cli]" }, + { "name": "--copy-from|src ", "description": "[command.create.options.copy]" }, + { "name": "--link-to ", "description": "[command.create.options.linkto]" } ] }, "help": { + "synopsis": "[COMMAND]", "modulePath": "../cli/help", - "description": "Get help for a command" - }, - "info": { - "modulePath": "../cli/cordova", - "description": "Generate project information" - }, - "platform": { - "modulePath": "../cli/cordova", - "description": "Manage project platforms" - }, - "plugin": { - "modulePath": "../cli/cordova", - "description": "Manage project plugins" - }, - "prepare": { - "modulePath": "../cli/cordova", - "description": "Copy files into platform(s) for building" - }, - "compile": { - "modulePath": "../cli/cordova", - "description": "Build platform(s)" - }, - "run": { - "modulePath": "../cli/cordova", - "description": "Run project (including prepare && compile)" - }, - "serve": { - "modulePath": "../cli/cordova", - "description": "Run project with a local webserver (including prepare)" + "description": "[command.help.description]" } } \ No newline at end of file diff --git a/src/taco-cli/cli/cordova.ts b/src/taco-cli/cli/cordova.ts index d0d1c666..4236465a 100644 --- a/src/taco-cli/cli/cordova.ts +++ b/src/taco-cli/cli/cordova.ts @@ -4,18 +4,23 @@ import cordova = require ("cordova"); import tacoUtility = require("taco-utils"); +import commands = tacoUtility.Commands; /* * Cordova * * Command class handling passthroughs to CordovaCLI */ -class Cordova extends tacoUtility.Commands.Command { - +class Cordova implements commands.ICommand { + info: commands.ICommandInfo; /** * Handles direct routing to Cordova CLI */ - public run(): void { - cordova.cli(this.cliArgs); + public run(args: string[]): void { + cordova.cli(args); + } + + public canHandleArgs(args: string[]): boolean { + return true; } } diff --git a/src/taco-cli/cli/create.ts b/src/taco-cli/cli/create.ts index 50e234e4..eae64e51 100644 --- a/src/taco-cli/cli/create.ts +++ b/src/taco-cli/cli/create.ts @@ -4,20 +4,22 @@ import tacoUtility = require("taco-utils"); import cordovaCommand = require("./cordova"); -var nopt = require("nopt"); +import commands = tacoUtility.Commands; import logger = tacoUtility.Logger; import level = logger.Level; +var nopt = require("nopt"); /* * Create * * handles "Taco Create" */ -class Create extends cordovaCommand { +class Create implements commands.ICommand { + public info: commands.ICommandInfo; /** * Sample only, shows processing specific taco commands, and passing remaining ones to Cordova CLI */ - run() { + public run(args: string[]): void { var knownOpts: any = { "template": String }; @@ -25,14 +27,18 @@ class Create extends cordovaCommand { "t": ["--template"] }; - var args = nopt(knownOpts, shortHands, process.argv, 2); + var createArgs = nopt(knownOpts, shortHands, args, 2); //sample getting args specific to taco - logger.logNewLine("Creating new project using template : " + args.template, level.Success); + logger.logLine("Creating new project using template : " + createArgs.template, level.Success); //sample routing remaining args to Cordova, stripped out template - this.cliArgs = args.argv.remain; - super.run(); //take this out if we don't need to route to Cordova CLI + //this.cliArgs = args.argv.remain; + //super.run(); //take this out if we don't need to route to Cordova CLI + } + + public canHandleArgs(args: string[]): boolean { + return true; } } diff --git a/src/taco-cli/cli/help.ts b/src/taco-cli/cli/help.ts index 3708bf66..462f0d89 100644 --- a/src/taco-cli/cli/help.ts +++ b/src/taco-cli/cli/help.ts @@ -8,6 +8,8 @@ import nopt = require("nopt"); var colors = require("colors"); import tacoUtility = require("taco-utils"); import commandsFactory = tacoUtility.Commands.CommandFactory; +import resourcesManager = tacoUtility.ResourcesManager; +import commands = tacoUtility.Commands; import logger = tacoUtility.Logger; import level = logger.Level; /* @@ -15,20 +17,29 @@ import level = logger.Level; * * handles "Taco Help" */ -class Help extends tacoUtility.Commands.Command { - private indent: string = " "; - private charsToDescription: number = 35; - private maxRight = 70; +class Help implements commands.ICommand { + public info: commands.ICommandInfo; + private indentWidth: number = 3; //indent string + private indent: string; + private charsToDescription: number = 35; //number of characters from start of line to description text + private maxRight = 80; //maximum characters we're allowing in each line + private tacoString = "taco"; + + public canHandleArgs(args: string[]): boolean { + return true; + } /** * entry point for printing helper */ - run() { + run(args: string[]) { + this.indent = this.generateSpaces(this.indentWidth); this.printHeader(); - if (this.cliArgs.length == 0) { + args = args.splice(3); + if (args.length == 0) { this.printGeneralUsage(); - } else if (this.cliArgs.length == 1) { - this.printCommandUsage(this.cliArgs[0]) + } else if (args.length == 1) { + this.printCommandUsage(args[0]) } } @@ -36,14 +47,14 @@ class Help extends tacoUtility.Commands.Command { * prints out Microsoft header */ public printHeader(): void { - logger.logNewLine("\n=================================================================", level.Normal); + logger.logLine("\n=================================================================", level.Normal); } /** * prints out general usage of all support TACO commands */ public printGeneralUsage(): void { - logger.logNewLine("\nGeneral Usage", level.Normal); + logger.logLine("\nGeneral Usage", level.Normal); } /** @@ -52,22 +63,23 @@ class Help extends tacoUtility.Commands.Command { */ public printCommandUsage(command: string): void { if (!commandsFactory.Listings || !commandsFactory.Listings[command]) { + logger.logErrorLine("command.help.badcomand"); this.printGeneralUsage(); return; } var list: tacoUtility.Commands.ICommandInfo = commandsFactory.Listings[command]; - logger.logNewLine("Synopsis\n", level.NormalBold); - logger.logNewLine(this.indent + list.synopsis + "\n", level.Success); - logger.logNewLine(list.description + "\n", level.NormalBold); + logger.logLine("Synopsis\n", level.NormalBold); + logger.logLine(this.indent + this.tacoString + " " + command + " " + list.synopsis + "\n", level.Success); + logger.logLine(this.getString(list.description) + "\n", level.NormalBold); this.printCommandTable(list.args, this.indent); - logger.logNewLine("\n" + this.indent + "Options:\n", level.NormalBold); + logger.logLine("\n" + this.indent + "Options:\n", level.NormalBold); this.printCommandTable(list.options, this.indent + this.indent); } /** * helper function to print out [name --- description] pairs for args and options - * @param {INameDescription[]} nameValuePairs - name-value pairs + * @param {INameDescription[]} nameValuePairs - array of name-value pairs * @param {string} indentFromLeft - string to insert from left */ public printCommandTable(nameValuePairs: tacoUtility.Commands.INameDescription[], indentFromLeft: string) { @@ -79,11 +91,22 @@ class Help extends tacoUtility.Commands.Command { logger.log(".", level.Normal); } - if (this.charsToDescription + nvp.description.length > this.maxRight) { - } - logger.log(" " + nvp.description + "\n", level.Normal); + logger.log(" " + this.getString(nvp.description) + "\n", level.Normal); }); } + + private generateSpaces(numSpaces: number): string { + var spaces: string = ""; + for (var i: number = 0; i < numSpaces; i++){ + spaces = spaces + " "; + } + + return spaces; + } + + private getString(id: string): string { + return resourcesManager.getString(id); + } } export = Help; \ No newline at end of file diff --git a/src/taco-cli/cli/taco.ts b/src/taco-cli/cli/taco.ts index b607bc5d..78d3913f 100644 --- a/src/taco-cli/cli/taco.ts +++ b/src/taco-cli/cli/taco.ts @@ -1,42 +1,47 @@ /// /// /// +/// import tacoUtility = require("taco-utils"); import resourcesManager = tacoUtility.ResourcesManager; -import commandsFactory = tacoUtility.Commands.CommandFactory; -import fs = require("fs"); +import commands = tacoUtility.Commands; +import commandsFactory = commands.CommandFactory; import path = require("path"); - +var cordova = require("cordova"); /* * Taco * * Main Taco class */ class Taco { - /** - * @constructor, initialize all other config classes + /* + * Initialize all other config classes, Invoke task to be run */ - constructor() { + public static run(): void { var resourcePath: string = path.resolve("../resources"); resourcesManager.init("en", resourcePath); commandsFactory.init("../cli/commands.json"); - } + + // parse taco command + var input: string = process.argv[2]; + var command: commands.ICommand = null; - /* - * Invoke task to be run - */ - public run(): void { - commandsFactory.runTask(); + // get appropriate task + if (input) { + command = commandsFactory.getTask(input, process.argv); + } else { + command = commandsFactory.getTask("help", process.argv); + } + + // if no command found that can handle these args, route directly to Cordova + if (!command) { + cordova.cli(process.argv.splice(1)); + return; + } + + command.run(process.argv); } } -/* - * Entry point function called from node - */ -function start(): void { - var taco = new Taco(); - taco.run(); -} - -export = start; \ No newline at end of file +export = Taco; \ No newline at end of file diff --git a/src/taco-cli/resources/en/resources.json b/src/taco-cli/resources/en/resources.json index 6c4e7c61..4896f3b0 100644 --- a/src/taco-cli/resources/en/resources.json +++ b/src/taco-cli/resources/en/resources.json @@ -1,4 +1,13 @@ { - "usage": "Usage: taco-cli command args", - "_usage.comment": "Usage string shown on first use in CLI" + "[command.create.description]": "Create a Cordova project", + "[command.create.args.path]": "Where to create the project", + "[command.create.args.id]": "Package ID for the project", + "[command.create.args.name]": "Human readable app name", + "[command.create.options.kit]": "Use the specified Cordova Dev Kit for this project rather than the default. Use \"taco kit list\" to see a list of available Kits.", + "[command.create.options.template]": "Use an alternate project template instead of blank.", + "[command.create.options.cli]": "Use a version of the Cordova CLI rather than a Cordova Dev Kit.", + "[command.create.options.copy]": "Use custom www assets instead using a template.", + "[command.create.options.linkto]": "Symlink to custom www assets without creating a copy.", + "[command.help.description]": "Get help for a command", + "command.help.badcomand": "%s is not a valid command" } \ No newline at end of file diff --git a/src/taco-utils/taco-utils.ts b/src/taco-utils/taco-utils.ts index c1c47c09..65e2e73c 100644 --- a/src/taco-utils/taco-utils.ts +++ b/src/taco-utils/taco-utils.ts @@ -34,11 +34,7 @@ module TacoUtility { case Level.NormalBold: return msg.normalBold; case Level.Success: return msg.success.bold; } - } - - export function logNewLine(msg: string, level: Level): void { - log(msg + "\n", level); - } + } /** * log @@ -58,6 +54,37 @@ module TacoUtility { process.stdout.write(msg); break; } + } + + /** + * for quick logging use + */ + export function logLine(msg: string, level: Level): void { + log(msg + "\n", level); + } + + export function logErrorLine(msg: string) { + logLine(msg, Level.Error); + } + + export function logWarnLine(msg: string) { + logLine(msg, Level.Warn); + } + + export function logLinkLine(msg: string) { + logLine(msg, Level.Link); + } + + export function logNormalLine(msg: string) { + logLine(msg, Level.Normal); + } + + export function logNormalBoldLine(msg: string) { + logLine(msg, Level.NormalBold); + } + + export function logSuccessLine(msg: string) { + logLine(msg, Level.Success); } } @@ -78,24 +105,19 @@ module TacoUtility { /** * Base command class, all other commands inherit from this */ - export class Command { + export interface ICommand { info: ICommandInfo; - cliArgs: string[]; - constructor(info: ICommandInfo) { - this.info = info; - this.cliArgs = process.argv.slice(3); - } - - public run() { - } + run(args: string[]): void; + canHandleArgs(args: string[]): boolean; } /** * Factory to create new Commands classes */ export class CommandFactory { + private static args: any[]; public static Listings: any; - private static Instance: Command; + private static Instance: ICommand; /** * Factory to create new Commands classes @@ -113,41 +135,31 @@ module TacoUtility { /** * get specific task object, given task name */ - public static getTask(name: string): Command { + public static getTask(name: string, inputArgs: string[]): ICommand { if (!name || !CommandFactory.Listings) { throw new Error("Cannot find command listing file"); } var moduleInfo: ICommandInfo = CommandFactory.Listings[name]; + if (!moduleInfo) { + return null; + } + var modulePath = path.resolve(moduleInfo.modulePath); if (!fs.existsSync(modulePath + ".js")) { throw new Error("Cannot find command module"); } - var commandMod: typeof Command = require(modulePath); - CommandFactory.Instance = new commandMod(moduleInfo); - if (!CommandFactory.Instance) { - throw new Error("Can't build command instance"); - } + var commandMod: any = require(modulePath); + CommandFactory.Instance = new commandMod(); + CommandFactory.Instance.info = moduleInfo; - return CommandFactory.Instance; - } - - /** - * run specific task, based on what's fed to the CLI - */ - public static runTask() { - var input: string = process.argv[2]; - var command: Command = null; - - if (input) { - command = CommandFactory.getTask(input); + if (CommandFactory.Instance && CommandFactory.Instance.canHandleArgs(inputArgs)) { + return CommandFactory.Instance; } else { - command = CommandFactory.getTask("help"); + return null; } - - command.run(); - } + } } } diff --git a/src/typings/taco-utils.d.ts b/src/typings/taco-utils.d.ts index 3cfee064..74d13d22 100644 --- a/src/typings/taco-utils.d.ts +++ b/src/typings/taco-utils.d.ts @@ -2,6 +2,9 @@ /// declare module TacoUtility { module Logger { + /** + * Warning levels + */ enum Level { Warn = 0, Error = 1, @@ -10,13 +13,25 @@ declare module TacoUtility { Success = 4, NormalBold = 5, } - function colorize(msg: string, level: Level): string; - function logNewLine(msg: string, level: Level): void; /** - * - * + * returns colorized string + * wrapping "colors" module because not yet possible to combine themes, i.e. ["yellow", "bold"]: https://github.com/Marak/colors.js/issues/72 + */ + function colorize(msg: string, level: Level): string; + /** + * log */ function log(msg: string, level: Level): void; + /** + * for quick logging use + */ + function logLine(msg: string, level: Level): void; + function logErrorLine(msg: string): void; + function logWarnLine(msg: string): void; + function logLinkLine(msg: string): void; + function logNormalLine(msg: string): void; + function logNormalBoldLine(msg: string): void; + function logSuccessLine(msg: string): void; } module Commands { interface INameDescription { @@ -30,18 +45,30 @@ declare module TacoUtility { args: INameDescription[]; options: INameDescription[]; } - class Command { + /** + * Base command class, all other commands inherit from this + */ + interface ICommand { info: ICommandInfo; - cliArgs: string[]; - constructor(info: ICommandInfo); - run(): void; + run(args: string[]): void; + canHandleArgs(args: string[]): boolean; } + /** + * Factory to create new Commands classes + */ class CommandFactory { + private static args; static Listings: any; private static Instance; + /** + * Factory to create new Commands classes + * initialize with json file containing commands + */ static init(commandsInfoPath: string): void; - static getTask(name: string): Command; - static runTask(): void; + /** + * get specific task object, given task name + */ + static getTask(name: string, inputArgs: string[]): ICommand; } } class ResourcesManager {