fasti 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.mcp.json +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +82 -0
- data/.rubocop_todo.yml +89 -0
- data/.serena/project.yml +68 -0
- data/.simplecov +31 -0
- data/.yardopts +9 -0
- data/AGENTS.md +60 -0
- data/CHANGELOG.md +25 -0
- data/CLAUDE.md +1 -0
- data/LICENSE.txt +21 -0
- data/README.md +416 -0
- data/RELEASING.md +202 -0
- data/Rakefile +34 -0
- data/TODO.md +11 -0
- data/benchmark/holiday_cache_benchmark.rb +111 -0
- data/benchmark/memory_benchmark.rb +86 -0
- data/docs/agents/git-pr.md +298 -0
- data/docs/agents/languages.md +388 -0
- data/docs/agents/rubocop.md +55 -0
- data/docs/plans/positional-arguments.md +303 -0
- data/docs/plans/structured-config.md +232 -0
- data/examples/config.rb +80 -0
- data/exe/fasti +6 -0
- data/lib/fasti/calendar.rb +292 -0
- data/lib/fasti/calendar_transition.rb +266 -0
- data/lib/fasti/cli.rb +550 -0
- data/lib/fasti/config/schema.rb +36 -0
- data/lib/fasti/config/types.rb +66 -0
- data/lib/fasti/config.rb +125 -0
- data/lib/fasti/error.rb +6 -0
- data/lib/fasti/formatter.rb +234 -0
- data/lib/fasti/style_parser.rb +211 -0
- data/lib/fasti/version.rb +6 -0
- data/lib/fasti.rb +21 -0
- data/mise.toml +5 -0
- data/sig/fasti.rbs +4 -0
- metadata +181 -0
@@ -0,0 +1,303 @@
|
|
1
|
+
# Positional Arguments - Fasti Development Plan
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
Replace current option-based month/year specification (`--month`/`--year`) with positional arguments to provide a more intuitive command-line interface.
|
5
|
+
|
6
|
+
## Goals
|
7
|
+
1. **Simplified Interface**: Remove `--month` and `--year` options in favor of positional arguments
|
8
|
+
2. **Intuitive Usage**: Natural argument parsing that matches user expectations
|
9
|
+
3. **Backward Compatibility**: Maintain all other existing functionality
|
10
|
+
4. **User Experience**: Clear error messages for invalid argument combinations
|
11
|
+
|
12
|
+
## Current Architecture
|
13
|
+
```bash
|
14
|
+
# Current option-based interface
|
15
|
+
fasti --month 6 --year 2024 # June 2024
|
16
|
+
fasti --month 6 # June current year
|
17
|
+
fasti --year 2024 # Current month 2024
|
18
|
+
fasti # Current month/year
|
19
|
+
|
20
|
+
# Current Options structure (month/year will be removed)
|
21
|
+
Options = Data.define(:month, :year, :format, :start_of_week, :country, :style)
|
22
|
+
```
|
23
|
+
|
24
|
+
## Target Architecture
|
25
|
+
```bash
|
26
|
+
# New positional argument interface
|
27
|
+
fasti 6 2024 # June 2024 (month year)
|
28
|
+
fasti 6 # June current year (1-12 = month)
|
29
|
+
fasti 2024 # Current month 2024 (13+ = year)
|
30
|
+
fasti # Current month/year
|
31
|
+
|
32
|
+
# Argument parsing rules:
|
33
|
+
# 0 args: current month + current year
|
34
|
+
# 1 arg: 1-12 → month + current year, 13+ → current month + year
|
35
|
+
# 2 args: first = month (any value), second = year
|
36
|
+
# month must be 1-12 or ArgumentError
|
37
|
+
|
38
|
+
# Options structure simplified (month/year removed)
|
39
|
+
Options = Data.define(:format, :start_of_week, :country, :style)
|
40
|
+
```
|
41
|
+
|
42
|
+
## Development Phases
|
43
|
+
|
44
|
+
### Phase 1: Foundation Setup
|
45
|
+
**Branch**: `feature/positional-arguments`
|
46
|
+
|
47
|
+
1. **Update Options Structure**
|
48
|
+
- Remove `:month` and `:year` from Options Data.define
|
49
|
+
- Update Options structure: `Options = Data.define(:format, :start_of_week, :country, :style)`
|
50
|
+
- Update all usages of Options throughout codebase
|
51
|
+
|
52
|
+
2. **Update CLI Argument Processing**
|
53
|
+
- Remove `--month` and `--year` option definitions from OptionParser
|
54
|
+
- Update CLI class documentation to reflect new interface
|
55
|
+
- Update help text to show positional argument usage
|
56
|
+
|
57
|
+
3. **Implement Positional Argument Parser**
|
58
|
+
- File: `lib/fasti/cli.rb`
|
59
|
+
- Add `parse_positional_args(argv)` method:
|
60
|
+
```ruby
|
61
|
+
def parse_positional_args(argv)
|
62
|
+
case argv.length
|
63
|
+
when 0
|
64
|
+
# Use current month and year
|
65
|
+
[Time.now.month, Time.now.year]
|
66
|
+
when 1
|
67
|
+
arg = argv[0].to_i
|
68
|
+
validate_single_argument!(arg)
|
69
|
+
if (1..12).include?(arg)
|
70
|
+
[arg, Time.now.year] # Month for current year
|
71
|
+
else
|
72
|
+
[Time.now.month, arg] # Year for current month
|
73
|
+
end
|
74
|
+
when 2
|
75
|
+
month = argv[0].to_i
|
76
|
+
year = argv[1].to_i
|
77
|
+
validate_month!(month)
|
78
|
+
validate_year!(year)
|
79
|
+
[month, year]
|
80
|
+
else
|
81
|
+
raise ArgumentError, "Too many arguments. Expected 0-2, got #{argv.length}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
4. **Add Validation Methods**
|
87
|
+
- Add `validate_single_argument!(arg)` for single argument validation
|
88
|
+
- Enhance existing `validate_month!` and `validate_year!` methods
|
89
|
+
- Ensure clear error messages for invalid inputs
|
90
|
+
|
91
|
+
### Phase 2: Integration
|
92
|
+
5. **Modify Option Parsing Flow**
|
93
|
+
- Update `parse_options(argv)` method to:
|
94
|
+
1. Parse options first with modified OptionParser (without --month/--year)
|
95
|
+
2. OptionParser.parse! automatically removes processed options from argv
|
96
|
+
3. Parse remaining arguments (now only positional) to extract month/year values
|
97
|
+
4. Pass month/year separately to calendar generation methods
|
98
|
+
|
99
|
+
6. **Update Calendar Generation Methods**
|
100
|
+
- Modify `generate_calendar`, `generate_month_calendar`, `generate_quarter_calendar`, `generate_year_calendar`
|
101
|
+
- Accept month and year as separate parameters instead of from Options struct
|
102
|
+
- Remove month/year access from Options throughout calendar generation logic
|
103
|
+
|
104
|
+
7. **Update Default Options Logic**
|
105
|
+
- Remove month/year from `default_options` method
|
106
|
+
- Simplify Options structure to only include format, start_of_week, country, style
|
107
|
+
- Handle month/year defaults in positional argument parsing
|
108
|
+
|
109
|
+
### Phase 3: Testing and Documentation
|
110
|
+
8. **Comprehensive Testing**
|
111
|
+
- Test all argument combinations (0, 1, 2 arguments)
|
112
|
+
- Test error cases (invalid months, negative years, too many arguments)
|
113
|
+
- Test integration with other options (`--format`, `--country`, etc.)
|
114
|
+
- Ensure backward compatibility for non-month/year options
|
115
|
+
- Test Options structure changes don't break existing functionality
|
116
|
+
|
117
|
+
9. **Update Documentation**
|
118
|
+
- CLI class documentation: Update method comments and examples
|
119
|
+
- Help text: Show new positional argument usage
|
120
|
+
- README.md: Update usage examples throughout
|
121
|
+
|
122
|
+
10. **Quality Assurance**
|
123
|
+
- RuboCop compliance
|
124
|
+
- All tests passing
|
125
|
+
- Manual testing of common use cases
|
126
|
+
- Error message clarity verification
|
127
|
+
|
128
|
+
### Phase 4: Deployment
|
129
|
+
11. **Create Pull Request**
|
130
|
+
- Comprehensive description of interface change
|
131
|
+
- Breaking change documentation
|
132
|
+
- Migration examples for common usage patterns
|
133
|
+
|
134
|
+
## Technical Implementation Details
|
135
|
+
|
136
|
+
### Design Decisions
|
137
|
+
|
138
|
+
#### Argument Order for Two Arguments
|
139
|
+
**Decision**: Fixed positional order (first argument = month, second argument = year)
|
140
|
+
|
141
|
+
**Alternative Considered**: Automatic order detection (larger value = year, smaller value = month)
|
142
|
+
|
143
|
+
**Rationale for Fixed Order**:
|
144
|
+
- **Predictable behavior**: Users know exactly what `fasti 6 2024` means
|
145
|
+
- **Standard CLI convention**: Most command-line tools use fixed positional argument order
|
146
|
+
- **Clear error handling**: Invalid month (e.g., `fasti 13 2024`) immediately produces a clear error message
|
147
|
+
- **No hidden corrections**: Invalid input fails explicitly rather than being "corrected" silently
|
148
|
+
- **Easier debugging**: Behavior is deterministic and traceable
|
149
|
+
|
150
|
+
**Problems with Automatic Detection**:
|
151
|
+
- **Ambiguous error cases**: `fasti 13 2024` would be interpreted as "2024 year, 13 month" and fail in a confusing way
|
152
|
+
- **Unexpected behavior**: Users might not understand why `fasti 25 2024` becomes "2024 year, 25 month"
|
153
|
+
- **Debugging complexity**: Non-obvious transformations make troubleshooting difficult
|
154
|
+
|
155
|
+
### Argument Parsing Logic
|
156
|
+
```ruby
|
157
|
+
# Option parsing flow
|
158
|
+
def parse_options(argv)
|
159
|
+
options_hash = default_options.to_h
|
160
|
+
|
161
|
+
# 1. Parse options first - removes them from argv automatically
|
162
|
+
parser = create_option_parser(options_hash, include_help: true)
|
163
|
+
parser.parse!(argv) # Destructively modifies argv
|
164
|
+
|
165
|
+
# 2. Parse remaining positional arguments
|
166
|
+
month, year = parse_positional_args(argv)
|
167
|
+
|
168
|
+
# 3. Create options and return with month/year
|
169
|
+
options = Options.new(**options_hash)
|
170
|
+
[month, year, options]
|
171
|
+
end
|
172
|
+
|
173
|
+
# Positional argument parsing (after options removed)
|
174
|
+
def parse_positional_args(argv)
|
175
|
+
case argv.length
|
176
|
+
when 0
|
177
|
+
[Time.now.month, Time.now.year]
|
178
|
+
when 1
|
179
|
+
interpret_single_argument(argv[0])
|
180
|
+
when 2
|
181
|
+
validate_two_arguments(argv[0], argv[1])
|
182
|
+
else
|
183
|
+
raise ArgumentError, "Too many arguments. Expected 0-2, got #{argv.length}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Single argument interpretation
|
188
|
+
def interpret_single_argument(arg)
|
189
|
+
value = arg.to_i
|
190
|
+
if value == 0 && arg != "0"
|
191
|
+
raise ArgumentError, "Invalid argument: '#{arg}'. Expected integer."
|
192
|
+
end
|
193
|
+
|
194
|
+
if (1..12).include?(value)
|
195
|
+
[value, Time.now.year] # Return [month, current_year]
|
196
|
+
elsif value >= 13
|
197
|
+
[Time.now.month, value] # Return [current_month, year]
|
198
|
+
else
|
199
|
+
raise ArgumentError, "Invalid argument: #{value}. Expected 1-12 (month) or 13+ (year)."
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Two argument validation
|
204
|
+
def validate_two_arguments(month_arg, year_arg)
|
205
|
+
month = month_arg.to_i
|
206
|
+
year = year_arg.to_i
|
207
|
+
|
208
|
+
raise ArgumentError, "Invalid month: '#{month_arg}'" if month == 0 && month_arg != "0"
|
209
|
+
raise ArgumentError, "Invalid year: '#{year_arg}'" if year == 0 && year_arg != "0"
|
210
|
+
|
211
|
+
validate_month!(month)
|
212
|
+
validate_year!(year)
|
213
|
+
|
214
|
+
[month, year] # Return [month, year]
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
### Updated CLI Interface Examples
|
219
|
+
```bash
|
220
|
+
# Display current month
|
221
|
+
fasti
|
222
|
+
|
223
|
+
# Display June of current year
|
224
|
+
fasti 6
|
225
|
+
|
226
|
+
# Display current month of 2024
|
227
|
+
fasti 2024
|
228
|
+
|
229
|
+
# Display June 2024
|
230
|
+
fasti 6 2024
|
231
|
+
|
232
|
+
# Display with other options (unchanged)
|
233
|
+
fasti 6 2024 --format year --country US
|
234
|
+
fasti 12 --start-of-week monday
|
235
|
+
```
|
236
|
+
|
237
|
+
### Error Handling
|
238
|
+
```bash
|
239
|
+
# Invalid month in two-argument case
|
240
|
+
$ fasti 13 2024
|
241
|
+
Error: Month must be between 1 and 12
|
242
|
+
|
243
|
+
# Too many arguments
|
244
|
+
$ fasti 6 2024 extra
|
245
|
+
Error: Too many arguments. Expected 0-2, got 3
|
246
|
+
|
247
|
+
# Invalid single argument (edge cases)
|
248
|
+
$ fasti 0
|
249
|
+
Error: Invalid argument: 0. Expected 1-12 (month) or 13+ (year).
|
250
|
+
|
251
|
+
$ fasti -5
|
252
|
+
Error: Invalid argument: -5. Expected 1-12 (month) or 13+ (year).
|
253
|
+
```
|
254
|
+
|
255
|
+
### Integration Notes
|
256
|
+
- Options structure simplified to `Options = Data.define(:format, :start_of_week, :country, :style)`
|
257
|
+
- All other CLI options (`--format`, `--country`, etc.) work identically
|
258
|
+
- Configuration file support unchanged (month/year options will be ignored if present)
|
259
|
+
- Calendar generation methods modified to accept month/year as separate parameters
|
260
|
+
|
261
|
+
## Risk Assessment
|
262
|
+
- **Medium Risk**: Breaking change to CLI interface and Options structure
|
263
|
+
- **Medium Risk**: Internal API changes to calendar generation methods
|
264
|
+
- **Low Risk**: Core functionality preserved, only interface changes
|
265
|
+
- **Mitigation**: Clear documentation and helpful error messages
|
266
|
+
|
267
|
+
## Success Criteria
|
268
|
+
- [ ] Options structure updated to remove month/year fields
|
269
|
+
- [ ] All existing functionality preserved (except `--month`/`--year` options)
|
270
|
+
- [ ] New positional argument parsing working correctly
|
271
|
+
- [ ] Calendar generation methods updated to accept month/year as parameters
|
272
|
+
- [ ] Comprehensive error handling with clear messages
|
273
|
+
- [ ] Documentation updated with examples
|
274
|
+
- [ ] All tests passing
|
275
|
+
- [ ] Documentation updated with new interface examples
|
276
|
+
- [ ] Help text and CLI documentation updated
|
277
|
+
|
278
|
+
## Files to Modify
|
279
|
+
- `lib/fasti/cli.rb` - Main CLI argument processing and Options structure
|
280
|
+
- `README.md` - Update usage examples
|
281
|
+
- `spec/fasti/cli_spec.rb` - Update tests for new interface
|
282
|
+
- Any files that reference `options.month` or `options.year` (to be identified during implementation)
|
283
|
+
|
284
|
+
## Breaking Changes
|
285
|
+
- **Removed Options**: `--month` and `--year` options no longer available
|
286
|
+
- **Options Structure**: `Options` no longer contains `:month` and `:year` fields
|
287
|
+
- **Internal API**: Calendar generation methods now accept month/year as separate parameters
|
288
|
+
- **New Interface**: Must use positional arguments for month/year specification
|
289
|
+
### Interface Examples
|
290
|
+
```bash
|
291
|
+
# New positional argument interface
|
292
|
+
fasti 6 2024 # June 2024
|
293
|
+
fasti 6 # June current year
|
294
|
+
fasti 2024 # Current month 2024
|
295
|
+
fasti # Current month/year
|
296
|
+
|
297
|
+
# Combined with other options
|
298
|
+
fasti 6 --format year # June current year with year format
|
299
|
+
fasti 2024 --country US # Current month 2024 with US holidays
|
300
|
+
```
|
301
|
+
|
302
|
+
---
|
303
|
+
*This plan serves as a comprehensive roadmap for implementing positional arguments while maintaining the core functionality.*
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# Structured Configuration - Fasti Development Plan
|
2
|
+
|
3
|
+
## ⚠️ Development Order Notice
|
4
|
+
**This plan depends on positional arguments implementation being completed first.**
|
5
|
+
|
6
|
+
The positional arguments feature (see `positional-arguments.md`) removes `--month` and `--year` options from the CLI interface and simplifies the Options structure to `Options = Data.define(:format, :start_of_week, :country, :style)`. This plan assumes that change has been implemented.
|
7
|
+
|
8
|
+
**Prerequisite**: Complete implementation of positional arguments before starting dry-configurable integration.
|
9
|
+
|
10
|
+
## Overview
|
11
|
+
Replace current shell-argument based configuration file (`~/.config/fastirc`) with Ruby-based configuration using dry-configurable and add validation using dry-validation.
|
12
|
+
|
13
|
+
## Goals
|
14
|
+
1. **Structured Configuration**: Replace shell arguments with Ruby DSL
|
15
|
+
2. **Validation**: Catch configuration errors with helpful messages
|
16
|
+
3. **Maintainability**: Easier to extend and modify configuration options
|
17
|
+
4. **User Experience**: Better error reporting for invalid configurations
|
18
|
+
|
19
|
+
## Current Architecture
|
20
|
+
```ruby
|
21
|
+
# Current fastirc (shell arguments) - after positional args implementation
|
22
|
+
--format year --country US --start-of-week monday
|
23
|
+
|
24
|
+
# Current Options structure (simplified by positional args feature)
|
25
|
+
Options = Data.define(:format, :start_of_week, :country, :style)
|
26
|
+
```
|
27
|
+
|
28
|
+
## Target Architecture
|
29
|
+
```ruby
|
30
|
+
# New fastirc (Ruby DSL)
|
31
|
+
configure do |config|
|
32
|
+
config.format = :year
|
33
|
+
config.country = :US
|
34
|
+
config.start_of_week = :monday
|
35
|
+
config.style.sunday = { bold: true }
|
36
|
+
config.style.holiday = { foreground: :red, bold: true }
|
37
|
+
config.style.today = { inverse: true }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Configuration priority: Positional args > CLI options > Config file > Locale detection > Defaults
|
41
|
+
# Options structure simplified (no month/year fields)
|
42
|
+
```
|
43
|
+
|
44
|
+
## Development Phases
|
45
|
+
|
46
|
+
### Phase 1: Foundation Setup
|
47
|
+
**Branch**: `feature/structured-config`
|
48
|
+
|
49
|
+
1. **Dependencies**
|
50
|
+
- Add to Gemfile:
|
51
|
+
```ruby
|
52
|
+
gem 'dry-configurable', '~> 1.0'
|
53
|
+
gem 'dry-validation', '~> 1.10'
|
54
|
+
# dry-schema will be installed automatically as dependency
|
55
|
+
```
|
56
|
+
- Run `bundle install`
|
57
|
+
|
58
|
+
2. **Extract and Enhance Options Class**
|
59
|
+
- File: `lib/fasti/options.rb`
|
60
|
+
- Extract `Options = Data.define(:format, :start_of_week, :country, :style)` from CLI class
|
61
|
+
- Add comprehensive option parsing responsibility:
|
62
|
+
```ruby
|
63
|
+
def self.parse(argv)
|
64
|
+
# Parse remaining command line arguments (positional args handled separately)
|
65
|
+
# Load environment variables
|
66
|
+
# Load configuration file
|
67
|
+
# Merge with priority: CLI options > Config file > Environment > Defaults
|
68
|
+
# Return [remaining_args, options_instance]
|
69
|
+
end
|
70
|
+
```
|
71
|
+
- Move validation methods from CLI class (except month/year validation)
|
72
|
+
- Move environment detection from CLI class
|
73
|
+
|
74
|
+
3. **Create Configuration Class**
|
75
|
+
- File: `lib/fasti/config.rb`
|
76
|
+
- Extend `Dry::Configurable`
|
77
|
+
- Define settings with defaults (no month/year settings):
|
78
|
+
```ruby
|
79
|
+
setting :format, default: :month
|
80
|
+
setting :country, default: -> { detect_country_from_locale || :us }
|
81
|
+
setting :start_of_week, default: :sunday
|
82
|
+
setting :style, default: {}
|
83
|
+
```
|
84
|
+
|
85
|
+
4. **Create Validation Contract**
|
86
|
+
- File: `lib/fasti/config_contract.rb`
|
87
|
+
- Define schema and custom rules (no month/year validation):
|
88
|
+
```ruby
|
89
|
+
class Fasti::ConfigContract < Dry::Validation::Contract
|
90
|
+
params do
|
91
|
+
optional(:format).value(included_in?: [:month, :quarter, :year])
|
92
|
+
optional(:country).value(:symbol)
|
93
|
+
optional(:start_of_week).value(included_in?: VALID_WEEKDAYS)
|
94
|
+
optional(:style).hash
|
95
|
+
end
|
96
|
+
|
97
|
+
rule(:country) do
|
98
|
+
# Custom validation for country codes
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
### Phase 2: Configuration Loading
|
104
|
+
5. **Ruby Config File Loading**
|
105
|
+
- Modify `CLI#load_config_options` method
|
106
|
+
- Change from shell argument parsing to Ruby file evaluation
|
107
|
+
- Add safety measures for code execution
|
108
|
+
- Handle syntax errors gracefully
|
109
|
+
|
110
|
+
6. **Configuration Validation**
|
111
|
+
- Integrate validation contract
|
112
|
+
- Provide user-friendly error messages
|
113
|
+
- Handle validation failures gracefully
|
114
|
+
|
115
|
+
### Phase 3: Integration
|
116
|
+
7. **Simplify CLI Class**
|
117
|
+
- Replace complex option parsing with `Options.parse(argv)`
|
118
|
+
- Remove moved methods (validation, environment detection, option parsing)
|
119
|
+
- Focus CLI on calendar generation and output
|
120
|
+
- Maintain backward compatibility of command-line interface
|
121
|
+
|
122
|
+
8. **Finalize Options Integration**
|
123
|
+
- Integrate Options.parse() with dry-configurable system
|
124
|
+
- Ensure proper error handling for invalid configurations
|
125
|
+
- Test integration between Options parsing and validation
|
126
|
+
- Maintain compatibility with Calendar and Formatter classes
|
127
|
+
|
128
|
+
### Phase 4: Testing and Documentation
|
129
|
+
9. **Comprehensive Testing**
|
130
|
+
- Test configuration loading and validation
|
131
|
+
- Test priority logic (CLI overrides config file)
|
132
|
+
- Test error handling for invalid configurations
|
133
|
+
- Test backward compatibility
|
134
|
+
|
135
|
+
10. **Update Documentation**
|
136
|
+
- README.md: New configuration format examples
|
137
|
+
- Migration guide from old format
|
138
|
+
- Error message explanations
|
139
|
+
|
140
|
+
11. **Quality Assurance**
|
141
|
+
- RuboCop compliance
|
142
|
+
- All tests passing
|
143
|
+
- Performance impact assessment
|
144
|
+
|
145
|
+
### Phase 5: Deployment
|
146
|
+
12. **Create Pull Request**
|
147
|
+
- Comprehensive description of changes
|
148
|
+
- Migration instructions
|
149
|
+
- Breaking changes documentation
|
150
|
+
|
151
|
+
## Technical Implementation Details
|
152
|
+
|
153
|
+
### Configuration File Location
|
154
|
+
- Remains: `~/.config/fastirc` (XDG compliant)
|
155
|
+
- Format changes from shell arguments to Ruby DSL
|
156
|
+
|
157
|
+
### Validation Rules
|
158
|
+
```ruby
|
159
|
+
# Format validation
|
160
|
+
format: [:month, :quarter, :year]
|
161
|
+
|
162
|
+
# Country validation
|
163
|
+
country: Valid ISO country codes or symbols
|
164
|
+
|
165
|
+
# Start of week validation
|
166
|
+
start_of_week: [:sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday]
|
167
|
+
|
168
|
+
# Style validation
|
169
|
+
style: Hash with valid day types and style attributes
|
170
|
+
|
171
|
+
# Note: Month/year validation removed - handled by positional arguments
|
172
|
+
```
|
173
|
+
|
174
|
+
### Error Handling
|
175
|
+
- Configuration file syntax errors
|
176
|
+
- Invalid configuration values
|
177
|
+
- Missing required dependencies
|
178
|
+
- Graceful fallback to defaults
|
179
|
+
|
180
|
+
### Implementation Notes
|
181
|
+
- No backward compatibility needed (pre-release project)
|
182
|
+
- Direct transition to new Ruby-based format
|
183
|
+
- Focus on clear documentation for new format
|
184
|
+
|
185
|
+
## Configuration Format Change
|
186
|
+
Since this project hasn't been officially released yet, we can change the configuration format without backward compatibility concerns.
|
187
|
+
|
188
|
+
### Configuration Format
|
189
|
+
```bash
|
190
|
+
# Old format (~/.config/fastirc) - after positional args implementation
|
191
|
+
--format quarter --country JP --start-of-week monday
|
192
|
+
|
193
|
+
# New format (~/.config/fastirc)
|
194
|
+
configure do |config|
|
195
|
+
config.format = :quarter
|
196
|
+
config.country = :JP
|
197
|
+
config.start_of_week = :monday
|
198
|
+
end
|
199
|
+
```
|
200
|
+
|
201
|
+
## Risk Assessment
|
202
|
+
- **Low Risk**: Pre-release project allows breaking changes
|
203
|
+
- **Low Risk**: Options structure simplified by positional args implementation
|
204
|
+
- **Low Risk**: CLI interface for non-month/year options unchanged
|
205
|
+
- **Mitigation**: Clear documentation and helpful error messages
|
206
|
+
|
207
|
+
## Success Criteria
|
208
|
+
- [ ] All existing functionality preserved
|
209
|
+
- [ ] New Ruby-based configuration working
|
210
|
+
- [ ] Comprehensive validation with clear error messages
|
211
|
+
- [ ] Documentation updated with examples
|
212
|
+
- [ ] All tests passing
|
213
|
+
- [ ] Performance maintained or improved
|
214
|
+
- [ ] Documentation updated with new configuration format examples
|
215
|
+
|
216
|
+
## Files to Modify
|
217
|
+
- `lib/fasti/cli.rb` - Configuration loading logic
|
218
|
+
- `lib/fasti.rb` - Add new config class require
|
219
|
+
- `Gemfile` - Add dry-validation dependency
|
220
|
+
- `README.md` - Update configuration documentation
|
221
|
+
- `spec/fasti/cli_spec.rb` - Update tests
|
222
|
+
|
223
|
+
## Files to Create
|
224
|
+
- `lib/fasti/options.rb` - Extracted Options class
|
225
|
+
- `lib/fasti/config.rb` - Main configuration class
|
226
|
+
- `lib/fasti/config_contract.rb` - Validation contract
|
227
|
+
- `spec/fasti/options_spec.rb` - Options tests
|
228
|
+
- `spec/fasti/config_spec.rb` - Configuration tests
|
229
|
+
- `spec/fasti/config_contract_spec.rb` - Validation tests
|
230
|
+
|
231
|
+
---
|
232
|
+
*This plan serves as a comprehensive roadmap for implementing dry-configurable integration while maintaining core functionality.*
|
data/examples/config.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Fasti Configuration Example
|
4
|
+
# This file shows how to configure fasti using dry-configurable
|
5
|
+
# Place this file at ~/.config/fasti/config.rb (or other XDG-compliant location)
|
6
|
+
|
7
|
+
Fasti.configure do |config|
|
8
|
+
# Basic calendar format and appearance
|
9
|
+
config.format = :month # :month, :quarter, :year
|
10
|
+
config.start_of_week = :monday # :sunday, :monday, etc.
|
11
|
+
config.country = :jp # ISO country code for holidays
|
12
|
+
|
13
|
+
# Style configuration using structured hash format
|
14
|
+
config.style = {
|
15
|
+
# Weekday styles
|
16
|
+
sunday: {
|
17
|
+
foreground: :red,
|
18
|
+
bold: true
|
19
|
+
},
|
20
|
+
|
21
|
+
monday: {
|
22
|
+
foreground: :blue
|
23
|
+
},
|
24
|
+
|
25
|
+
saturday: {
|
26
|
+
foreground: :cyan,
|
27
|
+
bold: true
|
28
|
+
},
|
29
|
+
|
30
|
+
# Special day styles
|
31
|
+
holiday: {
|
32
|
+
foreground: :red,
|
33
|
+
background: :yellow,
|
34
|
+
bold: true,
|
35
|
+
inverse: true
|
36
|
+
},
|
37
|
+
|
38
|
+
today: {
|
39
|
+
background: :green,
|
40
|
+
bold: true,
|
41
|
+
underline: :double
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Examples of different style attribute combinations:
|
47
|
+
#
|
48
|
+
# Color attributes:
|
49
|
+
# - foreground: :red, :blue, :green, :yellow, :magenta, :cyan, :white, :black, :default
|
50
|
+
# - foreground: "#FF0000", "#F00", "FF0000", "F00" (hex colors in various formats)
|
51
|
+
# - background: (same options as foreground)
|
52
|
+
#
|
53
|
+
# Boolean attributes:
|
54
|
+
# - bold: true/false
|
55
|
+
# - italic: true/false
|
56
|
+
# - faint: true/false
|
57
|
+
# - inverse: true/false
|
58
|
+
# - blink: true/false
|
59
|
+
# - hide: true/false
|
60
|
+
# - overline: true/false
|
61
|
+
#
|
62
|
+
# Special attributes:
|
63
|
+
# - underline: true/false/:double
|
64
|
+
|
65
|
+
# Alternative: Default-like minimal styling
|
66
|
+
# Fasti.configure do |config|
|
67
|
+
# config.format = :month
|
68
|
+
# config.style = {
|
69
|
+
# sunday: { bold: true },
|
70
|
+
# holiday: { bold: true },
|
71
|
+
# today: { inverse: true }
|
72
|
+
# }
|
73
|
+
# end
|
74
|
+
|
75
|
+
# Alternative: No styling (plain text)
|
76
|
+
# Fasti.configure do |config|
|
77
|
+
# config.format = :quarter
|
78
|
+
# config.country = :us
|
79
|
+
# # style defaults to nil (no custom styling)
|
80
|
+
# end
|