gentleman-trainer
Vim Trainer RPG system patterns for Gentleman.Dots. Trigger: When editing files in installer/internal/tui/trainer/, adding exercises, modules, or game mechanics.
When & Why to Use This Skill
This Claude skill is designed to manage and expand the Vim Trainer RPG system within the Gentleman.Dots project. It provides a comprehensive framework for creating interactive Vim exercises, designing gamified progression modules, and implementing automated validation logic to help users master Vim commands through a structured, terminal-based learning environment.
Use Cases
- Developing new Vim training modules by defining ModuleID constants and configuring sequential unlock orders for a gamified learning path.
- Designing complex 'boss fight' challenges that chain multiple exercises together to test user proficiency under time constraints.
- Creating structured Vim exercises with multiple valid solutions, optimal command paths, and educational hints for real-time feedback.
- Maintaining the Vim command simulator and validation logic to ensure accurate assessment of user inputs within the TUI trainer.
- Expanding the RPG progression system by implementing new lesson types, practice modes, and difficulty scaling (Levels 1-10).
| name | gentleman-trainer |
|---|---|
| description | > |
| Trigger | When editing files in installer/internal/tui/trainer/, adding exercises, modules, or game mechanics. |
| license | Apache-2.0 |
| author | gentleman-programming |
| version | "1.0" |
When to Use
Use this skill when:
- Adding new Vim training modules
- Creating exercises or boss fights
- Modifying progression/unlock system
- Working on the Vim command simulator
- Adding practice mode features
Critical Patterns
Pattern 1: ModuleID Constants
All modules MUST be defined as ModuleID constants in types.go:
type ModuleID string
const (
ModuleHorizontal ModuleID = "horizontal"
ModuleVertical ModuleID = "vertical"
ModuleTextObjects ModuleID = "textobjects"
ModuleChangeRepeat ModuleID = "cgn"
ModuleSubstitution ModuleID = "substitution"
ModuleRegex ModuleID = "regex"
ModuleMacros ModuleID = "macros"
// Add new modules here
)
Pattern 2: Exercise Structure
Every exercise follows this structure:
type Exercise struct {
ID string // "horizontal_001"
Module ModuleID // Parent module
Level int // 1-10 difficulty
Type ExerciseType // lesson, practice, boss
Code []string // Lines of code shown
CursorPos Position // Initial cursor
CursorTarget *Position // Target position (movement exercises)
Mission string // What user must do
Solutions []string // ALL valid solutions
Optimal string // Best/shortest solution
Hint string // Help text
Explanation string // Post-answer teaching
TimeoutSecs int // Before showing solution
Points int // Base score
}
Pattern 3: Module Unlock Order
Modules unlock sequentially - user must defeat boss to unlock next:
var moduleUnlockOrder = []ModuleID{
ModuleHorizontal, // Always unlocked
ModuleVertical, // After horizontal boss
ModuleTextObjects, // After vertical boss
ModuleChangeRepeat, // After textobjects boss
// ... etc
}
Pattern 4: Progression Flow
Lessons (sequential) → Practice (80% accuracy) → Boss Fight → Next Module
Decision Tree
Adding new module?
├── Add ModuleID constant in types.go
├── Add to moduleUnlockOrder slice
├── Add ModuleInfo in GetAllModules()
├── Create exercises_{module}.go file
├── Implement GetLessons(moduleID)
├── Implement GetBoss(moduleID)
└── Add practice exercises
Adding exercises?
├── Create Exercise with unique ID format: "{module}_{number}"
├── Provide multiple Solutions (all valid answers)
├── Set Optimal to shortest/best solution
├── Include Hint for learning
└── Add Explanation for post-answer
Adding boss fight?
├── Create BossExercise in exercises_{module}.go
├── Add 5-7 BossSteps (exercise chain)
├── Set Lives (usually 3)
├── Include variety of module skills
└── Return from GetBoss(moduleID)
Code Examples
Example 1: Creating a Module's Exercises File
// exercises_newmodule.go
package trainer
// NewModule lessons
func getNewModuleLessons() []Exercise {
return []Exercise{
{
ID: "newmodule_001",
Module: ModuleNewModule,
Level: 1,
Type: ExerciseLesson,
Code: []string{"function example() {", " return true;", "}"},
CursorPos: Position{Line: 0, Col: 0},
Mission: "Use 'xx' to delete two characters",
Solutions: []string{"xx", "2x", "dl dl"},
Optimal: "xx",
Hint: "x deletes character under cursor",
Explanation: "x is Vim's character delete. 2x or xx deletes two.",
Points: 10,
},
// ... more exercises
}
}
Example 2: Registering Module in GetAllModules
func GetAllModules() []ModuleInfo {
return []ModuleInfo{
// ... existing modules
{
ID: ModuleNewModule,
Name: "New Module",
Icon: "🆕",
Description: "Commands: xx, yy, zz",
BossName: "The New Boss",
},
}
}
Example 3: Boss Fight Structure
func getNewModuleBoss() *BossExercise {
return &BossExercise{
ID: "newmodule_boss",
Module: ModuleNewModule,
Name: "The New Boss",
Lives: 3,
Steps: []BossStep{
{
Exercise: Exercise{
ID: "newmodule_boss_1",
Module: ModuleNewModule,
Code: []string{"challenge code here"},
CursorPos: Position{Line: 0, Col: 0},
Mission: "First boss challenge",
Solutions: []string{"w", "W"},
Optimal: "w",
},
TimeLimit: 10,
},
// ... more steps (5-7 total)
},
}
}
Example 4: Exercise Validation
// Validation checks if answer is in Solutions
func ValidateAnswer(exercise *Exercise, answer string) bool {
answer = strings.TrimSpace(answer)
for _, solution := range exercise.Solutions {
if answer == solution {
return true
}
}
// Also check via simulator for creative solutions
return validateViaSimulator(exercise, answer)
}
Exercise Guidelines
Good Exercise Design
- Clear Mission: User knows exactly what to do
- Multiple Solutions: Accept all valid Vim ways
- Optimal Marked: Teach the best approach
- Progressive Difficulty: Level 1-10 within module
- Real Code: Use realistic code snippets
Solutions Array Rules
// GOOD: Accept all valid variations
Solutions: []string{"w", "W", "e", "E", "f "},
// BAD: Only accept one way
Solutions: []string{"w"},
Exercise ID Format
{module}_{number} → "horizontal_001"
{module}_boss_{step} → "horizontal_boss_1"
Commands
cd installer && go test ./internal/tui/trainer/... # Run all trainer tests
cd installer && go test -run TestExercise # Test exercises
cd installer && go test -run TestSimulator # Test Vim simulator
cd installer && go test -run TestProgression # Test unlock system
Resources
- Types: See
installer/internal/tui/trainer/types.gofor data structures - Exercises: See
installer/internal/tui/trainer/exercises_*.gofor patterns - Simulator: See
installer/internal/tui/trainer/simulator.gofor Vim emulation - Validation: See
installer/internal/tui/trainer/validation.gofor answer checking - Stats: See
installer/internal/tui/trainer/stats.gofor persistence