Added parse error log and parse recover to the config parser
parent
cb1273d4cb
commit
5566572269
|
@ -4,12 +4,6 @@
|
|||
|
||||
// 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
|
||||
get_code_extensions(Extension_List *list){
|
||||
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
|
||||
config_parser__advance_to_next(Config_Parser *ctx){
|
||||
Cpp_Token *t = ctx->token;
|
||||
|
@ -145,13 +183,13 @@ config_parser__match_text(Config_Parser *ctx, String text){
|
|||
return(result);
|
||||
}
|
||||
|
||||
static Config *config_parser__config(Config_Parser *ctx);
|
||||
static int32_t *config_parser__version(Config_Parser *ctx);
|
||||
static Config *config_parser__config (Config_Parser *ctx);
|
||||
static int32_t *config_parser__version (Config_Parser *ctx);
|
||||
static Config_Assignment *config_parser__assignment(Config_Parser *ctx);
|
||||
static Config_LValue *config_parser__lvalue(Config_Parser *ctx);
|
||||
static Config_RValue *config_parser__rvalue(Config_Parser *ctx);
|
||||
static Config_Compound *config_parser__compound(Config_Parser *ctx);
|
||||
static Config_Compound_Element *config_parser__element(Config_Parser *ctx);
|
||||
static Config_LValue *config_parser__lvalue (Config_Parser *ctx);
|
||||
static Config_RValue *config_parser__rvalue (Config_Parser *ctx);
|
||||
static Config_Compound *config_parser__compound (Config_Parser *ctx);
|
||||
static Config_Compound_Element *config_parser__element (Config_Parser *ctx);
|
||||
|
||||
static Config*
|
||||
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);
|
||||
}
|
||||
|
||||
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*
|
||||
config_parser__config(Config_Parser *ctx){
|
||||
int32_t *version = config_parser__version(ctx);
|
||||
|
@ -173,9 +244,10 @@ config_parser__config(Config_Parser *ctx){
|
|||
int32_t count = 0;
|
||||
for (;!config_parser__recognize_token(ctx, CPP_TOKEN_EOF);){
|
||||
Config_Assignment *assignment = config_parser__assignment(ctx);
|
||||
require(assignment != 0);
|
||||
zdll_push_back(first, last, assignment);
|
||||
count += 1;
|
||||
if (assignment != 0){
|
||||
zdll_push_back(first, last, assignment);
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Config *config = push_array(ctx->arena, Config, 1);
|
||||
|
@ -184,17 +256,57 @@ config_parser__config(Config_Parser *ctx){
|
|||
config->first = first;
|
||||
config->last = last;
|
||||
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);
|
||||
}
|
||||
|
||||
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*
|
||||
config_parser__version(Config_Parser *ctx){
|
||||
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_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);
|
||||
*ptr = value.integer;
|
||||
return(ptr);
|
||||
|
@ -203,11 +315,35 @@ config_parser__version(Config_Parser *ctx){
|
|||
static Config_Assignment*
|
||||
config_parser__assignment(Config_Parser *ctx){
|
||||
Config_LValue *l = config_parser__lvalue(ctx);
|
||||
require(l != 0);
|
||||
require(config_parser__match_token(ctx, CPP_TOKEN_EQ));
|
||||
if (l == 0){
|
||||
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);
|
||||
require(r != 0);
|
||||
require(config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON));
|
||||
if (r == 0){
|
||||
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);
|
||||
memset(assignment, 0, sizeof(*assignment));
|
||||
|
@ -276,7 +412,7 @@ config_parser__rvalue(Config_Parser *ctx){
|
|||
rvalue->type = ConfigRValueType_Integer;
|
||||
if (value.is_signed){
|
||||
rvalue->integer = value.integer;
|
||||
}
|
||||
}
|
||||
else{
|
||||
rvalue->uinteger = value.uinteger;
|
||||
}
|
||||
|
@ -395,42 +531,42 @@ config_evaluate_rvalue(Config *config, Config_Assignment *assignment, Config_RVa
|
|||
Config_RValue_Type type, void *out){
|
||||
bool32 success = false;
|
||||
if (r != 0 && !assignment->visited){
|
||||
if (r->type == ConfigRValueType_LValue){
|
||||
assignment->visited = true;
|
||||
Config_LValue *l = r->lvalue;
|
||||
success = config_var(config, l->identifier, l->index, type, out);
|
||||
assignment->visited = false;
|
||||
}
|
||||
else if (r->type == type){
|
||||
success = true;
|
||||
switch (type){
|
||||
case ConfigRValueType_Boolean:
|
||||
{
|
||||
*(bool32*)out = r->boolean;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_Integer:
|
||||
{
|
||||
*(int32_t*)out = r->integer;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_String:
|
||||
{
|
||||
*(String*)out = r->string;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_Character:
|
||||
{
|
||||
*(char*)out = r->character;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_Compound:
|
||||
{
|
||||
*(Config_Compound**)out = r->compound;
|
||||
}break;
|
||||
if (r->type == ConfigRValueType_LValue){
|
||||
assignment->visited = true;
|
||||
Config_LValue *l = r->lvalue;
|
||||
success = config_var(config, l->identifier, l->index, type, out);
|
||||
assignment->visited = false;
|
||||
}
|
||||
else if (r->type == type){
|
||||
success = true;
|
||||
switch (type){
|
||||
case ConfigRValueType_Boolean:
|
||||
{
|
||||
*(bool32*)out = r->boolean;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_Integer:
|
||||
{
|
||||
*(int32_t*)out = r->integer;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_String:
|
||||
{
|
||||
*(String*)out = r->string;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_Character:
|
||||
{
|
||||
*(char*)out = r->character;
|
||||
}break;
|
||||
|
||||
case ConfigRValueType_Compound:
|
||||
{
|
||||
*(Config_Compound**)out = r->compound;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
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));
|
||||
|
@ -525,10 +682,10 @@ config_compound_member(Config *config, Config_Compound *compound, String var_nam
|
|||
case ConfigLayoutType_Identifier:
|
||||
{
|
||||
implicit_index_is_valid = false;
|
||||
if (match(element->l.identifier, var_name)){
|
||||
if (match(element->l.identifier, var_name)){
|
||||
element_matches_query = true;
|
||||
}
|
||||
}break;
|
||||
}break;
|
||||
|
||||
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
|
||||
change_mapping(Application_Links *app, String mapping){
|
||||
bool32 did_remap = false;
|
||||
|
@ -956,7 +812,7 @@ text_data_to_token_array(Partition *arena, String data){
|
|||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!success){
|
||||
memset(&array, 0, sizeof(array));
|
||||
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);
|
||||
if (array.tokens != 0){
|
||||
parsed = text_data_and_token_array_to_parse_data(arena, file_name, data, array);
|
||||
if (parsed == 0){
|
||||
end_temp_memory(restore_point);
|
||||
if (parsed == 0){
|
||||
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));
|
||||
}
|
||||
|
||||
static void
|
||||
config_parse__data(Partition *scratch, String file_name, String data, Config_Data *config){
|
||||
static Config*
|
||||
config_parse__data(Partition *arena, String file_name, String data, Config_Data *config){
|
||||
config_init_default(config);
|
||||
|
||||
bool32 success = false;
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
|
||||
Config *parsed = text_data_to_parsed_data(scratch, file_name, data);
|
||||
if (parsed != 0){
|
||||
success = true;
|
||||
|
||||
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_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_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_string_var(parsed, "default_theme_name", 0, &config->default_theme_name);
|
||||
config_string_var(parsed, "default_font_name", 0, &config->default_font_name);
|
||||
config_string_var(parsed, "user_name", 0, &config->user_name);
|
||||
|
||||
config_string_var(parsed, "default_compiler_bat", 0, &config->default_compiler_bat);
|
||||
config_string_var(parsed, "default_flags_bat", 0, &config->default_flags_bat);
|
||||
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_string_var(parsed, "mapping", 0, &config->current_mapping);
|
||||
|
||||
char space[512];
|
||||
String str = make_fixed_width_string(space);
|
||||
if (config_string_var(parsed, "treat_as_code", 0, &str)){
|
||||
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);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
Config *parsed = text_data_to_parsed_data(arena, file_name, data);
|
||||
if (parsed != 0){
|
||||
success = true;
|
||||
|
||||
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_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_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_fixed_string_var(parsed, "default_theme_name", 0,
|
||||
&config->default_theme_name, config->default_theme_name_space);
|
||||
config_fixed_string_var(parsed, "default_font_name", 0,
|
||||
&config->default_font_name, config->default_font_name_space);
|
||||
config_fixed_string_var(parsed, "user_name", 0,
|
||||
&config->user_name, config->user_name_space);
|
||||
|
||||
config_fixed_string_var(parsed, "default_compiler_bat", 0,
|
||||
&config->default_compiler_bat, config->default_compiler_bat_space);
|
||||
config_fixed_string_var(parsed, "default_flags_bat", 0,
|
||||
&config->default_flags_bat, config->default_flags_bat_space);
|
||||
config_fixed_string_var(parsed, "default_compiler_sh", 0,
|
||||
&config->default_compiler_sh, config->default_compiler_sh_space);
|
||||
config_fixed_string_var(parsed, "default_flags_sh", 0,
|
||||
&config->default_flags_sh, config->default_flags_sh_space);
|
||||
|
||||
config_fixed_string_var(parsed, "mapping", 0,
|
||||
&config->current_mapping, config->current_mapping_space);
|
||||
|
||||
String str;
|
||||
if (config_string_var(parsed, "treat_as_code", 0, &str)){
|
||||
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){
|
||||
config_init_default(config);
|
||||
}
|
||||
|
||||
return(parsed);
|
||||
}
|
||||
|
||||
static void
|
||||
config_parse__file_handle(Partition *scratch,
|
||||
String file_name, FILE *file, Config_Data *config){
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
String data = dump_file_handle(scratch, file);
|
||||
static Config*
|
||||
config_parse__file_handle(Partition *arena,
|
||||
String file_name, FILE *file, Config_Data *config){
|
||||
Config *parsed = 0;
|
||||
String data = dump_file_handle(arena, file);
|
||||
if (data.str != 0){
|
||||
config_parse__data(scratch, file_name, data, config);
|
||||
parsed = config_parse__data(arena, file_name, data, config);
|
||||
}
|
||||
else{
|
||||
config_init_default(config);
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
return(parsed);
|
||||
}
|
||||
|
||||
static void
|
||||
config_parse__file_name(Application_Links *app, Partition *scratch,
|
||||
static Config*
|
||||
config_parse__file_name(Application_Links *app, Partition *arena,
|
||||
char *file_name, Config_Data *config){
|
||||
Config *parsed = 0;
|
||||
bool32 success = false;
|
||||
FILE *file = open_file_try_current_path_then_binary_path(app, file_name);
|
||||
if (file != 0){
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
String data = dump_file_handle(scratch, file);
|
||||
String data = dump_file_handle(arena, file);
|
||||
fclose(file);
|
||||
if (data.str != 0){
|
||||
config_parse__data(scratch, make_string_slowly(file_name), data, config);
|
||||
if (data.str != 0){
|
||||
parsed = config_parse__data(arena, make_string_slowly(file_name), data, config);
|
||||
success = true;
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
}
|
||||
if (!success){
|
||||
config_init_default(config);
|
||||
}
|
||||
return(parsed);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1107,64 +969,50 @@ init_theme_zero(Theme *theme){
|
|||
}
|
||||
}
|
||||
|
||||
static bool32
|
||||
theme_parse__data(Partition *scratch, String file_name, String data, Theme_Data *theme){
|
||||
static Config*
|
||||
theme_parse__data(Partition *arena, String file_name, String data, Theme_Data *theme){
|
||||
theme->name = make_fixed_width_string(theme->space);
|
||||
copy(&theme->name, "unnamed");
|
||||
init_theme_zero(&theme->theme);
|
||||
|
||||
bool32 success = false;
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
|
||||
Config *parsed = text_data_to_parsed_data(scratch, file_name, data);
|
||||
if (parsed != 0){
|
||||
success = true;
|
||||
|
||||
String theme_name = {0};
|
||||
if (config_string_var(parsed, "name", 0, &theme_name)){
|
||||
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;
|
||||
}
|
||||
Config *parsed = text_data_to_parsed_data(arena, file_name, data);
|
||||
if (parsed != 0){
|
||||
config_fixed_string_var(parsed, "name", 0, &theme->name, theme->space);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
theme->theme.colors[i] = color;
|
||||
}
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
return(success);
|
||||
|
||||
return(parsed);
|
||||
}
|
||||
|
||||
static bool32
|
||||
theme_parse__file_name(Application_Links *app, Partition *scratch,
|
||||
static Config*
|
||||
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){
|
||||
bool32 success = false;
|
||||
Config *parsed = 0;
|
||||
FILE *file = open_file_try_current_path_then_binary_path(app, file_name);
|
||||
if (file != 0){
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
String data = dump_file_handle(scratch, file);
|
||||
String data = dump_file_handle(arena, file);
|
||||
fclose(file);
|
||||
success = theme_parse__data(scratch, make_string_slowly(file_name), data, theme);
|
||||
end_temp_memory(temp);
|
||||
parsed = theme_parse__data(arena, make_string_slowly(file_name), data, theme);
|
||||
}
|
||||
if (!success){
|
||||
if (parsed == 0){
|
||||
char space[256];
|
||||
String str = make_fixed_width_string(space);
|
||||
append(&str, "Did not find ");
|
||||
|
@ -1172,14 +1020,19 @@ theme_parse__file_name(Application_Links *app, Partition *scratch,
|
|||
append(&str, ", color scheme not loaded");
|
||||
print_message(app, str.str, str.size);
|
||||
}
|
||||
return(success);
|
||||
return(parsed);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
static void
|
||||
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);
|
||||
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);
|
||||
|
@ -1187,8 +1040,12 @@ load_config_and_apply(Application_Links *app, Partition *scratch, Config_Data *c
|
|||
|
||||
static void
|
||||
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_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);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,23 @@
|
|||
#if !defined(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{
|
||||
Cpp_Token *start;
|
||||
Cpp_Token *token;
|
||||
|
@ -16,6 +33,10 @@ Cpp_Token *end;
|
|||
String data;
|
||||
|
||||
Partition *arena;
|
||||
|
||||
Config_Error *first_error;
|
||||
Config_Error *last_error;
|
||||
int32_t count_error;
|
||||
};
|
||||
|
||||
struct Config_LValue{
|
||||
|
@ -100,6 +121,12 @@ struct Config{
|
|||
Config_Assignment *first;
|
||||
Config_Assignment *last;
|
||||
int32_t count;
|
||||
|
||||
Config_Error *first_error;
|
||||
Config_Error *last_error;
|
||||
int32_t count_error;
|
||||
|
||||
String data;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config := [version] {assignment}
|
||||
|
||||
version := "version" "(" INTEGER ")"
|
||||
version := "version" "(" INTEGER ")" ";"
|
||||
assignment := lvalue "=" rvalue ";"
|
||||
lvalue := IDENTIFIER [ "[" INTEGER "]" ]
|
||||
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{
|
||||
String name;
|
||||
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(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(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_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 },
|
||||
|
@ -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_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(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(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 },
|
||||
|
@ -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_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(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_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, 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, 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_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 },
|
||||
|
@ -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_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(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_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_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, 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_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 },
|
||||
|
@ -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_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(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_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 },
|
||||
|
|
|
@ -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,
|
||||
Project *project){
|
||||
bool32 success = false;
|
||||
Config *parsed = 0;
|
||||
|
||||
Cpp_Token_Array array = text_data_to_token_array(scratch, data);
|
||||
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){
|
||||
success = true;
|
||||
memset(project, 0, sizeof(*project));
|
||||
project->loaded = true;
|
||||
|
||||
// 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
|
||||
parse_project__nearest_file(Application_Links *app, Partition *arena, Project *project){
|
||||
bool32 success = false;
|
||||
static Config*
|
||||
parse_project__nearest_file(Application_Links *app, Partition *scratch, Project *project){
|
||||
Config *parsed = 0;
|
||||
|
||||
String project_path = {0};
|
||||
Temp_Memory temp = begin_temp_memory(arena);
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
int32_t size = 32 << 10;
|
||||
char *space = push_array(arena, char, size);
|
||||
char *space = push_array(scratch, char, size);
|
||||
if (space != 0){
|
||||
project_path = make_string_cap(space, 0, size);
|
||||
project_path.size = directory_get_hot(app, project_path.str, project_path.memory_size);
|
||||
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;
|
||||
if (project_path.size == 0){
|
||||
print_message(app, literal("The hot directory is empty, cannot search for a project.\n"));
|
||||
}
|
||||
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){
|
||||
String project_root = dump.path;
|
||||
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{
|
||||
char message_space[512];
|
||||
|
@ -268,14 +268,15 @@ parse_project__nearest_file(Application_Links *app, Partition *arena, Project *p
|
|||
}
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(success);
|
||||
return(parsed);
|
||||
}
|
||||
|
||||
static void
|
||||
set_current_project(Application_Links *app, Partition *scratch, Project *project){
|
||||
memcpy(¤t_project, &project, sizeof(current_project));
|
||||
set_current_project(Application_Links *app, Partition *scratch, Project *project, Config *parsed){
|
||||
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
|
||||
uint32_t flags = 0;
|
||||
|
@ -292,6 +293,11 @@ set_current_project(Application_Links *app, Partition *scratch, Project *project
|
|||
append(&builder, file_dir);
|
||||
terminate_with_null(&builder);
|
||||
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
|
||||
|
@ -299,19 +305,20 @@ set_current_project_from_data(Application_Links *app, Partition *scratch,
|
|||
String file_name, String data, String file_dir){
|
||||
Temp_Memory temp = begin_temp_memory(scratch);
|
||||
Project project = {0};
|
||||
if (parse_project__data(scratch, file_name, data, file_dir,
|
||||
&project)){
|
||||
set_current_project(app, scratch, &project);
|
||||
Config *parsed = parse_project__data(scratch, file_name, data, file_dir, &project);
|
||||
if (parsed != 0){
|
||||
set_current_project(app, scratch, &project, parsed);
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
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);
|
||||
Project project = {0};
|
||||
if (parse_project__nearest_file(app, scratch, &project)){
|
||||
set_current_project(app, scratch, &project);
|
||||
Config *parsed = parse_project__nearest_file(app, scratch, &project);
|
||||
if (parsed != 0){
|
||||
set_current_project(app, scratch, &project, parsed);
|
||||
}
|
||||
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.")
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -31,7 +31,6 @@ struct Project{
|
|||
Fkey_Command fkey_commands[16];
|
||||
|
||||
bool32 open_recursively;
|
||||
|
||||
bool32 loaded;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
extensions = ".c.cpp.h.m.bat.sh.4coder.txt";
|
||||
open_recursively = true;
|
||||
|
||||
fkey_command_win[1] = {"build_tests.bat" , "*compilation*" , true , true };
|
||||
fkey_command_win[2] = {"generate_tests.bat" , "*compilation*" , true , true };
|
||||
fkey_command_win[3] = {"run_regression_tests.bat" , "*test*" , false, true };
|
||||
build_x86_win32 = "echo build: x86 & build.bat /DDEV_BUILD_X86";
|
||||
build_x86_linux = "echo build: x86 & ./build.sh -DDEV_BUILD_X86";
|
||||
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[2] = {"build_site.bat" , "*site*" , false, true };
|
||||
fkey_command_win[3] = {"build_string.bat" , "*compilation*" , true , true };
|
||||
fkey_command_win[4] = {"echo build: x86 & build.bat /DDEV_BUILD_X86" , "*compilation*", true, true };
|
||||
fkey_command_win[5] = {"build_metadata.bat" , "*compilation*" , true , true };
|
||||
fkey_command_win[6] = {"run_regression_tests.bat" , "*test*" , false, true };
|
||||
fkey_command_win[7] = {"build_tests.bat" , "*compilation*" , true , true };
|
||||
fkey_command_win[8] = {"generate_tests.bat" , "*compilation*" , true , true };
|
||||
fkey_command_win[12] = {"package.bat" , "*package*" , false, 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*" , .footer_panel = false, .save_dirty_files = true };
|
||||
fkey_command_win[3] = {"build_string.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||
fkey_command_win[4] = {build_x86_win32 , "*compilation*" , .footer_panel = true, .save_dirty_files = 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*" , .footer_panel = false, .save_dirty_files = true };
|
||||
fkey_command_win[7] = {"build_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||
fkey_command_win[8] = {"generate_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = 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_linux[2] = {"build_site.sh" , "*site*" , false, true };
|
||||
fkey_command_linux[3] = {"build_string.sh" , "*compilation*" , true , 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_win[1] = {"build_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||
fkey_command_win[2] = {"generate_tests.bat" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||
fkey_command_win[3] = {"run_regression_tests.bat" , "*test*" , .footer_panel = false, .save_dirty_files = true };
|
||||
|
||||
fkey_command_mac[1] = {"echo build: x64 & ./build.sh", "*compilation*" , true , true };
|
||||
fkey_command_mac[2] = {"build_site.sh" , "*site*" , false, true };
|
||||
fkey_command_mac[3] = {"build_string.sh" , "*compilation*" , true , true };
|
||||
fkey_command_mac[4] = {"echo build: x86 & ./build.sh -DDEV_BUILD_X86" , "*compilation*", true, true };
|
||||
fkey_command_mac[10] = {"./package.sh" , "*package*" , false, true };
|
||||
fkey_command_linux[1] = {"echo build: x64 & ./build.sh", "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||
fkey_command_linux[2] = {"build_site.sh" , "*site*" , .footer_panel = false, .save_dirty_files = true };
|
||||
fkey_command_linux[3] = {"build_string.sh" , "*compilation*" , .footer_panel = true , .save_dirty_files = true };
|
||||
fkey_command_linux[4] = {build_x86_linux , "*compilation*" , .footer_panel = true , .save_dirty_files = 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 n> \END Interactively 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 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 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} <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.
|
||||
|
@ -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 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} <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} <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.
|
||||
|
@ -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} <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 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 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.
|
||||
|
@ -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} <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 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} <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.
|
||||
|
@ -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 n> \END Interactively 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 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 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} <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.
|
||||
|
@ -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 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} <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 +> \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.
|
||||
|
@ -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} <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 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 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.
|
||||
|
@ -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} <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 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} <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.
|
||||
|
|
Loading…
Reference in New Issue