How to generate a grouped list of shortcuts by inline ⁠[category::…] property?

First, search the help docs and this forum. Maybe your question has been answered! The debugging steps can help, too. Still stuck? Delete this line and proceed.

What I’m trying to do

I maintain a list of keyboard shortcuts in Obsidian, and each shortcut lives in a list item like this:

  • #shortcuts #tool/Raycast » ♦︎ / → Improve Writing [category::ai]
  • #shortcuts #tool/Raycast » K` → Open Palette [category::ui]
  • #shortcuts #tool/Raycast » G` → Google Chrome

I want a pure-Dataview query (no DataviewJS) that:

  • Filters only items tagged ⁠#shortcuts and ⁠#tool/
  • Extracts the inline ⁠[category::…] property from each list item
  • Groups the shortcuts by their ⁠category value (showing uncategorized under a blank or “none” group)
  • Uses ⁠LIST WITHOUT ID so that Dataview renders each category as a sub-list heading
    The end result should look roughly like:
    • ai
    • ⁠♦︎ / → Improve Writing
    • ui
    • ⁠⌘K⁠** → Open Palette • (no category) • **⌘⁠G → Google Chrome

Things I have tried

```dataview
LIST WITHOUT ID T.text
FROM 
	#shortcuts 
FLATTEN 
	file.lists as T 
WHERE 
	contains(T.tags, "#tool/" + this.file.name) AND contains(T.tags, "#shortcuts")
GROUP BY 
	T.category as Category
```

Resulting



And

```dataview
LIST WITHOUT ID T.text
FROM 
	#shortcuts 
FLATTEN 
	file.lists as T 
WHERE 
	contains(T.tags, "#tool/" + this.file.name) AND contains(T.tags, "#shortcuts")
```

Resulting

1. Basic LIST + FLATTEN, grouping on a non-existent ⁠T.category field:

LIST WITHOUT ID T.text
FROM #shortcuts
FLATTEN file.lists AS T
WHERE contains(T.tags, "#tool/" + this.file.name)
  AND contains(T.tags, "#shortcuts")
GROUP BY T.category AS Category

2. Attempted to extract category via regex in the LIST expression—Dataview parsing errors:

LIST WITHOUT ID
  (regexreplace(split(text,"»")[0],".*\\*\\*(.+?)\\*\\*.*","$1")
   + " → "
   + regexreplace(text,".*→\\s*(.+)$","$1")) AS Shortcut
FROM #shortcuts
WHERE contains(tags,"#tool/"+this.file.name)
FLATTEN regexmatch("\\[category::([^\\]]+)\\]",text).groups[0] AS Category
GROUP BY Category

3. Simplified to raw ⁠text AS Shortcut—still no grouping because ⁠Category is not recognized:

LIST WITHOUT ID text AS Shortcut
FROM #shortcuts
WHERE contains(tags,"#tool/"+this.file.name)
FLATTEN regexmatch("\\[category::([^\\]]+)\\]",text).groups[0] AS Category
GROUP BY Category

Sounds like you’re going for a query like:

LIST regexreplace(rows.t.text, "#\S+\s|»\s|\[category::\S+\]", "")
FROM #shortcuts 
FLATTEN filter(file.lists, (l) => contains(l.tags, "shortcuts") AND contains(l.tags, "tool/" + this.file.name)) AS t
GROUP BY t.category

It assumes all of your categories have no spaces, based on your examples. If you have categories with spaces, then adjust the regex for it.

You said you want WITHOUT ID, which would hide the category grouping, but you said you want to see the category grouping, so I did it the way you described not the way you prescribed.

I tried but still I’m getting empty groups:

You spelled the property key category as “cateogry”.