some clean up on the indent rule code
This commit is contained in:
parent
55eb007f68
commit
5b2077c6d7
File diff suppressed because one or more lines are too long
|
@ -2,6 +2,10 @@
|
|||
#ifndef FCODER_AUTO_INDENT_INC
|
||||
#define FCODER_AUTO_INDENT_INC
|
||||
|
||||
//
|
||||
// Generic Line Indenter
|
||||
//
|
||||
|
||||
struct Hard_Start_Result{
|
||||
int32_t char_pos;
|
||||
int32_t indent_pos;
|
||||
|
@ -62,36 +66,80 @@ struct Indent_Options{
|
|||
int32_t tab_width;
|
||||
};
|
||||
|
||||
#include "4cpp_lexer.h"
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, int32_t line){
|
||||
Partial_Cursor partial_cursor;
|
||||
app->buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &partial_cursor);
|
||||
return(partial_cursor.pos);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_index(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
Partial_Cursor partial_cursor;
|
||||
app->buffer_compute_cursor(app, buffer, seek_pos(pos), &partial_cursor);
|
||||
return(partial_cursor.line);
|
||||
}
|
||||
|
||||
static Cpp_Token*
|
||||
get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line){
|
||||
int32_t line_start = buffer_get_line_start(app, buffer, line);
|
||||
Cpp_Get_Token_Result get_token = cpp_get_token(&tokens, line_start);
|
||||
static Buffer_Batch_Edit
|
||||
make_batch_from_indent_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
int32_t line_start, int32_t line_end, int32_t *indent_marks,
|
||||
Indent_Options opts){
|
||||
|
||||
if (get_token.in_whitespace){
|
||||
get_token.token_index += 1;
|
||||
Buffer_Batch_Edit result = {0};
|
||||
|
||||
int32_t edit_max = line_end - line_start;
|
||||
int32_t edit_count = 0;
|
||||
|
||||
Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
|
||||
|
||||
char *str_base = (char*)part->base + part->pos;
|
||||
int32_t str_size = 0;
|
||||
|
||||
// NOTE(allen): Shift the array so that line_i can just operate in
|
||||
// it's natural value range.
|
||||
indent_marks -= line_start;
|
||||
|
||||
for (int32_t line_i = line_start; line_i < line_end; ++line_i){
|
||||
int32_t line_start = buffer_get_line_start(app, buffer, line_i);
|
||||
Hard_Start_Result hard_start =
|
||||
buffer_find_hard_start(app, buffer, line_start, opts.tab_width);
|
||||
|
||||
int32_t correct_indentation = indent_marks[line_i];
|
||||
if (hard_start.all_whitespace && opts.empty_blank_lines) correct_indentation = 0;
|
||||
if (correct_indentation == -1) correct_indentation = hard_start.indent_pos;
|
||||
|
||||
// TODO(allen): Only replace spaces if we are using space based indentation.
|
||||
// TODO(allen): See if the first clause can just be removed because it's dumb.
|
||||
if (!hard_start.all_space || correct_indentation != hard_start.indent_pos){
|
||||
Buffer_Edit new_edit;
|
||||
new_edit.str_start = str_size;
|
||||
str_size += correct_indentation;
|
||||
char *str = push_array(part, char, correct_indentation);
|
||||
int32_t j = 0;
|
||||
if (opts.use_tabs){
|
||||
int32_t i = 0;
|
||||
for (; i + opts.tab_width <= correct_indentation; i += opts.tab_width) str[j++] = '\t';
|
||||
for (; i < correct_indentation; ++i) str[j++] = ' ';
|
||||
}
|
||||
else{
|
||||
for (; j < correct_indentation; ++j) str[j] = ' ';
|
||||
}
|
||||
new_edit.len = j;
|
||||
new_edit.start = line_start;
|
||||
new_edit.end = hard_start.char_pos;
|
||||
edits[edit_count++] = new_edit;
|
||||
}
|
||||
|
||||
Assert(edit_count <= edit_max);
|
||||
}
|
||||
|
||||
Cpp_Token *result = tokens.tokens + get_token.token_index;
|
||||
result.str = str_base;
|
||||
result.str_len = str_size;
|
||||
|
||||
result.edits = edits;
|
||||
result.edit_count = edit_count;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
set_line_indents(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
int32_t line_start, int32_t line_end, int32_t *indent_marks, Indent_Options opts){
|
||||
Buffer_Batch_Edit batch =
|
||||
make_batch_from_indent_marks(app, part, buffer, line_start, line_end, indent_marks, opts);
|
||||
|
||||
if (batch.edit_count > 0){
|
||||
app->buffer_batch_edit(app, buffer, batch.str, batch.str_len,
|
||||
batch.edits, batch.edit_count, BatchEdit_PreserveTokens);
|
||||
}
|
||||
}
|
||||
|
||||
static Cpp_Token*
|
||||
seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token,
|
||||
Cpp_Token_Type open_type, Cpp_Token_Type close_type){
|
||||
|
@ -119,6 +167,91 @@ seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token,
|
|||
return(token);
|
||||
}
|
||||
|
||||
static Cpp_Token*
|
||||
find_anchor_token(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens,
|
||||
int32_t line_start, int32_t tab_width, int32_t *current_indent_out){
|
||||
Cpp_Token *token = get_first_token_at_line(app, buffer, tokens, line_start);
|
||||
|
||||
if (token != tokens.tokens){
|
||||
--token;
|
||||
for (; token > tokens.tokens; --token){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
switch(token->type){
|
||||
case CPP_TOKEN_BRACE_OPEN:
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
goto out_of_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
out_of_loop:;
|
||||
}
|
||||
|
||||
int32_t current_indent = 0;
|
||||
int32_t found_safe_start_position = 0;
|
||||
do{
|
||||
int32_t line = buffer_get_line_index(app, buffer, token->start);
|
||||
int32_t start = buffer_get_line_start(app, buffer, line);
|
||||
|
||||
Hard_Start_Result hard_start = buffer_find_hard_start(app, buffer, start, tab_width);
|
||||
current_indent = hard_start.indent_pos;
|
||||
|
||||
Cpp_Token *start_token = get_first_token_at_line(app, buffer, tokens, line);
|
||||
Cpp_Token *brace_token = token;
|
||||
|
||||
if (start_token->type == CPP_TOKEN_PARENTHESE_OPEN){
|
||||
if (start_token == tokens.tokens){
|
||||
found_safe_start_position = 1;
|
||||
}
|
||||
else{
|
||||
token = start_token-1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
int32_t close = 0;
|
||||
|
||||
for (token = brace_token; token > start_token; --token){
|
||||
switch(token->type){
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
case CPP_TOKEN_BRACKET_CLOSE:
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
close = token->type;
|
||||
goto out_of_loop2;
|
||||
}
|
||||
}
|
||||
out_of_loop2:;
|
||||
|
||||
switch (close){
|
||||
case 0: token = start_token; found_safe_start_position = 1; break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
token = seek_matching_token_backwards(tokens, token-1,
|
||||
CPP_TOKEN_PARENTHESE_OPEN,
|
||||
CPP_TOKEN_PARENTHESE_CLOSE);
|
||||
break;
|
||||
|
||||
case CPP_TOKEN_BRACKET_CLOSE:
|
||||
token = seek_matching_token_backwards(tokens, token-1,
|
||||
CPP_TOKEN_BRACKET_OPEN,
|
||||
CPP_TOKEN_BRACKET_CLOSE);
|
||||
break;
|
||||
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
token = seek_matching_token_backwards(tokens, token-1,
|
||||
CPP_TOKEN_BRACE_OPEN,
|
||||
CPP_TOKEN_BRACE_CLOSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(found_safe_start_position == 0);
|
||||
*current_indent_out = current_indent;
|
||||
|
||||
return(token);
|
||||
}
|
||||
|
||||
//
|
||||
// Indent Rules
|
||||
//
|
||||
|
||||
struct Indent_Parse_State{
|
||||
int32_t current_indent;
|
||||
int32_t previous_line_indent;
|
||||
|
@ -135,14 +268,7 @@ compute_this_indent(Application_Links *app, Buffer_Summary *buffer, Indent_Parse
|
|||
int32_t this_indent = 0;
|
||||
|
||||
int32_t this_line_start = buffer_get_line_start(app, buffer, line_i);
|
||||
int32_t next_line_start = 0;
|
||||
|
||||
if (line_i+1 < buffer->line_count){
|
||||
next_line_start = buffer_get_line_start(app, buffer, line_i+1);
|
||||
}
|
||||
else{
|
||||
next_line_start = buffer->size;
|
||||
}
|
||||
int32_t next_line_start = buffer_get_line_start(app, buffer, line_i+1);
|
||||
|
||||
bool32 did_special_behavior = false;
|
||||
|
||||
|
@ -215,134 +341,55 @@ compute_this_indent(Application_Links *app, Buffer_Summary *buffer, Indent_Parse
|
|||
}
|
||||
|
||||
static int32_t*
|
||||
get_line_indentation_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer, Cpp_Token_Array tokens,
|
||||
int32_t line_start, int32_t line_end, int32_t tab_width){
|
||||
get_indentation_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
Cpp_Token_Array tokens, int32_t line_start, int32_t line_end, int32_t tab_width){
|
||||
|
||||
int32_t indent_mark_count = line_end - line_start;
|
||||
int32_t *indent_marks = push_array(part, int32_t, indent_mark_count);
|
||||
|
||||
Indent_Parse_State indent = {0};
|
||||
Cpp_Token *token = get_first_token_at_line(app, buffer, tokens, line_start);
|
||||
|
||||
if (token != tokens.tokens){
|
||||
--token;
|
||||
for (; token > tokens.tokens; --token){
|
||||
if (!(token->flags & CPP_TFLAG_PP_BODY)){
|
||||
switch(token->type){
|
||||
case CPP_TOKEN_BRACE_OPEN:
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
goto out_of_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
out_of_loop:;
|
||||
}
|
||||
|
||||
// TODO(allen): This can maybe be it's own function now, so that we
|
||||
// can do the decls in the order we want and avoid the extra binary search.
|
||||
int32_t found_safe_start_position = 0;
|
||||
do{
|
||||
int32_t line = buffer_get_line_index(app, buffer, token->start);
|
||||
int32_t start = buffer_get_line_start(app, buffer, line);
|
||||
Hard_Start_Result hard_start = buffer_find_hard_start(app, buffer, start, tab_width);
|
||||
|
||||
indent.current_indent = hard_start.indent_pos;
|
||||
|
||||
Cpp_Token *start_token = get_first_token_at_line(app, buffer, tokens, line);
|
||||
Cpp_Token *brace_token = token;
|
||||
|
||||
if (start_token->type == CPP_TOKEN_PARENTHESE_OPEN){
|
||||
if (start_token == tokens.tokens){
|
||||
found_safe_start_position = 1;
|
||||
}
|
||||
else{
|
||||
token = start_token-1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
int32_t close = 0;
|
||||
|
||||
for (token = brace_token; token > start_token; --token){
|
||||
switch(token->type){
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
case CPP_TOKEN_BRACKET_CLOSE:
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
close = token->type;
|
||||
goto out_of_loop2;
|
||||
}
|
||||
}
|
||||
out_of_loop2:;
|
||||
|
||||
switch (close){
|
||||
case 0: token = start_token; found_safe_start_position = 1; break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
token = seek_matching_token_backwards(tokens, token-1,
|
||||
CPP_TOKEN_PARENTHESE_OPEN,
|
||||
CPP_TOKEN_PARENTHESE_CLOSE);
|
||||
break;
|
||||
|
||||
case CPP_TOKEN_BRACKET_CLOSE:
|
||||
token = seek_matching_token_backwards(tokens, token-1,
|
||||
CPP_TOKEN_BRACKET_OPEN,
|
||||
CPP_TOKEN_BRACKET_CLOSE);
|
||||
break;
|
||||
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
token = seek_matching_token_backwards(tokens, token-1,
|
||||
CPP_TOKEN_BRACE_OPEN,
|
||||
CPP_TOKEN_BRACE_CLOSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(found_safe_start_position == 0);
|
||||
|
||||
// NOTE(allen): Shift the array so that line_i can just operate in
|
||||
// it's natural value range.
|
||||
// Shift the array so line_i works correctly.
|
||||
indent_marks -= line_start;
|
||||
|
||||
int32_t line_i = buffer_get_line_index(app, buffer, token->start);
|
||||
|
||||
if (line_i > line_start){
|
||||
line_i = line_start;
|
||||
// Decide where to start indentation parsing.
|
||||
Indent_Parse_State indent = {0};
|
||||
Cpp_Token *token_ptr = find_anchor_token(app, buffer, tokens, line_start,
|
||||
tab_width, &indent.current_indent);
|
||||
|
||||
int32_t line_index = buffer_get_line_index(app, buffer, token_ptr->start);
|
||||
|
||||
if (line_index > line_start){
|
||||
line_index = line_start;
|
||||
}
|
||||
|
||||
int32_t next_line_start = buffer->size;
|
||||
if (line_i+1 < buffer->line_count){
|
||||
next_line_start = buffer_get_line_start(app, buffer, line_i+1);
|
||||
}
|
||||
int32_t next_line_start_pos = buffer_get_line_start(app, buffer, line_index+1);
|
||||
|
||||
switch (token->type){
|
||||
switch (token_ptr->type){
|
||||
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += tab_width; break;
|
||||
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += tab_width; break;
|
||||
case CPP_TOKEN_PARENTHESE_OPEN: indent.current_indent += tab_width; break;
|
||||
}
|
||||
|
||||
indent.previous_line_indent = indent.current_indent;
|
||||
Cpp_Token T;
|
||||
Cpp_Token prev_token = *token;
|
||||
++token;
|
||||
|
||||
for (; line_i < line_end; ++token){
|
||||
if (token < tokens.tokens + tokens.count){
|
||||
T = *token;
|
||||
for (;line_index < line_end;){
|
||||
Cpp_Token prev_token = *token_ptr;
|
||||
Cpp_Token token;
|
||||
|
||||
++token_ptr;
|
||||
if (token_ptr < tokens.tokens + tokens.count){
|
||||
token = *token_ptr;
|
||||
}
|
||||
else{
|
||||
T.type = CPP_TOKEN_EOF;
|
||||
T.start = buffer->size;
|
||||
T.flags = 0;
|
||||
token.type = CPP_TOKEN_EOF;
|
||||
token.start = buffer->size;
|
||||
token.flags = 0;
|
||||
}
|
||||
|
||||
for (; T.start >= next_line_start && line_i < line_end;){
|
||||
if (line_i+1 < buffer->line_count){
|
||||
next_line_start = buffer_get_line_start(app, buffer, line_i+1);
|
||||
}
|
||||
else{
|
||||
next_line_start = buffer->size;
|
||||
}
|
||||
for (;token.start >= next_line_start_pos && line_index < line_end;){
|
||||
next_line_start_pos = buffer_get_line_start(app, buffer, line_index+1);
|
||||
|
||||
int32_t this_indent =
|
||||
compute_this_indent(app, buffer, indent, T, prev_token, line_i, tab_width);
|
||||
compute_this_indent(app, buffer, indent, token, prev_token, line_index, tab_width);
|
||||
|
||||
// NOTE(allen): Rebase the paren anchor if the first token
|
||||
// after an open paren is on the next line.
|
||||
|
@ -356,15 +403,16 @@ get_line_indentation_marks(Application_Links *app, Partition *part, Buffer_Summa
|
|||
}
|
||||
}
|
||||
|
||||
if (line_i >= line_start){
|
||||
indent_marks[line_i] = this_indent;
|
||||
if (line_index >= line_start){
|
||||
indent_marks[line_index] = this_indent;
|
||||
}
|
||||
++line_i;
|
||||
++line_index;
|
||||
|
||||
indent.previous_line_indent = this_indent;
|
||||
}
|
||||
|
||||
switch (T.type){
|
||||
// Update indent state.
|
||||
switch (token.type){
|
||||
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += 4; break;
|
||||
case CPP_TOKEN_BRACKET_CLOSE: indent.current_indent -= 4; break;
|
||||
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += 4; break;
|
||||
|
@ -372,18 +420,18 @@ get_line_indentation_marks(Application_Links *app, Partition *part, Buffer_Summa
|
|||
|
||||
case CPP_TOKEN_COMMENT:
|
||||
{
|
||||
int32_t line = buffer_get_line_index(app, buffer, T.start);
|
||||
int32_t line = buffer_get_line_index(app, buffer, token.start);
|
||||
int32_t start = buffer_get_line_start(app, buffer, line);
|
||||
|
||||
indent.comment_shift = (indent.current_indent - (T.start - start));
|
||||
indent.comment_shift = (indent.current_indent - (token.start - start));
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
if (!(T.flags & CPP_TFLAG_PP_BODY)){
|
||||
if (!(token.flags & CPP_TFLAG_PP_BODY)){
|
||||
if (indent.paren_nesting < ArrayCount(indent.paren_anchor_indent)){
|
||||
int32_t line = buffer_get_line_index(app, buffer, T.start);
|
||||
int32_t line = buffer_get_line_index(app, buffer, token.start);
|
||||
int32_t start = buffer_get_line_start(app, buffer, line);
|
||||
int32_t char_pos = T.start - start;
|
||||
int32_t char_pos = token.start - start;
|
||||
|
||||
Hard_Start_Result hard_start =
|
||||
buffer_find_hard_start(app, buffer, start, tab_width);
|
||||
|
@ -398,126 +446,31 @@ get_line_indentation_marks(Application_Links *app, Partition *part, Buffer_Summa
|
|||
break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
if (!(T.flags & CPP_TFLAG_PP_BODY)){
|
||||
if (!(token.flags & CPP_TFLAG_PP_BODY)){
|
||||
--indent.paren_nesting;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prev_token = T;
|
||||
}
|
||||
|
||||
// NOTE(allen): Unshift the indent_marks array so that the return value
|
||||
// is the exact starting point of the array that was actually allocated.
|
||||
// Unshift the indent_marks array.
|
||||
indent_marks += line_start;
|
||||
|
||||
return(indent_marks);
|
||||
}
|
||||
|
||||
struct Make_Batch_Result{
|
||||
char *str_base;
|
||||
int32_t str_size;
|
||||
|
||||
Buffer_Edit *edits;
|
||||
int32_t edit_max;
|
||||
int32_t edit_count;
|
||||
};
|
||||
|
||||
static Make_Batch_Result
|
||||
make_batch_from_indent_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
int32_t line_start, int32_t line_end, int32_t *indent_marks, Indent_Options opts){
|
||||
|
||||
Make_Batch_Result result = {0};
|
||||
|
||||
int32_t edit_max = line_end - line_start;
|
||||
int32_t edit_count = 0;
|
||||
|
||||
Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
|
||||
|
||||
char *str_base = (char*)part->base + part->pos;
|
||||
int32_t str_size = 0;
|
||||
|
||||
// NOTE(allen): Shift the array so that line_i can just operate in
|
||||
// it's natural value range.
|
||||
indent_marks -= line_start;
|
||||
|
||||
for (int32_t line_i = line_start; line_i < line_end; ++line_i){
|
||||
int32_t line_start = buffer_get_line_start(app, buffer, line_i);
|
||||
Hard_Start_Result hard_start =
|
||||
buffer_find_hard_start(app, buffer, line_start, opts.tab_width);
|
||||
|
||||
int32_t correct_indentation = indent_marks[line_i];
|
||||
if (hard_start.all_whitespace && opts.empty_blank_lines) correct_indentation = 0;
|
||||
if (correct_indentation == -1) correct_indentation = hard_start.indent_pos;
|
||||
|
||||
// TODO(allen): Only replace spaces if we are using space based indentation.
|
||||
// TODO(allen): See if the first clause can just be removed because it's dumb.
|
||||
if ((hard_start.all_whitespace && hard_start.char_pos > line_start) ||
|
||||
!hard_start.all_space || correct_indentation != hard_start.indent_pos){
|
||||
|
||||
Buffer_Edit new_edit;
|
||||
new_edit.str_start = str_size;
|
||||
str_size += correct_indentation;
|
||||
char *str = push_array(part, char, correct_indentation);
|
||||
int32_t j = 0;
|
||||
if (opts.use_tabs){
|
||||
int32_t i = 0;
|
||||
for (; i + opts.tab_width <= correct_indentation; i += opts.tab_width) str[j++] = '\t';
|
||||
for (; i < correct_indentation; ++i) str[j++] = ' ';
|
||||
}
|
||||
else{
|
||||
for (; j < correct_indentation; ++j) str[j] = ' ';
|
||||
}
|
||||
new_edit.len = j;
|
||||
new_edit.start = line_start;
|
||||
new_edit.end = hard_start.char_pos;
|
||||
edits[edit_count++] = new_edit;
|
||||
}
|
||||
|
||||
Assert(edit_count <= edit_max);
|
||||
}
|
||||
|
||||
result.str_base = str_base;
|
||||
result.str_size = str_size;
|
||||
|
||||
result.edits = edits;
|
||||
result.edit_max = edit_max;
|
||||
result.edit_count = edit_count;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool32
|
||||
buffer_auto_indent(Application_Links *app, Partition *part, Buffer_Summary *buffer,
|
||||
int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags)/*
|
||||
DOC_PARAM(buffer, The buffer specifies the buffer in which to apply auto indentation.)
|
||||
DOC_PARAM(start, This parameter specifies the absolute position of the start of the indentation range.)
|
||||
DOC_PARAM(end, This parameter specifies the absolute position of the end of the indentation range.)
|
||||
DOC_PARAM(tab_width, The tab_width parameter specifies how many spaces should be used for one indentation in space mode.)
|
||||
DOC_PARAM(flags, This parameter specifies behaviors for the indentation.)
|
||||
DOC_RETURN(This call returns non-zero when the call succeeds.)
|
||||
|
||||
DOC(Applies the built in auto-indentation rule to the code in the range
|
||||
from start to end by inserting spaces or tabs at the beginning of the
|
||||
lines. If the buffer does not have lexing enabled or the lexing job has
|
||||
not completed this function will fail.)
|
||||
|
||||
DOC_SEE(Auto_Indent_Flag)
|
||||
DOC_SEE(4coder_Buffer_Positioning_System)
|
||||
*/{
|
||||
|
||||
Indent_Options opts = {0};
|
||||
int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags){
|
||||
|
||||
bool32 result = 0;
|
||||
if (buffer->exists && buffer->tokens_are_ready){
|
||||
result = 1;
|
||||
|
||||
opts.empty_blank_lines = (flags & AutoIndent_ClearLine);
|
||||
opts.use_tabs = (flags & AutoIndent_UseTab);
|
||||
opts.tab_width = tab_width;
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
// TODO(allen): Only read in the tokens in the range we need.
|
||||
// Stage 1: Setup
|
||||
// Read the tokens to be used for indentation.
|
||||
// Get the first and last lines to indent.
|
||||
Cpp_Token_Array tokens;
|
||||
tokens.count = app->buffer_token_count(app, buffer);
|
||||
tokens.max_count = tokens.count;
|
||||
|
@ -525,19 +478,21 @@ DOC_SEE(4coder_Buffer_Positioning_System)
|
|||
app->buffer_read_tokens(app, buffer, 0, tokens.count, tokens.tokens);
|
||||
|
||||
int32_t line_start = buffer_get_line_index(app, buffer, start);
|
||||
int32_t line_end = buffer_get_line_index(app, buffer, end);
|
||||
int32_t line_end = buffer_get_line_index(app, buffer, end) + 1;
|
||||
|
||||
// Stage 2: Decide Indent Amounts
|
||||
// Get an array representing how much each line in [line_start,line_end]
|
||||
// should be indented.
|
||||
int32_t *indent_marks =
|
||||
get_line_indentation_marks(app, part, buffer, tokens,
|
||||
line_start, line_end, opts.tab_width);
|
||||
get_indentation_marks(app, part, buffer, tokens, line_start, line_end, tab_width);
|
||||
|
||||
Make_Batch_Result batch =
|
||||
make_batch_from_indent_marks(app, part, buffer, line_start, line_end, indent_marks, opts);
|
||||
// Stage 3: Set the Line Indents
|
||||
Indent_Options opts = {0};
|
||||
opts.empty_blank_lines = (flags & AutoIndent_ClearLine);
|
||||
opts.use_tabs = (flags & AutoIndent_UseTab);
|
||||
opts.tab_width = tab_width;
|
||||
|
||||
if (batch.edit_count > 0){
|
||||
app->buffer_batch_edit(app, buffer, batch.str_base, batch.str_size,
|
||||
batch.edits, batch.edit_count, BatchEdit_PreserveTokens);
|
||||
}
|
||||
set_line_indents(app, part, buffer, line_start, line_end, indent_marks, opts);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
|
|
@ -547,6 +547,46 @@ buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Some Basic Buffer Positioning
|
||||
//
|
||||
|
||||
#include "4cpp_lexer.h"
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, int32_t line){
|
||||
Partial_Cursor partial_cursor;
|
||||
int32_t result = buffer->size;
|
||||
if (line < buffer->line_count){
|
||||
app->buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &partial_cursor);
|
||||
result = partial_cursor.pos;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
buffer_get_line_index(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
Partial_Cursor partial_cursor;
|
||||
app->buffer_compute_cursor(app, buffer, seek_pos(pos), &partial_cursor);
|
||||
return(partial_cursor.line);
|
||||
}
|
||||
|
||||
static Cpp_Token*
|
||||
get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line){
|
||||
int32_t line_start = buffer_get_line_start(app, buffer, line);
|
||||
Cpp_Get_Token_Result get_token = cpp_get_token(&tokens, line_start);
|
||||
|
||||
if (get_token.in_whitespace){
|
||||
get_token.token_index += 1;
|
||||
}
|
||||
|
||||
Cpp_Token *result = tokens.tokens + get_token.token_index;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Fundamental Editing
|
||||
//
|
||||
|
|
|
@ -123,15 +123,6 @@ ENUM(int32_t, Event_Message_Type_ID){
|
|||
EventMessage_CloseView
|
||||
};
|
||||
|
||||
/* DOC(A Buffer_Batch_Edit_Type is a type of batch operation.) */
|
||||
ENUM(int32_t, Buffer_Batch_Edit_Type){
|
||||
/* DOC(The BatchEdit_Normal operation is always correct but does the most work.) */
|
||||
BatchEdit_Normal,
|
||||
/* DOC(The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens.
|
||||
This usually applies when whitespace is being replaced with whitespace.) */
|
||||
BatchEdit_PreserveTokens
|
||||
};
|
||||
|
||||
/* DOC(A Buffer_Setting_ID names a setting in a buffer.) */
|
||||
ENUM(int32_t, Buffer_Setting_ID){
|
||||
/* DOC(BufferSetting_Null is not a valid setting, it is reserved to detect errors.) */
|
||||
|
@ -702,14 +693,41 @@ struct Event_Message{
|
|||
};
|
||||
|
||||
/*
|
||||
DOC(Theme_Color stores a style tag/color pair, for the purpose of setting and getting colors in the theme .)
|
||||
DOC(Theme_Color stores a style tag/color pair, for the purpose of setting and getting colors in the theme.)
|
||||
DOC_SEE(Style_Tag)
|
||||
DOC_SEE(int_color)
|
||||
*/
|
||||
struct Theme_Color{
|
||||
/* DOC(The style slot in the style palette.) */
|
||||
Style_Tag tag;
|
||||
/* DOC(The color in the slot.) */
|
||||
int_color color;
|
||||
};
|
||||
|
||||
/* DOC(A Buffer_Batch_Edit_Type is a type of batch operation.) */
|
||||
ENUM(int32_t, Buffer_Batch_Edit_Type){
|
||||
/* DOC(The BatchEdit_Normal operation is always correct but does the most work if there are tokens to correct.) */
|
||||
BatchEdit_Normal,
|
||||
/* DOC(The BatchEdit_PreserveTokens operation is one in which none of the edits add, delete, or change any tokens.
|
||||
This usually applies when whitespace is being replaced with whitespace.) */
|
||||
BatchEdit_PreserveTokens
|
||||
};
|
||||
|
||||
/*
|
||||
DOC(This struct is used to bundle the parameters of the buffer_batch_edit function. It is convenient
|
||||
for a few functions that return a batch edit to the user.)
|
||||
DOC_SEE(buffer_batch_edit)
|
||||
*/
|
||||
struct Buffer_Batch_Edit{
|
||||
/* DOC(The pointer to the edit string buffer.) */
|
||||
char *str;
|
||||
/* DOC(The length of the edit string buffer.) */
|
||||
int32_t str_len;
|
||||
|
||||
/* DOC(The array of edits to be applied.) */
|
||||
Buffer_Edit *edits;
|
||||
/* DOC(The number of edits in the array.) */
|
||||
int32_t edit_count;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1295,10 +1295,10 @@ in the system, the call will fail.)
|
|||
Assert(panel_ptr != panel);
|
||||
active = (i32)(panel_ptr - models->layout.panels);
|
||||
}
|
||||
Assert(active != -1 && panel != models->layout.panels + active);
|
||||
|
||||
// If the panel we're closing was previously active, we have to switch to it's sibling.
|
||||
if (models->layout.active_panel == (i32)(panel - models->layout.panels)){
|
||||
Assert(active != -1 && panel != models->layout.panels + active);
|
||||
models->layout.active_panel = active;
|
||||
}
|
||||
|
||||
|
|
|
@ -5123,26 +5123,6 @@ draw_file_bar(Render_Target *target, View *view, Editing_File *file, i32_Rect re
|
|||
append_ss(&bar_text, make_lit_string(" nix"));
|
||||
}
|
||||
|
||||
append_ss(&bar_text, make_lit_string(" -"));
|
||||
|
||||
Command_Map *map = view->map;
|
||||
if (map == &models->map_top){
|
||||
append_ss(&bar_text, make_lit_string(" global"));
|
||||
}
|
||||
else if (map == &models->map_file){
|
||||
append_ss(&bar_text, make_lit_string(" file"));
|
||||
}
|
||||
else if (map == &models->map_ui){
|
||||
append_ss(&bar_text, make_lit_string(" gui"));
|
||||
}
|
||||
else{
|
||||
i32 map_index = (i32)(view->map - models->user_maps);
|
||||
i32 map_id = models->map_id_table[map_index];
|
||||
|
||||
append_ss (&bar_text, make_lit_string(" user:"));
|
||||
append_int_to_str(&bar_text, map_id);
|
||||
}
|
||||
|
||||
intbar_draw_string(target, &bar, bar_text, base_color);
|
||||
|
||||
|
||||
|
|
24
TODO.txt
24
TODO.txt
|
@ -82,30 +82,32 @@
|
|||
|
||||
; BEFORE I SHIP
|
||||
;
|
||||
; [X] killing compilation panel changes active panel
|
||||
; [X] tokens in the custom API
|
||||
; [X] token seeking on custom side
|
||||
; [X] auto indent on the custom side
|
||||
; [] clean up and comment the auto indent code to allow for customizations
|
||||
; [] more built in options for auto indenting
|
||||
; [] expose dirty flags
|
||||
; [] option to not open *messages* every startup
|
||||
; [] commands for resizing panels
|
||||
; [] make panel resizing not whacky with child panels
|
||||
; [] killing compilation panel changes active panel
|
||||
; [] control over how mouse effects panel focus
|
||||
; [] API docs as text file
|
||||
; [] user file bar string
|
||||
; [] mouse down/up distinction
|
||||
; [] hook on exit
|
||||
; [] read only files
|
||||
; [] occasionally missing the (!) mark on files on windows
|
||||
; [] case insensitive interactive switch buffer
|
||||
; [] option to hide hidden files
|
||||
; [] tab to complete folder names in the new file dialogue
|
||||
; [] view fails to follow cursor when the view is shrunk
|
||||
; [] view fails to follow cursor after deleting long line
|
||||
; [] scroll down on compilation buffer durring compilation
|
||||
;
|
||||
;
|
||||
|
||||
; [] commands for resizing panels
|
||||
; [] user file bar string
|
||||
; [] option to not open *messages* every startup
|
||||
; [] API docs as text file
|
||||
; [] read only files
|
||||
; [] tab to complete folder names in the new file dialogue
|
||||
; [] option to hide hidden files
|
||||
; [] view fails to follow cursor when the view is shrunk
|
||||
; [] view fails to follow cursor after deleting long line
|
||||
; [] control over how mouse effects panel focus
|
||||
|
||||
; TODOS
|
||||
; [X] success message when compiler works
|
||||
|
|
Loading…
Reference in New Issue