Barret Gaylor
31 posts
I am a game designer who recently became interested in coding in a handmade way. I am not that experienced, but I want to learn.
Correct indents in python files
Edited by Barret Gaylor on Reason: Initial post
I'm trying to create a python mode for 4coder. I have already made the 4coder_language_py.h file, but now I just need to make 4coder do the line indentation correctly. I'm guessing this might have something to do with 4coder_auto_indent.cpp or 4coder_default_hooks.cpp, but I'm not fimilar enough with the customization layer to know for sure. Any help will be appreciated. Thank you.
Barret Gaylor
31 posts
I am a game designer who recently became interested in coding in a handmade way. I am not that experienced, but I want to learn.
Correct indents in python files
Ok, I think I figured it out.

here's the code I created:
https://github.com/Barret5Ocal/4coderPython

first I added the code for the parse context.

 1 2 3 4 5 6 7  if(match(ext, "py")){ if(parse_context_language_py == 0){ init_language_py(app); } parse_context_id = parse_context_language_py; python_yes = true; } 

I added the python_yes variable for the next bit of code.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 if(python_yes) // NOTE(allen): Decide buffer settings bool32 use_virtual_whitespace = false; bool32 use_lexer = false; bool32 wrap_lines = true; if (treat_as_todo){ lex_without_strings = true; wrap_lines = true; use_virtual_whitespace = true; use_lexer = true; } else if (treat_as_code){ wrap_lines = global_config.enable_code_wrapping; use_virtual_whitespace = global_config.enable_virtual_whitespace; use_lexer = true; } if (match(make_string(buffer.buffer_name, buffer.buffer_name_len), "*compilation*")){ wrap_lines = false; } if(python_yes) { use_virtual_whitespace = false; wrap_lines = false; } //if (buffer.size >= (192 << 10)){ if (buffer.size >= (128 << 10)){ wrap_lines = false; use_virtual_whitespace = false; } 

I don't know how to get 4coder to auto indent when you press enter if anyone knows how to do that it world be a great help.
Simon Anciaux
1194 posts
Correct indents in python files
I don't know if having auto indentation for python will be possible as I believe 4coder at the moment rely on the tokenizer for C like language (using {, }, (, ) ) to do the indentation.

Barret Gaylor
31 posts
I am a game designer who recently became interested in coding in a handmade way. I am not that experienced, but I want to learn.
Correct indents in python files
Dang. Well turning off virtual white space will be fine for now. It would be great if I could find a way to run the python code in the editor
Barret Gaylor
31 posts
I am a game designer who recently became interested in coding in a handmade way. I am not that experienced, but I want to learn.
Correct indents in python files
Actually this is way harder than I thought it was going to be. I order for this to work I'm going to have to get the auto indents to work for python.
Simon Anciaux
1194 posts
Correct indents in python files
Edited by Simon Anciaux on
Maybe you should try contacting Allen on twitter or the 4coder discord to know what would be the best way to handle python.

I don't know much about adding support for a new language in 4coder, but my guess would be that for python you'd better treat the file as plain text, add a function to highlight python keywords just by comparing text, and do a few simple indentation functions. For example when you press "enter" call write_and_indent_python that would look at the text line, search for "if", "for"... or other keyword that would increment or decrement the indentation. And probably having a function to increase / decrease the indentation of the selection. I know next to nothing about Python so I don't really know what's necessary.

To do text highlighting you could use something like this. Note that this is a simple text search so you probably want to modify it to be more robust :

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 typedef struct Highlight_Pair { String_Const_u8 needle; ARGB_Color color; } Highlight_Pair; function void draw_string_highlights( Application_Links *app, Buffer_ID buffer, Text_Layout_ID text_layout_id, Highlight_Pair *pairs, i32 pair_count ) { Range_i64 visible_range = text_layout_get_visible_range( app, text_layout_id ); Highlight_Pair* pair = pairs; for ( i32 i = 0; i < pair_count; i += 1, pair += 1 ) { if ( pair->needle.size <= 0 ) { continue; } i64 position = visible_range.min; seek_string_forward( app, buffer, position - 1, visible_range.max, pair->needle, &position ); while ( position < visible_range.max ) { Range_i64 range = Ii64_size( position, pair->needle.size ); paint_text_color( app, text_layout_id, range, pair->color ); seek_string_forward( app, buffer, position, visible_range.max, pair->needle, &position ); } } } /* In the render_buffer hook */ Highlight_Pair pairs[ ] = { string_u8_litexpr( "if " ), finalize_color( defcolor_keyword, 0 ), string_u8_litexpr( "for " ), finalize_color( defcolor_keyword, 0 ), string_u8_litexpr( "def " ), finalize_color( defcolor_keyword, 0 ), ... }; draw_string_highlights( app, buffer, text_layout_id, pairs, ArrayCount( pairs ) ); 
Barret Gaylor
31 posts
I am a game designer who recently became interested in coding in a handmade way. I am not that experienced, but I want to learn.
Correct indents in python files
Thanks for the help. Maybe you could make the auto indenter make an indent whenever the user presses enter on a line that ends with a ':'. Also, do you know how to get into the 4coder discord?
Simon Anciaux
1194 posts
Correct indents in python files
Edited by Simon Anciaux on Reason: typo
On http://4coder.net/ At the bottom of the page there is a link that reads "Handmade Network discord" which is actually the invite to the 4coder discord.

The problem with the python indentation (as I understand it, and I will say it again: I know next to nothing about Python) is that there is no rules to when the indentation should decrease a level. For example:
 1 2 3 if test: do_something() do_semithing_2() 

There is no rule saying that do_something_2 should not be indented, and if you change the indentation you change the flow of the program.

If I remember correctly the auto indentation in 4coder will run on the whole file when you save the file and some other actions, and that would not work with python. That's why I think you should treat python files as plain text and write some indentation function to help you, but that wouldn't be an auto indenter.

Here is an example of indenting a line after pressing enter. It will not work if treat_as_code is set as that would cause the C++ auto indenter to reindent (I think), and it assumes virtual whitespace is off. I believe that having another function bound to <shift + enter> that would create a new line with a decreased indentation level would be useful to "close a scope". It's not properly tested.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 CUSTOM_COMMAND_SIG( python_new_line_indent ) { View_ID view = get_active_view( app, 0 ); Buffer_ID buffer = view_get_buffer( app, view, 0 ); Scratch_Block scratch( app ); i64 line = get_line_number_from_pos( app, buffer, view_get_cursor_pos( app, view ) ); String_Const_u8 string = push_buffer_line( app, scratch, buffer, line ); i64 tab_count = 0; i64 space_count = 0; for ( umm i = 0; i < string.size; i++ ) { if ( string.str[ i ] == ' ' ) { space_count++; } else if ( string.str[ i ] == '\t' ) { tab_count++; } else { break; } } i64 indent_level = tab_count; indent_level += space_count / global_config.indent_width; indent_level += ( space_count % global_config.indent_width ) ? 1 : 0; i64 cursor = view_get_cursor_pos( app, view ); if ( cursor > 1 ) { u8 c = buffer_get_char( app, buffer, cursor - 1 ); if ( c == ':' ) { indent_level += 1; } } String_u8 insert = { 0 }; if ( global_config.indent_with_tabs ) { i64 size = 1 + indent_level; insert = string_u8_push( scratch, size ); string_append_character( &insert, '\n' ); for ( i64 i = 0; i < indent_level; i++ ) { string_append_character( &insert, '\t' ); } } else { i64 size = 1 + indent_level * global_config.indent_width; insert = string_u8_push( scratch, size ); string_append_character( &insert, '\n' ); for ( i64 i = 1; i < size; i++ ) { string_append_character( &insert, ' ' ); } } write_text( app, SCu8( insert.str, insert.size ) ); } 
Barret Gaylor
31 posts
I am a game designer who recently became interested in coding in a handmade way. I am not that experienced, but I want to learn.
Correct indents in python files
Sounds good. How would I implements this code in my 4coder? Sorry, I'm new to modding 4coder. Also, how do you turn on keyword highlighting on a plain text file?
Simon Anciaux
1194 posts
Correct indents in python files
Edited by Simon Anciaux on
I would like to reiterate that