working on removing open_hook from view_set_file
parent
db058ea6d7
commit
a690547aa2
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Binary file not shown.
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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!
|
||||
|
||||
|
|
|
@ -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!
|
||||
|
||||
|
|
|
@ -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%
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue