Repository: obsidian-tasks-group/obsidian-tasks
Pull request #2308 (2023-09-29 19:03:09)

feat: Add task.priorityNameGroupText and task.status.typeGroupText
<!--- Provide a general summary of your changes in the Title above -->

# Description

Easier custom grouping, by adding:

- `task.priorityNameGroupText` - the following give identical output:
    - `group by function task.priorityNameGroupText`
    - `group by priority`
- `task.status.typeGroupText` - the following give identical output:
    - `group by function task.status.typeGroupText`
    - `group by status.type`

These are useful if creating a custom group name by joining together different task properties.

They give the same natural sort order as the built-in groups, without needing complex custom grouping code to force the natural sort order.

## Motivation and Context

Exploring ways of answering #2307 by making complex custom groups easier to write.

## How has this been tested?

- View new unit tests

## Screenshots (if appropriate)

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [x] **New feature** (prefix: `feat` - non-breaking change which adds functionality)
- [x] **Documentation** (prefix: `docs` - improvements to any documentation content **for users**)

Internal changes:

- [x] **Refactor** (prefix: `refactor` - non-breaking change which only improves the design or structure of existing code, and making no changes to its external behaviour)
- [x] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [x] My change requires a change to the documentation.
- [x] I have [updated the documentation](https://publish.obsidian.md/tasks-contributing/Documentation/About+Documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://publish.obsidian.md/tasks-contributing) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [x] My contribution follow this project's [contributing guide](https://publish.obsidian.md/tasks-contributing)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)



Patch:
diff --git a/docs/Introduction.md b/docs/Introduction.md
index 871adc67..829a2f96 100644
--- a/docs/Introduction.md
+++ b/docs/Introduction.md
@@ -6,6 +6,7 @@ publish: true
 
 ## What's New?
 
+- X.Y.Z: 🔥 Add [[Task Properties|task properties]] `task.priorityNameGroupText` and `task.status.typeGroupText`
 - 4.8.0: 🔥 Add [[Query Properties#Values for Query File Properties|query file properties]] `query.file.pathWithoutExtension` and `query.file.filenameWithoutExtension`
 - 4.8.0: 🔥 Add [[Task Properties#Values for File Properties|task file properties]] `task.file.pathWithoutExtension` and `task.file.filenameWithoutExtension`
 - 4.7.0: 🔥 Use [[Query Properties]] and [[Placeholders]] to filter and group with the query's file path, root, folder and name.
diff --git a/docs/Queries/Grouping.md b/docs/Queries/Grouping.md
index 80cce5ac..ed351c46 100644
--- a/docs/Queries/Grouping.md
+++ b/docs/Queries/Grouping.md
@@ -100,10 +100,14 @@ Since Tasks 4.0.0, **[[Custom Grouping|custom grouping]] by status names** is no
 
 Since Tasks 4.0.0, **[[Custom Grouping|custom grouping]] by status types** is now possible.
 
+`task.status.typeGroupText` was added in Tasks X.Y.Z.
+
 <!-- placeholder to force blank line before included text --><!-- include: CustomGroupingExamples.test.statuses_task.status.type_docs.approved.md -->
 
 - ```group by function task.status.type```
   - Unlike "group by status.type", this sorts the status types in alphabetical order.
+- ```group by function task.status.typeGroupText```
+  - This sorts the status types in the same order as "group by status.type".
 
 <!-- placeholder to force blank line after included text --><!-- endInclude -->
 
@@ -366,6 +370,8 @@ The value `task.descriptionWithoutTags` returns a copy of the description with a
 
 Since Tasks 4.0.0, **[[Custom Grouping|custom grouping]] by priority name and number** is now possible.
 
+`task.priorityNameGroupText` was added in Tasks X.Y.Z.
+
 Using the priority name:
 
 <!-- placeholder to force blank line before included text --><!-- include: CustomGroupingExamples.test.other_properties_task.priorityName_docs.approved.md -->
@@ -374,9 +380,9 @@ Using the priority name:
   - Group by the task's priority name.
   - The priority names are displayed in alphabetical order.
   - Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'.
-- ```group by function '%%' + task.priorityNumber.toString() + '%%' + task.priorityName +' priority'```
+- ```group by function task.priorityNameGroupText```
   - Group by the task's priority name.
-  - The hidden priority number ensures that the headings are written from highest to lowest priority.
+  - The priority names are displayed from highest to lowest priority.
   - Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'.
 
 <!-- placeholder to force blank line after included text --><!-- endInclude -->
diff --git a/docs/Quick Reference.md b/docs/Quick Reference.md
index 331e9dff..83076970 100644
--- a/docs/Quick Reference.md
+++ b/docs/Quick Reference.md
@@ -8,57 +8,57 @@ aliases:
 
 This table summarizes the filters and other options available inside a `tasks` block.
 
-| [[Filters]]                                                                                                                                                                                                                                                                                                                                           | [[Sorting\|Sort]]                           | [[Grouping\|Group]]    | [[Layout\|Display]]    | [[About Scripting\|Scripting]]                               |
-| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------- | ---------------------- | ------------------------------------------------------------ |
-| **[[Filters#Filters for Dates in Tasks\|Status]]**                                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                              |
-| `done`<br>`not done`                                                                                                                                                                                                                                                                                                                                  | `sort by status`                            | `group by status`      |                        | `task.isDone`                                                |
-| `status.name (includes, does not include) <string>`<br>`status.name (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                   | `sort by status.name`                       | `group by status.name` |                        | `task.status.name`                                           |
-| `status.type (is, is not) (TODO, DONE, IN_PROGRESS, CANCELLED, NON_TASK)`                                                                                                                                                                                                                                                                             | `sort by status.type`                       | `group by status.type` |                        | `task.status.type`                                           |
-|                                                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        | `task.status.symbol`                                         |
-|                                                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        | `task.status.nextSymbol`                                     |
-| **[[Filters#Filters for Dates in Tasks\|Dates]]**                                                                                                                                                                                                                                                                                                     |                                             |                        |                        |                                                              |
-| `done (on, before, after, on or before, on or after) <date>`<br>`done (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has done date`<br>`no  done date`<br>`done date is invalid`                          | `sort by done`                              | `group by done`        | `hide done date`       | `task.done`                                                  |
-| `created (on, before, after, on or before, on or after) <date>`<br>`created (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has created date`<br>`no  created date`<br>`created date is invalid`           | `sort by created`                           | `group by created`     | `hide created date`    | `task.created`                                               |
-| `starts (on, before, after, on or before, on or after) <date>`<br>`starts (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has start date`<br>`no  start date`<br>`start date is invalid`                   | `sort by start`                             | `group by start`       | `hide start date`      | `task.start`                                                 |
-| `scheduled (on, before, after, on or before, on or after) <date>`<br>`scheduled (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has scheduled date`<br>`no  scheduled date`<br>`scheduled date is invalid` | `sort by scheduled`                         | `group by scheduled`   | `hide scheduled date`  | `task.scheduled`                                             |
-| `due (on, before, after, on or before, on or after) <date>`<br>`due (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has due date`<br>`no  due date`<br>`due date is invalid`                               | `sort by due`                               | `group by due`         | `hide due date`        | `task.due`                                                   |
-| `happens (on, before, after, on or before, on or after) <date>`<br>`happens (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has happens date`<br>`no  happens date`                                        | `sort by happens`                           | `group by happens`     |                        | `task.happens`                                               |
-| **[[Filters#Recurrence\|Recurrence]]**                                                                                                                                                                                                                                                                                                                |                                             |                        |                        |                                                              |
-| `is recurring`<br>`is not recurring`                                                                                                                                                                                                                                                                                                                  | `sort by recurring`                         | `group by recurring`   |                        | `task.isRecurring`                                           |
-| `recurrence (includes, does not include) <string>`<br>`recurrence (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                     |                                             | `group by recurrence`  | `hide recurrence rule` | `task.recurrenceRule`                                        |
-| **[[Filters#Priority\|Priority]]** and **[[Urgency\|urgency]]**                                                                                                                                                                                                                                                                                       |                                             |                        |                        |                                                              |
-| `priority is (above, below, not)? (lowest, low, none, medium, high, highest)`                                                                                                                                                                                                                                                                         | `sort by priority`                          | `group by priority`    | `hide priority`        | `task.priorityName`<br>`task.priorityNumber`                 |
-|                                                                                                                                                                                                                                                                                                                                                       | `sort by urgency`                           | `group by urgency`     | `show urgency`         | `task.urgency`                                               |
-| **[[Filters#Filters for File Properties\|File properties]]**                                                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                              |
-| `path (includes, does not include) <path>`<br>`path (regex matches, regex does not match) /regex/i`<br>`path includes {{query.file.path}}`<br>`path includes {{query.file.pathWithoutExtension}}`                                                                                                                                                     | `sort by path`                              | `group by path`        |                        | `task.file.path`<br>`task.file.pathWithoutExtension`         |
-| `root (includes, does not include) <root>`<br>`root (regex matches, regex does not match) /regex/i`<br>`root includes {{query.file.root}}`                                                                                                                                                                                                            |                                             | `group by root`        |                        | `task.file.root`                                             |
-| `folder (includes, does not include) <folder>`<br>`folder (regex matches, regex does not match) /regex/i`<br>`folder includes {{query.file.folder}}`                                                                                                                                                                                                  |                                             | `group by folder`      |                        | `task.file.folder`                                           |
-| `filename (includes, does not include) <filename>`<br>`filename (regex matches, regex does not match) /regex/i`<br>`filename includes {{query.file.filename}}`<br>`filename includes {{query.file.filenameWithoutExtension}}`                                                                                                                         | `sort by filename`                          | `group by filename`    |                        | `task.file.filename`<br>`task.file.filenameWithoutExtension` |
-| `heading (includes, does not include) <string>`<br>`heading (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                           | `sort by heading`                           | `group by heading`     |                        | `task.hasHeading`<br>`task.heading`                          |
-|                                                                                                                                                                                                                                                                                                                                                       |                                             | `group by backlink`    | `hide backlink`        |                                                              |
-| **[[Filters#Description\|Description]]**, **[[Filters#Tags\|Tags]]** and other odds and ends                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                              |
-| `description (includes, does not include) <string>`<br>`description (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                   | `sort by description`                       |                        |                        | `task.description`<br>`task.descriptionWithoutTags`          |
-| `has tags`<br>`no tags`<br>`tag (includes, does not include) <tag>`<br>`tags (include, do not include) <tag>`<br>`tag (regex matches, regex does not match) /regex/i`<br>`tags (regex matches, regex does not match) /regex/i`                                                                                                                        | `sort by tag`<br>`sort by tag <tag_number>` | `group by tags`        | `hide tags`            | `task.tags`                                                  |
-|                                                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        | `task.originalMarkdown`                                      |
-| **[[About Scripting\|Scripting]]**                                                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                              |
-| `filter by function`                                                                                                                                                                                                                                                                                                                                  |                                             | `group by function`    |                        |                                                              |
-| **[[Combining Filters]]**                                                                                                                                                                                                                                                                                                                             |                                             |                        |                        |                                                              |
-| `(filter 1) AND (filter 2)`                                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                              |
-| `(filter 1) OR (filter 2)`                                                                                                                                                                                                                                                                                                                            |                                             |                        |                        |                                                              |
-| `NOT (filter 1)`                                                                                                                                                                                                                                                                                                                                      |                                             |                        |                        |                                                              |
-| `(filter 1) XOR (filter 2)`                                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                              |
-| `(filter 1) AND NOT (filter 2)`                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        |                                                              |
-| `(filter 1) OR NOT (filter 2)`                                                                                                                                                                                                                                                                                                                        |                                             |                        |                        |                                                              |
-| `(filter 1) AND ((filter 2) OR (filter 3))`                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                              |
-| **Other Filter Options**                                                                                                                                                                                                                                                                                                                              |                                             |                        |                        |                                                              |
-| `exclude sub-items`                                                                                                                                                                                                                                                                                                                                   |                                             |                        |                        |                                                              |
-| `limit to <number> tasks`<br>`limit <number>`                                                                                                                                                                                                                                                                                                         |                                             |                        |                        |                                                              |
-| `limit groups to <number> tasks`<br>`limit groups <number>`                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                              |
-| **Other Layout Options**                                                                                                                                                                                                                                                                                                                              |                                             |                        |                        |                                                              |
-| `hide edit button`                                                                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                              |
-| `hide task count`                                                                                                                                                                                                                                                                                                                                     |                                             |                        |                        |                                                              |
-| `short mode`                                                                                                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                              |
-| **Other Instructions**                                                                                                                                                                                                                                                                                                                                |                                             |                        |                        |                                                              |
-| `ignore global query`                                                                                                                                                                                                                                                                                                                                 |                                             |                        |                        |                                                              |
-| `explain`                                                                                                                                                                                                                                                                                                                                             |                                             |                        |                        |                                                              |
-| `# comment`                                                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                              |
+| [[Filters]]                                                                                                                                                                                                                                                                                                                                           | [[Sorting\|Sort]]                           | [[Grouping\|Group]]    | [[Layout\|Display]]    | [[About Scripting\|Scripting]]                                               |
+| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------- | ---------------------- | ---------------------------------------------------------------------------- |
+| **[[Filters#Filters for Dates in Tasks\|Status]]**                                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                                              |
+| `done`<br>`not done`                                                                                                                                                                                                                                                                                                                                  | `sort by status`                            | `group by status`      |                        | `task.isDone`                                                                |
+| `status.name (includes, does not include) <string>`<br>`status.name (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                   | `sort by status.name`                       | `group by status.name` |                        | `task.status.name`                                                           |
+| `status.type (is, is not) (TODO, DONE, IN_PROGRESS, CANCELLED, NON_TASK)`                                                                                                                                                                                                                                                                             | `sort by status.type`                       | `group by status.type` |                        | `task.status.type`<br>`task.status.typeGroupText`                            |
+|                                                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        | `task.status.symbol`                                                         |
+|                                                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        | `task.status.nextSymbol`                                                     |
+| **[[Filters#Filters for Dates in Tasks\|Dates]]**                                                                                                                                                                                                                                                                                                     |                                             |                        |                        |                                                                              |
+| `done (on, before, after, on or before, on or after) <date>`<br>`done (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has done date`<br>`no  done date`<br>`done date is invalid`                          | `sort by done`                              | `group by done`        | `hide done date`       | `task.done`                                                                  |
+| `created (on, before, after, on or before, on or after) <date>`<br>`created (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has created date`<br>`no  created date`<br>`created date is invalid`           | `sort by created`                           | `group by created`     | `hide created date`    | `task.created`                                                               |
+| `starts (on, before, after, on or before, on or after) <date>`<br>`starts (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has start date`<br>`no  start date`<br>`start date is invalid`                   | `sort by start`                             | `group by start`       | `hide start date`      | `task.start`                                                                 |
+| `scheduled (on, before, after, on or before, on or after) <date>`<br>`scheduled (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has scheduled date`<br>`no  scheduled date`<br>`scheduled date is invalid` | `sort by scheduled`                         | `group by scheduled`   | `hide scheduled date`  | `task.scheduled`                                                             |
+| `due (on, before, after, on or before, on or after) <date>`<br>`due (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has due date`<br>`no  due date`<br>`due date is invalid`                               | `sort by due`                               | `group by due`         | `hide due date`        | `task.due`                                                                   |
+| `happens (on, before, after, on or before, on or after) <date>`<br>`happens (in, before, after, in or before, in or after) ...`<br>`... YYYY-MM-DD YYYY-MM-DD`<br>`... (last, this, next) (week, month, quarter, year)`<br>`... (YYYY-Www,YYYY-mm, YYYY-Qq, YYYY)`<br>`has happens date`<br>`no  happens date`                                        | `sort by happens`                           | `group by happens`     |                        | `task.happens`                                                               |
+| **[[Filters#Recurrence\|Recurrence]]**                                                                                                                                                                                                                                                                                                                |                                             |                        |                        |                                                                              |
+| `is recurring`<br>`is not recurring`                                                                                                                                                                                                                                                                                                                  | `sort by recurring`                         | `group by recurring`   |                        | `task.isRecurring`                                                           |
+| `recurrence (includes, does not include) <string>`<br>`recurrence (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                     |                                             | `group by recurrence`  | `hide recurrence rule` | `task.recurrenceRule`                                                        |
+| **[[Filters#Priority\|Priority]]** and **[[Urgency\|urgency]]**                                                                                                                                                                                                                                                                                       |                                             |                        |                        |                                                                              |
+| `priority is (above, below, not)? (lowest, low, none, medium, high, highest)`                                                                                                                                                                                                                                                                         | `sort by priority`                          | `group by priority`    | `hide priority`        | `task.priorityName`<br>`task.priorityNameGroupText`<br>`task.priorityNumber` |
+|                                                                                                                                                                                                                                                                                                                                                       | `sort by urgency`                           | `group by urgency`     | `show urgency`         | `task.urgency`                                                               |
+| **[[Filters#Filters for File Properties\|File properties]]**                                                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                                              |
+| `path (includes, does not include) <path>`<br>`path (regex matches, regex does not match) /regex/i`<br>`path includes {{query.file.path}}`<br>`path includes {{query.file.pathWithoutExtension}}`                                                                                                                                                     | `sort by path`                              | `group by path`        |                        | `task.file.path`<br>`task.file.pathWithoutExtension`                         |
+| `root (includes, does not include) <root>`<br>`root (regex matches, regex does not match) /regex/i`<br>`root includes {{query.file.root}}`                                                                                                                                                                                                            |                                             | `group by root`        |                        | `task.file.root`                                                             |
+| `folder (includes, does not include) <folder>`<br>`folder (regex matches, regex does not match) /regex/i`<br>`folder includes {{query.file.folder}}`                                                                                                                                                                                                  |                                             | `group by folder`      |                        | `task.file.folder`                                                           |
+| `filename (includes, does not include) <filename>`<br>`filename (regex matches, regex does not match) /regex/i`<br>`filename includes {{query.file.filename}}`<br>`filename includes {{query.file.filenameWithoutExtension}}`                                                                                                                         | `sort by filename`                          | `group by filename`    |                        | `task.file.filename`<br>`task.file.filenameWithoutExtension`                 |
+| `heading (includes, does not include) <string>`<br>`heading (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                           | `sort by heading`                           | `group by heading`     |                        | `task.hasHeading`<br>`task.heading`                                          |
+|                                                                                                                                                                                                                                                                                                                                                       |                                             | `group by backlink`    | `hide backlink`        |                                                                              |
+| **[[Filters#Description\|Description]]**, **[[Filters#Tags\|Tags]]** and other odds and ends                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                                              |
+| `description (includes, does not include) <string>`<br>`description (regex matches, regex does not match) /regex/i`                                                                                                                                                                                                                                   | `sort by description`                       |                        |                        | `task.description`<br>`task.descriptionWithoutTags`                          |
+| `has tags`<br>`no tags`<br>`tag (includes, does not include) <tag>`<br>`tags (include, do not include) <tag>`<br>`tag (regex matches, regex does not match) /regex/i`<br>`tags (regex matches, regex does not match) /regex/i`                                                                                                                        | `sort by tag`<br>`sort by tag <tag_number>` | `group by tags`        | `hide tags`            | `task.tags`                                                                  |
+|                                                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        | `task.originalMarkdown`                                                      |
+| **[[About Scripting\|Scripting]]**                                                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                                              |
+| `filter by function`                                                                                                                                                                                                                                                                                                                                  |                                             | `group by function`    |                        |                                                                              |
+| **[[Combining Filters]]**                                                                                                                                                                                                                                                                                                                             |                                             |                        |                        |                                                                              |
+| `(filter 1) AND (filter 2)`                                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                                              |
+| `(filter 1) OR (filter 2)`                                                                                                                                                                                                                                                                                                                            |                                             |                        |                        |                                                                              |
+| `NOT (filter 1)`                                                                                                                                                                                                                                                                                                                                      |                                             |                        |                        |                                                                              |
+| `(filter 1) XOR (filter 2)`                                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                                              |
+| `(filter 1) AND NOT (filter 2)`                                                                                                                                                                                                                                                                                                                       |                                             |                        |                        |                                                                              |
+| `(filter 1) OR NOT (filter 2)`                                                                                                                                                                                                                                                                                                                        |                                             |                        |                        |                                                                              |
+| `(filter 1) AND ((filter 2) OR (filter 3))`                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                                              |
+| **Other Filter Options**                                                                                                                                                                                                                                                                                                                              |                                             |                        |                        |                                                                              |
+| `exclude sub-items`                                                                                                                                                                                                                                                                                                                                   |                                             |                        |                        |                                                                              |
+| `limit to <number> tasks`<br>`limit <number>`                                                                                                                                                                                                                                                                                                         |                                             |                        |                        |                                                                              |
+| `limit groups to <number> tasks`<br>`limit groups <number>`                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                                              |
+| **Other Layout Options**                                                                                                                                                                                                                                                                                                                              |                                             |                        |                        |                                                                              |
+| `hide edit button`                                                                                                                                                                                                                                                                                                                                    |                                             |                        |                        |                                                                              |
+| `hide task count`                                                                                                                                                                                                                                                                                                                                     |                                             |                        |                        |                                                                              |
+| `short mode`                                                                                                                                                                                                                                                                                                                                          |                                             |                        |                        |                                                                              |
+| **Other Instructions**                                                                                                                                                                                                                                                                                                                                |                                             |                        |                        |                                                                              |
+| `ignore global query`                                                                                                                                                                                                                                                                                                                                 |                                             |                        |                        |                                                                              |
+| `explain`                                                                                                                                                                                                                                                                                                                                             |                                             |                        |                        |                                                                              |
+| `# comment`                                                                                                                                                                                                                                                                                                                                           |                                             |                        |                        |                                                                              |
diff --git a/docs/Scripting/Task Properties.md b/docs/Scripting/Task Properties.md
index 3e5a156f..f0094f40 100644
--- a/docs/Scripting/Task Properties.md
+++ b/docs/Scripting/Task Properties.md
@@ -29,11 +29,14 @@ For more information, including adding your own customised statuses, see [[Statu
 | `task.isDone` | `boolean` | `false` | `boolean` | `false` |
 | `task.status.name` | `string` | `'Todo'` | `string` | `'In Progress'` |
 | `task.status.type` | `string` | `'TODO'` | `string` | `'IN_PROGRESS'` |
+| `task.status.typeGroupText` | `string` | `'%%2%%TODO'` | `string` | `'%%1%%IN_PROGRESS'` |
 | `task.status.symbol` | `string` | `' '` | `string` | `'/'` |
 | `task.status.nextSymbol` | `string` | `'x'` | `string` | `'x'` |
 
 <!-- placeholder to force blank line after included text --><!-- endInclude -->
 
+1. `task.status.typeGroupText` (added in Tasks X.Y.Z) is a convenient way to sort status types in to a natural order in custom grouping functions.
+
 ## Values for Dates in Tasks
 
 <!-- placeholder to force blank line before included text --><!-- include: TaskProperties.test.task_dates.approved.md -->
@@ -65,6 +68,7 @@ For more information, including adding your own customised statuses, see [[Statu
 | `task.descriptionWithoutTags` | `string` | `'Do exercises'` | `string` | `'minimal task'` |
 | `task.priorityNumber` | `number` | `2` | `number` | `3` |
 | `task.priorityName` | `string` | `'Medium'` | `string` | `'Normal'` |
+| `task.priorityNameGroupText` | `string` | `'%%2%%Medium priority'` | `string` | `'%%3%%Normal priority'` |
 | `task.urgency` | `number` | `3.3000000000000007` | `number` | `1.9500000000000002` |
 | `task.isRecurring` | `boolean` | `true` | `boolean` | `false` |
 | `task.recurrenceRule` | `string` | `'every day when done'` | `string` | `''` |
@@ -75,6 +79,7 @@ For more information, including adding your own customised statuses, see [[Statu
 
 1. `task.description` has spaces at the start and end stripped off.
 1. `task.description` includes any tags.
+1. `task.priorityNameGroupText` (added in Tasks X.Y.Z) is a convenient way to sort priority names in to a natural order in custom grouping functions.
 1. `task.isRecurring` is:
     - `true` if the Task has a **valid** recurrence rule,
     - `false` if:
diff --git a/src/Query/Filter/PriorityField.ts b/src/Query/Filter/PriorityField.ts
index 3296f943..b6a299b2 100644
--- a/src/Query/Filter/PriorityField.ts
+++ b/src/Query/Filter/PriorityField.ts
@@ -2,7 +2,6 @@ import { Priority, Task } from '../../Task';
 import { Explanation } from '../Explain/Explanation';
 import type { Comparator } from '../Sorter';
 import type { GrouperFunction } from '../Grouper';
-import { PriorityTools } from '../../lib/PriorityTools';
 import { Field } from './Field';
 import { Filter } from './Filter';
 import { FilterOrErrorMessage } from './FilterOrErrorMessage';
@@ -93,10 +92,7 @@ export class PriorityField extends Field {
 
     public grouper(): GrouperFunction {
         return (task: Task) => {
-            const priorityName = PriorityTools.priorityNameUsingNormal(task.priority);
-            // Text inside the %%..%% comments is used to control the sort order.
-            // The comments are hidden by Obsidian when the headings are rendered.
-            return [`%%${task.priority}%%${priorityName} priority`];
+            return [task.priorityNameGroupText];
         };
     }
 }
diff --git a/src/Query/Filter/StatusTypeField.ts b/src/Query/Filter/StatusTypeField.ts
index 1ec08b39..51908410 100644
--- a/src/Query/Filter/StatusTypeField.ts
+++ b/src/Query/Filter/StatusTypeField.ts
@@ -113,30 +113,6 @@ export class StatusTypeField extends Field {
     }
 
     private static groupName(task: Task) {
-        let prefix: string;
-        // Add a numeric prefix to sort in to a meaningful order for users
-        switch (task.status.type) {
-            case StatusType.IN_PROGRESS:
-                prefix = '1';
-                break;
-            case StatusType.TODO:
-                prefix = '2';
-                break;
-            case StatusType.DONE:
-                prefix = '3';
-                break;
-            case StatusType.CANCELLED:
-                prefix = '4';
-                break;
-            case StatusType.NON_TASK:
-                prefix = '5';
-                break;
-            case StatusType.EMPTY:
-                prefix = '6';
-                break;
-        }
-        // Text inside the %%..%% comments is used to control the sorting in both sorting of tasks and naming of groups.
-        // The comments are hidden by Obsidian when the headings are rendered.
-        return `%%${prefix}%%${task.status.type}`;
+        return task.status.typeGroupText;
     }
 }
diff --git a/src/Status.ts b/src/Status.ts
index 875c51b8..86291beb 100644
--- a/src/Status.ts
+++ b/src/Status.ts
@@ -110,6 +110,41 @@ export class Status {
         return this.configuration.type;
     }
 
+    /**
+     * Returns the text to be used to represent the {@link StatusType} in group headings.
+     *
+     * The status types are in the same order as given by 'group by status.type'.
+     * This is provided as a convenience for use in custom grouping.
+     */
+    public get typeGroupText(): string {
+        const type = this.type;
+        let prefix: string;
+        // Add a numeric prefix to sort in to a meaningful order for users
+        switch (type) {
+            case StatusType.IN_PROGRESS:
+                prefix = '1';
+                break;
+            case StatusType.TODO:
+                prefix = '2';
+                break;
+            case StatusType.DONE:
+                prefix = '3';
+                break;
+            case StatusType.CANCELLED:
+                prefix = '4';
+                break;
+            case StatusType.NON_TASK:
+                prefix = '5';
+                break;
+            case StatusType.EMPTY:
+                prefix = '6';
+                break;
+        }
+        // Text inside the %%..%% comments is used to control the sorting in both sorting of tasks and naming of groups.
+        // The comments are hidden by Obsidian when the headings are rendered.
+        return `%%${prefix}%%${type}`;
+    }
+
     /**
      * Creates an instance of Status. The registry will be added later in the case
      * of the default statuses.
diff --git a/src/Task.ts b/src/Task.ts
index 9e875530..6f07c12b 100644
--- a/src/Task.ts
+++ b/src/Task.ts
@@ -473,6 +473,19 @@ export class Task {
         return Number.parseInt(this.priority);
     }
 
+    /**
+     * Returns the text to be used to represent the {@link priority} in group headings.
+     *
+     * Hidden text is used to sort the priorities in decreasing order, from
+     * {@link Priority.Highest} to {@link Priority.Lowest}.
+     */
+    public get priorityNameGroupText(): string {
+        const priorityName = PriorityTools.priorityNameUsingNormal(this.priority);
+        // Text inside the %%..%% comments is used to control the sort order.
+        // The comments are hidden by Obsidian when the headings are rendered.
+        return `%%${this.priority}%%${priorityName} priority`;
+    }
+
     /**
      * Return a copy of the description, with any tags removed.
      *


Test patch:
diff --git a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_docs.approved.md b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_docs.approved.md
index d2131d05..e34cc3bc 100644
--- a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_docs.approved.md
+++ b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_docs.approved.md
@@ -4,9 +4,9 @@
     - Group by the task's priority name.
     - The priority names are displayed in alphabetical order.
     - Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'.
-- ```group by function '%%' + task.priorityNumber.toString() + '%%' + task.priorityName +' priority'```
+- ```group by function task.priorityNameGroupText```
     - Group by the task's priority name.
-    - The hidden priority number ensures that the headings are written from highest to lowest priority.
+    - The priority names are displayed from highest to lowest priority.
     - Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'.
 
 
diff --git a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_results.approved.txt b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_results.approved.txt
index 1014e7a3..f7364e10 100644
--- a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_results.approved.txt
+++ b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.other_properties_task.priorityName_results.approved.txt
@@ -16,9 +16,9 @@ Normal
 ====================================================================================
 
 
-group by function '%%' + task.priorityNumber.toString() + '%%' + task.priorityName +' priority'
+group by function task.priorityNameGroupText
 Group by the task's priority name.
-The hidden priority number ensures that the headings are written from highest to lowest priority.
+The priority names are displayed from highest to lowest priority.
 Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'.
 =>
 %%0%%Highest priority
diff --git a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_docs.approved.md b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_docs.approved.md
index 0c76d3d6..0e5d8711 100644
--- a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_docs.approved.md
+++ b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_docs.approved.md
@@ -2,6 +2,8 @@
 
 - ```group by function task.status.type```
     - Unlike "group by status.type", this sorts the status types in alphabetical order.
+- ```group by function task.status.typeGroupText```
+    - This sorts the status types in the same order as "group by status.type".
 
 
 <!-- placeholder to force blank line after included text -->
diff --git a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_results.approved.txt b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_results.approved.txt
index 74f853f2..d04dc56a 100644
--- a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_results.approved.txt
+++ b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.statuses_task.status.type_results.approved.txt
@@ -12,3 +12,14 @@ IN_PROGRESS
 TODO
 ====================================================================================
 
+
+group by function task.status.typeGroupText
+This sorts the status types in the same order as "group by status.type".
+=>
+%%1%%IN_PROGRESS
+%%2%%TODO
+%%3%%DONE
+%%4%%CANCELLED
+%%6%%EMPTY
+====================================================================================
+
diff --git a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.ts b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.ts
index 12d159fd..ca507ec2 100644
--- a/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.ts
+++ b/tests/Scripting/ScriptingReference/CustomGrouping/CustomGroupingExamples.test.ts
@@ -304,6 +304,10 @@ describe('statuses', () => {
                     'group by function task.status.type',
                     'Unlike "group by status.type", this sorts the status types in alphabetical order',
                 ],
+                [
+                    'group by function task.status.typeGroupText',
+                    'This sorts the status types in the same order as "group by status.type"',
+                ],
             ],
             SampleTasks.withAllStatuses(),
         ],
@@ -426,9 +430,9 @@ describe('other properties', () => {
                     "Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'",
                 ],
                 [
-                    "group by function '%%' + task.priorityNumber.toString() + '%%' + task.priorityName +' priority'",
+                    'group by function task.priorityNameGroupText',
                     "Group by the task's priority name",
-                    'The hidden priority number ensures that the headings are written from highest to lowest priority.',
+                    'The priority names are displayed from highest to lowest priority.',
                     "Note that the default priority is called 'Normal', as opposed to with `group by priority` which calls the default 'None'",
                 ],
             ],
diff --git a/tests/Scripting/TaskProperties.test.task_other_fields.approved.md b/tests/Scripting/TaskProperties.test.task_other_fields.approved.md
index 2814aaed..c43fffae 100644
--- a/tests/Scripting/TaskProperties.test.task_other_fields.approved.md
+++ b/tests/Scripting/TaskProperties.test.task_other_fields.approved.md
@@ -6,6 +6,7 @@
 | `task.descriptionWithoutTags` | `string` | `'Do exercises'` | `string` | `'minimal task'` |
 | `task.priorityNumber` | `number` | `2` | `number` | `3` |
 | `task.priorityName` | `string` | `'Medium'` | `string` | `'Normal'` |
+| `task.priorityNameGroupText` | `string` | `'%%2%%Medium priority'` | `string` | `'%%3%%Normal priority'` |
 | `task.urgency` | `number` | `3.3000000000000007` | `number` | `1.9500000000000002` |
 | `task.isRecurring` | `boolean` | `true` | `boolean` | `false` |
 | `task.recurrenceRule` | `string` | `'every day when done'` | `string` | `''` |
diff --git a/tests/Scripting/TaskProperties.test.task_status.approved.md b/tests/Scripting/TaskProperties.test.task_status.approved.md
index ffa089c9..19eedcfa 100644
--- a/tests/Scripting/TaskProperties.test.task_status.approved.md
+++ b/tests/Scripting/TaskProperties.test.task_status.approved.md
@@ -5,6 +5,7 @@
 | `task.isDone` | `boolean` | `false` | `boolean` | `false` |
 | `task.status.name` | `string` | `'Todo'` | `string` | `'In Progress'` |
 | `task.status.type` | `string` | `'TODO'` | `string` | `'IN_PROGRESS'` |
+| `task.status.typeGroupText` | `string` | `'%%2%%TODO'` | `string` | `'%%1%%IN_PROGRESS'` |
 | `task.status.symbol` | `string` | `' '` | `string` | `'/'` |
 | `task.status.nextSymbol` | `string` | `'x'` | `string` | `'x'` |
 
diff --git a/tests/Scripting/TaskProperties.test.ts b/tests/Scripting/TaskProperties.test.ts
index e4f0e839..85f5435b 100644
--- a/tests/Scripting/TaskProperties.test.ts
+++ b/tests/Scripting/TaskProperties.test.ts
@@ -48,6 +48,7 @@ describe('task', () => {
             'task.isDone',
             'task.status.name',
             'task.status.type',
+            'task.status.typeGroupText',
             'task.status.symbol',
             'task.status.nextSymbol',
         ]);
@@ -70,6 +71,7 @@ describe('task', () => {
             'task.descriptionWithoutTags',
             'task.priorityNumber',
             'task.priorityName',
+            'task.priorityNameGroupText',
             'task.urgency',
             'task.isRecurring',
             'task.recurrenceRule',
diff --git a/tests/Status.test.ts b/tests/Status.test.ts
index 2057c15d..08699fde 100644
--- a/tests/Status.test.ts
+++ b/tests/Status.test.ts
@@ -123,6 +123,11 @@ describe('Status', () => {
         expect(status.type).toEqual(StatusType.NON_TASK);
         expect(status.availableAsCommand).toEqual(false);
     });
+
+    it('should provide text with sorting comments for convenience of custom grouping', () => {
+        const status = Status.makeCancelled();
+        expect(status.typeGroupText).toEqual('%%4%%CANCELLED');
+    });
 });
 
 describe('identicalTo', () => {