Skip to content

Commit 651b3ff

Browse files
committed
Added Console lexer for errors
- ConsoleDialog now contains a SCLEX_CONTAINER lexer for python and Visual Studio style errors - Click to switch to file, or open it, and jump to line
1 parent 77745d4 commit 651b3ff

5 files changed

Lines changed: 336 additions & 14 deletions

File tree

PythonScript/src/ConsoleDialog.cpp

Lines changed: 286 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Notepad_Plus_msgs.h"
44
#include "DockingDlgInterface.h"
55
#include "Scintilla.h"
6+
#include "SciLexer.h"
67
#include "resource.h"
78
#include "PythonConsole.h"
89

@@ -34,6 +35,7 @@ void ConsoleDialog::init(HINSTANCE hInst, NppData nppData, ConsoleInterface* con
3435
//Window::init(hInst, nppData._nppHandle);
3536
createOutputWindow(nppData._nppHandle);
3637
m_console = console;
38+
3739
}
3840

3941
BOOL ConsoleDialog::run_dlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -80,6 +82,25 @@ BOOL ConsoleDialog::run_dlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l
8082
//MessageBox(NULL, _T("Command") , _T("Python Command"), 0);
8183
return TRUE;
8284
}
85+
case WM_NOTIFY:
86+
{
87+
LPNMHDR nmhdr = reinterpret_cast<LPNMHDR>(lParam);
88+
if (m_scintilla == nmhdr->hwndFrom)
89+
{
90+
switch(nmhdr->code)
91+
{
92+
case SCN_STYLENEEDED:
93+
onStyleNeeded(reinterpret_cast<SCNotification*>(lParam));
94+
return FALSE;
95+
96+
case SCN_HOTSPOTCLICK:
97+
case SCN_HOTSPOTDOUBLECLICK:
98+
onHotspotClick(reinterpret_cast<SCNotification*>(lParam));
99+
return FALSE;
100+
}
101+
}
102+
return TRUE;
103+
}
83104
default:
84105
return DockingDlgInterface::run_dlgProc(message, wParam, lParam);
85106

@@ -280,7 +301,14 @@ void ConsoleDialog::createOutputWindow(HWND hParentWindow)
280301
::SendMessage(m_scintilla, SCI_STYLESETSIZE, 0 /* = style number */, 8 /* = size in points */);
281302
::SendMessage(m_scintilla, SCI_STYLESETSIZE, 1 /* = style number */, 8 /* = size in points */);
282303
::SendMessage(m_scintilla, SCI_STYLESETFORE, 1, RGB(250, 0, 0));
283-
304+
::SendMessage(m_scintilla, SCI_STYLESETSIZE, 2 /* = style number */, 8 /* = size in points */);
305+
::SendMessage(m_scintilla, SCI_STYLESETUNDERLINE, 2 /* = style number */, 1 /* = underline */);
306+
::SendMessage(m_scintilla, SCI_STYLESETSIZE, 3 /* = style number */, 8 /* = size in points */);
307+
::SendMessage(m_scintilla, SCI_STYLESETFORE, 3, RGB(250, 0, 0));
308+
::SendMessage(m_scintilla, SCI_STYLESETUNDERLINE, 3 /* = style number */, 1 /* = underline */);
309+
::SendMessage(m_scintilla, SCI_STYLESETHOTSPOT, 2, 1);
310+
::SendMessage(m_scintilla, SCI_STYLESETHOTSPOT, 3, 1);
311+
::SendMessage(m_scintilla, SCI_SETLEXER, SCLEX_CONTAINER, 0);
284312
}
285313

286314
void ConsoleDialog::writeText(int length, const char *text)
@@ -297,19 +325,24 @@ void ConsoleDialog::writeText(int length, const char *text)
297325

298326
void ConsoleDialog::writeError(int length, const char *text)
299327
{
300-
301-
302-
303-
::SendMessage(m_scintilla, SCI_SETREADONLY, 0, 0);
304-
305-
::SendMessage(m_scintilla, SCI_APPENDTEXT, length, reinterpret_cast<LPARAM>(text));
306-
::SendMessage(m_scintilla, SCI_SETREADONLY, 1, 0);
307-
308-
int docLength = ::SendMessage(m_scintilla, SCI_GETLENGTH, 0, 0);
309-
::SendMessage(m_scintilla, SCI_STARTSTYLING, docLength - length, 255);
310-
::SendMessage(m_scintilla, SCI_SETSTYLING, length, 1);
311-
::SendMessage(m_scintilla, SCI_GOTOPOS, docLength, 0);
328+
/*
329+
char *buffer = new char[length * 2];
330+
for(int pos = 0; pos < length; ++pos)
331+
{
332+
buffer[pos * 2] = text[pos];
333+
buffer[(pos * 2) + 1] = 1;
334+
}
335+
*/
336+
int docLength = callScintilla(SCI_GETLENGTH);
337+
callScintilla(SCI_SETREADONLY, 0);
338+
callScintilla(SCI_APPENDTEXT, length, reinterpret_cast<LPARAM>(text));
339+
callScintilla(SCI_SETREADONLY, 1);
340+
callScintilla(SCI_STARTSTYLING, docLength, 0x01);
341+
callScintilla(SCI_SETSTYLING, length, 1);
342+
// delete[] buffer;
312343

344+
callScintilla(SCI_COLOURISE, docLength, -1);
345+
callScintilla(SCI_GOTOPOS, docLength + length);
313346
}
314347

315348

@@ -369,4 +402,244 @@ void ConsoleDialog::clearText()
369402
::SendMessage(m_scintilla, SCI_SETREADONLY, 0, 0);
370403
::SendMessage(m_scintilla, SCI_CLEARALL, 0, 0);
371404
::SendMessage(m_scintilla, SCI_SETREADONLY, 1, 0);
405+
}
406+
407+
408+
void ConsoleDialog::onStyleNeeded(SCNotification* notification)
409+
{
410+
int startPos = callScintilla(SCI_GETENDSTYLED);
411+
int startLine = callScintilla(SCI_LINEFROMPOSITION, startPos);
412+
startPos = callScintilla(SCI_POSITIONFROMLINE, startLine);
413+
int endPos = notification->position;
414+
int endLine = callScintilla(SCI_LINEFROMPOSITION, endPos);
415+
416+
417+
LineDetails lineDetails;
418+
for(int lineNumber = startLine; lineNumber <= endLine; ++lineNumber)
419+
{
420+
lineDetails.lineLength = callScintilla(SCI_GETLINE, lineNumber);
421+
422+
if (lineDetails.lineLength > 0)
423+
{
424+
lineDetails.line = new char[lineDetails.lineLength + 1];
425+
callScintilla(SCI_GETLINE, lineNumber, reinterpret_cast<LPARAM>(lineDetails.line));
426+
lineDetails.line[lineDetails.lineLength] = '\0';
427+
428+
429+
430+
if (parseLine(&lineDetails))
431+
{
432+
int startPos = callScintilla(SCI_POSITIONFROMLINE, lineNumber);
433+
434+
callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameStart, 0x02);
435+
callScintilla(SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart, 0x02);
436+
callScintilla(SCI_STARTSTYLING, startPos + lineDetails.filenameEnd, 0x02);
437+
callScintilla(SCI_SETSTYLING, lineDetails.lineLength - lineDetails.filenameEnd, 0x00);
438+
}
439+
440+
delete[] lineDetails.line;
441+
442+
}
443+
}
444+
445+
}
446+
447+
bool ConsoleDialog::parseLine(LineDetails *lineDetails)
448+
{
449+
if (0 == strncmp(lineDetails->line, " File \"", 8))
450+
{
451+
return parsePythonErrorLine(lineDetails);
452+
}
453+
454+
if (0 == strncmp(lineDetails->line + 1, ":\\", 2))
455+
{
456+
return parseVSErrorLine(lineDetails);
457+
}
458+
459+
return false;
460+
}
461+
462+
bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails)
463+
{
464+
enum StyleState
465+
{
466+
SS_FILENAME,
467+
SS_LINENUMBER,
468+
SS_EXIT
469+
} styleState;
470+
471+
bool retVal = false;
472+
styleState = SS_FILENAME;
473+
474+
int pos = 0;
475+
lineDetails->filenameStart = 0;
476+
lineDetails->errorLineNo = -1;
477+
478+
while (styleState != SS_EXIT)
479+
{
480+
switch(styleState)
481+
{
482+
case SS_FILENAME:
483+
while(lineDetails->line[pos] != '(' && pos < lineDetails->lineLength)
484+
{
485+
++pos;
486+
}
487+
488+
if (lineDetails->line[pos] == '(') // Found the opening bracket for line no
489+
{
490+
++pos;
491+
styleState = SS_LINENUMBER;
492+
}
493+
else
494+
{
495+
styleState = SS_EXIT;
496+
}
497+
break;
498+
499+
case SS_LINENUMBER:
500+
{
501+
int startLineNoPos = pos;
502+
while(lineDetails->line[pos] >= '0' && lineDetails->line[pos] <= '9' && pos < lineDetails->lineLength)
503+
{
504+
++pos;
505+
}
506+
if (pos < (lineDetails->lineLength + 1)
507+
&& lineDetails->line[pos] == ')'
508+
&& lineDetails->line[pos+1] == ':')
509+
{
510+
lineDetails->errorLineNo = atoi(lineDetails->line + startLineNoPos) - 1;
511+
lineDetails->filenameEnd = startLineNoPos - 1;
512+
retVal = true;
513+
styleState = SS_EXIT;
514+
}
515+
else
516+
{
517+
pos = startLineNoPos + 1;
518+
styleState = SS_FILENAME;
519+
}
520+
break;
521+
}
522+
523+
case SS_EXIT:
524+
break;
525+
526+
default:
527+
styleState = SS_EXIT;
528+
break;
529+
}
530+
}
531+
return retVal;
532+
}
533+
534+
bool ConsoleDialog::parsePythonErrorLine(LineDetails *lineDetails)
535+
{
536+
enum StyleState
537+
{
538+
SS_BEGIN,
539+
SS_FILENAME,
540+
SS_EXPECTLINE,
541+
SS_LINENUMBER,
542+
SS_EXIT
543+
} styleState;
544+
545+
bool retVal = false;
546+
styleState = SS_BEGIN;
547+
lineDetails->errorLineNo = -1;
548+
int pos = 0;
549+
while(styleState != SS_EXIT)
550+
{
551+
switch(styleState)
552+
{
553+
case SS_BEGIN:
554+
if (strncmp(lineDetails->line, " File \"", 8) == 0)
555+
{
556+
pos = 8;
557+
lineDetails->filenameStart = 8;
558+
styleState = SS_FILENAME;
559+
}
560+
else
561+
{
562+
styleState = SS_EXIT;
563+
}
564+
break;
565+
566+
case SS_FILENAME:
567+
while(lineDetails->line[pos] != '\"' && pos < lineDetails->lineLength)
568+
{
569+
++pos;
570+
}
571+
572+
if (pos >= lineDetails->lineLength) // Not found, so revert to default style
573+
{
574+
styleState = SS_EXIT;
575+
}
576+
else
577+
{
578+
lineDetails->filenameEnd = pos;
579+
retVal = true;
580+
styleState = SS_EXPECTLINE;
581+
}
582+
break;
583+
584+
case SS_EXPECTLINE:
585+
if (strncmp(lineDetails->line + pos, "\", line ", 8) == 0)
586+
{
587+
pos += 8;
588+
styleState = SS_LINENUMBER;
589+
}
590+
else
591+
{
592+
styleState = SS_EXIT;
593+
}
594+
break;
595+
596+
case SS_LINENUMBER:
597+
lineDetails->errorLineNo = atoi(lineDetails->line + pos) - 1;
598+
styleState = SS_EXIT;
599+
break;
600+
601+
default:
602+
styleState = SS_EXIT;
603+
break;
604+
}
605+
}
606+
607+
return retVal;
608+
}
609+
610+
611+
612+
613+
void ConsoleDialog::styleDefaultLine(int lineNumber, int lineLength, const char * /* line */)
614+
{
615+
616+
int linePosition = callScintilla(SCI_POSITIONFROMLINE, lineNumber);
617+
// Set the mask to the hotspot bit (0x02)
618+
619+
callScintilla(SCI_STARTSTYLING, linePosition, 0x02);
620+
// and declare no hotspots
621+
callScintilla(SCI_SETSTYLING, lineLength, 0);
622+
623+
}
624+
625+
626+
void ConsoleDialog::onHotspotClick(SCNotification* notification)
627+
{
628+
629+
int lineNumber = callScintilla(SCI_LINEFROMPOSITION, notification->position);
630+
LineDetails lineDetails;
631+
lineDetails.lineLength = callScintilla(SCI_GETLINE, lineNumber);
632+
633+
if (lineDetails.lineLength > 0)
634+
{
635+
lineDetails.line = new char[lineDetails.lineLength + 1];
636+
callScintilla(SCI_GETLINE, lineNumber, reinterpret_cast<LPARAM>(lineDetails.line));
637+
lineDetails.line[lineDetails.lineLength] = '\0';
638+
if (parseLine(&lineDetails))
639+
{
640+
lineDetails.line[lineDetails.filenameEnd] = '\0';
641+
m_console->openFile(lineDetails.line + lineDetails.filenameStart, lineDetails.errorLineNo);
642+
}
643+
}
644+
372645
}

0 commit comments

Comments
 (0)