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
1 change: 1 addition & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ The keybind footer in the TUI only shows shortcuts that apply to the currently s

Widget-specific shortcuts:
- **Git widgets with empty-state toggles**: `h` hide `no git` / empty output where supported
- **Glyph widgets** (Git Branch, Git Worktree, Git Worktree Mode, Git Staged, Git Unstaged, Git Untracked, Git Conflicts, Git Ahead/Behind, Git Status, JJ Bookmarks, JJ Workspace): `g` set custom glyphs for the widget's symbols; Backspace in the editor renders without one, and multi-symbol widgets (Ahead/Behind, Status) edit each part in one list
- **Git Branch**: `l` toggle clickable branch links (GitHub, GitLab, self-hosted)
- **Git Root Dir**: `l` cycle IDE links (`off` → `VS Code` → `Cursor`)
- **Git PR**: `h` hide empty/no-PR/MR output, `s` toggle review status, `t` toggle title (renders "MR" for GitLab origins)
Expand Down
27 changes: 23 additions & 4 deletions src/widgets/GitAheadBehind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CustomKeybind,
Widget,
WidgetEditorDisplay,
WidgetEditorProps,
WidgetItem
} from '../types/Widget';
import {
Expand All @@ -18,6 +19,15 @@ import {
handleToggleNoGitAction,
isHideNoGitEnabled
} from './shared/git-no-git';
import {
getSlotSymbol,
getSymbolKeybind,
renderSymbolSlotsEditor,
type SymbolSlot
} from './shared/symbol-override';

const AHEAD_SLOT: SymbolSlot = { id: 'symbolAhead', label: 'Ahead', defaultSymbol: '↑' };
const BEHIND_SLOT: SymbolSlot = { id: 'symbolBehind', label: 'Behind', defaultSymbol: '↓' };

export class GitAheadBehindWidget implements Widget {
getDefaultColor(): string { return 'cyan'; }
Expand All @@ -43,11 +53,13 @@ export class GitAheadBehindWidget implements Widget {

render(item: WidgetItem, context: RenderContext, _settings: Settings): string | null {
const hideNoGit = isHideNoGitEnabled(item);
const aheadSymbol = getSlotSymbol(item, AHEAD_SLOT);
const behindSymbol = getSlotSymbol(item, BEHIND_SLOT);

if (context.isPreview) {
if (item.rawValue)
return '2,3';
return '↑2↓3';
return `${aheadSymbol}2${behindSymbol}3`;
}

if (!isInsideGitWorkTree(context)) {
Expand All @@ -70,15 +82,22 @@ export class GitAheadBehindWidget implements Widget {

const parts: string[] = [];
if (result.ahead > 0)
parts.push(`${result.ahead}`);
parts.push(`${aheadSymbol}${result.ahead}`);
if (result.behind > 0)
parts.push(`${result.behind}`);
parts.push(`${behindSymbol}${result.behind}`);

return parts.join('');
}

getCustomKeybinds(): CustomKeybind[] {
return getHideNoGitKeybinds();
return [
...getHideNoGitKeybinds(),
getSymbolKeybind()
];
}

renderEditor(props: WidgetEditorProps) {
return renderSymbolSlotsEditor(props, [AHEAD_SLOT, BEHIND_SLOT]);
}

getNumericValue(context: RenderContext, _item: WidgetItem): number | null {
Expand Down
23 changes: 18 additions & 5 deletions src/widgets/GitBranch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CustomKeybind,
Widget,
WidgetEditorDisplay,
WidgetEditorProps,
WidgetItem
} from '../types/Widget';
import {
Expand All @@ -27,7 +28,13 @@ import {
isHideNoGitEnabled
} from './shared/git-no-git';
import { isMetadataFlagEnabled } from './shared/metadata';
import {
formatSymbolPrefix,
getSymbolKeybind,
renderSymbolOverrideEditor
} from './shared/symbol-override';

const DEFAULT_SYMBOL = '⎇';
const LINK_KEY = 'linkToRepo';
const LEGACY_LINK_KEY = 'linkToGitHub';
const TOGGLE_LINK_ACTION = 'toggle-link';
Expand Down Expand Up @@ -88,22 +95,23 @@ export class GitBranchWidget implements Widget {
void settings;
const hideNoGit = isHideNoGitEnabled(item);
const isLink = isLinkEnabled(item);
const prefix = formatSymbolPrefix(item, DEFAULT_SYMBOL);

if (context.isPreview) {
const text = item.rawValue ? 'main' : '⎇ main';
const text = item.rawValue ? 'main' : `${prefix}main`;
return isLink ? renderOsc8Link('https://github.com/owner/repo/tree/main', text) : text;
}

if (!isInsideGitWorkTree(context)) {
return hideNoGit ? null : '⎇ no git';
return hideNoGit ? null : `${prefix}no git`;
}

const branch = this.getGitBranch(context);
if (!branch) {
return hideNoGit ? null : '⎇ no git';
return hideNoGit ? null : `${prefix}no git`;
}

const displayText = item.rawValue ? branch : `${branch}`;
const displayText = item.rawValue ? branch : `${prefix}${branch}`;

if (isLink) {
const origin = getRemoteInfo('origin', context);
Expand All @@ -125,10 +133,15 @@ export class GitBranchWidget implements Widget {
getCustomKeybinds(): CustomKeybind[] {
return [
...getHideNoGitKeybinds(),
{ key: 'l', label: '(l)ink to repo', action: TOGGLE_LINK_ACTION }
{ key: 'l', label: '(l)ink to repo', action: TOGGLE_LINK_ACTION },
getSymbolKeybind()
];
}

renderEditor(props: WidgetEditorProps) {
return renderSymbolOverrideEditor(props, DEFAULT_SYMBOL);
}

supportsRawValue(): boolean { return true; }
supportsColors(item: WidgetItem): boolean { return true; }
}
22 changes: 19 additions & 3 deletions src/widgets/GitConflicts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CustomKeybind,
Widget,
WidgetEditorDisplay,
WidgetEditorProps,
WidgetItem
} from '../types/Widget';
import {
Expand All @@ -18,6 +19,13 @@ import {
handleToggleNoGitAction,
isHideNoGitEnabled
} from './shared/git-no-git';
import {
formatSymbolPrefix,
getSymbolKeybind,
renderSymbolOverrideEditor
} from './shared/symbol-override';

const DEFAULT_SYMBOL = '⚠';

export class GitConflictsWidget implements Widget {
getDefaultColor(): string { return 'red'; }
Expand All @@ -43,11 +51,12 @@ export class GitConflictsWidget implements Widget {

render(item: WidgetItem, context: RenderContext, _settings: Settings): string | null {
const hideNoGit = isHideNoGitEnabled(item);
const prefix = formatSymbolPrefix(item, DEFAULT_SYMBOL);

if (context.isPreview) {
if (item.rawValue)
return '2';
return '⚠ 2';
return `${prefix}2`;
}

if (!isInsideGitWorkTree(context)) {
Expand All @@ -60,11 +69,18 @@ export class GitConflictsWidget implements Widget {
return count.toString();
}

return `${count}`;
return `${prefix}${count}`;
}

getCustomKeybinds(): CustomKeybind[] {
return getHideNoGitKeybinds();
return [
...getHideNoGitKeybinds(),
getSymbolKeybind()
];
}

renderEditor(props: WidgetEditorProps) {
return renderSymbolOverrideEditor(props, DEFAULT_SYMBOL);
}

getNumericValue(context: RenderContext, _item: WidgetItem): number | null {
Expand Down
19 changes: 16 additions & 3 deletions src/widgets/GitStaged.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CustomKeybind,
Widget,
WidgetEditorDisplay,
WidgetEditorProps,
WidgetItem
} from '../types/Widget';
import {
Expand All @@ -18,6 +19,11 @@ import {
handleToggleNoGitAction,
isHideNoGitEnabled
} from './shared/git-no-git';
import {
getSymbol,
getSymbolKeybind,
renderSymbolOverrideEditor
} from './shared/symbol-override';

const DEFAULT_SYMBOL = '+';

Expand Down Expand Up @@ -47,7 +53,7 @@ export class GitStagedWidget implements Widget {
const hideNoGit = isHideNoGitEnabled(item);

if (context.isPreview) {
return item.rawValue ? 'true' : (item.character ?? DEFAULT_SYMBOL);
return item.rawValue ? 'true' : getSymbol(item, DEFAULT_SYMBOL);
}

if (!isInsideGitWorkTree(context)) {
Expand All @@ -60,11 +66,18 @@ export class GitStagedWidget implements Widget {
return null;
}

return item.rawValue ? 'true' : (item.character ?? DEFAULT_SYMBOL);
return item.rawValue ? 'true' : getSymbol(item, DEFAULT_SYMBOL);
}

getCustomKeybinds(): CustomKeybind[] {
return getHideNoGitKeybinds();
return [
...getHideNoGitKeybinds(),
getSymbolKeybind()
];
}

renderEditor(props: WidgetEditorProps) {
return renderSymbolOverrideEditor(props, DEFAULT_SYMBOL);
}

getNumericValue(context: RenderContext, _item: WidgetItem): number | null {
Expand Down
31 changes: 25 additions & 6 deletions src/widgets/GitStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CustomKeybind,
Widget,
WidgetEditorDisplay,
WidgetEditorProps,
WidgetItem
} from '../types/Widget';
import {
Expand All @@ -18,6 +19,17 @@ import {
handleToggleNoGitAction,
isHideNoGitEnabled
} from './shared/git-no-git';
import {
getSlotSymbol,
getSymbolKeybind,
renderSymbolSlotsEditor,
type SymbolSlot
} from './shared/symbol-override';

const CONFLICTS_SLOT: SymbolSlot = { id: 'symbolConflicts', label: 'Conflicts', defaultSymbol: '!' };
const STAGED_SLOT: SymbolSlot = { id: 'symbolStaged', label: 'Staged', defaultSymbol: '+' };
const UNSTAGED_SLOT: SymbolSlot = { id: 'symbolUnstaged', label: 'Unstaged', defaultSymbol: '*' };
const UNTRACKED_SLOT: SymbolSlot = { id: 'symbolUntracked', label: 'Untracked', defaultSymbol: '?' };

export class GitStatusWidget implements Widget {
getDefaultColor(): string { return 'yellow'; }
Expand Down Expand Up @@ -62,22 +74,29 @@ export class GitStatusWidget implements Widget {
return this.formatStatus(item, status);
}

private formatStatus(_item: WidgetItem, status: { staged: boolean; unstaged: boolean; untracked: boolean; conflicts: boolean }): string {
private formatStatus(item: WidgetItem, status: { staged: boolean; unstaged: boolean; untracked: boolean; conflicts: boolean }): string {
const parts: string[] = [];
if (status.conflicts)
parts.push('!');
parts.push(getSlotSymbol(item, CONFLICTS_SLOT));
if (status.staged)
parts.push('+');
parts.push(getSlotSymbol(item, STAGED_SLOT));
if (status.unstaged)
parts.push('*');
parts.push(getSlotSymbol(item, UNSTAGED_SLOT));
if (status.untracked)
parts.push('?');
parts.push(getSlotSymbol(item, UNTRACKED_SLOT));

return parts.join('');
}

getCustomKeybinds(): CustomKeybind[] {
return getHideNoGitKeybinds();
return [
...getHideNoGitKeybinds(),
getSymbolKeybind()
];
}

renderEditor(props: WidgetEditorProps) {
return renderSymbolSlotsEditor(props, [CONFLICTS_SLOT, STAGED_SLOT, UNSTAGED_SLOT, UNTRACKED_SLOT]);
}

supportsRawValue(): boolean { return false; }
Expand Down
19 changes: 16 additions & 3 deletions src/widgets/GitUnstaged.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CustomKeybind,
Widget,
WidgetEditorDisplay,
WidgetEditorProps,
WidgetItem
} from '../types/Widget';
import {
Expand All @@ -18,6 +19,11 @@ import {
handleToggleNoGitAction,
isHideNoGitEnabled
} from './shared/git-no-git';
import {
getSymbol,
getSymbolKeybind,
renderSymbolOverrideEditor
} from './shared/symbol-override';

const DEFAULT_SYMBOL = '*';

Expand Down Expand Up @@ -47,7 +53,7 @@ export class GitUnstagedWidget implements Widget {
const hideNoGit = isHideNoGitEnabled(item);

if (context.isPreview) {
return item.rawValue ? 'true' : (item.character ?? DEFAULT_SYMBOL);
return item.rawValue ? 'true' : getSymbol(item, DEFAULT_SYMBOL);
}

if (!isInsideGitWorkTree(context)) {
Expand All @@ -60,11 +66,18 @@ export class GitUnstagedWidget implements Widget {
return null;
}

return item.rawValue ? 'true' : (item.character ?? DEFAULT_SYMBOL);
return item.rawValue ? 'true' : getSymbol(item, DEFAULT_SYMBOL);
}

getCustomKeybinds(): CustomKeybind[] {
return getHideNoGitKeybinds();
return [
...getHideNoGitKeybinds(),
getSymbolKeybind()
];
}

renderEditor(props: WidgetEditorProps) {
return renderSymbolOverrideEditor(props, DEFAULT_SYMBOL);
}

getNumericValue(context: RenderContext, _item: WidgetItem): number | null {
Expand Down
Loading