72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
||
package spellcheck
|
||
|
||
import (
|
||
"os"
|
||
"strings"
|
||
"unicode"
|
||
"unicode/utf8"
|
||
)
|
||
|
||
// Language uses the effective session message locale, with no English fallback.
|
||
// LANGUAGE is a translation fallback list, not the session's regional locale.
|
||
func Language() string {
|
||
for _, name := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} {
|
||
if value := os.Getenv(name); value != "" {
|
||
return language_tag(value)
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func language_tag(value string) string {
|
||
value, _, _ = strings.Cut(strings.TrimSpace(value), ".")
|
||
value, _, _ = strings.Cut(value, "@")
|
||
if value == "C" || value == "POSIX" {
|
||
return ""
|
||
}
|
||
value = strings.ReplaceAll(value, "-", "_")
|
||
for _, char := range value {
|
||
if !unicode.IsLetter(char) && char != '_' {
|
||
return ""
|
||
}
|
||
}
|
||
return value
|
||
}
|
||
|
||
// Word strips surrounding prose punctuation but leaves structured terminal
|
||
// tokens intact so they can be excluded rather than checked as fragments.
|
||
func Word(value string) string {
|
||
value = strings.TrimSpace(value)
|
||
if strings.HasPrefix(value, "-") || strings.HasPrefix(value, "#") || strings.HasPrefix(value, "@") ||
|
||
strings.ContainsAny(value, "/\\@_=0123456789") || strings.Contains(value, "://") {
|
||
return ""
|
||
}
|
||
value = strings.TrimFunc(value, func(char rune) bool { return !unicode.IsLetter(char) && !unicode.IsMark(char) })
|
||
if !valid_word(value) {
|
||
return ""
|
||
}
|
||
return value
|
||
}
|
||
|
||
func valid_word(value string) bool {
|
||
if !utf8.ValidString(value) || utf8.RuneCountInString(value) > 128 || value == "" {
|
||
return false
|
||
}
|
||
letters := false
|
||
for _, char := range value {
|
||
if unicode.IsLetter(char) {
|
||
letters = true
|
||
} else if !unicode.IsMark(char) && char != '\'' && char != '’' && char != '-' && char != '‐' {
|
||
return false
|
||
}
|
||
}
|
||
return letters
|
||
}
|
||
|
||
func Separator(char rune) bool {
|
||
return unicode.IsSpace(char) || unicode.IsPunct(char) && !strings.ContainsRune("'.:/@\\_=-’‐#", char)
|
||
}
|