26 KiB
id, title, tags, state, date_saved, date_read, date_archived
| id | title | tags | state | date_saved | date_read | date_archived | |
|---|---|---|---|---|---|---|---|
| id-generated-by-omnivore | Grouping - Tasks User Guide - Obsidian Publish |
|
ARCHIVED | 2023-07-16 10:23:40 | 2023-07-16 12:18:14 | 2023-07-16T10:05:16.592Z |
Grouping - Tasks User Guide - Obsidian Publish
#Omnivore
Read on Omnivore Read Original
Webpage
Grouping
Contents
This page is long. Here are some links to the main sections:
- Basics
- Custom Groups
- Group by Task Statuses
- Group by Dates in Tasks
- Group by Other Task Properties
- Group by File Properties
- Multiple groups
- Refining groups
- Notes
- Screenshots
- Examples
Basics
Introduced in Tasks 1.6.0.
By default, Tasks displays tasks in a single list.
To divide the matching tasks up with headings, you can add group by lines to the query.
Custom Groups
group by function was introduced in Tasks 4.0.0.
Tasks provides many built-in grouping options, but sometimes they don't quite do what is wanted by all users.
Now Tasks has a powerful mechanism for you to create your own custom groups, offering incredible flexibility.
There are many examples of the custom grouping instruction group by function in the documentation below, with explanations, for when the group by instructions built in to Tasks do not satisfy your preferences.
You can find out more about this very powerful facility in Custom Grouping.
Group by Task Statuses
For more information, including adding your own customised statuses, see Statuses.
Status
group by status(Done or Todo, which is capitalized for visibility in the headings)- Note that the Done group is displayed before the Todo group, which differs from the Sorting ordering of this property.
*Doneis used for tasks status typesDONE,CANCELLEDandNON_TASK
*Todois used for status types with typeTODOandIN_PROGRESS
- Note that the Done group is displayed before the Todo group, which differs from the Sorting ordering of this property.
Since Tasks 4.0.0, custom grouping by status is now possible.
group by function task.isDone ? "Action Required" : "Nothing To Do"- Use JavaScript's ternary operator to choose what to do for true (after the ?) and false (after the :) values.
Status Name
group by status.name- This groups by the names you give to your custom statuses, in alphabetical order.
group by status.name was introduced in Tasks 1.23.0.
Since Tasks 4.0.0, custom grouping by status names is now possible.
group by function task.status.name- Identical to "group by status.name".
group by function task.status.name.toUpperCase()- Convert the status names to capitals.
Status Type
group by status.type- This groups by the types you have given to your custom statuses.
- The groups will appear in this order, and with these group names:
*IN_PROGRESS
*TODO
*DONE
*CANCELLED
*NON_TASK
group by status.type was introduced in Tasks 1.23.0.
Since Tasks 4.0.0, custom grouping by status types is now possible.
group by function task.status.type- Unlike "group by status.type", this sorts the status types in alphabetical order.
Status Symbol
There is no built-in instruction to group by status symbols.
Since Tasks 4.0.0, custom grouping by status symbol is now possible.
group by function "Status symbol: " + task.status.symbol.replace(" ", "space")- Group by the status symbol, making space characters visible.
Next Status Symbol
There is no built-in instruction to group by next status symbols.
Since Tasks 4.0.0, custom grouping by next status symbol is now possible.
group by function "Next status symbol: " + task.status.nextSymbol.replace(" ", "space")- Group by the next status symbol, making space characters visible.
Group by Dates in Tasks
Due Date
-
group by due- The due date of the task, including the week-day, or
No due date.
- The due date of the task, including the week-day, or
-
duegrouping option was introduced in Tasks 1.7.0.
Since Tasks 4.0.0, custom grouping by due date is now possible.
These examples all use task.due property, which is a TasksDate object. You can see the current TasksDate source code, to explore its capabilities.
group by function task.due.format("YYYY-MM-DD dddd")- Like "group by due", except it uses no heading, instead of a heading "No due date", if there is no due date.
group by function task.due.formatAsDate()- Format date as YYYY-MM-DD or empty string (so no heading) if there is no due date.
group by function task.due.formatAsDateAndTime()- Format date as YYYY-MM-DD HH:mm or empty string if no due date.
- Note:
* This is shown for demonstration purposes.
* Currently the Tasks plugin does not support storing of times.
* Do not add times to your tasks, as it will break the reading of task data.
group by function task.due.format("YYYY[%%]-MM[%%] MMM", "no due date")- Group by month, for example
2023%%-05%% May...
* ... which gets rendered by Obsidian as2023 May. - Or show a default heading "no due date" if no date.
- The hidden month number is added, commented-out between two
%%strings, to control the sort order of headings. - To escape characters in format strings, you can wrap the characters in square brackets (here,
[%%]).
- Group by month, for example
group by function task.due.format("YYYY[%%]-MM[%%] MMM [- Week] WW")- Group by month and week number, for example
2023%%-05%% May - Week 22...
* ... which gets rendered by Obsidian as2023 May - Week 22. - If the month number is not embedded, in some years the first or last week of the year is displayed in a non-logical order.
- Group by month and week number, for example
DON'T PANIC! For users who are comfortable with JavaScript, these more complicated examples may also be of interest:
group by function task.due.moment?.fromNow() || ""- Group by the time from now, for example "8 days ago".
- Because Moment.fromNow() is not provided by TasksDate, we need special code for when there is no date value.
- Whilst interesting, the alphabetical sort order makes the headings a little hard to read.
group by function task.due.format("dddd")- Group by day of the week (Monday, Tuesday, etc).
- The day names are sorted alphabetically.
group by function task.due.format("[%%]d[%%]dddd")- Group by day of the week (Sunday, Monday, Tuesday, etc).
- The day names are sorted in date order, starting with Sunday.
group by function task.due.moment ? ( task.due.moment.day() === 0 ? task.due.format("[%%][8][%%]dddd") : task.due.format("[%%]d[%%]dddd") ) : "Undated"- Group by day of the week (Monday, Tuesday, etc).
- The day names are sorted in date order, starting with Monday.
- Tasks without due dates are displayed at the end, under a heading "Undated".
- This is best understood by pasting it in to a Tasks block in Obsidian and then deleting parts of the expression.
- The key technique is to say that if the day is Sunday (
0), then force it to be displayed as date number8, so it comes after the other days of the week.
group by function (!task.due.moment) ? '%%4%% Undated' : result = task.due.moment.isBefore(moment(), 'day') ? '%%1%% Overdue' : result = task.due.moment.isSame(moment(), 'day') ? '%%2%% Today' : '%%3%% Future'- Group task due dates in to 4 broad categories:
Overdue,Today,FutureandUndated, displayed in that order. - Try this on a line before
group by dueif there are a lot of due date headings, and you would like them to be broken down in to some kind of structure. - A limitation of Tasks expressions is that they each need to fit on a single line, so this uses nested ternary operators, making it powerful but very hard to read.
- In fact, for ease of development and testing, it was written in a full-fledged development environment as a series of if/else blocks, and then automatically refactored in these nested ternary operators.
- Group task due dates in to 4 broad categories:
group by function (!task.due.moment) ? '%%4%% ==Undated==' : result = task.due.moment.isBefore(moment(), 'day') ? '%%1%% ==Overdue==' : result = task.due.moment.isSame(moment(), 'day') ? '%%2%% ==Today==' : '%%3%% ==Future=='- As above, but the headings
Overdue,Today,FutureandUndatedare highlighted. - See the sample screenshot below.
- As above, but the headings
Sample image showing tasks grouped first by highlighted words Overdue, Today, Future and Undated, and then by individual due date.
Done Date
-
group by done- The done date of the task, including the week-day, or
No done date.
- The done date of the task, including the week-day, or
-
donegrouping option was introduced in Tasks 1.7.0.
Since Tasks 4.0.0, custom grouping by done date is now possible.
group by function task.done.format("YYYY-MM-DD dddd")- Like "group by done", except it uses an empty string instead of "No done date" if there is no done date.
Scheduled Date
-
group by scheduled- The scheduled date of the task, including the week-day, or
No scheduled date.
- The scheduled date of the task, including the week-day, or
-
scheduledgrouping option was introduced in Tasks 1.7.0.
Since Tasks 4.0.0, custom grouping by scheduled date is now possible.
group by function task.scheduled.format("YYYY-MM-DD dddd")- Like "group by scheduled", except it uses an empty string instead of "No scheduled date" if there is no scheduled date.
Start Date
-
group by start- The start date of the task, including the week-day, or
No start date.
- The start date of the task, including the week-day, or
-
startgrouping option was introduced in Tasks 1.7.0.
Since Tasks 4.0.0, custom grouping by start date is now possible.
-
group by function task.start.format("YYYY-MM-DD dddd")- Like "group by start", except it uses an empty string instead of "No start date" if there is no start date.
-
group by created- The created date of the task, including the week-day, or
No created date.
- The created date of the task, including the week-day, or
created grouping option was introduced in Tasks 2.0.0.
Since Tasks 4.0.0, custom grouping by created date is now possible.
group by function task.created.format("YYYY-MM-DD dddd")- Like "group by created", except it uses an empty string instead of "No created date" if there is no created date.
Happens
group by happens- The earliest of start date, scheduled date, and due date, including the week-day, or
No happens dateif none of those are set.
- The earliest of start date, scheduled date, and due date, including the week-day, or
happens grouping option was introduced in Tasks 1.11.0.
Since Tasks 4.0.0, custom grouping by happens date is now possible.
group by function task.happens.format("YYYY-MM-DD dddd")- Like "group by happens", except it uses an empty string instead of "No happens date" if there is no happens date.
Group by Other Task Properties
As well as the date-related groups above, groups can be created from properties in individual tasks.
Description
There is no built-in instruction to group by description.
Since Tasks 4.0.0, custom grouping by description is now possible.
group by function task.description- group by description.
- This might be useful for finding completed recurrences of the same task.
group by function task.description.toUpperCase()- Convert the description to capitals.
group by function task.description.slice(0, 25)- Truncate descriptions to at most their first 25 characters, and group by that string.
group by function task.description.replace('short', '==short==')- Highlight the word "short" in any group descriptions.
Description without tags
Since Tasks 4.2.0, it is possible to remove tags from the descriptions in custom groups, for use in custom grouping.
The value task.descriptionWithoutTags returns a copy of the description with all the tags removed, so that you can group together any tasks whose descriptions differ only by their tags.
group by function task.descriptionWithoutTags- Like
group by description, but it removes any tags from the group headings. - This might be useful for finding completed recurrences of the same task, even if the tags differ in some recurrences.
- Like
Priority
-
group by priority- The priority of the task, namely one of:
*Highest priority
*High priority
*Medium priority
*Normal priority
*Low priority
*Lowest priority
- The priority of the task, namely one of:
-
prioritygrouping option was introduced in Tasks 1.11.0.
Since Tasks 4.0.0, custom grouping by priority name and number is now possible.
Using the priority name:
group by function task.priorityName- 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 prioritywhich calls the default 'None'.
group by function '%%' + task.priorityNumber.toString() + '%%' + task.priorityName +' priority'- Group by the task's priority name.
- The hidden priority number ensures that the headings are written from highest to lowest priority.
- Note that the default priority is called 'Normal', as opposed to with
group by prioritywhich calls the default 'None'.
Using the priority number:
group by function task.priorityNumber- Group by the task's priority number, where Highest is 0 and Lowest is 5.
Urgency
-
group by urgency(urgency)- The groups run from the highest urgency to the lowest.
- You can reverse this with
group by urgency reverse.
-
urgencygrouping option was introduced in Tasks 3.6.0. -
In Tasks 4.0.0 the order of
group by urgencywas reversed, to put most urgent tasks first. Add or remove the wordreverseto get the original order.
Since Tasks 4.0.0, custom grouping by urgency is now possible.
group by function task.urgency.toFixed(3)- Show the urgency to 3 decimal places, unlike the built-in "group by urgency" which uses 2.
Recurrence
-
group by recurring- Whether the task is recurring: either
RecurringorNot Recurring.
- Whether the task is recurring: either
-
group by recurrence- The recurrence rule of the task, for example
every week on Sunday, orNonefor non-recurring tasks. - Note that the text displayed is generated programmatically and standardised, and so may not exactly match the text in any manually typed tasks. For example, a task with
🔁 every Sundayis grouped inevery week on Sunday.
- The recurrence rule of the task, for example
-
recurringandrecurrencegrouping options were introduced in Tasks 1.11.0.
Since Tasks 4.0.0, custom grouping by recurrence is now possible.
-
group by function task.isRecurring ? "Recurring" : "Non-Recurring"- Use JavaScript's ternary operator to choose what to do for true (after the ?) and false (after the :) values.
-
group by function task.recurrenceRule.replace('when done', '==when done==')- Group by recurrence rule, highlighting any occurrences of the words "when done".
Tags
-
group by tags- The tags of the tasks or
(No tags). If the task has multiple tags, it will show up under every tag.
- The tags of the tasks or
-
tagsgrouping option was introduced in Tasks 1.10.0. -
group by function task.tags- Like "group by tags" except that tasks with no tags have no heading instead of "(No tags)".
-
group by function task.tags.join(", ")- Tasks with multiple tags are listed once, with a heading that combines all the tags.
- Separating with commas means the tags are clickable in the headings.
-
group by function task.tags.sort().join(", ")- As above, but sorting the tags first ensures that the final headings are independent of order of tags in the tasks.
-
group by function task.tags.filter( (tag) => tag.includes("#context/") )- Only create headings for tags that contain "#context/".
-
group by function task.tags.filter( (tag) => ! tag.includes("#tag") )- Create headings for all tags that do not contain "#tag".
These are more complicated examples, which you might like to copy if you use tasks with nested tags and wish to group them at different tag nesting levels.
group by function task.tags.map( (tag) => tag.split('/')[0].replace('#', '') )#tag/subtag/sub-sub-taggivestag.
group by function task.tags.map( (tag) => tag.split('/')[1] ? tag.split('/').slice(1, 2) : '')#tag/subtag/sub-sub-taggivessubtag.
group by function task.tags.map( (tag) => tag.split('/')[2] ? tag.split('/').slice(2, 3) : '')#tag/subtag/sub-sub-taggivessub-sub-tag.
group by function task.tags.map( (tag) => tag.split('/')[3] ? tag.split('/').slice(3, 4) : '')#tag/subtag/sub-sub-taggives no heading, as there is no value at the 4th level.
group by function task.tags.map( (tag) => tag.split('/')[0] )#tag/subtag/sub-sub-taggives#tag.
group by function task.tags.map( (tag) => tag.split('/')[1] ? tag.split('/').slice(0, 2).join('/') : '')#tag/subtag/sub-sub-taggives#tag/subtag.
group by function task.tags.map( (tag) => tag.split('/')[2] ? tag.split('/').slice(0, 3).join('/') : '')#tag/subtag/sub-sub-taggives#tag/subtag/sub-sub-tag.
group by function task.tags.map( (tag) => tag.split('/')[3] ? tag.split('/').slice(0, 4).join('/') : '')#tag/subtag/sub-sub-taggives no heading, as there is no value at the 4th level.
Original Markdown
There is no built-in instruction to group by the original markdown line.
Since Tasks 4.0.0, custom grouping by original markdown line is now possible.
For example, this could be used to extract information from task.originalMarkdown that Tasks does not parse, to use for grouping tasks.
group by function '``' + task.originalMarkdown + '``'- Group by the raw text of the task's original line in the MarkDown file as code.
- Note the pairs of backtick characters ('`'), to preserve even single backtick characters in the task line.
- It's important to prevent the task checkbox (for example, '[ ]') from being rendered in the heading, as it gets very confusing if there are checkboxes on both headings and tasks.
group by function task.originalMarkdown.replace(/^[^\[\]]+\[.\] */, '')- An alternative to formatting the markdown line as code is to remove everything up to the end of the checkbox.
- Then render the rest of the task line as normal markdown.
Group by File Properties
File Path
group by path(the path to the file that contains the task, that is, the folder and the filename)
Since Tasks 4.0.0, custom grouping by file path is now possible.
group by function task.file.path- Like 'group by path' but includes the file extension.
Root
group by root(the top-level folder of the file that contains the task, that is, the first directory in the path, which will be/for files in root of the vault)
root grouping option was introduced in Tasks 1.11.0.
Since Tasks 4.0.0, custom grouping by root folder is now possible.
group by function task.file.root- Same as 'group by root'.
Folder
group by folder(the folder to the file that contains the task, which always ends in/and will be exactly/for files in root of the vault)
Since Tasks 4.0.0, custom grouping by folder is now possible.
group by function task.file.folder- Same as 'group by folder'.
group by function task.file.folder.slice(0, -1).split('/').pop() + '/'- Group by the immediate parent folder of the file containing task.
- Here's how it works:
* '.slice(0, -1)' removes the trailing slash ('/') from the original folder.
* '.split('/')' divides the remaining path up in to an array of folder names.
* '.pop()' returns the last folder name, that is, the parent of the file containing the task.
* Then the trailing slash is added back, to ensure we do not get an empty string for files in the top level of the vault.
File Name
group by filename(the link to the file that contains the task, without the.mdextension)- Note that tasks from different notes with the same file name will be grouped together in the same group.
Since Tasks 4.0.0, custom grouping by file name is now possible.
group by function task.file.filename- Like 'group by filename' but does not link to the file.
group by function '[[' + task.file.filename.replace('.md', '') + ( task.hasHeading ? ('#' + task.heading) : '') + ']]'- Like 'group by backlink' but links to the heading in the file.
Backlink
group by backlink(the text that would be shown in the task's backlink, combining the task's file name and heading, but with no link added)
Heading
group by heading(the heading preceding the task, or(No heading)if there are no headings in the file)
Since Tasks 4.0.0, custom grouping by heading is now possible.
group by function (task.heading + '.md' === task.file.filename) ? '' : task.heading- Group by heading, but only if the heading differs from the file name.
- This works well immediately after a 'group by filename' line.
- Note the three equals signs '===': these are important for safety in JavaScript.
Multiple groups
You can add multiple group by query options, each on an extra line. This will create nested groups. The first group has the highest priority.
Each subsequent group by will generate a new heading-level within the existing grouping:
- First
group byis displayed ash4headings - Second
group byis displayed ash5headings - Third and subsequent
group byare displayed ash6headings
Headings are displayed in case-sensitive alphabetical order, not the original order.
Refining groups
Reversing groups
Reversing of group headings was introduced in Tasks 3.7.0.
After the name of the property that you want to group by, you can add the reverse keyword. If given, the group headings will be reversed for that property.
For example:
group by duewill sort the group headings:- from oldest due date first...
- to newest due date last
group by due reversewill sort the group headings:- from newest due date first...
- to oldest due date last
The reverse keyword controls the order that group headings are displayed.
The sort by facility, by contrast, controls the order in which displays are displayed inside each group.
Limiting group size
You can limit the number of tasks in each group, perhaps to work on the most important things first.
Notes
The order of operations ensures that grouping does not modify which tasks are displayed, for example when the limit options are used:
- all the filter instructions are run
- then any sorting instructions are run
- then any
limitinstructions are run - then any grouping instructions are run
- then any
limit groupsinstructions are run
Screenshots
Before
Here is an example Tasks result, without any group by commands:
Tasks not grouped.
After
And here is what this might look like, when grouped by folder, filename and heading:
Tasks grouped.
Examples
Give me three levels of grouping, to indicate the locations of my tasks:
```tasks
not done
group by folder
group by filename
group by heading
Show me tasks I need to do today - and put today's tasks first, for visibility:
```routeros
```tasks
not done
due before tomorrow
group by due reverse
Grouping


