A comprehensive plugin for PyCharm that provides advanced support for the Harbour/Clipper programming language.
This plugin was implemented as vibe-coding project using OpenAI
O1
and Claude. For detailed development insights and experiences, see
the MAKING-OF.
- Installation
- Features
- Settings
- Roadmap
- Known Issues
- VS Code Users
- Building Plugin
- Development
- License
- Download the latest plugin from the releases page
- In PyCharm: Settings → Plugins → ⚙️ → Install Plugin from Disk...
- Select the downloaded plugin file and restart PyCharm
By default, PyCharm/IntelliJ has file size limits that may be too small for large Harbour projects. To work with files larger than 2.5 MB, you need to manually configure these limits:
- Go to Help → Edit Custom Properties
- Add the following lines to the file:
These values set the limits to 100 MB for code assistance and 200 MB for file opening.
idea.max.intellisense.filesize=102400 idea.max.content.load.filesize=204800 - Save the file and restart the IDE
Note: These are IDE-level settings that must be configured manually and cannot be changed by plugins at runtime.
- Syntax Highlighting - Complete color coding for Harbour/Clipper keywords, functions, and syntax
- Code Completion - Intelligent auto-completion for functions, methods, and variables
- Function Navigation - Go-to-declaration and reference resolution
- Rename Refactoring - Safe renaming of functions and variables across projects
- Structure View - Tree view of functions, procedures, and classes
- Code Formatting - Automatic code indentation and formatting
- Linting - Real-time code analysis and error detection
- Debugging - Full breakpoint debugging for console and GUI applications with database inspection
- Automatic Error Monitoring - Clickable stack traces for runtime errors
- Code Helpers - Quick actions to improve code quality and reduce typing
Full color coding support for Harbour/Clipper syntax with customizable color schemes. Keywords, functions, comments, strings, and operators are distinctly highlighted for better code readability.
Enhanced syntax highlighting with customizable color schemes
Intelligent auto-completion suggests functions, methods, variables, and Harbour commands as you type. Supports both built-in Harbour functions and user-defined functions from your project.
Smart auto-completion for Harbour functions and variables
Quickly navigate to function definitions with Ctrl+Click or Ctrl+B. The plugin resolves references across files for custom defined and built-in functions, variables, etc. For external harbour functions an external documentation link (configurable in the settings) will be opend.
Function navigation with external documentation links for built-in functions
Same applies for procedures, classes, methods and variables. Newly added function, procedures, etc. are added to the index once the file is saved.
Safely rename functions, procedures, and variables across your entire project with Shift+F6. All references are automatically updated while preserving code functionality.
Safe project-wide rename refactoring for functions and variables
The structure view panel (Alt+7) shows a tree overview of functions, procedures, classes, and variables in the current file for easy navigation.
Structure view showing project organization
Automatic code indentation and formatting follows Harbour conventions. Customize indentation, line breaks, and statement positioning in settings.
The Harbour plugin enables command-line formatting through PyCharm/IntelliJ's built-in CLI tools. This feature works automatically once the plugin is installed - no additional setup required.
How it works:
- PyCharm/IntelliJ IDEA provide the
formatcommand as part of their standard CLI tools - Our plugin registers the Harbour formatter with the IDE's formatting system
- When you run the format command on
.prgor.chfiles, the IDE uses our plugin's formatter - The IDE runs in headless mode (no GUI) to perform the formatting
# Format a single file
pycharm.sh format /path/to/file.prg
# Format all files in a directory recursively
pycharm.sh format -recursive /path/to/project
# Format with custom settings
pycharm.sh format -s /path/to/settings.xml /path/to/project# Format a single file
idea.sh format /path/to/file.prg
# Format all files in a directory recursively
idea.sh format -recursive /path/to/projectRequirements:
- The Harbour plugin must be installed in the IDE
- The IDE must not be running when using command-line formatting
- The
pycharm.shoridea.shscript must be in your PATH or use full path to the script
Testing the formatter: You can use these commands to test formatting during development without opening the IDE.
You can exclude specific sections of code from automatic formatting using special comments:
-
Block exclusion: Use
// fmt: offand// fmt: on(or# fmt: offand# fmt: on) to exclude a block of code:// fmt: off ? "This line will not be formatted" ? "Neither will this one" // fmt: on ? "This line will be formatted normally"
-
Single line exclusion: Use
// fmt: skip(or# fmt: skip) to skip formatting for a single line:? "This will be formatted" ? "This won't be formatted" // fmt: skip ? "This will be formatted"
Customizable code formatting options
Real-time code analysis provides instant feedback on syntax errors, undefined variables, and potential issues as you type. The linting engine integrates seamlessly with PyCharm's inspection framework.
Real-time linting highlights syntax errors and undefined variables
Configure linting settings in Settings → Tools → Harbour → Linting:
Customizable linting rules and severity levels
Note: For proper linting functionality, ensure all include paths are correctly configured in your project settings. Missing include files or incorrect paths may prevent the linter from detecting syntax errors and unused variables.
The plugin provides full debugging support for both console and GUI applications with PyCharm debugger integration featuring conditional breakpoints, variable inspection, step debugging, and watches.
- Local Variables: Function/procedure local variables (
LOCAL nVar) - Private Variables: Private memory variables (
PRIVATE m_nVar) - Public Variables: Public memory variables (
PUBLIC g_nVar) - Static Variables: Currently not supported due to Harbour VM limitations
-
Create Debug Configuration - Use
Harbour Applicationtype in PyCharm run configurations
Harbour Application debug configuration settingsNote: Debug flags (
-b -D__HARBOUR_DEBUG__) are automatically added when using PyCharm debug configurations.
2.Set Breakpoints - Click in the gutter next to line numbers
Console debugging with breakpoints and variable inspection
- Start Debugging - Use Debug button or Shift+F9
GUI debugging with PyCharm debugger and variable inspection
Tracepoints allow you to automatically stop execution when a variable's value changes. This is useful for tracking down where a variable gets modified unexpectedly.
To set a tracepoint:
- Stop at a breakpoint where the variable is visible
- Right-click on the variable in the Variables panel
- Select "Watch for Changes"
Right-click on a variable to watch for value changes
The debugger will automatically stop execution whenever the watched variable's value changes. Traced variables are indicated with a watch icon (👁️) in the Variables panel.
To remove a tracepoint, right-click the variable and select "Stop Watching for Changes".
Note: Tracepoints only trigger when the variable is in scope. If you enter a function where the variable doesn't exist, the tracepoint is silently skipped until you return to a scope where it's visible.
During debugging, the plugin provides a Database View tool window that shows all currently open database workareas in your Harbour application. This allows you to inspect database state while stepping through code.
Database workarea browser showing open databases during debugging
Features:
- View all open database workareas (Area 1, Area 2, etc.)
- Inspect current record data and field values
- See field structure (name, type, size)
- Navigate between records using Previous/Next buttons
- Jump to specific record numbers
- View indexes and schema information
- Refresh data to see updates
- Reorder attributes in the Current Record view to keep the fields you care about
on top:
- Drag a row with the left mouse button and drop it on another row
- Right-click a row for Move to Top, Move to Bottom, or Reset Order
- The custom order is remembered per workarea for the current session and is cleared on disconnect
The Database View automatically updates when you step through code that opens, closes, or modifies database records.
Performance Note: The Database View queries the debugger for workarea information on each update. For optimal debugging performance, keep the DB View panel collapsed when not actively inspecting database state.
The debugger supports pausing execution at the current point without setting breakpoints:
Method 1: Using Alt-D in PyCharm
- Press Alt-D in PyCharm while your Harbour program is running
- The debugger will pause at the next line of code execution
- Important: Alt-D must be pressed in PyCharm (not in the Harbour application window)
- Works even when the application is waiting for user input (GET/READ operations)
Method 2: Calling AltD() in Your Code
- Add
AltD()function calls in your Harbour code where you want to break - The debugger will stop at that line when executed
- Useful for conditional breaks:
IF nError > 0; AltD(); ENDIF
Limitations:
- Pressing Alt-D in the Harbour application window (not PyCharm) will not trigger a pause
- During GET/READ operations, the pause occurs at the last executed line before waiting for input
- Static Variables: Static variables are not visible in the debugger due to Harbour VM compilation-unit scoping
The plugin automatically provides clickable stack traces for runtime errors in the PyCharm console.
Clickable stack traces for quick navigation to error locations
If your project uses a custom ErrorBlock handler, you can still get clickable stack traces — and
the root cause of the error — by calling printDebugStackTrace(oError) from your error handler:
// Your custom error handling
ErrorBlock({|oError| MyCustomHandler(oError)})
FUNCTION MyCustomHandler(oError)
// Your custom error logic here
// Generate PyCharm-compatible stack trace with root cause when running in PyCharm
#ifdef DBG_PORT
printDebugStackTrace(oError)
#endif
// Continue with your error handling
RETURN NILKey points:
- Pass
oErrorso the PyCharm log shows the labeled root cause (Fehler / Operation / Filename / Code / SubSystem). The parameter is optional for backward compatibility — omitting it logs only the stack trace. - Call site matters for stack depth.
printDebugStackTracecaptures whatever is on the Harbour stack at the moment of the call — frames called after it are not yet on the stack. For the deepest visible chain, call it at the bottom of your error chain. Example: if your handler chain isErrorBlock → DefError → Fehler → Trouble → PrintStackTrace, put the call insidePrintStackTraceso all five frames are captured. - Use
#ifdef DBG_PORTto conditionally include it (works for both debug and run modes in PyCharm) - This generates clickable stack traces in PyCharm console
- Works alongside your existing error handling logic
- The code compiles cleanly outside PyCharm (the function call is skipped)
Charset: the plugin auto-detects the log charset in this order:
- UTF-8 — if your Harbour app converts via
hb_StrToUTF8()before letting the runtime write - Project Encoding —
File | Settings | Editor | File Encodings | Project Encoding(the Project Encoding dropdown — not "Default encoding for properties files", which only applies to.propertiesfiles) - ISO-8859-1 — universal fallback (every byte maps 1:1 to a character)
If umlauts still look broken (e.g. Grenzwert berschritten with the ü missing or replaced by
�) and you see the same breakage when your Harbour app prints oError:Description to its
own console, the issue is on the Harbour side — the byte for ü is already gone (or invalid)
in the string the runtime returns. Setup we normally recommend:
REQUEST HB_CODEPAGE_DEWIN // German Windows (CP1252)
REQUEST HB_LANG_DE
HB_CDPSELECT( "DEWIN" )
HB_LangSelect( "DE" )
hb_setTermCP( "DEWIN" )(Use DE850 for OEM/DOS-style consoles, or another codepage matching your environment.)
Diagnostic snippet — dump the actual bytes of the description so you can tell what your Harbour binary is producing:
LOCAL i, cDesc := oError:Description
? "Description bytes (" + LTrim(Str(Len(cDesc))) + ") for: [" + cDesc + "]"
FOR i := 1 TO Len(cDesc)
?? StrZero(Asc(SubStr(cDesc, i, 1)), 3) + " "
NEXTIf you see 252 (0xFC for ü in CP1252/ISO-8859-1) the byte is there and our plugin's
auto-detect will decode it correctly. If you see only ASCII codes (< 128) where the umlaut
should be, the byte has been dropped earlier — that is the Harbour build / lang module / CDP
issue and no plugin-side decoding can recover it.
Pass your own stack frames as the second argument: printDebugStackTrace(oError, cExtraStack). When supplied, cExtraStack replaces our internal stack walk — no
duplication. Format each frame as Stack: NAME(line) in file.prg\r\n so PyCharm can make it
clickable. Omit the argument to let us call ProcName/ProcLine ourselves.
The plugin provides quick actions to improve code quality and reduce repetitive typing:
Quickly declare undefined variables as LOCAL with proper placement and indentation.
How to use:
- Place cursor on any undefined variable in your code
- Press Alt+L
- The plugin automatically:
- Detects the variable name under cursor
- Finds the containing function or procedure
- Adds
LOCAL variableNamedeclaration at the proper position - Respects your LOCAL indentation settings
Example:
FUNCTION TestFunction()
LOCAL existingVar
myNewVar := 10 // Place cursor on 'myNewVar' and press Alt+L
// Plugin will add: LOCAL myNewVarFeatures:
- Smart placement after existing LOCAL declarations
- Validates variable names (prevents declaring keywords)
- Checks for duplicate declarations
- Uses indentation from code style settings
- Shows helpful notifications for errors or success
Access Harbour plugin settings: Settings → Tools → Harbour
Configure Harbour tools, paths, and debugging options
- Documentation URL - Base URL for external Harbour documentation
- Debug Log Directory - Location for debug logs (empty to disable)
- Build Output Directory - Default
.hbmkfor build artifacts - Auto-completion - Enable while typing (default: Ctrl+Space only)
- Include Paths - Add directories for #include file resolution
- Excluded Files - Files and directory patterns to exclude from navigation and indexing
- Commands - Customize code completion command list
To improve indexing performance, you can exclude directories from the plugin's indexing:
Settings → Tools → Harbour → Excluded Files tab
- Directory patterns: Add patterns like
backup,temp,Copy,.hbmkto exclude matching directories - Use the Browse button to select a directory - its name is added as a pattern
- Default:
.hbmk(build output directory) is excluded - Patterns match case-insensitively against directory names in paths
Note: This affects the Harbour plugin's indexing only. For complete exclusion from IntelliJ's native indexing, also mark directories as Excluded in Project Structure (F4).
Customize code formatting: Settings → Editor → Code Style → Harbour
Configure indentation, spacing, and formatting rules
Customize syntax highlighting: Settings → Editor → Color Scheme → Harbour
Customize syntax highlighting colors and themes
- Official JetBrains Plugin - Submit to JetBrains Marketplace for easier installation
- Process Coupling - When the debugging process in PyCharm is stopped the running harbour GUI should be terminated as well.
- Ctrl-hover should not show tooltip or navigate, only ctrl-click should.
- Ctrl-click: Internal function navigation may jump to function definition instead of showing a declaration dialog if the file w/ the function definition misses some include file or if the list of usages is very long. Subsequent click on function declaration itself work.
- most function/procedure features do not work yet for truncated keywords func/proce.
- PyCharm indexing non-Harbour files (e.g. .dbf/.dbt): The plugin's directory exclusion settings (Settings > Tools > Harbour > Excluded Files) only affect Harbour-specific features (navigation, completion, references). PyCharm's built-in indexer may still scan excluded directories for its own purposes (search, VCS, etc.). To fully exclude directories from PyCharm's indexer, right-click the directory in the Project view and select "Mark Directory as > Excluded".
For Visual Studio Code users, there's an excellent Harbour Code Extension available. This VS Code plugin was a great help and inspiration during the development of our PyCharm plugin, providing valuable insights into Harbour language support implementation.
- Java Development Kit 11+ - Download from Oracle or OpenJDK
- IntelliJ Platform Plugin SDK - Automatically downloaded by Gradle
-
Clone the repository:
git clone https://github.com/jo47011/intellij-harbour.git cd intellij-harbour -
Verify Java version:
java -version # Should show Java 11 or higher -
Build the plugin:
./gradlew buildPlugin # Linux/macOS gradlew.bat buildPlugin # Windows
Note: The
gradlew(Gradle Wrapper) script is included in the repository and automatically downloads the correct Gradle version. -
Find the built plugin:
build/distributions/harbour-language-plugin-x.x.x.zip
For plugin development, you can also run a development instance:
./gradlew runIdeThis launches PyCharm with the plugin pre-installed for testing.
For tests and command-line formatting that require the Harbour compiler, set HARBOUR_HOME:
# Linux/macOS
export HARBOUR_HOME=/path/to/harbour
# Windows
set HARBOUR_HOME=C:\harbourThe plugin expects the following structure:
$HARBOUR_HOME/bin/linux/gcc/harbour(Linux)$HARBOUR_HOME/bin/harbour.exe(Windows)$HARBOUR_HOME/include/(header files)
Located in: src/test/java/org/intellij/sdk/language/
| Test File | Purpose |
|---|---|
HarbourFormattingTest.java |
Format all PRG files in a directory and verify they compile |
SingleFileTest.java |
Individual file tests for specific formatting bugs |
StringContinuationTest.java |
Tests for string continuation handling |
HarbourFormattingTest (main formatter test - formats PRG files and verifies compilation):
# Format all PRG files in a directory
./gradlew test --tests "*HarbourFormattingTest*" -DtestDir=/path/to/prg/files
# With optional parameters
./gradlew test --tests "*HarbourFormattingTest*" \
-DtestDir=/path/to/prg/files \
-DharbourCompiler=/path/to/harbour \
-DharbourInclude=/path/to/include \
-DlineBreakPosition=99Other tests:
# Run all SingleFileTest tests
./gradlew test --tests "*SingleFileTest*"
# Run StringContinuationTest
./gradlew test --tests "*StringContinuationTest*"
# Run all tests (HarbourFormattingTest is skipped without -DtestDir)
./gradlew testThis project is licensed under the MIT License.