Skip to content

Commit fabd586

Browse files
authored
#23 feature request sorting notes with metadata (#26)
* #23 - support for sorting by metadata - added support for grouping items by the presence of specified metadata - new keyword `with-metadata:` introduced for that purpose in lexer - if metadata field name is omitted, the default `sort-index-value` is used - added support for sorting items by notes and folders metadata - new keyword 'by-metadata:' introduced for that purpose - if metadata field name is omitted, the default `sort-index-value` is used (or metadata name inheritance is used) - unit tests of sorting spec processor extended accordingly - documentation and code example in README.md - extended to also support true alphabetical on metadata fields - release unnecessary references after sorting completed
1 parent 9541202 commit fabd586

File tree

8 files changed

+1024
-45
lines changed

8 files changed

+1024
-45
lines changed

README.md

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Take full control of the order of your notes and folders:
77
- support for fully manual order
88
- list notes and folders names explicitly, or use prefixes or suffixes only
99
- wildcard names matching supported
10+
- group and sort notes and folders by notes custom metadata
1011
- support for automatic sorting by standard and non-standard rules
1112
- mixing manual and automatic ordering also supported
1213
- order by compound numbers in prefix, in suffix (e.g date in suffix) or inbetween
@@ -15,7 +16,7 @@ Take full control of the order of your notes and folders:
1516
- different sorting rules per group even inside the same folder
1617
- simple to use yet versatile configuration options
1718
- order configuration stored directly in your note(s) front matter
18-
- use a dedicated key in YAML
19+
- use a dedicated `sorting-spec:` key in YAML
1920
- folders not set up for the custom order remain on the standard Obsidian sorting
2021
- support for imposing inheritance of order specifications with flexible exclusion and overriding logic
2122

@@ -35,6 +36,7 @@ Take full control of the order of your notes and folders:
3536
- [Example 11: Sample book structure with compound Roman number suffixes](#example-11-sample-book-structure-with-compound-roman-number-suffixes)
3637
- [Example 12: Apply same sorting to all folders in the vault](#example-12-apply-same-sorting-to-all-folders-in-the-vault)
3738
- [Example 13: Sorting rules inheritance by subfolders](#example-13-sorting-rules-inheritance-by-subfolders)
39+
- [Example 14: Grouping and sorting by metadata value](#example-14-grouping-and-sorting-by-metadata-value)
3840
- [Alphabetical, Natural and True Alphabetical sorting orders](#alphabetical-natural-and-true-alphabetical-sorting-orders)
3941
- [Location of sorting specification YAML entry](#location-of-sorting-specification-yaml-entry)
4042
- [Ribbon icon](#ribbon-icon)
@@ -412,6 +414,86 @@ sorting-spec: |
412414
---
413415
```
414416

417+
### Example 14: Grouping and sorting by metadata value
418+
419+
Notes can contain metadata, let me use the example inspired by the [Feature Request #23](https://github.com/SebastianMC/obsidian-custom-sort/issues/23).
420+
Namely, someone can create notes when reading a book and use the `Pages` metadata field. In that field s/he enters page(s) number(s) of the book, for reference.
421+
422+
For example:
423+
424+
```yaml
425+
---
426+
Pages: 6
427+
...
428+
---
429+
```
430+
431+
or
432+
433+
```yaml
434+
---
435+
Pages: 7,8
436+
...
437+
---
438+
```
439+
440+
or
441+
442+
```yaml
443+
---
444+
Pages: 12-15
445+
...
446+
---
447+
```
448+
449+
Using this plugin you can sort notes by the value of the specific metadata, for example:
450+
451+
```yaml
452+
---
453+
sorting-spec: |
454+
target-folder: Remarks from 'The Little Prince' book
455+
< a-z by-metadata: Pages
456+
---
457+
```
458+
459+
In that approach, the notes containing the metadata `Pages` will go first, sorted alphabetically by the value of that metadata.
460+
The remaining notes (not having the metadata) will go below, sorted alphabetically by default.
461+
462+
In the above example the syntax `by-metadata: Pages` was used to tell the plugin about the metadata field name for sorting.
463+
The specified sorting `< a-z` is obviously alphabetical, and in this specific context it tells to sort by the value of the specified metadata (and not by the note or folder name).
464+
465+
In a more advanced fine-tuned approach you can explicitly group notes having some metadata and sort by that (or other) metadata:
466+
467+
```yaml
468+
---
469+
sorting-spec: |
470+
target-folder: Remarks from 'The Little Prince' book
471+
with-metadata: Pages
472+
< a-z by-metadata: Pages
473+
...
474+
> modified
475+
---
476+
```
477+
478+
In the above example the syntax `with-metadata: Pages` was used to tell the plugin about the metadata field name for grouping.
479+
The specified sorting `< a-z` is obviously alphabetical, and in this specific context it tells to sort by the value of the specified metadata (and not by the note or folder name).
480+
Then the remaining notes (not having the `Pages` metadata) are sorted by modification date descending.
481+
482+
> NOTE
483+
>
484+
> The grouping and sorting by metadata is not refreshed automatically after change of the metadata in note(s) to avoid impact on Obsidian performance.
485+
> After editing of metadata of some note(s) you have to explicitly click the plugin ribbon button to refresh the sorting. Or issue the command `sort on`. Or close and reopen the vault. Or restart Obsidian.
486+
> This behavior is intentionally different from other grouping and sorting rules, which stay active and up-to-date once enabled.
487+
488+
> NOTE
489+
>
490+
> For folders, metadata of their 'folder note' is scanned (if present)
491+
492+
> NOTE
493+
>
494+
> The `with-metadata:` keyword can be used with other specifiers like `/:files with-metadata: Pages` or `/folders with-metadata: Pages`
495+
> If the metadata name is omitted, the default `sort-index-value` metadata name is assumed.
496+
415497
## Alphabetical, Natural and True Alphabetical sorting orders
416498

417499
The 'A-Z' sorting (visible in Obsidian UI of file explorer) at some point before the 1.0.0 release of Obsidian actually became the so-called 'natural' sort order.

src/custom-sort/custom-sort-types.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import {MetadataCache, Plugin} from "obsidian";
2+
13
export enum CustomSortGroupType {
24
Outsiders, // Not belonging to any of other groups
35
MatchAll, // like a wildard *, used in connection with foldersOnly or filesOnly. The difference between the MatchAll and Outsiders is
46
ExactName, // ... that MatchAll captures the item (folder, note) and prevents further matching against other rules
57
ExactPrefix, // ... while the Outsiders captures items which didn't match any of other defined groups
68
ExactSuffix,
79
ExactHeadAndTail, // Like W...n or Un...ed, which is shorter variant of typing the entire title
10+
HasMetadataField // Notes (or folder's notes) containing a specific metadata field
811
}
912

1013
export enum CustomSortOrder {
@@ -20,13 +23,18 @@ export enum CustomSortOrder {
2023
byCreatedTimeAdvanced,
2124
byCreatedTimeReverse,
2225
byCreatedTimeReverseAdvanced,
26+
byMetadataFieldAlphabetical,
27+
byMetadataFieldTrueAlphabetical,
28+
byMetadataFieldAlphabeticalReverse,
29+
byMetadataFieldTrueAlphabeticalReverse,
2330
standardObsidian, // Let the folder sorting be in hands of Obsidian, whatever user selected in the UI
2431
default = alphabetical
2532
}
2633

2734
export interface RecognizedOrderValue {
2835
order: CustomSortOrder
2936
secondaryOrder?: CustomSortOrder
37+
applyToMetadataField?: string
3038
}
3139

3240
export type NormalizerFn = (s: string) => string | null
@@ -43,18 +51,27 @@ export interface CustomSortGroup {
4351
exactPrefix?: string
4452
exactSuffix?: string
4553
order?: CustomSortOrder
54+
byMetadataField?: string // for 'by-metadata:' if the order is by metadata alphabetical or reverse
4655
secondaryOrder?: CustomSortOrder
4756
filesOnly?: boolean
4857
matchFilenameWithExt?: boolean
49-
foldersOnly?: boolean,
58+
foldersOnly?: boolean
59+
withMetadataFieldName?: string // for 'with-metadata:'
5060
}
5161

5262
export interface CustomSortSpec {
5363
targetFoldersPaths: Array<string> // For root use '/'
5464
defaultOrder?: CustomSortOrder
65+
byMetadataField?: string // for 'by-metadata:' if the defaultOrder is by metadata alphabetical or reverse
5566
groups: Array<CustomSortGroup>
5667
outsidersGroupIdx?: number
5768
outsidersFilesGroupIdx?: number
5869
outsidersFoldersGroupIdx?: number
5970
itemsToHide?: Set<string>
71+
plugin?: Plugin // to hand over the access to App instance to the sorting engine
72+
73+
// For internal transient use
74+
_mCache?: MetadataCache
6075
}
76+
77+
export const DEFAULT_METADATA_FIELD_FOR_SORTING: string = 'sort-index-value'

0 commit comments

Comments
 (0)