lua2rtt.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * @File: lua2rtt.c
  3. * @Author: liu2guang
  4. * @Date: 2018-05-06 09:16:56
  5. *
  6. * @LICENSE: https://github.com/liu2guang/lua2rtt/blob/master/LICENSE.
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2018-05-06 liu2guang The first version.
  11. * 2018-07-03 liu2guang Update lua5.1.2->lua5.3.4.
  12. */
  13. #include "lua2rtt.h"
  14. #include "shell.h"
  15. static struct lua2rtt handle = {0};
  16. static rt_uint8_t lua2rtt_getc(void)
  17. {
  18. rt_uint8_t ch = 0;
  19. while(rt_device_read(handle.device, (-1), &ch, 1) != 1)
  20. {
  21. rt_sem_take(&(handle.rx_sem), RT_WAITING_FOREVER);
  22. }
  23. return ch;
  24. }
  25. static rt_err_t lua2rtt_rxcb(rt_device_t dev, rt_size_t size)
  26. {
  27. return rt_sem_release(&(handle.rx_sem));
  28. }
  29. static rt_bool_t lua2rtt_handle_history(const char *prompt)
  30. {
  31. rt_kprintf("\033[2K\r");
  32. rt_kprintf("%s%s", prompt, handle.line);
  33. return RT_FALSE;
  34. }
  35. static void lua2rtt_push_history(void)
  36. {
  37. if(handle.line_position > 0)
  38. {
  39. if(handle.history_count >= LUA2RTT_HISTORY_LINES)
  40. {
  41. if(rt_memcmp(&handle.lua_history[LUA2RTT_HISTORY_LINES-1], handle.line, LUA2RTT_CMD_SIZE))
  42. {
  43. int index;
  44. for(index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
  45. {
  46. rt_memcpy(&handle.lua_history[index][0], &handle.lua_history[index+1][0], LUA2RTT_CMD_SIZE);
  47. }
  48. rt_memset(&handle.lua_history[index][0], 0, LUA2RTT_CMD_SIZE);
  49. rt_memcpy(&handle.lua_history[index][0], handle.line, handle.line_position);
  50. handle.history_count = LUA2RTT_HISTORY_LINES;
  51. }
  52. }
  53. else
  54. {
  55. if(handle.history_count == 0 || rt_memcmp(&handle.lua_history[handle.history_count-1], handle.line, LUA2RTT_CMD_SIZE))
  56. {
  57. handle.history_current = handle.history_count;
  58. rt_memset(&handle.lua_history[handle.history_count][0], 0, LUA2RTT_CMD_SIZE);
  59. rt_memcpy(&handle.lua_history[handle.history_count][0], handle.line, handle.line_position);
  60. handle.history_count++;
  61. }
  62. }
  63. }
  64. handle.history_current = handle.history_count;
  65. }
  66. int lua2rtt_readline(const char *prompt, char *buffer, int buffer_size)
  67. {
  68. rt_uint8_t ch;
  69. start:
  70. rt_kprintf(prompt);
  71. while(1)
  72. {
  73. ch = lua2rtt_getc();
  74. if(ch == 0x1b)
  75. {
  76. handle.stat = LUA2RTT_WAIT_SPEC_KEY;
  77. continue;
  78. }
  79. else if(handle.stat == LUA2RTT_WAIT_SPEC_KEY)
  80. {
  81. if(ch == 0x5b)
  82. {
  83. handle.stat = LUA2RTT_WAIT_FUNC_KEY;
  84. continue;
  85. }
  86. handle.stat = LUA2RTT_WAIT_NORMAL;
  87. }
  88. else if(handle.stat == LUA2RTT_WAIT_FUNC_KEY)
  89. {
  90. handle.stat = LUA2RTT_WAIT_NORMAL;
  91. if(ch == 0x41)
  92. {
  93. if(handle.history_current > 0)
  94. {
  95. handle.history_current--;
  96. }
  97. else
  98. {
  99. handle.history_current = 0;
  100. continue;
  101. }
  102. rt_memcpy(handle.line, &handle.lua_history[handle.history_current][0], LUA2RTT_CMD_SIZE);
  103. handle.line_curpos = handle.line_position = rt_strlen(handle.line);
  104. lua2rtt_handle_history(prompt);
  105. continue;
  106. }
  107. else if(ch == 0x42)
  108. {
  109. if(handle.history_current < (handle.history_count-1))
  110. {
  111. handle.history_current++;
  112. }
  113. else
  114. {
  115. if(handle.history_count != 0)
  116. {
  117. handle.history_current = handle.history_count-1;
  118. }
  119. else
  120. {
  121. continue;
  122. }
  123. }
  124. rt_memcpy(handle.line, &handle.lua_history[handle.history_current][0], LUA2RTT_CMD_SIZE);
  125. handle.line_curpos = handle.line_position = rt_strlen(handle.line);
  126. lua2rtt_handle_history(prompt);
  127. continue;
  128. }
  129. else if(ch == 0x44)
  130. {
  131. if(handle.line_curpos)
  132. {
  133. rt_kprintf("\b");
  134. handle.line_curpos--;
  135. }
  136. continue;
  137. }
  138. else if(ch == 0x43)
  139. {
  140. if(handle.line_curpos < handle.line_position)
  141. {
  142. rt_kprintf("%c", handle.line[handle.line_curpos]);
  143. handle.line_curpos++;
  144. }
  145. continue;
  146. }
  147. }
  148. if(ch == '\0' || ch == 0xFF)
  149. {
  150. continue;
  151. }
  152. else if(ch == 0x7f || ch == 0x08)
  153. {
  154. if(handle.line_curpos == 0)
  155. {
  156. continue;
  157. }
  158. handle.line_curpos--;
  159. handle.line_position--;
  160. if(handle.line_position > handle.line_curpos)
  161. {
  162. rt_memmove(&handle.line[handle.line_curpos], &handle.line[handle.line_curpos+1],
  163. handle.line_position-handle.line_curpos);
  164. handle.line[handle.line_position] = 0;
  165. rt_kprintf("\b%s \b", &handle.line[handle.line_curpos]);
  166. int index;
  167. for(index = (handle.line_curpos); index <= (handle.line_position); index++)
  168. {
  169. rt_kprintf("\b");
  170. }
  171. }
  172. else
  173. {
  174. rt_kprintf("\b \b");
  175. handle.line[handle.line_position] = 0;
  176. }
  177. continue;
  178. }
  179. else if(ch == '\r' || ch == '\n')
  180. {
  181. lua2rtt_push_history();
  182. rt_kprintf("\n");
  183. if(handle.line_position == 0)
  184. {
  185. goto start;
  186. }
  187. else
  188. {
  189. rt_uint8_t temp = handle.line_position;
  190. rt_strncpy(buffer, handle.line, handle.line_position);
  191. rt_memset(handle.line, 0x00, sizeof(handle.line));
  192. buffer[handle.line_position] = 0;
  193. handle.line_curpos = handle.line_position = 0;
  194. return temp;
  195. }
  196. }
  197. else if(ch == 0x04)
  198. {
  199. if(handle.line_position == 0)
  200. {
  201. return 0;
  202. }
  203. else
  204. {
  205. continue;
  206. }
  207. }
  208. else if(ch == '\t')
  209. {
  210. continue;
  211. }
  212. else if(ch < 0x20 || ch >= 0x80)
  213. {
  214. continue;
  215. }
  216. if(handle.line_position >= LUA2RTT_CMD_SIZE)
  217. {
  218. continue;
  219. }
  220. if(handle.line_curpos < handle.line_position)
  221. {
  222. rt_memmove(&handle.line[handle.line_curpos+1], &handle.line[handle.line_curpos],
  223. handle.line_position-handle.line_curpos);
  224. handle.line[handle.line_curpos] = ch;
  225. rt_kprintf("%s", &handle.line[handle.line_curpos]);
  226. int index;
  227. for(index = (handle.line_curpos); index < (handle.line_position); index++)
  228. {
  229. rt_kprintf("\b");
  230. }
  231. }
  232. else
  233. {
  234. handle.line[handle.line_position] = ch;
  235. rt_kprintf("%c", ch);
  236. }
  237. ch = 0;
  238. handle.line_curpos++;
  239. handle.line_position++;
  240. }
  241. }
  242. static void lua2rtt_run(void *p)
  243. {
  244. const char *device_name = RT_CONSOLE_DEVICE_NAME;
  245. handle.device = rt_device_find(device_name);
  246. if(handle.device == RT_NULL)
  247. {
  248. LUA2RTT_DBG("The msh device find failed.\n");
  249. return;
  250. }
  251. handle.rx_indicate = handle.device->rx_indicate;
  252. rt_device_set_rx_indicate(handle.device, lua2rtt_rxcb);
  253. if(handle.argc == 1)
  254. {
  255. rt_kprintf("\nPress CTRL+D to exit Lua.\n");
  256. }
  257. extern int lua_main(int argc, char **argv);
  258. lua_main(handle.argc, handle.argv);
  259. if(handle.argc > 1)
  260. {
  261. rt_free(handle.argv[1]);
  262. }
  263. rt_sem_detach(&(handle.rx_sem));
  264. rt_device_set_rx_indicate(handle.device, handle.rx_indicate);
  265. // rt_kprintf("Exit Lua interactive mode.\n");
  266. rt_kprintf(FINSH_PROMPT);
  267. }
  268. static int lua2rtt(int argc, char **argv)
  269. {
  270. static rt_bool_t history_init = RT_FALSE;
  271. if(history_init == RT_FALSE)
  272. {
  273. rt_memset(&handle, 0x00, sizeof(struct lua2rtt));
  274. history_init = RT_TRUE;
  275. }
  276. else
  277. {
  278. handle.thread = RT_NULL;
  279. handle.stat = LUA2RTT_WAIT_NORMAL;
  280. handle.argc = 0;
  281. handle.argv[0] = RT_NULL;
  282. handle.argv[1] = RT_NULL;
  283. handle.argv[2] = RT_NULL;
  284. rt_memset(handle.line, 0x00, LUA2RTT_CMD_SIZE);
  285. handle.line_position = 0;
  286. handle.line_curpos = 0;
  287. handle.device = RT_NULL;
  288. handle.rx_indicate = RT_NULL;
  289. }
  290. rt_sem_init(&(handle.rx_sem), "lua2rtt_rxsem", 0, RT_IPC_FLAG_FIFO);
  291. handle.argc = argc;
  292. handle.argv[0] = "lua";
  293. handle.argv[1] = RT_NULL;
  294. handle.argv[2] = RT_NULL;
  295. if(argc > 1)
  296. {
  297. rt_size_t len = rt_strlen(argv[1]);
  298. handle.argv[1] = (char *)rt_malloc(len + 1);
  299. rt_memset(handle.argv[1], 0x00, len + 1);
  300. rt_strncpy(handle.argv[1], argv[1], len);
  301. }
  302. rt_uint8_t prio = rt_thread_self()->current_priority+1;
  303. handle.thread = rt_thread_create("lua", lua2rtt_run, RT_NULL, LUA2RTT_THREAD_STACK_SIZE, prio, 10);
  304. if(handle.thread == RT_NULL)
  305. {
  306. rt_sem_detach(&(handle.rx_sem));
  307. LUA2RTT_DBG("The Lua interpreter thread create failed.\n");
  308. return RT_ERROR;
  309. }
  310. rt_thread_startup(handle.thread);
  311. return RT_EOK;
  312. }
  313. MSH_CMD_EXPORT_ALIAS(lua2rtt, lua, Execute Lua parser.);