Merge pull request #96 from Melix19/improved_tab_look
Decreased tab symbol size to improve look
diff --git a/README.md b/README.md
index 20506b6..2322424 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@
- color palette support: you can switch between different color palettes, or even define your own
# Known issues
- - syntax highligthing of most languages - except C/C++ - is based on std::regex, which is diasppointingly slow. Because of that, the highlighting process is amortized between multiple frames. C/C++ has a hand-written tokenizer which is much faster.
+ - syntax highligthing of most languages - except C/C++ and Lua - is based on std::regex, which is diasppointingly slow. Because of that, the highlighting process is amortized between multiple frames. C/C++ and Lua have a hand-written tokenizer which is much faster.
Please post your screenshots if you find this little piece of software useful. :)
diff --git a/TextEditor.cpp b/TextEditor.cpp
index 1d4c989..a2b4138 100644
--- a/TextEditor.cpp
+++ b/TextEditor.cpp
@@ -105,9 +105,7 @@
{
istart = 0;
++lstart;
-
- if (lstart < lend)
- result += '\n';
+ result += '\n';
}
}
@@ -300,7 +298,7 @@
auto d = UTF8CharLength(*aValue);
while (d-- > 0 && *aValue != '\0')
line.insert(line.begin() + cindex++, Glyph(*aValue++, PaletteIndex::Default));
- ++aWhere.mColumn;
+ aWhere.mColumn = GetCharacterColumn(aWhere.mLine, cindex);
}
mTextChanged = true;
@@ -699,73 +697,82 @@
void TextEditor::HandleKeyboardInputs()
{
- ImGuiIO& io = ImGui::GetIO();
- auto shift = io.KeyShift;
- auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
- auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
-
if (ImGui::IsWindowFocused())
{
if (ImGui::IsWindowHovered())
ImGui::SetMouseCursor(ImGuiMouseCursor_TextInput);
//ImGui::CaptureKeyboardFromApp(true);
+ ImGuiIO& io = ImGui::GetIO();
+ auto isOSX = io.ConfigMacOSXBehaviors;
+ auto alt = io.KeyAlt;
+ auto ctrl = io.KeyCtrl;
+ auto shift = io.KeyShift;
+ auto super = io.KeySuper;
+
+ auto isShortcut = (isOSX ? (super && !ctrl) : (ctrl && !super)) && !alt && !shift;
+ auto isShiftShortcut = (isOSX ? (super && !ctrl) : (ctrl && !super)) && shift && !alt;
+ auto isWordmoveKey = isOSX ? alt : ctrl;
+ auto isAltOnly = alt && !ctrl && !shift && !super;
+ auto isCtrlOnly = ctrl && !alt && !shift && !super;
+ auto isShiftOnly = shift && !alt && !ctrl && !super;
+
io.WantCaptureKeyboard = true;
io.WantTextInput = true;
- if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z)))
+ if (!IsReadOnly() && isShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z)))
Undo();
- else if (!IsReadOnly() && !ctrl && !shift && alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
+ else if (!IsReadOnly() && isAltOnly && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
Undo();
- else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
+ else if (!IsReadOnly() && isShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
Redo();
- else if (!IsReadOnly() && ctrl && shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z)))
+ else if (!IsReadOnly() && isShiftShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z)))
Redo();
- else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
+ else if (!alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
MoveUp(1, shift);
- else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
+ else if (!alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
MoveDown(1, shift);
- else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
- MoveLeft(1, shift, ctrl);
- else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
- MoveRight(1, shift, ctrl);
- else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp)))
+ else if ((isOSX ? !ctrl : !alt) && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
+ MoveLeft(1, shift, isWordmoveKey);
+ else if ((isOSX ? !ctrl : !alt) && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
+ MoveRight(1, shift, isWordmoveKey);
+ else if (!alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp)))
MoveUp(GetPageSize() - 4, shift);
- else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown)))
+ else if (!alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown)))
MoveDown(GetPageSize() - 4, shift);
- else if (!alt && ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
+ else if (ctrl && !alt && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
MoveTop(shift);
- else if (ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
+ else if (ctrl && !alt && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
MoveBottom(shift);
- else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
+ else if (!alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
MoveHome(shift);
- else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
+ else if (!alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
MoveEnd(shift);
- else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
+ else if (!IsReadOnly() && !alt && !ctrl && !shift && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
Delete();
- else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
+ else if (!IsReadOnly() && !alt && !ctrl && !shift && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
Backspace();
- else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
+ else if (!alt && !ctrl && !shift && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
mOverwrite ^= true;
- else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
+ else if (isCtrlOnly && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
Copy();
- else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
+ else if (isShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
Copy();
- else if (!IsReadOnly() && !ctrl && shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
+ else if (!IsReadOnly() && isShiftOnly && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
Paste();
- else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_V)))
+ else if (!IsReadOnly() && isShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_V)))
Paste();
- else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_X)))
+ else if (isShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_X)))
Cut();
- else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
+ else if (isShiftOnly && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
Cut();
- else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_A)))
+ else if (isShortcut && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_A)))
SelectAll();
- else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
+ else if (!IsReadOnly() && !alt && !ctrl && !shift && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
EnterCharacter('\n', false);
- else if (!IsReadOnly() && !ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab)))
+ else if (!IsReadOnly() && !alt && !ctrl && !super && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab)))
EnterCharacter('\t', shift);
- if (!IsReadOnly() && !io.InputQueueCharacters.empty() && !ctrl)
+ if (!IsReadOnly() && !io.InputQueueCharacters.empty() && !ctrl && !super)
{
for (int i = 0; i < io.InputQueueCharacters.Size; i++)
{
@@ -2116,7 +2123,9 @@
std::string TextEditor::GetText() const
{
- return GetText(Coordinates(), Coordinates((int)mLines.size(), 0));
+ auto lastLine = (int)mLines.size() - 1;
+ auto lastLineLength = GetLineMaxColumn(lastLine);
+ return GetText(Coordinates(), Coordinates(lastLine, lastLineLength));
}
std::vector<std::string> TextEditor::GetTextLines() const
@@ -2355,18 +2364,18 @@
auto& startStr = mLanguageDefinition.mCommentStart;
auto& singleStartStr = mLanguageDefinition.mSingleLineComment;
- if (singleStartStr.size() > 0 &&
- currentIndex + singleStartStr.size() <= line.size() &&
- equals(singleStartStr.begin(), singleStartStr.end(), from, from + singleStartStr.size(), pred))
- {
- withinSingleLineComment = true;
- }
- else if (!withinSingleLineComment && currentIndex + startStr.size() <= line.size() &&
+ if (!withinSingleLineComment && currentIndex + startStr.size() <= line.size() &&
equals(startStr.begin(), startStr.end(), from, from + startStr.size(), pred))
{
commentStartLine = currentLine;
commentStartIndex = currentIndex;
}
+ else if (singleStartStr.size() > 0 &&
+ currentIndex + singleStartStr.size() <= line.size() &&
+ equals(singleStartStr.begin(), singleStartStr.end(), from, from + singleStartStr.size(), pred))
+ {
+ withinSingleLineComment = true;
+ }
inComment = inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
@@ -2761,6 +2770,177 @@
return false;
}
+static bool TokenizeLuaStyleString(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end)
+{
+ const char * p = in_begin;
+
+ bool is_single_quote = false;
+ bool is_double_quotes = false;
+ bool is_double_square_brackets = false;
+
+ switch (*p)
+ {
+ case '\'':
+ is_single_quote = true;
+ break;
+ case '"':
+ is_double_quotes = true;
+ break;
+ case '[':
+ p++;
+ if (p < in_end && *(p) == '[')
+ is_double_square_brackets = true;
+ break;
+ }
+
+ if (is_single_quote || is_double_quotes || is_double_square_brackets)
+ {
+ p++;
+
+ while (p < in_end)
+ {
+ // handle end of string
+ if ((is_single_quote && *p == '\'') || (is_double_quotes && *p == '"') || (is_double_square_brackets && *p == ']' && p + 1 < in_end && *(p + 1) == ']'))
+ {
+ out_begin = in_begin;
+
+ if (is_double_square_brackets)
+ out_end = p + 2;
+ else
+ out_end = p + 1;
+
+ return true;
+ }
+
+ // handle escape character for "
+ if (*p == '\\' && p + 1 < in_end && (is_single_quote || is_double_quotes))
+ p++;
+
+ p++;
+ }
+ }
+
+ return false;
+}
+
+static bool TokenizeLuaStyleIdentifier(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end)
+{
+ const char * p = in_begin;
+
+ if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || *p == '_')
+ {
+ p++;
+
+ while ((p < in_end) && ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_'))
+ p++;
+
+ out_begin = in_begin;
+ out_end = p;
+ return true;
+ }
+
+ return false;
+}
+
+static bool TokenizeLuaStyleNumber(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end)
+{
+ const char * p = in_begin;
+
+ const bool startsWithNumber = *p >= '0' && *p <= '9';
+
+ if (*p != '+' && *p != '-' && !startsWithNumber)
+ return false;
+
+ p++;
+
+ bool hasNumber = startsWithNumber;
+
+ while (p < in_end && (*p >= '0' && *p <= '9'))
+ {
+ hasNumber = true;
+
+ p++;
+ }
+
+ if (hasNumber == false)
+ return false;
+
+ if (p < in_end)
+ {
+ if (*p == '.')
+ {
+ p++;
+
+ while (p < in_end && (*p >= '0' && *p <= '9'))
+ p++;
+ }
+
+ // floating point exponent
+ if (p < in_end && (*p == 'e' || *p == 'E'))
+ {
+ p++;
+
+ if (p < in_end && (*p == '+' || *p == '-'))
+ p++;
+
+ bool hasDigits = false;
+
+ while (p < in_end && (*p >= '0' && *p <= '9'))
+ {
+ hasDigits = true;
+
+ p++;
+ }
+
+ if (hasDigits == false)
+ return false;
+ }
+ }
+
+ out_begin = in_begin;
+ out_end = p;
+ return true;
+}
+
+static bool TokenizeLuaStylePunctuation(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end)
+{
+ (void)in_end;
+
+ switch (*in_begin)
+ {
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case '!':
+ case '%':
+ case '#':
+ case '^':
+ case '&':
+ case '*':
+ case '(':
+ case ')':
+ case '-':
+ case '+':
+ case '=':
+ case '~':
+ case '|':
+ case '<':
+ case '>':
+ case '?':
+ case ':':
+ case '/':
+ case ';':
+ case ',':
+ case '.':
+ out_begin = in_begin;
+ out_end = in_begin + 1;
+ return true;
+ }
+
+ return false;
+}
+
const TextEditor::LanguageDefinition& TextEditor::LanguageDefinition::CPlusPlus()
{
static bool inited = false;
@@ -3138,7 +3318,7 @@
if (!inited)
{
static const char* const keywords[] = {
- "and", "break", "do", "", "else", "elseif", "end", "false", "for", "function", "if", "in", "", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while"
+ "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while"
};
for (auto& k : keywords)
@@ -3163,13 +3343,30 @@
langDef.mIdentifiers.insert(std::make_pair(std::string(k), id));
}
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("L?\\\"(\\\\.|[^\\\"])*\\\"", PaletteIndex::String));
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("\\\'[^\\\']*\\\'", PaletteIndex::String));
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?", PaletteIndex::Number));
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?", PaletteIndex::Number));
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("[+-]?[0-9]+[Uu]?[lL]?[lL]?", PaletteIndex::Number));
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("[a-zA-Z_][a-zA-Z0-9_]*", PaletteIndex::Identifier));
- langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/\\;\\,\\.]", PaletteIndex::Punctuation));
+ langDef.mTokenize = [](const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex) -> bool
+ {
+ paletteIndex = PaletteIndex::Max;
+
+ while (in_begin < in_end && isascii(*in_begin) && isblank(*in_begin))
+ in_begin++;
+
+ if (in_begin == in_end)
+ {
+ out_begin = in_end;
+ out_end = in_end;
+ paletteIndex = PaletteIndex::Default;
+ }
+ else if (TokenizeLuaStyleString(in_begin, in_end, out_begin, out_end))
+ paletteIndex = PaletteIndex::String;
+ else if (TokenizeLuaStyleIdentifier(in_begin, in_end, out_begin, out_end))
+ paletteIndex = PaletteIndex::Identifier;
+ else if (TokenizeLuaStyleNumber(in_begin, in_end, out_begin, out_end))
+ paletteIndex = PaletteIndex::Number;
+ else if (TokenizeLuaStylePunctuation(in_begin, in_end, out_begin, out_end))
+ paletteIndex = PaletteIndex::Punctuation;
+
+ return paletteIndex != PaletteIndex::Max;
+ };
langDef.mCommentStart = "--[[";
langDef.mCommentEnd = "]]";