/todo-tree

Use ripgrep to find TODO tags and display the results in a tree view

Primary LanguageJavaScriptOtherNOASSERTION

Todo Tree

Build Status

This extension quickly searches (using ripgrep your workspace for comment tags like TODO and FIXME, and displays them in a tree view in the explorer pane. Clicking a TODO within the tree will open the file and put the cursor on the line containing the TODO.

Found TODOs can also be highlighted in open files.

Please see the wiki for configuration examples.

screenshot

Notes:

  • The tree will only appear in the explorer pane when the extension finds some TODOs, unless todo-tree.tree.hideTreeWhenEmpty is set to false.
  • User rg.conf files are ignored.

Highlighting

Highlighting tags is configurable. Use defaultHighlight to set up highlights for all tags. If you need to configure individual tags differently, use customHighlight. If settings are not specified in customHighlight, the value from defaultHighlight is used. If a setting is not specified in defaultHighlight then the older, deprecated icon, iconColour and iconColours settings are used.

Both defaultHighlight and customHighlight allow for the following settings:

foreground - used to set the foreground colour of the highlight in the editor and the marker in the ruler.

background - used to set the background colour of the highlight in the editor.

Note: Foreground and background colours can be specified using HTML/CSS colour names (e.g. "Salmon"), RGB hex values (e.g. "#80FF00"), RGB CSS style values (e.g. "rgb(255,128,0)" or colours from the current theme, e.g. peekViewResult.background. Hex and RGB values can also have an alpha specified, e.g. "#ff800080" or "rgba(255,128,0,0.5)".

opacity - percentage value used with the background colour. 100% will produce an opaque background which will obscure selection and other decorations. Note: opacity can only be specified when hex or rgb colours are used.

fontWeight, fontStyle, textDecoration - can be used to style the highlight with standard CSS values.

borderRadius - used to set the border radius of the background of the highlight.

icon - used to set a different icon in the tree view. Must be a valid octicon (see https://octicons.github.com) or codicon (see https://microsoft.github.io/vscode-codicons/dist/codicon.html). If using codicons, specify them in the format "$(icon)". The icon defaults to a tick if it's not valid. You can also use "todo-tree", or "todo-tree-filled" if you want to use the icon from the activity view.

iconColour - used to set the colour of the icon in the tree. If not specified, it will try to use the foreground colour or the background colour. Colour can be specified as per foreground and background colours, except that theme colours are only available when using codicons. Theme colours are not supported for octicons.

gutterIcon - set to true to show the icon in the editor gutter. Note: Unfortunately, only octicons and the todo-tree icon can be displayed in the gutter.

rulerColour - used to set the colour of the marker in the overview ruler. If not specified, it will default to use the foreground colour. Colour can be specified as per foreground and background colours.

rulerLane - used to set the lane for the marker in the overview ruler. If not specified, it will default to the right hand lane. Use one of "left", "center", "right", or "full". You can also use "none" to disable the ruler markers.

type - used to control how much is highlighted in the editor. Valid values are:

  • tag - highlights just the tag
  • text - highlights the tag and any text after the tag
  • tag-and-comment - highlights the comment characters (or the start of the match) and the tag
  • text-and-comment - highlights the comment characters (or the start of the match), the tag and the text after the tag
  • line - highlights the entire line containing the tag
  • whole-line - highlights the entire line containing the tag to the full width of the editor

hideFromTree - used to hide tags from the tree, but still highlight in files

hideFromStatusBar - prevents the tag from being included in the status bar counts

Example:

"todo-tree.highlights.defaultHighlight": {
    "icon": "alert",
    "type": "text",
    "foreground": "red",
    "background": "white",
    "opacity": 50,
    "iconColour": "blue"
},
"todo-tree.highlights.customHighlight": {
    "TODO": {
        "icon": "check",
        "type": "line"
    },
    "FIXME": {
        "foreground": "black",
        "iconColour": "yellow",
        "gutterIcon": true
    }
}

Note: The highlight configuration is separate from the settings for the search. Adding settings in customHighlight does not automatically add the tags into todo-tree.general.tags.

Installing

You can install the latest version of the extension via the Visual Studio Marketplace here.

Alternatively, open Visual Studio code, press Ctrl+P or Cmd+P and type:

> ext install Gruntfuggly.todo-tree

Note: Don't forget to reload the window to activate the extension!

Source Code

The source code is available on GitHub here.

Controls

The tree view header can contain the following buttons:

collapse - Collapse all tree nodes
expand - Expand all tree nodes
flat - Show the tree view as a flat list, with the full filename for each TODO
tags - Show the view as a list of tags
tree - Show the tree view as a tree with expandable nodes for each folder (default)
tag - Group the TODOs in the tree by the tag
notag - Organise the TODOs by file (default)
filter - Only show items in the tree which match the entered filter text
clear-filter - Remove any active filter
refresh - Rebuild the tree
scan-open-files - Show tags from open files only
scan-workspace - Show tags from workspace
scan-current-file - Show the current file in the tree

Folder Filter Context Menu

Right clicking on a folder in the tree will bring up a context menu with the following options:

Hide This Folder - removes the folder from the tree

Only Show This Folder - remove all other folders and subfolders from the tree

Only Show This Folder And Subfolders - remove other folders from the tree, but keep subfolders

Reset Folder Filter - reset any folders previously filtered using the above

Note: The current filters are shown in the debug log. Also, the filter can always be reset by right clicking the Nothing Found item in the tree. If your tree becomes invisible because everything is filtered and hideTreeWhenEmpty is set to true, you can reset the filter by pressing F1 and selecting the Todo Tree: Reset Folder Filter command.

Commands

Tags

To make it easier to configure the tags, there are two commands available:

Todo Tree: Add Tag - allows entry of a new tag for searching

Todo Tree: Remove Tag - shows a list of current tags which can be selected for removing

Note: The Remove Tag command can be used to show current tags - just press Escape or Enter with out selecting any to close it.

Export

The contents of the tree can be exported using Todo Tree: Export Tree. A read-only file will be created using the path specified with todo-tree.general.exportPath. The file can be saved using File: Save As.... Note: Currently File: Save does not work which seems to be a VSCode bug (see microsoft/vscode#101952).

Configuration

The extension can be customised as follows (default values in brackets):

todo-tree.general.debug (false)
Show a debug channel in the output view.

todo-tree.general.enableFileWatcher (false)
Set this to true to turn on automatic updates when files in the workspace are created, changed or deleted.

todo-tree.general.exportPath (~/todo-tree-%Y%m%d-%H%M.txt)
Path to use when exporting the tree. Environment variables will be expanded, e.g ${HOME} and the path is passed through strftime (see https://github.com/samsonjs/strftime). Set the extension to .json to export as a JSON record.

todo-tree.general.rootFolder ("")
By default, any open workspaces will have a tree in the view. Use this to force another folder to be the root of the tree. You can include environment variables and also use ${workspaceFolder}. e.g.
"todo-tree.general.rootFolder": "${workspaceFolder}/test"
or
"todo-tree.general.rootFolder": "${HOME}/project".
Note: Other open files (outside of the rootFolder) will be shown (as they are opened) with their full path in brackets.

todo-tree.general.tags (["TODO","FIXME","BUG"])
This defines the tags which are recognised as TODOs. This list is automatically inserted into the regex.

todo-tree.general.tagGroups ({})
This setting allows multiple tags to be treated as a single group. Example:

    "todo-tree.general.tagGroups": {
        "FIXME": [
            "FIXME",
            "FIXIT",
            "FIX",
        ]
    },

This treats any of FIXME, FIXIT or FIX as FIXME. When the tree is grouped by tag, all of these will appear under the FIXME node. This also means that custom highlights are applied to the group, not each tag type. Note: all tags in the group should also appear in todo-tree.general.tags.

todo-tree.general.revealBehaviour (start of todo)
Change the cursor behaviour when selecting a todo from the explorer. Yo.u can choose from: start of todo (moves the cursor to the beginning of the todo), end of todo (moves the cursor to the end of the todo) highlight todo (selects the todo text), start of line (moves the cursor to the start of the line) and highlight line (selected the whole line)

todo-tree.general.statusBar (none)
What to show in the status bar - nothing (none), total count (total), counts per tag (tags), counts for the top three tags (top three) or counts for the current file only (current file).

todo-tree.general.statusBarClickBehaviour (cycle)
Set the behaviour of clicking the status bar to either cycle display formats, or reveal the tree.

todo-tree.filtering.includeGlobs ([])
Globs for use in limiting search results by inclusion, e.g. [\"**/unit-tests/*.js\"] to only show .js files in unit-tests subfolders. Globs help. Note: globs paths are absolute - not relative to the current workspace.

todo-tree.filtering.excludeGlobs ([])
Globs for use in limiting search results by exclusion (applied after includeGlobs), e.g. [\"**/*.txt\"] to ignore all .txt files

todo-tree.filtering.includedWorkspaces ([])
A list of workspace names to include as roots in the tree (wildcards can be used). An empty array includes all workspace folders.

todo-tree.filtering.excludedWorkspaces ([])
A list of workspace names to exclude as roots in the tree (wildcards can be used).

todo-tree.filtering.passGlobsToRipgrep (true)
Set this to false to apply the globs after the search (legacy behaviour).

todo-tree.filtering.useBuiltInExcludes (none)
Set this to use VSCode's built in files or search excludes. Can be one of none, file excludes (uses Files:Exclude), search excludes (Uses Search:Exclude) or file and search excludes (uses both).

todo-tree.filtering.ignoreGitSubmodules (false)
If true, any subfolders containing a .git file will be ignored when searching.

todo-tree.filtering.includeHiddenFiles (false)
If true, files starting with a period (.) will be included.

todo-tree.highlights.enabled (true)
Set this to false to turn off highlighting.

todo-tree.highlights.highlightDelay (500)
The delay before highlighting (milliseconds).

todo-tree.highlights.defaultHighlight ({})
Set default highlights. Example:

{
    "foreground": "white",
    "background": "red",
    "icon": "check",
    "type": "text"
}

todo-tree.highlights.customHighlight ({})
Set highlights per tag (or tag group). Example:

{
    "TODO": {
        "foreground": "white",
        "type": "text"
    },
    "FIXME": {
        "icon": "beaker"
    }
}

todo-tree.highlights.schemes (['file','untitled'])
Editor schemes to show highlights in. To show highlights in settings files, for instance, add vscode-userdata or for output windows, add output.

todo-tree.regex.regex ("((//|#|<!--|;|/\\*)\\s*($TAGS)|^\\s*- \\[ \\])")
This defines the regex used to locate TODOs. By default, it searches for tags in comments starting with //, #, ;, <!-- or /*. This should cover most languages. However if you want to refine it, make sure that the ($TAGS) is kept. The second part of the expression allows matching of Github markdown task lists. Note: This is a Rust regular expression, not javascript.

todo-tree.regex.regexCaseSensitive (true)
Set to false to allow tags to be matched regardless of case.

todo-tree.ripgrep.ripgrep ("")
Normally, the extension will locate ripgrep itself as and when required. If you want to use an alternate version of ripgrep, set this to point to wherever it is installed.

todo-tree.ripgrep.ripgrepArgs ("--max-columns=1000")
Use this to pass additional arguments to ripgrep. e.g. "-i" to make the search case insensitive. Use with caution!

todo-tree.ripgrep.ripgrepMaxBuffer (200)
By default, the ripgrep process will have a buffer of 200KB. However, this is sometimes not enough for all the tags you might want to see. This setting can be used to increase the buffer size accordingly.

todo-tree.tree.showInExplorer (true)
The tree is shown in the explorer view and also has it's own view in the activity bar. If you no longer want to see it in the explorer view, set this to false.

todo-tree.tree.hideTreeWhenEmpty (true)
Normally, the tree is removed from the explorer view if nothing is found. Set this to false to keep the view present.

todo-tree.tree.filterCaseSensitive (false)
Use this if you need the filtering to be case sensitive. Note: this does not the apply to the search.

todo-tree.tree.trackFile (true)
Set to false if you want to prevent tracking the open file in the tree view.

todo-tree.tree.showBadges (true)
Set to false to disable SCM status and badges in the tree. Note: This also unfortunately turns off themed icons.

todo-tree.tree.expanded* (false)
Set to true if you want new views to be expanded by default.

todo-tree.tree.flat* (false)
Set to true if you want new views to be flat by default.

todo-tree.tree.grouped* (false)
Set to true if you want new views to be grouped by default.

todo-tree.tree.tagsOnly* (false)
Set to true if you want new views with tags only by default.

todo-tree.tree.sortTagsOnlyViewAlphabetically (false)
Sort items in the tags only view alphabetically instead of by file and line number.

todo-tree.tree.showCountsInTree (false)
Set to true to show counts of TODOs in the tree.

todo-tree.tree.labelFormat (${tag} ${after})
Format of the TODO item labels. Available placeholders are ${line}, ${column}, ${tag}, ${before} (text from before the tag), ${after} (text from after the tag), ${filename}, ${filepath} and ${afterOrBefore} (use "after" text or "before" text if after is empty).

todo-tree.tree.scanMode (workspace)
By default the extension scans the whole workspace (workspace). Use this to limit the search to only open files (open files) or only the current file (current file).

todo-tree.tree.showScanModeButton (false)
Show a button on the tree view header to switch the scanMode (see above).

todo-tree.tree.hideIconsWhenGroupedByTag (false)
Hide item icons when grouping by tag.

todo-tree.tree.sort (true)
ripgrep searches using multiple threads to improve performance. The tree is sorted when it is populated so that it stays stable. If you want to use ripgrep's own sort arguments, set this to false. Note: Depending on what scan mode you select, you may also want to disable auto-refresh when disabling the sort, otherwise the tree may still be unstable.

todo-tree.tree.disableCompactFolders (false)
The tree will normally respect the VSCode's explorer.compactFolders setting. Set this to true if you want to disable compact folders in the todo tree.

todo-tree.tree.tooltipFormat (${filepath}, ${line})
Format of the tree item tooltips. Uses the same placeholders as todo-tree.tree.labelFormat (see above).

todo-tree.tree.buttons.reveal (true)
Show a button in the tree view title bar to reveal the current item (only when track file is not enabled).

todo-tree.tree.buttons.scanMode (false)
Show a button in the tree view title bar to change the Scan Mode setting.

todo-tree.tree.buttons.viewStyle (true)
Show a button in the tree view title bar to change the view style (tree, flat or tags only).

todo-tree.tree.buttons.groupByTag (true)
Show a button in the tree view title bar to enable grouping items by tag.

todo-tree.tree.buttons.filter (true)
Show a button in the tree view title bar allowing the tree to be filtered by entering some text.

todo-tree.tree.buttons.refresh (true)
Show a refresh button in the tree view title bar.

todo-tree.tree.buttons.expand (true)
Show a button in the tree view title bar to expand or collapse the whole tree.

todo-tree.tree.buttons.export (false)
Show a button in the tree view title bar to create a text file showing the tree content.

*Only applies to new workspaces. Once the view has been changed in the workspace, the current state is stored.

Multiline TODOs

If the regex contains \n, then multiline TODOs will be enabled. In this mode, the search results are processed slightly differently. If results are found which do not contain any tags from todo-tree.general.tags it will be assumed that they belong to the previous result that did have a tag. For example, if you set the regex to something like:

"todo-tree.regex.regex": "(//)\\s*($TAGS).*(\\n\\s*//\\s{2,}.*)*"

This will now match multiline TODOs where the extra lines have at least two spaces between the comment characters and the TODO item. e.g.

// TODO multiline example
//  second line
//  third line

If you want to match multiline TODOs in C++ style multiline comment blocks, you'll need something like:

"todo-tree.regex.regex": "(/\\*)\\s*($TAGS).*(\\n\\s*(//|/\\*|\\*\\*)\\s{2,}.*)*"

which should match:

/* TODO multiline example
**  second line
**  third line
*/

Note: If you are modifying settings using the settings GUI, you don't need to escape each backslash.

Warning: Multiline TODOs will not work with markdown TODOs and may have other unexpected results. There may also be a reduction in performance.

Excluding files and folders

To restrict the set of folders which is searched, you can define todo-tree.filtering.includeGlobs. This is an array of globs which the search results are matched against. If the results match any of the globs, they will be shown. By default the array is empty, which matches everything. See here for more information on globs. Note: globs paths are absolute - not relative to the current workspace.

To exclude folders/files from your search you can define todo-tree.filtering.excludeGlobs. If the search results match any of these globs, then the results will be ignored.

You can also include and exclude folders from the tree using the context menu. This folder filter is applied separately to the include/exclude globs.

Note: By default, ripgrep ignores files and folders from your .gitignore or .ignore files. If you want to include these files, set todo-tree.ripgrep.ripgrepArgs to --no-ignore.

Known Issues

Grouping by tag will only work when your configuration defines the tags using the todo-tree.general.tags setting. Older versions of the extension had the tags directly defined in the todo-tree.regex.regex whereas now, the regex replaces $TAGS with the contents of todo-tree.general.tags.

Grouping by tag doesn't work for markdown task list items as there is no tag to group with. The tree will show the files alongside the tag groups.

Tracking the file in the tree view when grouping by tag will reveal the first tag found.

When there is no current workspace, default icons will be shown in the tree.

Donate

If you find this extension useful, please feel free to donate here. Thanks!

Credits

Uses a modified version of ripgrep-js.

Main icons originally made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

Tree view icons made by Vaadin from www.flaticon.com is licensed by CC 3.0 BY

Tag icons made by Dave Gandy from www.flaticon.com is licensed by CC 3.0 BY

Tags Icon made by Vectors Market from www.flaticon.com is licensed by CC 3.0 BY

Reveal Icon made by Gregor Cresnar from www.flaticon.com

Lots of the icons have now been updated by johnletey to match the new VS Code 1.37.0 GUI. Much appreciated!