33#include < wx/regex.h>
44#include < backtracedlg.h>
55#include < cbstyledtextctrl.h>
6+ #include < watchesdlg.h>
67
78// Register the plugin with Code::Blocks.
89// We are using an anonymous namespace so we don't litter the global one.
@@ -44,16 +45,7 @@ int ID_LangMenu_RunPiped = wxNewId();//XRCID("idPyDebuggerMenuDebug");
4445
4546// events handling
4647BEGIN_EVENT_TABLE (PyDebugger, cbDebuggerPlugin)
47- // add any events you want to handle here
48- // // EVT_MENU(ID_LangMenu_Run,PyDebugger::OnRun)
49- // // EVT_MENU(ID_LangMenu_RunPiped,PyDebugger::OnDebugTarget)
50- // // EVT_MENU(XRCID("idPyDebuggerMenuDebug"),PyDebugger::OnContinue)
51- // // EVT_MENU(XRCID("idPyDebuggerMenuNext"),PyDebugger::OnNext)
52- // // EVT_MENU(XRCID("idPyDebuggerMenuStep"),PyDebugger::OnStep)
53- // // EVT_MENU(XRCID("idPyDebuggerMenuStop"),PyDebugger::OnStop)
5448 EVT_MENU (ID_LangMenu_DebugSendCommand,PyDebugger::OnSendCommand)
55- EVT_MENU(ID_LangMenu_ShowWatch,PyDebugger::OnViewWatch)
56- EVT_MENU(ID_LangMenu_UpdateWatch,PyDebugger::OnUpdateWatch)
5749 EVT_END_PROCESS(ID_PipedProcess, PyDebugger::OnTerminatePipedProcess)
5850 EVT_TIMER(ID_TimerPollDebugger, PyDebugger::OnTimer)
5951END_EVENT_TABLE()
@@ -183,63 +175,19 @@ wxString PyDebugger::AssembleBreakpointCommands()
183175 }
184176 return commands;
185177}
186-
178+
187179
188180wxString PyDebugger::AssembleWatchCommands ()
189- { // TODO: get this working
190- wxString commands;
191- wxString watchtext=m_WatchDlg->m_WatchText ->GetValue ();
192- wxRegEx re,re1,re2,re3,re4;
193- // Not sure regexes are really required, something simpler would also work...
194- re1.Compile (_T (" ^ *([^\\ t]*)(\\ t.*)*" ),wxRE_ADVANCED); // evaluate expression: syntax "expr = value" expr may contain == so regex must only match on single =
195- re2.Compile (_T (" ^ *([^\\ t]*)\\ : *(\\ t.*)*$" ),wxRE_ADVANCED); // evaluate members: syntax "objname:"
196- re3.Compile (_T (" ^ *[\\ .\\ *]" ),wxRE_ADVANCED); // subordinates of object in the form ".varname\tvalue" and errors will be deleted
197- re4.Compile (_T (" ^ *(\\ #.*)" ),wxRE_ADVANCED); // comment line syntax "# blah blah blah" no command processing
198-
199- // pull one line at a time and look for a regex match in each line
200- while ( watchtext.Len ()>0 )
201- {
202- int watchtextpos=watchtext.Find (_T (" \n " ));
203- wxString watchline;
204- if (watchtextpos<0 ) // not found
205- {
206- watchline=watchtext;
207- watchtext=_ (" " );
208- } else
209- {
210- watchline=(watchtextpos==0 ?_T (" " ):watchtext.Mid (0 ,watchtextpos));
211- watchtext=watchtext.Mid (watchtextpos+1 );
212- }
213- wxString expr, cmd;
214- if (watchline.Len ()==0 )
215- continue ;
216- if (re4.Matches (watchline))
217- {
218- expr=re4.GetMatch (watchline,1 );
219- expr.Replace (_T (" \t " ),_T (" \001 " ));
220- cmd=_T (" pc " )+expr+_T (" \n " );
221- commands+=cmd;
222- continue ;
223- }
224- if (re3.Matches (watchline))
225- continue ;
226- if (re2.Matches (watchline)&&re2.GetMatchCount ()>=2 )
227- {
228- expr=re2.GetMatch (watchline,1 );
229- cmd=_T (" pm1 " )+expr+_T (" \n " )+_T (" pm2 " )+expr+_T (" \n " );
230- commands+=cmd;
231- continue ;
232- }
233- if (re1.Matches (watchline)&&re1.GetMatchCount ()>=2 )
234- {
235- expr=re1.GetMatch (watchline,1 );
236- if (expr==_T (" " ))
237- continue ;
238- cmd=_T (" ps " )+expr+_T (" \n " );
239- commands+=cmd;
240- continue ;
241- }
242- }
181+ {
182+ wxString commands;
183+
184+ for (unsigned int i=0 ;i<m_watchlist.size ();++i)
185+ { // TODO: ITERATE INTO CHILD WATCHES
186+ PythonWatch *w=m_watchlist[i].get ();
187+ wxString s;
188+ w->GetSymbol (s);
189+ commands+=_T (" ps " )+s+_T (" \n " );
190+ }
243191 return commands;
244192}
245193
@@ -251,7 +199,7 @@ wxString PyDebugger::AssembleAliasCommands()
251199 commands+=_T (" alias pm1 print '%1: \\ 001',;print type(%1)\n " );
252200 commands+=_T (" alias pm2 for k in %1.__dict__.keys(): print '...',k,'\\ 001',type(k),'\\ 001',%1.__dict__[k],'\\ 002',\n " );
253201 // Print variable name, type and value
254- commands+=_T (" alias ps print '%1 \\ 001',;print type(%1), '\\ 001', %1\n " );
202+ commands+=_T (" alias ps print '%1\\ 001',;print str( type(%1))+ '\\ 001',;print %1\n " );
255203 // Print comment
256204 commands+=_T (" alias pc print '%1'\n " );
257205
@@ -320,17 +268,34 @@ void PyDebugger::OnTimer(wxTimerEvent& event)
320268 wxString exprresult=reprompt.GetMatch (m_outdebugbuf.Mid (m_debugbufpos),1 );
321269 if (cmd.type ==DBGCMDTYPE_WATCHEXPRESSION )
322270 {
271+ /* commands+=_T("alias ps print '%1 \\001',;print type(%1), '\\001', %1\n");*/
323272 // exprresult;
324273 if (reprompt.GetMatchCount ()>1 )
325- {
274+ {
275+ exprresult.RemoveLast ();
326276 exprresult.Replace (_T (" \t " ),_T (" \\ t" ),true );
327277 exprresult.Replace (_T (" \n " ),_T (" \\ n" ),true );
328- exprresult.Replace (_T (" \001 " ),_T (" \t " ),true );
329- exprresult.Replace (_T (" \002 " ),_T (" \n " ),true );
330- if (exprresult.Mid (exprresult.Len ()-2 ,2 )==_T (" \\ n" ))
331- exprresult=exprresult.Mid (0 ,exprresult.Len ()-2 );
332- m_watchstr+=exprresult+_T (" \n " );
333- // m_WatchDlg->UpdateVariable(exprresult); //TODO: implement this
278+ wxString symbol=exprresult.BeforeFirst (_T (' \001 ' ));
279+ exprresult=exprresult.AfterFirst (_T (' \001 ' ));
280+ wxString type=exprresult.BeforeFirst (_T (' \001 ' ));
281+ wxString value=exprresult.AfterFirst (_T (' \001 ' ));
282+ for (int i=0 ;i<m_watchlist.size ();++i)
283+ {
284+ PythonWatch *p;
285+ wxString s;
286+ m_watchlist[i].get ()->GetSymbol (s);
287+ if (s==symbol)
288+ p=m_watchlist[i].get ();
289+ else
290+ p=dynamic_cast <PythonWatch*>(m_watchlist[i]->FindChild (symbol));
291+ if (p)
292+ {
293+ p->SetType (type);
294+ p->SetValue (value);
295+ }
296+ }
297+ DebuggerManager &dbg_manager = *Manager::Get ()->GetDebuggerManager ();
298+ dbg_manager.GetWatchesDialog ()->UpdateWatches ();
334299 }
335300 }
336301 if (cmd.type ==DBGCMDTYPE_WATCHTOOLTIP )
@@ -476,9 +441,6 @@ void PyDebugger::OnTimer(wxTimerEvent& event)
476441 m_outprogbuf=_T (" " );
477442 m_progbufpos=0 ;
478443 m_TimerPollDebugger.Stop ();
479- if (m_watchstr!=_T (" " ))
480- m_WatchDlg->m_WatchText ->SetValue (m_watchstr);
481- m_watchstr=_T (" " );
482444 }
483445 }
484446}
@@ -534,7 +496,6 @@ bool PyDebugger::Debug(bool breakOnEntry)
534496 m_outbuf=_T (" " );
535497 m_outdebugbuf=_T (" " );
536498 m_outprogbuf=_T (" " );
537- m_watchstr=_T (" " );
538499 ReadPluginConfig ();
539500 if (!m_RunTarget)
540501 {
@@ -725,7 +686,7 @@ const cbBreakpoint* PyDebugger::GetBreakpoint(int index) const
725686
726687
727688cbBreakpoint* PyDebugger::AddBreakpoint (const wxString& file, int line)
728- {
689+ {
729690 if (!IsPythonFile (file))
730691 return NULL ;
731692 for (BPList::iterator itr=m_bplist.begin (); itr!=m_bplist.end (); ++itr)
@@ -800,6 +761,68 @@ void PyDebugger::DeleteAllBreakpoints()
800761}
801762
802763
764+ cbWatch* PyDebugger::AddWatch (const wxString& symbol)
765+ {
766+ PythonWatch::Pointer pwatch (new PythonWatch (symbol));
767+ m_watchlist.push_back (pwatch);
768+
769+ if (IsRunning ())
770+ DispatchCommands (_T (" ps " )+symbol+_T (" \n " ),DBGCMDTYPE_WATCHEXPRESSION );
771+ return pwatch.get ();
772+ }
773+
774+ void PyDebugger::DeleteWatch (cbWatch *watch)
775+ {
776+ // this will delete the root node of watch
777+ // TODO: Why do we need to delete root node?
778+ cbWatch *root_watch = GetRootWatch (watch);
779+ unsigned int i;
780+ for (i=0 ;i<m_watchlist.size ();++i)
781+ {
782+ if (m_watchlist[i].get ()==root_watch)
783+ break ;
784+ }
785+ if (i==m_watchlist.size ())
786+ return ;
787+
788+ m_watchlist.erase (m_watchlist.begin ()+i);
789+ }
790+
791+ bool PyDebugger::HasWatch (cbWatch *watch)
792+ {
793+ cbWatch *root_watch = GetRootWatch (watch);
794+ unsigned int i;
795+ for (i=0 ;i<m_watchlist.size ();++i)
796+ {
797+ if (m_watchlist[i].get ()==root_watch)
798+ break ;
799+ }
800+ return i<m_watchlist.size ();
801+ }
802+
803+ void PyDebugger::ShowWatchProperties (cbWatch *watch)
804+ {
805+ }
806+
807+ bool PyDebugger::SetWatchValue (cbWatch *watch, const wxString &value)
808+ {
809+ return false ;
810+ }
811+
812+ void PyDebugger::ExpandWatch (cbWatch *watch)
813+ {
814+ }
815+
816+ void PyDebugger::CollapseWatch (cbWatch *watch)
817+ {
818+ }
819+
820+ void PyDebugger::OnWatchesContextMenu (wxMenu &menu, const cbWatch &watch, wxObject *property)
821+ {
822+ }
823+
824+
825+
803826int PyDebugger::GetStackFrameCount () const
804827{
805828 return m_stackinfo.frames .size ();
@@ -913,30 +936,6 @@ void PyDebugger::OnRun(wxCommandEvent& event)
913936}
914937
915938
916- void PyDebugger::OnViewWatch (wxCommandEvent& event)
917- {
918- // This toggles display of watch
919- CodeBlocksDockEvent evt (event.IsChecked () ? cbEVT_SHOW_DOCK_WINDOW : cbEVT_HIDE_DOCK_WINDOW);
920- evt.pWindow = m_WatchDlg;
921- Manager::Get ()->ProcessEvent (evt);
922-
923- // TODO: Any required watch processing before watch is shown
924- // if (event.IsChecked())
925- // DoWatches();
926- }
927-
928-
929- void PyDebugger::OnUpdateWatch (wxCommandEvent& event)
930- {
931- if (m_DebuggerActive)
932- {
933- wxString wcommands=AssembleWatchCommands ();
934- DispatchCommands (wcommands,DBGCMDTYPE_WATCHEXPRESSION ,true );
935- }
936- }
937-
938-
939-
940939// constructor
941940PyDebugger::PyDebugger ()
942941{
@@ -949,7 +948,6 @@ PyDebugger::PyDebugger()
949948 }
950949 m_DebuggerActive=false ;
951950 m_RunTargetSelected=false ;
952- m_WatchDlg=NULL ;
953951
954952}
955953
@@ -977,31 +975,15 @@ void PyDebugger::OnAttachReal()
977975 // (see: does not need) this plugin...
978976 this ->ReadPluginConfig ();
979977 this ->UpdateConfig ();
980- // m_HasDebugLog = Manager::Get()->GetConfigManager(_T("debugger"))->ReadBool(_T("debug_log"), false);
981- // MessageManager* msgMan = Manager::Get()->GetMessageManager();
982978 m_DebugLog = new TextCtrlLogger (true );
983- // m_DebugLogPageIndex = msgMan->AddLog(m_DebugLog, _("PyDebugger"));
984- m_WatchDlg = new DebuggerWatch (Manager::Get ()->GetAppWindow (), this );
985979
986980 Manager::Get ()->RegisterEventSink (cbEVT_EDITOR_TOOLTIP, new cbEventFunctor<PyDebugger, CodeBlocksEvent>(this , &PyDebugger::OnValueTooltip));
987981
988982 CodeBlocksLogEvent evtlog (cbEVT_ADD_LOG_WINDOW,m_DebugLog, _ (" PyDebugger" ));
989- Manager::Get ()->ProcessEvent (evtlog);
990- CodeBlocksDockEvent evt (cbEVT_ADD_DOCK_WINDOW);
991- evt.name = _T (" Python Watch" );
992- evt.title = _T (" Python Watch" );
993- evt.pWindow = m_WatchDlg;
994- evt.dockSide = CodeBlocksDockEvent::dsFloating;
995- evt.desiredSize .Set (150 , 250 );
996- evt.floatingSize .Set (150 , 250 );
997- evt.minimumSize .Set (150 , 150 );
998- Manager::Get ()->ProcessEvent (evt);
983+ Manager::Get ()->ProcessEvent (evtlog);
984+
999985 DebuggerManager &dbg_manager = *Manager::Get ()->GetDebuggerManager ();
1000- dbg_manager.RegisterDebugger (this , _T (" python" ));
1001- // set log image
1002- // wxString prefix = ConfigManager::GetDataFolder() + _T("/images/");
1003- // bmp = cbLoadBitmap(prefix + _T("contents_16x16.png"), wxBITMAP_TYPE_PNG);
1004- // Manager::Get()->GetMessageManager()->SetLogImage(m_pDbgLog, bmp);
986+ dbg_manager.RegisterDebugger (this , _T (" python" ));
1005987
1006988}
1007989
@@ -1013,21 +995,14 @@ void PyDebugger::OnReleaseReal(bool appShutDown)
1013995 // NOTE: after this function, the inherited member variable
1014996 // m_IsAttached will be FALSE...
1015997
1016- // TODO: Handle destruction of any running python processes? (Maybe not necessary...)
1017- // TODO: Destroy any other objects that aren't cleaned up by the framework?
1018-
1019- if (m_WatchDlg)
1020- {
1021- CodeBlocksDockEvent evt (cbEVT_REMOVE_DOCK_WINDOW);
1022- evt.pWindow = m_WatchDlg;
1023- Manager::Get ()->ProcessEvent (evt);
1024- m_WatchDlg->Destroy ();
1025- }
1026- m_WatchDlg = 0L ;
998+ // TODO: Handle destruction of any running python debugger processes? (Maybe not necessary...)
1027999
10281000 CodeBlocksLogEvent evt (cbEVT_REMOVE_LOG_WINDOW,m_DebugLog);
10291001 Manager::Get ()->ProcessEvent (evt);
10301002 m_DebugLog = 0L ;
1003+
1004+ DebuggerManager &dbg_manager = *Manager::Get ()->GetDebuggerManager ();
1005+ dbg_manager.UnregisterDebugger (this );
10311006
10321007}
10331008
@@ -1050,8 +1025,6 @@ void PyDebugger::OnValueTooltip(CodeBlocksEvent& event)
10501025 return ;
10511026 if (!IsStopped ())
10521027 return ;
1053- // if (!Manager::Get()->GetConfigManager(_T("debugger"))->ReadBool(_T("eval_tooltip"), false))
1054- // return;
10551028
10561029 EditorBase* base = event.GetEditor ();
10571030 cbEditor* ed = base && base->IsBuiltinEditor () ? static_cast <cbEditor*>(base) : 0 ;
@@ -1125,8 +1098,8 @@ void PyDebugger::CreateMenu()
11251098// LangMenu->Append(XRCID("idPyDebuggerMenuStep"),_T("Step &Into"),_T(""));
11261099// LangMenu->Append(XRCID("idPyDebuggerMenuStop"),_T("&Stop"),_T(""));
11271100 LangMenu->Append (ID_LangMenu_DebugSendCommand,_T (" &Send Debugger Command" ),_T (" " ));
1128- LangMenu->Append (ID_LangMenu_ShowWatch,_T (" Toggle &Watch" ),_T (" " ),wxITEM_CHECK);
1129- LangMenu->Append (ID_LangMenu_UpdateWatch,_T (" &Update Watch" ),_T (" " ));
1101+ // LangMenu->Append(ID_LangMenu_ShowWatch,_T("Toggle &Watch"),_T(""),wxITEM_CHECK);
1102+ // LangMenu->Append(ID_LangMenu_UpdateWatch,_T("&Update Watch"),_T(""));
11301103}
11311104
11321105
0 commit comments