1 #include "SmartIndentPython.h"
2 
3 #include <sdk.h> // Code::Blocks SDK
4 
5 #ifndef CB_PRECOMP
6     #include <cbeditor.h>
7     #include <configmanager.h>
8     #include <editormanager.h>
9     #include <editorcolourset.h>
10     #include <manager.h>
11 #endif
12 
13 #include <cbstyledtextctrl.h>
14 
15 // Register the plugin with Code::Blocks.
16 // We are using an anonymous namespace so we don't litter the global one.
17 namespace
18 {
19     PluginRegistrant<SmartIndentPython> reg(wxT("SmartIndentPython"));
20 }
21 
OnEditorHook(cbEditor * ed,wxScintillaEvent & event) const22 void SmartIndentPython::OnEditorHook(cbEditor* ed, wxScintillaEvent& event) const
23 {
24     // check if smart indent is enabled
25     // check the event type and the currently set language
26     // if it is not a CharAdded event or the language is not Python return
27 
28     if (!ed)
29         return;
30 
31     if ( !SmartIndentEnabled() )
32         return;
33 
34     wxEventType type = event.GetEventType();
35     if ( type != wxEVT_SCI_CHARADDED )
36         return;
37 
38     cbStyledTextCtrl* stc = ed->GetControl();
39     if (!stc)
40         return;
41 
42     const wxString langname = Manager::Get()->GetEditorManager()->GetColourSet()->GetLanguageName(ed->GetLanguage());
43     if ( langname != wxT("Python") )
44         return;
45 
46     ed->AutoIndentDone(); // we are responsible.
47 
48     const int pos = stc->GetCurrentPos();
49     int currLine = stc->LineFromPosition(pos);
50 
51     if ( currLine == 0)
52         return;
53 
54     const wxChar ch = event.GetKey();
55 
56     // indent
57     if ( (ch == wxT('\n')) || ( (stc->GetEOLMode() == wxSCI_EOL_CR) && (ch == wxT('\r')) ) )
58     {
59         if (AutoIndentEnabled())
60         {
61             wxString indent = ed->GetLineIndentString(currLine-1);
62             const wxChar b = GetLastNonWhitespaceChar(ed);
63 
64             if (b == wxT(':'))
65                 Indent(stc, indent);
66             stc->BeginUndoAction();
67             stc->InsertText(pos, indent);
68             stc->GotoPos(pos + indent.Length());
69             stc->ChooseCaretX();
70             stc->EndUndoAction();
71         }
72     }
73 
74     bool braceCompleted = false;
75     if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() )
76         braceCompleted = stc->DoSelectionBraceCompletion(ch);
77     if (!braceCompleted && BraceCompletionEnabled())
78     {
79         stc->DoBraceCompletion(ch);
80         if (  !(stc->IsComment(stc->GetStyleAt(pos)) || stc->IsComment(stc->GetStyleAt(pos - 2)))
81             && (ch == wxT('"') || ch == wxT('\'')) )
82         {
83             const wxString tripleQuote(3, ch);
84             if (stc->GetTextRange(pos - 3, pos) == tripleQuote && !stc->IsString(stc->GetStyleAt(pos - 4)))
85                 stc->InsertText(pos, tripleQuote);
86         }
87     }
88 }
89