1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
10 static char history
[HIST_SIZE
][LINE_LEN
+1]; /* circ buf of nul terminated strings should be more effective */
11 static int hist_len
= 0;
12 static int hist_pos
= -1;
14 static char line
[LINE_LEN
+1];
25 K_BACKSPACE2
= '\x7f',
27 /* below are our made up values */
29 K_VT100_START
= 0x100,
51 static const struct vt100_seq vt100_seqs
[] = {
52 { .key
= K_UP
, .seq
= "[A" },
53 { .key
= K_DOWN
, .seq
= "[B" },
54 { .key
= K_RIGHT
, .seq
= "[C" },
55 { .key
= K_LEFT
, .seq
= "[D" },
56 { .key
= K_END
, .seq
= "[F" },
57 { .key
= K_HOME
, .seq
= "[H" },
58 { .key
= K_INSERT
, .seq
= "[2~" },
59 { .key
= K_DELETE
, .seq
= "[3~" },
60 { .key
= K_PGUP
, .seq
= "[5~" },
61 { .key
= K_PGDN
, .seq
= "[6~" },
65 static int vt100_cmp(const char *seq
, int len
, const char *ntseq
)
69 if (seq
[i
] != ntseq
[i
])
76 /* matched, but the sequence wasn't complete */
81 static const char *vt100_seq(enum vt100_key key
)
84 for (i
=0; i
<ALEN(vt100_seqs
); i
++) {
85 if (vt100_seqs
[i
].key
== key
)
86 return vt100_seqs
[i
].seq
;
92 static enum vt100_key
vt100_match(const char *seq
, int len
)
96 for (i
=0; i
<ALEN(vt100_seqs
); i
++) {
98 m
= vt100_cmp(seq
, len
, vt100_seqs
[i
].seq
);
100 return vt100_seqs
[i
].key
;
108 static void cbashell_command(const char *cmd
)
112 for (i
=0; command_list
[i
]; i
++)
113 if (command_list
[i
](cmd
) != 0)
119 * readline like prompt handling
120 * TODO history should be improved with a circ buf for string storage or sth,
121 * to be more effective.
123 static int cbashell_char(int c
)
125 if (hist_pos
>= 0 && !(c
== K_UP
|| c
== K_DOWN
)) {
126 strcpy(line
, history
[hist_pos
]);
130 if (c
>= ' ' && c
< '\x7f') {
131 /* guard against buffer overflow */
135 memmove(&line
[pos
+1], &line
[pos
], len
-pos
);
141 /* string (overwrites), move back x left */
142 printf("%s\x1b[%iD", &line
[pos
-1], len
-pos
);
149 strcpy(line
, history
[0]);
154 if (hist_len
>= HIST_SIZE
)
155 hist_len
= HIST_SIZE
-1;
157 for (i
=hist_len
-1; i
>=0; i
--)
158 strcpy(history
[i
+1], history
[i
]);
159 strcpy(history
[0], line
);
164 cbashell_command(line
);
171 if (c
== K_BACKSPACE
|| c
== K_BACKSPACE2
) {
173 memmove(&line
[pos
-1], &line
[pos
], len
-pos
);
179 /* move left, clear line right, string, move x left */
180 printf("\x1b[D\x1b[K%s\x1b[%iD", &line
[pos
], len
-pos
);
182 printf("\x1b[D\x1b[K");
188 memmove(&line
[pos
], &line
[pos
+1], len
-pos
-1);
193 /* clear line right, string, move x left */
194 printf("\x1b[K%s\x1b[%iD", &line
[pos
], len
-pos
);
205 printf("\x1b[D"); /* left */
211 printf("\x1b[C"); /* right */
216 printf("\x1b[%iD", pos
); /* left x */
222 printf("\x1b[%iC", len
-pos
); /* right x */
227 if (hist_pos
< hist_len
-1) {
230 printf("\x1b[%iD", pos
); /* left x */
231 printf("\x1b[K%s", history
[hist_pos
]); /* clear line right, print history */
232 len
= pos
= strlen(history
[hist_pos
]);
237 const char *newline
= line
;
240 newline
= history
[hist_pos
];
242 printf("\x1b[%iD", pos
); /* left x */
243 printf("\x1b[K%s", newline
); /* clear line right, print history */
244 len
= pos
= strlen(newline
);
249 printf("\x1b[%iD", pos
); /* left x */
250 printf("\x1b[K"); /* clear line right */
254 if (c
>= K_VT100_START
) {
255 /* debugging print */
256 printf("vt100:%i ", c
);
264 /* partial VT100 parsing, see
265 * http://ascii-table.com/ansi-escape-sequences-vt-100.php
267 int cbashell_charraw(int c
)
269 static int inside_esc
;
275 /* just a silly guard */
276 if (esc_pos
== sizeof(esc
))
280 c
= vt100_match(esc
, esc_pos
);
281 if (c
== K_INVALID
) {
284 r
|= cbashell_char('^');
285 r
|= cbashell_char('[');
286 for (i
=0; i
<esc_pos
; i
++)
287 r
|= cbashell_char(esc
[i
]);
296 return cbashell_char(c
);
305 return cbashell_char(c
);