From a1b0f805d157d328e20b01165029b320584d919c Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 17 Jul 2017 18:46:56 -0400 Subject: [PATCH] cleaned up the child process updating and CLI list managing --- 4coder_API/app_functions.h | 6 +- 4ed.cpp | 152 ++++++++++++--------------------- 4ed_api_implementation.cpp | 168 ++++++++++++++++++------------------- 4ed_app_target.cpp | 2 + 4ed_cli.cpp | 69 +++++++++++++++ 5 files changed, 208 insertions(+), 189 deletions(-) create mode 100644 4ed_cli.cpp diff --git a/4coder_API/app_functions.h b/4coder_API/app_functions.h index 89b2f12a..8ec1534c 100644 --- a/4coder_API/app_functions.h +++ b/4coder_API/app_functions.h @@ -1,7 +1,7 @@ struct Application_Links; #define GLOBAL_SET_SETTING_SIG(n) bool32 n(Application_Links *app, Global_Setting_ID setting, int32_t value) #define EXEC_COMMAND_SIG(n) bool32 n(Application_Links *app, Command_ID command_id) -#define EXEC_SYSTEM_COMMAND_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags) +#define EXEC_SYSTEM_COMMAND_SIG(n) bool32 n(Application_Links *app, View_Summary *view, Buffer_Identifier buffer_id, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags) #define CLIPBOARD_POST_SIG(n) void n(Application_Links *app, int32_t clipboard_id, char *str, int32_t len) #define CLIPBOARD_COUNT_SIG(n) int32_t n(Application_Links *app, int32_t clipboard_id) #define CLIPBOARD_INDEX_SIG(n) int32_t n(Application_Links *app, int32_t clipboard_id, int32_t item_index, char *out, int32_t len) @@ -394,7 +394,7 @@ app_links->send_exit_signal_ = Send_Exit_Signal;} while(false) #if defined(ALLOW_DEP_4CODER) static inline bool32 global_set_setting(Application_Links *app, Global_Setting_ID setting, int32_t value){return(app->global_set_setting(app, setting, value));} static inline bool32 exec_command(Application_Links *app, Command_ID command_id){return(app->exec_command(app, command_id));} -static inline bool32 exec_system_command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags){return(app->exec_system_command(app, view, buffer, path, path_len, command, command_len, flags));} +static inline bool32 exec_system_command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer_id, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags){return(app->exec_system_command(app, view, buffer_id, path, path_len, command, command_len, flags));} static inline void clipboard_post(Application_Links *app, int32_t clipboard_id, char *str, int32_t len){(app->clipboard_post(app, clipboard_id, str, len));} static inline int32_t clipboard_count(Application_Links *app, int32_t clipboard_id){return(app->clipboard_count(app, clipboard_id));} static inline int32_t clipboard_index(Application_Links *app, int32_t clipboard_id, int32_t item_index, char *out, int32_t len){return(app->clipboard_index(app, clipboard_id, item_index, out, len));} @@ -471,7 +471,7 @@ static inline void send_exit_signal(Application_Links *app){(app->send_exit_sign #else static inline bool32 global_set_setting(Application_Links *app, Global_Setting_ID setting, int32_t value){return(app->global_set_setting_(app, setting, value));} static inline bool32 exec_command(Application_Links *app, Command_ID command_id){return(app->exec_command_(app, command_id));} -static inline bool32 exec_system_command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags){return(app->exec_system_command_(app, view, buffer, path, path_len, command, command_len, flags));} +static inline bool32 exec_system_command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer_id, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags){return(app->exec_system_command_(app, view, buffer_id, path, path_len, command, command_len, flags));} static inline void clipboard_post(Application_Links *app, int32_t clipboard_id, char *str, int32_t len){(app->clipboard_post_(app, clipboard_id, str, len));} static inline int32_t clipboard_count(Application_Links *app, int32_t clipboard_id){return(app->clipboard_count_(app, clipboard_id));} static inline int32_t clipboard_index(Application_Links *app, int32_t clipboard_id, int32_t item_index, char *out, int32_t len){return(app->clipboard_index_(app, clipboard_id, item_index, out, len));} diff --git a/4ed.cpp b/4ed.cpp index 123413d3..06be0098 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -145,29 +145,18 @@ global_const char messages[] = #define DEFAULT_DISPLAY_WIDTH 672 #define DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH 550 -typedef enum App_State{ +enum App_State{ APP_STATE_EDIT, APP_STATE_RESIZING, // never below this APP_STATE_COUNT -} App_State; +}; -typedef struct App_State_Resizing{ +struct App_State_Resizing{ Panel_Divider *divider; -} App_State_Resizing; +}; -typedef struct CLI_Process{ - CLI_Handles cli; - Editing_File *out_file; - b32 cursor_at_end; -} CLI_Process; - -typedef struct CLI_List{ - CLI_Process *procs; - i32 count, max; -} CLI_List; - -typedef struct Command_Data{ +struct Command_Data{ Models *models; struct App_Vars *vars; System_Functions *system; @@ -175,9 +164,9 @@ typedef struct Command_Data{ i32 screen_width, screen_height; Key_Event_Data key; -} Command_Data; +}; -typedef enum Input_Types{ +enum Input_Types{ Input_AnyKey, Input_Esc, Input_MouseMove, @@ -185,18 +174,18 @@ typedef enum Input_Types{ Input_MouseRightButton, Input_MouseWheel, Input_Count -} Input_Types; +}; -typedef struct Consumption_Record{ +struct Consumption_Record{ b32 consumed; char consumer[32]; -} Consumption_Record; +}; -typedef struct Available_Input{ +struct Available_Input{ Key_Input_Data *keys; Mouse_State *mouse; Consumption_Record records[Input_Count]; -} Available_Input; +}; internal Available_Input init_available_input(Key_Input_Data *keys, Mouse_State *mouse){ @@ -297,14 +286,14 @@ struct App_Vars{ }; global_const App_Vars null_app_vars = {0}; -typedef enum Coroutine_Type{ +enum Coroutine_Type{ Co_View, Co_Command -} Coroutine_Type; -typedef struct App_Coroutine_State{ +}; +struct App_Coroutine_State{ void *co; i32 type; -} App_Coroutine_State; +}; inline App_Coroutine_State get_state(Application_Links *app){ @@ -1353,68 +1342,13 @@ App_Init_Sig(app_init){ hot_directory_init(&models->hot_directory, current_directory); // NOTE(allen): child proc list setup - i32 max_children = 16; - partition_align(partition, 8); - vars->cli_processes.procs = push_array(partition, CLI_Process, max_children); - vars->cli_processes.max = max_children; - vars->cli_processes.count = 0; + vars->cli_processes = make_cli_list(partition, 16); // NOTE(allen): init GUI keys models->user_up_key = key_up; models->user_down_key = key_down; } -internal i32 -update_cli_handle_without_file(System_Functions *system, Models *models, CLI_Handles *cli, char *dest, i32 max){ - i32 result = 0; - u32 amount = 0; - - system->cli_begin_update(cli); - if (system->cli_update_step(cli, dest, max, &amount)){ - result = 1; - } - - if (system->cli_end_update(cli)){ - result = -1; - } - - return(result); -} - -internal i32 -update_cli_handle_with_file(System_Functions *system, Models *models, CLI_Handles *cli, Editing_File *file, char *dest, i32 max, b32 cursor_at_end){ - i32 result = 0; - u32 amount = 0; - - system->cli_begin_update(cli); - if (system->cli_update_step(cli, dest, max, &amount)){ - amount = eol_in_place_convert_in(dest, amount); - output_file_append(system, models, file, make_string(dest, amount), cursor_at_end); - result = 1; - } - - if (system->cli_end_update(cli)){ - char str_space[256]; - String str = make_fixed_width_string(str_space); - append_ss(&str, make_lit_string("exited with code ")); - append_int_to_str(&str, cli->exit); - output_file_append(system, models, file, str, cursor_at_end); - result = -1; - } - - if (cursor_at_end){ - i32 new_cursor = buffer_size(&file->state.buffer); - for (View_Iter iter = file_view_iter_init(&models->layout, file, 0); - file_view_iter_good(iter); - iter = file_view_iter_next(iter)){ - view_cursor_move(system, iter.view, new_cursor); - } - } - - return(result); -} - - App_Step_Sig(app_step){ PRFL_BEGIN_FRAME(); @@ -1595,30 +1529,48 @@ App_Step_Sig(app_step){ // NOTE(allen): update child processes if (input->dt > 0){ - Temp_Memory temp = begin_temp_memory(&models->mem.part); - u32 max = KB(128); - char *dest = push_array(&models->mem.part, char, max); + Partition *scratch = &models->mem.part; - i32 count = vars->cli_processes.count; - for (i32 i = 0; i < count; ++i){ - CLI_Process *proc = vars->cli_processes.procs + i; - Editing_File *file = proc->out_file; + CLI_List *list = &vars->cli_processes; + + Temp_Memory temp = begin_temp_memory(&models->mem.part); + CLI_Process **procs_to_free = push_array(scratch, CLI_Process*, list->count); + u32 proc_free_count = 0; + + u32 max = KB(128); + char *dest = push_array(scratch, char, max); + + CLI_Process *proc_ptr = list->procs; + for (u32 i = 0; i < list->count; ++i, ++proc_ptr){ + Editing_File *file = proc_ptr->out_file; - if (file != 0){ - i32 r = update_cli_handle_with_file( - system, models, &proc->cli, file, dest, max, proc->cursor_at_end); - if (r < 0){ - *proc = vars->cli_processes.procs[--count]; - --i; + CLI_Handles *cli = &proc_ptr->cli; + + u32 amount = 0; + system->cli_begin_update(cli); + if (system->cli_update_step(cli, dest, max, &amount)){ + if (file != 0){ + amount = eol_in_place_convert_in(dest, amount); + output_file_append(system, models, file, make_string(dest, amount), proc_ptr->cursor_at_end); } } - else{ - update_cli_handle_without_file( - system, models, &proc->cli, dest, max); + + if (system->cli_end_update(cli)){ + if (file != 0){ + char str_space[256]; + String str = make_fixed_width_string(str_space); + append(&str, make_lit_string("exited with code ")); + append_int_to_str(&str, cli->exit); + output_file_append(system, models, file, str, proc_ptr->cursor_at_end); + } + procs_to_free[proc_free_count++] = proc_ptr; } } - vars->cli_processes.count = count; + for (u32 i = 0; i < proc_free_count; ++i){ + cli_list_free_proc(list, procs_to_free[i]); + } + end_temp_memory(temp); } diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 49bceab4..226e181f 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -216,10 +216,10 @@ DOC_SEE(Command_ID) // TODO(allen): This is a bit of a mess and needs to be fixed. API_EXPORT bool32 -Exec_System_Command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags) +Exec_System_Command(Application_Links *app, View_Summary *view, Buffer_Identifier buffer_id, char *path, int32_t path_len, char *command, int32_t command_len, Command_Line_Interface_Flag flags) /* DOC_PARAM(view, If the view parameter is non-null it specifies a view to display the command's output buffer, otherwise the command will still work but if there is a buffer capturing the output it will not automatically be displayed.) -DOC_PARAM(buffer, The buffer the command will output to is specified by the buffer parameter. See Buffer_Identifier for information on how this type specifies a buffer. The command will cause a crash if no buffer is specified.) +DOC_PARAM(buffer_id, The buffer the command will output to is specified by the buffer parameter. See Buffer_Identifier for information on how this type specifies a buffer. The command will cause a crash if no buffer is specified.) DOC_PARAM(path, The path parameter specifies the current working directory in which the command shall be executed. The string need not be null terminated.) DOC_PARAM(path_len, The parameter path_len specifies the length of the path string.) DOC_PARAM(command, The command parameter specifies the command that shall be executed. The string need not be null terminated.) @@ -239,63 +239,67 @@ DOC_SEE(Command_Line_Interface_Flag) System_Functions *system = cmd->system; App_Vars *vars = cmd->vars; Models *models = cmd->models; + Partition *part = &models->mem.part; + General_Memory *general = &models->mem.general; + Working_Set *working_set = &models->working_set; + bool32 result = true; char feedback_space[256]; String feedback_str = make_fixed_width_string(feedback_space); - Working_Set *working_set = &models->working_set; - CLI_Process *procs = vars->cli_processes.procs, *proc = 0; - Editing_File *file = 0; - b32 bind_to_new_view = true; - General_Memory *general = &models->mem.general; - - Partition *part = &models->mem.part; Temp_Memory temp = begin_temp_memory(part); - bool32 result = true; - - View *vptr = imp_get_view(cmd, view); - - if (vars->cli_processes.count < vars->cli_processes.max){ - file = get_file_from_identifier(system, working_set, buffer); + { + // NOTE(allen): Check that it is possible to store a new child process. + if (!cli_list_has_space(&vars->cli_processes)){ + append(&feedback_str, make_lit_string("ERROR: no available process slot\n")); + result = false; + goto done; + } - if (file){ + // NOTE(allen): Try to get the buffer that was specified if it exists. + Editing_File *file = get_file_from_identifier(system, working_set, buffer_id); + + // NOTE(allen): If the file exists check that it is legal. + if (file != 0){ if (file->settings.read_only == 0){ - append_ss(&feedback_str, make_lit_string("ERROR: ")); - append_ss(&feedback_str, file->name.live_name); - append_ss(&feedback_str, make_lit_string(" is not a read-only buffer\n")); - do_feedback_message(system, models, feedback_str); + append(&feedback_str, make_lit_string("ERROR: ")); + append(&feedback_str, file->name.live_name); + append(&feedback_str, make_lit_string(" is not a read-only buffer\n")); result = false; goto done; } if (file->settings.never_kill){ - append_ss(&feedback_str, make_lit_string("The buffer ")); - append_ss(&feedback_str, file->name.live_name); - append_ss(&feedback_str, make_lit_string(" is not killable")); - do_feedback_message(system, models, feedback_str); + append(&feedback_str, make_lit_string("ERROR: The buffer ")); + append(&feedback_str, file->name.live_name); + append(&feedback_str, make_lit_string(" is not killable")); result = false; goto done; } } - else if (buffer.name){ + + // NOTE(allen): If the buffer is specified by name but does not already exist, then create it. + if (file == 0 && buffer_id.name){ file = working_set_alloc_always(working_set, general); if (file == 0){ - append_ss(&feedback_str, make_lit_string("ERROR: unable to allocate a new buffer\n")); - do_feedback_message(system, models, feedback_str); + append(&feedback_str, make_lit_string("ERROR: unable to allocate a new buffer\n")); result = false; goto done; } - String name = make_string_terminated(part, buffer.name, buffer.name_len); + + String name = make_string_terminated(part, buffer_id.name, buffer_id.name_len); buffer_bind_name(general, working_set, file, name); init_read_only_file(system, models, file); } + // NOTE(allen): If there are conflicts in output buffer with an existing child process resolve it. if (file != 0){ - i32 proc_count = vars->cli_processes.count; - for (i32 i = 0; i < proc_count; ++i){ - if (procs[i].out_file == file){ + CLI_List *list = &vars->cli_processes; + CLI_Process *proc_ptr = list->procs; + for (u32 i = 0; i < list->count; ++i, ++proc_ptr){ + if (proc_ptr->out_file == file){ if (flags & CLI_OverlapWithConflict){ - procs[i].out_file = 0; + proc_ptr->out_file = 0; } else{ file = 0; @@ -304,30 +308,41 @@ DOC_SEE(Command_Line_Interface_Flag) } } - if (file){ - file_clear(system, models, file); - file->settings.unimportant = true; - - if (!(flags & CLI_AlwaysBindToView)){ - View_Iter iter = file_view_iter_init(&models->layout, file, 0); - if (file_view_iter_good(iter)){ - bind_to_new_view = false; - } - } - } - else{ -#define MSG "did not begin command-line command because the target buffer is already in use\n" - String msg = make_lit_string(MSG); -#undef MSG - append_ss(&feedback_str, msg); - do_feedback_message(system, models, feedback_str); + if (file == 0){ + append(&feedback_str, "did not begin command-line command because the target buffer is already in use\n"); result = false; goto done; } } + // NOTE(allen): If we have an output file, prepare it for child proc output. + if (file != 0){ + file_clear(system, models, file); + file->settings.unimportant = true; + } + + // NOTE(allen): If we have an output file and we need to bring it up in a new view, do so. + if (file != 0){ + b32 bind_to_new_view = true; + if (!(flags & CLI_AlwaysBindToView)){ + View_Iter iter = file_view_iter_init(&models->layout, file, 0); + if (file_view_iter_good(iter)){ + bind_to_new_view = false; + } + } + + if (bind_to_new_view){ + View *vptr = imp_get_view(cmd, view); + if (vptr != 0){ + view_set_file(system, vptr, file, models); + view_show_file(vptr); + } + } + } + + // NOTE(allen): Figure out the root path for the command. String path_string = {0}; - if (!path){ + if (path == 0){ terminate_with_null(&models->hot_directory.string); path_string = models->hot_directory.string; } @@ -335,46 +350,27 @@ DOC_SEE(Command_Line_Interface_Flag) path_string = make_string_terminated(part, path, path_len); } - { - String command_string = {0}; - - if (!command){ -#define NO_SCRIPT " echo no script specified" - command_string.str = NO_SCRIPT; - command_string.size = sizeof(NO_SCRIPT)-1; -#undef NO_SCRIPT - } - else{ - command_string = make_string_terminated(part, command, command_len); - } - - if (vptr != 0 && bind_to_new_view){ - view_set_file(system, vptr, file, models); - view_show_file(vptr); - } - - proc = procs + vars->cli_processes.count++; - proc->out_file = file; - if (flags & CLI_CursorAtEnd){ - proc->cursor_at_end = 1; - } - else{ - proc->cursor_at_end = 0; - } - - if (!system->cli_call(path_string.str, command_string.str, &proc->cli)){ - --vars->cli_processes.count; - } + // NOTE(allen): Figure out the command string. + String command_string = {0}; + if (command == 0){ + command_string = make_lit_string(" echo no script specified"); + } + else{ + command_string = make_string_terminated(part, command, command_len); + } + + // 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))){ + append(&feedback_str, "ERROR: Failed to make the cli call\n"); + result = false; } - } - else{ - append_ss(&feedback_str, make_lit_string("ERROR: no available process slot\n")); - do_feedback_message(system, models, feedback_str); - result = false; - goto done; } done:; + if (!result){ + do_feedback_message(system, models, feedback_str); + } + end_temp_memory(temp); return(result); } diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 33e3fc28..5fd112a6 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -57,6 +57,8 @@ #include "4ed_hot_directory.cpp" #include "4ed_parse_contexts.cpp" +#include "4ed_cli.cpp" + #include "4ed_gui.h" #include "4ed_gui.cpp" #include "4ed_layout.cpp" diff --git a/4ed_cli.cpp b/4ed_cli.cpp new file mode 100644 index 00000000..8b4d6ae2 --- /dev/null +++ b/4ed_cli.cpp @@ -0,0 +1,69 @@ +/* + * Mr. 4th Dimention - Allen Webster + * + * 17.07.2017 + * + * CLI handling code. + * + */ + +// TOP + +#if !defined(FRED_CLI_CPP) +#define FRED_CLI_CPP + +struct CLI_Process{ + CLI_Handles cli; + Editing_File *out_file; + b32 cursor_at_end; +}; + +struct CLI_List{ + CLI_Process *procs; + u32 count; + u32 max; +}; + +inline CLI_List +make_cli_list(Partition *part, u32 max){ + CLI_List list = {0}; + partition_align(part, 8); + list.procs = push_array(part, CLI_Process, max); + list.max = max; + return(list); +} + +inline b32 +cli_list_call(System_Functions *system, CLI_List *list, char *path, char *command, Editing_File *file, b32 cursor_at_end){ + b32 result = false; + + if (list->count < list->max){ + CLI_Process *proc = &list->procs[list->count++]; + proc->out_file = file; + proc->cursor_at_end = cursor_at_end; + result = system->cli_call(path, command, &proc->cli); + if (!result){ + --list->count; + } + } + + return(result); +} + +inline void +cli_list_free_proc(CLI_List *list, CLI_Process *proc){ + Assert(proc >= list->procs); + Assert(proc < list->procs + list->count); + *proc = list->procs[--list->count]; +} + +inline b32 +cli_list_has_space(CLI_List *list){ + b32 has_space = (list->count < list->max); + return(has_space); +} + +#endif + +// BOTTOM +