Fix regexp filtering errors

This commit is contained in:
IRBorisov 2023-10-04 18:46:52 +03:00
parent ce513eeb90
commit 09c95cb81f
8 changed files with 52 additions and 21 deletions

View File

@ -1,5 +1,7 @@
// Module: Schema library models.
import { TextMatcher } from '../utils/utils'
// ========= Users ===========
export interface IUser {
id: number | null
@ -53,13 +55,7 @@ export interface ILibraryUpdateData
// ============= API ===============
export function matchLibraryItem(query: string, target: ILibraryItem): boolean {
const queryI = query.toUpperCase()
if (target.alias.toUpperCase().match(queryI)) {
return true
} else if (target.title.toUpperCase().match(queryI)) {
return true
} else {
return false
}
const matcher = new TextMatcher(query);
return matcher.test(target.alias) || matcher.test(target.title);
}

View File

@ -1,4 +1,5 @@
import { Graph } from '../utils/Graph'
import { TextMatcher } from '../utils/utils'
import { ILibraryUpdateData } from './library'
import { ILibraryItem } from './library'
import { CstMatchMode } from './miscelanious'
@ -215,21 +216,22 @@ export function loadRSFormData(schema: IRSFormData): IRSForm {
return result;
}
export function matchConstituenta(query: string, target: IConstituenta, mode: CstMatchMode) {
export function matchConstituenta(query: string, target: IConstituenta, mode: CstMatchMode): boolean {
const matcher = new TextMatcher(query);
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
target.alias.match(query)) {
matcher.test(target.alias)) {
return true;
}
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TERM) &&
target.term_resolved.match(query)) {
matcher.test(target.term_resolved)) {
return true;
}
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.EXPR) &&
target.definition_formal.match(query)) {
matcher.test(target.definition_formal)) {
return true;
}
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TEXT)) {
return (target.definition_resolved.match(query) || target.convention.match(query));
return (matcher.test(target.definition_resolved) || matcher.test(target.convention));
}
return false;
}

View File

@ -166,6 +166,7 @@ export enum TokenID {
}
export enum RSErrorType {
unknownSymbol = 33283,
syntax = 33792,
missingParanthesis = 33798,
missingCurlyBrace = 33799,

View File

@ -74,6 +74,7 @@ function DlgCreateCst({ hideWindow, initial, onCreate }: DlgCreateCstProps) {
onChange={event => setTerm(event.target.value)}
/>
<RSInput id='expression' label='Формальное выражение'
placeholder='Родоструктурное выражение, задающее формальное определение'
editable
height='5.5rem'
value={expression}

View File

@ -240,7 +240,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
spellCheck
/>
<div className='text-sm mt-4 mb-2 font-semibold'>
<div className='mt-4 mb-2 text-sm font-semibold'>
Параметры словоформы
</div>
@ -283,7 +283,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
/>
</div>
<div className='flex flex-start justify-between'>
<div className='flex justify-between flex-start'>
<div className='flex items-center justify-start'>
<MiniButton
tooltip='Внести словоформу'
@ -304,7 +304,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
onClick={handleGenerateLexeme}
/>
</div>
<div className='text-sm mt-2 mb-1 font-semibold w-full text-center'>
<div className='w-full mt-2 mb-1 text-sm font-semibold text-center'>
Заданные вручную словоформы: [{forms.length}]
</div>
<MiniButton

View File

@ -92,6 +92,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
filtered = applyGraphFilter(schema, activeID, filterSource);
}
if (filterText) {
console.log(filterText);
filtered = filtered.filter((cst) => matchConstituenta(filterText, cst, filterMatch));
}
setFilteredData(filtered);
@ -141,9 +142,9 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
columnHelper.accessor(cst => describeConstituenta(cst), {
id: 'description',
header: 'Описание',
size: 500,
size: 1000,
minSize: 350,
maxSize: 500,
maxSize: 1000,
cell: props =>
<div style={{
fontSize: 12,
@ -155,9 +156,9 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
columnHelper.accessor('definition_formal', {
id: 'expression',
header: 'Выражение',
size: 1000,
size: 2000,
minSize: 0,
maxSize: 1000,
maxSize: 2000,
enableHiding: true,
cell: props =>
<div style={{

View File

@ -438,6 +438,8 @@ export function labelGrammeme(gram: GramData): string {
export function describeRSError(error: IRSErrorDescription): string {
switch (error.errorType) {
case RSErrorType.unknownSymbol:
return `Неизвестный символ: ${error.params[0]}`;
case RSErrorType.syntax:
return 'Неопределенная синтаксическая ошибка';
case RSErrorType.missingParanthesis:

View File

@ -15,3 +15,31 @@ export function trimString(target: string, maxLen: number): string {
return target.substring(0, maxLen) + '...';
}
}
/**
* Wrapper class for generalized text matching.
*
* If possible create regexp, otherwise use symbol matching.
*/
export class TextMatcher {
protected query: RegExp | string
constructor(query: string, isPlainText?: boolean, isCaseSensitive?: boolean) {
if (isPlainText) {
query = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
try {
this.query = new RegExp(query, isCaseSensitive ? '' : 'i');
} catch(exception: unknown) {
this.query = query;
}
}
test(text: string): boolean {
if (typeof this.query === 'string') {
return text.indexOf(this.query) !== -1;
} else {
return !!text.match(this.query);
}
}
}