extern/luajit-imgui: add source code properly

This adds luajit-imgui without submodules.

Signed-off-by: Ronald Caesar <github43132@proton.me>
This commit is contained in:
Ronald Caesar
2026-06-11 14:11:34 -04:00
parent e06f6bd00e
commit 5f0791e8b1
12306 changed files with 1367450 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
[submodule "cimgui"]
path = cimgui
url = https://github.com/cimgui/cimgui.git
branch = docking_inter
[submodule "cimplot"]
path = cimplot
url = https://github.com/cimgui/cimplot.git
[submodule "cimguizmo"]
path = cimguizmo
url = https://github.com/cimgui/cimguizmo.git
[submodule "cimguizmo_quat"]
path = cimguizmo_quat
url = https://github.com/cimgui/cimguizmo_quat.git
[submodule "cimnodes"]
path = cimnodes
url = https://github.com/cimgui/cimnodes.git
[submodule "cimnodes_r"]
path = cimnodes_r
url = https://github.com/cimgui/cimnodes_r.git
[submodule "cimCTE"]
path = cimCTE
url = https://github.com/cimgui/cimCTE.git
branch = main_goossens
[submodule "cimplot3d"]
path = cimplot3d
url = https://github.com/cimgui/cimplot3d.git
[submodule "cimnodes_editor"]
path = cimnodes_editor
url = https://github.com/cimgui/cimnodes_editor.git
+242
View File
@@ -0,0 +1,242 @@
cmake_minimum_required(VERSION 3.20)
Project(cimgui)
#set (CMAKE_CXX_STANDARD 14) #needed by santaclose/ImGuiColorTextEdit
set (CMAKE_CXX_STANDARD 17) #needed by goossens/ImGuiColorTextEdit
if(WIN32) #to mingw work as all the others
set(CMAKE_SHARED_LIBRARY_PREFIX "")
endif(WIN32)
#general settings
include_directories(cimgui/imgui)
include_directories(cimplot/implot)
include_directories(cimguizmo/ImGuizmo)
include_directories(./cimguizmo_quat/imGuIZMO.quat/imguizmo_quat)
include_directories(cimnodes/imnodes)
include_directories(cimCTE/ImGuiColorTextEdit)
add_definitions("-DIMGUI_USER_CONFIG=\"../cimconfig.h\"")
add_definitions("-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1")
add_definitions(-DIMNODES_NAMESPACE=imnodes)
include_directories(cimgui)
set(IMGUI_SOURCES ./cimgui/cimgui.cpp
./cimgui/imgui/imgui.cpp
./cimgui/imgui/imgui_draw.cpp
./cimgui/imgui/imgui_demo.cpp
./cimgui/imgui/imgui_widgets.cpp
./cimplot/cimplot.cpp
./cimplot/implot/implot.cpp
./cimplot/implot/implot_items.cpp
./cimplot/implot/implot_demo.cpp
./cimguizmo/cimguizmo.cpp
./cimguizmo/ImGuizmo/src/ImGuizmo.cpp
./cimguizmo_quat/cimguizmo_quat.cpp
./cimguizmo_quat/imGuIZMO.quat/imguizmo_quat/imGuIZMOquat.cpp
./cimnodes/cimnodes.cpp
./cimnodes/imnodes/imnodes.cpp
./cimnodes_r/cimnodes_r.cpp
./cimnodes_r/ImNodes/ImNodes.cpp
./cimnodes_r/ImNodes/ImNodesEz.cpp
./cimplot3d/cimplot3d.cpp
./cimplot3d/implot3d/implot3d.cpp
./cimplot3d/implot3d/implot3d_demo.cpp
./cimplot3d/implot3d/implot3d_items.cpp
./cimplot3d/implot3d/implot3d_meshes.cpp
./cimCTE/cimCTE.cpp
./cimCTE/ImGuiColorTextEdit/TextEditor.cpp
./cimCTE/ImGuiColorTextEdit/TextDiff.cpp
./cimnodes_editor/cimnodes_editor.cpp
./cimnodes_editor/imgui-node-editor/imgui_node_editor.cpp
./cimnodes_editor/imgui-node-editor/imgui_node_editor_api.cpp
./cimnodes_editor/imgui-node-editor/imgui_canvas.cpp
./cimnodes_editor/imgui-node-editor/crude_json.cpp
)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cimgui/imgui/imgui_tables.cpp)
list(APPEND IMGUI_SOURCES ./cimgui/imgui/imgui_tables.cpp)
endif()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cimgui/imgui/backends)
set(BACKENDS_FOLDER "./cimgui/imgui/backends/")
else()
set(BACKENDS_FOLDER "./cimgui/imgui/examples/")
endif()
set(IMGUI_SOURCES_glfw)
set(IMGUI_SOURCES_sdl)
set(IMGUI_SOURCES_sdl3)
set(IMGUI_LIBRARIES )
set(IMGUI_ft_LIBRARIES )
if (WIN32)
add_definitions("-DIMGUI_IMPL_API=extern \"C\" __declspec\(dllexport\)")
list(APPEND IMGUI_LIBRARIES imm32)
else(WIN32)
add_definitions("-DIMGUI_IMPL_API=extern \"C\" ")
endif(WIN32)
add_compile_definitions("IMGUI_IMPL_OPENGL_LOADER_GL3W")
add_definitions("-DIMGUIZMO_IMGUI_FOLDER=")
#optional adding implementations
option(IMPL_GLFW "add GLFW implementation" ON)
option(IMPL_SDL "add SDL implementation" ON)
option(IMPL_SDL3 "add SDL3 implementation" ON)
option(IMPL_OPENGL2 "add OPENGL2 implementation" ON)
option(IMPL_OPENGL3 "add OPENGL3 implementation" ON)
option(IMGUI_FREETYPE "add Freetype2" OFF)
option(IMPL_EXTRAS "knob and curve" ON)
option(IMPL_LOVE "add love impl" OFF)
if(IMPL_LOVE)
set(IMPL_GLFW OFF)
set(IMPL_SDL OFF)
set(IMPL_SDL3 OFF)
set(IMPL_OPENGL2 OFF)
set(IMPL_OPENGL3 OFF)
endif(IMPL_LOVE)
if(IMGUI_FREETYPE)
message(STATUS "Building with freetype")
if (DEFINED FREETYPE_PATH)
FIND_PACKAGE(freetype REQUIRED PATHS ${FREETYPE_PATH})
endif (DEFINED FREETYPE_PATH)
list(APPEND IMGUI_ft_LIBRARIES freetype)
list(APPEND IMGUI_LIBRARIES freetype)
list(APPEND IMGUI_SOURCES ./cimgui/imgui/misc/freetype/imgui_freetype.cpp)
endif(IMGUI_FREETYPE)
if(IMPL_OPENGL3)
list(APPEND IMGUI_SOURCES ${BACKENDS_FOLDER}imgui_impl_opengl3.cpp)
#./cimgui/imgui/examples/libs/gl3w/GL/gl3w.c)
#list(APPEND IMGUI_SOURCES ./extras/cimgui_extras.cpp) #Do_gl3winit not needed
#include_directories(cimgui/imgui/examples/libs/gl3w)
if(WIN32)
list(APPEND IMGUI_LIBRARIES opengl32)
else(WIN32)#Unix
list(APPEND IMGUI_LIBRARIES GL)
endif(WIN32)
endif(IMPL_OPENGL3)
if(IMPL_OPENGL2)
list(APPEND IMGUI_SOURCES ${BACKENDS_FOLDER}imgui_impl_opengl2.cpp)
if(WIN32)
list(APPEND IMGUI_LIBRARIES opengl32)
else(WIN32)#Unix
list(APPEND IMGUI_LIBRARIES GL)
endif(WIN32)
endif(IMPL_OPENGL2)
if(IMPL_EXTRAS)
list(APPEND IMGUI_SOURCES ./extras/knob.cpp)
endif(IMPL_EXTRAS)
add_library(cimgui_base OBJECT ${IMGUI_SOURCES})
if(IMGUI_FREETYPE)
target_compile_definitions(cimgui_base PUBLIC IMGUI_ENABLE_FREETYPE)
target_compile_definitions(cimgui_base PUBLIC IMGUI_ENABLE_STB_TRUETYPE)
endif(IMGUI_FREETYPE)
if(IMGUI_WCHAR32)
target_compile_definitions(cimgui_base PUBLIC IMGUI_USE_WCHAR32)
endif(IMGUI_WCHAR32)
target_link_libraries(cimgui_base PUBLIC ${IMGUI_ft_LIBRARIES})
if(UNIX)
set_property(TARGET cimgui_base PROPERTY POSITION_INDEPENDENT_CODE ON)
endif(UNIX)
if(IMPL_LOVE)
add_library(cimgui SHARED $<TARGET_OBJECTS:cimgui_base>)
target_link_libraries(cimgui PUBLIC ${IMGUI_LIBRARIES})
install(TARGETS cimgui
RUNTIME DESTINATION ${LUAJIT_BIN}
LIBRARY DESTINATION ${LUAJIT_BIN}
#ARCHIVE DESTINATION lib
)
endif(IMPL_LOVE)
if(IMPL_GLFW)
list(APPEND IMGUI_SOURCES_glfw ${BACKENDS_FOLDER}imgui_impl_glfw.cpp)
if (DEFINED GLFW_PATH)
message(STATUS "GLFW_PATH defined as " ${GLFW_PATH})
FIND_PACKAGE(glfw3 3.2 REQUIRED PATHS ${GLFW_PATH})
message( glfw include is ${GLFW_INCLUDE})
else (DEFINED GLFW_PATH)
message(STATUS GLFW_PATH not defined)
#include_directories(${GLFW_INCLUDE})
endif(DEFINED GLFW_PATH)
add_library(cimgui_glfw SHARED ${IMGUI_SOURCES_glfw} $<TARGET_OBJECTS:cimgui_base>)
target_link_libraries(cimgui_glfw PUBLIC ${IMGUI_LIBRARIES} glfw)
install(TARGETS cimgui_glfw
RUNTIME DESTINATION ${LUAJIT_BIN}
LIBRARY DESTINATION ${LUAJIT_BIN}
#ARCHIVE DESTINATION lib
)
endif(IMPL_GLFW)
if(IMPL_SDL)
list(APPEND IMGUI_SOURCES_sdl ${BACKENDS_FOLDER}imgui_impl_sdl2.cpp)
if(DEFINED SDL_PATH)
message(STATUS "SDL_PATH defined as " ${SDL_PATH})
FIND_PACKAGE(SDL2 REQUIRED PATHS ${SDL_PATH})
message(STATUS "sdlfound")
get_target_property(SDL_INCLUDE SDL2::SDL2 INTERFACE_INCLUDE_DIRECTORIES)
message(STATUS "sdlinclude is " ${SDL_INCLUDE} " or " ${SDL2_INCLUDE_DIRS})
#if not found latest SDL2 cmake config use older
if (("${SDL_INCLUDE}" STREQUAL "") OR ("${SDL_INCLUDE}" STREQUAL "SDL_INCLUDE-NOTFOUND"))
message(STATUS "sdlinclude2 is " ${SDL2_INCLUDE_DIRS})
include_directories(${SDL2_INCLUDE_DIRS})
set(IMGUI_SDL_LIBRARY ${SDL2_LIBRARIES})
else()#use new one SDL2 config
include_directories(${SDL_INCLUDE})
set(IMGUI_SDL_LIBRARY SDL2::SDL2)
endif()
else(DEFINED SDL_PATH) #using SDL2 submodule from anima
message(STATUS "SDL_PATH not defined")
set(IMGUI_SDL_LIBRARY SDL2)
endif(DEFINED SDL_PATH)
add_library(cimgui_sdl SHARED ${IMGUI_SOURCES_sdl} $<TARGET_OBJECTS:cimgui_base>)
target_link_libraries(cimgui_sdl PUBLIC ${IMGUI_LIBRARIES} ${IMGUI_SDL_LIBRARY})
install(TARGETS cimgui_sdl
RUNTIME DESTINATION ${LUAJIT_BIN}
LIBRARY DESTINATION ${LUAJIT_BIN}
#ARCHIVE DESTINATION lib
)
endif(IMPL_SDL)
if(IMPL_SDL3)
list(APPEND IMGUI_SOURCES_sdl3 ${BACKENDS_FOLDER}imgui_impl_sdl3.cpp)
if(DEFINED SDL3_PATH)
message(STATUS "SDL3_PATH defined as " ${SDL3_PATH})
FIND_PACKAGE(SDL3 REQUIRED CONFIG COMPONENTS Headers PATHS ${SDL3_PATH})
message(STATUS "sdl3found")
get_target_property(SDL3_INCLUDE SDL3::Headers INTERFACE_INCLUDE_DIRECTORIES)
message(STATUS "sdl3include is " ${SDL3_INCLUDE} )
#if not found latest SDL3 cmake config use older
if (("${SDL3_INCLUDE}" STREQUAL "") OR ("${SDL3_INCLUDE}" STREQUAL "SDL3_INCLUDE-NOTFOUND"))
message(STATUS "sdl3include2 is " SDL3::Headers)
include_directories(SDL3::Headers)
set(IMGUI_SDL3_LIBRARY SDL3::SDL3)
else()#use new one SDL2 config
include_directories(${SDL_INCLUDE})
set(IMGUI_SDL3_LIBRARY SDL3::SDL3)
endif()
else(DEFINED SDL3_PATH) #using SDL3 submodule from anima
message(STATUS "SDL3_PATH not defined")
set(IMGUI_SDL3_LIBRARY SDL3::SDL3)
endif(DEFINED SDL3_PATH)
add_library(cimgui_sdl3 SHARED ${IMGUI_SOURCES_sdl3} $<TARGET_OBJECTS:cimgui_base>)
target_link_libraries(cimgui_sdl3 PUBLIC ${IMGUI_LIBRARIES} ${IMGUI_SDL3_LIBRARY})
install(TARGETS cimgui_sdl3
RUNTIME DESTINATION ${LUAJIT_BIN}
LIBRARY DESTINATION ${LUAJIT_BIN}
#ARCHIVE DESTINATION lib
)
endif(IMPL_SDL3)
#install
install(DIRECTORY lua/imgui DESTINATION ${LUAJIT_BIN}/lua)
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017-2019 Victor Bombí
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+52
View File
@@ -0,0 +1,52 @@
# LuaJIT-ImGui
![sample](sample.png)
![notepad](https://github.com/user-attachments/assets/2a1f16b6-a88e-446c-ac07-869de5d79129)
![notepad](https://github.com/user-attachments/assets/b4ff1647-b26b-4b47-a41c-117d16426142)
This is a LuaJIT binding for the excellent C++ immediate gui [imgui](https://github.com/ocornut/imgui).
Uses cimgui to be the most "up to date" as possible.
There are backends for glfw, SDL2 and SDL3.
Notes:
* currently this wrapper is based on version [1.92.8 docking of imgui]
# cloning
Remember to do a recursive cloning of the repo to pull submodules also.
git clone --recurse-submodules https://github.com/sonoro1234/LuaJIT-ImGui.git
If already cloned and updating do from this repo folder:
git submodule update --init --recursive
# compiling
* linux cimgui_sdl (for love2d for example) needs: <code>sudo apt install libsdl2-dev</code>
* run one of the scripts in the build directory from a sibling folder to the repo. If you want to install,
(recomended) add this <code>-DLUAJIT_BIN="folder where LuaJIT is"</code> to the cmake command.
* make (or make install).
* If you didnt install in LuaJIT directory, set basedir variable in imgui.lua to the directory libimgui is found.
* Alternatively you can build https://github.com/sonoro1234/anima which includes LuaJIT-ImGui and dependencies.
# trying
* Remember you also need GLFW https://github.com/sonoro1234/LuaJIT-GLFW or SDL2 https://github.com/sonoro1234/LuaJIT-SDL2 .
* You have some scripts on the examples folder.
* New module imgui.window for simplified use. (see window_drag_drop.lua)
* In case you are in a hurry, you can get all done in the releases (GLFW version only).
* Releases are now done in https://github.com/sonoro1234/anima
# binding generation
* if cimgui is updated the binding can be remade with ./lua/build.bat
# used in
* https://github.com/sonoro1234/anima
* can be used for LOVE2D as explained in https://github.com/sonoro1234/LuaJIT-ImGui/issues/47
+4
View File
@@ -0,0 +1,4 @@
[submodule "ImGuiColorTextEdit"]
path = ImGuiColorTextEdit
url = https://github.com/goossens/ImGuiColorTextEdit.git
branch = master
+63
View File
@@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 3.5)
set(PROJECT_NAME cimCTE)
project(${PROJECT_NAME})
set(IMGUI_LIBRARIES)
file(GLOB IMGUI_SOURCES
../cimgui/cimgui.cpp
../cimgui/imgui/imgui.cpp
../cimgui/imgui/imgui_draw.cpp
../cimgui/imgui/imgui_demo.cpp
../cimgui/imgui/imgui_widgets.cpp
../cimgui/imgui/imgui_tables.cpp
cimCTE.cpp
ImGuiColorTextEdit/TextEditor.cpp
ImGuiColorTextEdit/TextDiff.cpp
)
if (IMGUI_FREETYPE)
message(STATUS "Building with freetype")
if (DEFINED FREETYPE_PATH)
FIND_PACKAGE(freetype REQUIRED PATHS ${FREETYPE_PATH})
endif (DEFINED FREETYPE_PATH)
list(APPEND IMGUI_ft_LIBRARIES freetype)
list(APPEND IMGUI_LIBRARIES freetype)
list(APPEND IMGUI_SOURCES ../cimgui/imgui/misc/freetype/imgui_freetype.cpp)
endif (IMGUI_FREETYPE)
set(IMGUI_STATIC "no" CACHE STRING "Build as a static library")
set(CMAKE_CXX_STANDARD 17) #needed by goossens/ImGuiColorTextEdit
if (IMGUI_STATIC)
add_library(${PROJECT_NAME} STATIC ${IMGUI_SOURCES})
else (IMGUI_STATIC)
add_library(${PROJECT_NAME} SHARED ${IMGUI_SOURCES})
endif (IMGUI_STATIC)
add_definitions("-DIMGUI_USER_CONFIG=\"../cimconfig.h\"")
if (IMGUI_FREETYPE)
target_compile_definitions(${PROJECT_NAME} PUBLIC IMGUI_ENABLE_FREETYPE)
target_compile_definitions(${PROJECT_NAME} PUBLIC IMGUI_ENABLE_STB_TRUETYPE)
endif (IMGUI_FREETYPE)
if (IMGUI_WCHAR32)
target_compile_definitions(${PROJECT_NAME} PUBLIC IMGUI_USE_WCHAR32)
endif (IMGUI_WCHAR32)
if (CIMGUI_VARGS0)
target_compile_definitions(${PROJECT_NAME} PUBLIC CIMGUI_VARGS0)
endif (CIMGUI_VARGS0)
target_compile_definitions(${PROJECT_NAME} PUBLIC IMGUI_DISABLE_OBSOLETE_FUNCTIONS=1)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ImGuiColorTextEdit)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../cimgui/imgui)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../cimgui)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
target_link_libraries(${PROJECT_NAME} ${IMGUI_LIBRARIES})
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION .
LIBRARY DESTINATION .
ARCHIVE DESTINATION .
)
@@ -0,0 +1,23 @@
name: Linux
on: [ push ]
jobs:
verify-ubuntu:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Setup libraries and tools
run: |
sudo apt update
sudo apt install xorg-dev libegl-dev libgl1-mesa-dev x11proto-core-dev libx11-dev
sudo apt install ninja-build
- name: Configure
run: cmake -B build -G "Ninja Multi-Config" -S example
- name: Build
run: cmake --build build --config Release
@@ -0,0 +1,20 @@
name: MacOS
on: [ push ]
jobs:
verify-macos:
runs-on: macos-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Setup Ninja
uses: ashutoshvarma/setup-ninja@master
- name: Configure
run: cmake -B build -G "Ninja Multi-Config" -S example
- name: Build
run: cmake --build build --config Release
@@ -0,0 +1,17 @@
name: Windows
on: [ push ]
jobs:
verify-windows:
runs-on: windows-2025
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Configure
run: cmake -B build -G "Visual Studio 17 2022" -A x64 -S example
- name: Build
run: cmake --build build --config Release
@@ -0,0 +1,19 @@
# Compiled Object files
*.o
*.obj
*.a
*.lib
*.exe
*.out
*.app
# MacOS files
.DS_Store
# Editor files
/.vscode
*.bak
Save/*
# Build files
/build
@@ -0,0 +1,136 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[INSERT CONTACT METHOD].
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
@@ -0,0 +1,50 @@
# Contributing to ImGuiColorTextEdit
We want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer
##Code of Conduct
ImGuiColorTextEdit has adopted a Code of Conduct that we expect project
participants to adhere to. Please read
[the full text](CODE_OF_CONDUCT.md) so that you can understand
what actions will and will not be tolerated.
## Development Process
We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
## Raising Issues
We use [GitHub issues](https://github.com/goossens/ImGuiColorTextEdit/issues)
to track public bugs. Report a bug by
[opening a new issue](https://github.com/goossens/ImGuiColorTextEdit/issues/new);
it's that easy! Great bug reports tend to have:
- A quick summary and/or background
- Steps to reproduce (be specific and give sample code if you can)
- What you expected would happen
- What actually happens
- Notes (possibly including why you think this might be happening,
or stuff you tried that didn't work)
## Pull Requests
Pull requests are the best way to propose changes to the codebase.
We actively welcome your pull requests:
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests.
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes.
5. Make sure your code lints.
6. Issue that pull request!
## Coding Style
All contributions must be in the same style as the rest of
ImGuiColorTextEdit.
## License
By contributing, you agree that your contributions will be
licensed under its MIT License.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024-2026 Johan A. Goossens. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+432
View File
@@ -0,0 +1,432 @@
<div align="center">
![MacOS status](https://img.shields.io/github/actions/workflow/status/goossens/ImGuiColorTextEdit/macos.yml?branch=master&label=MacOS&style=for-the-badge)
![Linux status](https://img.shields.io/github/actions/workflow/status/goossens/ImGuiColorTextEdit/linux.yml?branch=master&label=Linux&style=for-the-badge)
![Windows status](https://img.shields.io/github/actions/workflow/status/goossens/ImGuiColorTextEdit/windows.yml?branch=master&label=Windows&style=for-the-badge)
<br/>
![Repo size](https://img.shields.io/github/repo-size/goossens/ImGuiColorTextEdit?style=for-the-badge)
![Repo activity](https://img.shields.io/github/commit-activity/m/goossens/ImGuiColorTextEdit?label=Commits&style=for-the-badge)
<br/>
[![License](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)
![Maintained](https://img.shields.io/maintenance/yes/2026?style=for-the-badge)
![Version](https://img.shields.io/badge/version-0.9-blue?style=for-the-badge)
# Colorizing Text Editor and Text Diff for Dear ImGui
</div>
> [!NOTE]
> The editor is being refactored to enable new features like Word Wrap, Line Folding, full MiniMaps, Autocomplete and
> Language Server connectivity. This refactoring will break backwards compatibility. A preview is avalable in
> the [future branch](https://github.com/goossens/ImGuiColorTextEdit/tree/future). Once more testing is done, this new
> architecture will become the master branch.
TextEdit is a syntax highlighting text editor for
[Dear ImGui](https://github.com/ocornut/imgui) and it was originally developed by
[Balázs Jákó](https://github.com/BalazsJako/ImGuiColorTextEdit). Unfortunately, he no
longer has time to work on the project. In fact, the last update to his repository was
in June 2019. As a result, over 200 forks exist by people who like his work but want
to fix bugs and/or add new features. A fork by
[Santiago](https://github.com/santaclose/ImGuiColorTextEdit), also known as santaclose,
was the most actively maintained version (over 220 commits ahead of the original version)
when I was looking for a syntax highlighting text editor for Dear ImGui in late 2023.
This repository was originally a fork of Santiago's version and I tried to enhance it.
In late December 2024, I decided that it was better for me to rewrite the code from
the ground up while preserving the majority of the public APIs so it would be relatively
simple for me (and others) to reuse my rewrite. One of my fundamental arguments
for the rewrite was that the code had become hard to read and maintain (at least for me).
I decided to create a more object-oriented internal architecture (see below) that made
it clear who was responsible for what by using a layered approach. While rewriting
the code, a number of new features were also added.
The rewrite and now the maintenance of this code is part of a larger project
([ObjectTalk](https://github.com/goossens/ObjectTalk)) and this repository is simply
a snapshot of the relevant editor code to provide reuse. As part of this code is
automatically generated, references to the master project are provided where required.
You can find all text editor source code components here in the
[ObjectTalk repository](https://github.com/goossens/ObjectTalk/tree/master/3rdparty/imguieditor).
To respect its origins, this repository will remain a fork (of a fork) although
there is now little code in common.
![Screenshot](docs/textEditor.png)
Note: In the screenshot above, the tabs and the menubar are not part of the
text editor widget. They are part of a custom enclosing IDE (which is part of
the larger [ObjectTalk](https://github.com/goossens/ObjectTalk) project).
By not putting those things in the editor, integrators have maximum
flexibility to wrap the editor in their own context in the way they see fit. The
public API to externally implement these features is however included.
## Features
- Works on MacOS, Linux and Windows.
- Has look and feel similar to Visual Studio Code.
- Works with latest Dear ImGui version (currently v1.92.7) and does not use deprecated functions.
- Supports dynamic font sizes (courtesy of Dear ImGui v1.92+). Implemented in example application.
- Supports UTF-8 encoding with 16/32 bit codepoints (based on Dear ImGui configuration, see below).
- Is C++17 based (not unreasonable in 2026 I think) although Dear ImGui still uses C++11.
- Has no runtime dependencies other than Dear ImGui and the C++17 Standard Template Library (STL).
- Has full undo/redo capabilities and supports native clipboard with UTF-8 encoded strings.
- Has extendable syntax highlighting for multiple languages and API for custom languages.
- Has customizable color palettes (a dark and light version that work with Dear ImGui defaults are included).
- Has option to automatically insert spaces on tabs.
- Has find/replace user interface and API with full undo/redo.
- Find has options for whole word and/or case-sensitive searches.
- Provides optional autocomplete framework (see [more information here](docs/autocomplete.md)).
- Has marker API to specify lines and/or line numbers to highlight and optional show tooltips (
see [example](docs/markers.md)).
- Has optional scrollbar minimap to render cursor, selection and marker locations.
- Provides middle-mouse pan and scroll functions like CAD programs and browsers.
- Has API to attach user data to select lines or all lines (see [example](docs/userData.md)).
- Has API to decorate each line (useful for debuggers and IDEs) (see [example](docs/lineDecorator.md)).
- Provides optional and customizable right click (control + click on MacOS) context menus for line numbers or text
lines (see [example](docs/contextMenus.md))
- Provides auto completion for paired glyphs (\[, \{, \(, \", \') (can be turned on and off).
- If auto complete is turned on, accidentally typed closing glyphs are ignored.
- If auto complete is turned on, selections can be surrounded by paired glyphs.
- Supports blinking cursor (can be turned on/off using Dear ImGui's global io.ConfigInputTextCursorBlink flag).
- Supports bracket matching and coloring similar to Visual Studio Code (can be turned on and off).
- Supports multiple cursors and multiple selections.
- Provides auto indent with simplified implementation (can be turned on and off).
- Has API to filter selections (with full undo support).
- Uppercase/lowercase filter is example of selection filtering.
- Has API to filter each line in editor (with full undo support).
- Tabs to Space (and visa versa) are examples of line filtering.
- Has API to strip trailing whitespaces.
- Provides whitespace indicators for tabs and spaces (can be turned on and off individually or collectively).
- No longer uses regular expressions for colorizing text (see below).
- Provides an optional companion widget to show source code differences between versions (see below).
## Integration
As explained above, the editor is developed and maintained as part of a larger project.
In that bigger project, the editor is spread out over multiple source files and some
of those are automatically generated using tools or derived from datasets (like the
unicode database). Every time the editor is updated in the bigger project, relevant
files are concatenated into a simple 2 (or 5 if you also want to use TextDiff)
file distribution which is included here.
This repository therefore provides a simple mechanism to reuse the editor in any
Dear ImGui context by doing the following:
- Include the TextEditor.cpp and TextEditor.h files in your project.
- Instantiate a TextEditor object for each editor widget you need.
- Use the public API to set editor options or interact with the editor's contents.
- Call the TextEditor's Render member function every frame in your Dear ImGui loop.
- If you plan to use non-ASCII characters in your text, see the Unicode section below.
- Configure Dear ImGui's clipboard functions since that is what this editor uses.
If you also want to use the TextDiff widget, you must:
- Include TextDiff.cpp, TextDiff.h and dtl.h in your project.
- Instantiate a TextDiff object for each diff widget you need.
- Use the public API to set diff options.
- Call the TextDiff's Render member function every frame in your Dear ImGui loop.
- If you properly configured Dear ImGui for the TextEditor (see above), you are good to go.
For a complete example, please see the [example folder](example/).
**Note**: Like ImGui, it is recommended that you compile and link TextEditor and TextDiff
as a static library or directly as part of your sources (as suggested above).
However, if you must and are compiling TextEditor and/or TextDiff as separate DLLs, make sure
you set the current ImGui context with TextEditor::SetImGuiContext(ImGuiContext* ctx).
This ensures that global ImGui variables are correctly shared across the DLL boundary.
See GImGui documentation in imgui.cpp for more details.
## Default Keyboard and Mouse Mappings
- In the mappings listed below, the following modifier keys are used:
- Ctrl: this refers to the Command key on MacOS and the Control key on Linux and Windows.
- Alt: this refers to the Option key on MacOS and the Alt key on Linux and Windows.
- Shift: as you would expect on all platforms.
- If a keyboard has a left and right version of these modifiers, the meaning is not different.
- Cursor Movements:
- Single left mouse click moves the cursor.
- Arrow keys move cursor left, right, up and down.
- PageUp and PageDown do what you expect.
- Ctrl-UpArrow and Ctrl-DownArrow move to the start/end of the document.
- Home and End keys move to the start/end of the line.
- Holding down the Shift key extends the current selection(s).
- Holding down the Alt key with the left or right arrow moves a whole word on MacOS.
- Holding down the Ctrl key with the left or right arrow moves a whole word on Linux and Windows.
- Panning and Scrolling:
- The text scrolls automatically when you move the cursor through keyboard actions.
- Mouse actions that extend the selections also apply auto scrolling.
- The text in the editor can still be scrolled using those little bars that were invented in the 1970's.
- Devices with scroll wheels or those that simulated vertical and horizontal scroll wheels (like a touch pad, a
mouse with a builtin touch pad or a pen) can also scroll the text. This is actually implemented in Dear ImGui (and
used by the editor) and must be supported by your backend.
- The middle mouse button on a three-button mouse (or whatever is reported by your OS as a middle mouse button
event) enters pan or scroll mode mode depending on the configuration. Pan mode is the default and you can switch
this to Scroll mode by calling SetMiddleMouseScrollMode(). Calling SetMiddleMousePanMode() switches it back. The
example application uses a menu option to toggle modes.
- In pan mode, the text is grabbed and dragged as the cursor moves and as long as the middle mouse button is down.
- When you mouse approaches the edges of the editor window, it enters continuous panning mode and the further you
move away form the window, the faster it pans.
- Panning as described above is typical in CAD or 3D type applications.
- In scroll mode, you can release the middle mouse button and scroll the text just like you can in some browsers.
- Scroll mode is ended by any clicking any mouse button.
- Panning and scrolling operate in opposite directions as they are different paradigms.
- An optional indicator (default is on) is shown in the center of the editor window when entering pan/scroll mode.
If anybody finds this annoying, it can be turned off through an API by calling SetShowPanScrollIndicatorEnabled(
false).
- Cursors and Selections:
- Alt with single left mouse click creates a new cursor on MacOS.
- Ctrl with single left mouse click creates a new cursor on Linux and Windows.
- Ctrl-A select all text.
- Ctrl-D creates a new cursor and selects the next instance of the current selection.
- Double left mouse clicks on a curly bracket select the content of the relevant block and replaces all previous
cursors.
- Shift + Double left mouse clicks on a curly bracket select the content of the relevant block including the
brackets and replaces all previous cursors.
- Double left mouse clicks not on a bracket or parenthesis, select a word. Adding Shift extends current selection.
- Triple left mouse clicks select a line. Adding Shift extends current selection.
- Dragging mouse with left mouse button selects text. Shift extends current selection.
- Alt-Shift-RightArrow (on MacOS) and Ctrl-Shift-RightArrow (on Linux and Windows) grows all selections to outer
blocks. First just the content of the block, than including the curly brackets. Continuously hitting the key
combination keeps growing the selections.
- Alt-Shift-LeftArrow (on MacOS) and Ctrl-Shift-LeftArrow (on Linux and Windows) shrinks all selections to inner
blocks. First including the curly brackets, that just the content of the block. Continuously hitting the key
combination keeps shrinking the selections.
- Left mouse clicking or dragging over line numbers select line(s).
- When multiple cursors are active, hitting the ESC key cancels them.
- Clipboard Operations:
- Ctrl-X or Shift-Delete cuts selected text or current line if no selection.
- Ctrl-C or Ctrl-Insert copies selected text or current line if no selection.
- Ctrl-V or Shift-Insert pastes clipboard content.
- Ctrl-Z undos the last action.
- Shift-Ctrl-Z or Ctrl-Y redos the last undone action.
- Insert Text:
- Ctrl-Enter adds line below.
- Ctrl-Shift-Enter adds line above.
- Delete Text:
- Backspace deletes character to the left of cursor or deletes selection(s).
- Delete deletes character to the right of cursor or deletes selection(s).
- Ctrl-Shift-K deletes all selected lines.
- Text Manipulation:
- Ctrl-] indents current line or current lines.
- Ctrl-[ de-indents current line or current lines.
- Tab with selection indents current line or current lines.
- Ctrl-UpArrow moves current or all selected lines up.
- Ctrl-DownArrow moves current or all selected lines down.
- Ctrl-/ toggles comments if language with single line comments is specified.
- Find & Replace:
- Ctrl-f opens the find and replace window.
- If text is selected when Ctrl-f is hit, the selected text is used as the search term if the start and end are on
the same line.
- Else if the cursor is over a word when Ctrl-f is hit, that word is used as the search term.
- In all other cases, the previous search term is used.
- When the search and replace window is visible, hitting the ESC button closes it.
- Shift-Ctrl-f finds all instances and makes them separate cursors.
- Ctrl-g finds n
- Autocomplete:
- Once configured, Ctrl-space (or a custom key combination) triggers a manual autocomplete (even on MacOS as
Cmd-space globally triggers Spotlight searching on that platform).
- Typing also triggers autocomplete (based on context).
- You can configure which triggers you want (the default is for both manual and automatic (by just typing) to be
active)
- Autocomplete does not work when multiple cursors are active.
- Other:
- Insert key toggles between insert (default) and overwrite modes.
## Unicode and UTF-8
This rewrite of TextEditor uses UTF-8 encoded strings for the public API
and to interact with the clipboard like the original TextEditor versions.
The original and most of its forks use UTF-8 on the private side as well
which is effective from a storage perspective but it makes all the
processing a lot harder as you constantly have to parse UTF-8 sequences.
This rewrite internally uses unicode codepoints that are either 16 or 32 bits
depending on how Dear ImGui is configured. If IMGUI_USE_WCHAR32 is defined,
Dear ImGui as well as this editor use 32 bits to store a codepoint. If it is not
defined (which is the default), 16 bits are used for each codepoint which
basically limits unicode support to the Basic Multilingual Plane (see
[this article on Wikipedia](https://en.wikipedia.org/wiki/Plane_(Unicode))).
Regardless of whether 16 or 32 bit codepoints are used, it is your responsibility
to ensure Dear ImGui is configured with the correct font and font size. As of
Dear ImGui v1.92, you can now use dynamically sized fonts and use any font glyph
without setting up glyph ranges or a font atlas. All this functionality is in the
Dear ImGui core and the TextEditor uses it. Please see the example application on
how to use PushFont/PopFont around the TextEditor Render function. The demo app
also shows how to increase/decrease the font size on the fly.
## Architecture
While this editor relies on [Omar Cornut's Dear ImGui](https://github.com/ocornut/imgui),
it does not follow the "pure" one widget - one function approach. Since the editor
has to maintain a relatively complex and large internal state, it did not seem
to be practical to try and enforce full immediate mode. It therefore stores
its internal state in an object instance which is reused across frames. This
object is an instance of the TextEditor class which not only stores the
internal state, it also provides the public API. The "Render" member functions
however works like a normal Dear ImGui widget. It creates a child window to
render the editor so you can call Dear ImGui window functions like SetNextWindowSize
or set the font before calling Render.
The block diagram below shows the architecture of this widget. At the top is
the public facing TextEditor instance and at the bottom are the private classes
that store and maintain the internal state.
![Architecture](docs/architecture.png)
#### Document
This class, as the name suggests, stores the document that's being edited.
Internally, a Document is a std::vector of Lines that themselves are
std::vectors of Glyphs.
The Document class translates from the external UTF-8 encoding to the internal
codepoints and provides a number of member functions to manipulate contents,
calculate coordinates, assist searches and track overall content state.
The Line and Glyph classes are used to represent the document's structure with
Glyph just holding a codepoint and a color.
#### Cursors
The Cursors class maintains a list of Cursor instances and operates very much
like cursors do in Visual Studio Code. The list of cursors consists of the
main cursor (which is always present) and a optional set of additional cursors.
The last cursor added is considered the current cursor which has meaning for
some actions or API calls.
#### Transactions
This class contains a list of Transaction records to support do/undo/redo
operations. Each Transaction record contains insert and delete operations
performed on a document.
#### Colorizer
The colorizer maintains the color state of each glyph based on the rules
provided by the specifications in the Language object. The original version
used regular expressions for some languages but this was/is not very
performant. The new colorizer is based on multiple state-transition engines
that make it easier to express language rules and also improves performance.
The new colorizer only effects lines that have changed but keep in mind, that
for instance opening a multiline comment at the start of the document,
causes the entire document to be re-colored. Luckily the new engine is fast
enough that you don't notice this and it would only affect a single frame. I
think it is also important to point out that this widget is not really intended
for mega/gigabyte size text files. For those, I would still use a regular text
editors (if you can find one that can handle that requirement).
#### Bracketeer
This class keeps track of where bracket pairs (parenthesis, square brackets and
curly brackets) are in the document so they can be highlighted and colorized
when this feature is activated. It will also colorize unbalanced brackets as
errors. Brackets in comments and strings are ignored.
#### Autocomplete
This class keeps track of autocomplete activities when the feature is configured.
Once autocomplete is triggered, this class tracks the state, interacts with the
user and uses an external callback to provide suggestions in the current context
(see [details here](docs/autocomplete.md)).
#### Coordinate
Coordinates represent a character coordinate from the user's point of view,
i. e. consider an uniform grid on the screen as it is rendered, and each cell
has its own coordinate, starting from Tabs are counted as [1..tabsize]
spaces, depending on how many spaces are necessary to reach the next tab stop.
For example, coordinate (1, 5) represents the character 'B' in a line "\tABC",
when tabsize = 4, because it is rendered as "&nbsp;&nbsp;&nbsp;&nbsp;ABC" on the screen.
#### TextEditor
As mentioned above, the TextEditor class provides the public API. As is true
for all Dear InGui and the original text editor, all public member functions start
with an uppercase letter. Internally, all private member functions and variables
start with a lowercase letter so it's easy to see what's public and what's private.
In addition to being the public interface, the TextEditor class is also responsible
for synchronizing the state of the lower levels of the architecture. When for
instance the user pastes some text, TextEditor ensures that the Document gets
updated, Cursors get adjusted (if required), Transaction records are created (so
this paste operation can be undone and redone) and the Colorizer/Bracketeer are
informed of the changes.
The final responsibility of the TextEditor class is overall rendering and
user input (keyboard and mouse) processing.
#### TextDiff
TextDiff is a separate widget that is derived from TextEditor which allows
you to show the differences between two versions of some code while preserving color
highlighting. The code for this widget is in separate files (see integration above)
so it is optional. TextDiff is readonly and has two modes:
- **Integrated view** where differences are depicted vertically using the standard "diff" look and feel. This view is
implemented as a read-only TextEditor with markings and a line decorator which means that functions like text select
and copy are available. This is the default view.
- **Side-by-side view** where the original and altered versions are shown/compared side-by-side. This a a custom static
view that does not have the usual TextEditor features like text select or copy. Scrolling however is available.
In both modes, the provided text can be colored based on a specified language and
color palette like in the TextEditor. The background colors for the difference
highlighting are not part of the palette but can still be changed through a the public API.
Below are two screenshots of its use in both modes. Have a look at the code in the [example application](example/) to
see how easy it is to use this TextDiff widget.
![Screenshot 2](docs/textDiffCombined.png)
![Screenshot 3](docs/textDiffSideBySide.png)
## Issues
If you are interested in using this Text Editor, steal parts of the code, make
suggestions for improvements or contribute fixes/enhancements, be my guest as this
repository is released under the MIT license. For people that want to contribute,
[Contributing Guidelines](CONTRIBUTING.md) and a [Code of Conduct](CODE_OF_CONDUCT.md)
are available. If you find any problems or want to make a suggestion for improvement, please
[raise an issue on this repository](https://github.com/goossens/ImGuiColorTextEdit/issues).
## Credits
This version of ImGuiColorTextEdit was written from scratch by [Johan A. Goossens](https://github.com/goossens)
and if you end up using (parts of) this repository a shoutout or Github star would be appreciated.
Thank you to [Omar Cornut](https://github.com/ocornut/imgui) for creating Dear ImGui
in the first place. Without you, this editor would not exist.
I owe a great deal of gratitude to [Balázs Jákó](https://github.com/BalazsJako/ImGuiColorTextEdit)
who started this editor many years ago.
I also have to thank [Santiago (santaclose)](https://github.com/santaclose/ImGuiColorTextEdit)
for reviving this project, merging the unfinished developments and pull requests.
He was also responsible for adding features to the editor like multiple cursors.
Given that neither Balázs nor Santiago kept a credits list, it is highly likely
that many others have also made contributions. Theoretically I could go through
all the issues on the original and the fork but I think I have better use for my
time. If you believe you deserve credit here, please raise an issue with reference
to your work. I'll gladly add it.
For the Text Diff widget, credit goes to [Tatsuhiko Kubo (cubicdaiya)](https://github.com/cubicdaiya)
for his [Diff Template Library (DTL)](https://github.com/cubicdaiya/dtl) which is
released under the BSD License.
## License
This work is licensed under the terms of the MIT license.
For a copy, see <https://opensource.org/licenses/MIT>.
The included DTL library (which is only used in the Diff Widget) is released under the
[BSD license](https://github.com/cubicdaiya/dtl/blob/master/COPYING).
File diff suppressed because it is too large Load Diff
+121
View File
@@ -0,0 +1,121 @@
// TextDiff - A syntax highlighting text diff widget for Dear ImGui.
// Copyright (c) 2024-2026 Johan A. Goossens. All rights reserved.
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#pragma once
//
// Include files
//
#include "TextEditor.h"
//
// TextDiff
//
class IMGUI_API TextDiff : public TextEditor
{
public:
// constructor
TextDiff();
// specify visual mode (combined is default)
inline void SetSideBySideMode(bool flag)
{
sideBySideMode = flag;
}
inline bool GetSideBySideMode() const
{
return sideBySideMode;
}
// specify the text to be compared (using UTF-8 encoded strings)
void SetText(const std::string_view &left, const std::string_view &right);
// specify a new language
void SetLanguage(const Language *l);
// specify the background color for added/deleted lines
inline void SetColors(ImU32 ac, ImU32 dc)
{
addedColor = ac;
deletedColor = dc;
}
// render the text editor in a Dear ImGui context
void Render(const char *title, const ImVec2 &size = ImVec2(), bool border = false);
private:
// rendering mode
bool sideBySideMode = false;
// the two documents being compared
TextEditor::Document leftDocument;
TextEditor::Document rightDocument;
// number of digits in line numbers
int leftLineNumberDigits;
int rightLineNumberDigits;
// status of text line
enum class LineStatus
{
common,
added,
deleted
};
// information about a single visible line
class LineInfo
{
public:
LineInfo(size_t l, size_t r, LineStatus s)
: leftLine(l)
, rightLine(r)
, status(s)
{
}
size_t leftLine;
size_t rightLine;
LineStatus status;
};
std::vector<LineInfo> lineInfo;
bool updated = false;
// colors
ImU32 addedColor = IM_COL32(0, 150, 32, 128);
ImU32 deletedColor = IM_COL32(180, 0, 32, 128);
// side-by-side rendering parameters
float leftLineNumberWidth;
float rightLineNumberWidth;
float textColumnWidth;
float leftLineNumberPos;
float leftTextPos;
float rightLineNumberPos;
float rightTextPos;
float rightTextEnd;
float textScroll;
// split string into lines
void splitLines(std::vector<std::string_view> &result, const std::string_view &text);
// create a combined view of the two documents and their differences
void createCombinedView();
// line decorator
void decorateLine(TextEditor::Decorator &decorator);
// render the side-by-side mode and its parts
void renderSideBySide(const char *title, const ImVec2 &size, bool border);
void renderSideBySideBackground();
void renderSideBySideText();
void renderSideBySideLine(float x, float y, TextEditor::Line &line);
void renderSideBySideTextScrollbars();
void renderSideBySideMiniMap();
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

@@ -0,0 +1,176 @@
# Autocomplete
The text editor provides an optional autocomplete framework. Once configured, the editor
takes care of activation events (triggering), state tracking, visualization and insertion
of suggestions with full undo/redo. The application is responsible for providing the list
of suggestions through a callback or the API. This allows simple implementations to provide
suggestions in realtime and allows other implementations to do things asynchronously like
reaching out to a language server. Autocomplete can't be triggered when multiple cursors
are active as this causes a mess. Try it in Visual Studio Code if you want to see what I mean.
![Autocomplete](autocomplete.png)
To activate the feature, the app must provide a configuration like:
```c++
TextEditor::AutoCompleteConfig config;
config.callback = [this](TextEditor::AutoCompleteState& state) {
....
};
editor.SetAutoCompleteConfig(&config);
```
Deactivation can be achieved by passing **nullptr** to **SetAutoCompleteConfig**.
The **TextEditor::AutoCompleteConfig** class contains all the configuration options
and is defined as (please note defaults):
```c++
class AutoCompleteConfig {
public:
// specifies whether typing by the user triggers autocomplete
bool triggerOnTyping = true;
// specifies whether the specified shortcut triggers autocomplete
bool triggerOnShortcut = true;
// specifies whether typing (or shortcut) in comments or strings triggers autocomplete
bool triggerInComments = false;
bool triggerInStrings = false;
// manual trigger key sequence (default is Ctrl+space on all platforms, even MacOS)
// remember Dear ImGui reverses Ctrl and Command on MacOS
#if __APPLE__
ImGuiKeyChord triggerShortcut = ImGuiMod_Super | ImGuiKey_Space;
#else
ImGuiKeyChord triggerShortcut = ImGuiMod_Ctrl | ImGuiKey_Space;
#endif
// see if single suggestions are automatically inserted
// this only works when triggered manually
bool autoInsertSingleSuggestions = false;
// delay in milliseconds between autocomplete trigger and suggestions popup
std::chrono::milliseconds triggerDelay{200};
// text label used when no suggestions are available (this allows for internationalization)
std::string noSuggestionsLabel = "No suggestions";
// called when autocomplete is configured, active and the editor needs an updated suggestions list
// callback must populate and order suggestions in state object
// suggestion list is not cleared by editor between callbacks
// callback is called during the rendering process (so don't take too long)
// if it takes too long, applications should do search in separate thread and
// use API to report results (see SetAutoCompleteSuggestions)
// callback should set suggestionsPromise to true in this case
std::function<void(AutoCompleteState&)> callback;
// optional opaque void* that must be managed externally but passed to callback
void* userData = nullptr;
};
```
When the callback is activated, a **TextEditor::AutoCompleteState** object is passed
informing the app about the context and providing space to return suggestions.
It is defined as:
```c++
class AutoCompleteState {
public:
// current context (strings = UTF-8, columns = Nth visible column and indices = Nth codepoint)
// to understand the difference between column and index, think like a tab :-)
std::string searchTerm;
size_t line;
size_t searchTermStartColumn;
size_t searchTermStartIndex;
size_t searchTermEndColumn;
size_t searchTermEndIndex;
bool inIdentifier;
bool inNumber;
bool inComment;
bool inString;
// currently selected language (could be nullptr if no language is selected)
const Language* language;
// opaque void* provided by app when autocomplete was setup
void* userData;
// auto complete suggestions te be provided by app callback (the app is responsible for sorting)
// the editor does not automatically include language specific keywords or identifiers in the suggestion list
// this is left to the application so it can be context specific in case a language server is used
// a pointer to the current language definition is provided so callbacks have easy access
std::vector<std::string> suggestions;
// set this to true if you are building the suggestion list asynchronously and provide it later
// this way autocomplete is not cancelled if the suggestion list is empty and the user hits tab or enter
bool suggestionsPromise = false;
};
```
The editor also comes with a Trie class that implements fuzzy searching and
the example app shows how it can be used. Given that this is a primitive,
poor-man's solution, more sophisticated solutions probably required external
language engines/services that are beyond the scope of this editor. With the
provided API however, connections to external capabilities can be established
and context-sensitive suggestions can be provided based on the most advanced
algorithms (even good-old AI slop :-).
Below is a quick snippet that shows how to use the Trie class to implement
a poor-man's autocomplete without using a language server. This snippet
was taken from the [example application](../example/) so can see it in
context.
```c++
void Editor::setAutocompleteMode(bool flag) {
// see we are turning autocomplete on or off
if (flag) {
// rebuild word list
buildAutocompleteTrie();
// setup autocomplete by submitting a new configuration
TextEditor::AutoCompleteConfig config;
config.callback = [this](TextEditor::AutoCompleteState& state) {
trie.findSuggestions(state.suggestions, state.searchTerm);
};
editor.SetAutoCompleteConfig(&config);
// enable change tracking
// we don't track every keystroke, callbacks can be delayed up to 3000 milliseconds
// if you want live tracking, change 3000 to 0 (performance hit will be minimal for small documents)
editor.SetChangeCallback([this]() {
buildAutocompleteTrie();
}, 3000);
} else {
// disable autocomplete and change tracking
editor.SetAutoCompleteConfig(nullptr);
editor.SetChangeCallback(nullptr);
}
}
void Editor::buildAutocompleteTrie() {
// empty list first
trie.clear();
// add language words (if required)
auto language = editor.GetLanguage();
if (language) {
for (auto& word : language->keywords) { trie.insert(word); }
for (auto& word : language->declarations) { trie.insert(word); }
for (auto& word : language->identifiers) { trie.insert(word); }
}
// add all identifiers in current document
editor.IterateIdentifiers([this](const std::string& identifier) {
trie.insert(identifier);
});
}
```

Some files were not shown because too many files have changed in this diff Show More