Skip to content
This repository was archived by the owner on Feb 2, 2021. It is now read-only.

Commit 06d4f68

Browse files
Merge pull request #1021 from telerik/vladimirov/help-service
Do not track help command when other command fails
2 parents 0812ce9 + b5fe5ff commit 06d4f68

File tree

12 files changed

+502
-81
lines changed

12 files changed

+502
-81
lines changed

bootstrap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ $injector.require("dynamicHelpService", "./services/dynamic-help-service");
9292
$injector.require("microTemplateService", "./services/micro-templating-service");
9393
$injector.require("mobileHelper", "./mobile/mobile-helper");
9494
$injector.require("devicePlatformsConstants", "./mobile/device-platforms-constants");
95-
$injector.require("htmlHelpService", "./services/html-help-service");
95+
$injector.require("helpService", "./services/help-service");
9696
$injector.require("messageContractGenerator", "./services/message-contract-generator");
9797
$injector.require("proxyService", "./services/proxy-service");
9898
$injector.require("credentialsService", "./services/credentials-service");

commands/help.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
import { EOL } from "os";
2-
31
export class HelpCommand implements ICommand {
4-
constructor(private $logger: ILogger,
5-
private $injector: IInjector,
6-
private $htmlHelpService: IHtmlHelpService,
7-
private $staticConfig: Config.IStaticConfig,
2+
constructor(private $injector: IInjector,
3+
private $helpService: IHelpService,
84
private $options: ICommonOptions) { }
95

106
public enableHooks = false;
@@ -22,14 +18,9 @@ export class HelpCommand implements ICommand {
2218
}
2319

2420
if (this.$options.help) {
25-
const help = await this.$htmlHelpService.getCommandLineHelpForCommand(topic);
26-
if (this.$staticConfig.FULL_CLIENT_NAME) {
27-
this.$logger.info(this.$staticConfig.FULL_CLIENT_NAME.green.bold + EOL);
28-
}
29-
30-
this.$logger.printMarkdown(help);
21+
await this.$helpService.showCommandLineHelp(topic);
3122
} else {
32-
await this.$htmlHelpService.openHelpForCommandInBrowser(topic);
23+
await this.$helpService.openHelpForCommandInBrowser(topic);
3324
}
3425
}
3526
}

commands/post-install.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export class PostInstallCommand implements ICommand {
22
constructor(private $fs: IFileSystem,
33
private $staticConfig: Config.IStaticConfig,
44
private $commandsService: ICommandsService,
5-
private $htmlHelpService: IHtmlHelpService,
5+
private $helpService: IHelpService,
66
private $options: ICommonOptions,
77
private $doctorService: IDoctorService,
88
private $analyticsService: IAnalyticsService,
@@ -22,7 +22,7 @@ export class PostInstallCommand implements ICommand {
2222
}
2323
}
2424

25-
await this.$htmlHelpService.generateHtmlPages();
25+
await this.$helpService.generateHtmlPages();
2626

2727
const doctorResult = await this.$doctorService.printWarnings({ trackResult: false });
2828
// Explicitly ask for confirmation of usage-reporting:

declarations.d.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ interface IErrors {
540540
fail(formatStr: string, ...args: any[]): never;
541541
fail(opts: { formatStr?: string; errorCode?: number; suppressCommandHelp?: boolean }, ...args: any[]): never;
542542
failWithoutHelp(message: string, ...args: any[]): never;
543-
beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<boolean>): Promise<boolean>;
543+
beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<void>): Promise<boolean>;
544544
verifyHeap(message: string): void;
545545
printCallStack: boolean;
546546
}
@@ -955,17 +955,17 @@ interface IMicroTemplateService {
955955
parseContent(data: string, options: { isHtml: boolean }): Promise<string>;
956956
}
957957

958-
interface IHtmlHelpService {
958+
interface IHelpService {
959959
generateHtmlPages(): Promise<void>;
960960

961+
openHelpForCommandInBrowser(commandName: string): Promise<void>;
962+
961963
/**
962-
* Gets the help content for a specific command that should be shown on the terminal.
963-
* @param {string} commandName Name of the command for which to read the help.
964-
* @returns {Promise<string>} Help content of the command parsed with all terminal rules applied (stripped content that should be shown only for html help).
964+
* Shows command line help for specified command.
965+
* @param {string} commandName The name of the command for which to show the help.
966+
* @returns {Promise<void>}
965967
*/
966-
getCommandLineHelpForCommand(commandName: string): Promise<string>;
967-
968-
openHelpForCommandInBrowser(commandName: string): Promise<void>;
968+
showCommandLineHelp(commandName: string): Promise<void>;
969969
}
970970

971971
/**

definitions/config.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ declare module Config {
1313
ERROR_REPORT_SETTING_NAME: string;
1414
SYS_REQUIREMENTS_LINK: string;
1515
version: string;
16-
helpTextPath: string;
1716
getAdbFilePath(): Promise<string>;
1817
disableAnalytics?: boolean;
1918
disableCommandHooks?: boolean;

errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export class Errors implements IErrors {
151151
return this.fail({ formatStr: util.format.apply(null, args), suppressCommandHelp: true });
152152
}
153153

154-
public async beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<boolean>): Promise<boolean> {
154+
public async beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<void>): Promise<boolean> {
155155
try {
156156
return await action();
157157
} catch (ex) {

services/commands-service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ export class CommandsService implements ICommandsService {
2424
private $logger: ILogger,
2525
private $options: ICommonOptions,
2626
private $resources: IResourceLoader,
27-
private $staticConfig: Config.IStaticConfig) {
27+
private $staticConfig: Config.IStaticConfig,
28+
private $helpService: IHelpService) {
2829
}
2930

3031
public allCommands(opts: { includeDevCommands: boolean }): string[] {
@@ -77,9 +78,8 @@ export class CommandsService implements ICommandsService {
7778
return false;
7879
}
7980

80-
private async printHelp(commandName: string): Promise<boolean> {
81-
this.$options.help = true;
82-
return this.executeCommandUnchecked("help", [this.beautifyCommandName(commandName)]);
81+
private printHelp(commandName: string): Promise<void> {
82+
return this.$helpService.showCommandLineHelp(this.beautifyCommandName(commandName));
8383
}
8484

8585
private async executeCommandAction(commandName: string, commandArguments: string[], action: (_commandName: string, _commandArguments: string[]) => Promise<boolean>): Promise<boolean> {

services/dynamic-help-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class DynamicHelpService implements IDynamicHelpService {
1515

1616
public getLocalVariables(options: { isHtml: boolean }): IDictionary<any> {
1717
const isHtml = options.isHtml;
18-
//in html help we want to show all help. Only CONSOLE specific help(wrapped in if(isConsole) ) must be omitted
18+
// in html help we want to show all help. Only CONSOLE specific help(wrapped in if(isConsole) ) must be omitted
1919
const localVariables = this.$dynamicHelpProvider.getLocalVariables(options);
2020
localVariables["isLinux"] = isHtml || this.isPlatform("linux");
2121
localVariables["isWindows"] = isHtml || this.isPlatform("win32");

services/html-help-service.ts renamed to services/help-service.ts

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as path from "path";
22
import { EOL } from "os";
33
import marked = require("marked");
44

5-
export class HtmlHelpService implements IHtmlHelpService {
5+
export class HelpService implements IHelpService {
66
private static MARKDOWN_FILE_EXTENSION = ".md";
77
private static HTML_FILE_EXTENSION = ".html";
88
private static MAN_PAGE_NAME_REGEX = /@MAN_PAGE_NAME@/g;
@@ -38,23 +38,64 @@ export class HtmlHelpService implements IHtmlHelpService {
3838
private $fs: IFileSystem,
3939
private $staticConfig: Config.IStaticConfig,
4040
private $microTemplateService: IMicroTemplateService,
41-
private $opener: IOpener,
42-
private $commandsServiceProvider: ICommandsServiceProvider) {
41+
private $opener: IOpener) {
4342
this.pathToHtmlPages = this.$staticConfig.HTML_PAGES_DIR;
4443
this.pathToManPages = this.$staticConfig.MAN_PAGES_DIR;
4544
}
4645

46+
public async openHelpForCommandInBrowser(commandName: string): Promise<void> {
47+
const htmlPage = await this.convertCommandNameToFileName(commandName) + HelpService.HTML_FILE_EXTENSION;
48+
this.$logger.trace("Opening help for command '%s'. FileName is '%s'.", commandName, htmlPage);
49+
50+
this.$fs.ensureDirectoryExists(this.pathToHtmlPages);
51+
if (!this.tryOpeningSelectedPage(htmlPage)) {
52+
// HTML pages may have been skipped on post-install, lets generate them.
53+
this.$logger.trace("Required HTML file '%s' is missing. Let's try generating HTML files and see if we'll find it.", htmlPage);
54+
await this.generateHtmlPages();
55+
if (!this.tryOpeningSelectedPage(htmlPage)) {
56+
this.$errors.failWithoutHelp("Unable to find help for '%s'", commandName);
57+
}
58+
}
59+
}
60+
4761
public async generateHtmlPages(): Promise<void> {
4862
const mdFiles = this.$fs.enumerateFilesInDirectorySync(this.pathToManPages);
4963
const basicHtmlPage = this.$fs.readText(this.pathToBasicPage);
5064
await Promise.all(_.map(mdFiles, markdownFile => this.createHtmlPage(basicHtmlPage, markdownFile)));
5165
this.$logger.trace("Finished generating HTML files.");
5266
}
5367

68+
public async showCommandLineHelp(commandName: string): Promise<void> {
69+
const help = await this.getCommandLineHelpForCommand(commandName);
70+
if (this.$staticConfig.FULL_CLIENT_NAME) {
71+
this.$logger.info(this.$staticConfig.FULL_CLIENT_NAME.green.bold + EOL);
72+
}
73+
74+
this.$logger.printMarkdown(help);
75+
}
76+
77+
/**
78+
* Gets the help content for a specific command that should be shown on the terminal.
79+
* @param {string} commandName Name of the command for which to read the help.
80+
* @returns {Promise<string>} Help content of the command parsed with all terminal rules applied (stripped content that should be shown only for html help).
81+
*/
82+
private async getCommandLineHelpForCommand(commandName: string): Promise<string> {
83+
const helpText = await this.readMdFileForCommand(commandName);
84+
const commandLineHelp = (await this.$microTemplateService.parseContent(helpText, { isHtml: false }))
85+
.replace(/&nbsp;/g, " ")
86+
.replace(HelpService.MARKDOWN_LINK_REGEX, "$1")
87+
.replace(HelpService.SPAN_REGEX, (matchingSubstring: string, textBeforeSpan: string, textInsideSpan: string, index: number, fullString: string): string => {
88+
return textBeforeSpan + textInsideSpan.replace(this.newLineRegex, "");
89+
})
90+
.replace(HelpService.NEW_LINE_REGEX, EOL);
91+
92+
return commandLineHelp;
93+
}
94+
5495
// This method should return Promise in order to generate all html pages simultaneously.
5596
private async createHtmlPage(basicHtmlPage: string, pathToMdFile: string): Promise<void> {
5697
const mdFileName = path.basename(pathToMdFile);
57-
const htmlFileName = mdFileName.replace(HtmlHelpService.MARKDOWN_FILE_EXTENSION, HtmlHelpService.HTML_FILE_EXTENSION);
98+
const htmlFileName = mdFileName.replace(HelpService.MARKDOWN_FILE_EXTENSION, HelpService.HTML_FILE_EXTENSION);
5899
this.$logger.trace("Generating '%s' help topic.", htmlFileName);
59100

60101
const helpText = this.$fs.readText(pathToMdFile);
@@ -67,31 +108,16 @@ export class HtmlHelpService implements IHtmlHelpService {
67108
this.$logger.trace("HTML file path for '%s' man page is: '%s'.", mdFileName, filePath);
68109

69110
const outputHtml = basicHtmlPage
70-
.replace(HtmlHelpService.MAN_PAGE_NAME_REGEX, mdFileName.replace(HtmlHelpService.MARKDOWN_FILE_EXTENSION, ""))
71-
.replace(HtmlHelpService.HTML_COMMAND_HELP_REGEX, htmlText)
72-
.replace(HtmlHelpService.RELATIVE_PATH_TO_STYLES_CSS_REGEX, path.relative(path.dirname(filePath), this.pathToStylesCss))
73-
.replace(HtmlHelpService.RELATIVE_PATH_TO_IMAGES_REGEX, path.relative(path.dirname(filePath), this.pathToImages))
74-
.replace(HtmlHelpService.RELATIVE_PATH_TO_INDEX_REGEX, path.relative(path.dirname(filePath), this.pathToIndexHtml));
111+
.replace(HelpService.MAN_PAGE_NAME_REGEX, mdFileName.replace(HelpService.MARKDOWN_FILE_EXTENSION, ""))
112+
.replace(HelpService.HTML_COMMAND_HELP_REGEX, htmlText)
113+
.replace(HelpService.RELATIVE_PATH_TO_STYLES_CSS_REGEX, path.relative(path.dirname(filePath), this.pathToStylesCss))
114+
.replace(HelpService.RELATIVE_PATH_TO_IMAGES_REGEX, path.relative(path.dirname(filePath), this.pathToImages))
115+
.replace(HelpService.RELATIVE_PATH_TO_INDEX_REGEX, path.relative(path.dirname(filePath), this.pathToIndexHtml));
75116

76117
this.$fs.writeFile(filePath, outputHtml);
77118
this.$logger.trace("Finished writing file '%s'.", filePath);
78119
}
79120

80-
public async openHelpForCommandInBrowser(commandName: string): Promise<void> {
81-
const htmlPage = await this.convertCommandNameToFileName(commandName) + HtmlHelpService.HTML_FILE_EXTENSION;
82-
this.$logger.trace("Opening help for command '%s'. FileName is '%s'.", commandName, htmlPage);
83-
84-
this.$fs.ensureDirectoryExists(this.pathToHtmlPages);
85-
if (!this.tryOpeningSelectedPage(htmlPage)) {
86-
// HTML pages may have been skipped on post-install, lets generate them.
87-
this.$logger.trace("Required HTML file '%s' is missing. Let's try generating HTML files and see if we'll find it.", htmlPage);
88-
await this.generateHtmlPages();
89-
if (!this.tryOpeningSelectedPage(htmlPage)) {
90-
this.$errors.failWithoutHelp("Unable to find help for '%s'", commandName);
91-
}
92-
}
93-
}
94-
95121
private async convertCommandNameToFileName(commandName: string): Promise<string> {
96122
const defaultCommandMatch = commandName.match(/(\w+?)\|\*/);
97123
if (defaultCommandMatch) {
@@ -101,11 +127,8 @@ export class HtmlHelpService implements IHtmlHelpService {
101127

102128
const availableCommands = this.$injector.getRegisteredCommandsNames(true).sort();
103129
this.$logger.trace("List of registered commands: %s", availableCommands.join(", "));
104-
if (commandName && _.startsWith(commandName, this.$commandsServiceProvider.dynamicCommandsPrefix) && !_.includes(availableCommands, commandName)) {
105-
const dynamicCommands = await this.$commandsServiceProvider.getDynamicCommands();
106-
if (!_.includes(dynamicCommands, commandName)) {
107-
this.$errors.failWithoutHelp("Unknown command '%s'. Try '$ %s help' for a full list of supported commands.", commandName, this.$staticConfig.CLIENT_NAME.toLowerCase());
108-
}
130+
if (!_.includes(availableCommands, commandName)) {
131+
this.$errors.failWithoutHelp("Unknown command '%s'. Try '$ %s help' for a full list of supported commands.", commandName, this.$staticConfig.CLIENT_NAME.toLowerCase());
109132
}
110133

111134
return commandName.replace(/\|/g, "-") || "index";
@@ -127,7 +150,7 @@ export class HtmlHelpService implements IHtmlHelpService {
127150
}
128151

129152
private async readMdFileForCommand(commandName: string): Promise<string> {
130-
const mdFileName = await this.convertCommandNameToFileName(commandName) + HtmlHelpService.MARKDOWN_FILE_EXTENSION;
153+
const mdFileName = await this.convertCommandNameToFileName(commandName) + HelpService.MARKDOWN_FILE_EXTENSION;
131154
this.$logger.trace("Reading help for command '%s'. FileName is '%s'.", commandName, mdFileName);
132155

133156
const markdownFile = _.find(this.$fs.enumerateFilesInDirectorySync(this.pathToManPages), file => path.basename(file) === mdFileName);
@@ -137,19 +160,6 @@ export class HtmlHelpService implements IHtmlHelpService {
137160

138161
this.$errors.failWithoutHelp("Unknown command '%s'. Try '$ %s help' for a full list of supported commands.", mdFileName.replace(".md", ""), this.$staticConfig.CLIENT_NAME.toLowerCase());
139162
}
140-
141-
public async getCommandLineHelpForCommand(commandName: string): Promise<string> {
142-
const helpText = await this.readMdFileForCommand(commandName);
143-
const commandLineHelp = (await this.$microTemplateService.parseContent(helpText, { isHtml: false }))
144-
.replace(/&nbsp;/g, " ")
145-
.replace(HtmlHelpService.MARKDOWN_LINK_REGEX, "$1")
146-
.replace(HtmlHelpService.SPAN_REGEX, (matchingSubstring: string, textBeforeSpan: string, textInsideSpan: string, index: number, fullString: string): string => {
147-
return textBeforeSpan + textInsideSpan.replace(this.newLineRegex, "");
148-
})
149-
.replace(HtmlHelpService.NEW_LINE_REGEX, EOL);
150-
151-
return commandLineHelp;
152-
}
153163
}
154164

155-
$injector.register("htmlHelpService", HtmlHelpService);
165+
$injector.register("helpService", HelpService);

static-config-base.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ export abstract class StaticConfigBase implements Config.IStaticConfig {
3636

3737
constructor(protected $injector: IInjector) { }
3838

39-
public get helpTextPath(): string {
40-
return null;
41-
}
42-
4339
public async getAdbFilePath(): Promise<string> {
4440
if (!this._adbFilePath) {
4541
this._adbFilePath = await this.getAdbFilePathCore();

0 commit comments

Comments
 (0)