Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
release_ref: ${{ steps.meta.outputs.release_ref }}
release_sha: ${{ steps.meta.outputs.release_sha }}
release_short_sha: ${{ steps.meta.outputs.release_short_sha }}
targets: ${{ steps.targets.outputs.targets }}

steps:
- name: Check out repository
Expand Down Expand Up @@ -52,6 +53,10 @@ jobs:
echo "release_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
echo "release_short_sha=$(git rev-parse --short=12 HEAD)" >> "$GITHUB_OUTPUT"

- name: Resolve platform targets
id: targets
run: echo "targets=$(node -p "JSON.stringify(require('./scripts/release/targets.json'))")" >> "$GITHUB_OUTPUT"

- name: Run test suite
run: npm test

Expand All @@ -63,7 +68,7 @@ jobs:
uses: ./.github/workflows/reusable-build-vsix.yml
with:
ref: ${{ needs.preflight.outputs.release_ref }}
targets: '["win32-x64","win32-arm64","linux-x64","linux-arm64","linux-armhf","darwin-x64","darwin-arm64","alpine-x64","alpine-arm64","web"]'
targets: ${{ needs.preflight.outputs.targets }}
secrets: inherit

github-release:
Expand Down
21 changes: 15 additions & 6 deletions .github/workflows/pr-vsix-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
build: ${{ steps.context.outputs.build }}
pull-request-number: ${{ steps.context.outputs.pull-request-number }}
targets: ${{ steps.targets.outputs.targets }}
staging-artifact-id: ${{ steps.staging.outputs.artifact-id }}
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
Expand All @@ -47,11 +48,6 @@ jobs:
PR_VSIX_MERGE_INTERVAL_MS: 5000
run: node scripts/ci/resolve-pr-vsix-context.mjs

- name: Resolve platform targets
id: targets
if: steps.context.outputs.build == 'true'
run: echo "targets=$(node -p "JSON.stringify(require('./scripts/release/targets.json'))")" >> "$GITHUB_OUTPUT"

- name: Check out immutable build context
if: steps.context.outputs.build == 'true'
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
Expand All @@ -60,6 +56,18 @@ jobs:
fetch-depth: 0
persist-credentials: false

- name: Resolve platform targets
id: targets
if: steps.context.outputs.build == 'true'
run: |
node --input-type=module <<'NODE'
import fs from 'node:fs';
import { verifyTargetMap } from './scripts/ci/verify-pr-vsix.mjs';
const targets = JSON.parse(fs.readFileSync('scripts/release/targets.json', 'utf8'));
verifyTargetMap(targets);
fs.appendFileSync(process.env.GITHUB_OUTPUT, `targets=${JSON.stringify(targets)}\n`);
NODE

- name: Install dependencies
if: steps.context.outputs.build == 'true'
run: npm ci
Expand All @@ -82,6 +90,7 @@ jobs:
node scripts/ci/verify-pr-vsix.mjs artifacts/vsix

- name: Stage platform VSIX files
id: staging
if: steps.context.outputs.build == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
Expand Down Expand Up @@ -122,7 +131,7 @@ jobs:
needs:
- test-build
- publish
if: always() && needs.test-build.outputs.build == 'true'
if: always() && needs.test-build.outputs.staging-artifact-id != ''
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
prerelease: ${{ steps.meta.outputs.prerelease }}
release_ref: ${{ steps.meta.outputs.release_ref }}
release_sha: ${{ steps.meta.outputs.release_sha }}
targets: ${{ steps.targets.outputs.targets }}

steps:
- name: Check out repository
Expand Down Expand Up @@ -57,6 +58,10 @@ jobs:
REF_TYPE: ${{ github.ref_type }}
run: bash scripts/release/resolve-release-metadata.sh

- name: Resolve platform targets
id: targets
run: echo "targets=$(node -p "JSON.stringify(require('./scripts/release/targets.json'))")" >> "$GITHUB_OUTPUT"

- name: Run release test suite
run: npm test

Expand All @@ -69,7 +74,7 @@ jobs:
with:
ref: ${{ needs.preflight.outputs.release_ref }}
release_tag: ${{ needs.preflight.outputs.tag }}
targets: '["win32-x64","win32-arm64","linux-x64","linux-arm64","linux-armhf","darwin-x64","darwin-arm64","alpine-x64","alpine-arm64","web"]'
targets: ${{ needs.preflight.outputs.targets }}
secrets: inherit

publish:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ artifacts/**/*.log
artifacts/perf/runtime-benchmarks.json
artifacts/**/*.json
Better.TODO.Tree.settings.txt
.forge/
4 changes: 3 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.vscode/
.devcontainer/
.vscodeignore
.gitignore
node_modules/
src/
Expand All @@ -16,11 +18,11 @@ TODOS_LISTS/
TODOS_LISTS/**
.tools/
.act-artifacts/
.forge/
MIGRATION.md
OPEN_VSX_CERTIFICATE_REPORT.md
CHANGELOG.upstream.md
Better.TODO.Tree.settings.txt
buildCodiconNames.js
old-*.js
*.bak
*~
Expand Down
3 changes: 2 additions & 1 deletion .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ TODOS_LISTS/
TODOS_LISTS/**
.tools/
.act-artifacts/
.forge/
MIGRATION.md
OPEN_VSX_CERTIFICATE_REPORT.md
CHANGELOG.upstream.md
Better.TODO.Tree.settings.txt
buildCodiconNames.js
old-*.js
*.bak
*~
.devcontainer/
.npmignore
93 changes: 46 additions & 47 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,55 @@
## Extension Identity

- New public extension ID: `FanaticPythoner.better-todo-tree`
- Legacy public extension ID: `Gruntfuggly.todo-tree`
- Stable hidden view IDs kept for layout compatibility:
- Source extension ID: `Gruntfuggly.todo-tree`
- View IDs:
- `todo-tree-container`
- `todo-tree-view`

## Settings Compatibility

Better Todo Tree keeps both configuration namespaces in the manifest during the `0.x` line:

- current namespace: `better-todo-tree.*`
- legacy namespace: `todo-tree.*`

Runtime reads resolve in this order:

1. explicit `better-todo-tree.*` value
2. explicit `todo-tree.*` value
3. current default

All writes go to `better-todo-tree.*`.

On activation, the extension copies legacy `todo-tree.*` values into the matching `better-todo-tree.*` key at the same scope when the new key is unset. Supported scopes:

- Global
- Workspace
- Workspace Folder

Manual re-import command:

- `Better Todo Tree: Import Legacy Settings`

## Command Compatibility

All legacy `todo-tree.*` command IDs remain registered as hidden aliases to the rebranded command handlers. Existing keybindings, macros, and scripts keep working while public menus and the command palette expose the `better-todo-tree.*` IDs.

## Export Compatibility

Both export schemes are registered:

- current: `better-todo-tree-export:`
- legacy: `todotree-export:`

## Non-Portable State

Extension storage keyed by the old extension identifier is not migrated. The compatibility guarantee covers:

- settings
- public command IDs
- stable hidden view/container IDs

It does not cover old extension-local cache state or global/workspace mementos stored under the previous publisher/name.
## Todo Tree settings compatibility

Todo Tree settings are supported directly. Activation reads configuration without rewriting settings files.

| Contract | Behavior |
| --- | --- |
| Recognized settings | `better-todo-tree.*`, grouped `todo-tree.*`, historical flat Todo Tree keys |
| Live edits | Changes under either namespace refresh the affected scanners, highlights and tree controls |
| Scope | User, workspace, workspace folder and language overrides |
| Precedence | VS Code scope order; at the same scope: explicit current setting, grouped Todo Tree setting, historical flat key |
| Empty values | Explicit `false`, `0`, empty arrays and empty objects remain configured values |
| Object inheritance | Properties merge across scopes using VS Code object-setting semantics |
| Palette | `highlights.useColourScheme` defaults to `false` under both namespaces |
| Import command | `Better Todo Tree: Import Todo Tree Settings` copies recognized source values into unset destinations at the original scope |
| Source preservation | Import preserves every source key, unknown setting, retained historical setting and unrelated setting |
| Language import | Exact single-language and combined-language selector blocks remain intact |
| Failed write | Typed error; source retained; destination propagation verified before completion |
| Retry | Existing destination values remain intact; repeated import performs no writes |
| New workspace folder | Todo Tree settings work immediately; manual import includes the added folder |

Explicit import creates `better-todo-tree.*` overrides. Subsequent Todo Tree edits follow the same
scope and namespace precedence rules.

| Historical setting | Current behavior |
| --- | --- |
| `todo-tree.tree.showTagsFromOpenFilesOnly` | Maps `true` to `open files`, `false` to `workspace` |
| `todo-tree.tree.showScanOpenFilesOrWorkspaceButton` | Maps to `tree.buttons.scanMode` |
| `todo-tree.highlights.schemes` | Maps to `general.schemes` |
| `todo-tree.general.enableFileWatcher` | Enables external-file refresh in workspace scan modes |
| `todo-tree.general.fileWatcherGlob` | Selects file events that trigger the optional watcher |
| `todo-tree.ripgrep.ripgrepMaxBuffer`, `todo-tree.ripgrepMaxBuffer` | Preserved; streaming output has no aggregate output buffer |
| `todo-tree.tree.showInExplorer` | Preserved; VS Code owns view placement through Move View |

Extension storage owned by `Gruntfuggly.todo-tree` is separate from settings and is not read or copied.
Setting aliases are generated from current schemas by `npm run settings:sync` and checked during packaging.

## Commands and exports

- Command IDs: `better-todo-tree.*`.
- Export scheme: `better-todo-tree-export:`.
- Removed command aliases: `todo-tree.*`.
- Removed export alias: `todotree-export:`.
- Existing keybindings and macros must reference the current command IDs.
- View identifiers remain `todo-tree-container` and `todo-tree-view`.

## GitHub Release Environment

Expand Down
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ Found TODOs can also be highlighted in open files.

## Highlighting

>`better-todo-tree.highlights.useColourScheme` applies foreground and background colour sequences to tags in tag order.
>`better-todo-tree.highlights.useColourScheme` is opt-in. When enabled, it applies foreground and background colour sequences to tags in tag order.

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.

Custom highlights can also be specified for sub tags (if used).

<sup>*Note: `defaultHighlight` is not applied to sub tags.*</sup>
Subtags require a matching `customHighlight` entry. Omitted attributes inherit `defaultHighlight`.

Both `defaultHighlight` and `customHighlight` allow for the following settings:

Expand All @@ -114,7 +114,7 @@ Both `defaultHighlight` and `customHighlight` allow for the following settings:

`gutterIcon` - set to true to show the icon in the editor gutter.

<sup>*Note: Unfortunately, only octicons and the better-todo-tree icon can be displayed in the gutter.*</sup>
Octicons, codicons, and the Better Todo Tree icon can be displayed in the gutter. Gutter codicons use bundled default SVG shapes. Product icon themes control the tree icons.

`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.

Expand All @@ -129,12 +129,12 @@ Both `defaultHighlight` and `customHighlight` allow for the following settings:
- `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
- `tag-and-subTag` - as above, but allows the sub tag to be highlight too (with colours defined in custom highlights)
- `tag-and-subTag` - highlights the tag and a subtag with a matching custom highlight
- `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
- `capture-groups:n,m...` - highlights capture groups from the regex, where 'n' is the index into the regex
- `none` - disable highlightling in the document
- `none` - disables highlighting in the document

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

Expand Down Expand Up @@ -178,6 +178,8 @@ Alternatively, open Visual Studio code, press `Ctrl+P` or `Cmd+P` and type:

> ext install FanaticPythoner.better-todo-tree

Native packages cover Windows x64/Arm64, Linux x64/Arm64/Armhf, Alpine x64/Arm64, and macOS x64/Arm64. Browser-hosted VS Code is excluded because workspace scanning requires the Node extension host and the packaged ripgrep executable.

### Source Code

The source code is available on GitHub [here](https://github.com/FanaticPythoner/better-todo-tree).
Expand Down Expand Up @@ -299,6 +301,9 @@ This treats any of `FIXME`, `FIXIT` or `FIX` as `FIXME`. When the tree is groupe

<sup>*Note: all tags in the group should also appear in `better-todo-tree.general.tags`.*</sup>

VS Code omits the exact `__proto__` object key from its configuration API.
Assign that tag to a named group such as `PrototypeMarker`, then configure the group in `customHighlight`.

**better-todo-tree.general.revealBehaviour** (`start of todo`)</br>
Change the cursor behaviour when double-clicking a todo in the tree. You 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) or `start of line` (moves the cursor to the start of the line).

Expand Down Expand Up @@ -336,7 +341,7 @@ A list of workspace names to include as roots in the tree (wildcards can be used
A list of workspace names to exclude as roots in the tree (wildcards can be used).

**better-todo-tree.filtering.passGlobsToRipgrep** (`true`)</br>
Set this to false to apply the globs *after* the search (legacy behaviour).
Set this to false to apply the globs *after* the search.

**better-todo-tree.filtering.useBuiltInExcludes** (`none`)</br>
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).
Expand Down Expand Up @@ -380,15 +385,15 @@ Set highlights per tag (or tag group). Example:
}
```

**better-todo-tree.highlights.useColourScheme** (`true`)</br>
Applies foreground and background colour sequences to tags in tag order. This is a smaller configuration surface than per-tag `customHighlight` entries.
**better-todo-tree.highlights.useColourScheme** (`false`)</br>
Enable foreground and background colour sequences for tags in tag order. Custom and default highlight styles remain unchanged while this setting is disabled.

<sup>*Note: The colour scheme overrides the colours defined in* `better-todo-tree.highlights.defaultHighlight` *but not* `better-todo-tree.highlights.customHighlight`*.*</sup>

**better-todo-tree.highlights.backgroundColourScheme** (`["red","orange","yellow","green","blue","indigo","violet"]`)</br>
Defines colours for use in conjunction with `better-todo-tree.highlights.useColourScheme` to colour highlights. Colours can be defined in the same way as other colours (e.g. hex code, theme names, etc.). If there are more tags than colours, the sequence is repeated.

**better-todo-tree.highlights.foreroundColourScheme** (`["white","black","black","white","white","white","black"]`)</br>
**better-todo-tree.highlights.foregroundColourScheme** (`["white","black","black","white","white","white","black"]`)</br>
Defines colours for use in conjunction with `better-todo-tree.highlights.backgroundColourScheme` to colour highlights. These colours should be complementary to the background colours.

**better-todo-tree.regex.enableMultiLine** (`false`)</br>
Expand All @@ -402,7 +407,7 @@ This defines the regex used to locate TODOs. By default, it searches for tags in
<sup>*Regexes use ripgrep's Rust engine unless look-around, backreferences, or explicit ripgrep engine arguments select PCRE2.*</sup>

**better-todo-tree.regex.subTagRegex**
This is a regular expression for processing the text to the right of the tag, e.g. for extracting a sub tag, or removing unwanted characters. Anything that the regex matches will be removed from the text. If a capture group is included, the contents are extracted into a sub tag, which will be used in the tree to group similar tags. The sub tag can also be used as a placeholder in `better-todo-tree.tree.subTagClickUrl` and `better-todo-tree.tree.labelFormat`. Sub tags can also be highlighted by specifying a section in the `better-todo-tree.highlights.customHighlights` setting. To highlight the sub tag itself, set "type" to "tag-and-subTag" in custom highlights for the tag.
Extract a subtag or remove text following a tag with this regular expression. Matched text is removed from the displayed label. A capture group supplies the subtag for tree grouping and the `better-todo-tree.tree.subTagClickUrl` and `better-todo-tree.tree.labelFormat` placeholders. A matching `better-todo-tree.highlights.customHighlight` entry and the `tag-and-subTag` type enable subtag decoration.

Examples:

Expand All @@ -419,11 +424,10 @@ Empty value uses the packaged ripgrep binary. Set an absolute executable path to
**better-todo-tree.ripgrep.ripgrepArgs** (`"--max-columns=1000"`)</br>
Pass additional arguments to ripgrep. Engine arguments such as `--pcre2`, `-P`, and `--engine` override automatic engine selection.

**better-todo-tree.ripgrep.ripgrepMaxBuffer** (`200`)</br>
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.
Ripgrep output is parsed incrementally. No output-buffer size setting is required.

**better-todo-tree.ripgrep.usePatternFile** (`true`)</br>
A pattern file is used with ripgrep by default. If you experience issues with deleting the pattern file, set this to false to use the legacy method of providing the regex to ripgrep.
A pattern file is used with ripgrep by default. Setting this to false passes the regex as a command argument and avoids pattern-file creation and deletion.

**better-todo-tree.tree.hideTreeWhenEmpty** (`true`)</br>
Normally, the tree is removed from the explorer view if nothing is found. Set this to false to keep the view present.
Expand Down Expand Up @@ -647,7 +651,7 @@ When there is no current workspace, default icons will be shown in the tree.

## Compatibility

Better Todo Tree keeps reading legacy `todo-tree.*` settings and imports them into the new `better-todo-tree.*` namespace, so existing user configuration keeps working after the rebrand.
Existing Todo Tree configurations work directly, including `todo-tree.*` settings and historical flat keys. Changes take effect while the extension is running. **Better Todo Tree: Import Todo Tree Settings** copies settings into `better-todo-tree.*` at their original scopes and preserves the source configuration. Scope precedence follows VS Code; explicit `better-todo-tree.*` values win ties at the same scope. See [settings compatibility and import](MIGRATION.md#todo-tree-settings-compatibility).

### Credits

Expand Down
10 changes: 5 additions & 5 deletions artifacts/accuracy/regex-registry-equivalence.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
| Baseline regex entries | 118 |
| Baseline unique regexes | 83 |
| Current hardcoded regex entries | 0 |
| Registry fragments | 188 |
| Registry patterns | 210 |
| Registry fragments | 202 |
| Registry patterns | 224 |
| Source coverage | 83/83 |
| Behavior parity | 73/73 |
| Behavior parity | 72/72 |
| Compiled baseline regexes | 83/83 |
| Elapsed ms | 147.762 |
| Elapsed ms | 165.377 |

## Behavior Matrix

| Group | Passed | Total |
| --- | ---: | ---: |
| utils | 11 | 11 |
| utils | 10 | 10 |
| attributes | 5 | 5 |
| detection | 5 | 5 |
| regexEngine | 52 | 52 |
Expand Down
Loading