import { Worktree, Session } from '../types/index.js'; /** * One menu row: worktree metadata plus optional session (for multi-session worktrees). */ export interface SessionItem { worktree: Worktree; session?: Session; baseLabel: string; status: string; searchableName: string; fileChanges: string; aheadBehind: string; parentBranch: string; lastCommitDate: string; error?: string; lengths: { base: number; status: number; fileChanges: number; aheadBehind: number; parentBranch: number; lastCommitDate: number; }; } /** * Format a date as a relative time string (e.g., "2h ago", "3d ago"). */ export declare function formatRelativeDate(date: Date): string; export declare function truncateString(str: string, maxLength: number): string; /** * Sanitize a branch name into the form used for a worktree directory name: * slashes become dashes, characters outside [a-zA-Z0-9-_.] are stripped, * leading/trailing dashes are removed, and the result is lowercased. * * This is the single source of truth for that mapping. It is reused both to * generate worktree directories (see {@link generateWorktreeDirectory}) and to * decide whether an existing directory name already conveys the branch name * (see {@link formatWorktreeDirectorySuffix}), so a directory generated from a * branch is reliably recognized as a match. */ export declare function sanitizeNameForDirectory(value: string): string; export declare function generateWorktreeDirectory(projectPath: string, branchName: string, pattern?: string): string; /** * Returns the worktree directory basename to show alongside the branch name, * or an empty string when it would be redundant (main worktree, detached, * or the directory name matches the branch). * * The visible suffix is truncated; the raw basename is also returned so * callers that want to make it searchable can include it untruncated. */ export declare function formatWorktreeDirectorySuffix(wt: Worktree, fullBranchName: string): { displaySuffix: string; rawName: string; }; /** * Single source of truth for turning a worktree's branch state into a * display name: the branch name when checked out, or "detached " * (e.g. "detached heads/research/foo") when in detached HEAD state and a * ref could be resolved, falling back to the bare "detached" when not. */ export declare function getDisplayBranchName(wt: Pick): string; export declare function extractBranchParts(branchName: string): { prefix?: string; name: string; }; export declare function displaySuffix(session: Session, multipleForWorktree: boolean): string; /** * Prepares session items for display. * Supports multiple sessions per worktree. * When sortByLastSession is true, worktrees are sorted by the most recent * session lastAccessedAt timestamp (descending), and sessions within each * worktree are also sorted by lastAccessedAt. */ export declare function prepareSessionItems(worktrees: Worktree[], sessions: Session[], options?: { sortByLastSession?: boolean; }): SessionItem[]; /** * Column start positions for one rendered list, plus how the session state tag * (e.g. "[○ Idle]") is placed. */ export interface ColumnPositions { fileChanges: number; aheadBehind: number; parentBranch: number; status: number; lastCommitDate: number; /** * true: the state tag gets its own column at `status`, so every row's tag * starts at the same horizontal position, directly left of the commit date. * false: the state tag is appended right after the branch name (the layout * used before this column existed), because the aligned layout would not fit * the terminal width given to calculateColumnPositions. */ alignStatus: boolean; } /** * Calculates column positions based on content widths. * * `availableWidth` is the number of terminal columns the label may occupy * (i.e. terminal width minus whatever prefix the caller prepends). When the * aligned-status layout would not fit in it, the layout falls back to appending * the state tag to the name, which is narrower. Omit it to always align. */ export declare function calculateColumnPositions(items: SessionItem[], availableWidth?: number): ColumnPositions; /** * Assembles the final worktree label with proper column alignment */ export declare function assembleSessionLabel(item: SessionItem, columns: ColumnPositions): string; /** * Whether a worktree may be deleted by CCManager. * * Two worktrees are off limits: * - the main worktree, because git refuses to remove it and the repository * would be left without a checkout; * - the worktree that contains the current working directory, because removing * the directory CCManager is running in breaks the running process. * * Single source of truth for the rule, shared by the multi-select delete screen * and the per-row delete action. */ export declare function isDeletableWorktree(worktree: Pick, cwd?: string): boolean;