Patch #3323 2012-08-23 20:15
p2rkw
Abbreviations auto-complete- Download
- 3323-Abbreviations.patch (10.2 KB)
Index: src/plugins/abbreviations/abbreviations.h
===================================================================
--- src/plugins/abbreviations/abbreviations.h (wersja 8496)
+++ src/plugins/abbreviations/abbreviations.h (kopia robocza)
@@ -148,10 +148,16 @@
void OnEditAutoComplete(wxCommandEvent& /*event*/);
void OnEditMenuUpdateUI(wxUpdateUIEvent& event);
+public:
+ void EditorEventHook(cbEditor* editor, wxScintillaEvent& event);
+
private:
friend class AbbreviationsConfigPanel;
AutoCompleteMap m_AutoCompleteMap;
+ int m_EditorHookId;
+ /// is AutoComp opened by Abbreviations
+ bool m_IsAutoCompVisible;
private:
DECLARE_EVENT_TABLE();
};
Index: src/plugins/abbreviations/abbreviations.cpp
===================================================================
--- src/plugins/abbreviations/abbreviations.cpp (wersja 8496)
+++ src/plugins/abbreviations/abbreviations.cpp (kopia robocza)
@@ -11,6 +11,8 @@
#include <configurationpanel.h>
#include <cbstyledtextctrl.h>
+#include <editor_hooks.h>
+
#include "abbreviations.h"
#include "abbreviationsconfigpanel.h"
@@ -44,6 +46,8 @@
{
NotifyMissingFile(_T("abbreviations.zip"));
}
+
+ m_IsAutoCompVisible = false;
}
// destructor
@@ -65,6 +69,10 @@
LoadAutoCompleteConfig();
RegisterScripting();
+
+ // hook to editors
+ EditorHooks::HookFunctorBase* myhook = new EditorHooks::HookFunctor<Abbreviations>(this, &Abbreviations::EditorEventHook);
+ m_EditorHookId = EditorHooks::RegisterHook(myhook);
}
void Abbreviations::OnRelease(bool appShutDown)
@@ -82,6 +90,10 @@
{
m_Singleton = nullptr;
}
+
+ // unregister hook
+ // 'true' will delete the functor too
+ EditorHooks::UnregisterHook(m_EditorHookId, true);
}
void Abbreviations::RegisterScripting()
@@ -158,8 +170,38 @@
void Abbreviations::OnEditAutoComplete(wxCommandEvent& /*event*/)
{
- cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
- DoAutoComplete(ed);
+ cbEditor* editor = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
+ cbStyledTextCtrl* control = editor->GetControl();
+
+ const AutoCompleteMap& acm = m_AutoCompleteMap;
+
+ int curPos = control->GetCurrentPos();
+ int startPos = control->WordStartPosition(curPos, true);
+ const int endPos = control->WordEndPosition(curPos, true);
+
+ const wxString keyword = control->GetTextRange(startPos, endPos);
+ AutoCompleteMap::const_iterator it = acm.find(keyword);
+
+ if(it != acm.end() )
+ {
+ DoAutoComplete(editor);
+ }
+ else
+ {
+ wxArrayString items;
+ for( AutoCompleteMap::const_iterator it = acm.begin(); it != acm.end(); ++it )
+ {
+ if(it->first.Lower().StartsWith(keyword) )
+ {
+ items.Add(it->first);
+ }
+ }
+ items.Sort();
+ wxString itemsStr = GetStringFromArray(items, _T(" "));
+ control->AutoCompShow(endPos-startPos, itemsStr);
+ m_IsAutoCompVisible = control->AutoCompActive();
+ }
+
}
void Abbreviations::OnEditMenuUpdateUI(wxUpdateUIEvent& event)
@@ -187,83 +229,77 @@
if (control->CallTipActive())
control->CallTipCancel();
+ m_IsAutoCompVisible = false;
+
LogManager* msgMan = Manager::Get()->GetLogManager();
int curPos = control->GetCurrentPos();
int wordStartPos = control->WordStartPosition(curPos, true);
- wxString keyword = control->GetTextRange(wordStartPos, curPos);
+ const int endPos = control->WordEndPosition(curPos, true);
+ wxString keyword = control->GetTextRange(wordStartPos, endPos);
wxString lineIndent = ed->GetLineIndentString(control->GetCurrentLine());
msgMan->DebugLog(_T("Auto-complete keyword: ") + keyword);
- AutoCompleteMap::iterator it;
- for (it = m_AutoCompleteMap.begin(); it != m_AutoCompleteMap.end(); ++it)
+ AutoCompleteMap::iterator it = m_AutoCompleteMap.find(keyword);
+ if (it != m_AutoCompleteMap.end() )
{
- if (keyword == it->first)
+ // found; auto-complete it
+ msgMan->DebugLog(_T("Auto-complete match for keyword found."));
+
+ // indent code accordingly
+ wxString code = it->second;
+ code.Replace(_T("\n"), _T('\n') + lineIndent);
+
+ // look for and replace macros
+ int macroPos = code.Find(_T("$("));
+ while (macroPos != -1)
{
- // found; auto-complete it
- msgMan->DebugLog(_T("Auto-complete match for keyword found."));
+ // locate ending parenthesis
+ int macroPosEnd = macroPos + 2;
+ int len = (int)code.Length();
+ while (macroPosEnd < len && code.GetChar(macroPosEnd) != _T(')'))
+ ++macroPosEnd;
+ if (macroPosEnd == len)
+ return; // no ending parenthesis
- // indent code accordingly
- wxStr
download for full patch...
History
p2rkw 2012-08-26 13:08
- if keyword isn't complete abbreviation will display auto complete list with possible matches
- abbreviations now can be expandend even if cursor is inside keyword (not only at end)
topic on forum: http://forums.codeblocks.org/index.php/topic,16749.0.html
mortenmacfly 2012-10-27 21:02
One question:
In Abbreviations::EditorEventHook, why did you move the event.Skip() outof the else - tree?This changes the logic of the methods and would raise multiple autocomp boxes in case another plugin shows one, too (i.e. CC).
Was there a particular reason to do so?
p2rkw 2012-10-27 22:59
Hmm... I don't remember right now, but you're right: that Skip() should be inside else block. Here's my current implementation of Abbreviations::EditorEventHook : void Abbreviations::EditorEventHook(cbEditor* editor, wxScintillaEvent& event) { cbStyledTextCtrl* control = editor->GetControl(); if( !IsAttached() || !m_IsAutoCompVisible ) { event.Skip(); return; } if (event.GetEventType() == wxEVT_SCI_AUTOCOMP_SELECTION) { const wxString& itemText = event.GetText(); int curPos = control->GetCurrentPos(); int startPos = control->WordStartPosition(curPos, true); const int endPos = control->WordEndPosition(curPos, true); control->BeginUndoAction(); control->SetTargetStart(startPos); control->SetTargetEnd(endPos); control->ReplaceTarget(itemText); control->GotoPos(startPos + itemText.size() ); control->EndUndoAction(); DoAutoComplete(editor); //prevent other plugins(CC mostly) from insertion this keyword event.SetText( wxEmptyString ); event.SetEventType(wxEVT_NULL); } else //here should be: else if( vent.GetEventType() == wxEVT_SCI_AUTOCOMP_CANCELLED) { //but this event doesn't occur. m_IsAutoCompVisible = control->AutoCompActive(); if(!m_IsAutoCompVisible) { // allow others to handle this event event.Skip(); } } } As you can see I also added "event.SetEventType(wxEVT_NULL);" to prevent insertion event's text by CC. Unfortunately, without this line CC still can handle this event, even when it's not skipped with event.Skip() call. Boolean variable m_IsAutoCompVisible is set to true only when tooltip was opened by Abbreviations menu item or shortcut key. IMHO CC should also checks is auto complete tool-tip opened by itself. Then CC might call event.Skip() only on unwanted events( now its called on every single event).
mortenmacfly 2012-10-28 05:38
Ok.
Do you mind to simply update the patch against trunk? I am a bit confused with what and where to update now.
p2rkw 2012-10-31 20:44
Patch updated.