mirror of
https://github.com/janet-lang/janet
synced 2024-11-25 09:47:17 +00:00
Make autocompletion more zsh like
Also add a few ctrl sequences from readline, and ignore unknown ctrl sequences. Address #264 Adds Ctrl-n, Ctrl-p, and Ctrl-w Ignores unknown ctrl sequences No alt-* sequences yet.
This commit is contained in:
parent
9f8bc6bb8a
commit
da70807292
@ -301,16 +301,14 @@
|
|||||||
[[binding ctor dtor] & body]
|
[[binding ctor dtor] & body]
|
||||||
~(do
|
~(do
|
||||||
(def ,binding ,ctor)
|
(def ,binding ,ctor)
|
||||||
(defer (,(or dtor :close) ,binding)
|
,(apply defer [(or dtor :close) binding] body)))
|
||||||
,;body)))
|
|
||||||
|
|
||||||
(defmacro when-with
|
(defmacro when-with
|
||||||
"Similar to with, but if binding is false or nil, returns
|
"Similar to with, but if binding is false or nil, returns
|
||||||
nil without evaluating the body. Otherwise, the same as with."
|
nil without evaluating the body. Otherwise, the same as with."
|
||||||
[[binding ctor dtor] & body]
|
[[binding ctor dtor] & body]
|
||||||
~(if-let [,binding ,ctor]
|
~(if-let [,binding ,ctor]
|
||||||
(defer (,(or dtor :close) ,binding)
|
,(apply defer [(or dtor :close) binding] body)))
|
||||||
,;body)))
|
|
||||||
|
|
||||||
(defmacro if-with
|
(defmacro if-with
|
||||||
"Similar to with, but if binding is false or nil, evaluates
|
"Similar to with, but if binding is false or nil, evaluates
|
||||||
@ -318,7 +316,7 @@
|
|||||||
ctor is bound to binding."
|
ctor is bound to binding."
|
||||||
[[binding ctor dtor] truthy &opt falsey ]
|
[[binding ctor dtor] truthy &opt falsey ]
|
||||||
~(if-let [,binding ,ctor]
|
~(if-let [,binding ,ctor]
|
||||||
(defer (,(or dtor :close) ,binding) ,truthy)
|
,(apply defer [(or dtor :close) binding] [truthy])
|
||||||
,falsey))
|
,falsey))
|
||||||
|
|
||||||
(defn- for-template
|
(defn- for-template
|
||||||
|
@ -114,6 +114,7 @@ static JANET_THREAD_LOCAL int gbl_sigint_flag = 0;
|
|||||||
static JANET_THREAD_LOCAL struct termios gbl_termios_start;
|
static JANET_THREAD_LOCAL struct termios gbl_termios_start;
|
||||||
static JANET_THREAD_LOCAL JanetByteView gbl_matches[JANET_MATCH_MAX];
|
static JANET_THREAD_LOCAL JanetByteView gbl_matches[JANET_MATCH_MAX];
|
||||||
static JANET_THREAD_LOCAL int gbl_match_count = 0;
|
static JANET_THREAD_LOCAL int gbl_match_count = 0;
|
||||||
|
static JANET_THREAD_LOCAL int gbl_lines_below = 0;
|
||||||
|
|
||||||
/* Unsupported terminal list from linenoise */
|
/* Unsupported terminal list from linenoise */
|
||||||
static const char *badterms[] = {
|
static const char *badterms[] = {
|
||||||
@ -236,6 +237,17 @@ static void refresh(void) {
|
|||||||
janet_buffer_deinit(&b);
|
janet_buffer_deinit(&b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clearlines(void) {
|
||||||
|
for (int i = 0; i < gbl_lines_below; i++) {
|
||||||
|
fprintf(stderr, "\x1b[1B\x1b[999D\x1b[K");
|
||||||
|
}
|
||||||
|
if (gbl_lines_below) {
|
||||||
|
fprintf(stderr, "\x1b[%dA\x1b[999D", gbl_lines_below);
|
||||||
|
fflush(stderr);
|
||||||
|
gbl_lines_below = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int insert(char c, int draw) {
|
static int insert(char c, int draw) {
|
||||||
if (gbl_len < JANET_LINE_MAX - 1) {
|
if (gbl_len < JANET_LINE_MAX - 1) {
|
||||||
if (gbl_len == gbl_pos) {
|
if (gbl_len == gbl_pos) {
|
||||||
@ -329,12 +341,12 @@ static void kright(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kbackspace(void) {
|
static void kbackspace(int draw) {
|
||||||
if (gbl_pos > 0) {
|
if (gbl_pos > 0) {
|
||||||
memmove(gbl_buf + gbl_pos - 1, gbl_buf + gbl_pos, gbl_len - gbl_pos);
|
memmove(gbl_buf + gbl_pos - 1, gbl_buf + gbl_pos, gbl_len - gbl_pos);
|
||||||
gbl_pos--;
|
gbl_pos--;
|
||||||
gbl_buf[--gbl_len] = '\0';
|
gbl_buf[--gbl_len] = '\0';
|
||||||
refresh();
|
if (draw) refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,15 +506,17 @@ static void kshowcomp(void) {
|
|||||||
int num_cols = getcols();
|
int num_cols = getcols();
|
||||||
if (gbl_match_count >= 2) {
|
if (gbl_match_count >= 2) {
|
||||||
|
|
||||||
norawmode();
|
|
||||||
|
|
||||||
/* Second pass, print */
|
/* Second pass, print */
|
||||||
|
clearlines();
|
||||||
int col_width = maxlen + 4;
|
int col_width = maxlen + 4;
|
||||||
int cols = num_cols / col_width;
|
int cols = num_cols / col_width;
|
||||||
if (cols == 0) cols = 1;
|
if (cols == 0) cols = 1;
|
||||||
int current_col = 0;
|
int current_col = 0;
|
||||||
for (int i = 0; i < gbl_match_count; i++) {
|
for (int i = 0; i < gbl_match_count; i++) {
|
||||||
if (current_col == 0) putc('\n', stderr);
|
if (current_col == 0) {
|
||||||
|
putc('\n', stderr);
|
||||||
|
gbl_lines_below++;
|
||||||
|
}
|
||||||
JanetByteView s = gbl_matches[i];
|
JanetByteView s = gbl_matches[i];
|
||||||
fprintf(stderr, "%s", (const char *) s.bytes);
|
fprintf(stderr, "%s", (const char *) s.bytes);
|
||||||
for (int j = s.len; j < col_width; j++) {
|
for (int j = s.len; j < col_width; j++) {
|
||||||
@ -510,10 +524,11 @@ static void kshowcomp(void) {
|
|||||||
}
|
}
|
||||||
current_col = (current_col + 1) % cols;
|
current_col = (current_col + 1) % cols;
|
||||||
}
|
}
|
||||||
putc('\n', stderr);
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
rawmode();
|
/* Go up to original line (zsh-like autocompletion) */
|
||||||
|
fprintf(stderr, "\x1B[%dA", gbl_lines_below);
|
||||||
|
|
||||||
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,24 +553,9 @@ static int line() {
|
|||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
default:
|
default:
|
||||||
|
if (c < 0x20) break;
|
||||||
if (insert(c, 1)) return -1;
|
if (insert(c, 1)) return -1;
|
||||||
break;
|
break;
|
||||||
case 9: /* tab */
|
|
||||||
kshowcomp();
|
|
||||||
refresh();
|
|
||||||
break;
|
|
||||||
case 13: /* enter */
|
|
||||||
return 0;
|
|
||||||
case 3: /* ctrl-c */
|
|
||||||
errno = EAGAIN;
|
|
||||||
gbl_sigint_flag = 1;
|
|
||||||
return -1;
|
|
||||||
case 127: /* backspace */
|
|
||||||
case 8: /* ctrl-h */
|
|
||||||
kbackspace();
|
|
||||||
break;
|
|
||||||
case 4: /* ctrl-d, eof */
|
|
||||||
return -1;
|
|
||||||
case 1: /* ctrl-a */
|
case 1: /* ctrl-a */
|
||||||
gbl_pos = 0;
|
gbl_pos = 0;
|
||||||
refresh();
|
refresh();
|
||||||
@ -563,6 +563,14 @@ static int line() {
|
|||||||
case 2: /* ctrl-b */
|
case 2: /* ctrl-b */
|
||||||
kleft();
|
kleft();
|
||||||
break;
|
break;
|
||||||
|
case 3: /* ctrl-c */
|
||||||
|
errno = EAGAIN;
|
||||||
|
gbl_sigint_flag = 1;
|
||||||
|
clearlines();
|
||||||
|
return -1;
|
||||||
|
case 4: /* ctrl-d, eof */
|
||||||
|
clearlines();
|
||||||
|
return -1;
|
||||||
case 5: /* ctrl-e */
|
case 5: /* ctrl-e */
|
||||||
gbl_pos = gbl_len;
|
gbl_pos = gbl_len;
|
||||||
refresh();
|
refresh();
|
||||||
@ -570,21 +578,44 @@ static int line() {
|
|||||||
case 6: /* ctrl-f */
|
case 6: /* ctrl-f */
|
||||||
kright();
|
kright();
|
||||||
break;
|
break;
|
||||||
case 21:
|
case 127: /* backspace */
|
||||||
|
case 8: /* ctrl-h */
|
||||||
|
kbackspace(1);
|
||||||
|
break;
|
||||||
|
case 9: /* tab */
|
||||||
|
kshowcomp();
|
||||||
|
refresh();
|
||||||
|
break;
|
||||||
|
case 12: /* ctrl-l */
|
||||||
|
clear();
|
||||||
|
refresh();
|
||||||
|
break;
|
||||||
|
case 13: /* enter */
|
||||||
|
clearlines();
|
||||||
|
return 0;
|
||||||
|
case 14: /* ctrl-n */
|
||||||
|
historymove(-1);
|
||||||
|
break;
|
||||||
|
case 16: /* ctrl-p */
|
||||||
|
historymove(1);
|
||||||
|
break;
|
||||||
|
case 21: /* ctrl-u */
|
||||||
gbl_buf[0] = '\0';
|
gbl_buf[0] = '\0';
|
||||||
gbl_pos = gbl_len = 0;
|
gbl_pos = gbl_len = 0;
|
||||||
refresh();
|
refresh();
|
||||||
break;
|
break;
|
||||||
|
case 23: /* ctrl-w */
|
||||||
|
while (gbl_pos && is_symbol_char_gen(gbl_buf[gbl_pos - 1])) {
|
||||||
|
kbackspace(0);
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
break;
|
||||||
case 26: /* ctrl-z */
|
case 26: /* ctrl-z */
|
||||||
norawmode();
|
norawmode();
|
||||||
kill(getpid(), SIGSTOP);
|
kill(getpid(), SIGSTOP);
|
||||||
rawmode();
|
rawmode();
|
||||||
refresh();
|
refresh();
|
||||||
break;
|
break;
|
||||||
case 12:
|
|
||||||
clear();
|
|
||||||
refresh();
|
|
||||||
break;
|
|
||||||
case 27: /* escape sequence */
|
case 27: /* escape sequence */
|
||||||
/* Read the next two bytes representing the escape sequence.
|
/* Read the next two bytes representing the escape sequence.
|
||||||
* Use two calls to handle slow terminals returning the two
|
* Use two calls to handle slow terminals returning the two
|
||||||
@ -606,6 +637,7 @@ static int line() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
|
/* Single escape sequences */
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
@ -631,6 +663,7 @@ static int line() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (seq[0] == 'O') {
|
} else if (seq[0] == 'O') {
|
||||||
|
/* Alt codes */
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user