2
0

readline.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. * QEMU readline utility
  3. *
  4. * Copyright (c) 2003-2004 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "qemu/readline.h"
  26. #include "qemu/ctype.h"
  27. #include "qemu/cutils.h"
  28. #define IS_NORM 0
  29. #define IS_ESC 1
  30. #define IS_CSI 2
  31. #define IS_SS3 3
  32. void readline_show_prompt(ReadLineState *rs)
  33. {
  34. rs->printf_func(rs->opaque, "%s", rs->prompt);
  35. rs->flush_func(rs->opaque);
  36. rs->last_cmd_buf_index = 0;
  37. rs->last_cmd_buf_size = 0;
  38. rs->esc_state = IS_NORM;
  39. }
  40. /* update the displayed command line */
  41. static void readline_update(ReadLineState *rs)
  42. {
  43. int i, delta, len;
  44. if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
  45. memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
  46. for (i = 0; i < rs->last_cmd_buf_index; i++) {
  47. rs->printf_func(rs->opaque, "\033[D");
  48. }
  49. rs->cmd_buf[rs->cmd_buf_size] = '\0';
  50. if (rs->read_password) {
  51. len = strlen(rs->cmd_buf);
  52. for (i = 0; i < len; i++) {
  53. rs->printf_func(rs->opaque, "*");
  54. }
  55. } else {
  56. rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
  57. }
  58. rs->printf_func(rs->opaque, "\033[K");
  59. memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
  60. rs->last_cmd_buf_size = rs->cmd_buf_size;
  61. rs->last_cmd_buf_index = rs->cmd_buf_size;
  62. }
  63. if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
  64. delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
  65. if (delta > 0) {
  66. for (i = 0; i < delta; i++) {
  67. rs->printf_func(rs->opaque, "\033[C");
  68. }
  69. } else {
  70. delta = -delta;
  71. for (i = 0; i < delta; i++) {
  72. rs->printf_func(rs->opaque, "\033[D");
  73. }
  74. }
  75. rs->last_cmd_buf_index = rs->cmd_buf_index;
  76. }
  77. rs->flush_func(rs->opaque);
  78. }
  79. static void readline_insert_char(ReadLineState *rs, int ch)
  80. {
  81. if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
  82. memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
  83. rs->cmd_buf + rs->cmd_buf_index,
  84. rs->cmd_buf_size - rs->cmd_buf_index);
  85. rs->cmd_buf[rs->cmd_buf_index] = ch;
  86. rs->cmd_buf_size++;
  87. rs->cmd_buf_index++;
  88. }
  89. }
  90. static void readline_backward_char(ReadLineState *rs)
  91. {
  92. if (rs->cmd_buf_index > 0) {
  93. rs->cmd_buf_index--;
  94. }
  95. }
  96. static void readline_forward_char(ReadLineState *rs)
  97. {
  98. if (rs->cmd_buf_index < rs->cmd_buf_size) {
  99. rs->cmd_buf_index++;
  100. }
  101. }
  102. static void readline_delete_char(ReadLineState *rs)
  103. {
  104. if (rs->cmd_buf_index < rs->cmd_buf_size) {
  105. memmove(rs->cmd_buf + rs->cmd_buf_index,
  106. rs->cmd_buf + rs->cmd_buf_index + 1,
  107. rs->cmd_buf_size - rs->cmd_buf_index - 1);
  108. rs->cmd_buf_size--;
  109. }
  110. }
  111. static void readline_backspace(ReadLineState *rs)
  112. {
  113. if (rs->cmd_buf_index > 0) {
  114. readline_backward_char(rs);
  115. readline_delete_char(rs);
  116. }
  117. }
  118. static void readline_backword(ReadLineState *rs)
  119. {
  120. int start;
  121. if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
  122. return;
  123. }
  124. start = rs->cmd_buf_index - 1;
  125. /* find first word (backwards) */
  126. while (start > 0) {
  127. if (!qemu_isspace(rs->cmd_buf[start])) {
  128. break;
  129. }
  130. --start;
  131. }
  132. /* find first space (backwards) */
  133. while (start > 0) {
  134. if (qemu_isspace(rs->cmd_buf[start])) {
  135. ++start;
  136. break;
  137. }
  138. --start;
  139. }
  140. /* remove word */
  141. if (start < rs->cmd_buf_index) {
  142. memmove(rs->cmd_buf + start,
  143. rs->cmd_buf + rs->cmd_buf_index,
  144. rs->cmd_buf_size - rs->cmd_buf_index);
  145. rs->cmd_buf_size -= rs->cmd_buf_index - start;
  146. rs->cmd_buf_index = start;
  147. }
  148. }
  149. static void readline_bol(ReadLineState *rs)
  150. {
  151. rs->cmd_buf_index = 0;
  152. }
  153. static void readline_eol(ReadLineState *rs)
  154. {
  155. rs->cmd_buf_index = rs->cmd_buf_size;
  156. }
  157. static void readline_up_char(ReadLineState *rs)
  158. {
  159. int idx;
  160. if (rs->hist_entry == 0) {
  161. return;
  162. }
  163. if (rs->hist_entry == -1) {
  164. /* Find latest entry */
  165. for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
  166. if (rs->history[idx] == NULL) {
  167. break;
  168. }
  169. }
  170. rs->hist_entry = idx;
  171. }
  172. rs->hist_entry--;
  173. if (rs->hist_entry >= 0) {
  174. pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
  175. rs->history[rs->hist_entry]);
  176. rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
  177. }
  178. }
  179. static void readline_down_char(ReadLineState *rs)
  180. {
  181. if (rs->hist_entry == -1) {
  182. return;
  183. }
  184. if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
  185. rs->history[++rs->hist_entry] != NULL) {
  186. pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
  187. rs->history[rs->hist_entry]);
  188. } else {
  189. rs->cmd_buf[0] = 0;
  190. rs->hist_entry = -1;
  191. }
  192. rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
  193. }
  194. static void readline_hist_add(ReadLineState *rs, const char *cmdline)
  195. {
  196. char *hist_entry, *new_entry;
  197. int idx;
  198. if (cmdline[0] == '\0') {
  199. return;
  200. }
  201. new_entry = NULL;
  202. if (rs->hist_entry != -1) {
  203. /* We were editing an existing history entry: replace it */
  204. hist_entry = rs->history[rs->hist_entry];
  205. idx = rs->hist_entry;
  206. if (strcmp(hist_entry, cmdline) == 0) {
  207. goto same_entry;
  208. }
  209. }
  210. /* Search cmdline in history buffers */
  211. for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
  212. hist_entry = rs->history[idx];
  213. if (hist_entry == NULL) {
  214. break;
  215. }
  216. if (strcmp(hist_entry, cmdline) == 0) {
  217. same_entry:
  218. if (idx == READLINE_MAX_CMDS - 1) {
  219. return;
  220. }
  221. new_entry = hist_entry;
  222. /* Put this entry at the end of history */
  223. memmove(&rs->history[idx], &rs->history[idx + 1],
  224. (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
  225. rs->history[READLINE_MAX_CMDS - 1] = NULL;
  226. for (; idx < READLINE_MAX_CMDS; idx++) {
  227. if (rs->history[idx] == NULL) {
  228. break;
  229. }
  230. }
  231. break;
  232. }
  233. }
  234. if (idx == READLINE_MAX_CMDS) {
  235. /* Need to get one free slot */
  236. g_free(rs->history[0]);
  237. memmove(rs->history, &rs->history[1],
  238. (READLINE_MAX_CMDS - 1) * sizeof(char *));
  239. rs->history[READLINE_MAX_CMDS - 1] = NULL;
  240. idx = READLINE_MAX_CMDS - 1;
  241. }
  242. if (new_entry == NULL) {
  243. new_entry = g_strdup(cmdline);
  244. }
  245. rs->history[idx] = new_entry;
  246. rs->hist_entry = -1;
  247. }
  248. /* completion support */
  249. void readline_add_completion(ReadLineState *rs, const char *str)
  250. {
  251. if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
  252. int i;
  253. for (i = 0; i < rs->nb_completions; i++) {
  254. if (!strcmp(rs->completions[i], str)) {
  255. return;
  256. }
  257. }
  258. rs->completions[rs->nb_completions++] = g_strdup(str);
  259. }
  260. }
  261. void readline_add_completion_of(ReadLineState *rs,
  262. const char *pfx, const char *str)
  263. {
  264. if (!strncmp(str, pfx, strlen(pfx))) {
  265. readline_add_completion(rs, str);
  266. }
  267. }
  268. void readline_set_completion_index(ReadLineState *rs, int index)
  269. {
  270. rs->completion_index = index;
  271. }
  272. static int completion_comp(const void *a, const void *b)
  273. {
  274. return strcmp(*(const char **) a, *(const char **) b);
  275. }
  276. static void readline_completion(ReadLineState *rs)
  277. {
  278. int len, i, j, max_width, nb_cols, max_prefix;
  279. char *cmdline;
  280. rs->nb_completions = 0;
  281. cmdline = g_strndup(rs->cmd_buf, rs->cmd_buf_index);
  282. rs->completion_finder(rs->opaque, cmdline);
  283. g_free(cmdline);
  284. /* no completion found */
  285. if (rs->nb_completions <= 0) {
  286. return;
  287. }
  288. if (rs->nb_completions == 1) {
  289. len = strlen(rs->completions[0]);
  290. for (i = rs->completion_index; i < len; i++) {
  291. readline_insert_char(rs, rs->completions[0][i]);
  292. }
  293. /* extra space for next argument. XXX: make it more generic */
  294. if (len > 0 && rs->completions[0][len - 1] != '/') {
  295. readline_insert_char(rs, ' ');
  296. }
  297. } else {
  298. qsort(rs->completions, rs->nb_completions, sizeof(char *),
  299. completion_comp);
  300. rs->printf_func(rs->opaque, "\n");
  301. max_width = 0;
  302. max_prefix = 0;
  303. for (i = 0; i < rs->nb_completions; i++) {
  304. len = strlen(rs->completions[i]);
  305. if (i == 0) {
  306. max_prefix = len;
  307. } else {
  308. if (len < max_prefix) {
  309. max_prefix = len;
  310. }
  311. for (j = 0; j < max_prefix; j++) {
  312. if (rs->completions[i][j] != rs->completions[0][j]) {
  313. max_prefix = j;
  314. }
  315. }
  316. }
  317. if (len > max_width) {
  318. max_width = len;
  319. }
  320. }
  321. if (max_prefix > 0)
  322. for (i = rs->completion_index; i < max_prefix; i++) {
  323. readline_insert_char(rs, rs->completions[0][i]);
  324. }
  325. max_width += 2;
  326. if (max_width < 10) {
  327. max_width = 10;
  328. } else if (max_width > 80) {
  329. max_width = 80;
  330. }
  331. nb_cols = 80 / max_width;
  332. j = 0;
  333. for (i = 0; i < rs->nb_completions; i++) {
  334. rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
  335. if (++j == nb_cols || i == (rs->nb_completions - 1)) {
  336. rs->printf_func(rs->opaque, "\n");
  337. j = 0;
  338. }
  339. }
  340. readline_show_prompt(rs);
  341. }
  342. for (i = 0; i < rs->nb_completions; i++) {
  343. g_free(rs->completions[i]);
  344. }
  345. }
  346. static void readline_clear_screen(ReadLineState *rs)
  347. {
  348. rs->printf_func(rs->opaque, "\033[2J\033[1;1H");
  349. readline_show_prompt(rs);
  350. }
  351. /* return true if command handled */
  352. void readline_handle_byte(ReadLineState *rs, int ch)
  353. {
  354. switch (rs->esc_state) {
  355. case IS_NORM:
  356. switch (ch) {
  357. case 1:
  358. readline_bol(rs);
  359. break;
  360. case 4:
  361. readline_delete_char(rs);
  362. break;
  363. case 5:
  364. readline_eol(rs);
  365. break;
  366. case 9:
  367. readline_completion(rs);
  368. break;
  369. case 12:
  370. readline_clear_screen(rs);
  371. break;
  372. case 10:
  373. case 13:
  374. rs->cmd_buf[rs->cmd_buf_size] = '\0';
  375. if (!rs->read_password) {
  376. readline_hist_add(rs, rs->cmd_buf);
  377. }
  378. rs->printf_func(rs->opaque, "\n");
  379. rs->cmd_buf_index = 0;
  380. rs->cmd_buf_size = 0;
  381. rs->last_cmd_buf_index = 0;
  382. rs->last_cmd_buf_size = 0;
  383. rs->readline_func(rs->opaque, rs->cmd_buf, rs->readline_opaque);
  384. break;
  385. case 23:
  386. /* ^W */
  387. readline_backword(rs);
  388. break;
  389. case 27:
  390. rs->esc_state = IS_ESC;
  391. break;
  392. case 127:
  393. case 8:
  394. readline_backspace(rs);
  395. break;
  396. case 155:
  397. rs->esc_state = IS_CSI;
  398. break;
  399. default:
  400. if (ch >= 32) {
  401. readline_insert_char(rs, ch);
  402. }
  403. break;
  404. }
  405. break;
  406. case IS_ESC:
  407. if (ch == '[') {
  408. rs->esc_state = IS_CSI;
  409. rs->esc_param = 0;
  410. } else if (ch == 'O') {
  411. rs->esc_state = IS_SS3;
  412. rs->esc_param = 0;
  413. } else {
  414. rs->esc_state = IS_NORM;
  415. }
  416. break;
  417. case IS_CSI:
  418. switch (ch) {
  419. case 'A':
  420. case 'F':
  421. readline_up_char(rs);
  422. break;
  423. case 'B':
  424. case 'E':
  425. readline_down_char(rs);
  426. break;
  427. case 'D':
  428. readline_backward_char(rs);
  429. break;
  430. case 'C':
  431. readline_forward_char(rs);
  432. break;
  433. case '0' ... '9':
  434. rs->esc_param = rs->esc_param * 10 + (ch - '0');
  435. goto the_end;
  436. case '~':
  437. switch (rs->esc_param) {
  438. case 1:
  439. readline_bol(rs);
  440. break;
  441. case 3:
  442. readline_delete_char(rs);
  443. break;
  444. case 4:
  445. readline_eol(rs);
  446. break;
  447. }
  448. break;
  449. default:
  450. break;
  451. }
  452. rs->esc_state = IS_NORM;
  453. the_end:
  454. break;
  455. case IS_SS3:
  456. switch (ch) {
  457. case 'F':
  458. readline_eol(rs);
  459. break;
  460. case 'H':
  461. readline_bol(rs);
  462. break;
  463. }
  464. rs->esc_state = IS_NORM;
  465. break;
  466. }
  467. readline_update(rs);
  468. }
  469. void readline_start(ReadLineState *rs, const char *prompt, int read_password,
  470. ReadLineFunc *readline_func, void *opaque)
  471. {
  472. pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
  473. rs->readline_func = readline_func;
  474. rs->readline_opaque = opaque;
  475. rs->read_password = read_password;
  476. readline_restart(rs);
  477. }
  478. void readline_restart(ReadLineState *rs)
  479. {
  480. rs->cmd_buf_index = 0;
  481. rs->cmd_buf_size = 0;
  482. }
  483. const char *readline_get_history(ReadLineState *rs, unsigned int index)
  484. {
  485. if (index >= READLINE_MAX_CMDS) {
  486. return NULL;
  487. }
  488. return rs->history[index];
  489. }
  490. void readline_free(ReadLineState *rs)
  491. {
  492. int i;
  493. if (!rs) {
  494. return;
  495. }
  496. for (i = 0; i < READLINE_MAX_CMDS; i++) {
  497. g_free(rs->history[i]);
  498. }
  499. g_free(rs);
  500. }
  501. ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
  502. ReadLineFlushFunc *flush_func,
  503. void *opaque,
  504. ReadLineCompletionFunc *completion_finder)
  505. {
  506. ReadLineState *rs = g_new0(ReadLineState, 1);
  507. rs->hist_entry = -1;
  508. rs->opaque = opaque;
  509. rs->printf_func = printf_func;
  510. rs->flush_func = flush_func;
  511. rs->completion_finder = completion_finder;
  512. return rs;
  513. }