fix: Clean up list command output, adding --varCounts argument (#3)
This commit is contained in:
Родитель
b17f2217fa
Коммит
82066cd09d
157
cli.js
157
cli.js
|
@ -3,86 +3,84 @@
|
|||
import chalk from 'chalk'
|
||||
import { extname } from 'path'
|
||||
import yargs from 'yargs'
|
||||
import { forEachPropertiesFile, getInfo } from './lib/get-info.js'
|
||||
import { listPropertiesFiles } from './lib/list-properties-files.js'
|
||||
import { transformJs } from './lib/transform-js.js'
|
||||
import { transformProperties } from './lib/transform-properties.js'
|
||||
|
||||
yargs(process.argv.slice(2))
|
||||
.options({
|
||||
all: {
|
||||
alias: 'a',
|
||||
default: false,
|
||||
desc: 'When given a JS file, migrate all messages in .properties file',
|
||||
type: 'boolean'
|
||||
},
|
||||
attrDot: {
|
||||
alias: 'd',
|
||||
default: 'last',
|
||||
describe: 'Consider a dot in a property key to start an attribute name',
|
||||
choices: ['first', 'last', 'none']
|
||||
},
|
||||
bug: {
|
||||
alias: 'b',
|
||||
desc: 'Bugzilla bug id',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
exclude: {
|
||||
alias: 'e',
|
||||
default: [],
|
||||
desc: '.properties files to exclude; should match the file path end',
|
||||
requiresArg: true,
|
||||
type: 'array'
|
||||
},
|
||||
format: {
|
||||
alias: 'f',
|
||||
desc: "Command for Python code formatter. Set to '' to disable.",
|
||||
default: './mach lint --fix',
|
||||
type: 'string'
|
||||
},
|
||||
ftlPath: {
|
||||
alias: 'p',
|
||||
desc: 'Path to target FTL file',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
ftlPrefix: {
|
||||
alias: 'x',
|
||||
desc: 'Prefix for Fluent message keys',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
include: {
|
||||
alias: 'i',
|
||||
default: [],
|
||||
desc: '.properties files to include; should match the file path end',
|
||||
requiresArg: true,
|
||||
type: 'array'
|
||||
},
|
||||
'js-only': {
|
||||
alias: 'j',
|
||||
default: false,
|
||||
desc: 'Only migrate JS file',
|
||||
type: 'boolean'
|
||||
},
|
||||
root: {
|
||||
alias: 'r',
|
||||
desc: 'Root of mozilla-central (usually autodetected)',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
strict: {
|
||||
alias: 's',
|
||||
default: false,
|
||||
desc: 'In JS, require string literals matching message keys to be detected as known method arguments',
|
||||
type: 'boolean'
|
||||
}
|
||||
})
|
||||
|
||||
.command(
|
||||
'$0 <path>',
|
||||
'Convert files to use Fluent Localization rather than string bundles',
|
||||
{},
|
||||
{
|
||||
all: {
|
||||
alias: 'a',
|
||||
default: false,
|
||||
desc: 'When given a JS file, migrate all messages in .properties file',
|
||||
type: 'boolean'
|
||||
},
|
||||
attrDot: {
|
||||
alias: 'd',
|
||||
default: 'last',
|
||||
describe: 'Consider a dot in a property key to start an attribute name',
|
||||
choices: ['first', 'last', 'none']
|
||||
},
|
||||
bug: {
|
||||
alias: 'b',
|
||||
desc: 'Bugzilla bug id',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
exclude: {
|
||||
alias: 'e',
|
||||
default: [],
|
||||
desc: '.properties files to exclude; should match the file path end',
|
||||
requiresArg: true,
|
||||
type: 'array'
|
||||
},
|
||||
format: {
|
||||
alias: 'f',
|
||||
desc: "Command for Python code formatter. Set to '' to disable.",
|
||||
default: './mach lint --fix',
|
||||
type: 'string'
|
||||
},
|
||||
ftlPath: {
|
||||
alias: 'p',
|
||||
desc: 'Path to target FTL file',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
ftlPrefix: {
|
||||
alias: 'x',
|
||||
desc: 'Prefix for Fluent message keys',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
include: {
|
||||
alias: 'i',
|
||||
default: [],
|
||||
desc: '.properties files to include; should match the file path end',
|
||||
requiresArg: true,
|
||||
type: 'array'
|
||||
},
|
||||
'js-only': {
|
||||
alias: 'j',
|
||||
default: false,
|
||||
desc: 'Only migrate JS file',
|
||||
type: 'boolean'
|
||||
},
|
||||
root: {
|
||||
alias: 'r',
|
||||
desc: 'Root of mozilla-central (usually autodetected)',
|
||||
requiresArg: true,
|
||||
type: 'string'
|
||||
},
|
||||
strict: {
|
||||
alias: 's',
|
||||
default: false,
|
||||
desc: 'In JS, require string literals matching message keys to be detected as known method arguments',
|
||||
type: 'boolean'
|
||||
}
|
||||
},
|
||||
({ path, ...options }) =>
|
||||
extname(path) === '.properties'
|
||||
? transformProperties(path, options)
|
||||
|
@ -91,9 +89,16 @@ yargs(process.argv.slice(2))
|
|||
|
||||
.command(
|
||||
'list [filename..]',
|
||||
'Show information about .properties files',
|
||||
{},
|
||||
(args) => forEachPropertiesFile(args.filename, getInfo)
|
||||
'Show information about .properties files in the given files or directories.',
|
||||
{
|
||||
varCounts: {
|
||||
alias: 'c',
|
||||
default: false,
|
||||
desc: 'For each .properties file, list message counts by number of variables [no vars, 1 var, 2 vars, ...]',
|
||||
type: 'boolean'
|
||||
}
|
||||
},
|
||||
listPropertiesFiles
|
||||
)
|
||||
|
||||
.help()
|
||||
|
|
|
@ -2,34 +2,42 @@ import { parse } from 'dot-properties'
|
|||
import { readdir, readFile, stat } from 'fs/promises'
|
||||
import { relative, resolve } from 'path'
|
||||
|
||||
export async function getInfo(path) {
|
||||
const src = await readFile(path, 'utf8')
|
||||
const info = [0, 0, 0, 0]
|
||||
for (const msg of Object.values(parse(src))) {
|
||||
const m = msg.match(/%(\d\$)?|\$/g)
|
||||
const idx = m ? Math.min(m.length, 3) : 0
|
||||
info[idx] += 1
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
export async function forEachPropertiesFile(roots, cb) {
|
||||
for (const root of roots) {
|
||||
export async function listPropertiesFiles({ filename = ['.'], varCounts }) {
|
||||
for (const root of filename) {
|
||||
const path = resolve(root)
|
||||
const stats = await stat(path)
|
||||
if (stats.isFile()) {
|
||||
const res = await cb(path)
|
||||
if (res) console.log(relative('.', path), res)
|
||||
const relPath = relative('.', path)
|
||||
if (varCounts) console.log(relPath, await getInfo(path))
|
||||
else console.log(relPath)
|
||||
} else if (stats.isDirectory()) {
|
||||
console.log(relative('.', path))
|
||||
const relDir = relative('.', path) || '.'
|
||||
console.log(`${relDir}/`)
|
||||
for await (const pf of findPropertiesFiles(path)) {
|
||||
const res = await cb(pf)
|
||||
if (res) console.log(' ', relative(path, pf), res)
|
||||
const relPath = relative(path, pf)
|
||||
if (varCounts) console.log(' ', relPath, await getInfo(pf))
|
||||
else console.log(' ', relPath)
|
||||
}
|
||||
} else throw new Error(`Not a file or directory: ${path}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function getInfo(path) {
|
||||
const src = await readFile(path, 'utf8')
|
||||
const info = [0]
|
||||
for (const msg of Object.values(parse(src))) {
|
||||
const m = msg.match(/%(\d\$)?|\$/g)
|
||||
const varCount = m?.length ?? 0
|
||||
if (info.length < varCount + 1) {
|
||||
const prevLen = info.length
|
||||
info.length = varCount + 1
|
||||
info.fill(0, prevLen)
|
||||
}
|
||||
info[varCount] += 1
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
async function* findPropertiesFiles(root) {
|
||||
for (const ent of await readdir(root, { withFileTypes: true })) {
|
||||
if (ent.isDirectory()) {
|
Загрузка…
Ссылка в новой задаче