Skip to content

Commit

Permalink
fix: support automatic creation of cspell-tools.config.yaml (#4631)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Jul 13, 2023
1 parent f8ad3c8 commit f9fea67
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 13 deletions.
3 changes: 2 additions & 1 deletion packages/cspell-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
"cspell-trie-lib": "workspace:*",
"gensequence": "^5.0.2",
"glob": "^10.3.3",
"hunspell-reader": "workspace:*"
"hunspell-reader": "workspace:*",
"yaml": "^2.3.1"
},
"engines": {
"node": ">=16"
Expand Down
5 changes: 4 additions & 1 deletion packages/cspell-tools/src/AppOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ export interface CompileCommonAppOptions {
max_depth?: string;
maxDepth?: string;
merge?: string;
experimental: string[];
experimental?: string[];
split?: boolean;
sort?: boolean;
keepRawCase?: boolean;
trie?: boolean;
trie3?: boolean;
trie4?: boolean;
trieBase?: string;
listFile?: string[];
useLegacySplitter?: boolean;
/** Indicate that a config file should be created instead of building. */
init?: boolean;
}
export interface CompileAppOptions extends CompileCommonAppOptions {
sort: boolean;
Expand Down
14 changes: 11 additions & 3 deletions packages/cspell-tools/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ function addCompileOptions(compileCommand: program.Command): program.Command {
)
.option('--trie3', 'Use file format trie3', false)
.option('--trie4', 'Use file format trie4', false)
.option('--trie-base <number>', 'Advanced: Set the trie base number. A value between 10 and 36');
.option('--trie-base <number>', 'Advanced: Set the trie base number. A value between 10 and 36')
.option(
'--list-file <filename...>',
'Path to a file that contains the list of files to compile. A list file contains one file per line.'
)
.option(
'--init',
'Create a build command `cspell-tools.config.yaml` file based upon the options given instead of building.'
);
}

interface ShasumOptions {
Expand Down Expand Up @@ -77,7 +85,7 @@ export async function run(program: program.Command, argv: string[], flags?: Feat

program.version(npmPackage.version);

addCompileOptions(program.command('compile <src...>').description('Compile words into a cspell dictionary files.'))
addCompileOptions(program.command('compile [src...]').description('Compile words into a cspell dictionary files.'))
.option('--trie', 'Compile into a trie file.', false)
.option('--no-sort', 'Do not sort the result')
.action((src: string[], options: CompileAppOptions) => {
Expand All @@ -86,7 +94,7 @@ export async function run(program: program.Command, argv: string[], flags?: Feat

addCompileOptions(
program
.command('compile-trie <src...>')
.command('compile-trie [src...]')
.description(
'Compile words lists or Hunspell dictionary into trie files used by cspell.\nAlias of `compile --trie`'
)
Expand Down
38 changes: 38 additions & 0 deletions packages/cspell-tools/src/compile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { writeFile } from 'node:fs/promises';

import { describe, expect, test, vi } from 'vitest';

import { processCompileAction } from './compile.js';

vi.mock('node:fs/promises', () => ({
writeFile: vi.fn().mockImplementation(() => Promise.resolve(undefined)),
}));

const mockWriteFile = vi.mocked(writeFile);

vi.spyOn(console, 'log').mockImplementation(() => undefined);

describe('compile', () => {
test('--init option', async () => {
const options = {
compress: true,
sort: true,
merge: 'public-licenses',
output: '.',
listFile: ['source-files.txt'],
init: true,
};
const expected = `\
targets:
- name: public-licenses
targetDirectory: .
compress: true
format: plaintext
sources:
- listFile: source-files.txt
sort: true
`;
await processCompileAction([], options, undefined);
expect(mockWriteFile).toHaveBeenLastCalledWith('cspell-tools.config.yaml', expected);
});
});
28 changes: 25 additions & 3 deletions packages/cspell-tools/src/compile.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
import { writeFile } from 'node:fs/promises';

import { opConcatMap, pipe } from '@cspell/cspell-pipe/sync';
import YAML from 'yaml';

import type { CompileCommonAppOptions } from './AppOptions.js';
import { compile } from './compiler/compile.js';
import { createCompileRequest } from './compiler/createCompileRequest.js';
import type { CompileRequest } from './config/config.js';
import type { FeatureFlags } from './FeatureFlags/index.js';
import { getSystemFeatureFlags, parseFlags } from './FeatureFlags/index.js';
import { globP } from './util/globP.js';

getSystemFeatureFlags().register('compound', 'Enable compound dictionary sources.');

const defaultConfigFile = 'cspell-tools.config.yaml';

export async function processCompileAction(
src: string[],
options: CompileCommonAppOptions,
featureFlags: FeatureFlags | undefined
): Promise<void> {
const ff = featureFlags || getSystemFeatureFlags();
parseFlags(ff, options.experimental);
parseFlags(ff, options.experimental || []);
return useCompile(src, options);
}

async function useCompile(src: string[], options: CompileCommonAppOptions): Promise<void> {
console.log(
'Compile:\n output: %s\n compress: %s\n files:\n %s \n\n',
'Compile:\n output: %s\n compress: %s\n files:\n %s ',
options.output || 'default',
options.compress ? 'true' : 'false',
src.join('\n ')
);
if (options.listFile && options.listFile.length) {
console.log(' list files:\n %s', options.listFile.join('\n '));
}
console.log('\n\n');

const globResults = await Promise.all(src.map((s) => globP(s)));
const sources = [
Expand All @@ -35,5 +45,17 @@ async function useCompile(src: string[], options: CompileCommonAppOptions): Prom
),
];

return compile(createCompileRequest(sources, options));
const request = createCompileRequest(sources, options);
return options.init ? initConfig(request) : compile(request);
}

async function initConfig(request: CompileRequest): Promise<void> {
const content = YAML.stringify(request, null, 2);
console.log('Writing config file: %s', defaultConfigFile);
await writeFile(defaultConfigFile, content);

console.log(`Init complete.
To build, use:
cspell-tools-cli build
`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,57 @@ exports[`createCompileRequest > createCompileRequest 4`] = `
],
}
`;

exports[`createCompileRequest > createCompileRequest 5`] = `
{
"targets": [
{
"compress": false,
"format": "plaintext",
"name": "python-sources",
"sources": [
{
"listFile": "python-sources.txt",
},
],
"targetDirectory": ".",
},
],
}
`;

exports[`createCompileRequest > createCompileRequest 6`] = `
{
"targets": [
{
"compress": false,
"format": "plaintext",
"name": "python-sources",
"sources": [
{
"listFile": "python-sources.txt",
},
],
"targetDirectory": "python",
},
],
}
`;

exports[`createCompileRequest > createCompileRequest 7`] = `
{
"targets": [
{
"compress": false,
"format": "plaintext",
"name": "python",
"sources": [
{
"listFile": "python-sources.txt",
},
],
"targetDirectory": ".",
},
],
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ describe('createCompileRequest', () => {
${['src/words.txt']} | ${comp()}
${['src/words.txt', 'src/cities.txt']} | ${comp({ output: 'out' })}
${['src/words.txt', 'src/cities.txt']} | ${comp({ output: 'out', merge: 'combo' })}
${[]} | ${comp({ listFile: ['python-sources.txt'] })}
${[]} | ${comp({ listFile: ['python-sources.txt'], output: 'python' })}
${[]} | ${comp({ listFile: ['python-sources.txt'], merge: 'python' })}
`('createCompileRequest', ({ source, options }) => {
const req = createCompileRequest(source, options);
// Make sure the test passes on Windows.
Expand Down
18 changes: 14 additions & 4 deletions packages/cspell-tools/src/compiler/createCompileRequest.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import * as path from 'path';

import type { CompileCommonAppOptions } from '../AppOptions.js';
import type { CompileRequest, DictionaryFormats, Target } from '../config/index.js';
import type { CompileRequest, DictionaryFormats, DictionarySource, FileSource, Target } from '../config/index.js';

export function createCompileRequest(sources: string[], options: CompileCommonAppOptions): CompileRequest {
export function createCompileRequest(sourceFiles: string[], options: CompileCommonAppOptions): CompileRequest {
const { max_depth, maxDepth, experimental = [], split, keepRawCase, useLegacySplitter } = options;

const sources: DictionarySource[] = [...sourceFiles, ...(options.listFile || []).map((listFile) => ({ listFile }))];

const targets = calcTargets(sources, options);
const generateNonStrict = experimental.includes('compound') || undefined;

Expand All @@ -23,7 +25,7 @@ export function createCompileRequest(sources: string[], options: CompileCommonAp

return req;
}
function calcTargets(sources: string[], options: CompileCommonAppOptions): Target[] {
function calcTargets(sources: DictionarySource[], options: CompileCommonAppOptions): Target[] {
const { merge, output = '.' } = options;

const format = calcFormat(options);
Expand All @@ -42,7 +44,7 @@ function calcTargets(sources: string[], options: CompileCommonAppOptions): Targe
}

const targets: Target[] = sources.map((source) => {
const name = toTargetName(path.basename(source));
const name = toTargetName(baseNameOfSource(source));
const target: Target = {
name,
targetDirectory: output,
Expand All @@ -69,3 +71,11 @@ function parseNumber(s: string | undefined): number | undefined {
const n = parseInt(s ?? '');
return isNaN(n) ? undefined : n;
}

function baseNameOfSource(source: DictionarySource): string {
return typeof source === 'string' ? source : isFileSource(source) ? source.filename : source.listFile;
}

function isFileSource(source: DictionarySource): source is FileSource {
return typeof source !== 'string' && (<FileSource>source).filename !== undefined;
}
5 changes: 4 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f9fea67

Please sign in to comment.