Skip to content

Commit

Permalink
feat: POC for allowing flexible command taxonomy
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Feb 16, 2022
1 parent a58315d commit c602ddd
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
21 changes: 18 additions & 3 deletions src/config/config.ts
Expand Up @@ -8,9 +8,8 @@ import {format} from 'util'
import {Options, Plugin as IPlugin} from '../interfaces/plugin'
import {Config as IConfig, ArchTypes, PlatformTypes, LoadOptions} from '../interfaces/config'
import {Command, Hook, Hooks, PJSON, Topic} from '../interfaces'
import {Debug} from './util'
import * as Plugin from './plugin'
import {compact, flatMap, loadJSON, uniq} from './util'
import {Debug, compact, flatMap, loadJSON, uniq, permutations} from './util'
import {isProd} from '../util'
import ModuleLoader from '../module-loader'

Expand Down Expand Up @@ -81,6 +80,8 @@ export class Config implements IConfig {

topicSeparator: ':' | ' ' = ':'

flexibleTaxonomy!: boolean

protected warned = false

private _commands?: Command.Plugin[]
Expand Down Expand Up @@ -122,6 +123,7 @@ export class Config implements IConfig {
this.windows = this.platform === 'win32'
this.bin = this.pjson.oclif.bin || this.name
this.dirname = this.pjson.oclif.dirname || this.name
this.flexibleTaxonomy = this.pjson.oclif.flexibleTaxonomy || false
// currently, only colons or spaces are valid separators
if (this.pjson.oclif.topicSeparator && [':', ' '].includes(this.pjson.oclif.topicSeparator)) this.topicSeparator = this.pjson.oclif.topicSeparator!
if (this.platform === 'win32') this.dirname = this.dirname.replace('/', '\\')
Expand Down Expand Up @@ -383,7 +385,20 @@ export class Config implements IConfig {

get commands(): Command.Plugin[] {
if (this._commands) return this._commands
this._commands = flatMap(this.plugins, p => p.commands)
if (this.flexibleTaxonomy) {
const commands = flatMap(this.plugins, p => p.commands)
this._commands = [...commands]
for (const cmd of commands) {
const parts = cmd.id.split(':')
const combos = permutations(parts).flatMap(c => c.join(':'))
for (const combo of combos) {
this._commands.push({...cmd, id: combo})
}
}
} else {
this._commands = flatMap(this.plugins, p => p.commands)
}

return this._commands
}

Expand Down
24 changes: 24 additions & 0 deletions src/config/util.ts
Expand Up @@ -61,3 +61,27 @@ export function Debug(...scope: string[]): (..._: any) => void {
if (d.enabled) displayWarnings()
return (...args: any[]) => d(...args)
}

// Adapted from https://github.com/angus-c/just/blob/master/packages/array-permutations/index.js
export function permutations(arr: string[]): Array<string[]> {
if (arr.length === 0) return []
if (arr.length === 1) return [arr]

const output = []
const partialPermutations = permutations(arr.slice(1))
const first = arr[0]

for (let i = 0, len = partialPermutations.length; i < len; i++) {
const partial = partialPermutations[i]

for (let j = 0, len2 = partial.length; j <= len2; j++) {
const start = partial.slice(0, j)
const end = partial.slice(j)
const merged = start.concat(first, end)

output.push(merged)
}
}

return output
}
1 change: 1 addition & 0 deletions src/interfaces/pjson.ts
Expand Up @@ -16,6 +16,7 @@ export namespace PJSON {
schema?: number;
description?: string;
topicSeparator?: ':' | ' ';
flexibleTaxonomy?: boolean;
hooks?: { [name: string]: (string | string[]) };
commands?: string;
default?: string;
Expand Down

0 comments on commit c602ddd

Please sign in to comment.