Changeset 12677 in project


Ignore:
Timestamp:
12/01/08 05:15:57 (11 years ago)
Author:
mfredrickson
Message:

This checkin of readline has 2 changes:

  1. All the C code is moved into readline-egg.c as a housecleaning measure. At the moment it is just #include'd into readline.scm - but in the future, it may be compiled on its own.
  1. File globbing works for quoted completions (e.g. '(load "my-fil[tab]' -> will complete with all files starting with "my-fil*"). Non-quoted completions behave as before.

This is a pre-release checkin while I get the docs updated, bump the version number, double check the exports, etc.

Location:
release/3/readline
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • release/3/readline/readline.meta

    r10122 r12677  
    88 (license "GPL-2")
    99 (author "Tony Garnock-Jones")
    10  (files "readline.setup" "readline.scm" "readline.html"))
     10 (files "readline.setup" "readline.scm" "readline.html" "readline-egg.c"))
  • release/3/readline/readline.scm

    r12493 r12677  
    8989 (uses posix)
    9090
    91  (export
    92 
    93   gnu-readline
    94   make-gnu-readline-port
    95   %gnu-readline-signal-cleanup
    96 
    97   gnu-readline-clear-history
    98   gnu-readline-read-history
    99   gnu-readline-write-history
    100   gnu-readline-append-history
    101   gnu-readline-truncate-history
    102   gnu-history-new-lines
    103   gnu-history-install-file-manager
    104 
    105   gnu-readline-parse-and-bind
    106   gnu-readline-set-bounce-ms
    107  
    108   gnu-readline-completions
    109   ))
     91 ;(export
     92 ;
     93 ; gnu-readline
     94 ; make-gnu-readline-port
     95 ; %gnu-readline-signal-cleanup
     96 ;
     97 ; gnu-readline-clear-history
     98 ; gnu-readline-read-history
     99 ; gnu-readline-write-history
     100 ; gnu-readline-append-history
     101 ; gnu-readline-truncate-history
     102 ; gnu-history-new-lines
     103 ; gnu-history-install-file-manager
     104 ;
     105 ; gnu-readline-parse-and-bind
     106 ; gnu-readline-set-bounce-ms
     107 ;
     108 ; gnu-readline-completions
     109 ; )
     110  )
    110111
    111112
    112113#>
    113 #include <stdlib.h>
    114 #include <string.h>
    115 #include <stdio.h>
    116 #include <sys/poll.h>
    117 #include <readline/readline.h>
    118 #include <readline/history.h>
    119 
    120 static char *gnu_readline_buf = NULL;
    121 static int gnu_readline_bounce_ms = 500;
    122 static int gnu_readline_paren_balance = 0;
    123 static int gnu_readline_brace_balance = 0;
    124 static int gnu_history_newlines = 0;
    125 
    126 ////\\\\//// Paren Bouncing ////\\\\////
    127 
    128 /* Returns: (if positive) the position of the matching paren
    129             (if negative) the number of unmatched closing parens */
    130 int gnu_readline_skip(int pos, int open_key, int close_key)
    131 {
    132         while (--pos > -1) {
    133                 if (pos > 0 && rl_line_buffer[pos - 1] == '\\') {
    134                         continue;
    135                 } else if (rl_line_buffer[pos] == open_key) {
    136                         return pos;
    137                 } else if (rl_line_buffer[pos] == close_key) {
    138                         pos = gnu_readline_skip(pos, open_key, close_key);
    139                 } else if (rl_line_buffer[pos] == '"') {
    140                         pos = gnu_readline_skip(pos, '"', '"');
    141                 }
    142         }
    143         return pos;
    144 }
    145 
    146 // Return what the balance is between opening and closing keys
    147 int gnu_readline_match_balance(int open_key, int close_key)
    148 {
    149         int pos;
    150         int open = 0;
    151 
    152         // Can't use rl_end intead of strlen: gives length of whole buffer
    153         pos = gnu_readline_skip(strlen(rl_line_buffer), open_key, close_key);
    154         if (pos < 0)
    155                 return pos + 1;
    156 
    157         while (pos >= 0) {
    158                 open++;
    159                 pos = gnu_readline_skip(pos, open_key, close_key);
    160         }
    161 
    162         return open;
    163 }
    164 
    165 // Resets the global vars that track paren balance
    166 void gnu_readline_clear_balances()
    167 {
    168         gnu_readline_paren_balance = 0;
    169         gnu_readline_brace_balance = 0;
    170 }
    171 
    172 
    173 // Finds the matching paren (starting from just left of the cursor)
    174 int gnu_readline_find_match(int key)
    175 {
    176         if (key == ')')
    177                 return gnu_readline_skip(rl_point - 1, '(', ')');
    178         else if (key == ']')
    179                 return gnu_readline_skip(rl_point - 1, '[', ']');
    180        
    181         return 0;
    182 }
    183 
    184 // Delays, but returns early if key press occurs
    185 void gnu_readline_timid_delay(ms)
    186 {
    187         struct pollfd pfd;
    188        
    189         pfd.fd = fileno(rl_instream);
    190         pfd.events = POLLIN || POLLPRI;
    191         pfd.revents = 0;
    192        
    193         poll(&pfd, 1, ms);
    194 }
    195 
    196 // Bounces the cursor to the matching paren for a while
    197 int gnu_readline_paren_bounce(int count, int key)
    198 {
    199         int insert_success;
    200         int old_point;
    201         int matching;
    202 
    203         if (gnu_readline_bounce_ms == 0)
    204                 return 0;
    205 
    206         // Write the just entered paren out first
    207         insert_success = rl_insert(count, key);
    208         if (insert_success != 0)
    209                 return insert_success;
    210         rl_redisplay();
    211 
    212         // Need at least two chars to bounce...
    213         if (rl_point < 2) // rl_point set to next char (implicit +1)
    214                 return 0;
    215 
    216         // If it's an escaped paren, don't bounce...
    217         if (rl_line_buffer[rl_point - 2] == '\\')
    218                 return 0;
    219 
    220         // Bounce
    221         old_point = rl_point;
    222         matching = gnu_readline_find_match(key);
    223         if (matching < 0)
    224                 return 0;
    225         else
    226                 rl_point = matching;
    227         rl_redisplay();
    228         gnu_readline_timid_delay(gnu_readline_bounce_ms);
    229         rl_point = old_point;
    230 
    231         return 0;
    232 }
    233 
    234 
    235 ////\\\\//// Tab Completion ////\\\\////
    236 
    237 // Prototype for callback into scm
    238 C_word gnu_readline_scm_complete(char *, int, int);
    239 
    240 // Gets called (repeatedly) when readline tries to do a completion
    241 char *gnu_readline_tab_complete(const char *text, int status) {
    242         C_word result;
    243         char *str;
    244         int len;
    245         char *copied_str;
    246 
    247         /* All of this is for older versions of chicken (< 2.3), which don't
    248            reliably null-terminate strings */
    249 
    250         // Get scheme string for possible completion via callback
    251         result = gnu_readline_scm_complete((char *)text, strlen(text), status);
    252 
    253         if (result == C_SCHEME_FALSE)
    254                 return NULL;
    255 
    256         // Convert into C types
    257         str = C_c_string(result);
    258         len = C_num_to_int(C_i_string_length(result));
    259 
    260         if (len == 0)
    261                 return NULL;
    262 
    263         // Copy (note: the readline lib frees this copy)
    264         copied_str = (char *)malloc(len + 1);
    265         strncpy(copied_str, str, len);
    266         copied_str[len] = '\0';
    267 
    268         return copied_str;
    269 }
    270 
    271 
    272 ////\\\\//// Other Stuff ////\\\\////
    273 
    274 /*
    275 // This is code that is supposed to alter the behaviour of ctrl-w so that it recognizes
    276 // parens as delimiters.  It works, but I can't bind it to ctrl-w, because that key code
    277 // is intercepted by the terminal (I think).
    278 
    279 // Ripped off from readline src
    280 #define emacs_mode 1
    281 #define whitespace_ext(c) ( ((c) == ' ') || ((c) == '\t') || ((c) == '(') || ((c) == '[') )
    282 
    283 int gnu_readline_lisp_word_rubout(int count, int key)
    284 {
    285         int orig_point;
    286 
    287         if (rl_point == 0) {
    288                 rl_ding ();
    289         } else {
    290                 orig_point = rl_point;
    291                 if (count <= 0)
    292                         count = 1;
    293 
    294                 while (count--) {
    295                         while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
    296                                 rl_point--;
    297 
    298                         while (rl_point && (whitespace_ext (rl_line_buffer[rl_point - 1]) == 0))
    299                                 rl_point--;
    300                 }
    301                
    302                 if (orig_point == rl_point &&
    303                         (rl_line_buffer[rl_point - 1] == '(' || rl_line_buffer[rl_point - 1] == '['))
    304                         rl_point--;
    305 
    306                 rl_kill_text (orig_point, rl_point);
    307                 if (rl_editing_mode == emacs_mode)
    308                         rl_mark = rl_point;
    309         }
    310 
    311         return 0;
    312 }
    313 */
    314 
    315 int gnu_history_new_lines()
    316 {
    317     return gnu_history_newlines;
    318 }
    319 
    320 int gnu_readline_append_history(char *filename)
    321 {
    322     return append_history(gnu_history_newlines, filename);
    323 }
    324 
    325 
    326 // Set everything up
    327 void gnu_readline_init()
    328 {
    329         using_history();
    330         rl_bind_key(')', gnu_readline_paren_bounce);
    331         rl_bind_key(']', gnu_readline_paren_bounce);
    332         rl_completion_entry_function = &gnu_readline_tab_complete;
    333         rl_variable_bind("rl_catch_signals", 0);
    334         rl_clear_signals();
    335         rl_set_signals();
    336         //rl_add_defun ("lisp-word-rubout" , gnu_readline_lisp_word_rubout, -1);
    337 }
    338 
    339 
    340 // Called from scheme to get user input
    341 char *gnu_readline_readline(char *prompt, char *prompt2)
    342 {
    343         char *empty_prompt;
    344         int prompt_len;
    345         HIST_ENTRY *h;
    346 
    347         if (gnu_readline_buf != NULL) {
    348                 free(gnu_readline_buf);
    349                 gnu_readline_buf = NULL;
    350         }
    351 
    352         if ((gnu_readline_paren_balance || gnu_readline_brace_balance) == 0)
    353                 gnu_readline_buf = readline(prompt);
    354         else
    355                 gnu_readline_buf = readline(prompt2);
    356 
    357         if (gnu_readline_buf != NULL && *gnu_readline_buf != '\0') {
    358                 h = history_get(history_base + history_length - 1);
    359                 if (NULL == h || 0 != strcmp(h->line, gnu_readline_buf)) {
    360                         add_history(gnu_readline_buf);
    361                         gnu_history_newlines++;
    362                 }
    363         }
    364 
    365         gnu_readline_paren_balance += gnu_readline_match_balance('(', ')');
    366         gnu_readline_brace_balance += gnu_readline_match_balance('[', ']');
    367         if (gnu_readline_paren_balance < 0 || gnu_readline_brace_balance < 0)
    368                 gnu_readline_clear_balances();
    369 
    370         return(gnu_readline_buf);
    371 }
    372 
    373 void gnu_readline_signal_cleanup()
    374 {
    375     gnu_readline_clear_balances();
    376     free(gnu_readline_buf);
    377     gnu_readline_buf = NULL;
    378     rl_free_line_state();
    379     rl_cleanup_after_signal();
    380 }
    381 
     114 #include "readline-egg.c"
    382115<#
    383116
     
    425158        "gnu_readline_bounce_ms = time;"))
    426159
    427 
     160;; get access to the quoting flag
     161(define-foreign-variable is-quoted? int "rl_completion_quote_character")
     162(define-foreign-variable filename-completion int "rl_filename_completion_desired")
    428163
    429164;; Handler for the command history file
     
    555290                                          (symbol->string (caar ref))))))))))
    556291
     292;; handling filename completion
     293(define (turn-on-filenames)
     294  (set! filename-completion 1))
     295 
    557296(define (create-file-ef word)
     297  (turn-on-filenames)
    558298  (let ((files (glob (string-append word "*"))))
    559299    (lambda ()
     
    566306  (make-parameter
    567307    (list
    568       (list 'macros create-macro-ef)
    569       (list 'statics create-static-ef)
    570       (list 'symbols create-symbol-ef)
    571       (list 'files create-file-ef))))
    572 
    573 
     308      (cons 'macros create-macro-ef)
     309      (cons 'statics create-static-ef)
     310      (cons 'symbols create-symbol-ef))))
     311
     312(define gnu-readline-quoted-completions
     313  (make-parameter
     314    (list
     315      (cons 'files create-file-ef))))
     316     
    574317;; This is the completion function called by readline
    575318;; It's called repeatedly until it returns an empty string
     
    578321   (define-external (gnu_readline_scm_complete (c-string word) (int len) (int state)) scheme-object
    579322         ;; If state is zero, init enumeration funcs.  Don't try to complete an empty string...
     323         ;(print is-quoted?)
    580324         (when (zero? state)
    581325           (if (not (zero? len))
    582                  (set! enum-funcs
    583                    (map (lambda (pair) ((cadr pair) word)) (gnu-readline-completions)))
     326                 (set! enum-funcs (choose-completion-procs word))
    584327                 ""))
    585328         ;; Call the enumeration funcs, discarding the ones that are done
     
    595338                                 (else (loop)))))))))
    596339
    597 
     340;; This function simply chooses which completion type is appropriate
     341;; and then gets those procedures ready.
     342(define (choose-completion-procs word)
     343  (map
     344    (lambda (pair) ((cdr pair) word))
     345    (if (= 34 is-quoted?)
     346      (gnu-readline-quoted-completions)
     347      (gnu-readline-completions))))
    598348
    599349;; Things that will always be there...
Note: See TracChangeset for help on using the changeset viewer.