Files
pnpm/completion/plugin-commands-completion/src/complete.ts
Khải 004addf63e feat(completion): print completion code to stdout (#7597)
* feat(completion): generate-completion

close #3083

* feat: better error message

* test: generate-completion

* feat(completion): add powershell

* chore(deps): update @pnpm/tabtab to 0.3.0

* switch to provided type declarations
* fix typings
* update tests
* update bundle scripts

* refactor: remove unnecessary `??`

* refactor: replace a type def with provided types

* chore(deps): update @pnpm/tabtab to 0.4.0

* feat(cli): rename completion command

* chore(deps): update @pnpm/tabtab to 0.4.1

* refactor: use tabtab's new features

* fix: pass shell

* chore(deps): update @pnpm/tabtab to 0.5.0

* chore(deps): update @pnpm/tabtab to 0.5.1

* fix: remove unused import

* refactor: move completion to plugins

* feat: remove `{install,uninstall}-completion`

Just `pnpm completion` is enough

* test: fix

* refactor: direct import

* refactor: move tests to next to the lib

* refactor: merge 2 packages into 1

* fix: update changeset and remove install-completion
2024-02-06 23:18:17 +01:00

86 lines
2.9 KiB
TypeScript

import { type CompletionItem } from '@pnpm/tabtab'
import { type CompletionFunc } from '@pnpm/command'
import { findWorkspaceDir } from '@pnpm/find-workspace-dir'
import { findWorkspacePackages } from '@pnpm/workspace.find-packages'
import { getOptionCompletions } from './getOptionType'
import { optionTypesToCompletions } from './optionTypesToCompletions'
export async function complete (
ctx: {
cliOptionsTypesByCommandName: Record<string, () => Record<string, unknown>>
completionByCommandName: Record<string, CompletionFunc>
initialCompletion: () => CompletionItem[]
shorthandsByCommandName: Record<string, Record<string, string | string[]>>
universalOptionsTypes: Record<string, unknown>
universalShorthands: Record<string, string>
},
input: {
params: string[]
cmd: string | null
currentTypedWordType: 'option' | 'value' | null
lastOption: string | null
options: Record<string, unknown>
}
): Promise<CompletionItem[]> {
if (input.options.version) return []
const optionTypes = {
...ctx.universalOptionsTypes,
...((input.cmd && ctx.cliOptionsTypesByCommandName[input.cmd]?.()) ?? {}),
}
// Autocompleting option values
if (input.currentTypedWordType !== 'option') {
if (input.lastOption === '--filter') {
const workspaceDir = await findWorkspaceDir(process.cwd()) ?? process.cwd()
const allProjects = await findWorkspacePackages(workspaceDir, {
supportedArchitectures: {
os: ['current'],
cpu: ['current'],
libc: ['current'],
},
})
return allProjects
.map(({ manifest }) => ({ name: manifest.name }))
.filter((item): item is CompletionItem => !!item.name)
} else if (input.lastOption) {
const optionCompletions = getOptionCompletions(
optionTypes as any, // eslint-disable-line
{
...ctx.universalShorthands,
...(input.cmd ? ctx.shorthandsByCommandName[input.cmd] : {}),
},
input.lastOption
)
if (optionCompletions !== undefined) {
return optionCompletions.map((name) => ({ name }))
}
}
}
let completions: CompletionItem[] = []
if (input.currentTypedWordType !== 'option') {
if (!input.cmd || input.currentTypedWordType === 'value' && !ctx.completionByCommandName[input.cmd]) {
completions = ctx.initialCompletion()
} else if (ctx.completionByCommandName[input.cmd]) {
try {
completions = await ctx.completionByCommandName[input.cmd](input.options, input.params)
} catch (err) {
// Ignore
}
}
}
if (input.currentTypedWordType === 'value') {
return completions
}
if (!input.cmd) {
return [
...completions,
...optionTypesToCompletions(optionTypes),
{ name: '--version' },
]
}
return [
...completions,
...optionTypesToCompletions(optionTypes as any), // eslint-disable-line
]
}