package editor import ( "testing" "glint/internal/spell" "glint/internal/theme" ) // grammarSpans returns, for each Wavy span in the built visual model, its text // mapped to its undercurl color — enough to tell grammar (green) from spell (red). func grammarSpans(e *Editor) map[string]string { got := map[string]string{} for _, vr := range e.buildVisual() { for _, sp := range vr.spans { if sp.Wavy { got[sp.Text] = string(sp.UnderColor) } } } return got } func grammarEditor(t *testing.T, content string) *Editor { t.Helper() e := New() e.SetTheme(theme.FlexokiDark()) e.SetContent([]byte(content)) e.SetGrammar(true) return e } func TestGrammarUnderlinesRange(t *testing.T) { e := grammarEditor(t, "This is a a test") // "a a" spans rune columns [8,11). e.SetGrammarDiags(map[int][][2]int{0: {{8, 11}}}) green := string(theme.FlexokiDark().Grammar) spans := grammarSpans(e) if spans["a a"] != green { t.Errorf("expected \"a a\" underlined green (%s); got wavy spans %v", green, spans) } } func TestGrammarInactiveWhenOff(t *testing.T) { e := grammarEditor(t, "This is a a test") e.SetGrammarDiags(map[int][][2]int{0: {{8, 11}}}) e.SetGrammar(false) if s := grammarSpans(e); len(s) != 0 { t.Errorf("grammar off should render no undercurl; got %v", s) } } func TestGrammarInactiveOnCodeFile(t *testing.T) { e := grammarEditor(t, "This is a a test") e.SetLanguage("main.go") // code file: grammar skipped like spellcheck e.SetGrammarDiags(map[int][][2]int{0: {{8, 11}}}) if s := grammarSpans(e); len(s) != 0 { t.Errorf("grammar should skip code files; got %v", s) } } // TestSpellingWinsOverGrammar asserts a misspelled word inside a grammar range // keeps its red spell underline rather than being repainted green. func TestSpellingWinsOverGrammar(t *testing.T) { d, err := spell.Load() if err != nil { t.Fatalf("spell.Load: %v", err) } e := New() e.SetTheme(theme.FlexokiDark()) e.SetContent([]byte("This recieve is wrong")) e.SetDict(d) e.SetSpell(true) e.SetGrammar(true) // "recieve" is a misspelling at rune columns [5,12); cover it with a grammar range. e.SetGrammarDiags(map[int][][2]int{0: {{5, 12}}}) spans := grammarSpans(e) red := string(theme.FlexokiDark().Spell) if spans["recieve"] != red { t.Errorf("misspelled \"recieve\" should stay red (%s), not grammar green; got %v", red, spans) } }