From 3c5b8f7ae67e7d61b1b9ef80f74bc88fa5990c09 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Sat, 6 Aug 2022 03:07:32 +0200 Subject: [PATCH] Fixed multiple lines shown in changed lines Also fixed copying not copying line endings of unchanged lines --- .../kotlin/app/extensions/StringExtensions.kt | 2 +- .../kotlin/app/git/diff/HunkDiffGenerator.kt | 10 ++- src/main/kotlin/app/ui/Diff.kt | 62 ++++++++++++------- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/app/extensions/StringExtensions.kt b/src/main/kotlin/app/extensions/StringExtensions.kt index 75a3000..918ed69 100644 --- a/src/main/kotlin/app/extensions/StringExtensions.kt +++ b/src/main/kotlin/app/extensions/StringExtensions.kt @@ -30,7 +30,7 @@ val String.dirPath: String this } -fun String.removeLineEndings(): String { +fun String.removeLineDelimiters(): String { return this.removeSuffix("\n") .removeSuffix("\r\n") } diff --git a/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt b/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt index 84baa83..649fe25 100644 --- a/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt +++ b/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt @@ -117,7 +117,15 @@ class HunkDiffGenerator @AssistedInject constructor( while (oldCurrentLine < oldEndLine || newCurrentLine < newEndLine) { if (oldCurrentLine < curEdit.beginA || endIdx + 1 < curIdx) { - val lineText = oldRawText.lineAt(oldCurrentLine) + var lineText = oldRawText.lineAt(oldCurrentLine) + + if( + oldCurrentLine < oldRawText.size() - 1 || // If it's not the last + (oldCurrentLine == oldRawText.size() - 1 && !oldRawText.isMissingNewlineAtEnd) // Or is the last and contains new line at the end + ) { + lineText += oldRawText.lineDelimiter.orEmpty() + } + lines.add(Line(lineText, oldCurrentLine, newCurrentLine, LineType.CONTEXT)) oldCurrentLine++ diff --git a/src/main/kotlin/app/ui/Diff.kt b/src/main/kotlin/app/ui/Diff.kt index 5220b88..9f710e3 100644 --- a/src/main/kotlin/app/ui/Diff.kt +++ b/src/main/kotlin/app/ui/Diff.kt @@ -22,8 +22,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.input.key.Key -import androidx.compose.ui.input.key.key import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon @@ -33,7 +31,8 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import app.extensions.removeLineEndings +import app.extensions.lineDelimiter +import app.extensions.removeLineDelimiters import app.extensions.toStringWithSpaces import app.git.DiffEntryType import app.git.EntryContent @@ -84,7 +83,9 @@ fun Diff( } ) { when (viewDiffResult) { - ViewDiffResult.DiffNotFound -> { onCloseDiffView() } + ViewDiffResult.DiffNotFound -> { + onCloseDiffView() + } is ViewDiffResult.Loaded -> { val diffEntryType = viewDiffResult.diffEntryType val diffEntry = viewDiffResult.diffResult.diffEntry @@ -143,7 +144,8 @@ fun NonTextDiff(diffResult: DiffResult.NonText) { if (showOldAndNew) { Column( - modifier = Modifier.weight(0.5f) + modifier = Modifier + .weight(0.5f) .padding(start = 24.dp, end = 8.dp, top = 24.dp, bottom = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -151,7 +153,8 @@ fun NonTextDiff(diffResult: DiffResult.NonText) { SideDiff(oldBinaryContent) } Column( - modifier = Modifier.weight(0.5f) + modifier = Modifier + .weight(0.5f) .padding(start = 8.dp, end = 24.dp, top = 24.dp, bottom = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -160,14 +163,16 @@ fun NonTextDiff(diffResult: DiffResult.NonText) { } } else if (oldBinaryContent != EntryContent.Missing) { Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() .padding(all = 24.dp), ) { SideDiff(oldBinaryContent) } } else if (newBinaryContent != EntryContent.Missing) { Column( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() .padding(all = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -303,7 +308,7 @@ fun HunkHeader( color = MaterialTheme.colors.stageButton } - if(diffEntryType is DiffEntryType.UnstagedDiff) { + if (diffEntryType is DiffEntryType.UnstagedDiff) { SecondaryButton( text = "Discard hunk", backgroundButton = MaterialTheme.colors.error, @@ -436,18 +441,33 @@ fun DiffLine( ) } - Text( - text = line.text.replace( // TODO this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615 - "\t", - " " - ).removeLineEndings(), - modifier = Modifier - .padding(start = 8.dp) - .fillMaxSize(), - fontFamily = FontFamily.Monospace, - style = MaterialTheme.typography.body2, - overflow = TextOverflow.Visible, - ) + Row { + Text( + text = line.text.replace( // TODO this replace is a workaround until this issue gets fixed https://github.com/JetBrains/compose-jb/issues/615 + "\t", + " " + ).removeLineDelimiters(), + modifier = Modifier + .padding(start = 8.dp) + .fillMaxSize(), + fontFamily = FontFamily.Monospace, + style = MaterialTheme.typography.body2, + overflow = TextOverflow.Visible, + ) + + val lineDelimiter = line.text.lineDelimiter + + // Display line delimiter in its own text with a maxLines = 1. This will fix the issue + // where copying a line didn't contain the line ending & also fix the issue where the text line would + // display multiple lines even if there is only a single line with a line delimiter at the end + if(lineDelimiter != null) { + Text( + text = lineDelimiter, + maxLines = 1, + ) + } + + } } }