Added parse error log and parse recover to the config parser
This commit is contained in:
parent
cb1273d4cb
commit
5566572269
|
@ -4,12 +4,6 @@
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
// TODO(allen): Stop handling files this way! My own API should be able to do this!!?!?!?!!?!?!!!!?
|
|
||||||
// NOTE(allen): Actually need binary buffers for some stuff to work, but not this parsing thing here.
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
static CString_Array
|
static CString_Array
|
||||||
get_code_extensions(Extension_List *list){
|
get_code_extensions(Extension_List *list){
|
||||||
CString_Array array = {0};
|
CString_Array array = {0};
|
||||||
|
@ -54,6 +48,50 @@ parse_extension_line_to_extension_list(String str, Extension_List *list){
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
static Error_Location
|
||||||
|
get_error_location(char *base, char *pos){
|
||||||
|
Error_Location location = {0};
|
||||||
|
location.line_number = 1;
|
||||||
|
location.column_number = 1;
|
||||||
|
for (char *ptr = base;
|
||||||
|
ptr < pos;
|
||||||
|
ptr += 1){
|
||||||
|
if (*ptr == '\n'){
|
||||||
|
location.line_number += 1;
|
||||||
|
location.column_number = 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
location.column_number += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String
|
||||||
|
config_stringize_errors(Partition *arena, Config *parsed){
|
||||||
|
String result = {0};
|
||||||
|
result.str = push_array(arena, char, 0);
|
||||||
|
result.memory_size = partition_remaining(arena);
|
||||||
|
for (Config_Error *error = parsed->first_error;
|
||||||
|
error != 0;
|
||||||
|
error = error->next){
|
||||||
|
Error_Location location = get_error_location(parsed->data.str, error->pos);
|
||||||
|
append(&result, error->file_name);
|
||||||
|
append(&result, ":");
|
||||||
|
append_int_to_str(&result, location.line_number);
|
||||||
|
append(&result, ":");
|
||||||
|
append_int_to_str(&result, location.column_number);
|
||||||
|
append(&result, ": ");
|
||||||
|
append(&result, error->text);
|
||||||
|
append(&result, "\n");
|
||||||
|
}
|
||||||
|
result.memory_size = result.size;
|
||||||
|
push_array(arena, char, result.size);
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
static void
|
static void
|
||||||
config_parser__advance_to_next(Config_Parser *ctx){
|
config_parser__advance_to_next(Config_Parser *ctx){
|
||||||
Cpp_Token *t = ctx->token;
|
Cpp_Token *t = ctx->token;
|
||||||
|
@ -145,13 +183,13 @@ config_parser__match_text(Config_Parser *ctx, String text){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Config *config_parser__config(Config_Parser *ctx);
|
static Config *config_parser__config (Config_Parser *ctx);
|
||||||
static int32_t *config_parser__version(Config_Parser *ctx);
|
static int32_t *config_parser__version (Config_Parser *ctx);
|
||||||
static Config_Assignment *config_parser__assignment(Config_Parser *ctx);
|
static Config_Assignment *config_parser__assignment(Config_Parser *ctx);
|
||||||
static Config_LValue *config_parser__lvalue(Config_Parser *ctx);
|
static Config_LValue *config_parser__lvalue (Config_Parser *ctx);
|
||||||
static Config_RValue *config_parser__rvalue(Config_Parser *ctx);
|
static Config_RValue *config_parser__rvalue (Config_Parser *ctx);
|
||||||
static Config_Compound *config_parser__compound(Config_Parser *ctx);
|
static Config_Compound *config_parser__compound (Config_Parser *ctx);
|
||||||
static Config_Compound_Element *config_parser__element(Config_Parser *ctx);
|
static Config_Compound_Element *config_parser__element (Config_Parser *ctx);
|
||||||
|
|
||||||
static Config*
|
static Config*
|
||||||
text_data_and_token_array_to_parse_data(Partition *arena, String file_name, String data, Cpp_Token_Array array){
|
text_data_and_token_array_to_parse_data(Partition *arena, String file_name, String data, Cpp_Token_Array array){
|
||||||
|
@ -164,6 +202,39 @@ text_data_and_token_array_to_parse_data(Partition *arena, String file_name, Stri
|
||||||
return(config);
|
return(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Config_Error*
|
||||||
|
config_parser__push_error(Config_Parser *ctx){
|
||||||
|
Config_Error *error = push_array(ctx->arena, Config_Error, 1);
|
||||||
|
zdll_push_back(ctx->first_error, ctx->last_error, error);
|
||||||
|
error->file_name = ctx->file_name;
|
||||||
|
error->pos = ctx->data.str + ctx->token->start;
|
||||||
|
ctx->count_error += 1;
|
||||||
|
return(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String
|
||||||
|
config_parser__begin_string(Config_Parser *ctx){
|
||||||
|
String str;
|
||||||
|
str.str = push_array(ctx->arena, char, 0);
|
||||||
|
str.size = 0;
|
||||||
|
str.memory_size = ctx->arena->max - ctx->arena->pos;
|
||||||
|
return(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
config_parser__end_string(Config_Parser *ctx, String *str){
|
||||||
|
str->memory_size = str->size;
|
||||||
|
push_array(ctx->arena, char, str->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
config_parser__log_error(Config_Parser *ctx, char *error_text){
|
||||||
|
Config_Error *error = config_parser__push_error(ctx);
|
||||||
|
error->text = config_parser__begin_string(ctx);
|
||||||
|
append(&error->text, error_text);
|
||||||
|
config_parser__end_string(ctx, &error->text);
|
||||||
|
}
|
||||||
|
|
||||||
static Config*
|
static Config*
|
||||||
config_parser__config(Config_Parser *ctx){
|
config_parser__config(Config_Parser *ctx){
|
||||||
int32_t *version = config_parser__version(ctx);
|
int32_t *version = config_parser__version(ctx);
|
||||||
|
@ -173,9 +244,10 @@ config_parser__config(Config_Parser *ctx){
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
for (;!config_parser__recognize_token(ctx, CPP_TOKEN_EOF);){
|
for (;!config_parser__recognize_token(ctx, CPP_TOKEN_EOF);){
|
||||||
Config_Assignment *assignment = config_parser__assignment(ctx);
|
Config_Assignment *assignment = config_parser__assignment(ctx);
|
||||||
require(assignment != 0);
|
if (assignment != 0){
|
||||||
zdll_push_back(first, last, assignment);
|
zdll_push_back(first, last, assignment);
|
||||||
count += 1;
|
count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Config *config = push_array(ctx->arena, Config, 1);
|
Config *config = push_array(ctx->arena, Config, 1);
|
||||||
|
@ -184,17 +256,57 @@ config_parser__config(Config_Parser *ctx){
|
||||||
config->first = first;
|
config->first = first;
|
||||||
config->last = last;
|
config->last = last;
|
||||||
config->count = count;
|
config->count = count;
|
||||||
|
config->first_error = ctx->first_error;
|
||||||
|
config->last_error = ctx->last_error;
|
||||||
|
config->count_error = ctx->count_error;
|
||||||
|
config->data = ctx->data;
|
||||||
return(config);
|
return(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
config_parser__recover_parse(Config_Parser *ctx){
|
||||||
|
for (;;){
|
||||||
|
if (config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (config_parser__recognize_token(ctx, CPP_TOKEN_EOF)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
config_parser__advance_to_next(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t*
|
static int32_t*
|
||||||
config_parser__version(Config_Parser *ctx){
|
config_parser__version(Config_Parser *ctx){
|
||||||
require(config_parser__match_text(ctx, make_lit_string("version")));
|
require(config_parser__match_text(ctx, make_lit_string("version")));
|
||||||
require(config_parser__match_token(ctx, CPP_TOKEN_PARENTHESE_OPEN));
|
|
||||||
require(config_parser__recognize_token(ctx, CPP_TOKEN_INTEGER_CONSTANT));
|
if (!config_parser__match_token(ctx, CPP_TOKEN_PARENTHESE_OPEN)){
|
||||||
|
config_parser__log_error(ctx, "expected token '(' for version specifier: 'version(#)'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_parser__recognize_token(ctx, CPP_TOKEN_INTEGER_CONSTANT)){
|
||||||
|
config_parser__log_error(ctx, "expected an integer constant for version specifier: 'version(#)'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
Config_Integer value = config_parser__get_int(ctx);
|
Config_Integer value = config_parser__get_int(ctx);
|
||||||
config_parser__advance_to_next(ctx);
|
config_parser__advance_to_next(ctx);
|
||||||
require(config_parser__match_token(ctx, CPP_TOKEN_PARENTHESE_CLOSE));
|
|
||||||
|
if (!config_parser__match_token(ctx, CPP_TOKEN_PARENTHESE_CLOSE)){
|
||||||
|
config_parser__log_error(ctx, "expected token ')' for version specifier: 'version(#)'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON)){
|
||||||
|
config_parser__log_error(ctx, "expected token ';' for version specifier: 'version(#)'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t *ptr = push_array(ctx->arena, int32_t, 1);
|
int32_t *ptr = push_array(ctx->arena, int32_t, 1);
|
||||||
*ptr = value.integer;
|
*ptr = value.integer;
|
||||||
return(ptr);
|
return(ptr);
|
||||||
|
@ -203,11 +315,35 @@ config_parser__version(Config_Parser *ctx){
|
||||||
static Config_Assignment*
|
static Config_Assignment*
|
||||||
config_parser__assignment(Config_Parser *ctx){
|
config_parser__assignment(Config_Parser *ctx){
|
||||||
Config_LValue *l = config_parser__lvalue(ctx);
|
Config_LValue *l = config_parser__lvalue(ctx);
|
||||||
require(l != 0);
|
if (l == 0){
|
||||||
require(config_parser__match_token(ctx, CPP_TOKEN_EQ));
|
config_parser__log_error(ctx, "expected an l-value; l-value formats: 'identifier', 'identifier[#]'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_parser__match_token(ctx, CPP_TOKEN_EQ)){
|
||||||
|
config_parser__log_error(ctx, "expected token '=' for assignment: 'l-value = r-value;'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
Config_RValue *r = config_parser__rvalue(ctx);
|
Config_RValue *r = config_parser__rvalue(ctx);
|
||||||
require(r != 0);
|
if (r == 0){
|
||||||
require(config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON));
|
config_parser__log_error(ctx, "expected an r-value; r-value formats:\n"
|
||||||
|
"\tconstants (true, false, integers, hexadecimal integers, strings, characters)\n"
|
||||||
|
"\tany l-value that is set in the file\n"
|
||||||
|
"\tcompound: '{ compound-element, compound-element, compound-element ...}'\n"
|
||||||
|
"\ta compound-element is an r-value, and can have a layout specifier\n"
|
||||||
|
"\tcompound-element with layout specifier: .name = r-value, .integer = r-value");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON)){
|
||||||
|
config_parser__log_error(ctx, "expected token ';' for assignment: 'l-value = r-value;'");
|
||||||
|
config_parser__recover_parse(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
Config_Assignment *assignment = push_array(ctx->arena, Config_Assignment, 1);
|
Config_Assignment *assignment = push_array(ctx->arena, Config_Assignment, 1);
|
||||||
memset(assignment, 0, sizeof(*assignment));
|
memset(assignment, 0, sizeof(*assignment));
|
||||||
|
@ -276,7 +412,7 @@ config_parser__rvalue(Config_Parser *ctx){
|
||||||
rvalue->type = ConfigRValueType_Integer;
|
rvalue->type = ConfigRValueType_Integer;
|
||||||
if (value.is_signed){
|
if (value.is_signed){
|
||||||
rvalue->integer = value.integer;
|
rvalue->integer = value.integer;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
rvalue->uinteger = value.uinteger;
|
rvalue->uinteger = value.uinteger;
|
||||||
}
|
}
|
||||||
|
@ -395,42 +531,42 @@ config_evaluate_rvalue(Config *config, Config_Assignment *assignment, Config_RVa
|
||||||
Config_RValue_Type type, void *out){
|
Config_RValue_Type type, void *out){
|
||||||
bool32 success = false;
|
bool32 success = false;
|
||||||
if (r != 0 && !assignment->visited){
|
if (r != 0 && !assignment->visited){
|
||||||
if (r->type == ConfigRValueType_LValue){
|
if (r->type == ConfigRValueType_LValue){
|
||||||
assignment->visited = true;
|
assignment->visited = true;
|
||||||
Config_LValue *l = r->lvalue;
|
Config_LValue *l = r->lvalue;
|
||||||
success = config_var(config, l->identifier, l->index, type, out);
|
success = config_var(config, l->identifier, l->index, type, out);
|
||||||
assignment->visited = false;
|
assignment->visited = false;
|
||||||
}
|
}
|
||||||
else if (r->type == type){
|
else if (r->type == type){
|
||||||
success = true;
|
success = true;
|
||||||
switch (type){
|
switch (type){
|
||||||
case ConfigRValueType_Boolean:
|
case ConfigRValueType_Boolean:
|
||||||
{
|
{
|
||||||
*(bool32*)out = r->boolean;
|
*(bool32*)out = r->boolean;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case ConfigRValueType_Integer:
|
case ConfigRValueType_Integer:
|
||||||
{
|
{
|
||||||
*(int32_t*)out = r->integer;
|
*(int32_t*)out = r->integer;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case ConfigRValueType_String:
|
case ConfigRValueType_String:
|
||||||
{
|
{
|
||||||
*(String*)out = r->string;
|
*(String*)out = r->string;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case ConfigRValueType_Character:
|
case ConfigRValueType_Character:
|
||||||
{
|
{
|
||||||
*(char*)out = r->character;
|
*(char*)out = r->character;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case ConfigRValueType_Compound:
|
case ConfigRValueType_Compound:
|
||||||
{
|
{
|
||||||
*(Config_Compound**)out = r->compound;
|
*(Config_Compound**)out = r->compound;
|
||||||
}break;
|
}break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return(success);
|
return(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,6 +620,27 @@ config_string_var(Config *config, char *var_name, int32_t subscript, String *var
|
||||||
return(config_var(config, make_string_slowly(var_name), subscript, ConfigRValueType_String, var_out));
|
return(config_var(config, make_string_slowly(var_name), subscript, ConfigRValueType_String, var_out));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool32
|
||||||
|
config_placed_string_var(Config *config, String var_name, int32_t subscript,
|
||||||
|
String *var_out, char *space, int32_t space_size){
|
||||||
|
*var_out = make_string_cap(space, 0, space_size);
|
||||||
|
String str = {0};
|
||||||
|
bool32 result = config_string_var(config, var_name, subscript, &str);
|
||||||
|
if (result){
|
||||||
|
copy(var_out, str);
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool32
|
||||||
|
config_placed_string_var(Config *config, char *var_name, int32_t subscript,
|
||||||
|
String *var_out, char *space, int32_t space_size){
|
||||||
|
return(config_placed_string_var(config, make_string_slowly(var_name), subscript,
|
||||||
|
var_out, space, space_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define config_fixed_string_var(c,v,s,o,a) config_placed_string_var((c),(v),(s),(o),(a),sizeof(a))
|
||||||
|
|
||||||
static bool32
|
static bool32
|
||||||
config_char_var(Config *config, String var_name, int32_t subscript, char *var_out){
|
config_char_var(Config *config, String var_name, int32_t subscript, char *var_out){
|
||||||
return(config_var(config, var_name, subscript, ConfigRValueType_Character, var_out));
|
return(config_var(config, var_name, subscript, ConfigRValueType_Character, var_out));
|
||||||
|
@ -525,10 +682,10 @@ config_compound_member(Config *config, Config_Compound *compound, String var_nam
|
||||||
case ConfigLayoutType_Identifier:
|
case ConfigLayoutType_Identifier:
|
||||||
{
|
{
|
||||||
implicit_index_is_valid = false;
|
implicit_index_is_valid = false;
|
||||||
if (match(element->l.identifier, var_name)){
|
if (match(element->l.identifier, var_name)){
|
||||||
element_matches_query = true;
|
element_matches_query = true;
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case ConfigLayoutType_Integer:
|
case ConfigLayoutType_Integer:
|
||||||
{
|
{
|
||||||
|
@ -620,307 +777,6 @@ config_compound_compound_member(Config *config, Config_Compound *compound,
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
static Cpp_Token
|
|
||||||
read_config_token(Cpp_Token_Array array, int32_t *i_ptr){
|
|
||||||
Cpp_Token token = {0};
|
|
||||||
int32_t i = *i_ptr;
|
|
||||||
for (; i < array.count; ++i){
|
|
||||||
Cpp_Token comment_token = array.tokens[i];
|
|
||||||
if (comment_token.type != CPP_TOKEN_COMMENT){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i < array.count){
|
|
||||||
token = array.tokens[i];
|
|
||||||
}
|
|
||||||
*i_ptr = i;
|
|
||||||
return(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Config_Line
|
|
||||||
read_config_line(Cpp_Token_Array array, int32_t *i_ptr, char *text){
|
|
||||||
Config_Line config_line = {0};
|
|
||||||
|
|
||||||
int32_t i = *i_ptr;
|
|
||||||
config_line.id_token = read_config_token(array, &i);
|
|
||||||
int32_t text_index_start = config_line.id_token.start;
|
|
||||||
if (config_line.id_token.type == CPP_TOKEN_IDENTIFIER){
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
Cpp_Token token = read_config_token(array, &i);
|
|
||||||
|
|
||||||
bool32 lvalue_success = true;
|
|
||||||
if (token.type == CPP_TOKEN_BRACKET_OPEN){
|
|
||||||
lvalue_success = false;
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
config_line.subscript_token = read_config_token(array, &i);
|
|
||||||
if (config_line.subscript_token.type == CPP_TOKEN_INTEGER_CONSTANT){
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
token = read_config_token(array, &i);
|
|
||||||
if (token.type == CPP_TOKEN_BRACKET_CLOSE){
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
token = read_config_token(array, &i);
|
|
||||||
lvalue_success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lvalue_success){
|
|
||||||
if (token.type == CPP_TOKEN_EQ){
|
|
||||||
config_line.eq_token = read_config_token(array, &i);
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
Cpp_Token val_token = read_config_token(array, &i);
|
|
||||||
|
|
||||||
bool32 rvalue_success = true;
|
|
||||||
if (val_token.type == CPP_TOKEN_BRACE_OPEN){
|
|
||||||
rvalue_success = false;
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
config_line.val_array_start = i;
|
|
||||||
|
|
||||||
bool32 expecting_array_item = 1;
|
|
||||||
for (; i < array.count; ++i){
|
|
||||||
Cpp_Token array_token = read_config_token(array, &i);
|
|
||||||
if (array_token.size == 0){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (array_token.type == CPP_TOKEN_BRACE_CLOSE){
|
|
||||||
config_line.val_array_end = i;
|
|
||||||
rvalue_success = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (array_token.type == CPP_TOKEN_COMMA){
|
|
||||||
if (!expecting_array_item){
|
|
||||||
expecting_array_item = true;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (expecting_array_item){
|
|
||||||
expecting_array_item = false;
|
|
||||||
++config_line.val_array_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rvalue_success){
|
|
||||||
config_line.val_token = val_token;
|
|
||||||
++i;
|
|
||||||
if (i < array.count){
|
|
||||||
Cpp_Token semicolon_token = read_config_token(array, &i);
|
|
||||||
if (semicolon_token.type == CPP_TOKEN_SEMICOLON){
|
|
||||||
config_line.read_success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config_line.read_success){
|
|
||||||
Cpp_Token token = {0};
|
|
||||||
if (i < array.count){
|
|
||||||
token = array.tokens[i];
|
|
||||||
}
|
|
||||||
int32_t text_index_current = token.start + token.size;
|
|
||||||
if (text_index_current <= text_index_start){
|
|
||||||
if (array.count > 0){
|
|
||||||
token = array.tokens[array.count - 1];
|
|
||||||
text_index_current = token.start + token.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text_index_current > text_index_start){
|
|
||||||
config_line.error_str = make_string(text + text_index_start, text_index_current - text_index_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < array.count; ++i){
|
|
||||||
Cpp_Token skip_token = read_config_token(array, &i);
|
|
||||||
if (skip_token.type == CPP_TOKEN_SEMICOLON){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*i_ptr = i;
|
|
||||||
|
|
||||||
return(config_line);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Config_Item
|
|
||||||
get_config_item(Config_Line line, char *mem, Cpp_Token_Array array){
|
|
||||||
Config_Item item = {0};
|
|
||||||
item.line = line;
|
|
||||||
item.array = array;
|
|
||||||
item.mem = mem;
|
|
||||||
if (line.id_token.size != 0){
|
|
||||||
item.id = make_string(mem + line.id_token.start, line.id_token.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.subscript_token.size != 0){
|
|
||||||
String subscript_str = make_string(mem + line.subscript_token.start,line.subscript_token.size);
|
|
||||||
item.subscript_index = str_to_int_s(subscript_str);
|
|
||||||
item.has_subscript = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_var(Config_Item item, char *var_name, int32_t *subscript, uint32_t token_type, void *var_out){
|
|
||||||
bool32 result = false;
|
|
||||||
bool32 subscript_success = true;
|
|
||||||
if (item.line.val_token.type == token_type){
|
|
||||||
if ((var_name == 0 && item.id.size == 0) || match(item.id, var_name)){
|
|
||||||
if (subscript){
|
|
||||||
if (item.has_subscript){
|
|
||||||
*subscript = item.subscript_index;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
subscript_success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subscript_success){
|
|
||||||
if (var_out){
|
|
||||||
switch (token_type){
|
|
||||||
case CPP_TOKEN_BOOLEAN_CONSTANT:
|
|
||||||
{
|
|
||||||
*(bool32*)var_out = (item.mem[item.line.val_token.start] == 't');
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case CPP_TOKEN_INTEGER_CONSTANT:
|
|
||||||
{
|
|
||||||
if (match(make_string(item.mem + item.line.val_token.start, 2), "0x")){
|
|
||||||
// Hex Integer
|
|
||||||
String val = make_string(item.mem + item.line.val_token.start + 2, item.line.val_token.size - 2);
|
|
||||||
*(uint32_t*)var_out = hexstr_to_int(val);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// Integer
|
|
||||||
String val = make_string(item.mem + item.line.val_token.start, item.line.val_token.size);
|
|
||||||
*(int32_t*)var_out = str_to_int(val);
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case CPP_TOKEN_STRING_CONSTANT:
|
|
||||||
{
|
|
||||||
String str = make_string(item.mem + item.line.val_token.start + 1,item.line.val_token.size - 2);
|
|
||||||
copy((String*)var_out, str);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case CPP_TOKEN_IDENTIFIER:
|
|
||||||
{
|
|
||||||
String str = make_string(item.mem + item.line.val_token.start,item.line.val_token.size);
|
|
||||||
copy((String*)var_out, str);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case CPP_TOKEN_BRACE_OPEN:
|
|
||||||
{
|
|
||||||
Config_Array_Reader *array_reader = (Config_Array_Reader*)var_out;
|
|
||||||
array_reader->array = item.array;
|
|
||||||
array_reader->mem = item.mem;
|
|
||||||
array_reader->i = item.line.val_array_start;
|
|
||||||
array_reader->val_array_end = item.line.val_array_end;
|
|
||||||
array_reader->good = 1;
|
|
||||||
}break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_bool_var(Config_Item item, char *var_name, int32_t *subscript, bool32 *var_out){
|
|
||||||
return(config_var(item, var_name, subscript, CPP_TOKEN_BOOLEAN_CONSTANT, var_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_int_var(Config_Item item, char *var_name, int32_t *subscript, int32_t *var_out){
|
|
||||||
return(config_var(item, var_name, subscript, CPP_TOKEN_INTEGER_CONSTANT, var_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_uint_var(Config_Item item, char *var_name, int32_t *subscript, uint32_t *var_out){
|
|
||||||
return(config_var(item, var_name, subscript, CPP_TOKEN_INTEGER_CONSTANT, var_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_string_var(Config_Item item, char *var_name, int32_t *subscript, String *var_out){
|
|
||||||
return(config_var(item, var_name, subscript, CPP_TOKEN_STRING_CONSTANT, var_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_identifier_var(Config_Item item, char *var_name, int32_t *subscript, String *var_out){
|
|
||||||
return(config_var(item, var_name, subscript, CPP_TOKEN_IDENTIFIER, var_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_array_var(Config_Item item, char *var_name, int32_t *subscript, Config_Array_Reader *array_reader){
|
|
||||||
return(config_var(item, var_name, subscript, CPP_TOKEN_BRACE_OPEN, array_reader));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_array_next_item(Config_Array_Reader *array_reader, Config_Item *item){
|
|
||||||
bool32 result = false;
|
|
||||||
|
|
||||||
for (;array_reader->i < array_reader->val_array_end;
|
|
||||||
++array_reader->i){
|
|
||||||
Cpp_Token array_token = read_config_token(array_reader->array, &array_reader->i);
|
|
||||||
if (array_token.size == 0 || array_reader->i >= array_reader->val_array_end){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_token.type == CPP_TOKEN_BRACE_CLOSE){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (array_token.type){
|
|
||||||
case CPP_TOKEN_BOOLEAN_CONSTANT:
|
|
||||||
case CPP_TOKEN_INTEGER_CONSTANT:
|
|
||||||
case CPP_TOKEN_STRING_CONSTANT:
|
|
||||||
{
|
|
||||||
Config_Line line = {0};
|
|
||||||
line.val_token = array_token;
|
|
||||||
line.read_success = 1;
|
|
||||||
*item = get_config_item(line, array_reader->mem, array_reader->array);
|
|
||||||
result = true;
|
|
||||||
++array_reader->i;
|
|
||||||
goto doublebreak;
|
|
||||||
}break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doublebreak:;
|
|
||||||
|
|
||||||
array_reader->good = result;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
config_array_good(Config_Array_Reader *array_reader){
|
|
||||||
return(array_reader->good);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
change_mapping(Application_Links *app, String mapping){
|
change_mapping(Application_Links *app, String mapping){
|
||||||
bool32 did_remap = false;
|
bool32 did_remap = false;
|
||||||
|
@ -956,7 +812,7 @@ text_data_to_token_array(Partition *arena, String data){
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!success){
|
if (!success){
|
||||||
memset(&array, 0, sizeof(array));
|
memset(&array, 0, sizeof(array));
|
||||||
end_temp_memory(restore_point);
|
end_temp_memory(restore_point);
|
||||||
|
@ -971,11 +827,11 @@ text_data_to_parsed_data(Partition *arena, String file_name, String data){
|
||||||
Cpp_Token_Array array = text_data_to_token_array(arena, data);
|
Cpp_Token_Array array = text_data_to_token_array(arena, data);
|
||||||
if (array.tokens != 0){
|
if (array.tokens != 0){
|
||||||
parsed = text_data_and_token_array_to_parse_data(arena, file_name, data, array);
|
parsed = text_data_and_token_array_to_parse_data(arena, file_name, data, array);
|
||||||
if (parsed == 0){
|
if (parsed == 0){
|
||||||
end_temp_memory(restore_point);
|
end_temp_memory(restore_point);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return(parsed);
|
||||||
return(parsed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
@ -1019,85 +875,91 @@ config_init_default(Config_Data *config){
|
||||||
memset(&config->code_exts, 0, sizeof(config->code_exts));
|
memset(&config->code_exts, 0, sizeof(config->code_exts));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static Config*
|
||||||
config_parse__data(Partition *scratch, String file_name, String data, Config_Data *config){
|
config_parse__data(Partition *arena, String file_name, String data, Config_Data *config){
|
||||||
config_init_default(config);
|
config_init_default(config);
|
||||||
|
|
||||||
bool32 success = false;
|
bool32 success = false;
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
|
||||||
|
|
||||||
Config *parsed = text_data_to_parsed_data(scratch, file_name, data);
|
Config *parsed = text_data_to_parsed_data(arena, file_name, data);
|
||||||
if (parsed != 0){
|
if (parsed != 0){
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
config_bool_var(parsed, "enable_code_wrapping", 0, &config->enable_code_wrapping);
|
config_bool_var(parsed, "enable_code_wrapping", 0, &config->enable_code_wrapping);
|
||||||
config_bool_var(parsed, "automatically_adjust_wrapping", 0, &config->automatically_adjust_wrapping);
|
config_bool_var(parsed, "automatically_adjust_wrapping", 0, &config->automatically_adjust_wrapping);
|
||||||
config_bool_var(parsed, "automatically_indent_text_on_save", 0, &config->automatically_indent_text_on_save);
|
config_bool_var(parsed, "automatically_indent_text_on_save", 0, &config->automatically_indent_text_on_save);
|
||||||
config_bool_var(parsed, "automatically_save_changes_on_build", 0, &config->automatically_save_changes_on_build);
|
config_bool_var(parsed, "automatically_save_changes_on_build", 0, &config->automatically_save_changes_on_build);
|
||||||
|
|
||||||
config_int_var(parsed, "default_wrap_width", 0, &config->default_wrap_width);
|
config_int_var(parsed, "default_wrap_width", 0, &config->default_wrap_width);
|
||||||
config_int_var(parsed, "default_min_base_width", 0, &config->default_min_base_width);
|
config_int_var(parsed, "default_min_base_width", 0, &config->default_min_base_width);
|
||||||
|
|
||||||
config_string_var(parsed, "default_theme_name", 0, &config->default_theme_name);
|
config_fixed_string_var(parsed, "default_theme_name", 0,
|
||||||
config_string_var(parsed, "default_font_name", 0, &config->default_font_name);
|
&config->default_theme_name, config->default_theme_name_space);
|
||||||
config_string_var(parsed, "user_name", 0, &config->user_name);
|
config_fixed_string_var(parsed, "default_font_name", 0,
|
||||||
|
&config->default_font_name, config->default_font_name_space);
|
||||||
config_string_var(parsed, "default_compiler_bat", 0, &config->default_compiler_bat);
|
config_fixed_string_var(parsed, "user_name", 0,
|
||||||
config_string_var(parsed, "default_flags_bat", 0, &config->default_flags_bat);
|
&config->user_name, config->user_name_space);
|
||||||
config_string_var(parsed, "default_compiler_sh", 0, &config->default_compiler_sh);
|
|
||||||
config_string_var(parsed, "default_flags_sh", 0, &config->default_flags_sh);
|
config_fixed_string_var(parsed, "default_compiler_bat", 0,
|
||||||
|
&config->default_compiler_bat, config->default_compiler_bat_space);
|
||||||
config_string_var(parsed, "mapping", 0, &config->current_mapping);
|
config_fixed_string_var(parsed, "default_flags_bat", 0,
|
||||||
|
&config->default_flags_bat, config->default_flags_bat_space);
|
||||||
char space[512];
|
config_fixed_string_var(parsed, "default_compiler_sh", 0,
|
||||||
String str = make_fixed_width_string(space);
|
&config->default_compiler_sh, config->default_compiler_sh_space);
|
||||||
if (config_string_var(parsed, "treat_as_code", 0, &str)){
|
config_fixed_string_var(parsed, "default_flags_sh", 0,
|
||||||
parse_extension_line_to_extension_list(str, &config->code_exts);
|
&config->default_flags_sh, config->default_flags_sh_space);
|
||||||
}
|
|
||||||
|
config_fixed_string_var(parsed, "mapping", 0,
|
||||||
config_bool_var(parsed, "automatically_load_project", 0, &config->automatically_load_project);
|
&config->current_mapping, config->current_mapping_space);
|
||||||
config_bool_var(parsed, "lalt_lctrl_is_altgr", 0, &config->lalt_lctrl_is_altgr);
|
|
||||||
}
|
String str;
|
||||||
|
if (config_string_var(parsed, "treat_as_code", 0, &str)){
|
||||||
end_temp_memory(temp);
|
parse_extension_line_to_extension_list(str, &config->code_exts);
|
||||||
|
}
|
||||||
|
|
||||||
|
config_bool_var(parsed, "automatically_load_project", 0, &config->automatically_load_project);
|
||||||
|
config_bool_var(parsed, "lalt_lctrl_is_altgr", 0, &config->lalt_lctrl_is_altgr);
|
||||||
|
}
|
||||||
|
|
||||||
if (!success){
|
if (!success){
|
||||||
config_init_default(config);
|
config_init_default(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static Config*
|
||||||
config_parse__file_handle(Partition *scratch,
|
config_parse__file_handle(Partition *arena,
|
||||||
String file_name, FILE *file, Config_Data *config){
|
String file_name, FILE *file, Config_Data *config){
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
Config *parsed = 0;
|
||||||
String data = dump_file_handle(scratch, file);
|
String data = dump_file_handle(arena, file);
|
||||||
if (data.str != 0){
|
if (data.str != 0){
|
||||||
config_parse__data(scratch, file_name, data, config);
|
parsed = config_parse__data(arena, file_name, data, config);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
config_init_default(config);
|
config_init_default(config);
|
||||||
}
|
}
|
||||||
end_temp_memory(temp);
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static Config*
|
||||||
config_parse__file_name(Application_Links *app, Partition *scratch,
|
config_parse__file_name(Application_Links *app, Partition *arena,
|
||||||
char *file_name, Config_Data *config){
|
char *file_name, Config_Data *config){
|
||||||
|
Config *parsed = 0;
|
||||||
bool32 success = false;
|
bool32 success = false;
|
||||||
FILE *file = open_file_try_current_path_then_binary_path(app, file_name);
|
FILE *file = open_file_try_current_path_then_binary_path(app, file_name);
|
||||||
if (file != 0){
|
if (file != 0){
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
String data = dump_file_handle(arena, file);
|
||||||
String data = dump_file_handle(scratch, file);
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
if (data.str != 0){
|
if (data.str != 0){
|
||||||
config_parse__data(scratch, make_string_slowly(file_name), data, config);
|
parsed = config_parse__data(arena, make_string_slowly(file_name), data, config);
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
end_temp_memory(temp);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!success){
|
if (!success){
|
||||||
config_init_default(config);
|
config_init_default(config);
|
||||||
}
|
}
|
||||||
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1107,64 +969,50 @@ init_theme_zero(Theme *theme){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool32
|
static Config*
|
||||||
theme_parse__data(Partition *scratch, String file_name, String data, Theme_Data *theme){
|
theme_parse__data(Partition *arena, String file_name, String data, Theme_Data *theme){
|
||||||
theme->name = make_fixed_width_string(theme->space);
|
theme->name = make_fixed_width_string(theme->space);
|
||||||
copy(&theme->name, "unnamed");
|
copy(&theme->name, "unnamed");
|
||||||
init_theme_zero(&theme->theme);
|
init_theme_zero(&theme->theme);
|
||||||
|
|
||||||
bool32 success = false;
|
Config *parsed = text_data_to_parsed_data(arena, file_name, data);
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
if (parsed != 0){
|
||||||
|
config_fixed_string_var(parsed, "name", 0, &theme->name, theme->space);
|
||||||
Config *parsed = text_data_to_parsed_data(scratch, file_name, data);
|
|
||||||
if (parsed != 0){
|
for (int32_t i = 0; i < Stag_COUNT; ++i){
|
||||||
success = true;
|
char *name = style_tag_names[i];
|
||||||
|
uint32_t color = 0;
|
||||||
String theme_name = {0};
|
if (!config_uint_var(parsed, name, 0, &color)){
|
||||||
if (config_string_var(parsed, "name", 0, &theme_name)){
|
color = 0xFFFF00FF;
|
||||||
copy(&theme->name, theme_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < Stag_COUNT; ++i){
|
|
||||||
char *name = style_tag_names[i];
|
|
||||||
uint32_t color = 0;
|
|
||||||
if (!config_uint_var(parsed, name, 0, &color)){
|
|
||||||
color = 0xFFFF00FF;
|
|
||||||
}
|
|
||||||
theme->theme.colors[i] = color;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
theme->theme.colors[i] = color;
|
||||||
end_temp_memory(temp);
|
}
|
||||||
|
|
||||||
return(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool32
|
|
||||||
theme_parse__file_handle(Partition *scratch, String file_name, FILE *file, Theme_Data *theme){
|
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
|
||||||
String data = dump_file_handle(scratch, file);
|
|
||||||
bool32 success = false;
|
|
||||||
if (data.str != 0){
|
|
||||||
success = theme_parse__data(scratch, file_name, data, theme);
|
|
||||||
}
|
}
|
||||||
end_temp_memory(temp);
|
|
||||||
return(success);
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool32
|
static Config*
|
||||||
theme_parse__file_name(Application_Links *app, Partition *scratch,
|
theme_parse__file_handle(Partition *arena, String file_name, FILE *file, Theme_Data *theme){
|
||||||
|
String data = dump_file_handle(arena, file);
|
||||||
|
Config *parsed = 0;
|
||||||
|
if (data.str != 0){
|
||||||
|
parsed = theme_parse__data(arena, file_name, data, theme);
|
||||||
|
}
|
||||||
|
return(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Config*
|
||||||
|
theme_parse__file_name(Application_Links *app, Partition *arena,
|
||||||
char *file_name, Theme_Data *theme){
|
char *file_name, Theme_Data *theme){
|
||||||
bool32 success = false;
|
Config *parsed = 0;
|
||||||
FILE *file = open_file_try_current_path_then_binary_path(app, file_name);
|
FILE *file = open_file_try_current_path_then_binary_path(app, file_name);
|
||||||
if (file != 0){
|
if (file != 0){
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
String data = dump_file_handle(arena, file);
|
||||||
String data = dump_file_handle(scratch, file);
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
success = theme_parse__data(scratch, make_string_slowly(file_name), data, theme);
|
parsed = theme_parse__data(arena, make_string_slowly(file_name), data, theme);
|
||||||
end_temp_memory(temp);
|
|
||||||
}
|
}
|
||||||
if (!success){
|
if (parsed == 0){
|
||||||
char space[256];
|
char space[256];
|
||||||
String str = make_fixed_width_string(space);
|
String str = make_fixed_width_string(space);
|
||||||
append(&str, "Did not find ");
|
append(&str, "Did not find ");
|
||||||
|
@ -1172,14 +1020,19 @@ theme_parse__file_name(Application_Links *app, Partition *scratch,
|
||||||
append(&str, ", color scheme not loaded");
|
append(&str, ", color scheme not loaded");
|
||||||
print_message(app, str.str, str.size);
|
print_message(app, str.str, str.size);
|
||||||
}
|
}
|
||||||
return(success);
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_config_and_apply(Application_Links *app, Partition *scratch, Config_Data *config){
|
load_config_and_apply(Application_Links *app, Partition *scratch, Config_Data *config){
|
||||||
config_parse__file_name(app, scratch, "config.4coder", config);
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
|
Config *parsed = config_parse__file_name(app, scratch, "config.4coder", config);
|
||||||
|
String error_text = config_stringize_errors(scratch, parsed);
|
||||||
|
print_message(app, error_text.str, error_text.size);
|
||||||
|
end_temp_memory(temp);
|
||||||
|
|
||||||
change_mapping(app, config->current_mapping);
|
change_mapping(app, config->current_mapping);
|
||||||
adjust_all_buffer_wrap_widths(app, config->default_wrap_width, config->default_min_base_width);
|
adjust_all_buffer_wrap_widths(app, config->default_wrap_width, config->default_min_base_width);
|
||||||
global_set_setting(app, GlobalSetting_LAltLCtrlIsAltGr, config->lalt_lctrl_is_altgr);
|
global_set_setting(app, GlobalSetting_LAltLCtrlIsAltGr, config->lalt_lctrl_is_altgr);
|
||||||
|
@ -1187,8 +1040,12 @@ load_config_and_apply(Application_Links *app, Partition *scratch, Config_Data *c
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_theme_file_into_live_set(Application_Links *app, Partition *scratch, char *file_name){
|
load_theme_file_into_live_set(Application_Links *app, Partition *scratch, char *file_name){
|
||||||
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
Theme_Data theme = {0};
|
Theme_Data theme = {0};
|
||||||
theme_parse__file_name(app, scratch, file_name, &theme);
|
Config *config = theme_parse__file_name(app, scratch, file_name, &theme);
|
||||||
|
String error_text = config_stringize_errors(scratch, config);
|
||||||
|
print_message(app, error_text.str, error_text.size);
|
||||||
|
end_temp_memory(temp);
|
||||||
create_theme(app, &theme.theme, theme.name.str, theme.name.size);
|
create_theme(app, &theme.theme, theme.name.str, theme.name.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,23 @@
|
||||||
#if !defined(FCODER_CONFIG_H)
|
#if !defined(FCODER_CONFIG_H)
|
||||||
#define FCODER_CONFIG_H
|
#define FCODER_CONFIG_H
|
||||||
|
|
||||||
|
// TODO(allen): Stop handling files this way! My own API should be able to do this!!?!?!?!!?!?!!!!?
|
||||||
|
// NOTE(allen): Actually need binary buffers for some stuff to work, but not this parsing thing here.
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct Error_Location{
|
||||||
|
int32_t line_number;
|
||||||
|
int32_t column_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Config_Error{
|
||||||
|
Config_Error *next;
|
||||||
|
Config_Error *prev;
|
||||||
|
String file_name;
|
||||||
|
char *pos;
|
||||||
|
String text;
|
||||||
|
};
|
||||||
|
|
||||||
struct Config_Parser{
|
struct Config_Parser{
|
||||||
Cpp_Token *start;
|
Cpp_Token *start;
|
||||||
Cpp_Token *token;
|
Cpp_Token *token;
|
||||||
|
@ -16,6 +33,10 @@ Cpp_Token *end;
|
||||||
String data;
|
String data;
|
||||||
|
|
||||||
Partition *arena;
|
Partition *arena;
|
||||||
|
|
||||||
|
Config_Error *first_error;
|
||||||
|
Config_Error *last_error;
|
||||||
|
int32_t count_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config_LValue{
|
struct Config_LValue{
|
||||||
|
@ -100,6 +121,12 @@ struct Config{
|
||||||
Config_Assignment *first;
|
Config_Assignment *first;
|
||||||
Config_Assignment *last;
|
Config_Assignment *last;
|
||||||
int32_t count;
|
int32_t count;
|
||||||
|
|
||||||
|
Config_Error *first_error;
|
||||||
|
Config_Error *last_error;
|
||||||
|
int32_t count_error;
|
||||||
|
|
||||||
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
config := [version] {assignment}
|
config := [version] {assignment}
|
||||||
|
|
||||||
version := "version" "(" INTEGER ")"
|
version := "version" "(" INTEGER ")" ";"
|
||||||
assignment := lvalue "=" rvalue ";"
|
assignment := lvalue "=" rvalue ";"
|
||||||
lvalue := IDENTIFIER [ "[" INTEGER "]" ]
|
lvalue := IDENTIFIER [ "[" INTEGER "]" ]
|
||||||
rvalue := lvalue | BOOLEAN | INTEGER | STRING | CHARACTER | "{" compound_body
|
rvalue := lvalue | BOOLEAN | INTEGER | STRING | CHARACTER | "{" compound_body
|
||||||
|
|
|
@ -36,37 +36,6 @@ struct ID_Based_Jump_Location{
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
struct Config_Line{
|
|
||||||
Cpp_Token id_token;
|
|
||||||
Cpp_Token subscript_token;
|
|
||||||
Cpp_Token eq_token;
|
|
||||||
Cpp_Token val_token;
|
|
||||||
int32_t val_array_start;
|
|
||||||
int32_t val_array_end;
|
|
||||||
int32_t val_array_count;
|
|
||||||
String error_str;
|
|
||||||
bool32 read_success;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Config_Item{
|
|
||||||
Config_Line line;
|
|
||||||
Cpp_Token_Array array;
|
|
||||||
char *mem;
|
|
||||||
String id;
|
|
||||||
int32_t subscript_index;
|
|
||||||
bool32 has_subscript;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Config_Array_Reader{
|
|
||||||
Cpp_Token_Array array;
|
|
||||||
char *mem;
|
|
||||||
int32_t i;
|
|
||||||
int32_t val_array_end;
|
|
||||||
bool32 good;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
struct Named_Mapping{
|
struct Named_Mapping{
|
||||||
String name;
|
String name;
|
||||||
Custom_Command_Function *remap_command;
|
Custom_Command_Function *remap_command;
|
||||||
|
|
|
@ -229,7 +229,7 @@ static Command_Metadata fcoder_metacmd_table[193] = {
|
||||||
{ PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 368 },
|
{ PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 368 },
|
||||||
{ PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 174 },
|
{ PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 174 },
|
||||||
{ PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 187 },
|
{ PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 187 },
|
||||||
{ PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 373 },
|
{ PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 380 },
|
||||||
{ PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "C:\\work\\4ed\\code\\4coder_build_commands.cpp", 46, 205 },
|
{ PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "C:\\work\\4ed\\code\\4coder_build_commands.cpp", 46, 205 },
|
||||||
{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 441 },
|
{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 441 },
|
||||||
{ PROC_LINKS(copy, 0), "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 26 },
|
{ PROC_LINKS(copy, 0), "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 26 },
|
||||||
|
@ -295,7 +295,7 @@ static Command_Metadata fcoder_metacmd_table[193] = {
|
||||||
{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 800 },
|
{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 800 },
|
||||||
{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 747 },
|
{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 747 },
|
||||||
{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 759 },
|
{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 759 },
|
||||||
{ PROC_LINKS(load_project, 0), "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 396 },
|
{ PROC_LINKS(load_project, 0), "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 403 },
|
||||||
{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1101 },
|
{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1101 },
|
||||||
{ PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 110 },
|
{ PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 110 },
|
||||||
{ PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 383 },
|
{ PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 383 },
|
||||||
|
@ -317,8 +317,8 @@ static Command_Metadata fcoder_metacmd_table[193] = {
|
||||||
{ PROC_LINKS(newline_or_goto_position_same_panel_direct, 0), "newline_or_goto_position_same_panel_direct", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_direct.cpp", 43, 116 },
|
{ PROC_LINKS(newline_or_goto_position_same_panel_direct, 0), "newline_or_goto_position_same_panel_direct", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_direct.cpp", 43, 116 },
|
||||||
{ PROC_LINKS(newline_or_goto_position_same_panel_sticky, 0), "newline_or_goto_position_same_panel_sticky", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 571 },
|
{ PROC_LINKS(newline_or_goto_position_same_panel_sticky, 0), "newline_or_goto_position_same_panel_sticky", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 571 },
|
||||||
{ PROC_LINKS(newline_or_goto_position_sticky, 0), "newline_or_goto_position_sticky", 31, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 556 },
|
{ PROC_LINKS(newline_or_goto_position_sticky, 0), "newline_or_goto_position_sticky", 31, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 556 },
|
||||||
{ PROC_LINKS(open_all_code, 0), "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 380 },
|
{ PROC_LINKS(open_all_code, 0), "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 387 },
|
||||||
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 387 },
|
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 394 },
|
||||||
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1457 },
|
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1457 },
|
||||||
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1320 },
|
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1320 },
|
||||||
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Switches to the next active panel and begins an open file dialogue.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1465 },
|
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Switches to the next active panel and begins an open file dialogue.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1465 },
|
||||||
|
@ -335,8 +335,8 @@ static Command_Metadata fcoder_metacmd_table[193] = {
|
||||||
{ PROC_LINKS(paste_next, 0), "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 84 },
|
{ PROC_LINKS(paste_next, 0), "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 84 },
|
||||||
{ PROC_LINKS(paste_next_and_indent, 0), "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 135 },
|
{ PROC_LINKS(paste_next_and_indent, 0), "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 135 },
|
||||||
{ PROC_LINKS(place_in_scope, 0), "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 481 },
|
{ PROC_LINKS(place_in_scope, 0), "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 481 },
|
||||||
{ PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 403 },
|
{ PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 410 },
|
||||||
{ PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 428 },
|
{ PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 435 },
|
||||||
{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 893 },
|
{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 893 },
|
||||||
{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 913 },
|
{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 913 },
|
||||||
{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 931 },
|
{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 931 },
|
||||||
|
@ -378,7 +378,7 @@ static Command_Metadata fcoder_metacmd_table[193] = {
|
||||||
{ PROC_LINKS(set_bindings_default, 0), "set_bindings_default", 20, "Remap keybindings using the 'default' mapping rule.", 51, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 61 },
|
{ PROC_LINKS(set_bindings_default, 0), "set_bindings_default", 20, "Remap keybindings using the 'default' mapping rule.", 51, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 61 },
|
||||||
{ PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24, "Remap keybindings using the 'mac-default' mapping rule.", 55, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 75 },
|
{ PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24, "Remap keybindings using the 'mac-default' mapping rule.", 55, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 75 },
|
||||||
{ PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 86 },
|
{ PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 86 },
|
||||||
{ PROC_LINKS(setup_new_project, 0), "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 475 },
|
{ PROC_LINKS(setup_new_project, 0), "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 482 },
|
||||||
{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 464 },
|
{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 464 },
|
||||||
{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 450 },
|
{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 450 },
|
||||||
{ PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1259 },
|
{ PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1259 },
|
||||||
|
|
|
@ -144,17 +144,17 @@ open_all_files_in_hot_with_extension(Application_Links *app, Partition *scratch,
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
static bool32
|
static Config*
|
||||||
parse_project__data(Partition *scratch, String file_name, String data, String file_dir,
|
parse_project__data(Partition *scratch, String file_name, String data, String file_dir,
|
||||||
Project *project){
|
Project *project){
|
||||||
bool32 success = false;
|
Config *parsed = 0;
|
||||||
|
|
||||||
Cpp_Token_Array array = text_data_to_token_array(scratch, data);
|
Cpp_Token_Array array = text_data_to_token_array(scratch, data);
|
||||||
if (array.tokens != 0){
|
if (array.tokens != 0){
|
||||||
Config *parsed = text_data_and_token_array_to_parse_data(scratch, file_name, data, array);
|
parsed = text_data_and_token_array_to_parse_data(scratch, file_name, data, array);
|
||||||
if (parsed != 0){
|
if (parsed != 0){
|
||||||
success = true;
|
|
||||||
memset(project, 0, sizeof(*project));
|
memset(project, 0, sizeof(*project));
|
||||||
|
project->loaded = true;
|
||||||
|
|
||||||
// Set new project directory
|
// Set new project directory
|
||||||
{
|
{
|
||||||
|
@ -223,32 +223,32 @@ parse_project__data(Partition *scratch, String file_name, String data, String fi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(success);
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool32
|
static Config*
|
||||||
parse_project__nearest_file(Application_Links *app, Partition *arena, Project *project){
|
parse_project__nearest_file(Application_Links *app, Partition *scratch, Project *project){
|
||||||
bool32 success = false;
|
Config *parsed = 0;
|
||||||
|
|
||||||
String project_path = {0};
|
String project_path = {0};
|
||||||
Temp_Memory temp = begin_temp_memory(arena);
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
int32_t size = 32 << 10;
|
int32_t size = 32 << 10;
|
||||||
char *space = push_array(arena, char, size);
|
char *space = push_array(scratch, char, size);
|
||||||
if (space != 0){
|
if (space != 0){
|
||||||
project_path = make_string_cap(space, 0, size);
|
project_path = make_string_cap(space, 0, size);
|
||||||
project_path.size = directory_get_hot(app, project_path.str, project_path.memory_size);
|
project_path.size = directory_get_hot(app, project_path.str, project_path.memory_size);
|
||||||
end_temp_memory(temp);
|
end_temp_memory(temp);
|
||||||
push_array(arena, char, project_path.size);
|
push_array(scratch, char, project_path.size);
|
||||||
project_path.memory_size = project_path.size;
|
project_path.memory_size = project_path.size;
|
||||||
if (project_path.size == 0){
|
if (project_path.size == 0){
|
||||||
print_message(app, literal("The hot directory is empty, cannot search for a project.\n"));
|
print_message(app, literal("The hot directory is empty, cannot search for a project.\n"));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
File_Name_Path_Data dump = dump_file_search_up_path(arena, project_path, make_lit_string("project.4coder"));
|
File_Name_Path_Data dump = dump_file_search_up_path(scratch, project_path, make_lit_string("project.4coder"));
|
||||||
if (dump.data.str != 0){
|
if (dump.data.str != 0){
|
||||||
String project_root = dump.path;
|
String project_root = dump.path;
|
||||||
remove_last_folder(&project_root);
|
remove_last_folder(&project_root);
|
||||||
success = parse_project__data(arena, dump.file_name, dump.data, project_root, project);
|
parsed = parse_project__data(scratch, dump.file_name, dump.data, project_root, project);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
char message_space[512];
|
char message_space[512];
|
||||||
|
@ -268,14 +268,15 @@ parse_project__nearest_file(Application_Links *app, Partition *arena, Project *p
|
||||||
}
|
}
|
||||||
end_temp_memory(temp);
|
end_temp_memory(temp);
|
||||||
|
|
||||||
return(success);
|
return(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_current_project(Application_Links *app, Partition *scratch, Project *project){
|
set_current_project(Application_Links *app, Partition *scratch, Project *project, Config *parsed){
|
||||||
memcpy(¤t_project, &project, sizeof(current_project));
|
memcpy(¤t_project, project, sizeof(current_project));
|
||||||
|
current_project.dir = current_project.dir_space;
|
||||||
|
|
||||||
String file_dir = make_string(project->dir_space, project->dir_len);
|
String file_dir = make_string(current_project.dir_space, current_project.dir_len);
|
||||||
|
|
||||||
// Open all project files
|
// Open all project files
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
@ -292,6 +293,11 @@ set_current_project(Application_Links *app, Partition *scratch, Project *project
|
||||||
append(&builder, file_dir);
|
append(&builder, file_dir);
|
||||||
terminate_with_null(&builder);
|
terminate_with_null(&builder);
|
||||||
set_window_title(app, builder.str);
|
set_window_title(app, builder.str);
|
||||||
|
|
||||||
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
|
String error_text = config_stringize_errors(scratch, parsed);
|
||||||
|
print_message(app, error_text.str, error_text.size);
|
||||||
|
end_temp_memory(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -299,19 +305,20 @@ set_current_project_from_data(Application_Links *app, Partition *scratch,
|
||||||
String file_name, String data, String file_dir){
|
String file_name, String data, String file_dir){
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
Project project = {0};
|
Project project = {0};
|
||||||
if (parse_project__data(scratch, file_name, data, file_dir,
|
Config *parsed = parse_project__data(scratch, file_name, data, file_dir, &project);
|
||||||
&project)){
|
if (parsed != 0){
|
||||||
set_current_project(app, scratch, &project);
|
set_current_project(app, scratch, &project, parsed);
|
||||||
}
|
}
|
||||||
end_temp_memory(temp);
|
end_temp_memory(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_project_from_nearest_project_file(Application_Links *app, Partition *scratch){
|
set_current_project_from_nearest_project_file(Application_Links *app, Partition *scratch){
|
||||||
Temp_Memory temp = begin_temp_memory(scratch);
|
Temp_Memory temp = begin_temp_memory(scratch);
|
||||||
Project project = {0};
|
Project project = {0};
|
||||||
if (parse_project__nearest_file(app, scratch, &project)){
|
Config *parsed = parse_project__nearest_file(app, scratch, &project);
|
||||||
set_current_project(app, scratch, &project);
|
if (parsed != 0){
|
||||||
|
set_current_project(app, scratch, &project, parsed);
|
||||||
}
|
}
|
||||||
end_temp_memory(temp);
|
end_temp_memory(temp);
|
||||||
}
|
}
|
||||||
|
@ -397,7 +404,7 @@ CUSTOM_COMMAND_SIG(load_project)
|
||||||
CUSTOM_DOC("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.")
|
CUSTOM_DOC("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.")
|
||||||
{
|
{
|
||||||
save_all_dirty_buffers(app);
|
save_all_dirty_buffers(app);
|
||||||
set_project_from_nearest_project_file(app, &global_part);
|
set_current_project_from_nearest_project_file(app, &global_part);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(project_fkey_command)
|
CUSTOM_COMMAND_SIG(project_fkey_command)
|
||||||
|
|
|
@ -31,7 +31,6 @@ struct Project{
|
||||||
Fkey_Command fkey_commands[16];
|
Fkey_Command fkey_commands[16];
|
||||||
|
|
||||||
bool32 open_recursively;
|
bool32 open_recursively;
|
||||||
|
|
||||||
bool32 loaded;
|
bool32 loaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,34 @@
|
||||||
extensions = ".c.cpp.h.m.bat.sh.4coder.txt";
|
extensions = ".c.cpp.h.m.bat.sh.4coder.txt";
|
||||||
open_recursively = true;
|
open_recursively = true;
|
||||||
|
|
||||||
fkey_command_win[1] = {"build_tests.bat" , "*compilation*" , true , true };
|
build_x86_win32 = "echo build: x86 & build.bat /DDEV_BUILD_X86";
|
||||||
fkey_command_win[2] = {"generate_tests.bat" , "*compilation*" , true , true };
|
build_x86_linux = "echo build: x86 & ./build.sh -DDEV_BUILD_X86";
|
||||||
fkey_command_win[3] = {"run_regression_tests.bat" , "*test*" , false, true };
|
build_x86_mac = "echo build: x86 & ./build.sh -DDEV_BUILD_X86";
|
||||||
|
|
||||||
fkey_command_win[1] = {"echo build: x64 & build.bat", "*compilation*" , true , true };
|
fkey_command_win[1] = {"echo build: x64 & build.bat", "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_win[2] = {"build_site.bat" , "*site*" , false, true };
|
fkey_command_win[2] = {"build_site.bat" , "*site*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
fkey_command_win[3] = {"build_string.bat" , "*compilation*" , true , true };
|
fkey_command_win[3] = {"build_string.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_win[4] = {"echo build: x86 & build.bat /DDEV_BUILD_X86" , "*compilation*", true, true };
|
fkey_command_win[4] = {build_x86_win32 , "*compilation*" , .footer_panel = true, .save_dirty_files = true };
|
||||||
fkey_command_win[5] = {"build_metadata.bat" , "*compilation*" , true , true };
|
fkey_command_win[5] = {"build_metadata.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_win[6] = {"run_regression_tests.bat" , "*test*" , false, true };
|
fkey_command_win[6] = {"run_regression_tests.bat" , "*test*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
fkey_command_win[7] = {"build_tests.bat" , "*compilation*" , true , true };
|
fkey_command_win[7] = {"build_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_win[8] = {"generate_tests.bat" , "*compilation*" , true , true };
|
fkey_command_win[8] = {"generate_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_win[12] = {"package.bat" , "*package*" , false, true };
|
fkey_command_win[12] = {"package.bat" , "*package*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
|
|
||||||
fkey_command_linux[1] = {"echo build: x64 & ./build.sh", "*compilation*" , true , true };
|
fkey_command_win[1] = {"build_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_linux[2] = {"build_site.sh" , "*site*" , false, true };
|
fkey_command_win[2] = {"generate_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_linux[3] = {"build_string.sh" , "*compilation*" , true , true };
|
fkey_command_win[3] = {"run_regression_tests.bat" , "*test*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
fkey_command_linux[4] = {"echo build: x86 & ./build.sh -DDEV_BUILD_X86" , "*compilation*", true, true };
|
|
||||||
fkey_command_linux[5] = {"./build_metadata.sh" , "*compilation*" , true , true };
|
|
||||||
fkey_command_linux[12] = {"./package.sh" , "*package*" , false, true };
|
|
||||||
|
|
||||||
fkey_command_mac[1] = {"echo build: x64 & ./build.sh", "*compilation*" , true , true };
|
fkey_command_linux[1] = {"echo build: x64 & ./build.sh", "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_mac[2] = {"build_site.sh" , "*site*" , false, true };
|
fkey_command_linux[2] = {"build_site.sh" , "*site*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
fkey_command_mac[3] = {"build_string.sh" , "*compilation*" , true , true };
|
fkey_command_linux[3] = {"build_string.sh" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_mac[4] = {"echo build: x86 & ./build.sh -DDEV_BUILD_X86" , "*compilation*", true, true };
|
fkey_command_linux[4] = {build_x86_linux , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
fkey_command_mac[10] = {"./package.sh" , "*package*" , false, true };
|
fkey_command_linux[5] = {"./build_metadata.sh" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
|
fkey_command_linux[12] = {"./package.sh" , "*package*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
|
|
||||||
|
fkey_command_mac[1] = {"echo build: x64 & ./build.sh", "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
|
fkey_command_mac[2] = {"build_site.sh" , "*site*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
|
fkey_command_mac[3] = {"build_string.sh" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
|
fkey_command_mac[4] = {build_x86_mac , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||||
|
fkey_command_mac[10] = {"./package.sh" , "*package*" , .footer_panel = false, .save_dirty_files = true };
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,10 @@ The following bindings apply in all situations.
|
||||||
\ITEM \STYLE{code} <ctrl <> \END Change the currently active panel, moving to the panel with the next lowest view_id.
|
\ITEM \STYLE{code} <ctrl <> \END Change the currently active panel, moving to the panel with the next lowest view_id.
|
||||||
\ITEM \STYLE{code} <ctrl n> \END Interactively creates a new file.
|
\ITEM \STYLE{code} <ctrl n> \END Interactively creates a new file.
|
||||||
\ITEM \STYLE{code} <ctrl o> \END Interactively opens or creates a new file.
|
\ITEM \STYLE{code} <ctrl o> \END Interactively opens or creates a new file.
|
||||||
\ITEM \STYLE{code} <alt o> \END Reads a filename from surrounding '"' characters and attempts to open the corresponding file, displaying it in the other view.
|
\ITEM \STYLE{code} <alt o> \END Switches to the next active panel and begins an open file dialogue.
|
||||||
\ITEM \STYLE{code} <ctrl k> \END Interactively kill an open buffer.
|
\ITEM \STYLE{code} <ctrl k> \END Interactively kill an open buffer.
|
||||||
\ITEM \STYLE{code} <ctrl i> \END Interactively switch to an open buffer.
|
\ITEM \STYLE{code} <ctrl i> \END Interactively switch to an open buffer.
|
||||||
\ITEM \STYLE{code} <ctrl h> \END Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.
|
\ITEM \STYLE{code} <ctrl h> \END Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.
|
||||||
\ITEM \STYLE{code} <ctrl H> \END If a project file has already been loaded, reloads the same file. Useful for when the project configuration is changed.
|
|
||||||
\ITEM \STYLE{code} <ctrl S> \END Saves all buffers marked dirty (showing the '*' indicator).
|
\ITEM \STYLE{code} <ctrl S> \END Saves all buffers marked dirty (showing the '*' indicator).
|
||||||
\ITEM \STYLE{code} <alt c> \END Opens the 4coder colors and fonts selector menu.
|
\ITEM \STYLE{code} <alt c> \END Opens the 4coder colors and fonts selector menu.
|
||||||
\ITEM \STYLE{code} <alt .> \END If the special build panel is open, makes the build panel the active panel.
|
\ITEM \STYLE{code} <alt .> \END If the special build panel is open, makes the build panel the active panel.
|
||||||
|
@ -54,7 +53,6 @@ The following bindings apply in all situations.
|
||||||
\ITEM \STYLE{code} <alt w> \END Sets the current view to hide it's scrollbar.
|
\ITEM \STYLE{code} <alt w> \END Sets the current view to hide it's scrollbar.
|
||||||
\ITEM \STYLE{code} <alt b> \END Toggles the visibility status of the current view's filebar.
|
\ITEM \STYLE{code} <alt b> \END Toggles the visibility status of the current view's filebar.
|
||||||
\ITEM \STYLE{code} <alt @> \END Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.
|
\ITEM \STYLE{code} <alt @> \END Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.
|
||||||
\ITEM \STYLE{code} <ctrl page up> \END Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.
|
|
||||||
\ITEM \STYLE{code} <alt E> \END Attempts to close 4coder.
|
\ITEM \STYLE{code} <alt E> \END Attempts to close 4coder.
|
||||||
\ITEM \STYLE{code} <ctrl +> \END Increase the size of the face used by the current buffer.
|
\ITEM \STYLE{code} <ctrl +> \END Increase the size of the face used by the current buffer.
|
||||||
\ITEM \STYLE{code} <ctrl -> \END Decrease the size of the face used by the current buffer.
|
\ITEM \STYLE{code} <ctrl -> \END Decrease the size of the face used by the current buffer.
|
||||||
|
@ -119,7 +117,6 @@ The following bindings apply in general text files and most apply in code files,
|
||||||
\ITEM \STYLE{code} <alt F> \END Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.
|
\ITEM \STYLE{code} <alt F> \END Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.
|
||||||
\ITEM \STYLE{code} <ctrl g> \END Queries the user for a number, and jumps the cursor to the corresponding line.
|
\ITEM \STYLE{code} <ctrl g> \END Queries the user for a number, and jumps the cursor to the corresponding line.
|
||||||
\ITEM \STYLE{code} <ctrl G> \END Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.
|
\ITEM \STYLE{code} <ctrl G> \END Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.
|
||||||
\ITEM \STYLE{code} <ctrl j> \END Converts all ascii text in the range between the cursor and the mark to lowercase.
|
|
||||||
\ITEM \STYLE{code} <ctrl K> \END Kills the current buffer.
|
\ITEM \STYLE{code} <ctrl K> \END Kills the current buffer.
|
||||||
\ITEM \STYLE{code} <ctrl l> \END Toggles the current buffer's line wrapping status.
|
\ITEM \STYLE{code} <ctrl l> \END Toggles the current buffer's line wrapping status.
|
||||||
\ITEM \STYLE{code} <ctrl L> \END Create a copy of the line on which the cursor sits.
|
\ITEM \STYLE{code} <ctrl L> \END Create a copy of the line on which the cursor sits.
|
||||||
|
@ -133,7 +130,6 @@ The following bindings apply in general text files and most apply in code files,
|
||||||
\ITEM \STYLE{code} <alt s> \END Queries the user for a name and saves the contents of the current buffer, altering the buffer's name too.
|
\ITEM \STYLE{code} <alt s> \END Queries the user for a name and saves the contents of the current buffer, altering the buffer's name too.
|
||||||
\ITEM \STYLE{code} <ctrl t> \END Begins an incremental search down through the current buffer for the word or token under the cursor.
|
\ITEM \STYLE{code} <ctrl t> \END Begins an incremental search down through the current buffer for the word or token under the cursor.
|
||||||
\ITEM \STYLE{code} <ctrl T> \END Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.
|
\ITEM \STYLE{code} <ctrl T> \END Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.
|
||||||
\ITEM \STYLE{code} <ctrl u> \END Converts all ascii text in the range between the cursor and the mark to uppercase.
|
|
||||||
\ITEM \STYLE{code} <ctrl v> \END Paste from the top of clipboard and run auto-indent on the newly pasted text.
|
\ITEM \STYLE{code} <ctrl v> \END Paste from the top of clipboard and run auto-indent on the newly pasted text.
|
||||||
\ITEM \STYLE{code} <alt v> \END Toggles the current buffer's virtual whitespace status.
|
\ITEM \STYLE{code} <alt v> \END Toggles the current buffer's virtual whitespace status.
|
||||||
\ITEM \STYLE{code} <ctrl V> \END Paste the next item on the clipboard and run auto-indent on the newly pasted text.
|
\ITEM \STYLE{code} <ctrl V> \END Paste the next item on the clipboard and run auto-indent on the newly pasted text.
|
||||||
|
@ -198,11 +194,10 @@ The following bindings apply in all situations.
|
||||||
\ITEM \STYLE{code} <cmnd <> \END Change the currently active panel, moving to the panel with the next lowest view_id.
|
\ITEM \STYLE{code} <cmnd <> \END Change the currently active panel, moving to the panel with the next lowest view_id.
|
||||||
\ITEM \STYLE{code} <cmnd n> \END Interactively creates a new file.
|
\ITEM \STYLE{code} <cmnd n> \END Interactively creates a new file.
|
||||||
\ITEM \STYLE{code} <cmnd o> \END Interactively opens or creates a new file.
|
\ITEM \STYLE{code} <cmnd o> \END Interactively opens or creates a new file.
|
||||||
\ITEM \STYLE{code} <ctrl o> \END Reads a filename from surrounding '"' characters and attempts to open the corresponding file, displaying it in the other view.
|
\ITEM \STYLE{code} <ctrl o> \END Switches to the next active panel and begins an open file dialogue.
|
||||||
\ITEM \STYLE{code} <cmnd k> \END Interactively kill an open buffer.
|
\ITEM \STYLE{code} <cmnd k> \END Interactively kill an open buffer.
|
||||||
\ITEM \STYLE{code} <cmnd i> \END Interactively switch to an open buffer.
|
\ITEM \STYLE{code} <cmnd i> \END Interactively switch to an open buffer.
|
||||||
\ITEM \STYLE{code} <cmnd h> \END Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.
|
\ITEM \STYLE{code} <cmnd h> \END Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.
|
||||||
\ITEM \STYLE{code} <cmnd H> \END If a project file has already been loaded, reloads the same file. Useful for when the project configuration is changed.
|
|
||||||
\ITEM \STYLE{code} <cmnd S> \END Saves all buffers marked dirty (showing the '*' indicator).
|
\ITEM \STYLE{code} <cmnd S> \END Saves all buffers marked dirty (showing the '*' indicator).
|
||||||
\ITEM \STYLE{code} <ctrl c> \END Opens the 4coder colors and fonts selector menu.
|
\ITEM \STYLE{code} <ctrl c> \END Opens the 4coder colors and fonts selector menu.
|
||||||
\ITEM \STYLE{code} <ctrl .> \END If the special build panel is open, makes the build panel the active panel.
|
\ITEM \STYLE{code} <ctrl .> \END If the special build panel is open, makes the build panel the active panel.
|
||||||
|
@ -218,7 +213,6 @@ The following bindings apply in all situations.
|
||||||
\ITEM \STYLE{code} <ctrl w> \END Sets the current view to hide it's scrollbar.
|
\ITEM \STYLE{code} <ctrl w> \END Sets the current view to hide it's scrollbar.
|
||||||
\ITEM \STYLE{code} <ctrl b> \END Toggles the visibility status of the current view's filebar.
|
\ITEM \STYLE{code} <ctrl b> \END Toggles the visibility status of the current view's filebar.
|
||||||
\ITEM \STYLE{code} <ctrl @> \END Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.
|
\ITEM \STYLE{code} <ctrl @> \END Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.
|
||||||
\ITEM \STYLE{code} <cmnd page up> \END Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.
|
|
||||||
\ITEM \STYLE{code} <ctrl E> \END Attempts to close 4coder.
|
\ITEM \STYLE{code} <ctrl E> \END Attempts to close 4coder.
|
||||||
\ITEM \STYLE{code} <ctrl +> \END Increase the size of the face used by the current buffer.
|
\ITEM \STYLE{code} <ctrl +> \END Increase the size of the face used by the current buffer.
|
||||||
\ITEM \STYLE{code} <ctrl -> \END Decrease the size of the face used by the current buffer.
|
\ITEM \STYLE{code} <ctrl -> \END Decrease the size of the face used by the current buffer.
|
||||||
|
@ -282,7 +276,6 @@ The following bindings apply in general text files and most apply in code files,
|
||||||
\ITEM \STYLE{code} <ctrl F> \END Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.
|
\ITEM \STYLE{code} <ctrl F> \END Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.
|
||||||
\ITEM \STYLE{code} <cmnd g> \END Queries the user for a number, and jumps the cursor to the corresponding line.
|
\ITEM \STYLE{code} <cmnd g> \END Queries the user for a number, and jumps the cursor to the corresponding line.
|
||||||
\ITEM \STYLE{code} <cmnd G> \END Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.
|
\ITEM \STYLE{code} <cmnd G> \END Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.
|
||||||
\ITEM \STYLE{code} <cmnd j> \END Converts all ascii text in the range between the cursor and the mark to lowercase.
|
|
||||||
\ITEM \STYLE{code} <cmnd K> \END Kills the current buffer.
|
\ITEM \STYLE{code} <cmnd K> \END Kills the current buffer.
|
||||||
\ITEM \STYLE{code} <cmnd l> \END Toggles the current buffer's line wrapping status.
|
\ITEM \STYLE{code} <cmnd l> \END Toggles the current buffer's line wrapping status.
|
||||||
\ITEM \STYLE{code} <cmnd L> \END Create a copy of the line on which the cursor sits.
|
\ITEM \STYLE{code} <cmnd L> \END Create a copy of the line on which the cursor sits.
|
||||||
|
@ -295,7 +288,6 @@ The following bindings apply in general text files and most apply in code files,
|
||||||
\ITEM \STYLE{code} <ctrl s> \END Queries the user for a name and saves the contents of the current buffer, altering the buffer's name too.
|
\ITEM \STYLE{code} <ctrl s> \END Queries the user for a name and saves the contents of the current buffer, altering the buffer's name too.
|
||||||
\ITEM \STYLE{code} <cmnd t> \END Begins an incremental search down through the current buffer for the word or token under the cursor.
|
\ITEM \STYLE{code} <cmnd t> \END Begins an incremental search down through the current buffer for the word or token under the cursor.
|
||||||
\ITEM \STYLE{code} <cmnd T> \END Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.
|
\ITEM \STYLE{code} <cmnd T> \END Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.
|
||||||
\ITEM \STYLE{code} <cmnd u> \END Converts all ascii text in the range between the cursor and the mark to uppercase.
|
|
||||||
\ITEM \STYLE{code} <cmnd v> \END Paste from the top of clipboard and run auto-indent on the newly pasted text.
|
\ITEM \STYLE{code} <cmnd v> \END Paste from the top of clipboard and run auto-indent on the newly pasted text.
|
||||||
\ITEM \STYLE{code} <ctrl v> \END Toggles the current buffer's virtual whitespace status.
|
\ITEM \STYLE{code} <ctrl v> \END Toggles the current buffer's virtual whitespace status.
|
||||||
\ITEM \STYLE{code} <cmnd V> \END Paste the next item on the clipboard and run auto-indent on the newly pasted text.
|
\ITEM \STYLE{code} <cmnd V> \END Paste the next item on the clipboard and run auto-indent on the newly pasted text.
|
||||||
|
|
Loading…
Reference in New Issue