Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 87689e1

Browse files
committed
Implemented change-block navigation
* Modified behavior of the Prev/Next Change buttons in DiffView toolbar. * Well-defined change-blocks are pre-calculated and can be navigated between. * Current change-block is highlighted in the Diff panel(s). * Prev/next at start/end of range (re-)scrolls to first/last change-block (I.e when unset, or already at first/last change-block, or at the only one.) * Current change-block is unset in RefreshContent().
1 parent 1bda4de commit 87689e1

File tree

7 files changed

+252
-31
lines changed

7 files changed

+252
-31
lines changed

‎src/Commands/Diff.cs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ public Models.DiffResult Result()
5151
_result.TextDiff.MaxLineNumber = Math.Max(_newLine, _oldLine);
5252
}
5353

54+
if (_result.TextDiff != null)
55+
_result.TextDiff.ProcessChangeBlocks();
56+
5457
return _result;
5558
}
5659

‎src/Models/DiffResult.cs‎

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Text;
33
using System.Text.RegularExpressions;
44

5+
using CommunityToolkit.Mvvm.ComponentModel;
6+
57
using Avalonia;
68
using Avalonia.Media.Imaging;
79

@@ -59,16 +61,70 @@ public bool IsInRange(int idx)
5961
}
6062
}
6163

62-
public partial class TextDiff
64+
public class TextDiffChangeBlock
65+
{
66+
public TextDiffChangeBlock(int startLine, int endLine)
67+
{
68+
StartLine = startLine;
69+
EndLine = endLine;
70+
}
71+
72+
public int StartLine { get; set; } = 0;
73+
public int EndLine { get; set; } = 0;
74+
75+
public bool IsInRange(int line)
76+
{
77+
return line >= StartLine && line <= EndLine;
78+
}
79+
}
80+
81+
public partial class TextDiff : ObservableObject
6382
{
6483
public string File { get; set; } = string.Empty;
6584
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
6685
public Vector ScrollOffset { get; set; } = Vector.Zero;
6786
public int MaxLineNumber = 0;
6887

88+
public int CurrentChangeBlockIdx
89+
{
90+
get => _currentChangeBlockIdx;
91+
set => SetProperty(ref _currentChangeBlockIdx, value);
92+
}
93+
6994
public string Repo { get; set; } = null;
7095
public DiffOption Option { get; set; } = null;
7196

97+
public List<TextDiffChangeBlock> ChangeBlocks { get; set; } = [];
98+
99+
public void ProcessChangeBlocks()
100+
{
101+
ChangeBlocks.Clear();
102+
int lineIdx = 0, blockStartIdx = 0;
103+
bool isNewBlock = true;
104+
foreach (var line in Lines)
105+
{
106+
lineIdx++;
107+
if (line.Type == Models.TextDiffLineType.Added ||
108+
line.Type == Models.TextDiffLineType.Deleted ||
109+
line.Type == Models.TextDiffLineType.None) // Empty
110+
{
111+
if (isNewBlock)
112+
{
113+
isNewBlock = false;
114+
blockStartIdx = lineIdx;
115+
}
116+
}
117+
else
118+
{
119+
if (!isNewBlock)
120+
{
121+
ChangeBlocks.Add(new TextDiffChangeBlock(blockStartIdx, lineIdx - 1));
122+
isNewBlock = true;
123+
}
124+
}
125+
}
126+
}
127+
72128
public TextDiffSelection MakeSelection(int startLine, int endLine, bool isCombined, bool isOldSide)
73129
{
74130
var rs = new TextDiffSelection();
@@ -626,6 +682,8 @@ private bool ProcessIndicatorForPatchSingleSide(StringBuilder builder, TextDiffL
626682
return true;
627683
}
628684

685+
private int _currentChangeBlockIdx = -1; // NOTE: Use -1 as "not set".
686+
629687
[GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")]
630688
private static partial Regex REG_INDICATOR();
631689
}

‎src/ViewModels/DiffContext.cs‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,40 @@ public DiffContext(string repo, Models.DiffOption option, DiffContext previous =
7373
LoadDiffContent();
7474
}
7575

76+
public void PrevChange()
77+
{
78+
if (_content is Models.TextDiff textDiff)
79+
{
80+
if (textDiff.CurrentChangeBlockIdx > 0)
81+
{
82+
textDiff.CurrentChangeBlockIdx--;
83+
}
84+
else if (textDiff.ChangeBlocks.Count > 0)
85+
{
86+
// Force property value change and (re-)jump to first change block
87+
textDiff.CurrentChangeBlockIdx = -1;
88+
textDiff.CurrentChangeBlockIdx = 0;
89+
}
90+
}
91+
}
92+
93+
public void NextChange()
94+
{
95+
if (_content is Models.TextDiff textDiff)
96+
{
97+
if (textDiff.CurrentChangeBlockIdx < textDiff.ChangeBlocks.Count - 1)
98+
{
99+
textDiff.CurrentChangeBlockIdx++;
100+
}
101+
else if (textDiff.ChangeBlocks.Count > 0)
102+
{
103+
// Force property value change and (re-)jump to last change block
104+
textDiff.CurrentChangeBlockIdx = -1;
105+
textDiff.CurrentChangeBlockIdx = textDiff.ChangeBlocks.Count - 1;
106+
}
107+
}
108+
}
109+
76110
public void ToggleFullTextDiff()
77111
{
78112
Preference.Instance.UseFullTextDiff = !Preference.Instance.UseFullTextDiff;

‎src/ViewModels/TwoSideTextDiff.cs‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,43 @@ public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
4545

4646
FillEmptyLines();
4747

48+
ProcessChangeBlocks();
49+
4850
if (previous != null && previous.File == File)
4951
_syncScrollOffset = previous._syncScrollOffset;
5052
}
5153

54+
public List<Models.TextDiffChangeBlock> ChangeBlocks { get; set; } = [];
55+
56+
public void ProcessChangeBlocks()
57+
{
58+
ChangeBlocks.Clear();
59+
int lineIdx = 0, blockStartIdx = 0;
60+
bool isNewBlock = true;
61+
foreach (var line in Old) // NOTE: Same block size in both Old and New lines.
62+
{
63+
lineIdx++;
64+
if (line.Type == Models.TextDiffLineType.Added ||
65+
line.Type == Models.TextDiffLineType.Deleted ||
66+
line.Type == Models.TextDiffLineType.None) // Empty
67+
{
68+
if (isNewBlock)
69+
{
70+
isNewBlock = false;
71+
blockStartIdx = lineIdx;
72+
}
73+
}
74+
else
75+
{
76+
if (!isNewBlock)
77+
{
78+
ChangeBlocks.Add(new Models.TextDiffChangeBlock(blockStartIdx, lineIdx - 1));
79+
isNewBlock = true;
80+
}
81+
}
82+
}
83+
}
84+
5285
public void ConvertsToCombinedRange(Models.TextDiff combined, ref int startLine, ref int endLine, bool isOldSide)
5386
{
5487
endLine = Math.Min(endLine, combined.Lines.Count - 1);

‎src/Views/DiffView.axaml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@
241241
<DataTemplate DataType="m:TextDiff">
242242
<v:TextDiffView
243243
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"
244-
UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"/>
244+
UseFullTextDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
245+
CurrentChangeBlockIdx="{Binding CurrentChangeBlockIdx, Mode=OneWay}"/>
245246
</DataTemplate>
246247

247248
<!-- Empty or only EOL changes -->

‎src/Views/TextDiffView.axaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
3131
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
3232
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
33+
CurrentChangeBlockIdx="{Binding #ThisControl.CurrentChangeBlockIdx}"
3334
EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}"
3435
SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"/>
3536

@@ -61,6 +62,7 @@
6162
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
6263
WordWrap="False"
6364
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
65+
CurrentChangeBlockIdx="{Binding #ThisControl.CurrentChangeBlockIdx}"
6466
EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}"
6567
SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"/>
6668

@@ -82,6 +84,7 @@
8284
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
8385
WordWrap="False"
8486
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
87+
CurrentChangeBlockIdx="{Binding #ThisControl.CurrentChangeBlockIdx}"
8588
EnableChunkSelection="{Binding #ThisControl.EnableChunkSelection}"
8689
SelectedChunk="{Binding #ThisControl.SelectedChunk, Mode=TwoWay}"/>
8790

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /