Class: SplttyCLI::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/spltty_cli/config.rb

Overview

Reads / writes the CLI-owned config.json. Holds user-authored payment methods and an auto-maintained ledgers cache (see Discovery). The ledgers key may be absent on load — it is created on demand.

Defined Under Namespace

Classes: Error

Constant Summary collapse

WORKSPACE_DIR =

Where a workspace keeps its config, relative to the workspace root. spltty install writes it; every other command finds it by walking up from the cwd (see .discover).

".spltty"
WORKSPACE_FILE =
"config.json"
DEFAULT =
{
  "accounts_dir"    => "../accounts",
  "default_ledger"  => "expenses",
  "date_format"     => "%Y-%m-%d",
  "payment_methods" => {},
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, data) ⇒ Config

Returns a new instance of Config.



27
28
29
30
31
# File 'lib/spltty_cli/config.rb', line 27

def initialize(path, data)
  @path = path
  @data = data
  @accounts_dir_override = nil
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



25
26
27
# File 'lib/spltty_cli/config.rb', line 25

def data
  @data
end

#pathObject (readonly)

Returns the value of attribute path.



25
26
27
# File 'lib/spltty_cli/config.rb', line 25

def path
  @path
end

Class Method Details

.discover(start_dir = Dir.pwd) ⇒ Object

Walk up from start_dir looking for .spltty/config.json — the same nearest-ancestor rule git uses for .git. Returns the absolute path of the first hit, or nil when there is no workspace above start_dir.



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/spltty_cli/config.rb', line 54

def self.discover(start_dir = Dir.pwd)
  dir = File.expand_path(start_dir)
  loop do
    candidate = File.join(dir, WORKSPACE_DIR, WORKSPACE_FILE)
    return candidate if File.file?(candidate)

    parent = File.dirname(dir)
    return nil if parent == dir # reached the filesystem root

    dir = parent
  end
end

.load(path) ⇒ Object

Load config.json, or start from DEFAULT when the file does not exist yet (the ledgers block gets written on the first discovery run).

Raises:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/spltty_cli/config.rb', line 35

def self.load(path)
  data =
    if File.exist?(path)
      begin
        JSON.parse(File.read(path))
      rescue JSON::ParserError => e
        raise Error, "malformed config at #{path}: #{e.message}"
      end
    else
      Marshal.load(Marshal.dump(DEFAULT))
    end
  raise Error, "config root must be a JSON object" unless data.is_a?(Hash)

  new(path, data)
end

.workspace_path(dir) ⇒ Object

Absolute path of the config file for a workspace rooted at dir.



68
69
70
# File 'lib/spltty_cli/config.rb', line 68

def self.workspace_path(dir)
  File.join(File.expand_path(dir), WORKSPACE_DIR, WORKSPACE_FILE)
end

Instance Method Details

#accounts_dirObject

Absolute accounts directory. Resolved relative to the config file unless an override (from --accounts-dir / env) was supplied.



74
75
76
77
# File 'lib/spltty_cli/config.rb', line 74

def accounts_dir
  base = @accounts_dir_override || @data["accounts_dir"] || "../accounts"
  File.expand_path(base, File.dirname(@path))
end

#accounts_dir=(absolute_path) ⇒ Object

Override with an already-absolute path (App expands --accounts-dir vs cwd).



80
81
82
# File 'lib/spltty_cli/config.rb', line 80

def accounts_dir=(absolute_path)
  @accounts_dir_override = absolute_path
end

#date_formatObject



88
89
90
# File 'lib/spltty_cli/config.rb', line 88

def date_format
  @data["date_format"] || "%Y-%m-%d"
end

#default_ledgerObject



84
85
86
# File 'lib/spltty_cli/config.rb', line 84

def default_ledger
  @data["default_ledger"]
end

#groupsObject

Global split groups (shared across ledgers). Created lazily. Ledger-specific groups live under ledgers["groups"]; these are the promoted globals.



99
100
101
# File 'lib/spltty_cli/config.rb', line 99

def groups
  @data["groups"] ||= {}
end

#ledger_key(name) ⇒ Object

Case-insensitive resolution of a ledger name to its canonical config key.



130
131
132
133
134
# File 'lib/spltty_cli/config.rb', line 130

def ledger_key(name)
  return nil if name.nil? || name.empty?

  ledgers.keys.find { |k| k.casecmp?(name) }
end

#ledgersObject

The ledgers cache — created lazily so a minimal config (methods only) works.



93
94
95
# File 'lib/spltty_cli/config.rb', line 93

def ledgers
  @data["ledgers"] ||= {}
end

#participantsObject

Everyone who can appear in a Paid By / Responsible cell. Recorded by spltty install and used to render the workspace CLAUDE.md; the split groups remain the authority on how a cost is divided.



110
111
112
# File 'lib/spltty_cli/config.rb', line 110

def participants
  @data["participants"] ||= []
end

#payment_method(name) ⇒ Object

Resolve a payment method by its full name or its configured slug (both case-insensitive) → returns [canonical_name, cfg], or [name, nil] when unknown (e.g. one-off methods like "cash").



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/spltty_cli/config.rb', line 117

def payment_method(name)
  return [nil, nil] if name.nil? || name.empty?

  n = name.strip
  key = payment_methods.keys.find { |k| k.casecmp?(n) }
  key ||= payment_methods.keys.find do |k|
    slug = payment_methods[k]["slug"]
    slug && slug.casecmp?(n)
  end
  key ? [key, payment_methods[key]] : [name, nil]
end

#payment_methodsObject



103
104
105
# File 'lib/spltty_cli/config.rb', line 103

def payment_methods
  @data["payment_methods"] ||= {}
end

#saveObject



136
137
138
# File 'lib/spltty_cli/config.rb', line 136

def save
  File.write(@path, JSON.pretty_generate(@data) + "\n")
end