mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-31 07:40:33 +00:00
feat(cli): list commands (#4245)
* add listCommands to cli/run * add listCommands to cli/run (2) * lint * lint * lint * fix * fixes * fix * lint * maxCharsPerLine = process.stdout.columns * 80 / 100 * fix test * fix imports * refactor foldLines() * default process.stdout.columns to 80 * default to 80 * fix * fix test * lint * fix test * add help flags to main usage * fix * fix * fix
This commit is contained in:
parent
1dd32d0d21
commit
6dadadfa25
@ -1,12 +1,9 @@
|
||||
import parseArgs from 'minimist'
|
||||
import { name, version } from '../package.json'
|
||||
import { loadNuxtConfig, indent, foldLines } from './utils'
|
||||
import { loadNuxtConfig } from './utils'
|
||||
import { indent, foldLines, startSpaces, optionSpaces } from './formatting'
|
||||
import * as imports from './imports'
|
||||
|
||||
const startSpaces = 2
|
||||
const optionSpaces = 2
|
||||
const maxCharsPerLine = 80
|
||||
|
||||
export default class NuxtCommand {
|
||||
constructor({ name, description, usage, options, run } = {}) {
|
||||
this.name = name || ''
|
||||
@ -117,15 +114,14 @@ export default class NuxtCommand {
|
||||
const i = indent(maxOptionLength + optionSpaces - option.length)
|
||||
return foldLines(
|
||||
option + i + description,
|
||||
maxCharsPerLine,
|
||||
startSpaces + maxOptionLength + optionSpaces * 2,
|
||||
startSpaces + optionSpaces
|
||||
)
|
||||
}).join('\n')
|
||||
|
||||
const usage = foldLines(`Usage: nuxt ${this.usage} [options]`, maxCharsPerLine, startSpaces)
|
||||
const description = foldLines(this.description, maxCharsPerLine, startSpaces)
|
||||
const opts = foldLines(`Options:`, maxCharsPerLine, startSpaces) + '\n\n' + _opts
|
||||
const usage = foldLines(`Usage: nuxt ${this.usage} [options]`, startSpaces)
|
||||
const description = foldLines(this.description, startSpaces)
|
||||
const opts = foldLines(`Options:`, startSpaces) + '\n\n' + _opts
|
||||
|
||||
return `${usage}\n\n${description}\n\n${opts}\n\n`
|
||||
}
|
||||
|
29
packages/cli/src/formatting.js
Normal file
29
packages/cli/src/formatting.js
Normal file
@ -0,0 +1,29 @@
|
||||
import wrapAnsi from 'wrap-ansi'
|
||||
|
||||
export const startSpaces = 2
|
||||
export const optionSpaces = 2
|
||||
|
||||
// 80% of terminal column width
|
||||
export const maxCharsPerLine = (process.stdout.columns || 100) * 80 / 100
|
||||
|
||||
export function indent(count, chr = ' ') {
|
||||
return chr.repeat(count)
|
||||
}
|
||||
|
||||
export function indentLines(string, spaces, firstLineSpaces) {
|
||||
const lines = Array.isArray(string) ? string : string.split('\n')
|
||||
let s = ''
|
||||
if (lines.length) {
|
||||
const i0 = indent(firstLineSpaces === undefined ? spaces : firstLineSpaces)
|
||||
s = i0 + lines.shift()
|
||||
}
|
||||
if (lines.length) {
|
||||
const i = indent(spaces)
|
||||
s += '\n' + lines.map(l => i + l).join('\n')
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
export function foldLines(string, spaces, firstLineSpaces, maxCharsPerLine) {
|
||||
return indentLines(wrapAnsi(string, maxCharsPerLine, { trim: false }), spaces, firstLineSpaces)
|
||||
}
|
@ -2,6 +2,34 @@ import consola from 'consola'
|
||||
import NuxtCommand from './command'
|
||||
import * as commands from './commands'
|
||||
import setup from './setup'
|
||||
import { indent, foldLines, startSpaces, optionSpaces } from './formatting'
|
||||
|
||||
async function listCommands(_commands) {
|
||||
_commands = await Promise.all(
|
||||
Object.keys(_commands).map((cmd) => {
|
||||
return _commands[cmd]().then(m => m.default)
|
||||
})
|
||||
)
|
||||
let maxLength = 0
|
||||
const commandsHelp = []
|
||||
for (const name in _commands) {
|
||||
commandsHelp.push([_commands[name].usage, _commands[name].description])
|
||||
maxLength = Math.max(maxLength, _commands[name].usage.length)
|
||||
}
|
||||
|
||||
const _cmmds = commandsHelp.map(([cmd, description]) => {
|
||||
const i = indent(maxLength + optionSpaces - cmd.length)
|
||||
return foldLines(
|
||||
cmd + i + description,
|
||||
startSpaces + maxLength + optionSpaces * 2,
|
||||
startSpaces + optionSpaces
|
||||
)
|
||||
}).join('\n')
|
||||
|
||||
const usage = foldLines(`Usage: nuxt <command> [--help|-h]`, startSpaces)
|
||||
const cmmds = foldLines(`Commands:`, startSpaces) + '\n\n' + _cmmds
|
||||
process.stdout.write(`${usage}\n\n${cmmds}\n\n`)
|
||||
}
|
||||
|
||||
export default function run() {
|
||||
const defaultCommand = 'dev'
|
||||
@ -18,6 +46,10 @@ export default function run() {
|
||||
if (cmds.has(cmd)) {
|
||||
process.argv.splice(2, 1)
|
||||
} else {
|
||||
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
||||
listCommands({ ...commands }).then(() => process.exit(0))
|
||||
return
|
||||
}
|
||||
cmd = defaultCommand
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ import path from 'path'
|
||||
import { existsSync } from 'fs'
|
||||
import consola from 'consola'
|
||||
import esm from 'esm'
|
||||
import wrapAnsi from 'wrap-ansi'
|
||||
import defaultsDeep from 'lodash/defaultsDeep'
|
||||
import { getDefaultNuxtConfig } from '@nuxt/config'
|
||||
|
||||
@ -62,25 +61,3 @@ export async function loadNuxtConfig(argv) {
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
export function indent(count, chr = ' ') {
|
||||
return chr.repeat(count)
|
||||
}
|
||||
|
||||
export function indentLines(string, spaces, firstLineSpaces) {
|
||||
const lines = Array.isArray(string) ? string : string.split('\n')
|
||||
let s = ''
|
||||
if (lines.length) {
|
||||
const i0 = indent(firstLineSpaces === undefined ? spaces : firstLineSpaces)
|
||||
s = i0 + lines.shift().trim()
|
||||
}
|
||||
if (lines.length) {
|
||||
const i = indent(spaces)
|
||||
s += '\n' + lines.map(l => i + l.trim()).join('\n')
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
export function foldLines(string, maxCharsPerLine, spaces, firstLineSpaces) {
|
||||
return indentLines(wrapAnsi(string, maxCharsPerLine, { trim: false }), spaces, firstLineSpaces)
|
||||
}
|
||||
|
@ -3,8 +3,7 @@
|
||||
exports[`cli/command builds help text 1`] = `
|
||||
" Usage: nuxt this is how you do it [options]
|
||||
|
||||
a very long description that is longer than 80 chars and should wrap to the next
|
||||
line while keeping indentation
|
||||
a very long description that should not wrap to the next line because is not longer than the terminal width
|
||||
|
||||
Options:
|
||||
|
||||
@ -16,8 +15,7 @@ exports[`cli/command builds help text 1`] = `
|
||||
--port, -p Port number on which to start the application
|
||||
--hostname, -H Hostname on which to start the application
|
||||
--unix-socket, -n Path to a UNIX socket
|
||||
--foo very long option that is longer than 80 chars and should wrap
|
||||
to the next line while keeping indentation
|
||||
--foo very long option that is not longer than the terminal width and should not wrap to the next line
|
||||
|
||||
"
|
||||
`;
|
||||
|
@ -101,15 +101,15 @@ describe('cli/command', () => {
|
||||
|
||||
test('builds help text', () => {
|
||||
const cmd = new Command({
|
||||
description: 'a very long description that is longer than 80 chars and ' +
|
||||
'should wrap to the next line while keeping indentation',
|
||||
description: 'a very long description that should not wrap to the next line because is not longer ' +
|
||||
'than the terminal width',
|
||||
usage: 'this is how you do it',
|
||||
options: {
|
||||
...allOptions,
|
||||
foo: {
|
||||
type: 'boolean',
|
||||
description: 'very long option that is longer than 80 chars and ' +
|
||||
'should wrap to the next line while keeping indentation'
|
||||
description: 'very long option that is not longer than the terminal width and ' +
|
||||
'should not wrap to the next line'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { getDefaultNuxtConfig } from '@nuxt/config'
|
||||
import { consola } from '../utils'
|
||||
import * as utils from '../../src/utils'
|
||||
import * as fmt from '../../src/formatting'
|
||||
|
||||
describe('cli/utils', () => {
|
||||
afterEach(() => jest.resetAllMocks())
|
||||
@ -96,10 +97,10 @@ describe('cli/utils', () => {
|
||||
})
|
||||
|
||||
test('indent', () => {
|
||||
expect(utils.indent(4)).toBe(' ')
|
||||
expect(fmt.indent(4)).toBe(' ')
|
||||
})
|
||||
|
||||
test('indent custom char', () => {
|
||||
expect(utils.indent(4, '-')).toBe('----')
|
||||
expect(fmt.indent(4, '-')).toBe('----')
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user