@fresh-editor/fresh-editor 0.1.70 → 0.1.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/package.json +1 -1
- package/plugins/audit_mode.i18n.json +441 -63
- package/plugins/audit_mode.ts +231 -234
- package/plugins/buffer_modified.i18n.json +34 -4
- package/plugins/calculator.i18n.json +49 -7
- package/plugins/clangd_support.i18n.json +119 -17
- package/plugins/color_highlighter.i18n.json +86 -20
- package/plugins/csharp_support.i18n.json +43 -7
- package/plugins/diagnostics_panel.i18n.json +127 -19
- package/plugins/find_references.i18n.json +167 -41
- package/plugins/git_blame.i18n.json +262 -34
- package/plugins/git_find_file.i18n.json +182 -38
- package/plugins/git_grep.i18n.json +95 -17
- package/plugins/git_gutter.i18n.json +54 -12
- package/plugins/git_log.i18n.json +256 -34
- package/plugins/lib/fresh.d.ts +94 -0
- package/plugins/live_grep.i18n.json +104 -26
- package/plugins/markdown_compose.i18n.json +123 -21
- package/plugins/merge_conflict.i18n.json +440 -62
- package/plugins/path_complete.i18n.json +44 -8
- package/plugins/search_replace.i18n.json +239 -53
- package/plugins/test_i18n.i18n.json +50 -0
- package/plugins/theme_editor.i18n.json +2560 -519
- package/plugins/theme_editor.ts +1007 -469
- package/plugins/todo_highlighter.i18n.json +108 -24
- package/plugins/vi_mode.i18n.json +825 -111
- package/plugins/welcome.i18n.json +127 -19
package/plugins/audit_mode.ts
CHANGED
|
@@ -1009,6 +1009,16 @@ interface SideBySideDiffState {
|
|
|
1009
1009
|
let activeSideBySideState: SideBySideDiffState | null = null;
|
|
1010
1010
|
let nextScrollSyncGroupId = 1;
|
|
1011
1011
|
|
|
1012
|
+
// State for composite buffer-based diff view
|
|
1013
|
+
interface CompositeDiffState {
|
|
1014
|
+
compositeBufferId: number;
|
|
1015
|
+
oldBufferId: number;
|
|
1016
|
+
newBufferId: number;
|
|
1017
|
+
filePath: string;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
let activeCompositeDiffState: CompositeDiffState | null = null;
|
|
1021
|
+
|
|
1012
1022
|
globalThis.review_drill_down = async () => {
|
|
1013
1023
|
const bid = editor.getActiveBufferId();
|
|
1014
1024
|
const props = editor.getTextPropertiesAtCursor(bid);
|
|
@@ -1048,21 +1058,9 @@ globalThis.review_drill_down = async () => {
|
|
|
1048
1058
|
return;
|
|
1049
1059
|
}
|
|
1050
1060
|
|
|
1051
|
-
// Close
|
|
1052
|
-
// Store the review buffer ID so we can restore it later
|
|
1053
|
-
const reviewBufferId = bid;
|
|
1054
|
-
|
|
1055
|
-
// Compute aligned diff for the FULL file with all hunks
|
|
1056
|
-
const alignedLines = computeFullFileAlignedDiff(oldContent, newContent, fileHunks);
|
|
1057
|
-
|
|
1058
|
-
// Generate content for both panes
|
|
1059
|
-
const oldPane = generateDiffPaneContent(alignedLines, 'old');
|
|
1060
|
-
const newPane = generateDiffPaneContent(alignedLines, 'new');
|
|
1061
|
-
|
|
1062
|
-
// Close any existing side-by-side views
|
|
1061
|
+
// Close any existing side-by-side views (old split-based approach)
|
|
1063
1062
|
if (activeSideBySideState) {
|
|
1064
1063
|
try {
|
|
1065
|
-
// Remove scroll sync group first
|
|
1066
1064
|
if (activeSideBySideState.scrollSyncGroupId !== null) {
|
|
1067
1065
|
(editor as any).removeScrollSyncGroup(activeSideBySideState.scrollSyncGroupId);
|
|
1068
1066
|
}
|
|
@@ -1072,143 +1070,133 @@ globalThis.review_drill_down = async () => {
|
|
|
1072
1070
|
activeSideBySideState = null;
|
|
1073
1071
|
}
|
|
1074
1072
|
|
|
1075
|
-
//
|
|
1076
|
-
|
|
1073
|
+
// Close any existing composite diff view
|
|
1074
|
+
if (activeCompositeDiffState) {
|
|
1075
|
+
try {
|
|
1076
|
+
editor.closeCompositeBuffer(activeCompositeDiffState.compositeBufferId);
|
|
1077
|
+
editor.closeBuffer(activeCompositeDiffState.oldBufferId);
|
|
1078
|
+
editor.closeBuffer(activeCompositeDiffState.newBufferId);
|
|
1079
|
+
} catch {}
|
|
1080
|
+
activeCompositeDiffState = null;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// Create virtual buffers for old and new content
|
|
1084
|
+
const oldLines = oldContent.split('\n');
|
|
1085
|
+
const newLines = newContent.split('\n');
|
|
1077
1086
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1087
|
+
const oldEntries: TextPropertyEntry[] = oldLines.map((line, idx) => ({
|
|
1088
|
+
text: line + '\n',
|
|
1089
|
+
properties: { type: 'line', lineNum: idx + 1 }
|
|
1090
|
+
}));
|
|
1091
|
+
|
|
1092
|
+
const newEntries: TextPropertyEntry[] = newLines.map((line, idx) => ({
|
|
1093
|
+
text: line + '\n',
|
|
1094
|
+
properties: { type: 'line', lineNum: idx + 1 }
|
|
1095
|
+
}));
|
|
1096
|
+
|
|
1097
|
+
// Create source buffers (hidden from tabs, used by composite)
|
|
1098
|
+
const oldBufferId = await editor.createVirtualBuffer({
|
|
1099
|
+
name: `*OLD:${h.file}*`,
|
|
1100
|
+
mode: "normal",
|
|
1082
1101
|
read_only: true,
|
|
1102
|
+
entries: oldEntries,
|
|
1103
|
+
show_line_numbers: true,
|
|
1083
1104
|
editing_disabled: true,
|
|
1084
|
-
|
|
1085
|
-
split_id: currentSplitId,
|
|
1086
|
-
show_line_numbers: false,
|
|
1087
|
-
line_wrap: false
|
|
1105
|
+
hidden_from_tabs: true
|
|
1088
1106
|
});
|
|
1089
|
-
const oldSplitId = currentSplitId;
|
|
1090
|
-
|
|
1091
|
-
// Close the Review Diff buffer after showing OLD
|
|
1092
|
-
editor.closeBuffer(reviewBufferId);
|
|
1093
|
-
|
|
1094
|
-
// Apply highlights to old pane
|
|
1095
|
-
editor.clearNamespace(oldBufferId, "diff-view");
|
|
1096
|
-
for (const hl of oldPane.highlights) {
|
|
1097
|
-
const bg = hl.bg || [-1, -1, -1];
|
|
1098
|
-
editor.addOverlay(
|
|
1099
|
-
oldBufferId, "diff-view",
|
|
1100
|
-
hl.range[0], hl.range[1],
|
|
1101
|
-
hl.fg[0], hl.fg[1], hl.fg[2],
|
|
1102
|
-
false, hl.bold || false, false,
|
|
1103
|
-
bg[0], bg[1], bg[2],
|
|
1104
|
-
hl.extend_to_line_end || false
|
|
1105
|
-
);
|
|
1106
|
-
}
|
|
1107
1107
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
mode: "diff-view",
|
|
1108
|
+
const newBufferId = await editor.createVirtualBuffer({
|
|
1109
|
+
name: `*NEW:${h.file}*`,
|
|
1110
|
+
mode: "normal",
|
|
1112
1111
|
read_only: true,
|
|
1112
|
+
entries: newEntries,
|
|
1113
|
+
show_line_numbers: true,
|
|
1113
1114
|
editing_disabled: true,
|
|
1114
|
-
|
|
1115
|
-
ratio: 0.5,
|
|
1116
|
-
direction: "vertical",
|
|
1117
|
-
show_line_numbers: false,
|
|
1118
|
-
line_wrap: false
|
|
1115
|
+
hidden_from_tabs: true
|
|
1119
1116
|
});
|
|
1120
|
-
const newBufferId = newRes.buffer_id;
|
|
1121
|
-
const newSplitId = newRes.split_id!;
|
|
1122
|
-
|
|
1123
|
-
// Apply highlights to new pane
|
|
1124
|
-
editor.clearNamespace(newBufferId, "diff-view");
|
|
1125
|
-
for (const hl of newPane.highlights) {
|
|
1126
|
-
const bg = hl.bg || [-1, -1, -1];
|
|
1127
|
-
editor.addOverlay(
|
|
1128
|
-
newBufferId, "diff-view",
|
|
1129
|
-
hl.range[0], hl.range[1],
|
|
1130
|
-
hl.fg[0], hl.fg[1], hl.fg[2],
|
|
1131
|
-
false, hl.bold || false, false,
|
|
1132
|
-
bg[0], bg[1], bg[2],
|
|
1133
|
-
hl.extend_to_line_end || false
|
|
1134
|
-
);
|
|
1135
|
-
}
|
|
1136
1117
|
|
|
1137
|
-
//
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
scrollSyncGroupId = nextScrollSyncGroupId++;
|
|
1146
|
-
(editor as any).createScrollSyncGroup(scrollSyncGroupId, oldSplitId, newSplitId);
|
|
1147
|
-
|
|
1148
|
-
// Compute sync anchors from aligned lines
|
|
1149
|
-
// Each aligned line is a sync point - we map line indices to anchors
|
|
1150
|
-
// For the new core sync, we use line numbers (not byte offsets)
|
|
1151
|
-
const anchors: [number, number][] = [];
|
|
1152
|
-
for (let i = 0; i < alignedLines.length; i++) {
|
|
1153
|
-
// Add anchors at meaningful boundaries: start of file, and at change boundaries
|
|
1154
|
-
const line = alignedLines[i];
|
|
1155
|
-
const prevLine = i > 0 ? alignedLines[i - 1] : null;
|
|
1156
|
-
|
|
1157
|
-
// Add anchor at start of file
|
|
1158
|
-
if (i === 0) {
|
|
1159
|
-
anchors.push([0, 0]);
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
// Add anchor at change boundaries (when change type changes)
|
|
1163
|
-
if (prevLine && prevLine.changeType !== line.changeType) {
|
|
1164
|
-
anchors.push([i, i]);
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// Add anchor at end
|
|
1169
|
-
if (alignedLines.length > 0) {
|
|
1170
|
-
anchors.push([alignedLines.length, alignedLines.length]);
|
|
1118
|
+
// Convert hunks to composite buffer format (parse counts from git diff)
|
|
1119
|
+
const compositeHunks: TsCompositeHunk[] = fileHunks.map(fh => {
|
|
1120
|
+
// Parse actual counts from the hunk lines
|
|
1121
|
+
let oldCount = 0, newCount = 0;
|
|
1122
|
+
for (const line of fh.lines) {
|
|
1123
|
+
if (line.startsWith('-')) oldCount++;
|
|
1124
|
+
else if (line.startsWith('+')) newCount++;
|
|
1125
|
+
else if (line.startsWith(' ')) { oldCount++; newCount++; }
|
|
1171
1126
|
}
|
|
1127
|
+
return {
|
|
1128
|
+
old_start: fh.oldRange.start - 1, // Convert to 0-indexed
|
|
1129
|
+
old_count: oldCount || 1,
|
|
1130
|
+
new_start: fh.range.start - 1, // Convert to 0-indexed
|
|
1131
|
+
new_count: newCount || 1
|
|
1132
|
+
};
|
|
1133
|
+
});
|
|
1172
1134
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1135
|
+
// Create composite buffer with side-by-side layout
|
|
1136
|
+
const compositeBufferId = await editor.createCompositeBuffer({
|
|
1137
|
+
name: `*Diff: ${h.file}*`,
|
|
1138
|
+
mode: "diff-view",
|
|
1139
|
+
layout: {
|
|
1140
|
+
layout_type: "side-by-side",
|
|
1141
|
+
ratios: [0.5, 0.5],
|
|
1142
|
+
show_separator: true
|
|
1143
|
+
},
|
|
1144
|
+
sources: [
|
|
1145
|
+
{
|
|
1146
|
+
buffer_id: oldBufferId,
|
|
1147
|
+
label: "OLD (HEAD)",
|
|
1148
|
+
editable: false,
|
|
1149
|
+
style: {
|
|
1150
|
+
remove_bg: [80, 40, 40],
|
|
1151
|
+
gutter_style: "diff-markers"
|
|
1152
|
+
}
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
buffer_id: newBufferId,
|
|
1156
|
+
label: "NEW (Working)",
|
|
1157
|
+
editable: false,
|
|
1158
|
+
style: {
|
|
1159
|
+
add_bg: [40, 80, 40],
|
|
1160
|
+
gutter_style: "diff-markers"
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
],
|
|
1164
|
+
hunks: compositeHunks.length > 0 ? compositeHunks : null
|
|
1165
|
+
});
|
|
1178
1166
|
|
|
1179
|
-
// Store state for
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
newSplitId,
|
|
1167
|
+
// Store state for cleanup
|
|
1168
|
+
activeCompositeDiffState = {
|
|
1169
|
+
compositeBufferId,
|
|
1183
1170
|
oldBufferId,
|
|
1184
1171
|
newBufferId,
|
|
1185
|
-
|
|
1186
|
-
oldLineByteOffsets: oldPane.lineByteOffsets,
|
|
1187
|
-
newLineByteOffsets: newPane.lineByteOffsets,
|
|
1188
|
-
scrollSyncGroupId
|
|
1172
|
+
filePath: h.file
|
|
1189
1173
|
};
|
|
1190
|
-
activeDiffViewState = { lSplit: oldSplitId, rSplit: newSplitId };
|
|
1191
1174
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1175
|
+
// Show the composite buffer (replaces the review diff buffer)
|
|
1176
|
+
editor.showBuffer(compositeBufferId);
|
|
1177
|
+
|
|
1178
|
+
const addedCount = fileHunks.reduce((sum, fh) => {
|
|
1179
|
+
return sum + fh.lines.filter(l => l.startsWith('+')).length;
|
|
1180
|
+
}, 0);
|
|
1181
|
+
const removedCount = fileHunks.reduce((sum, fh) => {
|
|
1182
|
+
return sum + fh.lines.filter(l => l.startsWith('-')).length;
|
|
1183
|
+
}, 0);
|
|
1184
|
+
const modifiedCount = Math.min(addedCount, removedCount);
|
|
1185
|
+
|
|
1186
|
+
editor.setStatus(editor.t("status.diff_summary", { added: String(addedCount), removed: String(removedCount), modified: String(modifiedCount) }));
|
|
1196
1187
|
}
|
|
1197
1188
|
};
|
|
1198
1189
|
|
|
1199
|
-
// Define the diff-view mode
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
["
|
|
1204
|
-
|
|
1205
|
-
["
|
|
1206
|
-
["
|
|
1207
|
-
["
|
|
1208
|
-
["
|
|
1209
|
-
["Up", "move_up"],
|
|
1210
|
-
["PageDown", "move_page_down"],
|
|
1211
|
-
["PageUp", "move_page_up"],
|
|
1190
|
+
// Define the diff-view mode - inherits from "normal" for all standard navigation/selection/copy
|
|
1191
|
+
// Only adds diff-specific keybindings (close, hunk navigation)
|
|
1192
|
+
editor.defineMode("diff-view", "normal", [
|
|
1193
|
+
// Close the diff view
|
|
1194
|
+
["q", "close"],
|
|
1195
|
+
// Hunk navigation (diff-specific)
|
|
1196
|
+
["n", "review_next_hunk"],
|
|
1197
|
+
["p", "review_prev_hunk"],
|
|
1198
|
+
["]", "review_next_hunk"],
|
|
1199
|
+
["[", "review_prev_hunk"],
|
|
1212
1200
|
], true);
|
|
1213
1201
|
|
|
1214
1202
|
// --- Review Comment Actions ---
|
|
@@ -1528,7 +1516,7 @@ globalThis.on_review_buffer_closed = (data: any) => {
|
|
|
1528
1516
|
if (data.buffer_id === state.reviewBufferId) stop_review_diff();
|
|
1529
1517
|
};
|
|
1530
1518
|
|
|
1531
|
-
// Side-by-side diff for current file
|
|
1519
|
+
// Side-by-side diff for current file using composite buffers
|
|
1532
1520
|
globalThis.side_by_side_diff_current_file = async () => {
|
|
1533
1521
|
const bid = editor.getActiveBufferId();
|
|
1534
1522
|
const absolutePath = editor.getBufferPath(bid);
|
|
@@ -1584,20 +1572,22 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1584
1572
|
|
|
1585
1573
|
for (const line of lines) {
|
|
1586
1574
|
if (line.startsWith('@@')) {
|
|
1587
|
-
const match = line.match(/@@ -(\d+)
|
|
1575
|
+
const match = line.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@(.*)/);
|
|
1588
1576
|
if (match) {
|
|
1589
1577
|
const oldStart = parseInt(match[1]);
|
|
1590
|
-
const
|
|
1578
|
+
const oldCount = match[2] ? parseInt(match[2]) : 1;
|
|
1579
|
+
const newStart = parseInt(match[3]);
|
|
1580
|
+
const newCount = match[4] ? parseInt(match[4]) : 1;
|
|
1591
1581
|
currentHunk = {
|
|
1592
1582
|
id: `${filePath}:${newStart}`,
|
|
1593
1583
|
file: filePath,
|
|
1594
|
-
range: { start: newStart, end: newStart },
|
|
1595
|
-
oldRange: { start: oldStart, end: oldStart },
|
|
1584
|
+
range: { start: newStart, end: newStart + newCount - 1 },
|
|
1585
|
+
oldRange: { start: oldStart, end: oldStart + oldCount - 1 },
|
|
1596
1586
|
type: 'modify',
|
|
1597
1587
|
lines: [],
|
|
1598
1588
|
status: 'pending',
|
|
1599
1589
|
reviewStatus: 'pending',
|
|
1600
|
-
contextHeader: match[
|
|
1590
|
+
contextHeader: match[5]?.trim() || "",
|
|
1601
1591
|
byteOffset: 0
|
|
1602
1592
|
};
|
|
1603
1593
|
fileHunks.push(currentHunk);
|
|
@@ -1631,13 +1621,6 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1631
1621
|
return;
|
|
1632
1622
|
}
|
|
1633
1623
|
|
|
1634
|
-
// Compute aligned diff for the FULL file
|
|
1635
|
-
const alignedLines = computeFullFileAlignedDiff(oldContent, newContent, fileHunks);
|
|
1636
|
-
|
|
1637
|
-
// Generate content for both panes
|
|
1638
|
-
const oldPane = generateDiffPaneContent(alignedLines, 'old');
|
|
1639
|
-
const newPane = generateDiffPaneContent(alignedLines, 'new');
|
|
1640
|
-
|
|
1641
1624
|
// Close any existing side-by-side views
|
|
1642
1625
|
if (activeSideBySideState) {
|
|
1643
1626
|
try {
|
|
@@ -1650,109 +1633,111 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1650
1633
|
activeSideBySideState = null;
|
|
1651
1634
|
}
|
|
1652
1635
|
|
|
1653
|
-
//
|
|
1654
|
-
|
|
1636
|
+
// Close any existing composite diff view
|
|
1637
|
+
if (activeCompositeDiffState) {
|
|
1638
|
+
try {
|
|
1639
|
+
editor.closeCompositeBuffer(activeCompositeDiffState.compositeBufferId);
|
|
1640
|
+
editor.closeBuffer(activeCompositeDiffState.oldBufferId);
|
|
1641
|
+
editor.closeBuffer(activeCompositeDiffState.newBufferId);
|
|
1642
|
+
} catch {}
|
|
1643
|
+
activeCompositeDiffState = null;
|
|
1644
|
+
}
|
|
1655
1645
|
|
|
1656
|
-
// Create
|
|
1657
|
-
const
|
|
1658
|
-
|
|
1659
|
-
|
|
1646
|
+
// Create virtual buffers for old and new content
|
|
1647
|
+
const oldLines = oldContent.split('\n');
|
|
1648
|
+
const newLines = newContent.split('\n');
|
|
1649
|
+
|
|
1650
|
+
const oldEntries: TextPropertyEntry[] = oldLines.map((line, idx) => ({
|
|
1651
|
+
text: line + '\n',
|
|
1652
|
+
properties: { type: 'line', lineNum: idx + 1 }
|
|
1653
|
+
}));
|
|
1654
|
+
|
|
1655
|
+
const newEntries: TextPropertyEntry[] = newLines.map((line, idx) => ({
|
|
1656
|
+
text: line + '\n',
|
|
1657
|
+
properties: { type: 'line', lineNum: idx + 1 }
|
|
1658
|
+
}));
|
|
1659
|
+
|
|
1660
|
+
// Create source buffers (hidden from tabs, used by composite)
|
|
1661
|
+
const oldBufferId = await editor.createVirtualBuffer({
|
|
1662
|
+
name: `*OLD:${filePath}*`,
|
|
1663
|
+
mode: "normal",
|
|
1660
1664
|
read_only: true,
|
|
1665
|
+
entries: oldEntries,
|
|
1666
|
+
show_line_numbers: true,
|
|
1661
1667
|
editing_disabled: true,
|
|
1662
|
-
|
|
1663
|
-
split_id: currentSplitId,
|
|
1664
|
-
show_line_numbers: false,
|
|
1665
|
-
line_wrap: false
|
|
1668
|
+
hidden_from_tabs: true
|
|
1666
1669
|
});
|
|
1667
|
-
const oldSplitId = currentSplitId;
|
|
1668
|
-
|
|
1669
|
-
// Apply highlights to old pane
|
|
1670
|
-
editor.clearNamespace(oldBufferId, "diff-view");
|
|
1671
|
-
for (const hl of oldPane.highlights) {
|
|
1672
|
-
const bg = hl.bg || [-1, -1, -1];
|
|
1673
|
-
editor.addOverlay(
|
|
1674
|
-
oldBufferId, "diff-view",
|
|
1675
|
-
hl.range[0], hl.range[1],
|
|
1676
|
-
hl.fg[0], hl.fg[1], hl.fg[2],
|
|
1677
|
-
false, hl.bold || false, false,
|
|
1678
|
-
bg[0], bg[1], bg[2],
|
|
1679
|
-
hl.extend_to_line_end || false
|
|
1680
|
-
);
|
|
1681
|
-
}
|
|
1682
1670
|
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
mode: "diff-view",
|
|
1671
|
+
const newBufferId = await editor.createVirtualBuffer({
|
|
1672
|
+
name: `*NEW:${filePath}*`,
|
|
1673
|
+
mode: "normal",
|
|
1687
1674
|
read_only: true,
|
|
1675
|
+
entries: newEntries,
|
|
1676
|
+
show_line_numbers: true,
|
|
1688
1677
|
editing_disabled: true,
|
|
1689
|
-
|
|
1690
|
-
ratio: 0.5,
|
|
1691
|
-
direction: "vertical",
|
|
1692
|
-
show_line_numbers: false,
|
|
1693
|
-
line_wrap: false
|
|
1678
|
+
hidden_from_tabs: true
|
|
1694
1679
|
});
|
|
1695
|
-
const newBufferId = newRes.buffer_id;
|
|
1696
|
-
const newSplitId = newRes.split_id!;
|
|
1697
1680
|
|
|
1698
|
-
//
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1681
|
+
// Convert hunks to composite buffer format
|
|
1682
|
+
const compositeHunks: TsCompositeHunk[] = fileHunks.map(h => ({
|
|
1683
|
+
old_start: h.oldRange.start - 1, // Convert to 0-indexed
|
|
1684
|
+
old_count: h.oldRange.end - h.oldRange.start + 1,
|
|
1685
|
+
new_start: h.range.start - 1, // Convert to 0-indexed
|
|
1686
|
+
new_count: h.range.end - h.range.start + 1
|
|
1687
|
+
}));
|
|
1688
|
+
|
|
1689
|
+
// Create composite buffer with side-by-side layout
|
|
1690
|
+
const compositeBufferId = await editor.createCompositeBuffer({
|
|
1691
|
+
name: `*Diff: ${filePath}*`,
|
|
1692
|
+
mode: "diff-view",
|
|
1693
|
+
layout: {
|
|
1694
|
+
layout_type: "side-by-side",
|
|
1695
|
+
ratios: [0.5, 0.5],
|
|
1696
|
+
show_separator: true
|
|
1697
|
+
},
|
|
1698
|
+
sources: [
|
|
1699
|
+
{
|
|
1700
|
+
buffer_id: oldBufferId,
|
|
1701
|
+
label: "OLD (HEAD)",
|
|
1702
|
+
editable: false,
|
|
1703
|
+
style: {
|
|
1704
|
+
remove_bg: [80, 40, 40],
|
|
1705
|
+
gutter_style: "diff-markers"
|
|
1706
|
+
}
|
|
1707
|
+
},
|
|
1708
|
+
{
|
|
1709
|
+
buffer_id: newBufferId,
|
|
1710
|
+
label: "NEW (Working)",
|
|
1711
|
+
editable: false,
|
|
1712
|
+
style: {
|
|
1713
|
+
add_bg: [40, 80, 40],
|
|
1714
|
+
gutter_style: "diff-markers"
|
|
1715
|
+
}
|
|
1728
1716
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
}
|
|
1733
|
-
(editor as any).setScrollSyncAnchors(scrollSyncGroupId, anchors);
|
|
1734
|
-
} catch (e) {
|
|
1735
|
-
editor.debug(`Failed to create scroll sync group: ${e}`);
|
|
1736
|
-
scrollSyncGroupId = null;
|
|
1737
|
-
}
|
|
1717
|
+
],
|
|
1718
|
+
hunks: compositeHunks.length > 0 ? compositeHunks : null
|
|
1719
|
+
});
|
|
1738
1720
|
|
|
1739
|
-
// Store state
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
newSplitId,
|
|
1721
|
+
// Store state for cleanup
|
|
1722
|
+
activeCompositeDiffState = {
|
|
1723
|
+
compositeBufferId,
|
|
1743
1724
|
oldBufferId,
|
|
1744
1725
|
newBufferId,
|
|
1745
|
-
|
|
1746
|
-
oldLineByteOffsets: oldPane.lineByteOffsets,
|
|
1747
|
-
newLineByteOffsets: newPane.lineByteOffsets,
|
|
1748
|
-
scrollSyncGroupId
|
|
1726
|
+
filePath
|
|
1749
1727
|
};
|
|
1750
|
-
activeDiffViewState = { lSplit: oldSplitId, rSplit: newSplitId };
|
|
1751
1728
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1729
|
+
// Show the composite buffer
|
|
1730
|
+
editor.showBuffer(compositeBufferId);
|
|
1731
|
+
|
|
1732
|
+
const addedCount = fileHunks.reduce((sum, h) => {
|
|
1733
|
+
return sum + h.lines.filter(l => l.startsWith('+')).length;
|
|
1734
|
+
}, 0);
|
|
1735
|
+
const removedCount = fileHunks.reduce((sum, h) => {
|
|
1736
|
+
return sum + h.lines.filter(l => l.startsWith('-')).length;
|
|
1737
|
+
}, 0);
|
|
1738
|
+
const modifiedCount = Math.min(addedCount, removedCount);
|
|
1739
|
+
|
|
1740
|
+
editor.setStatus(editor.t("status.diff_summary", { added: String(addedCount), removed: String(removedCount), modified: String(modifiedCount) }));
|
|
1756
1741
|
};
|
|
1757
1742
|
|
|
1758
1743
|
// Register Modes and Commands
|
|
@@ -1772,7 +1757,7 @@ editor.registerCommand("%cmd.overall_feedback", "%cmd.overall_feedback_desc", "r
|
|
|
1772
1757
|
editor.registerCommand("%cmd.export_markdown", "%cmd.export_markdown_desc", "review_export_session", "review-mode");
|
|
1773
1758
|
editor.registerCommand("%cmd.export_json", "%cmd.export_json_desc", "review_export_json", "review-mode");
|
|
1774
1759
|
|
|
1775
|
-
// Handler for when buffers are closed - cleans up scroll sync groups
|
|
1760
|
+
// Handler for when buffers are closed - cleans up scroll sync groups and composite buffers
|
|
1776
1761
|
globalThis.on_buffer_closed = (data: any) => {
|
|
1777
1762
|
// If one of the diff view buffers is closed, clean up the scroll sync group
|
|
1778
1763
|
if (activeSideBySideState) {
|
|
@@ -1788,6 +1773,18 @@ globalThis.on_buffer_closed = (data: any) => {
|
|
|
1788
1773
|
activeDiffViewState = null;
|
|
1789
1774
|
}
|
|
1790
1775
|
}
|
|
1776
|
+
|
|
1777
|
+
// Clean up composite diff state if the composite buffer is closed
|
|
1778
|
+
if (activeCompositeDiffState) {
|
|
1779
|
+
if (data.buffer_id === activeCompositeDiffState.compositeBufferId) {
|
|
1780
|
+
// Close the source buffers
|
|
1781
|
+
try {
|
|
1782
|
+
editor.closeBuffer(activeCompositeDiffState.oldBufferId);
|
|
1783
|
+
editor.closeBuffer(activeCompositeDiffState.newBufferId);
|
|
1784
|
+
} catch {}
|
|
1785
|
+
activeCompositeDiffState = null;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1791
1788
|
};
|
|
1792
1789
|
|
|
1793
1790
|
editor.on("buffer_closed", "on_buffer_closed");
|
|
@@ -1797,7 +1794,7 @@ editor.defineMode("review-mode", "normal", [
|
|
|
1797
1794
|
["s", "review_stage_hunk"], ["d", "review_discard_hunk"],
|
|
1798
1795
|
// Navigation
|
|
1799
1796
|
["n", "review_next_hunk"], ["p", "review_prev_hunk"], ["r", "review_refresh"],
|
|
1800
|
-
["Enter", "review_drill_down"], ["q", "
|
|
1797
|
+
["Enter", "review_drill_down"], ["q", "close"],
|
|
1801
1798
|
// Review actions
|
|
1802
1799
|
["c", "review_add_comment"],
|
|
1803
1800
|
["a", "review_approve_hunk"],
|
|
@@ -4,16 +4,21 @@
|
|
|
4
4
|
"status.initialized": "Buffer Modified: initialized for %{path}",
|
|
5
5
|
"status.cleared_on_save": "Buffer Modified: cleared on save"
|
|
6
6
|
},
|
|
7
|
-
"
|
|
8
|
-
"status.loaded": "Plugin Buffer
|
|
9
|
-
"status.initialized": "Buffer
|
|
10
|
-
"status.cleared_on_save": "Buffer
|
|
7
|
+
"cs": {
|
|
8
|
+
"status.loaded": "Plugin Buffer Modified nacten",
|
|
9
|
+
"status.initialized": "Buffer Modified: inicializovano pro %{path}",
|
|
10
|
+
"status.cleared_on_save": "Buffer Modified: vymazano pri ulozeni"
|
|
11
11
|
},
|
|
12
12
|
"de": {
|
|
13
13
|
"status.loaded": "Buffer Modified Plugin geladen",
|
|
14
14
|
"status.initialized": "Buffer Modified: initialisiert für %{path}",
|
|
15
15
|
"status.cleared_on_save": "Buffer Modified: beim Speichern gelöscht"
|
|
16
16
|
},
|
|
17
|
+
"es": {
|
|
18
|
+
"status.loaded": "Plugin Buffer Modificado cargado",
|
|
19
|
+
"status.initialized": "Buffer Modificado: inicializado para %{path}",
|
|
20
|
+
"status.cleared_on_save": "Buffer Modificado: limpiado al guardar"
|
|
21
|
+
},
|
|
17
22
|
"fr": {
|
|
18
23
|
"status.loaded": "Plugin Buffer Modified chargé",
|
|
19
24
|
"status.initialized": "Buffer Modified: initialisé pour %{path}",
|
|
@@ -24,6 +29,31 @@
|
|
|
24
29
|
"status.initialized": "Buffer Modified: %{path}を初期化しました",
|
|
25
30
|
"status.cleared_on_save": "Buffer Modified: 保存時にクリアしました"
|
|
26
31
|
},
|
|
32
|
+
"ko": {
|
|
33
|
+
"status.loaded": "Buffer Modified 플러그인이 로드되었습니다",
|
|
34
|
+
"status.initialized": "Buffer Modified: %{path} 초기화됨",
|
|
35
|
+
"status.cleared_on_save": "Buffer Modified: 저장 시 지워짐"
|
|
36
|
+
},
|
|
37
|
+
"pt-BR": {
|
|
38
|
+
"status.loaded": "Plugin Buffer Modified carregado",
|
|
39
|
+
"status.initialized": "Buffer Modified: inicializado para %{path}",
|
|
40
|
+
"status.cleared_on_save": "Buffer Modified: limpo ao salvar"
|
|
41
|
+
},
|
|
42
|
+
"ru": {
|
|
43
|
+
"status.loaded": "Плагин Buffer Modified загружен",
|
|
44
|
+
"status.initialized": "Buffer Modified: инициализирован для %{path}",
|
|
45
|
+
"status.cleared_on_save": "Buffer Modified: очищен при сохранении"
|
|
46
|
+
},
|
|
47
|
+
"th": {
|
|
48
|
+
"status.loaded": "โหลดปลั๊กอิน Buffer Modified แล้ว",
|
|
49
|
+
"status.initialized": "Buffer Modified: เริ่มต้นสำหรับ %{path}",
|
|
50
|
+
"status.cleared_on_save": "Buffer Modified: ล้างเมื่อบันทึก"
|
|
51
|
+
},
|
|
52
|
+
"uk": {
|
|
53
|
+
"status.loaded": "Плагін Buffer Modified завантажено",
|
|
54
|
+
"status.initialized": "Buffer Modified: ініціалізовано для %{path}",
|
|
55
|
+
"status.cleared_on_save": "Buffer Modified: очищено при збереженні"
|
|
56
|
+
},
|
|
27
57
|
"zh-CN": {
|
|
28
58
|
"status.loaded": "Buffer Modified插件已加载",
|
|
29
59
|
"status.initialized": "Buffer Modified: 已为%{path}初始化",
|