1
1
mirror of https://github.com/theoludwig/programming-challenges.git synced 2024-12-08 00:45:29 +01:00

feat(cli): add commands/search

This commit is contained in:
Divlo 2023-01-05 18:29:07 +01:00
parent 70564f174a
commit c8a7a6dcd4
No known key found for this signature in database
GPG Key ID: 8F9478F220CE65E9
3 changed files with 73 additions and 2 deletions

View File

@ -4,6 +4,7 @@ import { GenerateChallengeCommand } from './commands/generate/challenge.js'
import { GenerateSolutionCommand } from './commands/generate/solution.js' import { GenerateSolutionCommand } from './commands/generate/solution.js'
import { RunSolutionCommand } from './commands/run/solution.js' import { RunSolutionCommand } from './commands/run/solution.js'
import { RunTestCommand } from './commands/run/test.js' import { RunTestCommand } from './commands/run/test.js'
import { SearchCommand } from './commands/search/index.js'
export const cli = new Cli({ export const cli = new Cli({
binaryLabel: 'programming-challenges', binaryLabel: 'programming-challenges',
@ -16,3 +17,4 @@ cli.register(GenerateChallengeCommand)
cli.register(GenerateSolutionCommand) cli.register(GenerateSolutionCommand)
cli.register(RunTestCommand) cli.register(RunTestCommand)
cli.register(RunSolutionCommand) cli.register(RunSolutionCommand)
cli.register(SearchCommand)

View File

@ -0,0 +1,61 @@
import path from 'node:path'
import fs from 'node:fs'
import { Command, Option } from 'clipanion'
import * as typanion from 'typanion'
import chalk from 'chalk'
import { template } from '../../services/Template.js'
import { Challenge } from '../../services/Challenge.js'
export class SearchCommand extends Command {
static paths = [['search']]
static usage = {
description: 'Search challenges in the programming language specified.'
}
public solved = Option.Boolean('--solved', false, {
description:
'Challenges which have already been solved (at least with one solution).'
})
public programmingLanguage = Option.String('--language', {
description: 'The programming language used to solve the challenge.',
required: true,
validator: typanion.isString()
})
async execute(): Promise<number> {
try {
await template.verifySupportedProgrammingLanguage(
this.programmingLanguage
)
const challenges = await Challenge.getChallenges()
const challengesResult: Challenge[] = []
for (const challenge of challenges) {
const solutionsPath = path.join(challenge.path, 'solutions')
const solutions = await fs.promises.readdir(solutionsPath)
if (
(!this.solved && !solutions.includes(this.programmingLanguage)) ||
(this.solved && solutions.includes(this.programmingLanguage))
) {
challengesResult.push(challenge)
}
}
const message = this.solved
? 'Challenges already solved'
: 'Challenges not yet solved'
console.log(`${message} in ${chalk.bold(this.programmingLanguage)}:`)
for (const challenge of challengesResult) {
console.log(` - ${challenge.name}`)
}
return 0
} catch (error) {
if (error instanceof Error) {
console.error(`${chalk.bold.red('Error:')} ${error.message}`)
}
return 1
}
}
}

View File

@ -15,6 +15,7 @@ export interface GenerateChallengeOptions extends ChallengeOptions {
} }
export class Challenge implements ChallengeOptions { export class Challenge implements ChallengeOptions {
public static BASE_URL = new URL('../../challenges/', import.meta.url)
public name: string public name: string
public path: string public path: string
@ -22,11 +23,18 @@ export class Challenge implements ChallengeOptions {
const { name } = options const { name } = options
this.name = name this.name = name
this.path = fileURLToPath( this.path = fileURLToPath(
new URL(`../../challenges/${name}`, import.meta.url) new URL(`./${name}`, Challenge.BASE_URL)
) )
} }
static async generate(options: GenerateChallengeOptions): Promise<Challenge> { public static async getChallenges(): Promise<Challenge[]> {
const challengeNames = await fs.promises.readdir( Challenge.BASE_URL)
return challengeNames.map((challengeName) => {
return new Challenge({ name: challengeName })
})
}
public static async generate(options: GenerateChallengeOptions): Promise<Challenge> {
const { name, githubUser } = options const { name, githubUser } = options
const challenge = new Challenge({ name }) const challenge = new Challenge({ name })
if (await isExistingPath(challenge.path)) { if (await isExistingPath(challenge.path)) {