36 lines
1.1 KiB
Dart
36 lines
1.1 KiB
Dart
/// Letters of an A–Z index; names that don't start with a letter go under `#`.
|
||
final indexLetters = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), '#'];
|
||
|
||
const _accented = 'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝŸ';
|
||
const _unaccented = 'AAAAAACEEEEIIIINOOOOOUUUUYY';
|
||
|
||
/// Uppercase without accents, so "Émile" sorts and indexes under E.
|
||
String _fold(String name) {
|
||
return [
|
||
for (final char in name.trim().toUpperCase().split(''))
|
||
switch (_accented.indexOf(char)) {
|
||
-1 => char,
|
||
final index => _unaccented[index],
|
||
},
|
||
].join();
|
||
}
|
||
|
||
String indexLetterOf(String name) {
|
||
final folded = _fold(name);
|
||
if (folded.isEmpty) return '#';
|
||
|
||
final first = folded[0];
|
||
return indexLetters.contains(first) ? first : '#';
|
||
}
|
||
|
||
/// A–Z regardless of case and accents, with the `#` names last.
|
||
int compareByIndex(String a, String b) {
|
||
final byLetter = indexLetters
|
||
.indexOf(indexLetterOf(a))
|
||
.compareTo(indexLetters.indexOf(indexLetterOf(b)));
|
||
if (byLetter != 0) return byLetter;
|
||
|
||
final byName = _fold(a).compareTo(_fold(b));
|
||
return byName != 0 ? byName : a.compareTo(b);
|
||
}
|