]> git.lizzy.rs Git - linenoise.git/blobdiff - linenoise.c
API converted to be readline alike. Ctrl-d behavior fixed.
[linenoise.git] / linenoise.c
index 386ab6c69620b73368da4070151d73a7f0ce84a4..bcef68ef6ff726825df8842127b3fe563b3827cf 100644 (file)
@@ -1,6 +1,10 @@
 /* linenoise.c -- guerrilla line editing library against the idea that a
  * line editing lib needs to be 20,000 lines of C code.
  *
+ * You can find the latest source code at:
+ * 
+ *   http://github.com/antirez/linenoise
+ *
  * Does a number of crazy assumptions that happen to be true in 99.9999% of
  * the 2010 UNIX computers around.
  *
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * Reference: http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
+ * References:
+ * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+ * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
  *
- * Works with:
+ * Todo list:
+ * - Switch to gets() if $TERM is something we can't support.
+ * - Filter bogus Ctrl+<char> combinations.
+ * - Win32 support
  *
- * Linux console (TERM = Linux)
- * Linux KDE terminal application (TERM = xterm)
- * Linux xterm (TERM = xterm)
- * Mac OS X iTerm (TERM = xterm)
+ * Bloat:
+ * - Completion?
+ * - History search like Ctrl+r in readline?
  *
- * Broken with:
+ * 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
+ * flickering effect with some slow terminal, but the lesser sequences
+ * the more compatible.
  *
- * Mac OS X default Terminal application (TERM = xterm) 
+ * CHA (Cursor Horizontal Absolute)
+ *    Sequence: ESC [ n G
+ *    Effect: moves cursor to column n
  *
- * TODO
+ * EL (Erase Line)
+ *    Sequence: ESC [ n K
+ *    Effect: if n is 0 or missing, clear from cursor to end of line
+ *    Effect: if n is 1, clear from beginning of line to cursor
+ *    Effect: if n is 2, clear entire line
  *
- * - Switch to gets() if $TERM is something we can't support.
- * - Completion?
+ * CUF (CUrsor Forward)
+ *    Sequence: ESC [ n C
+ *    Effect: moves cursor forward of n chars
+ * 
  */
 
 #include <termios.h>
@@ -61,6 +80,8 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
+#define LINENOISE_MAX_LINE 4096
+
 static struct termios orig_termios; /* in order to restore at exit */
 static int rawmode = 0; /* for atexit() function to check if restore is needed*/
 static int atexit_registered = 0; /* register atexit just 1 time */
@@ -135,7 +156,7 @@ static int getColumns(void) {
     return ws.ws_col;
 }
 
-static void refreshLine(int fd, char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
+static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
     char seq[64];
     size_t plen = strlen(prompt);
     
@@ -162,7 +183,7 @@ static void refreshLine(int fd, char *prompt, char *buf, size_t len, size_t pos,
     if (write(fd,seq,strlen(seq)) == -1) return;
 }
 
-static int linenoisePrompt(int fd, char *buf, size_t buflen, char *prompt) {
+static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) {
     size_t plen = strlen(prompt);
     size_t pos = 0;
     size_t len = 0;
@@ -186,13 +207,16 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, char *prompt) {
         if (nread <= 0) return len;
         switch(c) {
         case 13:    /* enter */
-        case 4:     /* ctrl+d */
             history_len--;
             return len;
+        case 4:     /* ctrl+d */
+            history_len--;
+            return (len == 0) ? -1 : (int)len;
         case 3:     /* ctrl+c */
             errno = EAGAIN;
             return -1;
         case 127:   /* backspace */
+        case 8:     /* ctrl+h */
             if (pos > 0 && len > 0) {
                 memmove(buf+pos-1,buf+pos,len-pos);
                 pos--;
@@ -282,7 +306,7 @@ static int linenoisePrompt(int fd, char *buf, size_t buflen, char *prompt) {
     return len;
 }
 
-int linenoise(char *buf, size_t buflen, char *prompt) {
+static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
     int fd = STDIN_FILENO;
     int count;
 
@@ -297,6 +321,15 @@ int linenoise(char *buf, size_t buflen, char *prompt) {
     return count;
 }
 
+char *linenoise(const char *prompt) {
+    char buf[LINENOISE_MAX_LINE];
+    int count;
+
+    count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
+    if (count == -1) return NULL;
+    return strdup(buf);
+}
+
 /* Using a circular buffer is smarter, but a bit more complex to handle. */
 int linenoiseHistoryAdd(char *line) {
     if (history_max_len == 0) return 0;