-
-
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!