diff --git a/4coder_API.html b/4coder_API.html index 9084e3f2..f42a4e1a 100644 --- a/4coder_API.html +++ b/4coder_API.html @@ -19,7 +19,7 @@ li:before { content: "4"; color: #005000; font-family:"Webdings"; }

§1 Introduction

-This is the documentation for alpha 4.0.8 super! The documentation has been made as accurate as possible but there may be errors. If you have questions or discover errors please contact editor@4coder.net.

+This is the documentation for alpha 4.0.9 super! The documentation has been made as accurate as possible but there may be errors. If you have questions or discover errors please contact editor@4coder.net.

@@ -93,6 +93,9 @@ This is the documentation for alpha 4.0.8 super! The documentation has been made set_active_view
  • +view_set_split_proportion +
  • +
  • view_compute_cursor
  • @@ -364,21 +367,21 @@ should not be killed durring a buffer loop.
    Parameters
    buffer
    -
    the buffer to read out of
    +
    The buffer to be read.
    start
    -
    the beginning of the read range
    +
    The beginning of the read range.
    end
    -
    one past the end of the read range
    +
    One past the end of the read range.
    out
    -
    the output buffer to fill with the result of the read
    +
    The output buffer to fill with the result of the read.
    -
    Return
    returns non-zero on success
    Description
    The output buffer must have a capacity of at least (end - start) +
    Return
    Returns non-zero on success.
    Description
    The output buffer must have a capacity of at least (end - start). The output is not null terminated. This call fails if the buffer does not exist, or if the read range @@ -595,26 +598,40 @@ Views should not be closed or opened durring a view loop.
    Return
    returns non-zero on success
    Description
    If the given view is a currently open view, it is set as the active view, and takes subsequent commands and is returned from get_active_view.
    See Also
    get_active_view

    +
    +

    §2.2.22: view_set_split_proportion

    +
    int app->view_set_split_proportion( +
    Application_Links *app,
    View_Summary *view,
    float t
    ) +
    +
    Parameters
    +
    view
    +
    The view on which to adjust size.
    +
    +
    +
    t
    +
    The proportion of the view's containing box that it should occupy in [0,1]
    +
    +
    Return
    Returns non-zero on success.

    -

    §2.2.22: view_compute_cursor

    +

    §2.2.23: view_compute_cursor

    int app->view_compute_cursor(
    Application_Links *app,
    View_Summary *view,
    Buffer_Seek seek,
    Full_Cursor *cursor_out
    )
    Parameters
    view
    -
    the view on which to run the cursor computation
    +
    The view on which to run the cursor computation.
    seek
    -
    the seek position
    +
    The seek position.
    cursor_out
    -
    on success this is filled with result of the seek
    +
    On success this is filled with result of the seek.
    -
    Return
    returns non-zero on success
    Description
    Computes a full cursor for the given seek position.
    See Also
    Buffer_Seek

    +
    Return
    Returns non-zero on success.
    Description
    Computes a full cursor for the given seek position.
    See Also
    Buffer_Seek

    -

    §2.2.23: view_set_cursor

    +

    §2.2.24: view_set_cursor

    int app->view_set_cursor(
    Application_Links *app,
    View_Summary *view,
    Buffer_Seek seek,
    int set_preferred_x
    )
    @@ -633,7 +650,7 @@ from get_active_view.
    Return
    returns non-zero on success
    Description
    Sets the the view's cursor position. set_preferred_x should usually be true unless the change in cursor position is is a vertical motion that tries to keep the cursor in the same column or x position.
    See Also
    Buffer_Seek

    -

    §2.2.24: view_set_mark

    +

    §2.2.25: view_set_mark

    int app->view_set_mark(
    Application_Links *app,
    View_Summary *view,
    Buffer_Seek seek
    )
    @@ -647,7 +664,7 @@ cursor position is is a vertical motion that tries to keep the cursor in the sam
    Return
    returns non-zero on success
    Description
    Sets the the view's mark position.
    See Also
    Buffer_Seek

    -

    §2.2.25: view_set_highlight

    +

    §2.2.26: view_set_highlight

    int app->view_set_highlight(
    Application_Links *app,
    View_Summary *view,
    int start,
    int end,
    int turn_on
    )
    @@ -672,7 +689,7 @@ is set to true the highlight will be shown and the cursor will be hidden. After that either setting the with view_set_cursor or calling view_set_highlight and the turn_on set to false, will switch back to showing the cursor.

    -

    §2.2.26: view_set_buffer

    +

    §2.2.27: view_set_buffer

    int app->view_set_buffer(
    Application_Links *app,
    View_Summary *view,
    int buffer_id,
    unsigned int flags
    )
    @@ -691,7 +708,7 @@ the turn_on set to false, will switch back to showing the cursor.

    Return
    returns non-zero on success
    Description
    On success view_set_buffer sets the specified view's current buffer and cancels and dialogue shown in the view and displays the file.
    See Also
    Set_Buffer_Flag

    -

    §2.2.27: view_post_fade

    +

    §2.2.28: view_post_fade

    int app->view_post_fade(
    Application_Links *app,
    View_Summary *view,
    float seconds,
    int start,
    int end,
    unsigned int color
    )
    @@ -717,21 +734,21 @@ cancels and dialogue shown in the view and displays the file.
    -

    §2.2.28: view_set_paste_rewrite_

    +

    §2.2.29: view_set_paste_rewrite_

    void app->view_set_paste_rewrite_(
    Application_Links *app,
    View_Summary *view
    )
    No documentation generated for this function, assume it is non-public.

    -

    §2.2.29: view_get_paste_rewrite_

    +

    §2.2.30: view_get_paste_rewrite_

    int app->view_get_paste_rewrite_(
    Application_Links *app,
    View_Summary *view
    )
    No documentation generated for this function, assume it is non-public.

    -

    §2.2.30: get_user_input

    +

    §2.2.31: get_user_input

    User_Input app->get_user_input(
    Application_Links *app,
    unsigned int get_type,
    unsigned int abort_type
    )
    @@ -749,19 +766,19 @@ command is executed an abort signal is returned. If an abort signal is ever ret command should finish execution without any more calls that preempt the command. If a get condition is met the user input is returned
    See Also
    Input_Type_Flag
    User_Input

    -

    §2.2.31: get_command_input

    +

    §2.2.32: get_command_input

    User_Input app->get_command_input(
    Application_Links *app
    )
    Return
    returns the input that triggered the command in execution.
    See Also
    User_Input

    -

    §2.2.32: get_mouse_state

    +

    §2.2.33: get_mouse_state

    Mouse_State app->get_mouse_state(
    Application_Links *app
    )
    Return
    returns the current mouse state
    See Also
    Mouse_State

    -

    §2.2.33: start_query_bar

    +

    §2.2.34: start_query_bar

    int app->start_query_bar(
    Application_Links *app,
    Query_Bar *bar,
    unsigned int flags
    )
    @@ -776,7 +793,7 @@ If a get condition is met the user input is returned
    Return
    returns non-zero on success
    Description
    The memory pointed to by bar must remain valid until a call to end_query_bar or until the command returns.

    -

    §2.2.34: end_query_bar

    +

    §2.2.35: end_query_bar

    void app->end_query_bar(
    Application_Links *app,
    Query_Bar *bar,
    unsigned int flags
    )
    @@ -790,7 +807,7 @@ until the command returns.

    Description
    bar must be a pointer previously passed to start_query_bar previously in the same command.



    -

    §2.2.36: change_theme

    +

    §2.2.37: change_theme

    void app->change_theme(
    Application_Links *app,
    char *name,
    int len
    )
    @@ -818,7 +835,7 @@ until the command returns.


    -

    §2.2.37: change_font

    +

    §2.2.38: change_font

    void app->change_font(
    Application_Links *app,
    char *name,
    int len
    )
    @@ -832,7 +849,7 @@ until the command returns.


    -

    §2.2.38: set_theme_colors

    +

    §2.2.39: set_theme_colors

    void app->set_theme_colors(
    Application_Links *app,
    Theme_Color *colors,
    int count
    )
    @@ -847,7 +864,7 @@ until the command returns.

    Description
    For each color struct in the array, the color in the style pallet is set to the color code paired with the tag.

    -

    §2.2.39: get_theme_colors

    +

    §2.2.40: get_theme_colors

    void app->get_theme_colors(
    Application_Links *app,
    Theme_Color *colors,
    int count
    )
    @@ -862,7 +879,7 @@ code paired with the tag.

    Description
    For each color struct in the array, the color field of the struct is filled with the color from the specified color in the pallet.

    -

    §2.2.40: directory_get_hot

    +

    §2.2.41: directory_get_hot

    int app->directory_get_hot(
    Application_Links *app,
    char *out,
    int capacity
    )
    @@ -880,7 +897,7 @@ accessed in the GUI. Whenever the GUI is opened it shows the hot directory. In the future this will be deprecated and eliminated in favor of more flexible directories controlled by the custom side.

    -

    §2.2.41: get_file_list

    +

    §2.2.42: get_file_list

    File_List app->get_file_list(
    Application_Links *app,
    char *dir,
    int len
    )
    @@ -896,7 +913,7 @@ directories controlled by the custom side.

    the specified directory. The File_List returned should be passed to free_file_list when it is no longer in use.
    -

    §2.2.42: free_file_list

    +

    §2.2.43: free_file_list

    void app->free_file_list(
    Application_Links *app,
    File_List list
    )
    @@ -906,7 +923,7 @@ when it is no longer in use.

    Description
    after this call the file list passed in should not be read or written to

    -

    §2.2.43: file_exists

    +

    §2.2.44: file_exists

    int app->file_exists(
    Application_Links *app,
    char *filename,
    int len
    )
    @@ -920,7 +937,7 @@ when it is no longer in use.

    Return
    returns non-zero if the file exists, returns zero if the file does not exist

    -

    §2.2.44: directory_cd

    +

    §2.2.45: directory_cd

    int app->directory_cd(
    Application_Links *app,
    char *dir,
    int *len,
    int capacity,
    char *rel_path,
    int rel_len
    )
    @@ -952,7 +969,7 @@ For instance if dir contains "C:/Users/MySelf" and rel is "Documents" the buffer "C:/Users/MySelf/Documents" and len will contain the length of that string. This call can also be used with rel set to ".." to traverse to parent folders.

    -

    §2.2.45: get_4ed_path

    +

    §2.2.46: get_4ed_path

    int app->get_4ed_path(
    Application_Links *app,
    char *out,
    int capacity
    )
    diff --git a/4coder_custom_api.h b/4coder_custom_api.h index 652826ba..803df366 100644 --- a/4coder_custom_api.h +++ b/4coder_custom_api.h @@ -20,6 +20,7 @@ #define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int view_id, unsigned int access) #define GET_ACTIVE_VIEW_SIG(n) View_Summary n(Application_Links *app, unsigned int access) #define SET_ACTIVE_VIEW_SIG(n) int n(Application_Links *app, View_Summary *view) +#define VIEW_SET_SPLIT_PROPORTION_SIG(n) int n(Application_Links *app, View_Summary *view, float t) #define VIEW_COMPUTE_CURSOR_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Seek seek, Full_Cursor *cursor_out) #define VIEW_SET_CURSOR_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Seek seek, int set_preferred_x) #define VIEW_SET_MARK_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Seek seek) @@ -67,6 +68,7 @@ extern "C"{ typedef GET_VIEW_SIG(Get_View_Function); typedef GET_ACTIVE_VIEW_SIG(Get_Active_View_Function); typedef SET_ACTIVE_VIEW_SIG(Set_Active_View_Function); + typedef VIEW_SET_SPLIT_PROPORTION_SIG(View_Set_Split_Proportion_Function); typedef VIEW_COMPUTE_CURSOR_SIG(View_Compute_Cursor_Function); typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function); typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function); @@ -117,6 +119,7 @@ struct Application_Links{ Get_View_Function *get_view; Get_Active_View_Function *get_active_view; Set_Active_View_Function *set_active_view; + View_Set_Split_Proportion_Function *view_set_split_proportion; View_Compute_Cursor_Function *view_compute_cursor; View_Set_Cursor_Function *view_set_cursor; View_Set_Mark_Function *view_set_mark; @@ -169,6 +172,7 @@ app_links->get_view_next = Get_View_Next;\ app_links->get_view = Get_View;\ app_links->get_active_view = Get_Active_View;\ app_links->set_active_view = Set_Active_View;\ +app_links->view_set_split_proportion = View_Set_Split_Proportion;\ app_links->view_compute_cursor = View_Compute_Cursor;\ app_links->view_set_cursor = View_Set_Cursor;\ app_links->view_set_mark = View_Set_Mark;\ diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index da094bfe..8337d8b9 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -1,8 +1,10 @@ // TOP +#ifndef FCODER_DEFAULT_BINDINGS +#define FCODER_DEFAULT_BINDINGS + #include "4coder_default_include.cpp" -#include "4coder_default_building.cpp" // NOTE(allen|a3.3): All of your custom ids should be enumerated // as shown here, they may start at 0, and you can only have @@ -191,7 +193,7 @@ default_keys(Bind_Helper *context){ bind(context, 'P', MDFR_CTRL, cmdid_close_panel); bind(context, 'n', MDFR_CTRL, cmdid_interactive_new); bind(context, 'o', MDFR_CTRL, cmdid_interactive_open); - bind(context, ',', MDFR_CTRL, change_active_panel_skip_build); + bind(context, ',', MDFR_CTRL, change_active_panel); bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_buffer); bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer); bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker); @@ -199,17 +201,11 @@ default_keys(Bind_Helper *context){ bind(context, 'o', MDFR_ALT, open_in_other); bind(context, 'w', MDFR_CTRL, save_as); - bind(context, 'm', MDFR_ALT, build_in_build_panel); - bind(context, ',', MDFR_ALT, close_build_panel); + bind(context, 'm', MDFR_ALT, build_search); bind(context, 'x', MDFR_ALT, execute_arbitrary_command); bind(context, 'z', MDFR_ALT, execute_any_cli); bind(context, 'Z', MDFR_ALT, execute_previous_cli); - // NOTE(allen): These callbacks may not actually be useful to you, but - // go look at them and see what they do. - bind(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files); - bind(context, 'M', MDFR_ALT, build_at_launch_location); - end_map(context); begin_map(context, my_code_map); @@ -241,7 +237,7 @@ default_keys(Bind_Helper *context){ bind(context, '=', MDFR_CTRL, write_increment); bind(context, 't', MDFR_ALT, write_allen_todo); - bind(context, 'n', MDFR_ALT, write_allen_note); + bind(context, 'y', MDFR_ALT, write_allen_note); bind(context, '[', MDFR_CTRL, open_long_braces); bind(context, '{', MDFR_CTRL, open_long_braces_semicolon); bind(context, '}', MDFR_CTRL, open_long_braces_break); @@ -350,6 +346,8 @@ get_bindings(void *data, int size){ return(result); } -#endif +#endif //NO_BINDING + +#endif //FCODER_DEFAULT_BINDINGS // BOTTOM diff --git a/4coder_default_building.cpp b/4coder_default_building.cpp deleted file mode 100644 index d59efca4..00000000 --- a/4coder_default_building.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -#include "4coder_custom.h" - -#define FCPP_STRING_IMPLEMENTATION -#include "4coder_string.h" - -#include "4coder_helper.h" - -CUSTOM_COMMAND_SIG(build_search){ - // NOTE(allen|a3.3): An example of traversing the filesystem through parent - // directories looking for a file, in this case a batch file to execute. - // - // - // Step 1: Grab all of the user memory (or, you know, less if you've got better - // thing to do with some of it). Make a string and store the hot directory in it. - // - // Step 2: app->file_exists queries the file system to see if "/build.bat" exists. - // If it does exist several parameters are pushed and cmdid_command_line is executed: - // - par_flags: flags for specifiying behaviors - // CLI_OverlapWithConflict - (on by default) if another CLI is still using the output buffer - // that process is detached from the buffer and this process executes outputing to the buffer - // CLI_AlwaysBindToView - if set, the current view always switches to the output buffer - // even if the output buffer is open in another view - // - // - par_name: the name of the buffer to fill with the output from the process - // - par_buffer_id: the buffer_id of the buffer to to fill with output - // If both are set buffer_id is used and the name is ignored. - // If neither is set the command runs without storing output anywhere. - // - // - par_cli_path: sets the path from which the command is executed - // If this parameter is unset the command runs from the hot directory. - // - // - par_cli_command: sets the actual command to be executed, this can be almost any - // command that you could execute through a command line interface. - // If this parameter is unset the command get's it's command from the range between - // the mark and cursor. - // - // Step 3: If the batch file did not exist change the dir string to the parent directory using - // app->directory_cd. The cd function can also be used to navigate to subdirectories. - // It returns true if it can actually move in the specified direction, and false otherwise. - // - // This doesn't actually change the hot directory of 4coder, it's only effect is to - // modify the string you passed in to reflect the change in directory if that change was possible. - - int old_size; - int size = app->memory_size/2; - - unsigned int access = AccessAll; - View_Summary view = app->get_active_view(app, access); - - String dir = make_string(app->memory, 0, size); - dir.size = app->directory_get_hot(app, dir.str, dir.memory_size); - - String command = make_string((char*)app->memory + size, 0, size); - - for(;;){ - old_size = dir.size; - append(&dir, "build.bat"); - - if (app->file_exists(app, dir.str, dir.size)){ - dir.size = old_size; - append(&command, '"'); - append(&command, dir); - append(&command, "build\""); - - app->exec_system_command(app, &view, - buffer_identifier(literal("*compilation*")), - dir.str, dir.size, - command.str, command.size, - CLI_OverlapWithConflict); - - break; - } - dir.size = old_size; - - if (app->directory_cd(app, dir.str, &dir.size, dir.memory_size, literal("..")) == 0){ - dir.size = app->directory_get_hot(app, dir.str, dir.memory_size); - command = make_lit_string("echo couldn't find build.bat"); - app->exec_system_command(app, &view, - buffer_identifier(literal("*compilation*")), - dir.str, dir.size, - command.str, command.size, - CLI_OverlapWithConflict); - break; - } - } -} - -CUSTOM_COMMAND_SIG(build_in_build_panel){ - Buffer_Summary buffer = app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); - View_Summary build_view = {0}; - View_Summary original_view = app->get_active_view(app, AccessAll); - - if (buffer.exists){ - build_view = get_first_view_with_buffer(app, buffer.buffer_id); - } - - if (!build_view.exists){ - exec_command(app, cmdid_open_panel_hsplit); - build_view = app->get_active_view(app, AccessAll); - } - - app->set_active_view(app, &build_view); - exec_command(app, build_search); - app->set_active_view(app, &original_view); -} - -CUSTOM_COMMAND_SIG(close_build_panel){ - Buffer_Summary buffer = app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); - - if (buffer.exists){ - View_Summary build_view = get_first_view_with_buffer(app, buffer.buffer_id); - View_Summary original_view = app->get_active_view(app, AccessAll); - - app->set_active_view(app, &build_view); - exec_command(app, cmdid_close_panel); - app->set_active_view(app, &original_view); - } -} - -CUSTOM_COMMAND_SIG(change_active_panel_skip_build){ - Buffer_Summary buffer = app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); - - if (buffer.exists){ - View_Summary build_view = get_first_view_with_buffer(app, buffer.buffer_id); - - View_Summary view = app->get_active_view(app, AccessAll); - int prev_view_id = view.view_id; - - exec_command(app, cmdid_change_active_panel); - view = app->get_active_view(app, AccessAll); - - for (;(view.view_id != prev_view_id && - build_view.view_id == view.view_id);){ - prev_view_id = view.view_id; - exec_command(app, cmdid_change_active_panel); - view = app->get_active_view(app, AccessAll); - } - } -} - -CUSTOM_COMMAND_SIG(open_file_in_quotes_build){ - char file_name_[256]; - String file_name = make_fixed_width_string(file_name_); - - if (file_name_in_quotes(app, &file_name)){ - exec_command(app, change_active_panel_skip_build); - View_Summary view = app->get_active_view(app, AccessAll); - view_open_file(app, &view, expand_str(file_name), false); - } -} - -// TODO(allen): This is a bit nasty. I want a system for picking -// the most advanced and correct version of a command to bind to a -// name based on which files are included. -#ifndef OPEN_FILE_IN_QUOTES -# define OPEN_FILE_IN_QUOTES 2 -#elif OPEN_FILE_IN_QUOTES <= 2 -# undef OPEN_FILE_IN_QUOTES -# define OPEN_FILE_IN_QUOTES 2 -#endif - -#if OPEN_FILE_IN_QUOTES <= 2 -# ifdef open_file_in_quotes -# undef open_file_in_quotes -# endif -# define open_file_in_quotes open_file_in_quotes_build -#endif - -CUSTOM_COMMAND_SIG(open_in_other_build){ - exec_command(app, change_active_panel_skip_build); - exec_command(app, cmdid_interactive_open); -} - -// TODO(allen): This is a bit nasty. I want a system for picking -// the most advanced and correct version of a command to bind to a -// name based on which files are included. -#ifndef OPEN_IN_OTHER -# define OPEN_IN_OTHER 1 -#elif OPEN_IN_OTHER <= 1 -# undef OPEN_IN_OTHER -# define OPEN_IN_OTHER 1 -#endif - -#if OPEN_IN_OTHER <= 1 -# ifdef open_in_other -# undef open_in_other -# endif -# define open_in_other open_in_other_build -#endif - - diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 55e3abd2..e1621e32 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -1,4 +1,7 @@ +#ifndef FCODER_DEFAULT_INCLUDE +#define FCODER_DEFAULT_INCLUDE + #include "4coder_custom.h" #define FCPP_STRING_IMPLEMENTATION @@ -1344,6 +1347,131 @@ CUSTOM_COMMAND_SIG(write_and_auto_tab){ exec_command(app, auto_tab_line_at_cursor); } +// +// Default Building Stuff +// + +CUSTOM_COMMAND_SIG(build_search_regular){ + // NOTE(allen|a3.3): An example of traversing the filesystem through parent + // directories looking for a file, in this case a batch file to execute. + // + // + // Step 1: Grab all of the user memory (or, you know, less if you've got better + // thing to do with some of it). Make a string and store the hot directory in it. + // + // Step 2: app->file_exists queries the file system to see if "/build.bat" exists. + // If it does exist several parameters are pushed and cmdid_command_line is executed: + // - par_flags: flags for specifiying behaviors + // CLI_OverlapWithConflict - (on by default) if another CLI is still using the output buffer + // that process is detached from the buffer and this process executes outputing to the buffer + // CLI_AlwaysBindToView - if set, the current view always switches to the output buffer + // even if the output buffer is open in another view + // + // - par_name: the name of the buffer to fill with the output from the process + // - par_buffer_id: the buffer_id of the buffer to to fill with output + // If both are set buffer_id is used and the name is ignored. + // If neither is set the command runs without storing output anywhere. + // + // - par_cli_path: sets the path from which the command is executed + // If this parameter is unset the command runs from the hot directory. + // + // - par_cli_command: sets the actual command to be executed, this can be almost any + // command that you could execute through a command line interface. + // If this parameter is unset the command get's it's command from the range between + // the mark and cursor. + // + // Step 3: If the batch file did not exist change the dir string to the parent directory using + // app->directory_cd. The cd function can also be used to navigate to subdirectories. + // It returns true if it can actually move in the specified direction, and false otherwise. + // + // This doesn't actually change the hot directory of 4coder, it's only effect is to + // modify the string you passed in to reflect the change in directory if that change was possible. + + int old_size; + int size = app->memory_size/2; + + unsigned int access = AccessAll; + View_Summary view = app->get_active_view(app, access); + + String dir = make_string(app->memory, 0, size); + dir.size = app->directory_get_hot(app, dir.str, dir.memory_size); + + String command = make_string((char*)app->memory + size, 0, size); + + for(;;){ + old_size = dir.size; + append(&dir, "build.bat"); + + if (app->file_exists(app, dir.str, dir.size)){ + dir.size = old_size; + append(&command, '"'); + append(&command, dir); + append(&command, "build\""); + + app->exec_system_command(app, &view, + buffer_identifier(literal("*compilation*")), + dir.str, dir.size, + command.str, command.size, + CLI_OverlapWithConflict); + + break; + } + dir.size = old_size; + + if (app->directory_cd(app, dir.str, &dir.size, dir.memory_size, literal("..")) == 0){ + dir.size = app->directory_get_hot(app, dir.str, dir.memory_size); + command = make_lit_string("echo couldn't find build.bat"); + app->exec_system_command(app, &view, + buffer_identifier(literal("*compilation*")), + dir.str, dir.size, + command.str, command.size, + CLI_OverlapWithConflict); + break; + } + } +} + +// TODO(allen): This is a bit nasty. I want a system for picking +// the most advanced and correct version of a command to bind to a +// name based on which files are included. +#ifndef BUILD_SEARCH +# define BUILD_SEARCH 1 +#elif BUILD_SEARCH <= 1 +# undef BUILD_SEARCH +# define BUILD_SEARCH 1 +#endif + +#if BUILD_SEARCH <= 1 +# ifdef build_search +# undef build_search +# endif +# define build_search build_search_regular +#endif + + +CUSTOM_COMMAND_SIG(change_active_panel_regular){ + exec_command(app, cmdid_change_active_panel); +} + +// TODO(allen): This is a bit nasty. I want a system for picking +// the most advanced and correct version of a command to bind to a +// name based on which files are included. +#ifndef CHANGE_ACTIVE_PANEL +# define CHANGE_ACTIVE_PANEL 1 +#elif CHANGE_ACTIVE_PANEL <= 1 +# undef CHANGE_ACTIVE_PANEL +# define CHANGE_ACTIVE_PANEL 1 +#endif + +#if CHANGE_ACTIVE_PANEL <= 1 +# ifdef change_active_panel +# undef change_active_panel +# endif +# define change_active_panel change_active_panel_regular +#endif + + + // NOTE(allen|a4): scroll rule information // // The parameters: @@ -1431,4 +1559,4 @@ SCROLL_RULE_SIG(smooth_scroll_rule){ return(result); } - +#endif diff --git a/4coder_helper.h b/4coder_helper.h index c8f5b7cf..1aada635 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -279,16 +279,18 @@ get_first_view_with_buffer(Application_Links *app, int buffer_id){ View_Summary result = {}; View_Summary test = {}; - unsigned int access = AccessAll; - for(test = app->get_view_first(app, access); - test.exists; - app->get_view_next(app, &test, access)){ - - Buffer_Summary buffer = app->get_buffer(app, test.buffer_id, access); - - if(buffer.buffer_id == buffer_id){ - result = test; - break; + if (buffer_id != 0){ + unsigned int access = AccessAll; + for(test = app->get_view_first(app, access); + test.exists; + app->get_view_next(app, &test, access)){ + + Buffer_Summary buffer = app->get_buffer(app, test.buffer_id, access); + + if(buffer.buffer_id == buffer_id){ + result = test; + break; + } } } diff --git a/4coder_string.h b/4coder_string.h index 506c7959..4d9f1f0e 100644 --- a/4coder_string.h +++ b/4coder_string.h @@ -128,6 +128,10 @@ FSTRING_LINK int32_t rfind_substr(String s, int32_t start, String seek FSTRING_LINK int32_t find_substr_insensitive(char *s, int32_t start, String seek); FSTRING_LINK int32_t find_substr_insensitive(String s, int32_t start, String seek); +FSTRING_LINK String skip_whitespace(String s); +FSTRING_LINK String chop_whitespace(String s); +FSTRING_LINK String skip_chop_whitespace(String s); + FSTRING_INLINE fstr_bool has_substr(char *s, String seek) { return (s[find_substr(s, 0, seek)] != 0); } FSTRING_INLINE fstr_bool has_substr(String s, String seek) { return (find_substr(s, 0, seek) < s.size); } @@ -674,6 +678,31 @@ find_substr_insensitive(String str, int32_t start, String seek){ return str.size; } +FSTRING_LINK String +skip_whitespace(String str){ + String result = {0}; + int i = 0; + for (; i < str.size && char_is_whitespace(str.str[i]); ++i); + result = substr(str, i, str.size - i); + return(result); +} + +FSTRING_LINK String +chop_whitespace(String str){ + String result = {0}; + int i = str.size; + for (; i > 0 && char_is_whitespace(str.str[i-1]); --i); + result = substr(str, 0, i); + return(result); +} + +FSTRING_LINK String +skip_chop_whitespace(String str){ + str = skip_whitespace(str); + str = chop_whitespace(str); + return(str); +} + FSTRING_LINK int32_t int_to_str_size(int32_t x){ int32_t size = 1; diff --git a/4coder_version.h b/4coder_version.h index 9fa0ac48..024273b1 100644 --- a/4coder_version.h +++ b/4coder_version.h @@ -1,6 +1,6 @@ #define MAJOR 4 #define MINOR 0 -#define PATCH 8 +#define PATCH 9 #define VN__(a,b,c) #a"."#b"."#c #define VN_(a,b,c) VN__(a,b,c) diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index d788ce2c..861754cc 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -609,14 +609,14 @@ DOC_SEE(Seek_Boundary_Flag) API_EXPORT int Buffer_Read_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out)/* -DOC_PARAM(buffer, the buffer to read out of) -DOC_PARAM(start, the beginning of the read range) -DOC_PARAM(end, one past the end of the read range) -DOC_PARAM(out, the output buffer to fill with the result of the read) -DOC_RETURN(returns non-zero on success) +DOC_PARAM(buffer, The buffer to be read.) +DOC_PARAM(start, The beginning of the read range.) +DOC_PARAM(end, One past the end of the read range.) +DOC_PARAM(out, The output buffer to fill with the result of the read.) +DOC_RETURN(Returns non-zero on success.) DOC ( -The output buffer must have a capacity of at least (end - start) +The output buffer must have a capacity of at least (end - start). The output is not null terminated. This call fails if the buffer does not exist, or if the read range @@ -1107,9 +1107,12 @@ DOC_SEE(get_active_view) return(result); } -/* API_EXPORT int -View_Set_Split_Proportion_(Application_Links *app, View_Summary *view, float t){ +View_Set_Split_Proportion(Application_Links *app, View_Summary *view, float t)/* +DOC_PARAM(view, The view on which to adjust size.) +DOC_PARAM(t, The proportion of the view's containing box that it should occupy in [0,1]) +DOC_RETURN(Returns non-zero on success.) +*/{ Command_Data *cmd = (Command_Data*)app->cmd_context; Models *models = cmd->models; Editing_Layout *layout = &models->layout; @@ -1121,18 +1124,24 @@ View_Set_Split_Proportion_(Application_Links *app, View_Summary *view, float t){ Panel *panel = vptr->panel; Panel_Divider *div = layout->dividers + panel->parent; + + if (panel->which_child == 1){ + t = 1-t; + } + + div->pos = t; + layout_fix_all_panels(layout); } return(result); } -*/ API_EXPORT int View_Compute_Cursor(Application_Links *app, View_Summary *view, Buffer_Seek seek, Full_Cursor *cursor_out)/* -DOC_PARAM(view, the view on which to run the cursor computation) -DOC_PARAM(seek, the seek position) -DOC_PARAM(cursor_out, on success this is filled with result of the seek) -DOC_RETURN(returns non-zero on success) +DOC_PARAM(view, The view on which to run the cursor computation.) +DOC_PARAM(seek, The seek position.) +DOC_PARAM(cursor_out, On success this is filled with result of the seek.) +DOC_RETURN(Returns non-zero on success.) DOC ( Computes a full cursor for the given seek position. diff --git a/4ed_metagen.cpp b/4ed_metagen.cpp index 4ca615cf..b6b219ee 100644 --- a/4ed_metagen.cpp +++ b/4ed_metagen.cpp @@ -420,31 +420,6 @@ get_next_line(String source, String line){ return(next); } -String -skip_whitespace(String str){ - String result = {0}; - int i = 0; - for (; i < str.size && char_is_whitespace(str.str[i]); ++i); - result = substr(str, i, str.size - i); - return(result); -} - -String -chop_whitespace(String str){ - String result = {0}; - int i = str.size; - for (; i > 0 && char_is_whitespace(str.str[i-1]); --i); - result = substr(str, 0, i); - return(result); -} - -String -skip_chop_whitespace(String str){ - str = skip_whitespace(str); - str = chop_whitespace(str); - return(str); -} - int is_comment(String str){ int result = 0; diff --git a/power/4coder_default_building.cpp b/power/4coder_default_building.cpp new file mode 100644 index 00000000..5c5b4901 --- /dev/null +++ b/power/4coder_default_building.cpp @@ -0,0 +1,312 @@ + +#ifndef FCODER_DEFAULT_BUILDING +#define FCODER_DEFAULT_BUILDING + +#include "4coder_custom.h" + +#define FCPP_STRING_IMPLEMENTATION +#include "4coder_string.h" + +#include "4coder_helper.h" + +// +// Basic Build Behavior +// + +CUSTOM_COMMAND_SIG(build_in_build_panel){ + Buffer_Summary buffer = + app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); + View_Summary build_view = {0}; + View_Summary original_view = app->get_active_view(app, AccessAll); + + if (buffer.exists){ + build_view = get_first_view_with_buffer(app, buffer.buffer_id); + } + + if (!build_view.exists){ + exec_command(app, cmdid_open_panel_hsplit); + build_view = app->get_active_view(app, AccessAll); + app->view_set_split_proportion(app, &build_view, .2f); + } + + app->set_active_view(app, &build_view); + exec_command(app, build_search); + app->set_active_view(app, &original_view); +} + +// TODO(allen): This is a bit nasty. I want a system for picking +// the most advanced and correct version of a command to bind to a +// name based on which files are included. +#ifndef BUILD_SEARCH +# define BUILD_SEARCH 2 +#elif BUILD_SEARCH <= 2 +# undef BUILD_SEARCH +# define BUILD_SEARCH 2 +#endif + +#if BUILD_SEARCH <= 2 +# ifdef build_search +# undef build_search +# endif +# define build_search build_in_build_panel +#endif + +CUSTOM_COMMAND_SIG(close_build_panel){ + Buffer_Summary buffer = + app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); + + if (buffer.exists){ + View_Summary build_view = get_first_view_with_buffer(app, buffer.buffer_id); + View_Summary original_view = app->get_active_view(app, AccessAll); + + app->set_active_view(app, &build_view); + exec_command(app, cmdid_close_panel); + app->set_active_view(app, &original_view); + } +} + +CUSTOM_COMMAND_SIG(change_active_panel_build){ + Buffer_Summary buffer = app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); + + if (buffer.exists){ + View_Summary build_view = get_first_view_with_buffer(app, buffer.buffer_id); + + View_Summary view = app->get_active_view(app, AccessAll); + int prev_view_id = view.view_id; + + exec_command(app, cmdid_change_active_panel); + view = app->get_active_view(app, AccessAll); + + for (;(view.view_id != prev_view_id && + build_view.view_id == view.view_id);){ + prev_view_id = view.view_id; + exec_command(app, cmdid_change_active_panel); + view = app->get_active_view(app, AccessAll); + } + } +} + +// TODO(allen): This is a bit nasty. I want a system for picking +// the most advanced and correct version of a command to bind to a +// name based on which files are included. +#ifndef CHANGE_ACTIVE_PANEL +# define CHANGE_ACTIVE_PANEL 2 +#elif CHANGE_ACTIVE_PANEL <= 2 +# undef CHANGE_ACTIVE_PANEL +# define CHANGE_ACTIVE_PANEL 2 +#endif + +#if CHANGE_ACTIVE_PANEL <= 2 +# ifdef change_active_panel +# undef change_active_panel +# endif +# define change_active_panel change_active_panel_build +#endif + +CUSTOM_COMMAND_SIG(open_file_in_quotes_build){ + char file_name_[256]; + String file_name = make_fixed_width_string(file_name_); + + if (file_name_in_quotes(app, &file_name)){ + exec_command(app, change_active_panel_build); + View_Summary view = app->get_active_view(app, AccessAll); + view_open_file(app, &view, expand_str(file_name), false); + } +} + +// TODO(allen): This is a bit nasty. I want a system for picking +// the most advanced and correct version of a command to bind to a +// name based on which files are included. +#ifndef OPEN_FILE_IN_QUOTES +# define OPEN_FILE_IN_QUOTES 2 +#elif OPEN_FILE_IN_QUOTES <= 2 +# undef OPEN_FILE_IN_QUOTES +# define OPEN_FILE_IN_QUOTES 2 +#endif + +#if OPEN_FILE_IN_QUOTES <= 2 +# ifdef open_file_in_quotes +# undef open_file_in_quotes +# endif +# define open_file_in_quotes open_file_in_quotes_build +#endif + +CUSTOM_COMMAND_SIG(open_in_other_build){ + exec_command(app, change_active_panel_build); + exec_command(app, cmdid_interactive_open); +} + +// TODO(allen): This is a bit nasty. I want a system for picking +// the most advanced and correct version of a command to bind to a +// name based on which files are included. +#ifndef OPEN_IN_OTHER +# define OPEN_IN_OTHER 1 +#elif OPEN_IN_OTHER <= 1 +# undef OPEN_IN_OTHER +# define OPEN_IN_OTHER 1 +#endif + +#if OPEN_IN_OTHER <= 1 +# ifdef open_in_other +# undef open_in_other +# endif +# define open_in_other open_in_other_build +#endif + +// +// Jump to Error +// + +static int +read_line(Application_Links *app, + View_Summary *view, + int line, + String *str){ + + Full_Cursor begin = {0}; + Full_Cursor end = {0}; + + int success = false; + + if (app->view_compute_cursor(app, view, + seek_line_char(line, 1), &begin)){ + if (app->view_compute_cursor(app, view, + seek_line_char(line, 65536), &end)){ + + Buffer_Summary buffer = app->get_buffer(app, view->buffer_id, AccessAll); + if (begin.line == line){ + if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer.size){ + int size = (end.pos - begin.pos); + if (size <= str->memory_size){ + success = true; + app->buffer_read_range(app, &buffer, begin.pos, end.pos, str->str); + str->size = size; + } + } + } + + } + } + + return(success); +} + +struct Jump_Location{ + String file; + int line; +}; + +static void +jump_to_location(Application_Links *app, View_Summary *view, Jump_Location *l){ + view_open_file(app, view, l->file.str, l->file.size, false); + app->view_set_cursor(app, view, seek_line_char(l->line, 1), true); +} + +static int +msvc_parse_error(String line, Jump_Location *location, int *colon_char){ + int result = false; + + int colon_pos = find(line, 0, ')'); + colon_pos = find(line, colon_pos, ':'); + if (colon_pos < line.size){ + String location_str = substr(line, 0, colon_pos); + location_str = skip_chop_whitespace(location_str); + + int paren_pos = find(location_str, 0, '('); + if (paren_pos < location_str.size){ + String file = substr(location_str, 0, paren_pos); + file = skip_chop_whitespace(file); + + int close_pos = find(location_str, 0, ')') + 1; + if (close_pos == location_str.size && file.size > 0){ + String line_number = substr(location_str, + paren_pos+1, + close_pos-paren_pos-2); + line_number = skip_chop_whitespace(line_number); + + if (line_number.size > 0){ + copy(&location->file, file); + location->line = str_to_int(line_number); + *colon_char = colon_pos; + result = true; + } + } + } + } + + return(result); +} + +static int +msvc_next_error(Application_Links *app, + View_Summary *comp_out, int *start_line, + void *memory, int memory_size, + Jump_Location *location, + int direction, + int *colon_char){ + + int result = false; + int line = *start_line + direction; + String line_str = make_string(memory, 0, memory_size); + for (;;){ + if (read_line(app, comp_out, line, &line_str)){ + if (msvc_parse_error(line_str, location, colon_char)){ + result = true; + break; + } + line += direction; + } + else{ + break; + } + } + + if (line < 0){ + line = 0; + } + + *start_line = line; + + return(result); +} + +static void +msvc_goto_error(Application_Links *app, int direction){ + View_Summary active_view = app->get_active_view(app, AccessAll); + + Buffer_Summary buffer = app->get_buffer_by_name(app, literal("*compilation*"), AccessAll); + if (buffer.exists){ + View_Summary view = get_first_view_with_buffer(app, buffer.buffer_id); + int line = view.cursor.line; + + int ms = app->memory_size/2; + Jump_Location location = {0}; + location.file = make_string(app->memory, 0, ms); + void *m = (char*)app->memory + ms; + + int colon_char = 0; + if (msvc_next_error(app, &view, &line, m, ms, &location, direction, &colon_char)){ + jump_to_location(app, &active_view, &location); + app->view_set_cursor(app, &view, seek_line_char(line, colon_char+1), true); + } + } +} + +CUSTOM_COMMAND_SIG(msvc_goto_next_error){ + msvc_goto_error(app, 1); +} + +CUSTOM_COMMAND_SIG(msvc_goto_prev_error){ + msvc_goto_error(app, -1); +} + +CUSTOM_COMMAND_SIG(msvc_goto_first_error){ + View_Summary active_view = app->get_active_view(app, AccessAll); + app->view_set_cursor(app, &active_view, seek_pos(0), true); + + msvc_goto_error(app, 1); +} + + +#endif + diff --git a/power/4coder_experiments.cpp b/power/4coder_experiments.cpp index 41df77da..93cb6c63 100644 --- a/power/4coder_experiments.cpp +++ b/power/4coder_experiments.cpp @@ -1,6 +1,9 @@ // TOP +#include "4coder_default_include.cpp" +#include "4coder_default_building.cpp" + #define NO_BINDING #include "4coder_default_bindings.cpp" @@ -280,6 +283,13 @@ get_bindings(void *data, int size){ // You can also use the helper "restart_map" instead of // begin_map to clear everything that was in the map and // bind new things instead. + begin_map(context, mapid_global); + bind(context, ',', MDFR_ALT, close_build_panel); + bind(context, 'n', MDFR_ALT, msvc_goto_next_error); + bind(context, 'N', MDFR_ALT, msvc_goto_prev_error); + bind(context, 'M', MDFR_ALT, msvc_goto_first_error); + end_map(context); + begin_map(context, mapid_file); bind(context, 'k', MDFR_ALT, kill_rect); end_map(context);