forked from dfranx/ImGuiColorTextEdit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathImGuiColorTextEdit.h
More file actions
1047 lines (870 loc) · 37.9 KB
/
ImGuiColorTextEdit.h
File metadata and controls
1047 lines (870 loc) · 37.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#ifndef IMGUICTE_ENABLE_SPIRV
#define IMGUICTE_ENABLE_SPIRV 0
#endif
#include <string>
#include <vector>
#include <array>
#include <memory>
#include <unordered_set>
#include <unordered_map>
#include <functional>
#include <thread>
#include <map>
#include <regex>
#include <imgui.h>
#if IMGUICTE_ENABLE_SPIRV
#include <SHADERed/Objects/SPIRVParser.h>
#endif
namespace ImTextEdit {
struct Coordinates {
int mLine; ///< Zero-based line index.
int mColumn; ///< Zero-based column index.
Coordinates()
: mLine(0)
, mColumn(0)
{
}
Coordinates(int aLine, int aColumn)
: mLine(aLine)
, mColumn(aColumn)
{
assert(aLine >= 0);
assert(aColumn >= 0);
}
bool operator==(const Coordinates& o) const
{
return mLine == o.mLine && mColumn == o.mColumn;
}
bool operator!=(const Coordinates& o) const
{
return mLine != o.mLine || mColumn != o.mColumn;
}
bool operator<(const Coordinates& o) const
{
if (mLine != o.mLine)
return mLine < o.mLine;
return mColumn < o.mColumn;
}
bool operator>(const Coordinates& o) const
{
if (mLine != o.mLine)
return mLine > o.mLine;
return mColumn > o.mColumn;
}
bool operator<=(const Coordinates& o) const
{
if (mLine != o.mLine)
return mLine < o.mLine;
return mColumn <= o.mColumn;
}
bool operator>=(const Coordinates& o) const
{
if (mLine != o.mLine)
return mLine > o.mLine;
return mColumn >= o.mColumn;
}
};
inline Coordinates Invalid()
{
static Coordinates invalid(-1, -1);
return invalid;
}
struct Identifier {
Identifier() {}
Identifier(const std::string& declr)
: mDeclaration(declr)
{
}
Coordinates mLocation; ///< Location of the identifier.
std::string mDeclaration;///< Declaration string.
};
typedef std::unordered_map<std::string, Identifier> Identifiers;
typedef std::unordered_set<std::string> Keywords;
enum class PaletteIndex {
Default,
Keyword,
Number,
String,
CharLiteral,
Punctuation,
Preprocessor,
Identifier,
KnownIdentifier,
PreprocIdentifier,
Comment,
MultiLineComment,
Background,
Cursor,
Selection,
ErrorMarker,
Breakpoint,
BreakpointOutline,
CurrentLineIndicator,
CurrentLineIndicatorOutline,
LineNumber,
CurrentLineFill,
CurrentLineFillInactive,
CurrentLineEdge,
ErrorMessage,
BreakpointDisabled,
UserFunction,
UserType,
UniformVariable,
GlobalVariable,
LocalVariable,
FunctionArgument,
Max
};
enum class ShortcutID {
Undo,
Redo,
MoveUp,
SelectUp,
MoveDown,
SelectDown,
MoveLeft,
SelectLeft,
MoveWordLeft,
SelectWordLeft,
MoveRight,
SelectRight,
MoveWordRight,
SelectWordRight,
MoveUpBlock,
SelectUpBlock,
MoveDownBlock,
SelectDownBlock,
MoveTop,
SelectTop,
MoveBottom,
SelectBottom,
MoveStartLine,
SelectStartLine,
MoveEndLine,
SelectEndLine,
ForwardDelete,
ForwardDeleteWord,
DeleteRight,
BackwardDelete,
BackwardDeleteWord,
DeleteLeft,
OverwriteCursor,
Copy,
Paste,
Cut,
SelectAll,
AutocompleteOpen,
AutocompleteSelect,
AutocompleteSelectActive,
AutocompleteUp,
AutocompleteDown,
NewLine,
Indent,
Unindent,
Find,
Replace,
FindNext,
DebugStep,
DebugStepInto,
DebugStepOut,
DebugContinue,
DebugJumpHere,
DebugBreakpoint,
DebugStop,
DuplicateLine,
CommentLines,
UncommentLines,
Count
};
struct Shortcut {
bool Alt;
bool Ctrl;
bool Shift;
int Key1;
int Key2;
Shortcut(int vk1 = -1, int vk2 = -2, bool alt = false, bool ctrl = false, bool shift = false)
: Key1(vk1)
, Key2(vk2)
, Alt(alt)
, Ctrl(ctrl)
, Shift(shift)
{
}
};
enum class SelectionMode {
Normal,
Word,
Line
};
struct LanguageDefinition {
typedef std::pair<std::string, PaletteIndex> TokenRegexString;
typedef std::vector<TokenRegexString> TokenRegexStrings;
typedef bool (*TokenizeCallback)(const char* in_begin, const char* in_end, const char*& out_begin, const char*& out_end,
PaletteIndex& paletteIndex);
std::string mName;
Keywords mKeywords;
Identifiers mIdentifiers;
Identifiers mPreprocIdentifiers;
std::vector<std::string> single_line_comments;
std::vector<std::pair<std::string,std::string>> block_comments;
char mPreprocChar;
bool mAutoIndentation;
TokenizeCallback mTokenize;
TokenRegexStrings mTokenRegexStrings;
bool mCaseSensitive;
LanguageDefinition()
: mPreprocChar('#')
, mAutoIndentation(true)
, mTokenize(nullptr)
, mCaseSensitive(true)
{
}
};
const LanguageDefinition& CPlusPlus();
const LanguageDefinition& HLSL();
const LanguageDefinition& GLSL();
const LanguageDefinition& SPIRV();
const LanguageDefinition& C();
const LanguageDefinition& SQL();
const LanguageDefinition& AngelScript();
const LanguageDefinition& Lua();
const LanguageDefinition& JSON();
const LanguageDefinition& JSONC();
const LanguageDefinition& JSONWithHash();
/// \brief JSON5 language definition for ImGuiColorTextEdit.
/// Notes:
/// - Regex syntax: std::regex ECMAScript (no non-capturing groups).
/// - Order matters: numbers (incl. Infinity/NaN/hex) go before identifiers.
/// - Strings support line continuation via backslash-newline (\\\r?\n).
const LanguageDefinition& JSON5();
/// \brief Markdown language definition (basic highlighting).
const LanguageDefinition& Markdown();
/// \brief dotenv (.env) language definition.
const LanguageDefinition& DotEnv();
/// \brief XML language definition.
const LanguageDefinition& XML();
/// \brief CSV language definition (comma/semicolon separated, quoted fields).
const LanguageDefinition& CSV();
/// \brief HTML language definition.
const LanguageDefinition& HTML();
/// \brief CSS language definition.
const LanguageDefinition& CSS();
/// \brief CMake language definition.
/// Highlights common commands, variables ${...}, strings, comments.
const LanguageDefinition& CMake();
/// \brief YAML language definition (coarse tokenization).
/// Notes: indentation-sensitive grammar is not modeled; tokens only.
const LanguageDefinition& YAML();
/// \brief TOML language definition (1.0-ish, coarse).
const LanguageDefinition& TOML();
/// \brief INI language definition: [section], key=value, ;/# comments.
const LanguageDefinition& INI();
/// \brief Dockerfile language definition.
const LanguageDefinition& Dockerfile();
/// \brief Diff/patch language definition (unified diff).
const LanguageDefinition& Diff();
/// \brief Bash / POSIX shell language definition.
const LanguageDefinition& Bash();
enum class DebugAction
{
Step,
StepInto,
StepOut,
Continue,
Stop
};
/// \brief Interactive text editor with syntax highlighting for ImGui.
/// \note Right-to-left scripts and complex text shaping are not supported.
class TextEditor {
public:
static const int LineNumberSpace = 20;
static const int DebugDataSpace = 10;
/// \brief Represents a debugger breakpoint.
struct Breakpoint {
int mLine; ///< Line index where the breakpoint is located.
bool mEnabled; ///< Indicates whether the breakpoint is enabled.
bool mUseCondition; ///< True if a conditional expression is evaluated.
std::string mCondition; ///< Conditional expression evaluated at runtime.
Breakpoint()
: mLine(-1)
, mEnabled(false)
{
}
};
typedef std::string String;
typedef std::map<int, std::string> ErrorMarkers;
typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;
typedef uint8_t Char;
struct Glyph {
Char mChar; ///< Character code point.
PaletteIndex mColorIndex = PaletteIndex::Default; ///< Highlight color index.
bool mComment : 1; ///< True if part of a single-line comment.
bool mMultiLineComment : 1; ///< True if part of a multi-line comment.
bool mPreprocessor : 1; ///< True if part of a preprocessor block.
Glyph(Char aChar, PaletteIndex aColorIndex)
: mChar(aChar)
, mColorIndex(aColorIndex)
, mComment(false)
, mMultiLineComment(false)
, mPreprocessor(false)
{
}
};
typedef std::vector<Glyph> Line;
typedef std::vector<Line> Lines;
/// \brief Create a text editor instance.
TextEditor();
/// \brief Destroy the editor instance.
~TextEditor();
/// \brief Set the language definition used for syntax highlighting.
/// \param aLanguageDef Language definition to apply.
void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
/// \brief Get current language definition.
/// \return Reference to the active language definition.
const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
/// \brief Get the active color palette.
/// \return Palette describing colors for each \ref PaletteIndex.
const Palette& GetPalette() const { return mPaletteBase; }
/// \brief Set the color palette used for rendering.
/// \param aValue New palette value.
void SetPalette(const Palette& aValue);
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
bool HasBreakpoint(int line);
void AddBreakpoint(int line, bool useCondition = false, std::string condition = "", bool enabled = true);
void RemoveBreakpoint(int line);
void SetBreakpointEnabled(int line, bool enable);
Breakpoint& GetBreakpoint(int line);
inline const std::vector<Breakpoint>& GetBreakpoints() { return mBreakpoints; }
void SetCurrentLineIndicator(int line, bool displayBar = true);
inline int GetCurrentLineIndicator() { return mDebugCurrentLine; }
inline bool IsDebugging() { return mDebugCurrentLine > 0; }
/// \brief Render the editor inside an ImGui window.
/// \param aTitle Window title string.
/// \param aSize Desired size in pixels.
/// \param aBorder Set to true to draw a border.
/// \code
/// ImTextEdit::TextEditor editor;
/// editor.SetText("int main() { return 0; }");
/// editor.Render("Code");
/// \endcode
void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
/// \brief Replace the entire editor contents.
/// \param aText New text to display.
void SetText(const std::string& aText);
/// \brief Retrieve all text from the editor.
/// \return Complete text buffer.
std::string GetText() const;
/// \brief Set editor text from individual lines.
/// \param aLines Vector where each element represents one line.
void SetTextLines(const std::vector<std::string>& aLines);
/// \brief Copy editor text into a vector of lines.
/// \param out Destination vector receiving one string per line.
void GetTextLines(std::vector<std::string>& out) const;
/// \brief Get currently selected text.
/// \return Selected substring or empty string if nothing is selected.
std::string GetSelectedText() const;
/// \brief Get text from the line containing the cursor.
/// \return Line contents without trailing newline.
std::string GetCurrentLineText() const;
/// \brief Get total number of lines in the document.
/// \return Line count.
int GetTotalLines() const { return (int)mLines.size(); }
/// \brief Determine if overwrite mode is active.
/// \return True when characters replace existing ones.
bool IsOverwrite() const { return mOverwrite; }
/// \brief Check whether the editor window has input focus.
/// \return True if focused.
bool IsFocused() const { return mFocused; }
/// \brief Enable or disable read-only mode.
/// \param aValue True to disallow modifications.
void SetReadOnly(bool aValue);
/// \brief Determine if the editor is currently read-only.
/// \return True if modifications are not permitted.
bool IsReadOnly() { return mReadOnly || IsDebugging(); }
/// \brief Check whether the text has changed since the last reset.
/// \return True if content was modified.
bool IsTextChanged() const { return mTextChanged; }
/// \brief Check whether the cursor position has changed.
/// \return True if the cursor moved.
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
/// \brief Clear the text-changed flag and tracked lines.
inline void ResetTextChanged()
{
mTextChanged = false;
mChangedLines.clear();
}
/// \brief Determine if syntax colorization is enabled.
/// \return True when colorizer is active.
bool IsColorizerEnabled() const { return mColorizerEnabled; }
/// \brief Enable or disable syntax colorization.
/// \param aValue True to enable the colorizer.
void SetColorizerEnable(bool aValue);
/// \brief Get cursor position using configured tab size.
/// \note GetCursorPosition() returns position assuming a tab equals four spaces.
Coordinates GetCorrectCursorPosition();
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
/// \brief Move the cursor to a specific coordinate.
/// \param aPosition Zero-based line and column.
void SetCursorPosition(const Coordinates& aPosition);
/// \brief Enable or disable mouse input handling.
/// \param aValue True to allow mouse interactions.
inline void SetHandleMouseInputs(bool aValue) { mHandleMouseInputs = aValue; }
/// \brief Check if mouse inputs are being handled.
/// \return True when mouse input is enabled.
inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
/// \brief Enable or disable keyboard input handling.
/// \param aValue True to allow keyboard interactions.
inline void SetHandleKeyboardInputs(bool aValue) { mHandleKeyboardInputs = aValue; }
/// \brief Check if keyboard inputs are being handled.
/// \return True when keyboard input is enabled.
inline bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; }
/// \brief Ignore the parent ImGui child region.
/// \param aValue True to ignore child status.
inline void SetImGuiChildIgnored(bool aValue) { mIgnoreImGuiChild = aValue; }
/// \brief Check whether child region status is ignored.
/// \return True when child is ignored.
inline bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; }
/// \brief Toggle visualization of whitespace characters.
/// \param aValue True to display spaces and tabs.
inline void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; }
/// \brief Determine if whitespace visualization is enabled.
/// \return True when spaces and tabs are shown.
inline bool IsShowingWhitespaces() const { return mShowWhitespaces; }
/// \brief Insert text at the cursor position.
/// \param aValue String to insert.
/// \param indent True to auto-indent inserted text.
void InsertText(const std::string& aValue, bool indent = false);
/// \brief Insert text at the cursor position.
/// \param aValue Null-terminated string to insert.
/// \param indent True to auto-indent inserted text.
void InsertText(const char* aValue, bool indent = false);
/// \brief Move the cursor up by a number of lines.
/// \param aAmount Number of lines to move.
/// \param aSelect True to extend the selection.
void MoveUp(int aAmount = 1, bool aSelect = false);
/// \brief Move the cursor down by a number of lines.
/// \param aAmount Number of lines to move.
/// \param aSelect True to extend the selection.
void MoveDown(int aAmount = 1, bool aSelect = false);
/// \brief Move the cursor left.
/// \param aAmount Number of columns to move.
/// \param aSelect True to extend the selection.
/// \param aWordMode When true, move by words instead of characters.
void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
/// \brief Move the cursor right.
/// \param aAmount Number of columns to move.
/// \param aSelect True to extend the selection.
/// \param aWordMode When true, move by words instead of characters.
void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
/// \brief Move the cursor to the first line.
/// \param aSelect True to extend the selection.
void MoveTop(bool aSelect = false);
/// \brief Move the cursor to the last line.
/// \param aSelect True to extend the selection.
void MoveBottom(bool aSelect = false);
/// \brief Move the cursor to the beginning of the current line.
/// \param aSelect True to extend the selection.
void MoveHome(bool aSelect = false);
/// \brief Move the cursor to the end of the current line.
/// \param aSelect True to extend the selection.
void MoveEnd(bool aSelect = false);
/// \brief Set the beginning of the selection.
/// \param aPosition Start coordinate.
void SetSelectionStart(const Coordinates& aPosition);
/// \brief Set the end of the selection.
/// \param aPosition End coordinate.
void SetSelectionEnd(const Coordinates& aPosition);
/// \brief Define a selection range.
/// \param aStart Start coordinate.
/// \param aEnd End coordinate.
/// \param aMode Selection behavior.
void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
/// \brief Select the word under the cursor.
void SelectWordUnderCursor();
/// \brief Select the entire document.
void SelectAll();
/// \brief Determine whether text is currently selected.
/// \return True when a selection exists.
bool HasSelection() const;
/// \brief Copy current selection to the clipboard.
void Copy();
/// \brief Cut current selection to the clipboard.
void Cut();
/// \brief Paste clipboard contents at the cursor position.
void Paste();
/// \brief Delete the current selection.
void Delete();
/// \brief Check whether an undo operation is available.
/// \return True if there are actions to undo.
bool CanUndo();
/// \brief Check whether a redo operation is available.
/// \return True if there are actions to redo.
bool CanRedo();
/// \brief Undo a number of actions.
/// \param aSteps Number of steps to undo.
void Undo(int aSteps = 1);
/// \brief Redo a number of actions.
/// \param aSteps Number of steps to redo.
void Redo(int aSteps = 1);
/// \brief Get expressions relevant for debugging on a given line.
/// \param line Line index to inspect.
/// \return List of expressions.
std::vector<std::string> GetRelevantExpressions(int line);
/// \brief Highlight specific lines.
/// \param lines Indices of lines to highlight.
inline void SetHighlightedLines(const std::vector<int>& lines) { mHighlightedLines = lines; }
/// \brief Clear all highlighted lines.
inline void ClearHighlightedLines() { mHighlightedLines.clear(); }
/// \brief Set the width of a tab character.
/// \param s Number of spaces per tab (0-32).
inline void SetTabSize(int s) { mTabSize = std::max<int>(0, std::min<int>(32, s)); }
/// \brief Get the width of a tab character.
/// \return Number of spaces per tab.
inline int GetTabSize() { return mTabSize; }
/// \brief Toggle insertion of spaces instead of tab characters.
/// \param s True to insert spaces.
inline void SetInsertSpaces(bool s) { mInsertSpaces = s; }
/// \brief Check whether spaces are inserted instead of tabs.
/// \return True when spaces are used.
inline int GetInsertSpaces() { return mInsertSpaces; }
/// \brief Enable smart indentation.
/// \param s True to enable.
inline void SetSmartIndent(bool s) { mSmartIndent = s; }
/// \brief Automatically indent pasted text.
/// \param s True to enable.
inline void SetAutoIndentOnPaste(bool s) { mAutoindentOnPaste = s; }
/// \brief Highlight the current line.
/// \param s True to enable line highlighting.
inline void SetHighlightLine(bool s) { mHighlightLine = s; }
/// \brief Automatically insert matching braces.
/// \param s True to enable brace completion.
inline void SetCompleteBraces(bool s) { mCompleteBraces = s; }
/// \brief Enable horizontal scrolling.
/// \param s True to allow horizontal scrolling.
inline void SetHorizontalScroll(bool s) { mHorizontalScroll = s; }
/// \brief Enable predictive autocomplete.
/// \param s True to enable suggestions.
inline void SetSmartPredictions(bool s) { mAutocomplete = s; }
/// \brief Show function declaration tooltip on hover.
/// \param s True to enable.
inline void SetFunctionDeclarationTooltip(bool s) { mFunctionDeclarationTooltipEnabled = s; }
/// \brief Show user function tooltips on hover.
/// \param s True to enable.
inline void SetFunctionTooltips(bool s) { mFuncTooltips = s; }
/// \brief Manually activate or deactivate autocomplete popup.
/// \param cac True to activate.
inline void SetActiveAutocomplete(bool cac) { mActiveAutocomplete = cac; }
/// \brief Display markers on the scrollbar.
/// \param markers True to enable markers.
inline void SetScrollbarMarkers(bool markers) { mScrollbarMarkers = markers; }
/// \brief Show or hide the sidebar.
/// \param s True to show the sidebar.
inline void SetSidebarVisible(bool s) { mSidebar = s; }
/// \brief Enable or disable search UI.
/// \param s True to allow searching.
inline void SetSearchEnabled(bool s) { mHasSearch = s; }
/// \brief Highlight matching brackets.
/// \param s True to enable bracket highlighting.
inline void SetHiglightBrackets(bool s) { mHighlightBrackets = s; }
/// \brief Enable or disable code folding.
/// \param s True to enable folding.
inline void SetFoldEnabled(bool s) { mFoldEnabled = s; }
/// \brief Set UI scale factor.
/// \param scale Scale multiplier.
inline void SetUIScale(float scale) { mUIScale = scale; }
/// \brief Set UI font size in pixels.
/// \param size Font size in pixels.
inline void SetUIFontSize(float size) { mUIFontSize = size; }
/// \brief Set editor font size in pixels.
/// \param size Font size in pixels.
inline void SetEditorFontSize(float size) { mEditorFontSize = size; }
/// \brief Override a default shortcut.
/// \param id Identifier of the shortcut to override.
/// \param s New shortcut definition.
void SetShortcut(ShortcutID id, Shortcut s);
/// \brief Toggle display of line numbers in the sidebar.
/// \param s True to show line numbers.
inline void SetShowLineNumbers(bool s)
{
mShowLineNumbers = s;
mTextStart = (s ? 20 : 6);
mLeftMargin = (s ? (DebugDataSpace + LineNumberSpace) : (DebugDataSpace - LineNumberSpace));
}
/// \brief Get horizontal offset where text rendering starts.
/// \return Offset in pixels from the left edge.
inline int GetTextStart() const { return mShowLineNumbers ? 7 : 3; }
/// \brief Recompute syntax highlighting for a set of lines.
/// \param aFromLine Starting line index.
/// \param aCount Number of lines to colorize, -1 for all remaining lines.
void Colorize(int aFromLine = 0, int aCount = -1);
/// \brief Recompute syntax highlighting for an explicit range.
/// \param aFromLine First line index.
/// \param aToLine Last line index.
void ColorizeRange(int aFromLine = 0, int aToLine = 0);
/// \brief Recompute syntax highlighting for the entire document.
void ColorizeInternal();
# if IMGUICTE_ENABLE_SPIRV
inline void ClearAutocompleteData()
{
mACFunctions.clear();
mACUserTypes.clear();
mACUniforms.clear();
mACGlobals.clear();
}
# else
inline void ClearAutocompleteData() {}
# endif
inline void ClearAutocompleteEntries()
{
mACEntries.clear();
mACEntrySearch.clear();
}
# if IMGUICTE_ENABLE_SPIRV
inline const std::unordered_map<std::string, ed::SPIRVParser::Function>& GetAutocompleteFunctions() { return mACFunctions; }
inline const std::unordered_map<std::string, std::vector<ed::SPIRVParser::Variable>>& GetAutocompleteUserTypes() { return mACUserTypes; }
inline const std::vector<ed::SPIRVParser::Variable>& GetAutocompleteUniforms() { return mACUniforms; }
inline const std::vector<ed::SPIRVParser::Variable>& GetAutocompleteGlobals() { return mACGlobals; }
inline void SetAutocompleteFunctions(const std::unordered_map<std::string, ed::SPIRVParser::Function>& funcs)
{
mACFunctions = funcs;
}
inline void SetAutocompleteUserTypes(const std::unordered_map<std::string, std::vector<ed::SPIRVParser::Variable>>& utypes)
{
mACUserTypes = utypes;
}
inline void SetAutocompleteUniforms(const std::vector<ed::SPIRVParser::Variable>& unis)
{
mACUniforms = unis;
}
inline void SetAutocompleteGlobals(const std::vector<ed::SPIRVParser::Variable>& globs)
{
mACGlobals = globs;
}
# endif
/// \brief Add a custom autocomplete entry.
/// \param search Lookup string used for filtering suggestions.
/// \param display Text displayed in the suggestion list.
/// \param value Text inserted when the suggestion is accepted.
inline void AddAutocompleteEntry(const std::string& search, const std::string& display, const std::string& value)
{
mACEntrySearch.push_back(search);
mACEntries.push_back(std::make_pair(display, value));
}
std::function<void(TextEditor*, int)> OnDebuggerJump;
std::function<void(TextEditor*, DebugAction)> OnDebuggerAction;
std::function<void(TextEditor*, const std::string&)> OnIdentifierHover;
std::function<bool(TextEditor*, const std::string&)> HasIdentifierHover;
std::function<void(TextEditor*, const std::string&)> OnExpressionHover;
std::function<bool(TextEditor*, const std::string&)> HasExpressionHover;
std::function<void(TextEditor*, int)> OnBreakpointRemove;
std::function<void(TextEditor*, int, bool, const std::string&, bool)> OnBreakpointUpdate;
std::function<void(TextEditor*, const std::string&, Coordinates coords)> OnCtrlAltClick;
std::function<void(TextEditor*, const std::string&, const std::string&)> RequestOpen;
std::function<void(TextEditor*)> OnContentUpdate;
inline void SetPath(const std::string& path) { mPath = path; }
inline const std::string& GetPath() { return mPath; }
private:
std::string mPath;
typedef std::vector<std::pair<std::regex, PaletteIndex>> RegexList;
struct EditorState
{
Coordinates mSelectionStart;
Coordinates mSelectionEnd;
Coordinates mCursorPosition;
};
class UndoRecord
{
public:
UndoRecord() {}
~UndoRecord() {}
UndoRecord(
const std::string& aAdded,
const Coordinates aAddedStart,
const Coordinates aAddedEnd,
const std::string& aRemoved,
const Coordinates aRemovedStart,
const Coordinates aRemovedEnd,
TextEditor::EditorState& aBefore,
TextEditor::EditorState& aAfter);
void Undo(TextEditor* aEditor);
void Redo(TextEditor* aEditor);
std::string mAdded;
Coordinates mAddedStart;
Coordinates mAddedEnd;
std::string mRemoved;
Coordinates mRemovedStart;
Coordinates mRemovedEnd;
EditorState mBefore;
EditorState mAfter;
};
typedef std::vector<UndoRecord> UndoBuffer;
void ProcessInputs();
float TextDistanceToLineStart(const Coordinates& aFrom) const;
void EnsureCursorVisible();
int GetPageSize() const;
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
Coordinates GetActualCursorCoordinates() const;
Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
void Advance(Coordinates& aCoordinates) const;
void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd);
int InsertTextAt(Coordinates& aWhere, const char* aValue, bool indent = false);
void AddUndo(UndoRecord& aValue);
Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const;
Coordinates MousePosToCoordinates(const ImVec2& aPosition) const;
ImVec2 CoordinatesToScreenPos(const Coordinates& aPosition) const;
Coordinates FindWordStart(const Coordinates& aFrom) const;
Coordinates FindWordEnd(const Coordinates& aFrom) const;
Coordinates FindNextWord(const Coordinates& aFrom) const;
int GetCharacterIndex(const Coordinates& aCoordinates) const;
int GetCharacterColumn(int aLine, int aIndex) const;
int GetLineCharacterCount(int aLine) const;
int GetLineMaxColumn(int aLine) const;
bool IsOnWordBoundary(const Coordinates& aAt) const;
void RemoveLine(int aStart, int aEnd);
void RemoveLine(int aIndex);
Line& InsertLine(int aIndex, int column);
void EnterCharacter(ImWchar aChar, bool aShift);
void Backspace();
void DeleteSelection();
std::string GetWordUnderCursor() const;
std::string GetWordAt(const Coordinates& aCoords) const;
ImU32 GetGlyphColor(const Glyph& aGlyph) const;
Coordinates FindFirst(const std::string& what, const Coordinates& fromWhere);
void HandleKeyboardInputs();
void HandleMouseInputs();
void RenderInternal(const char* aTitle);
bool mFuncTooltips;
float mUIScale, mUIFontSize, mEditorFontSize;
inline float mUICalculateSize(float h)
{
return h * (mUIScale + mUIFontSize / 18.0f - 1.0f);
}
inline float mEditorCalculateSize(float h)
{
return h * (mUIScale + mEditorFontSize / 18.0f - 1.0f);
}
bool mFunctionDeclarationTooltipEnabled;
Coordinates mFunctionDeclarationCoord;
bool mFunctionDeclarationTooltip;
std::string mFunctionDeclaration;
void mOpenFunctionDeclarationTooltip(const std::string& obj, Coordinates coord);
std::string mBuildFunctionDef(const std::string& func, const std::string& lang);
# if IMGUICTE_ENABLE_SPIRV
std::string mBuildVariableType(const ed::SPIRVParser::Variable& var, const std::string& lang);
# endif
float mLineSpacing;
Lines mLines;
EditorState mState;
UndoBuffer mUndoBuffer;
int mUndoIndex;
int mReplaceIndex;
bool mSidebar;
bool mHasSearch;
char mFindWord[256];
bool mFindOpened;
bool mFindJustOpened;
bool mFindNext;
bool mFindFocused, mReplaceFocused;
bool mReplaceOpened;
char mReplaceWord[256];
bool mFoldEnabled;
std::vector<Coordinates> mFoldBegin, mFoldEnd;
std::vector<int> mFoldConnection;
std::vector<bool> mFold;
bool mFoldSorted;
void mRemoveFolds(const Coordinates& start, const Coordinates& end);
void mRemoveFolds(std::vector<Coordinates>& folds, const Coordinates& start, const Coordinates& end);
uint64_t mFoldLastIteration;
float mLastScroll;
std::vector<std::string> mACEntrySearch;
std::vector<std::pair<std::string, std::string>> mACEntries;
bool mIsSnippet;
std::vector<Coordinates> mSnippetTagStart, mSnippetTagEnd;
std::vector<int> mSnippetTagID;
std::vector<bool> mSnippetTagHighlight;
int mSnippetTagSelected, mSnippetTagLength, mSnippetTagPreviousLength;
std::string mAutcompleteParse(const std::string& str, const Coordinates& start);
void mAutocompleteSelect();
bool m_requestAutocomplete, m_readyForAutocomplete;
void m_buildMemberSuggestions(bool* keepACOpened = nullptr);
void m_buildSuggestions(bool* keepACOpened = nullptr);
bool mActiveAutocomplete;
bool mAutocomplete;
# if IMGUICTE_ENABLE_SPIRV
std::unordered_map<std::string, ed::SPIRVParser::Function> mACFunctions;
std::unordered_map<std::string, std::vector<ed::SPIRVParser::Variable>> mACUserTypes;
std::vector<ed::SPIRVParser::Variable> mACUniforms;
std::vector<ed::SPIRVParser::Variable> mACGlobals;
# endif
std::string mACWord;
std::vector<std::pair<std::string, std::string>> mACSuggestions;
int mACIndex;
bool mACOpened;
bool mACSwitched; // if == true then allow selection with enter
std::string mACObject; // if mACObject is not empty, it means user typed '.' -> suggest struct members and methods for mACObject
Coordinates mACPosition;
std::vector<Shortcut> m_shortcuts;
bool mScrollbarMarkers;
std::vector<int> mChangedLines;
std::vector<int> mHighlightedLines;
bool mHorizontalScroll;
bool mCompleteBraces;
bool mShowLineNumbers;
bool mHighlightLine;
bool mHighlightBrackets;
bool mInsertSpaces;
bool mSmartIndent;
bool mFocused;
int mTabSize;
bool mOverwrite;
bool mReadOnly;
bool mWithinRender;
bool mScrollToCursor;
bool mScrollToTop;
bool mTextChanged;
bool mColorizerEnabled;
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
int mLeftMargin;
bool mCursorPositionChanged;
int mColorRangeMin, mColorRangeMax;
SelectionMode mSelectionMode;
bool mHandleKeyboardInputs;