Indent next line only on hitting enter

This commit is contained in:
PS 2024-02-10 20:12:36 -08:00
parent 5aebe18778
commit 24c8370f75
2 changed files with 112 additions and 10 deletions

View File

@ -437,14 +437,84 @@ CUSTOM_DOC("Auto-indents the range between the cursor and the mark.")
move_past_lead_whitespace(app, view, buffer); move_past_lead_whitespace(app, view, buffer);
} }
function i64
get_line_indent_level(Application_Links *app, View_ID view, Buffer_ID buffer, i64 line)
{
Scratch_Block scratch(app);
String_Const_u8 line_string = push_buffer_line(app, scratch, buffer, line);
i64 line_start_pos = get_line_start_pos(app, buffer, line);
Range_i64 line_indent_range = Ii64(0, 0);
i64 tabs_at_beginning = 0;
i64 spaces_at_beginning = 0;
for(u64 i = 0; i < line_string.size; i += 1)
{
if(line_string.str[i] == '\t')
{
tabs_at_beginning += 1;
}
else if(character_is_whitespace(line_string.str[i]))
{
spaces_at_beginning += 1;
}
else if(!character_is_whitespace(line_string.str[i]))
{
line_indent_range.max = (i64)i;
break;
}
}
// NOTE(PS): This is in the event that we are unindenting a line that
// is JUST tabs or spaces - rather than unindenting nothing
// and then reindenting the proper amount, this should cause
// the removal of all leading tabs and spaces on an otherwise
// empty line
bool place_cursor_at_end = false;
if (line_indent_range.max == 0 && line_string.size > 0)
{
line_indent_range.max = line_string.size;
place_cursor_at_end = true;
}
Range_i64 indent_range =
{
line_indent_range.min + line_start_pos,
line_indent_range.max + line_start_pos,
};
i64 indent_width = (i64)def_get_config_u64(app, vars_save_string_lit("indent_width"));
i64 spaces_per_indent_level = indent_width;
i64 indent_level = spaces_at_beginning / spaces_per_indent_level + tabs_at_beginning;
return indent_level;
}
function String_Const_u8
get_indent_string(Application_Links* app, Arena* scratch)
{
i64 indent_width = (i64)def_get_config_u64(app, vars_save_string_lit("indent_width"));
b32 indent_with_tabs = def_get_config_b32(vars_save_string_lit("indent_with_tabs"));
String_Const_u8 result;
if (indent_with_tabs) {
result = string_u8_litexpr("\t");
} else {
result = push_stringf(scratch, "%.*s", Min(indent_width, 16), " ");
}
return result;
}
CUSTOM_COMMAND_SIG(write_text_and_auto_indent) CUSTOM_COMMAND_SIG(write_text_and_auto_indent)
CUSTOM_DOC("Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.") CUSTOM_DOC("Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.")
{ {
ProfileScope(app, "write and auto indent"); ProfileScope(app, "write and auto indent");
Scratch_Block scratch(app);
User_Input in = get_current_input(app); User_Input in = get_current_input(app);
String_Const_u8 insert = to_writable(&in); String_Const_u8 insert = to_writable(&in);
if (insert.str != 0 && insert.size > 0){ if (insert.str != 0 && insert.size > 0){
b32 do_auto_indent = false; b32 do_auto_indent = false;
b32 only_indent_next_line = true;
b32 is_newline = false;
for (u64 i = 0; !do_auto_indent && i < insert.size; i += 1){ for (u64 i = 0; !do_auto_indent && i < insert.size; i += 1){
switch (insert.str[i]){ switch (insert.str[i]){
case ';': case ':': case ';': case ':':
@ -452,16 +522,30 @@ CUSTOM_DOC("Inserts text and auto-indents the line on which the cursor sits if a
case '(': case ')': case '(': case ')':
case '[': case ']': case '[': case ']':
case '#': case '#':
case '\n': case '\t':
{ {
do_auto_indent = true; do_auto_indent = true;
}break; }break;
case '\n': case '\t':
{
do_auto_indent = true;
is_newline = true;
}break;
} }
} }
if (do_auto_indent){
View_ID view = get_active_view(app, Access_ReadWriteVisible); View_ID view = get_active_view(app, Access_ReadWriteVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
String_Const_u8 file_name = push_buffer_file_name(app, scratch, buffer);
String_Const_u8 ext = string_file_extension(file_name);
if (string_match(ext, string_u8_litexpr("js")) ||
string_match(ext, string_u8_litexpr("css")))
{
only_indent_next_line = do_auto_indent;
}
if (do_auto_indent){
History_Group group = history_group_begin(app, buffer);
Range_i64 pos = {}; Range_i64 pos = {};
if (view_has_highlighted_range(app, view)){ if (view_has_highlighted_range(app, view)){
pos = get_view_range(app, view); pos = get_view_range(app, view);
@ -473,11 +557,29 @@ CUSTOM_DOC("Inserts text and auto-indents the line on which the cursor sits if a
write_text_input(app); write_text_input(app);
i64 end_pos = view_get_cursor_pos(app, view); i64 end_pos = view_get_cursor_pos(app, view);
if (!only_indent_next_line) {
pos.min = Min(pos.min, end_pos); pos.min = Min(pos.min, end_pos);
pos.max = Max(pos.max, end_pos); pos.max = Max(pos.max, end_pos);
auto_indent_buffer(app, buffer, pos, 0); auto_indent_buffer(app, buffer, pos, 0);
move_past_lead_whitespace(app, view, buffer); move_past_lead_whitespace(app, view, buffer);
} else if (only_indent_next_line && is_newline) {
String_Const_u8 indent_string = get_indent_string(app, scratch);
// getting the indent from the PREVIOUS line, not the line
// the cursor is about to be on - since that line is new,
// and therefore, empty
i64 line = get_line_number_from_pos(app, buffer, pos.min);
i64 indent_level = get_line_indent_level(app, view, buffer, line);
pos.min = pos.max = end_pos;
for(i64 i = 0; i < indent_level; i += 1)
{
buffer_replace_range(app, buffer, Ii64(pos.max), indent_string);
}
move_past_lead_whitespace(app, view, buffer);
}
history_group_end(group);
} }
else{ else{
write_text_input(app); write_text_input(app);

View File

@ -555,7 +555,7 @@ static Command_Metadata fcoder_metacmd_table[269] = {
{ PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "C:\\projects\\4coder_gs\\code\\custom\\4coder_combined_write_commands.cpp", 68, 82 }, { PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "C:\\projects\\4coder_gs\\code\\custom\\4coder_combined_write_commands.cpp", 68, 82 },
{ PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "C:\\projects\\4coder_gs\\code\\custom\\4coder_combined_write_commands.cpp", 68, 88 }, { PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "C:\\projects\\4coder_gs\\code\\custom\\4coder_combined_write_commands.cpp", 68, 88 },
{ PROC_LINKS(write_space, 0), false, "write_space", 11, "Inserts a space.", 16, "C:\\projects\\4coder_gs\\code\\custom\\4coder_base_commands.cpp", 58, 67 }, { PROC_LINKS(write_space, 0), false, "write_space", 11, "Inserts a space.", 16, "C:\\projects\\4coder_gs\\code\\custom\\4coder_base_commands.cpp", 58, 67 },
{ PROC_LINKS(write_text_and_auto_indent, 0), false, "write_text_and_auto_indent", 26, "Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.", 145, "C:\\projects\\4coder_gs\\code\\custom\\4coder_auto_indent.cpp", 56, 440 }, { PROC_LINKS(write_text_and_auto_indent, 0), false, "write_text_and_auto_indent", 26, "Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.", 145, "C:\\projects\\4coder_gs\\code\\custom\\4coder_auto_indent.cpp", 56, 507 },
{ PROC_LINKS(write_text_input, 0), false, "write_text_input", 16, "Inserts whatever text was used to trigger this command.", 55, "C:\\projects\\4coder_gs\\code\\custom\\4coder_base_commands.cpp", 58, 59 }, { PROC_LINKS(write_text_input, 0), false, "write_text_input", 16, "Inserts whatever text was used to trigger this command.", 55, "C:\\projects\\4coder_gs\\code\\custom\\4coder_base_commands.cpp", 58, 59 },
{ PROC_LINKS(write_todo, 0), false, "write_todo", 10, "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "C:\\projects\\4coder_gs\\code\\custom\\4coder_combined_write_commands.cpp", 68, 76 }, { PROC_LINKS(write_todo, 0), false, "write_todo", 10, "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "C:\\projects\\4coder_gs\\code\\custom\\4coder_combined_write_commands.cpp", 68, 76 },
{ PROC_LINKS(write_underscore, 0), false, "write_underscore", 16, "Inserts an underscore.", 22, "C:\\projects\\4coder_gs\\code\\custom\\4coder_base_commands.cpp", 58, 73 }, { PROC_LINKS(write_underscore, 0), false, "write_underscore", 16, "Inserts an underscore.", 22, "C:\\projects\\4coder_gs\\code\\custom\\4coder_base_commands.cpp", 58, 73 },