Complete guide for contributing to VimMaster. Architecture overview, APIs, and development setup.
# Clone the repository git clone https://github.com/renzorlive/vimmaster.git cd vimmaster # Switch to development branch git checkout advanced-testing # Open in browser open index.html # macOS start index.html # Windows xdg-open index.html # Linux
VimMaster is built with a modular architecture where each module has a specific responsibility:
// Main application modules js/ โโโ main.js // Application entry point and initialization โโโ game-state.js // Centralized state management โโโ levels.js // Level definitions and progression logic โโโ vim-engine.js // Core Vim command processing โโโ ui-components.js // UI rendering and user interactions โโโ progress-system.js // Progress tracking and persistence โโโ challenge-mode.js // Timed challenges and competitions โโโ cheat-mode.js // Hint system and help functionality
// Typical command execution flow
User Input โ Vim Engine โ Game State โ UI Update โ Level Validation
vimmaster/ โโโ index.html # Main game interface โโโ css/ โ โโโ main.css # Game styling and themes โโโ js/ # Core JavaScript modules โ โโโ main.js # App initialization โ โโโ game-state.js # State management โ โโโ levels.js # Level definitions โ โโโ vim-engine.js # Vim command processor โ โโโ ui-components.js # UI components โ โโโ progress-system.js # Progress tracking โ โโโ challenge-mode.js # Challenge system โ โโโ cheat-mode.js # Hint system โโโ docs/ # Documentation website โโโ tests/ # Test files โโโ README.md # Project overview
Centralized state management for the entire game. All game data flows through this class.
| Property | Type | Description |
|---|---|---|
content |
string[] |
Array of text lines in the editor |
cursor |
{row: number, col: number} |
Current cursor position (0-indexed) |
mode |
'NORMAL' | 'INSERT' | 'VISUAL' |
Current Vim mode |
currentLevel |
number |
Current level index (0-based) |
// Initialize game state const gameState = new GameState(); // Set initial content gameState.content = [ "Hello, World!", "Welcome to VimMaster" ]; // Move cursor gameState.cursor = { row: 0, col: 7 }; // Switch to insert mode gameState.mode = 'INSERT';
Each level is defined as an object with specific properties that control the learning experience.
| Property | Required | Description |
|---|---|---|
name |
Yes | Display name for the level |
instructions |
Yes | What the player needs to accomplish |
initialContent |
Yes | Starting text content for the level |
validation |
Yes | Function that returns true when level is complete |
setup |
No | Function to initialize level-specific state |
hints |
No | Array of progressive hints for the level |
// Example: New level for teaching 'f' command const findCharacterLevel = { name: "Find Character", instructions: "Use 'f' followed by a character to jump to it. Find the 'x' in the line below.", initialContent: [ "The quick brown fox jumps over the lazy dog" ], setup: function(gameState) { // Set cursor to beginning of line gameState.cursor = { row: 0, col: 0 }; gameState.mode = 'NORMAL'; }, validation: function(gameState) { // Check if cursor is on the 'x' character const line = gameState.content[0]; const cursorChar = line[gameState.cursor.col]; return cursorChar === 'x' && gameState.usedFindCommand; }, hints: [ "Try typing 'f' followed by the character you want to find", "The 'f' command moves the cursor to the next occurrence of a character", "Type 'fx' to jump to the letter 'x'" ] };
// In levels.js, add your level to the levels array const levels = [ // ... existing levels findCharacterLevel, // ... more levels ];
// Test the level by playing through it // Ensure validation works correctly // Check that hints are helpful // Verify the learning objective is clear
The Vim engine processes keyboard input and executes Vim commands based on the current mode.
// Example: Adding the 'f' (find) command handleNormalMode(key) { switch(key) { case 'f': // Enter find mode, wait for next character this.waitingForFindChar = true; break; default: if (this.waitingForFindChar) { this.findCharacter(key); this.waitingForFindChar = false; } } } findCharacter(char) { const currentLine = this.gameState.content[this.gameState.cursor.row]; const startCol = this.gameState.cursor.col + 1; const foundIndex = currentLine.indexOf(char, startCol); if (foundIndex !== -1) { this.gameState.cursor = { row: this.gameState.cursor.row, col: foundIndex }; this.gameState.usedFindCommand = true; } }
// Test command in isolation function testFindCommand() { const gameState = new GameState(); gameState.content = ["hello world"]; gameState.cursor = { row: 0, col: 0 }; // Simulate 'fw' command const engine = new VimEngine(gameState); engine.processKeypress({ key: 'f' }); engine.processKeypress({ key: 'w' }); // Verify cursor moved to 'w' console.assert(gameState.cursor.col === 6, "Find command failed"); }
# 1. Fork and clone the repository git clone https://github.com/YOUR_USERNAME/vimmaster.git cd vimmaster # 2. Create a feature branch git checkout -b feature/new-level-find-command # 3. Make your changes # - Add new level or command # - Test thoroughly # - Update documentation if needed # 4. Commit with descriptive message git add . git commit -m "Add level 17: Find character command (f)" # 5. Push and create pull request git push origin feature/new-level-find-command