Jim Tcl
Check-in [e8aebbb399]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:linenoise: Update for optimised insert

Update to version: https://github.com/msteveb/linenoise/commit/d7bcf93d4de7581e043283ab461eca2310dd8fdc

Signed-off-by: Steve Bennett <steveb@workware.net.au>

Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e8aebbb3999267e10c5cd60f2c0b5d5cded9317b
User & Date: steveb@workware.net.au 2018-07-25 07:04:32
Context
2018-07-26
20:59
jim-interp.c: fix compile warning with GCC 8.1.1

GCC complains about possible truncation from snprintf() jim-interp.c: In function ‘JimInterpCommand’: jim-interp.c:164:46: warning: ‘%ld’ directive output may be truncated writing between 1 and 20 bytes into a region of size 19 [-Wformat-truncation=] snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); ^~~ jim-interp.c:164:32: note: directive argument in the range [-9223372036854775807, 9223372036854775807] snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); ^~~~~~~~~~~~~~~~~~ jim-interp.c:164:5: note: ‘snprintf’ output between 15 and 34 bytes into a destination of size 32 snprintf(buf, sizeof(buf), "interp.handle%ld", Jim_GetId(interp)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> check-in: 3bb8ebd082 user: borneo.antonio@gmail.com tags: trunk

2018-07-25
07:04
linenoise: Update for optimised insert

Update to version: https://github.com/msteveb/linenoise/commit/d7bcf93d4de7581e043283ab461eca2310dd8fdc

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: e8aebbb399 user: steveb@workware.net.au tags: trunk

05:30
Update autosetup to v0.6.8

autosetup changes: - The syntax for templates has changed slightly - Update config.guess and config.sub to 2018-03-08 - Add rpath support - Add --runstatedir

Also: - enable rpath when building libjim as shared - ensure that 'make test' works on MacOS when libjim is shared

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: ddb44ce9e6 user: steveb@workware.net.au tags: trunk

Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to linenoise.c.

   176    176   void sb_append(stringbuf *sb, const char *str)
   177    177   {
   178    178   	sb_append_len(sb, str, strlen(str));
   179    179   }
   180    180   
   181    181   void sb_append_len(stringbuf *sb, const char *str, int len)
   182    182   {
   183         -	int utf8_strlen(const char *str, int bytelen);
   184    183   	if (sb->remaining < len + 1) {
   185    184   		sb_realloc(sb, sb->last + len + 1 + SB_INCREMENT);
   186    185   	}
   187    186   	memcpy(sb->data + sb->last, str, len);
   188    187   	sb->data[sb->last + len] = 0;
   189    188   
   190    189   	sb->last += len;
................................................................................
   476    475   /* Structure to contain the status of the current (being edited) line */
   477    476   struct current {
   478    477       stringbuf *buf; /* Current buffer. Always null terminated */
   479    478       int pos;    /* Cursor position, measured in chars */
   480    479       int cols;   /* Size of the window, in chars */
   481    480       int nrows;  /* How many rows are being used in multiline mode (>= 1) */
   482    481       int rpos;   /* The current row containing the cursor - multiline mode only */
          482  +    int availcols;  /* refreshLine() caches available cols after the prompt here */
   483    483       const char *prompt;
   484    484       stringbuf *capture; /* capture buffer, or NULL for none. Always null terminated */
   485    485       stringbuf *output;  /* used only during refreshLine() - output accumulator */
   486    486   #if defined(USE_TERMIOS)
   487    487       int fd;     /* Terminal fd */
   488    488   #elif defined(USE_WINCONSOLE)
   489    489       HANDLE outh; /* Console output handle */
................................................................................
  1242   1242   
  1243   1243   void linenoiseSetMultiLine(int enableml)
  1244   1244   {
  1245   1245       mlmode = enableml;
  1246   1246   }
  1247   1247   
  1248   1248   /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
  1249         - * to the right of the prompt. */
  1250         -static void refreshShowHints(struct current *current, const char *buf, int availcols) {
         1249  + * to the right of the prompt.
         1250  + * Returns 1 if a hint was shown, or 0 if not
         1251  + * If 'display' is 0, does no output. Just returns the appropriate return code.
         1252  + */
         1253  +static int refreshShowHints(struct current *current, const char *buf, int availcols, int display)
         1254  +{
         1255  +    int rc = 0;
  1251   1256       if (showhints && hintsCallback && availcols > 0) {
  1252   1257           int bold = 0;
  1253   1258           int color = -1;
  1254   1259           char *hint = hintsCallback(buf, &color, &bold, hintsUserdata);
  1255   1260           if (hint) {
  1256         -            const char *pt;
  1257         -            if (bold == 1 && color == -1) color = 37;
  1258         -            if (bold || color > 0) {
  1259         -                int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
  1260         -                setOutputHighlight(current, props, 3);
  1261         -            }
  1262         -            DRL("<hint bold=%d,color=%d>", bold, color);
  1263         -            pt = hint;
  1264         -            while (*pt) {
  1265         -                int ch;
  1266         -                int n = utf8_tounicode(pt, &ch);
  1267         -                int width = char_display_width(ch);
  1268         -
  1269         -                if (width >= availcols) {
  1270         -                    DRL("<hinteol>");
  1271         -                    break;
         1261  +            rc = 1;
         1262  +            if (display) {
         1263  +                const char *pt;
         1264  +                if (bold == 1 && color == -1) color = 37;
         1265  +                if (bold || color > 0) {
         1266  +                    int props[3] = { bold, color, 49 }; /* bold, color, fgnormal */
         1267  +                    setOutputHighlight(current, props, 3);
         1268  +                }
         1269  +                DRL("<hint bold=%d,color=%d>", bold, color);
         1270  +                pt = hint;
         1271  +                while (*pt) {
         1272  +                    int ch;
         1273  +                    int n = utf8_tounicode(pt, &ch);
         1274  +                    int width = char_display_width(ch);
         1275  +
         1276  +                    if (width >= availcols) {
         1277  +                        DRL("<hinteol>");
         1278  +                        break;
         1279  +                    }
         1280  +                    DRL_CHAR(ch);
         1281  +
         1282  +                    availcols -= width;
         1283  +                    outputChars(current, pt, n);
         1284  +                    pt += n;
         1285  +                }
         1286  +                if (bold || color > 0) {
         1287  +                    clearOutputHighlight(current);
  1272   1288                   }
  1273         -                DRL_CHAR(ch);
  1274         -
  1275         -                availcols -= width;
  1276         -                outputChars(current, pt, n);
  1277         -                pt += n;
         1289  +                /* Call the function to free the hint returned. */
         1290  +                if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
  1278   1291               }
  1279         -            if (bold || color > 0) {
  1280         -                clearOutputHighlight(current);
  1281         -            }
  1282         -            /* Call the function to free the hint returned. */
  1283         -            if (freeHintsCallback) freeHintsCallback(hint, hintsUserdata);
  1284   1292           }
  1285   1293       }
         1294  +    return rc;
  1286   1295   }
  1287   1296   
  1288   1297   #ifdef USE_TERMIOS
  1289   1298   static void refreshStart(struct current *current)
  1290   1299   {
  1291   1300       /* We accumulate all output here */
  1292   1301       assert(current->output == NULL);
................................................................................
  1323   1332       int displaycol;
  1324   1333       int displayrow;
  1325   1334       int visible;
  1326   1335       int currentpos;
  1327   1336       int notecursor;
  1328   1337       int cursorcol = 0;
  1329   1338       int cursorrow = 0;
         1339  +    int hint;
  1330   1340       struct esc_parser parser;
  1331   1341   
  1332   1342   #ifdef DEBUG_REFRESHLINE
  1333   1343       dfh = fopen("linenoise.debuglog", "a");
  1334   1344   #endif
  1335   1345   
  1336   1346       /* Should intercept SIGWINCH. For now, just get the size every time */
................................................................................
  1503   1513           cursorcol = displaycol;
  1504   1514           cursorrow = displayrow;
  1505   1515       }
  1506   1516   
  1507   1517       DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n\n", displaycol, displayrow, cursorcol, cursorrow);
  1508   1518   
  1509   1519       /* (f) show hints */
  1510         -    refreshShowHints(current, buf, current->cols - displaycol);
         1520  +    hint = refreshShowHints(current, buf, current->cols - displaycol, 1);
         1521  +
         1522  +    /* Remember how many many cols are available for insert optimisation */
         1523  +    if (prompt == current->prompt && hint == 0) {
         1524  +        current->availcols = current->cols - displaycol;
         1525  +    }
         1526  +    else {
         1527  +        /* Can't optimise */
         1528  +        current->availcols = 0;
         1529  +    }
  1511   1530   
  1512   1531       refreshEndChars(current);
  1513   1532   
  1514   1533       /* (g) move the cursor to the correct place */
  1515   1534       cursorUp(current, displayrow - cursorrow);
  1516   1535       setCursorPos(current, cursorcol);
  1517   1536   
................................................................................
  1575   1594    */
  1576   1595   static int insert_char(struct current *current, int pos, int ch)
  1577   1596   {
  1578   1597       if (pos >= 0 && pos <= sb_chars(current->buf)) {
  1579   1598           char buf[MAX_UTF8_LEN + 1];
  1580   1599           int offset = utf8_index(sb_str(current->buf), pos);
  1581   1600           int n = utf8_getchars(buf, ch);
         1601  +        int rc = 1;
  1582   1602   
  1583   1603           /* null terminate since sb_insert() requires it */
  1584   1604           buf[n] = 0;
  1585   1605   
  1586         -        /* Optimisation removed - see reason in remove_char() */
  1587         -
         1606  +        /* Now we try to optimise in the simple but very common case that:
         1607  +         * - we are inserting at EOL
         1608  +         * - there are enough columns available
         1609  +         * - no hints are being shown
         1610  +         */
         1611  +        if (pos == current->pos && pos == sb_chars(current->buf)) {
         1612  +            int width = char_display_width(ch);
         1613  +            if (current->availcols > width) {
         1614  +                /* Yes, can optimise */
         1615  +                current->availcols -= width;
         1616  +                rc = 2;
         1617  +            }
         1618  +        }
  1588   1619           sb_insert(current->buf, offset, buf);
  1589   1620           if (current->pos >= pos) {
  1590   1621               current->pos++;
  1591   1622           }
  1592         -        return 1;
         1623  +        if (rc == 2) {
         1624  +            if (refreshShowHints(current, sb_str(current->buf), current->availcols, 0)) {
         1625  +                /* A hint needs to be shown, so can't optimise after all */
         1626  +                rc = 1;
         1627  +            }
         1628  +            else {
         1629  +                /* optimised output */
         1630  +                outputChars(current, buf, n);
         1631  +            }
         1632  +        }
         1633  +        return rc;
  1593   1634       }
  1594   1635       return 0;
  1595   1636   }
  1596   1637   
  1597   1638   /**
  1598   1639    * Captures up to 'n' characters starting at 'pos' for the cut buffer.
  1599   1640    *
................................................................................
  1601   1642    */
  1602   1643   static void capture_chars(struct current *current, int pos, int nchars)
  1603   1644   {
  1604   1645       if (pos >= 0 && (pos + nchars - 1) < sb_chars(current->buf)) {
  1605   1646           int offset = utf8_index(sb_str(current->buf), pos);
  1606   1647           int nbytes = utf8_index(sb_str(current->buf) + offset, nchars);
  1607   1648   
  1608         -        if (nbytes) {
         1649  +        if (nbytes > 0) {
  1609   1650               if (current->capture) {
  1610   1651                   sb_clear(current->capture);
  1611   1652               }
  1612   1653               else {
  1613   1654                   current->capture = sb_alloc();
  1614   1655               }
  1615   1656               sb_append_len(current->capture, sb_str(current->buf) + offset, nbytes);
................................................................................
  1984   2025       }
  1985   2026       return sb_len(current->buf);
  1986   2027   }
  1987   2028   
  1988   2029   int linenoiseColumns(void)
  1989   2030   {
  1990   2031       struct current current;
         2032  +    current.output = NULL;
  1991   2033       enableRawMode (&current);
  1992   2034       getWindowSize (&current);
  1993   2035       disableRawMode (&current);
  1994   2036       return current.cols;
  1995   2037   }
  1996   2038   
  1997   2039   /**