Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: erlang/otp
base: master
...
head fork: whitelynx/otp
compare: master
Checking mergeability… Don't worry, you can still create the pull request.
  • 9 commits
  • 3 files changed
  • 3 commit comments
  • 1 contributor
Commits on Mar 16, 2012
@whitelynx whitelynx Updated ttsl_drv.c to support escape sequences. (color)
- Removed unused ISPRINT macro from win32/ttsl_drv.c.
- Added UTF8_ISPRINT and ASCII_ISPRINT macros which allow ESC (27), and changed existing isprint calls to use them instead.
9628259
Commits on Mar 17, 2012
@whitelynx whitelynx Added \1 and \2 to the allowed characters so gnu readline-style escap…
…e sequence start and stop markers can be passed.
fe13c0e
@whitelynx whitelynx Added prompt_length to calculate prompt length taking readline-style …
…\1...\2 ignored ranges into account.

This mostly fixes colored shell prompts, though sometimes when going through history, we seem to erase one character too many.
83c6aa0
@whitelynx whitelynx Corrected indentation to match surrounding code. db8b4d1
Commits on Mar 18, 2012
@whitelynx whitelynx Corrected comment for UTF8_ISPRINT and ASCII_ISPRINT. 4343f74
@whitelynx whitelynx Added the ability to customize line-editing key bindings in edlin.
- Added edlin:key_map_func/1 to set a custom key_map function.
- Exported edlin:key_map/2 so you can fall back to the default bindings from user code.
974c016
@whitelynx whitelynx Added the 'backward_kill_line' line-editing command to edlin. fe067b1
Commits on Sep 13, 2012
@whitelynx whitelynx Merge remote-tracking branch 'remotes/upstream/master' 96738c2
Commits on Mar 23, 2013
@whitelynx whitelynx Merged latest from upstream/master. 95388ab
View
103 erts/emulator/drivers/unix/ttsl_drv.c
@@ -89,9 +89,9 @@ static Uint32 *lbuf; /* The current line buffer */
static int llen; /* The current line length */
static int lpos; /* The current "cursor position" in the line buffer */
-/*
+/*
* Tags used in line buffer to show that these bytes represent special characters,
- * Max unicode is 0x0010ffff, so we have lots of place for meta tags...
+ * Max unicode is 0x0010ffff, so we have lots of place for meta tags...
*/
#define CONTROL_TAG 0x10000000U /* Control character, value in first position */
#define ESCAPED_TAG 0x01000000U /* Escaped character, value in first position */
@@ -99,6 +99,15 @@ static int lpos; /* The current "cursor position" in the line buf
#define MAXSIZE (1 << 16)
+/*
+ * Check if a character is printable in either UTF8 mode or ASCII mode.
+ * Includes ESC (27) so that ANSI escape sequences (color, terminal title,
+ * etc.) work, and \1 and \2 so that we can recognize readline-style escape
+ * sequence boundaries.
+ */
+#define UTF8_ISPRINT(ch) (ch == 1 || ch == 2 || ch == 27 || ch >= 128 || isprint(ch))
+#define ASCII_ISPRINT(ch) (ch == 1 || ch == 2 || ch == 27 || (ch <= 255 && isprint(ch)))
+
#define COL(_l) ((_l) % cols)
#define LINE(_l) ((_l) / cols)
@@ -294,7 +303,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
ttysl_out = fdopen(ttysl_fd, "w");
#ifdef PRIMITIVE_UTF8_CHECK
- setlocale(LC_CTYPE, ""); /* Set international environment,
+ setlocale(LC_CTYPE, ""); /* Set international environment,
ignore result */
if (((l = getenv("LC_ALL")) && *l) ||
((l = getenv("LC_CTYPE")) && *l) ||
@@ -302,7 +311,7 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
if (strstr(l, "UTF-8"))
utf8_mode = 1;
}
-
+
#else
l = setlocale(LC_CTYPE, ""); /* Set international environment */
if (l != NULL) {
@@ -330,14 +339,14 @@ static ErlDrvData ttysl_start(ErlDrvPort port, char* buf)
#define DEF_WIDTH 80
static void ttysl_get_window_size(Uint32 *width, Uint32 *height)
{
-#ifdef TIOCGWINSZ
+#ifdef TIOCGWINSZ
struct winsize ws;
if (ioctl(ttysl_fd,TIOCGWINSZ,&ws) == 0) {
*width = (Uint32) ws.ws_col;
*height = (Uint32) ws.ws_row;
- if (*width <= 0)
+ if (*width <= 0)
*width = DEF_WIDTH;
- if (*height <= 0)
+ if (*height <= 0)
*height = DEF_HEIGHT;
return;
}
@@ -345,7 +354,7 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height)
*width = DEF_WIDTH;
*height = DEF_HEIGHT;
}
-
+
static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data,
unsigned int command,
char *buf, ErlDrvSizeT len,
@@ -416,9 +425,9 @@ static int put_utf8(int ch, byte *target, int sz, int *pos)
if (((*pos) + 1) >= sz) {
return -1;
}
- target[(*pos)++] = (((byte) (x >> 6)) |
+ target[(*pos)++] = (((byte) (x >> 6)) |
((byte) 0xC0));
- target[(*pos)++] = (((byte) (x & 0x3F)) |
+ target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x10000) {
if ((x >= 0xD800 && x <= 0xDFFF) ||
@@ -430,32 +439,32 @@ static int put_utf8(int ch, byte *target, int sz, int *pos)
return -1;
}
- target[(*pos)++] = (((byte) (x >> 12)) |
+ target[(*pos)++] = (((byte) (x >> 12)) |
((byte) 0xE0));
- target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
+ target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
((byte) 0x80));
- target[(*pos)++] = (((byte) (x & 0x3F)) |
+ target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x110000) { /* Standard imposed max */
if (((*pos) + 3) >= sz) {
return -1;
}
- target[(*pos)++] = (((byte) (x >> 18)) |
+ target[(*pos)++] = (((byte) (x >> 18)) |
((byte) 0xF0));
- target[(*pos)++] = ((((byte) (x >> 12)) & 0x3F) |
+ target[(*pos)++] = ((((byte) (x >> 12)) & 0x3F) |
((byte) 0x80));
- target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
+ target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
((byte) 0x80));
- target[(*pos)++] = (((byte) (x & 0x3F)) |
+ target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else {
return -1;
}
return 0;
}
-
-static int pick_utf8(byte *s, int sz, int *pos)
+
+static int pick_utf8(byte *s, int sz, int *pos)
{
int size = sz - (*pos);
byte *source;
@@ -476,9 +485,9 @@ static int pick_utf8(byte *s, int sz, int *pos)
return -1;
}
(*pos) += 2;
- unipoint =
+ unipoint =
(((Uint) ((*source) & ((byte) 0x1F))) << 6) |
- ((Uint) (source[1] & ((byte) 0x3F)));
+ ((Uint) (source[1] & ((byte) 0x3F)));
return (int) unipoint;
} else if (((*source) & ((byte) 0xF0)) == 0xE0) {
if (size < 3) {
@@ -489,7 +498,7 @@ static int pick_utf8(byte *s, int sz, int *pos)
(((*source) == 0xE0) && (source[1] < 0xA0)) /* overlong */ ) {
return -1;
}
- if ((((*source) & ((byte) 0xF)) == 0xD) &&
+ if ((((*source) & ((byte) 0xF)) == 0xD) &&
((source[1] & 0x20) != 0)) {
return -1;
}
@@ -498,10 +507,10 @@ static int pick_utf8(byte *s, int sz, int *pos)
return -1;
}
(*pos) += 3;
- unipoint =
+ unipoint =
(((Uint) ((*source) & ((byte) 0xF))) << 12) |
(((Uint) (source[1] & ((byte) 0x3F))) << 6) |
- ((Uint) (source[2] & ((byte) 0x3F)));
+ ((Uint) (source[2] & ((byte) 0x3F)));
return (int) unipoint;
} else if (((*source) & ((byte) 0xF8)) == 0xF0) {
if (size < 4) {
@@ -514,16 +523,16 @@ static int pick_utf8(byte *s, int sz, int *pos)
return -1;
}
if ((((*source) & ((byte)0x7)) > 0x4U) ||
- ((((*source) & ((byte)0x7)) == 0x4U) &&
+ ((((*source) & ((byte)0x7)) == 0x4U) &&
((source[1] & ((byte)0x3F)) > 0xFU))) {
return -1;
}
(*pos) += 4;
- unipoint =
+ unipoint =
(((Uint) ((*source) & ((byte) 0x7))) << 18) |
(((Uint) (source[1] & ((byte) 0x3F))) << 12) |
(((Uint) (source[2] & ((byte) 0x3F))) << 6) |
- ((Uint) (source[3] & ((byte) 0x3F)));
+ ((Uint) (source[3] & ((byte) 0x3F)));
return (int) unipoint;
} else {
return -1;
@@ -533,7 +542,7 @@ static int pick_utf8(byte *s, int sz, int *pos)
}
}
-static int octal_or_hex_positions(Uint c)
+static int octal_or_hex_positions(Uint c)
{
int x = 0;
Uint ch = c;
@@ -574,7 +583,7 @@ static void octal_or_hex_format(Uint ch, byte *buf, int *pos)
while(num--) {
buf[(*pos)++] = ((byte) ((ch >> (3*num)) & 0x7U) + '0');
}
- }
+ }
}
/*
@@ -594,9 +603,9 @@ static int check_buf_size(byte *s, int n)
ch = (int) s[pos];
DEBUGLOG(("Invalid UTF8:%d",ch));
++pos;
- }
+ }
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
- if (ch >= 128 || isprint(ch)) {
+ if (UTF8_ISPRINT(ch)) {
DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch));
size++; /* Buffer contains wide characters... */
} else if (ch == '\t') {
@@ -606,10 +615,10 @@ static int check_buf_size(byte *s, int n)
size += 2;
}
} else {
- if (ch <= 255 && isprint(ch)) {
+ if (ASCII_ISPRINT(ch)) {
DEBUGLOG(("Printable:%d",ch));
size++;
- } else if (ch == '\t')
+ } else if (ch == '\t')
size += 8;
else if (ch >= 128) {
DEBUGLOG(("Non printable:%d",ch));
@@ -621,7 +630,7 @@ static int check_buf_size(byte *s, int n)
}
}
}
-
+
if (size + lpos >= lbuf_size) {
lbuf_size = size + lpos + BUFSIZ;
@@ -636,14 +645,14 @@ static int check_buf_size(byte *s, int n)
static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count)
{
- if (lpos > MAXSIZE)
+ if (lpos > MAXSIZE)
put_chars((byte*)"\n", 1);
switch (buf[0]) {
case OP_PUTC:
DEBUGLOG(("OP: Putc(%lu)",(unsigned long) count-1));
if (check_buf_size((byte*)buf+1, count-1) == 0)
- return;
+ return;
put_chars((byte*)buf+1, count-1);
break;
case OP_MOVE:
@@ -684,7 +693,7 @@ static void ttysl_from_tty(ErlDrvData ttysl_data, ErlDrvEvent fd)
p += utf8buf_size;
utf8buf_size = 0;
}
-
+
if ((i = read((int)(SWord)fd, (char *) p, left)) >= 0) {
if (p != b) {
i += (p - b);
@@ -898,7 +907,7 @@ static int insert_buf(byte *s, int n)
DEBUGLOG(("insert_buf: Invalid UTF8:%d",ch));
++pos;
}
- if ((utf8_mode && (ch >= 128 || isprint(ch))) || (ch <= 255 && isprint(ch))) {
+ if ((utf8_mode && UTF8_ISPRINT(ch)) || ASCII_ISPRINT(ch)) {
DEBUGLOG(("insert_buf: Printable(UTF-8):%d",ch));
lbuf[lpos++] = (Uint32) ch;
} else if (ch >= 128) { /* not utf8 mode */
@@ -932,10 +941,10 @@ static int insert_buf(byte *s, int n)
lbuf[lpos++] = CONTROL_TAG;
}
}
- return lpos - buffpos; /* characters "written" into
+ return lpos - buffpos; /* characters "written" into
current buffer (may be less due to newline) */
}
-
+
/*
@@ -1150,7 +1159,7 @@ static int move_down(int n)
tputs(down, 1, outc);
return TRUE;
}
-
+
/*
* Updates cols if terminal has resized (SIGWINCH). Should be called
@@ -1165,14 +1174,14 @@ static int move_down(int n)
static void update_cols(void)
{
Uint32 width, height;
-
+
if (cols_needs_update) {
cols_needs_update = FALSE;
ttysl_get_window_size(&width, &height);
cols = width;
}
}
-
+
/*
* Put a terminal device into non-canonical mode with ECHO off.
@@ -1236,7 +1245,7 @@ static int tty_init(int fd, int canon, int echo, int sig)
tty_smode.c_iflag &= ~(BRKINT|IGNPAR|ICRNL|IXON|IXANY);
#else
tty_smode.c_iflag &= ~(BRKINT|IGNPAR|ICRNL|IXON);
-#endif
+#endif
tty_smode.c_lflag &= ~(ISIG|IEXTEN);
}
return 0;
@@ -1262,11 +1271,11 @@ static int tty_reset(int fd) /* of terminal device */
if (tcsetattr(fd, TCSANOW, &tty_rmode) < 0)
return(-1);
-
+
return(0);
}
-/*
+/*
* Signal handler to cope with signals so that we can reset the tty
* to the orignal settings
*/
@@ -1285,7 +1294,7 @@ static RETSIGTYPE suspend(int sig)
sys_sigrelease(sig); /* Allow 'sig' to come through */
kill(getpid(), sig); /* Send ourselves the signal */
sys_sigblock(sig); /* Reset to old mask */
- sys_sigset(sig, suspend); /* Reset signal handler */
+ sys_sigset(sig, suspend); /* Reset signal handler */
if (tty_set(ttysl_fd) < 0) {
fprintf(stderr,"Can't set tty raw \n");
View
83 erts/emulator/drivers/win32/ttsl_drv.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
+ *
* Copyright Ericsson AB 1996-2011. All Rights Reserved.
- *
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
/*
@@ -57,9 +57,9 @@ Uint32 *lbuf; /* The current line buffer */
int llen; /* The current line length */
int lpos; /* The current "cursor position" in the line buffer */
-/*
+/*
* Tags used in line buffer to show that these bytes represent special characters,
- * Max unicode is 0x0010ffff, so we have lots of place for meta tags...
+ * Max unicode is 0x0010ffff, so we have lots of place for meta tags...
*/
#define CONTROL_TAG 0x10000000U /* Control character, value in first position */
#define ESCAPED_TAG 0x01000000U /* Escaped character, value in first position */
@@ -67,7 +67,14 @@ int lpos; /* The current "cursor position" in the line buf
#define MAXSIZE (1 << 16)
-#define ISPRINT(c) (isprint(c) || (128+32 <= (c) && (c) < 256))
+/*
+ * Check if a character is printable in either UTF8 mode or ASCII mode.
+ * Includes ESC (27) so that ANSI escape sequences (color, terminal title,
+ * etc.) work, and \1 and \2 so that we can recognize readline-style escape
+ * sequence boundaries.
+ */
+#define UTF8_ISPRINT(ch) (ch == 1 || ch == 2 || ch == 27 || ch >= 128 || isprint(ch))
+#define ASCII_ISPRINT(ch) (ch == 1 || ch == 2 || ch == 27 || (ch <= 255 && isprint(ch)))
#define DEBUGLOG(X) /* nothing */
@@ -165,7 +172,7 @@ static void ttysl_get_window_size(Uint32 *width, Uint32 *height)
*width = ConGetColumns();
*height = ConGetRows();
}
-
+
static ErlDrvSSizeT ttysl_control(ErlDrvData drv_data,
unsigned int command,
@@ -233,9 +240,9 @@ static int put_utf8(int ch, byte *target, int sz, int *pos)
if (((*pos) + 1) >= sz) {
return -1;
}
- target[(*pos)++] = (((byte) (x >> 6)) |
+ target[(*pos)++] = (((byte) (x >> 6)) |
((byte) 0xC0));
- target[(*pos)++] = (((byte) (x & 0x3F)) |
+ target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x10000) {
if ((x >= 0xD800 && x <= 0xDFFF) ||
@@ -247,32 +254,32 @@ static int put_utf8(int ch, byte *target, int sz, int *pos)
return -1;
}
- target[(*pos)++] = (((byte) (x >> 12)) |
+ target[(*pos)++] = (((byte) (x >> 12)) |
((byte) 0xE0));
- target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
+ target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
((byte) 0x80));
- target[(*pos)++] = (((byte) (x & 0x3F)) |
+ target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else if (x < 0x110000) { /* Standard imposed max */
if (((*pos) + 3) >= sz) {
return -1;
}
- target[(*pos)++] = (((byte) (x >> 18)) |
+ target[(*pos)++] = (((byte) (x >> 18)) |
((byte) 0xF0));
- target[(*pos)++] = ((((byte) (x >> 12)) & 0x3F) |
+ target[(*pos)++] = ((((byte) (x >> 12)) & 0x3F) |
((byte) 0x80));
- target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
+ target[(*pos)++] = ((((byte) (x >> 6)) & 0x3F) |
((byte) 0x80));
- target[(*pos)++] = (((byte) (x & 0x3F)) |
+ target[(*pos)++] = (((byte) (x & 0x3F)) |
((byte) 0x80));
} else {
return -1;
}
return 0;
}
-
-static int pick_utf8(byte *s, int sz, int *pos)
+
+static int pick_utf8(byte *s, int sz, int *pos)
{
int size = sz - (*pos);
byte *source;
@@ -293,9 +300,9 @@ static int pick_utf8(byte *s, int sz, int *pos)
return -1;
}
(*pos) += 2;
- unipoint =
+ unipoint =
(((Uint) ((*source) & ((byte) 0x1F))) << 6) |
- ((Uint) (source[1] & ((byte) 0x3F)));
+ ((Uint) (source[1] & ((byte) 0x3F)));
return (int) unipoint;
} else if (((*source) & ((byte) 0xF0)) == 0xE0) {
if (size < 3) {
@@ -306,7 +313,7 @@ static int pick_utf8(byte *s, int sz, int *pos)
(((*source) == 0xE0) && (source[1] < 0xA0)) /* overlong */ ) {
return -1;
}
- if ((((*source) & ((byte) 0xF)) == 0xD) &&
+ if ((((*source) & ((byte) 0xF)) == 0xD) &&
((source[1] & 0x20) != 0)) {
return -1;
}
@@ -315,10 +322,10 @@ static int pick_utf8(byte *s, int sz, int *pos)
return -1;
}
(*pos) += 3;
- unipoint =
+ unipoint =
(((Uint) ((*source) & ((byte) 0xF))) << 12) |
(((Uint) (source[1] & ((byte) 0x3F))) << 6) |
- ((Uint) (source[2] & ((byte) 0x3F)));
+ ((Uint) (source[2] & ((byte) 0x3F)));
return (int) unipoint;
} else if (((*source) & ((byte) 0xF8)) == 0xF0) {
if (size < 4) {
@@ -331,16 +338,16 @@ static int pick_utf8(byte *s, int sz, int *pos)
return -1;
}
if ((((*source) & ((byte)0x7)) > 0x4U) ||
- ((((*source) & ((byte)0x7)) == 0x4U) &&
+ ((((*source) & ((byte)0x7)) == 0x4U) &&
((source[1] & ((byte)0x3F)) > 0xFU))) {
return -1;
}
(*pos) += 4;
- unipoint =
+ unipoint =
(((Uint) ((*source) & ((byte) 0x7))) << 18) |
(((Uint) (source[1] & ((byte) 0x3F))) << 12) |
(((Uint) (source[2] & ((byte) 0x3F))) << 6) |
- ((Uint) (source[3] & ((byte) 0x3F)));
+ ((Uint) (source[3] & ((byte) 0x3F)));
return (int) unipoint;
} else {
return -1;
@@ -350,7 +357,7 @@ static int pick_utf8(byte *s, int sz, int *pos)
}
}
-static int octal_or_hex_positions(Uint c)
+static int octal_or_hex_positions(Uint c)
{
int x = 0;
Uint ch = c;
@@ -391,7 +398,7 @@ static void octal_or_hex_format(Uint ch, byte *buf, int *pos)
while(num--) {
buf[(*pos)++] = ((byte) ((ch >> (3*num)) & 0x7U) + '0');
}
- }
+ }
}
/*
@@ -411,9 +418,9 @@ static int check_buf_size(byte *s, int n)
ch = (int) s[pos];
DEBUGLOG(("Invalid UTF8:%d",ch));
++pos;
- }
+ }
if (utf8_mode) { /* That is, terminal is UTF8 compliant */
- if (ch >= 128 || isprint(ch)) {
+ if (UTF8_ISPRINT(ch)) {
DEBUGLOG(("Printable(UTF-8:%d):%d",(pos - opos),ch));
size++; /* Buffer contains wide characters... */
} else if (ch == '\t') {
@@ -423,10 +430,10 @@ static int check_buf_size(byte *s, int n)
size += 2;
}
} else {
- if (ch <= 255 && isprint(ch)) {
+ if (ASCII_ISPRINT(ch)) {
DEBUGLOG(("Printable:%d",ch));
size++;
- } else if (ch == '\t')
+ } else if (ch == '\t')
size += 8;
else if (ch >= 128) {
DEBUGLOG(("Non printable:%d",ch));
@@ -438,7 +445,7 @@ static int check_buf_size(byte *s, int n)
}
}
}
-
+
if (size + lpos >= lbuf_size) {
lbuf_size = size + lpos + BUFSIZ;
@@ -453,14 +460,14 @@ static int check_buf_size(byte *s, int n)
static void ttysl_from_erlang(ErlDrvData ttysl_data, char* buf, ErlDrvSizeT count)
{
- if (lpos > MAXSIZE)
+ if (lpos > MAXSIZE)
put_chars((byte*)"\n", 1);
switch (buf[0]) {
case OP_PUTC:
DEBUGLOG(("OP: Putc(%I64u)",(unsigned long long)count-1));
if (check_buf_size((byte*)buf+1, count-1) == 0)
- return;
+ return;
put_chars((byte*)buf+1, count-1);
break;
case OP_MOVE:
@@ -669,7 +676,7 @@ static int insert_buf(byte *s, int n)
DEBUGLOG(("insert_buf: Invalid UTF8:%d",ch));
++pos;
}
- if ((utf8_mode && (ch >= 128 || isprint(ch))) || (ch <= 255 && isprint(ch))) {
+ if ((utf8_mode && UTF8_ISPRINT(ch)) || ASCII_ISPRINT(ch)) {
DEBUGLOG(("insert_buf: Printable(UTF-8):%d",ch));
lbuf[lpos++] = (Uint32) ch;
} else if (ch >= 128) { /* not utf8 mode */
@@ -699,7 +706,7 @@ static int insert_buf(byte *s, int n)
lbuf[lpos++] = CONTROL_TAG;
}
}
- return lpos - buffpos; /* characters "written" into
+ return lpos - buffpos; /* characters "written" into
current buffer (may be less due to newline) */
}
static int write_buf(Uint32 *s, int n)
View
68 lib/stdlib/src/edlin.erl
@@ -26,6 +26,7 @@
-export([erase_line/1,erase_inp/1,redraw_line/1]).
-export([length_before/1,length_after/1,prompt/1]).
-export([current_line/1, current_chars/1]).
+-export([key_map/2, key_map_func/1]).
%%-export([expand/1]).
-export([edit_line1/2]).
@@ -34,6 +35,8 @@
-export([over_word/3]).
+-define(DEF_KEY_MAP_FUNC, default).
+
%% A Continuation has the structure:
%% {line,Prompt,CurrentLine,EditPrefix}
@@ -43,6 +46,13 @@
%% the editor.
init() ->
+ KeyMapFun = case application:get_env(stdlib, edlin_key_map_func) of
+ {ok,Fun} ->
+ Fun;
+ _ ->
+ default
+ end,
+ put(key_map_func, KeyMapFun),
put(kill_buffer, []).
%% start(Prompt)
@@ -75,8 +85,9 @@ edit_line1(Cs, {line,P,L,M}) ->
edit([C|Cs], P, Line, {blink,_}, [_|Rs]) -> %Remove blink here
edit([C|Cs], P, Line, none, Rs);
-edit([C|Cs], P, {Bef,Aft}, Prefix, Rs0) ->
- case key_map(C, Prefix) of
+edit([C|Rest], P, {Bef,Aft}, Prefix, Rs0) ->
+ {Mapped, Cs} = wrap_key_map(C, Rest, Prefix),
+ case Mapped of
meta ->
edit(Cs, P, {Bef,Aft}, meta, Rs0);
meta_left_sq_bracket ->
@@ -158,10 +169,39 @@ prefix_arg(none) -> 1;
prefix_arg({ctlu,N}) -> N;
prefix_arg(N) -> N.
+%% Set the key map function to use for shell input.
+-spec key_map_func(KeyMapFunc) -> KeyMapFunc when
+ KeyMapFunc :: 'default' | {module(),atom()}.
+
+key_map_func(KeyMapFunc) ->
+ Prev = case application:get_env(stdlib, edlin_key_map_func) of
+ undefined ->
+ ?DEF_KEY_MAP_FUNC;
+ {ok, Old} ->
+ Old
+ end,
+ application_controller:set_env(stdlib, edlin_key_map_func, KeyMapFunc),
+ Prev.
+
+%% wrap_key_map(Char, RemainingCharacters, Prefix)
+%% Wrap key_map or another key-mapping function so we can push keywords
+%% without requiring user key map functions to implement it.
+
+wrap_key_map(A, _, _) when is_atom(A) -> A; % so we can push keywords
+wrap_key_map(C, Cs, Prefix) ->
+ KeyMapFun = case get(key_map_func) of
+ ?DEF_KEY_MAP_FUNC ->
+ fun key_map/3;
+ Fun ->
+ Fun
+ end,
+ KeyMapFun(C, Cs, Prefix).
+
+key_map(C, Cs, Prefix) -> {key_map(C, Prefix),Cs}.
+
%% key_map(Char, Prefix)
%% Map a character and a prefix to an action.
-key_map(A, _) when is_atom(A) -> A; % so we can push keywords
key_map($\^A, none) -> beginning_of_line;
key_map($\^B, none) -> backward_char;
key_map($\^D, none) -> forward_delete_char;
@@ -337,6 +377,9 @@ do_op(backward_kill_word, Bef0, Aft, Rs) ->
do_op(kill_line, Bef, Aft, Rs) ->
put(kill_buffer, Aft),
{{Bef,[]},[{delete_chars,length(Aft)}|Rs]};
+do_op(backward_kill_line, Bef, Aft, Rs) ->
+ put(kill_buffer, Bef),
+ {{[],Aft},[{delete_chars,-length(Bef)}|Rs]};
do_op(yank, Bef, [], Rs) ->
Kill = get(kill_buffer),
{{reverse(Kill, Bef),[]},[{put_chars, unicode,Kill}|Rs]};
@@ -527,7 +570,7 @@ erase_inp({line,_,{Bef,Aft},_}) ->
reverse(erase([], Bef, Aft, [])).
erase(Pbs, Bef, Aft, Rs) ->
- [{delete_chars,-length(Pbs)-length(Bef)},{delete_chars,length(Aft)}|Rs].
+ [{delete_chars,-prompt_length(Pbs)-length(Bef)},{delete_chars,length(Aft)}|Rs].
redraw_line({line,Pbs,{Bef,Aft},_}) ->
reverse(redraw(Pbs, Bef, Aft, [])).
@@ -541,6 +584,23 @@ length_before({line,Pbs,{Bef,_Aft},_}) ->
length_after({line,_,{_Bef,Aft},_}) ->
length(Aft).
+%% prompt_length(Pbs) ->
+%% Length
+%% Calculate the length of a prompt string, ignoring characters between \1 and
+%% \2, like readline.
+prompt_length(Pbs) ->
+ case string:chr(Pbs, 1) of
+ 0 ->
+ length(Pbs);
+ NextIgnorePos ->
+ case string:chr(Pbs, 2) of
+ 0 ->
+ NextIgnorePos - 1;
+ NextResumePos ->
+ NextIgnorePos - 1 + prompt_length(string:substr(Pbs, NextResumePos + 1))
+ end
+ end.
+
prompt({line,Pbs,_,_}) ->
Pbs.

Showing you all comments on commits in this comparison.

@yrashk

Hi, have you tried submitting this to the OTP team? Would be lovely to have this in the next release!

@whitelynx

No, I haven't yet... I've been preoccupied with other projects. I'll try and get a pull request put together soon, though.

@yrashk

They don't do pull requests — they accept patches over erlang-patches (http://erlang.org/mailman/listinfo/erlang-patches) mailing list.

Something went wrong with that request. Please try again.