mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-29 13:16:50 -06:00
formula: same_name folds case without merging ı and i
Lower-casing then upper-casing made dotless ı equal to i (both become I), which Unicode's default case folding keeps apart; LET(i,1,ı,2,i) could return the ı binding. same_name now lower-cases and adds the folds lower case misses (ß/ẞ -> ss, ſ -> s, ς -> σ). Tests cover ı/i and the Greek final sigma.
This commit is contained in:
@@ -606,6 +606,9 @@ fn let_lambda_names_ignore_case_in_any_script() {
|
||||
// `ß` upper-cases to `SS`, yet `ẞ` is its capital.
|
||||
t.set("A6", "=LET(ß,100,ẞ*2)");
|
||||
assert_eq!(t.num("A6"), 200.0);
|
||||
// Dotless ı is a different name from i.
|
||||
t.set("A7", "=LET(i,1,ı,2,i)");
|
||||
assert_eq!(t.num("A7"), 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -16,10 +16,21 @@ pub use parser::{MAX_FORMULA_LEN, ParseError, normalize_function_name, parse};
|
||||
pub use printer::{print, print_r1c1, quote_sheet};
|
||||
|
||||
/// Whether two LET/LAMBDA names are the same: case-insensitive in any script, as in Excel
|
||||
/// (`dług` = `DŁUG`, `ß` = `ẞ`). Each character is lower-cased, then upper-cased, so letters whose
|
||||
/// upper case is not one character (`ß` -> `SS`) still match their capital.
|
||||
/// (`dług` = `DŁUG`, `ß` = `ẞ`). Close to Unicode's default case folding: lower case, plus the
|
||||
/// folds lower-casing misses for letters a name may hold (`ß`/`ẞ` -> `ss`, `ſ` -> `s`, `ς` -> `σ`).
|
||||
/// Dotless `ı` stays distinct from `i`, as outside Turkic languages.
|
||||
pub fn same_name(a: &str, b: &str) -> bool {
|
||||
let fold = |s: &str| s.chars().flat_map(char::to_lowercase).flat_map(char::to_uppercase).collect::<String>();
|
||||
let fold = |s: &str| -> String {
|
||||
s.chars()
|
||||
.flat_map(char::to_lowercase)
|
||||
.flat_map(|c| match c {
|
||||
'ß' => ['s', 's'].into_iter().take(2),
|
||||
'ſ' => ['s', 's'].into_iter().take(1),
|
||||
'ς' => ['σ', 'σ'].into_iter().take(1),
|
||||
c => [c, c].into_iter().take(1),
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
a == b || fold(a) == fold(b)
|
||||
}
|
||||
|
||||
|
||||
@@ -105,5 +105,10 @@ fn local_names_match_aliases_in_any_case_like_the_evaluator() {
|
||||
assert_eq!(input("LET(ſi;LAMBDA(x;x*2);SI(3))"), "LET(ſi,LAMBDA(x,x*2),SI(3))");
|
||||
assert!(gridcraft_formula::same_name("ß", "ẞ"));
|
||||
assert!(gridcraft_formula::same_name("dług", "DŁUG"));
|
||||
assert!(gridcraft_formula::same_name("ſi", "SI"));
|
||||
assert!(gridcraft_formula::same_name("σοφός", "ΣΟΦΌΣ"));
|
||||
// Dotless ı is its own letter outside Turkic languages.
|
||||
assert!(!gridcraft_formula::same_name("ı", "i"));
|
||||
assert!(!gridcraft_formula::same_name("ı", "I"));
|
||||
assert!(!gridcraft_formula::same_name("a", "b"));
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ workbooks; results checked in as data, not Excel files) and fixing what it finds
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-19 | minor | LET and LAMBDA names compare case-insensitively in any script, as in Excel: `=LET(dług,100,DŁUG*2)` is 200 (was #NAME?); also LET-bound lambdas called or passed by name (`żar(2)`, `MAP(…,Λ)`), `ISOMITTED`, and formula-bar alias translation (one shared `gridcraft_formula::same_name`, which also matches `ß` with `ẞ`) |
|
||||
| 2026-10-19 | minor | LET and LAMBDA names compare case-insensitively in any script, as in Excel: `=LET(dług,100,DŁUG*2)` is 200 (was #NAME?); also LET-bound lambdas called or passed by name (`żar(2)`, `MAP(…,Λ)`), `ISOMITTED`, and formula-bar alias translation (one shared `gridcraft_formula::same_name`, which matches `ß` with `ẞ` and keeps dotless `ı` apart from `i`) |
|
||||
| 2026-10-15 | minor | MEDIAN and AGGREGATE median use an overflow-safe midpoint (#1579); regressions cover finite extremes, tiny values and dependent recalculation |
|
||||
| 2026-10-13 | minor | Clear reports changed stored cells sparsely, including those beyond the first million coordinates; dependent formulas and removed spills update, while clearing empty merges still unblocks spills (#1032) |
|
||||
| 2026-10-12 | minor | USDOLLAR added as a Compatibility function (not on Microsoft's list, so the counts don't change); MIRR with no positive flow is -1, COUNTIF's bare `"<="` / `">="` skip empty strings, INDIRECT with `a1` = FALSE gives `#REF!` for A1-style text (#738) |
|
||||
|
||||
Reference in New Issue
Block a user