-
-
Save teryror/f07fb553a0a935e6c5a9cbd1a0add54c to your computer and use it in GitHub Desktop.
// ... | |
static int32_t* | |
get_indentation_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line_start, int32_t line_end, bool32 exact_align, 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); | |
// Shift the array so line_index works correctly. | |
indent_marks -= line_start; | |
// NOTE: TLD modifications begin here | |
bool tld_golang_indentation = false; | |
Parse_Context_ID parse_context_id = 0; | |
buffer_get_setting(app, buffer, BufferSetting_ParserContext, (int32_t *) &parse_context_id); | |
if (parse_context_id == tld_parse_context_language_golang) { | |
tld_golang_indentation = true; | |
} | |
// NOTE: TLD modifications end here | |
// 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); | |
if (token_ptr == 0){ | |
for (int32_t line_index = line_start; line_index < line_end; ++line_index){ | |
indent_marks[line_index] = 0; | |
} | |
} | |
else{ | |
int32_t line_number = buffer_get_line_number(app, buffer, token_ptr->start); | |
if (line_number > line_start){ | |
line_number = line_start; | |
} | |
if (token_ptr == tokens.tokens){ | |
indent.current_indent = 0; | |
} | |
int32_t next_line_start_pos = buffer_get_line_start(app, buffer, line_number); | |
indent.previous_line_indent = indent.current_indent; | |
Cpp_Token prev_token = {0}; | |
Cpp_Token token = {0}; | |
if (token_ptr < tokens.tokens + tokens.count){ | |
token = *token_ptr; | |
} | |
// Back up and consume this token too IF it is a scope opener. | |
if (token.type == CPP_TOKEN_BRACE_OPEN || token.type == CPP_TOKEN_BRACKET_OPEN){ | |
--token_ptr; | |
} | |
// LOOP OVER TOKENS | |
for (;;){ | |
if (line_number >= line_end){ | |
break; | |
} | |
prev_token = token; | |
++token_ptr; | |
if (token_ptr < tokens.tokens + tokens.count){ | |
token = *token_ptr; | |
} | |
else{ | |
token.type = CPP_TOKEN_EOF; | |
token.start = buffer->size; | |
token.flags = 0; | |
} | |
for (;token.start >= next_line_start_pos && line_number < line_end;){ | |
next_line_start_pos = buffer_get_line_start(app, buffer, line_number + 1); | |
int32_t this_indent = 0; | |
int32_t previous_indent = indent.previous_line_indent; | |
int32_t this_line_start = buffer_get_line_start(app, buffer, line_number); | |
int32_t next_line_start = next_line_start_pos; | |
bool32 did_multi_line_behavior = false; | |
// NOTE(allen): Check for multi-line tokens | |
if (prev_token.start <= this_line_start && prev_token.start + prev_token.size > this_line_start){ | |
if (prev_token.type == CPP_TOKEN_COMMENT || prev_token.type == CPP_TOKEN_STRING_CONSTANT){ | |
Hard_Start_Result hard_start = buffer_find_hard_start(app, buffer, this_line_start, tab_width); | |
if (exact_align){ | |
this_indent = indent.previous_comment_indent; | |
} | |
else{ | |
if (hard_start.all_whitespace){ | |
this_indent = previous_indent; | |
} | |
else{ | |
int32_t line_pos = hard_start.char_pos - this_line_start; | |
this_indent = line_pos + indent.comment_shift; | |
if (this_indent < 0){ | |
this_indent = 0; | |
} | |
} | |
} | |
if (!hard_start.all_whitespace){ | |
if (line_number >= line_start){ | |
indent.previous_comment_indent = this_indent; | |
} | |
else{ | |
indent.previous_comment_indent = hard_start.indent_pos; | |
} | |
} | |
did_multi_line_behavior = true; | |
} | |
} | |
if (!did_multi_line_behavior){ | |
this_indent = indent.current_indent; | |
if (token.start < next_line_start){ | |
if (token.flags & CPP_TFLAG_PP_DIRECTIVE){ | |
this_indent = 0; | |
} | |
else{ | |
switch (token.type){ | |
case CPP_TOKEN_BRACKET_CLOSE: this_indent -= tab_width; break; | |
case CPP_TOKEN_BRACE_CLOSE: this_indent -= tab_width; break; | |
case CPP_TOKEN_BRACE_OPEN: break; | |
default: | |
if (indent.current_indent > 0){ | |
bool32 statement_complete = false; | |
Cpp_Token *prev_usable_token_ptr = token_ptr - 1; | |
Cpp_Token prev_usable_token = {0}; | |
if (prev_usable_token_ptr >= tokens.tokens){ | |
prev_usable_token = *prev_usable_token_ptr; | |
} | |
// Scan backwards for the previous token that actually tells us about the statement. | |
bool32 has_prev_usable_token = true; | |
#define NotUsable(T) \ | |
(((T).flags&CPP_TFLAG_PP_BODY) || ((T).flags&CPP_TFLAG_PP_DIRECTIVE) || ((T).type == CPP_TOKEN_COMMENT)) | |
if (NotUsable(prev_usable_token)){ | |
has_prev_usable_token = false; | |
for (--prev_usable_token_ptr; | |
prev_usable_token_ptr >= tokens.tokens; | |
--prev_usable_token_ptr){ | |
prev_usable_token = *prev_usable_token_ptr; | |
if (!NotUsable(prev_usable_token)){ | |
has_prev_usable_token = true; | |
break; | |
} | |
} | |
} | |
#undef NotUsable | |
if (!has_prev_usable_token){ | |
statement_complete = true; | |
} | |
else{ | |
if (prev_usable_token.type == CPP_TOKEN_BRACKET_OPEN || | |
prev_usable_token.type == CPP_TOKEN_BRACE_OPEN || | |
prev_usable_token.type == CPP_TOKEN_BRACE_CLOSE || | |
prev_usable_token.type == CPP_TOKEN_SEMICOLON || | |
prev_usable_token.type == CPP_TOKEN_COLON || | |
prev_usable_token.type == CPP_TOKEN_COMMA || | |
(tld_golang_indentation && ( // NOTE: TLD modifications begin here | |
prev_usable_token.type == CPP_TOKEN_KEY_CONTROL_FLOW || | |
prev_usable_token.type == CPP_TOKEN_BOOLEAN_CONSTANT || | |
prev_usable_token.type == CPP_TOKEN_STRING_CONSTANT || | |
prev_usable_token.type == CPP_TOKEN_IDENTIFIER || | |
prev_usable_token.type == CPP_TOKEN_INTEGER_CONSTANT || | |
prev_usable_token.type == CPP_TOKEN_FLOATING_CONSTANT || | |
prev_usable_token.type == CPP_TOKEN_CHARACTER_CONSTANT || | |
prev_usable_token.type == CPP_TOKEN_PARENTHESE_CLOSE || | |
prev_usable_token.type == CPP_TOKEN_BRACKET_CLOSE))){ | |
// NOTE: TLD modification ends here | |
statement_complete = true; | |
} | |
} | |
if (!statement_complete){ | |
this_indent += tab_width; | |
} | |
} | |
} | |
} | |
} | |
if (this_indent < 0) this_indent = 0; | |
} | |
if (indent.paren_nesting > 0){ | |
if (prev_token.type != CPP_TOKEN_PARENTHESE_OPEN){ | |
int32_t level = indent.paren_nesting-1; | |
if (level >= ArrayCount(indent.paren_anchor_indent)){ | |
level = ArrayCount(indent.paren_anchor_indent)-1; | |
} | |
this_indent = indent.paren_anchor_indent[level]; | |
} | |
} | |
// Rebase the paren anchor if the first token | |
// after the open paren is on the next line. | |
if (indent.paren_nesting > 0){ | |
if (prev_token.type == CPP_TOKEN_PARENTHESE_OPEN){ | |
int32_t level = indent.paren_nesting-1; | |
if (level >= ArrayCount(indent.paren_anchor_indent)){ | |
level = ArrayCount(indent.paren_anchor_indent)-1; | |
} | |
indent.paren_anchor_indent[level] = this_indent; | |
} | |
} | |
if (line_number >= line_start){ | |
indent_marks[line_number] = this_indent; | |
} | |
++line_number; | |
indent.previous_line_indent = this_indent; | |
} | |
// Update indent state. | |
switch (token.type){ | |
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += tab_width; break; | |
case CPP_TOKEN_BRACKET_CLOSE: indent.current_indent -= tab_width; break; | |
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += tab_width; break; | |
case CPP_TOKEN_BRACE_CLOSE: indent.current_indent -= tab_width; break; | |
case CPP_TOKEN_COMMENT: | |
{ | |
int32_t line = buffer_get_line_number(app, buffer, token.start); | |
int32_t start = buffer_get_line_start(app, buffer, line); | |
indent.comment_shift = (indent.current_indent - (token.start - start)); | |
indent.previous_comment_indent = (token.start - start); | |
}break; | |
case CPP_TOKEN_PARENTHESE_OPEN: | |
{ | |
if (!(token.flags & CPP_TFLAG_PP_BODY)){ | |
if (indent.paren_nesting < ArrayCount(indent.paren_anchor_indent)){ | |
int32_t line = buffer_get_line_number(app, buffer, token.start); | |
int32_t start = buffer_get_line_start(app, buffer, line); | |
int32_t char_pos = token.start - start; | |
Hard_Start_Result hard_start = buffer_find_hard_start(app, buffer, start, tab_width); | |
int32_t line_pos = hard_start.char_pos - start; | |
indent.paren_anchor_indent[indent.paren_nesting] = char_pos - line_pos + indent.previous_line_indent + 1; | |
} | |
++indent.paren_nesting; | |
} | |
}break; | |
case CPP_TOKEN_PARENTHESE_CLOSE: | |
{ | |
if (!(token.flags & CPP_TFLAG_PP_BODY)){ | |
if (indent.paren_nesting > 0){ | |
--indent.paren_nesting; | |
} | |
} | |
}break; | |
} | |
} | |
} | |
// Unshift the indent_marks array. | |
indent_marks += line_start; | |
return(indent_marks); | |
} | |
// ... |
/****************************************************************************** | |
Author: Tristan Dannenberg | |
Notice: No warranty is offered or implied; use this code at your own risk. | |
******************************************************************************* | |
LICENSE | |
This software is dual-licensed to the public domain and under the following | |
license: you are granted a perpetual, irrevocable license to copy, modify, | |
publish, and distribute this file as you see fit. | |
******************************************************************************* | |
This file provides a parse context for golang syntax highlighting. | |
******************************************************************************/ | |
#if !defined(FTLD_LANGUAGE_GO_HPP) | |
#define FTLD_LANGUAGE_GO_HPP | |
static Parse_Context_ID tld_parse_context_language_golang; | |
#define PSAT(s, t) {s, sizeof(s)-1, t} | |
static void | |
tld_init_language_golang(Application_Links *app){ | |
if (tld_parse_context_language_golang != 0) return; | |
Parser_String_And_Type kw[] = { | |
PSAT("true", CPP_TOKEN_BOOLEAN_CONSTANT), | |
PSAT("false", CPP_TOKEN_BOOLEAN_CONSTANT), | |
// NOTE: Not a _boolean_ constant, obviously, but a keyword literal that | |
// should be highlighted and influence indentationo as such. | |
PSAT("nil", CPP_TOKEN_BOOLEAN_CONSTANT), | |
// NOTE: Some keywords can be statements in their own right. We'll designate | |
// those as CPP_TOKEN_KEY_CONTROL_FLOW, and all others as CPP_TOKEN_KEY_OTHER. | |
// | |
// This may not necessarily reflect their use in the language, but the indenter | |
// needs to be able to tell the two apart. | |
PSAT("continue", CPP_TOKEN_KEY_CONTROL_FLOW), | |
PSAT("break", CPP_TOKEN_KEY_CONTROL_FLOW), | |
PSAT("fallthrough", CPP_TOKEN_KEY_CONTROL_FLOW), | |
PSAT("return", CPP_TOKEN_KEY_CONTROL_FLOW), | |
PSAT("case", CPP_TOKEN_KEY_OTHER), | |
PSAT("chan", CPP_TOKEN_KEY_OTHER), | |
PSAT("const", CPP_TOKEN_KEY_OTHER), | |
PSAT("default", CPP_TOKEN_KEY_OTHER), | |
PSAT("defer", CPP_TOKEN_KEY_OTHER), | |
PSAT("else", CPP_TOKEN_KEY_OTHER), | |
PSAT("for", CPP_TOKEN_KEY_OTHER), | |
PSAT("func", CPP_TOKEN_KEY_OTHER), | |
PSAT("go", CPP_TOKEN_KEY_OTHER), | |
PSAT("goto", CPP_TOKEN_KEY_OTHER), | |
PSAT("if", CPP_TOKEN_KEY_OTHER), | |
PSAT("import", CPP_TOKEN_KEY_OTHER), | |
PSAT("interface", CPP_TOKEN_KEY_OTHER), | |
PSAT("map", CPP_TOKEN_KEY_OTHER), | |
PSAT("package", CPP_TOKEN_KEY_OTHER), | |
PSAT("range", CPP_TOKEN_KEY_OTHER), | |
PSAT("select", CPP_TOKEN_KEY_OTHER), | |
PSAT("struct", CPP_TOKEN_KEY_OTHER), | |
PSAT("switch", CPP_TOKEN_KEY_OTHER), | |
PSAT("type", CPP_TOKEN_KEY_OTHER), | |
PSAT("var", CPP_TOKEN_KEY_OTHER), | |
}; | |
tld_parse_context_language_golang = create_parse_context(app, kw, ArrayCount(kw), 0, 0); | |
} | |
#undef PSAT | |
#endif |
@ClaudioBarros I wonder if you have managed to implement it? I have 4coder 4.0.30 and so far I've figured that 4tld_language_go.h indeed belongs in the languages folder, and that it should be included in 4coder_default_hooks.cpp with the other languages' headers, and the function tld_init_language_golang called and parse_context_id set in the default_file_settings hook, like so:
if (match(ext, "go")){
if (tld_parse_context_language_golang == 0){
tld_init_language_golang(app);
}
parse_context_id = tld_parse_context_language_golang;
}
.go has to be included in treat_as_code in your config.4coder for that to work.
I think you should also copy the "TLD" notes in this gist's 4coder_auto_indent.cpp to the get_indentation_marks function in your own 4coder_auto_indent.cpp but that doesn't work because tld_parse_context_language_golang is not available in that scope. I'm guessing that it has something to do with the fact that this code is 2 years old.
I'm having trouble implementing this, and I was hoping you could provide me with some guidance.
Does this work with 4coder's latest version?
Do I have to replace the 4coder_auto_indent.cpp file with the one provided here, or do I simply add the given code to the end of the original file?
I guess the 4ltd_language_go.h should just be copied over to the 4coder 'languages' directory, right?
And then I would just run the buildsuper script and it should now support golang?
Thanks in advance, have a nice day!