On 9/22/2013 7:50 AM, Andrej Mitrovic wrote:
I run into these all the time, and I have to spend half a minute
scanning left and right trying to figure out where the damn missing
brace went. Marginal benefit my ass.


I programmed into my editor (MicroEmacs) the F3 command. F3, when sitting on one of ()[]{}<> will find the matching character, even if nested. If it is not on one of those characters, it finds the next occurrence of that character.

As a bonus, if it is on the # character at the beginning of the line, it will find the matching #if, #ifdef, #elif, #else, or #endif :-)

I find it very, very handy.

It's based on an elithp macro written for Emacs back in the 1980's. If your editor has any ability to have user-written extensions, this is a simple one, and I highly recommend it. Here's the corresponding MicroEmacs implementation:

-----------------------------------------------------------------------
/*********************************
 * Examine line at '.'.
 * Returns:
 *      HASH_xxx
 *      0       anything else
 */

#define HASH_IF         1
#define HASH_ELIF       2
#define HASH_ELSE       3
#define HASH_ENDIF      4

static int ifhash(clp)
LINE *clp;
{
    register int len;
    register int i,h;
    static char *hash[] = {"if","elif","else","endif"};

    len = llength(clp);
    if (len < 3 || lgetc(clp,0) != '#')
        goto ret0;
    for (i = 1; ; i++)
    {
        if (i >= len)
            goto ret0;
        if (!isspace(lgetc(clp,i)))
            break;
    }
    for (h = 0; h < arraysize(hash); h++)
        if (len - i >= strlen(hash[h]) &&
            memcmp(&clp->l_text[i],hash[h],strlen(hash[h])) == 0)
            return h + 1;
ret0:
    return 0;
}


/*********************************
 * Search for the next occurence of the character at '.'.
 * If character is a (){}[]<>, search for matching bracket.
 * If '.' is on #if, #elif, or #else search for next #elif, #else or #endif.
 * If '.' is on #endif, search backwards for corresponding #if.
 */

int search_paren(f, n)
    {
    register LINE *clp;
    register int cbo;
    register int len;
    register int i;
    char chinc,chdec,ch;
    int count;
    int forward;
    int h;
    static char bracket[][2] = {{'(',')'},{'<','>'},{'[',']'},{'{','}'}};

    clp = curwp->w_dotp;             /* get pointer to current line  */
    cbo = curwp->w_doto;             /* and offset into that line    */
    count = 0;

    len = llength(clp);
    if (cbo >= len)
        chinc = '\n';
    else
        chinc = lgetc(clp,cbo);

    if (cbo == 0 && (h = ifhash(clp)) != 0)
    {   forward = h != HASH_ENDIF;
    }
    else
    {
        if (inword())
        {   // Search for word the cursor is currently on
            int s;
            do
                s = backchar(FALSE, 1);
            while (s && inword());

            if (s && forwchar(FALSE, 1))
            {
                int start = curwp->w_doto;
                if (word_forw(FALSE, 1))
                {
                    cbo = curwp->w_doto;
                    int i;
                    for (i = 0; i < NPAT - 1 && start + i < cbo; i++)
                    {
                        pat[i] = lgetc(clp, start + i);
                    }
                    pat[i] = 0;
                    if (Dsearchagain(f, n))
                        return backchar(FALSE, 1);
                }
            }
            mlwrite("Not found");
            return FALSE;
        }
        forward = TRUE;                 /* forward                      */
        h = 0;
        chdec = chinc;
        for (i = 0; i < 4; i++)
            if (bracket[i][0] == chinc)
            {   chdec = bracket[i][1];
                break;
            }
        for (i = 0; i < 4; i++)
            if (bracket[i][1] == chinc)
            {   chdec = bracket[i][0];
                forward = FALSE;        /* search backwards             */
                break;
            }
    }

    while (1)                           /* while not end of buffer      */
    {
        if (forward)
        {
            if (h || cbo >= len)
            {
                clp = lforw(clp);
                if (clp == curbp->b_linep)   /* if end of buffer     */
                    break;
                len = llength(clp);
                cbo = 0;
            }
            else
                cbo++;
        }
        else /* backward */
        {
            if (h || cbo == 0)
            {
                clp = lback(clp);
                if (clp == curbp->b_linep)
                    break;
                len = llength(clp);
                cbo = len;
            }
            else
                --cbo;
        }

        if (h)
        {   int h2;

            cbo = 0;
            h2 = ifhash(clp);
            if (h2)
            {   if (h == HASH_ENDIF)
                {
                    if (h2 == HASH_ENDIF)
                        count++;
                    else if (h2 == HASH_IF)
                    {   if (count-- == 0)
                            goto found;
                    }
                }
                else
                {   if (h2 == HASH_IF)
                        count++;
                    else
                    {   if (count == 0)
                            goto found;
                        if (h2 == HASH_ENDIF)
                            count--;
                    }
                }
            }
        }
        else
        {
            ch = (cbo < len) ? lgetc(clp,cbo) : '\n';
            if (eq(ch,chdec))
            {   if (count-- == 0)
                {
                    /* We've found it   */
                found:
                    curwp->w_dotp  = clp;
                    curwp->w_doto  = cbo;
                    curwp->w_flag |= WFMOVE;
                    return (TRUE);
                }
            }
            else if (eq(ch,chinc))
                count++;
        }
    }
    mlwrite("Not found");
    return (FALSE);
}

Reply via email to