on main help sign in
Merge pull request #16 from charmbracelet/diff-overhaul

feat(diffview): add a standalone diffview component

commit93b41c91d4dc499849d0b33b435d649e8f4ddaee authorAndrey Nering <andreynering@users.noreply.github.com> dateMon 16 Jun 2025, 16:42 (1 year ago) parentacb1ad134fa3c1
352 files changed+5755−460
go.mod+3−2 go.sum+4−4 internal/exp/diffview/Taskfile.yaml+102 internal/exp/diffview/chroma.go+52 internal/exp/diffview/diffview.go+681 internal/exp/diffview/diffview_test.go+300 internal/exp/diffview/split.go+74 internal/exp/diffview/style.go+124 internal/exp/diffview/testdata/TestDefault.after+10 internal/exp/diffview/testdata/TestDefault.before+9 internal/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/DarkMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/LightMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Split/Default/DarkMode.golden+7 internal/exp/diffview/testdata/TestDiffView/Split/Default/LightMode.golden+7 internal/exp/diffview/testdata/TestDiffView/Split/LargeWidth/DarkMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/LargeWidth/LightMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/DarkMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/LightMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/Narrow/DarkMode.golden+4 internal/exp/diffview/testdata/TestDiffView/Split/Narrow/LightMode.golden+4 internal/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/DarkMode.golden+7 internal/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/LightMode.golden+7 internal/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/DarkMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/LightMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/SmallWidth/DarkMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Split/SmallWidth/LightMode.golden+15 internal/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/DarkMode.golden+17 internal/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/LightMode.golden+17 internal/exp/diffview/testdata/TestDiffView/Unified/Default/DarkMode.golden+8 internal/exp/diffview/testdata/TestDiffView/Unified/Default/LightMode.golden+8 internal/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/DarkMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/LightMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/DarkMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/LightMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/Narrow/DarkMode.golden+7 internal/exp/diffview/testdata/TestDiffView/Unified/Narrow/LightMode.golden+7 internal/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/DarkMode.golden+8 internal/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/LightMode.golden+8 internal/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/DarkMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/LightMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/DarkMode.golden+16 internal/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/LightMode.golden+16 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf001.golden+1 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf002.golden+2 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf003.golden+3 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf004.golden+4 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf005.golden+5 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf006.golden+6 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf007.golden+7 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf008.golden+8 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf009.golden+9 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf010.golden+10 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf011.golden+11 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf012.golden+12 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf013.golden+13 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf014.golden+14 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf015.golden+15 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf016.golden+16 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf017.golden+17 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf018.golden+18 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf019.golden+19 internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf020.golden+20 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf001.golden+1 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf002.golden+2 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf003.golden+3 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf004.golden+4 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf005.golden+5 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf006.golden+6 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf007.golden+7 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf008.golden+8 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf009.golden+9 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf010.golden+10 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf011.golden+11 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf012.golden+12 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf013.golden+13 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf014.golden+14 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf015.golden+15 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf016.golden+16 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf017.golden+17 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf018.golden+18 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf019.golden+19 internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf020.golden+20 internal/exp/diffview/testdata/TestDiffViewTabs/Split.golden+15 internal/exp/diffview/testdata/TestDiffViewTabs/Unified.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf001.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf002.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf003.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf004.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf005.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf006.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf007.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf008.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf009.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf010.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf011.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf012.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf013.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf014.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf015.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf016.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf017.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf018.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf019.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf020.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf021.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf022.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf023.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf024.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf025.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf026.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf027.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf028.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf029.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf030.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf031.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf032.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf033.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf034.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf035.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf036.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf037.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf038.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf039.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf040.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf041.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf042.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf043.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf044.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf045.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf046.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf047.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf048.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf049.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf050.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf051.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf052.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf053.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf054.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf055.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf056.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf057.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf058.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf059.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf060.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf061.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf062.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf063.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf064.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf065.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf066.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf067.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf068.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf069.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf070.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf071.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf072.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf073.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf074.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf075.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf076.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf077.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf078.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf079.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf080.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf081.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf082.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf083.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf084.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf085.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf086.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf087.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf088.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf089.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf090.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf091.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf092.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf093.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf094.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf095.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf096.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf097.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf098.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf099.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf100.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf101.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf102.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf103.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf104.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf105.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf106.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf107.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf108.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf109.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf110.golden+15 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf001.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf002.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf003.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf004.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf005.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf006.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf007.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf008.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf009.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf010.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf011.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf012.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf013.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf014.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf015.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf016.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf017.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf018.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf019.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf020.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf021.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf022.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf023.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf024.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf025.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf026.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf027.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf028.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf029.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf030.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf031.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf032.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf033.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf034.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf035.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf036.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf037.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf038.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf039.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf040.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf041.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf042.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf043.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf044.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf045.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf046.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf047.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf048.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf049.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf050.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf051.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf052.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf053.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf054.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf055.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf056.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf057.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf058.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf059.golden+16 internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf060.golden+16 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf00.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf01.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf02.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf03.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf04.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf05.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf06.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf07.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf08.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf09.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf10.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf11.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf12.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf13.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf14.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf15.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf16.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf17.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf18.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf19.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf20.golden+7 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf00.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf01.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf02.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf03.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf04.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf05.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf06.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf07.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf08.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf09.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf10.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf11.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf12.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf13.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf14.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf15.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf16.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf17.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf18.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf19.golden+8 internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf20.golden+8 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf00.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf01.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf02.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf03.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf04.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf05.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf06.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf07.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf08.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf09.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf10.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf11.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf12.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf13.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf14.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf15.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf16.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf00.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf01.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf02.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf03.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf04.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf05.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf06.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf07.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf08.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf09.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf10.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf11.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf12.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf13.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf14.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf15.golden+5 internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf16.golden+5 internal/exp/diffview/testdata/TestMultipleHunks.after+15 internal/exp/diffview/testdata/TestMultipleHunks.before+13 internal/exp/diffview/testdata/TestNarrow.after+3 internal/exp/diffview/testdata/TestNarrow.before+3 internal/exp/diffview/testdata/TestTabs.after+15 internal/exp/diffview/testdata/TestTabs.before+13 internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/Content.golden+11 internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/JSON.golden+40 internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/Content.golden+12 internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/JSON.golden+44 internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/Content.golden+13 internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/JSON.golden+48 internal/exp/diffview/testdata/TestUdiff/Unified.golden+11 internal/exp/diffview/udiff_test.go+92 internal/exp/diffview/util.go+39 internal/exp/diffview/util_test.go+27 internal/llm/agent/tools.go−1 internal/llm/tools/edit.go+31−23 internal/llm/tools/patch.go−372 internal/tui/components/chat/messages/renderer.go+7−39 internal/tui/components/core/helpers.go+11 internal/tui/components/dialogs/permissions/permissions.go+6−19
go.mod+3−2
@@ -9,7 +9,7 @@ require (
99 github.com/PuerkitoBio/goquery v1.9.2
1010 github.com/alecthomas/chroma/v2 v2.15.0
1111 github.com/anthropics/anthropic-sdk-go v1.4.0
12− github.com/aymanbagabas/go-udiff v0.2.0
12+ github.com/aymanbagabas/go-udiff v0.3.1
1313 github.com/bmatcuk/doublestar/v4 v4.8.1
1414 github.com/charlievieth/fastwalk v1.0.11
1515 github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250607113720-eb5e1cf3b09e
@@ -18,6 +18,7 @@ require (
1818 github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1.0.20250523195325-2d1af06b557c
1919 github.com/charmbracelet/x/ansi v0.9.3-0.20250602153603-fb931ed90413
2020 github.com/charmbracelet/x/exp/charmtone v0.0.0-20250530202730-6ba1785cd7b9
21+ github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a
2122 github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec
2223 github.com/fsnotify/fsnotify v1.8.0
2324 github.com/go-logfmt/logfmt v0.6.0
@@ -65,7 +66,7 @@ require (
6566 github.com/aymerick/douceur v0.2.0 // indirect
6667 github.com/charmbracelet/colorprofile v0.3.1 // indirect
6768 github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa // indirect
68− github.com/charmbracelet/x/exp/slice v0.0.0-20250528180458-2d5d6cb84620
69+ github.com/charmbracelet/x/exp/slice v0.0.0-20250611152503-f53cdd7e01ef
6970 github.com/charmbracelet/x/input v0.3.5-0.20250509021451-13796e822d86 // indirect
7071 github.com/charmbracelet/x/term v0.2.1 // indirect
7172 github.com/charmbracelet/x/windows v0.2.1 // indirect
go.sum+4−4
@@ -60,8 +60,8 @@ github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
6060github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
6161github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
6262github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
63−github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
64−github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
63+github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
64+github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
6565github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
6666github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
6767github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
@@ -86,8 +86,8 @@ github.com/charmbracelet/x/exp/charmtone v0.0.0-20250530202730-6ba1785cd7b9 h1:f
8686github.com/charmbracelet/x/exp/charmtone v0.0.0-20250530202730-6ba1785cd7b9/go.mod h1:vr+xCFylsPYq2qSz+n5/jItjcK2/PgrKFMTI7VRR6CI=
8787github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a h1:FsHEJ52OC4VuTzU8t+n5frMjLvpYWEznSr/u8tnkCYw=
8888github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
89−github.com/charmbracelet/x/exp/slice v0.0.0-20250528180458-2d5d6cb84620 h1:/PN4jqP3ki9NvtHRrYZ9ewCutKZB6DK8frTW+Dj/MWs=
90−github.com/charmbracelet/x/exp/slice v0.0.0-20250528180458-2d5d6cb84620/go.mod h1:vI5nDVMWi6veaYH+0Fmvpbe/+cv/iJfMntdh+N0+Tms=
89+github.com/charmbracelet/x/exp/slice v0.0.0-20250611152503-f53cdd7e01ef h1:v7qwsZ2OxzlwvpKwz8dtZXp7fIJlcDEUOyFBNE4fz4Q=
90+github.com/charmbracelet/x/exp/slice v0.0.0-20250611152503-f53cdd7e01ef/go.mod h1:vI5nDVMWi6veaYH+0Fmvpbe/+cv/iJfMntdh+N0+Tms=
9191github.com/charmbracelet/x/input v0.3.5-0.20250509021451-13796e822d86 h1:BxAEmOBIDajkgao3EsbBxKQCYvgYPGdT62WASLvtf4Y=
9292github.com/charmbracelet/x/input v0.3.5-0.20250509021451-13796e822d86/go.mod h1:62Rp/6EtTxoeJDSdtpA3tJp3y3ZRpsiekBSje+K8htA=
9393github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
internal/exp/diffview/Taskfile.yamlnew file+102
@@ -0,0 +1,102 @@
1+version: "3"
2+
3+tasks:
4+ test:
5+ desc: Run tests
6+ cmds:
7+ - go test ./... {{.CLI_ARGS}}
8+
9+ test:update:
10+ desc: Run tests and update golden files
11+ cmds:
12+ - go test ./... -update {{.CLI_ARGS}}
13+
14+ test:print:
15+ desc: Print golden files for debugging
16+ method: none
17+ sources:
18+ - ./testdata/TestDiffView/**/*.golden
19+ cmds:
20+ - for: sources
21+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
22+ silent: true
23+
24+ test:print:width:unified:
25+ desc: Print golden files for debugging
26+ method: none
27+ sources:
28+ - ./testdata/TestDiffViewWidth/Unified/*.golden
29+ cmds:
30+ - for: sources
31+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
32+ silent: true
33+
34+ test:print:width:split:
35+ desc: Print golden files for debugging
36+ method: none
37+ sources:
38+ - ./testdata/TestDiffViewWidth/Split/*.golden
39+ cmds:
40+ - for: sources
41+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
42+ silent: true
43+
44+ test:print:height:unified:
45+ desc: Print golden files for debugging
46+ method: none
47+ sources:
48+ - ./testdata/TestDiffViewHeight/Unified/*.golden
49+ cmds:
50+ - for: sources
51+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
52+ silent: true
53+
54+ test:print:height:split:
55+ desc: Print golden files for debugging
56+ method: none
57+ sources:
58+ - ./testdata/TestDiffViewHeight/Split/*.golden
59+ cmds:
60+ - for: sources
61+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
62+ silent: true
63+
64+ test:print:xoffset:unified:
65+ desc: Print golden files for debugging
66+ method: none
67+ sources:
68+ - ./testdata/TestDiffViewXOffset/Unified/*.golden
69+ cmds:
70+ - for: sources
71+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
72+ silent: true
73+
74+ test:print:xoffset:split:
75+ desc: Print golden files for debugging
76+ method: none
77+ sources:
78+ - ./testdata/TestDiffViewXOffset/Split/*.golden
79+ cmds:
80+ - for: sources
81+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
82+ silent: true
83+
84+ test:print:yoffset:unified:
85+ desc: Print golden files for debugging
86+ method: none
87+ sources:
88+ - ./testdata/TestDiffViewYOffset/Unified/*.golden
89+ cmds:
90+ - for: sources
91+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
92+ silent: true
93+
94+ test:print:yoffset:split:
95+ desc: Print golden files for debugging
96+ method: none
97+ sources:
98+ - ./testdata/TestDiffViewYOffset/Split/*.golden
99+ cmds:
100+ - for: sources
101+ cmd: echo && echo "------- {{.ITEM}} -------" && echo && cat {{.ITEM}}
102+ silent: true
internal/exp/diffview/chroma.gonew file+52
@@ -0,0 +1,52 @@
1+package diffview
2+
3+import (
4+ "fmt"
5+ "image/color"
6+ "io"
7+
8+ "github.com/alecthomas/chroma/v2"
9+ "github.com/charmbracelet/lipgloss/v2"
10+)
11+
12+var _ chroma.Formatter = chromaFormatter{}
13+
14+// chromaFormatter is a custom formatter for Chroma that uses Lip Gloss for
15+// foreground styling, while keeping a forced background color.
16+type chromaFormatter struct {
17+ bgColor color.Color
18+}
19+
20+// Format implements the chroma.Formatter interface.
21+func (c chromaFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) error {
22+ for token := it(); token != chroma.EOF; token = it() {
23+ entry := style.Get(token.Type)
24+ if entry.IsZero() {
25+ if _, err := fmt.Fprint(w, token.Value); err != nil {
26+ return err
27+ }
28+ continue
29+ }
30+
31+ s := lipgloss.NewStyle().
32+ Background(c.bgColor)
33+
34+ if entry.Bold == chroma.Yes {
35+ s = s.Bold(true)
36+ }
37+ if entry.Underline == chroma.Yes {
38+ s = s.Underline(true)
39+ }
40+ if entry.Italic == chroma.Yes {
41+ s = s.Italic(true)
42+ }
43+ if entry.Colour.IsSet() {
44+ s = s.Foreground(lipgloss.Color(entry.Colour.String()))
45+ }
46+
47+ if _, err := fmt.Fprint(w, s.Render(token.Value)); err != nil {
48+ return err
49+ }
50+ }
51+ return nil
52+}
internal/exp/diffview/diffview.gonew file+681
@@ -0,0 +1,681 @@
1+package diffview
2+
3+import (
4+ "fmt"
5+ "image/color"
6+ "strconv"
7+ "strings"
8+
9+ "github.com/alecthomas/chroma/v2"
10+ "github.com/alecthomas/chroma/v2/lexers"
11+ "github.com/aymanbagabas/go-udiff"
12+ "github.com/aymanbagabas/go-udiff/myers"
13+ "github.com/charmbracelet/lipgloss/v2"
14+ "github.com/charmbracelet/x/ansi"
15+)
16+
17+const (
18+ leadingSymbolsSize = 2
19+ lineNumPadding = 1
20+)
21+
22+type file struct {
23+ path string
24+ content string
25+}
26+
27+type layout int
28+
29+const (
30+ layoutUnified layout = iota + 1
31+ layoutSplit
32+)
33+
34+// DiffView represents a view for displaying differences between two files.
35+type DiffView struct {
36+ layout layout
37+ before file
38+ after file
39+ contextLines int
40+ lineNumbers bool
41+ highlight bool
42+ height int
43+ width int
44+ xOffset int
45+ yOffset int
46+ style Style
47+ tabWidth int
48+ chromaStyle *chroma.Style
49+
50+ isComputed bool
51+ err error
52+ unified udiff.UnifiedDiff
53+ edits []udiff.Edit
54+
55+ splitHunks []splitHunk
56+
57+ codeWidth int
58+ fullCodeWidth int // with leading symbols
59+ extraColOnAfter bool // add extra column on after panel
60+ beforeNumDigits int
61+ afterNumDigits int
62+}
63+
64+// New creates a new DiffView with default settings.
65+func New() *DiffView {
66+ dv := &DiffView{
67+ layout: layoutUnified,
68+ contextLines: udiff.DefaultContextLines,
69+ lineNumbers: true,
70+ tabWidth: 8,
71+ }
72+ dv.style = DefaultDarkStyle()
73+ return dv
74+}
75+
76+// Unified sets the layout of the DiffView to unified.
77+func (dv *DiffView) Unified() *DiffView {
78+ dv.layout = layoutUnified
79+ return dv
80+}
81+
82+// Split sets the layout of the DiffView to split (side-by-side).
83+func (dv *DiffView) Split() *DiffView {
84+ dv.layout = layoutSplit
85+ return dv
86+}
87+
88+// Before sets the "before" file for the DiffView.
89+func (dv *DiffView) Before(path, content string) *DiffView {
90+ dv.before = file{path: path, content: content}
91+ return dv
92+}
93+
94+// After sets the "after" file for the DiffView.
95+func (dv *DiffView) After(path, content string) *DiffView {
96+ dv.after = file{path: path, content: content}
97+ return dv
98+}
99+
100+// ContextLines sets the number of context lines for the DiffView.
101+func (dv *DiffView) ContextLines(contextLines int) *DiffView {
102+ dv.contextLines = contextLines
103+ return dv
104+}
105+
106+// Style sets the style for the DiffView.
107+func (dv *DiffView) Style(style Style) *DiffView {
108+ dv.style = style
109+ return dv
110+}
111+
112+// LineNumbers sets whether to display line numbers in the DiffView.
113+func (dv *DiffView) LineNumbers(lineNumbers bool) *DiffView {
114+ dv.lineNumbers = lineNumbers
115+ return dv
116+}
117+
118+// SyntaxHightlight sets whether to enable syntax highlighting in the DiffView.
119+func (dv *DiffView) SyntaxHightlight(highlight bool) *DiffView {
120+ dv.highlight = highlight
121+ return dv
122+}
123+
124+// Height sets the height of the DiffView.
125+func (dv *DiffView) Height(height int) *DiffView {
126+ dv.height = height
127+ return dv
128+}
129+
130+// Width sets the width of the DiffView.
131+func (dv *DiffView) Width(width int) *DiffView {
132+ dv.width = width
133+ return dv
134+}
135+
136+// XOffset sets the horizontal offset for the DiffView.
137+func (dv *DiffView) XOffset(xOffset int) *DiffView {
138+ dv.xOffset = xOffset
139+ return dv
140+}
141+
142+// YOffset sets the vertical offset for the DiffView.
143+func (dv *DiffView) YOffset(yOffset int) *DiffView {
144+ dv.yOffset = yOffset
145+ return dv
146+}
147+
148+// TabWidth sets the tab width. Only relevant for code that contains tabs, like
149+// Go code.
150+func (dv *DiffView) TabWidth(tabWidth int) *DiffView {
151+ dv.tabWidth = tabWidth
152+ return dv
153+}
154+
155+// ChromaStyle sets the chroma style for syntax highlighting.
156+// If nil, no syntax highlighting will be applied.
157+func (dv *DiffView) ChromaStyle(style *chroma.Style) *DiffView {
158+ dv.chromaStyle = style
159+ return dv
160+}
161+
162+// String returns the string representation of the DiffView.
163+func (dv *DiffView) String() string {
164+ dv.replaceTabs()
165+ if err := dv.computeDiff(); err != nil {
166+ return err.Error()
167+ }
168+ dv.convertDiffToSplit()
169+ dv.adjustStyles()
170+ dv.detectNumDigits()
171+
172+ if dv.width <= 0 {
173+ dv.detectCodeWidth()
174+ } else {
175+ dv.resizeCodeWidth()
176+ }
177+
178+ style := lipgloss.NewStyle()
179+ if dv.width > 0 {
180+ style = style.MaxWidth(dv.width)
181+ }
182+ if dv.height > 0 {
183+ style = style.MaxHeight(dv.height)
184+ }
185+
186+ switch dv.layout {
187+ case layoutUnified:
188+ return style.Render(strings.TrimSuffix(dv.renderUnified(), "\n"))
189+ case layoutSplit:
190+ return style.Render(strings.TrimSuffix(dv.renderSplit(), "\n"))
191+ default:
192+ panic("unknown diffview layout")
193+ }
194+}
195+
196+// replaceTabs replaces tabs in the before and after file contents with spaces
197+// according to the specified tab width.
198+func (dv *DiffView) replaceTabs() {
199+ spaces := strings.Repeat(" ", dv.tabWidth)
200+ dv.before.content = strings.ReplaceAll(dv.before.content, "\t", spaces)
201+ dv.after.content = strings.ReplaceAll(dv.after.content, "\t", spaces)
202+}
203+
204+// computeDiff computes the differences between the "before" and "after" files.
205+func (dv *DiffView) computeDiff() error {
206+ if dv.isComputed {
207+ return dv.err
208+ }
209+ dv.isComputed = true
210+ dv.edits = myers.ComputeEdits( //nolint:staticcheck
211+ dv.before.content,
212+ dv.after.content,
213+ )
214+ dv.unified, dv.err = udiff.ToUnifiedDiff(
215+ dv.before.path,
216+ dv.after.path,
217+ dv.before.content,
218+ dv.edits,
219+ dv.contextLines,
220+ )
221+ return dv.err
222+}
223+
224+// convertDiffToSplit converts the unified diff to a split diff if the layout is
225+// set to split.
226+func (dv *DiffView) convertDiffToSplit() {
227+ if dv.layout != layoutSplit {
228+ return
229+ }
230+
231+ dv.splitHunks = make([]splitHunk, len(dv.unified.Hunks))
232+ for i, h := range dv.unified.Hunks {
233+ dv.splitHunks[i] = hunkToSplit(h)
234+ }
235+}
236+
237+// adjustStyles adjusts adds padding and alignment to the styles.
238+func (dv *DiffView) adjustStyles() {
239+ setPadding := func(s lipgloss.Style) lipgloss.Style {
240+ return s.Padding(0, lineNumPadding).Align(lipgloss.Right)
241+ }
242+ dv.style.MissingLine.LineNumber = setPadding(dv.style.MissingLine.LineNumber)
243+ dv.style.DividerLine.LineNumber = setPadding(dv.style.DividerLine.LineNumber)
244+ dv.style.EqualLine.LineNumber = setPadding(dv.style.EqualLine.LineNumber)
245+ dv.style.InsertLine.LineNumber = setPadding(dv.style.InsertLine.LineNumber)
246+ dv.style.DeleteLine.LineNumber = setPadding(dv.style.DeleteLine.LineNumber)
247+}
248+
249+// detectNumDigits calculates the maximum number of digits needed for before and
250+// after line numbers.
251+func (dv *DiffView) detectNumDigits() {
252+ dv.beforeNumDigits = 0
253+ dv.afterNumDigits = 0
254+
255+ for _, h := range dv.unified.Hunks {
256+ dv.beforeNumDigits = max(dv.beforeNumDigits, len(strconv.Itoa(h.FromLine+len(h.Lines))))
257+ dv.afterNumDigits = max(dv.afterNumDigits, len(strconv.Itoa(h.ToLine+len(h.Lines))))
258+ }
259+}
260+
261+// detectCodeWidth calculates the maximum width of code lines in the diff view.
262+func (dv *DiffView) detectCodeWidth() {
263+ switch dv.layout {
264+ case layoutUnified:
265+ dv.detectUnifiedCodeWidth()
266+ case layoutSplit:
267+ dv.detectSplitCodeWidth()
268+ }
269+ dv.fullCodeWidth = dv.codeWidth + leadingSymbolsSize
270+}
271+
272+// detectUnifiedCodeWidth calculates the maximum width of code lines in a
273+// unified diff.
274+func (dv *DiffView) detectUnifiedCodeWidth() {
275+ dv.codeWidth = 0
276+
277+ for _, h := range dv.unified.Hunks {
278+ shownLines := ansi.StringWidth(dv.hunkLineFor(h))
279+
280+ for _, l := range h.Lines {
281+ lineWidth := ansi.StringWidth(strings.TrimSuffix(l.Content, "\n")) + 1
282+ dv.codeWidth = max(dv.codeWidth, lineWidth, shownLines)
283+ }
284+ }
285+}
286+
287+// detectSplitCodeWidth calculates the maximum width of code lines in a
288+// split diff.
289+func (dv *DiffView) detectSplitCodeWidth() {
290+ dv.codeWidth = 0
291+
292+ for i, h := range dv.splitHunks {
293+ shownLines := ansi.StringWidth(dv.hunkLineFor(dv.unified.Hunks[i]))
294+
295+ for _, l := range h.lines {
296+ if l.before != nil {
297+ codeWidth := ansi.StringWidth(strings.TrimSuffix(l.before.Content, "\n")) + 1
298+ dv.codeWidth = max(dv.codeWidth, codeWidth, shownLines)
299+ }
300+ if l.after != nil {
301+ codeWidth := ansi.StringWidth(strings.TrimSuffix(l.after.Content, "\n")) + 1
302+ dv.codeWidth = max(dv.codeWidth, codeWidth, shownLines)
303+ }
304+ }
305+ }
306+}
307+
308+// resizeCodeWidth resizes the code width to fit within the specified width.
309+func (dv *DiffView) resizeCodeWidth() {
310+ fullNumWidth := dv.beforeNumDigits + dv.afterNumDigits
311+ fullNumWidth += lineNumPadding * 4 // left and right padding for both line numbers
312+
313+ switch dv.layout {
314+ case layoutUnified:
315+ dv.codeWidth = dv.width - fullNumWidth - leadingSymbolsSize
316+ case layoutSplit:
317+ remainingWidth := dv.width - fullNumWidth - leadingSymbolsSize*2
318+ dv.codeWidth = remainingWidth / 2
319+ dv.extraColOnAfter = isOdd(remainingWidth)
320+ }
321+
322+ dv.fullCodeWidth = dv.codeWidth + leadingSymbolsSize
323+}
324+
325+// renderUnified renders the unified diff view as a string.
326+func (dv *DiffView) renderUnified() string {
327+ var b strings.Builder
328+
329+ fullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
330+ printedLines := -dv.yOffset
331+
332+ write := func(s string) {
333+ if printedLines >= 0 {
334+ b.WriteString(s)
335+ }
336+ }
337+
338+outer:
339+ for i, h := range dv.unified.Hunks {
340+ ls := dv.style.DividerLine
341+ if dv.lineNumbers {
342+ write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
343+ write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
344+ }
345+ content := ansi.Truncate(dv.hunkLineFor(h), dv.fullCodeWidth, "…")
346+ write(ls.Code.Width(dv.fullCodeWidth).Render(content))
347+ write("\n")
348+ printedLines++
349+
350+ beforeLine := h.FromLine
351+ afterLine := h.ToLine
352+
353+ for j, l := range h.Lines {
354+ // print ellipis if we don't have enough space to print the rest of the diff
355+ hasReachedHeight := dv.height > 0 && printedLines+1 == dv.height
356+ isLastHunk := i+1 == len(dv.unified.Hunks)
357+ isLastLine := j+1 == len(h.Lines)
358+ if hasReachedHeight && (!isLastHunk || !isLastLine) {
359+ ls := dv.lineStyleForType(l.Kind)
360+ if dv.lineNumbers {
361+ write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
362+ write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
363+ }
364+ write(fullContentStyle.Render(
365+ ls.Code.Width(dv.fullCodeWidth).Render(" …"),
366+ ))
367+ write("\n")
368+ break outer
369+ }
370+
371+ getContent := func(ls LineStyle) string {
372+ content := strings.TrimSuffix(l.Content, "\n")
373+ content = dv.hightlightCode(content, ls.Code.GetBackground())
374+ content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
375+ content = ansi.Truncate(content, dv.codeWidth, "…")
376+ return content
377+ }
378+
379+ leadingEllipsis := dv.xOffset > 0 && strings.TrimSpace(content) != ""
380+
381+ switch l.Kind {
382+ case udiff.Equal:
383+ ls := dv.style.EqualLine
384+ content := getContent(ls)
385+ if dv.lineNumbers {
386+ write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
387+ write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
388+ }
389+ write(fullContentStyle.Render(
390+ ls.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
391+ ))
392+ beforeLine++
393+ afterLine++
394+ case udiff.Insert:
395+ ls := dv.style.InsertLine
396+ content := getContent(ls)
397+ if dv.lineNumbers {
398+ write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
399+ write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
400+ }
401+ write(fullContentStyle.Render(
402+ ls.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
403+ ls.Code.Width(dv.codeWidth).Render(content),
404+ ))
405+ afterLine++
406+ case udiff.Delete:
407+ ls := dv.style.DeleteLine
408+ content := getContent(ls)
409+ if dv.lineNumbers {
410+ write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
411+ write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
412+ }
413+ write(fullContentStyle.Render(
414+ ls.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
415+ ls.Code.Width(dv.codeWidth).Render(content),
416+ ))
417+ beforeLine++
418+ }
419+ write("\n")
420+
421+ printedLines++
422+ }
423+ }
424+
425+ for printedLines < dv.height {
426+ ls := dv.style.MissingLine
427+ if dv.lineNumbers {
428+ write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
429+ write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
430+ }
431+ write(ls.Code.Width(dv.fullCodeWidth).Render(" "))
432+ write("\n")
433+ printedLines++
434+ }
435+
436+ return b.String()
437+}
438+
439+// renderSplit renders the split (side-by-side) diff view as a string.
440+func (dv *DiffView) renderSplit() string {
441+ var b strings.Builder
442+
443+ beforeFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth)
444+ afterFullContentStyle := lipgloss.NewStyle().MaxWidth(dv.fullCodeWidth + btoi(dv.extraColOnAfter))
445+ printedLines := -dv.yOffset
446+
447+ write := func(s string) {
448+ if printedLines >= 0 {
449+ b.WriteString(s)
450+ }
451+ }
452+
453+outer:
454+ for i, h := range dv.splitHunks {
455+ ls := dv.style.DividerLine
456+ if dv.lineNumbers {
457+ write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
458+ }
459+ content := ansi.Truncate(dv.hunkLineFor(dv.unified.Hunks[i]), dv.fullCodeWidth, "…")
460+ write(ls.Code.Width(dv.fullCodeWidth).Render(content))
461+ if dv.lineNumbers {
462+ write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
463+ }
464+ write(ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
465+ write("\n")
466+ printedLines++
467+
468+ beforeLine := h.fromLine
469+ afterLine := h.toLine
470+
471+ for j, l := range h.lines {
472+ // print ellipis if we don't have enough space to print the rest of the diff
473+ hasReachedHeight := dv.height > 0 && printedLines+1 == dv.height
474+ isLastHunk := i+1 == len(dv.unified.Hunks)
475+ isLastLine := j+1 == len(h.lines)
476+ if hasReachedHeight && (!isLastHunk || !isLastLine) {
477+ ls := dv.style.MissingLine
478+ if l.before != nil {
479+ ls = dv.lineStyleForType(l.before.Kind)
480+ }
481+ if dv.lineNumbers {
482+ write(ls.LineNumber.Render(pad("…", dv.beforeNumDigits)))
483+ }
484+ write(beforeFullContentStyle.Render(
485+ ls.Code.Width(dv.fullCodeWidth).Render(" …"),
486+ ))
487+ ls = dv.style.MissingLine
488+ if l.after != nil {
489+ ls = dv.lineStyleForType(l.after.Kind)
490+ }
491+ if dv.lineNumbers {
492+ write(ls.LineNumber.Render(pad("…", dv.afterNumDigits)))
493+ }
494+ write(afterFullContentStyle.Render(
495+ ls.Code.Width(dv.fullCodeWidth).Render(" …"),
496+ ))
497+ write("\n")
498+ break outer
499+ }
500+
501+ getContent := func(content string, ls LineStyle) string {
502+ content = strings.TrimSuffix(content, "\n")
503+ content = dv.hightlightCode(content, ls.Code.GetBackground())
504+ content = ansi.GraphemeWidth.Cut(content, dv.xOffset, len(content))
505+ content = ansi.Truncate(content, dv.codeWidth, "…")
506+ return content
507+ }
508+ getLeadingEllipsis := func(content string) bool {
509+ return dv.xOffset > 0 && strings.TrimSpace(content) != ""
510+ }
511+
512+ switch {
513+ case l.before == nil:
514+ ls := dv.style.MissingLine
515+ if dv.lineNumbers {
516+ write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
517+ }
518+ write(beforeFullContentStyle.Render(
519+ ls.Code.Width(dv.fullCodeWidth).Render(" "),
520+ ))
521+ case l.before.Kind == udiff.Equal:
522+ ls := dv.style.EqualLine
523+ content := getContent(l.before.Content, ls)
524+ leadingEllipsis := getLeadingEllipsis(content)
525+ if dv.lineNumbers {
526+ write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
527+ }
528+ write(beforeFullContentStyle.Render(
529+ ls.Code.Width(dv.fullCodeWidth).Render(ternary(leadingEllipsis, " …", " ") + content),
530+ ))
531+ beforeLine++
532+ case l.before.Kind == udiff.Delete:
533+ ls := dv.style.DeleteLine
534+ content := getContent(l.before.Content, ls)
535+ leadingEllipsis := getLeadingEllipsis(content)
536+ if dv.lineNumbers {
537+ write(ls.LineNumber.Render(pad(beforeLine, dv.beforeNumDigits)))
538+ }
539+ write(beforeFullContentStyle.Render(
540+ ls.Symbol.Render(ternary(leadingEllipsis, "-…", "- ")) +
541+ ls.Code.Width(dv.codeWidth).Render(content),
542+ ))
543+ beforeLine++
544+ }
545+
546+ switch {
547+ case l.after == nil:
548+ ls := dv.style.MissingLine
549+ if dv.lineNumbers {
550+ write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
551+ }
552+ write(afterFullContentStyle.Render(
553+ ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "),
554+ ))
555+ case l.after.Kind == udiff.Equal:
556+ ls := dv.style.EqualLine
557+ content := getContent(l.after.Content, ls)
558+ leadingEllipsis := getLeadingEllipsis(content)
559+ if dv.lineNumbers {
560+ write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
561+ }
562+ write(afterFullContentStyle.Render(
563+ ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(ternary(leadingEllipsis, " …", " ") + content),
564+ ))
565+ afterLine++
566+ case l.after.Kind == udiff.Insert:
567+ ls := dv.style.InsertLine
568+ content := getContent(l.after.Content, ls)
569+ leadingEllipsis := getLeadingEllipsis(content)
570+ if dv.lineNumbers {
571+ write(ls.LineNumber.Render(pad(afterLine, dv.afterNumDigits)))
572+ }
573+ write(afterFullContentStyle.Render(
574+ ls.Symbol.Render(ternary(leadingEllipsis, "+…", "+ ")) +
575+ ls.Code.Width(dv.codeWidth+btoi(dv.extraColOnAfter)).Render(content),
576+ ))
577+ afterLine++
578+ }
579+
580+ write("\n")
581+
582+ printedLines++
583+ }
584+ }
585+
586+ for printedLines < dv.height {
587+ ls := dv.style.MissingLine
588+ if dv.lineNumbers {
589+ write(ls.LineNumber.Render(pad(" ", dv.beforeNumDigits)))
590+ }
591+ write(ls.Code.Width(dv.fullCodeWidth).Render(" "))
592+ if dv.lineNumbers {
593+ write(ls.LineNumber.Render(pad(" ", dv.afterNumDigits)))
594+ }
595+ write(ls.Code.Width(dv.fullCodeWidth + btoi(dv.extraColOnAfter)).Render(" "))
596+ write("\n")
597+ printedLines++
598+ }
599+
600+ return b.String()
601+}
602+
603+// hunkLineFor formats the header line for a hunk in the unified diff view.
604+func (dv *DiffView) hunkLineFor(h *udiff.Hunk) string {
605+ beforeShownLines, afterShownLines := dv.hunkShownLines(h)
606+
607+ return fmt.Sprintf(
608+ " @@ -%d,%d +%d,%d @@ ",
609+ h.FromLine,
610+ beforeShownLines,
611+ h.ToLine,
612+ afterShownLines,
613+ )
614+}
615+
616+// hunkShownLines calculates the number of lines shown in a hunk for both before
617+// and after versions.
618+func (dv *DiffView) hunkShownLines(h *udiff.Hunk) (before, after int) {
619+ for _, l := range h.Lines {
620+ switch l.Kind {
621+ case udiff.Equal:
622+ before++
623+ after++
624+ case udiff.Insert:
625+ after++
626+ case udiff.Delete:
627+ before++
628+ }
629+ }
630+ return
631+}
632+
633+func (dv *DiffView) lineStyleForType(t udiff.OpKind) LineStyle {
634+ switch t {
635+ case udiff.Equal:
636+ return dv.style.EqualLine
637+ case udiff.Insert:
638+ return dv.style.InsertLine
639+ case udiff.Delete:
640+ return dv.style.DeleteLine
641+ default:
642+ return dv.style.MissingLine
643+ }
644+}
645+
646+func (dv *DiffView) hightlightCode(source string, bgColor color.Color) string {
647+ if dv.chromaStyle == nil {
648+ return source
649+ }
650+
651+ l := dv.getChromaLexer(source)
652+ f := dv.getChromaFormatter(bgColor)
653+
654+ it, err := l.Tokenise(nil, source)
655+ if err != nil {
656+ return source
657+ }
658+
659+ var b strings.Builder
660+ if err := f.Format(&b, dv.chromaStyle, it); err != nil {
661+ return source
662+ }
663+ return b.String()
664+}
665+
666+func (dv *DiffView) getChromaLexer(source string) chroma.Lexer {
667+ l := lexers.Match(dv.before.path)
668+ if l == nil {
669+ l = lexers.Analyse(source)
670+ }
671+ if l == nil {
672+ l = lexers.Fallback
673+ }
674+ return chroma.Coalesce(l)
675+}
676+
677+func (dv *DiffView) getChromaFormatter(gbColor color.Color) chroma.Formatter {
678+ return chromaFormatter{
679+ bgColor: gbColor,
680+ }
681+}
internal/exp/diffview/diffview_test.gonew file+300
@@ -0,0 +1,300 @@
1+package diffview_test
2+
3+import (
4+ _ "embed"
5+ "fmt"
6+ "strings"
7+ "testing"
8+
9+ "github.com/alecthomas/chroma/v2/styles"
10+ "github.com/charmbracelet/crush/internal/exp/diffview"
11+ "github.com/charmbracelet/x/ansi"
12+ "github.com/charmbracelet/x/exp/golden"
13+)
14+
15+//go:embed testdata/TestDefault.before
16+var TestDefaultBefore string
17+
18+//go:embed testdata/TestDefault.after
19+var TestDefaultAfter string
20+
21+//go:embed testdata/TestMultipleHunks.before
22+var TestMultipleHunksBefore string
23+
24+//go:embed testdata/TestMultipleHunks.after
25+var TestMultipleHunksAfter string
26+
27+//go:embed testdata/TestNarrow.before
28+var TestNarrowBefore string
29+
30+//go:embed testdata/TestNarrow.after
31+var TestNarrowAfter string
32+
33+//go:embed testdata/TestTabs.before
34+var TestTabsBefore string
35+
36+//go:embed testdata/TestTabs.after
37+var TestTabsAfter string
38+
39+type (
40+ TestFunc func(dv *diffview.DiffView) *diffview.DiffView
41+ TestFuncs map[string]TestFunc
42+)
43+
44+var (
45+ UnifiedFunc = func(dv *diffview.DiffView) *diffview.DiffView {
46+ return dv.Unified()
47+ }
48+ SplitFunc = func(dv *diffview.DiffView) *diffview.DiffView {
49+ return dv.Split()
50+ }
51+
52+ DefaultFunc = func(dv *diffview.DiffView) *diffview.DiffView {
53+ return dv.
54+ Before("main.go", TestDefaultBefore).
55+ After("main.go", TestDefaultAfter)
56+ }
57+ NoLineNumbersFunc = func(dv *diffview.DiffView) *diffview.DiffView {
58+ return dv.
59+ Before("main.go", TestDefaultBefore).
60+ After("main.go", TestDefaultAfter).
61+ LineNumbers(false)
62+ }
63+ MultipleHunksFunc = func(dv *diffview.DiffView) *diffview.DiffView {
64+ return dv.
65+ Before("main.go", TestMultipleHunksBefore).
66+ After("main.go", TestMultipleHunksAfter)
67+ }
68+ CustomContextLinesFunc = func(dv *diffview.DiffView) *diffview.DiffView {
69+ return dv.
70+ Before("main.go", TestMultipleHunksBefore).
71+ After("main.go", TestMultipleHunksAfter).
72+ ContextLines(4)
73+ }
74+ NarrowFunc = func(dv *diffview.DiffView) *diffview.DiffView {
75+ return dv.
76+ Before("text.txt", TestNarrowBefore).
77+ After("text.txt", TestNarrowAfter)
78+ }
79+ SmallWidthFunc = func(dv *diffview.DiffView) *diffview.DiffView {
80+ return dv.
81+ Before("main.go", TestMultipleHunksBefore).
82+ After("main.go", TestMultipleHunksAfter).
83+ Width(40)
84+ }
85+ LargeWidthFunc = func(dv *diffview.DiffView) *diffview.DiffView {
86+ return dv.
87+ Before("main.go", TestMultipleHunksBefore).
88+ After("main.go", TestMultipleHunksAfter).
89+ Width(120)
90+ }
91+ NoSyntaxHighlightFunc = func(dv *diffview.DiffView) *diffview.DiffView {
92+ return dv.
93+ Before("main.go", TestMultipleHunksBefore).
94+ After("main.go", TestMultipleHunksAfter).
95+ ChromaStyle(nil)
96+ }
97+
98+ LightModeFunc = func(dv *diffview.DiffView) *diffview.DiffView {
99+ return dv.
100+ Style(diffview.DefaultLightStyle()).
101+ ChromaStyle(styles.Get("catppuccin-latte"))
102+ }
103+ DarkModeFunc = func(dv *diffview.DiffView) *diffview.DiffView {
104+ return dv.
105+ Style(diffview.DefaultDarkStyle()).
106+ ChromaStyle(styles.Get("catppuccin-macchiato"))
107+ }
108+
109+ LayoutFuncs = TestFuncs{
110+ "Unified": UnifiedFunc,
111+ "Split": SplitFunc,
112+ }
113+ BehaviorFuncs = TestFuncs{
114+ "Default": DefaultFunc,
115+ "NoLineNumbers": NoLineNumbersFunc,
116+ "MultipleHunks": MultipleHunksFunc,
117+ "CustomContextLines": CustomContextLinesFunc,
118+ "Narrow": NarrowFunc,
119+ "SmallWidth": SmallWidthFunc,
120+ "LargeWidth": LargeWidthFunc,
121+ "NoSyntaxHighlight": NoSyntaxHighlightFunc,
122+ }
123+ ThemeFuncs = TestFuncs{
124+ "LightMode": LightModeFunc,
125+ "DarkMode": DarkModeFunc,
126+ }
127+)
128+
129+func TestDiffView(t *testing.T) {
130+ for layoutName, layoutFunc := range LayoutFuncs {
131+ t.Run(layoutName, func(t *testing.T) {
132+ for behaviorName, behaviorFunc := range BehaviorFuncs {
133+ t.Run(behaviorName, func(t *testing.T) {
134+ for themeName, themeFunc := range ThemeFuncs {
135+ t.Run(themeName, func(t *testing.T) {
136+ t.Parallel()
137+
138+ dv := diffview.New()
139+ dv = layoutFunc(dv)
140+ dv = themeFunc(dv)
141+ dv = behaviorFunc(dv)
142+
143+ output := dv.String()
144+ golden.RequireEqual(t, []byte(output))
145+
146+ switch behaviorName {
147+ case "SmallWidth":
148+ assertLineWidth(t, 40, output)
149+ case "LargeWidth":
150+ assertLineWidth(t, 120, output)
151+ }
152+ })
153+ }
154+ })
155+ }
156+ })
157+ }
158+}
159+
160+func TestDiffViewTabs(t *testing.T) {
161+ for layoutName, layoutFunc := range LayoutFuncs {
162+ t.Run(layoutName, func(t *testing.T) {
163+ t.Parallel()
164+
165+ dv := diffview.New().
166+ Before("main.go", TestTabsBefore).
167+ After("main.go", TestTabsAfter).
168+ Style(diffview.DefaultLightStyle()).
169+ ChromaStyle(styles.Get("catppuccin-latte"))
170+ dv = layoutFunc(dv)
171+
172+ output := dv.String()
173+ golden.RequireEqual(t, []byte(output))
174+ })
175+ }
176+}
177+
178+func TestDiffViewWidth(t *testing.T) {
179+ for layoutName, layoutFunc := range LayoutFuncs {
180+ t.Run(layoutName, func(t *testing.T) {
181+ for width := 1; width <= 110; width++ {
182+ if layoutName == "Unified" && width > 60 {
183+ continue
184+ }
185+
186+ t.Run(fmt.Sprintf("WidthOf%03d", width), func(t *testing.T) {
187+ t.Parallel()
188+
189+ dv := diffview.New().
190+ Before("main.go", TestMultipleHunksBefore).
191+ After("main.go", TestMultipleHunksAfter).
192+ Width(width).
193+ Style(diffview.DefaultLightStyle()).
194+ ChromaStyle(styles.Get("catppuccin-latte"))
195+ dv = layoutFunc(dv)
196+
197+ output := dv.String()
198+ golden.RequireEqual(t, []byte(output))
199+
200+ assertLineWidth(t, width, output)
201+ })
202+ }
203+ })
204+ }
205+}
206+
207+func TestDiffViewHeight(t *testing.T) {
208+ for layoutName, layoutFunc := range LayoutFuncs {
209+ t.Run(layoutName, func(t *testing.T) {
210+ for height := 1; height <= 20; height++ {
211+ t.Run(fmt.Sprintf("HeightOf%03d", height), func(t *testing.T) {
212+ t.Parallel()
213+
214+ dv := diffview.New().
215+ Before("main.go", TestMultipleHunksBefore).
216+ After("main.go", TestMultipleHunksAfter).
217+ Height(height).
218+ Style(diffview.DefaultLightStyle()).
219+ ChromaStyle(styles.Get("catppuccin-latte"))
220+ dv = layoutFunc(dv)
221+
222+ output := dv.String()
223+ golden.RequireEqual(t, []byte(output))
224+
225+ assertHeight(t, height, output)
226+ })
227+ }
228+ })
229+ }
230+}
231+
232+func TestDiffViewXOffset(t *testing.T) {
233+ for layoutName, layoutFunc := range LayoutFuncs {
234+ t.Run(layoutName, func(t *testing.T) {
235+ for xOffset := range 21 {
236+ t.Run(fmt.Sprintf("XOffsetOf%02d", xOffset), func(t *testing.T) {
237+ t.Parallel()
238+
239+ dv := diffview.New().
240+ Before("main.go", TestDefaultBefore).
241+ After("main.go", TestDefaultAfter).
242+ Style(diffview.DefaultLightStyle()).
243+ ChromaStyle(styles.Get("catppuccin-latte")).
244+ Width(60).
245+ XOffset(xOffset)
246+ dv = layoutFunc(dv)
247+
248+ output := dv.String()
249+ golden.RequireEqual(t, []byte(output))
250+
251+ assertLineWidth(t, 60, output)
252+ })
253+ }
254+ })
255+ }
256+}
257+
258+func TestDiffViewYOffset(t *testing.T) {
259+ for layoutName, layoutFunc := range LayoutFuncs {
260+ t.Run(layoutName, func(t *testing.T) {
261+ for yOffset := range 17 {
262+ t.Run(fmt.Sprintf("YOffsetOf%02d", yOffset), func(t *testing.T) {
263+ t.Parallel()
264+
265+ dv := diffview.New().
266+ Before("main.go", TestMultipleHunksBefore).
267+ After("main.go", TestMultipleHunksAfter).
268+ Style(diffview.DefaultLightStyle()).
269+ ChromaStyle(styles.Get("catppuccin-latte")).
270+ Height(5).
271+ YOffset(yOffset)
272+ dv = layoutFunc(dv)
273+
274+ output := dv.String()
275+ golden.RequireEqual(t, []byte(output))
276+
277+ assertHeight(t, 5, output)
278+ })
279+ }
280+ })
281+ }
282+}
283+
284+func assertLineWidth(t *testing.T, expected int, output string) {
285+ var lineWidth int
286+ for line := range strings.SplitSeq(output, "\n") {
287+ lineWidth = max(lineWidth, ansi.StringWidth(line))
288+ }
289+ if lineWidth != expected {
290+ t.Errorf("expected output width to be == %d, got %d", expected, lineWidth)
291+ }
292+}
293+
294+func assertHeight(t *testing.T, expected int, output string) {
295+ output = strings.TrimSuffix(output, "\n")
296+ lines := strings.Count(output, "\n") + 1
297+ if lines != expected {
298+ t.Errorf("expected output height to be == %d, got %d", expected, lines)
299+ }
300+}
internal/exp/diffview/split.gonew file+74
@@ -0,0 +1,74 @@
1+package diffview
2+
3+import (
4+ "slices"
5+
6+ "github.com/aymanbagabas/go-udiff"
7+ "github.com/charmbracelet/x/exp/slice"
8+)
9+
10+type splitHunk struct {
11+ fromLine int
12+ toLine int
13+ lines []*splitLine
14+}
15+
16+type splitLine struct {
17+ before *udiff.Line
18+ after *udiff.Line
19+}
20+
21+func hunkToSplit(h *udiff.Hunk) (sh splitHunk) {
22+ lines := slices.Clone(h.Lines)
23+ sh = splitHunk{
24+ fromLine: h.FromLine,
25+ toLine: h.ToLine,
26+ lines: make([]*splitLine, 0, len(lines)),
27+ }
28+
29+ for {
30+ var ul udiff.Line
31+ var ok bool
32+ ul, lines, ok = slice.Shift(lines)
33+ if !ok {
34+ break
35+ }
36+
37+ var sl splitLine
38+
39+ switch ul.Kind {
40+
41+ // For equal lines, add as is
42+ case udiff.Equal:
43+ sl.before = &ul
44+ sl.after = &ul
45+
46+ // For inserted lines, set after and keep before as nil
47+ case udiff.Insert:
48+ sl.before = nil
49+ sl.after = &ul
50+
51+ // For deleted lines, set before and loop over the next lines
52+ // searching for the equivalent after line.
53+ case udiff.Delete:
54+ sl.before = &ul
55+
56+ inner:
57+ for i, l := range lines {
58+ switch l.Kind {
59+ case udiff.Insert:
60+ var ll udiff.Line
61+ ll, lines, _ = slice.DeleteAt(lines, i)
62+ sl.after = &ll
63+ break inner
64+ case udiff.Equal:
65+ break inner
66+ }
67+ }
68+ }
69+
70+ sh.lines = append(sh.lines, &sl)
71+ }
72+
73+ return
74+}
internal/exp/diffview/style.gonew file+124
@@ -0,0 +1,124 @@
1+package diffview
2+
3+import (
4+ "github.com/charmbracelet/lipgloss/v2"
5+ "github.com/charmbracelet/x/exp/charmtone"
6+)
7+
8+// LineStyle defines the styles for a given line type in the diff view.
9+type LineStyle struct {
10+ LineNumber lipgloss.Style
11+ Symbol lipgloss.Style
12+ Code lipgloss.Style
13+}
14+
15+// Style defines the overall style for the diff view, including styles for
16+// different line types such as divider, missing, equal, insert, and delete
17+// lines.
18+type Style struct {
19+ DividerLine LineStyle
20+ MissingLine LineStyle
21+ EqualLine LineStyle
22+ InsertLine LineStyle
23+ DeleteLine LineStyle
24+}
25+
26+// DefaultLightStyle provides a default light theme style for the diff view.
27+func DefaultLightStyle() Style {
28+ return Style{
29+ DividerLine: LineStyle{
30+ LineNumber: lipgloss.NewStyle().
31+ Foreground(charmtone.Iron).
32+ Background(charmtone.Thunder),
33+ Code: lipgloss.NewStyle().
34+ Foreground(charmtone.Oyster).
35+ Background(charmtone.Anchovy),
36+ },
37+ MissingLine: LineStyle{
38+ LineNumber: lipgloss.NewStyle().
39+ Background(charmtone.Ash),
40+ Code: lipgloss.NewStyle().
41+ Background(charmtone.Ash),
42+ },
43+ EqualLine: LineStyle{
44+ LineNumber: lipgloss.NewStyle().
45+ Foreground(charmtone.Charcoal).
46+ Background(charmtone.Ash),
47+ Code: lipgloss.NewStyle().
48+ Foreground(charmtone.Pepper).
49+ Background(charmtone.Salt),
50+ },
51+ InsertLine: LineStyle{
52+ LineNumber: lipgloss.NewStyle().
53+ Foreground(charmtone.Turtle).
54+ Background(lipgloss.Color("#c8e6c9")),
55+ Symbol: lipgloss.NewStyle().
56+ Foreground(charmtone.Turtle).
57+ Background(lipgloss.Color("#e8f5e9")),
58+ Code: lipgloss.NewStyle().
59+ Foreground(charmtone.Pepper).
60+ Background(lipgloss.Color("#e8f5e9")),
61+ },
62+ DeleteLine: LineStyle{
63+ LineNumber: lipgloss.NewStyle().
64+ Foreground(charmtone.Cherry).
65+ Background(lipgloss.Color("#ffcdd2")),
66+ Symbol: lipgloss.NewStyle().
67+ Foreground(charmtone.Cherry).
68+ Background(lipgloss.Color("#ffebee")),
69+ Code: lipgloss.NewStyle().
70+ Foreground(charmtone.Pepper).
71+ Background(lipgloss.Color("#ffebee")),
72+ },
73+ }
74+}
75+
76+// DefaultDarkStyle provides a default dark theme style for the diff view.
77+func DefaultDarkStyle() Style {
78+ return Style{
79+ DividerLine: LineStyle{
80+ LineNumber: lipgloss.NewStyle().
81+ Foreground(charmtone.Smoke).
82+ Background(charmtone.Sapphire),
83+ Code: lipgloss.NewStyle().
84+ Foreground(charmtone.Smoke).
85+ Background(charmtone.Ox),
86+ },
87+ MissingLine: LineStyle{
88+ LineNumber: lipgloss.NewStyle().
89+ Background(charmtone.Charcoal),
90+ Code: lipgloss.NewStyle().
91+ Background(charmtone.Charcoal),
92+ },
93+ EqualLine: LineStyle{
94+ LineNumber: lipgloss.NewStyle().
95+ Foreground(charmtone.Ash).
96+ Background(charmtone.Charcoal),
97+ Code: lipgloss.NewStyle().
98+ Foreground(charmtone.Salt).
99+ Background(charmtone.Pepper),
100+ },
101+ InsertLine: LineStyle{
102+ LineNumber: lipgloss.NewStyle().
103+ Foreground(charmtone.Turtle).
104+ Background(lipgloss.Color("#293229")),
105+ Symbol: lipgloss.NewStyle().
106+ Foreground(charmtone.Turtle).
107+ Background(lipgloss.Color("#303a30")),
108+ Code: lipgloss.NewStyle().
109+ Foreground(charmtone.Salt).
110+ Background(lipgloss.Color("#303a30")),
111+ },
112+ DeleteLine: LineStyle{
113+ LineNumber: lipgloss.NewStyle().
114+ Foreground(charmtone.Cherry).
115+ Background(lipgloss.Color("#332929")),
116+ Symbol: lipgloss.NewStyle().
117+ Foreground(charmtone.Cherry).
118+ Background(lipgloss.Color("#3a3030")),
119+ Code: lipgloss.NewStyle().
120+ Foreground(charmtone.Salt).
121+ Background(lipgloss.Color("#3a3030")),
122+ },
123+ }
124+}
internal/exp/diffview/testdata/TestDefault.afternew file+10
@@ -0,0 +1,10 @@
1+package main
2+
3+import (
4+ "fmt"
5+)
6+
7+func main() {
8+ content := "Hello, world!"
9+ fmt.Println(content)
10+}
internal/exp/diffview/testdata/TestDefault.beforenew file+9
@@ -0,0 +1,9 @@
1+package main
2+
3+import (
4+ "fmt"
5+)
6+
7+func main() {
8+ fmt.Println("Hello, world!")
9+}
internal/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/DarkMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …  @@ -1,13 +1,15 @@    …   
2+  1  package main   1  package main 
3+  2     2   
4+  3  import (   3  import ( 
5+  4   "fmt"   4   "fmt" 
6+       5 +  "strings" 
7+  5  )   6  ) 
8+  6     7   
9+  7  func main() {   8  func main() { 
10+  8   fmt.Println(getContent())   9   fmt.Println(getContent()) 
11+  9  }  10  } 
12+ 10    11   
13+ 11  func getContent() string {  12  func getContent() string { 
14+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
15+      14 +  return content 
16+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/CustomContextLines/LightMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …  @@ -1,13 +1,15 @@    …   
2+  1  package main   1  package main 
3+  2     2   
4+  3  import (   3  import ( 
5+  4   "fmt"   4   "fmt" 
6+       5 +  "strings" 
7+  5  )   6  ) 
8+  6     7   
9+  7  func main() {   8  func main() { 
10+  8   fmt.Println(getContent())   9   fmt.Println(getContent()) 
11+  9  }  10  } 
12+ 10    11   
13+ 11  func getContent() string {  12  func getContent() string { 
14+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
15+      14 +  return content 
16+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/Default/DarkMode.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  )   5  ) 
3+  6     6   
4+  7  func main() {   7  func main() { 
5+  8 -  fmt.Println("Hello, world!")   8 +  content := "Hello, world!" 
6+       9 +  fmt.Println(content) 
7+  9  }  10  } 
internal/exp/diffview/testdata/TestDiffView/Split/Default/LightMode.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  )   5  ) 
3+  6     6   
4+  7  func main() {   7  func main() { 
5+  8 -  fmt.Println("Hello, world!")   8 +  content := "Hello, world!" 
6+       9 +  fmt.Println(content) 
7+  9  }  10  } 
internal/exp/diffview/testdata/TestDiffView/Split/LargeWidth/DarkMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/LargeWidth/LightMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/DarkMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/MultipleHunks/LightMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/Narrow/DarkMode.goldennew file+4
@@ -0,0 +1,4 @@
1+ …  @@ -1,3 +1,3 @@   …   
2+ 1 - a  1 + d 
3+ 2 - b  2 + e 
4+ 3 - c  3 + f 
internal/exp/diffview/testdata/TestDiffView/Split/Narrow/LightMode.goldennew file+4
@@ -0,0 +1,4 @@
1+ …  @@ -1,3 +1,3 @@   …   
2+ 1 - a  1 + d 
3+ 2 - b  2 + e 
4+ 3 - c  3 + f 
internal/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/DarkMode.goldennew file+7
@@ -0,0 +1,7 @@
1+ @@ -5,5 +5,6 @@    
2+ )  ) 
3+    
4+ func main() {  func main() { 
5+-  fmt.Println("Hello, world!") +  content := "Hello, world!" 
6+  +  fmt.Println(content) 
7+ }  } 
internal/exp/diffview/testdata/TestDiffView/Split/NoLineNumbers/LightMode.goldennew file+7
@@ -0,0 +1,7 @@
1+ @@ -5,5 +5,6 @@    
2+ )  ) 
3+    
4+ func main() {  func main() { 
5+-  fmt.Println("Hello, world!") +  content := "Hello, world!" 
6+  +  fmt.Println(content) 
7+ }  } 
internal/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/DarkMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4  "fmt"   4  "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/NoSyntaxHighlight/LightMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4  "fmt"   4  "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/SmallWidth/DarkMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 …  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getConte… 12  func getConte…
13+ 12 -  return "H… 13 +  content :…
14+      14 +  return co…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Split/SmallWidth/LightMode.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 …  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getConte… 12  func getConte…
13+ 12 -  return "H… 13 +  content :…
14+      14 +  return co…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/DarkMode.goldennew file+17
@@ -0,0 +1,17 @@
1+  …   …  @@ -1,13 +1,15 @@  
2+  1   1  package main 
3+  2   2   
4+  3   3  import ( 
5+  4   4   "fmt" 
6+     5 +  "strings" 
7+  5   6  ) 
8+  6   7   
9+  7   8  func main() { 
10+  8   9   fmt.Println(getContent()) 
11+  9  10  } 
12+ 10  11   
13+ 11  12  func getContent() string { 
14+ 12    -  return "Hello, world!" 
15+    13 +  content := strings.ToUpper("Hello, World!") 
16+    14 +  return content 
17+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/CustomContextLines/LightMode.goldennew file+17
@@ -0,0 +1,17 @@
1+  …   …  @@ -1,13 +1,15 @@  
2+  1   1  package main 
3+  2   2   
4+  3   3  import ( 
5+  4   4   "fmt" 
6+     5 +  "strings" 
7+  5   6  ) 
8+  6   7   
9+  7   8  func main() { 
10+  8   9   fmt.Println(getContent()) 
11+  9  10  } 
12+ 10  11   
13+ 11  12  func getContent() string { 
14+ 12    -  return "Hello, world!" 
15+    13 +  content := strings.ToUpper("Hello, World!") 
16+    14 +  return content 
17+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/Default/DarkMode.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  ) 
3+  6   6   
4+  7   7  func main() { 
5+  8    -  fmt.Println("Hello, world!") 
6+     8 +  content := "Hello, world!" 
7+     9 +  fmt.Println(content) 
8+  9  10  } 
internal/exp/diffview/testdata/TestDiffView/Unified/Default/LightMode.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  ) 
3+  6   6   
4+  7   7  func main() { 
5+  8    -  fmt.Println("Hello, world!") 
6+     8 +  content := "Hello, world!" 
7+     9 +  fmt.Println(content) 
8+  9  10  } 
internal/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/DarkMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/LargeWidth/LightMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/DarkMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/MultipleHunks/LightMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/Narrow/DarkMode.goldennew file+7
@@ -0,0 +1,7 @@
1+ …  …  @@ -1,3 +1,3 @@  
2+ 1    - a 
3+ 2    - b 
4+ 3    - c 
5+    1 + d 
6+    2 + e 
7+    3 + f 
internal/exp/diffview/testdata/TestDiffView/Unified/Narrow/LightMode.goldennew file+7
@@ -0,0 +1,7 @@
1+ …  …  @@ -1,3 +1,3 @@  
2+ 1    - a 
3+ 2    - b 
4+ 3    - c 
5+    1 + d 
6+    2 + e 
7+    3 + f 
internal/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/DarkMode.goldennew file+8
@@ -0,0 +1,8 @@
1+ @@ -5,5 +5,6 @@  
2+ ) 
3+  
4+ func main() { 
5+-  fmt.Println("Hello, world!") 
6++  content := "Hello, world!" 
7++  fmt.Println(content) 
8+ } 
internal/exp/diffview/testdata/TestDiffView/Unified/NoLineNumbers/LightMode.goldennew file+8
@@ -0,0 +1,8 @@
1+ @@ -5,5 +5,6 @@  
2+ ) 
3+  
4+ func main() { 
5+-  fmt.Println("Hello, world!") 
6++  content := "Hello, world!" 
7++  fmt.Println(content) 
8+ } 
internal/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/DarkMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4  "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/NoSyntaxHighlight/LightMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4  "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/DarkMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUppe…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffView/Unified/SmallWidth/LightMode.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUppe…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf001.goldennew file+1
@@ -0,0 +1 @@
1+  …  @@ -2,6 +2,7 @@    …   
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf002.goldennew file+2
@@ -0,0 +1,2 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf003.goldennew file+3
@@ -0,0 +1,3 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf004.goldennew file+4
@@ -0,0 +1,4 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf005.goldennew file+5
@@ -0,0 +1,5 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf006.goldennew file+6
@@ -0,0 +1,6 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf007.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf008.goldennew file+8
@@ -0,0 +1,8 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf009.goldennew file+9
@@ -0,0 +1,9 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf010.goldennew file+10
@@ -0,0 +1,10 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf011.goldennew file+11
@@ -0,0 +1,11 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf012.goldennew file+12
@@ -0,0 +1,12 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf013.goldennew file+13
@@ -0,0 +1,13 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf014.goldennew file+14
@@ -0,0 +1,14 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf015.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf016.goldennew file+16
@@ -0,0 +1,16 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
16+          
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf017.goldennew file+17
@@ -0,0 +1,17 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
16+          
17+          
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf018.goldennew file+18
@@ -0,0 +1,18 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
16+          
17+          
18+          
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf019.goldennew file+19
@@ -0,0 +1,19 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
16+          
17+          
18+          
19+          
internal/exp/diffview/testdata/TestDiffViewHeight/Split/HeightOf020.goldennew file+20
@@ -0,0 +1,20 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
16+          
17+          
18+          
19+          
20+          
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf001.goldennew file+1
@@ -0,0 +1 @@
1+  …   …  @@ -2,6 +2,7 @@  
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf002.goldennew file+2
@@ -0,0 +1,2 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf003.goldennew file+3
@@ -0,0 +1,3 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf004.goldennew file+4
@@ -0,0 +1,4 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf005.goldennew file+5
@@ -0,0 +1,5 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf006.goldennew file+6
@@ -0,0 +1,6 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf007.goldennew file+7
@@ -0,0 +1,7 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf008.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf009.goldennew file+9
@@ -0,0 +1,9 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf010.goldennew file+10
@@ -0,0 +1,10 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf011.goldennew file+11
@@ -0,0 +1,11 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf012.goldennew file+12
@@ -0,0 +1,12 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf013.goldennew file+13
@@ -0,0 +1,13 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf014.goldennew file+14
@@ -0,0 +1,14 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf015.goldennew file+15
@@ -0,0 +1,15 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf016.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf017.goldennew file+17
@@ -0,0 +1,17 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
17+        
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf018.goldennew file+18
@@ -0,0 +1,18 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
17+        
18+        
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf019.goldennew file+19
@@ -0,0 +1,19 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
17+        
18+        
19+        
internal/exp/diffview/testdata/TestDiffViewHeight/Unified/HeightOf020.goldennew file+20
@@ -0,0 +1,20 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
17+        
18+        
19+        
20+        
internal/exp/diffview/testdata/TestDiffViewTabs/Split.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewTabs/Unified.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf001.goldennew file+15
@@ -0,0 +1,15 @@
1+ 
2+ 
3+ 
4+ 
5+ 
6+ 
7+ 
8+ 
9+ 
10+ 
11+ 
12+ 
13+ 
14+ 
15+ 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf002.goldennew file+15
@@ -0,0 +1,15 @@
1+  
2+  
3+  
4+  
5+  
6+  
7+  
8+  
9+  
10+  
11+ 1
12+ 1
13+ 1
14+  
15+ 1
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf003.goldennew file+15
@@ -0,0 +1,15 @@
1+  …
2+  2
3+  3
4+  4
5+  
6+  5
7+  6
8+  7
9+  …
10+  9
11+ 10
12+ 11
13+ 12
14+  
15+ 13
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf004.goldennew file+15
@@ -0,0 +1,15 @@
1+  … 
2+  2 
3+  3 
4+  4 
5+   
6+  5 
7+  6 
8+  7 
9+  … 
10+  9 
11+ 10 
12+ 11 
13+ 12 
14+   
15+ 13 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf005.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  
2+  2  
3+  3  
4+  4  
5+    
6+  5  
7+  6  
8+  7  
9+  …  
10+  9  
11+ 10  
12+ 11  
13+ 12 -
14+    
15+ 13  
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf006.goldennew file+15
@@ -0,0 +1,15 @@
1+  …   
2+  2  
3+  3  
4+  4  
5+    
6+  5  
7+  6  
8+  7  
9+  …   
10+  9  
11+ 10  
12+ 11  
13+ 12 - 
14+    
15+ 13  
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf007.goldennew file+15
@@ -0,0 +1,15 @@
1+  …   …
2+  2   
3+  3   
4+  4   
5+     
6+  5   
7+  6   
8+  7   
9+  …   …
10+  9   
11+ 10   
12+ 11   
13+ 12 -  
14+     
15+ 13   
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf008.goldennew file+15
@@ -0,0 +1,15 @@
1+  …   … 
2+  2    
3+  3    
4+  4    
5+      
6+  5    
7+  6    
8+  7    
9+  …   … 
10+  9   1
11+ 10   1
12+ 11   1
13+ 12 -  1
14+     1
15+ 13   1
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf009.goldennew file+15
@@ -0,0 +1,15 @@
1+  … …  … 
2+  2    2 
3+  3    3 
4+  4    4 
5+      5 
6+  5    6 
7+  6    7 
8+  7    8 
9+  … …  … 
10+  9   10 
11+ 10   11 
12+ 11   12 
13+ 12 - 13 
14+     14 
15+ 13   15 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf010.goldennew file+15
@@ -0,0 +1,15 @@
1+  … …  …  
2+  2    2  
3+  3    3  
4+  4    4  
5+      5 +
6+  5    6  
7+  6    7  
8+  7    8  
9+  … …  …  
10+  9   10  
11+ 10   11  
12+ 11   12  
13+ 12 - 13 +
14+     14 +
15+ 13   15  
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf011.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  …  …  
2+  2    2  
3+  3    3  
4+  4    4  
5+      5 +
6+  5    6  
7+  6    7  
8+  7    8  
9+  …  …  …  
10+  9   10  
11+ 10   11  
12+ 11   12  
13+ 12 -  13 +
14+     14 +
15+ 13   15  
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf012.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  …  …   
2+  2    2  
3+  3    3  
4+  4    4  
5+      5 + 
6+  5    6  
7+  6    7  
8+  7    8  
9+  …  …  …   
10+  9   10  
11+ 10   11  
12+ 11   12  
13+ 12 -  13 + 
14+     14 + 
15+ 13   15  
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf013.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  …  …   
2+  2    2   
3+  3    3   
4+  4    4   
5+      5 +  
6+  5    6   
7+  6    7   
8+  7    8   
9+  …  …  …   
10+  9   10   
11+ 10   11   
12+ 11   12   
13+ 12 -  13 +  
14+     14 +  
15+ 13   15   
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf014.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  …  …   
2+  2     2   
3+  3  …  3  …
4+  4  …  4  …
5+       5 + …
6+  5  )  6  )
7+  6     7   
8+  7  …  8  …
9+  …  …  …   
10+  9  } 10  }
11+ 10    11   
12+ 11  … 12  …
13+ 12 - … 13 + …
14+      14 + …
15+ 13  } 15  }
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf015.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  …  …   
2+  2     2   
3+  3  …  3  … 
4+  4  …  4  … 
5+       5 + … 
6+  5  )  6  ) 
7+  6     7   
8+  7  …  8  … 
9+  …  …  …   
10+  9  } 10  } 
11+ 10    11   
12+ 11  … 12  … 
13+ 12 - … 13 + … 
14+      14 + … 
15+ 13  } 15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf016.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @…  …   
2+  2     2   
3+  3  i…  3  i…
4+  4   …  4   …
5+       5 +  …
6+  5  )   6  ) 
7+  6     7   
8+  7  f…  8  f…
9+  …  @…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  f… 12  f…
13+ 12 -  … 13 +  …
14+      14 +  …
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf017.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @…  …   
2+  2     2   
3+  3  i…  3  i… 
4+  4   …  4   … 
5+       5 +  … 
6+  5  )   6  ) 
7+  6     7   
8+  7  f…  8  f… 
9+  …  @…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  f… 12  f… 
13+ 12 -  … 13 +  … 
14+      14 +  … 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf018.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@…  …   
2+  2     2   
3+  3  im…  3  im…
4+  4   …  4   …
5+       5 +  …
6+  5  )   6  ) 
7+  6     7   
8+  7  fu…  8  fu…
9+  …  @@…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  fu… 12  fu…
13+ 12 -  … 13 +  …
14+      14 +  …
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf019.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@…  …   
2+  2     2   
3+  3  im…  3  im… 
4+  4   …  4   … 
5+       5 +  … 
6+  5  )   6  ) 
7+  6     7   
8+  7  fu…  8  fu… 
9+  …  @@…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  fu… 12  fu… 
13+ 12 -  … 13 +  … 
14+      14 +  … 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf020.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ …  …   
2+  2     2   
3+  3  imp…  3  imp…
4+  4   …  4   …
5+       5 +  …
6+  5  )   6  ) 
7+  6     7   
8+  7  fun…  8  fun…
9+  …  @@ …  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  fun… 12  fun…
13+ 12 -  … 13 +  …
14+      14 +  …
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf021.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ …  …   
2+  2     2   
3+  3  imp…  3  imp… 
4+  4   …  4   … 
5+       5 +  … 
6+  5  )   6  ) 
7+  6     7   
8+  7  fun…  8  fun… 
9+  …  @@ …  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  fun… 12  fun… 
13+ 12 -  … 13 +  … 
14+      14 +  … 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf022.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -…  …   
2+  2     2   
3+  3  impo…  3  impo…
4+  4   …  4   …
5+       5 +  …
6+  5  )   6  ) 
7+  6     7   
8+  7  func…  8  func…
9+  …  @@ -…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func… 12  func…
13+ 12 -  … 13 +  …
14+      14 +  …
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf023.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -…  …   
2+  2     2   
3+  3  impo…  3  impo… 
4+  4   …  4   … 
5+       5 +  … 
6+  5  )   6  ) 
7+  6     7   
8+  7  func…  8  func… 
9+  …  @@ -…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func… 12  func… 
13+ 12 -  … 13 +  … 
14+      14 +  … 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf024.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2…  …   
2+  2     2   
3+  3  impor…  3  impor…
4+  4   "…  4   "…
5+       5 +  "…
6+  5  )   6  ) 
7+  6     7   
8+  7  func …  8  func …
9+  …  @@ -9…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func … 12  func …
13+ 12 -  r… 13 +  c…
14+      14 +  r…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf025.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2…  …   
2+  2     2   
3+  3  impor…  3  impor… 
4+  4   "…  4   "… 
5+       5 +  "… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func …  8  func … 
9+  …  @@ -9…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func … 12  func … 
13+ 12 -  r… 13 +  c… 
14+      14 +  r… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf026.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,…  …   
2+  2     2   
3+  3  import…  3  import…
4+  4   "f…  4   "f…
5+       5 +  "s…
6+  5  )   6  ) 
7+  6     7   
8+  7  func m…  8  func m…
9+  …  @@ -9,…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func g… 12  func g…
13+ 12 -  re… 13 +  co…
14+      14 +  re…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf027.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,…  …   
2+  2     2   
3+  3  import…  3  import… 
4+  4   "f…  4   "f… 
5+       5 +  "s… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func m…  8  func m… 
9+  …  @@ -9,…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func g… 12  func g… 
13+ 12 -  re… 13 +  co… 
14+      14 +  re… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf028.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6…  …   
2+  2     2   
3+  3  import (  3  import (
4+  4   "fm…  4   "fm…
5+       5 +  "st…
6+  5  )   6  ) 
7+  6     7   
8+  7  func ma…  8  func ma…
9+  …  @@ -9,5…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func ge… 12  func ge…
13+ 12 -  ret… 13 +  con…
14+      14 +  ret…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf029.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6…  …   
2+  2     2   
3+  3  import (  3  import ( 
4+  4   "fm…  4   "fm… 
5+       5 +  "st… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func ma…  8  func ma… 
9+  …  @@ -9,5…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func ge… 12  func ge… 
13+ 12 -  ret… 13 +  con… 
14+      14 +  ret… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf030.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 …  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"  4   "fmt"
5+       5 +  "str…
6+  5  )   6  ) 
7+  6     7   
8+  7  func mai…  8  func mai…
9+  …  @@ -9,5 …  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func get… 12  func get…
13+ 12 -  retu… 13 +  cont…
14+      14 +  retu…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf031.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 …  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"  4   "fmt" 
5+       5 +  "str… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func mai…  8  func mai… 
9+  …  @@ -9,5 …  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func get… 12  func get… 
13+ 12 -  retu… 13 +  cont… 
14+      14 +  retu… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf032.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "stri…
6+  5  )   6  ) 
7+  6     7   
8+  7  func main…  8  func main…
9+  …  @@ -9,5 +…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getC… 12  func getC…
13+ 12 -  retur… 13 +  conte…
14+      14 +  retur…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf033.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "stri… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main…  8  func main… 
9+  …  @@ -9,5 +…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getC… 12  func getC… 
13+ 12 -  retur… 13 +  conte… 
14+      14 +  retur… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf034.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strin…
6+  5  )   6  ) 
7+  6     7   
8+  7  func main(…  8  func main(…
9+  …  @@ -9,5 +1…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getCo… 12  func getCo…
13+ 12 -  return… 13 +  conten…
14+      14 +  return…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf035.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strin… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main(…  8  func main(… 
9+  …  @@ -9,5 +1…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getCo… 12  func getCo… 
13+ 12 -  return… 13 +  conten… 
14+      14 +  return… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf036.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "string…
6+  5  )   6  ) 
7+  6     7   
8+  7  func main()…  8  func main()…
9+  …  @@ -9,5 +10…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getCon… 12  func getCon…
13+ 12 -  return … 13 +  content…
14+      14 +  return …
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf037.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "string… 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main()…  8  func main()… 
9+  …  @@ -9,5 +10…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getCon… 12  func getCon… 
13+ 12 -  return … 13 +  content… 
14+      14 +  return … 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf038.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings"
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {  8  func main() {
9+  …  @@ -9,5 +10,…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getCont… 12  func getCont…
13+ 12 -  return "… 13 +  content …
14+      14 +  return c…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf039.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {  8  func main() { 
9+  …  @@ -9,5 +10,…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getCont… 12  func getCont… 
13+ 12 -  return "… 13 +  content … 
14+      14 +  return c… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf040.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 …  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getConte… 12  func getConte…
13+ 12 -  return "H… 13 +  content :…
14+      14 +  return co…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf041.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 …  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getConte… 12  func getConte… 
13+ 12 -  return "H… 13 +  content :… 
14+      14 +  return co… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf042.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 …  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getConten… 12  func getConten…
13+ 12 -  return "He… 13 +  content :=…
14+      14 +  return con…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf043.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @…  …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 …  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getConten… 12  func getConten… 
13+ 12 -  return "He… 13 +  content :=… 
14+      14 +  return con… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf044.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@   …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent… 12  func getContent…
13+ 12 -  return "Hel… 13 +  content := …
14+      14 +  return cont…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf045.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@   …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @…  …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent… 12  func getContent… 
13+ 12 -  return "Hel… 13 +  content := … 
14+      14 +  return cont… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf046.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@   …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent(… 12  func getContent(…
13+ 12 -  return "Hell… 13 +  content := s…
14+      14 +  return conte…
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf047.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@   …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent(… 12  func getContent(… 
13+ 12 -  return "Hell… 13 +  content := s… 
14+      14 +  return conte… 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf048.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent()… 12  func getContent()…
13+ 12 -  return "Hello… 13 +  content := st…
14+      14 +  return content
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf049.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent()… 12  func getContent()… 
13+ 12 -  return "Hello… 13 +  content := st… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf050.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() … 12  func getContent() …
13+ 12 -  return "Hello,… 13 +  content := str…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf051.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() … 12  func getContent() … 
13+ 12 -  return "Hello,… 13 +  content := str… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf052.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() s… 12  func getContent() s…
13+ 12 -  return "Hello, … 13 +  content := stri…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf053.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() s… 12  func getContent() s… 
13+ 12 -  return "Hello, … 13 +  content := stri… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf054.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() st… 12  func getContent() st…
13+ 12 -  return "Hello, w… 13 +  content := strin…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf055.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() st… 12  func getContent() st… 
13+ 12 -  return "Hello, w… 13 +  content := strin… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf056.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() str… 12  func getContent() str…
13+ 12 -  return "Hello, wo… 13 +  content := string…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf057.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() str… 12  func getContent() str… 
13+ 12 -  return "Hello, wo… 13 +  content := string… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf058.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() stri… 12  func getContent() stri…
13+ 12 -  return "Hello, wor… 13 +  content := strings…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf059.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() stri… 12  func getContent() stri… 
13+ 12 -  return "Hello, wor… 13 +  content := strings… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf060.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() strin… 12  func getContent() strin…
13+ 12 -  return "Hello, worl… 13 +  content := strings.…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf061.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() strin… 12  func getContent() strin… 
13+ 12 -  return "Hello, worl… 13 +  content := strings.… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf062.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string… 12  func getContent() string…
13+ 12 -  return "Hello, world… 13 +  content := strings.T…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf063.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string… 12  func getContent() string… 
13+ 12 -  return "Hello, world… 13 +  content := strings.T… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf064.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string { 12  func getContent() string {
13+ 12 -  return "Hello, world!" 13 +  content := strings.To…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf065.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string { 12  func getContent() string { 
13+ 12 -  return "Hello, world!" 13 +  content := strings.To… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf066.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToU…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf067.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToU… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf068.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUp…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf069.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUp… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf070.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpp…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf071.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpp… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf072.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUppe…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf073.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUppe… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf074.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf075.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf076.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper(…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf077.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper(… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf078.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf079.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf080.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("H…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf081.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("H… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf082.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("He…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf083.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("He… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf084.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hel…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf085.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hel… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf086.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hell…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf087.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hell… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf088.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf089.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf090.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello,…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf091.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello,… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf092.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, …
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf093.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, … 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf094.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, W…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf095.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, W… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf096.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, Wo…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf097.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, Wo… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf098.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, Wor…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf099.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, Wor… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf100.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, Worl…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf101.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, Worl… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf102.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf103.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf104.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!…
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf105.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!… 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf106.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!")
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf107.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf108.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf109.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Split/WidthOf110.goldennew file+15
@@ -0,0 +1,15 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+       5 +  "strings" 
6+  5  )   6  ) 
7+  6     7   
8+  7  func main() {   8  func main() { 
9+  …  @@ -9,5 +10,6 @@    …   
10+  9  }  10  } 
11+ 10    11   
12+ 11  func getContent() string {  12  func getContent() string { 
13+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
14+      14 +  return content 
15+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf001.goldennew file+16
@@ -0,0 +1,16 @@
1+ 
2+ 
3+ 
4+ 
5+ 
6+ 
7+ 
8+ 
9+ 
10+ 
11+ 
12+ 
13+ 
14+ 
15+ 
16+ 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf002.goldennew file+16
@@ -0,0 +1,16 @@
1+  
2+  
3+  
4+  
5+  
6+  
7+  
8+  
9+  
10+  
11+ 1
12+ 1
13+ 1
14+  
15+  
16+ 1
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf003.goldennew file+16
@@ -0,0 +1,16 @@
1+  …
2+  2
3+  3
4+  4
5+  
6+  5
7+  6
8+  7
9+  …
10+  9
11+ 10
12+ 11
13+ 12
14+  
15+  
16+ 13
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf004.goldennew file+16
@@ -0,0 +1,16 @@
1+  … 
2+  2 
3+  3 
4+  4 
5+   
6+  5 
7+  6 
8+  7 
9+  … 
10+  9 
11+ 10 
12+ 11 
13+ 12 
14+   
15+   
16+ 13 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf005.goldennew file+16
@@ -0,0 +1,16 @@
1+  …  
2+  2  
3+  3  
4+  4  
5+    
6+  5  
7+  6  
8+  7  
9+  …  
10+  9  
11+ 10  
12+ 11  
13+ 12  
14+    
15+    
16+ 13  
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf006.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   
2+  2   
3+  3   
4+  4   
5+     
6+  5   
7+  6   
8+  7   
9+  …   
10+  9  1
11+ 10  1
12+ 11  1
13+ 12   
14+    1
15+    1
16+ 13  1
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf007.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …
2+  2   2
3+  3   3
4+  4   4
5+     5
6+  5   6
7+  6   7
8+  7   8
9+  …   …
10+  9  10
11+ 10  11
12+ 11  12
13+ 12   
14+    13
15+    14
16+ 13  15
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf008.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   … 
2+  2   2 
3+  3   3 
4+  4   4 
5+     5 
6+  5   6 
7+  6   7 
8+  7   8 
9+  …   … 
10+  9  10 
11+ 10  11 
12+ 11  12 
13+ 12    
14+    13 
15+    14 
16+ 13  15 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf009.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   … …
2+  2   2  
3+  3   3  
4+  4   4  
5+     5 +
6+  5   6  
7+  6   7  
8+  7   8  
9+  …   … …
10+  9  10  
11+ 10  11  
12+ 11  12  
13+ 12    -
14+    13 +
15+    14 +
16+ 13  15  
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf010.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  …
2+  2   2  
3+  3   3  
4+  4   4  
5+     5 + 
6+  5   6  
7+  6   7  
8+  7   8  
9+  …   …  …
10+  9  10  
11+ 10  11  
12+ 11  12  
13+ 12    - 
14+    13 + 
15+    14 + 
16+ 13  15  
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf011.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  …
2+  2   2   
3+  3   3  …
4+  4   4  …
5+     5 + …
6+  5   6  )
7+  6   7   
8+  7   8  …
9+  …   …  …
10+  9  10  }
11+ 10  11   
12+ 11  12  …
13+ 12    - …
14+    13 + …
15+    14 + …
16+ 13  15  }
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf012.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @…
2+  2   2   
3+  3   3  i…
4+  4   4   …
5+     5 +  …
6+  5   6  ) 
7+  6   7   
8+  7   8  f…
9+  …   …  @…
10+  9  10  } 
11+ 10  11   
12+ 11  12  f…
13+ 12    -  …
14+    13 +  …
15+    14 +  …
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf013.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@…
2+  2   2   
3+  3   3  im…
4+  4   4   …
5+     5 +  …
6+  5   6  ) 
7+  6   7   
8+  7   8  fu…
9+  …   …  @@…
10+  9  10  } 
11+ 10  11   
12+ 11  12  fu…
13+ 12    -  …
14+    13 +  …
15+    14 +  …
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf014.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ …
2+  2   2   
3+  3   3  imp…
4+  4   4   …
5+     5 +  …
6+  5   6  ) 
7+  6   7   
8+  7   8  fun…
9+  …   …  @@ …
10+  9  10  } 
11+ 10  11   
12+ 11  12  fun…
13+ 12    -  …
14+    13 +  …
15+    14 +  …
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf015.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -…
2+  2   2   
3+  3   3  impo…
4+  4   4   …
5+     5 +  …
6+  5   6  ) 
7+  6   7   
8+  7   8  func…
9+  …   …  @@ -…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func…
13+ 12    -  …
14+    13 +  …
15+    14 +  …
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf016.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2…
2+  2   2   
3+  3   3  impor…
4+  4   4   "…
5+     5 +  "…
6+  5   6  ) 
7+  6   7   
8+  7   8  func …
9+  …   …  @@ -9…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func …
13+ 12    -  r…
14+    13 +  c…
15+    14 +  r…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf017.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,…
2+  2   2   
3+  3   3  import…
4+  4   4   "f…
5+     5 +  "s…
6+  5   6  ) 
7+  6   7   
8+  7   8  func m…
9+  …   …  @@ -9,…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func g…
13+ 12    -  re…
14+    13 +  co…
15+    14 +  re…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf018.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6…
2+  2   2   
3+  3   3  import (
4+  4   4   "fm…
5+     5 +  "st…
6+  5   6  ) 
7+  6   7   
8+  7   8  func ma…
9+  …   …  @@ -9,5…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func ge…
13+ 12    -  ret…
14+    13 +  con…
15+    14 +  ret…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf019.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 …
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt"
5+     5 +  "str…
6+  5   6  ) 
7+  6   7   
8+  7   8  func mai…
9+  …   …  @@ -9,5 …
10+  9  10  } 
11+ 10  11   
12+ 11  12  func get…
13+ 12    -  retu…
14+    13 +  cont…
15+    14 +  retu…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf020.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +…
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "stri…
6+  5   6  ) 
7+  6   7   
8+  7   8  func main…
9+  …   …  @@ -9,5 +…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getC…
13+ 12    -  retur…
14+    13 +  conte…
15+    14 +  retur…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf021.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2…
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strin…
6+  5   6  ) 
7+  6   7   
8+  7   8  func main(…
9+  …   …  @@ -9,5 +1…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getCo…
13+ 12    -  return…
14+    13 +  conten…
15+    14 +  return…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf022.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,…
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "string…
6+  5   6  ) 
7+  6   7   
8+  7   8  func main()…
9+  …   …  @@ -9,5 +10…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getCon…
13+ 12    -  return …
14+    13 +  content…
15+    14 +  return …
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf023.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7…
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings"
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() {
9+  …   …  @@ -9,5 +10,…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getCont…
13+ 12    -  return "…
14+    13 +  content …
15+    14 +  return c…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf024.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 …
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getConte…
13+ 12    -  return "H…
14+    13 +  content :…
15+    14 +  return co…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf025.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @…
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 …
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getConten…
13+ 12    -  return "He…
14+    13 +  content :=…
15+    14 +  return con…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf026.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@ 
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @…
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent…
13+ 12    -  return "Hel…
14+    13 +  content := …
15+    14 +  return cont…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf027.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@ 
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent(…
13+ 12    -  return "Hell…
14+    13 +  content := s…
15+    14 +  return conte…
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf028.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent()…
13+ 12    -  return "Hello…
14+    13 +  content := st…
15+    14 +  return content
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf029.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() …
13+ 12    -  return "Hello,…
14+    13 +  content := str…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf030.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() s…
13+ 12    -  return "Hello, …
14+    13 +  content := stri…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf031.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() st…
13+ 12    -  return "Hello, w…
14+    13 +  content := strin…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf032.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() str…
13+ 12    -  return "Hello, wo…
14+    13 +  content := string…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf033.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() stri…
13+ 12    -  return "Hello, wor…
14+    13 +  content := strings…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf034.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() strin…
13+ 12    -  return "Hello, worl…
14+    13 +  content := strings.…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf035.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string…
13+ 12    -  return "Hello, world…
14+    13 +  content := strings.T…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf036.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string {
13+ 12    -  return "Hello, world!"
14+    13 +  content := strings.To…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf037.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToU…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf038.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUp…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf039.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpp…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf040.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUppe…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf041.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf042.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper(…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf043.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf044.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("H…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf045.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("He…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf046.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hel…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf047.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hell…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf048.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf049.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello,…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf050.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, …
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf051.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, W…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf052.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, Wo…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf053.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, Wor…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf054.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, Worl…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf055.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf056.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!…
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf057.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!")
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf058.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf059.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewWidth/Unified/WidthOf060.goldennew file+16
@@ -0,0 +1,16 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+     5 +  "strings" 
6+  5   6  ) 
7+  6   7   
8+  7   8  func main() { 
9+  …   …  @@ -9,5 +10,6 @@  
10+  9  10  } 
11+ 10  11   
12+ 11  12  func getContent() string { 
13+ 12    -  return "Hello, world!" 
14+    13 +  content := strings.ToUpper("Hello, World!") 
15+    14 +  return content 
16+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf00.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  )   5  ) 
3+  6     6   
4+  7  func main() {   7  func main() { 
5+  8 -  fmt.Println("Hello,…  8 +  content := "Hello, …
6+       9 +  fmt.Println(content)
7+  9  }  10  } 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf01.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …unc main() {   7  …unc main() { 
5+  8 -… fmt.Println("Hello, …  8 +… content := "Hello, w…
6+       9 +… fmt.Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf02.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …nc main() {   7  …nc main() { 
5+  8 -… fmt.Println("Hello, w…  8 +… content := "Hello, wo…
6+       9 +… fmt.Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf03.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …c main() {   7  …c main() { 
5+  8 -… fmt.Println("Hello, wo…  8 +… content := "Hello, wor…
6+       9 +… fmt.Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf04.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  … main() {   7  … main() { 
5+  8 -…fmt.Println("Hello, wor…  8 +…content := "Hello, worl…
6+       9 +…fmt.Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf05.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …main() {   7  …main() { 
5+  8 -…mt.Println("Hello, worl…  8 +…ontent := "Hello, world…
6+       9 +…mt.Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf06.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …ain() {   7  …ain() { 
5+  8 -…t.Println("Hello, world…  8 +…ntent := "Hello, world!"
6+       9 +…t.Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf07.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …in() {   7  …in() { 
5+  8 -….Println("Hello, world!…  8 +…tent := "Hello, world!" 
6+       9 +….Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf08.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …n() {   7  …n() { 
5+  8 -…Println("Hello, world!")  8 +…ent := "Hello, world!" 
6+       9 +…Println(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf09.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …() {   7  …() { 
5+  8 -…rintln("Hello, world!")   8 +…nt := "Hello, world!" 
6+       9 +…rintln(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf10.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …) {   7  …) { 
5+  8 -…intln("Hello, world!")   8 +…t := "Hello, world!" 
6+       9 +…intln(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf11.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  … {   7  … { 
5+  8 -…ntln("Hello, world!")   8 +… := "Hello, world!" 
6+       9 +…ntln(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf12.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …{   7  …{ 
5+  8 -…tln("Hello, world!")   8 +…:= "Hello, world!" 
6+       9 +…tln(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf13.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…ln("Hello, world!")   8 +…= "Hello, world!" 
6+       9 +…ln(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf14.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…n("Hello, world!")   8 +… "Hello, world!" 
6+       9 +…n(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf15.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…("Hello, world!")   8 +…"Hello, world!" 
6+       9 +…(content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf16.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…"Hello, world!")   8 +…Hello, world!" 
6+       9 +…content) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf17.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…Hello, world!")   8 +…ello, world!" 
6+       9 +…ontent) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf18.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…ello, world!")   8 +…llo, world!" 
6+       9 +…ntent) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf19.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…llo, world!")   8 +…lo, world!" 
6+       9 +…tent) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Split/XOffsetOf20.goldennew file+7
@@ -0,0 +1,7 @@
1+  …  @@ -5,5 +5,6 @@    …   
2+  5  …   5  … 
3+  6     6   
4+  7  …   7  … 
5+  8 -…lo, world!")   8 +…o, world!" 
6+       9 +…ent) 
7+  9  …  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf00.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  ) 
3+  6   6   
4+  7   7  func main() { 
5+  8    -  fmt.Println("Hello, world!") 
6+     8 +  content := "Hello, world!" 
7+     9 +  fmt.Println(content) 
8+  9  10  } 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf01.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …unc main() { 
5+  8    -… fmt.Println("Hello, world!") 
6+     8 +… content := "Hello, world!" 
7+     9 +… fmt.Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf02.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …nc main() { 
5+  8    -… fmt.Println("Hello, world!") 
6+     8 +… content := "Hello, world!" 
7+     9 +… fmt.Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf03.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …c main() { 
5+  8    -… fmt.Println("Hello, world!") 
6+     8 +… content := "Hello, world!" 
7+     9 +… fmt.Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf04.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … main() { 
5+  8    -…fmt.Println("Hello, world!") 
6+     8 +…content := "Hello, world!" 
7+     9 +…fmt.Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf05.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …main() { 
5+  8    -…mt.Println("Hello, world!") 
6+     8 +…ontent := "Hello, world!" 
7+     9 +…mt.Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf06.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …ain() { 
5+  8    -…t.Println("Hello, world!") 
6+     8 +…ntent := "Hello, world!" 
7+     9 +…t.Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf07.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …in() { 
5+  8    -….Println("Hello, world!") 
6+     8 +…tent := "Hello, world!" 
7+     9 +….Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf08.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …n() { 
5+  8    -…Println("Hello, world!") 
6+     8 +…ent := "Hello, world!" 
7+     9 +…Println(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf09.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …() { 
5+  8    -…rintln("Hello, world!") 
6+     8 +…nt := "Hello, world!" 
7+     9 +…rintln(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf10.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …) { 
5+  8    -…intln("Hello, world!") 
6+     8 +…t := "Hello, world!" 
7+     9 +…intln(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf11.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … { 
5+  8    -…ntln("Hello, world!") 
6+     8 +… := "Hello, world!" 
7+     9 +…ntln(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf12.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  …{ 
5+  8    -…tln("Hello, world!") 
6+     8 +…:= "Hello, world!" 
7+     9 +…tln(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf13.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…ln("Hello, world!") 
6+     8 +…= "Hello, world!" 
7+     9 +…ln(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf14.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…n("Hello, world!") 
6+     8 +… "Hello, world!" 
7+     9 +…n(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf15.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…("Hello, world!") 
6+     8 +…"Hello, world!" 
7+     9 +…(content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf16.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…"Hello, world!") 
6+     8 +…Hello, world!" 
7+     9 +…content) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf17.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…Hello, world!") 
6+     8 +…ello, world!" 
7+     9 +…ontent) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf18.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…ello, world!") 
6+     8 +…llo, world!" 
7+     9 +…ntent) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf19.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…llo, world!") 
6+     8 +…lo, world!" 
7+     9 +…tent) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewXOffset/Unified/XOffsetOf20.goldennew file+8
@@ -0,0 +1,8 @@
1+  …   …  @@ -5,5 +5,6 @@  
2+  5   5  … 
3+  6   6  … 
4+  7   7  … 
5+  8    -…lo, world!") 
6+     8 +…o, world!" 
7+     9 +…ent) 
8+  9  10  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf00.goldennew file+5
@@ -0,0 +1,5 @@
1+  …  @@ -2,6 +2,7 @@    …   
2+  2     2   
3+  3  import (   3  import ( 
4+  4   "fmt"   4   "fmt" 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf01.goldennew file+5
@@ -0,0 +1,5 @@
1+  2     2   
2+  3  import (   3  import ( 
3+  4   "fmt"   4   "fmt" 
4+       5 +  "strings" 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf02.goldennew file+5
@@ -0,0 +1,5 @@
1+  3  import (   3  import ( 
2+  4   "fmt"   4   "fmt" 
3+       5 +  "strings" 
4+  5  )   6  ) 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf03.goldennew file+5
@@ -0,0 +1,5 @@
1+  4   "fmt"   4   "fmt" 
2+       5 +  "strings" 
3+  5  )   6  ) 
4+  6     7   
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf04.goldennew file+5
@@ -0,0 +1,5 @@
1+       5 +  "strings" 
2+  5  )   6  ) 
3+  6     7   
4+  7  func main() {   8  func main() { 
5+  …  @@ -9,5 +10,6 @@    …   
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf05.goldennew file+5
@@ -0,0 +1,5 @@
1+  5  )   6  ) 
2+  6     7   
3+  7  func main() {   8  func main() { 
4+  …  @@ -9,5 +10,6 @@    …   
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf06.goldennew file+5
@@ -0,0 +1,5 @@
1+  6     7   
2+  7  func main() {   8  func main() { 
3+  …  @@ -9,5 +10,6 @@    …   
4+  9  }  10  } 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf07.goldennew file+5
@@ -0,0 +1,5 @@
1+  7  func main() {   8  func main() { 
2+  …  @@ -9,5 +10,6 @@    …   
3+  9  }  10  } 
4+ 10    11   
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf08.goldennew file+5
@@ -0,0 +1,5 @@
1+  …  @@ -9,5 +10,6 @@    …   
2+  9  }  10  } 
3+ 10    11   
4+ 11  func getContent() string {  12  func getContent() string { 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf09.goldennew file+5
@@ -0,0 +1,5 @@
1+  9  }  10  } 
2+ 10    11   
3+ 11  func getContent() string {  12  func getContent() string { 
4+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
5+  …  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf10.goldennew file+5
@@ -0,0 +1,5 @@
1+ 10    11   
2+ 11  func getContent() string {  12  func getContent() string { 
3+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
4+      14 +  return content 
5+ 13  }  15  } 
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf11.goldennew file+5
@@ -0,0 +1,5 @@
1+ 11  func getContent() string {  12  func getContent() string { 
2+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
3+      14 +  return content 
4+ 13  }  15  } 
5+          
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf12.goldennew file+5
@@ -0,0 +1,5 @@
1+ 12 -  return "Hello, world!"  13 +  content := strings.ToUpper("Hello, World!") 
2+      14 +  return content 
3+ 13  }  15  } 
4+          
5+          
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf13.goldennew file+5
@@ -0,0 +1,5 @@
1+      14 +  return content 
2+ 13  }  15  } 
3+          
4+          
5+          
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf14.goldennew file+5
@@ -0,0 +1,5 @@
1+ 13  }  15  } 
2+          
3+          
4+          
5+          
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf15.goldennew file+5
@@ -0,0 +1,5 @@
1+          
2+          
3+          
4+          
5+          
internal/exp/diffview/testdata/TestDiffViewYOffset/Split/YOffsetOf16.goldennew file+5
@@ -0,0 +1,5 @@
1+          
2+          
3+          
4+          
5+          
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf00.goldennew file+5
@@ -0,0 +1,5 @@
1+  …   …  @@ -2,6 +2,7 @@  
2+  2   2   
3+  3   3  import ( 
4+  4   4   "fmt" 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf01.goldennew file+5
@@ -0,0 +1,5 @@
1+  2   2   
2+  3   3  import ( 
3+  4   4   "fmt" 
4+     5 +  "strings" 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf02.goldennew file+5
@@ -0,0 +1,5 @@
1+  3   3  import ( 
2+  4   4   "fmt" 
3+     5 +  "strings" 
4+  5   6  ) 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf03.goldennew file+5
@@ -0,0 +1,5 @@
1+  4   4   "fmt" 
2+     5 +  "strings" 
3+  5   6  ) 
4+  6   7   
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf04.goldennew file+5
@@ -0,0 +1,5 @@
1+     5 +  "strings" 
2+  5   6  ) 
3+  6   7   
4+  7   8  func main() { 
5+  …   …  @@ -9,5 +10,6 @@  
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf05.goldennew file+5
@@ -0,0 +1,5 @@
1+  5   6  ) 
2+  6   7   
3+  7   8  func main() { 
4+  …   …  @@ -9,5 +10,6 @@  
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf06.goldennew file+5
@@ -0,0 +1,5 @@
1+  6   7   
2+  7   8  func main() { 
3+  …   …  @@ -9,5 +10,6 @@  
4+  9  10  } 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf07.goldennew file+5
@@ -0,0 +1,5 @@
1+  7   8  func main() { 
2+  …   …  @@ -9,5 +10,6 @@  
3+  9  10  } 
4+ 10  11   
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf08.goldennew file+5
@@ -0,0 +1,5 @@
1+  …   …  @@ -9,5 +10,6 @@  
2+  9  10  } 
3+ 10  11   
4+ 11  12  func getContent() string { 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf09.goldennew file+5
@@ -0,0 +1,5 @@
1+  9  10  } 
2+ 10  11   
3+ 11  12  func getContent() string { 
4+ 12    -  return "Hello, world!" 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf10.goldennew file+5
@@ -0,0 +1,5 @@
1+ 10  11   
2+ 11  12  func getContent() string { 
3+ 12    -  return "Hello, world!" 
4+    13 +  content := strings.ToUpper("Hello, World!") 
5+  …   …  … 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf11.goldennew file+5
@@ -0,0 +1,5 @@
1+ 11  12  func getContent() string { 
2+ 12    -  return "Hello, world!" 
3+    13 +  content := strings.ToUpper("Hello, World!") 
4+    14 +  return content 
5+ 13  15  } 
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf12.goldennew file+5
@@ -0,0 +1,5 @@
1+ 12    -  return "Hello, world!" 
2+    13 +  content := strings.ToUpper("Hello, World!") 
3+    14 +  return content 
4+ 13  15  } 
5+        
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf13.goldennew file+5
@@ -0,0 +1,5 @@
1+    13 +  content := strings.ToUpper("Hello, World!") 
2+    14 +  return content 
3+ 13  15  } 
4+        
5+        
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf14.goldennew file+5
@@ -0,0 +1,5 @@
1+    14 +  return content 
2+ 13  15  } 
3+        
4+        
5+        
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf15.goldennew file+5
@@ -0,0 +1,5 @@
1+ 13  15  } 
2+        
3+        
4+        
5+        
internal/exp/diffview/testdata/TestDiffViewYOffset/Unified/YOffsetOf16.goldennew file+5
@@ -0,0 +1,5 @@
1+        
2+        
3+        
4+        
5+        
internal/exp/diffview/testdata/TestMultipleHunks.afternew file+15
@@ -0,0 +1,15 @@
1+package main
2+
3+import (
4+ "fmt"
5+ "strings"
6+)
7+
8+func main() {
9+ fmt.Println(getContent())
10+}
11+
12+func getContent() string {
13+ content := strings.ToUpper("Hello, World!")
14+ return content
15+}
internal/exp/diffview/testdata/TestMultipleHunks.beforenew file+13
@@ -0,0 +1,13 @@
1+package main
2+
3+import (
4+ "fmt"
5+)
6+
7+func main() {
8+ fmt.Println(getContent())
9+}
10+
11+func getContent() string {
12+ return "Hello, world!"
13+}
internal/exp/diffview/testdata/TestNarrow.afternew file+3
@@ -0,0 +1,3 @@
1+d
2+e
3+f
internal/exp/diffview/testdata/TestNarrow.beforenew file+3
@@ -0,0 +1,3 @@
1+a
2+b
3+c
internal/exp/diffview/testdata/TestTabs.afternew file+15
@@ -0,0 +1,15 @@
1+package main
2+
3+import (
4+ "fmt"
5+ "strings"
6+)
7+
8+func main() {
9+ fmt.Println(getContent())
10+}
11+
12+func getContent() string {
13+ content := strings.ToUpper("Hello, World!")
14+ return content
15+}
internal/exp/diffview/testdata/TestTabs.beforenew file+13
@@ -0,0 +1,13 @@
1+package main
2+
3+import (
4+ "fmt"
5+)
6+
7+func main() {
8+ fmt.Println(getContent())
9+}
10+
11+func getContent() string {
12+ return "Hello, world!"
13+}
internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/Content.goldennew file+11
@@ -0,0 +1,11 @@
1+--- main.go
2++++ main.go
3+@@ -5,5 +5,6 @@
4+ )
5+
6+ func main() {
7+- fmt.Println("Hello, World!")
8++ content := "Hello, World!"
9++ fmt.Println(content)
10+ }
11+\ No newline at end of file
internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLines/JSON.goldennew file+40
@@ -0,0 +1,40 @@
1+{
2+ "From": "main.go",
3+ "To": "main.go",
4+ "Hunks": [
5+ {
6+ "FromLine": 5,
7+ "ToLine": 5,
8+ "Lines": [
9+ {
10+ "Kind": 2,
11+ "Content": "\t)\n"
12+ },
13+ {
14+ "Kind": 2,
15+ "Content": "\n"
16+ },
17+ {
18+ "Kind": 2,
19+ "Content": "\tfunc main() {\n"
20+ },
21+ {
22+ "Kind": 0,
23+ "Content": "\t\tfmt.Println(\"Hello, World!\")\n"
24+ },
25+ {
26+ "Kind": 1,
27+ "Content": "\t\tcontent := \"Hello, World!\"\n"
28+ },
29+ {
30+ "Kind": 1,
31+ "Content": "\t\tfmt.Println(content)\n"
32+ },
33+ {
34+ "Kind": 2,
35+ "Content": "\t}"
36+ }
37+ ]
38+ }
39+ ]
40+}
internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/Content.goldennew file+12
@@ -0,0 +1,12 @@
1+--- main.go
2++++ main.go
3+@@ -4,6 +4,7 @@
4+ "fmt"
5+ )
6+
7+ func main() {
8+- fmt.Println("Hello, World!")
9++ content := "Hello, World!"
10++ fmt.Println(content)
11+ }
12+\ No newline at end of file
internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusOne/JSON.goldennew file+44
@@ -0,0 +1,44 @@
1+{
2+ "From": "main.go",
3+ "To": "main.go",
4+ "Hunks": [
5+ {
6+ "FromLine": 4,
7+ "ToLine": 4,
8+ "Lines": [
9+ {
10+ "Kind": 2,
11+ "Content": "\t\t\"fmt\"\n"
12+ },
13+ {
14+ "Kind": 2,
15+ "Content": "\t)\n"
16+ },
17+ {
18+ "Kind": 2,
19+ "Content": "\n"
20+ },
21+ {
22+ "Kind": 2,
23+ "Content": "\tfunc main() {\n"
24+ },
25+ {
26+ "Kind": 0,
27+ "Content": "\t\tfmt.Println(\"Hello, World!\")\n"
28+ },
29+ {
30+ "Kind": 1,
31+ "Content": "\t\tcontent := \"Hello, World!\"\n"
32+ },
33+ {
34+ "Kind": 1,
35+ "Content": "\t\tfmt.Println(content)\n"
36+ },
37+ {
38+ "Kind": 2,
39+ "Content": "\t}"
40+ }
41+ ]
42+ }
43+ ]
44+}
internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/Content.goldennew file+13
@@ -0,0 +1,13 @@
1+--- main.go
2++++ main.go
3+@@ -3,7 +3,8 @@
4+ import (
5+ "fmt"
6+ )
7+
8+ func main() {
9+- fmt.Println("Hello, World!")
10++ content := "Hello, World!"
11++ fmt.Println(content)
12+ }
13+\ No newline at end of file
internal/exp/diffview/testdata/TestUdiff/ToUnifiedDiff/DefaultContextLinesPlusTwo/JSON.goldennew file+48
@@ -0,0 +1,48 @@
1+{
2+ "From": "main.go",
3+ "To": "main.go",
4+ "Hunks": [
5+ {
6+ "FromLine": 3,
7+ "ToLine": 3,
8+ "Lines": [
9+ {
10+ "Kind": 2,
11+ "Content": "\timport (\n"
12+ },
13+ {
14+ "Kind": 2,
15+ "Content": "\t\t\"fmt\"\n"
16+ },
17+ {
18+ "Kind": 2,
19+ "Content": "\t)\n"
20+ },
21+ {
22+ "Kind": 2,
23+ "Content": "\n"
24+ },
25+ {
26+ "Kind": 2,
27+ "Content": "\tfunc main() {\n"
28+ },
29+ {
30+ "Kind": 0,
31+ "Content": "\t\tfmt.Println(\"Hello, World!\")\n"
32+ },
33+ {
34+ "Kind": 1,
35+ "Content": "\t\tcontent := \"Hello, World!\"\n"
36+ },
37+ {
38+ "Kind": 1,
39+ "Content": "\t\tfmt.Println(content)\n"
40+ },
41+ {
42+ "Kind": 2,
43+ "Content": "\t}"
44+ }
45+ ]
46+ }
47+ ]
48+}
internal/exp/diffview/testdata/TestUdiff/Unified.goldennew file+11
@@ -0,0 +1,11 @@
1+--- main.go
2++++ main.go
3+@@ -5,5 +5,6 @@
4+ )
5+
6+ func main() {
7+- fmt.Println("Hello, World!")
8++ content := "Hello, World!"
9++ fmt.Println(content)
10+ }
11+\ No newline at end of file
internal/exp/diffview/udiff_test.gonew file+92
@@ -0,0 +1,92 @@
1+package diffview_test
2+
3+import (
4+ "bytes"
5+ "encoding/json"
6+ "testing"
7+
8+ "github.com/aymanbagabas/go-udiff"
9+ "github.com/aymanbagabas/go-udiff/myers"
10+ "github.com/charmbracelet/x/exp/golden"
11+)
12+
13+func TestUdiff(t *testing.T) {
14+ before := `package main
15+
16+ import (
17+ "fmt"
18+ )
19+
20+ func main() {
21+ fmt.Println("Hello, World!")
22+ }`
23+
24+ after := `package main
25+
26+ import (
27+ "fmt"
28+ )
29+
30+ func main() {
31+ content := "Hello, World!"
32+ fmt.Println(content)
33+ }`
34+
35+ t.Run("Unified", func(t *testing.T) {
36+ content := udiff.Unified("main.go", "main.go", before, after)
37+ golden.RequireEqual(t, []byte(content))
38+ })
39+
40+ t.Run("ToUnifiedDiff", func(t *testing.T) {
41+ toUnifiedDiff := func(t *testing.T, before, after string, contextLines int) udiff.UnifiedDiff {
42+ edits := myers.ComputeEdits(before, after) //nolint:staticcheck
43+ unifiedDiff, err := udiff.ToUnifiedDiff("main.go", "main.go", before, edits, contextLines)
44+ if err != nil {
45+ t.Fatalf("ToUnifiedDiff failed: %v", err)
46+ }
47+ return unifiedDiff
48+ }
49+ toJSON := func(t *testing.T, unifiedDiff udiff.UnifiedDiff) []byte {
50+ var buff bytes.Buffer
51+ encoder := json.NewEncoder(&buff)
52+ encoder.SetIndent("", " ")
53+ if err := encoder.Encode(unifiedDiff); err != nil {
54+ t.Fatalf("Failed to encode unified diff: %v", err)
55+ }
56+ return buff.Bytes()
57+ }
58+
59+ t.Run("DefaultContextLines", func(t *testing.T) {
60+ unifiedDiff := toUnifiedDiff(t, before, after, udiff.DefaultContextLines)
61+
62+ t.Run("Content", func(t *testing.T) {
63+ golden.RequireEqual(t, []byte(unifiedDiff.String()))
64+ })
65+ t.Run("JSON", func(t *testing.T) {
66+ golden.RequireEqual(t, toJSON(t, unifiedDiff))
67+ })
68+ })
69+
70+ t.Run("DefaultContextLinesPlusOne", func(t *testing.T) {
71+ unifiedDiff := toUnifiedDiff(t, before, after, udiff.DefaultContextLines+1)
72+
73+ t.Run("Content", func(t *testing.T) {
74+ golden.RequireEqual(t, []byte(unifiedDiff.String()))
75+ })
76+ t.Run("JSON", func(t *testing.T) {
77+ golden.RequireEqual(t, toJSON(t, unifiedDiff))
78+ })
79+ })
80+
81+ t.Run("DefaultContextLinesPlusTwo", func(t *testing.T) {
82+ unifiedDiff := toUnifiedDiff(t, before, after, udiff.DefaultContextLines+2)
83+
84+ t.Run("Content", func(t *testing.T) {
85+ golden.RequireEqual(t, []byte(unifiedDiff.String()))
86+ })
87+ t.Run("JSON", func(t *testing.T) {
88+ golden.RequireEqual(t, toJSON(t, unifiedDiff))
89+ })
90+ })
91+ })
92+}
internal/exp/diffview/util.gonew file+39
@@ -0,0 +1,39 @@
1+package diffview
2+
3+import (
4+ "fmt"
5+ "strings"
6+
7+ "github.com/charmbracelet/x/ansi"
8+)
9+
10+func pad(v any, width int) string {
11+ s := fmt.Sprintf("%v", v)
12+ w := ansi.StringWidth(s)
13+ if w >= width {
14+ return s
15+ }
16+ return strings.Repeat(" ", width-w) + s
17+}
18+
19+func isEven(n int) bool {
20+ return n%2 == 0
21+}
22+
23+func isOdd(n int) bool {
24+ return !isEven(n)
25+}
26+
27+func btoi(b bool) int {
28+ if b {
29+ return 1
30+ }
31+ return 0
32+}
33+
34+func ternary[T any](cond bool, t, f T) T {
35+ if cond {
36+ return t
37+ }
38+ return f
39+}
internal/exp/diffview/util_test.gonew file+27
@@ -0,0 +1,27 @@
1+package diffview
2+
3+import (
4+ "testing"
5+)
6+
7+func TestPad(t *testing.T) {
8+ tests := []struct {
9+ input any
10+ width int
11+ expected string
12+ }{
13+ {7, 2, " 7"},
14+ {7, 3, " 7"},
15+ {"a", 2, " a"},
16+ {"a", 3, " a"},
17+ {"…", 2, " …"},
18+ {"…", 3, " …"},
19+ }
20+
21+ for _, tt := range tests {
22+ result := pad(tt.input, tt.width)
23+ if result != tt.expected {
24+ t.Errorf("expected %q, got %q", tt.expected, result)
25+ }
26+ }
27+}
internal/llm/agent/tools.go−1
@@ -33,7 +33,6 @@ func CoderAgentTools(
3333 tools.NewLsTool(),
3434 tools.NewSourcegraphTool(),
3535 tools.NewViewTool(lspClients),
36− tools.NewPatchTool(lspClients, permissions, history),
3736 tools.NewWriteTool(lspClients, permissions, history),
3837 NewAgentTool(sessions, messages, lspClients),
3938 }, otherTools...,
internal/llm/tools/edit.go+31−23
@@ -24,14 +24,16 @@ type EditParams struct {
2424}
2525
2626type EditPermissionsParams struct {
27− FilePath string `json:"file_path"`
28− Diff string `json:"diff"`
27+ FilePath string `json:"file_path"`
28+ OldContent string `json:"old_content,omitempty"`
29+ NewContent string `json:"new_content,omitempty"`
2930}
3031
3132type EditResponseMetadata struct {
32− Diff string `json:"diff"`
33− Additions int `json:"additions"`
34− Removals int `json:"removals"`
33+ Additions int `json:"additions"`
34+ Removals int `json:"removals"`
35+ OldContent string `json:"old_content,omitempty"`
36+ NewContent string `json:"new_content,omitempty"`
3537}
3638
3739type editTool struct {
@@ -191,7 +193,7 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
191193 return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
192194 }
193195
194− diff, additions, removals := diff.GenerateDiff(
196+ _, additions, removals := diff.GenerateDiff(
195197 "",
196198 content,
197199 filePath,
@@ -209,8 +211,9 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
209211 Action: "write",
210212 Description: fmt.Sprintf("Create file %s", filePath),
211213 Params: EditPermissionsParams{
212− FilePath: filePath,
213− Diff: diff,
214+ FilePath: filePath,
215+ OldContent: "",
216+ NewContent: content,
214217 },
215218 },
216219 )
@@ -243,9 +246,10 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
243246 return WithResponseMetadata(
244247 NewTextResponse("File created: "+filePath),
245248 EditResponseMetadata{
246− Diff: diff,
247− Additions: additions,
248− Removals: removals,
249+ OldContent: "",
250+ NewContent: content,
251+ Additions: additions,
252+ Removals: removals,
249253 },
250254 ), nil
251255}
@@ -301,7 +305,7 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
301305 return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
302306 }
303307
304− diff, additions, removals := diff.GenerateDiff(
308+ _, additions, removals := diff.GenerateDiff(
305309 oldContent,
306310 newContent,
307311 filePath,
@@ -320,8 +324,9 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
320324 Action: "write",
321325 Description: fmt.Sprintf("Delete content from file %s", filePath),
322326 Params: EditPermissionsParams{
323− FilePath: filePath,
324− Diff: diff,
327+ FilePath: filePath,
328+ OldContent: oldContent,
329+ NewContent: newContent,
325330 },
326331 },
327332 )
@@ -362,9 +367,10 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
362367 return WithResponseMetadata(
363368 NewTextResponse("Content deleted from file: "+filePath),
364369 EditResponseMetadata{
365− Diff: diff,
366− Additions: additions,
367− Removals: removals,
370+ OldContent: oldContent,
371+ NewContent: newContent,
372+ Additions: additions,
373+ Removals: removals,
368374 },
369375 ), nil
370376}
@@ -422,7 +428,7 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
422428 if sessionID == "" || messageID == "" {
423429 return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
424430 }
425− diff, additions, removals := diff.GenerateDiff(
431+ _, additions, removals := diff.GenerateDiff(
426432 oldContent,
427433 newContent,
428434 filePath,
@@ -440,8 +446,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
440446 Action: "write",
441447 Description: fmt.Sprintf("Replace content in file %s", filePath),
442448 Params: EditPermissionsParams{
443− FilePath: filePath,
444− Diff: diff,
449+ FilePath: filePath,
450+ OldContent: oldContent,
451+ NewContent: newContent,
445452 },
446453 },
447454 )
@@ -482,8 +489,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
482489 return WithResponseMetadata(
483490 NewTextResponse("Content replaced in file: "+filePath),
484491 EditResponseMetadata{
485− Diff: diff,
486− Additions: additions,
487− Removals: removals,
492+ OldContent: oldContent,
493+ NewContent: newContent,
494+ Additions: additions,
495+ Removals: removals,
488496 }), nil
489497}
internal/llm/tools/patch.godeleted−372
@@ -1,372 +0,0 @@
1−package tools
2−
3−import (
4− "context"
5− "encoding/json"
6− "fmt"
7− "os"
8− "path/filepath"
9− "time"
10−
11− "github.com/charmbracelet/crush/internal/config"
12− "github.com/charmbracelet/crush/internal/diff"
13− "github.com/charmbracelet/crush/internal/history"
14− "github.com/charmbracelet/crush/internal/logging"
15− "github.com/charmbracelet/crush/internal/lsp"
16− "github.com/charmbracelet/crush/internal/permission"
17−)
18−
19−type PatchParams struct {
20− PatchText string `json:"patch_text"`
21−}
22−
23−type PatchResponseMetadata struct {
24− FilesChanged []string `json:"files_changed"`
25− Additions int `json:"additions"`
26− Removals int `json:"removals"`
27−}
28−
29−type patchTool struct {
30− lspClients map[string]*lsp.Client
31− permissions permission.Service
32− files history.Service
33−}
34−
35−const (
36− PatchToolName = "patch"
37− patchDescription = `Applies a patch to multiple files in one operation. This tool is useful for making coordinated changes across multiple files.
38−
39−The patch text must follow this format:
40−*** Begin Patch
41−*** Update File: /path/to/file
42−@@ Context line (unique within the file)
43− Line to keep
44−-Line to remove
45−+Line to add
46− Line to keep
47−*** Add File: /path/to/new/file
48−+Content of the new file
49−+More content
50−*** Delete File: /path/to/file/to/delete
51−*** End Patch
52−
53−Before using this tool:
54−1. Use the FileRead tool to understand the files' contents and context
55−2. Verify all file paths are correct (use the LS tool)
56−
57−CRITICAL REQUIREMENTS FOR USING THIS TOOL:
58−
59−1. UNIQUENESS: Context lines MUST uniquely identify the specific sections you want to change
60−2. PRECISION: All whitespace, indentation, and surrounding code must match exactly
61−3. VALIDATION: Ensure edits result in idiomatic, correct code
62−4. PATHS: Always use absolute file paths (starting with /)
63−
64−The tool will apply all changes in a single atomic operation.`
65−)
66−
67−func NewPatchTool(lspClients map[string]*lsp.Client, permissions permission.Service, files history.Service) BaseTool {
68− return &patchTool{
69− lspClients: lspClients,
70− permissions: permissions,
71− files: files,
72− }
73−}
74−
75−func (p *patchTool) Info() ToolInfo {
76− return ToolInfo{
77− Name: PatchToolName,
78− Description: patchDescription,
79− Parameters: map[string]any{
80− "patch_text": map[string]any{
81− "type": "string",
82− "description": "The full patch text that describes all changes to be made",
83− },
84− },
85− Required: []string{"patch_text"},
86− }
87−}
88−
89−func (p *patchTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error) {
90− var params PatchParams
91− if err := json.Unmarshal([]byte(call.Input), &params); err != nil {
92− return NewTextErrorResponse("invalid parameters"), nil
93− }
94−
95− if params.PatchText == "" {
96− return NewTextErrorResponse("patch_text is required"), nil
97− }
98−
99− // Identify all files needed for the patch and verify they've been read
100− filesToRead := diff.IdentifyFilesNeeded(params.PatchText)
101− for _, filePath := range filesToRead {
102− absPath := filePath
103− if !filepath.IsAbs(absPath) {
104− wd := config.WorkingDirectory()
105− absPath = filepath.Join(wd, absPath)
106− }
107−
108− if getLastReadTime(absPath).IsZero() {
109− return NewTextErrorResponse(fmt.Sprintf("you must read the file %s before patching it. Use the FileRead tool first", filePath)), nil
110− }
111−
112− fileInfo, err := os.Stat(absPath)
113− if err != nil {
114− if os.IsNotExist(err) {
115− return NewTextErrorResponse(fmt.Sprintf("file not found: %s", absPath)), nil
116− }
117− return ToolResponse{}, fmt.Errorf("failed to access file: %w", err)
118− }
119−
120− if fileInfo.IsDir() {
121− return NewTextErrorResponse(fmt.Sprintf("path is a directory, not a file: %s", absPath)), nil
122− }
123−
124− modTime := fileInfo.ModTime()
125− lastRead := getLastReadTime(absPath)
126− if modTime.After(lastRead) {
127− return NewTextErrorResponse(
128− fmt.Sprintf("file %s has been modified since it was last read (mod time: %s, last read: %s)",
129− absPath, modTime.Format(time.RFC3339), lastRead.Format(time.RFC3339),
130− )), nil
131− }
132− }
133−
134− // Check for new files to ensure they don't already exist
135− filesToAdd := diff.IdentifyFilesAdded(params.PatchText)
136− for _, filePath := range filesToAdd {
137− absPath := filePath
138− if !filepath.IsAbs(absPath) {
139− wd := config.WorkingDirectory()
140− absPath = filepath.Join(wd, absPath)
141− }
142−
143− _, err := os.Stat(absPath)
144− if err == nil {
145− return NewTextErrorResponse(fmt.Sprintf("file already exists and cannot be added: %s", absPath)), nil
146− } else if !os.IsNotExist(err) {
147− return ToolResponse{}, fmt.Errorf("failed to check file: %w", err)
148− }
149− }
150−
151− // Load all required files
152− currentFiles := make(map[string]string)
153− for _, filePath := range filesToRead {
154− absPath := filePath
155− if !filepath.IsAbs(absPath) {
156− wd := config.WorkingDirectory()
157− absPath = filepath.Join(wd, absPath)
158− }
159−
160− content, err := os.ReadFile(absPath)
161− if err != nil {
162− return ToolResponse{}, fmt.Errorf("failed to read file %s: %w", absPath, err)
163− }
164− currentFiles[filePath] = string(content)
165− }
166−
167− // Process the patch
168− patch, fuzz, err := diff.TextToPatch(params.PatchText, currentFiles)
169− if err != nil {
170− return NewTextErrorResponse(fmt.Sprintf("failed to parse patch: %s", err)), nil
171− }
172−
173− if fuzz > 3 {
174− return NewTextErrorResponse(fmt.Sprintf("patch contains fuzzy matches (fuzz level: %d). Please make your context lines more precise", fuzz)), nil
175− }
176−
177− // Convert patch to commit
178− commit, err := diff.PatchToCommit(patch, currentFiles)
179− if err != nil {
180− return NewTextErrorResponse(fmt.Sprintf("failed to create commit from patch: %s", err)), nil
181− }
182−
183− // Get session ID and message ID
184− sessionID, messageID := GetContextValues(ctx)
185− if sessionID == "" || messageID == "" {
186− return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a patch")
187− }
188−
189− // Request permission for all changes
190− for path, change := range commit.Changes {
191− switch change.Type {
192− case diff.ActionAdd:
193− dir := filepath.Dir(path)
194− patchDiff, _, _ := diff.GenerateDiff("", *change.NewContent, path)
195− p := p.permissions.Request(
196− permission.CreatePermissionRequest{
197− SessionID: sessionID,
198− Path: dir,
199− ToolName: PatchToolName,
200− Action: "create",
201− Description: fmt.Sprintf("Create file %s", path),
202− Params: EditPermissionsParams{
203− FilePath: path,
204− Diff: patchDiff,
205− },
206− },
207− )
208− if !p {
209− return ToolResponse{}, permission.ErrorPermissionDenied
210− }
211− case diff.ActionUpdate:
212− currentContent := ""
213− if change.OldContent != nil {
214− currentContent = *change.OldContent
215− }
216− newContent := ""
217− if change.NewContent != nil {
218− newContent = *change.NewContent
219− }
220− patchDiff, _, _ := diff.GenerateDiff(currentContent, newContent, path)
221− dir := filepath.Dir(path)
222− p := p.permissions.Request(
223− permission.CreatePermissionRequest{
224− SessionID: sessionID,
225− Path: dir,
226− ToolName: PatchToolName,
227− Action: "update",
228− Description: fmt.Sprintf("Update file %s", path),
229− Params: EditPermissionsParams{
230− FilePath: path,
231− Diff: patchDiff,
232− },
233− },
234− )
235− if !p {
236− return ToolResponse{}, permission.ErrorPermissionDenied
237− }
238− case diff.ActionDelete:
239− dir := filepath.Dir(path)
240− patchDiff, _, _ := diff.GenerateDiff(*change.OldContent, "", path)
241− p := p.permissions.Request(
242− permission.CreatePermissionRequest{
243− SessionID: sessionID,
244− Path: dir,
245− ToolName: PatchToolName,
246− Action: "delete",
247− Description: fmt.Sprintf("Delete file %s", path),
248− Params: EditPermissionsParams{
249− FilePath: path,
250− Diff: patchDiff,
251− },
252− },
253− )
254− if !p {
255− return ToolResponse{}, permission.ErrorPermissionDenied
256− }
257− }
258− }
259−
260− // Apply the changes to the filesystem
261− err = diff.ApplyCommit(commit, func(path string, content string) error {
262− absPath := path
263− if !filepath.IsAbs(absPath) {
264− wd := config.WorkingDirectory()
265− absPath = filepath.Join(wd, absPath)
266− }
267−
268− // Create parent directories if needed
269− dir := filepath.Dir(absPath)
270− if err := os.MkdirAll(dir, 0o755); err != nil {
271− return fmt.Errorf("failed to create parent directories for %s: %w", absPath, err)
272− }
273−
274− return os.WriteFile(absPath, []byte(content), 0o644)
275− }, func(path string) error {
276− absPath := path
277− if !filepath.IsAbs(absPath) {
278− wd := config.WorkingDirectory()
279− absPath = filepath.Join(wd, absPath)
280− }
281− return os.Remove(absPath)
282− })
283− if err != nil {
284− return NewTextErrorResponse(fmt.Sprintf("failed to apply patch: %s", err)), nil
285− }
286−
287− // Update file history for all modified files
288− changedFiles := []string{}
289− totalAdditions := 0
290− totalRemovals := 0
291−
292− for path, change := range commit.Changes {
293− absPath := path
294− if !filepath.IsAbs(absPath) {
295− wd := config.WorkingDirectory()
296− absPath = filepath.Join(wd, absPath)
297− }
298− changedFiles = append(changedFiles, absPath)
299−
300− oldContent := ""
301− if change.OldContent != nil {
302− oldContent = *change.OldContent
303− }
304−
305− newContent := ""
306− if change.NewContent != nil {
307− newContent = *change.NewContent
308− }
309−
310− // Calculate diff statistics
311− _, additions, removals := diff.GenerateDiff(oldContent, newContent, path)
312− totalAdditions += additions
313− totalRemovals += removals
314−
315− // Update history
316− file, err := p.files.GetByPathAndSession(ctx, absPath, sessionID)
317− if err != nil && change.Type != diff.ActionAdd {
318− // If not adding a file, create history entry for existing file
319− _, err = p.files.Create(ctx, sessionID, absPath, oldContent)
320− if err != nil {
321− logging.Debug("Error creating file history", "error", err)
322− }
323− }
324−
325− if err == nil && change.Type != diff.ActionAdd && file.Content != oldContent {
326− // User manually changed content, store intermediate version
327− _, err = p.files.CreateVersion(ctx, sessionID, absPath, oldContent)
328− if err != nil {
329− logging.Debug("Error creating file history version", "error", err)
330− }
331− }
332−
333− // Store new version
334− if change.Type == diff.ActionDelete {
335− _, err = p.files.CreateVersion(ctx, sessionID, absPath, "")
336− } else {
337− _, err = p.files.CreateVersion(ctx, sessionID, absPath, newContent)
338− }
339− if err != nil {
340− logging.Debug("Error creating file history version", "error", err)
341− }
342−
343− // Record file operations
344− recordFileWrite(absPath)
345− recordFileRead(absPath)
346− }
347−
348− // Run LSP diagnostics on all changed files
349− for _, filePath := range changedFiles {
350− waitForLspDiagnostics(ctx, filePath, p.lspClients)
351− }
352−
353− result := fmt.Sprintf("Patch applied successfully. %d files changed, %d additions, %d removals",
354− len(changedFiles), totalAdditions, totalRemovals)
355−
356− diagnosticsText := ""
357− for _, filePath := range changedFiles {
358− diagnosticsText += getDiagnostics(filePath, p.lspClients)
359− }
360−
361− if diagnosticsText != "" {
362− result += "\n\nDiagnostics:\n" + diagnosticsText
363− }
364−
365− return WithResponseMetadata(
366− NewTextResponse(result),
367− PatchResponseMetadata{
368− FilesChanged: changedFiles,
369− Additions: totalAdditions,
370− Removals: totalRemovals,
371− }), nil
372−}
internal/tui/components/chat/messages/renderer.go+7−39
@@ -6,11 +6,11 @@ import (
66 "strings"
77 "time"
88
9− "github.com/charmbracelet/crush/internal/diff"
109 "github.com/charmbracelet/crush/internal/fileutil"
1110 "github.com/charmbracelet/crush/internal/highlight"
1211 "github.com/charmbracelet/crush/internal/llm/agent"
1312 "github.com/charmbracelet/crush/internal/llm/tools"
13+ "github.com/charmbracelet/crush/internal/tui/components/core"
1414 "github.com/charmbracelet/crush/internal/tui/styles"
1515 "github.com/charmbracelet/lipgloss/v2"
1616 "github.com/charmbracelet/lipgloss/v2/tree"
@@ -148,7 +148,6 @@ func init() {
148148 registry.register(tools.GrepToolName, func() renderer { return grepRenderer{} })
149149 registry.register(tools.LSToolName, func() renderer { return lsRenderer{} })
150150 registry.register(tools.SourcegraphToolName, func() renderer { return sourcegraphRenderer{} })
151− registry.register(tools.PatchToolName, func() renderer { return patchRenderer{} })
152151 registry.register(tools.DiagnosticsToolName, func() renderer { return diagnosticsRenderer{} })
153152 registry.register(agent.AgentToolName, func() renderer { return agentRenderer{} })
154153}
@@ -258,9 +257,12 @@ func (er editRenderer) Render(v *toolCallCmp) string {
258257 return renderPlainContent(v, v.result.Content)
259258 }
260259
261− trunc := truncateHeight(meta.Diff, responseContextHeight)
262− diffView, _ := diff.FormatDiff(trunc, diff.WithTotalWidth(v.textWidth()-2))
263− return diffView
260+ formatter := core.DiffFormatter().
261+ Before(fileutil.PrettyPath(params.FilePath), meta.OldContent).
262+ After(fileutil.PrettyPath(params.FilePath), meta.NewContent).
263+ Split().
264+ Width(v.textWidth() - 2) // -2 for padding
265+ return formatter.String()
264266 })
265267}
266268
@@ -446,38 +448,6 @@ func (sr sourcegraphRenderer) Render(v *toolCallCmp) string {
446448 })
447449}
448450
449−// -----------------------------------------------------------------------------
450−// Patch renderer
451−// -----------------------------------------------------------------------------
452−
453−// patchRenderer handles multi-file patches with change summaries
454−type patchRenderer struct {
455− baseRenderer
456−}
457−
458−// Render displays patch summary with file count and change statistics
459−func (pr patchRenderer) Render(v *toolCallCmp) string {
460− var params tools.PatchParams
461− if err := pr.unmarshalParams(v.call.Input, &params); err != nil {
462− return pr.renderError(v, "Invalid patch parameters")
463− }
464−
465− args := newParamBuilder().addMain("multiple files").build()
466−
467− return pr.renderWithParams(v, "Patch", args, func() string {
468− var meta tools.PatchResponseMetadata
469− if err := pr.unmarshalParams(v.result.Metadata, &meta); err != nil {
470− return renderPlainContent(v, v.result.Content)
471− }
472−
473− summary := fmt.Sprintf("Changed %d files (%d+ %d-)",
474− len(meta.FilesChanged), meta.Additions, meta.Removals)
475− filesList := strings.Join(meta.FilesChanged, "\n")
476−
477− return renderPlainContent(v, summary+"\n\n"+filesList)
478− })
479−}
480−
481451// -----------------------------------------------------------------------------
482452// Diagnostics renderer
483453// -----------------------------------------------------------------------------
@@ -711,8 +681,6 @@ func prettifyToolName(name string) string {
711681 return "View"
712682 case tools.WriteToolName:
713683 return "Write"
714− case tools.PatchToolName:
715− return "Patch"
716684 default:
717685 return name
718686 }
internal/tui/components/core/helpers.go+11
@@ -4,6 +4,8 @@ import (
44 "image/color"
55 "strings"
66
7+ "github.com/alecthomas/chroma/v2"
8+ "github.com/charmbracelet/crush/internal/exp/diffview"
79 "github.com/charmbracelet/crush/internal/tui/styles"
810 "github.com/charmbracelet/lipgloss/v2"
911 "github.com/charmbracelet/x/ansi"
@@ -144,3 +146,12 @@ func SelectableButtons(buttons []ButtonOpts, spacing string) string {
144146
145147 return lipgloss.JoinHorizontal(lipgloss.Left, parts...)
146148}
149+
150+func DiffFormatter() *diffview.DiffView {
151+ formatDiff := diffview.New()
152+ style := chroma.MustNewStyle("crush", styles.GetChromaTheme())
153+ diff := formatDiff.
154+ SyntaxHightlight(true).
155+ ChromaStyle(style)
156+ return diff
157+}
internal/tui/components/dialogs/permissions/permissions.go+6−19
@@ -267,24 +267,13 @@ func (p *permissionDialogCmp) renderBashContent() string {
267267
268268func (p *permissionDialogCmp) renderEditContent() string {
269269 if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok {
270− diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) {
271− return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width()))
272− })
273−
274− contentHeight := min(p.height-9, lipgloss.Height(diff))
275− p.contentViewPort.SetHeight(contentHeight)
276− p.contentViewPort.SetContent(diff)
277− return p.styleViewport()
278− }
279− return ""
280−}
281−
282−func (p *permissionDialogCmp) renderPatchContent() string {
283− if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok {
284− diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) {
285− return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width()))
286− })
270+ formatter := core.DiffFormatter().
271+ Before(fileutil.PrettyPath(pr.FilePath), pr.OldContent).
272+ After(fileutil.PrettyPath(pr.FilePath), pr.NewContent).
273+ Width(p.contentViewPort.Width()).
274+ Split()
287275
276+ diff := formatter.String()
288277 contentHeight := min(p.height-9, lipgloss.Height(diff))
289278 p.contentViewPort.SetHeight(contentHeight)
290279 p.contentViewPort.SetContent(diff)
@@ -381,8 +370,6 @@ func (p *permissionDialogCmp) render() string {
381370 contentFinal = p.renderBashContent()
382371 case tools.EditToolName:
383372 contentFinal = p.renderEditContent()
384− case tools.PatchToolName:
385− contentFinal = p.renderPatchContent()
386373 case tools.WriteToolName:
387374 contentFinal = p.renderWriteContent()
388375 case tools.FetchToolName: