pi-diff-review 0.1.7 → 0.1.9

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/README.md CHANGED
@@ -33,6 +33,7 @@ pi install https://github.com/cmpadden/pi-diff-review
33
33
  - `esc` clears the active selection, or exits review when no selection is active
34
34
  - `n/p` to jump hunks
35
35
  - `c` to add or edit a comment for the current line or selected range
36
+ - `C` to add or edit an overall diff comment
36
37
  - `x` to delete a comment for the current line or selected range
37
38
  - `Enter` to submit comments back to pi
38
39
  - `q` to exit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-diff-review",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Local diff review TUI extension for pi",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/prompt.ts CHANGED
@@ -18,6 +18,8 @@ export function formatLocation(line: {
18
18
  }
19
19
 
20
20
  function formatCommentLocation(comment: ReviewComment): string {
21
+ if (comment.global) return "Overall diff";
22
+
21
23
  const start = formatLocation({
22
24
  filePath: comment.filePath,
23
25
  oldLineNumber: comment.startOldLineNumber,
@@ -35,6 +35,8 @@ function lineNumberCell(value?: number): string {
35
35
  return value == null ? " " : String(value).padStart(4, " ");
36
36
  }
37
37
 
38
+ const GLOBAL_COMMENT_KEY = "__global_diff_comment__";
39
+
38
40
  export class ReviewComponent {
39
41
  private selected = 0;
40
42
  private scrollTop = 0;
@@ -82,13 +84,28 @@ export class ReviewComponent {
82
84
  });
83
85
 
84
86
  this.editor.onSubmit = (value) => {
87
+ const trimmed = value.trim();
88
+ if (this.editingCommentKey === GLOBAL_COMMENT_KEY) {
89
+ if (!trimmed) {
90
+ if (this.comments.delete(GLOBAL_COMMENT_KEY))
91
+ this.markCommentsChanged();
92
+ } else {
93
+ this.comments.set(
94
+ GLOBAL_COMMENT_KEY,
95
+ this.buildGlobalComment(trimmed),
96
+ );
97
+ this.markCommentsChanged();
98
+ }
99
+ this.exitEditMode();
100
+ return;
101
+ }
102
+
85
103
  const selection = this.getActiveCommentSelection();
86
104
  if (!selection) {
87
105
  this.exitEditMode();
88
106
  return;
89
107
  }
90
108
 
91
- const trimmed = value.trim();
92
109
  const key = this.getSelectionKey(selection.start, selection.end);
93
110
  if (!trimmed) {
94
111
  if (this.comments.delete(key)) this.markCommentsChanged();
@@ -183,6 +200,10 @@ export class ReviewComponent {
183
200
  this.startEditMode();
184
201
  return;
185
202
  }
203
+ if (data === "C") {
204
+ this.startGlobalEditMode();
205
+ return;
206
+ }
186
207
  if (matchesKey(data, "enter")) {
187
208
  const comments = [...this.comments.values()].sort((a, b) =>
188
209
  a.id.localeCompare(b.id),
@@ -204,8 +225,8 @@ export class ReviewComponent {
204
225
  this.editMode
205
226
  ? `${this.lines.length} lines • ${this.comments.size} comments • editing comment • Enter save • Esc/Ctrl+C cancel`
206
227
  : this.hasSelection()
207
- ? `${this.lines.length} lines • ${this.comments.size} comments • J/K extend • Esc clear selection • c comment range • Enter submit`
208
- : `${this.lines.length} lines • ${this.comments.size} comments • ${this.getPositionText(selectedLine)} • j/k move • g/G top/bottom • ctrl-u/d page • t unified/split • ? explain • J/K extend • c comment • x delete • n/p hunk • Enter submit • q quit`,
228
+ ? `${this.lines.length} lines • ${this.comments.size} comments • J/K extend • Esc clear selection • c comment range • C overall comment • Enter submit`
229
+ : `${this.lines.length} lines • ${this.comments.size} comments • ${this.getPositionText(selectedLine)} • j/k move • g/G top/bottom • ctrl-u/d page • t unified/split • ? explain • J/K extend • c comment • C overall • x delete • n/p hunk • Enter submit • q quit`,
209
230
  ),
210
231
  width,
211
232
  ),
@@ -512,6 +533,18 @@ export class ReviewComponent {
512
533
  this.commentLineKeysRevision = this.commentsRevision;
513
534
  }
514
535
 
536
+ private buildGlobalComment(text: string): ReviewComment {
537
+ return {
538
+ id: GLOBAL_COMMENT_KEY,
539
+ filePath: "Overall diff",
540
+ text,
541
+ global: true,
542
+ startLineId: GLOBAL_COMMENT_KEY,
543
+ endLineId: GLOBAL_COMMENT_KEY,
544
+ lineText: "",
545
+ };
546
+ }
547
+
515
548
  private buildCommentFromSelection(
516
549
  selection: SelectionBounds,
517
550
  text: string,
@@ -577,6 +610,15 @@ export class ReviewComponent {
577
610
  this.tui.requestRender();
578
611
  }
579
612
 
613
+ private startGlobalEditMode(): void {
614
+ const existing = this.comments.get(GLOBAL_COMMENT_KEY);
615
+ this.rightPaneMode = "comments";
616
+ this.editMode = true;
617
+ this.editingCommentKey = GLOBAL_COMMENT_KEY;
618
+ this.editor.setText(existing?.text ?? "");
619
+ this.tui.requestRender(true);
620
+ }
621
+
580
622
  private startEditMode(): void {
581
623
  const selection = this.getActiveCommentSelection();
582
624
  if (!selection) return;
@@ -586,6 +628,7 @@ export class ReviewComponent {
586
628
  if (startLine.filePath !== endLine.filePath) return;
587
629
 
588
630
  const existing = this.getCommentForSelection(selection);
631
+ this.rightPaneMode = "comments";
589
632
  this.editMode = true;
590
633
  this.editingCommentKey = this.getSelectionKey(
591
634
  selection.start,
@@ -809,6 +852,42 @@ export class ReviewComponent {
809
852
  );
810
853
  lines.push("");
811
854
 
855
+ if (this.editMode && this.editingCommentKey === GLOBAL_COMMENT_KEY) {
856
+ lines[1] = truncateToWidth(
857
+ this.theme.fg("dim", "Overall diff comment"),
858
+ width,
859
+ );
860
+ lines.push(
861
+ ...wrapTextWithAnsi(
862
+ this.theme.fg(
863
+ "dim",
864
+ "Editing overall diff comment. Enter saves. Esc or Ctrl+C cancels.",
865
+ ),
866
+ width,
867
+ ),
868
+ );
869
+ lines.push("");
870
+ for (const line of this.editor.render(Math.max(10, width))) {
871
+ lines.push(truncateToWidth(line, width));
872
+ }
873
+ return lines.slice(0, height);
874
+ }
875
+
876
+ const globalComment = this.comments.get(GLOBAL_COMMENT_KEY);
877
+ if (globalComment) {
878
+ lines.push(
879
+ truncateToWidth(
880
+ this.theme.fg("accent", this.theme.bold("Overall diff comment")),
881
+ width,
882
+ ),
883
+ );
884
+ lines.push(
885
+ ...wrapTextWithAnsi(this.theme.fg("text", globalComment.text), width),
886
+ );
887
+ lines.push(...wrapTextWithAnsi(this.theme.fg("dim", "C edits"), width));
888
+ lines.push("");
889
+ }
890
+
812
891
  if (!selectedLine) {
813
892
  lines.push(
814
893
  ...wrapTextWithAnsi(
@@ -824,7 +903,7 @@ export class ReviewComponent {
824
903
  ...wrapTextWithAnsi(
825
904
  this.theme.fg(
826
905
  "muted",
827
- "Move to a diff line and press c to add a comment.",
906
+ "Move to a diff line and press c to add a comment, or press C for an overall diff comment.",
828
907
  ),
829
908
  width,
830
909
  ),
@@ -889,8 +968,8 @@ export class ReviewComponent {
889
968
  this.theme.fg(
890
969
  "dim",
891
970
  this.hasSelection()
892
- ? "Press c to add a range comment."
893
- : "Press c to add one. Use J/K to extend a range.",
971
+ ? "Press c to add a range comment, or C for an overall diff comment."
972
+ : "Press c to add one. Use J/K to extend a range. Press C for an overall diff comment.",
894
973
  ),
895
974
  width,
896
975
  ),
package/src/types.ts CHANGED
@@ -6,6 +6,7 @@ export type ReviewComment = {
6
6
  id: string;
7
7
  filePath: string;
8
8
  text: string;
9
+ global?: boolean;
9
10
  startLineId: string;
10
11
  endLineId: string;
11
12
  startOldLineNumber?: number;