Skip to content
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ Use `tag` for the glass channel when you want a compact translucent badge around

> `scheme` controls presets only — it no longer decides scope.

**Apply a scheme to every tag at once:** run **TaskVision: Set Highlight Scheme for All Tags** from the Command Palette or the tree view's `⋯` overflow menu, then pick `neon`, `glass`, `neon+glass`, or `none`. TaskVision writes the choice into every existing `customHighlight` entry **and** `defaultHighlight`, so you no longer have to edit each tag by hand.

---

## Quick Start
Expand Down
2 changes: 2 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ TaskVision 使用四个独立样式通道:

> `scheme` 只控制预设启用,不再决定作用范围。

**一次性为所有标签设置方案:** 在命令面板或树视图标题栏的 `⋯` 溢出菜单中运行 **TaskVision: 为所有标签设置高亮方案**,然后选择 `neon`、`glass`、`neon+glass` 或 `none`。TaskVision 会把所选方案写入每一个已存在的 `customHighlight` 条目**以及** `defaultHighlight`,无需再逐个标签手动修改。

---

## 快速开始
Expand Down
8 changes: 8 additions & 0 deletions agent/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@

## Session Summary

- Active focus: Implemented issue #2 — added a command to uniformly set the highlight scheme for all tags, resolving that shipped per-tag `customHighlight` entries hid `defaultHighlight`.
- Verification: `npx qunit test/highlightScheme.tests.js` (5 passing), `npm test` (126 passing), `npm run webpack`, `git --no-pager diff --check` (clean).

## Active Session Task

| Priority | Task | Status | Owner | Due |
| -------- | ------------------------------------------------ | --------- | ----- | ---------- |
| P1 | Add "set highlight scheme for all tags" command | Completed | AI | 2026-07-08 |
- Active focus: Fixed issue #1 — Cursor rendered a solid gray background block behind the `neon+glass` tag highlight where VS Code showed the intended translucent glass box.
- Root cause: `buildGlassDecorationOptions` in `src/highlights.js` placed `borderRadius` on the decoration base rule while `backgroundColor`/`border` lived only in `light`/`dark`; a border/borderRadius base rule without a co-located background triggers Cursor's fallback gray fill (microsoft/vscode#175819, wayou/vscode-todo-highlight#434).
- Fix: re-scoped `borderRadius` into `light`/`dark` alongside the border and injected `backgroundColor: 'transparent'` on any themed object that carries a border/borderRadius without an explicit background; VS Code appearance unchanged.
Expand Down
2 changes: 2 additions & 0 deletions agent/timeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

| 日期时间 | 任务/变更 | 修改文件 | 实现逻辑 | 修改动机 | 结果/备注 |
| ---------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 2026-07-08 11:00 | 新增“为所有标签统一设置高亮方案”命令(issue #2) | src/highlightScheme.js, src/extension.js, package.json, package.nls.json, package.nls.zh-cn.json, test/highlightScheme.tests.js, test/extension.tests.js, README.md, README_zh.md, agent/tasks.md, agent/timeline.md | 新增纯函数模块 `highlightScheme.applySchemeToAllTags`:深拷贝后把所选 scheme 写入每个已存在的 customHighlight 条目及 defaultHighlight(`none` 则删除 scheme 键,保留其他属性、不改动入参);在 extension.js 注册 `taskvision.setHighlightSchemeForAllTags`,QuickPick 选择 neon/glass/neon+glass/none 后经 `resolveConfigTarget()` 依次写入 customHighlight 与 defaultHighlight,复用既有配置变更监听自动刷新高亮;package.json 贡献命令并加入树视图标题溢出菜单,补齐中英文 NLS,更新 README | issue #2:用户希望一次性统一设置所有 tag 的高亮方案,而内置 per-tag customHighlight 会覆盖 defaultHighlight,导致 defaultHighlight 看似无效 | 已完成;验证执行 `npx qunit test/highlightScheme.tests.js`(5 passing)、`npm test`(126 passing)、`npm run webpack`、`git --no-pager diff --check`(无输出)|
| 2026-04-29 20:45 | 重新分析 AI 上下文功能逻辑与协作思路 | agent/tasks.md, agent/timeline.md | 只读梳理 `aiContext` 导出器、扩展命令链路、task/context/session sidecar store、稳定 ID 生成、README 协议说明、配置 schema 与测试覆盖,并确认 `.taskvision` 生成文件当前被 Git 跟踪 | 用户要求重新检查 AI 上下文功能部分的逻辑与思路是否合理,需要在继续实现前判断产品定位、数据源边界、会话语义和协作契约是否自洽 | 已完成分析;结论为“外部 agent 交接包”的核心方向合理,但 implementation session 未进入导出、sidecar/source 权责边界、跟踪生成文件、状态报告语义和 Extension Host 集成测试仍需收敛;验证执行只读源码/文档/测试核查与 `git --no-pager ls-files .taskvision .gitignore`,未运行测试套件 |
| 2026-07-08 11:05 | 修复 Cursor 中标签高亮出现灰色背景块(Issue #1) | src/highlights.js, test/highlights.decorations.tests.js, agent/tasks.md, agent/timeline.md | 重写 `buildGlassDecorationOptions`:把 `borderRadius` 从装饰顶层移入 `light`/`dark` 主题对象并与 `border` 同层;对任何带 `border`/`borderRadius` 但缺少显式背景的主题对象注入 `backgroundColor: 'transparent'`;导出 `_buildGlassDecorationOptions` 供行为测试;新增测试断言不再有顶层 `borderRadius`、`borderRadius` 与背景同层、border-only 时回退透明背景 | Cursor(VS Code 派生版)对同时带 `border`+`borderRadius` 但基础 CSS 规则无显式背景的装饰会填充默认灰色块(microsoft/vscode#175819、wayou/vscode-todo-highlight#434);原实现把顶层 `borderRadius` 与 `light`/`dark` 背景拆分到不同规则,导致基础规则只有圆角无背景被 Cursor 灰填充,而 VS Code 正常。重新归位后取值不变,VS Code 外观保持一致 | 已完成;验证执行 `npx qunit test/highlights.decorations.tests.js`(5 passing)、`npm test`(124 passing)、`npm run webpack`(成功);Cursor 未安装于当前环境(`code` 存在、`cursor` 缺失),最终 Cursor 视觉确认需维护者复核;已开 PR(未合并),`Fixes #1` |
| 2026-07-08 11:05 | 修复 issue #4:ripgrep 输出超过 maxBuffer 时返回部分结果而非整体失败 | src/ripgrep.js, src/extension.js, package.json, package.nls.json, package.nls.zh-cn.json, test/ripgrep.tests.js, agent/tasks.md, agent/timeline.md | 将 `taskvision.ripgrep.ripgrepMaxBuffer` 默认值从 200 提升到 20480(20 MB)并同步中英文 markdownDescription;`ripgrep.search` 超过 maxBuffer 时不再 reject,而是置 `truncated` 标记、SIGINT 停止进程,并在 close 处理器优先 `resolve` `formatResults` 的部分结果(数组附带 `truncated`/`maxBuffer`),保留真实 SIGINT interrupted 与退出码分支;extension.js `search()` 检测 `matches.truncated` 后调用一次性 `notifyBufferTruncated` 警告(复用 `OPEN_SETTINGS_BUTTON` 模式),并在 `rebuild()` 重置该一次性标记;新增部分结果回归测试 | 大型仓库因 ripgrep stdout 超过 200 KB 默认缓冲导致整体 reject、树视图零结果(GitHub issue #4),需要在提高上限的同时对超限做优雅降级,保证已收集的标签仍能展示 | 已完成;验证执行 `npm test`(120 passing,含新增 truncation 用例且既有 `ripgrep.kill forwards SIGINT` interrupted 用例未回归)、`npm run webpack`(构建成功) |
| 2026-07-08 11:05 | 支持 `%` 注释风格下的 TODO/FIXME 识别 (issue #3) | package.json, src/extension.js, reproduce_issue_v9.js, test/tests.js, CHANGELOG.md, agent/tasks.md, agent/timeline.md | 在默认检测正则 `taskvision.regex.regex` 的注释前缀选择组中加入 `%`(`(//\|#\|<!--\|;\|/\*\|%\|^\|...)`),并同步更新 `src/extension.js` 中“重置为默认”命令与 `reproduce_issue_v9.js` stub 中的同一字面量;新增断言 `% TODO fix this`/`% FIXME` 被默认正则识别、且 `//`、`#` 前缀仍生效的 QUnit 用例,并在 CHANGELOG 增加 Unreleased 记录 | LaTeX/Matlab/Erlang 使用 `%` 作为行注释符,原正则缺少 `%`,导致这些注释中的 TODO/FIXME 无法被检测(GitHub issue #3 反馈,报告者建议将 `%` 加入检测正则) | 已完成;验证执行 `npm ci`、`npm test`(120 passing, 0 failing,新增用例通过)、`npm run webpack`(构建成功)、`node -e` 校验 package.json 为合法 JSON 且默认正则含 `%` |
Expand Down
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
"when": "view =~ /taskvision/",
"group": "navigation@1.3"
},
{
"command": "taskvision.setHighlightSchemeForAllTags",
"when": "view =~ /taskvision/",
"group": "1-highlights@1"
},
{
"command": "taskvision.reveal",
"when": "view =~ /taskvision/ && taskvision-tags-only == false && taskvision-show-reveal-button == true",
Expand Down Expand Up @@ -674,6 +679,12 @@
"command": "taskvision.customizeAppearance",
"title": "Customize Tag Appearance",
"category": "%taskvision.command.category%"
},
{
"command": "taskvision.setHighlightSchemeForAllTags",
"title": "%taskvision.command.setHighlightSchemeForAllTags.title%",
"category": "%taskvision.command.category%",
"icon": "$(symbol-color)"
}
],
"configuration": [
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"taskvision.command.setTaskStatus.title": "Set Task Status",
"taskvision.command.setTaskPriority.title": "Set Task Priority",
"taskvision.command.editTaskNote.title": "Edit Task Note",
"taskvision.command.setHighlightSchemeForAllTags.title": "Set Highlight Scheme for All Tags",
"taskvision.configuration.title": "TaskVision",
"taskvision.configuration.filtering": "Filtering",
"taskvision.configuration.filtering.excludedWorkspaces.markdownDescription": "An array of workspace names to exclude as roots in the tree (wildcards can be used).",
Expand Down
1 change: 1 addition & 0 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"taskvision.command.setTaskStatus.title": "设置任务状态",
"taskvision.command.setTaskPriority.title": "设置任务优先级",
"taskvision.command.editTaskNote.title": "编辑任务备注",
"taskvision.command.setHighlightSchemeForAllTags.title": "为所有标签设置高亮方案",
"taskvision.configuration.title": "待办事项树",
"taskvision.configuration.filtering": "滤波",
"taskvision.configuration.filtering.excludedWorkspaces.markdownDescription": "配置一个工作区名称的列表,列表中的工作区不允许作为树状图的根(允许使用通配符)。",
Expand Down
50 changes: 50 additions & 0 deletions src/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var contextStore = require('./contextStore.js');
var changeSessionStore = require('./changeSessionStore.js');
var annotationParser = require('./annotationParser.js');
var aiContext = require('./aiContext.js');
var highlightScheme = require('./highlightScheme.js');

var searchList = [];
var currentFilter;
Expand Down Expand Up @@ -2451,6 +2452,55 @@ function activate(context) {
}
}));

context.subscriptions.push(vscode.commands.registerCommand('taskvision.setHighlightSchemeForAllTags', function () {
var currentConfig = vscode.workspace.getConfiguration('taskvision.highlights');
var customHighlight = currentConfig.get('customHighlight', {});
var defaultHighlight = currentConfig.get('defaultHighlight', {});
var configTarget = resolveConfigTarget();

var items = [
{
label: '$(zap) Neon',
detail: 'Enable glow preset for every tag',
value: 'neon'
},
{
label: '$(browser) Glass',
detail: 'Enable glass preset for every tag',
value: 'glass'
},
{
label: '$(sparkle) Neon + Glass',
detail: 'Enable both glow and glass presets for every tag',
value: 'neon+glass'
},
{
label: '$(circle-slash) None',
detail: 'Clear scheme preset for every tag',
value: 'none'
}
];

vscode.window.showQuickPick(items, {
placeHolder: 'Choose a highlight scheme to apply to ALL tags',
matchOnDetail: true
}).then(function (selection) {
if (!selection) {
return;
}

var updated = highlightScheme.applySchemeToAllTags(customHighlight, defaultHighlight, selection.value);

return Promise.resolve(currentConfig.update('customHighlight', updated.customHighlight, configTarget))
.then(function () {
return currentConfig.update('defaultHighlight', updated.defaultHighlight, configTarget);
})
.then(function () {
vscode.window.showInformationMessage('Applied "' + selection.value + '" highlight scheme to all tags');
});
});
}));

context.subscriptions.push(vscode.commands.registerCommand('taskvision.customizeAppearance', function (node) {
if (node && node.tag) {
var currentConfig = vscode.workspace.getConfiguration('taskvision.highlights');
Expand Down
33 changes: 33 additions & 0 deletions src/highlightScheme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
function clone(value) {
return value ? JSON.parse(JSON.stringify(value)) : {};
}

function shouldClear(scheme) {
return scheme === undefined || scheme === null || scheme === '' || scheme === 'none';
}

function applyScheme(target, scheme) {
if (!target || typeof target !== 'object') {
return;
}
if (shouldClear(scheme)) {
delete target.scheme;
} else {
target.scheme = scheme;
}
}

function applySchemeToAllTags(customHighlight, defaultHighlight, scheme) {
var updatedCustom = clone(customHighlight);
var updatedDefault = clone(defaultHighlight);

Object.keys(updatedCustom).forEach(function (tag) {
applyScheme(updatedCustom[tag], scheme);
});

applyScheme(updatedDefault, scheme);

return { customHighlight: updatedCustom, defaultHighlight: updatedDefault };
}

module.exports.applySchemeToAllTags = applySchemeToAllTags;
30 changes: 29 additions & 1 deletion test/extension.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,33 @@ QUnit.test('extension updates font appearance in a single customHighlight write'
assert.ok(source.indexOf('updateConfigValues({ fontWeight: font.fontWeight, fontStyle: font.fontStyle });') !== -1);
});

QUnit.test('extension registers a command to set the highlight scheme for all tags', function (assert) {
var source = fs.readFileSync('src/extension.js', 'utf8');

assert.ok(source.indexOf("var highlightScheme = require('./highlightScheme.js');") !== -1, 'requires the highlightScheme module');
assert.ok(source.indexOf("vscode.commands.registerCommand('taskvision.setHighlightSchemeForAllTags'") !== -1, 'registers the command');
assert.ok(source.indexOf('highlightScheme.applySchemeToAllTags(customHighlight, defaultHighlight, selection.value)') !== -1, 'delegates to the pure helper');
assert.ok(source.indexOf('var configTarget = resolveConfigTarget();') !== -1, 'uses resolveConfigTarget for the write target');
assert.ok(source.indexOf("currentConfig.update('customHighlight', updated.customHighlight, configTarget)") !== -1, 'writes customHighlight with the resolved target');
assert.ok(source.indexOf("currentConfig.update('defaultHighlight', updated.defaultHighlight, configTarget)") !== -1, 'writes defaultHighlight with the resolved target');
});

QUnit.test('package contributes the set-scheme-for-all-tags command in the view title overflow menu', function (assert) {
var packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));

var command = packageJson.contributes.commands.find(function (candidate) {
return candidate.command === 'taskvision.setHighlightSchemeForAllTags';
});
assert.ok(command, 'command is contributed');
assert.strictEqual(command.title, '%taskvision.command.setHighlightSchemeForAllTags.title%', 'command title uses an NLS key');

var titleMenu = packageJson.contributes.menus['view/title'].find(function (item) {
return item.command === 'taskvision.setHighlightSchemeForAllTags';
});
assert.ok(titleMenu, 'command is added to the view/title menu');
assert.ok(titleMenu.group.indexOf('navigation') === -1, 'command is placed in the overflow menu, not the navigation bar');
});

QUnit.test('extension source accepts built-in taskvision icons during validation', function (assert) {
var source = readSource('src/icons.js');

Expand All @@ -73,7 +100,8 @@ QUnit.test('package localizes contributed command titles', function (assert) {
'taskvision.addMissingTaskStatuses',
'taskvision.setTaskStatus',
'taskvision.setTaskPriority',
'taskvision.editTaskNote'
'taskvision.editTaskNote',
'taskvision.setHighlightSchemeForAllTags'
];

commandIds.forEach(function (commandId) {
Expand Down
Loading
Loading