working on removing open_hook from view_set_file

This commit is contained in:
Allen Webster 2016-05-13 15:15:38 -04:00
parent db058ea6d7
commit a690547aa2
9 changed files with 380 additions and 51 deletions

View File

@ -357,6 +357,7 @@ struct Application_Links;
#define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_index)
#define GET_BUFFER_BY_NAME(n) Buffer_Summary n(Application_Links *app, char *filename, int len)
// TODO(allen): Need more flexible seek system somehow. Regex? Just expose the text stream to the user?
#define BUFFER_SEEK_DELIMITER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
#define BUFFER_SEEK_STRING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
#define BUFFER_SEEK_STRING_INSENSITIVE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)

View File

@ -40,6 +40,7 @@ struct Models{
u32 command_coroutine_flags[2];
Hook_Function *hooks[hook_type_count];
Application_Links *app;
i32 *buffer_param_indices;
i32 buffer_param_count, buffer_param_max;

BIN
4ed_data.ctm Normal file

Binary file not shown.

View File

@ -576,6 +576,9 @@ file_create_from_string(System_Functions *system, Models *models,
file->state.undo.history_head_block = 0;
file->state.undo.current_block_normal = 1;
}
Hook_Function *open_hook = models->hooks[hook_open_file];
open_hook(models->app);
}
internal b32
@ -1283,9 +1286,8 @@ view_set_file(
view->reinit_scrolling = 1;
}
}
// TODO(allen): Bypass all this nonsense, it's a hack! Hooks need parameters!
// Just accept it and pass the file to the open hook when it is loaded.
#if 0
if (file){
if (open_hook && file->settings.is_initialized == 0){
models->buffer_param_indices[models->buffer_param_count++] = file->id.id;
@ -1294,13 +1296,6 @@ view_set_file(
file->settings.is_initialized = 1;
}
}
#if 0
if (set_vui){
// TODO(allen): Fix this! There should be a way to easily separate setting a file,
// and switching to file mode, so that they don't cross over eachother like this.
view->showing_ui = VUI_None;
}
#endif
}

View File

@ -1,4 +1,4 @@
Distribution Date: 12.5.2016 (dd.mm.yyyy)
Distribution Date: 13.5.2016 (dd.mm.yyyy)
Thank you for contributing to the 4coder project!

View File

@ -1,4 +1,4 @@
Distribution Date: 12.5.2016 (dd.mm.yyyy)
Distribution Date: 13.5.2016 (dd.mm.yyyy)
Thank you for contributing to the 4coder project!

View File

@ -1,29 +1,42 @@
@echo off
call "ctime" -begin 4ed_data.ctm
set OPTS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /wd4390 /WX
set OPTS=%OPTS% /GR- /EHa- /nologo /FC
set INCLUDES=/I..\foreign
set LIBS=user32.lib winmm.lib gdi32.lib opengl32.lib
set ICON=..\res\icon.res
set DEFINES=
set FirstError=0
pushd ..\meta
cl %OPTS% ..\code\4ed_metagen.cpp /Femetagen
if %ERRORLEVEL% neq 0 (set FirstError=1)
popd
pushd ..\code
"..\meta\metagen"
if %ERRORLEVEL% neq 0 (set FirstError=1)
popd
pushd ..\build
REM call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp
call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp
call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp
REM call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp
REM call "..\code\buildsuper.bat" ..\code\power\4coder_casey.cpp
if %ERRORLEVEL% neq 0 (set FirstError=1)
set EXPORTS=/EXPORT:app_get_functions
cl %OPTS% %INCLUDES% %DEFINES% ..\code\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS%
if %ERRORLEVEL% neq 0 (set FirstError=1)
cl %OPTS% %INCLUDES% %DEFINES% ..\code\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed
if %ERRORLEVEL% neq 0 (set FirstError=1)
popd
call "ctime" -end 4ed_data.ctm %FirstError%

View File

@ -14,6 +14,13 @@
/* TODO(casey): Here are our current issues
- High priority:
- Buffer switching still seems a little bit broken. I find I can't reliably hit switch-return
and switch to the most recently viewed file that wasn't one of the two currently viewed buffers?
But maybe I'm imagining things?
- High-DPI settings break rendering and all fonts just show up as solid squares
- Pretty sure auto-indent has some bugs. Things that should be pretty easy to indent
properly even from only a few surrounding lines seem to be indented improperly at the moment
- Multi-line comments should default to indenting to the indentation of the line prior?
- Would like the option to indent to hanging parentheses, equals signs, etc. instead of
always just "one tab in from the previous line".
- Actually, maybe just expose the dirty state, so that the user can decide whether to
@ -24,18 +31,29 @@
- Auto-complete doesn't pick nearby words first, it seems, which makes it much slower to use?
- Bug with not being able to switch-to-corresponding-file in another buffer
without accidentally bringing up the file open dialog?
- Up/down arrows and mouse clicks on wrapped lines don't seem to work properly with several wraps.
(eg., a line wrapped to more than 2 physical lines on the screen often doesn't work anymore,
with up or down jumping to totally wrong places, and mouse clicking jumping to wrong places
as well - similarly, scrolling breaks, in that it thinks it has "hit the end" of the buffer
when you cursor down, but the cursor and the rest of the wrapped lines are actually off
the bottom of the screen)
- Display:
- There are often repaint bugs with 4coder coming to the front / unminimizing, etc.
I think this might have something to do with the way you're doing lots of semaphore
locking but I haven't investigated yet.
- Need a word-wrap mode that wraps at word boundaries instead of characters
- Need to be able to set a word wrap length at something other than the window
?FIXED First go-to-line for a file seems to still just go to the beginning of the buffer?
Not sure Allen's right about the slash problem, but either way, we need some
way to fix it.
- Need a way of highlighting the current line like Emacs does for the benefit
of people on The Stream(TM)
- NOTE / IMPORTANT / TODO highlighting? Ability to customize? Whatever.
- Some kind of parentheses highlighting? I can write this myself, but I
would need some way of adding highlight information to the buffer.
- Need a way of highlighting the current line like Emacs does for the benefit
of people on The Stream(TM)
- Some kind of matching brace display so in long ifs, etc., you can see
what they match (maybe draw it directly into the buffer?)
- Indentation:
- Multiple // lines don't seem to indent properly. The first one will go to the correct place, but the subsequent ones will go to the first column regardless?
@ -44,28 +62,44 @@
the same margin as the prev. line (4coder just goes back to column 1). It'd
be nice if it go _better_ than Emacs, with no need to manually flow comments,
etc.
- Up/down arrows and mouse clicks on wrapped lines don't seem to work properly after the second wrap
(eg., a line wrapped to more than 2 physical lines on the screen.)
- Buffer management:
- Switch-to-buffer with no typing, just return, should switch to the most recently
used buffer that is not currently displayed in a view.
?FIXED Kill-buffer should perform this switch automatically, or it should be easy
to build a custom kill buffer that does
- Seems like there's no way to switch to buffers whose names are substrings of other
buffers' names without using the mouse?
- Also, mouse-clicking on buffers doesn't seem to work reliably? Often it just goes to a
blank window?
- File system
- When switching to a buffer that has changed on disk, notify? Really this can just
be some way to query the modification flag and then the customization layer can do it?
- Still can't seem to open a zero-length file?
- I'd prefer it if file-open could create new files, and that I could get called on that
so I can insert my boilerplate headers on new files
- I'd prefer it if file-open deleted per-character instead of deleting entire path sections
- Need auto-complete for things like "arbitrary command", with options listed, etc.,
so this should either be built into 4ed, or the custom DLL should have the ability
to display possible completions and iterate over internal cmdid's, etc. Possibly
the latter, for maximal ability of customizers to add their own commands?
- Default directory for file open / build search should be that of the current
buffer, not tracked separately? Probably I should code this on my own.
- Macro recording/playback
- Arbitrary cool features:
- LOC count for the buffer and for all buffers summed shown in the title bar?
- Show auto-parsed #if/if/for/while/etc. statements at else and closing places.
- Automatic highlighting of the region in side the parentheses / etc.
- You should just implement a shell inside 4coder which can call all the 4coder
stuff as well as execute system stuff, so that from now on you just write
scripts "in 4coder", etc., so they are always portable everywhere 4coder runs?
- Things I should write:
- Ability to do "file open from same directory as the current buffer"
- Spell-checker
- To-do list dependent on project?
- Repeat last replace?
- Maybe search could be a permanent thing, so instead of initiating a search,
you're just _changing_ the search term with MODAL-S, and then there's _always_
a next-of-these-in... and that could go through buffers in order, to...
*/
// NOTE(casey): Microsoft/Windows is poopsauce.
@ -73,10 +107,10 @@
#include <math.h>
#include <stdio.h>
#include "..\4coder_default_includes.cpp"
#include "..\4coder_default_include.cpp"
enum maps{
my_code_map
my_code_map
};
#ifndef Assert
@ -90,6 +124,7 @@ struct Parsed_Error
String target_file_name;
int target_line_number;
int target_column_number;
int source_buffer_id;
int source_position;
@ -114,6 +149,7 @@ enum token_type
Token_Percent,
Token_Colon,
Token_Number,
Token_Comma,
Token_EndOfStream,
};
@ -231,6 +267,7 @@ GetToken(tokenizer *Tokenizer)
case '/': {Token.Type = Token_ForwardSlash;} break;
case '%': {Token.Type = Token_Percent;} break;
case ':': {Token.Type = Token_Colon;} break;
case ',': {Token.Type = Token_Comma;} break;
default:
{
@ -380,6 +417,7 @@ CUSTOM_COMMAND_SIG(casey_kill_to_end_of_line)
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
app->buffer_replace_range(app, &buffer, range.min, range.max, 0, 0);
exec_command(app, auto_tab_line_at_cursor);
}
CUSTOM_COMMAND_SIG(casey_paste_and_tab)
@ -396,6 +434,12 @@ CUSTOM_COMMAND_SIG(casey_seek_beginning_of_line_and_tab)
exec_command(app, auto_tab_line_at_cursor);
}
CUSTOM_COMMAND_SIG(casey_seek_beginning_of_line)
{
exec_command(app, auto_tab_line_at_cursor);
exec_command(app, cmdid_seek_beginning_of_line);
}
struct switch_to_result
{
bool Switched;
@ -621,7 +665,7 @@ casey_goto_error(Application_Links *app, Parsed_Error e)
switch_to_result Switch = SwitchToOrLoadFile(app, e.target_file_name, false);
if(Switch.Switched)
{
app->view_set_cursor(app, &Switch.view, seek_line_char(e.target_line_number, 0), 1);
app->view_set_cursor(app, &Switch.view, seek_line_char(e.target_line_number, e.target_column_number), 1);
}
View_Summary compilation_view = get_first_view_with_buffer(app, e.source_buffer_id);
@ -667,6 +711,18 @@ casey_parse_error(Application_Links *app, Buffer_Summary buffer, View_Summary vi
if(LineToken.Type == Token_Number)
{
token CloseToken = GetToken(&Tokenizer);
int column_number = 0;
if(CloseToken.Type == Token_Comma)
{
token ColumnToken = GetToken(&Tokenizer);
if(ColumnToken.Type == Token_Number)
{
column_number = atoi(ColumnToken.Text);
CloseToken = GetToken(&Tokenizer);
}
}
if(CloseToken.Type == Token_CloseParen)
{
token ColonToken = GetToken(&Tokenizer);
@ -693,6 +749,7 @@ casey_parse_error(Application_Links *app, Buffer_Summary buffer, View_Summary vi
result.exists = true;
result.target_file_name = make_string(Seek, (int)(Token.Text - Seek));;
result.target_line_number = line_number;
result.target_column_number = column_number;
result.source_buffer_id = buffer.buffer_id;
result.source_position = start + (int)(ColonToken.Text - ParsingRegion);
@ -1066,7 +1123,8 @@ CUSTOM_COMMAND_SIG(casey_execute_arbitrary_command)
internal void
UpdateModalIndicator(Application_Links *app)
{
Theme_Color normal_colors[] = {
Theme_Color normal_colors[] =
{
{Stag_Cursor, 0x40FF40},
{Stag_At_Cursor, 0x161616},
{Stag_Mark, 0x808080},
@ -1076,7 +1134,8 @@ UpdateModalIndicator(Application_Links *app)
{Stag_Bar, 0xCACACA}
};
Theme_Color edit_colors[] = {
Theme_Color edit_colors[] =
{
{Stag_Cursor, 0xFF0000},
{Stag_At_Cursor, 0x00FFFF},
{Stag_Mark, 0xFF6F1A},
@ -1137,22 +1196,22 @@ DEFINE_MODAL_KEY(modal_forward_slash, cmdid_change_active_panel);
DEFINE_MODAL_KEY(modal_semicolon, cmdid_cursor_mark_swap); // TODO(casey): Maybe cmdid_history_backward?
DEFINE_BIMODAL_KEY(modal_open_bracket, casey_begin_keyboard_macro_recording, write_and_auto_tab);
DEFINE_BIMODAL_KEY(modal_close_bracket, casey_end_keyboard_macro_recording, write_and_auto_tab);
DEFINE_MODAL_KEY(modal_a, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_a, cmdid_write_character); // TODO(casey): Arbitrary command + casey_quick_calc
DEFINE_MODAL_KEY(modal_b, cmdid_interactive_switch_buffer);
DEFINE_MODAL_KEY(modal_c, casey_find_corresponding_file);
DEFINE_MODAL_KEY(modal_d, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_d, casey_kill_to_end_of_line);
DEFINE_MODAL_KEY(modal_e, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_f, casey_paste_and_tab);
DEFINE_MODAL_KEY(modal_g, goto_line);
DEFINE_MODAL_KEY(modal_h, cmdid_auto_tab_range);
DEFINE_MODAL_KEY(modal_i, cmdid_redo);
DEFINE_MODAL_KEY(modal_j, casey_imenu);
DEFINE_MODAL_KEY(modal_k, casey_kill_to_end_of_line);
DEFINE_MODAL_KEY(modal_l, replace_in_range);
DEFINE_MODAL_KEY(modal_i, cmdid_move_up);
DEFINE_MODAL_KEY(modal_j, seek_white_or_token_left);
DEFINE_MODAL_KEY(modal_k, cmdid_move_down);
DEFINE_MODAL_KEY(modal_l, seek_white_or_token_right);
DEFINE_MODAL_KEY(modal_m, casey_save_and_make_without_asking);
DEFINE_MODAL_KEY(modal_n, casey_goto_next_error);
DEFINE_MODAL_KEY(modal_o, query_replace);
DEFINE_MODAL_KEY(modal_p, casey_quick_calc);
DEFINE_MODAL_KEY(modal_p, replace_in_range);
DEFINE_MODAL_KEY(modal_q, cmdid_copy);
DEFINE_MODAL_KEY(modal_r, reverse_search); // NOTE(allen): I've modified my default search so you can use it now.
DEFINE_MODAL_KEY(modal_s, search);
@ -1161,7 +1220,7 @@ DEFINE_MODAL_KEY(modal_u, cmdid_undo);
DEFINE_MODAL_KEY(modal_v, casey_switch_buffer_other_window);
DEFINE_MODAL_KEY(modal_w, cmdid_cut);
DEFINE_MODAL_KEY(modal_x, casey_find_corresponding_file_other_window);
DEFINE_MODAL_KEY(modal_y, auto_tab_line_at_cursor);
DEFINE_MODAL_KEY(modal_y, cmdid_redo);
DEFINE_MODAL_KEY(modal_z, cmdid_interactive_open);
DEFINE_MODAL_KEY(modal_1, casey_build_search); // TODO(casey): Shouldn't need to bind a key for this?
@ -1183,7 +1242,7 @@ DEFINE_BIMODAL_KEY(modal_down, cmdid_move_down, cmdid_move_down);
DEFINE_BIMODAL_KEY(modal_left, seek_white_or_token_left, cmdid_move_left);
DEFINE_BIMODAL_KEY(modal_right, seek_white_or_token_right, cmdid_move_right);
DEFINE_BIMODAL_KEY(modal_delete, casey_delete_token_right, cmdid_delete);
DEFINE_BIMODAL_KEY(modal_home, cmdid_seek_beginning_of_line, casey_seek_beginning_of_line_and_tab);
DEFINE_BIMODAL_KEY(modal_home, casey_seek_beginning_of_line, casey_seek_beginning_of_line_and_tab);
DEFINE_BIMODAL_KEY(modal_end, cmdid_seek_end_of_line, cmdid_seek_end_of_line);
DEFINE_BIMODAL_KEY(modal_page_up, cmdid_page_up, cmdid_seek_whitespace_up);
DEFINE_BIMODAL_KEY(modal_page_down, cmdid_page_down, cmdid_seek_whitespace_down);
@ -1365,14 +1424,50 @@ HOOK_SIG(casey_start)
app->change_theme(app, literal("Handmade Hero"));
app->change_font(app, literal("liberation mono"));
Theme_Color colors[] =
{
{Stag_Default, 0xA08563},
// {Stag_Bar, },
// {Stag_Bar_Active, },
// {Stag_Base, },
// {Stag_Pop1, },
// {Stag_Pop2, },
// {Stag_Back, },
// {Stag_Margin, },
// {Stag_Margin_Hover, },
// {Stag_Margin_Active, },
// {Stag_Cursor, },
// {Stag_At_Cursor, },
// {Stag_Highlight, },
// {Stag_At_Highlight, },
{Stag_Comment, 0x7D7D7D},
{Stag_Keyword, 0xCD950C},
// {Stag_Str_Constant, },
// {Stag_Char_Constant, },
// {Stag_Int_Constant, },
// {Stag_Float_Constant, },
// {Stag_Bool_Constant, },
{Stag_Preproc, 0xDAB98F},
{Stag_Include, 0x6B8E23},
// {Stag_Special_Character, },
// {Stag_Highlight_Junk, },
// {Stag_Highlight_White, },
// {Stag_Paste, },
// {Stag_Undo, },
// {Stag_Next_Undo, },
};
app->set_theme_colors(app, colors, ArrayCount(colors));
win32_toggle_fullscreen();
return(0);
}
void
get_bindings(Bind_Helper *context)
extern "C" GET_BINDING_DATA(get_bindings)
{
Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual;
set_hook(context, hook_start, casey_start);
set_hook(context, hook_open_file, casey_file_settings);
set_scroll_rule(context, casey_smooth_scroll_rule);
@ -1388,18 +1483,12 @@ get_bindings(Bind_Helper *context)
bind(context, 'b', MDFR_NONE, cmdid_interactive_switch_buffer);
bind(context, key_page_up, MDFR_NONE, search);
bind(context, key_page_down, MDFR_NONE, reverse_search);
// NOTE(allen): I added this here myself, I believe this is what you want.
bind(context, 'm', MDFR_NONE, casey_save_and_make_without_asking);
}
end_map(context);
begin_map(context, mapid_file);
// NOTE(allen): This is a new concept in the API. Binding this can be thought of as binding
// all combos which have an ascii code (shifted or not) and unmodified by CTRL or ALT.
// As of now, if this is used it cannot be overriden for particular combos; this overrides
// normal bindings.
bind_vanilla_keys(context, cmdid_write_character);
bind(context, key_insert, MDFR_NONE, begin_free_typing);
@ -1496,4 +1585,8 @@ get_bindings(Bind_Helper *context)
bind(context, '\t', MDFR_SHIFT, modal_tab);
end_map(context);
end_bind_helper(context);
return context->write_total;
}

View File

@ -26,6 +26,230 @@ CUSTOM_COMMAND_SIG(kill_rect){
}
}
// NOTE(allen): This stream stuff will be moved to helper if it looks
// like it will be helpful. So if you want to use it to build your own
// commands I suggest you move it there first.
struct Stream_Chunk{
Application_Links *app;
Buffer_Summary *buffer;
char *base_data;
int start, end;
int data_size;
char *data;
};
int
round_down(int x, int b){
int r = 0;
if (x >= 0){
r = x - (x % b);
}
return(r);
}
int
round_up(int x, int b){
int r = 0;
if (x >= 0){
r = x - (x % b) + b;
}
return(r);
}
int
init_stream_chunk(Stream_Chunk *chunk,
Application_Links *app, Buffer_Summary *buffer,
int pos, char *data, int size){
int result = 0;
app->refresh_buffer(app, buffer);
if (pos >= 0 && pos < buffer->size && size > 0){
result = 1;
chunk->app = app;
chunk->buffer = buffer;
chunk->base_data = data;
chunk->data_size = size;
chunk->start = round_down(pos, size);
chunk->end = round_up(pos, size);
if (chunk->end > buffer->size){
chunk->end = buffer->size;
}
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
}
return(result);
}
int
forward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
int result = 0;
app->refresh_buffer(app, buffer);
if (chunk->end < buffer->size){
result = 1;
chunk->start = chunk->end;
chunk->end += chunk->data_size;
if (chunk->end > buffer->size){
chunk->end = buffer->size;
}
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
}
return(result);
}
int
backward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
int result = 0;
app->refresh_buffer(app, buffer);
if (chunk->start > 0){
result = 1;
chunk->end = chunk->start;
chunk->start -= chunk->data_size;
if (chunk->start < 0){
chunk->start = 0;
}
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
}
return(result);
}
// TODO(allen): Both of these brace related commands would work better
// if the API exposed access to the tokens in a code file.
CUSTOM_COMMAND_SIG(mark_matching_brace){
View_Summary view = app->get_active_view(app);
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
int start_pos = view.cursor.pos;
// NOTE(allen): The user provides the memory that the chunk uses,
// this chunk will then be filled at each step of the text stream loop.
// This way you can look for something that should be nearby without
// having to copy the whole file in at once.
Stream_Chunk chunk;
char chunk_space[(1 << 10)];
int result = 0;
int found_result = 0;
int i = start_pos;
int still_looping = 1;
int nesting_counter = 0;
char at_cursor = 0;
if (init_stream_chunk(&chunk, app, &buffer, i, chunk_space, sizeof(chunk_space))){
// NOTE(allen): This is important! The data array is a pointer that is adjusted
// so that indexing it with "i" will put it with the chunk that is actually loaded.
// If i goes below chunk.start or above chunk.end _that_ is an invalid access.
at_cursor = chunk.data[i];
if (at_cursor == '{'){
do{
for (++i; i < chunk.end; ++i){
at_cursor = chunk.data[i];
if (at_cursor == '{'){
++nesting_counter;
}
else if (at_cursor == '}'){
if (nesting_counter == 0){
found_result = 1;
result = i;
goto finished;
}
else{
--nesting_counter;
}
}
}
still_looping = forward_stream_chunk(&chunk);
}
while (still_looping);
}
else if (at_cursor == '}'){
do{
for (--i; i >= chunk.start; --i){
at_cursor = chunk.data[i];
if (at_cursor == '}'){
++nesting_counter;
}
else if (at_cursor == '{'){
if (nesting_counter == 0){
found_result = 1;
result = i;
goto finished;
}
else{
--nesting_counter;
}
}
}
still_looping = backward_stream_chunk(&chunk);
}
while (still_looping);
}
}
finished:
if (found_result){
app->view_set_mark(app, &view, seek_pos(result));
}
}
CUSTOM_COMMAND_SIG(cursor_to_surrounding_scope){
View_Summary view = app->get_active_view(app);
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
int start_pos = view.cursor.pos - 1;
Stream_Chunk chunk;
char chunk_space[(1 << 10)];
int result = 0;
int found_result = 0;
int i = start_pos;
int still_looping = 1;
int nesting_counter = 0;
char at_cursor = 0;
if (init_stream_chunk(&chunk, app, &buffer, i, chunk_space, sizeof(chunk_space))){
do{
for (; i >= chunk.start; --i){
at_cursor = chunk.data[i];
if (at_cursor == '}'){
++nesting_counter;
}
else if (at_cursor == '{'){
if (nesting_counter == 0){
found_result = 1;
result = i;
goto finished;
}
else{
--nesting_counter;
}
}
}
still_looping = backward_stream_chunk(&chunk);
} while(still_looping);
}
finished:
if (found_result){
app->view_set_cursor(app, &view, seek_pos(result), 0);
}
}
// NOTE(allen): Incomplete
#if 0
CUSTOM_COMMAND_SIG(complete_word){
app->print_message(app, literal("complete_word\n"));
@ -44,7 +268,7 @@ CUSTOM_COMMAND_SIG(complete_word){
start = view.cursor.pos;
String complete_string;
int size = (start - end);
int size = (end - start);
char complete_space[256];
if (size < sizeof(complete_space) - 1){
@ -54,11 +278,12 @@ CUSTOM_COMMAND_SIG(complete_word){
complete_string.str[size] = 0;
// TODO(allen): Complete this when the heavy duty coroutine stuff
// and the hash table are available
// and the hash table are available.
app->print_message(app, complete_string.str, complete_string.size);
}
}
#endif
// TODO(allen): Query theme settings
#if 0
@ -83,7 +308,8 @@ CUSTOM_COMMAND_SIG(save_theme_settings){
void experiment_extension(Bind_Helper *context){
bind(context, 'k', MDFR_ALT, kill_rect);
bind(context, '+', MDFR_CTRL, complete_word);
bind(context, '/', MDFR_ALT, mark_matching_brace);
bind(context, '\'', MDFR_ALT, cursor_to_surrounding_scope);
}
#include <stdio.h>