From 93bf37d1506f90169e1445f3b1e758548d2d3a44 Mon Sep 17 00:00:00 2001 From: Bindu Date: Sat, 8 Jul 2023 23:30:22 -0700 Subject: [PATCH] Support fold/unfold diff hunks in stash detail view --- src/commands/diffingCommands.ts | 47 +++++++++++++++++++++++++++++- src/views/general/sectionHeader.ts | 1 + src/views/stashDetailView.ts | 4 +-- syntaxes/magit.tmGrammar.json | 2 +- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/commands/diffingCommands.ts b/src/commands/diffingCommands.ts index 1e57052..1fb2d91 100644 --- a/src/commands/diffingCommands.ts +++ b/src/commands/diffingCommands.ts @@ -3,6 +3,7 @@ import { MagitRepository } from '../models/magitRepository'; import { gitRun } from '../utils/gitRawRunner'; import { DiffView } from '../views/diffView'; import { MenuUtil, MenuState } from '../menu/menu'; +import GitTextUtils from '../utils/gitTextUtils'; import { PickMenuUtil, PickMenuItem } from '../menu/pickMenu'; import { StashDetailView } from '../views/stashDetailView'; import MagitUtils from '../utils/magitUtils'; @@ -14,6 +15,7 @@ import { Status } from '../typings/git'; import { MagitChange } from '../models/magitChange'; import { Stash } from '../models/stash'; import ViewUtils from '../utils/viewUtils'; +import { constants } from 'buffer'; const diffingMenu = { title: 'Diffing', @@ -102,9 +104,51 @@ async function showStash({ repository }: MenuState) { } } +function toMagitChange(nameStatusText: string, diff: string): MagitChange[] { + const DIFF_PREFIX = 'diff --git'; + const filesWithStatus = nameStatusText.split(Constants.LineSplitterRegex).filter(t => t !== '').map(s => s.split('\t')); + const diffs = diff.split(DIFF_PREFIX).filter(r => r !== ''); + + if (filesWithStatus.length !== diffs.length) { + return []; + } + + return diffs.map((diff, idx) => { + const [status, ...paths] = filesWithStatus[idx]; + const uri = Uri.file(paths[paths.length - 1]); + const fileStatus = getStatusFromString(status); + return { + diff, + uri, + originalUri: uri, + status: fileStatus, + renameUri: undefined, + relativePath: paths.join(' -> '), + hunks: diff ? GitTextUtils.diffToHunks(diff, uri) : undefined, + }; + }); +} + +function getStatusFromString(status: String): number { + switch (status.charAt(0)) { + case 'A': + return Status.INDEX_ADDED; + case 'C': + return Status.INDEX_COPIED ; + case 'D': + return Status.DELETED; + case 'R' : + return Status.INDEX_RENAMED; + case 'M': + default: + return Status.MODIFIED; + } +} + export async function showStashDetail(repository: MagitRepository, stash: Stash) { const uri = StashDetailView.encodeLocation(repository, stash); + const nameStatusTask = gitRun(repository.gitRepository, ['stash', 'show', '--name-status', `stash@{${stash.index}}`]); const stashShowTask = gitRun(repository.gitRepository, ['stash', 'show', '-p', `stash@{${stash.index}}`]); let stashUntrackedFiles: MagitChange[] = []; try { @@ -124,9 +168,10 @@ export async function showStashDetail(repository: MagitRepository, stash: Stash) } catch { } + const nameStatusText = (await nameStatusTask).stdout; const stashDiff = (await stashShowTask).stdout; - return ViewUtils.showView(uri, new StashDetailView(uri, stash, stashDiff, stashUntrackedFiles)); + return ViewUtils.showView(uri, new StashDetailView(uri, stash, toMagitChange(nameStatusText, stashDiff), stashUntrackedFiles)); } async function showCommit({ repository }: MenuState) { diff --git a/src/views/general/sectionHeader.ts b/src/views/general/sectionHeader.ts index 2dd6581..f313aa4 100644 --- a/src/views/general/sectionHeader.ts +++ b/src/views/general/sectionHeader.ts @@ -18,6 +18,7 @@ export enum Section { Tags = 'Tags', PullRequests = 'Pull Requests', Issues = 'Issues', + Changes='Changes', } export class SectionHeaderView extends UnclickableTextView { diff --git a/src/views/stashDetailView.ts b/src/views/stashDetailView.ts index 605d9cc..47d90af 100644 --- a/src/views/stashDetailView.ts +++ b/src/views/stashDetailView.ts @@ -13,7 +13,7 @@ export class StashDetailView extends DocumentView { static UriPath: string = 'stash.magit'; needsUpdate = false; - constructor(public uri: Uri, stash: Stash, diff: string, untrackedFiles: MagitChange[]) { + constructor(public uri: Uri, stash: Stash, diffChanges: MagitChange[], untrackedFiles: MagitChange[] ) { super(uri); this.addSubview(new TextView(`Stash@{${stash.index}} ${stash.description}`)); @@ -22,7 +22,7 @@ export class StashDetailView extends DocumentView { this.addSubview(new ChangeSectionView(Section.Untracked, untrackedFiles, `-stashDetail@{${stash.index}}`)); } - this.addSubview(new TextView(diff)); + this.addSubview(new ChangeSectionView(Section.Changes, diffChanges, `-stashDetail@{${stash.index}}`)); } public update(state: MagitRepository): void { } diff --git a/syntaxes/magit.tmGrammar.json b/syntaxes/magit.tmGrammar.json index a1d543c..28a52ac 100644 --- a/syntaxes/magit.tmGrammar.json +++ b/syntaxes/magit.tmGrammar.json @@ -38,7 +38,7 @@ ] }, "sectionHeader": { - "match": "^(Untracked files|((Unstaged|Staged) changes)|Stashes|Recent commits|Unmerged into|Unpushed to|Unpulled from|HEAD|Branches|Remote|Tags|Pull Requests|Issues|GitError!|(Merging .*(?= \\())|(Rebasing .* onto .*$)|Cherry Picking|Reverting|Stash@{\\d+}|(Commits in .*$))", + "match": "^(Untracked files|((Unstaged|Staged) changes)|Stashes|Recent commits|Unmerged into|Unpushed to|Unpulled from|HEAD|Branches|Remote|Tags|Pull Requests|Issues|GitError!|(Merging .*(?= \\())|(Rebasing .* onto .*$)|Cherry Picking|Reverting|Stash@{\\d+}|(Commits in .*$))|Changes", "name": "strong keyword.operator.new.section.header.magit magit.header" }, "highlight": {