Syntax highlighting text editor for ImGui This project is a fork of dfranx/ImGuiColorTextEdit.
Compatible with Dear ImGui 1.92 and later. Deprecated ImGui APIs such as GetKeyIndex have been removed.
Demo project: https://github.com/BalazsJako/ColorTextEditorDemo
void Render(const char* title, const ImVec2& size = ImVec2(), bool border = false);– draw the editor.void SetText(const std::string& text);/std::string GetText() const;void SetLanguageDefinition(const LanguageDefinition& lang);– enable syntax highlighting.void SetPalette(const TextEditor::Palette& colors);/const TextEditor::Palette& GetPalette() const;void SetReadOnly(bool value);/bool IsReadOnly();Coordinates GetCursorPosition() const;/void SetCursorPosition(const Coordinates& pos);void InsertText(const std::string& text, bool indent = false);void Undo();void Redo();void Copy();void Cut();void Paste();void Delete();
- Language definitions:
CPlusPlus(),HLSL(),GLSL(),SPIRV(),C(),SQL(),AngelScript(),Lua(),JSON(),JSONC(),JSONWithHash() - Palettes:
GetDarkPalette(),GetLightPalette(),GetRetroBluePalette() - Shortcuts:
GetDefaultShortcuts()
IMGUICTE_USE_SDL2: enable when using SDL2 backend to handle keyboard input.IMGUICTE_ENABLE_SPIRV: enable to support SPIR-V highlighting, requiringspirv_crossand disabling certain non-SPIR-V features.
The project originated as Balazs Jako's ImGuiColorTextEdit, a simple text editor widget with syntax highlighting. It has since grown through contributions from many developers.
The editor builds on Omar Cornut's Dear ImGui but departs from the strictly immediate "one widget – one function" paradigm. To manage its substantial internal state, the widget stores data in a persistent object reused across frames.
The codebase remains a work in progress; please report any issues.
| Language | Function |
|---|---|
| CPlusPlus | const LanguageDefinition& CPlusPlus(); |
| HLSL | const LanguageDefinition& HLSL(); |
| GLSL | const LanguageDefinition& GLSL(); |
| SPIRV | const LanguageDefinition& SPIRV(); |
| C | const LanguageDefinition& C(); |
| SQL | const LanguageDefinition& SQL(); |
| AngelScript | const LanguageDefinition& AngelScript(); |
| Lua | const LanguageDefinition& Lua(); |
| JSON | const LanguageDefinition& JSON(); |
| JSONC | const LanguageDefinition& JSONC(); |
| JSON5 | const LanguageDefinition& JSON5(); |
| JSONWithHash | const LanguageDefinition& JSONWithHash(); |
| Markdown | const LanguageDefinition& Markdown(); |
| DotEnv | const LanguageDefinition& DotEnv(); |
| XML | const LanguageDefinition& XML(); |
| CSV | const LanguageDefinition& CSV(); |
| HTML | const LanguageDefinition& HTML(); |
| CSS | const LanguageDefinition& CSS(); |
| CMake | const LanguageDefinition& CMake(); |
| YAML | const LanguageDefinition& YAML(); |
| TOML | const LanguageDefinition& TOML(); |
| INI | const LanguageDefinition& INI(); |
| Dockerfile | const LanguageDefinition& Dockerfile(); |
| Diff | const LanguageDefinition& Diff(); |
| Bash | const LanguageDefinition& Bash(); |
The snippet below demonstrates how to embed ImGuiColorTextEdit in a JSON tool and how to tweak the color palette. The code is condensed for clarity but shows a typical integration pattern.
#include "ImGuiColorTextEdit.h"
// Create the editor and enable JSON syntax
ImTextEdit::TextEditor editor;
auto lang = ImTextEdit::JSON();
editor.SetLanguageDefinition(lang);
// Optional: create a custom color palette based on the dark theme
ImTextEdit::TextEditor::Palette customPalette = ImTextEdit::GetDarkPalette();
customPalette[(int)ImTextEdit::PaletteIndex::Keyword] = ImVec4(0.86f, 0.40f, 0.24f, 1.0f); // keywords
customPalette[(int)ImTextEdit::PaletteIndex::String] = ImVec4(0.90f, 0.76f, 0.18f, 1.0f); // strings
editor.SetPalette(customPalette);
// --- main render loop ---
const float window_width = window.getSize().x;
const float window_height = window.getSize().y;
auto cpos = editor.GetCursorPosition();
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2(window_width, window_height - indent_basement), ImGuiCond_Always);
ImGui::Begin("CryptoJsonMainMenu", nullptr,
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_MenuBar);
if (ImGui::BeginMenuBar()) {
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Open"))
file_dialog_open = true;
if (ImGui::MenuItem("Save", nullptr, false, cj_config.is_init)) {
auto text = editor.GetText();
// save text to file
}
if (ImGui::MenuItem("Save as..."))
file_dialog_save = true;
if (ImGui::MenuItem("Quit", "Alt-F4"))
break;
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Edit")) {
bool readOnly = editor.IsReadOnly();
if (ImGui::MenuItem("Read-only mode", nullptr, &readOnly))
editor.SetReadOnly(readOnly);
ImGui::Separator();
if (ImGui::MenuItem("Undo", "ALT-Backspace", nullptr, !readOnly && editor.CanUndo()))
editor.Undo();
if (ImGui::MenuItem("Redo", "Ctrl-Y", nullptr, !readOnly && editor.CanRedo()))
editor.Redo();
ImGui::Separator();
if (ImGui::MenuItem("Copy", "Ctrl-C", nullptr, editor.HasSelection()))
editor.Copy();
if (ImGui::MenuItem("Cut", "Ctrl-X", nullptr, !readOnly && editor.HasSelection()))
editor.Cut();
if (ImGui::MenuItem("Delete", "Del", nullptr, !readOnly && editor.HasSelection()))
editor.Delete();
if (ImGui::MenuItem("Paste", "Ctrl-V", nullptr, !readOnly && ImGui::GetClipboardText() != nullptr))
editor.Paste();
ImGui::Separator();
if (ImGui::MenuItem("Select all"))
editor.SetSelection(ImTextEdit::Coordinates(), ImTextEdit::Coordinates(editor.GetTotalLines(), 0));
ImGui::EndMenu();
}
if (ImGui::BeginMenu("View")) {
if (ImGui::MenuItem("Dark palette"))
editor.SetPalette(ImTextEdit::GetDarkPalette());
if (ImGui::MenuItem("Light palette"))
editor.SetPalette(ImTextEdit::GetLightPalette());
if (ImGui::MenuItem("Retro blue palette"))
editor.SetPalette(ImTextEdit::GetRetroBluePalette());
if (ImGui::MenuItem("Custom palette"))
editor.SetPalette(customPalette);
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1, cpos.mColumn + 1, editor.GetTotalLines(),
editor.IsOverwrite() ? "Ovr" : "Ins",
editor.CanUndo() ? "*" : " ",
editor.GetLanguageDefinition().mName.c_str(), cj_config.path.c_str());
editor.Render("TextEditor");
ImGui::End();
ImGui::Begin("##basement", NULL,
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
{
if (ImGui::Button("Validate")) {
JsonSax json_sax;
const std::string text = editor.GetText();
json::sax_parse(text, &json_sax);
ImTextEdit::TextEditor::ErrorMarkers markers;
for (const auto& err : json_sax.errors) {
int line = std::count(text.begin(), text.begin() + err.first, '\n');
markers.insert({line, err.second});
}
editor.SetErrorMarkers(markers);
}
ImGui::SameLine();
if (ImGui::Button("Copy")) {
const std::string text = editor.GetText();
ImGui::SetClipboardText(text.c_str());
}
}
ImGui::End();- approximates typical code editor look and feel (essential mouse/keyboard commands work - I mean, the commands I normally use :))
- undo/redo
- UTF-8 support
- works with both fixed and variable-width fonts
- extensible syntax highlighting for multiple languages
- identifier declarations: a small piece of description can be associated with an identifier. The editor displays it in a tooltip when the mouse cursor is hovered over the identifier
- error markers: the user can specify a list of error messages together the line of occurence, the editor will highligh the lines with red backround and display error message in a tooltip when the mouse cursor is hovered over the line
- large files: there is no explicit limit set on file size or number of lines (below 2GB, performance is not affected when large files are loaded (except syntax coloring, see below)
- color palette support: you can switch between different color palettes, or even define your own
- whitespace indicators (TAB, space)
- syntax highligthing of most languages - except C/C++ - is based on std::regex, which is diasppointingly slow. Because of that, the highlighting process is amortized between multiple frames. C/C++ has a hand-written tokenizer which is much faster.
Please post your screenshots if you find this little piece of software useful. :)
If you want to contribute, please refer to CONTRIBUTE file.
