You are assisting with the development of SimpleIDE - a lightweight, professional VB.NET IDE built with GTK# 3 on Linux using .NET 8.0. The IDE is similar to VS Code in functionality and includes:
- Multi-file tabbed editor with VB.NET syntax highlighting
- Project Explorer with .vbproj file parsing
- Build system integration with async dotnet CLI operations
- Dockable build output panel with error/warning navigation
- Line numbers with click-to-select and drag-to-select functionality
- Settings window with theme support and persistence
- Enhanced status bar with cursor position, language mode, and encoding
- Keyboard shortcuts (Ctrl+S, Ctrl+Y, Ctrl+G, Ctrl+A, F6, Shift+F6, Ctrl+Shift+B)
- Welcome splash screen with scaled icon when no files are open
- Undo/Redo system (Ctrl+Z, Ctrl+R) with per-character tracking
- API integration for Claude.AI, providing implementation for multiple chats, and Claude projects
- Integrated Help System
- Variables:
l= Local,p= Private field,v= Parameter,g= Global - Types:
i= Integer,b= Boolean (when needed for clarity) - Default is String, no prefix needed
- Objects get capital letter:
lButton,pTreeView,vTextBuffer
Public Enum ExampleEnum
eUnspecified
eFirstValue
eSecondValue
eLastValue
End Enum- Always start with
eUnspecified - Always end with
eLastValue - All values prefixed with
e
- Method names: PascalCase (
SaveSettings,LoadColorPreferences) - Events:
On[Event]pattern (OnColorChanged,OnSettingsApplied) - Event handlers: Use
AddHandlersyntax, notHandles
- Always fully qualify
System.IO.Path(GTK has its own Path) - Use
Environment.NewLinenotvbNewLine - Use CSS providers for fonts, not deprecated
ModifyFont() - Always call
ShowAll()after adding GTK widgets - Use
StyleProviderPriorityas UInteger values (USER = 800) - Cast Gdk.Key values when comparing to KeyPressEventArgs.Event.Key to avoid ambiguity
Try-Catchblocks everywhere withConsole.WriteLinefor debugging- Comments: Use
' TODO:,' FIXED:,' NOTE:prefixes - No floating code: All code must be inside methods/properties
- One class per file: Each class gets its own .vb file
- DO NOT GUESS METHOD NAMES WHEN PROVIDING CHANGES TO CODE!
- Research the actual method names that exist in the codebase.
- Separation of concerns
- Event-driven communication between forms
- Use partial classes for large forms (
MainWindow.*.vbpattern) - Centralized persistence logic in
SettingsManager
- GTK# 3.24.24.38 on .NET 8.0
- VB.NET with proper namespace structure (root
SimpleIDEnamespace) - Linux file paths (use
/not\) - Resources embedded in assembly
- TextBuffer ambiguity: Use
SelectRange+DeleteSelectioninstead ofDelete - Line numbers not showing: Check
NoShowAll, parent visibility, and size allocation - Build output paths: Handle both absolute and relative paths
- Icon loading: Resource name is
SimpleIDE.icon.png(notSimpleIDE.Resources.icon.png)
- Incremental development: Get each feature working perfectly before moving to next
- Test mentally before suggesting implementation
- Maintain existing architecture patterns
- Preserve all working functionality
- Use existing Models and Utilities where possible
- Follow ALL coding conventions without exception
- Use proper partial class structure for MainWindow extensions
- Implement comprehensive error handling with try-catch blocks
- Use the existing CssHelper utility for styling
- Maintain the event-driven architecture
- Test that new code integrates with existing systems
- This project has a root namespace:
SimpleIDE - NEVER declare the root namespace in code files
- Files in the root namespace should have NO namespace declaration
- Files in sub-namespaces should declare ONLY the sub-namespace part
' File in root namespace (SimpleIDE) - NO namespace declaration
Public Class MainWindow
' This class is automatically in SimpleIDE namespace
End Class
' File in sub-namespace (SimpleIDE.Utilities) - declare ONLY "Utilities"
Namespace Utilities
Public Class FileHelper
' This class is automatically in SimpleIDE.Utilities
End Class
End Namespace
' File in nested sub-namespace (SimpleIDE.Models.Syntax) - declare ONLY "Models.Syntax"
Namespace Models.Syntax
Public Class SyntaxNode
' This class is automatically in SimpleIDE.Models.Syntax
End Class
End NamespaceImport Rules
ALWAYS use full imports from within the project NEVER use fully qualified names for project type declarations The root namespace is automatically available
Import Examples:
' CORRECT - importing from within the project
Imports SimpleIDE.Utilities ' include root namespace
Imports SimpleIDE.Models ' include root namespace
' WRONG - never write these
Imports Utilities ' Doesn't import SimpleIDE.Utilities
Imports Models ' Doesn't import SimpleIDE.Models
Imports Widgets.Editors ' Doesn't import SimpleIDE.Widgets.Editors
' CORRECT - using types from the project
Dim lHelper As New FileHelper() ' From SimpleIDE.Utilities
Dim lColorSet As New SyntaxColorSet() ' From SimpleIDE.Models
' WRONG - never use fully qualified names for project types
Dim lHelper As New SimpleIDE.Utilities.FileHelper() ' Don't do this
Dim lColorSet As New SimpleIDE.Models.SyntaxColorSet() ' Don't do thisKey Rules:
Root namespace (SimpleIDE) is NEVER declared in namespace statements Sub-namespaces declare ONLY their relative path from root Imports use full paths with the root namespace Never fully qualify types from within the project
Search ALL project files with every prompt to understand the context of code implementation and suggestions. Do not use non-existent member declarations in examples. Be aware of the potential for mistakes and attempt to avoid mistakes that can result in incomplete or incorrect solutions and unnecessarily waste James' tokens. If your research reveals a better implementation, provide information about it to the user, and allow the user to determine if he wishes you to provide the implementation.
AGAIN - Perform Comprehensive Research
First, search for and identify the actual compiler error messages before proposing any solutions.
EVERY public or protected member MUST have XML documentation comments:
- Classes, Structures, Modules, Interfaces
- Properties (including auto-properties)
- Methods, Functions, Subs
- Events
- Fields (if public/protected)
- Enums and their members
- Constructors
''' <summary>
''' Brief description of what the member does (REQUIRED)
''' </summary>
''' <param name="vParameterName">Description of parameter purpose and valid values</param>
''' <returns>Description of return value (for Functions only)</returns>
''' <remarks>Optional: Additional implementation details or usage notes</remarks>
''' <example>Optional: Usage example</example>
''' <exception cref="ExceptionType">When this exception is thrown</exception>''' <summary>
''' Manages syntax highlighting and code parsing for VB.NET source files
''' </summary>
''' <remarks>
''' This class maintains the document structure and provides real-time parsing
''' </remarks>
Public Class CustomDrawingEditor''' <summary>
''' Loads a source file from disk and parses its content
''' </summary>
''' <param name="vFilePath">Full path to the source file to load</param>
''' <param name="vEncoding">Text encoding to use (defaults to UTF-8)</param>
''' <returns>True if successfully loaded and parsed, False otherwise</returns>
''' <exception cref="IOException">Thrown when file cannot be accessed</exception>
Public Function LoadFile(vFilePath As String, Optional vEncoding As Encoding = Nothing) As Boolean''' <summary>
''' Gets or sets whether the editor content has been modified since last save
''' </summary>
''' <value>True if modified, False if pristine</value>
Public Property IsModified As Boolean''' <summary>
''' Raised when the cursor position changes in the editor
''' </summary>
''' <param name="vLine">New line number (0-based)</param>
''' <param name="vColumn">New column position (0-based)</param>
Public Event CursorPositionChanged(vLine As Integer, vColumn As Integer)''' <summary>
''' Specifies the type of syntax node in the parse tree
''' </summary>
Public Enum NodeType
''' <summary>Unknown or unspecified node type</summary>
eUnspecified
''' <summary>Class declaration node</summary>
eClass
''' <summary>Method or function node</summary>
eMethod
''' <summary>Property declaration node</summary>
eProperty
''' <summary>Sentinel value for enum bounds checking</summary>
eLastValue
End Enum-
Summaries must be actionable:
- Methods: Start with a verb ("Loads", "Saves", "Calculates", "Validates")
- Properties: Start with "Gets", "Sets", or "Gets or sets"
- Classes: Describe the responsibility ("Manages", "Represents", "Provides")
-
Parameter descriptions must include:
- Purpose of the parameter
- Valid value ranges or constraints
- Special values (Nothing, empty string, etc.)
- Units if applicable (pixels, milliseconds, etc.)
-
Return value descriptions must specify:
- What the value represents
- Special return values (Nothing, -1, empty collection)
- Conditions for different return values
-
Be concise but complete:
- Summary: One sentence, no period at end
- Parameters/Returns: Complete sentences with periods
- Remarks: Use for important implementation details
The hover tooltips will display:
- Summary as the primary description
- Parameters when hovering over method calls
- Returns information for functions
- Remarks for additional context
- Exceptions to warn about error conditions
ALL members including private ones MUST be documented - tooltips appear when hovering over ANY identifier in the code:
''' <summary>
''' Internal helper to validate line boundaries
''' </summary>
''' <param name="vLine">Line number to validate (0-based)</param>
''' <returns>True if line is within document bounds, False otherwise</returns>
Private Function IsValidLine(vLine As Integer) As BooleanImportant: When a developer hovers over any identifier in the code editor:
- The tooltip displays the XML documentation regardless of access level
- Private members show their documentation when referenced anywhere in the code
- This helps with understanding implementation details while coding
These XML comments are parsed by the VBParser and stored in the SyntaxNode structure, then accessed by the IntelliSense engine to provide hover tooltips and parameter hints. Missing documentation will result in no tooltip information being available.
Method Artifact Format (CRITICAL)
When providing code changes for individual methods, ALWAYS create separate artifacts for each method with the following format:
For REPLACING existing methods:
' Replace: [FullyQualifiedName]
[method code only - no imports, namespace, or class wrapper]Example:
' Replace: SimpleIDE.Editors.CustomDrawingEditor.JoinLines
Public Sub JoinLines(vLine As Integer)
' method implementation
End SubFor ADDING new methods:
' Add: [FullyQualifiedName]
' To: [PartialFileName]
[method code only - no imports, namespace, or class wrapper]Example:
' Add: SimpleIDE.Editors.CustomDrawingEditor.GetTextInRange
' To: CustomDrawingEditor.Helpers.vb
Friend Function GetTextInRange(vStartLine As Integer, vStartColumn As Integer,
vEndLine As Integer, vEndColumn As Integer) As String
' method implementation
End FunctionRules:
One method per artifact - Never combine multiple methods in a single artifact Method name in artifact title - Use a descriptive title like "GetTextInRange Method" or "JoinLines (Updated)" No wrapper code - Never include Imports, Namespace, or Class declarations Fully qualified names - Always use complete namespace path to avoid ambiguity Clear action - Always specify "Replace:" or "Add:" File hint for additions - When adding new methods, specify which partial file
Workflow Support: These artifacts are designed to work with the IDE's Object Explorer integration:
User copies the fully qualified name from the comment User searches in Object Explorer User copies the entire artifact content User right-clicks the method node and selects "Replace Method With Clipboard Contents" (for replacements) Or adds to the specified file (for new methods)
This format will also enable future AI Assistant integration where these methods can be exposed as callable functions.
Claude has access to execute bash commands directly in the project directory through the MCP shell server configured in Claude Desktop. This tool is available as shell:shell_exec and runs commands with /home/jamesp/Projects/VbIDE as the working directory.
Common commands:
dotnet build- Build the projectdotnet run- Run the IDEdotnet clean- Clean build artifactsgit status- Check git status- Any bash command needed for development
Claude can read/write files in the project directory using the simpleide tools.
- First run
dotnet buildto see the current errors - Search project files to understand the context
- Provide complete fixed files (not fragments)
- Run
dotnet buildagain to verify the fix
- Always search for existing implementations first
- Maintain the established patterns (Hungarian notation, etc.)
- Test changes by building:
dotnet build - Provide complete files for replacement
- Run
dotnet runto reproduce the issue - Check relevant log files if any
- Search codebase for error messages
- Provide targeted fixes
- Complete file replacements preferred over snippets
- Production-ready code, not examples
- Follow existing architecture patterns
- Maintain separation of concerns
ALWAYS use the Filesystem:edit_file tool for modifying existing files.
DO NOT use str_replace - it has issues with file paths in this project.
The correct syntax is: Filesystem:edit_file with parameters:
path: full path to file (e.g., /home/jamesp/Projects/VbIDE/SomeFile.vb) edits: array of {oldText: "exact text to replace", newText: "replacement text"}
For file modifications:
- First use
Filesystem:read_fileorshell:shell_execwith grep to see the current content - Then use
Filesystem:edit_fileto make changes - The tool will show a diff of the changes
Example:
- WRONG: Using str_replace
- RIGHT: Using Filesystem:edit_file with exact text matches
-
Use
Filesystem:write_fileorcreate_filefor NEW files only -
Use
Filesystem:edit_filefor modifying EXISTING files -
Never add unnecessary files - prefer modifying existing files when possible
- ThemeManager holds the current
EditorThemeobject with color definitions EditorThemecontains properties likeBackgroundColor,ForegroundColor,CurrentLineColor, etc.- All custom widgets MUST use
ThemeManager.GetCurrentThemeObject()to retrieve colors
CORRECT approach:
Private pThemeManager As ThemeManager Public Sub SetThemeManager(vThemeManager As ThemeManager) pThemeManager = vThemeManager AddHandler pThemeManager.ThemeChanged, AddressOf OnThemeChanged ApplyCurrentTheme() End Sub Private Sub OnThemeChanged(vTheme As EditorTheme) ApplyCurrentTheme() End Sub Private Sub ApplyCurrentTheme() Dim lTheme As EditorTheme = pThemeManager.GetCurrentThemeObject() ' Map EditorTheme colors to widget-specific colors pBackgroundColor = ParseColor(lTheme.BackgroundColor) pTextColor = ParseColor(lTheme.ForegroundColor) QueueDraw() End Sub
WRONG approach - DO NOT hardcode theme colors:
' ❌ NEVER do this - hardcoded colors based on theme names Select Case lThemeName.ToLower() Case "dark" pBackgroundColor = New RGBA() with {.Red = 0.15, ...}
Theme Color Mapping Guidelines
- Use ParseColor() to convert hex strings to RGBA
- Use DarkenColor() and LightenColor() for derived colors
- Map EditorTheme properties to widget-specific colors consistently
- Always subscribe to ThemeChanged event for dynamic updates
/SimpleIDE ├── Program.vb # Entry point (root namespace) ├── MainWindow.vb # Main window (root namespace) ├── MainWindow..vb # Partial classes for MainWindow ├── /Editors # Text editors and specialized editors │ ├── CustomDrawingEditor.vb │ └── CustomDrawingEditor..vb # Partial classes ├── /Widgets # Reusable UI components │ ├── CustomDrawNotebook.vb │ ├── CustomDrawProjectExplorer.vb │ └── *Panel.vb # Various panel widgets ├── /Managers # Business logic and coordination │ ├── ThemeManager.vb │ ├── SettingsManager.vb │ ├── ProjectManager.vb │ └── BuildManager.vb ├── /Models # Data structures and DTOs │ ├── EditorTheme.vb │ ├── TabInfo.vb │ └── SyntaxColorSet.vb ├── /Utilities # Helper functions and tools │ ├── FileOperations.vb │ └── CssHelper.vb ├── /Syntax # Parsing and highlighting │ ├── VBTokenizer.vb │ └── CodeSenseEngine.vb ├── /Dialogs # Modal dialogs ├── /Interfaces # Interface definitions └── /AI # AI integration components
- Partial classes:
ClassName.Category.vb(e.g.,MainWindow.Build.vb) - Widgets:
CustomDraw[Name].vbfor custom-drawn controls - Managers:
[Responsibility]Manager.vb - One class per file (except partial classes)
When creating widgets with manual Cairo rendering:
-
Base Structure:
Partial Public Class CustomDrawWidget Inherits Box ' or DrawingArea Private pDrawingArea As DrawingArea Private pThemeManager As ThemeManager Private pSettingsManager As SettingsManager
-
Initialization Pattern:
- Create DrawingArea in constructor
- Set event masks: ButtonPressMask, PointerMotionMask, etc.
- Wire up draw handler: AddHandler pDrawingArea.Drawn, AddressOf OnDraw
- Set CanFocus = True if widget needs keyboard input
- Drawing Method Template:
Private Sub OnDraw(vSender As Object, vArgs As DrawnArgs) Try Dim lContext As Cairo.Context = vArgs.Cr Dim lWidth As Integer = pDrawingArea.AllocatedWidth Dim lHeight As Integer = pDrawingArea.AllocatedHeight ' Drawing code here vArgs.RetVal = True Catch ex As Exception Console.WriteLine($"OnDraw error: {ex.Message}") End Try End Sub
- Resource Cleanup:
- Dispose Cairo contexts when done
- Unsubscribe from events in Dispose
- Clear pixbuf references
- Theme Integration:
- MUST implement SetThemeManager() method
- Subscribe to ThemeChanged event
- Retrieve colors from EditorTheme object (never hardcode)
- Call QueueDraw() when theme changes
- Partial Class Organization:
- .vb - Core structure, properties, public API
- .Drawing.vb - Cairo rendering code
- .Events.vb - Mouse/keyboard event handlers
- .Theme.vb - Theme integration
- .Navigation.vb - Navigation logic (if applicable)
Widgets should NOT create their own managers. Instead:
-
MainWindow creates managers in constructor:
pSettingsManager = New SettingsManager() pThemeManager = New ThemeManager(pSettingsManager) pProjectManager = New ProjectManager()
-
Managers passed to widgets via setter methods:
' In MainWindow initialization pProjectExplorer.SetThemeManager(pThemeManager) pProjectExplorer.SetProjectManager(pProjectManager)
- Widgets store manager references:
Public Sub SetThemeManager(vThemeManager As ThemeManager) pThemeManager = vThemeManager AddHandler pThemeManager.ThemeChanged, AddressOf OnThemeChanged ApplyCurrentTheme() End Sub
- ThemeManager holds the current
This ensures single instances and proper initialization order.
### 5. **Performance Guidelines**
## Performance Best Practices
### Cairo Drawing
- **Viewport culling**: Only draw visible items
```vb
If lItemY < pScrollOffset OrElse lItemY > pScrollOffset + lVisibleHeight Then
Return ' Skip off-screen items
End If
```
- Context management: Use Save()/Restore() for state isolation
- Dispose resources: Always dispose Pixbufs, Patterns, Gradients
GTK Performance
- Batch updates: Use QueueDraw() instead of multiple redraws
- Avoid ShowAll() on large hierarchies during updates
- Event throttling: Use timers for high-frequency events (mouse move)
- Lazy initialization: Create heavy widgets only when needed
String Operations
- Use StringBuilder for multiple concatenations
- Cache frequently accessed string properties
- Avoid repeated Split() operations on the same text
### 6. **Common Pitfalls**
## Common Mistakes to Avoid
### 1. TextBuffer Ambiguity
❌ `lBuffer.Delete(lStart, lEnd)` - Ambiguous
✅ `lBuffer.SelectRange(lStart, lEnd)` then `lBuffer.DeleteSelection(True, True)`
### 2. Hardcoded Theme Colors
❌ Setting colors based on theme name strings
✅ Retrieving colors from `EditorTheme` object via `ThemeManager`
### 3. ShowAll() Visibility Issues
❌ Calling `ShowAll()` then hiding specific widgets
✅ Set `NoShowAll = True` for widgets that should stay hidden
### 4. Path Separator Confusion
❌ Using `\` for paths (Windows style)
✅ Using `/` for paths or `System.IO.Path.Combine()`
### 5. Namespace Qualification
❌ `Imports Utilities` (without root namespace)
✅ `Imports SimpleIDE.Utilities`
### 6. Event Handler Memory Leaks
❌ Subscribing to events without unsubscribing in Dispose
✅ Always `RemoveHandler` in Dispose method
### 7. Conflicting Implementations
❌ Having multiple methods that do the same thing differently (like LoadThemeColors vs ApplyTheme)
✅ Single source of truth - one correct implementation