PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/libedit/emacs.c

https://github.com/okuoku/freebsd-head
C | 505 lines | 276 code | 83 blank | 146 comment | 58 complexity | 599bf101fb5b0cf216b00ce6bfca6c94 MD5 | raw file
  1. /*-
  2. * Copyright (c) 1992, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Christos Zoulas of Cornell University.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the University nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $
  33. */
  34. #if !defined(lint) && !defined(SCCSID)
  35. static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
  36. #endif /* not lint && not SCCSID */
  37. #include <sys/cdefs.h>
  38. __FBSDID("$FreeBSD$");
  39. /*
  40. * emacs.c: Emacs functions
  41. */
  42. #include "sys.h"
  43. #include "el.h"
  44. /* em_delete_or_list():
  45. * Delete character under cursor or list completions if at end of line
  46. * [^D]
  47. */
  48. protected el_action_t
  49. /*ARGSUSED*/
  50. em_delete_or_list(EditLine *el, int c)
  51. {
  52. if (el->el_line.cursor == el->el_line.lastchar) {
  53. /* if I'm at the end */
  54. if (el->el_line.cursor == el->el_line.buffer) {
  55. /* and the beginning */
  56. term_writec(el, c); /* then do an EOF */
  57. return (CC_EOF);
  58. } else {
  59. /*
  60. * Here we could list completions, but it is an
  61. * error right now
  62. */
  63. term_beep(el);
  64. return (CC_ERROR);
  65. }
  66. } else {
  67. if (el->el_state.doingarg)
  68. c_delafter(el, el->el_state.argument);
  69. else
  70. c_delafter1(el);
  71. if (el->el_line.cursor > el->el_line.lastchar)
  72. el->el_line.cursor = el->el_line.lastchar;
  73. /* bounds check */
  74. return (CC_REFRESH);
  75. }
  76. }
  77. /* em_delete_next_word():
  78. * Cut from cursor to end of current word
  79. * [M-d]
  80. */
  81. protected el_action_t
  82. /*ARGSUSED*/
  83. em_delete_next_word(EditLine *el, int c __unused)
  84. {
  85. char *cp, *p, *kp;
  86. if (el->el_line.cursor == el->el_line.lastchar)
  87. return (CC_ERROR);
  88. cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  89. el->el_state.argument, ce__isword);
  90. for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
  91. /* save the text */
  92. *kp++ = *p;
  93. el->el_chared.c_kill.last = kp;
  94. c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
  95. if (el->el_line.cursor > el->el_line.lastchar)
  96. el->el_line.cursor = el->el_line.lastchar;
  97. /* bounds check */
  98. return (CC_REFRESH);
  99. }
  100. /* em_yank():
  101. * Paste cut buffer at cursor position
  102. * [^Y]
  103. */
  104. protected el_action_t
  105. /*ARGSUSED*/
  106. em_yank(EditLine *el, int c __unused)
  107. {
  108. char *kp, *cp;
  109. if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
  110. return (CC_NORM);
  111. if (el->el_line.lastchar +
  112. (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
  113. el->el_line.limit)
  114. return (CC_ERROR);
  115. el->el_chared.c_kill.mark = el->el_line.cursor;
  116. cp = el->el_line.cursor;
  117. /* open the space, */
  118. c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
  119. /* copy the chars */
  120. for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
  121. *cp++ = *kp;
  122. /* if an arg, cursor at beginning else cursor at end */
  123. if (el->el_state.argument == 1)
  124. el->el_line.cursor = cp;
  125. return (CC_REFRESH);
  126. }
  127. /* em_kill_line():
  128. * Cut the entire line and save in cut buffer
  129. * [^U]
  130. */
  131. protected el_action_t
  132. /*ARGSUSED*/
  133. em_kill_line(EditLine *el, int c __unused)
  134. {
  135. char *kp, *cp;
  136. cp = el->el_line.buffer;
  137. kp = el->el_chared.c_kill.buf;
  138. while (cp < el->el_line.lastchar)
  139. *kp++ = *cp++; /* copy it */
  140. el->el_chared.c_kill.last = kp;
  141. /* zap! -- delete all of it */
  142. el->el_line.lastchar = el->el_line.buffer;
  143. el->el_line.cursor = el->el_line.buffer;
  144. return (CC_REFRESH);
  145. }
  146. /* em_kill_region():
  147. * Cut area between mark and cursor and save in cut buffer
  148. * [^W]
  149. */
  150. protected el_action_t
  151. /*ARGSUSED*/
  152. em_kill_region(EditLine *el, int c __unused)
  153. {
  154. char *kp, *cp;
  155. if (!el->el_chared.c_kill.mark)
  156. return (CC_ERROR);
  157. if (el->el_chared.c_kill.mark > el->el_line.cursor) {
  158. cp = el->el_line.cursor;
  159. kp = el->el_chared.c_kill.buf;
  160. while (cp < el->el_chared.c_kill.mark)
  161. *kp++ = *cp++; /* copy it */
  162. el->el_chared.c_kill.last = kp;
  163. c_delafter(el, cp - el->el_line.cursor);
  164. } else { /* mark is before cursor */
  165. cp = el->el_chared.c_kill.mark;
  166. kp = el->el_chared.c_kill.buf;
  167. while (cp < el->el_line.cursor)
  168. *kp++ = *cp++; /* copy it */
  169. el->el_chared.c_kill.last = kp;
  170. c_delbefore(el, cp - el->el_chared.c_kill.mark);
  171. el->el_line.cursor = el->el_chared.c_kill.mark;
  172. }
  173. return (CC_REFRESH);
  174. }
  175. /* em_copy_region():
  176. * Copy area between mark and cursor to cut buffer
  177. * [M-W]
  178. */
  179. protected el_action_t
  180. /*ARGSUSED*/
  181. em_copy_region(EditLine *el, int c __unused)
  182. {
  183. char *kp, *cp;
  184. if (!el->el_chared.c_kill.mark)
  185. return (CC_ERROR);
  186. if (el->el_chared.c_kill.mark > el->el_line.cursor) {
  187. cp = el->el_line.cursor;
  188. kp = el->el_chared.c_kill.buf;
  189. while (cp < el->el_chared.c_kill.mark)
  190. *kp++ = *cp++; /* copy it */
  191. el->el_chared.c_kill.last = kp;
  192. } else {
  193. cp = el->el_chared.c_kill.mark;
  194. kp = el->el_chared.c_kill.buf;
  195. while (cp < el->el_line.cursor)
  196. *kp++ = *cp++; /* copy it */
  197. el->el_chared.c_kill.last = kp;
  198. }
  199. return (CC_NORM);
  200. }
  201. /* em_gosmacs_transpose():
  202. * Exchange the two characters before the cursor
  203. * Gosling emacs transpose chars [^T]
  204. */
  205. protected el_action_t
  206. em_gosmacs_transpose(EditLine *el, int c)
  207. {
  208. if (el->el_line.cursor > &el->el_line.buffer[1]) {
  209. /* must have at least two chars entered */
  210. c = el->el_line.cursor[-2];
  211. el->el_line.cursor[-2] = el->el_line.cursor[-1];
  212. el->el_line.cursor[-1] = c;
  213. return (CC_REFRESH);
  214. } else
  215. return (CC_ERROR);
  216. }
  217. /* em_next_word():
  218. * Move next to end of current word
  219. * [M-f]
  220. */
  221. protected el_action_t
  222. /*ARGSUSED*/
  223. em_next_word(EditLine *el, int c __unused)
  224. {
  225. if (el->el_line.cursor == el->el_line.lastchar)
  226. return (CC_ERROR);
  227. el->el_line.cursor = c__next_word(el->el_line.cursor,
  228. el->el_line.lastchar,
  229. el->el_state.argument,
  230. ce__isword);
  231. if (el->el_map.type == MAP_VI)
  232. if (el->el_chared.c_vcmd.action != NOP) {
  233. cv_delfini(el);
  234. return (CC_REFRESH);
  235. }
  236. return (CC_CURSOR);
  237. }
  238. /* em_upper_case():
  239. * Uppercase the characters from cursor to end of current word
  240. * [M-u]
  241. */
  242. protected el_action_t
  243. /*ARGSUSED*/
  244. em_upper_case(EditLine *el, int c __unused)
  245. {
  246. char *cp, *ep;
  247. ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  248. el->el_state.argument, ce__isword);
  249. for (cp = el->el_line.cursor; cp < ep; cp++)
  250. if (islower((unsigned char)*cp))
  251. *cp = toupper((unsigned char)*cp);
  252. el->el_line.cursor = ep;
  253. if (el->el_line.cursor > el->el_line.lastchar)
  254. el->el_line.cursor = el->el_line.lastchar;
  255. return (CC_REFRESH);
  256. }
  257. /* em_capitol_case():
  258. * Capitalize the characters from cursor to end of current word
  259. * [M-c]
  260. */
  261. protected el_action_t
  262. /*ARGSUSED*/
  263. em_capitol_case(EditLine *el, int c __unused)
  264. {
  265. char *cp, *ep;
  266. ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  267. el->el_state.argument, ce__isword);
  268. for (cp = el->el_line.cursor; cp < ep; cp++) {
  269. if (isalpha((unsigned char)*cp)) {
  270. if (islower((unsigned char)*cp))
  271. *cp = toupper((unsigned char)*cp);
  272. cp++;
  273. break;
  274. }
  275. }
  276. for (; cp < ep; cp++)
  277. if (isupper((unsigned char)*cp))
  278. *cp = tolower((unsigned char)*cp);
  279. el->el_line.cursor = ep;
  280. if (el->el_line.cursor > el->el_line.lastchar)
  281. el->el_line.cursor = el->el_line.lastchar;
  282. return (CC_REFRESH);
  283. }
  284. /* em_lower_case():
  285. * Lowercase the characters from cursor to end of current word
  286. * [M-l]
  287. */
  288. protected el_action_t
  289. /*ARGSUSED*/
  290. em_lower_case(EditLine *el, int c __unused)
  291. {
  292. char *cp, *ep;
  293. ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  294. el->el_state.argument, ce__isword);
  295. for (cp = el->el_line.cursor; cp < ep; cp++)
  296. if (isupper((unsigned char)*cp))
  297. *cp = tolower((unsigned char)*cp);
  298. el->el_line.cursor = ep;
  299. if (el->el_line.cursor > el->el_line.lastchar)
  300. el->el_line.cursor = el->el_line.lastchar;
  301. return (CC_REFRESH);
  302. }
  303. /* em_set_mark():
  304. * Set the mark at cursor
  305. * [^@]
  306. */
  307. protected el_action_t
  308. /*ARGSUSED*/
  309. em_set_mark(EditLine *el, int c __unused)
  310. {
  311. el->el_chared.c_kill.mark = el->el_line.cursor;
  312. return (CC_NORM);
  313. }
  314. /* em_exchange_mark():
  315. * Exchange the cursor and mark
  316. * [^X^X]
  317. */
  318. protected el_action_t
  319. /*ARGSUSED*/
  320. em_exchange_mark(EditLine *el, int c __unused)
  321. {
  322. char *cp;
  323. cp = el->el_line.cursor;
  324. el->el_line.cursor = el->el_chared.c_kill.mark;
  325. el->el_chared.c_kill.mark = cp;
  326. return (CC_CURSOR);
  327. }
  328. /* em_universal_argument():
  329. * Universal argument (argument times 4)
  330. * [^U]
  331. */
  332. protected el_action_t
  333. /*ARGSUSED*/
  334. em_universal_argument(EditLine *el, int c __unused)
  335. { /* multiply current argument by 4 */
  336. if (el->el_state.argument > 1000000)
  337. return (CC_ERROR);
  338. el->el_state.doingarg = 1;
  339. el->el_state.argument *= 4;
  340. return (CC_ARGHACK);
  341. }
  342. /* em_meta_next():
  343. * Add 8th bit to next character typed
  344. * [<ESC>]
  345. */
  346. protected el_action_t
  347. /*ARGSUSED*/
  348. em_meta_next(EditLine *el, int c __unused)
  349. {
  350. el->el_state.metanext = 1;
  351. return (CC_ARGHACK);
  352. }
  353. /* em_toggle_overwrite():
  354. * Switch from insert to overwrite mode or vice versa
  355. */
  356. protected el_action_t
  357. /*ARGSUSED*/
  358. em_toggle_overwrite(EditLine *el, int c __unused)
  359. {
  360. el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
  361. MODE_REPLACE : MODE_INSERT;
  362. return (CC_NORM);
  363. }
  364. /* em_copy_prev_word():
  365. * Copy current word to cursor
  366. */
  367. protected el_action_t
  368. /*ARGSUSED*/
  369. em_copy_prev_word(EditLine *el, int c __unused)
  370. {
  371. char *cp, *oldc, *dp;
  372. if (el->el_line.cursor == el->el_line.buffer)
  373. return (CC_ERROR);
  374. oldc = el->el_line.cursor;
  375. /* does a bounds check */
  376. cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
  377. el->el_state.argument, ce__isword);
  378. c_insert(el, oldc - cp);
  379. for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
  380. *dp++ = *cp;
  381. el->el_line.cursor = dp;/* put cursor at end */
  382. return (CC_REFRESH);
  383. }
  384. /* em_inc_search_next():
  385. * Emacs incremental next search
  386. */
  387. protected el_action_t
  388. /*ARGSUSED*/
  389. em_inc_search_next(EditLine *el, int c __unused)
  390. {
  391. el->el_search.patlen = 0;
  392. return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
  393. }
  394. /* em_inc_search_prev():
  395. * Emacs incremental reverse search
  396. */
  397. protected el_action_t
  398. /*ARGSUSED*/
  399. em_inc_search_prev(EditLine *el, int c __unused)
  400. {
  401. el->el_search.patlen = 0;
  402. return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
  403. }
  404. /* em_delete_prev_char():
  405. * Delete the character to the left of the cursor
  406. * [^?]
  407. */
  408. protected el_action_t
  409. /*ARGSUSED*/
  410. em_delete_prev_char(EditLine *el, int c __unused)
  411. {
  412. if (el->el_line.cursor <= el->el_line.buffer)
  413. return (CC_ERROR);
  414. if (el->el_state.doingarg)
  415. c_delbefore(el, el->el_state.argument);
  416. else
  417. c_delbefore1(el);
  418. el->el_line.cursor -= el->el_state.argument;
  419. if (el->el_line.cursor < el->el_line.buffer)
  420. el->el_line.cursor = el->el_line.buffer;
  421. return (CC_REFRESH);
  422. }