Merge branch 'master' into 127-folder-and-file-with-the-same-basename-sorting
# Conflicts: # src/custom-sort/sorting-spec-processor.spec.ts
This commit is contained in:
commit
9cf01e9591
|
@ -14,8 +14,16 @@ import {
|
||||||
RomanNumberNormalizerFn,
|
RomanNumberNormalizerFn,
|
||||||
SortingSpecProcessor
|
SortingSpecProcessor
|
||||||
} from "./sorting-spec-processor"
|
} from "./sorting-spec-processor"
|
||||||
import {CustomSortGroupType, CustomSortOrder, CustomSortSpec, IdentityNormalizerFn} from "./custom-sort-types";
|
import {
|
||||||
import {FolderMatchingRegexp, FolderMatchingTreeNode} from "./folder-matching-rules";
|
CustomSortGroupType,
|
||||||
|
CustomSortOrder,
|
||||||
|
CustomSortSpec,
|
||||||
|
IdentityNormalizerFn
|
||||||
|
} from "./custom-sort-types";
|
||||||
|
import {
|
||||||
|
FolderMatchingRegexp,
|
||||||
|
FolderMatchingTreeNode
|
||||||
|
} from "./folder-matching-rules";
|
||||||
|
|
||||||
const txtInputExampleA: string = `
|
const txtInputExampleA: string = `
|
||||||
order-asc: a-z
|
order-asc: a-z
|
||||||
|
@ -562,6 +570,68 @@ describe('SortingSpecProcessor', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const txtInputThreeDotsCases: string = `
|
||||||
|
target-folder: AAA
|
||||||
|
...
|
||||||
|
....
|
||||||
|
// Only in the below scenario the / is treated as empty-separator and swallowed
|
||||||
|
./...
|
||||||
|
// Below tricky and not obvious cases
|
||||||
|
../...
|
||||||
|
.../..
|
||||||
|
../...S
|
||||||
|
S.../..
|
||||||
|
S../...S
|
||||||
|
`
|
||||||
|
|
||||||
|
const expectedSortSpecForThreeDotsCases: { [key: string]: CustomSortSpec } = {
|
||||||
|
"AAA": {
|
||||||
|
groups: [{
|
||||||
|
type: CustomSortGroupType.MatchAll
|
||||||
|
},{
|
||||||
|
exactSuffix: '.',
|
||||||
|
type: CustomSortGroupType.ExactSuffix
|
||||||
|
},{
|
||||||
|
exactPrefix: '.',
|
||||||
|
type: CustomSortGroupType.ExactPrefix
|
||||||
|
},{
|
||||||
|
exactPrefix: '..',
|
||||||
|
type: CustomSortGroupType.ExactPrefix
|
||||||
|
},{
|
||||||
|
exactSuffix: '/..',
|
||||||
|
type: CustomSortGroupType.ExactSuffix
|
||||||
|
},{
|
||||||
|
exactPrefix: '..',
|
||||||
|
exactSuffix: 'S',
|
||||||
|
type: CustomSortGroupType.ExactHeadAndTail
|
||||||
|
},{
|
||||||
|
exactPrefix: 'S',
|
||||||
|
exactSuffix: '/..',
|
||||||
|
type: CustomSortGroupType.ExactHeadAndTail
|
||||||
|
},{
|
||||||
|
exactPrefix: 'S..',
|
||||||
|
exactSuffix: 'S',
|
||||||
|
type: CustomSortGroupType.ExactHeadAndTail
|
||||||
|
},{
|
||||||
|
type: CustomSortGroupType.Outsiders
|
||||||
|
}],
|
||||||
|
outsidersGroupIdx: 8,
|
||||||
|
targetFoldersPaths: ['AAA']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('SortingSpecProcessor', () => {
|
||||||
|
let processor: SortingSpecProcessor;
|
||||||
|
beforeEach(() => {
|
||||||
|
processor = new SortingSpecProcessor();
|
||||||
|
});
|
||||||
|
it('should correctly handle some of three-dots scenarios', () => {
|
||||||
|
const inputTxtArr: Array<string> = txtInputThreeDotsCases.split('\n')
|
||||||
|
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
|
||||||
|
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForThreeDotsCases)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const txtInputTrueAlphabeticalSortAttr: string = `
|
const txtInputTrueAlphabeticalSortAttr: string = `
|
||||||
target-folder: True Alpha
|
target-folder: True Alpha
|
||||||
< true a-z
|
< true a-z
|
||||||
|
@ -2823,6 +2893,78 @@ describe('convertPlainStringSortingGroupSpecToArraySpec', () => {
|
||||||
'...', 'tion. !!!'
|
'...', 'tion. !!!'
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
it('should recognize four dots escaper - variant 0', () => {
|
||||||
|
const s = './...'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'.', '...'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - variant 1', () => {
|
||||||
|
const s = '../...'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'..', '...'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - variant 2', () => {
|
||||||
|
const s = './...Some'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'.', '...', 'Some'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - variant 3', () => {
|
||||||
|
const s = 'Some./...'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some.','...'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - variant 3a', () => {
|
||||||
|
const s = 'Some./.....'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some./..','...'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - variant 3b', () => {
|
||||||
|
const s = 'Some./.....X'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some.','...', '..X'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - variant 4', () => {
|
||||||
|
const s = 'Some./...Some'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some.','...', 'Some'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - tricky variant 4', () => {
|
||||||
|
const s = 'Some./... haha ...Some'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some.','...', ' haha ...Some'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should recognize four dots escaper - tricky variant 5', () => {
|
||||||
|
const s = 'S.../..'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'S','...', '/..'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should NOT recognize four dots escaper - tricky variant 1', () => {
|
||||||
|
const s = 'Some... haha ./...Some'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some','...', ' haha ./...Some'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should NOT recognize four dots escaper - tricky variant 2', () => {
|
||||||
|
const s = 'Some... haha .../...Some'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'Some', '...', ' haha .../...Some'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
it('should NOT recognize four dots escaper - tricky variant 3', () => {
|
||||||
|
const s = '.../...'
|
||||||
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
'...', '/...'
|
||||||
|
])
|
||||||
|
})
|
||||||
it('should recognize some edge case', () => {
|
it('should recognize some edge case', () => {
|
||||||
const s = 'Edge...... ... ..... ... eee?'
|
const s = 'Edge...... ... ..... ... eee?'
|
||||||
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
expect(processor.convertPlainStringSortingGroupSpecToArraySpec(s)).toEqual([
|
||||||
|
|
|
@ -98,6 +98,10 @@ const ContextFreeProblems = new Set<ProblemCode>([
|
||||||
const ThreeDots = '...';
|
const ThreeDots = '...';
|
||||||
const ThreeDotsLength = ThreeDots.length;
|
const ThreeDotsLength = ThreeDots.length;
|
||||||
|
|
||||||
|
const AmbigueFourDotsEscaper = './...'
|
||||||
|
const AmbigueFourDotsEscaperLength = AmbigueFourDotsEscaper.length
|
||||||
|
const AmbigueFourDotsEscaperOverlap = 1 // Number of leading chars in the Escaper to retain in original string
|
||||||
|
|
||||||
interface CustomSortOrderAscDescPair {
|
interface CustomSortOrderAscDescPair {
|
||||||
asc: CustomSortOrder
|
asc: CustomSortOrder
|
||||||
desc: CustomSortOrder
|
desc: CustomSortOrder
|
||||||
|
@ -367,7 +371,7 @@ const inlineRegexSymbolsArrEscapedForRegex: Array<string> = [
|
||||||
escapeRegexUnsafeCharacters(InlineRegexSymbol_Digit2),
|
escapeRegexUnsafeCharacters(InlineRegexSymbol_Digit2),
|
||||||
escapeRegexUnsafeCharacters(InlineRegexSymbol_0_to_3),
|
escapeRegexUnsafeCharacters(InlineRegexSymbol_0_to_3),
|
||||||
escapeRegexUnsafeCharacters(InlineRegexSymbol_CapitalLetter),
|
escapeRegexUnsafeCharacters(InlineRegexSymbol_CapitalLetter),
|
||||||
escapeRegexUnsafeCharacters(InlineRegexSymbol_LowercaseLetter)
|
escapeRegexUnsafeCharacters(InlineRegexSymbol_LowercaseLetter),
|
||||||
]
|
]
|
||||||
|
|
||||||
interface RegexExpr {
|
interface RegexExpr {
|
||||||
|
@ -382,7 +386,7 @@ const inlineRegexSymbolsToRegexExpressionsArr: { [key: string]: RegexExpr} = {
|
||||||
[InlineRegexSymbol_Digit2]: {regexExpr: '[0-9]'},
|
[InlineRegexSymbol_Digit2]: {regexExpr: '[0-9]'},
|
||||||
[InlineRegexSymbol_0_to_3]: {regexExpr: '[0-3]'},
|
[InlineRegexSymbol_0_to_3]: {regexExpr: '[0-3]'},
|
||||||
[InlineRegexSymbol_CapitalLetter]: {regexExpr: '[\\p{Lu}\\p{Lt}]', isUnicode: true, isCaseSensitive: true},
|
[InlineRegexSymbol_CapitalLetter]: {regexExpr: '[\\p{Lu}\\p{Lt}]', isUnicode: true, isCaseSensitive: true},
|
||||||
[InlineRegexSymbol_LowercaseLetter]: {regexExpr: '\\p{Ll}', isUnicode: true, isCaseSensitive: true}
|
[InlineRegexSymbol_LowercaseLetter]: {regexExpr: '\\p{Ll}', isUnicode: true, isCaseSensitive: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
const inlineRegexSymbolsDetectionRegex = new RegExp(inlineRegexSymbolsArrEscapedForRegex.join('|'), 'gi')
|
const inlineRegexSymbolsDetectionRegex = new RegExp(inlineRegexSymbolsArrEscapedForRegex.join('|'), 'gi')
|
||||||
|
@ -1565,17 +1569,31 @@ export class SortingSpecProcessor {
|
||||||
return [ThreeDots, spec.substring(ThreeDotsLength)];
|
return [ThreeDots, spec.substring(ThreeDotsLength)];
|
||||||
}
|
}
|
||||||
if (spec.endsWith(ThreeDots)) {
|
if (spec.endsWith(ThreeDots)) {
|
||||||
|
if (spec.endsWith(AmbigueFourDotsEscaper)) {
|
||||||
|
return [spec.substring(0, spec.length - AmbigueFourDotsEscaperLength + AmbigueFourDotsEscaperOverlap), ThreeDots];
|
||||||
|
} else {
|
||||||
return [spec.substring(0, spec.length - ThreeDotsLength), ThreeDots];
|
return [spec.substring(0, spec.length - ThreeDotsLength), ThreeDots];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const idx = spec.indexOf(ThreeDots);
|
const idx = spec.indexOf(ThreeDots);
|
||||||
|
const idxOfAmbigueFourDotsEscaper = spec.indexOf(AmbigueFourDotsEscaper)
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
|
if (idxOfAmbigueFourDotsEscaper >= 0 &&
|
||||||
|
idxOfAmbigueFourDotsEscaper === idx - (AmbigueFourDotsEscaperLength - ThreeDotsLength) ) {
|
||||||
|
return [
|
||||||
|
spec.substring(0, idxOfAmbigueFourDotsEscaper + AmbigueFourDotsEscaperOverlap),
|
||||||
|
ThreeDots,
|
||||||
|
spec.substring(idx + ThreeDotsLength)
|
||||||
|
];
|
||||||
|
} else {
|
||||||
return [
|
return [
|
||||||
spec.substring(0, idx),
|
spec.substring(0, idx),
|
||||||
ThreeDots,
|
ThreeDots,
|
||||||
spec.substring(idx + ThreeDotsLength)
|
spec.substring(idx + ThreeDotsLength)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unrecognized, treat as exact match
|
// Unrecognized, treat as exact match
|
||||||
return [spec];
|
return [spec];
|
||||||
|
|
Loading…
Reference in New Issue