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
*/
2018-05-08 07:14:23 +00:00
// TOP
2017-01-29 00:03:23 +00:00
2021-01-09 05:20:39 +00:00
////////////////////////////////
// NOTE(allen): File Pattern Operators
2021-01-09 07:06:55 +00:00
function Prj_Pattern_List
2021-01-09 05:20:39 +00:00
prj_pattern_list_from_extension_array ( Arena * arena , String8Array list ) {
2021-01-09 07:06:55 +00:00
Prj_Pattern_List result = { } ;
2020-12-05 20:32:56 +00:00
for ( i32 i = 0 ;
i < list . count ;
+ + i ) {
2021-01-09 07:06:55 +00:00
Prj_Pattern_Node * node = push_array ( arena , Prj_Pattern_Node , 1 ) ;
2021-01-01 23:33:03 +00:00
sll_queue_push ( result . first , result . last , node ) ;
result . count + = 1 ;
2021-01-09 05:20:39 +00:00
String8 str = push_stringf ( arena , " *.%.*s " , string_expand ( list . vals [ i ] ) ) ;
2021-01-01 23:33:03 +00:00
node - > pattern . absolutes = string_split_wildcards ( arena , str ) ;
2018-05-08 07:14:23 +00:00
}
2021-01-01 23:33:03 +00:00
return ( result ) ;
}
2021-01-09 07:06:55 +00:00
function Prj_Pattern_List
2021-01-01 23:33:03 +00:00
prj_pattern_list_from_var ( Arena * arena , Variable_Handle var ) {
2021-01-09 07:06:55 +00:00
Prj_Pattern_List result = { } ;
2021-01-01 23:33:03 +00:00
for ( Vars_Children ( child_var , var ) ) {
2021-01-09 07:06:55 +00:00
Prj_Pattern_Node * node = push_array ( arena , Prj_Pattern_Node , 1 ) ;
2021-01-01 23:33:03 +00:00
sll_queue_push ( result . first , result . last , node ) ;
result . count + = 1 ;
2021-01-09 05:20:39 +00:00
String8 str = vars_string_from_var ( arena , child_var ) ;
2021-01-01 23:33:03 +00:00
node - > pattern . absolutes = string_split_wildcards ( arena , str ) ;
}
return ( result ) ;
2018-05-09 05:22:33 +00:00
}
2021-01-09 07:06:55 +00:00
function Prj_Pattern_List
2021-01-07 08:41:04 +00:00
prj_get_standard_blacklist ( Arena * arena ) {
2021-01-09 05:20:39 +00:00
String8 dot = string_u8_litexpr ( " .* " ) ;
String8Array black_array = { } ;
2021-01-07 08:41:04 +00:00
black_array . strings = & dot ;
black_array . count = 1 ;
return ( prj_pattern_list_from_extension_array ( arena , black_array ) ) ;
}
function b32
2021-01-09 07:06:55 +00:00
prj_match_in_pattern_list ( String8 string , Prj_Pattern_List list ) {
2021-01-07 08:41:04 +00:00
b32 found_match = false ;
2021-01-09 07:06:55 +00:00
for ( Prj_Pattern_Node * node = list . first ;
2021-01-07 08:41:04 +00:00
node ! = 0 ;
node = node - > next ) {
if ( string_wildcard_match ( node - > pattern . absolutes , string , StringMatch_Exact ) ) {
found_match = true ;
break ;
}
}
return ( found_match ) ;
}
2018-05-09 05:22:33 +00:00
2019-10-25 06:17:54 +00:00
function void
2021-01-09 05:20:39 +00:00
prj_close_files_with_ext ( Application_Links * app , String8Array extension_array ) {
2019-06-01 23:33:31 +00:00
Scratch_Block scratch ( app ) ;
2017-01-29 00:03:23 +00:00
2019-06-01 23:33:31 +00:00
i32 buffers_to_close_max = Thousand ( 100 ) ;
Buffer_ID * buffers_to_close = push_array ( scratch , Buffer_ID , buffers_to_close_max ) ;
2018-05-09 05:22:33 +00:00
2019-04-05 02:03:36 +00:00
b32 do_repeat = false ;
2018-05-09 05:22:33 +00:00
do {
2019-06-01 23:33:31 +00:00
i32 buffers_to_close_count = 0 ;
2019-04-05 02:03:36 +00:00
do_repeat = false ;
2018-05-09 05:22:33 +00:00
2019-10-18 02:54:02 +00:00
for ( Buffer_ID buffer = get_buffer_next ( app , 0 , Access_Always ) ;
2019-04-05 02:03:36 +00:00
buffer ! = 0 ;
2019-10-18 02:54:02 +00:00
buffer = get_buffer_next ( app , buffer , Access_Always ) ) {
2019-04-05 02:03:36 +00:00
b32 is_match = true ;
2018-05-09 05:22:33 +00:00
if ( extension_array . count > 0 ) {
2019-06-01 23:33:31 +00:00
Temp_Memory name_temp = begin_temp ( scratch ) ;
2021-01-09 05:20:39 +00:00
String8 file_name = push_buffer_file_name ( app , scratch , buffer ) ;
2019-04-05 02:03:36 +00:00
is_match = false ;
if ( file_name . size > 0 ) {
2021-01-09 05:20:39 +00:00
String8 extension = string_file_extension ( file_name ) ;
2019-02-26 23:08:42 +00:00
for ( i32 i = 0 ; i < extension_array . count ; + + i ) {
2019-06-01 23:33:31 +00:00
if ( string_match ( extension , extension_array . strings [ i ] ) ) {
2019-04-05 02:03:36 +00:00
is_match = true ;
2018-05-09 05:22:33 +00:00
break ;
}
}
}
2019-06-01 23:33:31 +00:00
end_temp ( name_temp ) ;
2018-05-09 05:22:33 +00:00
}
if ( is_match ) {
if ( buffers_to_close_count > = buffers_to_close_max ) {
2019-04-05 02:03:36 +00:00
do_repeat = true ;
2018-05-09 05:22:33 +00:00
break ;
}
2019-04-05 02:03:36 +00:00
buffers_to_close [ buffers_to_close_count + + ] = buffer ;
2018-05-09 05:22:33 +00:00
}
2017-01-29 00:03:23 +00:00
}
2019-02-26 23:08:42 +00:00
for ( i32 i = 0 ; i < buffers_to_close_count ; + + i ) {
2019-06-19 02:31:59 +00:00
buffer_kill ( app , buffers_to_close [ i ] , BufferKill_AlwaysKill ) ;
2017-01-29 00:03:23 +00:00
}
2018-05-09 05:22:33 +00:00
} while ( do_repeat ) ;
2017-01-29 00:03:23 +00:00
}
2021-01-07 08:41:04 +00:00
function void
2021-01-09 07:06:55 +00:00
prj_open_files_pattern_filter__rec ( Application_Links * app , String8 path , Prj_Pattern_List whitelist , Prj_Pattern_List blacklist , Prj_Open_File_Flags flags ) {
2019-06-01 23:33:31 +00:00
Scratch_Block scratch ( app ) ;
2019-10-25 06:17:54 +00:00
2019-10-26 20:48:50 +00:00
ProfileScopeNamed ( app , " get file list " , profile_get_file_list ) ;
2019-10-08 01:42:23 +00:00
File_List list = system_get_file_list ( scratch , path ) ;
2019-10-26 20:48:50 +00:00
ProfileCloseNow ( profile_get_file_list ) ;
2018-05-09 05:22:33 +00:00
2019-08-04 00:49:40 +00:00
File_Info * * info = list . infos ;
2019-02-26 23:08:42 +00:00
for ( u32 i = 0 ; i < list . count ; + + i , + + info ) {
2021-01-09 05:20:39 +00:00
String8 file_name = ( * * info ) . file_name ;
2019-08-04 00:49:40 +00:00
if ( HasFlag ( ( * * info ) . attributes . flags , FileAttribute_IsDirectory ) ) {
2021-01-09 05:20:39 +00:00
if ( ( flags & PrjOpenFileFlag_Recursive ) = = 0 ) {
2021-01-01 23:33:03 +00:00
continue ;
}
2021-01-07 08:41:04 +00:00
if ( prj_match_in_pattern_list ( file_name , blacklist ) ) {
2021-01-01 23:33:03 +00:00
continue ;
}
2021-01-09 05:20:39 +00:00
String8 new_path = push_u8_stringf ( scratch , " %.*s%.*s/ " , string_expand ( path ) , string_expand ( file_name ) ) ;
2021-01-07 08:41:04 +00:00
prj_open_files_pattern_filter__rec ( app , new_path , whitelist , blacklist , flags ) ;
2018-05-09 05:22:33 +00:00
}
else {
2021-01-07 08:41:04 +00:00
if ( ! prj_match_in_pattern_list ( file_name , whitelist ) ) {
2018-05-26 07:49:37 +00:00
continue ;
2018-05-09 05:22:33 +00:00
}
2021-01-07 08:41:04 +00:00
if ( prj_match_in_pattern_list ( file_name , blacklist ) ) {
2018-05-26 07:49:37 +00:00
continue ;
2018-05-09 05:22:33 +00:00
}
2021-01-09 05:20:39 +00:00
String8 full_path = push_u8_stringf ( scratch , " %.*s%.*s " , string_expand ( path ) , string_expand ( file_name ) ) ;
2019-06-19 02:31:59 +00:00
create_buffer ( app , full_path , 0 ) ;
2017-01-29 00:03:23 +00:00
}
}
}
2019-10-25 06:17:54 +00:00
function void
2021-01-09 07:06:55 +00:00
prj_open_files_pattern_filter ( Application_Links * app , String8 dir , Prj_Pattern_List whitelist , Prj_Pattern_List blacklist , Prj_Open_File_Flags flags ) {
2019-10-22 07:15:49 +00:00
ProfileScope ( app , " open all files in directory pattern " ) ;
2019-06-01 23:33:31 +00:00
Scratch_Block scratch ( app ) ;
2021-01-09 05:20:39 +00:00
String8 directory = dir ;
2019-06-01 23:33:31 +00:00
if ( ! character_is_slash ( string_get_character ( directory , directory . size - 1 ) ) ) {
2019-06-18 22:56:09 +00:00
directory = push_u8_stringf ( scratch , " %.*s/ " , string_expand ( dir ) ) ;
2018-05-30 07:58:22 +00:00
}
2021-01-07 08:41:04 +00:00
prj_open_files_pattern_filter__rec ( app , directory , whitelist , blacklist , flags ) ;
2018-05-09 05:22:33 +00:00
}
2019-10-25 06:17:54 +00:00
function void
2021-01-09 05:20:39 +00:00
prj_open_all_files_with_ext_in_hot ( Application_Links * app , String8Array array , Prj_Open_File_Flags flags ) {
2019-06-01 23:33:31 +00:00
Scratch_Block scratch ( app ) ;
2021-01-09 05:20:39 +00:00
String8 hot = push_hot_directory ( app , scratch ) ;
String8 directory = hot ;
2019-06-01 23:33:31 +00:00
if ( ! character_is_slash ( string_get_character ( hot , hot . size - 1 ) ) ) {
2019-06-18 22:56:09 +00:00
directory = push_u8_stringf ( scratch , " %.*s/ " , string_expand ( hot ) ) ;
2018-05-30 07:58:22 +00:00
}
2021-01-09 07:06:55 +00:00
Prj_Pattern_List whitelist = prj_pattern_list_from_extension_array ( scratch , array ) ;
Prj_Pattern_List blacklist = prj_get_standard_blacklist ( scratch ) ;
2021-01-09 05:20:39 +00:00
prj_open_files_pattern_filter ( app , hot , whitelist , blacklist , flags ) ;
2018-05-09 05:22:33 +00:00
}
2021-01-09 05:20:39 +00:00
////////////////////////////////
// NOTE(allen): Project Files
2020-12-05 20:32:56 +00:00
2021-01-13 05:56:01 +00:00
function void
prj_stringize__string_list ( Application_Links * app , Arena * arena , String8 name , Variable_Handle list , String8List * out ) {
Scratch_Block scratch ( app , arena ) ;
string_list_pushf ( arena , out , " %.*s = { \n " , string_expand ( name ) ) ;
for ( Vars_Children ( child , list ) ) {
String8 child_string = vars_string_from_var ( scratch , child ) ;
if ( child_string . size > 0 ) {
// TODO(allen): escape child_string
string_list_pushf ( arena , out , " \" %.*s \" , \n " , string_expand ( child_string ) ) ;
}
}
string_list_pushf ( arena , out , " }; \n " ) ;
}
function void
prj_stringize_project ( Application_Links * app , Arena * arena , Variable_Handle project , String8List * out ) {
Scratch_Block scratch ( app , arena ) ;
2021-01-15 23:18:58 +00:00
// NOTE(allen): String IDs
String_ID version_id = vars_save_string_lit ( " version " ) ;
String_ID project_name_id = vars_save_string_lit ( " project_name " ) ;
String_ID patterns_id = vars_save_string_lit ( " patterns " ) ;
String_ID blacklist_patterns_id = vars_save_string_lit ( " blacklist_patterns " ) ;
2021-01-15 23:49:28 +00:00
String_ID load_paths_id = vars_save_string_lit ( " load_paths " ) ;
2021-01-15 23:18:58 +00:00
String_ID path_id = vars_save_string_lit ( " path " ) ;
String_ID relative_id = vars_save_string_lit ( " relative " ) ;
String_ID recursive_id = vars_save_string_lit ( " recursive " ) ;
2021-01-15 23:49:28 +00:00
String_ID commands_id = vars_save_string_lit ( " commands " ) ;
String_ID out_id = vars_save_string_lit ( " out " ) ;
String_ID footer_panel_id = vars_save_string_lit ( " footer_panel " ) ;
String_ID save_dirty_files_id = vars_save_string_lit ( " save_dirty_files " ) ;
String_ID cursor_at_end_id = vars_save_string_lit ( " cursor_at_end " ) ;
2021-01-16 00:18:30 +00:00
String_ID fkey_command_id = vars_save_string_lit ( " fkey_command " ) ;
2021-01-15 23:18:58 +00:00
String8 os_strings [ ] = { str8_lit ( " win " ) , str8_lit ( " linux " ) , str8_lit ( " mac " ) , } ;
local_const i32 os_string_count = ArrayCount ( os_strings ) ;
String_ID os_string_ids [ os_string_count ] ;
for ( i32 i = 0 ; i < os_string_count ; i + = 1 ) {
os_string_ids [ i ] = vars_save_string ( os_strings [ i ] ) ;
}
2021-01-15 23:49:28 +00:00
// NOTE(allen): Stringizing...
// NOTE(allen): Header Stuff
2021-01-15 23:18:58 +00:00
u64 version = vars_u64_from_var ( app , vars_read_key ( project , version_id ) ) ;
2021-01-13 05:56:01 +00:00
version = clamp_bot ( 2 , version ) ;
string_list_pushf ( arena , out , " version(%llu); \n " , version ) ;
2021-01-15 23:18:58 +00:00
String8 project_name = vars_string_from_var ( scratch , vars_read_key ( project , project_name_id ) ) ;
2021-01-13 05:56:01 +00:00
if ( project_name . size > 0 ) {
// TODO(allen): escape project_name
string_list_pushf ( arena , out , " project_name = \" %.*s \" ; \n " , string_expand ( project_name ) ) ;
}
string_list_push ( arena , out , str8_lit ( " \n " ) ) ;
2021-01-15 23:49:28 +00:00
// NOTE(allen): File Match Patterns
2021-01-15 23:18:58 +00:00
Variable_Handle patterns = vars_read_key ( project , patterns_id ) ;
2021-01-13 05:56:01 +00:00
if ( ! vars_is_nil ( patterns ) ) {
prj_stringize__string_list ( app , arena , str8_lit ( " patterns " ) , patterns , out ) ;
}
2021-01-15 23:18:58 +00:00
Variable_Handle blacklist_patterns = vars_read_key ( project , blacklist_patterns_id ) ;
2021-01-13 05:56:01 +00:00
if ( ! vars_is_nil ( blacklist_patterns ) ) {
prj_stringize__string_list ( app , arena , str8_lit ( " blacklist_patterns " ) , blacklist_patterns , out ) ;
}
string_list_push ( arena , out , str8_lit ( " \n " ) ) ;
2021-01-15 23:18:58 +00:00
2021-01-15 23:49:28 +00:00
// NOTE(allen): Load Paths
2021-01-15 23:18:58 +00:00
Variable_Handle load_paths = vars_read_key ( project , load_paths_id ) ;
if ( ! vars_is_nil ( load_paths ) ) {
string_list_push ( arena , out , str8_lit ( " load_paths = { \n " ) ) ;
for ( i32 i = 0 ; i < os_string_count ; i + = 1 ) {
Variable_Handle os_paths = vars_read_key ( load_paths , os_string_ids [ i ] ) ;
if ( ! vars_is_nil ( os_paths ) ) {
String8 os_string = os_strings [ i ] ;
string_list_pushf ( arena , out , " .%.*s = { \n " , string_expand ( os_string ) ) ;
for ( Vars_Children ( child , os_paths ) ) {
Variable_Handle path_var = vars_read_key ( child , path_id ) ;
Variable_Handle recursive_var = vars_read_key ( child , recursive_id ) ;
Variable_Handle relative_var = vars_read_key ( child , relative_id ) ;
2021-01-15 23:49:28 +00:00
// TODO(allen): escape path_string
2021-01-15 23:18:58 +00:00
String8 path_string = vars_string_from_var ( scratch , path_var ) ;
b32 recursive = vars_b32_from_var ( recursive_var ) ;
b32 relative = vars_b32_from_var ( relative_var ) ;
string_list_push ( arena , out , str8_lit ( " { " ) ) ;
string_list_pushf ( arena , out , " .path = \" %.*s \" , " , string_expand ( path_string ) ) ;
string_list_pushf ( arena , out , " .recursive = %s, " , ( recursive ? " true " : " false " ) ) ;
string_list_pushf ( arena , out , " .relative = %s, " , ( relative ? " true " : " false " ) ) ;
string_list_push ( arena , out , str8_lit ( " }, \n " ) ) ;
}
string_list_push ( arena , out , str8_lit ( " }, \n " ) ) ;
}
}
string_list_push ( arena , out , str8_lit ( " }; \n " ) ) ;
2021-01-15 23:49:28 +00:00
string_list_push ( arena , out , str8_lit ( " \n " ) ) ;
2021-01-15 23:18:58 +00:00
}
2021-01-15 23:49:28 +00:00
// NOTE(allen): Commands
Variable_Handle commands = vars_read_key ( project , commands_id ) ;
if ( ! vars_is_nil ( commands ) ) {
string_list_push ( arena , out , str8_lit ( " commands = { \n " ) ) ;
for ( Vars_Children ( command , commands ) ) {
String8 command_name = vars_key_from_var ( scratch , command ) ;
string_list_pushf ( arena , out , " .%.*s = { \n " , string_expand ( command_name ) ) ;
for ( i32 i = 0 ; i < os_string_count ; i + = 1 ) {
Variable_Handle os_cmd_var = vars_read_key ( command , os_string_ids [ i ] ) ;
if ( ! vars_is_nil ( os_cmd_var ) ) {
// TODO(allen): escape os_cmd_string
String8 os_cmd_string = vars_string_from_var ( scratch , os_cmd_var ) ;
string_list_pushf ( arena , out , " .%.*s = \" %.*s \" , \n " , string_expand ( os_strings [ i ] ) , string_expand ( os_cmd_string ) ) ;
}
}
Variable_Handle out_var = vars_read_key ( command , out_id ) ;
Variable_Handle footer_panel_var = vars_read_key ( command , footer_panel_id ) ;
Variable_Handle save_dirty_files_var = vars_read_key ( command , save_dirty_files_id ) ;
Variable_Handle cursor_at_end_var = vars_read_key ( command , cursor_at_end_id ) ;
// TODO(allen): escape out_string
String8 out_string = vars_string_from_var ( scratch , out_var ) ;
b32 footer_panel = vars_b32_from_var ( footer_panel_var ) ;
b32 save_dirty_files = vars_b32_from_var ( save_dirty_files_var ) ;
b32 cursor_at_end = vars_b32_from_var ( cursor_at_end_var ) ;
string_list_pushf ( arena , out , " .out = \" %.*s \" , \n " , string_expand ( out_string ) ) ;
string_list_pushf ( arena , out , " .footer_panel = %s, \n " , ( footer_panel ? " true " : " false " ) ) ;
string_list_pushf ( arena , out , " .save_dirty_files = %s, \n " , ( save_dirty_files ? " true " : " false " ) ) ;
string_list_pushf ( arena , out , " .cursor_at_end = %s, \n " , ( cursor_at_end ? " true " : " false " ) ) ;
string_list_push ( arena , out , str8_lit ( " }, \n " ) ) ;
}
string_list_push ( arena , out , str8_lit ( " }; \n " ) ) ;
2021-01-16 00:18:30 +00:00
string_list_push ( arena , out , str8_lit ( " \n " ) ) ;
}
// NOTE(allen): FKey Command
Variable_Handle fkey_commands = vars_read_key ( project , fkey_command_id ) ;
if ( ! vars_is_nil ( fkey_commands ) ) {
string_list_push ( arena , out , str8_lit ( " fkey_command = { \n " ) ) ;
for ( Vars_Children ( child , fkey_commands ) ) {
String8 key = vars_key_from_var ( scratch , child ) ;
String8 name = vars_string_from_var ( scratch , child ) ;
string_list_pushf ( arena , out , " .%.*s = \" %.*s \" , \n " , string_expand ( key ) , string_expand ( name ) ) ;
}
string_list_push ( arena , out , str8_lit ( " }; \n " ) ) ;
string_list_push ( arena , out , str8_lit ( " \n " ) ) ;
2021-01-15 23:49:28 +00:00
}
2021-01-13 05:56:01 +00:00
}
2021-01-09 06:58:05 +00:00
function Prj_Setup_Status
2021-01-09 05:20:39 +00:00
prj_file_is_setup ( Application_Links * app , String8 script_path , String8 script_file ) {
2021-01-09 06:58:05 +00:00
Prj_Setup_Status result = { } ;
2021-01-09 05:20:39 +00:00
{
Scratch_Block scratch ( app ) ;
String8 bat_path = push_u8_stringf ( scratch , " %.*s/%.*s.bat " ,
string_expand ( script_path ) ,
string_expand ( script_file ) ) ;
result . bat_exists = file_exists ( app , bat_path ) ;
2018-05-08 07:14:23 +00:00
}
2021-01-09 05:20:39 +00:00
{
Scratch_Block scratch ( app ) ;
String8 sh_path = push_u8_stringf ( scratch , " %.*s/%.*s.sh " ,
string_expand ( script_path ) ,
string_expand ( script_file ) ) ;
result . sh_exists = file_exists ( app , sh_path ) ;
}
{
Scratch_Block scratch ( app ) ;
String8 project_path = push_u8_stringf ( scratch , " %.*s/project.4coder " ,
string_expand ( script_path ) ) ;
result . sh_exists = file_exists ( app , project_path ) ;
}
result . everything_exists = ( result . bat_exists & & result . sh_exists & & result . project_exists ) ;
return ( result ) ;
2018-05-08 07:14:23 +00:00
}
2021-01-09 05:20:39 +00:00
function b32
prj_generate_bat ( Arena * scratch , String8 opts , String8 compiler , String8 script_path , String8 script_file ,
String8 code_file , String8 output_dir , String8 binary_file ) {
b32 success = false ;
2021-01-01 23:33:03 +00:00
2021-01-09 05:20:39 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2021-01-01 23:33:03 +00:00
2021-01-09 05:20:39 +00:00
String8 cf = push_string_copy ( scratch , code_file ) ;
String8 od = push_string_copy ( scratch , output_dir ) ;
String8 bf = push_string_copy ( scratch , binary_file ) ;
2018-06-02 00:29:36 +00:00
2019-06-01 23:33:31 +00:00
cf = string_mod_replace_character ( cf , ' / ' , ' \\ ' ) ;
od = string_mod_replace_character ( od , ' / ' , ' \\ ' ) ;
bf = string_mod_replace_character ( bf , ' / ' , ' \\ ' ) ;
2018-06-02 00:29:36 +00:00
2021-01-09 05:20:39 +00:00
String8 file_name = push_u8_stringf ( scratch , " %.*s/%.*s.bat " ,
string_expand ( script_path ) ,
string_expand ( script_file ) ) ;
2018-06-02 00:29:36 +00:00
2019-06-01 23:33:31 +00:00
FILE * bat_script = fopen ( ( char * ) file_name . str , " wb " ) ;
2018-06-02 00:29:36 +00:00
if ( bat_script ! = 0 ) {
fprintf ( bat_script , " @echo off \n \n " ) ;
2019-06-01 23:33:31 +00:00
fprintf ( bat_script , " set opts=%.*s \n " , ( i32 ) opts . size , opts . str ) ;
2018-06-02 00:29:36 +00:00
fprintf ( bat_script , " set code=%%cd%% \n " ) ;
2019-06-01 23:33:31 +00:00
fprintf ( bat_script , " pushd %.*s \n " , ( i32 ) od . size , od . str ) ;
2018-06-02 00:29:36 +00:00
fprintf ( bat_script , " %.*s %%opts%% %%code%% \\ %.*s -Fe%.*s \n " ,
2019-06-01 23:33:31 +00:00
( i32 ) compiler . size , compiler . str , ( i32 ) cf . size , cf . str , ( i32 ) bf . size , bf . str ) ;
2018-06-02 00:29:36 +00:00
fprintf ( bat_script , " popd \n " ) ;
fclose ( bat_script ) ;
success = true ;
}
2019-06-01 23:33:31 +00:00
end_temp ( temp ) ;
2018-06-02 00:29:36 +00:00
return ( success ) ;
}
2019-10-25 06:17:54 +00:00
function b32
2021-01-09 05:20:39 +00:00
prj_generate_sh ( Arena * scratch , String8 opts , String8 compiler , String8 script_path , String8 script_file , String8 code_file , String8 output_dir , String8 binary_file ) {
2019-02-26 23:08:42 +00:00
b32 success = false ;
2018-06-02 00:29:36 +00:00
2019-06-01 23:33:31 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2018-06-02 00:29:36 +00:00
2021-01-09 05:20:39 +00:00
String8 cf = code_file ;
String8 od = output_dir ;
String8 bf = binary_file ;
2018-06-02 00:29:36 +00:00
2021-01-09 05:20:39 +00:00
String8 file_name = push_u8_stringf ( scratch , " %.*s/%.*s.sh " ,
string_expand ( script_path ) ,
string_expand ( script_file ) ) ;
2018-06-02 00:29:36 +00:00
2019-06-01 23:33:31 +00:00
FILE * sh_script = fopen ( ( char * ) file_name . str , " wb " ) ;
2018-06-02 00:29:36 +00:00
if ( sh_script ! = 0 ) {
fprintf ( sh_script , " #!/bin/bash \n \n " ) ;
fprintf ( sh_script , " code= \" $PWD \" \n " ) ;
2019-06-01 23:33:31 +00:00
fprintf ( sh_script , " opts=%.*s \n " , string_expand ( opts ) ) ;
fprintf ( sh_script , " cd %.*s > /dev/null \n " , string_expand ( od ) ) ;
fprintf ( sh_script , " %.*s $opts $code/%.*s -o %.*s \n " , string_expand ( compiler ) , string_expand ( cf ) , string_expand ( bf ) ) ;
2018-06-02 00:29:36 +00:00
fprintf ( sh_script , " cd $code > /dev/null \n " ) ;
fclose ( sh_script ) ;
success = true ;
}
2019-06-01 23:33:31 +00:00
end_temp ( temp ) ;
2018-06-02 00:29:36 +00:00
return ( success ) ;
}
2019-10-25 06:17:54 +00:00
function b32
2021-01-09 05:20:39 +00:00
prj_generate_project ( Arena * scratch , String8 script_path , String8 script_file , String8 output_dir , String8 binary_file ) {
2019-02-26 23:08:42 +00:00
b32 success = false ;
2018-06-02 00:29:36 +00:00
2019-06-01 23:33:31 +00:00
Temp_Memory temp = begin_temp ( scratch ) ;
2018-06-02 00:29:36 +00:00
2021-01-09 05:20:39 +00:00
String8 od = output_dir ;
String8 bf = binary_file ;
2018-06-02 00:29:36 +00:00
2021-01-09 05:20:39 +00:00
String8 od_win = string_replace ( scratch , od ,
string_u8_litexpr ( " / " ) , string_u8_litexpr ( " \\ " ) ) ;
String8 bf_win = string_replace ( scratch , bf ,
string_u8_litexpr ( " / " ) , string_u8_litexpr ( " \\ " ) ) ;
2018-06-02 00:29:36 +00:00
2021-01-09 05:20:39 +00:00
String8 file_name = push_u8_stringf ( scratch , " %.*s/project.4coder " , string_expand ( script_path ) ) ;
2018-06-02 00:29:36 +00:00
2019-06-01 23:33:31 +00:00
FILE * out = fopen ( ( char * ) file_name . str , " wb " ) ;
2018-06-02 00:29:36 +00:00
if ( out ! = 0 ) {
2021-01-12 06:36:49 +00:00
fprintf ( out , " version(2); \n " ) ;
2019-06-01 23:33:31 +00:00
fprintf ( out , " project_name = \" %.*s \" ; \n " , string_expand ( binary_file ) ) ;
2018-06-02 00:29:36 +00:00
fprintf ( out , " patterns = { \n " ) ;
fprintf ( out , " \" *.c \" , \n " ) ;
fprintf ( out , " \" *.cpp \" , \n " ) ;
fprintf ( out , " \" *.h \" , \n " ) ;
fprintf ( out , " \" *.m \" , \n " ) ;
fprintf ( out , " \" *.bat \" , \n " ) ;
fprintf ( out , " \" *.sh \" , \n " ) ;
fprintf ( out , " \" *.4coder \" , \n " ) ;
fprintf ( out , " }; \n " ) ;
2018-06-02 23:02:14 +00:00
fprintf ( out , " blacklist_patterns = { \n " ) ;
2018-06-02 00:29:36 +00:00
fprintf ( out , " \" .* \" , \n " ) ;
fprintf ( out , " }; \n " ) ;
fprintf ( out , " load_paths_base = { \n " ) ;
2018-06-02 23:02:14 +00:00
fprintf ( out , " { \" . \" , .relative = true, .recursive = true, }, \n " ) ;
2018-06-02 00:29:36 +00:00
fprintf ( out , " }; \n " ) ;
fprintf ( out , " load_paths = { \n " ) ;
2021-01-12 06:36:49 +00:00
fprintf ( out , " .win = load_paths_base, \n " ) ;
fprintf ( out , " .linux = load_paths_base, \n " ) ;
fprintf ( out , " .mac = load_paths_base, \n " ) ;
2018-06-02 00:29:36 +00:00
fprintf ( out , " }; \n " ) ;
fprintf ( out , " \n " ) ;
2021-01-12 06:36:49 +00:00
fprintf ( out , " commands = { \n " ) ;
fprintf ( out , " .build = { .out = \" *compilation* \" , .footer_panel = true, .save_dirty_files = true, \n " ) ;
fprintf ( out , " .win = \" %.*s.bat \" , \n " , string_expand ( script_file ) ) ;
fprintf ( out , " .linux = \" ./%.*s.sh \" , \n " , string_expand ( script_file ) ) ;
fprintf ( out , " .mac = \" ./%.*s.sh \" , }, \n " , string_expand ( script_file ) ) ;
fprintf ( out , " .run = { .out = \" *run* \" , .footer_panel = false, .save_dirty_files = false, \n " ) ;
fprintf ( out , " .win = \" %.*s \\ \\ %.*s \" , \n " , string_expand ( od_win ) , string_expand ( bf_win ) ) ;
fprintf ( out , " .linux = \" %.*s/%.*s \" , \n " , string_expand ( od ) , string_expand ( bf ) ) ;
fprintf ( out , " .mac = \" %.*s/%.*s \" , }, \n " , string_expand ( od ) , string_expand ( bf ) ) ;
2018-06-02 00:29:36 +00:00
fprintf ( out , " }; \n " ) ;
2021-01-16 00:18:30 +00:00
fprintf ( out , " fkey_command = { \n " ) ;
fprintf ( out , " .F1 = \" run \" ; \n " ) ;
fprintf ( out , " .F2 = \" run \" ; \n " ) ;
fprintf ( out , " }; \n " ) ;
2018-06-02 00:29:36 +00:00
fclose ( out ) ;
success = true ;
}
2019-06-01 23:33:31 +00:00
end_temp ( temp ) ;
2018-06-02 00:29:36 +00:00
return ( success ) ;
}
2019-10-25 06:17:54 +00:00
function void
2021-01-09 06:58:05 +00:00
prj_setup_scripts ( Application_Links * app , Prj_Setup_Script_Flags flags ) {
2019-10-01 02:06:21 +00:00
Scratch_Block scratch ( app ) ;
2021-01-09 05:20:39 +00:00
String8 script_path = push_hot_directory ( app , scratch ) ;
2018-06-02 00:29:36 +00:00
2021-01-09 06:58:05 +00:00
b32 do_project_file = ( flags & PrjSetupScriptFlag_Project ) ;
b32 do_bat_script = ( flags & PrjSetupScriptFlag_Bat ) ;
b32 do_sh_script = ( flags & PrjSetupScriptFlag_Sh ) ;
2019-02-26 23:08:42 +00:00
b32 needs_to_do_work = false ;
2021-01-09 06:58:05 +00:00
Prj_Setup_Status status = { } ;
2018-06-02 00:29:36 +00:00
if ( do_project_file ) {
2021-01-09 05:20:39 +00:00
status = prj_file_is_setup ( app , script_path , string_u8_litexpr ( " build " ) ) ;
2018-06-02 00:29:36 +00:00
needs_to_do_work =
! status . project_exists | |
( do_bat_script & & ! status . bat_exists ) | |
( do_sh_script & & ! status . sh_exists ) ;
}
else {
needs_to_do_work = true ;
}
if ( needs_to_do_work ) {
// Query the User for Key File Names
2017-11-09 18:30:24 +00:00
2021-01-09 06:58:05 +00:00
b32 finished_queries = false ;
local_const i32 text_field_cap = 1024 ;
String8 script_file = { } ;
String8 code_file = { } ;
String8 output_dir = { } ;
String8 binary_file = { } ;
2017-11-09 18:30:24 +00:00
2021-01-09 06:58:05 +00:00
{
Query_Bar_Group bar_group ( app ) ;
Query_Bar script_file_bar = { } ;
Query_Bar code_file_bar = { } ;
Query_Bar output_dir_bar = { } ;
Query_Bar binary_file_bar = { } ;
b32 get_script_file = ! do_project_file ;
b32 get_code_file = ( ( do_bat_script & & ! status . bat_exists ) | | ( do_sh_script & & ! status . sh_exists ) ) ;
if ( get_script_file ) {
script_file_bar . prompt = string_u8_litexpr ( " Script Name: " ) ;
script_file_bar . string . str = push_array ( scratch , u8 , text_field_cap ) ;
script_file_bar . string_capacity = text_field_cap ;
if ( ! query_user_string ( app , & script_file_bar ) | |
script_file_bar . string . size = = 0 ) {
goto fail_out ;
}
}
if ( get_code_file ) {
code_file_bar . prompt = string_u8_litexpr ( " Build Target: " ) ;
code_file_bar . string . str = push_array ( scratch , u8 , text_field_cap ) ;
code_file_bar . string_capacity = text_field_cap ;
if ( ! query_user_string ( app , & code_file_bar ) | |
code_file_bar . string . size = = 0 ) {
goto fail_out ;
}
}
output_dir_bar . prompt = string_u8_litexpr ( " Output Directory: " ) ;
output_dir_bar . string . str = push_array ( scratch , u8 , text_field_cap ) ;
output_dir_bar . string_capacity = text_field_cap ;
if ( ! query_user_string ( app , & output_dir_bar ) ) {
goto fail_out ;
}
if ( output_dir_bar . string . size = = 0 ) {
output_dir_bar . string . str [ 0 ] = ' . ' ;
output_dir_bar . string . size = 1 ;
}
binary_file_bar . prompt = string_u8_litexpr ( " Binary Output: " ) ;
binary_file_bar . string . str = push_array ( scratch , u8 , text_field_cap ) ;
binary_file_bar . string_capacity = text_field_cap ;
if ( ! query_user_string ( app , & binary_file_bar ) | |
binary_file_bar . string . size = = 0 ) {
goto fail_out ;
}
finished_queries = true ;
script_file = script_file_bar . string ;
code_file = code_file_bar . string ;
output_dir = output_dir_bar . string ;
binary_file = binary_file_bar . string ;
fail_out : ;
}
2017-11-09 18:30:24 +00:00
2021-01-09 06:58:05 +00:00
if ( ! finished_queries ) {
2018-06-02 00:29:36 +00:00
return ;
}
2017-11-09 18:30:24 +00:00
2018-06-02 00:29:36 +00:00
if ( do_project_file ) {
2021-01-09 06:58:05 +00:00
script_file = string_u8_litexpr ( " build " ) ;
2018-06-02 00:29:36 +00:00
}
2017-11-09 18:30:24 +00:00
2018-06-02 00:29:36 +00:00
if ( ! do_project_file ) {
2021-01-09 06:58:05 +00:00
status = prj_file_is_setup ( app , script_path , script_file ) ;
2018-06-02 00:29:36 +00:00
}
2017-11-09 18:30:24 +00:00
// Generate Scripts
2018-06-02 00:29:36 +00:00
if ( do_bat_script ) {
if ( ! status . bat_exists ) {
2021-01-09 05:20:39 +00:00
String8 default_flags_bat = def_get_config_string ( scratch , vars_save_string_lit ( " default_flags_bat " ) ) ;
String8 default_compiler_bat = def_get_config_string ( scratch , vars_save_string_lit ( " default_compiler_bat " ) ) ;
2020-11-26 03:20:36 +00:00
2021-01-09 06:58:05 +00:00
if ( ! prj_generate_bat ( scratch , default_flags_bat , default_compiler_bat , script_path ,
script_file , code_file , output_dir , binary_file ) ) {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " could not create build.bat for new project \n " ) ) ;
2018-06-02 00:29:36 +00:00
}
2017-11-09 18:30:24 +00:00
}
else {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " the batch script already exists, no changes made to it \n " ) ) ;
2017-11-09 18:30:24 +00:00
}
}
2018-06-02 00:29:36 +00:00
if ( do_sh_script ) {
if ( ! status . bat_exists ) {
2021-01-09 05:20:39 +00:00
String8 default_flags_sh = def_get_config_string ( scratch , vars_save_string_lit ( " default_flags_sh " ) ) ;
String8 default_compiler_sh = def_get_config_string ( scratch , vars_save_string_lit ( " default_compiler_sh " ) ) ;
if ( ! prj_generate_sh ( scratch , default_flags_sh , default_compiler_sh ,
2021-01-09 06:58:05 +00:00
script_path , script_file , code_file , output_dir , binary_file ) ) {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " could not create build.sh for new project \n " ) ) ;
2018-06-02 00:29:36 +00:00
}
2017-11-09 18:30:24 +00:00
}
else {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " the shell script already exists, no changes made to it \n " ) ) ;
2017-11-09 18:30:24 +00:00
}
}
2018-06-02 00:29:36 +00:00
if ( do_project_file ) {
if ( ! status . project_exists ) {
2021-01-09 06:58:05 +00:00
if ( ! prj_generate_project ( scratch , script_path , script_file , output_dir , binary_file ) ) {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " could not create project.4coder for new project \n " ) ) ;
2018-06-02 00:29:36 +00:00
}
2017-11-09 18:30:24 +00:00
}
else {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " project.4coder already exists, no changes made to it \n " ) ) ;
2017-11-09 18:30:24 +00:00
}
}
}
else {
2018-06-02 00:29:36 +00:00
if ( do_project_file ) {
2019-06-01 23:33:31 +00:00
print_message ( app , string_u8_litexpr ( " project already setup, no changes made \n " ) ) ;
2018-06-02 00:29:36 +00:00
}
2017-11-09 18:30:24 +00:00
}
2018-06-02 00:29:36 +00:00
}
2021-01-09 05:20:39 +00:00
////////////////////////////////
// NOTE(allen): Project Operations
function void
prj_exec_command ( Application_Links * app , Variable_Handle cmd_var ) {
Scratch_Block scratch ( app ) ;
String_ID os_id = vars_save_string_lit ( OS_NAME ) ;
String8 cmd = vars_string_from_var ( scratch , vars_read_key ( cmd_var , os_id ) ) ;
if ( cmd . size > 0 ) {
String_ID out_id = vars_save_string_lit ( " out " ) ;
String_ID footer_panel_id = vars_save_string_lit ( " footer_panel " ) ;
String_ID save_dirty_files_id = vars_save_string_lit ( " save_dirty_files " ) ;
String_ID cursor_at_end_id = vars_save_string_lit ( " cursor_at_end " ) ;
b32 save_dirty_files = vars_b32_from_var ( vars_read_key ( cmd_var , save_dirty_files_id ) ) ;
if ( save_dirty_files ) {
save_all_dirty_buffers ( app ) ;
}
u32 flags = CLI_OverlapWithConflict | CLI_SendEndSignal ;
b32 cursor_at_end = vars_b32_from_var ( vars_read_key ( cmd_var , cursor_at_end_id ) ) ;
if ( cursor_at_end ) {
flags | = CLI_CursorAtEnd ;
}
View_ID view = 0 ;
Buffer_Identifier buffer_id = { } ;
b32 set_fancy_font = false ;
String8 out = vars_string_from_var ( scratch , vars_read_key ( cmd_var , out_id ) ) ;
if ( out . size > 0 ) {
buffer_id = buffer_identifier ( out ) ;
b32 footer_panel = vars_b32_from_var ( vars_read_key ( cmd_var , footer_panel_id ) ) ;
if ( footer_panel ) {
view = get_or_open_build_panel ( app ) ;
if ( string_match ( out , string_u8_litexpr ( " *compilation* " ) ) ) {
set_fancy_font = true ;
}
}
else {
Buffer_ID buffer = buffer_identifier_to_id ( app , buffer_id ) ;
view = get_first_view_with_buffer ( app , buffer ) ;
if ( view = = 0 ) {
view = get_active_view ( app , Access_Always ) ;
}
}
block_zero_struct ( & prev_location ) ;
lock_jump_buffer ( app , out ) ;
}
else {
// TODO(allen): fix the exec_system_command call so it can take a null buffer_id.
buffer_id = buffer_identifier ( string_u8_litexpr ( " *dump* " ) ) ;
}
Variable_Handle command_list_var = vars_parent ( cmd_var ) ;
Variable_Handle prj_var = vars_parent ( command_list_var ) ;
String8 prj_dir = prj_path_from_project ( scratch , prj_var ) ;
exec_system_command ( app , view , buffer_id , prj_dir , cmd , flags ) ;
if ( set_fancy_font ) {
set_fancy_compilation_buffer_font ( app ) ;
}
}
2017-11-09 18:30:24 +00:00
}
2021-01-09 05:20:39 +00:00
function Variable_Handle
prj_command_from_name ( Application_Links * app , String8 cmd_name ) {
Scratch_Block scratch ( app ) ;
// TODO(allen): fallback for multiple stages of reading
Variable_Handle cmd_list = def_get_config_var ( vars_save_string_lit ( " commands " ) ) ;
Variable_Handle cmd = vars_read_key ( cmd_list , vars_save_string ( cmd_name ) ) ;
return ( cmd ) ;
2018-06-02 00:29:36 +00:00
}
2021-01-09 05:20:39 +00:00
function void
prj_exec_command_name ( Application_Links * app , String8 cmd_name ) {
Scratch_Block scratch ( app ) ;
Variable_Handle cmd = prj_command_from_name ( app , cmd_name ) ;
prj_exec_command ( app , cmd ) ;
2018-06-02 00:29:36 +00:00
}
2021-01-09 05:20:39 +00:00
function void
prj_exec_command_fkey_index ( Application_Links * app , i32 fkey_index ) {
// TODO(allen): ideally if one fkey_command is missing this index the fallback
// can be continued.
Variable_Handle fkeys = def_get_config_var ( vars_save_string_lit ( " fkey_command " ) ) ;
Scratch_Block scratch ( app ) ;
2021-01-16 00:18:30 +00:00
String8 fkey_index_str = push_stringf ( scratch , " F%d " , fkey_index + 1 ) ;
2021-01-09 05:20:39 +00:00
String_ID fkey_index_id = vars_save_string ( fkey_index_str ) ;
Variable_Handle cmd_name_var = vars_read_key ( fkeys , fkey_index_id ) ;
String8 cmd_name = vars_string_from_var ( scratch , cmd_name_var ) ;
prj_exec_command_name ( app , cmd_name ) ;
2018-06-02 00:29:36 +00:00
}
2021-01-09 05:20:39 +00:00
function String8
2021-01-13 05:56:01 +00:00
prj_full_file_path_from_project ( Arena * arena , Variable_Handle project ) {
2021-01-09 05:20:39 +00:00
String8 project_full_path = vars_string_from_var ( arena , project ) ;
2021-01-13 05:56:01 +00:00
return ( project_full_path ) ;
}
function String8
prj_path_from_project ( Arena * arena , Variable_Handle project ) {
String8 project_full_path = prj_full_file_path_from_project ( arena , project ) ;
2021-01-09 05:20:39 +00:00
String8 project_dir = string_remove_last_folder ( project_full_path ) ;
return ( project_dir ) ;
}
2018-09-17 18:47:06 +00:00
2021-01-06 05:00:37 +00:00
function Variable_Handle
2021-01-09 05:20:39 +00:00
prj_cmd_from_user ( Application_Links * app , Variable_Handle prj_var , String8 query ) {
2021-01-06 05:00:37 +00:00
Scratch_Block scratch ( app ) ;
Lister_Block lister ( app , scratch ) ;
lister_set_query ( lister , query ) ;
lister_set_default_handlers ( lister ) ;
Variable_Handle cmd_list_var = vars_read_key ( prj_var , vars_save_string_lit ( " commands " ) ) ;
String_ID os_id = vars_save_string_lit ( OS_NAME ) ;
for ( Variable_Handle cmd = vars_first_child ( cmd_list_var ) ;
! vars_is_nil ( cmd ) ;
cmd = vars_next_sibling ( cmd ) ) {
Variable_Handle os_cmd = vars_read_key ( cmd , os_id ) ;
if ( ! vars_is_nil ( os_cmd ) ) {
2021-01-09 05:20:39 +00:00
String8 cmd_name = vars_key_from_var ( scratch , cmd ) ;
String8 os_cmd_str = vars_string_from_var ( scratch , os_cmd ) ;
2021-01-06 05:00:37 +00:00
lister_add_item ( lister , cmd_name , os_cmd_str , cmd . ptr , 0 ) ;
}
}
Variable_Handle result = vars_get_nil ( ) ;
Lister_Result l_result = run_lister ( app , lister ) ;
if ( ! l_result . canceled ) {
if ( l_result . user_data ! = 0 ) {
result . ptr = ( Variable * ) l_result . user_data ;
}
}
return ( result ) ;
}
2021-01-09 05:20:39 +00:00
////////////////////////////////
// NOTE(allen): Commands
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. " )
{
Scratch_Block scratch ( app ) ;
String8 treat_as_code = def_get_config_string ( scratch , vars_save_string_lit ( " treat_as_code " ) ) ;
String8Array extensions = parse_extension_line_to_extension_list ( app , scratch , treat_as_code ) ;
prj_close_files_with_ext ( app , extensions ) ;
}
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. " )
{
Scratch_Block scratch ( app ) ;
String8 treat_as_code = def_get_config_string ( scratch , vars_save_string_lit ( " treat_as_code " ) ) ;
String8Array extensions = parse_extension_line_to_extension_list ( app , scratch , treat_as_code ) ;
prj_open_all_files_with_ext_in_hot ( app , extensions , 0 ) ;
}
CUSTOM_COMMAND_SIG ( open_all_code_recursive )
CUSTOM_DOC ( " Works as open_all_code but also runs in all subdirectories. " )
{
Scratch_Block scratch ( app ) ;
String8 treat_as_code = def_get_config_string ( scratch , vars_save_string_lit ( " treat_as_code " ) ) ;
String8Array extensions = parse_extension_line_to_extension_list ( app , scratch , treat_as_code ) ;
prj_open_all_files_with_ext_in_hot ( app , extensions , PrjOpenFileFlag_Recursive ) ;
}
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. " )
{
2021-01-12 06:36:49 +00:00
// TODO(allen): compress this _thoughtfully_
2021-01-09 05:20:39 +00:00
ProfileScope ( app , " load project " ) ;
save_all_dirty_buffers ( app ) ;
Scratch_Block scratch ( app ) ;
// NOTE(allen): Load the project file from the hot directory
String8 project_path = push_hot_directory ( app , scratch ) ;
File_Name_Data dump = dump_file_search_up_path ( app , scratch , project_path , string_u8_litexpr ( " project.4coder " ) ) ;
String8 project_root = string_remove_last_folder ( dump . file_name ) ;
if ( dump . data . str = = 0 ) {
print_message ( app , string_u8_litexpr ( " Did not find project.4coder. \n " ) ) ;
}
// NOTE(allen): Parse config data out of project file
Config * config_parse = 0 ;
2021-01-13 05:56:01 +00:00
Variable_Handle prj_var = vars_get_nil ( ) ;
2021-01-09 05:20:39 +00:00
if ( dump . data . str ! = 0 ) {
Token_Array array = token_array_from_text ( app , scratch , dump . data ) ;
if ( array . tokens ! = 0 ) {
config_parse = def_config_parse ( app , scratch , dump . file_name , dump . data , array ) ;
if ( config_parse ! = 0 ) {
i32 version = 0 ;
if ( config_parse - > version ! = 0 ) {
version = * config_parse - > version ;
}
switch ( version ) {
case 0 :
case 1 :
{
2021-01-13 05:56:01 +00:00
prj_var = prj_v1_to_v2 ( app , project_root , config_parse ) ;
2021-01-09 05:20:39 +00:00
} break ;
default :
{
2021-01-13 05:56:01 +00:00
prj_var = def_fill_var_from_config ( app , vars_get_root ( ) , vars_save_string_lit ( " prj_config " ) , config_parse ) ;
2021-01-09 05:20:39 +00:00
} break ;
}
}
}
}
// NOTE(allen): Print Project
2021-01-13 05:56:01 +00:00
if ( ! vars_is_nil ( prj_var ) ) {
vars_print ( app , prj_var ) ;
2021-01-09 05:20:39 +00:00
print_message ( app , string_u8_litexpr ( " \n " ) ) ;
}
// NOTE(allen): Print Errors
if ( config_parse ! = 0 ) {
String8 error_text = config_stringize_errors ( app , scratch , config_parse ) ;
if ( error_text . size > 0 ) {
print_message ( app , string_u8_litexpr ( " Project errors: \n " ) ) ;
print_message ( app , error_text ) ;
print_message ( app , string_u8_litexpr ( " \n " ) ) ;
}
}
// NOTE(allen): Open All Project Files
2021-01-13 05:56:01 +00:00
Variable_Handle load_paths_var = vars_read_key ( prj_var , vars_save_string_lit ( " load_paths " ) ) ;
2021-01-09 05:20:39 +00:00
Variable_Handle load_paths_os_var = vars_read_key ( load_paths_var , vars_save_string_lit ( OS_NAME ) ) ;
String_ID path_id = vars_save_string_lit ( " path " ) ;
String_ID recursive_id = vars_save_string_lit ( " recursive " ) ;
String_ID relative_id = vars_save_string_lit ( " relative " ) ;
2021-01-13 05:56:01 +00:00
Variable_Handle whitelist_var = vars_read_key ( prj_var , vars_save_string_lit ( " patterns " ) ) ;
Variable_Handle blacklist_var = vars_read_key ( prj_var , vars_save_string_lit ( " blacklist_patterns " ) ) ;
2021-01-09 05:20:39 +00:00
2021-01-09 07:06:55 +00:00
Prj_Pattern_List whitelist = prj_pattern_list_from_var ( scratch , whitelist_var ) ;
Prj_Pattern_List blacklist = prj_pattern_list_from_var ( scratch , blacklist_var ) ;
2021-01-09 05:20:39 +00:00
for ( Variable_Handle load_path_var = vars_first_child ( load_paths_os_var ) ;
! vars_is_nil ( load_path_var ) ;
load_path_var = vars_next_sibling ( load_path_var ) ) {
Variable_Handle path_var = vars_read_key ( load_path_var , path_id ) ;
Variable_Handle recursive_var = vars_read_key ( load_path_var , recursive_id ) ;
Variable_Handle relative_var = vars_read_key ( load_path_var , relative_id ) ;
2019-10-25 23:33:50 +00:00
2021-01-09 05:20:39 +00:00
String8 path = vars_string_from_var ( scratch , path_var ) ;
b32 recursive = vars_b32_from_var ( recursive_var ) ;
b32 relative = vars_b32_from_var ( relative_var ) ;
u32 flags = 0 ;
if ( recursive ) {
flags | = PrjOpenFileFlag_Recursive ;
2019-10-25 23:33:50 +00:00
}
2021-01-09 05:20:39 +00:00
String8 file_dir = path ;
if ( relative ) {
2021-01-13 05:56:01 +00:00
String8 prj_dir = prj_path_from_project ( scratch , prj_var ) ;
2021-01-09 05:20:39 +00:00
String8List file_dir_list = { } ;
string_list_push ( scratch , & file_dir_list , prj_dir ) ;
string_list_push_overlap ( scratch , & file_dir_list , ' / ' , path ) ;
string_list_push_overlap ( scratch , & file_dir_list , ' / ' , SCu8 ( ) ) ;
file_dir = string_list_flatten ( scratch , file_dir_list , StringFill_NullTerminate ) ;
2019-10-25 23:33:50 +00:00
}
2021-01-09 05:20:39 +00:00
prj_open_files_pattern_filter ( app , file_dir , whitelist , blacklist , flags ) ;
2019-10-25 23:33:50 +00:00
}
2021-01-09 05:20:39 +00:00
// NOTE(allen): Set Window Title
2021-01-13 05:56:01 +00:00
Variable_Handle proj_name_var = vars_read_key ( prj_var , vars_save_string_lit ( " project_name " ) ) ;
String_ID proj_name_id = vars_key_id_from_var ( prj_var ) ;
2021-01-09 05:20:39 +00:00
if ( proj_name_id ! = 0 ) {
String8 proj_name = vars_read_string ( scratch , proj_name_id ) ;
String8 title = push_u8_stringf ( scratch , " 4coder project: %.*s " , string_expand ( proj_name ) ) ;
set_window_title ( app , title ) ;
}
}
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. " )
{
ProfileScope ( app , " project fkey command " ) ;
User_Input input = get_current_input ( app ) ;
b32 got_ind = false ;
i32 ind = 0 ;
if ( input . event . kind = = InputEventKind_KeyStroke ) {
if ( KeyCode_F1 < = input . event . key . code & & input . event . key . code < = KeyCode_F16 ) {
ind = ( input . event . key . code - KeyCode_F1 ) ;
got_ind = true ;
}
else if ( KeyCode_1 < = input . event . key . code & & input . event . key . code < = KeyCode_9 ) {
ind = ( input . event . key . code - ' 1 ' ) ;
got_ind = true ;
}
else if ( input . event . key . code = = KeyCode_0 ) {
ind = 9 ;
got_ind = true ;
}
if ( got_ind ) {
prj_exec_command_fkey_index ( app , ind ) ;
}
}
}
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. " )
{
Scratch_Block scratch ( app ) ;
Variable_Handle prj_var = vars_read_key ( vars_get_root ( ) , vars_save_string_lit ( " prj_config " ) ) ;
String8 prj_dir = prj_path_from_project ( scratch , prj_var ) ;
if ( prj_dir . size > 0 ) {
set_hot_directory ( app , prj_dir ) ;
}
}
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. " )
{
2021-01-09 06:58:05 +00:00
prj_setup_scripts ( app , PrjSetupScriptFlag_Project | PrjSetupScriptFlag_Bat | PrjSetupScriptFlag_Sh ) ;
2021-01-09 05:20:39 +00:00
load_project ( app ) ;
}
CUSTOM_COMMAND_SIG ( setup_build_bat )
CUSTOM_DOC ( " Queries the user for several configuration options and initializes a new build batch script. " )
{
2021-01-09 06:58:05 +00:00
prj_setup_scripts ( app , PrjSetupScriptFlag_Bat ) ;
2021-01-09 05:20:39 +00:00
}
CUSTOM_COMMAND_SIG ( setup_build_sh )
CUSTOM_DOC ( " Queries the user for several configuration options and initializes a new build shell script. " )
{
2021-01-09 06:58:05 +00:00
prj_setup_scripts ( app , PrjSetupScriptFlag_Sh ) ;
2021-01-09 05:20:39 +00:00
}
CUSTOM_COMMAND_SIG ( setup_build_bat_and_sh )
CUSTOM_DOC ( " Queries the user for several configuration options and initializes a new build batch script. " )
{
2021-01-09 06:58:05 +00:00
prj_setup_scripts ( app , PrjSetupScriptFlag_Bat | PrjSetupScriptFlag_Sh ) ;
2019-10-25 23:33:50 +00:00
}
2018-09-17 18:47:06 +00:00
CUSTOM_COMMAND_SIG ( project_command_lister )
CUSTOM_DOC ( " Open a lister of all commands in the currently loaded project. " )
{
2021-01-06 05:00:37 +00:00
Variable_Handle prj_var = vars_read_key ( vars_get_root ( ) , vars_save_string_lit ( " prj_config " ) ) ;
Variable_Handle prj_cmd = prj_cmd_from_user ( app , prj_var , string_u8_litexpr ( " Command: " ) ) ;
if ( ! vars_is_nil ( prj_cmd ) ) {
prj_exec_command ( app , prj_cmd ) ;
2018-09-17 18:47:06 +00:00
}
}
2021-01-13 05:56:01 +00:00
CUSTOM_COMMAND_SIG ( project_reprint )
CUSTOM_DOC ( " Prints the current project to the file it was loaded from; prints in the most recent project file version " )
{
Variable_Handle prj_var = vars_read_key ( vars_get_root ( ) , vars_save_string_lit ( " prj_config " ) ) ;
if ( ! vars_is_nil ( prj_var ) ) {
Scratch_Block scratch ( app ) ;
String8 prj_full_path = prj_full_file_path_from_project ( scratch , prj_var ) ;
prj_full_path = push_string_copy ( scratch , prj_full_path ) ;
String8 message = push_stringf ( scratch , " Reprinting project file: %.*s \n " , string_expand ( prj_full_path ) ) ;
print_message ( app , message ) ;
String8List prj_string = { } ;
prj_stringize_project ( app , scratch , prj_var , & prj_string ) ;
FILE * file = fopen ( ( char * ) prj_full_path . str , " wb " ) ;
if ( file = = 0 ) {
print_message ( app , str8_lit ( " Could not open project file \n " ) ) ;
}
else {
for ( String8Node * node = prj_string . first ;
node ! = 0 ;
node = node - > next ) {
2021-01-24 23:30:57 +00:00
fwrite ( node - > string . str , 1 , ( size_t ) node - > string . size , file ) ;
2021-01-13 05:56:01 +00:00
}
fclose ( file ) ;
print_message ( app , str8_lit ( " Reloading project buffer \n " ) ) ;
Buffer_ID buffer = get_buffer_by_file_name ( app , prj_full_path , Access_Always ) ;
if ( buffer ! = 0 ) {
buffer_reopen ( app , buffer , 0 ) ;
}
else {
create_buffer ( app , prj_full_path , 0 ) ;
}
}
}
}
2017-01-29 00:03:23 +00:00
// BOTTOM