Skip to content

Commit

Permalink
1.0.70 (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
acharneski authored May 14, 2024
1 parent 34d2dda commit b91c89a
Show file tree
Hide file tree
Showing 5 changed files with 1,528 additions and 96 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Gradle Releases -> https://github.com/gradle/gradle/releases
libraryGroup = com.simiacryptus.skyenet
libraryVersion = 1.0.69
libraryVersion = 1.0.70
gradleVersion = 7.6.1
96 changes: 56 additions & 40 deletions webui/src/main/kotlin/com/simiacryptus/diff/IterativePatchUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ object IterativePatchUtil {
enum class LineType { CONTEXT, ADD, DELETE }
class LineRecord(
val index: Int,
val line: String,
val line: String?,
var previousLine: LineRecord? = null,
var nextLine: LineRecord? = null,
var matchingLine: LineRecord? = null,
Expand All @@ -26,6 +26,15 @@ object IterativePatchUtil {
}
}

/**
* Normalizes a line by removing all whitespace.
* @param line The line to normalize.
* @return The normalized line.
*/
private fun normalizeLine(line: String): String {
return line.replace("\\s".toRegex(), "")
}

/**
* Applies a patch to the given source text.
* @param source The original text.
Expand All @@ -45,7 +54,7 @@ object IterativePatchUtil {

// Step 3: Establish a distance metric for matches based on Levenshtein distance and distance to established links.
// Use this to establish the links based on a shortest-first policy and iterate until no more good matches are found.
linkByLevenshteinDistance(sourceLines, patchLines)
// linkByLevenshteinDistance(sourceLines, patchLines)

// Generate the patched text using the established links
return generatePatchedTextUsingLinks(sourceLines, patchLines)
Expand All @@ -70,30 +79,30 @@ object IterativePatchUtil {
// Process the rest of the lines
while (sourceLineBuffer.isNotEmpty()) {
// Copy all lines until the next matched line
sourceLineBuffer.takeWhile { it.matchingLine == null }.toTypedArray().forEach {
sourceLineBuffer.remove(it)
patchedTextBuilder.appendLine(it.line)
}
if (sourceLineBuffer.isEmpty()) break
val codeLine = sourceLineBuffer.removeFirst()
var patchLine = codeLine.matchingLine!!
when (patchLine.type) {
LineType.DELETE -> { /* Skip adding the line */
}

LineType.CONTEXT -> patchedTextBuilder.appendLine(codeLine.line)
LineType.ADD -> {
// This should not happen as ADD lines should not be matched to source lines
throw IllegalStateException("ADD line is matched to source line")
when {
codeLine.matchingLine == null -> {
// If the line is not matched and is adjacent to a non-matched line, add it as a context line
if(codeLine.nextLine?.matchingLine == null || codeLine.previousLine?.matchingLine == null) {
patchedTextBuilder.appendLine(codeLine.line)
}
}
codeLine.matchingLine!!.type == LineType.DELETE -> null // Skip adding the line
codeLine.matchingLine!!.type == LineType.CONTEXT -> patchedTextBuilder.appendLine(codeLine.line)
codeLine.matchingLine!!.type == LineType.ADD -> throw IllegalStateException("ADD line is matched to source line")
}

// Add lines marked as ADD in the patch following the current matched line
while (patchLine.nextLine?.type == LineType.ADD) {
patchedTextBuilder.appendLine(patchLine.nextLine?.line)
patchLine = patchLine.nextLine!!
var nextPatchLine = codeLine.matchingLine?.nextLine
while (nextPatchLine != null && nextPatchLine.matchingLine == null) {
when(nextPatchLine.type) {
LineType.ADD -> patchedTextBuilder.appendLine(nextPatchLine.line)
LineType.CONTEXT -> patchedTextBuilder.appendLine(nextPatchLine.line)
LineType.DELETE -> null // Skip adding the line
}
nextPatchLine = nextPatchLine.nextLine
}
}

return patchedTextBuilder.toString().trimEnd()
}

Expand All @@ -103,13 +112,13 @@ object IterativePatchUtil {
* @param patchLines The patch lines.
*/
private fun linkUniqueMatchingLines(sourceLines: List<LineRecord>, patchLines: List<LineRecord>) {
val sourceLineMap = sourceLines.groupBy { it.line.trim() }
val sourceLineMap = sourceLines.groupBy { normalizeLine(it.line!!) }
val patchLineMap = patchLines.filter {
when (it.type) {
LineType.ADD -> false // ADD lines are not matched to source lines
else -> true
}
}.groupBy { it.line.trim() }
}.groupBy { normalizeLine(it.line!!) }

sourceLineMap.keys.intersect(patchLineMap.keys).forEach { key ->
val sourceLine = sourceLineMap[key]?.singleOrNull()
Expand Down Expand Up @@ -139,24 +148,28 @@ object IterativePatchUtil {
while (patchPrev.type == LineType.ADD && patchPrev.previousLine != null) {
patchPrev = patchPrev.previousLine!!
}
if (sourcePrev.line.trim() == patchPrev.line.trim() && sourcePrev.matchingLine == null && patchPrev.matchingLine == null) {
sourcePrev.matchingLine = patchPrev
patchPrev.matchingLine = sourcePrev
foundMatch = true
if (normalizeLine(sourcePrev.line!!) == normalizeLine(patchPrev.line!!) && sourcePrev.matchingLine == null && patchPrev.matchingLine == null) {
if (sourcePrev.line.trim() == patchPrev.line!!.trim() && sourcePrev.matchingLine == null && patchPrev.matchingLine == null) {
sourcePrev.matchingLine = patchPrev
patchPrev.matchingLine = sourcePrev
foundMatch = true
}
}
}

// Check the next line for a potential match
if (sourceLine.nextLine != null && patchLine.nextLine != null) {
val sourceNext = sourceLine.nextLine!!
var patchNext = patchLine.nextLine!!
while (patchNext.type == LineType.ADD && patchNext.nextLine != null) {
patchNext = patchNext.nextLine!!
}
if (sourceNext.line.trim() == patchNext.line.trim() && sourceNext.matchingLine == null && patchNext.matchingLine == null) {
sourceNext.matchingLine = patchNext
patchNext.matchingLine = sourceNext
foundMatch = true
// Check the next line for a potential match
if (sourceLine.nextLine != null && patchLine.nextLine != null) {
val sourceNext = sourceLine.nextLine!!
var patchNext = patchLine.nextLine!!
while (patchNext.type == LineType.ADD && patchNext.nextLine != null) {
patchNext = patchNext.nextLine!!
}
if (normalizeLine(sourceNext.line!!) == normalizeLine(patchNext.line!!) && sourceNext.matchingLine == null && patchNext.matchingLine == null) {
if (sourceNext.line.trim() == patchNext.line!!.trim() && sourceNext.matchingLine == null && patchNext.matchingLine == null) {
sourceNext.matchingLine = patchNext
patchNext.matchingLine = sourceNext
foundMatch = true
}
}
}
}
}
Expand Down Expand Up @@ -189,7 +202,7 @@ object IterativePatchUtil {
if (patchLine.matchingLine != null) continue // Skip lines that already have matches

// Calculate the Levenshtein distance between unmatched source and patch lines
val distance = levenshteinDistance.apply(sourceLine.line.trim(), patchLine.line.trim())
val distance = levenshteinDistance.apply(normalizeLine(sourceLine.line!!), normalizeLine(patchLine.line!!))
if (distance <= maxDistance) {
// Consider proximity to established links as a secondary factor
val proximity = calculateProximityDistance(sourceLine, patchLine)
Expand Down Expand Up @@ -287,6 +300,9 @@ object IterativePatchUtil {
LineRecord(
index = index, line = line.let {
when {
it.trimStart().startsWith("+++") -> null
it.trimStart().startsWith("---") -> null
it.trimStart().startsWith("@@") -> null
it.trimStart().startsWith("+") -> it.trimStart().substring(1)
it.trimStart().startsWith("-") -> it.trimStart().substring(1)
else -> it
Expand All @@ -297,6 +313,6 @@ object IterativePatchUtil {
else -> LineType.CONTEXT
}
)
})
}.filter { it.line != null })

}
31 changes: 1 addition & 30 deletions webui/src/main/resources/application/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,35 +306,7 @@ document.addEventListener('DOMContentLoaded', () => {
setInterval(() => {
applyToAllSvg();
}, 5000); // Adjust the interval as needed

// Set the initial active tab after the DOM is fully loaded
document.querySelectorAll('.tabs-container').forEach(tabsContainer => {
const firstButton = tabsContainer.querySelector('.tab-button');
if (firstButton) {
firstButton.click();
}
});

// Ensure all tabs are processed even if they are not initially displayed
document.querySelectorAll('.tab-content').forEach(content => {
if (!content.classList.contains('active')) {
content.style.display = 'none';
}
});
// Ensure nested tabs are updated when new content is added dynamically
document.querySelectorAll('.tabs-container').forEach(tabsContainer => {
updateNestedTabs(tabsContainer);
});
// Ensure tabs are updated when new content is added dynamically
const observer = new MutationObserver(() => {
document.querySelectorAll('.tabs-container').forEach(tabsContainer => {
const firstButton = tabsContainer.querySelector('.tab-button');
if (firstButton) {
firstButton.click();
}
});
});
observer.observe(document.body, { childList: true, subtree: true });

function setTheme(theme) {
document.getElementById('theme_style').href = theme + '.css';
localStorage.setItem('theme', theme);
Expand Down Expand Up @@ -366,7 +338,6 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementById('theme_style').href = savedTheme + '.css';
}


const historyElement = document.getElementById('history');
if (historyElement) historyElement.addEventListener('click', () => showModal('sessions'));
const settingsElement = document.getElementById('settings');
Expand Down
64 changes: 40 additions & 24 deletions webui/src/main/resources/application/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,63 @@ function updateTabs() {
event.stopPropagation();
const forTab = button.getAttribute('data-for-tab');
let tabsParent = button.closest('.tabs-container');
tabsParent.querySelectorAll('.tab-button').forEach(tabButton => tabButton.classList.remove('active'));
tabsParent.querySelectorAll('.tab-button').forEach(tabButton => {
if (tabButton.closest('.tabs-container') === tabsParent) tabButton.classList.remove('active')
});
button.classList.add('active');
let selectedContent = null;
tabsParent.querySelectorAll('.tab-content').forEach(content => {
const contentParent = content.closest('.tabs-container');
if (contentParent === tabsParent) {
if (content.closest('.tabs-container') === tabsParent) {
if (content.getAttribute('data-tab') === forTab) {
content.classList.add('active');
content.style.display = 'block'; // Ensure the content is displayed
content.style.display = 'block'; // Ensure the content is displayed
selectedContent = content;
} else {
content.classList.remove('active')
content.style.display = 'none'; // Ensure the content is hidden
content.style.display = 'none'; // Ensure the content is hidden
}
}
});
// Ensure nested tabs are updated
updateNestedTabs(tabsParent);
if (selectedContent !== null) updateNestedTabs(selectedContent);
})
});
}

function updateNestedTabs(tabsParent) {
tabsParent.querySelectorAll('.tab-content .tabs-container').forEach(nestedTabsContainer => {
const firstNestedButton = nestedTabsContainer.querySelector('.tab-button');
if (firstNestedButton) {
firstNestedButton.click();
function updateNestedTabs(element) {
element.querySelectorAll('.tabs-container').forEach(tabsContainer => {
try {
let hasActiveButton = false;
tabsContainer.querySelectorAll('.tab-button').forEach(nestedButton => {
if (nestedButton.classList.contains('active')) {
hasActiveButton = true;
}
});
if (!hasActiveButton) {
/* Determine if a tab-content element in this tabs-container has the active class. If so, use its data-tab value to find the matching button and ensure it is marked active */
const activeContent = tabsContainer.querySelector('.tab-content.active');
if (activeContent) {
const activeTab = activeContent.getAttribute('data-tab');
const activeButton = tabsContainer.querySelector(`.tab-button[data-for-tab="${activeTab}"]`);
if (activeButton !== null) {
activeButton.classList.add('active');
}
} else {
/* Add 'active' to the class list of the first button */
const firstButton = tabsContainer.querySelector('.tab-button');
if (firstButton !== null) {
firstButton.classList.add('active');
}
}
}
} catch (e) {
console.log("Error updating tabs: " + e);
}
});
}

document.addEventListener('DOMContentLoaded', () => {
try {
updateTabs();
// Set the initial active tab
document.querySelectorAll('.tabs-container').forEach(tabsContainer => {
const firstButton = tabsContainer.querySelector('.tab-button');
if (firstButton) {
firstButton.click();
}
});
} catch (e) {
console.log("Error updating tabs: " + e);
}
updateTabs();
updateNestedTabs(document);
});

window.updateTabs = updateTabs; // Expose updateTabs to the global scope
Loading

0 comments on commit b91c89a

Please sign in to comment.