import { resolveTaskLocations } from "@/commands/resolveTaskLocations"; import { findFieldRange, replaceFrontmatterField, } from "@/frontmatter/frontmatterFields"; import { isTaskFileName, TASK_LANGUAGE_ID, } from "@/model/taskFile"; import { IConfigProvider, IFileSystem } from "@/ports"; import * as vscode from "vscode"; import { resolveTaskFolderForPath } from "./resolveTaskFolder"; export type FrontmatterEditDeps = { fs: IFileSystem; config: IConfigProvider; }; export const EditableField = { STATUS: "status", PRIORITY: "priority", ASSIGNEE: "assignee", TAGS: "tags", } as const; export type EditableField = (typeof EditableField)[keyof typeof EditableField]; function isTaskDocument(document: vscode.TextDocument): boolean { if (document.languageId === TASK_LANGUAGE_ID) return true; return isTaskFileName(document.fileName); } export async function resolveDocument( uriArg?: string, ): Promise { if (typeof uriArg === "string" && uriArg.length > 0) { const uri = vscode.Uri.parse(uriArg); return vscode.workspace.openTextDocument(uri); } const active = vscode.window.activeTextEditor?.document; if (active && isTaskDocument(active)) { return active; } return undefined; } export function workspaceCwdFor( document: vscode.TextDocument, ): string | undefined { const folder = vscode.workspace.getWorkspaceFolder(document.uri); return folder?.uri.fsPath; } export async function applyFieldValue( document: vscode.TextDocument, key: EditableField, value: string, ): Promise { const text = document.getText(); const result = replaceFrontmatterField(text, key, value); if (!result.ok) { void vscode.window.showErrorMessage( result.reason === "no-field" ? `Field "${key}" not found in frontmatter` : "No YAML frontmatter in this file", ); return false; } const valueRange = findFieldRange(text, key); if (!valueRange) { const full = new vscode.Range( document.positionAt(0), document.positionAt(text.length), ); const edit = new vscode.WorkspaceEdit(); edit.replace(document.uri, full, result.content); return vscode.workspace.applyEdit(edit); } const range = new vscode.Range( valueRange.startLine, valueRange.startCol, valueRange.endLine, valueRange.endCol, ); const edit = new vscode.WorkspaceEdit(); edit.replace(document.uri, range, value); return vscode.workspace.applyEdit(edit); } export function getCurrentFieldValue( text: string, field: string, ): string | undefined { const range = findFieldRange(text, field); if (!range) return undefined; const lines = text.split(/\r?\n/); const raw = lines[range.startLine]!.slice( range.startCol, range.endCol, ).trim(); if ( (raw.startsWith('"') && raw.endsWith('"')) || (raw.startsWith("'") && raw.endsWith("'")) ) { return raw.slice(1, raw.length - 1); } return raw; } export async function resolveTaskFolder( document: vscode.TextDocument, config: IConfigProvider, ): Promise { const locations = resolveTaskLocations(config); return resolveTaskFolderForPath(document.fileName, locations); }