mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 19:40:11 +08:00
refactor: separate matchers
This commit is contained in:
1 parent
8280f7073d
commit
e83d913852
10 files changed
+114
-92
No files matched your search
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "@linux-odyssey/game",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "dist/index.ts",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc -b"
|
||||||
|
},
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/* eslint-disable max-classes-per-file */
|
|
||||||
import { Command } from './command'
|
|
||||||
import { Matcher } from './matcher'
|
|
||||||
|
|
||||||
export class CommandMatcher implements Matcher {
|
|
||||||
private matcher: RegExp
|
|
||||||
constructor(pattern: string, args?: string) {
|
|
||||||
this.matcher = new RegExp(pattern, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
match(command: Partial<Command>): boolean {
|
|
||||||
return !!command.command && this.matcher.test(command.command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ErrorMatcher implements Matcher {
|
|
||||||
private matcher?: RegExp
|
|
||||||
constructor(errorPattern?: string) {
|
|
||||||
if (errorPattern) {
|
|
||||||
this.matcher = new RegExp(errorPattern)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match(command: Partial<Command>): boolean {
|
|
||||||
if (!this.matcher) {
|
|
||||||
return !command.error
|
|
||||||
}
|
|
||||||
return this.matcher.test(command.error || '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PwdMatcher implements Matcher {
|
|
||||||
constructor(private pwd: string) {}
|
|
||||||
|
|
||||||
match(command: Partial<Command>): boolean {
|
|
||||||
return command.pwd === this.pwd
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OutputMatcher implements Matcher {
|
|
||||||
private matcher: RegExp
|
|
||||||
constructor(pattern: string, args?: string) {
|
|
||||||
this.matcher = new RegExp(pattern, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
match(command: Partial<Command>): boolean {
|
|
||||||
return !!command.output && this.matcher.test(command.output.trim())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ICondition {
|
|
||||||
command?: string
|
|
||||||
output?: string
|
|
||||||
error?: string
|
|
||||||
pwd?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Condition {
|
|
||||||
private matchers: Matcher[] = []
|
|
||||||
|
|
||||||
constructor({ command, output, error, pwd }: ICondition) {
|
|
||||||
if (command) this.matchers.push(new CommandMatcher(command))
|
|
||||||
if (output) this.matchers.push(new OutputMatcher(output))
|
|
||||||
if (pwd) this.matchers.push(new PwdMatcher(pwd))
|
|
||||||
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
|
|
||||||
}
|
|
||||||
|
|
||||||
match(command: Partial<Command>): boolean {
|
|
||||||
return this.matchers.every((matcher) => {
|
|
||||||
return matcher.match(command)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Command } from '../command.js'
|
||||||
|
import { Matcher } from './matcher.js'
|
||||||
|
|
||||||
|
export class CommandMatcher implements Matcher {
|
||||||
|
private matcher: RegExp
|
||||||
|
constructor(command: string, flags?: string) {
|
||||||
|
this.matcher = new RegExp(command, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
match(command: Partial<Command>): boolean {
|
||||||
|
return !!command.command && this.matcher.test(command.command)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Command } from '../command.js'
|
||||||
|
import { PwdMatcher } from './pwdMatcher.js'
|
||||||
|
import { CommandMatcher } from './commandMatcher.js'
|
||||||
|
import { ErrorMatcher } from './errorMatcher.js'
|
||||||
|
import { Matcher } from './matcher.js'
|
||||||
|
import { OutputMatcher } from './outputMatcher.js'
|
||||||
|
|
||||||
|
export interface ICondition {
|
||||||
|
command?: string
|
||||||
|
output?: string
|
||||||
|
error?: string
|
||||||
|
pwd?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Condition {
|
||||||
|
private matchers: Matcher[] = []
|
||||||
|
|
||||||
|
constructor({ command, output, error, pwd }: ICondition) {
|
||||||
|
if (command) this.matchers.push(new CommandMatcher(command))
|
||||||
|
if (output) this.matchers.push(new OutputMatcher(output))
|
||||||
|
if (pwd) this.matchers.push(new PwdMatcher(pwd))
|
||||||
|
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
|
||||||
|
}
|
||||||
|
|
||||||
|
match(command: Partial<Command>): boolean {
|
||||||
|
return this.matchers.every((matcher) => {
|
||||||
|
return matcher.match(command)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Matcher } from './matcher.js'
|
||||||
|
import { Command } from '../command.js'
|
||||||
|
|
||||||
|
export class ErrorMatcher implements Matcher {
|
||||||
|
private matcher?: RegExp
|
||||||
|
constructor(errorPattern?: string) {
|
||||||
|
if (errorPattern) {
|
||||||
|
this.matcher = new RegExp(errorPattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match(command: Partial<Command>): boolean {
|
||||||
|
if (!this.matcher) {
|
||||||
|
return !command.error
|
||||||
|
}
|
||||||
|
return this.matcher.test(command.error || '')
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Command } from './command'
|
import { Command } from '../command.js'
|
||||||
|
|
||||||
export interface Matcher {
|
export interface Matcher {
|
||||||
match(command: Partial<Command>): boolean
|
match(command: Partial<Command>): boolean
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Command } from '../command.js'
|
||||||
|
import { Matcher } from './matcher.js'
|
||||||
|
|
||||||
|
export class OutputMatcher implements Matcher {
|
||||||
|
private matcher: RegExp
|
||||||
|
constructor(pattern: string, args?: string) {
|
||||||
|
this.matcher = new RegExp(pattern, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
match(command: Partial<Command>): boolean {
|
||||||
|
return !!command.output && this.matcher.test(command.output.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Command } from '../command.js'
|
||||||
|
import { Matcher } from './matcher.js'
|
||||||
|
|
||||||
|
export class PwdMatcher implements Matcher {
|
||||||
|
constructor(private pwd: string) {}
|
||||||
|
|
||||||
|
match(command: Partial<Command>): boolean {
|
||||||
|
return command.pwd === this.pwd
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,16 @@
|
|||||||
import { test, expect } from '@jest/globals'
|
import { test, expect } from '@jest/globals'
|
||||||
import {
|
import { Condition } from '../src/condition/condition'
|
||||||
CommandMatcher,
|
import { OutputMatcher } from '../src/condition/outputMatcher'
|
||||||
ErrorMatcher,
|
import { PwdMatcher } from '../src/condition/pwdMatcher'
|
||||||
PwdMatcher,
|
import { CommandMatcher } from '../src/condition/commandMatcher'
|
||||||
OutputMatcher,
|
import { ErrorMatcher } from '../src/condition/errorMatcher.js'
|
||||||
Condition,
|
|
||||||
} from '../src/condition'
|
|
||||||
import { Command } from '../src/command'
|
|
||||||
|
|
||||||
test('command match', () => {
|
test('command match', () => {
|
||||||
const command: Command = {
|
const matcher = new CommandMatcher('^echo start$')
|
||||||
command: 'echo start',
|
expect(matcher.match({ command: 'echo start' })).toBe(true)
|
||||||
output: 'start',
|
expect(matcher.match({ command: 'echo start1' })).toBe(false)
|
||||||
error: '',
|
// Currently not supported
|
||||||
pwd: '/home/user',
|
expect(matcher.match({ command: 'echo "start"' })).toBe(false)
|
||||||
}
|
|
||||||
|
|
||||||
const matcher = new CommandMatcher('^echo start$', 'i')
|
|
||||||
expect(matcher.match(command)).toBe(true)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('error matcher', () => {
|
test('error matcher', () => {
|
||||||
@@ -50,7 +43,7 @@ test('output matcher', () => {
|
|||||||
expect(matcher.match({ output: 'start\n' })).toBe(true)
|
expect(matcher.match({ output: 'start\n' })).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('condition match', () => {
|
test('condition match command', () => {
|
||||||
const condition = new Condition({
|
const condition = new Condition({
|
||||||
command: '^echo start$',
|
command: '^echo start$',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
Reference in new issue
Block a user