Skip to content

Commit 2df63dd

Browse files
authored
Merge pull request #13075 from keymanapp/fix/developer/13072-make-kmc-log-options-consistent
fix(developer): make kmc log options consistent across all commands
2 parents a94adfb + adf4b80 commit 2df63dd

File tree

17 files changed

+153
-182
lines changed

17 files changed

+153
-182
lines changed

Diff for: developer/docs/help/reference/kmc/cli/reference.md

+27-23
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,33 @@ The following parameters are available:
9090

9191
: Prints the version number of kmc
9292

93-
`--no-error-reporting`, `--error-reporting`
93+
`--color`, `--no-color`
94+
95+
: Controls colorization for log messages, using ANSI color controls. If both of
96+
these settings are omitted, kmc will attempt to detect from console, and will
97+
use colorization for interactive terminals, and no colorization when
98+
redirection is being used.
99+
100+
`--error-reporting`, `--no-error-reporting`
94101

95-
: Enable or disable error reporting to keyman.com, overriding [user
96-
settings](../../user-settings). Error reporting is for fatal errors in the
97-
compiler, and not errors in compiled files. No user data is sent in error
102+
: Enable or disable error reporting to keyman.com, overriding
103+
[user settings](../../user-settings). Error reporting is for fatal errors in
104+
the compiler, and not errors in compiled files. No user data is sent in error
98105
reports, although some filenames and paths may be present in the diagnostic
99106
data attached to the report.
100107

108+
`--log-format <logFormat>`
109+
110+
: Output log format. The available options are:
111+
* `formatted` (default): emits log messages in a human-readable format
112+
* `tsv`: emits log messages in UTF-8 tab-separated format. This format will be
113+
stable across versions of kmc. The format has the following fields:
114+
* filename
115+
* line number
116+
* severity
117+
* code
118+
* message
119+
101120
`-l <logLevel>`, `--log-level <logLevel>`
102121

103122
: Controls the level of logging to console for messages relating to the
@@ -108,23 +127,19 @@ The following parameters are available:
108127
* `hint`: emits compilation errors, warnings, and hints
109128
* `info` (default): emits compilation errors, warnings, hints, and
110129
informational messages
130+
* `verbose`: emits all compilation messages, including verbose
131+
informational messages
111132
* `debug`: emits all compilation messages, plus internal debug messages
112133

113-
Logging of specific [messages](messages) can be controlled with `--message`, `-m`.
134+
Logging of specific [messages](messages) can be controlled with `--message`,
135+
`-m` (`build` command only).
114136

115137
Note that when warnings are treated as errors
116138
(`--compiler-warnings-as-errors`, `-w`), they will still be logged as
117139
warnings, so suppressing warnings while using this flag may be confusing.
118140

119141
## `kmc build` options
120142

121-
`--color`, `--no-color`
122-
123-
: Controls colorization for log messages, using ANSI color controls. If both of
124-
these settings are omitted, kmc will attempt to detect from console, and will
125-
use colorization for interactive terminals, and no colorization when
126-
redirection is being used.
127-
128143
`-d`, `--debug`
129144

130145
: Include debug information in output files. Debug information is used for
@@ -167,17 +182,6 @@ The following parameters are available:
167182
: Turns off warnings (CWARN_HeaderStatementIsDeprecated,
168183
CWARN_LanguageHeadersDeprecatedInKeyman10) for deprecated code styles
169184

170-
`--log-format <logFormat>`
171-
172-
: Output log format. The available options are:
173-
* `formatted` (default): emits log messages in a human-readable format
174-
* `tsv`: emits log messages in UTF-8 tab-separated format. This format will be
175-
stable across versions of kmc. The format has the following fields:
176-
* filename
177-
* line number
178-
* severity
179-
* code
180-
* message
181185

182186
`-o <filename>`, `--out-file <filename>`
183187

Diff for: developer/src/common/web/utils/src/compiler-interfaces.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -291,10 +291,8 @@ export interface CompilerMessageOverride {
291291
level: CompilerErrorSeverityOverride;
292292
};
293293

294-
export interface CompilerCallbackOptions {
295-
logLevel?: CompilerLogLevel;
296-
logFormat?: CompilerLogFormat;
297-
color?: boolean; // null or undefined == use console default
294+
export interface CompilerCallbackOptions extends CompilerBaseOptions {
295+
// TODO: these overlap with CompilerOptions, should refactor
298296
compilerWarningsAsErrors?: boolean;
299297
messageOverrides?: CompilerMessageOverrideMap;
300298
};

Diff for: developer/src/kmc-copy/src/KeymanProjectCopier.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Copy a keyboard or lexical model project
55
*/
66

7-
import { CloudUrls, GitHubUrls, CompilerCallbacks, CompilerLogLevel, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KeymanDeveloperProject, KeymanDeveloperProjectOptions, KPJFileReader, KPJFileWriter, KpsFileReader, KpsFileWriter, ValidIds } from "@keymanapp/developer-utils";
7+
import { CloudUrls, GitHubUrls, CompilerCallbacks, KeymanCompiler, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult, KeymanDeveloperProject, KeymanDeveloperProjectOptions, KPJFileReader, KPJFileWriter, KpsFileReader, KpsFileWriter, ValidIds, CompilerBaseOptions } from "@keymanapp/developer-utils";
88
import { KeymanFileTypes } from "@keymanapp/common-types";
99

1010
import { CopierMessages } from "./copier-messages.js";
@@ -19,12 +19,7 @@ type CopierFunction = (
1919
* @public
2020
* Options for the Keyman Developer project copier
2121
*/
22-
export interface CopierOptions /* not inheriting from CompilerBaseOptions */ {
23-
/**
24-
* Reporting level to console, used by NodeCompilerCallbacks (not used in
25-
* compiler modules; all messages are still reported to the internal log)
26-
*/
27-
logLevel?: CompilerLogLevel;
22+
export interface CopierOptions extends CompilerBaseOptions {
2823
/**
2924
* output path where project folder will be created
3025
*/

Diff for: developer/src/kmc-generate/src/abstract-generator.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Base interfaces and classes for generating Keyman Developer source files
55
*/
66

7-
import { CompilerCallbacks, CompilerLogLevel, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult } from "@keymanapp/developer-utils";
7+
import { CompilerBaseOptions, CompilerCallbacks, KeymanCompilerArtifact, KeymanCompilerArtifacts, KeymanCompilerResult } from "@keymanapp/developer-utils";
88
import { GeneratorMessages } from './generator-messages.js';
99
import { KeymanTargets } from "@keymanapp/common-types";
1010

@@ -13,12 +13,7 @@ import { KeymanTargets } from "@keymanapp/common-types";
1313
* @public
1414
* Options for the Keyman Developer project generator
1515
*/
16-
export interface GeneratorOptions /* not inheriting from CompilerBaseOptions */ {
17-
/**
18-
* Reporting level to console, used by NodeCompilerCallbacks (not used in
19-
* compiler modules; all messages are still reported to the internal log)
20-
*/
21-
logLevel?: CompilerLogLevel;
16+
export interface GeneratorOptions extends CompilerBaseOptions {
2217
/**
2318
* identifier (basename) of the keyboard or model
2419
*/

Diff for: developer/src/kmc-generate/src/basic-generator.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ export class BasicGenerator extends AbstractGenerator {
2727
protected preGenerate() {
2828
const dt = new Date();
2929

30-
this.languageTags = this.options.languageTags.length
30+
this.languageTags = this.options.languageTags?.length
3131
? this.options.languageTags.map(tag => new Intl.Locale(tag).minimize().toString())
3232
: [this.DEFAULT_LOCALE];
3333

3434
// Verify that targets passed in are valid
3535
let failed = false;
36-
for(const target of this.options.targets) {
36+
for(const target of this.options.targets ?? []) {
3737
if(!KeymanTargets.AllKeymanTargets.includes(target)) {
3838
this.callbacks.reportMessage(GeneratorMessages.Error_InvalidTarget({target}));
3939
failed = true;
@@ -43,7 +43,7 @@ export class BasicGenerator extends AbstractGenerator {
4343
return false;
4444
}
4545

46-
if(this.options.targets.includes(KeymanTargets.KeymanTarget.any) || this.options.targets.length == 0) {
46+
if(this.options.targets?.includes(KeymanTargets.KeymanTarget.any) || !this.options.targets?.length) {
4747
this.resolvedTargets = KeymanTargets.AllKeymanTargets.filter(target => target != KeymanTargets.KeymanTarget.any);
4848
} else {
4949
this.resolvedTargets = [].concat(this.options.targets);

Diff for: developer/src/kmc/src/commands/analyze.ts

+21-10
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@ import * as path from 'path';
33
import { Command, Option } from 'commander';
44
import { NodeCompilerCallbacks } from '../util/NodeCompilerCallbacks.js';
55
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
6-
import { CompilerCallbacks, CompilerLogLevel } from '@keymanapp/developer-utils';
6+
import { CompilerBaseOptions, CompilerCallbacks } from '@keymanapp/developer-utils';
77
import { AnalyzeOskCharacterUse, AnalyzeOskRewritePua } from '@keymanapp/kmc-analyze';
88
import { BaseOptions } from '../util/baseOptions.js';
99
import { runOnFiles } from '../util/projectRunner.js';
1010
import { exitProcess } from '../util/sysexits.js';
11+
import { commanderOptionsToBaseOptions } from '../util/extendedCompilerOptions.js';
1112

12-
interface AnalysisActivityOptions /* not inheriting from CompilerBaseOptions */ {
13-
/**
14-
* Reporting level to console, used by NodeCompilerCallbacks (not used in compiler modules;
15-
* all messages are still reported to the internal log)
16-
*/
17-
logLevel?: CompilerLogLevel;
13+
interface AnalysisActivityOptions extends CompilerBaseOptions {
1814
base?: string;
1915
stripDottedCircle?: boolean;
2016
includeCounts?: boolean;
@@ -30,7 +26,7 @@ export function declareAnalyze(program: Command) {
3026

3127
function declareOskCharUse(command: Command) {
3228
let subCommand = command.command('osk-char-use [infile...]');
33-
BaseOptions.addLogLevel(subCommand);
29+
BaseOptions.addAll(subCommand);
3430
subCommand
3531
.description('Analyze On Screen Keyboards for character usage')
3632
.option('-b, --base', 'First PUA codepoint to use, in hexadecimal (default F100)', 'F100')
@@ -75,9 +71,24 @@ function declareOskRewrite(command: Command) {
7571
});
7672
}
7773

74+
function commanderOptionsToAnalyzeOptions(options: any): AnalysisActivityOptions {
75+
// TODO: split options per sub-command
76+
const result: AnalysisActivityOptions = {
77+
...commanderOptionsToBaseOptions(options),
78+
// AnalysisActivityOptions
79+
base: options.base,
80+
includeCounts: options.includeCounts ?? false,
81+
inputMappingFile: options.inputMappingFile,
82+
mappingFile: options.mappingFile,
83+
stripDottedCircle: options.stripDottedCircle ?? false,
84+
};
85+
return result;
86+
}
87+
7888
async function analyze(action: (callbacks: CompilerCallbacks, filenames: string[], options: AnalysisActivityOptions)=>Promise<boolean>,
79-
filenames: string[], options: AnalysisActivityOptions): Promise<boolean> {
80-
let callbacks = new NodeCompilerCallbacks({logLevel: options.logLevel});
89+
filenames: string[], commanderOptions: any): Promise<boolean> {
90+
const options = commanderOptionsToAnalyzeOptions(commanderOptions);
91+
let callbacks = new NodeCompilerCallbacks(options);
8192
try {
8293
return await action(callbacks, filenames, options);
8394
} catch(e) {

Diff for: developer/src/kmc/src/commands/build.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,18 @@ import { NodeCompilerCallbacks } from '../util/NodeCompilerCallbacks.js';
77
import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
88
import { KeymanFileTypes } from '@keymanapp/common-types';
99
import { CompilerOptions, CompilerFileCallbacks } from '@keymanapp/developer-utils';
10-
import { BaseOptions } from '../util/baseOptions.js';
10+
import { BuildBaseOptions } from '../util/baseOptions.js';
1111
import { expandFileLists } from '../util/fileLists.js';
1212
import { isProject } from '../util/projectLoader.js';
1313
import { buildTestData } from './buildTestData/index.js';
1414
import { buildWindowsPackageInstaller } from './buildWindowsPackageInstaller/index.js';
15-
import { commandOptionsToCompilerOptions } from '../util/extendedCompilerOptions.js';
15+
import { commanderOptionsToCompilerOptions } from '../util/extendedCompilerOptions.js';
1616
import { exitProcess } from '../util/sysexits.js';
1717

1818
export function declareBuild(program: Command) {
1919
// TODO: localization?
2020
const buildCommand = program
2121
.command('build')
22-
.option('--color', 'Force colorization for log messages')
23-
.option('--no-color', 'No colorization for log messages; if both omitted, detects from console')
2422

2523
// These options are only used with build file but are included here so that
2624
// they are visible in `kmc build --help`
@@ -32,7 +30,7 @@ export function declareBuild(program: Command) {
3230
.option('--no-compiler-version', 'Exclude compiler version metadata from output')
3331
.option('--no-warn-deprecated-code', 'Turn off warnings for deprecated code styles');
3432

35-
BaseOptions.addAll(buildCommand);
33+
BuildBaseOptions.addAll(buildCommand);
3634

3735
buildCommand.command('file [infile...]', {isDefault: true})
3836
.description(`Compile one or more source files or projects ('file' subcommand is default).`)
@@ -74,7 +72,7 @@ function initialize(commanderOptions: any) {
7472
// We use a default callback instance when validating command line, but throw
7573
// it away once we have completed initialization
7674
const initializationCallbacks = new NodeCompilerCallbacks({});
77-
const options = commandOptionsToCompilerOptions(commanderOptions, initializationCallbacks);
75+
const options = commanderOptionsToCompilerOptions(commanderOptions, initializationCallbacks);
7876
return options;
7977
}
8078

Diff for: developer/src/kmc/src/commands/buildTestData/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import * as kmcLdml from '@keymanapp/kmc-ldml';
44
import { CompilerCallbacks, defaultCompilerOptions, LDMLKeyboardTestDataXMLSourceFile, LDMLKeyboardXMLSourceFileReader } from '@keymanapp/developer-utils';
55
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
66
import { fileURLToPath } from 'url';
7-
import { CommandLineBaseOptions } from 'src/util/baseOptions.js';
7+
import { CommandLineBuildBaseOptions } from 'src/util/baseOptions.js';
88
import { exitProcess } from '../../util/sysexits.js';
99
import { InfrastructureMessages } from '../../messages/infrastructureMessages.js';
1010
import { dirname } from 'node:path';
1111

1212
export async function buildTestData(infile: string, _options: any, commander: any): Promise<void> {
13-
const options: CommandLineBaseOptions = commander.optsWithGlobals();
13+
const options: CommandLineBuildBaseOptions = commander.optsWithGlobals();
1414

1515
let compilerOptions: kmcLdml.LdmlCompilerOptions = {
1616
...defaultCompilerOptions,

Diff for: developer/src/kmc/src/commands/buildWindowsPackageInstaller/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import * as path from 'path';
33
import { CompilerCallbacks, defaultCompilerOptions } from '@keymanapp/developer-utils';
44
import { NodeCompilerCallbacks } from '../../util/NodeCompilerCallbacks.js';
55
import { WindowsPackageInstallerCompiler, WindowsPackageInstallerSources } from '@keymanapp/kmc-package';
6-
import { CommandLineBaseOptions } from 'src/util/baseOptions.js';
6+
import { CommandLineBuildBaseOptions } from 'src/util/baseOptions.js';
77
import { exitProcess } from '../../util/sysexits.js';
88

9-
interface WindowsPackageInstallerCommandLineOptions extends CommandLineBaseOptions {
9+
interface WindowsPackageInstallerCommandLineOptions extends CommandLineBuildBaseOptions {
1010
msi: string;
1111
exe: string;
1212
license: string;

Diff for: developer/src/kmc/src/commands/copy.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import { InfrastructureMessages } from '../messages/infrastructureMessages.js';
1010
import { BaseOptions } from '../util/baseOptions.js';
1111
import { exitProcess } from '../util/sysexits.js';
1212
import { CopierOptions, KeymanProjectCopier } from '@keymanapp/kmc-copy';
13+
import { commanderOptionsToBaseOptions } from '../util/extendedCompilerOptions.js';
1314

1415
/* c8 ignore start */
1516

1617
export function declareCopy(program: Command) {
1718
const command = program.command('copy <project>');
18-
BaseOptions.addLogLevel(command);
19+
BaseOptions.addAll(command);
1920
command
2021
.description('Copy a Keyman keyboard or lexical model project')
2122
.option('-o, --out-path <path>', 'New name and path for project')
@@ -35,6 +36,8 @@ export function declareCopy(program: Command) {
3536

3637
function commanderOptionsToCopierOptions(options: any): CopierOptions {
3738
const result: CopierOptions = {
39+
...commanderOptionsToBaseOptions(options),
40+
// CopierOptions
3841
outPath: options.outPath,
3942
dryRun: options.dryRun ?? false,
4043
relocateExternalFiles: options.relocateExternal ?? false,
@@ -46,15 +49,16 @@ const MaxDryRunCopyLogMessages = 10000;
4649

4750
async function copyProject(ids: string | string[], _options: any, commander: any): Promise<never|void> {
4851
const commanderOptions = commander.optsWithGlobals();
49-
const callbacks = new NodeCompilerCallbacks({logLevel: commanderOptions.logLevel ?? 'info'});
50-
if(!await doCopy(callbacks, ids, commanderOptions)) {
52+
const options = commanderOptionsToCopierOptions(commanderOptions);
53+
const callbacks = new NodeCompilerCallbacks(options);
54+
if(!await doCopy(callbacks, ids, options)) {
5155
return await exitProcess(1);
5256
}
5357
}
5458

5559
/* c8 ignore stop */
5660

57-
async function doCopy(callbacks: NodeCompilerCallbacks, sources: string | string[], commanderOptions: any): Promise<boolean> {
61+
async function doCopy(callbacks: NodeCompilerCallbacks, sources: string | string[], options: CopierOptions): Promise<boolean> {
5862
const source = sources;
5963

6064
if(!source || typeof source != 'string') {
@@ -64,8 +68,6 @@ async function doCopy(callbacks: NodeCompilerCallbacks, sources: string | string
6468
return false;
6569
}
6670

67-
const options = commanderOptionsToCopierOptions(commanderOptions);
68-
6971
if(options.dryRun) {
7072
// For dry run, we may need a lot of log messages, to show
7173
// where all the files are copied to

0 commit comments

Comments
 (0)