adding license and readme

This commit is contained in:
William Dillon 2025-11-25 21:19:08 -05:00
parent c145062ff0
commit 8e59d986ff
2 changed files with 127 additions and 0 deletions

21
LICENSE Normal file
View File

@ -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.

106
README.md Normal file
View File

@ -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.