properly implement until_end_of_word
parent
16fbbebb58
commit
6af75f364d
|
@ -152,19 +152,32 @@ iterate_file_buffer_until_reverse :: proc(it: ^FileBufferIter, until_proc: Until
|
||||||
for until_proc(it, iterate_file_buffer_reverse) {}
|
for until_proc(it, iterate_file_buffer_reverse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterate_peek :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> (character: u8, peek_it: FileBufferIter, cond: bool) {
|
||||||
|
peek_it = it^;
|
||||||
|
character, _, cond = iter_proc(&peek_it);
|
||||||
|
if !cond {
|
||||||
|
return character, peek_it, cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
character = get_character_at_iter(peek_it);
|
||||||
|
return character, peek_it, cond;
|
||||||
|
}
|
||||||
|
|
||||||
until_non_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
until_non_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
before_it := it^;
|
||||||
|
|
||||||
if character, _, cond := iter_proc(it); cond && strings.is_space(rune(character)) {
|
if character, _, cond := iter_proc(it); cond && strings.is_space(rune(character)) {
|
||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it^ = before_it;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
until_before_non_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
until_before_non_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
peek_it := it^;
|
if character, peek_it, cond := iterate_peek(it, iter_proc); cond && strings.is_space(rune(character)) {
|
||||||
if character, _, cond := iter_proc(&peek_it); cond && strings.is_space(rune(character)) {
|
|
||||||
it^ = peek_it;
|
it^ = peek_it;
|
||||||
return cond;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -173,11 +186,13 @@ until_before_non_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) ->
|
||||||
until_non_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
until_non_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
// TODO: make this global
|
// TODO: make this global
|
||||||
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
before_it := it^;
|
||||||
|
|
||||||
if character, _, cond := iter_proc(it); cond && strings.ascii_set_contains(set, character) {
|
if character, _, cond := iter_proc(it); cond && strings.ascii_set_contains(set, character) {
|
||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it^ = before_it;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,8 +200,7 @@ until_before_non_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) ->
|
||||||
// TODO: make this global
|
// TODO: make this global
|
||||||
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
peek_it := it^;
|
if character, peek_it, cond := iterate_peek(it, iter_proc); cond && strings.ascii_set_contains(set, character) {
|
||||||
if character, _, cond := iter_proc(&peek_it); cond && strings.ascii_set_contains(set, character) {
|
|
||||||
it^ = peek_it;
|
it^ = peek_it;
|
||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
@ -196,25 +210,53 @@ until_before_non_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) ->
|
||||||
|
|
||||||
until_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
until_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
before_it := it^;
|
||||||
|
|
||||||
if character, _, cond := iter_proc(it); cond && !strings.ascii_set_contains(set, character) {
|
if character, _, cond := iter_proc(it); cond && !strings.ascii_set_contains(set, character) {
|
||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it^ = before_it;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_before_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
|
if character, peek_it, cond := iterate_peek(it, iter_proc); cond && !strings.ascii_set_contains(set, character) {
|
||||||
|
it^ = peek_it;
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_before_alpha_num_or_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
|
if character, peek_it, cond := iterate_peek(it, iter_proc); cond && (!strings.ascii_set_contains(set, character) && !strings.is_space(rune(character))) {
|
||||||
|
it^ = peek_it;
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
until_start_of_word :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
until_start_of_word :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
// if not already on a word, iterate until non-whitespace
|
// if on a symbol go to next symbol or word
|
||||||
if character, _, cond := iter_proc(it); cond && (!strings.ascii_set_contains(set, character) && !strings.is_space(rune(character))) {
|
current_character := get_character_at_iter(it^);
|
||||||
for until_before_non_whitespace(it, iter_proc) {}
|
if !strings.ascii_set_contains(set, current_character) && !strings.is_space(rune(current_character)) {
|
||||||
|
_, _, cond := iter_proc(it);
|
||||||
|
if !cond { return false; }
|
||||||
|
|
||||||
|
for until_alpha_num(it, iter_proc) {}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for until_before_non_alpha_num(it, iter_proc) {}
|
for until_non_alpha_num(it, iter_proc) {}
|
||||||
for until_before_non_whitespace(it, iter_proc) {}
|
for until_non_whitespace(it, iter_proc) {}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -222,12 +264,41 @@ until_start_of_word :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
until_end_of_word :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
until_end_of_word :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
if character, _, cond := iter_proc(it); cond && !strings.ascii_set_contains(set, character) && !strings.is_space(rune(character)) {
|
current_character := get_character_at_iter(it^);
|
||||||
for until_before_non_whitespace(it, iter_proc) {}
|
if character, peek_it, cond := iterate_peek(it, iter_proc); strings.ascii_set_contains(set, current_character) {
|
||||||
return false;
|
// if current charater is a word
|
||||||
|
|
||||||
|
if strings.is_space(rune(character)) {
|
||||||
|
it^ = peek_it;
|
||||||
|
for until_non_whitespace(it, iter_proc) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.ascii_set_contains(set, character) {
|
||||||
|
// we are within a word
|
||||||
for until_before_non_alpha_num(it, iter_proc) {}
|
for until_before_non_alpha_num(it, iter_proc) {}
|
||||||
|
} else {
|
||||||
|
// we are at the start of a word
|
||||||
|
for until_before_alpha_num_or_whitespace(it, iter_proc) {}
|
||||||
|
}
|
||||||
|
} else if character, peek_it, cond := iterate_peek(it, iter_proc); !strings.ascii_set_contains(set, current_character) {
|
||||||
|
// if current charater is a symbol
|
||||||
|
|
||||||
|
if strings.is_space(rune(character)) {
|
||||||
|
it^ = peek_it;
|
||||||
|
for until_non_whitespace(it, iter_proc) {}
|
||||||
|
|
||||||
|
character = get_character_at_iter(it^);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.ascii_set_contains(set, character) {
|
||||||
|
// we are within a run of symbols
|
||||||
|
for until_before_alpha_num_or_whitespace(it, iter_proc) {}
|
||||||
|
} else {
|
||||||
|
// we are at the start of a run of symbols
|
||||||
|
for until_before_non_alpha_num(it, iter_proc) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,11 +453,9 @@ move_cursor_up :: proc(buffer: ^FileBuffer, amount: int = 1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.cursor = it.cursor;
|
buffer.cursor = it.cursor;
|
||||||
|
}
|
||||||
|
|
||||||
if buffer.cursor.line < buffer.top_line + 5 && buffer.cursor.line >= 4 {
|
update_file_buffer_scroll(buffer);
|
||||||
buffer.top_line = buffer.cursor.line - 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
move_cursor_down :: proc(buffer: ^FileBuffer, amount: int = 1) {
|
move_cursor_down :: proc(buffer: ^FileBuffer, amount: int = 1) {
|
||||||
|
@ -410,10 +479,7 @@ move_cursor_down :: proc(buffer: ^FileBuffer, amount: int = 1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.cursor = it.cursor;
|
buffer.cursor = it.cursor;
|
||||||
|
update_file_buffer_scroll(buffer);
|
||||||
if buffer.cursor.line > buffer.top_line + (buffer.glyph_buffer_height - 5) {
|
|
||||||
buffer.top_line = buffer.cursor.line - (buffer.glyph_buffer_height - 5);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
move_cursor_left :: proc(buffer: ^FileBuffer) {
|
move_cursor_left :: proc(buffer: ^FileBuffer) {
|
||||||
|
@ -440,7 +506,24 @@ move_cursor_forward_start_of_word :: proc(buffer: ^FileBuffer) {
|
||||||
update_file_buffer_scroll(buffer);
|
update_file_buffer_scroll(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
move_cursor_forward_end_of_word :: proc(buffer: ^FileBuffer) {
|
||||||
|
it := new_file_buffer_iter_with_cursor(buffer, buffer.cursor);
|
||||||
|
iterate_file_buffer_until(&it, until_end_of_word);
|
||||||
|
buffer.cursor = it.cursor;
|
||||||
|
|
||||||
|
update_file_buffer_scroll(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
move_cursor_backward_start_of_word :: proc(buffer: ^FileBuffer) {
|
move_cursor_backward_start_of_word :: proc(buffer: ^FileBuffer) {
|
||||||
|
it := new_file_buffer_iter_with_cursor(buffer, buffer.cursor);
|
||||||
|
iterate_file_buffer_until_reverse(&it, until_end_of_word);
|
||||||
|
//iterate_file_buffer_until(&it, until_non_whitespace);
|
||||||
|
buffer.cursor = it.cursor;
|
||||||
|
|
||||||
|
update_file_buffer_scroll(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
move_cursor_backward_end_of_word :: proc(buffer: ^FileBuffer) {
|
||||||
it := new_file_buffer_iter_with_cursor(buffer, buffer.cursor);
|
it := new_file_buffer_iter_with_cursor(buffer, buffer.cursor);
|
||||||
iterate_file_buffer_until_reverse(&it, until_start_of_word);
|
iterate_file_buffer_until_reverse(&it, until_start_of_word);
|
||||||
buffer.cursor = it.cursor;
|
buffer.cursor = it.cursor;
|
||||||
|
@ -602,10 +685,13 @@ is_keyword :: proc(start: FileBufferIter, end: FileBufferIter) -> (matches: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
keyword_index += 1;
|
keyword_index += 1;
|
||||||
if keyword_index >= len(keyword) && it == end {
|
if keyword_index >= len(keyword)-1 && it == end {
|
||||||
|
if get_character_at_iter(it) == keyword[keyword_index] {
|
||||||
matches = true;
|
matches = true;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if keyword_index >= len(keyword) {
|
} else if keyword_index >= len(keyword)-1 {
|
||||||
break;
|
break;
|
||||||
} else if it == end {
|
} else if it == end {
|
||||||
break;
|
break;
|
||||||
|
@ -706,20 +792,18 @@ color_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
|
|
||||||
iterate_file_buffer_until(&it, until_end_of_word);
|
iterate_file_buffer_until(&it, until_end_of_word);
|
||||||
|
|
||||||
end_of_word_it := it;
|
|
||||||
_, _, succ := iterate_file_buffer_reverse(&end_of_word_it);
|
|
||||||
if !succ { break; }
|
|
||||||
|
|
||||||
// TODO: color keywords
|
// TODO: color keywords
|
||||||
if is_keyword(start_it, it) {
|
if is_keyword(start_it, it) {
|
||||||
color_character(buffer, start_it.cursor, end_of_word_it.cursor, .Blue);
|
color_character(buffer, start_it.cursor, it.cursor, .Blue);
|
||||||
} else if character, _, cond := iterate_file_buffer(&it); cond {
|
} else if character, _, cond := iterate_peek(&it, iterate_file_buffer); cond {
|
||||||
if character == '(' {
|
if character == '(' {
|
||||||
color_character(buffer, start_it.cursor, end_of_word_it.cursor, .Green);
|
color_character(buffer, start_it.cursor, it.cursor, .Green);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterate_file_buffer(&it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -840,8 +924,8 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, fon
|
||||||
update_file_buffer_scroll :: proc(buffer: ^FileBuffer) {
|
update_file_buffer_scroll :: proc(buffer: ^FileBuffer) {
|
||||||
if buffer.cursor.line > (buffer.top_line + buffer.glyph_buffer_height - 5) {
|
if buffer.cursor.line > (buffer.top_line + buffer.glyph_buffer_height - 5) {
|
||||||
buffer.top_line = math.max(buffer.cursor.line - buffer.glyph_buffer_height + 5, 0);
|
buffer.top_line = math.max(buffer.cursor.line - buffer.glyph_buffer_height + 5, 0);
|
||||||
} else {
|
} else if buffer.cursor.line < (buffer.top_line + 5) {
|
||||||
// TODO: scroll buffer up
|
buffer.top_line = math.max(buffer.cursor.line - 5, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,10 @@ register_default_input_actions :: proc(input_map: ^core.InputMap) {
|
||||||
core.register_key_action(input_map, .W, proc(state: ^State) {
|
core.register_key_action(input_map, .W, proc(state: ^State) {
|
||||||
core.move_cursor_forward_start_of_word(&state.buffers[state.current_buffer]);
|
core.move_cursor_forward_start_of_word(&state.buffers[state.current_buffer]);
|
||||||
}, "move forward one word");
|
}, "move forward one word");
|
||||||
|
core.register_key_action(input_map, .E, proc(state: ^State) {
|
||||||
|
core.move_cursor_forward_end_of_word(&state.buffers[state.current_buffer]);
|
||||||
|
}, "move forward to end of word");
|
||||||
|
|
||||||
core.register_key_action(input_map, .B, proc(state: ^State) {
|
core.register_key_action(input_map, .B, proc(state: ^State) {
|
||||||
core.move_cursor_backward_start_of_word(&state.buffers[state.current_buffer]);
|
core.move_cursor_backward_start_of_word(&state.buffers[state.current_buffer]);
|
||||||
}, "move backward one word");
|
}, "move backward one word");
|
||||||
|
@ -155,6 +159,10 @@ register_default_input_actions :: proc(input_map: ^core.InputMap) {
|
||||||
core.register_key_action(input_map, .I, proc(state: ^State) {
|
core.register_key_action(input_map, .I, proc(state: ^State) {
|
||||||
state.mode = .Insert;
|
state.mode = .Insert;
|
||||||
}, "enter insert mode");
|
}, "enter insert mode");
|
||||||
|
core.register_key_action(input_map, .A, proc(state: ^State) {
|
||||||
|
core.move_cursor_right(&state.buffers[state.current_buffer]);
|
||||||
|
state.mode = .Insert;
|
||||||
|
}, "enter insert mode after character (append)");
|
||||||
|
|
||||||
core.register_key_action(input_map, .SPACE, core.new_input_map(), "leader commands");
|
core.register_key_action(input_map, .SPACE, core.new_input_map(), "leader commands");
|
||||||
register_default_leader_actions(&(&input_map.key_actions[.SPACE]).action.(core.InputMap));
|
register_default_leader_actions(&(&input_map.key_actions[.SPACE]).action.(core.InputMap));
|
||||||
|
@ -317,7 +325,7 @@ main :: proc() {
|
||||||
ui.draw_buffer_list_window(&state);
|
ui.draw_buffer_list_window(&state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.current_input_map != &state.input_map {
|
if true || state.current_input_map != &state.input_map {
|
||||||
longest_description := 0;
|
longest_description := 0;
|
||||||
for key, action in state.current_input_map.key_actions {
|
for key, action in state.current_input_map.key_actions {
|
||||||
if len(action.description) > longest_description {
|
if len(action.description) > longest_description {
|
||||||
|
|
Loading…
Reference in New Issue