]> git.lizzy.rs Git - linenoise.git/commitdiff
Support reverse incremental search with ^R
authorSteve Bennett <steveb@workware.net.au>
Thu, 30 Sep 2010 20:11:32 +0000 (06:11 +1000)
committerSteve Bennett <steveb@workware.net.au>
Fri, 8 Apr 2011 01:37:19 +0000 (11:37 +1000)
Signed-off-by: Steve Bennett <steveb@workware.net.au>
linenoise.c

index cb29fa02b4b0f6bc3327b09345aaec0256e2e149..3911a518d15e723995f1c531245ce1bacf83bb06 100644 (file)
  *
  * Todo list:
  * - Switch to gets() if $TERM is something we can't support.
- * - Filter bogus Ctrl+<char> combinations.
  * - Win32 support
  *
  * Bloat:
  * - Completion?
- * - History search like Ctrl+r in readline?
  *
  * List of escape sequences used by this program, we do everything just
  * with three sequences. In order to be so cheap we may have some
@@ -325,6 +323,7 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt)
         char seq[2], seq2[2];
 
         nread = read(fd,&c,1);
+process_char:
         if (nread <= 0) return len;
 
         /* Only autocomplete when the callback is set. It returns < 0 when
@@ -368,6 +367,64 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt)
                 return -1;
             }
             break;
+        case 18:    /* ctrl-r */
+            {
+                /* Display the reverse-i-search prompt and process chars */
+                char rbuf[50];
+                char rprompt[80];
+                int i = 0;
+                rbuf[0] = 0;
+                while (1) {
+                    snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf);
+                    refreshLine(fd,rprompt,buf,len,pos,cols);
+                    nread = read(fd,&c,1);
+                    if (nread == 1) {
+                        if (c == 8 || c == 127) {
+                            if (i > 0) {
+                                rbuf[--i] = 0;
+                            }
+                            continue;
+                        }
+                        if (c == 7) {
+                            /* ctrl-g terminates the search with no effect */
+                            buf[0] = 0;
+                            len = 0;
+                            pos = 0;
+                            break;
+                        }
+                        if (c >= ' ' && c <= '~') {
+                            if (i < (int)sizeof(rbuf)) {
+                                int j;
+                                const char *p = NULL;
+                                rbuf[i++] = c;
+                                rbuf[i] = 0;
+                                /* Now search back through the history for a match */
+                                for (j = history_len - 1; j > 0; j--) {
+                                    p = strstr(history[j], rbuf);
+                                    if (p) {
+                                        /* Found a match. Copy it */
+                                        strncpy(buf,history[j],buflen);
+                                        buf[buflen] = '\0';
+                                        len = strlen(buf);
+                                        pos = p - history[j];
+                                        break;
+                                    }
+                                }
+                                if (!p) {
+                                    /* No match, so don't add it */
+                                    rbuf[--i] = 0;
+                                }
+                            }
+                            continue;
+                        }
+                    }
+                    break;
+                }
+                /* Go process the char normally */
+                refreshLine(fd,prompt,buf,len,pos,cols);
+                goto process_char;
+            }
+            break;
         case 20:    /* ctrl-t */
             if (pos > 0 && pos < len) {
                 int aux = buf[pos-1];