Two experimental features + version bump before release

- `aaa-z` and `a-zzz` sort orders (uppercase first, alphanumeric order and lowercase  first, alphanumeric)
- `vsc-unicode` sort order, which is equivalent to what VS Code refers to as 'unicode' sorting (which name is arbitrary and confusing, yet familar to VS Code users)
This commit is contained in:
SebastianMC 2024-01-27 23:25:59 +01:00
parent fe98a27f5d
commit a2a808e78b
7 changed files with 127 additions and 19 deletions

View File

@ -1,7 +1,7 @@
{ {
"id": "custom-sort", "id": "custom-sort",
"name": "Custom File Explorer sorting", "name": "Custom File Explorer sorting",
"version": "2.1.4", "version": "2.1.5",
"minAppVersion": "0.16.2", "minAppVersion": "0.16.2",
"description": "Allows for manual and automatic, config-driven reordering and sorting of files and folders in File Explorer", "description": "Allows for manual and automatic, config-driven reordering and sorting of files and folders in File Explorer",
"author": "SebastianMC", "author": "SebastianMC",

View File

@ -1,6 +1,6 @@
{ {
"name": "obsidian-custom-sort", "name": "obsidian-custom-sort",
"version": "2.1.4", "version": "2.1.5",
"description": "Custom Sort plugin for Obsidian (https://obsidian.md)", "description": "Custom Sort plugin for Obsidian (https://obsidian.md)",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {

View File

@ -13,10 +13,14 @@ export enum CustomSortGroupType {
export enum CustomSortOrder { export enum CustomSortOrder {
alphabetical = 1, // = 1 to allow: if (customSortOrder) { ... alphabetical = 1, // = 1 to allow: if (customSortOrder) { ...
alphabeticalLowerFirst,
alphabeticalUpperFirst,
alphabeticalWithFileExt, alphabeticalWithFileExt,
trueAlphabetical, trueAlphabetical,
trueAlphabeticalWithFileExt, trueAlphabeticalWithFileExt,
alphabeticalReverse, alphabeticalReverse,
alphabeticalLowerFirstReverse,
alphabeticalUpperFirstReverse,
alphabeticalReverseWithFileExt, alphabeticalReverseWithFileExt,
trueAlphabeticalReverse, trueAlphabeticalReverse,
trueAlphabeticalReverseWithFileExt, trueAlphabeticalReverseWithFileExt,
@ -38,7 +42,9 @@ export enum CustomSortOrder {
fileFirst, fileFirst,
folderFirst, folderFirst,
alphabeticalWithFilesPreferred, // When the (base)names are equal, the file has precedence over a folder alphabeticalWithFilesPreferred, // When the (base)names are equal, the file has precedence over a folder
alphabeticalWithFoldersPreferred, // When the (base)names are equal, the file has precedence over a folder alphabeticalWithFoldersPreferred, // When the (base)names are equal, the file has precedence over a folder,
vscUnicode, // the Visual Studio Code lexicographic order named 'unicode' (which is very misleading, at the same time familiar to VS Code users
vscUnicodeReverse, // ... see compareFilesUnicode function https://github.com/microsoft/vscode/blob/a19b2d5fb0202e00fb930dc850d2695ec512e495/src/vs/base/common/comparers.ts#L80
default = alphabeticalWithFilesPreferred default = alphabeticalWithFilesPreferred
} }

View File

@ -49,6 +49,20 @@ export const CollatorCompare = new Intl.Collator(undefined, {
numeric: true, numeric: true,
}).compare; }).compare;
export const CollatorCompareUpperFirst = new Intl.Collator(undefined, {
usage: "sort",
sensitivity: "base",
numeric: true,
caseFirst: "upper"
}).compare;
export const CollatorCompareLowerFirst = new Intl.Collator(undefined, {
usage: "sort",
sensitivity: "base",
numeric: true,
caseFirst: "lower"
}).compare;
export const CollatorTrueAlphabeticalCompare = new Intl.Collator(undefined, { export const CollatorTrueAlphabeticalCompare = new Intl.Collator(undefined, {
usage: "sort", usage: "sort",
sensitivity: "base", sensitivity: "base",
@ -178,23 +192,27 @@ const folderGoesFirstWhenSameBasenameAsFolder = (stringCompareResult: number, a:
(!!stringCompareResult) ? stringCompareResult : (a.isFolder === b.isFolder ? EQUAL_OR_UNCOMPARABLE : (a.isFolder ? -1 : 1) ); (!!stringCompareResult) ? stringCompareResult : (a.isFolder === b.isFolder ? EQUAL_OR_UNCOMPARABLE : (a.isFolder ? -1 : 1) );
const Sorters: { [key in CustomSortOrder]: SorterFn } = { const Sorters: { [key in CustomSortOrder]: SorterFn } = {
[CustomSortOrder.alphabetical]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(a.sortString, b.sortString), [CustomSortOrder.alphabetical]: (a: FIFS, b: FIFS) => CollatorCompare(a.sortString, b.sortString),
[CustomSortOrder.alphabeticalLowerFirst]: (a: FIFS, b: FIFS) => CollatorCompareLowerFirst(a.sortString, b.sortString),
[CustomSortOrder.alphabeticalUpperFirst]: (a: FIFS, b: FIFS) => CollatorCompareUpperFirst(a.sortString, b.sortString),
[CustomSortOrder.alphabeticalWithFilesPreferred]: (a: FIFS, b: FIFS) => fileGoesFirstWhenSameBasenameAsFolder(CollatorCompare(a.sortString, b.sortString),a,b), [CustomSortOrder.alphabeticalWithFilesPreferred]: (a: FIFS, b: FIFS) => fileGoesFirstWhenSameBasenameAsFolder(CollatorCompare(a.sortString, b.sortString),a,b),
[CustomSortOrder.alphabeticalWithFoldersPreferred]: (a: FIFS, b: FIFS) => fileGoesFirstWhenSameBasenameAsFolder(CollatorCompare(a.sortString, b.sortString),a,b), [CustomSortOrder.alphabeticalWithFoldersPreferred]: (a: FIFS, b: FIFS) => fileGoesFirstWhenSameBasenameAsFolder(CollatorCompare(a.sortString, b.sortString),a,b),
[CustomSortOrder.alphabeticalWithFileExt]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(a.sortStringWithExt, b.sortStringWithExt), [CustomSortOrder.alphabeticalWithFileExt]: (a: FIFS, b: FIFS) => CollatorCompare(a.sortStringWithExt, b.sortStringWithExt),
[CustomSortOrder.trueAlphabetical]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorTrueAlphabeticalCompare(a.sortString, b.sortString), [CustomSortOrder.trueAlphabetical]: (a: FIFS, b: FIFS) => CollatorTrueAlphabeticalCompare(a.sortString, b.sortString),
[CustomSortOrder.trueAlphabeticalWithFileExt]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorTrueAlphabeticalCompare(a.sortStringWithExt, b.sortStringWithExt), [CustomSortOrder.trueAlphabeticalWithFileExt]: (a: FIFS, b: FIFS) => CollatorTrueAlphabeticalCompare(a.sortStringWithExt, b.sortStringWithExt),
[CustomSortOrder.alphabeticalReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(b.sortString, a.sortString), [CustomSortOrder.alphabeticalReverse]: (a: FIFS, b: FIFS) => CollatorCompare(b.sortString, a.sortString),
[CustomSortOrder.alphabeticalReverseWithFileExt]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(b.sortStringWithExt, a.sortStringWithExt), [CustomSortOrder.alphabeticalLowerFirstReverse]: (a: FIFS, b: FIFS) => CollatorCompareLowerFirst(b.sortString, a.sortString),
[CustomSortOrder.trueAlphabeticalReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorTrueAlphabeticalCompare(b.sortString, a.sortString), [CustomSortOrder.alphabeticalUpperFirstReverse]: (a: FIFS, b: FIFS) => CollatorCompareUpperFirst(b.sortString, a.sortString),
[CustomSortOrder.trueAlphabeticalReverseWithFileExt]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorTrueAlphabeticalCompare(b.sortStringWithExt, a.sortStringWithExt), [CustomSortOrder.alphabeticalReverseWithFileExt]: (a: FIFS, b: FIFS) => CollatorCompare(b.sortStringWithExt, a.sortStringWithExt),
[CustomSortOrder.byModifiedTime]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (a.mtime - b.mtime), [CustomSortOrder.trueAlphabeticalReverse]: (a: FIFS, b: FIFS) => CollatorTrueAlphabeticalCompare(b.sortString, a.sortString),
[CustomSortOrder.trueAlphabeticalReverseWithFileExt]: (a: FIFS, b: FIFS) => CollatorTrueAlphabeticalCompare(b.sortStringWithExt, a.sortStringWithExt),
[CustomSortOrder.byModifiedTime]: (a: FIFS, b: FIFS) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (a.mtime - b.mtime),
[CustomSortOrder.byModifiedTimeAdvanced]: sorterByFolderMDate(), [CustomSortOrder.byModifiedTimeAdvanced]: sorterByFolderMDate(),
[CustomSortOrder.byModifiedTimeReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (b.mtime - a.mtime), [CustomSortOrder.byModifiedTimeReverse]: (a: FIFS, b: FIFS) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (b.mtime - a.mtime),
[CustomSortOrder.byModifiedTimeReverseAdvanced]: sorterByFolderMDate(true), [CustomSortOrder.byModifiedTimeReverseAdvanced]: sorterByFolderMDate(true),
[CustomSortOrder.byCreatedTime]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (a.ctime - b.ctime), [CustomSortOrder.byCreatedTime]: (a: FIFS, b: FIFS) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (a.ctime - b.ctime),
[CustomSortOrder.byCreatedTimeAdvanced]: sorterByFolderCDate(), [CustomSortOrder.byCreatedTimeAdvanced]: sorterByFolderCDate(),
[CustomSortOrder.byCreatedTimeReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (b.ctime - a.ctime), [CustomSortOrder.byCreatedTimeReverse]: (a: FIFS, b: FIFS) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (b.ctime - a.ctime),
[CustomSortOrder.byCreatedTimeReverseAdvanced]: sorterByFolderCDate(true), [CustomSortOrder.byCreatedTimeReverseAdvanced]: sorterByFolderCDate(true),
[CustomSortOrder.byMetadataFieldAlphabetical]: sorterByMetadataField(StraightOrder, !TrueAlphabetical, SortingLevelId.forPrimary), [CustomSortOrder.byMetadataFieldAlphabetical]: sorterByMetadataField(StraightOrder, !TrueAlphabetical, SortingLevelId.forPrimary),
[CustomSortOrder.byMetadataFieldTrueAlphabetical]: sorterByMetadataField(StraightOrder, TrueAlphabetical, SortingLevelId.forPrimary), [CustomSortOrder.byMetadataFieldTrueAlphabetical]: sorterByMetadataField(StraightOrder, TrueAlphabetical, SortingLevelId.forPrimary),
@ -202,8 +220,10 @@ const Sorters: { [key in CustomSortOrder]: SorterFn } = {
[CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse]: sorterByMetadataField(ReverseOrder, TrueAlphabetical, SortingLevelId.forPrimary), [CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse]: sorterByMetadataField(ReverseOrder, TrueAlphabetical, SortingLevelId.forPrimary),
[CustomSortOrder.byBookmarkOrder]: sorterByBookmarkOrder(StraightOrder), [CustomSortOrder.byBookmarkOrder]: sorterByBookmarkOrder(StraightOrder),
[CustomSortOrder.byBookmarkOrderReverse]: sorterByBookmarkOrder(ReverseOrder), [CustomSortOrder.byBookmarkOrderReverse]: sorterByBookmarkOrder(ReverseOrder),
[CustomSortOrder.fileFirst]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder === b.isFolder) ? EQUAL_OR_UNCOMPARABLE : (a.isFolder ? 1 : -1), [CustomSortOrder.fileFirst]: (a: FIFS, b: FIFS) => (a.isFolder === b.isFolder) ? EQUAL_OR_UNCOMPARABLE : (a.isFolder ? 1 : -1),
[CustomSortOrder.folderFirst]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder === b.isFolder) ? EQUAL_OR_UNCOMPARABLE : (a.isFolder ? -1 : 1), [CustomSortOrder.folderFirst]: (a: FIFS, b: FIFS) => (a.isFolder === b.isFolder) ? EQUAL_OR_UNCOMPARABLE : (a.isFolder ? -1 : 1),
[CustomSortOrder.vscUnicode]: (a: FIFS, b: FIFS) => (a.sortString === b.sortString) ? EQUAL_OR_UNCOMPARABLE : (a.sortString < b.sortString ? -1 : 1),
[CustomSortOrder.vscUnicodeReverse]: (a: FIFS, b: FIFS) => (a.sortString === b.sortString) ? EQUAL_OR_UNCOMPARABLE : (b.sortString < a.sortString ? -1 : 1),
// A fallback entry which should not be used - the getSorterFor() function below should protect against it // A fallback entry which should not be used - the getSorterFor() function below should protect against it
[CustomSortOrder.standardObsidian]: (a: FIFS, b: FIFS) => CollatorCompare(a.sortString, b.sortString), [CustomSortOrder.standardObsidian]: (a: FIFS, b: FIFS) => CollatorCompare(a.sortString, b.sortString),

View File

@ -711,6 +711,84 @@ describe('SortingSpecProcessor', () => {
}) })
}) })
const txtInputExoticExperimentalSortAttr: string = `
target-folder: upper first
< aaa-z
target-folder: upper first Rev
> aaa-z
target-folder: lower first
< a-zzz
target-folder: lower first Rev
> a-zzz
target-folder: VS Code unicode lexicographic
< vsc-unicode
target-folder: VS Code unicode lexicographic reverse
> vsc-unicode
`
const expectedSortSpecForExoticExperimentalSorting: { [key: string]: CustomSortSpec } = {
"upper first": {
defaultOrder: CustomSortOrder.alphabeticalUpperFirst,
groups: [{
type: CustomSortGroupType.Outsiders
}],
outsidersGroupIdx: 0,
targetFoldersPaths: ['upper first']
},
"upper first Rev": {
defaultOrder: CustomSortOrder.alphabeticalUpperFirstReverse,
groups: [{
type: CustomSortGroupType.Outsiders
}],
outsidersGroupIdx: 0,
targetFoldersPaths: ['upper first Rev']
},
"lower first": {
defaultOrder: CustomSortOrder.alphabeticalLowerFirst,
groups: [{
type: CustomSortGroupType.Outsiders
}],
outsidersGroupIdx: 0,
targetFoldersPaths: ['lower first']
},
"lower first Rev": {
defaultOrder: CustomSortOrder.alphabeticalLowerFirstReverse,
groups: [{
type: CustomSortGroupType.Outsiders
}],
outsidersGroupIdx: 0,
targetFoldersPaths: ['lower first Rev']
},
"VS Code unicode lexicographic": {
defaultOrder: CustomSortOrder.vscUnicode,
groups: [{
type: CustomSortGroupType.Outsiders
}],
outsidersGroupIdx: 0,
targetFoldersPaths: ['VS Code unicode lexicographic']
},
"VS Code unicode lexicographic reverse": {
defaultOrder: CustomSortOrder.vscUnicodeReverse,
groups: [{
type: CustomSortGroupType.Outsiders
}],
outsidersGroupIdx: 0,
targetFoldersPaths: ['VS Code unicode lexicographic reverse']
}
}
describe('SortingSpecProcessor', () => {
let processor: SortingSpecProcessor;
beforeEach(() => {
processor = new SortingSpecProcessor();
});
it('should recognize the exotic experimental sorting attribute for a folder', () => {
const inputTxtArr: Array<string> = txtInputExoticExperimentalSortAttr.split('\n')
const result = processor.parseSortSpecFromText(inputTxtArr, 'mock-folder', 'custom-name-note.md')
expect(result?.sortSpecByPath).toEqual(expectedSortSpecForExoticExperimentalSorting)
})
})
const txtInputSimplistic1: string = ` const txtInputSimplistic1: string = `
target-folder: /* target-folder: /*
/:files /:files

View File

@ -116,8 +116,10 @@ const MAX_SORT_LEVEL: number = 1
// remember about .toLowerCase() before comparison! // remember about .toLowerCase() before comparison!
const OrderLiterals: { [key: string]: CustomSortOrderAscDescPair } = { const OrderLiterals: { [key: string]: CustomSortOrderAscDescPair } = {
'a-zzz': {asc: CustomSortOrder.alphabeticalLowerFirst, desc: CustomSortOrder.alphabeticalLowerFirstReverse},
'a-z.': {asc: CustomSortOrder.alphabeticalWithFileExt, desc: CustomSortOrder.alphabeticalReverseWithFileExt}, 'a-z.': {asc: CustomSortOrder.alphabeticalWithFileExt, desc: CustomSortOrder.alphabeticalReverseWithFileExt},
'a-z': {asc: CustomSortOrder.alphabetical, desc: CustomSortOrder.alphabeticalReverse}, 'a-z': {asc: CustomSortOrder.alphabetical, desc: CustomSortOrder.alphabeticalReverse},
'aaa-z': {asc: CustomSortOrder.alphabeticalUpperFirst, desc: CustomSortOrder.alphabeticalUpperFirstReverse},
'true a-z.': {asc: CustomSortOrder.trueAlphabeticalWithFileExt, desc: CustomSortOrder.trueAlphabeticalReverseWithFileExt}, 'true a-z.': {asc: CustomSortOrder.trueAlphabeticalWithFileExt, desc: CustomSortOrder.trueAlphabeticalReverseWithFileExt},
'true a-z': {asc: CustomSortOrder.trueAlphabetical, desc: CustomSortOrder.trueAlphabeticalReverse}, 'true a-z': {asc: CustomSortOrder.trueAlphabetical, desc: CustomSortOrder.trueAlphabeticalReverse},
'created': {asc: CustomSortOrder.byCreatedTime, desc: CustomSortOrder.byCreatedTimeReverse}, 'created': {asc: CustomSortOrder.byCreatedTime, desc: CustomSortOrder.byCreatedTimeReverse},
@ -128,7 +130,8 @@ const OrderLiterals: { [key: string]: CustomSortOrderAscDescPair } = {
'ui selected': {asc: CustomSortOrder.standardObsidian, desc: CustomSortOrder.standardObsidian}, 'ui selected': {asc: CustomSortOrder.standardObsidian, desc: CustomSortOrder.standardObsidian},
'by-bookmarks-order': {asc: CustomSortOrder.byBookmarkOrder, desc: CustomSortOrder.byBookmarkOrderReverse}, 'by-bookmarks-order': {asc: CustomSortOrder.byBookmarkOrder, desc: CustomSortOrder.byBookmarkOrderReverse},
'files-first': {asc: CustomSortOrder.fileFirst, desc: CustomSortOrder.fileFirst}, 'files-first': {asc: CustomSortOrder.fileFirst, desc: CustomSortOrder.fileFirst},
'folders-first': {asc: CustomSortOrder.folderFirst, desc: CustomSortOrder.folderFirst} 'folders-first': {asc: CustomSortOrder.folderFirst, desc: CustomSortOrder.folderFirst},
'vsc-unicode': {asc: CustomSortOrder.vscUnicode, desc: CustomSortOrder.vscUnicodeReverse}
} }
const OrderByMetadataLexeme: string = 'by-metadata:' const OrderByMetadataLexeme: string = 'by-metadata:'

View File

@ -38,5 +38,6 @@
"2.1.1": "0.16.2", "2.1.1": "0.16.2",
"2.1.2": "0.16.2", "2.1.2": "0.16.2",
"2.1.3": "0.16.2", "2.1.3": "0.16.2",
"2.1.4": "0.16.2" "2.1.4": "0.16.2",
"2.1.5": "0.16.2"
} }