@@ -36,7 +36,23 @@ function sort.sort_text(a, b)
36
36
return a .sortText < b .sortText
37
37
end
38
38
39
+ --- Swaps the case of a single character at index i in string s
40
+ --- @param s string
41
+ --- @param i integer
42
+ --- @return integer
43
+ local function swap_case (s , i )
44
+ local byte = string.byte (s , i )
45
+ if byte >= 65 and byte <= 90 then -- uppercase A-Z
46
+ return byte + 32 -- convert to lowercase
47
+ elseif byte >= 97 and byte <= 122 then -- lowercase a-z
48
+ return byte - 32 -- convert to uppercase
49
+ else
50
+ return byte -- non-alphabetic characters
51
+ end
52
+ end
53
+
39
54
function sort .label (a , b )
55
+ -- prefer foo_bar over _foo_bar
40
56
local _ , entry1_under = a .label :find (' ^_+' )
41
57
local _ , entry2_under = b .label :find (' ^_+' )
42
58
entry1_under = entry1_under or 0
@@ -46,7 +62,17 @@ function sort.label(a, b)
46
62
elseif entry1_under < entry2_under then
47
63
return true
48
64
end
49
- return a .label < b .label
65
+
66
+ -- prefer "a" over "A" and "a" over "b"
67
+ -- Compare characters one by one with case flipping
68
+ for i = 1 , math.min (# a .label , # b .label ) do
69
+ local char_a = swap_case (a .label , i )
70
+ local char_b = swap_case (b .label , i )
71
+
72
+ if char_a ~= char_b then return char_a < char_b end
73
+ end
74
+
75
+ if # a .label ~= # b .label then return # a .label < # b .label end
50
76
end
51
77
52
78
return sort
0 commit comments