@ -24,7 +24,7 @@ namespace sigc {
# endif
}
Window : : Window ( ) : compiling ( false ) , debugging ( false ) {
Window : : Window ( ) {
JDEBUG ( " start " ) ;
set_title ( " juCi++ " ) ;
set_events ( Gdk : : POINTER_MOTION_MASK | Gdk : : FOCUS_CHANGE_MASK | Gdk : : SCROLL_MASK | Gdk : : LEAVE_NOTIFY_MASK ) ;
@ -203,22 +203,6 @@ Window::Window() : compiling(false), debugging(false) {
JDEBUG ( " end " ) ;
} // Window constructor
std : : unique_ptr < CMake > Window : : get_cmake ( ) {
boost : : filesystem : : path path ;
if ( notebook . get_current_page ( ) ! = - 1 )
path = notebook . get_current_view ( ) - > file_path . parent_path ( ) ;
else
path = Directories : : get ( ) . current_path ;
if ( path . empty ( ) )
return nullptr ;
auto cmake = std : : unique_ptr < CMake > ( new CMake ( path ) ) ;
if ( cmake - > project_path . empty ( ) )
return nullptr ;
if ( ! CMake : : create_default_build ( cmake - > project_path ) )
return nullptr ;
return cmake ;
}
void Window : : configure ( ) {
Config : : get ( ) . load ( ) ;
auto style_context = Gtk : : StyleContext : : create ( ) ;
@ -672,32 +656,10 @@ void Window::set_menu_actions() {
# ifdef JUCI_ENABLE_DEBUG
menu . add_action ( " debug_set_run_arguments " , [ this ] ( ) {
auto cmake = get_cmake ( ) ;
if ( ! cmake )
project = notebook . get_project ( ) ;
auto run_arguments = std : : make_shared < std : : pair < std : : string , std : : string > > ( project - > debug_get_run_arguments ( ) ) ;
if ( run_arguments - > second . empty ( ) )
return ;
auto project_path = std : : make_shared < boost : : filesystem : : path > ( cmake - > project_path ) ;
auto run_arguments_it = debug_run_arguments . find ( project_path - > string ( ) ) ;
std : : string run_arguments ;
if ( run_arguments_it ! = debug_run_arguments . end ( ) )
run_arguments = run_arguments_it - > second ;
if ( run_arguments . empty ( ) ) {
auto executable = cmake - > get_executable ( notebook . get_current_page ( ) ! = - 1 ? notebook . get_current_view ( ) - > file_path : " " ) . string ( ) ;
if ( executable ! = " " ) {
auto project_path = cmake - > project_path ;
auto debug_build_path = CMake : : get_debug_build_path ( project_path ) ;
if ( ! debug_build_path . empty ( ) ) {
size_t pos = executable . find ( project_path . string ( ) ) ;
if ( pos ! = std : : string : : npos )
executable . replace ( pos , project_path . string ( ) . size ( ) , debug_build_path . string ( ) ) ;
}
run_arguments = filesystem : : escape_argument ( executable ) ;
}
else
run_arguments = filesystem : : escape_argument ( CMake : : get_debug_build_path ( cmake - > project_path ) ) ;
}
entry_box . clear ( ) ;
entry_box . labels . emplace_back ( ) ;
@ -706,258 +668,76 @@ void Window::set_menu_actions() {
label_it - > set_text ( " Set empty to let juCi++ deduce executable " ) ;
} ;
label_it - > update ( 0 , " " ) ;
entry_box . entries . emplace_back ( run_arguments , [ this , project_path ] ( const std : : string & content ) {
debug_run_arguments [ project_path - > string ( ) ] = content ;
entry_box . entries . emplace_back ( run_arguments - > second , [ this , run_arguments ] ( const std : : string & content ) {
Project : : debug_run_arguments [ run_arguments - > first ] = content ;
entry_box . hide ( ) ;
} , 50 ) ;
auto entry_it = entry_box . entries . begin ( ) ;
entry_it - > set_placeholder_text ( " Project : Set Run Arguments" ) ;
entry_box . buttons . emplace_back ( " Project : set run arguments" , [ this , entry_it ] ( ) {
entry_it - > set_placeholder_text ( " Debug : Set Run Arguments" ) ;
entry_box . buttons . emplace_back ( " Debug : set run arguments" , [ this , entry_it ] ( ) {
entry_it - > activate ( ) ;
} ) ;
entry_box . show ( ) ;
} ) ;
menu . add_action ( " debug_start_continue " , [ this ] ( ) {
if ( debugging ) {
Debug : : get ( ) . continue_debug ( ) ;
if ( Project : : debugging ) {
project - > debug_continue ( ) ;
return ;
}
if ( Config : : get ( ) . window . save_on_compile_or_run )
notebook . save_project_files ( ) ;
auto cmake = get_cmake ( ) ;
if ( ! cmake )
return ;
auto project_path = cmake - > project_path ;
auto debug_build_path = CMake : : get_debug_build_path ( project_path ) ;
if ( debug_build_path . empty ( ) )
return ;
if ( ! CMake : : create_debug_build ( project_path ) )
return ;
auto run_arguments_it = debug_run_arguments . find ( project_path . string ( ) ) ;
std : : string run_arguments ;
if ( run_arguments_it ! = debug_run_arguments . end ( ) )
run_arguments = run_arguments_it - > second ;
std : : string command ;
if ( ! run_arguments . empty ( ) ) {
command = run_arguments ;
}
else {
command = cmake - > get_executable ( notebook . get_current_page ( ) ! = - 1 ? notebook . get_current_view ( ) - > file_path : " " ) . string ( ) ;
if ( command . empty ( ) ) {
Terminal : : get ( ) . print ( " Could not find add_executable in the following paths: \n " ) ;
for ( auto & path : cmake - > paths )
Terminal : : get ( ) . print ( " " + path . string ( ) + " \n " ) ;
Terminal : : get ( ) . print ( " Solution: either use Debug Set Run Arguments, or open a source file within a directory where add_executable is set. \n " , true ) ;
return ;
}
size_t pos = command . find ( project_path . string ( ) ) ;
if ( pos ! = std : : string : : npos )
command . replace ( pos , project_path . string ( ) . size ( ) , debug_build_path . string ( ) ) ;
command = filesystem : : escape_argument ( command ) ;
}
auto breakpoints = std : : make_shared < std : : vector < std : : pair < boost : : filesystem : : path , int > > > ( ) ;
for ( int c = 0 ; c < notebook . size ( ) ; c + + ) {
auto view = notebook . get_view ( c ) ;
if ( project_path = = view - > project_path ) {
auto iter = view - > get_buffer ( ) - > begin ( ) ;
if ( view - > get_source_buffer ( ) - > get_source_marks_at_iter ( iter , " debug_breakpoint " ) . size ( ) > 0 )
breakpoints - > emplace_back ( view - > file_path , iter . get_line ( ) + 1 ) ;
while ( view - > get_source_buffer ( ) - > forward_iter_to_source_mark ( iter , " debug_breakpoint " ) )
breakpoints - > emplace_back ( view - > file_path , iter . get_line ( ) + 1 ) ;
}
}
project = notebook . get_project ( ) ;
debugging = true ;
Terminal : : get ( ) . print ( " Compiling and debugging " + command + " \n " ) ;
Terminal : : get ( ) . async_process ( Config : : get ( ) . terminal . make_command , debug_build_path , [ this , breakpoints , command , debug_build_path ] ( int exit_status ) {
if ( exit_status ! = EXIT_SUCCESS )
debugging = false ;
else {
debug_start_mutex . lock ( ) ;
Debug : : get ( ) . start ( command , debug_build_path , breakpoints , [ this , command ] ( int exit_status ) {
debugging = false ;
Terminal : : get ( ) . async_print ( command + " returned: " + std : : to_string ( exit_status ) + ' \n ' ) ;
} , [ this ] ( const std : : string & status ) {
debug_status_mutex . lock ( ) ;
debug_status = status ;
debug_status_mutex . unlock ( ) ;
debug_update_status ( ) ;
} , [ this ] ( const boost : : filesystem : : path & file_path , int line_nr , int line_index ) {
debug_stop_mutex . lock ( ) ;
debug_stop . first = file_path ;
debug_stop . second . first = line_nr ;
debug_stop . second . second = line_index ;
debug_stop_mutex . unlock ( ) ;
debug_update_stop ( ) ;
//Remove debug stop source mark
} ) ;
debug_start_mutex . unlock ( ) ;
}
project - > debug_start ( [ this ] ( const std : : string & status ) {
debug_status_mutex . lock ( ) ;
debug_status = status ;
debug_status_mutex . unlock ( ) ;
debug_update_status ( ) ;
} , [ this ] ( const boost : : filesystem : : path & file_path , int line_nr , int line_index ) {
debug_stop_mutex . lock ( ) ;
debug_stop . first = file_path ;
debug_stop . second . first = line_nr ;
debug_stop . second . second = line_index ;
debug_stop_mutex . unlock ( ) ;
debug_update_stop ( ) ;
} ) ;
} ) ;
menu . add_action ( " debug_stop " , [ this ] ( ) {
if ( debugging ) {
Debug : : get ( ) . stop ( ) ;
}
if ( project )
project - > debug_stop ( ) ;
} ) ;
menu . add_action ( " debug_kill " , [ this ] ( ) {
if ( debugging ) {
Debug : : get ( ) . kill ( ) ;
}
if ( project )
project - > debug_kill ( ) ;
} ) ;
menu . add_action ( " debug_step_over " , [ this ] ( ) {
if ( debugging )
Debug : : get ( ) . step_over ( ) ;
if ( project )
project - > debug_step_over ( ) ;
} ) ;
menu . add_action ( " debug_step_into " , [ this ] ( ) {
if ( debugging )
Debug : : get ( ) . step_into ( ) ;
if ( project )
project - > debug_step_into ( ) ;
} ) ;
menu . add_action ( " debug_step_out " , [ this ] ( ) {
if ( debugging )
Debug : : get ( ) . step_out ( ) ;
if ( project )
project - > debug_step_out ( ) ;
} ) ;
menu . add_action ( " debug_backtrace " , [ this ] ( ) {
if ( debugging & & notebook . get_current_page ( ) ! = - 1 ) {
auto backtrace = Debug : : get ( ) . get_backtrace ( ) ;
auto view = notebook . get_current_view ( ) ;
auto iter = view - > get_iter_for_dialog ( ) ;
view - > selection_dialog = std : : unique_ptr < SelectionDialog > ( new SelectionDialog ( * view , view - > get_buffer ( ) - > create_mark ( iter ) , true , true ) ) ;
auto rows = std : : make_shared < std : : unordered_map < std : : string , Debug : : Frame > > ( ) ;
if ( backtrace . size ( ) = = 0 )
return ;
for ( auto & frame : backtrace ) {
std : : string row = " <i> " + frame . module_filename + " </i> " ;
//Shorten frame.function_name if it is too long
if ( frame . function_name . size ( ) > 120 ) {
frame . function_name = frame . function_name . substr ( 0 , 58 ) + " .... " + frame . function_name . substr ( frame . function_name . size ( ) - 58 ) ;
}
if ( frame . file_path . empty ( ) )
row + = " - " + Glib : : Markup : : escape_text ( frame . function_name ) ;
else {
auto file_path = boost : : filesystem : : path ( frame . file_path ) . filename ( ) . string ( ) ;
row + = " :<b> " + Glib : : Markup : : escape_text ( file_path ) + " : " + std : : to_string ( frame . line_nr ) + " </b> - " + Glib : : Markup : : escape_text ( frame . function_name ) ;
}
( * rows ) [ row ] = frame ;
view - > selection_dialog - > add_row ( row ) ;
}
view - > selection_dialog - > on_select = [ this , rows ] ( const std : : string & selected , bool hide_window ) {
auto frame = rows - > at ( selected ) ;
if ( ! frame . file_path . empty ( ) ) {
notebook . open ( frame . file_path ) ;
if ( notebook . get_current_page ( ) ! = - 1 ) {
auto view = notebook . get_current_view ( ) ;
Debug : : get ( ) . select_frame ( frame . index ) ;
view - > get_buffer ( ) - > place_cursor ( view - > get_buffer ( ) - > get_iter_at_line_index ( frame . line_nr - 1 , frame . line_index - 1 ) ) ;
while ( g_main_context_pending ( NULL ) )
g_main_context_iteration ( NULL , false ) ;
if ( notebook . get_current_page ( ) ! = - 1 & & notebook . get_current_view ( ) = = view )
view - > scroll_to ( view - > get_buffer ( ) - > get_insert ( ) , 0.0 , 1.0 , 0.5 ) ;
}
}
} ;
view - > selection_dialog - > show ( ) ;
}
if ( project )
project - > debug_backtrace ( ) ;
} ) ;
menu . add_action ( " debug_show_variables " , [ this ] ( ) {
if ( debugging & & notebook . get_current_page ( ) ! = - 1 ) {
auto variables = Debug : : get ( ) . get_variables ( ) ;
auto view = notebook . get_current_view ( ) ;
auto iter = view - > get_iter_for_dialog ( ) ;
view - > selection_dialog = std : : unique_ptr < SelectionDialog > ( new SelectionDialog ( * view , view - > get_buffer ( ) - > create_mark ( iter ) , true , true ) ) ;
auto rows = std : : make_shared < std : : unordered_map < std : : string , Debug : : Variable > > ( ) ;
if ( variables . size ( ) = = 0 )
return ;
for ( auto & variable : variables ) {
std : : string row = " # " + std : : to_string ( variable . thread_index_id ) + " :# " + std : : to_string ( variable . frame_index ) + " : " + variable . file_path . filename ( ) . string ( ) + " : " + std : : to_string ( variable . line_nr ) + " - <b> " + Glib : : Markup : : escape_text ( variable . name ) + " </b> " ;
( * rows ) [ row ] = variable ;
view - > selection_dialog - > add_row ( row ) ;
}
view - > selection_dialog - > on_select = [ this , rows ] ( const std : : string & selected , bool hide_window ) {
auto variable = rows - > at ( selected ) ;
if ( ! variable . file_path . empty ( ) ) {
notebook . open ( variable . file_path ) ;
if ( notebook . get_current_page ( ) ! = - 1 ) {
auto view = notebook . get_current_view ( ) ;
Debug : : get ( ) . select_frame ( variable . frame_index , variable . thread_index_id ) ;
view - > get_buffer ( ) - > place_cursor ( view - > get_buffer ( ) - > get_iter_at_line_index ( variable . line_nr - 1 , variable . line_index - 1 ) ) ;
while ( g_main_context_pending ( NULL ) )
g_main_context_iteration ( NULL , false ) ;
if ( notebook . get_current_page ( ) ! = - 1 & & notebook . get_current_view ( ) = = view )
view - > scroll_to ( view - > get_buffer ( ) - > get_insert ( ) , 0.0 , 1.0 , 0.5 ) ;
}
}
} ;
view - > selection_dialog - > on_hide = [ this ] ( ) {
debug_variable_tooltips . hide ( ) ;
debug_variable_tooltips . clear ( ) ;
} ;
view - > selection_dialog - > on_changed = [ this , rows , iter ] ( const std : : string & selected ) {
if ( selected . empty ( ) ) {
debug_variable_tooltips . hide ( ) ;
return ;
}
if ( notebook . get_current_page ( ) ! = - 1 ) {
auto view = notebook . get_current_view ( ) ;
debug_variable_tooltips . clear ( ) ;
auto create_tooltip_buffer = [ this , rows , view , selected ] ( ) {
auto variable = rows - > at ( selected ) ;
auto tooltip_buffer = Gtk : : TextBuffer : : create ( view - > get_buffer ( ) - > get_tag_table ( ) ) ;
Glib : : ustring value = variable . value ;
if ( ! value . empty ( ) ) {
Glib : : ustring : : iterator iter ;
while ( ! value . validate ( iter ) ) {
auto next_char_iter = iter ;
next_char_iter + + ;
value . replace ( iter , next_char_iter , " ? " ) ;
}
tooltip_buffer - > insert_with_tag ( tooltip_buffer - > get_insert ( ) - > get_iter ( ) , value . substr ( 0 , value . size ( ) - 1 ) , " def:note " ) ;
}
return tooltip_buffer ;
} ;
debug_variable_tooltips . emplace_back ( create_tooltip_buffer , * view , view - > get_buffer ( ) - > create_mark ( iter ) , view - > get_buffer ( ) - > create_mark ( iter ) ) ;
debug_variable_tooltips . show ( true ) ;
}
} ;
view - > selection_dialog - > show ( ) ;
}
if ( project )
project - > debug_show_variables ( ) ;
} ) ;
menu . add_action ( " debug_run_command " , [ this ] ( ) {
entry_box . clear ( ) ;
entry_box . entries . emplace_back ( last_run_debug_command , [ this ] ( const std : : string & content ) {
if ( content ! = " " ) {
if ( debugging ) {
auto command_return = Debug : : get ( ) . run_command ( content ) ;
Terminal : : get ( ) . async_print ( command_return . first ) ;
Terminal : : get ( ) . async_print ( command_return . second , true ) ;
}
if ( project )
project - > debug_run_command ( content ) ;
last_run_debug_command = content ;
}
entry_box . hide ( ) ;
@ -993,7 +773,7 @@ void Window::set_menu_actions() {
}
} ) ;
menu . add_action ( " debug_goto_stop " , [ this ] ( ) {
if ( debugging ) {
if ( project & & project - > debugging ) {
debug_stop_mutex . lock ( ) ;
auto debug_stop_copy = debug_stop ;
debug_stop_mutex . unlock ( ) ;
@ -1119,9 +899,8 @@ bool Window::on_delete_event(GdkEventAny *event) {
}
Terminal : : get ( ) . kill_async_processes ( ) ;
# ifdef JUCI_ENABLE_DEBUG
debug_start_mutex . lock ( ) ;
Debug : : get ( ) . delete_debug ( ) ;
debug_start_mutex . unlock ( ) ;
if ( project )
project - > debug_delete ( ) ;
# endif
return false ;
}