| name | gentleman-trainer |
| description | Vim Trainer RPG system patterns for Gentleman.Dots. Trigger: When editing files in installer/internal/tui/trainer/, adding exercises, modules, or game mechanics.
|
| license | Apache-2.0 |
| metadata | {"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"
)
Pattern 2: Exercise Structure
Every exercise follows this structure:
type Exercise struct {
ID string
Module ModuleID
Level int
Type ExerciseType
Code []string
CursorPos Position
CursorTarget *Position
Mission string
Solutions []string
Optimal string
Hint string
Explanation string
TimeoutSecs int
Points int
}
Pattern 3: Module Unlock Order
Modules unlock sequentially - user must defeat boss to unlock next:
var moduleUnlockOrder = []ModuleID{
ModuleHorizontal,
ModuleVertical,
ModuleTextObjects,
ModuleChangeRepeat,
}
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
package trainer
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,
},
}
}
Example 2: Registering Module in GetAllModules
func GetAllModules() []ModuleInfo {
return []ModuleInfo{
{
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,
},
},
}
}
Example 4: Exercise Validation
func ValidateAnswer(exercise *Exercise, answer string) bool {
answer = strings.TrimSpace(answer)
for _, solution := range exercise.Solutions {
if answer == solution {
return true
}
}
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
Solutions: []string{"w", "W", "e", "E", "f "},
Solutions: []string{"w"},
Exercise ID Format
{module}_{number} → "horizontal_001"
{module}_boss_{step} → "horizontal_boss_1"
Commands
cd installer && go test ./internal/tui/trainer/...
cd installer && go test -run TestExercise
cd installer && go test -run TestSimulator
cd installer && go test -run TestProgression
Resources
- Types: See
installer/internal/tui/trainer/types.go for data structures
- Exercises: See
installer/internal/tui/trainer/exercises_*.go for patterns
- Simulator: See
installer/internal/tui/trainer/simulator.go for Vim emulation
- Validation: See
installer/internal/tui/trainer/validation.go for answer checking
- Stats: See
installer/internal/tui/trainer/stats.go for persistence