NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
codeformatter.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "codeformatter.hpp"
20#include "editor.h"
21
22using namespace std;
23
35int CodeFormatter::insertTextAndMove(int nPosition, const wxString& sText)
36{
37 m_editor->InsertText(nPosition, sText);
38 return sText.length();
39}
40
41
51void CodeFormatter::IndentCode(int nFirstLine, int nLastLine) // int nFirstLine = 0, int nLastLine = -1
52{
53 if (nFirstLine < 0)
54 nFirstLine = 0;
55
56 if (nLastLine <= 0 || nLastLine > m_editor->GetLineCount())
57 nLastLine = m_editor->GetLineCount();
58
59 m_editor->SetTabWidth(4);
60
61 // If we do not start at the beginning of the document,
62 // then keep the latest indentation
63 int nIndentCount = nFirstLine > 0 ? m_editor->GetLineIndentation(nFirstLine) / 4 : 0;
64 int nCurrentIndent = 0;
65
66 int singleLineIndent = 0;
67 int nLastSingleIndent = 0;
68 m_editor->BeginUndoAction();
69
70 // Go through the complete document
71 for (int i = nFirstLine; i < nLastLine; i++)
72 {
73 nLastSingleIndent = singleLineIndent;
74 singleLineIndent = 0;
75 int pos = m_editor->PositionFromLine(i);
76
77 // Ignore line comments
79 continue;
80
81 // Ignore block comments
82 while (m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, pos) && pos < m_editor->GetLineEndPosition(nLastLine))
83 pos++;
84
85 if (pos > m_editor->GetLineEndPosition(i) - 1)
86 continue;
87
88 // Determine the current indentation level
89 nCurrentIndent = determineIndentationLevel(i, singleLineIndent);
90
91 if (m_editor->getFileType() == FILE_CPP && nLastSingleIndent && nCurrentIndent)
92 nLastSingleIndent = 0;
93
94 // Apply the indentation level
95 if (!nCurrentIndent && singleLineIndent < 0)
96 {
97 singleLineIndent = 0;
98 m_editor->SetLineIndentation(i, 4 * (nIndentCount - 1));
99 }
100 else if (!nCurrentIndent)
101 m_editor->SetLineIndentation(i, 4 * (nIndentCount + nLastSingleIndent));
102 else if (nCurrentIndent < 0)
103 {
104 nIndentCount += nCurrentIndent;
105 m_editor->SetLineIndentation(i, 4 * nIndentCount);
106 }
107 else
108 {
109 m_editor->SetLineIndentation(i, 4 * nIndentCount);
110 nIndentCount += nCurrentIndent;
111 }
112
113 if (m_editor->GetCurrentLine() == i
114 && m_editor->GetCurrentPos() - pos < nIndentCount
115 && !m_editor->HasSelection()
116 && m_editor->GetTextRange(pos, m_editor->GetLineEndPosition(i)).find_first_not_of(" \t\n\r") == string::npos)
117 m_editor->GotoPos(pos + nIndentCount);
118 }
119
120 m_editor->EndUndoAction();
121}
122
123
136int CodeFormatter::determineIndentationLevel(int nLine, int& singleLineIndent)
137{
138 // Use the correct indentation level calculator
139 // for the current language
141 return determineIndentationLevelNSCR(nLine, singleLineIndent);
142 else if (m_editor->getFileType() == FILE_MATLAB)
143 return determineIndentationLevelMATLAB(nLine, singleLineIndent);
144 else if (m_editor->getFileType() == FILE_CPP)
145 return determineIndentationLevelCPP(nLine, singleLineIndent);
146
147 return 0;
148}
149
150
160int CodeFormatter::determineIndentationLevelNSCR(int nLine, int& singleLineIndent)
161{
162 int nIndentCount = 0;
163
164 int nLineStart = m_editor->PositionFromLine(nLine);
165 int nLineEnd = m_editor->GetLineEndPosition(nLine);
166
167 // Search through the line
168 for (int i = nLineStart; i < nLineEnd; i++)
169 {
170 // Examine flow control statements
171 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_COMMAND || m_editor->GetStyleAt(i) == wxSTC_NSCR_PROCEDURE_COMMANDS)
172 {
173 wxString word = m_editor->GetTextRange(i, m_editor->WordEndPosition(i + 1, true));
174
175 if (m_editor->isBlockEnd(word) != wxNOT_FOUND)
176 nIndentCount--;
177 else if (m_editor->isBlockStart(word, false) != wxNOT_FOUND)
178 nIndentCount++;
179 else if (m_editor->isBlockMiddle(word) != wxNOT_FOUND)
180 singleLineIndent = -1;
181
182 i += word.length();
183 }
184
185 // Examine install sections
186 if (m_editor->getFileType() == FILE_NSCR && m_editor->GetStyleAt(i) == wxSTC_NSCR_INSTALL)
187 {
188 wxString word;
189
190 if (m_editor->GetCharAt(i) == '<' && m_editor->FindText(i, nLineEnd, ">") != -1)
191 {
192 word = m_editor->GetTextRange(i, m_editor->WordEndPosition(i + 2, true) + 1);
193
194 if (m_editor->isBlockStart(word, false) != wxNOT_FOUND)
195 nIndentCount++;
196 else if (m_editor->isBlockEnd(word) != wxNOT_FOUND)
197 nIndentCount--;
198 }
199
200 if (word.length())
201 i += word.length() - 1;
202 }
203
204 // Examine line continuations
205 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_OPERATORS && m_editor->GetTextRange(i, i + 2) == "\\\\")
206 singleLineIndent = 1;
207 }
208
209 return nIndentCount;
210}
211
212
222int CodeFormatter::determineIndentationLevelMATLAB(int nLine, int& singleLineIndent)
223{
224 int nIndentCount = 0;
225
226 int nLineStart = m_editor->PositionFromLine(nLine);
227 int nLineEnd = m_editor->GetLineEndPosition(nLine);
228
229 for (int i = nLineStart; i < nLineEnd; i++)
230 {
231 if (m_editor->GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
232 {
233 wxString word = m_editor->GetTextRange(i, m_editor->WordEndPosition(i + 1, true));
234
235 if (m_editor->isBlockEnd(word) != wxNOT_FOUND)
236 nIndentCount--;
237 else if (m_editor->isBlockStart(word, false) != wxNOT_FOUND)
238 nIndentCount++;
239 else if (m_editor->isBlockMiddle(word) != wxNOT_FOUND)
240 singleLineIndent = -1;
241
242 i += word.length();
243 }
244
245 if (m_editor->GetStyleAt(i) == wxSTC_MATLAB_OPERATOR && m_editor->GetTextRange(i, i + 3) == "...")
246 singleLineIndent = 1;
247 }
248
249 return nIndentCount;
250}
251
252
262int CodeFormatter::determineIndentationLevelCPP(int nLine, int& singleLineIndent)
263{
264 int nIndentCount = 0;
265
266 int nLineStart = m_editor->PositionFromLine(nLine);
267 int nLineEnd = m_editor->GetLineEndPosition(nLine);
268
269 for (int i = nLineStart; i < nLineEnd; i++)
270 {
271 if (m_editor->GetStyleAt(i) == wxSTC_C_OPERATOR)
272 {
273 if (m_editor->GetCharAt(i) == '{')
274 nIndentCount++;
275
276 if (m_editor->GetCharAt(i) == '}')
277 nIndentCount--;
278 }
279
280 if (m_editor->GetStyleAt(i) == wxSTC_C_WORD)
281 {
282 wxString word = m_editor->GetTextRange(i, m_editor->WordEndPosition(i + 1, true));
283
284 if (word == "private" || word == "protected" || word == "public" || word == "case" || word == "default")
285 singleLineIndent = -1;
286
287 if (word == "if" || word == "else" || word == "for" || word == "while")
288 singleLineIndent = 1;
289
290 i += word.length();
291 }
292 }
293
294 return nIndentCount;
295}
296
297
311void CodeFormatter::FormatCode(int nFirstLine, int nLastLine)
312{
313 if (nFirstLine < 0)
314 nFirstLine = 0;
315
316 if (nLastLine <= 0 || nLastLine > m_editor->GetLineCount())
317 nLastLine = m_editor->GetLineCount();
318
319 // Format the code
321 ApplyAutoFormatNSCR(nFirstLine, nLastLine);
322 else if (m_editor->getFileType() == FILE_MATLAB)
323 ApplyAutoFormatMATLAB(nFirstLine, nLastLine);
324 else if (m_editor->getFileType() == FILE_CPP)
325 ApplyAutoFormatCPP(nFirstLine, nLastLine);
326
327 // Indent the code
328 IndentCode(nFirstLine, m_editor->LineFromPosition(m_editor->GetLineEndPosition(nLastLine)));
329}
330
331
340void CodeFormatter::ApplyAutoFormatNSCR(int nFirstLine, int nLastLine)
341{
343 return;
344
345 m_editor->BeginUndoAction();
346
347 int nFirstPosition = m_editor->PositionFromLine(nFirstLine);
348 int nLastPosition = m_editor->GetLineEndPosition(nLastLine);
349 int nIndentationLevel = (m_editor->getFileType() == FILE_NPRC) ? -1 : 0;
350
351 for (int i = nFirstPosition; i < nLastPosition; i++)
352 {
355 continue;
356
357 if (m_editor->GetCharAt(i) == '\r'
358 || m_editor->GetCharAt(i) == '\n')
359 continue;
360
361 // Jump over operator keywords
362 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_OPERATOR_KEYWORDS
363 || (m_editor->GetStyleAt(i) == wxSTC_NSCR_OPERATORS && m_editor->GetTextRange(i, i + 1) == "<>"))
364 {
365 for (; i < nLastPosition; i++)
366 {
367 if ((m_editor->GetStyleAt(i) != wxSTC_NSCR_STRING && (m_editor->GetCharAt(i) == ' '
368 || m_editor->GetCharAt(i) == ';'))
369 || m_editor->GetCharAt(i) == '\r'
370 || m_editor->GetCharAt(i) == '\n')
371 break;
372 }
373 }
374
375 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_OPERATORS)
376 {
377 int currentChar = m_editor->GetCharAt(i);
378 int prevChar = m_editor->GetCharAt(i - 1);
379 int nextChar = m_editor->GetCharAt(i + 1);
380 static std::string sParens = "(){}[]";
381
382 if (currentChar == '(' && m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_COMMAND)
383 nLastPosition += insertTextAndMove(i, " ");
384 else if (currentChar == '('
385 && (m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_FUNCTION
386 || m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_CUSTOM_FUNCTION
387 || m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_PROCEDURES
388 || m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_METHOD
389 || m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_PREDEFS))
390 {
391 // Apply logic to the contents of the function parentheses
392 nLastPosition += formatFunctionParentheses(i, wxSTC_NSCR_OPERATORS);
393 }
394 else if (sParens.find(currentChar) != std::string::npos)
395 continue;
396 else if (currentChar == ',' && nextChar != ' ')
397 nLastPosition += insertTextAndMove(i + 1, " ");
398 else if (currentChar == '?' && nextChar != currentChar && prevChar != currentChar)
399 {
400 if (nextChar != ' ')
401 nLastPosition += insertTextAndMove(i + 1, " ");
402
403 if (prevChar != ' ')
404 nLastPosition += insertTextAndMove(i, " ");
405 }
406 else if (currentChar == '<' || currentChar == '>' || currentChar == '!' || currentChar == '=')
407 {
408 static std::string sLeadingChars = " (=+-!*/^<>:|";
409
410 if (currentChar == '='
411 && (m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_OPTION
412 || m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_OPTION
413 || m_editor->GetStyleAt(i - 1) == wxSTC_NSCR_COMMAND))
414 continue;
415
416 if (nextChar != ' '
417 && nextChar != '='
418 && nextChar != '>'
419 && currentChar != '!'
420 && !(currentChar == '>' && prevChar == '<')
421 && m_editor->GetStyleAt(i - 1) != wxSTC_NSCR_OPTION
422 && m_editor->GetStyleAt(i + 1) != wxSTC_NSCR_OPTION)
423 nLastPosition += insertTextAndMove(i + 1, " ");
424
425 if (sLeadingChars.find(prevChar) == std::string::npos && !(currentChar == '<' && nextChar == '>'))
426 nLastPosition += insertTextAndMove(i, " ");
427 }
428
429 nLastPosition += formatOperators(i, prevChar, currentChar, nextChar, true);
430 }
431
432 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_COMMAND)
433 {
434 int nPos1 = i;
435
436 while (m_editor->GetStyleAt(i + 1) == wxSTC_NSCR_COMMAND)
437 i++;
438
439 wxString command = m_editor->GetTextRange(nPos1, i + 1);
440 int nCurrentLineStart = m_editor->PositionFromLine(m_editor->LineFromPosition(nPos1));
441 int nCurrentLineEnd = m_editor->GetLineEndPosition(m_editor->LineFromPosition(nPos1));
442
443 if (command == "global" || command == "load" || command == "append")
444 {
445 i = nCurrentLineEnd;
446 continue;
447 }
448 else if (command == "set")
449 {
450 for (; i <= nCurrentLineEnd; i++)
451 {
452 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_OPERATORS && m_editor->GetCharAt(i) == '[')
453 {
454 int bracepos = m_editor->BraceMatch(i);
455
456 if (bracepos > 0)
457 {
458 for (; i < bracepos; i++)
459 {
460 if (m_editor->GetCharAt(i) == ',' && m_editor->GetCharAt(i + 1) != ' ')
461 nLastPosition += insertTextAndMove(i + 1, " ");
462 }
463 }
464 }
465 }
466 }
467
468 // Line break after block statement
469 if (command == "if"
470 || command == "elseif"
471 || command == "for"
472 || command == "switch"
473 || command == "while")
474 {
475 int parens = i;
476 parens = m_editor->FindText(i, nCurrentLineEnd, "(");
477
478 if (parens > 0)
479 {
480 parens = m_editor->BraceMatch(parens);
481
482 if (parens > 0)
483 {
484 int nextVisibleCharAfterParens = m_editor->GetTextRange(parens + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t");
485
486 if (nextVisibleCharAfterParens != wxNOT_FOUND
487 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, parens + 1 + nextVisibleCharAfterParens)
488 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, parens + 1 + nextVisibleCharAfterParens))
489 nLastPosition += insertTextAndMove(parens + 1, "\r\n");
490 }
491 }
492 }
493 else if (command == "else" || command == "try")
494 {
495 int nextVisibleCharAfterCommand = m_editor->GetTextRange(i + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t");
496
497 if (nextVisibleCharAfterCommand != wxNOT_FOUND
498 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, i + 1 + nextVisibleCharAfterCommand)
499 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, i + 1 + nextVisibleCharAfterCommand))
500 nLastPosition += insertTextAndMove(i + 1, "\r\n");
501 }
502 else if (command == "case" || command == "default" || command == "catch")
503 {
504 int nColon = m_editor->FindText(i, nCurrentLineEnd, ":");
505 int nextVisibleCharAfterColon = m_editor->GetTextRange(nColon + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t");
506
507 if (nextVisibleCharAfterColon != wxNOT_FOUND
508 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, nColon + 1 + nextVisibleCharAfterColon)
509 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, nColon + 1 + nextVisibleCharAfterColon))
510 nLastPosition += insertTextAndMove(nColon + 1, "\r\n");
511 }
512
513 // Line break in front of block statement
514 if (m_editor->getBlockID(command) != wxNOT_FOUND)
515 {
516 if (m_editor->GetTextRange(nCurrentLineStart, nPos1).find_first_not_of(" \t") != std::string::npos)
517 {
518 nLastPosition += insertTextAndMove(nPos1, "\r\n");
519 i += 2;
520 }
521 }
522
523 if (m_editor->isBlockStart(command, false) != wxNOT_FOUND)
524 {
525 if (nIndentationLevel <= 0)
526 {
527 int nLine = m_editor->LineFromPosition(i);
528 int position = m_editor->PositionFromLine(nLine - 1);
529
530 while (m_editor->GetCharAt(position) == ' ' || m_editor->GetCharAt(position) == '\t')
531 position++;
532
533 if (nLine
534 && m_editor->GetLine(nLine - 1).find_first_not_of(" \t\r\n") != std::string::npos
535 && m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, m_editor->PositionFromLine(nLine - 1))
536 && m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, m_editor->PositionFromLine(nLine - 1))
538 {
539 nLastPosition += insertTextAndMove(m_editor->PositionFromLine(nLine), "\r\n");
540 i += 2;
541 }
542 }
543
544 nIndentationLevel++;
545 }
546
547 if (m_editor->isBlockEnd(command) != wxNOT_FOUND)
548 {
549 nIndentationLevel--;
550
551 if (nIndentationLevel <= 0)
552 {
553 int nLine = m_editor->LineFromPosition(i);
554
555 if (nLine < m_editor->GetLineCount() - 1
556 && m_editor->GetLine(nLine + 1).find_first_not_of(" \t\r\n") != std::string::npos)
557 nLastPosition += insertTextAndMove(m_editor->PositionFromLine(nLine + 1), "\r\n");
558 }
559 }
560 }
561
562 if (m_editor->GetStyleAt(i) == wxSTC_NSCR_STRING)
563 nLastPosition += formatStrings(i, true);
564 }
565
566 m_editor->EndUndoAction();
567}
568
569
578void CodeFormatter::ApplyAutoFormatMATLAB(int nFirstLine, int nLastLine)
579{
581 return;
582
583 m_editor->BeginUndoAction();
584
585 int nFirstPosition = m_editor->PositionFromLine(nFirstLine);
586 int nLastPosition = m_editor->GetLineEndPosition(nLastLine);
587 int nIndentationLevel = -1;
588
589 for (int i = nFirstPosition; i < nLastPosition; i++)
590 {
591 if (m_editor->GetStyleAt(i) == wxSTC_MATLAB_COMMENT)
592 continue;
593
594 if (m_editor->GetCharAt(i) == '\r'
595 || m_editor->GetCharAt(i) == '\n')
596 continue;
597
598 if (m_editor->GetStyleAt(i) == wxSTC_MATLAB_OPERATOR)
599 {
600 int currentChar = m_editor->GetCharAt(i);
601 int prevChar = m_editor->GetCharAt(i - 1);
602 int nextChar = m_editor->GetCharAt(i + 1);
603 static std::string sParens = "(){}[]";
604
605 if (currentChar == '('
606 && (m_editor->GetStyleAt(i - 1) == wxSTC_MATLAB_IDENTIFIER
607 || m_editor->GetStyleAt(i - 1) == wxSTC_MATLAB_KEYWORD))
608 {
609 // Apply logic to the contents of the function parentheses
610 nLastPosition += formatFunctionParentheses(i, wxSTC_MATLAB_OPERATOR);
611 }
612 else if (sParens.find(currentChar) != string::npos)
613 continue;
614 else if (currentChar == ',' && nextChar != ' ')
615 nLastPosition += insertTextAndMove(i + 1, " ");
616 else if (currentChar == '?' && nextChar != currentChar && prevChar != currentChar)
617 {
618 if (nextChar != ' ')
619 nLastPosition += insertTextAndMove(i + 1, " ");
620
621 if (prevChar != ' ')
622 nLastPosition += insertTextAndMove(i, " ");
623 }
624 else if (currentChar == '<' || currentChar == '>' || currentChar == '~' || currentChar == '=')
625 {
626 static std::string sLeadingChars = " (=+-*/^<>:~";
627
628 if (nextChar != ' ' && nextChar != '=' && nextChar != '>' && currentChar != '~' && !(currentChar == '>' && prevChar == '<'))
629 nLastPosition += insertTextAndMove(i + 1, " ");
630
631 if (sLeadingChars.find(prevChar) == string::npos && !(currentChar == '<' && nextChar == '>'))
632 nLastPosition += insertTextAndMove(i, " ");
633 }
634
635 nLastPosition += formatOperators(i, prevChar, currentChar, nextChar, false);
636 }
637
638 if (m_editor->GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
639 {
640 int nPos1 = i;
641
642 while (m_editor->GetStyleAt(i + 1) == wxSTC_MATLAB_KEYWORD)
643 i++;
644
645 wxString command = m_editor->GetTextRange(nPos1, i + 1);
646 int nCurrentLineStart = m_editor->PositionFromLine(m_editor->LineFromPosition(nPos1));
647 int nCurrentLineEnd = m_editor->GetLineEndPosition(m_editor->LineFromPosition(nPos1));
648
649 if (command == "if"
650 || command == "elseif"
651 || command == "switch"
652 || command == "case"
653 || command == "for"
654 || command == "while")
655 {
656 if (m_editor->GetCharAt(i + 1) != ' ')
657 nCurrentLineEnd += insertTextAndMove(i + 1, " ");
658
659 int parens = i + 1;
660
661 while (m_editor->GetCharAt(parens) == ' ')
662 parens++;
663
664 if (parens != '(' && parens != '[' && parens != '{')
665 parens = -1;
666
667 if (parens > 0)
668 {
669 parens = m_editor->BraceMatch(parens);
670
671 if (parens > 0)
672 {
673 if (m_editor->GetTextRange(parens + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t") != string::npos)
674 nLastPosition += insertTextAndMove(parens + 1, "\r\n");
675 }
676 }
677 else
678 {
679 parens = m_editor->FindText(i, nCurrentLineEnd, ";");
680
681 if (parens > 0)
682 {
683 if (m_editor->GetTextRange(parens + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t") != string::npos)
684 nLastPosition += insertTextAndMove(parens + 1, "\r\n");
685 }
686 }
687 }
688 else if (command == "else")
689 {
690 if (m_editor->GetTextRange(i + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t") != string::npos)
691 nLastPosition += insertTextAndMove(i + 1, "\r\n");
692 }
693
694 if (command == "if"
695 || command == "for"
696 || command == "else"
697 || command == "elseif"
698 || command == "switch"
699 || command == "case"
700 || command == "do"
701 || command == "otherwise"
702 || command == "try"
703 || command == "catch"
704 || command == "until"
705 || command == "while"
706 || command == "end")
707 {
708 if (m_editor->GetTextRange(nCurrentLineStart, nPos1).find_first_not_of(" \t") != string::npos)
709 {
710 nLastPosition += insertTextAndMove(nPos1, "\r\n");
711 i += 2;
712 }
713 }
714
715 if (command == "if"
716 || command == "for"
717 || command == "while"
718 || command == "try"
719 || command == "do"
720 || command == "function"
721 || command == "switch"
722 || command == "case")
723 {
724 if (nIndentationLevel <= 0)
725 {
726 int nLine = m_editor->LineFromPosition(i);
727 int position = m_editor->PositionFromLine(nLine - 1);
728
729 while (m_editor->GetCharAt(position) == ' ' || m_editor->GetCharAt(position) == '\t')
730 position++;
731
732 if (nLine
733 && m_editor->GetLine(nLine - 1).find_first_not_of(" \t\r\n") != string::npos
734 && m_editor->GetStyleAt(m_editor->PositionFromLine(nLine - 1)) != wxSTC_MATLAB_COMMENT
735 && m_editor->GetStyleAt(position) != wxSTC_MATLAB_COMMENT)
736 {
737 nLastPosition += insertTextAndMove(m_editor->PositionFromLine(nLine), "\r\n");
738 i += 2;
739 }
740 }
741
742 nIndentationLevel++;
743 }
744
745 if (command == "end")
746 {
747 nIndentationLevel--;
748
749 if (nIndentationLevel <= 0)
750 {
751 int nLine = m_editor->LineFromPosition(i);
752
753 if (nLine < m_editor->GetLineCount() - 1
754 && m_editor->GetLine(nLine + 1).find_first_not_of(" \t\r\n") != string::npos)
755 nLastPosition += insertTextAndMove(m_editor->PositionFromLine(nLine + 1), "\r\n");
756 }
757 }
758 }
759
760 if (m_editor->GetStyleAt(i) == wxSTC_MATLAB_STRING)
761 nLastPosition += formatStrings(i, false);
762 }
763
764 m_editor->EndUndoAction();
765}
766
767
776void CodeFormatter::ApplyAutoFormatCPP(int nFirstLine, int nLastLine)
777{
778 if (m_editor->getFileType() != FILE_CPP)
779 return;
780
781 m_editor->BeginUndoAction();
782
783 int nFirstPosition = m_editor->PositionFromLine(nFirstLine);
784 int nLastPosition = m_editor->GetLineEndPosition(nLastLine);
785 int nIndentationLevel = -1;
786
787 for (int i = nFirstPosition; i < nLastPosition; i++)
788 {
791 continue;
792
793 if (m_editor->GetCharAt(i) == '\r'
794 || m_editor->GetCharAt(i) == '\n')
795 continue;
796
797 if (m_editor->GetStyleAt(i) == wxSTC_C_OPERATOR)
798 {
799 int currentChar = m_editor->GetCharAt(i);
800 int prevChar = m_editor->GetCharAt(i - 1);
801 int nextChar = m_editor->GetCharAt(i + 1);
802 int nCurrentLineStart = m_editor->PositionFromLine(m_editor->LineFromPosition(i));
803 int nCurrentLineEnd = m_editor->GetLineEndPosition(m_editor->LineFromPosition(i));
804 static std::string sParens = "()[]";
805
806 if (currentChar == '-' && nextChar == '>')
807 {
808 i++;
809 continue;
810 }
811
812 if (currentChar == '(' && m_editor->GetStyleAt(i - 1) == wxSTC_C_WORD)
813 nLastPosition += insertTextAndMove(i, " ");
814 else if (currentChar == '('
815 && (m_editor->GetStyleAt(i - 1) == wxSTC_C_WORD2))
816 {
817 // Apply logic to the contents of the function parentheses
818 nLastPosition += formatFunctionParentheses(i, wxSTC_C_OPERATOR);
819 }
820 else if (sParens.find(currentChar) != string::npos)
821 continue;
822 else if (currentChar == '{' || currentChar == '}')
823 {
824 if (currentChar == '{')
825 nIndentationLevel++;
826
827 if (currentChar == '}')
828 nIndentationLevel--;
829
830 if (m_editor->GetTextRange(i + 1, nCurrentLineEnd).find_first_not_of(" \t\r\n") != string::npos)
831 {
832 nLastPosition += 2;
833 insertTextAndMove(i + 1, "\r\n");
834 }
835
836 if (m_editor->GetTextRange(nCurrentLineStart, i).find_first_not_of(" \t") != string::npos)
837 {
838 nLastPosition += 2;
839 i += insertTextAndMove(i, "\r\n");
840 }
841 }
842 else if (currentChar == ',' && nextChar != ' ')
843 nLastPosition += insertTextAndMove(i + 1, " ");
844 else if (currentChar == '?' && nextChar != currentChar && prevChar != currentChar)
845 {
846 if (nextChar != ' ')
847 nLastPosition += insertTextAndMove(i + 1, " ");
848
849 if (prevChar != ' ')
850 nLastPosition += insertTextAndMove(i, " ");
851 }
852 else if (currentChar == '<' || currentChar == '>' || currentChar == '!' || currentChar == '=')
853 {
854 static std::string sLeadingChars = " (=+-!*/^<>:";
855
856 if (currentChar == '<'
857 && (m_editor->GetStyleAt(i - 1) == wxSTC_C_WORD || m_editor->GetStyleAt(i - 1) == wxSTC_C_WORD))
858 continue;
859
860 if (currentChar == '>'
861 && (m_editor->GetStyleAt(i - 1) == wxSTC_C_WORD || m_editor->GetStyleAt(i + 1) == wxSTC_C_WORD))
862 continue;
863
864 if (nextChar != ' '
865 && nextChar != '='
866 && nextChar != '>'
867 && currentChar != '!'
868 && !(currentChar == '>' && prevChar == '<'))
869 nLastPosition += insertTextAndMove(i + 1, " ");
870
871 if (sLeadingChars.find(prevChar) == string::npos && !(currentChar == '<' && nextChar == '>'))
872 nLastPosition += insertTextAndMove(i, " ");
873 }
874
875 nLastPosition += formatOperators(i, prevChar, currentChar, nextChar, false);
876 }
877
878 if (m_editor->GetStyleAt(i) == wxSTC_C_WORD)
879 {
880 int nPos1 = i;
881
882 while (m_editor->GetStyleAt(i + 1) == wxSTC_C_WORD)
883 i++;
884
885 wxString command = m_editor->GetTextRange(nPos1, i + 1);
886 int nCurrentLineStart = m_editor->PositionFromLine(m_editor->LineFromPosition(nPos1));
887 int nCurrentLineEnd = m_editor->GetLineEndPosition(m_editor->LineFromPosition(nPos1));
888
889 if (command == "if"
890 || command == "switch"
891 || command == "for"
892 || command == "while")
893 {
894 int parens = i;
895 parens = m_editor->FindText(i, nCurrentLineEnd, "(");
896
897 if (parens > 0)
898 {
899 parens = m_editor->BraceMatch(parens);
900
901 if (parens > 0)
902 {
903 int nextVisibleCharAfterParens = m_editor->GetTextRange(parens + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t;");
904
905 if (nextVisibleCharAfterParens != wxNOT_FOUND
906 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, parens + 1 + nextVisibleCharAfterParens)
907 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, parens + 1 + nextVisibleCharAfterParens))
908 nLastPosition += insertTextAndMove(parens + 1, "\r\n");
909 }
910 }
911 }
912 else if (command == "else")
913 {
914 int nextVisibleCharAfterCommand = m_editor->GetTextRange(i + 1, nCurrentLineEnd).find_first_not_of(" \r\n\t");
915
916 if (nextVisibleCharAfterCommand != wxNOT_FOUND
917 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMAND, i + 1 + nextVisibleCharAfterCommand)
918 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, i + 1 + nextVisibleCharAfterCommand)
919 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, i + 1 + nextVisibleCharAfterCommand))
920 nLastPosition += insertTextAndMove(i + 1, "\r\n");
921 }
922
923 if (command == "if"
924 || command == "for"
925 || command == "while"
926 || command == "do"
927 || command == "try")
928 {
929 if (command == "while" && m_editor->GetTextRange(i + 1, nCurrentLineEnd).find(';') != string::npos)
930 continue;
931
932 if (command == "if" && m_editor->GetTextRange(nCurrentLineStart, i).find("else") != string::npos)
933 continue;
934
935 if (nIndentationLevel <= 0)
936 {
937 int nLine = m_editor->LineFromPosition(i);
938 int position = m_editor->PositionFromLine(nLine - 1);
939
940 while (m_editor->GetCharAt(position) == ' ' || m_editor->GetCharAt(position) == '\t')
941 position++;
942
943 if (nLine
944 && m_editor->GetLine(nLine - 1).find_first_not_of(" \t\r\n") != string::npos
945 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_BLOCK, m_editor->PositionFromLine(nLine - 1))
946 && !m_editor->isStyleType(NumeReEditor::STYLE_COMMENT_LINE, m_editor->PositionFromLine(nLine - 1))
948 {
949 nLastPosition += insertTextAndMove(m_editor->PositionFromLine(nLine), "\r\n");
950 i += 2;
951 }
952 }
953 }
954 }
955
956 if (m_editor->GetStyleAt(i) == wxSTC_C_STRING)
957 nLastPosition += formatStrings(i, false);
958 }
959
960 m_editor->EndUndoAction();
961}
962
963
973int CodeFormatter::formatFunctionParentheses(int& pos, int operatorStyleNum)
974{
975 int nParens = m_editor->BraceMatch(pos);
976 int offset = 0;
977
978 if (nParens > 0)
979 {
980 for (; pos < nParens; pos++)
981 {
982 if (m_editor->GetStyleAt(pos) == operatorStyleNum)
983 {
984 char currentChar = m_editor->GetCharAt(pos);
985 char nextChar = m_editor->GetCharAt(pos + 1);
986 char prevChar = m_editor->GetCharAt(pos - 1);
987
988 if (currentChar == ',' && nextChar != ' ')
989 {
990 offset += insertTextAndMove(pos + 1, " ");
991 nParens++;
992 }
993
994 if (currentChar == '=' && nextChar != ' ' && m_editor->GetStyleAt(pos + 1) != operatorStyleNum)
995 {
996 offset += insertTextAndMove(pos + 1, " ");
997 nParens++;
998 }
999
1000 if (currentChar == '=' && prevChar != ' ' && m_editor->GetStyleAt(pos - 1) != operatorStyleNum)
1001 {
1002 offset += insertTextAndMove(pos, " ");
1003 nParens++;
1004 }
1005 }
1006 }
1007 }
1008
1009 return offset;
1010}
1011
1012
1024int CodeFormatter::formatOperators(int pos, char prevChar, char currentChar, char nextChar, bool isNSCR)
1025{
1026 int offset = 0;
1027
1028 if (currentChar == '+' || currentChar == '-')
1029 {
1030 if (nextChar != ' '
1031 && nextChar != currentChar
1032 && nextChar != '='
1033 && nextChar != ';'
1034 && prevChar != '('
1035 && prevChar != '{'
1036 && prevChar != '['
1037 && m_editor->GetCharAt(pos - 2) != ','
1038 && m_editor->GetCharAt(pos - 2) != '='
1039 && (!isNSCR || (m_editor->GetStyleAt(pos + 1) != wxSTC_NSCR_COMMAND
1040 && m_editor->GetStyleAt(pos + 1) != wxSTC_NSCR_OPTION
1041 && m_editor->GetStyleAt(pos - 1) != wxSTC_NSCR_COMMAND
1042 && m_editor->GetStyleAt(pos - 1) != wxSTC_NSCR_OPTION
1043 && nextChar != '>')))
1044 offset += insertTextAndMove(pos + 1, " ");
1045
1046 if (prevChar != ' '
1047 && prevChar != currentChar
1048 && nextChar != currentChar
1049 && prevChar != '('
1050 && prevChar != '['
1051 && prevChar != '{')
1052 offset += insertTextAndMove(pos, " ");
1053 }
1054 else if (currentChar == '&' || currentChar == '|')
1055 {
1056 if (nextChar != ' ' && nextChar != currentChar && (!isNSCR || nextChar != '>'))
1057 offset += insertTextAndMove(pos + 1, " ");
1058
1059 if (prevChar != ' ' && prevChar != currentChar)
1060 offset += insertTextAndMove(pos, " ");
1061 }
1062 else if ((currentChar == '*' || currentChar == '/' || currentChar == '^')
1063 && nextChar == '='
1064 && prevChar != ' '
1065 && nextChar != currentChar
1066 && prevChar != currentChar)
1067 offset += insertTextAndMove(pos, " ");
1068
1069 return offset;
1070}
1071
1072
1082int CodeFormatter::formatStrings(int pos, bool isNSCR)
1083{
1084 int style = m_editor->GetStyleAt(pos);
1085 int offset = 0;
1086 char prevChar = m_editor->GetCharAt(pos - 1);
1087 char nextChar = m_editor->GetCharAt(pos + 1);
1088
1089 if (m_editor->GetStyleAt(pos + 1) != style
1090 && m_editor->GetLineEndPosition(m_editor->LineFromPosition(pos)) != pos + 1
1091 && nextChar != ' '
1092 && nextChar != ','
1093 && nextChar != ';'
1094 && nextChar != ')'
1095 && nextChar != ']'
1096 && nextChar != '}')
1097 offset += insertTextAndMove(pos + 1, " ");
1098
1099 if (m_editor->GetStyleAt(pos - 1) != style
1100 && m_editor->PositionFromLine(m_editor->LineFromPosition(pos)) != pos
1101 && prevChar != ' '
1102 && prevChar != '('
1103 && prevChar != '['
1104 && prevChar != '{'
1105 && (!isNSCR || !(prevChar == '=' && m_editor->GetStyleAt(pos - 2) == wxSTC_NSCR_OPTION)))
1106 offset += insertTextAndMove(pos, " ");
1107
1108 return offset;
1109}
1110
1111
1112
void ApplyAutoFormatNSCR(int nFirstLine, int nLastLine)
Applies autoformatting to NumeRe code.
int determineIndentationLevel(int nLine, int &singleLineIndent)
Determines the indentation level of the selected line.
int formatFunctionParentheses(int &pos, int operatorStyleNum)
Formats the contents of function parentheses.
int determineIndentationLevelCPP(int nLine, int &singleLineIndent)
Determines the indentation level of the selected line of C++ code.
int determineIndentationLevelNSCR(int nLine, int &singleLineIndent)
Determines the indentation level of the selected line of NumeRe code.
void ApplyAutoFormatCPP(int nFirstLine, int nLastLine)
Applies autoformatting to C++ code.
NumeReEditor * m_editor
void IndentCode(int nFirstLine, int nLastLine)
Automatically indents the code based upon its hierarchy.
void FormatCode(int nFirstLine, int nLastLine)
Applies automatic formatting to the selected code lines.
int insertTextAndMove(int nPosition, const wxString &sText)
Inserts text and returns the length of the insertion.
int formatOperators(int pos, char prevChar, char currentChar, char nextChar, bool isNSCR)
Helper to format binary operators.
int formatStrings(int pos, bool isNSCR)
Helper to format characters around string literals.
int determineIndentationLevelMATLAB(int nLine, int &singleLineIndent)
Determines the indentation level of the selected line of MATLAB code.
void ApplyAutoFormatMATLAB(int nFirstLine, int nLastLine)
Applies autoformatting to MATLAB code.
bool isStyleType(StyleType _type, int nPos)
Determine the syntax style type at the selected position.
Definition: editor.cpp:8249
int getBlockID(const wxString &word)
This function returns the block ID.
Definition: editor.cpp:7235
int isBlockStart(const wxString &sWord, bool allowIntermediate=false)
This function returns true, if a passed word corresponds to a control flow statement block start.
Definition: editor.cpp:7109
int isBlockMiddle(const wxString &sWord)
This function returns, whether a word matches to a block middle statement (e.g. elseif).
Definition: editor.cpp:7180
@ STYLE_COMMAND
Definition: editor.h:324
@ STYLE_COMMENT_LINE
Definition: editor.h:320
@ STYLE_COMMENT_BLOCK
Definition: editor.h:321
int isBlockEnd(const wxString &sWord)
This function returns true, if a passed word corresponds to a control flow statement block end.
Definition: editor.cpp:7152
FileFilterType getFileType()
Definition: editor.h:290
@ FILE_CPP
@ FILE_NPRC
@ FILE_NSCR
@ FILE_MATLAB