/* Authorship: Written by Jeff Dunlop. Explicitly released to the public domain. There is no code contained within that is derivative of any copyrighted code. Predictability: Template expansion is currently supported for the following constructs: if(), while(), do while (), for() and switch(). It occurs if there is only one group of contiguous alphabetic characters preceding the cursor, the group of characters is recognized as a substring of a supported construct and the space-bar is pressed. Configurability: This source is active if c-mode is active. In general, CloseBack and Topindent govern indentation behavior. The only issue remaining to be resolved is whether your opening bracket is on its own line. This is controlled by old_style, which defaults to false. A relatively non-issue is whether templates are turned on (the default). Setting enable_templates to 0 disables them. If you find working around expansion when you know it's going to happen a pain, you might try assigning expansion to another key or alternately, assign a space character to a different key. However, it is not too difficult to use the right-arrow key in cases where you want lateral movement without expansion as long as virtual-space is enabled. */ keytable c_tab; /* key table for c mode */ #include int old_style = 0, enable_templates = 1; expand_if(where) { /* 1. Examine the line to see if we should expand */ char *template = "if ( )\n{\n}", *oldtemplate = "if ( ) {\n}", *p = where + ( old_style ? oldtemplate : template ); while ( *p ) { insert(*p); if ( *p == '{' || *p == '}') { fix_c_indentation(); } p++; } search(-1, ")"); point--; } expand_while(where) { char *template = "while ( )\n{\n}", *oldtemplate = "while ( ) {\n}", *p = where + ( old_style ? oldtemplate : template ); while ( *p ) { insert(*p); if ( *p == '{' || *p == '}') fix_c_indentation(); p++; } search(-1, ")"); point--; } expand_for(where) { char *template = "for ( ; ; )\n{\n}", *oldtemplate = "for ( ; ; ) {\n}", *p = where + ( old_style ? oldtemplate : template ); while ( *p ) { insert(*p); if ( *p == '{' || *p == '}') fix_c_indentation(); p++; } search(-1, ")"); point -= 4; } expand_dowhile(where) { char *template = "do\n{\n} while ( );", *oldtemplate = "do {\n} while ( );", *p = where + ( old_style ? oldtemplate : template ); while ( *p ) { insert(*p); if ( *p == '{' || *p == '}') fix_c_indentation(); p++; } search(-1, ")"); point--; } expand_switch(where) { char *template = "switch ( )\n{\ncase:\n};", *oldtemplate = "switch ( ) {\ncase:\n};", *p = where + ( old_style ? oldtemplate : template ); while ( *p ) { insert(*p); if ( *p == '{' || *p == '}' || *p == ':') fix_c_indentation(); p++; } search(-1, ")"); point--; } expand_comment() { } int max(a, b) { return a < b ? a : b; } expand_template() on c_tab[' '] { char buf[80]; int len, here = point; if ( !enable_templates ) { insert(' '); return; } if ( !all_blanks(point, give_end_line()) ) { insert(' '); return; } re_search(-1, "[^a-z]"); if ( point < give_begin_line() ) point = give_begin_line(); if ( isspace(curchar()) ) point++; if ( !all_blanks(give_begin_line(), point) ) { point = here; insert(' '); return; } len = here - point; if ( len < 80 ) { grab(point, here, buf); buf[len] = 0; } else { point = here; insert(' '); return; } say("buf=%s, len=%d", buf, len); if ( len < 1 ) { point = here; insert(' '); return; } if ( strncmp(buf, "if", max(2, len)) == 0 ) { point = here; expand_if(len); return; } if ( strncmp(buf, "while", max(5, len)) == 0 ) { point = here; expand_while(len); return; } if ( strncmp(buf, "for", max(3, len)) == 0 ) { point = here; expand_for(len); return; } if ( strncmp(buf, "do", max(2, len)) == 0 ) { point = here; expand_dowhile(len); return; } if ( strncmp(buf, "switch", max(5, len)) == 0 ) { point = here; expand_switch(len); return; } point = here; insert(' '); return; }