cfprefs

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2025 License: MIT Imports: 7 Imported by: 0

README

go-cfprefs

Go module wrapper for the CFPreferences API's in macOS.

Features

  • Read and write macOS preferences using native Go types
  • Automatic type conversion between Go types and CoreFoundation types
  • Support for all common data types: strings, numbers, booleans, dates, arrays, dictionaries, and binary data
    • Use JSON Pointer paths to access nested structures

Installation

go get github.com/jheddings/go-cfprefs

Usage

Reading Preferences
import "github.com/jheddings/go-cfprefs"

// Read a preference value
value, err := cfprefs.Get("com.apple.finder", "ShowPathbar")
if err != nil {
    log.Fatal(err)
}

// Read a nested value using JSON Pointer path
value, err = cfprefs.Get("com.example.app", "config/server/port")
if err != nil {
    log.Fatal(err)
}
Writing Preferences

The Set function accepts any native Go type and automatically converts it to the appropriate CoreFoundation type:

import "github.com/jheddings/go-cfprefs"

// Write a string
err := cfprefs.Set("com.example.app", "username", "john_doe")

// Write a number
err = cfprefs.Set("com.example.app", "count", 42)

// Write a boolean
err = cfprefs.Set("com.example.app", "enabled", true)

// Write a float
err = cfprefs.Set("com.example.app", "pi", 3.14159)

// Write a date
err = cfprefs.Set("com.example.app", "lastAccess", time.Now())

// Write an array
err = cfprefs.Set("com.example.app", "items", []any{"apple", "banana", "cherry"})

// Write a dictionary
err = cfprefs.Set("com.example.app", "config", map[string]any{
    "theme": "dark",
    "fontSize": 14,
    "autoSave": true,
})

// Write a nested value using JSON Pointer path
err = cfprefs.Set("com.example.app", "config/server/port", 8080)
Deleting Preferences
// Delete a top-level key
err := cfprefs.Delete("com.example.app", "username")

// Delete a nested value using JSON Pointer path
err = cfprefs.Delete("com.example.app", "config/server/port")
Checking if a Key Exists
// Check for a top-level key
exists, err := cfprefs.Exists("com.example.app", "username")

// Check for a nested value using JSON Pointer path
exists, err = cfprefs.Exists("com.example.app", "config/server/port")

Path Syntax

Preference keys can be specified as simple names or as JSON Pointer paths to access nested values. Use / to separate object keys and array indices.

Examples
  • settings — top-level key
  • user/name — nested object field
  • items/0 — first element of an array
  • config/database/host — deeply nested field

For more details, see the JSON Pointer RFC.

Command-Line Interface

There is a basic CLI that acts as a demonstration of this module, as well as used for testing.

License

This project is licensed under the terms of the MIT license. See LICENSE for details.

Documentation

Index

Constants

View Source
const (
	// ArrayAppendOp is a special operator used to indicate an append operation.
	// When used in a keypath (e.g., "array-test/items/~]"), it signals that a
	// new element should be appended to end of the array.
	ArrayAppendOp = "~]"

	// ArrayPrependOp is a special operator used to indicate a prepend operation.
	// When used in a keypath (e.g., "array-test/items/~["), it signals that a
	// new element should be prepended to the beginning of the array.
	ArrayPrependOp = "~["
)

Variables

View Source
var (
	// ErrKeyNotFound is returned when a requested key does not exist
	ErrKeyNotFound = errors.New("key not found")

	// ErrInvalidKeyPath is returned when a key path is malformed
	ErrInvalidKeyPath = errors.New("invalid key path")

	// ErrTypeMismatch is returned when a value is not of the expected type
	ErrTypeMismatch = errors.New("type mismatch")

	// ErrInternal is returned when an internal error occurs
	ErrInternal = errors.New("internal error")
)

Sentinel errors for common failures

Functions

func Delete

func Delete(appID, keypath string) error

Delete removes a preference value at the given keypath and application ID. If the keypath is a simple name, it deletes the entire key. If the keypath is a JSON Pointer path, it deletes the value at the specified path.

Example usage:

// Delete a simple value
err := Delete("com.example.app", "username")

// Delete a nested value
err := Delete("com.example.app", "config/server/port")

Returns an error if the keypath is invalid or the value cannot be deleted.

func Exists

func Exists(appID, keypath string) (bool, error)

Exists checks if a preference key exists for the given application ID.

The keypath can be a simple name or include a JSON Pointer path (e.g., "config/server/port") to access nested values within the preference.

Example usage:

// Check if a simple key exists
exists, err := Exists("com.example.app", "username")

// Check if a nested value exists
exists, err := Exists("com.example.app", "config/server/port")

Returns true if the key exists, false otherwise.

func Get

func Get(appID, keypath string) (any, error)

Get retrieves a preference value for the given key and application ID.

The keypath can be a simple name or include a JSON Pointer path (e.g., "config/server/port") to access nested values within the preference.

Example usage:

// Get a simple value
value, err := Get("com.example.app", "username")

// Get a nested value
value, err := Get("com.example.app", "config/server/port")

Returns the value at the specified path or an error if not found.

func GetBool

func GetBool(appID, keypath string) (bool, error)

GetBool retrieves a boolean preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a boolean.

func GetData added in v0.2.0

func GetData(appID, keypath string) ([]byte, error)

GetData retrieves a []byte preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a []byte.

func GetDate added in v0.2.0

func GetDate(appID, keypath string) (time.Time, error)

GetDate retrieves a time.Time preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a time.Time.

func GetFloat

func GetFloat(appID, keypath string) (float64, error)

GetFloat retrieves a float preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a float.

func GetInt

func GetInt(appID, keypath string) (int64, error)

GetInt retrieves an integer preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not an integer.

func GetKeys added in v0.2.0

func GetKeys(appID string) ([]string, error)

GetKeys retrieves all keys for the given appID. Returns an error if the appID is not found.

func GetMap added in v0.2.0

func GetMap(appID, keypath string) (map[string]any, error)

GetMap retrieves a map[string]any preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a map[string]any.

func GetSlice added in v0.2.0

func GetSlice(appID, keypath string) ([]any, error)

GetSlice retrieves a []any preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a []any.

func GetStr

func GetStr(appID, keypath string) (string, error)

GetStr retrieves a string preference value for the given key and application ID. Returns an error if the key doesn't exist or if the value is not a string.

func Set

func Set(appID, keypath string, value any) error

Set writes a preference value for the given key and application ID.

The keypath can be a simple name or include a JSON Pointer path (e.g., "config/server/port") to access nested values within the preference.

Example usage:

// Set a simple value
err := Set("com.example.app", "username", "John Doe")

// Set a nested value
err := Set("com.example.app", "config/server/port", 8080)

Types

type InternalErr added in v0.3.0

type InternalErr struct {
	Err error
	Msg string
}

InternalErr represents an error that is internal to the library

func NewInternalError added in v0.3.0

func NewInternalError() *InternalErr

NewInternalError creates a new InternalErr

func (*InternalErr) Error added in v0.3.0

func (e *InternalErr) Error() string

Error returns the error message

func (*InternalErr) Is added in v0.3.0

func (e *InternalErr) Is(target error) bool

Is implements support for errors.Is

func (*InternalErr) Unwrap added in v0.3.0

func (e *InternalErr) Unwrap() error

Unwrap returns the underlying error

func (*InternalErr) WithMsg added in v0.3.0

func (e *InternalErr) WithMsg(msg string) *InternalErr

WithMsg adds a custom message to the error

func (*InternalErr) WithMsgF added in v0.3.0

func (e *InternalErr) WithMsgF(format string, a ...any) *InternalErr

WithMsgF adds a formatted custom message to the error

func (*InternalErr) Wrap added in v0.3.0

func (e *InternalErr) Wrap(err error) *InternalErr

Wrap wraps an error with the InternalErr

type KeyNotFoundErr added in v0.3.0

type KeyNotFoundErr struct {
	AppID string
	Key   string
	Msg   string
	Err   error
}

KeyNotFoundErr represents an error when a preference key is not found

func NewKeyNotFoundError added in v0.3.0

func NewKeyNotFoundError(appID, key string) *KeyNotFoundErr

NewKeyNotFoundError creates a new KeyNotFoundErr

func (*KeyNotFoundErr) Error added in v0.3.0

func (e *KeyNotFoundErr) Error() string

Error returns the error message

func (*KeyNotFoundErr) Is added in v0.3.0

func (e *KeyNotFoundErr) Is(target error) bool

Is implements support for errors.Is

func (*KeyNotFoundErr) Unwrap added in v0.3.0

func (e *KeyNotFoundErr) Unwrap() error

Unwrap returns the underlying error

func (*KeyNotFoundErr) WithMsg added in v0.3.0

func (e *KeyNotFoundErr) WithMsg(msg string) *KeyNotFoundErr

WithMsg adds a custom message to the error

func (*KeyNotFoundErr) WithMsgF added in v0.3.0

func (e *KeyNotFoundErr) WithMsgF(format string, a ...any) *KeyNotFoundErr

WithMsgF adds a formatted custom message to the error

func (*KeyNotFoundErr) Wrap added in v0.3.0

func (e *KeyNotFoundErr) Wrap(err error) *KeyNotFoundErr

Wrap wraps an error with the KeyNotFoundErr

type KeyPathErr added in v0.3.0

type KeyPathErr struct {
	Msg string
	Err error
}

KeyPathErr represents an error with a key path

func NewKeyPathError added in v0.3.0

func NewKeyPathError() *KeyPathErr

NewKeyPathError creates a new KeyPathErr

func (*KeyPathErr) Error added in v0.3.0

func (e *KeyPathErr) Error() string

Error returns the error message

func (*KeyPathErr) Is added in v0.3.0

func (e *KeyPathErr) Is(target error) bool

Is implements support for errors.Is

func (*KeyPathErr) Unwrap added in v0.3.0

func (e *KeyPathErr) Unwrap() error

Unwrap returns the underlying error

func (*KeyPathErr) WithMsg added in v0.3.0

func (e *KeyPathErr) WithMsg(msg string) *KeyPathErr

WithMsg adds a custom message to the error

func (*KeyPathErr) WithMsgF added in v0.3.0

func (e *KeyPathErr) WithMsgF(format string, a ...any) *KeyPathErr

WithMsgF adds a formatted custom message to the error

func (*KeyPathErr) Wrap added in v0.3.0

func (e *KeyPathErr) Wrap(err error) *KeyPathErr

Wrap wraps an error with the KeyPathErr

type TypeMismatchErr added in v0.3.0

type TypeMismatchErr struct {
	AppID    string
	Key      string
	Expected any
	Actual   any
	Err      error
}

TypeMismatchErr represents a type mismatch error

func NewTypeMismatchError added in v0.3.0

func NewTypeMismatchError(expected, actual any) *TypeMismatchErr

NewTypeMismatchError creates a new TypeMismatchErr

func (*TypeMismatchErr) Error added in v0.3.0

func (e *TypeMismatchErr) Error() string

Error returns the error message

func (*TypeMismatchErr) Is added in v0.3.0

func (e *TypeMismatchErr) Is(target error) bool

Is implements support for errors.Is

func (*TypeMismatchErr) Unwrap added in v0.3.0

func (e *TypeMismatchErr) Unwrap() error

Unwrap returns the underlying error

func (*TypeMismatchErr) WithKey added in v0.3.0

func (e *TypeMismatchErr) WithKey(appID, key string) *TypeMismatchErr

WithKey adds an appID and key to the error

func (*TypeMismatchErr) Wrap added in v0.3.0

func (e *TypeMismatchErr) Wrap(err error) *TypeMismatchErr

Wrap wraps an error with the TypeMismatchErr

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址