From 8e59d986ff8b84fc7725a692df33d065b8ab19b3 Mon Sep 17 00:00:00 2001 From: William Dillon Date: Tue, 25 Nov 2025 21:19:08 -0500 Subject: [PATCH] adding license and readme --- LICENSE | 21 +++++++++++ README.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..df40e39 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 William Dillon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ee58173 --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +# settings + +A small, concurrency-safe Go package to load simple key/value configuration files and keep them updated automatically. + +**Package**: `settings` + +**Quick overview** +- **What it does:** Parses simple text files containing key/value pairs and stores them in a thread-safe in-memory map. It can watch the file (via a background goroutine) and refresh values when the file on disk changes. +- **File format:** Each non-empty, non-comment line must contain a key and a value separated by a delimiter (`:` or `=`). Lines beginning with `//` or `#` are treated as comments and ignored. + +**Key features** +- **Automatic updates:** A background maintenance goroutine periodically calls `Update()` to reload the file when it changes. +- **Thread-safe:** All exported methods on `Settings` use mutexes or atomic flags where appropriate. +- **Simple scanner:** The `scanner` reads lines, supports comments and a small set of delimiters, and returns clear errors for malformed lines. + +**Installation** + +This package is part of the current module. To run tests or use it, ensure your module is initialized (see `go.mod`) and import it using the module path where it's hosted, e.g.: + +```go +import "your/module/path/settings" +``` + +Replace `your/module/path` with your module path. + +**Public API** +- `func NewSettings(filename string, logUpdates bool) *Settings` — create a `Settings` instance using `context.Background()`; starts the background maintenance goroutine. +- `func NewSettingsWithContext(ctx context.Context, filename string, logUpdates bool) *Settings` — same as above but accepts a `context.Context` to control lifecycle (cancellation stops the maintenance goroutine). +- `func (s *Settings) GetFilename() string` — returns the current filename. +- `func (s *Settings) SetFilename(filename string) (updated bool)` — atomically change the filename and attempt an immediate update; returns true if filename changed. +- `func (s *Settings) SetKeyValue(key, value string) (updated bool)` — set a key/value pair in the in-memory map (returns whether it changed). +- `func (s *Settings) ContainsKey(key string) bool` — returns whether a key exists. +- `func (s *Settings) GetKeyValue(key string) string` — returns the value for a key (empty string if not present). +- `func (s *Settings) Update() error` — force a synchronous update from the current filename; returns an error on IO problems. + +Constants / package variables +- `MaintenanceRoutinePace` (time.Duration) — pacing for the background maintenance goroutine (default `time.Second`). +- `WarnIfFileNotFound` (bool) — when true, log messages for missing files even if they are `os.ErrNotExist`. + +Scanner details +- `KeyValueDelimiterChars` — allowed delimiter bytes (default `':'` and `'='`). +- `ErrNoValidDelimiter` — returned when a non-comment non-empty line doesn't contain a valid delimiter. +- `LineIsComment(line string) bool` — returns true for lines starting with `//` or `#`. + +File format example + +Valid settings file contents: + +``` +// comments allowed +# another comment +host: localhost +port = 8080 + +mode: production +``` + +Notes on behavior +- When created, `NewSettings*` immediately attempts an initial load. If the file doesn't exist or another IO error occurs, an error is logged but a `Settings` instance is still returned. +- The background maintenance goroutine invokes `Update()` every `MaintenanceRoutinePace`. Use `NewSettingsWithContext` and pass a cancellable context to stop the goroutine when you no longer need the `Settings` instance. +- `SetFilename` will attempt to read the new file immediately. If reading fails an error may be logged depending on `WarnIfFileNotFound`. +- `LogUpdates` is an `atomic.Bool` on the `Settings` struct; set to `true` if you want the package to log add/update operations for keys. + +Examples + +Create and use `Settings`: + +```go +ctx := context.Background() +settings := settings.NewSettingsWithContext(ctx, "config.settings", false) + +// read a value +if settings.ContainsKey("host") { + host := settings.GetKeyValue("host") + fmt.Println("host =", host) +} + +// change the file being used +settings.SetFilename("other.settings") + +// programmatically set a value +settings.SetKeyValue("local_only", "true") + +// force a synchronous reload +if err := settings.Update(); err != nil { + log.Printf("update error: %v", err) +} +``` + +Running tests + +From the repository root run: + +```bash +go test ./... +``` + +This package includes unit tests for both the `scanner` and the `Settings` behaviors (see `scanner_test.go` and `settings_test.go`). + +Contributing / License + +This repository has no public license in the source tree. If you plan to reuse or publish this code, add a LICENSE file or consult the repository owner. + +Questions + +If you want any additional examples, a different README layout, or embedded documentation for each exported symbol, tell me which format you prefer and I will update the file.