From 7699b377679c358a044ae2e0b152c7bf987977ee Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 1 Jun 2018 17:29:36 -0700 Subject: [PATCH] Upgraded new project commands, cursor at bottom of output option --- 4coder_generated/command_metadata.h | 83 +++-- 4coder_helper.cpp | 15 + 4coder_long_command_switch.cpp | 9 + 4coder_project_commands.cpp | 559 +++++++++++++++++++--------- 4coder_project_commands.h | 9 + 4ed.cpp | 48 +-- 4ed_api_implementation.cpp | 13 +- project.4coder | 2 +- 8 files changed, 488 insertions(+), 250 deletions(-) diff --git a/4coder_generated/command_metadata.h b/4coder_generated/command_metadata.h index fef42c2a..ad80a3dc 100644 --- a/4coder_generated/command_metadata.h +++ b/4coder_generated/command_metadata.h @@ -1,7 +1,7 @@ #define command_id(c) (fcoder_metacmd_ID_##c) #define command_metadata(c) (&fcoder_metacmd_table[command_id(c)]) #define command_metadata_by_id(id) (&fcoder_metacmd_table[id]) -#define command_one_past_last_id 193 +#define command_one_past_last_id 196 #if defined(CUSTOM_COMMAND_SIG) #define PROC_LINKS(x,y) x #else @@ -173,6 +173,9 @@ CUSTOM_COMMAND_SIG(set_bindings_choose); CUSTOM_COMMAND_SIG(set_bindings_default); CUSTOM_COMMAND_SIG(set_bindings_mac_default); CUSTOM_COMMAND_SIG(set_mark); +CUSTOM_COMMAND_SIG(setup_build_bat); +CUSTOM_COMMAND_SIG(setup_build_bat_and_sh); +CUSTOM_COMMAND_SIG(setup_build_sh); CUSTOM_COMMAND_SIG(setup_new_project); CUSTOM_COMMAND_SIG(show_filebar); CUSTOM_COMMAND_SIG(show_scrollbar); @@ -212,7 +215,7 @@ char *source_name; int32_t source_name_len; int32_t line_number; }; -static Command_Metadata fcoder_metacmd_table[193] = { +static Command_Metadata fcoder_metacmd_table[196] = { { PROC_LINKS(allow_mouse, 0), "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "C:\\work\\4ed\\code\\4coder_default_framework.cpp", 49, 199 }, { PROC_LINKS(auto_tab_line_at_cursor, 0), "auto_tab_line_at_cursor", 23, "Auto-indents the line on which the cursor sits.", 47, "C:\\work\\4ed\\code\\4coder_auto_indent.cpp", 43, 722 }, { PROC_LINKS(auto_tab_range, 0), "auto_tab_range", 14, "Auto-indents the range between the cursor and the mark.", 55, "C:\\work\\4ed\\code\\4coder_auto_indent.cpp", 43, 733 }, @@ -229,7 +232,7 @@ static Command_Metadata fcoder_metacmd_table[193] = { { PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 368 }, { PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 174 }, { PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 187 }, -{ PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 974 }, +{ PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 986 }, { PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "C:\\work\\4ed\\code\\4coder_build_commands.cpp", 46, 205 }, { PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 441 }, { PROC_LINKS(copy, 0), "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 26 }, @@ -295,7 +298,7 @@ static Command_Metadata fcoder_metacmd_table[193] = { { PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 800 }, { PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 747 }, { PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 759 }, -{ PROC_LINKS(load_project, 0), "load_project", 12, "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.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 997 }, +{ PROC_LINKS(load_project, 0), "load_project", 12, "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.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1009 }, { PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1101 }, { PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 110 }, { PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 383 }, @@ -317,8 +320,8 @@ static Command_Metadata fcoder_metacmd_table[193] = { { PROC_LINKS(newline_or_goto_position_same_panel_direct, 0), "newline_or_goto_position_same_panel_direct", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_direct.cpp", 43, 116 }, { PROC_LINKS(newline_or_goto_position_same_panel_sticky, 0), "newline_or_goto_position_same_panel_sticky", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 571 }, { PROC_LINKS(newline_or_goto_position_sticky, 0), "newline_or_goto_position_sticky", 31, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 556 }, -{ PROC_LINKS(open_all_code, 0), "open_all_code", 13, "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.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 981 }, -{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 988 }, +{ PROC_LINKS(open_all_code, 0), "open_all_code", 13, "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.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 993 }, +{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1000 }, { PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1457 }, { PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1320 }, { PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Switches to the next active panel and begins an open file dialogue.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1465 }, @@ -335,8 +338,8 @@ static Command_Metadata fcoder_metacmd_table[193] = { { PROC_LINKS(paste_next, 0), "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 84 }, { PROC_LINKS(paste_next_and_indent, 0), "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 135 }, { PROC_LINKS(place_in_scope, 0), "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 481 }, -{ PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20, "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.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1004 }, -{ PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1029 }, +{ PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20, "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.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1016 }, +{ PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1041 }, { PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 893 }, { PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 913 }, { PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 931 }, @@ -378,7 +381,10 @@ static Command_Metadata fcoder_metacmd_table[193] = { { PROC_LINKS(set_bindings_default, 0), "set_bindings_default", 20, "Remap keybindings using the 'default' mapping rule.", 51, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 61 }, { PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24, "Remap keybindings using the 'mac-default' mapping rule.", 55, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 75 }, { PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 86 }, -{ PROC_LINKS(setup_new_project, 0), "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1077 }, +{ PROC_LINKS(setup_build_bat, 0), "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1426 }, +{ PROC_LINKS(setup_build_bat_and_sh, 0), "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1438 }, +{ PROC_LINKS(setup_build_sh, 0), "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1432 }, +{ PROC_LINKS(setup_new_project, 0), "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1419 }, { PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 464 }, { PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 450 }, { PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1259 }, @@ -572,31 +578,34 @@ static int32_t fcoder_metacmd_ID_set_bindings_choose = 161; static int32_t fcoder_metacmd_ID_set_bindings_default = 162; static int32_t fcoder_metacmd_ID_set_bindings_mac_default = 163; static int32_t fcoder_metacmd_ID_set_mark = 164; -static int32_t fcoder_metacmd_ID_setup_new_project = 165; -static int32_t fcoder_metacmd_ID_show_filebar = 166; -static int32_t fcoder_metacmd_ID_show_scrollbar = 167; -static int32_t fcoder_metacmd_ID_snipe_token_or_word = 168; -static int32_t fcoder_metacmd_ID_snipe_token_or_word_right = 169; -static int32_t fcoder_metacmd_ID_suppress_mouse = 170; -static int32_t fcoder_metacmd_ID_swap_buffers_between_panels = 171; -static int32_t fcoder_metacmd_ID_to_lowercase = 172; -static int32_t fcoder_metacmd_ID_to_uppercase = 173; -static int32_t fcoder_metacmd_ID_toggle_filebar = 174; -static int32_t fcoder_metacmd_ID_toggle_fullscreen = 175; -static int32_t fcoder_metacmd_ID_toggle_line_wrap = 176; -static int32_t fcoder_metacmd_ID_toggle_mouse = 177; -static int32_t fcoder_metacmd_ID_toggle_show_whitespace = 178; -static int32_t fcoder_metacmd_ID_toggle_virtual_whitespace = 179; -static int32_t fcoder_metacmd_ID_undo = 180; -static int32_t fcoder_metacmd_ID_view_buffer_other_panel = 181; -static int32_t fcoder_metacmd_ID_word_complete = 182; -static int32_t fcoder_metacmd_ID_write_and_auto_tab = 183; -static int32_t fcoder_metacmd_ID_write_block = 184; -static int32_t fcoder_metacmd_ID_write_character = 185; -static int32_t fcoder_metacmd_ID_write_explicit_enum_flags = 186; -static int32_t fcoder_metacmd_ID_write_explicit_enum_values = 187; -static int32_t fcoder_metacmd_ID_write_hack = 188; -static int32_t fcoder_metacmd_ID_write_note = 189; -static int32_t fcoder_metacmd_ID_write_todo = 190; -static int32_t fcoder_metacmd_ID_write_underscore = 191; -static int32_t fcoder_metacmd_ID_write_zero_struct = 192; +static int32_t fcoder_metacmd_ID_setup_build_bat = 165; +static int32_t fcoder_metacmd_ID_setup_build_bat_and_sh = 166; +static int32_t fcoder_metacmd_ID_setup_build_sh = 167; +static int32_t fcoder_metacmd_ID_setup_new_project = 168; +static int32_t fcoder_metacmd_ID_show_filebar = 169; +static int32_t fcoder_metacmd_ID_show_scrollbar = 170; +static int32_t fcoder_metacmd_ID_snipe_token_or_word = 171; +static int32_t fcoder_metacmd_ID_snipe_token_or_word_right = 172; +static int32_t fcoder_metacmd_ID_suppress_mouse = 173; +static int32_t fcoder_metacmd_ID_swap_buffers_between_panels = 174; +static int32_t fcoder_metacmd_ID_to_lowercase = 175; +static int32_t fcoder_metacmd_ID_to_uppercase = 176; +static int32_t fcoder_metacmd_ID_toggle_filebar = 177; +static int32_t fcoder_metacmd_ID_toggle_fullscreen = 178; +static int32_t fcoder_metacmd_ID_toggle_line_wrap = 179; +static int32_t fcoder_metacmd_ID_toggle_mouse = 180; +static int32_t fcoder_metacmd_ID_toggle_show_whitespace = 181; +static int32_t fcoder_metacmd_ID_toggle_virtual_whitespace = 182; +static int32_t fcoder_metacmd_ID_undo = 183; +static int32_t fcoder_metacmd_ID_view_buffer_other_panel = 184; +static int32_t fcoder_metacmd_ID_word_complete = 185; +static int32_t fcoder_metacmd_ID_write_and_auto_tab = 186; +static int32_t fcoder_metacmd_ID_write_block = 187; +static int32_t fcoder_metacmd_ID_write_character = 188; +static int32_t fcoder_metacmd_ID_write_explicit_enum_flags = 189; +static int32_t fcoder_metacmd_ID_write_explicit_enum_values = 190; +static int32_t fcoder_metacmd_ID_write_hack = 191; +static int32_t fcoder_metacmd_ID_write_note = 192; +static int32_t fcoder_metacmd_ID_write_todo = 193; +static int32_t fcoder_metacmd_ID_write_underscore = 194; +static int32_t fcoder_metacmd_ID_write_zero_struct = 195; diff --git a/4coder_helper.cpp b/4coder_helper.cpp index 7dc505c9..e7b3e087 100644 --- a/4coder_helper.cpp +++ b/4coder_helper.cpp @@ -1130,6 +1130,21 @@ lexer_keywords_default_init(Partition *arena, Cpp_Keyword_Table *kw_out, Cpp_Key //////////////////////////////// +static String +get_hot_directory(Application_Links *app, Partition *arena){ + Temp_Memory temp = begin_temp_memory(arena); + int32_t space_cap = partition_remaining(arena); + char *space = push_array(arena, char, space_cap); + String hot_dir = make_string_cap(space, 0, space_cap); + hot_dir.size = directory_get_hot(app, hot_dir.str, hot_dir.memory_size); + end_temp_memory(temp); + push_array(arena, char, hot_dir.size); + hot_dir.memory_size = hot_dir.size; + return(hot_dir); +} + +//////////////////////////////// + static String dump_file_handle(Partition *arena, FILE *file){ String str = {0}; diff --git a/4coder_long_command_switch.cpp b/4coder_long_command_switch.cpp index 946e01cf..76e9e597 100644 --- a/4coder_long_command_switch.cpp +++ b/4coder_long_command_switch.cpp @@ -44,6 +44,15 @@ CUSTOM_DOC("Execute a 'long form' command.") else if (match(bar.string, make_lit_string("new project"))){ setup_new_project(app); } + else if (match(bar.string, make_lit_string("new bat"))){ + setup_build_bat(app); + } + else if (match(bar.string, make_lit_string("new sh"))){ + setup_build_sh(app); + } + else if (match(bar.string, make_lit_string("new scripts"))){ + setup_build_bat_and_sh(app); + } else if (match(bar.string, make_lit_string("delete file"))){ delete_file_query(app); } diff --git a/4coder_project_commands.cpp b/4coder_project_commands.cpp index b23a5668..b0aec44f 100644 --- a/4coder_project_commands.cpp +++ b/4coder_project_commands.cpp @@ -416,12 +416,13 @@ parse_project__config_data__version_1(Partition *arena, String root_dir, Config bool32 can_emit_command = true; - String name = {0}; Config_Compound *cmd_set = 0; + String name = {0}; + String cmd_str = {0}; String out = {0}; bool32 footer_panel = false; bool32 save_dirty_files = true; - String cmd_str = {0}; + bool32 cursor_at_end = false; if (!config_compound_string_member(parsed, src, "name", 0, &name)){ can_emit_command = false; @@ -468,12 +469,15 @@ parse_project__config_data__version_1(Partition *arena, String root_dir, Config config_compound_bool_member(parsed, src, "footer_panel", 3, &footer_panel); config_compound_bool_member(parsed, src, "save_dirty_files", 4, &save_dirty_files); + config_compound_bool_member(parsed, src, "cursor_at_end", 5, + &cursor_at_end); dst->name = push_string_copy(arena, name); dst->cmd = push_string_copy(arena, cmd_str); dst->out = push_string_copy(arena, out); dst->footer_panel = footer_panel; dst->save_dirty_files = save_dirty_files; + dst->cursor_at_end = cursor_at_end; } finish_command:; @@ -691,6 +695,7 @@ project_deep_copy__inner(Partition *arena, Project *project){ } dst->footer_panel = src->footer_panel; dst->save_dirty_files = src->save_dirty_files; + dst->cursor_at_end = src->cursor_at_end; } } @@ -775,6 +780,9 @@ config_feedback_command_array(String *space, char *name, Project_Command_Array * append(space, ".save_dirty_files = "); append(space, command->save_dirty_files?"true":"false"); append(space, ", "); + append(space, ".cursor_at_end = "); + append(space, command->cursor_at_end?"true":"false"); + append(space, ", "); append(space, "},\n"); } append(space, "};\n"); @@ -927,6 +935,7 @@ exec_project_fkey_command(Application_Links *app, int32_t fkey_index){ if (fkey->cmd.size > 0){ bool32 footer_panel = fkey->footer_panel; bool32 save_dirty_files = fkey->save_dirty_files; + bool32 cursor_at_end = fkey->cursor_at_end; if (save_dirty_files){ save_all_dirty_buffers(app); @@ -936,6 +945,9 @@ exec_project_fkey_command(Application_Links *app, int32_t fkey_index){ View_Summary *view_ptr = 0; Buffer_Identifier buffer_id = {0}; uint32_t flags = CLI_OverlapWithConflict; + if (cursor_at_end){ + flags |= CLI_CursorAtEnd; + } bool32 set_fancy_font = false; if (fkey->out.size > 0){ @@ -1038,29 +1050,26 @@ CUSTOM_DOC("Changes 4coder's hot directory to the root directory of the currentl /////////////////////////////// static Project_Setup_Status -project_is_setup(Application_Links *app, char *dir, int32_t dir_len, int32_t dir_capacity){ +project_is_setup(Application_Links *app, Partition *scratch, String script_path, String script_file){ Project_Setup_Status result = {0}; - Temp_Memory temp = begin_temp_memory(&global_part); + Temp_Memory temp = begin_temp_memory(scratch); static int32_t needed_extra_space = 15; + char *space = push_array(&global_part, char, script_path.size + needed_extra_space); + String str = make_string_cap(space, 0, script_path.size + needed_extra_space); + copy(&str, script_path); - 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"); + int32_t dir_len = str.size; + append(&str, "/"); + append(&str, script_file); + append(&str, ".bat"); result.bat_exists = file_exists(app, str.str, str.size); str.size = dir_len; - append(&str, "/build.sh"); + append(&str, "/"); + append(&str, script_file); + append(&str, ".sh"); result.sh_exists = file_exists(app, str.str, str.size); str.size = dir_len; @@ -1074,175 +1083,363 @@ project_is_setup(Application_Links *app, char *dir, int32_t dir_len, int32_t dir return(result); } +static Project_Key_Strings +project_key_strings_query_user(Application_Links *app, + bool32 get_script_file, bool32 get_code_file, + char *script_file_space, int32_t script_file_cap, + char *code_file_space, int32_t code_file_cap, + char *output_dir_space, int32_t output_dir_cap, + char *binary_file_space, int32_t binary_file_cap){ + Project_Key_Strings keys = {0}; + + Query_Bar script_file_bar = {0}; + Query_Bar code_file_bar = {0}; + Query_Bar output_dir_bar = {0}; + Query_Bar binary_file_bar = {0}; + + if (get_script_file){ + script_file_bar.prompt = make_lit_string("Script Name: "); + script_file_bar.string = make_string_cap(script_file_space, 0, script_file_cap); + + if (!query_user_string(app, &script_file_bar)) return(keys); + if (script_file_bar.string.size == 0) return(keys); + } + + if (get_code_file){ + code_file_bar.prompt = make_lit_string("Build Target: "); + code_file_bar.string = make_string_cap(code_file_space, 0, code_file_cap); + + if (!query_user_string(app, &code_file_bar)) return(keys); + if (code_file_bar.string.size == 0) return(keys); + } + + output_dir_bar.prompt = make_lit_string("Output Directory: "); + output_dir_bar.string = make_string_cap(output_dir_space, 0, output_dir_cap); + + if (!query_user_string(app, &output_dir_bar)) return(keys); + 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_string_cap(binary_file_space, 0, binary_file_cap); + + if (!query_user_string(app, &binary_file_bar)) return(keys); + if (binary_file_bar.string.size == 0) return(keys); + + + keys.success = true; + keys.script_file = script_file_bar.string; + keys.code_file = code_file_bar.string; + keys.output_dir = output_dir_bar.string; + keys.binary_file = binary_file_bar.string; + + return(keys); +} + +static bool32 +project_generate_bat_script(Partition *scratch, String opts, String compiler, + String script_path, String script_file, + String code_file, String output_dir, String binary_file){ + bool32 success = false; + + Temp_Memory temp = begin_temp_memory(scratch); + + String cf = push_string_copy(scratch, code_file); + String od = push_string_copy(scratch, output_dir); + String bf = push_string_copy(scratch, binary_file); + + replace_char(&cf, '/', '\\'); + replace_char(&od, '/', '\\'); + replace_char(&bf, '/', '\\'); + + int32_t space_cap = partition_remaining(scratch); + char *space = push_array(scratch, char, space_cap); + String file_name = make_string_cap(space, 0, space_cap); + append(&file_name, script_path); + append(&file_name, "/"); + append(&file_name, script_file); + append(&file_name, ".bat"); + terminate_with_null(&file_name); + + FILE *bat_script = fopen(file_name.str, "wb"); + if (bat_script != 0){ + fprintf(bat_script, "@echo off\n\n"); + fprintf(bat_script, "set opts=%.*s\n", opts.size, opts.str); + fprintf(bat_script, "set code=%%cd%%\n"); + + fprintf(bat_script, "pushd %.*s\n", od.size, od.str); + fprintf(bat_script, "%.*s %%opts%% %%code%%\\%.*s -Fe%.*s\n", + compiler.size, compiler.str, cf.size, cf.str, bf.size, bf.str); + fprintf(bat_script, "popd\n"); + + fclose(bat_script); + success = true; + } + + end_temp_memory(temp); + + return(success); +} + +static bool32 +project_generate_sh_script(Partition *scratch, String opts, String compiler, + String script_path, String script_file, + String code_file, String output_dir, String binary_file){ + bool32 success = false; + + Temp_Memory temp = begin_temp_memory(scratch); + + String cf = code_file; + String od = output_dir; + String bf = binary_file; + + int32_t space_cap = partition_remaining(scratch); + char *space = push_array(scratch, char, space_cap); + String file_name = make_string_cap(space, 0, space_cap); + append(&file_name, script_path); + append(&file_name, "/"); + append(&file_name, script_file); + append(&file_name, ".sh"); + terminate_with_null(&file_name); + + FILE *sh_script = fopen(file_name.str, "wb"); + if (sh_script != 0){ + fprintf(sh_script, "#!/bin/bash\n\n"); + + fprintf(sh_script, "code=\"$PWD\"\n"); + + fprintf(sh_script, "opts=%.*s\n", opts.size, opts.str); + + fprintf(sh_script, "cd %.*s > /dev/null\n", od.size, od.str); + fprintf(sh_script, "%.*s $opts $code/%.*s -o %.*s\n", + compiler.size, compiler.str, cf.size, cf.str, bf.size, bf.str); + fprintf(sh_script, "cd $code > /dev/null\n"); + + fclose(sh_script); + success = true; + } + + end_temp_memory(temp); + + return(success); +} + +static bool32 +project_generate_project_4coder_file(Partition *scratch, + String script_path, String script_file, + String output_dir, String binary_file){ + bool32 success = false; + + Temp_Memory temp = begin_temp_memory(scratch); + + String od = output_dir; + String bf = binary_file; + + String od_win = push_string(scratch, od.size*2); + String bf_win = push_string(scratch, bf.size*2); + + append(&od_win, od); + append(&bf_win, bf); + + replace_str(&od_win, "/", "\\\\"); + replace_str(&bf_win, "/", "\\\\"); + + int32_t space_cap = partition_remaining(scratch); + char *space = push_array(scratch, char, space_cap); + String file_name = make_string_cap(space, 0, space_cap); + append(&file_name, script_path); + append(&file_name, "/project.4coder"); + terminate_with_null(&file_name); + + FILE *out = fopen(file_name.str, "wb"); + if (out != 0){ + fprintf(out, "version(1);\n"); + fprintf(out, "project_name = \"%.*s\";\n", binary_file.size, binary_file.str); + 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"); + fprintf(out, "patterns = {\n"); + fprintf(out, "\".*\",\n"); + fprintf(out, "};\n"); + fprintf(out, "load_paths_base = {\n"); + fprintf(out, " { \".\", .relative = true, .recursive = true, },"); + fprintf(out, "};\n"); + fprintf(out, "load_paths = {\n"); + fprintf(out, " { load_paths_base, .os = \"win\", },\n"); + fprintf(out, " { load_paths_base, .os = \"linux\", },\n"); + fprintf(out, " { load_paths_base, .os = \"mac\", },\n"); + fprintf(out, "};\n"); + + fprintf(out, "\n"); + + fprintf(out, "command_list = {\n"); + fprintf(out, " { .name = \"build\",\n"); + fprintf(out, " .out = \"*compilation*\", .footer_panel = true, .save_dirty_files = true,\n"); + fprintf(out, " .cmd = { { \"%.*s.bat\", .os = \"win\" },\n", + script_file.size, script_file.str); + fprintf(out, " { \"%.*s.sh\" , .os = \"linux\" },\n", + script_file.size, script_file.str); + fprintf(out, " { \"%.*s.sh\" , .os = \"mac\" }, }, },\n", + script_file.size, script_file.str); + fprintf(out, " { .name = \"run\",\n"); + fprintf(out, " .out = \"*run*\", .footer_panel = false, .save_dirty_files = false,\n"); + fprintf(out, " .cmd = { { \"%.*s\\\\%.*s\", .os = \"win\" },\n", + od_win.size, od_win.str, bf_win.size, bf_win.str); + fprintf(out, " { \"%.*s/%.*s\" , .os = \"linux\" },\n", + od.size, od.str, bf.size, bf.str); + fprintf(out, " { \"%.*s/%.*s\" , .os = \"mac\" }, }, },\n", + od.size, od.str, bf.size, bf.str); + fprintf(out, "};\n"); + + fprintf(out, "fkey_command[1] = \"build\";\n"); + fprintf(out, "fkey_command[2] = \"run\";\n"); + + fclose(out); + success = true; + } + + end_temp_memory(temp); + + return(success); +} + +static void +project_setup_scripts__generic(Application_Links *app, Partition *scratch, + bool32 do_project_file, + bool32 do_bat_script, + bool32 do_sh_script){ + Temp_Memory temp = begin_temp_memory(scratch); + String script_path = get_hot_directory(app, scratch); + + bool32 needs_to_do_work = false; + Project_Setup_Status status = {0}; + if (do_project_file){ + status = project_is_setup(app, scratch, script_path, make_lit_string("build")); + 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 + char script_file_space[1024]; + char code_file_space [1024]; + char output_dir_space [1024]; + char binary_file_space[1024]; + + bool32 get_script_file = !do_project_file; + bool32 get_code_file = + (do_bat_script && !status.bat_exists) || + (do_sh_script && !status.sh_exists); + + Project_Key_Strings keys = + project_key_strings_query_user(app, + get_script_file, get_code_file, + script_file_space, sizeof(script_file_space), + code_file_space, sizeof(code_file_space), + output_dir_space, sizeof(output_dir_space), + binary_file_space, sizeof(binary_file_space)); + + if (!keys.success){ + return; + } + + if (do_project_file){ + keys.script_file = make_lit_string("build"); + } + + if (!do_project_file){ + status = project_is_setup(app, scratch, script_path, keys.script_file); + } + + // Generate Scripts + if (do_bat_script){ + if (!status.bat_exists){ + if (!project_generate_bat_script(scratch, + global_config.default_flags_bat, + global_config.default_compiler_bat, + script_path, keys.script_file, + keys.code_file, keys.output_dir, keys.binary_file)){ + print_message(app, literal("could not create build.bat for new project\n")); + } + } + else{ + print_message(app, literal("the batch script already exists, no changes made to it\n")); + } + } + + if (do_sh_script){ + if (!status.bat_exists){ + if (!project_generate_sh_script(scratch, + global_config.default_flags_sh, + global_config.default_compiler_sh, + script_path, keys.script_file, + keys.code_file, keys.output_dir, keys.binary_file)){ + print_message(app, literal("could not create build.sh for new project\n")); + } + } + else{ + print_message(app, literal("the shell script already exists, no changes made to it\n")); + } + } + + if (do_project_file){ + if (!status.project_exists){ + if (!project_generate_project_4coder_file(scratch, script_path, keys.script_file, + keys.output_dir, keys.binary_file)){ + 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{ + if (do_project_file){ + print_message(app, literal("project already setup, no changes made\n")); + } + } + + end_temp_memory(temp); +} + 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.") { - 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", - global_config.default_flags_bat.size, - global_config.default_flags_bat.str); - fprintf(bat_script, "set code=%%cd%%\n"); - - fprintf(bat_script, "pushd %.*s\n", - output_dir.size, output_dir.str); - fprintf(bat_script, "%.*s %%opts%% %%code%%\\%.*s -Fe%.*s\n", - global_config.default_compiler_bat.size, - global_config.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"); - - fprintf(sh_script, "code=\"$PWD\"\n"); - - fprintf(sh_script, "opts=%.*s\n", - global_config.default_flags_sh.size, - global_config.default_flags_sh.str); - - fprintf(sh_script, "cd %.*s > /dev/null\n", - output_dir.size, output_dir.str); - fprintf(sh_script, "%.*s $opts $code/%.*s -o %.*s\n", - global_config.default_compiler_sh.size, - global_config.default_compiler_sh.str, - code_file.size, code_file.str, - binary_file.size, binary_file.str); - fprintf(sh_script, "cd $code > /dev/null\n"); - - 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, "\\\\", "/"); - - fprintf(project_script, "fkey_command_linux[1] = {\"./build.sh\", \"*compilation*\", true , true };\n"); - 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); - - fprintf(project_script, "fkey_command_mac[1] = {\"./build.sh\", \"*compilation*\", true , true };\n"); - 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")); - } - + project_setup_scripts__generic(app, &global_part, true, true, true); 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.") +{ + project_setup_scripts__generic(app, &global_part, false, true, false); +} + +CUSTOM_COMMAND_SIG(setup_build_sh) +CUSTOM_DOC("Queries the user for several configuration options and initializes a new build shell script.") +{ + project_setup_scripts__generic(app, &global_part, false, false, true); +} + +CUSTOM_COMMAND_SIG(setup_build_bat_and_sh) +CUSTOM_DOC("Queries the user for several configuration options and initializes a new build batch script.") +{ + project_setup_scripts__generic(app, &global_part, false, true, true); +} + // BOTTOM diff --git a/4coder_project_commands.h b/4coder_project_commands.h index 4e3b1955..7a9638f4 100644 --- a/4coder_project_commands.h +++ b/4coder_project_commands.h @@ -41,6 +41,7 @@ struct Project_Command{ String out; bool32 footer_panel; bool32 save_dirty_files; + bool32 cursor_at_end; }; struct Project_Command_Array{ @@ -76,6 +77,14 @@ struct Project_Setup_Status{ bool32 everything_exists; }; +struct Project_Key_Strings{ + bool32 success; + String script_file; + String code_file; + String output_dir; + String binary_file; +}; + #endif // BOTTOM diff --git a/4ed.cpp b/4ed.cpp index 484c9b15..90ac7a54 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -137,31 +137,31 @@ inline void output_file_append(System_Functions *system, Models *models, Editing_File *file, String value){ if (!file->is_dummy){ i32 end = buffer_size(&file->state.buffer); - edit_single(system, models, file, - end, end, value.str, value.size); + edit_single(system, models, file, end, end, value.str, value.size); + } +} + +internal void +file_cursor_to_end(System_Functions *system, Models *models, Editing_File *file){ + Assert(file != 0); + i32 pos = buffer_size(&file->state.buffer); + for (Panel *panel = models->layout.used_sentinel.next; + panel != &models->layout.used_sentinel; + panel = panel->next){ + View *view = panel->view; + if (view->transient.file_data.file != file){ + continue; + } + view_cursor_move(system, view, pos); } } inline void -do_feedback_message(System_Functions *system, Models *models, String value, b32 set_to_start = 0){ +do_feedback_message(System_Functions *system, Models *models, String value){ Editing_File *file = models->message_buffer; - if (file != 0){ output_file_append(system, models, file, value); - i32 pos = 0; - if (!set_to_start){ - pos = buffer_size(&file->state.buffer); - } - - for (Panel *panel = models->layout.used_sentinel.next; - panel != &models->layout.used_sentinel; - panel = panel->next){ - View *view = panel->view; - if (view->transient.file_data.file != file){ - continue; - } - view_cursor_move(system, view, pos); - } + file_cursor_to_end(system, models, file); } } @@ -1559,15 +1559,16 @@ App_Step_Sig(app_step){ CLI_Process *proc_ptr = list->procs; for (u32 i = 0; i < list->count; ++i, ++proc_ptr){ Editing_File *file = proc_ptr->out_file; - CLI_Handles *cli = &proc_ptr->cli; + b32 edited_file = false; u32 amount = 0; system->cli_begin_update(cli); if (system->cli_update_step(cli, dest, max, &amount)){ - if (file != 0){ + if (file != 0 && amount > 0){ amount = eol_in_place_convert_in(dest, amount); output_file_append(system, models, file, make_string(dest, amount)); + edited_file = true; } } @@ -1578,13 +1579,16 @@ App_Step_Sig(app_step){ append(&str, make_lit_string("exited with code ")); append_int_to_str(&str, cli->exit); output_file_append(system, models, file, str); + edited_file = true; } procs_to_free[proc_free_count++] = proc_ptr; } + + if (proc_ptr->cursor_at_end && file != 0){ + file_cursor_to_end(system, models, file); + } } - // TODO(allen): proc_ptr->cursor_at_end - for (i32 i = proc_free_count - 1; i >= 0; --i){ cli_list_free_proc(list, procs_to_free[i]); } diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 76b13f99..07aef51d 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -286,14 +286,6 @@ DOC_SEE(Command_Line_Interface_Flag) file = working_set_alloc_always(working_set, general); Assert(file != 0); -#if 0 - if (file == 0){ - append(&feedback_str, make_lit_string("ERROR: unable to allocate a new buffer\n")); - result = false; - goto done; - } -#endif - String name = push_string(part, buffer_id.name, buffer_id.name_len); buffer_bind_name(models, general, part, working_set, file, name); init_read_only_file(system, models, file); @@ -366,7 +358,10 @@ DOC_SEE(Command_Line_Interface_Flag) } // NOTE(allen): Attept to execute the command. - if (!cli_list_call(system, &vars->cli_processes, path_string.str, command_string.str, file, ((flags & CLI_CursorAtEnd) != 0))){ + char *path_str = path_string.str; + char *command_str = command_string.str; + b32 cursor_at_end = ((flags & CLI_CursorAtEnd) != 0); + if (!cli_list_call(system, &vars->cli_processes, path_str, command_str, file, cursor_at_end)){ append(&feedback_str, "ERROR: Failed to make the cli call\n"); result = false; } diff --git a/project.4coder b/project.4coder index b648a062..7983b281 100644 --- a/project.4coder +++ b/project.4coder @@ -26,7 +26,7 @@ build_x86_mac = "echo build: x86 & ./build.sh -DDEV_BUILD_X86"; command_list = { { .name = "build x64", - .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, + .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = true, .cmd = { {"echo build: x64 & build.bat" , .os = "win" }, {"echo build: x64 & ./build.sh", .os = "linux"}, {"echo build: x64 & ./build.sh", .os = "mac" }, }, },