Skip to content

Commit 6db08ec

Browse files
committed
Console parser improvements
- GCC errors now parsed - MSBuild errors now parsed - VS errors with column number now parsed - error/warnings are parsed, so they come out red/yellow from stdout or stderr - Added "MADE IN GERMANY" to website :)
1 parent a1f27e8 commit 6db08ec

4 files changed

Lines changed: 265 additions & 27 deletions

File tree

PythonScript/src/ConsoleDialog.cpp

Lines changed: 241 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -354,16 +354,55 @@ void ConsoleDialog::createOutputWindow(HWND hParentWindow)
354354
{
355355
m_scintilla = (HWND)::SendMessage(_hParent, NPPM_CREATESCINTILLAHANDLE, 0, reinterpret_cast<LPARAM>(hParentWindow));
356356
callScintilla(SCI_SETREADONLY, 1, 0);
357+
358+
/* Style bits
359+
* LSB 0 - stderr = 1
360+
* 1 - hotspot
361+
* 2 - warning
362+
* ... to be continued
363+
*/
364+
365+
366+
// 0 is stdout, black text
357367
callScintilla(SCI_STYLESETSIZE, 0 /* = style number */, 8 /* = size in points */);
368+
369+
// 1 is stderr, red text
358370
callScintilla(SCI_STYLESETSIZE, 1 /* = style number */, 8 /* = size in points */);
359371
callScintilla(SCI_STYLESETFORE, 1, RGB(250, 0, 0));
372+
373+
// 2 is stdout, black text, underline hotspot
360374
callScintilla(SCI_STYLESETSIZE, 2 /* = style number */, 8 /* = size in points */);
361375
callScintilla(SCI_STYLESETUNDERLINE, 2 /* = style number */, 1 /* = underline */);
376+
callScintilla(SCI_STYLESETHOTSPOT, 2, 1);
377+
378+
// 3 is stderr, red text, underline hotspot
362379
callScintilla(SCI_STYLESETSIZE, 3 /* = style number */, 8 /* = size in points */);
363380
callScintilla(SCI_STYLESETFORE, 3, RGB(250, 0, 0));
364381
callScintilla(SCI_STYLESETUNDERLINE, 3 /* = style number */, 1 /* = underline */);
365-
callScintilla(SCI_STYLESETHOTSPOT, 2, 1);
366382
callScintilla(SCI_STYLESETHOTSPOT, 3, 1);
383+
384+
// 4 stdout warning without hotspot
385+
callScintilla(SCI_STYLESETSIZE, 4 /* = style number */, 8 /* = size in points */);
386+
callScintilla(SCI_STYLESETFORE, 4, RGB(199, 175, 7)); // mucky yellow
387+
388+
389+
// 5 stderr warning without hotspot
390+
callScintilla(SCI_STYLESETSIZE, 5 /* = style number */, 8 /* = size in points */);
391+
callScintilla(SCI_STYLESETFORE, 5, RGB(255, 128, 64)); // orange
392+
393+
394+
// 6 is hotspot, stdout, warning
395+
callScintilla(SCI_STYLESETSIZE, 6 /* = style number */, 8 /* = size in points */);
396+
callScintilla(SCI_STYLESETFORE, 6, RGB(199, 175, 7)); // mucky yellow
397+
callScintilla(SCI_STYLESETUNDERLINE, 6 /* = style number */, 1 /* = underline */);
398+
callScintilla(SCI_STYLESETHOTSPOT, 6, 1);
399+
400+
// 7 is hotspot, stderr, warning
401+
callScintilla(SCI_STYLESETSIZE, 7 /* = style number */, 8 /* = size in points */);
402+
callScintilla(SCI_STYLESETFORE, 7, RGB(255, 128, 64)); // orange
403+
callScintilla(SCI_STYLESETUNDERLINE, 7 /* = style number */, 1 /* = underline */);
404+
callScintilla(SCI_STYLESETHOTSPOT, 7, 1);
405+
367406
callScintilla(SCI_USEPOPUP, 0);
368407
callScintilla(SCI_SETLEXER, SCLEX_CONTAINER);
369408
}
@@ -484,7 +523,7 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification)
484523
lineDetails.line = new char[lineDetails.lineLength + 1];
485524
callScintilla(SCI_GETLINE, lineNumber, reinterpret_cast<LPARAM>(lineDetails.line));
486525
lineDetails.line[lineDetails.lineLength] = '\0';
487-
526+
lineDetails.errorLevel = EL_UNSET;
488527

489528

490529
if (parseLine(&lineDetails))
@@ -494,10 +533,44 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification)
494533
// Check that it's not just a file called '<console>'
495534
if (strncmp(lineDetails.line + lineDetails.filenameStart, "<console>", lineDetails.filenameEnd - lineDetails.filenameStart))
496535
{
497-
callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameStart, 0x02);
498-
callScintilla(SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart, 0x02);
499-
callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameEnd, 0x02);
500-
callScintilla(SCI_SETSTYLING, lineDetails.lineLength - lineDetails.filenameEnd, 0x00);
536+
int mask, style;
537+
switch(lineDetails.errorLevel)
538+
{
539+
case EL_WARNING:
540+
mask = 0x04;
541+
style = 0x04;
542+
break;
543+
544+
case EL_ERROR:
545+
mask = 0x01;
546+
style = 0x01;
547+
break;
548+
549+
case EL_UNSET:
550+
case EL_INFO:
551+
default:
552+
mask = 0x00;
553+
style = 0x00;
554+
break;
555+
}
556+
557+
if (lineDetails.filenameStart > 0)
558+
{
559+
callScintilla(SCI_STARTSTYLING, startPos, mask);
560+
callScintilla(SCI_SETSTYLING, lineDetails.filenameStart, style);
561+
}
562+
563+
564+
callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameStart, mask | 0x02);
565+
callScintilla(SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart, style | 0x02);
566+
567+
if (lineDetails.lineLength > lineDetails.filenameEnd)
568+
{
569+
callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameEnd, mask);
570+
callScintilla(SCI_SETSTYLING, lineDetails.lineLength - lineDetails.filenameEnd, style);
571+
}
572+
573+
501574
}
502575
}
503576

@@ -513,39 +586,63 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification)
513586

514587
bool ConsoleDialog::parseLine(LineDetails *lineDetails)
515588
{
516-
if (0 == strncmp(lineDetails->line, " File \"", 8))
589+
// Eg.
590+
// File "C:\Users\Dave\AppData\Roaming\Notepad++\plugins\Config\PythonScript\scripts\fourth.py", line 2, in <module>
591+
if (0 == strncmp(lineDetails->line, " File \"", 8)
592+
&& parsePythonErrorLine(lineDetails))
517593
{
518-
return parsePythonErrorLine(lineDetails);
594+
return true;
519595
}
520-
521-
if (0 == strncmp(lineDetails->line + 1, ":\\", 2))
596+
597+
// Eg.
598+
// e:\work\pythonscript\pythonscript\src\consoledialog.cpp(523): error C2065: 'ee' : undeclared identifier
599+
// Potentially with spaces in front if MSBUILD used
600+
// Line number can contain "," for column (523,5)
601+
if (parseVSErrorLine(lineDetails))
522602
{
523-
return parseVSErrorLine(lineDetails);
603+
return true;
524604
}
525605

606+
// Eg.
607+
// C:/PalmDev/sdk-4/include/Core/System/NetMgr.h:550: warning: ignoring pragma: ;
608+
if (parseGCCErrorLine(lineDetails))
609+
{
610+
return true;
611+
}
612+
526613
return false;
527614
}
528615

529616
bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails)
530617
{
531618
enum StyleState
532619
{
620+
SS_BEGIN,
533621
SS_FILENAME,
534622
SS_LINENUMBER,
623+
SS_ERRORTYPE,
535624
SS_EXIT
536625
} styleState;
537626

538627
bool retVal = false;
539-
styleState = SS_FILENAME;
628+
styleState = SS_BEGIN;
540629

541630
int pos = 0;
542-
lineDetails->filenameStart = 0;
543631
lineDetails->errorLineNo = -1;
544632

545633
while (styleState != SS_EXIT)
546634
{
547635
switch(styleState)
548636
{
637+
case SS_BEGIN:
638+
while(lineDetails->line[pos] == ' ')
639+
{
640+
++pos;
641+
}
642+
lineDetails->filenameStart = pos;
643+
styleState = SS_FILENAME;
644+
break;
645+
549646
case SS_FILENAME:
550647
while(lineDetails->line[pos] != '(' && pos < lineDetails->lineLength)
551648
{
@@ -566,18 +663,137 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails)
566663
case SS_LINENUMBER:
567664
{
568665
int startLineNoPos = pos;
666+
int endLineNoPos;
569667
while(lineDetails->line[pos] >= '0' && lineDetails->line[pos] <= '9' && pos < lineDetails->lineLength)
570668
{
571669
++pos;
572670
}
671+
endLineNoPos = pos;
672+
673+
if (pos < (lineDetails->lineLength + 1)
674+
&& lineDetails->line[pos] == ',')
675+
{
676+
++pos;
677+
while(lineDetails->line[pos] >= '0' && lineDetails->line[pos] <= '9' && pos < lineDetails->lineLength)
678+
{
679+
++pos;
680+
}
681+
}
682+
683+
573684
if (pos < (lineDetails->lineLength + 1)
574685
&& lineDetails->line[pos] == ')'
575686
&& lineDetails->line[pos+1] == ':')
687+
{
688+
char *lineNumber = new char[endLineNoPos - startLineNoPos + 2];
689+
strncpy_s(lineNumber, endLineNoPos - startLineNoPos + 2, lineDetails->line + startLineNoPos, endLineNoPos - startLineNoPos);
690+
lineDetails->errorLineNo = atoi(lineNumber) - 1;
691+
delete[] lineNumber;
692+
lineDetails->filenameEnd = startLineNoPos - 1;
693+
retVal = true;
694+
pos += 3; // jump past "): " to either error or warning
695+
styleState = SS_ERRORTYPE;
696+
}
697+
else
698+
{
699+
pos = startLineNoPos + 1;
700+
styleState = SS_FILENAME;
701+
}
702+
break;
703+
}
704+
705+
case SS_ERRORTYPE:
706+
if (0 == strncmp(lineDetails->line + pos, "error", 5))
707+
{
708+
lineDetails->errorLevel = EL_ERROR;
709+
}
710+
else if (0 == strncmp(lineDetails->line + pos, "warning", 7))
711+
{
712+
lineDetails->errorLevel = EL_WARNING;
713+
}
714+
styleState = SS_EXIT;
715+
break;
716+
717+
case SS_EXIT:
718+
break;
719+
720+
default:
721+
styleState = SS_EXIT;
722+
break;
723+
}
724+
}
725+
return retVal;
726+
}
727+
728+
729+
bool ConsoleDialog::parseGCCErrorLine(LineDetails *lineDetails)
730+
{
731+
enum StyleState
732+
{
733+
SS_FILENAME,
734+
SS_LINENUMBER,
735+
SS_ERRORTYPE,
736+
SS_EXIT
737+
} styleState;
738+
739+
bool retVal = false;
740+
styleState = SS_FILENAME;
741+
742+
int pos = 0;
743+
lineDetails->filenameStart = 0;
744+
lineDetails->errorLineNo = -1;
745+
746+
while (styleState != SS_EXIT)
747+
{
748+
switch(styleState)
749+
{
750+
case SS_FILENAME:
751+
{
752+
bool isEscaped = false;
753+
while((lineDetails->line[pos] != ':' || pos == 1) && pos < lineDetails->lineLength)
754+
{
755+
// Unescaped space, so leave - this isn't a gcc error
756+
if (lineDetails->line[pos] == ' ' && !isEscaped)
757+
{
758+
styleState = SS_EXIT;
759+
break;
760+
}
761+
762+
if (lineDetails->line[pos] == '\\')
763+
isEscaped = true;
764+
765+
++pos;
766+
767+
isEscaped = false;
768+
}
769+
770+
if (lineDetails->line[pos] == ':') // Found the colon for line no
771+
{
772+
++pos;
773+
styleState = SS_LINENUMBER;
774+
}
775+
else
776+
{
777+
styleState = SS_EXIT;
778+
}
779+
}
780+
break;
781+
782+
case SS_LINENUMBER:
783+
{
784+
int startLineNoPos = pos;
785+
while(lineDetails->line[pos] >= '0' && lineDetails->line[pos] <= '9' && pos < lineDetails->lineLength)
786+
{
787+
++pos;
788+
}
789+
if (pos < (lineDetails->lineLength + 1)
790+
&& lineDetails->line[pos] == ':')
576791
{
577792
lineDetails->errorLineNo = atoi(lineDetails->line + startLineNoPos) - 1;
578793
lineDetails->filenameEnd = startLineNoPos - 1;
579794
retVal = true;
580-
styleState = SS_EXIT;
795+
pos += 2;
796+
styleState = SS_ERRORTYPE;
581797
}
582798
else
583799
{
@@ -586,6 +802,17 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails)
586802
}
587803
break;
588804
}
805+
case SS_ERRORTYPE:
806+
if (0 == strncmp(lineDetails->line + pos, "error", 5))
807+
{
808+
lineDetails->errorLevel = EL_ERROR;
809+
}
810+
else if (0 == strncmp(lineDetails->line + pos, "warning", 7))
811+
{
812+
lineDetails->errorLevel = EL_WARNING;
813+
}
814+
styleState = SS_EXIT;
815+
break;
589816

590817
case SS_EXIT:
591818
break;
@@ -677,17 +904,7 @@ bool ConsoleDialog::parsePythonErrorLine(LineDetails *lineDetails)
677904

678905

679906

680-
void ConsoleDialog::styleDefaultLine(int lineNumber, int lineLength, const char * /* line */)
681-
{
682-
683-
int linePosition = callScintilla(SCI_POSITIONFROMLINE, lineNumber);
684-
// Set the mask to the hotspot bit (0x02)
685-
686-
callScintilla(SCI_STARTSTYLING, linePosition, 0x02);
687-
// and declare no hotspots
688-
callScintilla(SCI_SETSTYLING, lineLength, 0);
689907

690-
}
691908

692909

693910
void ConsoleDialog::onHotspotClick(SCNotification* notification)

PythonScript/src/ConsoleDialog.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class ConsoleDialog : public DockingDlgInterface
5252
void onStyleNeeded(SCNotification* notification);
5353
bool parsePythonErrorLine(LineDetails *lineDetails);
5454
bool parseVSErrorLine(LineDetails *lineDetails);
55-
void styleDefaultLine(int lineNumber, int lineLength, const char *line);
55+
bool parseGCCErrorLine(LineDetails *lineDetails);
56+
//void styleDefaultLine(int lineNumber, int lineLength, const char *line);
5657
void onHotspotClick(SCNotification* notification);
5758
bool parseLine(LineDetails *lineDetails);
5859

@@ -75,6 +76,13 @@ class ConsoleDialog : public DockingDlgInterface
7576

7677
};
7778

79+
enum ErrorLevel
80+
{
81+
EL_UNSET,
82+
EL_INFO,
83+
EL_WARNING,
84+
EL_ERROR
85+
};
7886

7987
struct LineDetails
8088
{
@@ -84,6 +92,7 @@ struct LineDetails
8492
int errorLineNo;
8593
int filenameStart;
8694
int filenameEnd;
95+
ErrorLevel errorLevel;
8796
};
8897

8998
#endif

0 commit comments

Comments
 (0)