cleaned up the child process updating and CLI list managing

This commit is contained in:
Allen Webster 2017-07-17 18:46:56 -04:00
parent bd2ef80f30
commit a1b0f805d1
5 changed files with 208 additions and 189 deletions

View File

@ -1,7 +1,7 @@
struct Application_Links; struct Application_Links;
#define GLOBAL_SET_SETTING_SIG(n) bool32 n(Application_Links *app, Global_Setting_ID setting, int32_t value) #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_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_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_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) #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) #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 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_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 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_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));} 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 #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 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_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 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_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));} 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));}

150
4ed.cpp
View File

@ -145,29 +145,18 @@ global_const char messages[] =
#define DEFAULT_DISPLAY_WIDTH 672 #define DEFAULT_DISPLAY_WIDTH 672
#define DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH 550 #define DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH 550
typedef enum App_State{ enum App_State{
APP_STATE_EDIT, APP_STATE_EDIT,
APP_STATE_RESIZING, APP_STATE_RESIZING,
// never below this // never below this
APP_STATE_COUNT APP_STATE_COUNT
} App_State; };
typedef struct App_State_Resizing{ struct App_State_Resizing{
Panel_Divider *divider; Panel_Divider *divider;
} App_State_Resizing; };
typedef struct CLI_Process{ struct Command_Data{
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{
Models *models; Models *models;
struct App_Vars *vars; struct App_Vars *vars;
System_Functions *system; System_Functions *system;
@ -175,9 +164,9 @@ typedef struct Command_Data{
i32 screen_width, screen_height; i32 screen_width, screen_height;
Key_Event_Data key; Key_Event_Data key;
} Command_Data; };
typedef enum Input_Types{ enum Input_Types{
Input_AnyKey, Input_AnyKey,
Input_Esc, Input_Esc,
Input_MouseMove, Input_MouseMove,
@ -185,18 +174,18 @@ typedef enum Input_Types{
Input_MouseRightButton, Input_MouseRightButton,
Input_MouseWheel, Input_MouseWheel,
Input_Count Input_Count
} Input_Types; };
typedef struct Consumption_Record{ struct Consumption_Record{
b32 consumed; b32 consumed;
char consumer[32]; char consumer[32];
} Consumption_Record; };
typedef struct Available_Input{ struct Available_Input{
Key_Input_Data *keys; Key_Input_Data *keys;
Mouse_State *mouse; Mouse_State *mouse;
Consumption_Record records[Input_Count]; Consumption_Record records[Input_Count];
} Available_Input; };
internal Available_Input internal Available_Input
init_available_input(Key_Input_Data *keys, Mouse_State *mouse){ 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}; global_const App_Vars null_app_vars = {0};
typedef enum Coroutine_Type{ enum Coroutine_Type{
Co_View, Co_View,
Co_Command Co_Command
} Coroutine_Type; };
typedef struct App_Coroutine_State{ struct App_Coroutine_State{
void *co; void *co;
i32 type; i32 type;
} App_Coroutine_State; };
inline App_Coroutine_State inline App_Coroutine_State
get_state(Application_Links *app){ get_state(Application_Links *app){
@ -1353,68 +1342,13 @@ App_Init_Sig(app_init){
hot_directory_init(&models->hot_directory, current_directory); hot_directory_init(&models->hot_directory, current_directory);
// NOTE(allen): child proc list setup // NOTE(allen): child proc list setup
i32 max_children = 16; vars->cli_processes = make_cli_list(partition, 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;
// NOTE(allen): init GUI keys // NOTE(allen): init GUI keys
models->user_up_key = key_up; models->user_up_key = key_up;
models->user_down_key = key_down; 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){ App_Step_Sig(app_step){
PRFL_BEGIN_FRAME(); PRFL_BEGIN_FRAME();
@ -1595,30 +1529,48 @@ App_Step_Sig(app_step){
// NOTE(allen): update child processes // NOTE(allen): update child processes
if (input->dt > 0){ if (input->dt > 0){
Partition *scratch = &models->mem.part;
CLI_List *list = &vars->cli_processes;
Temp_Memory temp = begin_temp_memory(&models->mem.part); 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); u32 max = KB(128);
char *dest = push_array(&models->mem.part, char, max); char *dest = push_array(scratch, char, max);
i32 count = vars->cli_processes.count; CLI_Process *proc_ptr = list->procs;
for (i32 i = 0; i < count; ++i){ for (u32 i = 0; i < list->count; ++i, ++proc_ptr){
CLI_Process *proc = vars->cli_processes.procs + i; Editing_File *file = proc_ptr->out_file;
Editing_File *file = proc->out_file;
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){ if (file != 0){
i32 r = update_cli_handle_with_file( amount = eol_in_place_convert_in(dest, amount);
system, models, &proc->cli, file, dest, max, proc->cursor_at_end); output_file_append(system, models, file, make_string(dest, amount), proc_ptr->cursor_at_end);
if (r < 0){
*proc = vars->cli_processes.procs[--count];
--i;
}
}
else{
update_cli_handle_without_file(
system, models, &proc->cli, dest, max);
} }
} }
vars->cli_processes.count = count; 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;
}
}
for (u32 i = 0; i < proc_free_count; ++i){
cli_list_free_proc(list, procs_to_free[i]);
}
end_temp_memory(temp); end_temp_memory(temp);
} }

View File

@ -216,10 +216,10 @@ DOC_SEE(Command_ID)
// TODO(allen): This is a bit of a mess and needs to be fixed. // TODO(allen): This is a bit of a mess and needs to be fixed.
API_EXPORT bool32 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(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, 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(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.) 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; System_Functions *system = cmd->system;
App_Vars *vars = cmd->vars; App_Vars *vars = cmd->vars;
Models *models = cmd->models; 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]; char feedback_space[256];
String feedback_str = make_fixed_width_string(feedback_space); 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); Temp_Memory temp = begin_temp_memory(part);
bool32 result = true; {
// 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;
}
View *vptr = imp_get_view(cmd, view); // 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);
if (vars->cli_processes.count < vars->cli_processes.max){ // NOTE(allen): If the file exists check that it is legal.
file = get_file_from_identifier(system, working_set, buffer); if (file != 0){
if (file){
if (file->settings.read_only == 0){ if (file->settings.read_only == 0){
append_ss(&feedback_str, make_lit_string("ERROR: ")); append(&feedback_str, make_lit_string("ERROR: "));
append_ss(&feedback_str, file->name.live_name); append(&feedback_str, file->name.live_name);
append_ss(&feedback_str, make_lit_string(" is not a read-only buffer\n")); append(&feedback_str, make_lit_string(" is not a read-only buffer\n"));
do_feedback_message(system, models, feedback_str);
result = false; result = false;
goto done; goto done;
} }
if (file->settings.never_kill){ if (file->settings.never_kill){
append_ss(&feedback_str, make_lit_string("The buffer ")); append(&feedback_str, make_lit_string("ERROR: The buffer "));
append_ss(&feedback_str, file->name.live_name); append(&feedback_str, file->name.live_name);
append_ss(&feedback_str, make_lit_string(" is not killable")); append(&feedback_str, make_lit_string(" is not killable"));
do_feedback_message(system, models, feedback_str);
result = false; result = false;
goto done; 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); file = working_set_alloc_always(working_set, general);
if (file == 0){ if (file == 0){
append_ss(&feedback_str, make_lit_string("ERROR: unable to allocate a new buffer\n")); append(&feedback_str, make_lit_string("ERROR: unable to allocate a new buffer\n"));
do_feedback_message(system, models, feedback_str);
result = false; result = false;
goto done; 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); buffer_bind_name(general, working_set, file, name);
init_read_only_file(system, models, file); 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){ if (file != 0){
i32 proc_count = vars->cli_processes.count; CLI_List *list = &vars->cli_processes;
for (i32 i = 0; i < proc_count; ++i){ CLI_Process *proc_ptr = list->procs;
if (procs[i].out_file == file){ for (u32 i = 0; i < list->count; ++i, ++proc_ptr){
if (proc_ptr->out_file == file){
if (flags & CLI_OverlapWithConflict){ if (flags & CLI_OverlapWithConflict){
procs[i].out_file = 0; proc_ptr->out_file = 0;
} }
else{ else{
file = 0; file = 0;
@ -304,30 +308,41 @@ DOC_SEE(Command_Line_Interface_Flag)
} }
} }
if (file){ 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_clear(system, models, file);
file->settings.unimportant = true; 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)){ if (!(flags & CLI_AlwaysBindToView)){
View_Iter iter = file_view_iter_init(&models->layout, file, 0); View_Iter iter = file_view_iter_init(&models->layout, file, 0);
if (file_view_iter_good(iter)){ if (file_view_iter_good(iter)){
bind_to_new_view = false; 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);
} }
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);
result = false;
goto done;
} }
} }
// NOTE(allen): Figure out the root path for the command.
String path_string = {0}; String path_string = {0};
if (!path){ if (path == 0){
terminate_with_null(&models->hot_directory.string); terminate_with_null(&models->hot_directory.string);
path_string = 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); path_string = make_string_terminated(part, path, path_len);
} }
{ // NOTE(allen): Figure out the command string.
String command_string = {0}; String command_string = {0};
if (command == 0){
if (!command){ command_string = make_lit_string(" echo no script specified");
#define NO_SCRIPT " echo no script specified"
command_string.str = NO_SCRIPT;
command_string.size = sizeof(NO_SCRIPT)-1;
#undef NO_SCRIPT
} }
else{ else{
command_string = make_string_terminated(part, command, command_len); command_string = make_string_terminated(part, command, command_len);
} }
if (vptr != 0 && bind_to_new_view){ // NOTE(allen): Attept to execute the command.
view_set_file(system, vptr, file, models); if (!cli_list_call(system, &vars->cli_processes, path_string.str, command_string.str, file, ((flags & CLI_CursorAtEnd) != 0))){
view_show_file(vptr); append(&feedback_str, "ERROR: Failed to make the cli call\n");
}
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;
}
}
}
else{
append_ss(&feedback_str, make_lit_string("ERROR: no available process slot\n"));
do_feedback_message(system, models, feedback_str);
result = false; result = false;
goto done; }
} }
done:; done:;
if (!result){
do_feedback_message(system, models, feedback_str);
}
end_temp_memory(temp); end_temp_memory(temp);
return(result); return(result);
} }

View File

@ -57,6 +57,8 @@
#include "4ed_hot_directory.cpp" #include "4ed_hot_directory.cpp"
#include "4ed_parse_contexts.cpp" #include "4ed_parse_contexts.cpp"
#include "4ed_cli.cpp"
#include "4ed_gui.h" #include "4ed_gui.h"
#include "4ed_gui.cpp" #include "4ed_gui.cpp"
#include "4ed_layout.cpp" #include "4ed_layout.cpp"

69
4ed_cli.cpp Normal file
View File

@ -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