Lots of progress on the profiler; no more infinite recursion in listers

This commit is contained in:
Allen Webster 2019-10-19 18:17:44 -07:00
parent 6bc43256c6
commit 323782f7f7
25 changed files with 1066 additions and 724 deletions

View File

@ -31,7 +31,7 @@ coroutine_main(void *ptr){
Coroutine *me = (Coroutine*)ptr;
Thread_Context tctx_ = {};
thread_ctx_init(&tctx_, get_base_allocator_system());
thread_ctx_init(&tctx_, get_base_allocator_system(), get_base_allocator_system());
me->tctx = &tctx_;
// NOTE(allen): Init handshake

View File

@ -2397,6 +2397,15 @@ rect_range_y(Rect_f32 r){
return(If32(r.y0, r.y1));
}
internal i32
rect_area(Rect_i32 r){
return((r.x1 - r.x0)*(r.y1 - r.y0));
}
internal f32
rect_area(Rect_f32 r){
return((r.x1 - r.x0)*(r.y1 - r.y0));
}
internal b32
rect_overlap(Rect_i32 a, Rect_i32 b){
return(range_overlap(rect_range_x(a), rect_range_x(b)) &&
@ -2825,10 +2834,15 @@ end_temp(Temp_Memory temp){
////////////////////////////////
internal void
thread_ctx_init(Thread_Context *tctx, Base_Allocator *allocator){
thread_ctx_init(Thread_Context *tctx, Base_Allocator *allocator,
Base_Allocator *prof_allocator){
block_zero_struct(tctx);
tctx->allocator = allocator;
tctx->node_arena = make_arena(allocator, KB(4), 8);
tctx->prof_allocator = prof_allocator;
tctx->prof_id_counter = 1;
tctx->prof_arena = make_arena(prof_allocator, KB(4));
}
internal void

View File

@ -1126,17 +1126,60 @@ struct Temp_Memory{
};
};
////////////////////////////////
union Arena_Node{
struct Arena_Node{
Arena_Node *next;
Arena arena;
};
////////////////////////////////
typedef u64 Profile_ID;
struct Profile_Record{
Profile_Record *next;
Profile_ID id;
u64 time;
String_Const_u8 location;
String_Const_u8 name;
};
struct Profile_Thread{
Profile_Thread *next;
Profile_Record *first_record;
Profile_Record *last_record;
i32 record_count;
i32 thread_id;
};
typedef u32 Profile_Enable_Flag;
enum{
ProfileEnable_UserBit = 0x1,
ProfileEnable_InspectBit = 0x2,
};
struct Profile_Global_List{
Arena node_arena;
Arena_Node *first_arena;
Arena_Node *last_arena;
Profile_Thread *first_thread;
Profile_Thread *last_thread;
i32 thread_count;
Profile_Enable_Flag disable_bits;
};
////////////////////////////////
struct Thread_Context{
Base_Allocator *allocator;
Arena node_arena;
Arena_Node *free_arenas;
Arena *sharable_scratch;
Base_Allocator *prof_allocator;
Profile_ID prof_id_counter;
Arena prof_arena;
Profile_Record *prof_first;
Profile_Record *prof_last;
i32 prof_record_count;
};
typedef i32 Scratch_Share_Code;

View File

@ -18,7 +18,7 @@ custom_layer_init(Application_Links *app){
Thread_Context *tctx = get_thread_context(app);
mapping_init(tctx, &framework_mapping);
setup_default_mapping(&framework_mapping);
profile_history_init();
global_prof_init();
}
#endif

View File

@ -149,6 +149,16 @@ get_next_view_after_active(Application_Links *app, Access_Flag access){
////////////////////////////////
static void
call_after_ui_shutdown(Application_Links *app, View_ID view, Custom_Command_Function *func){
Managed_Scope scope = view_get_managed_scope(app, view);
Custom_Command_Function **call_next =
scope_attachment(app, scope, view_call_next, Custom_Command_Function*);
*call_next = func;
}
////////////////////////////////
static void
view_buffer_set(Application_Links *app, Buffer_ID *buffers, i32 *positions, i32 count){
if (count > 0){
@ -382,6 +392,7 @@ default_4coder_initialize(Application_Links *app, String_Const_u8_Array file_nam
view_highlight_range = managed_id_declare(app, SCu8("DEFAULT.highlight" ));
view_highlight_buffer = managed_id_declare(app, SCu8("DEFAULT.highlight_buf" ));
view_render_hook = managed_id_declare(app, SCu8("DEFAULT.render" ));
view_call_next = managed_id_declare(app, SCu8("DEFAULT.call_next" ));
buffer_map_id = managed_id_declare(app, SCu8("DEFAULT.buffer_map_id" ));
buffer_eol_setting = managed_id_declare(app, SCu8("DEFAULT.buffer_eol_setting"));

View File

@ -40,6 +40,7 @@ global Managed_ID view_ui_data = 0;
global Managed_ID view_highlight_range = 0;
global Managed_ID view_highlight_buffer = 0;
global Managed_ID view_render_hook = 0;
global Managed_ID view_call_next = 0;
global Managed_ID buffer_map_id = 0;
global Managed_ID buffer_eol_setting = 0;

View File

@ -82,6 +82,13 @@ CUSTOM_DOC("Input consumption loop for default view behavior")
Command_Binding binding = map_get_binding_recursive(&framework_mapping, map_id, &input.event);
Managed_Scope scope = view_get_managed_scope(app, view);
Custom_Command_Function** next_call = 0;
call_again:
next_call = scope_attachment(app, scope, view_call_next, Custom_Command_Function*);
*next_call = 0;
if (binding.custom == 0){
// NOTE(allen): we don't have anything to do with this input,
// leave it marked unhandled so that if there's a follow up
@ -90,7 +97,6 @@ CUSTOM_DOC("Input consumption loop for default view behavior")
}
else{
// NOTE(allen): before the command is called do some book keeping
Managed_Scope scope = view_get_managed_scope(app, view);
Rewrite_Type *next_rewrite = scope_attachment(app, scope, view_next_rewrite_loc, Rewrite_Type);
*next_rewrite = Rewrite_None;
if (fcoder_mode == FCoderMode_NotepadLike){
@ -124,6 +130,12 @@ CUSTOM_DOC("Input consumption loop for default view behavior")
}
}
}
next_call = scope_attachment(app, scope, view_call_next, Custom_Command_Function*);
if (*next_call != 0){
binding.custom = *next_call;
goto call_again;
}
}
}
}
@ -694,6 +706,8 @@ BUFFER_HOOK_SIG(default_file_save){
BUFFER_EDIT_RANGE_SIG(default_buffer_edit_range){
// buffer_id, range, text
ProfileScope(app, "default edit range");
Interval_i64 replace_range = Ii64(range.first, range.first + text.size);
i64 insert_size = range_size(range);
i64 text_shift = replace_range_shift(replace_range, insert_size);

View File

@ -58,6 +58,8 @@
#define DYNAMIC_LINK_API
#include "generated/system_api.cpp"
#include "4coder_system_helpers.cpp"
#include "4coder_profile.cpp"
#include "4coder_profile_static_enable.cpp"
#include "4coder_events.cpp"
#include "4coder_custom.cpp"
#include "4coder_log.cpp"
@ -65,7 +67,6 @@
#include "4coder_table.cpp"
#include "4coder_string_match.cpp"
#include "4coder_buffer_seek_constructors.cpp"
#include "4coder_profile.cpp"
#include "4coder_token.cpp"
#include "generated/lexer_cpp.cpp"
@ -75,10 +76,10 @@
#include "4coder_delta_rule.cpp"
#include "4coder_fancy.cpp"
#include "4coder_draw.cpp"
#include "4coder_lister_base.cpp"
#include "4coder_font_helper.cpp"
#include "4coder_config.cpp"
#include "4coder_default_framework.cpp"
#include "4coder_lister_base.cpp"
#include "4coder_base_commands.cpp"
#include "4coder_insertion.cpp"
#include "4coder_eol.cpp"

View File

@ -644,5 +644,26 @@ draw_notepad_style_cursor_highlight(Application_Links *app, View_ID view_id,
}
}
////////////////////////////////
function Rect_f32
get_tool_tip_box(Rect_f32 container, Vec2_f32 p, Vec2_f32 box_dims){
Rect_f32 box = {};
Vec2_f32 container_dims = rect_dim(container);
if (box_dims.x <= container_dims.x &&
box_dims.y <= container_dims.y){
p.x -= 6.f;
p.y += 22.f;
if (p.x + box_dims.x > container.x1){
p.x = container.x1 - box_dims.x;
}
if (p.y + box_dims.y > container.y1){
p.y = container.y1 - box_dims.y;
}
box = Rf32_xy_wh(p, box_dims);
}
return(box);
}
// BOTTOM

View File

@ -199,8 +199,8 @@ fancy_string_list_single(Fancy_String *fancy_string){
}
static Vec2_f32
draw_fancy_string(Application_Links *app, Face_ID font_id, Fancy_String *string, Vec2 P,
int_color fore, int_color back, u32 flags, Vec2 dP){
draw_fancy_string(Application_Links *app, Face_ID font_id, Fancy_String *string,
Vec2_f32 P, int_color fore, int_color back, u32 flags, Vec2_f32 dP){
for (;string != 0;
string = string->next){
Face_ID use_font_id = (string->font_id) ? string->font_id : font_id;

View File

@ -2326,6 +2326,20 @@ guess_line_ending_kind_from_buffer_contents(Application_Links *app, Buffer_ID bu
////////////////////////////////
function Command_Metadata*
get_command_metadata(Custom_Command_Function *func){
Command_Metadata *result = 0;
for (i32 i = 0; i < ArrayCount(fcoder_metacmd_table); i += 1){
if (func == fcoder_metacmd_table[i].proc){
result = &fcoder_metacmd_table[i];
break;
}
}
return(result);
}
////////////////////////////////
// TODO(allen): REWRITE THIS EXACTLY HOW YOU WANT IT --- start ---
internal Child_Process_Set_Target_Flags

View File

@ -244,7 +244,8 @@ set_view_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, Buf
}
static void
jump_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, Name_Line_Column_Location location){
jump_to_location(Application_Links *app, View_ID view, Buffer_ID buffer,
Name_Line_Column_Location location){
view_set_active(app, view);
set_view_to_location(app, view, buffer, seek_line_col(location.line, location.column));
if (auto_center_after_jumps){
@ -252,6 +253,15 @@ jump_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, Name_Li
}
}
static void
jump_to_location(Application_Links *app, View_ID view,
Name_Line_Column_Location location){
Buffer_ID buffer = 0;
if (get_jump_buffer(app, &buffer, &location)){
jump_to_location(app, view, buffer, location);
}
}
static void
jump_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, ID_Pos_Jump_Location location){
view_set_active(app, view);
@ -261,6 +271,14 @@ jump_to_location(Application_Links *app, View_ID view, Buffer_ID buffer, ID_Pos_
}
}
function void
jump_to_location(Application_Links *app, View_ID view, String_Const_u8 location){
Parsed_Jump jump = parse_jump_location(location);
if (jump.success){
jump_to_location(app, view, jump.location);
}
}
////////////////////////////////
// TODO(allen): rewrite

View File

@ -653,11 +653,18 @@ lister_run(Application_Links *app, View_ID view, Lister *lister){
Command_Binding binding =
map_get_binding_recursive(mapping, map, &in.event);
if (binding.custom != 0){
i64 old_num = get_current_input_sequence_number(app);
binding.custom(app);
i64 num = get_current_input_sequence_number(app);
if (old_num < num){
break;
Command_Metadata *metadata = get_command_metadata(binding.custom);
if (metadata != 0){
if (metadata->is_ui){
call_after_ui_shutdown(app, view, binding.custom);
break;
}
else{
binding.custom(app);
}
}
else{
binding.custom(app);
}
}
else{

View File

@ -484,7 +484,7 @@ activate_switch_buffer(Application_Links *app,
return(ListerActivation_Finished);
}
CUSTOM_COMMAND_SIG(interactive_switch_buffer)
CUSTOM_UI_COMMAND_SIG(interactive_switch_buffer)
CUSTOM_DOC("Interactively switch to an open buffer.")
{
View_ID view = get_active_view(app, Access_Always);
@ -503,7 +503,7 @@ activate_kill_buffer(Application_Links *app,
return(ListerActivation_Finished);
}
CUSTOM_COMMAND_SIG(interactive_kill_buffer)
CUSTOM_UI_COMMAND_SIG(interactive_kill_buffer)
CUSTOM_DOC("Interactively kill an open buffer.")
{
View_ID view = get_active_view(app, Access_Always);
@ -574,7 +574,7 @@ activate_open_or_new(Application_Links *app,
return(result);
}
CUSTOM_COMMAND_SIG(interactive_open_or_new)
CUSTOM_UI_COMMAND_SIG(interactive_open_or_new)
CUSTOM_DOC("Interactively open a file out of the file system.")
{
View_ID view = get_active_view(app, Access_Always);
@ -613,7 +613,7 @@ activate_new(Application_Links *app,
return(result);
}
CUSTOM_COMMAND_SIG(interactive_new)
CUSTOM_UI_COMMAND_SIG(interactive_new)
CUSTOM_DOC("Interactively creates a new file.")
{
View_ID view = get_active_view(app, Access_Always);
@ -646,7 +646,7 @@ activate_open(Application_Links *app,
return(result);
}
CUSTOM_COMMAND_SIG(interactive_open)
CUSTOM_UI_COMMAND_SIG(interactive_open)
CUSTOM_DOC("Interactively opens a file.")
{
View_ID view = get_active_view(app, Access_Always);
@ -709,7 +709,7 @@ launch_custom_command_lister(Application_Links *app, i32 *command_ids, i32 comma
}
}
CUSTOM_COMMAND_SIG(command_lister)
CUSTOM_UI_COMMAND_SIG(command_lister)
CUSTOM_DOC("Opens an interactive list of all registered commands.")
{
launch_custom_command_lister(app, 0, 0);

View File

@ -214,14 +214,16 @@ token_str(String_Const_u8 text, Token token){
///////////////////////////////
typedef u32 Meta_Command_Entry_Type;
typedef i32 Meta_Command_Entry_Kind;
enum{
MetaCommandEntry_DocString,
MetaCommandEntry_Alias,
MetaCommandEntryKind_ERROR,
MetaCommandEntryKind_Normal,
MetaCommandEntryKind_UI,
};
struct Meta_Command_Entry{
Meta_Command_Entry *next;
Meta_Command_Entry_Kind kind;
String_Const_u8 name;
u8 *source_name;
i64 line_number;
@ -229,9 +231,6 @@ struct Meta_Command_Entry{
struct{
String_Const_u8 doc;
} docstring;
struct{
String_Const_u8 potential;
} alias;
};
};
@ -240,9 +239,9 @@ struct Meta_Command_Entry_Arrays{
Meta_Command_Entry *last_doc_string;
i32 doc_string_count;
Meta_Command_Entry *first_alias;
Meta_Command_Entry *last_alias;
i32 alias_count;
Meta_Command_Entry *first_ui;
Meta_Command_Entry *last_ui;
i32 ui_count;
};
///////////////////////////////
@ -515,16 +514,29 @@ extract_string(Reader *reader, String_Const_u8 *str_out){
return(extract_string(reader, str_out, 0));
}
function Meta_Command_Entry_Kind
parse_command_kind(String_Const_u8 kind){
Meta_Command_Entry_Kind result = MetaCommandEntryKind_ERROR;
if (string_match(kind, string_u8_litexpr("Normal"))){
result = MetaCommandEntryKind_Normal;
}
else if (string_match(kind, string_u8_litexpr("UI"))){
result = MetaCommandEntryKind_UI;
}
return(result);
}
static b32
parse_documented_command(Arena *arena, Meta_Command_Entry_Arrays *arrays, Reader *reader){
String_Const_u8 name = {};
String_Const_u8 kind = {};
String_Const_u8 file_name = {};
String_Const_u8 line_number = {};
String_Const_u8 doc = {};
// Getting the command's name
i64 start_pos = 0;
if (!require_key_identifier(reader, "CUSTOM_COMMAND_SIG", &start_pos)){
if (!require_key_identifier(reader, "CUSTOM_COMMAND", &start_pos)){
return(false);
}
@ -552,6 +564,14 @@ parse_documented_command(Arena *arena, Meta_Command_Entry_Arrays *arrays, Reader
return(false);
}
if (!require_comma(reader)){
return(false);
}
if (!extract_identifier(reader, &kind)){
return(false);
}
if (!require_close_parenthese(reader)){
return(false);
}
@ -590,6 +610,7 @@ parse_documented_command(Arena *arena, Meta_Command_Entry_Arrays *arrays, Reader
String_Const_u8 source_name = string_interpret_escapes(arena, file_name_unquoted);
Meta_Command_Entry *new_entry = push_array(arena, Meta_Command_Entry, 1);
new_entry->kind = parse_command_kind(kind);
new_entry->name = name;
new_entry->source_name = source_name.str;
new_entry->line_number = (i32)string_to_integer(line_number, 10);
@ -600,49 +621,6 @@ parse_documented_command(Arena *arena, Meta_Command_Entry_Arrays *arrays, Reader
return(true);
}
static b32
parse_alias(Arena *arena, Meta_Command_Entry_Arrays *arrays, Reader *reader){
String_Const_u8 name = {};
String_Const_u8 potential = {};
// Getting the alias's name
i64 start_pos = 0;
if (!require_define(reader, &start_pos)){
return(false);
}
if (!extract_identifier(reader, &name)){
return(false);
}
// Getting the alias's target
if (!require_key_identifier(reader, "CUSTOM_ALIAS")){
return(false);
}
if (!require_open_parenthese(reader)){
return(false);
}
if (!extract_identifier(reader, &potential)){
return(false);
}
if (!require_close_parenthese(reader)){
return(false);
}
Meta_Command_Entry *new_entry = push_array(arena, Meta_Command_Entry, 1);
new_entry->name = name;
new_entry->source_name = reader->source_name;
new_entry->line_number = line_number(reader, start_pos);
new_entry->alias.potential = potential;
sll_queue_push(arrays->first_alias, arrays->last_alias, new_entry);
++arrays->alias_count;
return(true);
}
///////////////////////////////
static void
@ -661,15 +639,16 @@ parse_text(Arena *arena, Meta_Command_Entry_Arrays *entry_arrays, u8 *source_nam
b32 in_preproc_body = HasFlag(token.flags, TokenBaseFlag_PreprocessorBody);
if (!in_preproc_body && string_match(lexeme, string_u8_litexpr("CUSTOM_DOC"))){
if (!in_preproc_body &&
string_match(lexeme, string_u8_litexpr("CUSTOM_DOC"))){
Temp_Read temp_read = begin_temp_read(reader);
b32 found_start_pos = false;
for (i32 R = 0; R < 10; ++R){
for (i32 R = 0; R < 12; ++R){
Token p_token = prev_token(reader);
if (p_token.kind == TokenBaseKind_Identifier){
String_Const_u8 p_lexeme = token_str(text, p_token);
if (string_match(p_lexeme, string_u8_litexpr("CUSTOM_COMMAND_SIG"))){
if (string_match(p_lexeme, string_u8_litexpr("CUSTOM_COMMAND"))){
found_start_pos = true;
break;
}
@ -688,31 +667,8 @@ parse_text(Arena *arena, Meta_Command_Entry_Arrays *entry_arrays, u8 *source_nam
}
}
}
else if (string_match(lexeme, string_u8_litexpr("CUSTOM_ALIAS"))){
Temp_Read temp_read = begin_temp_read(reader);
else if (string_match(lexeme, string_u8_litexpr("CUSTOM_UI_COMMAND"))){
b32 found_start_pos = false;
for (i32 R = 0; R < 3; ++R){
Token p_token = prev_token(reader);
if (p_token.sub_kind == TokenCppKind_PPDefine){
if (R == 2){
found_start_pos = true;
}
break;
}
if (p_token.kind == TokenBaseKind_EOF){
break;
}
}
if (!found_start_pos){
end_temp_read(temp_read);
}
else{
if (!parse_alias(arena, entry_arrays, reader)){
end_temp_read(temp_read);
}
}
}
}
@ -875,6 +831,7 @@ main(int argc, char **argv){
fprintf(out,
"struct Command_Metadata{\n"
"PROC_LINKS(Custom_Command_Function, void) *proc;\n"
"b32 is_ui;\n"
"char *name;\n"
"i32 name_len;\n"
"char *description;\n"
@ -892,17 +849,21 @@ main(int argc, char **argv){
Temp_Memory temp = begin_temp(arena);
// HACK(allen): We could just get these at the HEAD END of the process,
// then we only have to do it once per file, and pass the lengths through.
//umem source_name_len = cstring_length(entry->source_name);
String_Const_u8 source_name = SCu8(entry->source_name);
String_Const_u8 printable = string_replace(arena, source_name,
SCu8("\\"), SCu8("\\\\"),
StringFill_NullTerminate);
char *is_ui = "false";
if (entry->kind == MetaCommandEntryKind_UI){
is_ui = "true";
}
fprintf(out,
"{ PROC_LINKS(%.*s, 0), \"%.*s\", %d, \"%.*s\", %d, \"%s\", %d, %lld },\n",
"{ PROC_LINKS(%.*s, 0), %s, \"%.*s\", %d, "
"\"%.*s\", %d, \"%s\", %d, %lld },\n",
string_expand(entry->name),
is_ui,
string_expand(entry->name),
(i32)entry->name.size,
string_expand(entry->docstring.doc),

View File

@ -4,122 +4,191 @@
// TOP
function Profile_Group*
make_profile_group__inner(u32 slot_count, u32 stack_size, char *source_location){
Arena arena = make_arena_system(KB(4));
Profile_Group *group = push_array(&arena, Profile_Group, 1);
group->arena = arena;
group->thread_id = system_thread_get_id();
group->source_location = SCu8(source_location);
group->slot_names = push_array_zero(&group->arena, String_Const_u8, slot_count);
group->timer_stack = push_array_zero(&group->arena, Profile_Slot, stack_size);
group->slot_count = slot_count;
group->stack_size = stack_size;
group->stack_top = 0;
group->first = 0;
group->last = 0;
return(group);
}
#define make_profile_group(L,T) make_profile_group__inner((L),(T), file_name_line_number)
global Profile_Global_List global_prof_list = {};
global System_Mutex global_prof_mutex = {};
function void
profile_define(Profile_Group *group, u32 slot_index, char *name){
if (slot_index < group->slot_count){
group->slot_names[slot_index] = SCu8(name);
}
global_prof_init(void){
global_prof_mutex = system_mutex_make();
global_prof_list.node_arena = make_arena(get_base_allocator_system(),
KB(4));
}
function void
profile__record(Profile_Group *group, u32 slot_index, u64 time){
Profile_Record *record = push_array(&group->arena, Profile_Record, 1);
record->slot_index = slot_index;
record->time = time;
sll_queue_push(group->first, group->last, record);
}
function void
profile_begin_range(Profile_Group *group, u32 slot_index){
Assert(group->stack_top < group->stack_size);
Profile_Slot *slot = &group->timer_stack[group->stack_top];
Profile_Slot *prev = 0;
if (group->stack_top > 0){
prev = &group->timer_stack[group->stack_top - 1];
}
slot->slot_index = slot_index;
group->stack_top += 1;
slot->accumulated_time = 0;
u64 time = system_now_time();
slot->start_time = time;
if (prev != 0){
prev->accumulated_time += time - prev->start_time;
}
}
function void
profile_end_range(Profile_Group *group){
u64 time = system_now_time();
Assert(group->stack_top > 0);
group->stack_top -= 1;
if (group->stack_top > 0){
Profile_Slot *prev = &group->timer_stack[group->stack_top - 1];
prev->start_time = time;
}
Profile_Slot *slot = &group->timer_stack[group->stack_top];
u64 accumulated = time - slot->start_time + slot->accumulated_time;
profile__record(group, slot->slot_index, accumulated);
}
function void
profile_add_note(Profile_Group *group, u32 slot_index){
profile__record(group, slot_index, 0);
}
function void
profile_group_post(Profile_Group *group){
Assert(group->stack_top == 0);
system_mutex_acquire(profile_history.mutex);
if (profile_history.disable_bits == 0){
sll_queue_push(profile_history.first, profile_history.last, group);
}
else{
Arena arena = group->arena;
linalloc_clear(&arena);
}
system_mutex_release(profile_history.mutex);
}
function void
profile_history_set_enabled(b32 value, Profile_Enable_Flag flag){
system_mutex_acquire(profile_history.mutex);
if (value){
RemFlag(profile_history.disable_bits, flag);
}
else{
AddFlag(profile_history.disable_bits, flag);
}
system_mutex_release(profile_history.mutex);
}
function void
profile_history_clear(void){
system_mutex_acquire(profile_history.mutex);
for (Profile_Group *node = profile_history.first, *next = 0;
function Profile_Thread*
global_prof_get_thread(i32 thread_id){
Profile_Thread *result = 0;
for (Profile_Thread *node = global_prof_list.first_thread;
node != 0;
node = next){
next = node->next;
Arena arena = node->arena;
linalloc_clear(&arena);
node = node->next){
if (thread_id == node->thread_id){
result = node;
break;
}
}
profile_history.first = 0;
profile_history.last = 0;
system_mutex_release(profile_history.mutex);
if (result == 0){
result = push_array_zero(&global_prof_list.node_arena, Profile_Thread, 1);
sll_queue_push(global_prof_list.first_thread, global_prof_list.last_thread, result);
global_prof_list.thread_count += 1;
result->thread_id = thread_id;
}
return(result);
}
function void
profile_history_init(void){
profile_history.mutex = system_mutex_make();
profile_history.disable_bits = 0;
global_prof_clear(void){
Mutex_Lock lock(global_prof_mutex);
for (Arena_Node *node = global_prof_list.first_arena;
node != 0;
node = node->next){
linalloc_clear(&node->arena);
}
global_prof_list.first_arena = 0;
global_prof_list.last_arena = 0;
linalloc_clear(&global_prof_list.node_arena);
global_prof_list.first_thread = 0;
global_prof_list.last_thread = 0;
global_prof_list.thread_count = 0;
}
function void
thread_profile_flush(Thread_Context *tctx){
if (tctx->prof_record_count > 0){
Mutex_Lock lock(global_prof_mutex);
if (global_prof_list.disable_bits == 0){
Profile_Thread* thread = global_prof_get_thread(system_thread_get_id());
Arena_Node* node = push_array(&global_prof_list.node_arena, Arena_Node, 1);
sll_queue_push(global_prof_list.first_arena, global_prof_list.last_arena,
node);
node->arena = tctx->prof_arena;
tctx->prof_arena = make_arena(get_base_allocator_system(), KB(4));
if (thread->first_record == 0){
thread->first_record = tctx->prof_first;
thread->last_record = tctx->prof_last;
}
else{
thread->last_record->next = tctx->prof_first;
thread->last_record = tctx->prof_last;
}
thread->record_count += tctx->prof_record_count;
tctx->prof_record_count = 0;
tctx->prof_first = 0;
tctx->prof_last = 0;
}
}
}
function void
global_prof_set_enabled(b32 value, Profile_Enable_Flag flag){
Mutex_Lock lock(global_prof_mutex);
if (value){
RemFlag(global_prof_list.disable_bits, flag);
}
else{
AddFlag(global_prof_list.disable_bits, flag);
}
}
function void
thread_profile_record__inner(Thread_Context *tctx, Profile_ID id, u64 time,
String_Const_u8 name, String_Const_u8 location){
Profile_Record *record = push_array_zero(&tctx->prof_arena, Profile_Record, 1);
sll_queue_push(tctx->prof_first, tctx->prof_last, record);
tctx->prof_record_count += 1;
record->id = id;
record->time = time;
record->location = location;
record->name = name;
}
function Profile_ID
thread_profile_record_push(Thread_Context *tctx, u64 time,
String_Const_u8 name, String_Const_u8 location){
Profile_ID id = tctx->prof_id_counter;
tctx->prof_id_counter += 1;
thread_profile_record__inner(tctx, id, time, name, location);
return(id);
}
function void
thread_profile_record_pop(Thread_Context *tctx, u64 time, Profile_ID id){
Assert(tctx->prof_id_counter > 1);
tctx->prof_id_counter = id;
thread_profile_record__inner(tctx, id, time, SCu8(""), SCu8(""));
}
function Profile_ID
thread_profile_record_push(Application_Links *app, u64 time,
String_Const_u8 name, String_Const_u8 location){
Thread_Context *tctx = get_thread_context(app);
return(thread_profile_record_push(tctx, time, name, location));
}
function void
thread_profile_record_pop(Application_Links *app, u64 time, Profile_ID id){
Thread_Context *tctx = get_thread_context(app);
thread_profile_record_pop(tctx, time, id);
}
////////////////////////////////
function void
profile_block__init(Thread_Context *tctx, String_Const_u8 name,
String_Const_u8 location, Profile_Block *block){
block->tctx = tctx;
block->is_closed = false;
block->id = thread_profile_record_push(tctx, system_now_time(), name, location);
}
function void
profile_block__init(Thread_Context *tctx, String_Const_u8 name,
String_Const_u8 location, Profile_Scope_Block *block){
block->tctx = tctx;
block->is_closed = false;
block->id = thread_profile_record_push(tctx, system_now_time(), name, location);
}
////////
Profile_Block::Profile_Block(Thread_Context *tctx, String_Const_u8 name,
String_Const_u8 location){
profile_block__init(tctx, name, location, this);
}
Profile_Block::Profile_Block(Application_Links *app, String_Const_u8 name,
String_Const_u8 location){
profile_block__init(get_thread_context(app), name, location, this);
}
Profile_Block::~Profile_Block(){
this->close_now();
}
void
Profile_Block::close_now(){
if (!this->is_closed){
thread_profile_record_pop(this->tctx, system_now_time(), this->id);
this->is_closed = true;
}
}
////////
Profile_Scope_Block::Profile_Scope_Block(Thread_Context *tctx, String_Const_u8 name,
String_Const_u8 location){
profile_block__init(tctx, name, location, this);
}
Profile_Scope_Block::Profile_Scope_Block(Application_Links *app, String_Const_u8 name,
String_Const_u8 location){
profile_block__init(get_thread_context(app), name, location, this);
}
Profile_Scope_Block::~Profile_Scope_Block(){
this->close_now();
thread_profile_flush(this->tctx);
}
void
Profile_Scope_Block::close_now(){
if (!this->is_closed){
thread_profile_record_pop(this->tctx, system_now_time(), this->id);
this->is_closed = true;
}
}
////////////////////////////////
@ -127,19 +196,19 @@ profile_history_init(void){
CUSTOM_COMMAND_SIG(profile_enable)
CUSTOM_DOC("Allow 4coder's self profiler to gather new profiling information.")
{
profile_history_set_enabled(true, ProfileEnable_UserBit);
global_prof_set_enabled(true, ProfileEnable_UserBit);
}
CUSTOM_COMMAND_SIG(profile_disable)
CUSTOM_DOC("Prevent 4coder's self profiler from gathering new profiling information.")
{
profile_history_set_enabled(false, ProfileEnable_UserBit);
global_prof_set_enabled(false, ProfileEnable_UserBit);
}
CUSTOM_COMMAND_SIG(profile_clear)
CUSTOM_DOC("Clear all profiling information from 4coder's self profiler.")
{
profile_history_clear();
global_prof_clear();
}
// BOTTOM

View File

@ -1,5 +1,5 @@
/*
* 4coder_profile.h - Types for built in self profiling report.
* 4coder_profile.cpp - Built in self profiling report.
*/
// TOP
@ -7,53 +7,28 @@
#if !defined(FCODER_PROFILE_H)
#define FCODER_PROFILE_H
struct Profile_Slot{
u64 start_time;
u64 accumulated_time;
u32 slot_index;
};
struct Profile_Record{
Profile_Record *next;
struct Profile_Group *group;
u64 time;
u32 slot_index;
};
struct Profile_Group{
Profile_Group *next;
struct Profile_Block{
Thread_Context *tctx;
b32 is_closed;
Profile_ID id;
Arena arena;
Profile_Block(Thread_Context *tctx, String_Const_u8 name, String_Const_u8 location);
Profile_Block(Application_Links *app, String_Const_u8 name, String_Const_u8 location);
~Profile_Block();
void close_now();
};
struct Profile_Scope_Block{
Thread_Context *tctx;
b32 is_closed;
Profile_ID id;
i32 thread_id;
String_Const_u8 source_location;
String_Const_u8 *slot_names;
Profile_Slot *timer_stack;
u32 slot_count;
u32 stack_size;
u32 stack_top;
Profile_Record *first;
Profile_Record *last;
Profile_Scope_Block(Application_Links *app, String_Const_u8 name, String_Const_u8 location);
Profile_Scope_Block(Thread_Context *tctx, String_Const_u8 name, String_Const_u8 location);
~Profile_Scope_Block();
void close_now();
};
////////////////////////////////
typedef u32 Profile_Enable_Flag;
enum{
ProfileEnable_UserBit = 0x1,
ProfileEnable_InspectBit = 0x2
};
struct Profile_History{
System_Mutex mutex;
Profile_Enable_Flag disable_bits;
Profile_Group *first;
Profile_Group *last;
};
global Profile_History profile_history = {};
#endif
// BOTTOM

View File

@ -4,134 +4,191 @@
// TOP
function Profile_Thread*
get_column_from_thread_id(Profile_Thread *first, i32 thread_id){
Profile_Thread *result = 0;
for (Profile_Thread *node = first;
function Profile_Slot*
profile_parse_get_slot(Arena *arena, Profile_Inspection *insp,
String_Const_u8 loc, String_Const_u8 name){
Profile_Slot *result = 0;
for (Profile_Slot *node = insp->first_slot;
node != 0;
node = node->next){
if (node->thread_id == thread_id){
if (string_match(node->location, loc) &&
string_match(node->name, name)){
result = node;
break;
}
}
return(result);
}
function Profile_Universal_Slot*
get_universal_slot(Profile_Thread *column, String_Const_u8 source_location,
u32 slot_index){
Profile_Universal_Slot *result = 0;
for (Profile_Universal_Slot *node = column->first_slot;
node != 0;
node = node->next){
if (node->slot_index == slot_index &&
string_match(node->source_location, source_location)){
result = node;
break;
}
if (result == 0){
result = push_array_zero(arena, Profile_Slot, 1);
sll_queue_push(insp->first_slot, insp->last_slot, result);
insp->slot_count += 1;
result->location = loc;
result->name = name;
}
return(result);
}
function void
sort_universal_slots(Profile_Universal_Slot **slots, i32 first, i32 one_past_last){
if (first + 1 < one_past_last){
i32 pivot = one_past_last - 1;
Profile_Universal_Slot *pivot_slot = slots[pivot];
i32 j = first;
for (i32 i = first; i < pivot; i += 1){
Profile_Universal_Slot *slot = slots[i];
b32 goes_first = false;
if (slot->total_time > pivot_slot->total_time){
goes_first = true;
profile_parse_error(Arena *arena, Profile_Inspection *insp, String_Const_u8 message,
String_Const_u8 location){
Profile_Error *error = push_array(arena, Profile_Error, 1);
sll_queue_push(insp->first_error, insp->last_error, error);
insp->error_count += 1;
error->message = message;
error->location = location;
}
function Profile_Record*
profile_parse_record(Arena *arena, Profile_Inspection *insp,
Profile_Node *parent, Profile_Record *record,
Range_u64 *total_time_range){
for (;record != 0;){
if (record->id <= parent->id){
break;
}
Profile_ID id = record->id;
Profile_Node *node = push_array(arena, Profile_Node, 1);
sll_queue_push(parent->first_child, parent->last_child, node);
parent->child_count += 1;
String_Const_u8 location = record->location;
String_Const_u8 name = record->name;
node->time.min = record->time;
node->time.max = max_u64;
node->id = id;
node->first_child = 0;
node->last_child = 0;
node->child_count = 0;
node->closed = false;
record = profile_parse_record(arena, insp, node, record->next,
total_time_range);
b32 quit_loop = false;
Profile_Slot *slot = 0;
if (record == 0 || record->id < id){
if (record == 0){
#define M "List ended before all nodes closed"
profile_parse_error(arena, insp, string_u8_litexpr(M), location);
#undef M
}
else if (slot->total_time == pivot_slot->total_time){
if (slot->count > pivot_slot->count){
goes_first = true;
}
else if (slot->count == pivot_slot->count){
i32 comp = string_compare(slot->source_location,
pivot_slot->source_location);
if (comp < 0){
goes_first = true;
}
else if (comp == 0){
if (slot->slot_index < pivot_slot->slot_index){
goes_first = true;
}
}
else{
#define M "Node '%.*s' closed by parent ending (or higher priority sibling starting)"
String_Const_u8 str = push_u8_stringf(arena, M, string_expand(name));
profile_parse_error(arena, insp, str, location);
#undef M
if (parent->id != 0){
quit_loop = true;
}
}
if (goes_first){
Swap(Profile_Universal_Slot*, slots[i], slots[j]);
j += 1;
slot = profile_parse_get_slot(arena, insp, location, name);
}
else if (record->id == id){
String_Const_u8 close_location = record->location;
String_Const_u8 close_name = record->name;
slot = profile_parse_get_slot(arena, insp, location, name);
node->time.max = record->time;
node->closed = true;
total_time_range->min = min(total_time_range->min, node->time.min);
total_time_range->max = max(total_time_range->max, node->time.max);
record = record->next;
}
else{
// NOTE(allen): This would mean that record exists and it's id
// is greater than id, but then the sub-call should not have returned!
InvalidPath;
}
node->slot = slot;
if (!slot->corrupted_time){
if (node->closed){
slot->total_time += range_size(node->time);
}
else{
slot->corrupted_time = true;
}
}
Swap(Profile_Universal_Slot*, slots[j], slots[pivot]);
sort_universal_slots(slots, first, j);
sort_universal_slots(slots, j + 1, one_past_last);
slot->hit_count += 1;
if (quit_loop){
break;
}
}
return(record);
}
function Profile_Inspection
profile_inspect(Arena *arena, Profile_History *history){
Profile_Inspection inspect = {};
for (Profile_Group *node = history->first;
profile_parse(Arena *arena){
Mutex_Lock lock(global_prof_mutex);
Profile_Global_List *src = &global_prof_list;
Profile_Inspection result = {};
result.thread_count = src->thread_count;
result.threads = push_array_zero(arena, Profile_Inspection_Thread,
result.thread_count);
i32 counter = 0;
Profile_Inspection_Thread *insp_thread = result.threads;
for (Profile_Thread *node = src->first_thread;
node != 0;
node = node->next){
i32 thread_id = node->thread_id;
Profile_Thread *column = get_column_from_thread_id(inspect.thread_first,
thread_id);
if (column == 0){
column = push_array_zero(arena, Profile_Thread, 1);
sll_queue_push(inspect.thread_first, inspect.thread_last, column);
inspect.thread_count += 1;
column->thread_id = thread_id;
}
node = node->next, counter += 1, insp_thread += 1){
insp_thread->thread_id = node->thread_id;
Profile_Group_Ptr *ptr = push_array(arena, Profile_Group_Ptr, 1);
sll_queue_push(column->first_group, column->last_group, ptr);
ptr->group = node;
String_Const_u8 source_location = node->source_location;
for (Profile_Record *record = node->first;
record != 0;
record = record->next){
Profile_Universal_Slot *univ_slot =
get_universal_slot(column, source_location, record->slot_index);
if (univ_slot == 0){
univ_slot = push_array(arena, Profile_Universal_Slot, 1);
sll_queue_push(column->first_slot, column->last_slot, univ_slot);
column->slot_count += 1;
univ_slot->source_location = source_location;
univ_slot->slot_index = record->slot_index;
univ_slot->name = node->slot_names[univ_slot->slot_index];
univ_slot->count = 0;
univ_slot->total_time = 0;
}
univ_slot->count += 1;
univ_slot->total_time += record->time;
}
// NOTE(allen): This is the "negative infinity" range.
// We will be "maxing" it against all the ranges durring the parse,
// to get the root range.
Range_u64 time_range = {max_u64, 0};
profile_parse_record(arena, &result, &insp_thread->root, node->first_record,
&time_range);
insp_thread->root.time = time_range;
}
for (Profile_Thread *column = inspect.thread_first;
column != 0;
column = column->next){
i32 count = column->slot_count;
Profile_Universal_Slot **slots = push_array(arena, Profile_Universal_Slot*, count);
column->sorted_slots = slots;
i32 counter = 0;
for (Profile_Universal_Slot *node = column->first_slot;
node != 0;
node = node->next){
slots[counter] = node;
counter += 1;
}
sort_universal_slots(slots, 0, count);
return(result);
}
////////////////////////////////
struct Tab_State{
Vec2_f32 p;
Range_f32 tabs_y;
Face_ID face_id;
f32 x_half_padding;
Vec2_f32 m_p;
};
function void
profile_draw_tab(Application_Links *app, Tab_State *state, Profile_Inspection *insp,
String_Const_u8 string, Profile_Inspection_Tab tab_id){
Scratch_Block scratch(app);
state->p.x += state->x_half_padding;
Fancy_String_List list = {};
push_fancy_string(scratch, &list, fancy_pass_through(), string);
b32 hover = false;
f32 width = get_fancy_string_advance(app, state->face_id, list.first);
Rect_f32 box = Rf32(If32_size(state->p.x, width), state->tabs_y);
if (rect_contains_point(box, state->m_p)){
hover = true;
insp->tab_id_hovered = tab_id;
}
return(inspect);
int_color text = Stag_Default;
int_color back = 0;
if (insp->tab_id == tab_id){
text = Stag_Pop2;
}
else if (hover){
text = Stag_Pop1;
}
Vec2_f32 np = draw_fancy_string(app, state->face_id, list.first, state->p,
text, back);
state->p = np;
state->p.x += state->x_half_padding;
}
function void
@ -147,145 +204,188 @@ profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){
f32 normal_advance = metrics.normal_advance;
f32 block_height = line_height*2.f;
system_mutex_acquire(profile_history.mutex);
Mouse_State mouse = get_mouse_state(app);
Vec2_f32 m_p = V2f32(mouse.p);
Profile_Inspection inspect = global_profile_inspection;
Profile_Inspection *inspect = &global_profile_inspection;
f32 column_width = rect_width(region)/(f32)inspect.thread_count;
Rect_f32_Pair header_body = rect_split_top_bottom(region, block_height);
Range_f32 full_y = rect_range_y(region);
Range_f32 header_y = rect_range_y(header_body.min);
Range_f32 body_y = rect_range_y(header_body.max);
f32 pos_x = region.x0;
for (Profile_Thread *column = inspect.thread_first;
column != 0;
column = column->next){
Range_f32 column_x = If32_size(pos_x, column_width);
Range_f32 text_x = If32(column_x.min + 6.f, column_x.max - 6.f);
f32 text_width = range_size(text_x);
f32 count_width = normal_advance*6.f;
f32 time_width = normal_advance*9.f;
f32 half_padding = normal_advance*0.25f;
f32 label_width = text_width - count_width - time_width;
if (label_width < normal_advance*10.f){
f32 count_ratio = 6.f/25.f;
f32 time_ratio = 9.f/25.f;
f32 label_ratio = 10.f/25.f;
count_width = text_width*count_ratio;
time_width = text_width*time_ratio;
label_width = text_width*label_ratio;
}
if (inspect->thread_count == 0){
Fancy_String_List text = {};
push_fancy_string(scratch, &text, fancy_id(Stag_Pop2),
string_u8_litexpr("no profile data"));
f32 width = get_fancy_string_advance(app, face_id, text.first);
Vec2_f32 view_center = (region.p0 + region.p1)*0.5f;
Vec2_f32 half_dim = V2f32(width, line_height)*0.5f;
Vec2_f32 p = view_center - half_dim;
draw_fancy_string(app, face_id, text.first, p, Stag_Default, 0);
}
else{
Rect_f32_Pair tabs_body = rect_split_top_bottom(region, line_height + 2.f);
Range_f32 tabs_y = rect_range_y(tabs_body.min);
i32 count = column->slot_count;
f32 x_padding = normal_advance*1.5f;
f32 x_half_padding = x_padding*0.5f;
draw_set_clip(app, Rf32(column_x, full_y));
inspect->tab_id_hovered = ProfileInspectTab_None;
block_zero_struct(&inspect->location_jump_hovered);
// NOTE(allen): header
// NOTE(allen): tabs
{
Rect_f32 box = Rf32(column_x, header_y);
draw_rectangle_outline(app, box, 6.f, 3.f, Stag_Margin_Active);
}
// NOTE(allen): list
{
f32 pos_y = body_y.min;
Profile_Universal_Slot **slot_ptr = column->sorted_slots;
for (i32 i = 0; i < count; i += 1, slot_ptr += 1){
Range_f32 slot_y = If32_size(pos_y, block_height);
Rect_f32 box = Rf32(column_x, slot_y);
draw_rectangle_outline(app, box, 6.f, 3.f, Stag_Margin);
pos_y = slot_y.max;
f32 y = (tabs_y.min + tabs_y.max - line_height)*0.5f;
f32 x = region.x0;
Tab_State tab_state = {};
tab_state.p = V2f32(x, y);
tab_state.tabs_y = tabs_y;
tab_state.face_id = face_id;
tab_state.x_half_padding = x_half_padding;
tab_state.m_p = m_p;
draw_rectangle(app, tabs_body.min, 0.f, Stag_Margin_Hover);
if (inspect->tab_id == ProfileInspectTab_None){
inspect->tab_id = ProfileInspectTab_Threads;
}
profile_draw_tab(app, &tab_state, inspect,
string_u8_litexpr("threads"),
ProfileInspectTab_Threads);
if (inspect->slot_count > 0){
profile_draw_tab(app, &tab_state, inspect,
string_u8_litexpr("slots"),
ProfileInspectTab_Slots);
}
if (inspect->error_count > 0){
profile_draw_tab(app, &tab_state, inspect,
string_u8_litexpr("errors"),
ProfileInspectTab_Errors);
}
}
// NOTE(allen): header text
{
draw_set_clip(app, Rf32(text_x, full_y));
switch (inspect->tab_id){
case ProfileInspectTab_Slots:
{
draw_set_clip(app, tabs_body.max);
Range_f32 x = rect_range_x(tabs_body.max);
f32 y_pos = tabs_body.max.y0;
for (Profile_Slot *node = inspect->first_slot;
node != 0;
node = node->next){
Range_f32 y = If32_size(y_pos, block_height);
i32 name_width = 30;
Fancy_String_List list = {};
if (node->name.size > name_width){
push_fancy_stringf(scratch, &list, fancy_id(Stag_Pop1),
"%.*s... ",
name_width - 3, node->name.str);
}
else{
push_fancy_stringf(scratch, &list, fancy_id(Stag_Pop1),
"%-*.*s ",
name_width,
string_expand(node->name));
}
if (node->corrupted_time){
push_fancy_string(scratch, &list, fancy_id(Stag_Pop2),
string_u8_litexpr("timing error "));
}
else{
push_fancy_stringf(scratch, &list, fancy_id(Stag_Pop2),
"%11.8fs ",
((f32)node->total_time)/1000000.f);
}
push_fancy_stringf(scratch, &list, fancy_id(Stag_Keyword),
"hit # %5d", node->hit_count);
Vec2_f32 p = V2f32(x.min + x_half_padding,
(y.min + y.max - line_height)*0.5f);
draw_fancy_string(app, face_id, list.first, p, 0, 0);
Rect_f32 box = Rf32(x, y);
int_color margin = Stag_Margin;
if (rect_contains_point(box, m_p)){
inspect->location_jump_hovered = node->location;
margin = Stag_Margin_Hover;
}
draw_rectangle_outline(app, box, 6.f, 3.f, margin);
y_pos = y.max;
}
}break;
case ProfileInspectTab_Errors:
{
draw_set_clip(app, tabs_body.max);
Range_f32 x = rect_range_x(tabs_body.max);
f32 y_pos = tabs_body.max.y0;
for (Profile_Error *node = inspect->first_error;
node != 0;
node = node->next){
Range_f32 y = If32_size(y_pos, block_height);
Fancy_String_List list = {};
push_fancy_string(scratch, &list, fancy_id(Stag_Pop2),
node->message);
Vec2_f32 p = V2f32(x.min + x_half_padding,
(y.min + y.max - line_height)*0.5f);
draw_fancy_string(app, face_id, list.first, p, 0, 0);
Rect_f32 box = Rf32(x, y);
int_color margin = Stag_Margin;
if (rect_contains_point(box, m_p)){
inspect->location_jump_hovered = node->location;
margin = Stag_Margin_Hover;
}
draw_rectangle_outline(app, box, 6.f, 3.f, margin);
y_pos = y.max;
}
}break;
}
if (inspect->tab_id_hovered != ProfileInspectTab_None){
// NOTE(allen): no tool tip for tabs
}
else if (inspect->location_jump_hovered.size > 0){
draw_set_clip(app, region);
Fancy_String_List list = {};
push_fancy_stringf(scratch, &list, fancy_id(Stag_Keyword),
"%d", column->thread_id);
f32 y = (header_y.min + header_y.max - line_height)*0.5f;
draw_fancy_string(app, face_id, list.first, V2f32(text_x.min, y), Stag_Default, 0);
}
// NOTE(allen): list text counts
{
Range_f32 x = If32_size(text_x.min + label_width + time_width + half_padding, count_width);
f32 pos_y = body_y.min;
Profile_Universal_Slot **slot_ptr = column->sorted_slots;
for (i32 i = 0; i < count; i += 1, slot_ptr += 1){
Range_f32 slot_y = If32_size(pos_y, block_height);
f32 y = (slot_y.min + slot_y.max - line_height)*0.5f;
Profile_Universal_Slot *slot = *slot_ptr;
Fancy_String_List list = {};
push_fancy_stringf(scratch, &list, fancy_id(Stag_Pop1),
"%5u", slot->count);
draw_fancy_string(app, face_id, list.first, V2f32(x.min, y), Stag_Default, 0);
pos_y = slot_y.max;
push_fancy_stringf(scratch, &list, fancy_rgba(1.f, 1.f, 1.f, 0.5f),
"jump to: '%.*s'",
string_expand(inspect->location_jump_hovered));
f32 width = get_fancy_string_advance(app, face_id, list.first);
Vec2_f32 dims = V2f32(width + x_padding, line_height + 2.f);
Rect_f32 box = get_tool_tip_box(region, m_p, dims);
if (rect_area(box) > 0.f){
draw_rectangle(app, box, 6.f, 0x80000000);
draw_fancy_string(app, face_id, list.first,
V2f32(box.x0 + x_half_padding, box.y0 + 1.f),
0, 0);
}
}
// NOTE(allen): list text labels
{
Range_f32 x = If32_size(text_x.min + label_width + half_padding, time_width - half_padding);
draw_set_clip(app, Rf32(x, full_y));
f32 pos_y = body_y.min;
Profile_Universal_Slot **slot_ptr = column->sorted_slots;
for (i32 i = 0; i < count; i += 1, slot_ptr += 1){
Range_f32 slot_y = If32_size(pos_y, block_height);
f32 y = (slot_y.min + slot_y.max - line_height)*0.5f;
Profile_Universal_Slot *slot = *slot_ptr;
Fancy_String_List list = {};
push_fancy_stringf(scratch, &list, fancy_id(Stag_Pop2),
"%-8.6f", (f32)(slot->total_time)/1000000.f);
draw_fancy_string(app, face_id, list.first, V2f32(x.min, y), Stag_Default, 0);
pos_y = slot_y.max;
}
}
// NOTE(allen): list text labels
{
Range_f32 x = If32_size(text_x.min, label_width - half_padding);
draw_set_clip(app, Rf32(x, full_y));
f32 pos_y = body_y.min;
Profile_Universal_Slot **slot_ptr = column->sorted_slots;
for (i32 i = 0; i < count; i += 1, slot_ptr += 1){
Range_f32 slot_y = If32_size(pos_y, block_height);
f32 y = (slot_y.min + slot_y.max - line_height)*0.5f;
Profile_Universal_Slot *slot = *slot_ptr;
Fancy_String_List list = {};
push_fancy_stringf(scratch, &list, fancy_id(Stag_Default),
"%.*s ", string_expand(slot->name));
draw_fancy_string(app, face_id, list.first, V2f32(x.min, y), Stag_Default, 0);
pos_y = slot_y.max;
}
}
pos_x = column_x.max;
}
system_mutex_release(profile_history.mutex);
draw_set_clip(app, prev_clip);
}
CUSTOM_COMMAND_SIG(profile_inspect)
CUSTOM_DOC("Inspect all currently collected profiling information in 4coder's self profiler.")
{
if (HasFlag(profile_history.disable_bits, ProfileEnable_InspectBit)){
if (HasFlag(global_prof_list.disable_bits, ProfileEnable_InspectBit)){
return;
}
profile_history_set_enabled(false, ProfileEnable_InspectBit);
global_prof_set_enabled(false, ProfileEnable_InspectBit);
Scratch_Block scratch(app);
global_profile_inspection = profile_inspect(scratch, &profile_history);
global_profile_inspection = profile_parse(scratch);
Profile_Inspection *insp = &global_profile_inspection;
View_ID view = get_active_view(app, Access_Always);
View_Context ctx = view_current_context(app, view);
@ -299,18 +399,32 @@ CUSTOM_DOC("Inspect all currently collected profiling information in 4coder's se
break;
}
#if 0
b32 handled = true;
switch (in.event.kind){
case InputEventKind_MouseButton:
{
switch (in.event.mouse.code){
case MouseCode_Left:
{
if (insp->tab_id_hovered != ProfileInspectTab_None){
insp->tab_id = insp->tab_id_hovered;
}
else if (insp->location_jump_hovered.size != 0){
View_ID target_view = view;
target_view = get_next_view_looped_primary_panels(app, target_view, Access_Always);
String_Const_u8 location = insp->location_jump_hovered;
jump_to_location(app, target_view, location);
}
}break;
}
}break;
default:
{
handled = false;
}break;
}
#else
b32 handled = false;
#endif
if (!handled){
// TODO(allen): dedup this stuff.
// TODO(allen): get mapping and map from a more flexible source.
@ -337,7 +451,7 @@ CUSTOM_DOC("Inspect all currently collected profiling information in 4coder's se
}
}
profile_history_set_enabled(true, ProfileEnable_InspectBit);
global_prof_set_enabled(true, ProfileEnable_InspectBit);
view_pop_context(app, view);
}

View File

@ -7,41 +7,62 @@
#if !defined(FCODER_PROFILE_INSPECT_H)
#define FCODER_PROFILE_INSPECT_H
struct Profile_Group_Ptr{
Profile_Group_Ptr *next;
Profile_Group *group;
};
struct Profile_Universal_Slot{
Profile_Universal_Slot *next;
String_Const_u8 source_location;
u32 slot_index;
struct Profile_Slot{
Profile_Slot *next;
String_Const_u8 location;
String_Const_u8 name;
u32 count;
b32 corrupted_time;
u64 total_time;
i32 hit_count;
};
struct Profile_Thread{
Profile_Thread *next;
struct Profile_Node{
Profile_Node *next;
Profile_Slot *slot;
Range_u64 time;
Profile_ID id;
Profile_Node *first_child;
Profile_Node *last_child;
i32 child_count;
b32 closed;
};
struct Profile_Inspection_Thread{
i32 thread_id;
Profile_Group_Ptr *first_group;
Profile_Group_Ptr *last_group;
Profile_Universal_Slot *first_slot;
Profile_Universal_Slot *last_slot;
i32 slot_count;
Profile_Universal_Slot **sorted_slots;
Profile_Node root;
};
struct Profile_Error{
Profile_Error *next;
String_Const_u8 message;
String_Const_u8 location;
};
typedef i32 Profile_Inspection_Tab;
enum{
ProfileInspectTab_None,
ProfileInspectTab_Threads,
ProfileInspectTab_Slots,
ProfileInspectTab_Errors
};
struct Profile_Inspection{
Profile_Thread *thread_first;
Profile_Thread *thread_last;
Profile_Slot *first_slot;
Profile_Slot *last_slot;
Profile_Error *first_error;
Profile_Error *last_error;
Profile_Inspection_Thread *threads;
i32 slot_count;
i32 thread_count;
i32 error_count;
Profile_Inspection_Tab tab_id;
Profile_Inspection_Tab tab_id_hovered;
String_Const_u8 location_jump_hovered;
};
global Profile_Inspection global_profile_inspection = {};

View File

@ -0,0 +1,21 @@
/*
* 4coder_profile_static_disable.cpp - Statically removes all profile posting code
* that follows until the next 4coder_profile_static_enable.cpp
*/
// TOP
#if defined(ProfileBegin)
#undef ProfileBegin
#undef ProfileEnd
#undef ProfileBlock
#undef ProfileScope
#endif
#define ProfileBegin(T,N)
#define ProfileEnd(T,I)
#define ProfileBlock(T,N)
#define ProfileScope(T,N)
// BOTTOM

View File

@ -0,0 +1,29 @@
/*
* 4coder_profile_static_enable.cpp - Macro interface for self profiler.
*/
// TOP
#if defined(ProfileBegin)
#undef ProfileBegin
#undef ProfileEnd
#undef ProfileBlock
#undef ProfileScope
#endif
#define ProfileBegin(T,N) \
thread_profile_record_push((T), system_now_time(), \
string_u8_litexpr(N), string_u8_litexpr(file_name_line_number))
#define ProfileEnd(T,I) thread_profile_record_pop((T), system_now_time(), (I))
#define ProfileBlock(T,N) \
Profile_Block glue(profile_block_, __LINE__) \
((T), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number))
#define ProfileScope(T,N) \
Profile_Scope_Block glue(profile_block_, __LINE__) \
((T), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number))
// BOTTOM

View File

@ -289,6 +289,7 @@ word_complete_list_extend_from_raw(Application_Links *app, Arena *arena,
String_Match_List *matches,
List_String_Const_u8 *list,
Table_Data_u64 *used_table){
ProfileScope(app, "word complete list extend from raw");
Scratch_Block scratch(app);
for (String_Match *node = matches->first;
node != 0;
@ -391,6 +392,8 @@ word_complete_it_read(Word_Complete_Iterator *it){
CUSTOM_COMMAND_SIG(word_complete)
CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.")
{
ProfileScope(app, "word complete");
View_ID view = get_active_view(app, Access_ReadWriteVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
if (buffer != 0){
@ -412,6 +415,8 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with
local_persist Word_Complete_State state = {};
if (first_completion || !state.initialized){
ProfileBlock(app, "word complete state init");
word_complete_it_release(&state.it);
i64 pos = view_get_cursor_pos(app, view);
@ -425,6 +430,8 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with
}
if (state.initialized){
ProfileBlock(app, "word complete apply");
word_complete_it_next(&state.it);
String_Const_u8 str = word_complete_it_read(&state.it);

View File

@ -454,18 +454,18 @@ STRUCT Record_Info{
TYPEDEF void Custom_Command_Function(struct Application_Links *app);
#if defined(CUSTOM_COMMAND_SIG) || defined(CUSTOM_DOC) || defined(CUSTOM_ALIAS)
#error Please do not define CUSTOM_COMMAND_SIG, CUSTOM_DOC, or CUSTOM_ALIAS
#if defined(CUSTOM_COMMAND_SIG) || defined(CUSTOM_UI_COMMAND) || defined(CUSTOM_DOC) || defined(CUSTOM_COMMAND)
#error Please do not define CUSTOM_COMMAND_SIG, CUSTOM_DOC, or CUSTOM_UI_COMMAND
#endif
#if !defined(META_PASS)
#define CUSTOM_COMMAND_SIG(name) void name(struct Application_Links *app)
#define CUSTOM_UI_COMMAND_SIG(name) void name(struct Application_Links *app)
#define CUSTOM_DOC(str)
#define CUSTOM_ALIAS(x) x
#else
#define CUSTOM_COMMAND_SIG(name) CUSTOM_COMMAND_SIG(name, __FILE__, __LINE__)
#define CUSTOM_COMMAND_SIG(name) CUSTOM_COMMAND(name, __FILE__, __LINE__, Normal)
#define CUSTOM_UI_COMMAND_SIG(name) CUSTOM_COMMAND(name, __FILE__, __LINE__, UI)
#define CUSTOM_DOC(str) CUSTOM_DOC(str)
#define CUSTOM_ALIAS(x) CUSTOM_ALIAS(x)
#endif
// TODO(allen): rename

View File

@ -223,6 +223,7 @@ CUSTOM_COMMAND_SIG(default_try_exit);
#endif
struct Command_Metadata{
PROC_LINKS(Custom_Command_Function, void) *proc;
b32 is_ui;
char *name;
i32 name_len;
char *description;
@ -232,217 +233,217 @@ i32 source_name_len;
i32 line_number;
};
static Command_Metadata fcoder_metacmd_table[211] = {
{ PROC_LINKS(default_view_input_handler, 0), "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 56 },
{ PROC_LINKS(profile_enable, 0), "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 127 },
{ PROC_LINKS(profile_disable, 0), "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 133 },
{ PROC_LINKS(profile_clear, 0), "profile_clear", 13, "Clear all profiling information from 4coder's self profiler.", 60, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 139 },
{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2106 },
{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2112 },
{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2118 },
{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2124 },
{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2130 },
{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2138 },
{ PROC_LINKS(change_active_panel, 0), "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 203 },
{ PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 213 },
{ PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 223 },
{ PROC_LINKS(open_panel_hsplit, 0), "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 233 },
{ PROC_LINKS(suppress_mouse, 0), "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 298 },
{ PROC_LINKS(allow_mouse, 0), "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 304 },
{ PROC_LINKS(toggle_mouse, 0), "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 310 },
{ PROC_LINKS(set_mode_to_original, 0), "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 316 },
{ PROC_LINKS(set_mode_to_notepad_like, 0), "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 322 },
{ PROC_LINKS(toggle_highlight_line_at_cursor, 0), "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 328 },
{ PROC_LINKS(toggle_highlight_enclosing_scopes, 0), "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 334 },
{ PROC_LINKS(toggle_paren_matching_helper, 0), "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 340 },
{ PROC_LINKS(toggle_fullscreen, 0), "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 346 },
{ PROC_LINKS(write_text_input, 0), "write_text_input", 16, "Inserts whatever character was used to trigger this command.", 60, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 58 },
{ PROC_LINKS(write_space, 0), "write_space", 11, "Inserts an underscore.", 22, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 66 },
{ PROC_LINKS(write_underscore, 0), "write_underscore", 16, "Inserts an underscore.", 22, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 72 },
{ PROC_LINKS(delete_char, 0), "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 78 },
{ PROC_LINKS(backspace_char, 0), "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 95 },
{ PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 114 },
{ PROC_LINKS(cursor_mark_swap, 0), "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 123 },
{ PROC_LINKS(delete_range, 0), "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 133 },
{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 153 },
{ PROC_LINKS(delete_alpha_numeric_boundary, 0), "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 161 },
{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 181 },
{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 189 },
{ PROC_LINKS(center_view, 0), "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 199 },
{ PROC_LINKS(left_adjust_view, 0), "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 213 },
{ PROC_LINKS(click_set_cursor_and_mark, 0), "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 225 },
{ PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 235 },
{ PROC_LINKS(click_set_cursor_if_lbutton, 0), "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 245 },
{ PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 257 },
{ PROC_LINKS(mouse_wheel_scroll, 0), "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 267 },
{ PROC_LINKS(move_up, 0), "move_up", 7, "Moves the cursor up one line.", 29, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 321 },
{ PROC_LINKS(move_down, 0), "move_down", 9, "Moves the cursor down one line.", 31, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 327 },
{ PROC_LINKS(move_up_10, 0), "move_up_10", 10, "Moves the cursor up ten lines.", 30, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 333 },
{ PROC_LINKS(move_down_10, 0), "move_down_10", 12, "Moves the cursor down ten lines.", 32, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 339 },
{ PROC_LINKS(move_down_textual, 0), "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 345 },
{ PROC_LINKS(page_up, 0), "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 355 },
{ PROC_LINKS(page_down, 0), "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 363 },
{ PROC_LINKS(move_up_to_blank_line, 0), "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 393 },
{ PROC_LINKS(move_down_to_blank_line, 0), "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 399 },
{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 405 },
{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 411 },
{ PROC_LINKS(move_up_to_blank_line_end, 0), "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 417 },
{ PROC_LINKS(move_down_to_blank_line_end, 0), "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 423 },
{ PROC_LINKS(move_left, 0), "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 429 },
{ PROC_LINKS(move_right, 0), "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 441 },
{ PROC_LINKS(move_right_whitespace_boundary, 0), "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 463 },
{ PROC_LINKS(move_left_whitespace_boundary, 0), "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 471 },
{ PROC_LINKS(move_right_token_boundary, 0), "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 479 },
{ PROC_LINKS(move_left_token_boundary, 0), "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 487 },
{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 495 },
{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 503 },
{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 511 },
{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 519 },
{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 527 },
{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 535 },
{ PROC_LINKS(select_all, 0), "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 545 },
{ PROC_LINKS(to_uppercase, 0), "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 558 },
{ PROC_LINKS(to_lowercase, 0), "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 571 },
{ PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 584 },
{ PROC_LINKS(basic_change_active_panel, 0), "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 618 },
{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 626 },
{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 635 },
{ PROC_LINKS(hide_scrollbar, 0), "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 642 },
{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 649 },
{ PROC_LINKS(hide_filebar, 0), "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 656 },
{ PROC_LINKS(toggle_filebar, 0), "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 663 },
{ PROC_LINKS(toggle_fps_meter, 0), "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 672 },
{ PROC_LINKS(increase_face_size, 0), "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 678 },
{ PROC_LINKS(decrease_face_size, 0), "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 689 },
{ PROC_LINKS(mouse_wheel_change_face_size, 0), "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 700 },
{ PROC_LINKS(toggle_virtual_whitespace, 0), "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 717 },
{ PROC_LINKS(toggle_show_whitespace, 0), "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 726 },
{ PROC_LINKS(toggle_line_numbers, 0), "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 735 },
{ PROC_LINKS(exit_4coder, 0), "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 741 },
{ PROC_LINKS(goto_line, 0), "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 749 },
{ PROC_LINKS(search, 0), "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 977 },
{ PROC_LINKS(reverse_search, 0), "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 983 },
{ PROC_LINKS(search_identifier, 0), "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 989 },
{ PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 995 },
{ PROC_LINKS(replace_in_range, 0), "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1042 },
{ PROC_LINKS(replace_in_buffer, 0), "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1051 },
{ PROC_LINKS(replace_in_all_buffers, 0), "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1060 },
{ 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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1150 },
{ 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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1171 },
{ 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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1187 },
{ PROC_LINKS(save_all_dirty_buffers, 0), "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1222 },
{ PROC_LINKS(delete_file_query, 0), "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1247 },
{ PROC_LINKS(save_to_query, 0), "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1291 },
{ PROC_LINKS(rename_file_query, 0), "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1324 },
{ 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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1362 },
{ PROC_LINKS(move_line_up, 0), "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1396 },
{ PROC_LINKS(move_line_down, 0), "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1402 },
{ PROC_LINKS(duplicate_line, 0), "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1408 },
{ PROC_LINKS(delete_line, 0), "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1422 },
{ 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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1487 },
{ PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1519 },
{ PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1532 },
{ PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1544 },
{ PROC_LINKS(kill_buffer, 0), "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1578 },
{ PROC_LINKS(save, 0), "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1586 },
{ PROC_LINKS(reopen, 0), "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1596 },
{ PROC_LINKS(undo, 0), "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1825 },
{ PROC_LINKS(redo, 0), "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1838 },
{ PROC_LINKS(undo_all_buffers, 0), "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1852 },
{ PROC_LINKS(redo_all_buffers, 0), "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1923 },
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2024 },
{ PROC_LINKS(default_file_externally_modified, 0), "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2031 },
{ PROC_LINKS(set_eol_mode_to_crlf, 0), "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 80 },
{ PROC_LINKS(set_eol_mode_to_lf, 0), "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 91 },
{ PROC_LINKS(set_eol_mode_to_binary, 0), "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 102 },
{ PROC_LINKS(set_eol_mode_from_contents, 0), "set_eol_mode_from_contents", 26, "Sets the buffer's line ending mode to match the contents of the buffer.", 71, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 113 },
{ PROC_LINKS(interactive_switch_buffer, 0), "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 487 },
{ PROC_LINKS(interactive_kill_buffer, 0), "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 506 },
{ PROC_LINKS(interactive_open_or_new, 0), "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 577 },
{ PROC_LINKS(interactive_new, 0), "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 616 },
{ PROC_LINKS(interactive_open, 0), "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 649 },
{ PROC_LINKS(command_lister, 0), "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 712 },
{ PROC_LINKS(auto_indent_whole_file, 0), "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 356 },
{ PROC_LINKS(auto_indent_line_at_cursor, 0), "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 365 },
{ PROC_LINKS(auto_indent_range, 0), "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 375 },
{ PROC_LINKS(write_text_and_auto_indent, 0), "write_text_and_auto_indent", 26, "Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.", 145, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 385 },
{ PROC_LINKS(list_all_locations, 0), "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 166 },
{ 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, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 172 },
{ PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 178 },
{ 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, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 184 },
{ PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 190 },
{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 196 },
{ PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 202 },
{ PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 208 },
{ PROC_LINKS(list_all_locations_of_type_definition, 0), "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 214 },
{ 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, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 222 },
{ PROC_LINKS(word_complete, 0), "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 391 },
{ PROC_LINKS(goto_jump_at_cursor, 0), "goto_jump_at_cursor", 19, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.", 187, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 346 },
{ PROC_LINKS(goto_jump_at_cursor_same_panel, 0), "goto_jump_at_cursor_same_panel", 30, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.", 167, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 373 },
{ PROC_LINKS(goto_next_jump, 0), "goto_next_jump", 14, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 462 },
{ PROC_LINKS(goto_prev_jump, 0), "goto_prev_jump", 14, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations.", 127, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 479 },
{ PROC_LINKS(goto_next_jump_no_skips, 0), "goto_next_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations.", 132, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 492 },
{ PROC_LINKS(goto_prev_jump_no_skips, 0), "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 509 },
{ PROC_LINKS(goto_first_jump, 0), "goto_first_jump", 15, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.", 95, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 523 },
{ PROC_LINKS(goto_first_jump_same_panel_sticky, 0), "goto_first_jump_same_panel_sticky", 33, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.", 153, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 540 },
{ PROC_LINKS(if_read_only_goto_position, 0), "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 562 },
{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 579 },
{ PROC_LINKS(view_jump_list_with_lister, 0), "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 104 },
{ PROC_LINKS(show_the_log_graph, 0), "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 990 },
{ PROC_LINKS(copy, 0), "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 19 },
{ PROC_LINKS(cut, 0), "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 28 },
{ PROC_LINKS(paste, 0), "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 39 },
{ 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, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 73 },
{ PROC_LINKS(paste_and_indent, 0), "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 115 },
{ 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, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 122 },
{ PROC_LINKS(execute_previous_cli, 0), "execute_previous_cli", 20, "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "w:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 7 },
{ PROC_LINKS(execute_any_cli, 0), "execute_any_cli", 15, "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "w:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 22 },
{ PROC_LINKS(build_search, 0), "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 128 },
{ PROC_LINKS(build_in_build_panel, 0), "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 163 },
{ PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 178 },
{ PROC_LINKS(change_to_build_panel, 0), "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 184 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 917 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 923 },
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 929 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 937 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 944 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 969 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1303 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1310 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1316 },
{ 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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1322 },
{ PROC_LINKS(project_command_lister, 0), "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1338 },
{ PROC_LINKS(list_all_functions_current_buffer, 0), "list_all_functions_current_buffer", 33, "Creates a jump list of lines of the current buffer that appear to define or declare functions.", 94, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 267 },
{ PROC_LINKS(list_all_functions_current_buffer_lister, 0), "list_all_functions_current_buffer_lister", 40, "Creates a lister of locations that look like function definitions and declarations in the buffer.", 97, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 277 },
{ PROC_LINKS(list_all_functions_all_buffers, 0), "list_all_functions_all_buffers", 30, "Creates a jump list of lines from all buffers that appear to define or declare functions.", 89, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 289 },
{ PROC_LINKS(list_all_functions_all_buffers_lister, 0), "list_all_functions_all_buffers_lister", 37, "Creates a lister of locations that look like function definitions and declarations all buffers.", 95, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 295 },
{ PROC_LINKS(select_surrounding_scope, 0), "select_surrounding_scope", 24, "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 7 },
{ PROC_LINKS(select_next_scope_absolute, 0), "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 32 },
{ PROC_LINKS(select_next_scope_after_current, 0), "select_next_scope_after_current", 31, "Finds the first scope started by '{' after the mark and puts the cursor and mark on the '{' and '}'. This command is meant to be used after a scope is already selected so that it will have the effect of selecting the next scope after the current scope.", 253, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 41 },
{ PROC_LINKS(select_prev_scope_absolute, 0), "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 50 },
{ 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, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 67 },
{ PROC_LINKS(delete_current_scope, 0), "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 73 },
{ PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 },
{ PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 54 },
{ PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 62 },
{ PROC_LINKS(if0_off, 0), "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 70 },
{ PROC_LINKS(write_todo, 0), "write_todo", 10, "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 76 },
{ PROC_LINKS(write_hack, 0), "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 82 },
{ PROC_LINKS(write_note, 0), "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 88 },
{ PROC_LINKS(write_block, 0), "write_block", 11, "At the cursor, insert a block comment.", 38, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 94 },
{ PROC_LINKS(write_zero_struct, 0), "write_zero_struct", 17, "At the cursor, insert a ' = {};'.", 33, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 100 },
{ PROC_LINKS(comment_line, 0), "comment_line", 12, "Insert '//' at the beginning of the line after leading whitespace.", 66, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 125 },
{ PROC_LINKS(uncomment_line, 0), "uncomment_line", 14, "If present, delete '//' at the beginning of the line after leading whitespace.", 78, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 137 },
{ PROC_LINKS(comment_line_toggle, 0), "comment_line_toggle", 19, "Turns uncommented lines into commented lines and vice versa for comments starting with '//'.", 92, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 149 },
{ PROC_LINKS(snippet_lister, 0), "snippet_lister", 14, "Opens a snippet lister for inserting whole pre-written snippets of text.", 72, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 231 },
{ PROC_LINKS(miblo_increment_basic, 0), "miblo_increment_basic", 21, "Increment an integer under the cursor by one.", 45, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 29 },
{ PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 44 },
{ PROC_LINKS(miblo_increment_time_stamp, 0), "miblo_increment_time_stamp", 26, "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 231 },
{ 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, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 237 },
{ PROC_LINKS(miblo_increment_time_stamp_minute, 0), "miblo_increment_time_stamp_minute", 33, "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 243 },
{ PROC_LINKS(miblo_decrement_time_stamp_minute, 0), "miblo_decrement_time_stamp_minute", 33, "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 249 },
{ PROC_LINKS(profile_inspect, 0), "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 278 },
{ PROC_LINKS(default_startup, 0), "default_startup", 15, "Default command for responding to a startup event", 49, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 },
{ PROC_LINKS(default_try_exit, 0), "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 21 },
{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 56 },
{ PROC_LINKS(profile_enable, 0), false, "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 196 },
{ PROC_LINKS(profile_disable, 0), false, "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 202 },
{ PROC_LINKS(profile_clear, 0), false, "profile_clear", 13, "Clear all profiling information from 4coder's self profiler.", 60, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 208 },
{ PROC_LINKS(seek_beginning_of_textual_line, 0), false, "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2106 },
{ PROC_LINKS(seek_end_of_textual_line, 0), false, "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2112 },
{ PROC_LINKS(seek_beginning_of_line, 0), false, "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2118 },
{ PROC_LINKS(seek_end_of_line, 0), false, "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2124 },
{ PROC_LINKS(goto_beginning_of_file, 0), false, "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2130 },
{ PROC_LINKS(goto_end_of_file, 0), false, "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2138 },
{ PROC_LINKS(change_active_panel, 0), false, "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 213 },
{ PROC_LINKS(change_active_panel_backwards, 0), false, "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 223 },
{ PROC_LINKS(open_panel_vsplit, 0), false, "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 233 },
{ PROC_LINKS(open_panel_hsplit, 0), false, "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 243 },
{ PROC_LINKS(suppress_mouse, 0), false, "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 308 },
{ PROC_LINKS(allow_mouse, 0), false, "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 314 },
{ PROC_LINKS(toggle_mouse, 0), false, "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 320 },
{ PROC_LINKS(set_mode_to_original, 0), false, "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 326 },
{ PROC_LINKS(set_mode_to_notepad_like, 0), false, "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 332 },
{ PROC_LINKS(toggle_highlight_line_at_cursor, 0), false, "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 338 },
{ PROC_LINKS(toggle_highlight_enclosing_scopes, 0), false, "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 344 },
{ PROC_LINKS(toggle_paren_matching_helper, 0), false, "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 350 },
{ PROC_LINKS(toggle_fullscreen, 0), false, "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 356 },
{ PROC_LINKS(write_text_input, 0), false, "write_text_input", 16, "Inserts whatever character was used to trigger this command.", 60, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 58 },
{ PROC_LINKS(write_space, 0), false, "write_space", 11, "Inserts an underscore.", 22, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 66 },
{ PROC_LINKS(write_underscore, 0), false, "write_underscore", 16, "Inserts an underscore.", 22, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 72 },
{ PROC_LINKS(delete_char, 0), false, "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 78 },
{ PROC_LINKS(backspace_char, 0), false, "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 95 },
{ PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 114 },
{ PROC_LINKS(cursor_mark_swap, 0), false, "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 123 },
{ PROC_LINKS(delete_range, 0), false, "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 133 },
{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), false, "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 153 },
{ PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 161 },
{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), false, "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 181 },
{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), false, "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 189 },
{ PROC_LINKS(center_view, 0), false, "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 199 },
{ PROC_LINKS(left_adjust_view, 0), false, "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 213 },
{ PROC_LINKS(click_set_cursor_and_mark, 0), false, "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 225 },
{ PROC_LINKS(click_set_cursor, 0), false, "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 235 },
{ PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 245 },
{ PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 257 },
{ PROC_LINKS(mouse_wheel_scroll, 0), false, "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 267 },
{ PROC_LINKS(move_up, 0), false, "move_up", 7, "Moves the cursor up one line.", 29, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 321 },
{ PROC_LINKS(move_down, 0), false, "move_down", 9, "Moves the cursor down one line.", 31, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 327 },
{ PROC_LINKS(move_up_10, 0), false, "move_up_10", 10, "Moves the cursor up ten lines.", 30, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 333 },
{ PROC_LINKS(move_down_10, 0), false, "move_down_10", 12, "Moves the cursor down ten lines.", 32, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 339 },
{ PROC_LINKS(move_down_textual, 0), false, "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 345 },
{ PROC_LINKS(page_up, 0), false, "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 355 },
{ PROC_LINKS(page_down, 0), false, "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 363 },
{ PROC_LINKS(move_up_to_blank_line, 0), false, "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 393 },
{ PROC_LINKS(move_down_to_blank_line, 0), false, "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 399 },
{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), false, "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 405 },
{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), false, "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 411 },
{ PROC_LINKS(move_up_to_blank_line_end, 0), false, "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 417 },
{ PROC_LINKS(move_down_to_blank_line_end, 0), false, "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 423 },
{ PROC_LINKS(move_left, 0), false, "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 429 },
{ PROC_LINKS(move_right, 0), false, "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 441 },
{ PROC_LINKS(move_right_whitespace_boundary, 0), false, "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 463 },
{ PROC_LINKS(move_left_whitespace_boundary, 0), false, "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 471 },
{ PROC_LINKS(move_right_token_boundary, 0), false, "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 479 },
{ PROC_LINKS(move_left_token_boundary, 0), false, "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 487 },
{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), false, "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 495 },
{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), false, "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 503 },
{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), false, "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 511 },
{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), false, "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 519 },
{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), false, "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 527 },
{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), false, "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 535 },
{ PROC_LINKS(select_all, 0), false, "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 545 },
{ PROC_LINKS(to_uppercase, 0), false, "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 558 },
{ PROC_LINKS(to_lowercase, 0), false, "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 571 },
{ PROC_LINKS(clean_all_lines, 0), false, "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 584 },
{ PROC_LINKS(basic_change_active_panel, 0), false, "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 618 },
{ PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 626 },
{ PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 635 },
{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 642 },
{ PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 649 },
{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 656 },
{ PROC_LINKS(toggle_filebar, 0), false, "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 663 },
{ PROC_LINKS(toggle_fps_meter, 0), false, "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 672 },
{ PROC_LINKS(increase_face_size, 0), false, "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 678 },
{ PROC_LINKS(decrease_face_size, 0), false, "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 689 },
{ PROC_LINKS(mouse_wheel_change_face_size, 0), false, "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 700 },
{ PROC_LINKS(toggle_virtual_whitespace, 0), false, "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 717 },
{ PROC_LINKS(toggle_show_whitespace, 0), false, "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 726 },
{ PROC_LINKS(toggle_line_numbers, 0), false, "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 735 },
{ PROC_LINKS(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 741 },
{ PROC_LINKS(goto_line, 0), false, "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 749 },
{ PROC_LINKS(search, 0), false, "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 977 },
{ PROC_LINKS(reverse_search, 0), false, "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 983 },
{ PROC_LINKS(search_identifier, 0), false, "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 989 },
{ PROC_LINKS(reverse_search_identifier, 0), false, "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 995 },
{ PROC_LINKS(replace_in_range, 0), false, "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1042 },
{ PROC_LINKS(replace_in_buffer, 0), false, "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1051 },
{ PROC_LINKS(replace_in_all_buffers, 0), false, "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1060 },
{ PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1150 },
{ PROC_LINKS(query_replace_identifier, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1171 },
{ PROC_LINKS(query_replace_selection, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1187 },
{ PROC_LINKS(save_all_dirty_buffers, 0), false, "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1222 },
{ PROC_LINKS(delete_file_query, 0), false, "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1247 },
{ PROC_LINKS(save_to_query, 0), false, "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1291 },
{ PROC_LINKS(rename_file_query, 0), false, "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1324 },
{ PROC_LINKS(make_directory_query, 0), false, "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1362 },
{ PROC_LINKS(move_line_up, 0), false, "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1396 },
{ PROC_LINKS(move_line_down, 0), false, "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1402 },
{ PROC_LINKS(duplicate_line, 0), false, "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1408 },
{ PROC_LINKS(delete_line, 0), false, "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1422 },
{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1487 },
{ PROC_LINKS(open_matching_file_cpp, 0), false, "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1519 },
{ PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1532 },
{ PROC_LINKS(swap_buffers_between_panels, 0), false, "swap_buffers_between_panels", 27, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1544 },
{ PROC_LINKS(kill_buffer, 0), false, "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1578 },
{ PROC_LINKS(save, 0), false, "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1586 },
{ PROC_LINKS(reopen, 0), false, "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1596 },
{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1825 },
{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1838 },
{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1852 },
{ PROC_LINKS(redo_all_buffers, 0), false, "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1923 },
{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2024 },
{ PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2031 },
{ PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 80 },
{ PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 91 },
{ PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 102 },
{ PROC_LINKS(set_eol_mode_from_contents, 0), false, "set_eol_mode_from_contents", 26, "Sets the buffer's line ending mode to match the contents of the buffer.", 71, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 113 },
{ PROC_LINKS(interactive_switch_buffer, 0), true, "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 487 },
{ PROC_LINKS(interactive_kill_buffer, 0), true, "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 506 },
{ PROC_LINKS(interactive_open_or_new, 0), true, "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 577 },
{ PROC_LINKS(interactive_new, 0), true, "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 616 },
{ PROC_LINKS(interactive_open, 0), true, "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 649 },
{ PROC_LINKS(command_lister, 0), true, "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 712 },
{ PROC_LINKS(auto_indent_whole_file, 0), false, "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 356 },
{ PROC_LINKS(auto_indent_line_at_cursor, 0), false, "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 365 },
{ PROC_LINKS(auto_indent_range, 0), false, "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 375 },
{ PROC_LINKS(write_text_and_auto_indent, 0), false, "write_text_and_auto_indent", 26, "Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.", 145, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 385 },
{ PROC_LINKS(list_all_locations, 0), false, "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 166 },
{ PROC_LINKS(list_all_substring_locations, 0), false, "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 172 },
{ PROC_LINKS(list_all_locations_case_insensitive, 0), false, "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 178 },
{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 184 },
{ PROC_LINKS(list_all_locations_of_identifier, 0), false, "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 190 },
{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), false, "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 196 },
{ PROC_LINKS(list_all_locations_of_selection, 0), false, "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 202 },
{ PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), false, "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 208 },
{ PROC_LINKS(list_all_locations_of_type_definition, 0), false, "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 214 },
{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 222 },
{ PROC_LINKS(word_complete, 0), false, "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 392 },
{ PROC_LINKS(goto_jump_at_cursor, 0), false, "goto_jump_at_cursor", 19, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.", 187, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 346 },
{ PROC_LINKS(goto_jump_at_cursor_same_panel, 0), false, "goto_jump_at_cursor_same_panel", 30, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.", 167, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 373 },
{ PROC_LINKS(goto_next_jump, 0), false, "goto_next_jump", 14, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 462 },
{ PROC_LINKS(goto_prev_jump, 0), false, "goto_prev_jump", 14, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations.", 127, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 479 },
{ PROC_LINKS(goto_next_jump_no_skips, 0), false, "goto_next_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations.", 132, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 492 },
{ PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 509 },
{ PROC_LINKS(goto_first_jump, 0), false, "goto_first_jump", 15, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.", 95, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 523 },
{ PROC_LINKS(goto_first_jump_same_panel_sticky, 0), false, "goto_first_jump_same_panel_sticky", 33, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.", 153, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 540 },
{ PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 562 },
{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), false, "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 579 },
{ PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 104 },
{ PROC_LINKS(show_the_log_graph, 0), false, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 990 },
{ PROC_LINKS(copy, 0), false, "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 19 },
{ PROC_LINKS(cut, 0), false, "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 28 },
{ PROC_LINKS(paste, 0), false, "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 39 },
{ PROC_LINKS(paste_next, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 73 },
{ PROC_LINKS(paste_and_indent, 0), false, "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 115 },
{ PROC_LINKS(paste_next_and_indent, 0), false, "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 122 },
{ PROC_LINKS(execute_previous_cli, 0), false, "execute_previous_cli", 20, "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "w:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 7 },
{ PROC_LINKS(execute_any_cli, 0), false, "execute_any_cli", 15, "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "w:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 22 },
{ PROC_LINKS(build_search, 0), false, "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 128 },
{ PROC_LINKS(build_in_build_panel, 0), false, "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 163 },
{ PROC_LINKS(close_build_panel, 0), false, "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 178 },
{ PROC_LINKS(change_to_build_panel, 0), false, "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 184 },
{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 917 },
{ PROC_LINKS(open_all_code, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 923 },
{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 929 },
{ PROC_LINKS(load_project, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 937 },
{ PROC_LINKS(project_fkey_command, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 944 },
{ PROC_LINKS(project_go_to_root_directory, 0), false, "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, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 969 },
{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1303 },
{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1310 },
{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1316 },
{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1322 },
{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1338 },
{ PROC_LINKS(list_all_functions_current_buffer, 0), false, "list_all_functions_current_buffer", 33, "Creates a jump list of lines of the current buffer that appear to define or declare functions.", 94, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 267 },
{ PROC_LINKS(list_all_functions_current_buffer_lister, 0), false, "list_all_functions_current_buffer_lister", 40, "Creates a lister of locations that look like function definitions and declarations in the buffer.", 97, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 277 },
{ PROC_LINKS(list_all_functions_all_buffers, 0), false, "list_all_functions_all_buffers", 30, "Creates a jump list of lines from all buffers that appear to define or declare functions.", 89, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 289 },
{ PROC_LINKS(list_all_functions_all_buffers_lister, 0), false, "list_all_functions_all_buffers_lister", 37, "Creates a lister of locations that look like function definitions and declarations all buffers.", 95, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 295 },
{ PROC_LINKS(select_surrounding_scope, 0), false, "select_surrounding_scope", 24, "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 7 },
{ PROC_LINKS(select_next_scope_absolute, 0), false, "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 32 },
{ PROC_LINKS(select_next_scope_after_current, 0), false, "select_next_scope_after_current", 31, "Finds the first scope started by '{' after the mark and puts the cursor and mark on the '{' and '}'. This command is meant to be used after a scope is already selected so that it will have the effect of selecting the next scope after the current scope.", 253, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 41 },
{ PROC_LINKS(select_prev_scope_absolute, 0), false, "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 50 },
{ PROC_LINKS(place_in_scope, 0), false, "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 67 },
{ PROC_LINKS(delete_current_scope, 0), false, "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 73 },
{ PROC_LINKS(open_long_braces, 0), false, "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 },
{ PROC_LINKS(open_long_braces_semicolon, 0), false, "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 54 },
{ PROC_LINKS(open_long_braces_break, 0), false, "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 62 },
{ PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 70 },
{ PROC_LINKS(write_todo, 0), false, "write_todo", 10, "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 76 },
{ PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 82 },
{ PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 88 },
{ PROC_LINKS(write_block, 0), false, "write_block", 11, "At the cursor, insert a block comment.", 38, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 94 },
{ PROC_LINKS(write_zero_struct, 0), false, "write_zero_struct", 17, "At the cursor, insert a ' = {};'.", 33, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 100 },
{ PROC_LINKS(comment_line, 0), false, "comment_line", 12, "Insert '//' at the beginning of the line after leading whitespace.", 66, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 125 },
{ PROC_LINKS(uncomment_line, 0), false, "uncomment_line", 14, "If present, delete '//' at the beginning of the line after leading whitespace.", 78, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 137 },
{ PROC_LINKS(comment_line_toggle, 0), false, "comment_line_toggle", 19, "Turns uncommented lines into commented lines and vice versa for comments starting with '//'.", 92, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 149 },
{ PROC_LINKS(snippet_lister, 0), false, "snippet_lister", 14, "Opens a snippet lister for inserting whole pre-written snippets of text.", 72, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 231 },
{ PROC_LINKS(miblo_increment_basic, 0), false, "miblo_increment_basic", 21, "Increment an integer under the cursor by one.", 45, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 29 },
{ PROC_LINKS(miblo_decrement_basic, 0), false, "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 44 },
{ PROC_LINKS(miblo_increment_time_stamp, 0), false, "miblo_increment_time_stamp", 26, "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 231 },
{ PROC_LINKS(miblo_decrement_time_stamp, 0), false, "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 237 },
{ PROC_LINKS(miblo_increment_time_stamp_minute, 0), false, "miblo_increment_time_stamp_minute", 33, "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 243 },
{ PROC_LINKS(miblo_decrement_time_stamp_minute, 0), false, "miblo_decrement_time_stamp_minute", 33, "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 249 },
{ PROC_LINKS(profile_inspect, 0), false, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 377 },
{ PROC_LINKS(default_startup, 0), false, "default_startup", 15, "Default command for responding to a startup event", 49, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 },
{ PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 21 },
};
static i32 fcoder_metacmd_ID_default_view_input_handler = 0;
static i32 fcoder_metacmd_ID_profile_enable = 1;

View File

@ -1440,7 +1440,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
// NOTE(allen): context setup
Thread_Context _tctx = {};
thread_ctx_init(&_tctx, get_base_allocator_system());
thread_ctx_init(&_tctx, get_base_allocator_system(), get_base_allocator_system());
block_zero_struct(&win32vars);
win32vars.tctx = &_tctx;