2017-01-29 00:03:23 +00:00
/*
2017-11-09 18:30:24 +00:00
4 coder_project_commands . cpp - commands for loading and using a project .
2017-01-29 00:03:23 +00:00
2017-11-09 18:30:24 +00:00
type : ' drop - in - command - pack '
2017-01-29 00:03:23 +00:00
*/
2017-11-09 18:30:24 +00:00
// top
2017-01-29 00:03:23 +00:00
2017-11-09 18:30:24 +00:00
# if !defined(fcoder_project_commands_cpp)
# define fcoder_project_commands_cpp
2017-01-29 00:03:23 +00:00
# include "4coder_default_framework.h"
# include "4coder_lib/4coder_mem.h"
# include "4coder_build_commands.cpp"
2017-11-09 18:30:24 +00:00
// TODO(allen): Make this a string operation or a lexer operation or something
2017-01-29 00:03:23 +00:00
static void
interpret_escaped_string ( char * dst , String src ) {
int32_t mode = 0 ;
int32_t j = 0 ;
for ( int32_t i = 0 ; i < src . size ; + + i ) {
switch ( mode ) {
case 0 :
{
if ( src . str [ i ] = = ' \\ ' ) {
mode = 1 ;
}
else {
dst [ j + + ] = src . str [ i ] ;
}
} break ;
case 1 :
{
switch ( src . str [ i ] ) {
case ' \\ ' : { dst [ j + + ] = ' \\ ' ; mode = 0 ; } break ;
case ' n ' : { dst [ j + + ] = ' \n ' ; mode = 0 ; } break ;
case ' t ' : { dst [ j + + ] = ' \t ' ; mode = 0 ; } break ;
case ' " ' : { dst [ j + + ] = ' " ' ; mode = 0 ; } break ;
case ' 0 ' : { dst [ j + + ] = ' \0 ' ; mode = 0 ; } break ;
}
} break ;
}
}
dst [ j ] = 0 ;
}
2017-11-09 18:30:24 +00:00
///////////////////////////////
2017-01-29 00:03:23 +00:00
static void
close_all_files_with_extension ( Application_Links * app , Partition * scratch_part , char * * extension_list , int32_t extension_count ) {
Temp_Memory temp = begin_temp_memory ( scratch_part ) ;
2017-03-23 19:16:39 +00:00
int32_t buffers_to_close_max = partition_remaining ( scratch_part ) / sizeof ( int32_t ) ;
2017-01-29 00:03:23 +00:00
int32_t * buffers_to_close = push_array ( scratch_part , int32_t , buffers_to_close_max ) ;
int32_t buffers_to_close_count = 0 ;
bool32 do_repeat = 0 ;
do {
buffers_to_close_count = 0 ;
do_repeat = 0 ;
uint32_t access = AccessAll ;
Buffer_Summary buffer = { 0 } ;
for ( buffer = get_buffer_first ( app , access ) ;
buffer . exists ;
get_buffer_next ( app , & buffer , access ) ) {
bool32 is_match = 1 ;
if ( extension_count > 0 ) {
is_match = 0 ;
2017-02-12 06:01:01 +00:00
if ( buffer . file_name ! = 0 ) {
String extension = file_extension ( make_string ( buffer . file_name , buffer . file_name_len ) ) ;
for ( int32_t i = 0 ; i < extension_count ; + + i ) {
if ( match ( extension , extension_list [ i ] ) ) {
is_match = 1 ;
break ;
}
2017-01-29 00:03:23 +00:00
}
}
}
if ( is_match ) {
if ( buffers_to_close_count > = buffers_to_close_max ) {
do_repeat = 1 ;
break ;
}
buffers_to_close [ buffers_to_close_count + + ] = buffer . buffer_id ;
}
}
for ( int32_t i = 0 ; i < buffers_to_close_count ; + + i ) {
kill_buffer ( app , buffer_identifier ( buffers_to_close [ i ] ) , true , 0 ) ;
}
2017-11-09 18:30:24 +00:00
} while ( do_repeat ) ;
2017-01-29 00:03:23 +00:00
end_temp_memory ( temp ) ;
}
static void
2017-02-06 13:49:00 +00:00
open_all_files_with_extension_internal ( Application_Links * app , String dir , char * * extension_list , int32_t extension_count , bool32 recursive ) {
2017-01-29 00:03:23 +00:00
File_List list = get_file_list ( app , dir . str , dir . size ) ;
2017-02-06 13:49:00 +00:00
int32_t dir_size = dir . size ;
2017-01-29 00:03:23 +00:00
2017-03-23 22:45:32 +00:00
for ( uint32_t i = 0 ; i < list . count ; + + i ) {
2017-01-29 00:03:23 +00:00
File_Info * info = list . infos + i ;
2017-02-06 13:49:00 +00:00
if ( info - > folder ) {
2017-07-03 15:59:39 +00:00
if ( recursive & & info - > filename [ 0 ] ! = ' . ' ) {
2017-02-06 13:49:00 +00:00
dir . size = dir_size ;
2017-03-23 19:15:05 +00:00
append ( & dir , info - > filename ) ;
2017-02-06 13:49:00 +00:00
append ( & dir , " / " ) ;
open_all_files_with_extension_internal ( app , dir , extension_list , extension_count , recursive ) ;
}
}
else {
bool32 is_match = true ;
2017-01-29 00:03:23 +00:00
if ( extension_count > 0 ) {
2017-02-06 13:49:00 +00:00
is_match = false ;
2017-01-29 00:03:23 +00:00
String extension = make_string_cap ( info - > filename , info - > filename_len , info - > filename_len + 1 ) ;
extension = file_extension ( extension ) ;
for ( int32_t j = 0 ; j < extension_count ; + + j ) {
if ( match ( extension , extension_list [ j ] ) ) {
2017-02-06 13:49:00 +00:00
is_match = true ;
2017-01-29 00:03:23 +00:00
break ;
}
}
2017-02-06 13:49:00 +00:00
}
if ( is_match ) {
dir . size = dir_size ;
2017-03-23 19:15:05 +00:00
append ( & dir , info - > filename ) ;
2017-02-06 13:49:00 +00:00
create_buffer ( app , dir . str , dir . size , 0 ) ;
2017-01-29 00:03:23 +00:00
}
}
}
free_file_list ( app , list ) ;
2017-02-06 13:49:00 +00:00
}
static void
open_all_files_with_extension ( Application_Links * app , Partition * scratch_part , char * * extension_list , int32_t extension_count , bool32 recursive ) {
Temp_Memory temp = begin_temp_memory ( scratch_part ) ;
int32_t max_size = 4096 ;
char * memory = push_array ( scratch_part , char , max_size ) ;
String dir = make_string_cap ( memory , 0 , max_size ) ;
dir . size = directory_get_hot ( app , dir . str , dir . memory_size ) ;
open_all_files_with_extension_internal ( app , dir , extension_list , extension_count , recursive ) ;
2017-01-29 00:03:23 +00:00
end_temp_memory ( temp ) ;
}
// NOTE(allen|a4.0.14): open_all_code and close_all_code now use the extensions set in the loaded project. If there is no project loaded the extensions ".cpp.hpp.c.h.cc" are used.
2017-03-27 22:36:42 +00:00
static void
open_all_code ( Application_Links * app , String dir ) {
int32_t extension_count = 0 ;
char * * extension_list = get_current_project_extensions ( & extension_count ) ;
open_all_files_with_extension_internal ( app , dir , extension_list , extension_count , false ) ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( open_all_code )
CUSTOM_DOC ( " Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config. " )
{
2017-01-29 00:03:23 +00:00
int32_t extension_count = 0 ;
2017-02-26 21:44:40 +00:00
char * * extension_list = get_current_project_extensions ( & extension_count ) ;
2017-02-06 13:49:00 +00:00
open_all_files_with_extension ( app , & global_part , extension_list , extension_count , false ) ;
}
2017-03-27 22:36:42 +00:00
static void
open_all_code_recursive ( Application_Links * app , String dir ) {
int32_t extension_count = 0 ;
char * * extension_list = get_current_project_extensions ( & extension_count ) ;
open_all_files_with_extension_internal ( app , dir , extension_list , extension_count , true ) ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( open_all_code_recursive )
CUSTOM_DOC ( " Works as open_all_code but also runs in all subdirectories. " )
{
2017-02-06 13:49:00 +00:00
int32_t extension_count = 0 ;
2017-02-26 21:44:40 +00:00
char * * extension_list = get_current_project_extensions ( & extension_count ) ;
2017-02-06 13:49:00 +00:00
open_all_files_with_extension ( app , & global_part , extension_list , extension_count , true ) ;
2017-01-29 00:03:23 +00:00
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( close_all_code )
CUSTOM_DOC ( " Closes any buffer with a filename ending with an extension configured to be recognized as a code file type. " )
{
2017-01-29 00:03:23 +00:00
int32_t extension_count = 0 ;
2017-02-26 21:44:40 +00:00
char * * extension_list = get_current_project_extensions ( & extension_count ) ;
2017-01-29 00:03:23 +00:00
close_all_files_with_extension ( app , & global_part , extension_list , extension_count ) ;
}
2017-11-09 18:30:24 +00:00
///////////////////////////////
2017-03-27 22:36:42 +00:00
static void
2017-06-20 20:37:45 +00:00
load_project_from_config_data ( Application_Links * app , Partition * part , char * config_data , int32_t config_data_size , String project_dir ) {
2017-03-27 22:36:42 +00:00
Temp_Memory temp = begin_temp_memory ( part ) ;
2017-01-29 00:03:23 +00:00
2017-06-20 20:37:45 +00:00
char * mem = config_data ;
int32_t size = config_data_size ;
Cpp_Token_Array array ;
array . count = 0 ;
array . max_count = ( 1 < < 20 ) / sizeof ( Cpp_Token ) ;
array . tokens = push_array ( part , Cpp_Token , array . max_count ) ;
Cpp_Keyword_Table kw_table = { 0 } ;
Cpp_Keyword_Table pp_table = { 0 } ;
lexer_keywords_default_init ( part , & kw_table , & pp_table ) ;
Cpp_Lex_Data S = cpp_lex_data_init ( false , kw_table , pp_table ) ;
2017-11-15 00:06:00 +00:00
Cpp_Lex_Result result = cpp_lex_step ( & S , mem , size + 1 , HAS_NULL_TERM , & array , NO_OUT_LIMIT ) ;
2017-06-20 20:37:45 +00:00
if ( result = = LexResult_Finished ) {
// Clear out current project
if ( current_project . close_all_code_when_this_project_closes ) {
exec_command ( app , close_all_code ) ;
}
current_project = null_project ;
current_project . loaded = true ;
2017-05-19 23:55:50 +00:00
2017-06-20 20:37:45 +00:00
// Set new project directory
{
current_project . dir = current_project . dir_space ;
String str = make_fixed_width_string ( current_project . dir_space ) ;
copy ( & str , project_dir ) ;
terminate_with_null ( & str ) ;
current_project . dir_len = str . size ;
}
2017-03-27 22:36:42 +00:00
2017-06-20 20:37:45 +00:00
// Read the settings from project.4coder
for ( int32_t i = 0 ; i < array . count ; + + i ) {
2017-11-15 00:06:00 +00:00
Config_Line config_line = read_config_line ( array , & i , mem ) ;
2017-06-20 20:37:45 +00:00
if ( config_line . read_success ) {
Config_Item item = get_config_item ( config_line , mem , array ) ;
{
char str_space [ 512 ] ;
String str = make_fixed_width_string ( str_space ) ;
if ( config_string_var ( item , " extensions " , 0 , & str ) ) {
if ( str . size < sizeof ( current_project . extension_list . extension_space ) ) {
set_extensions ( & current_project . extension_list , str ) ;
print_message ( app , str . str , str . size ) ;
print_message ( app , " \n " , 1 ) ;
2017-03-27 22:36:42 +00:00
}
2017-06-20 20:37:45 +00:00
else {
print_message ( app , literal ( " STRING TOO LONG! \n " ) ) ;
2017-03-27 22:36:42 +00:00
}
2017-01-29 00:03:23 +00:00
}
2017-06-20 20:37:45 +00:00
}
{
bool32 open_recursively = false ;
if ( config_bool_var ( item , " open_recursively " , 0 , & open_recursively ) ) {
current_project . open_recursively = open_recursively ;
}
}
{
2017-11-21 21:30:40 +00:00
# if defined(IS_WINDOWS)
2017-06-27 02:47:00 +00:00
# define FKEY_COMMAND "fkey_command_win"
2017-11-21 21:30:40 +00:00
# elif defined(IS_LINUX)
2017-06-27 02:47:00 +00:00
# define FKEY_COMMAND "fkey_command_linux"
2017-11-21 21:30:40 +00:00
# elif defined(IS_MAC)
2017-06-27 02:47:00 +00:00
# define FKEY_COMMAND "fkey_command_mac"
2017-01-29 00:03:23 +00:00
# else
2017-06-27 02:47:00 +00:00
# error no project configuration names for this platform
2017-01-29 00:03:23 +00:00
# endif
2017-06-20 20:37:45 +00:00
int32_t index = 0 ;
Config_Array_Reader array_reader = { 0 } ;
if ( config_array_var ( item , FKEY_COMMAND , & index , & array_reader ) ) {
if ( index > = 1 & & index < = 16 ) {
Config_Item array_item = { 0 } ;
int32_t item_index = 0 ;
char space [ 256 ] ;
String msg = make_fixed_width_string ( space ) ;
append ( & msg , FKEY_COMMAND " [ " ) ;
append_int_to_str ( & msg , index ) ;
append ( & msg , " ] = { " ) ;
for ( config_array_next_item ( & array_reader , & array_item ) ;
config_array_good ( & array_reader ) ;
config_array_next_item ( & array_reader , & array_item ) ) {
2017-03-27 22:36:42 +00:00
2017-06-20 20:37:45 +00:00
if ( item_index > = 4 ) {
break ;
}
2017-01-29 00:03:23 +00:00
2017-06-20 20:37:45 +00:00
append ( & msg , " [ " ) ;
append_int_to_str ( & msg , item_index ) ;
append ( & msg , " ] = " ) ;
bool32 read_string = false ;
bool32 read_bool = false ;
char * dest_str = 0 ;
int32_t dest_str_size = 0 ;
bool32 * dest_bool = 0 ;
switch ( item_index ) {
case 0 :
{
dest_str = current_project . fkey_commands [ index - 1 ] . command ;
dest_str_size = sizeof ( current_project . fkey_commands [ index - 1 ] . command ) ;
read_string = true ;
} break ;
2017-03-27 22:36:42 +00:00
2017-06-20 20:37:45 +00:00
case 1 :
{
dest_str = current_project . fkey_commands [ index - 1 ] . out ;
dest_str_size = sizeof ( current_project . fkey_commands [ index - 1 ] . out ) ;
read_string = true ;
} break ;
2017-03-27 22:36:42 +00:00
2017-06-20 20:37:45 +00:00
case 2 :
{
dest_bool = & current_project . fkey_commands [ index - 1 ] . use_build_panel ;
read_bool = true ;
} break ;
2017-03-27 22:36:42 +00:00
2017-06-20 20:37:45 +00:00
case 3 :
{
dest_bool = & current_project . fkey_commands [ index - 1 ] . save_dirty_buffers ;
read_bool = true ;
} break ;
}
if ( read_string ) {
if ( config_int_var ( array_item , 0 , 0 , 0 ) ) {
append ( & msg , " NULL, " ) ;
dest_str [ 0 ] = 0 ;
2017-03-27 22:36:42 +00:00
}
2017-06-20 20:37:45 +00:00
char str_space [ 512 ] ;
String str = make_fixed_width_string ( str_space ) ;
if ( config_string_var ( array_item , 0 , 0 , & str ) ) {
if ( str . size < dest_str_size ) {
interpret_escaped_string ( dest_str , str ) ;
append ( & msg , dest_str ) ;
append ( & msg , " , " ) ;
2017-03-27 22:36:42 +00:00
}
2017-06-20 20:37:45 +00:00
else {
append ( & msg , " STRING TOO LONG!, " ) ;
2017-03-27 22:36:42 +00:00
}
}
2017-06-20 20:37:45 +00:00
}
if ( read_bool ) {
if ( config_bool_var ( array_item , 0 , 0 , dest_bool ) ) {
if ( * dest_bool ) {
append ( & msg , " true, " ) ;
}
else {
append ( & msg , " false, " ) ;
2017-01-29 00:03:23 +00:00
}
}
}
2017-03-27 22:36:42 +00:00
2017-06-20 20:37:45 +00:00
item_index + + ;
2017-01-29 00:03:23 +00:00
}
2017-06-20 20:37:45 +00:00
append ( & msg , " } \n " ) ;
print_message ( app , msg . str , msg . size ) ;
2017-01-29 00:03:23 +00:00
}
}
}
}
2017-11-15 00:06:00 +00:00
else if ( config_line . error_str . str ! = 0 ) {
char space [ 2048 ] ;
String str = make_fixed_width_string ( space ) ;
copy ( & str , " WARNING: bad syntax in 4coder.config at " ) ;
append ( & str , config_line . error_str ) ;
append ( & str , " \n " ) ;
print_message ( app , str . str , str . size ) ;
}
2017-06-20 20:37:45 +00:00
}
if ( current_project . close_all_files_when_project_opens ) {
close_all_files_with_extension ( app , part , 0 , 0 ) ;
}
// Open all project files
if ( current_project . open_recursively ) {
open_all_code_recursive ( app , project_dir ) ;
}
else {
open_all_code ( app , project_dir ) ;
2017-01-29 00:03:23 +00:00
}
2017-11-30 16:39:35 +00:00
// Set window title
char space [ 1024 ] ;
String builder = make_fixed_width_string ( space ) ;
append ( & builder , " 4coder: " ) ;
append ( & builder , project_dir ) ;
terminate_with_null ( & builder ) ;
//set_title(app, builder.str);
2017-03-27 22:36:42 +00:00
}
end_temp_memory ( temp ) ;
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( load_project )
CUSTOM_DOC ( " Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents. " )
{
2017-11-21 18:25:19 +00:00
save_all_dirty_buffers ( app ) ;
2017-03-27 22:36:42 +00:00
Partition * part = & global_part ;
2017-06-20 20:37:45 +00:00
Temp_Memory temp = begin_temp_memory ( part ) ;
2017-03-27 22:36:42 +00:00
char project_file_space [ 512 ] ;
2017-11-21 18:25:19 +00:00
String project_path = make_fixed_width_string ( project_file_space ) ;
project_path . size = directory_get_hot ( app , project_path . str , project_path . memory_size ) ;
if ( project_path . size > = project_path . memory_size ) {
project_path . size = 0 ;
2017-03-27 22:36:42 +00:00
}
2017-11-21 18:25:19 +00:00
if ( project_path . size ! = 0 ) {
2017-03-27 22:36:42 +00:00
bool32 load_failed = false ;
for ( ; ; ) {
2017-11-21 18:25:19 +00:00
int32_t original_size = project_path . size ;
append_sc ( & project_path , " project.4coder " ) ;
terminate_with_null ( & project_path ) ;
2017-03-27 22:36:42 +00:00
2017-11-21 18:25:19 +00:00
FILE * file = fopen ( project_path . str , " rb " ) ;
if ( file ! = 0 ) {
project_path . size = original_size ;
terminate_with_null ( & project_path ) ;
2017-06-20 20:37:45 +00:00
char * mem = 0 ;
int32_t size = 0 ;
bool32 file_read_success = file_handle_dump ( part , file , & mem , & size ) ;
2017-03-27 22:36:42 +00:00
fclose ( file ) ;
2017-06-20 20:37:45 +00:00
if ( file_read_success ) {
2017-11-21 18:25:19 +00:00
load_project_from_config_data ( app , part , mem , size , project_path ) ;
2017-06-20 20:37:45 +00:00
}
2017-03-27 22:36:42 +00:00
break ;
}
else {
2017-11-21 18:25:19 +00:00
project_path . size = original_size ;
remove_last_folder ( & project_path ) ;
2017-03-27 22:36:42 +00:00
2017-11-21 18:25:19 +00:00
if ( project_path . size > = original_size ) {
2017-03-27 22:36:42 +00:00
load_failed = true ;
break ;
}
}
}
if ( load_failed ) {
2017-01-29 00:03:23 +00:00
char message_space [ 512 ] ;
String message = make_fixed_width_string ( message_space ) ;
append_sc ( & message , " Did not find project.4coder. " ) ;
if ( current_project . dir ! = 0 ) {
append_sc ( & message , " Continuing with: " ) ;
append_sc ( & message , current_project . dir ) ;
}
else {
append_sc ( & message , " Continuing without a project " ) ;
}
2017-03-27 22:36:42 +00:00
append_s_char ( & message , ' \n ' ) ;
2017-01-29 00:03:23 +00:00
print_message ( app , message . str , message . size ) ;
}
}
else {
print_message ( app , literal ( " Failed trying to get project file name " ) ) ;
}
2017-06-20 20:37:45 +00:00
end_temp_memory ( temp ) ;
2017-01-29 00:03:23 +00:00
}
2017-11-21 18:25:19 +00:00
CUSTOM_COMMAND_SIG ( reload_current_project )
CUSTOM_DOC ( " If a project file has already been loaded, reloads the same file. Useful for when the project configuration is changed. " )
{
if ( current_project . loaded ) {
save_all_dirty_buffers ( app ) ;
char space [ 512 ] ;
String project_path = make_fixed_width_string ( space ) ;
append ( & project_path , make_string ( current_project . dir , current_project . dir_len ) ) ;
if ( project_path . size < 1 | | ! char_is_slash ( project_path . str [ project_path . size - 1 ] ) ) {
append ( & project_path , " / " ) ;
}
int32_t path_size = project_path . size ;
append ( & project_path , " project.4coder " ) ;
terminate_with_null ( & project_path ) ;
FILE * file = fopen ( project_path . str , " rb " ) ;
if ( file ! = 0 ) {
project_path . size = path_size ;
terminate_with_null ( & project_path ) ;
Partition * part = & global_part ;
Temp_Memory temp = begin_temp_memory ( part ) ;
char * mem = 0 ;
int32_t size = 0 ;
bool32 file_read_success = file_handle_dump ( part , file , & mem , & size ) ;
fclose ( file ) ;
if ( file_read_success ) {
load_project_from_config_data ( app , part , mem , size , project_path ) ;
}
end_temp_memory ( temp ) ;
}
else {
print_message ( app , literal ( " project.4coder file not found. Previous configuration left unchanged. " ) ) ;
}
}
}
2017-11-09 18:30:24 +00:00
///////////////////////////////
2017-01-29 00:03:23 +00:00
static void
exec_project_fkey_command ( Application_Links * app , int32_t command_ind ) {
2017-02-06 13:49:00 +00:00
Fkey_Command * fkey = & current_project . fkey_commands [ command_ind ] ;
char * command = fkey - > command ;
2017-01-29 00:03:23 +00:00
if ( command [ 0 ] ! = 0 ) {
2017-02-06 13:49:00 +00:00
char * out = fkey - > out ;
bool32 use_build_panel = fkey - > use_build_panel ;
bool32 save_dirty_buffers = fkey - > save_dirty_buffers ;
if ( save_dirty_buffers ) {
save_all_dirty_buffers ( app ) ;
}
2017-01-29 00:03:23 +00:00
int32_t command_len = str_size ( command ) ;
View_Summary view_ = { 0 } ;
View_Summary * view = 0 ;
Buffer_Identifier buffer_id = { 0 } ;
2017-07-17 21:16:29 +00:00
uint32_t flags = CLI_OverlapWithConflict ;
2017-01-29 00:03:23 +00:00
2017-06-30 01:24:43 +00:00
bool32 set_fancy_font = false ;
2017-01-29 00:03:23 +00:00
if ( out [ 0 ] ! = 0 ) {
int32_t out_len = str_size ( out ) ;
buffer_id = buffer_identifier ( out , out_len ) ;
view = & view_ ;
if ( use_build_panel ) {
view_ = get_or_open_build_panel ( app ) ;
if ( match ( out , " *compilation* " ) ) {
2017-06-30 01:24:43 +00:00
set_fancy_font = true ;
2017-01-29 00:03:23 +00:00
}
}
else {
view_ = get_active_view ( app , AccessAll ) ;
}
prev_location = null_location ;
lock_jump_buffer ( out , out_len ) ;
}
else {
// TODO(allen): fix the exec_system_command call so it can take a null buffer_id.
buffer_id = buffer_identifier ( literal ( " *dump* " ) ) ;
}
exec_system_command ( app , view , buffer_id , current_project . dir , current_project . dir_len , command , command_len , flags ) ;
if ( set_fancy_font ) {
set_fancy_compilation_buffer_font ( app ) ;
}
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( project_fkey_command )
CUSTOM_DOC ( " Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command. " )
{
2017-01-29 00:03:23 +00:00
User_Input input = get_command_input ( app ) ;
if ( input . type = = UserInputKey ) {
2017-03-27 22:36:42 +00:00
bool32 got_ind = false ;
int32_t ind = 0 ;
2017-01-29 00:03:23 +00:00
if ( input . key . keycode > = key_f1 & & input . key . keycode < = key_f16 ) {
2017-03-27 22:36:42 +00:00
ind = ( input . key . keycode - key_f1 ) ;
got_ind = true ;
}
else if ( input . key . character_no_caps_lock > = ' 1 ' & & input . key . character_no_caps_lock > = ' 9 ' ) {
ind = ( input . key . character_no_caps_lock - ' 1 ' ) ;
got_ind = true ;
}
else if ( input . key . character_no_caps_lock = = ' 0 ' ) {
ind = 9 ;
got_ind = true ;
}
if ( got_ind ) {
2017-01-29 00:03:23 +00:00
exec_project_fkey_command ( app , ind ) ;
}
}
}
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( project_go_to_root_directory )
CUSTOM_DOC ( " Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns. " )
{
2017-06-20 20:37:45 +00:00
if ( current_project . loaded ) {
directory_set_hot ( app , current_project . dir , current_project . dir_len ) ;
}
}
2017-11-09 18:30:24 +00:00
///////////////////////////////
struct Project_Setup_Status {
bool32 bat_exists ;
bool32 sh_exists ;
bool32 project_exists ;
bool32 everything_exists ;
} ;
static Project_Setup_Status
project_is_setup ( Application_Links * app , char * dir , int32_t dir_len , int32_t dir_capacity ) {
Project_Setup_Status result = { 0 } ;
Temp_Memory temp = begin_temp_memory ( & global_part ) ;
static int32_t needed_extra_space = 15 ;
String str = { 0 } ;
if ( dir_capacity > = dir_len + needed_extra_space ) {
str = make_string_cap ( dir , dir_len , dir_capacity ) ;
}
else {
char * space = push_array ( & global_part , char , dir_len + needed_extra_space ) ;
str = make_string_cap ( space , 0 , dir_len + needed_extra_space ) ;
copy ( & str , make_string ( dir , dir_len ) ) ;
}
str . size = dir_len ;
append ( & str , " /build.bat " ) ;
result . bat_exists = file_exists ( app , str . str , str . size ) ;
str . size = dir_len ;
append ( & str , " /build.sh " ) ;
result . sh_exists = file_exists ( app , str . str , str . size ) ;
str . size = dir_len ;
append ( & str , " /project.4coder " ) ;
result . project_exists = file_exists ( app , str . str , str . size ) ;
result . everything_exists = result . bat_exists & & result . sh_exists & & result . project_exists ;
end_temp_memory ( temp ) ;
return ( result ) ;
}
// TODO(allen): Stop using stdio.h, switch to a 4coder buffer API for all file manipulation.
# include <stdio.h>
2017-11-15 23:57:21 +00:00
CUSTOM_COMMAND_SIG ( setup_new_project )
CUSTOM_DOC ( " Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS. " )
{
2017-11-09 18:30:24 +00:00
char space [ 4096 ] ;
String str = make_fixed_width_string ( space ) ;
str . size = directory_get_hot ( app , str . str , str . memory_size ) ;
int32_t dir_size = str . size ;
Project_Setup_Status status = project_is_setup ( app , str . str , dir_size , str . memory_size ) ;
if ( ! status . everything_exists ) {
// Query the User for Key File Names
Query_Bar code_file_bar = { 0 } ;
Query_Bar output_dir_bar = { 0 } ;
Query_Bar binary_file_bar = { 0 } ;
char code_file_space [ 1024 ] ;
char output_dir_space [ 1024 ] ;
char binary_file_space [ 1024 ] ;
if ( ! status . bat_exists | | ! status . sh_exists ) {
code_file_bar . prompt = make_lit_string ( " Build Target: " ) ;
code_file_bar . string = make_fixed_width_string ( code_file_space ) ;
if ( ! query_user_string ( app , & code_file_bar ) ) return ;
if ( code_file_bar . string . size = = 0 ) return ;
}
output_dir_bar . prompt = make_lit_string ( " Output Directory: " ) ;
output_dir_bar . string = make_fixed_width_string ( output_dir_space ) ;
if ( ! query_user_string ( app , & output_dir_bar ) ) return ;
if ( output_dir_bar . string . size = = 0 ) {
copy ( & output_dir_bar . string , " . " ) ;
}
binary_file_bar . prompt = make_lit_string ( " Binary Output: " ) ;
binary_file_bar . string = make_fixed_width_string ( binary_file_space ) ;
if ( ! query_user_string ( app , & binary_file_bar ) ) return ;
if ( binary_file_bar . string . size = = 0 ) return ;
String code_file = code_file_bar . string ;
String output_dir = output_dir_bar . string ;
String binary_file = binary_file_bar . string ;
// Generate Scripts
if ( ! status . bat_exists ) {
replace_char ( & code_file , ' / ' , ' \\ ' ) ;
replace_char ( & output_dir , ' / ' , ' \\ ' ) ;
replace_char ( & binary_file , ' / ' , ' \\ ' ) ;
str . size = dir_size ;
append ( & str , " /build.bat " ) ;
terminate_with_null ( & str ) ;
FILE * bat_script = fopen ( str . str , " wb " ) ;
if ( bat_script ! = 0 ) {
fprintf ( bat_script , " @echo off \n \n " ) ;
fprintf ( bat_script , " SET OPTS=%.*s \n " ,
default_flags_bat . size , default_flags_bat . str ) ;
fprintf ( bat_script , " SET CODE_HOME=%%cd%% \n " ) ;
fprintf ( bat_script , " pushd %.*s \n " ,
output_dir . size , output_dir . str ) ;
fprintf ( bat_script , " %.*s %%OPTS%% %%CODE_HOME%% \\ %.*s -Fe%.*s \n " ,
default_compiler_bat . size , default_compiler_bat . str ,
code_file . size , code_file . str ,
binary_file . size , binary_file . str ) ;
fprintf ( bat_script , " popd \n " ) ;
fclose ( bat_script ) ;
}
else {
print_message ( app , literal ( " could not create build.bat for new project \n " ) ) ;
}
replace_char ( & code_file , ' \\ ' , ' / ' ) ;
replace_char ( & output_dir , ' \\ ' , ' / ' ) ;
replace_char ( & binary_file , ' \\ ' , ' / ' ) ;
}
else {
print_message ( app , literal ( " build.bat already exists, no changes made to it \n " ) ) ;
}
if ( ! status . sh_exists ) {
str . size = dir_size ;
append ( & str , " /build.sh " ) ;
terminate_with_null ( & str ) ;
FILE * sh_script = fopen ( str . str , " wb " ) ;
if ( sh_script ! = 0 ) {
fprintf ( sh_script , " #!/bin/bash \n \n " ) ;
2017-11-11 22:09:52 +00:00
fprintf ( sh_script , " CODE_HOME= \" $PWD \" \n " ) ;
2017-11-09 18:30:24 +00:00
fprintf ( sh_script , " OPTS=%.*s \n " ,
default_flags_sh . size , default_flags_sh . str ) ;
2017-11-22 18:56:51 +00:00
fprintf ( sh_script , " cd %.*s > /dev/null \n " ,
2017-11-09 18:30:24 +00:00
output_dir . size , output_dir . str ) ;
fprintf ( sh_script , " %.*s $OPTS $CODE_HOME/%.*s -o %.*s \n " ,
default_compiler_sh . size , default_compiler_sh . str ,
code_file . size , code_file . str ,
binary_file . size , binary_file . str ) ;
2017-11-22 18:56:51 +00:00
fprintf ( sh_script , " cd $CODE_HOME > /dev/null \n " ) ;
2017-11-09 18:30:24 +00:00
fclose ( sh_script ) ;
}
else {
print_message ( app , literal ( " could not create build.sh for new project \n " ) ) ;
}
}
else {
print_message ( app , literal ( " build.sh already exists, no changes made to it \n " ) ) ;
}
if ( ! status . project_exists ) {
str . size = dir_size ;
append ( & str , " /project.4coder " ) ;
terminate_with_null ( & str ) ;
FILE * project_script = fopen ( str . str , " wb " ) ;
if ( project_script ! = 0 ) {
fprintf ( project_script , " extensions = \" .c.cpp.h.m.bat.sh.4coder \" ; \n " ) ;
fprintf ( project_script , " open_recursively = true; \n \n " ) ;
replace_str ( & code_file , " / " , " \\ \\ " ) ;
replace_str ( & output_dir , " / " , " \\ \\ " ) ;
replace_str ( & binary_file , " / " , " \\ \\ " ) ;
fprintf ( project_script ,
" fkey_command_win[1] = { \" build.bat \" , \" *compilation* \" , true , true }; \n " ) ;
fprintf ( project_script ,
" fkey_command_win[2] = { \" %.*s \\ \\ %.*s \" , \" *run* \" , false , true }; \n " ,
output_dir . size , output_dir . str ,
binary_file . size , binary_file . str ) ;
replace_str ( & code_file , " \\ \\ " , " / " ) ;
replace_str ( & output_dir , " \\ \\ " , " / " ) ;
replace_str ( & binary_file , " \\ \\ " , " / " ) ;
2017-11-11 22:04:05 +00:00
fprintf ( project_script , " fkey_command_linux[1] = { \" ./build.sh \" , \" *compilation* \" , true , true }; \n " ) ;
2017-11-09 18:30:24 +00:00
fprintf ( project_script ,
" fkey_command_linux[2] = { \" %.*s/%.*s \" , \" *run* \" , false , true }; \n " ,
output_dir . size , output_dir . str ,
binary_file . size , binary_file . str ) ;
2017-11-11 22:04:05 +00:00
fprintf ( project_script , " fkey_command_mac[1] = { \" ./build.sh \" , \" *compilation* \" , true , true }; \n " ) ;
2017-11-09 18:30:24 +00:00
fprintf ( project_script ,
" fkey_command_mac[2] = { \" %.*s/%.*s \" , \" *run* \" , false , true }; \n " ,
output_dir . size , output_dir . str ,
binary_file . size , binary_file . str ) ;
fclose ( project_script ) ;
}
else {
print_message ( app , literal ( " could not create project.4coder for new project \n " ) ) ;
}
}
else {
print_message ( app , literal ( " project.4coder already exists, no changes made to it \n " ) ) ;
}
}
else {
print_message ( app , literal ( " project already setup, no changes made \n " ) ) ;
}
2017-11-21 18:25:19 +00:00
load_project ( app ) ;
2017-11-09 18:30:24 +00:00
}
2017-01-29 00:03:23 +00:00
# endif
// BOTTOM