This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Greg Harvey has written a patch to get Guile to do parenthesis matching using a stock readline library. I can't commit this change until the FSF gets a copyright assignment from Greg, but in the mean time, I thought people might appreciate it. (I certainly do. :) ) 1998-11-24 Jim Blandy <jimb@zwingli.cygnus.com> Match parentheses. (Contributed by Greg Harvey --- thanks!) * readline.c: #include "iselect.h". (scm_readline_opts): Add "bounce-parens" option. (match_paren, find_matching_paren, init_bouncing_parens): New functions. * readline.h: (SCM_N_READLINE_OPTIONS): Update. * readline.c (in_readline, reentry_barrier_mutex): Make these static. Index: readline.c =================================================================== RCS file: /egcs/carton/cvsfiles/guile/guile-core/libguile/readline.c,v retrieving revision 1.15 diff -c -r1.15 readline.c *** readline.c 1998/11/19 04:48:50 1.15 --- readline.c 1998/11/24 19:59:23 *************** *** 50,60 **** #include <readline/readline.h> #include <readline/history.h> scm_option scm_readline_opts[] = { { SCM_OPTION_BOOLEAN, "history-file", 1, "Use history file." }, { SCM_OPTION_INTEGER, "history-length", 200, ! "History length." } }; extern void stifle_history (int max); --- 50,66 ---- #include <readline/readline.h> #include <readline/history.h> + #include <sys/time.h> + #include "iselect.h" + + scm_option scm_readline_opts[] = { { SCM_OPTION_BOOLEAN, "history-file", 1, "Use history file." }, { SCM_OPTION_INTEGER, "history-length", 200, ! "History length." }, ! { SCM_OPTION_BOOLEAN, "bounce-parens", 1, ! "Match closing parenthesis/brackets to opening ones."} }; extern void stifle_history (int max); *************** *** 155,163 **** SCM_PROC (s_readline, "readline", 0, 4, 0, scm_readline); ! int in_readline = 0; #ifdef USE_THREADS ! scm_mutex_t reentry_barrier_mutex; #endif static void --- 161,169 ---- SCM_PROC (s_readline, "readline", 0, 4, 0, scm_readline); ! static int in_readline = 0; #ifdef USE_THREADS ! static scm_mutex_t reentry_barrier_mutex; #endif static void *************** *** 360,365 **** --- 366,458 ---- } } + /*Bouncing parenthesis (reimplemented by GH, 11/23/98, since readline is strict gpl)*/ + + static void match_paren(int x, int k); + static int find_matching_paren(int k); + static void init_bouncing_parens(); + + static void + init_bouncing_parens() + { + if(strncmp(rl_get_keymap_name(rl_get_keymap()), "vi", 2)) { + rl_bind_key(')', match_paren); + rl_bind_key(']', match_paren); + rl_bind_key('}', match_paren); + } + } + + static int + find_matching_paren(int k) + { + register int i; + register char c = 0; + int end_parens_found = 0; + + /* Choose the corresponding opening bracket. */ + if (k == ')') c = '('; + else if (k == ']') c = '['; + else if (k == '}') c = '{'; + + for (i=rl_point-2; i>=0; i--) + { + /* Is the current character part of a character literal? */ + if (i - 2 >= 0 + && rl_line_buffer[i - 1] == '\\' + && rl_line_buffer[i - 2] == '#') + ; + else if (rl_line_buffer[i] == k) + end_parens_found++; + else if (rl_line_buffer[i] == '"') + { + /* Skip over a string literal. */ + for (i--; i >= 0; i--) + if (rl_line_buffer[i] == '"' + && ! (i - 1 >= 0 + && rl_line_buffer[i - 1] == '\\')) + break; + } + else if (rl_line_buffer[i] == c) + { + if (end_parens_found==0) return i; + else --end_parens_found; + } + } + return -1; + } + + static void + match_paren(int x, int k) + { + int tmp; + fd_set readset; + struct timeval timeout; + + rl_insert(x, k); + if (!SCM_READLINE_BOUNCE_PARENS_P) + return; + + /* Did we just insert a quoted paren? If so, then don't bounce. */ + if (rl_point - 1 >= 1 + && rl_line_buffer[rl_point - 2] == '\\') + return; + + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + FD_ZERO(&readset); + FD_SET(fileno(rl_instream), &readset); + + if(rl_point > 1) { + tmp = rl_point; + rl_point = find_matching_paren(k); + if(rl_point > -1) { + rl_redisplay(); + scm_internal_select(1, &readset, NULL, NULL, &timeout); + } + rl_point = tmp; + } + } + void scm_init_readline () *************** *** 377,382 **** --- 470,476 ---- scm_init_opts (scm_readline_options, scm_readline_opts, SCM_N_READLINE_OPTIONS); + init_bouncing_parens(); scm_add_feature ("readline"); } Index: readline.h =================================================================== RCS file: /egcs/carton/cvsfiles/guile/guile-core/libguile/readline.h,v retrieving revision 1.7 diff -c -r1.7 readline.h *** readline.h 1998/11/09 14:15:30 1.7 --- readline.h 1998/11/24 19:59:23 *************** *** 48,54 **** #define SCM_HISTORY_FILE_P scm_readline_opts[0].val #define SCM_HISTORY_LENGTH scm_readline_opts[1].val ! #define SCM_N_READLINE_OPTIONS 2 extern SCM scm_readline_options (SCM setting); extern SCM scm_readline (SCM txt, SCM inp, SCM outp, SCM read_hook); --- 48,55 ---- #define SCM_HISTORY_FILE_P scm_readline_opts[0].val #define SCM_HISTORY_LENGTH scm_readline_opts[1].val ! #define SCM_READLINE_BOUNCE_PARENS_P scm_readline_opts[2].val ! #define SCM_N_READLINE_OPTIONS 3 extern SCM scm_readline_options (SCM setting); extern SCM scm_readline (SCM txt, SCM inp, SCM outp, SCM read_hook);