Skip to content

Commit

Permalink
Navigator: Sort files and folders alphanumerically
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadelessFox committed Sep 25, 2023
1 parent 5e83d91 commit 829f299
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.shade.decima.ui.navigator.NavigatorPath;
import com.shade.decima.ui.navigator.NavigatorSettings;
import com.shade.platform.model.runtime.ProgressMonitor;
import com.shade.platform.model.util.AlphanumericComparator;
import com.shade.util.NotNull;
import com.shade.util.Nullable;

Expand All @@ -13,7 +14,7 @@
public class NavigatorFolderNode extends NavigatorNode {
private static final Comparator<NavigatorNode> CHILDREN_COMPARATOR = Comparator
.comparingInt((NavigatorNode node) -> node instanceof NavigatorFolderNode ? -1 : 1)
.thenComparing(NavigatorNode::getLabel);
.thenComparing(NavigatorNode::getLabel, AlphanumericComparator.getInstance());

private final FilePath path;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.shade.platform.model.util;

import com.shade.util.NotNull;

import java.util.Comparator;

public class AlphanumericComparator implements Comparator<CharSequence> {
private static final AlphanumericComparator INSTANCE = new AlphanumericComparator();

private AlphanumericComparator() {
// prevents instantiation
}

@NotNull
public static AlphanumericComparator getInstance() {
return INSTANCE;
}

@Override
public int compare(CharSequence o1, CharSequence o2) {
final int len1 = o1.length();
final int len2 = o2.length();

int i = 0;
int j = 0;

while (i < len1 && j < len2) {
final char ch1 = o1.charAt(i);
final char ch2 = o2.charAt(i);

if (Character.isDigit(ch1) && Character.isDigit(ch2)) {
int num1 = 0;
int num2 = 0;

while (i < len1 && Character.isDigit(o1.charAt(i))) {
num1 = num1 * 10 + Character.digit(o1.charAt(i), 10);
i += 1;
}

while (j < len2 && Character.isDigit(o2.charAt(j))) {
num2 = num2 * 10 + Character.digit(o2.charAt(j), 10);
j += 1;
}

if (num1 != num2) {
return num1 - num2;
}
} else {
if (ch1 != ch2) {
return ch1 - ch2;
}

i += 1;
j += 1;
}
}

return len1 - len2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.shade.platform.util;

import com.shade.platform.model.util.AlphanumericComparator;
import com.shade.util.NotNull;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class AlphanumericComparatorTest {
@Test
public void alphanumericComparatorTest() {
alphanumericComparatorTestImpl(
List.of("img12", "img10", "img2", "img1", "img100_1", "img100_11", "img100", "img100_10", "img100_5"),
List.of("img1", "img2", "img10", "img12", "img100", "img100_1", "img100_5", "img100_10", "img100_11")
);

alphanumericComparatorTestImpl(
List.of("file1000", "file100", "file10", "file2", "file1", "file11", "file200", "file20", "file2a", "file2b"),
List.of("file1", "file2", "file2a", "file2b", "file10", "file11", "file20", "file100", "file200", "file1000")
);

alphanumericComparatorTestImpl(
List.of("doc10", "doc2", "doc20", "doc1", "doc3", "doc15", "doc4"),
List.of("doc1", "doc2", "doc3", "doc4", "doc10", "doc15", "doc20")
);

alphanumericComparatorTestImpl(
List.of("page2", "page12", "page3", "page22", "page4", "page13", "page23"),
List.of("page2", "page3", "page4", "page12", "page13", "page22", "page23")
);

alphanumericComparatorTestImpl(
List.of("item-5", "item-1", "item-10", "item-2", "item-11", "item-3", "item-20", "item-15"),
List.of("item-1", "item-2", "item-3", "item-5", "item-10", "item-11", "item-15", "item-20")
);

alphanumericComparatorTestImpl(
List.of("abc123def45", "abc12def345", "abc1234def5", "abc12345def4", "abc1234def45", "abc12345def456"),
List.of("abc12def345", "abc123def45", "abc1234def5", "abc1234def45", "abc12345def4", "abc12345def456")
);

alphanumericComparatorTestImpl(
List.of("file01_v2", "file02_v1", "file10_v10", "file02_v10", "file10_v2", "file1_v10"),
List.of("file01_v2", "file1_v10", "file02_v1", "file02_v10", "file10_v2", "file10_v10")
);

alphanumericComparatorTestImpl(
List.of("chapter-2.1.1", "chapter-10.1.1", "chapter-2.1.10", "chapter-10.1.2", "chapter-2.1.2"),
List.of("chapter-2.1.1", "chapter-2.1.2", "chapter-2.1.10", "chapter-10.1.1", "chapter-10.1.2")
);

alphanumericComparatorTestImpl(
List.of("item_1_2_3", "item_2_1_3", "item_1_10_3", "item_2_2_1", "item_1_2_10", "item_2_1_10", "item_1_10_1"),
List.of("item_1_2_3", "item_1_2_10", "item_1_10_1", "item_1_10_3", "item_2_1_3", "item_2_1_10", "item_2_2_1")
);
}

private void alphanumericComparatorTestImpl(
@NotNull Collection<? extends CharSequence> input,
@NotNull Collection<? extends CharSequence> expected
) {
final ArrayList<? extends CharSequence> sorted = new ArrayList<>(input);
sorted.sort(AlphanumericComparator.getInstance());

Assertions.assertEquals(expected, sorted);
}
}

0 comments on commit 829f299

Please sign in to comment.