Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,109 @@
|
||||
// Cthulhu screen reader.
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
)
|
||||
|
||||
const maxConfigSize = 1024 * 1024
|
||||
|
||||
func DefaultPath() (string, error) {
|
||||
if dataHome := os.Getenv("XDG_DATA_HOME"); dataHome != "" {
|
||||
return filepath.Join(dataHome, "cthulhu", "user-settings-go.toml"), nil
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve home directory: %w", err)
|
||||
}
|
||||
return filepath.Join(home, ".local", "share", "cthulhu", "user-settings-go.toml"), nil
|
||||
}
|
||||
|
||||
// Load reads legacy Python settings or the current versioned schema without
|
||||
// modifying the file. A present schema marker always selects strict decoding.
|
||||
func Load(path string) (Settings, error) {
|
||||
settings := DefaultSettings()
|
||||
if path == "" {
|
||||
var err error
|
||||
path, err = DefaultPath()
|
||||
if err != nil {
|
||||
return Settings{}, err
|
||||
}
|
||||
}
|
||||
settings.Path = path
|
||||
|
||||
file, err := os.Open(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return settings, nil
|
||||
}
|
||||
if err != nil {
|
||||
return Settings{}, fmt.Errorf("open configuration: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
contents, err := io.ReadAll(io.LimitReader(file, maxConfigSize+1))
|
||||
if err != nil {
|
||||
return Settings{}, fmt.Errorf("read configuration: %w", err)
|
||||
}
|
||||
if len(contents) > maxConfigSize {
|
||||
return Settings{}, fmt.Errorf("configuration exceeds %d bytes", maxConfigSize)
|
||||
}
|
||||
|
||||
var envelope struct {
|
||||
SchemaVersion *int `toml:"schema-version"`
|
||||
}
|
||||
if err := toml.Unmarshal(contents, &envelope); err != nil {
|
||||
return Settings{}, fmt.Errorf("parse configuration: %w", err)
|
||||
}
|
||||
if envelope.SchemaVersion != nil {
|
||||
settings, err := decodeWritable(contents)
|
||||
if err != nil {
|
||||
return Settings{}, err
|
||||
}
|
||||
settings.Path = path
|
||||
settings.Loaded = true
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
var parsed document
|
||||
if err := toml.Unmarshal(contents, &parsed); err != nil {
|
||||
return Settings{}, fmt.Errorf("parse configuration: %w", err)
|
||||
}
|
||||
apply(&settings, parsed.General)
|
||||
|
||||
profileName := selectedProfile(parsed.General, parsed.Profiles)
|
||||
if profileName != "" {
|
||||
profile, exists := parsed.Profiles[profileName]
|
||||
if !exists {
|
||||
return Settings{}, fmt.Errorf("configured profile %q does not exist", profileName)
|
||||
}
|
||||
apply(&settings, profile)
|
||||
}
|
||||
settings.ActiveProfile = profileName
|
||||
settings.Loaded = true
|
||||
if err := validate(settings); err != nil {
|
||||
return Settings{}, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
Reference in new issue
Block a user