From 4f06ee391deff7ad0e0367efa9ac7028e3a47176 Mon Sep 17 00:00:00 2001 From: cxl Date: Tue, 28 Jul 2015 18:37:43 +0000 Subject: [PATCH] ide: Now shows misplaced whitespaces #1201 git-svn-id: svn://ultimatepp.org/upp/trunk@8763 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/CodeEditor/CodeEditor.cpp | 2 + uppsrc/CodeEditor/Style.cpp | 3 ++ uppsrc/CodeEditor/hl_color.i | 3 ++ uppsrc/CtrlLib/LineEdit.cpp | 52 ++++++++++++++++++++--- uppsrc/CtrlLib/Text.cpp | 2 + uppsrc/CtrlLib/TextEdit.h | 5 +++ uppsrc/CtrlLib/src.tpp/LineEdit$en-us.tpp | 25 ++++++++++- uppsrc/ide/Config.cpp | 4 +- uppsrc/ide/Setup.cpp | 4 +- uppsrc/ide/ide.h | 1 + uppsrc/ide/ide.lay | 25 +++++------ uppsrc/ide/idewin.cpp | 1 + 12 files changed, 106 insertions(+), 21 deletions(-) diff --git a/uppsrc/CodeEditor/CodeEditor.cpp b/uppsrc/CodeEditor/CodeEditor.cpp index 3740cf489..f44c82a32 100644 --- a/uppsrc/CodeEditor/CodeEditor.cpp +++ b/uppsrc/CodeEditor/CodeEditor.cpp @@ -56,6 +56,8 @@ void CodeEditor::Highlight(const String& h) SetColor(LineEdit::PAPER_NORMAL, hl_style[HighlightSetup::PAPER_NORMAL].color); SetColor(LineEdit::PAPER_READONLY, hl_style[HighlightSetup::PAPER_READONLY].color); SetColor(LineEdit::PAPER_SELECTED, hl_style[HighlightSetup::PAPER_SELECTED].color); + SetColor(LineEdit::WHITESPACE, hl_style[HighlightSetup::WHITESPACE].color); + SetColor(LineEdit::WARN_WHITESPACE, hl_style[HighlightSetup::WARN_WHITESPACE].color); Refresh(); EditorBarLayout(); } diff --git a/uppsrc/CodeEditor/Style.cpp b/uppsrc/CodeEditor/Style.cpp index 16619d3eb..0e88af9b7 100644 --- a/uppsrc/CodeEditor/Style.cpp +++ b/uppsrc/CodeEditor/Style.cpp @@ -167,6 +167,9 @@ void HighlightSetup::DefaultHlStyles() SetHlStyle(PAPER_WARNING, Blend(White(), Yellow(), 50)); SetHlStyle(SHOW_LINE, Color(199, 247, 198)); + + SetHlStyle(WHITESPACE, Blend(SColorLight, SColorHighlight)); + SetHlStyle(WARN_WHITESPACE, Blend(SColorLight, SRed)); } END_UPP_NAMESPACE diff --git a/uppsrc/CodeEditor/hl_color.i b/uppsrc/CodeEditor/hl_color.i index 0529b4567..4e7d26ace 100644 --- a/uppsrc/CodeEditor/hl_color.i +++ b/uppsrc/CodeEditor/hl_color.i @@ -58,3 +58,6 @@ HL_COLOR(PAPER_SELWORD, t_("Selected word through file"), 0) HL_COLOR(PAPER_ERROR, t_("Error in compiler messages"), 0) HL_COLOR(PAPER_WARNING, t_("Warning in compiler messages"), 0) HL_COLOR(SHOW_LINE, t_("Current line highlight"), 0) + +HL_COLOR(WHITESPACE, t_("Whitespaces"), 1) +HL_COLOR(WARN_WHITESPACE, t_("Misplaced tabs and spaces"), 1) diff --git a/uppsrc/CtrlLib/LineEdit.cpp b/uppsrc/CtrlLib/LineEdit.cpp index 8a3c993b9..839514d10 100644 --- a/uppsrc/CtrlLib/LineEdit.cpp +++ b/uppsrc/CtrlLib/LineEdit.cpp @@ -24,6 +24,7 @@ LineEdit::LineEdit() { showreadonly = true; dorectsel = false; hline = Null; + warnwhitespace = false; } LineEdit::~LineEdit() {} @@ -304,7 +305,6 @@ void LineEdit::Paint0(Draw& w) { selh -= cpos; int pos = cpos; int fascent = font.Info().GetAscent(); - Color showcolor = Blend(SColorLight, SColorHighlight); int cursorline = GetLine(cursor); Highlight ih; ih.ink = color[IsShowEnabled() ? INK_NORMAL : INK_DISABLED]; @@ -314,7 +314,39 @@ void LineEdit::Paint0(Draw& w) { ih.font = font; ih.chr = 0; for(int i = sc.y; i < ll; i++) { + Color showcolor = color[WHITESPACE]; WString tx = line[i]; + bool warn_whitespace = false; + if(warnwhitespace && i != GetCursorLine()) { + int wkind = 0; + bool empty = true; + for(const wchar *s = tx; *s; s++) { + if(*s == '\t') { + if(wkind == ' ') { + warn_whitespace = true; + break; + } + wkind = '\t'; + } + else + if(*s == ' ') + wkind = ' '; + else + if(*s > ' ') { + empty = false; + wkind = 0; + } + } + if(wkind == ' ') + warn_whitespace = true; + if(empty && !warn_whitespace) { + String l = GetUtf8Line(i); + warn_whitespace = (i < 0 || !GetUtf8Line(i - 1).StartsWith(l)) && + (i >= GetLineCount() || !GetUtf8Line(i - 1).StartsWith(l)); + } + if(warn_whitespace) + showcolor = color[WARN_WHITESPACE]; + } bool do_highlight = tx.GetCount() < 100000; int len = tx.GetLength(); if(w.IsPainting(0, y, sz.cx, fsz.cy)) { @@ -329,6 +361,7 @@ void LineEdit::Paint0(Draw& w) { } else ln = tx.GetCount(); + int lgp = -1; for(int pass = 0; pass < 2; pass++) { int gp = 0; int scx = fsz.cx * sc.x; @@ -354,6 +387,8 @@ void LineEdit::Paint0(Draw& w) { } sOptimizedTextRenderer tw(w); while(q < ln) { + if(q == tx.GetCount()) + lgp = gp; Highlight h; if(do_highlight) h = hl[q]; @@ -374,7 +409,8 @@ void LineEdit::Paint0(Draw& w) { LLOG("Highlight -> tab[" << q << "] paper = " << h.paper); if(pass == 0 && x >= -fsz.cy * tabsize) { w.DrawRect(x, y, fsz.cx * l, fsz.cy, h.paper); - if(showtabs && h.paper != SColorHighlight && q < tx.GetLength()) { + if((showtabs || warn_whitespace) && + h.paper != SColorHighlight && q < tx.GetLength()) { w.DrawRect(x + 2, y + fsz.cy / 2, l * fsz.cx - 4, 1, showcolor); w.DrawRect(ngp * fsz.cx - scx - 3, y + 3, 1, fsz.cy - 6, showcolor); } @@ -389,8 +425,11 @@ void LineEdit::Paint0(Draw& w) { LLOG("Highlight -> space[" << q << "] paper = " << h.paper); if(pass == 0 && x >= -fsz.cy) { w.DrawRect(x, y, fsz.cx, fsz.cy, h.paper); - if(showspaces && h.paper != SColorHighlight && q < tx.GetLength()) - w.DrawRect(x + fsz.cx / 2, y + fsz.cy / 2, 2, 2, showcolor); + if((showspaces || warn_whitespace) + && h.paper != SColorHighlight && q < tx.GetLength()) { + int n = fsz.cy / 10 + 1; + w.DrawRect(x + fsz.cx / 2, y + fsz.cy / 2, n, n, showcolor); + } if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + 1) w.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor); } @@ -427,9 +466,9 @@ void LineEdit::Paint0(Draw& w) { if(bordercolumn > 0 && bordercolumn >= gp) w.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor); } - if(pass == 0 && showlines) { + if(pass == 0 && (showlines || warn_whitespace)) { int yy = 2 * fsz.cy / 3; - int x = gp * fsz.cx - scx; + int x = (lgp >= 0 ? lgp : gp) * fsz.cx - scx; w.DrawRect(x, y + yy, fsz.cx / 2, 1, showcolor); if(fsz.cx > 2) w.DrawRect(x + 1, y + yy - 1, 1, 3, showcolor); @@ -450,6 +489,7 @@ void LineEdit::Paint0(Draw& w) { selh -= len + 1; pos += len + 1; } + w.DrawRect(0, y, sz.cx, sz.cy - y, color[IsReadOnly() && showreadonly || !IsShowEnabled() ? PAPER_READONLY : PAPER_NORMAL]); DrawTiles(w, DropCaret(), CtrlImg::checkers()); } diff --git a/uppsrc/CtrlLib/Text.cpp b/uppsrc/CtrlLib/Text.cpp index bed8c9af3..efb33c5b7 100644 --- a/uppsrc/CtrlLib/Text.cpp +++ b/uppsrc/CtrlLib/Text.cpp @@ -20,6 +20,8 @@ TextCtrl::TextCtrl() color[PAPER_NORMAL] = SColorPaper; color[PAPER_READONLY] = SColorFace; color[PAPER_SELECTED] = SColorHighlight; + color[WHITESPACE] = Blend(SColorLight, SColorHighlight); + color[WARN_WHITESPACE] = Blend(SColorLight, SRed); processtab = true; processenter = true; nobg = false; diff --git a/uppsrc/CtrlLib/TextEdit.h b/uppsrc/CtrlLib/TextEdit.h index 8cf966296..39b7936cc 100644 --- a/uppsrc/CtrlLib/TextEdit.h +++ b/uppsrc/CtrlLib/TextEdit.h @@ -30,6 +30,8 @@ public: PAPER_NORMAL, PAPER_READONLY, PAPER_SELECTED, + WHITESPACE, + WARN_WHITESPACE, COLOR_COUNT, }; @@ -288,6 +290,7 @@ protected: bool showspaces; bool showlines; bool showreadonly; + bool warnwhitespace; bool dorectsel; // TODO: Refactor this ugly hack! void Paint0(Draw& w); @@ -390,6 +393,8 @@ public: bool IsShowSpaces() const { return showspaces; } LineEdit& ShowLineEndings(bool sl = true) { showlines = sl; Refresh(); return *this; } bool IsShowLineEndings() const { return showlines; } + LineEdit& WarnWhiteSpace(bool b = true) { warnwhitespace = b; Refresh(); return *this; } + bool IsWantWhiteSpace() const { return warnwhitespace; } LineEdit& WithCutLine(bool b) { cutline = b; return *this; } LineEdit& NoCutLine() { return WithCutLine(false); } bool IsWithCutLine() const { return cutline; } diff --git a/uppsrc/CtrlLib/src.tpp/LineEdit$en-us.tpp b/uppsrc/CtrlLib/src.tpp/LineEdit$en-us.tpp index e0188657a..655f21d58 100644 --- a/uppsrc/CtrlLib/src.tpp/LineEdit$en-us.tpp +++ b/uppsrc/CtrlLib/src.tpp/LineEdit$en-us.tpp @@ -344,7 +344,7 @@ Default is off.&] [s5;:LineEdit`:`:ShowSpaces`(bool`): [_^LineEdit^ LineEdit][@(0.0.255) `&]_[* ShowSpaces]([@(0.0.255) b ool]_[*@3 ss]_`=_[@(0.0.255) true])&] [s2;%% In this mode widget displays spaces with faint dots. Default -is off..&] +is off.&] [s3;%% &] [s4; &] [s5;:LineEdit`:`:IsShowSpaces`(`)const: [@(0.0.255) bool]_[* IsShowSpaces]()_[@(0.0.255) co @@ -352,6 +352,29 @@ nst]&] [s2;%% Returns status of ShowSpaces.&] [s3; &] [s4; &] +[s5;:Upp`:`:LineEdit`:`:ShowLineEndings`(bool`): [_^Upp`:`:LineEdit^ LineEdit][@(0.0.255) `& +]_[* ShowLineEndings]([@(0.0.255) bool]_[*@3 sl]_`=_[@(0.0.255) true])&] +[s2;%% In this mode widget displays line endings with faint dots. +Default is off.&] +[s3;%% &] +[s4; &] +[s5;:Upp`:`:LineEdit`:`:IsShowLineEndings`(`)const: [@(0.0.255) bool]_[* IsShowLineEnding +s]()_[@(0.0.255) const]&] +[s2;%% Returns status of ShowLineEndings.&] +[s3; &] +[s4; &] +[s5;:Upp`:`:LineEdit`:`:WarnWhiteSpace`(bool`): [_^Upp`:`:LineEdit^ LineEdit][@(0.0.255) `& +]_[* WarnWhiteSpace]([@(0.0.255) bool]_[*@3 b]_`=_[@(0.0.255) true])&] +[s2;%% In this mode widget shows whitespaces that seem to be misplaced, +like tabs after spaces or if line ends with spaces. Default is +off.&] +[s3;%% &] +[s4; &] +[s5;:Upp`:`:LineEdit`:`:IsWantWhiteSpace`(`)const: [@(0.0.255) bool]_[* IsWantWhiteSpace]( +)_[@(0.0.255) const]&] +[s2;%% Returns status of WarnWhiteSpace.&] +[s3; &] +[s4; &] [s5;:LineEdit`:`:WithCutLine`(bool`): [_^LineEdit^ LineEdit][@(0.0.255) `&]_[* WithCutLine]( [@(0.0.255) bool]_[*@3 b])&] [s2;%% In this mode widget calls CutLine when user presses Ctrl`+Y diff --git a/uppsrc/ide/Config.cpp b/uppsrc/ide/Config.cpp index 4c4e83745..fda82dc22 100644 --- a/uppsrc/ide/Config.cpp +++ b/uppsrc/ide/Config.cpp @@ -146,7 +146,7 @@ void Sentinel(Stream& s, const char *txt) void Ide::Serialize(Stream& s) { - int version = 6; + int version = 7; Sentinel(s, "before 12341234"); s.Magic(0x12341234); Sentinel(s, "after magic"); @@ -177,6 +177,8 @@ void Ide::Serialize(Stream& s) s % find_replace_restore_pos; } s % show_tabs; + if(version >= 7) + s % warnwhitespace; s % tabs_icons; s % tabs_crosses; s % tabs_grouping; diff --git a/uppsrc/ide/Setup.cpp b/uppsrc/ide/Setup.cpp index a2dd0a85f..8b58a8fb5 100644 --- a/uppsrc/ide/Setup.cpp +++ b/uppsrc/ide/Setup.cpp @@ -119,11 +119,12 @@ Font FontSelectManager::Get() { void Ide::UpdateFormat(CodeEditor& editor) { if(!IsActiveFile() || ActiveFile().tabsize <= 0) - editor.TabSize(editortabsize); + editor.TabSize(editortabsize); editor.IndentSpaces(indent_spaces); editor.IndentAmount(indent_amount); editor.ShowTabs(show_tabs); editor.ShowLineEndings(show_tabs); + editor.WarnWhiteSpace(warnwhitespace); editor.NoParenthesisIndent(no_parenthesis_indent); editor.HiliteScope(hilite_scope); editor.HiliteBracket(hilite_bracket); @@ -413,6 +414,7 @@ void Ide::SetupFormat() { (edt.indent_spaces, indent_spaces) (edt.no_parenthesis_indent, no_parenthesis_indent) (edt.showtabs, show_tabs) + (edt.warnwhitespace, warnwhitespace) (edt.lineends, line_endings) (edt.numbers, line_numbers) (edt.bookmark_pos, bookmark_pos) diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index 5682757ba..a612e0eab 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -557,6 +557,7 @@ public: bool show_status_bar; bool toolbar_in_row; bool show_tabs; + bool warnwhitespace; int line_endings; bool tabs_icons; int tabs_crosses; diff --git a/uppsrc/ide/ide.lay b/uppsrc/ide/ide.lay index 475511f9d..54cb5ff6e 100644 --- a/uppsrc/ide/ide.lay +++ b/uppsrc/ide/ide.lay @@ -537,7 +537,7 @@ LAYOUT(SetupHlLayout, 544, 288) ITEM(Button, hl_restore, SetLabel(t_("Restore default colors")).LeftPosZ(380, 160).TopPosZ(268, 16)) END_LAYOUT -LAYOUT(SetupEditorLayout, 544, 276) +LAYOUT(SetupEditorLayout, 544, 296) ITEM(Label, dv___0, SetLabel(t_("Tab size")).LeftPosZ(4, 108).TopPosZ(4, 19)) ITEM(EditIntSpin, tabsize, LeftPosZ(116, 52).TopPosZ(4, 19)) ITEM(Label, dv___2, SetLabel(t_("Indent")).LeftPosZ(4, 108).TopPosZ(24, 19)) @@ -550,18 +550,19 @@ LAYOUT(SetupEditorLayout, 544, 276) ITEM(Label, dv___9, SetLabel(t_("Line endings")).LeftPosZ(4, 108).TopPosZ(84, 19)) ITEM(DropList, lineends, LeftPosZ(116, 160).TopPosZ(84, 19)) ITEM(Option, showtabs, SetLabel(t_("Show tabs and line endings")).LeftPosZ(4, 272).TopPosZ(108, 16)) - ITEM(Option, indent_spaces, SetLabel(t_("Indent using spaces")).HSizePosZ(4, 268).TopPosZ(124, 16)) - ITEM(Option, no_parenthesis_indent, SetLabel(t_("No indent after parenthesis")).LeftPosZ(4, 272).TopPosZ(140, 16)) - ITEM(Option, numbers, SetLabel(t_("Show line numbers")).LeftPosZ(4, 272).TopPosZ(156, 16)) - ITEM(Option, bookmark_pos, SetLabel(t_("Bookmarks restore position")).LeftPosZ(4, 272).TopPosZ(172, 16)) - ITEM(Option, findpicksel, SetLabel(t_("Find picks selection")).LeftPosZ(4, 272).TopPosZ(188, 16)) - ITEM(Option, findpicktext, SetLabel(t_("Find picks selection or text")).LeftPosZ(4, 272).TopPosZ(204, 16)) - ITEM(Option, deactivate_save, SetLabel(t_("Save file on TheIde window deactivation")).LeftPosZ(4, 272).TopPosZ(220, 16)) - ITEM(Option, persistent_find_replace, SetLabel(t_("Do not close Find/Replace dialog automatically")).LeftPosZ(4, 272).TopPosZ(236, 16)) - ITEM(Option, find_replace_restore_pos, SetLabel(t_("Restore position on canceling incremental search")).LeftPosZ(4, 272).TopPosZ(252, 16)) - ITEM(Label, dv___21, SetLabel(t_("File Tabs")).LeftPosZ(304, 64).TopPosZ(4, 19)) + ITEM(Option, warnwhitespace, SetLabel(t_("Show possibly misplaced tabs and spaces")).LeftPosZ(4, 272).TopPosZ(124, 16)) + ITEM(Option, indent_spaces, SetLabel(t_("Indent using spaces")).HSizePosZ(4, 268).TopPosZ(140, 16)) + ITEM(Option, no_parenthesis_indent, SetLabel(t_("No indent after parenthesis")).LeftPosZ(4, 272).TopPosZ(156, 16)) + ITEM(Option, numbers, SetLabel(t_("Show line numbers")).LeftPosZ(4, 272).TopPosZ(172, 16)) + ITEM(Option, bookmark_pos, SetLabel(t_("Bookmarks restore position")).LeftPosZ(4, 272).TopPosZ(188, 16)) + ITEM(Option, findpicksel, SetLabel(t_("Find picks selection")).LeftPosZ(4, 272).TopPosZ(204, 16)) + ITEM(Option, findpicktext, SetLabel(t_("Find picks selection or text")).LeftPosZ(4, 272).TopPosZ(220, 16)) + ITEM(Option, deactivate_save, SetLabel(t_("Save file on TheIde window deactivation")).LeftPosZ(4, 272).TopPosZ(236, 16)) + ITEM(Option, persistent_find_replace, SetLabel(t_("Do not close Find/Replace dialog automatically")).LeftPosZ(4, 272).TopPosZ(252, 16)) + ITEM(Option, find_replace_restore_pos, SetLabel(t_("Restore position on canceling incremental search")).LeftPosZ(4, 272).TopPosZ(268, 16)) + ITEM(Label, dv___22, SetLabel(t_("File Tabs")).LeftPosZ(304, 64).TopPosZ(4, 19)) ITEM(DropList, filetabs, LeftPosZ(372, 64).TopPosZ(4, 19)) - ITEM(Label, dv___23, SetLabel(t_("Crosses")).LeftPosZ(304, 64).TopPosZ(24, 19)) + ITEM(Label, dv___24, SetLabel(t_("Crosses")).LeftPosZ(304, 64).TopPosZ(24, 19)) ITEM(DropList, tabs_crosses, LeftPosZ(372, 64).TopPosZ(24, 19)) ITEM(Option, tabs_icons, SetLabel(t_("Icons")).LeftPosZ(304, 132).TopPosZ(48, 16)) ITEM(Option, tabs_grouping, SetLabel(t_("Grouping")).LeftPosZ(304, 132).TopPosZ(68, 16)) diff --git a/uppsrc/ide/idewin.cpp b/uppsrc/ide/idewin.cpp index bfa197e8a..cc248608a 100644 --- a/uppsrc/ide/idewin.cpp +++ b/uppsrc/ide/idewin.cpp @@ -518,6 +518,7 @@ Ide::Ide() indent_spaces = false; show_status_bar = false; show_tabs = false; + warnwhitespace = true; tabs_icons = false; tabs_crosses = AlignedFrame::RIGHT; tabs_grouping = true;