vi.py 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. # -*- coding: utf-8 -*-
  2. # *****************************************************************************
  3. # Copyright (C) 2003-2006 Gary Bishop.
  4. # Copyright (C) 2006-2020 Michael Graz. <mgraz@plan10.com>
  5. # Copyright (C) 2006-2020 Jorgen Stenarson. <jorgen.stenarson@bostream.nu>
  6. # Copyright (C) 2020 Bassem Girgis. <brgirgis@gmail.com>
  7. #
  8. # Distributed under the terms of the BSD License. The full license is in
  9. # the file COPYING, distributed as part of this software.
  10. # *****************************************************************************
  11. import os
  12. import pyreadline3.lineeditor.lineobj as lineobj
  13. from pyreadline3.logger import log
  14. from . import basemode
  15. class ViMode(basemode.BaseMode):
  16. mode = "vi"
  17. def __init__(self, rlobj):
  18. super().__init__(rlobj)
  19. self.__vi_insert_mode = None
  20. def __repr__(self):
  21. return "<ViMode>"
  22. def process_keyevent(self, keyinfo):
  23. def nop(e):
  24. pass
  25. keytuple = keyinfo.tuple()
  26. # Process exit keys. Only exit on empty line
  27. if keytuple in self.exit_dispatch:
  28. if lineobj.EndOfLine(self.l_buffer) == 0:
  29. raise EOFError
  30. dispatch_func = self.key_dispatch.get(keytuple, self.vi_key)
  31. log("readline from keyboard:%s->%s" % (keytuple, dispatch_func))
  32. r = None
  33. if dispatch_func:
  34. r = dispatch_func(keyinfo)
  35. self.l_buffer.push_undo()
  36. self.previous_func = dispatch_func
  37. if r:
  38. self._update_line()
  39. return True
  40. return False
  41. # Methods below here are bindable emacs functions
  42. def init_editing_mode(self, e): # (M-C-j)
  43. """Initialize vi editingmode"""
  44. self.show_all_if_ambiguous = "on"
  45. self.key_dispatch = {}
  46. self.__vi_insert_mode = None
  47. self._vi_command = None
  48. self._vi_command_edit = None
  49. self._vi_key_find_char = None
  50. self._vi_key_find_direction = True
  51. self._vi_yank_buffer = None
  52. self._vi_multiplier1 = ""
  53. self._vi_multiplier2 = ""
  54. self._vi_undo_stack = []
  55. self._vi_undo_cursor = -1
  56. self._vi_current = None
  57. self._vi_search_text = ""
  58. self._vi_search_position = 0
  59. self.vi_save_line()
  60. self.vi_set_insert_mode(True)
  61. # make ' ' to ~ self insert
  62. for c in range(ord(" "), 127):
  63. self._bind_key("%s" % chr(c), self.vi_key)
  64. self._bind_key("BackSpace", self.vi_backspace)
  65. self._bind_key("Escape", self.vi_escape)
  66. self._bind_key("Return", self.vi_accept_line)
  67. self._bind_key("Left", self.backward_char)
  68. self._bind_key("Right", self.forward_char)
  69. self._bind_key("Home", self.beginning_of_line)
  70. self._bind_key("End", self.end_of_line)
  71. self._bind_key("Delete", self.delete_char)
  72. self._bind_key("Control-d", self.vi_eof)
  73. self._bind_key("Control-z", self.vi_eof)
  74. self._bind_key("Control-r", self.vi_redo)
  75. self._bind_key("Up", self.vi_arrow_up)
  76. self._bind_key("Control-p", self.vi_up)
  77. self._bind_key("Down", self.vi_arrow_down)
  78. self._bind_key("Control-n", self.vi_down)
  79. self._bind_key("Tab", self.vi_complete)
  80. # self._bind_key('Control-e', self.emacs)
  81. def vi_key(self, e):
  82. if not self._vi_command:
  83. self._vi_command = ViCommand(self)
  84. elif self._vi_command.is_end:
  85. if self._vi_command.is_edit:
  86. self._vi_command_edit = self._vi_command
  87. self._vi_command = ViCommand(self)
  88. self._vi_command.add_char(e.char)
  89. def vi_error(self):
  90. self._bell()
  91. def vi_get_is_insert_mode(self):
  92. return self.__vi_insert_mode
  93. vi_is_insert_mode = property(vi_get_is_insert_mode)
  94. def vi_escape(self, e):
  95. if self.vi_is_insert_mode:
  96. if self._vi_command:
  97. self._vi_command.add_char(e.char)
  98. else:
  99. self._vi_command = ViCommand(self)
  100. self.vi_set_insert_mode(False)
  101. self.l_buffer.point = lineobj.PrevChar
  102. elif self._vi_command and self._vi_command.is_replace_one:
  103. self._vi_command.add_char(e.char)
  104. else:
  105. self.vi_error()
  106. def vi_backspace(self, e):
  107. if self._vi_command:
  108. self._vi_command.add_char(e.char)
  109. else:
  110. self._vi_do_backspace(self._vi_command)
  111. def _vi_do_backspace(self, vi_cmd):
  112. if self.vi_is_insert_mode or (self._vi_command and self._vi_command.is_search):
  113. if self.l_buffer.point > 0:
  114. self.l_buffer.point -= 1
  115. if self.l_buffer.overwrite:
  116. try:
  117. prev = self._vi_undo_stack[self._vi_undo_cursor][1][
  118. self.l_buffer.point
  119. ]
  120. self.l_buffer.line_buffer[self.l_buffer.point] = prev
  121. except IndexError:
  122. del self.l_buffer.line_buffer[self.l_buffer.point]
  123. else:
  124. self.vi_save_line()
  125. del self.l_buffer.line_buffer[self.l_buffer.point]
  126. def vi_accept_line(self, e):
  127. if self._vi_command and self._vi_command.is_search:
  128. self._vi_command.do_search()
  129. return False
  130. self._vi_command = None
  131. self.vi_set_insert_mode(True)
  132. self._vi_undo_stack = []
  133. self._vi_undo_cursor = -1
  134. self._vi_current = None
  135. if self.l_buffer.line_buffer:
  136. self.add_history(self.l_buffer.copy())
  137. return self.accept_line(e)
  138. def vi_eof(self, e):
  139. raise EOFError
  140. def vi_set_insert_mode(self, value):
  141. if self.__vi_insert_mode == value:
  142. return
  143. self.__vi_insert_mode = value
  144. if value:
  145. self.vi_save_line()
  146. self.cursor_size = 25
  147. else:
  148. self.cursor_size = 100
  149. def vi_undo_restart(self):
  150. tpl_undo = (
  151. self.l_buffer.point,
  152. self.l_buffer.line_buffer[:],
  153. )
  154. self._vi_undo_stack = [tpl_undo]
  155. self._vi_undo_cursor = 0
  156. def vi_save_line(self):
  157. if self._vi_undo_stack and self._vi_undo_cursor >= 0:
  158. del self._vi_undo_stack[self._vi_undo_cursor + 1 :]
  159. # tpl_undo = (self.l_buffer.point, self.l_buffer[:], )
  160. tpl_undo = (
  161. self.l_buffer.point,
  162. self.l_buffer.line_buffer[:],
  163. )
  164. if (
  165. not self._vi_undo_stack
  166. or self._vi_undo_stack[self._vi_undo_cursor][1] != tpl_undo[1]
  167. ):
  168. self._vi_undo_stack.append(tpl_undo)
  169. self._vi_undo_cursor += 1
  170. def vi_undo_prepare(self):
  171. if self._vi_undo_cursor == len(self._vi_undo_stack) - 1:
  172. self.vi_save_line()
  173. def vi_undo(self, do_pop=True):
  174. self.vi_undo_prepare()
  175. if not self._vi_undo_stack or self._vi_undo_cursor <= 0:
  176. self.vi_error()
  177. return
  178. self._vi_undo_cursor -= 1
  179. self.vi_undo_assign()
  180. def vi_undo_all(self):
  181. self.vi_undo_prepare()
  182. if self._vi_undo_cursor > 0:
  183. self._vi_undo_cursor = 0
  184. self.vi_undo_assign()
  185. else:
  186. self.vi_error()
  187. def vi_undo_assign(self):
  188. tpl_undo = self._vi_undo_stack[self._vi_undo_cursor]
  189. self.l_buffer.line_buffer = tpl_undo[1][:]
  190. self.l_buffer.point = tpl_undo[0]
  191. def vi_redo(self, e):
  192. if self._vi_undo_cursor >= len(self._vi_undo_stack) - 1:
  193. self.vi_error()
  194. return
  195. self._vi_undo_cursor += 1
  196. self.vi_undo_assign()
  197. def vi_search(self, rng):
  198. for i in rng:
  199. line_history = self._history.history[i]
  200. pos = line_history.get_line_text().find(self._vi_search_text)
  201. if pos >= 0:
  202. self._vi_search_position = i
  203. self._history.history_cursor = i
  204. self.l_buffer.line_buffer = list(line_history.line_buffer)
  205. self.l_buffer.point = pos
  206. self.vi_undo_restart()
  207. return True
  208. self._bell()
  209. return False
  210. def vi_search_first(self):
  211. text = "".join(self.l_buffer.line_buffer[1:])
  212. if text:
  213. self._vi_search_text = text
  214. self._vi_search_position = len(self._history.history) - 1
  215. elif self._vi_search_text:
  216. self._vi_search_position -= 1
  217. else:
  218. self.vi_error()
  219. self.vi_undo()
  220. return
  221. if not self.vi_search(list(range(self._vi_search_position, -1, -1))):
  222. # Here: search text not found
  223. self.vi_undo()
  224. def vi_search_again_backward(self):
  225. self.vi_search(list(range(self._vi_search_position - 1, -1, -1)))
  226. def vi_search_again_forward(self):
  227. self.vi_search(
  228. list(range(self._vi_search_position + 1, len(self._history.history)))
  229. )
  230. def vi_up(self, e):
  231. if self._history.history_cursor == len(self._history.history):
  232. self._vi_current = self.l_buffer.line_buffer[:]
  233. # self._history.previous_history (e)
  234. self._history.previous_history(self.l_buffer)
  235. if self.vi_is_insert_mode:
  236. self.end_of_line(e)
  237. else:
  238. self.beginning_of_line(e)
  239. self.vi_undo_restart()
  240. def vi_down(self, e):
  241. if self._history.history_cursor >= len(self._history.history):
  242. self.vi_error()
  243. return
  244. if self._history.history_cursor < len(self._history.history) - 1:
  245. # self._history.next_history (e)
  246. self._history.next_history(self.l_buffer)
  247. if self.vi_is_insert_mode:
  248. self.end_of_line(e)
  249. else:
  250. self.beginning_of_line(e)
  251. self.vi_undo_restart()
  252. elif self._vi_current is not None:
  253. self._history.history_cursor = len(self._history.history)
  254. self.l_buffer.line_buffer = self._vi_current
  255. self.end_of_line(e)
  256. if not self.vi_is_insert_mode and self.l_buffer.point > 0:
  257. self.l_buffer.point -= 1
  258. self._vi_current = None
  259. else:
  260. self.vi_error()
  261. return
  262. def vi_arrow_up(self, e):
  263. self.vi_set_insert_mode(True)
  264. self.vi_up(e)
  265. self.vi_save_line()
  266. def vi_arrow_down(self, e):
  267. self.vi_set_insert_mode(True)
  268. self.vi_down(e)
  269. self.vi_save_line()
  270. def vi_complete(self, e):
  271. text = self.l_buffer.get_line_text()
  272. if text and not text.isspace():
  273. return self.complete(e)
  274. else:
  275. return self.vi_key(e)
  276. # vi input states
  277. # sequence of possible states are in the order below
  278. _VI_BEGIN = "vi_begin"
  279. _VI_MULTI1 = "vi_multi1"
  280. _VI_ACTION = "vi_action"
  281. _VI_MULTI2 = "vi_multi2"
  282. _VI_MOTION = "vi_motion"
  283. _VI_MOTION_ARGUMENT = "vi_motion_argument"
  284. _VI_REPLACE_ONE = "vi_replace_one"
  285. _VI_TEXT = "vi_text"
  286. _VI_SEARCH = "vi_search"
  287. _VI_END = "vi_end"
  288. # vi helper class
  289. class ViCommand:
  290. def __init__(self, readline):
  291. self.readline = readline
  292. self.lst_char = []
  293. self.state = _VI_BEGIN
  294. self.action = self.movement
  295. self.motion = None
  296. self.motion_argument = None
  297. self.text = None
  298. self.pos_motion = None
  299. self.is_edit = False
  300. self.is_overwrite = False
  301. self.is_error = False
  302. self.is_star = False
  303. self.delete_left = 0
  304. self.delete_right = 0
  305. self.readline._vi_multiplier1 = ""
  306. self.readline._vi_multiplier2 = ""
  307. self.set_override_multiplier(0)
  308. self.skip_multipler = False
  309. self.tabstop = 4
  310. self.dct_fcn = {
  311. ord("$"): self.key_dollar,
  312. ord("^"): self.key_hat,
  313. ord(";"): self.key_semicolon,
  314. ord(","): self.key_comma,
  315. ord("%"): self.key_percent,
  316. ord("."): self.key_dot,
  317. ord("/"): self.key_slash,
  318. ord("*"): self.key_star,
  319. ord("|"): self.key_bar,
  320. ord("~"): self.key_tilde,
  321. 8: self.key_backspace,
  322. }
  323. def add_char(self, char):
  324. self.lst_char.append(char)
  325. if self.state == _VI_BEGIN and self.readline.vi_is_insert_mode:
  326. self.readline.vi_save_line()
  327. self.state = _VI_TEXT
  328. if self.state == _VI_SEARCH:
  329. if char == "\x08": # backspace
  330. self.key_backspace(char)
  331. else:
  332. self.set_text(char)
  333. return
  334. if self.state == _VI_TEXT:
  335. if char == "\x1b": # escape
  336. self.escape(char)
  337. elif char == "\x09": # tab
  338. ts = self.tabstop
  339. ws = " " * (ts - (self.readline.l_buffer.point % ts))
  340. self.set_text(ws)
  341. elif char == "\x08": # backspace
  342. self.key_backspace(char)
  343. else:
  344. self.set_text(char)
  345. return
  346. if self.state == _VI_MOTION_ARGUMENT:
  347. self.set_motion_argument(char)
  348. return
  349. if self.state == _VI_REPLACE_ONE:
  350. self.replace_one(char)
  351. return
  352. try:
  353. fcn_instance = self.dct_fcn[ord(char)]
  354. except BaseException:
  355. fcn_instance = getattr(self, "key_%s" % char, None)
  356. if fcn_instance:
  357. fcn_instance(char)
  358. return
  359. if char.isdigit():
  360. self.key_digit(char)
  361. return
  362. # Here: could not process key
  363. self.error()
  364. def set_text(self, text):
  365. if self.text is None:
  366. self.text = text
  367. else:
  368. self.text += text
  369. self.set_buffer(text)
  370. def set_buffer(self, text):
  371. for char in text:
  372. if not self.char_isprint(char):
  373. continue
  374. # self.readline.l_buffer.insert_text(char)
  375. # continue
  376. # #overwrite in l_buffer obj
  377. if self.is_overwrite:
  378. if self.readline.l_buffer.point < len(
  379. self.readline.l_buffer.line_buffer
  380. ):
  381. # self.readline.l_buffer[self.l_buffer.point]=char
  382. self.readline.l_buffer.line_buffer[self.readline.l_buffer.point] = (
  383. char
  384. )
  385. else:
  386. # self.readline.l_buffer.insert_text(char)
  387. self.readline.l_buffer.line_buffer.append(char)
  388. else:
  389. # self.readline.l_buffer.insert_text(char)
  390. self.readline.l_buffer.line_buffer.insert(
  391. self.readline.l_buffer.point, char
  392. )
  393. self.readline.l_buffer.point += 1
  394. def replace_one(self, char):
  395. if char == "\x1b": # escape
  396. self.end()
  397. return
  398. self.is_edit = True
  399. self.readline.vi_save_line()
  400. times = self.get_multiplier()
  401. cursor = self.readline.l_buffer.point
  402. self.readline.l_buffer.line_buffer[cursor : cursor + times] = char * times
  403. if times > 1:
  404. self.readline.l_buffer.point += times - 1
  405. self.end()
  406. def char_isprint(self, char):
  407. return ord(char) >= ord(" ") and ord(char) <= ord("~")
  408. def key_dollar(self, char):
  409. self.motion = self.motion_end_in_line
  410. self.delete_right = 1
  411. self.state = _VI_MOTION
  412. self.apply()
  413. def key_hat(self, char):
  414. self.motion = self.motion_beginning_of_line
  415. self.state = _VI_MOTION
  416. self.apply()
  417. def key_0(self, char):
  418. if self.state in [_VI_BEGIN, _VI_ACTION]:
  419. self.key_hat(char)
  420. else:
  421. self.key_digit(char)
  422. def key_digit(self, char):
  423. if self.state in [_VI_BEGIN, _VI_MULTI1]:
  424. self.readline._vi_multiplier1 += char
  425. self.readline._vi_multiplier2 = ""
  426. self.state = _VI_MULTI1
  427. elif self.state in [_VI_ACTION, _VI_MULTI2]:
  428. self.readline._vi_multiplier2 += char
  429. self.state = _VI_MULTI2
  430. def key_w(self, char):
  431. if self.action == self.change:
  432. self.key_e(char)
  433. return
  434. self.motion = self.motion_word_short
  435. self.state = _VI_MOTION
  436. self.apply()
  437. def key_W(self, char):
  438. if self.action == self.change:
  439. self.key_E(char)
  440. return
  441. self.motion = self.motion_word_long
  442. self.state = _VI_MOTION
  443. self.apply()
  444. def key_e(self, char):
  445. self.motion = self.motion_end_short
  446. self.state = _VI_MOTION
  447. self.delete_right = 1
  448. self.apply()
  449. def key_E(self, char):
  450. self.motion = self.motion_end_long
  451. self.state = _VI_MOTION
  452. self.delete_right = 1
  453. self.apply()
  454. def key_b(self, char):
  455. self.motion = self.motion_back_short
  456. self.state = _VI_MOTION
  457. self.apply()
  458. def key_B(self, char):
  459. self.motion = self.motion_back_long
  460. self.state = _VI_MOTION
  461. self.apply()
  462. def key_f(self, char):
  463. self.readline._vi_key_find_direction = True
  464. self.motion = self.motion_find_char_forward
  465. self.delete_right = 1
  466. self.state = _VI_MOTION_ARGUMENT
  467. def key_F(self, char):
  468. self.readline._vi_key_find_direction = False
  469. self.motion = self.motion_find_char_backward
  470. self.delete_left = 1
  471. self.state = _VI_MOTION_ARGUMENT
  472. def key_t(self, char):
  473. self.motion = self.motion_to_char_forward
  474. self.delete_right = 1
  475. self.state = _VI_MOTION_ARGUMENT
  476. def key_T(self, char):
  477. self.motion = self.motion_to_char_backward
  478. self.state = _VI_MOTION_ARGUMENT
  479. def key_j(self, char):
  480. self.readline.vi_down(ViEvent(char))
  481. self.state = _VI_END
  482. def key_k(self, char):
  483. self.readline.vi_up(ViEvent(char))
  484. self.state = _VI_END
  485. def key_semicolon(self, char):
  486. if self.readline._vi_key_find_char is None:
  487. self.error()
  488. return
  489. if self.readline._vi_key_find_direction:
  490. self.motion = self.motion_find_char_forward
  491. else:
  492. self.motion = self.motion_find_char_backward
  493. self.set_motion_argument(self.readline._vi_key_find_char)
  494. def key_comma(self, char):
  495. if self.readline._vi_key_find_char is None:
  496. self.error()
  497. return
  498. if self.readline._vi_key_find_direction:
  499. self.motion = self.motion_find_char_backward
  500. else:
  501. self.motion = self.motion_find_char_forward
  502. self.set_motion_argument(self.readline._vi_key_find_char)
  503. def key_percent(self, char):
  504. """find matching <([{}])>"""
  505. self.motion = self.motion_matching
  506. self.delete_right = 1
  507. self.state = _VI_MOTION
  508. self.apply()
  509. def key_dot(self, char):
  510. vi_cmd_edit = self.readline._vi_command_edit
  511. if not vi_cmd_edit:
  512. return
  513. if vi_cmd_edit.is_star:
  514. self.key_star(char)
  515. return
  516. if self.has_multiplier():
  517. count = self.get_multiplier()
  518. else:
  519. count = 0
  520. # Create the ViCommand object after getting multiplier from self
  521. # Side effect of the ViCommand creation is resetting of global
  522. # multipliers
  523. vi_cmd = ViCommand(self.readline)
  524. if count >= 1:
  525. vi_cmd.set_override_multiplier(count)
  526. vi_cmd_edit.set_override_multiplier(count)
  527. elif vi_cmd_edit.override_multiplier:
  528. vi_cmd.set_override_multiplier(vi_cmd_edit.override_multiplier)
  529. for char in vi_cmd_edit.lst_char:
  530. vi_cmd.add_char(char)
  531. if vi_cmd_edit.is_overwrite and self.readline.l_buffer.point > 0:
  532. self.readline.l_buffer.point -= 1
  533. self.readline.vi_set_insert_mode(False)
  534. self.end()
  535. def key_slash(self, char):
  536. self.readline.vi_save_line()
  537. self.readline.l_buffer.line_buffer = ["/"]
  538. self.readline.l_buffer.point = 1
  539. self.state = _VI_SEARCH
  540. def key_star(self, char):
  541. self.is_star = True
  542. self.is_edit = True
  543. self.readline.vi_save_line()
  544. completions = self.readline._get_completions()
  545. if completions:
  546. text = " ".join(completions) + " "
  547. self.readline.l_buffer.line_buffer[
  548. self.readline.begidx : self.readline.endidx + 1
  549. ] = list(text)
  550. prefix_len = self.readline.endidx - self.readline.begidx
  551. self.readline.l_buffer.point += len(text) - prefix_len
  552. self.readline.vi_set_insert_mode(True)
  553. else:
  554. self.error()
  555. self.state = _VI_TEXT
  556. def key_bar(self, char):
  557. self.motion = self.motion_column
  558. self.state = _VI_MOTION
  559. self.apply()
  560. def key_tilde(self, char):
  561. self.is_edit = True
  562. self.readline.vi_save_line()
  563. for i in range(self.get_multiplier()):
  564. try:
  565. c = self.readline.l_buffer.line_buffer[self.readline.l_buffer.point]
  566. if c.isupper():
  567. self.readline.l_buffer.line_buffer[self.readline.l_buffer.point] = (
  568. c.lower()
  569. )
  570. elif c.islower():
  571. self.readline.l_buffer.line_buffer[self.readline.l_buffer.point] = (
  572. c.upper()
  573. )
  574. self.readline.l_buffer.point += 1
  575. except IndexError:
  576. break
  577. self.end()
  578. def key_h(self, char):
  579. self.motion = self.motion_left
  580. self.state = _VI_MOTION
  581. self.apply()
  582. def key_backspace(self, char):
  583. if self.state in [_VI_TEXT, _VI_SEARCH]:
  584. if self.text and len(self.text):
  585. self.text = self.text[:-1]
  586. try:
  587. # Remove backspaces for potential dot command
  588. self.lst_char.pop()
  589. self.lst_char.pop()
  590. except IndexError:
  591. pass
  592. else:
  593. self.key_h(char)
  594. self.readline._vi_do_backspace(self)
  595. if self.state == _VI_SEARCH and not (self.readline.l_buffer.line_buffer):
  596. self.state = _VI_BEGIN
  597. def key_l(self, char):
  598. self.motion = self.motion_right
  599. self.state = _VI_MOTION
  600. self.apply()
  601. def key_i(self, char):
  602. self.is_edit = True
  603. self.state = _VI_TEXT
  604. self.readline.vi_set_insert_mode(True)
  605. def key_I(self, char):
  606. self.is_edit = True
  607. self.state = _VI_TEXT
  608. self.readline.vi_set_insert_mode(True)
  609. self.readline.l_buffer.point = 0
  610. def key_a(self, char):
  611. self.is_edit = True
  612. self.state = _VI_TEXT
  613. self.readline.vi_set_insert_mode(True)
  614. if len(self.readline.l_buffer.line_buffer):
  615. self.readline.l_buffer.point += 1
  616. def key_A(self, char):
  617. self.is_edit = True
  618. self.state = _VI_TEXT
  619. self.readline.vi_set_insert_mode(True)
  620. self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer)
  621. def key_d(self, char):
  622. self.is_edit = True
  623. self.state = _VI_ACTION
  624. self.action = self.delete
  625. def key_D(self, char):
  626. self.is_edit = True
  627. self.state = _VI_ACTION
  628. self.action = self.delete_end_of_line
  629. self.apply()
  630. def key_x(self, char):
  631. self.is_edit = True
  632. self.state = _VI_ACTION
  633. self.action = self.delete_char
  634. self.apply()
  635. def key_X(self, char):
  636. self.is_edit = True
  637. self.state = _VI_ACTION
  638. self.action = self.delete_prev_char
  639. self.apply()
  640. def key_s(self, char):
  641. self.is_edit = True
  642. i1 = self.readline.l_buffer.point
  643. i2 = self.readline.l_buffer.point + self.get_multiplier()
  644. self.skip_multipler = True
  645. self.readline.vi_set_insert_mode(True)
  646. del self.readline.l_buffer.line_buffer[i1:i2]
  647. self.state = _VI_TEXT
  648. def key_S(self, char):
  649. self.is_edit = True
  650. self.readline.vi_set_insert_mode(True)
  651. self.readline.l_buffer.line_buffer = []
  652. self.readline.l_buffer.point = 0
  653. self.state = _VI_TEXT
  654. def key_c(self, char):
  655. self.is_edit = True
  656. self.state = _VI_ACTION
  657. self.action = self.change
  658. def key_C(self, char):
  659. self.is_edit = True
  660. self.readline.vi_set_insert_mode(True)
  661. del self.readline.l_buffer.line_buffer[self.readline.l_buffer.point :]
  662. self.state = _VI_TEXT
  663. def key_r(self, char):
  664. self.state = _VI_REPLACE_ONE
  665. def key_R(self, char):
  666. self.is_edit = True
  667. self.is_overwrite = True
  668. self.readline.l_buffer.overwrite = True
  669. self.readline.vi_set_insert_mode(True)
  670. self.state = _VI_TEXT
  671. def key_y(self, char):
  672. self._state = _VI_ACTION
  673. self.action = self.yank
  674. def key_Y(self, char):
  675. self.readline._vi_yank_buffer = self.readline.l_buffer.get_line_text()
  676. self.end()
  677. def key_p(self, char):
  678. if not self.readline._vi_yank_buffer:
  679. return
  680. self.is_edit = True
  681. self.readline.vi_save_line()
  682. self.readline.l_buffer.point += 1
  683. self.readline.l_buffer.insert_text(
  684. self.readline._vi_yank_buffer * self.get_multiplier()
  685. )
  686. self.readline.l_buffer.point -= 1
  687. self.state = _VI_END
  688. def key_P(self, char):
  689. if not self.readline._vi_yank_buffer:
  690. return
  691. self.is_edit = True
  692. self.readline.vi_save_line()
  693. self.readline.l_buffer.insert_text(
  694. self.readline._vi_yank_buffer * self.get_multiplier()
  695. )
  696. self.readline.l_buffer.point -= 1
  697. self.state = _VI_END
  698. def key_u(self, char):
  699. self.readline.vi_undo()
  700. self.state = _VI_END
  701. def key_U(self, char):
  702. self.readline.vi_undo_all()
  703. self.state = _VI_END
  704. def key_v(self, char):
  705. editor = ViExternalEditor(self.readline.l_buffer.line_buffer)
  706. self.readline.l_buffer.line_buffer = list(editor.result)
  707. self.readline.l_buffer.point = 0
  708. self.is_edit = True
  709. self.state = _VI_END
  710. def error(self):
  711. self.readline._bell()
  712. self.is_error = True
  713. def state_is_end(self):
  714. return self.state == _VI_END
  715. is_end = property(state_is_end)
  716. def state_is_search(self):
  717. return self.state == _VI_SEARCH
  718. is_search = property(state_is_search)
  719. def state_is_replace_one(self):
  720. return self.state == _VI_REPLACE_ONE
  721. is_replace_one = property(state_is_replace_one)
  722. def do_search(self):
  723. self.readline.vi_search_first()
  724. self.state = _VI_END
  725. def key_n(self, char):
  726. self.readline.vi_search_again_backward()
  727. self.state = _VI_END
  728. def key_N(self, char):
  729. self.readline.vi_search_again_forward()
  730. self.state = _VI_END
  731. def motion_beginning_of_line(self, line, index=0, count=1, **kw):
  732. return 0
  733. def motion_end_in_line(self, line, index=0, count=1, **kw):
  734. return max(0, len(self.readline.l_buffer.line_buffer) - 1)
  735. def motion_word_short(self, line, index=0, count=1, **kw):
  736. return vi_pos_word_short(line, index, count)
  737. def motion_word_long(self, line, index=0, count=1, **kw):
  738. return vi_pos_word_long(line, index, count)
  739. def motion_end_short(self, line, index=0, count=1, **kw):
  740. return vi_pos_end_short(line, index, count)
  741. def motion_end_long(self, line, index=0, count=1, **kw):
  742. return vi_pos_end_long(line, index, count)
  743. def motion_back_short(self, line, index=0, count=1, **kw):
  744. return vi_pos_back_short(line, index, count)
  745. def motion_back_long(self, line, index=0, count=1, **kw):
  746. return vi_pos_back_long(line, index, count)
  747. def motion_find_char_forward(self, line, index=0, count=1, char=None):
  748. self.readline._vi_key_find_char = char
  749. return vi_pos_find_char_forward(line, char, index, count)
  750. def motion_find_char_backward(self, line, index=0, count=1, char=None):
  751. self.readline._vi_key_find_char = char
  752. return vi_pos_find_char_backward(line, char, index, count)
  753. def motion_to_char_forward(self, line, index=0, count=1, char=None):
  754. return vi_pos_to_char_forward(line, char, index, count)
  755. def motion_to_char_backward(self, line, index=0, count=1, char=None):
  756. return vi_pos_to_char_backward(line, char, index, count)
  757. def motion_left(self, line, index=0, count=1, char=None):
  758. return max(0, index - count)
  759. def motion_right(self, line, index=0, count=1, char=None):
  760. return min(len(line), index + count)
  761. def motion_matching(self, line, index=0, count=1, char=None):
  762. return vi_pos_matching(line, index)
  763. def motion_column(self, line, index=0, count=1, char=None):
  764. return max(0, count - 1)
  765. def has_multiplier(self):
  766. return (
  767. self.override_multiplier
  768. or self.readline._vi_multiplier1
  769. or self.readline._vi_multiplier2
  770. )
  771. def get_multiplier(self):
  772. if self.override_multiplier:
  773. return int(self.override_multiplier)
  774. if self.readline._vi_multiplier1 == "":
  775. m1 = 1
  776. else:
  777. m1 = int(self.readline._vi_multiplier1)
  778. if self.readline._vi_multiplier2 == "":
  779. m2 = 1
  780. else:
  781. m2 = int(self.readline._vi_multiplier2)
  782. return m1 * m2
  783. def set_override_multiplier(self, count):
  784. self.override_multiplier = count
  785. def apply(self):
  786. if self.motion:
  787. self.pos_motion = self.motion(
  788. self.readline.l_buffer.line_buffer,
  789. self.readline.l_buffer.point,
  790. self.get_multiplier(),
  791. char=self.motion_argument,
  792. )
  793. if self.pos_motion < 0:
  794. self.error()
  795. return
  796. self.action()
  797. if self.state != _VI_TEXT:
  798. self.end()
  799. def movement(self):
  800. if self.pos_motion <= len(self.readline.l_buffer.line_buffer):
  801. self.readline.l_buffer.point = self.pos_motion
  802. else:
  803. self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer) - 1
  804. def yank(self):
  805. if self.pos_motion > self.readline.l_buffer.point:
  806. s = self.readline.l_buffer.line_buffer[
  807. self.readline.l_buffer.point : self.pos_motion + self.delete_right
  808. ]
  809. else:
  810. index = max(0, self.pos_motion - self.delete_left)
  811. s = self.readline.l_buffer.line_buffer[
  812. index : self.readline.l_buffer.point + self.delete_right
  813. ]
  814. self.readline._vi_yank_buffer = s
  815. def delete(self):
  816. self.readline.vi_save_line()
  817. self.yank()
  818. # point=lineobj.Point(self.readline.l_buffer)
  819. # pm=self.pos_motion
  820. # del self.readline.l_buffer[point:pm]
  821. # return
  822. if self.pos_motion > self.readline.l_buffer.point:
  823. del self.readline.l_buffer.line_buffer[
  824. self.readline.l_buffer.point : self.pos_motion + self.delete_right
  825. ]
  826. if self.readline.l_buffer.point > len(self.readline.l_buffer.line_buffer):
  827. self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer)
  828. else:
  829. index = max(0, self.pos_motion - self.delete_left)
  830. del self.readline.l_buffer.line_buffer[
  831. index : self.readline.l_buffer.point + self.delete_right
  832. ]
  833. self.readline.l_buffer.point = index
  834. def delete_end_of_line(self):
  835. self.readline.vi_save_line()
  836. # del self.readline.l_buffer [self.readline.l_buffer.point : ]
  837. line_text = self.readline.l_buffer.get_line_text()
  838. line_text = line_text[: self.readline.l_buffer.point]
  839. self.readline.l_buffer.set_line(line_text)
  840. if self.readline.l_buffer.point > 0:
  841. self.readline.l_buffer.point -= 1
  842. def delete_char(self):
  843. # point=lineobj.Point(self.readline.l_buffer)
  844. # del self.readline.l_buffer[point:point+self.get_multiplier ()]
  845. # return
  846. self.pos_motion = self.readline.l_buffer.point + self.get_multiplier()
  847. self.delete()
  848. end = max(0, len(self.readline.l_buffer) - 1)
  849. if self.readline.l_buffer.point > end:
  850. self.readline.l_buffer.point = end
  851. def delete_prev_char(self):
  852. self.pos_motion = self.readline.l_buffer.point - self.get_multiplier()
  853. self.delete()
  854. def change(self):
  855. self.readline.vi_set_insert_mode(True)
  856. self.delete()
  857. self.skip_multipler = True
  858. self.state = _VI_TEXT
  859. def escape(self, char):
  860. if self.state == _VI_TEXT:
  861. if not self.skip_multipler:
  862. times = self.get_multiplier()
  863. if times > 1 and self.text:
  864. extra = self.text * (times - 1)
  865. self.set_buffer(extra)
  866. self.state = _VI_END
  867. def set_motion_argument(self, char):
  868. self.motion_argument = char
  869. self.apply()
  870. def end(self):
  871. self.state = _VI_END
  872. if self.readline.l_buffer.point >= len(self.readline.l_buffer.line_buffer):
  873. self.readline.l_buffer.point = max(
  874. 0, len(self.readline.l_buffer.line_buffer) - 1
  875. )
  876. class ViExternalEditor:
  877. def __init__(self, line):
  878. if isinstance(line, type([])):
  879. line = "".join(line)
  880. file_tmp = self.get_tempfile()
  881. fp_tmp = self.file_open(file_tmp, "w")
  882. fp_tmp.write(line)
  883. fp_tmp.close()
  884. self.run_editor(file_tmp)
  885. fp_tmp = self.file_open(file_tmp, "r")
  886. self.result = fp_tmp.read()
  887. fp_tmp.close()
  888. self.file_remove(file_tmp)
  889. def get_tempfile(self):
  890. import tempfile
  891. return tempfile.mktemp(prefix="readline-", suffix=".py")
  892. def file_open(self, filename, mode):
  893. return open(filename, mode)
  894. def file_remove(self, filename):
  895. os.remove(filename)
  896. def get_editor(self):
  897. try:
  898. return os.environ["EDITOR"]
  899. except KeyError:
  900. return "notepad" # ouch
  901. def run_editor(self, filename):
  902. cmd = "%s %s" % (
  903. self.get_editor(),
  904. filename,
  905. )
  906. self.run_command(cmd)
  907. def run_command(self, command):
  908. os.system(command)
  909. class ViEvent:
  910. def __init__(self, char):
  911. self.char = char
  912. # vi standalone functions
  913. def vi_is_word(char):
  914. log(
  915. "xx vi_is_word: type(%s), %s"
  916. % (
  917. type(char),
  918. char,
  919. )
  920. )
  921. return char.isalpha() or char.isdigit() or char == "_"
  922. def vi_is_space(char):
  923. return char.isspace()
  924. def vi_is_word_or_space(char):
  925. return vi_is_word(char) or vi_is_space(char)
  926. def vi_pos_word_short(line, index=0, count=1):
  927. try:
  928. for i in range(count):
  929. in_word = vi_is_word(line[index])
  930. if not in_word:
  931. while not vi_is_word(line[index]):
  932. index += 1
  933. else:
  934. while vi_is_word(line[index]):
  935. index += 1
  936. while vi_is_space(line[index]):
  937. index += 1
  938. return index
  939. except IndexError:
  940. return len(line)
  941. def vi_pos_word_long(line, index=0, count=1):
  942. try:
  943. for i in range(count):
  944. in_space = vi_is_space(line[index])
  945. if not in_space:
  946. while not vi_is_space(line[index]):
  947. index += 1
  948. while vi_is_space(line[index]):
  949. index += 1
  950. return index
  951. except IndexError:
  952. return len(line)
  953. def vi_pos_end_short(line, index=0, count=1):
  954. try:
  955. for i in range(count):
  956. index += 1
  957. while vi_is_space(line[index]):
  958. index += 1
  959. in_word = vi_is_word(line[index])
  960. if not in_word:
  961. while not vi_is_word_or_space(line[index]):
  962. index += 1
  963. else:
  964. while vi_is_word(line[index]):
  965. index += 1
  966. return index - 1
  967. except IndexError:
  968. return max(0, len(line) - 1)
  969. def vi_pos_end_long(line, index=0, count=1):
  970. try:
  971. for i in range(count):
  972. index += 1
  973. while vi_is_space(line[index]):
  974. index += 1
  975. while not vi_is_space(line[index]):
  976. index += 1
  977. return index - 1
  978. except IndexError:
  979. return max(0, len(line) - 1)
  980. class vi_list(list):
  981. """This is a list that cannot have a negative index"""
  982. def __getitem__(self, key):
  983. try:
  984. if int(key) < 0:
  985. raise IndexError
  986. except ValueError:
  987. pass
  988. return list.__getitem__(self, key)
  989. def vi_pos_back_short(line, index=0, count=1):
  990. line = vi_list(line)
  991. try:
  992. for i in range(count):
  993. index -= 1
  994. while vi_is_space(line[index]):
  995. index -= 1
  996. in_word = vi_is_word(line[index])
  997. if in_word:
  998. while vi_is_word(line[index]):
  999. index -= 1
  1000. else:
  1001. while not vi_is_word_or_space(line[index]):
  1002. index -= 1
  1003. return index + 1
  1004. except IndexError:
  1005. return 0
  1006. def vi_pos_back_long(line, index=0, count=1):
  1007. line = vi_list(line)
  1008. try:
  1009. for i in range(count):
  1010. index -= 1
  1011. while vi_is_space(line[index]):
  1012. index -= 1
  1013. while not vi_is_space(line[index]):
  1014. index -= 1
  1015. return index + 1
  1016. except IndexError:
  1017. return 0
  1018. def vi_pos_find_char_forward(line, char, index=0, count=1):
  1019. try:
  1020. for i in range(count):
  1021. index += 1
  1022. while line[index] != char:
  1023. index += 1
  1024. return index
  1025. except IndexError:
  1026. return -1
  1027. def vi_pos_find_char_backward(line, char, index=0, count=1):
  1028. try:
  1029. for i in range(count):
  1030. index -= 1
  1031. while True:
  1032. if index < 0:
  1033. return -1
  1034. if line[index] == char:
  1035. break
  1036. index -= 1
  1037. return index
  1038. except IndexError:
  1039. return -1
  1040. def vi_pos_to_char_forward(line, char, index=0, count=1):
  1041. index = vi_pos_find_char_forward(line, char, index, count)
  1042. if index > 0:
  1043. return index - 1
  1044. return index
  1045. def vi_pos_to_char_backward(line, char, index=0, count=1):
  1046. index = vi_pos_find_char_backward(line, char, index, count)
  1047. if index >= 0:
  1048. return index + 1
  1049. return index
  1050. _vi_dct_matching = {
  1051. "<": (">", +1),
  1052. ">": ("<", -1),
  1053. "(": (")", +1),
  1054. ")": ("(", -1),
  1055. "[": ("]", +1),
  1056. "]": ("[", -1),
  1057. "{": ("}", +1),
  1058. "}": ("{", -1),
  1059. }
  1060. def vi_pos_matching(line, index=0):
  1061. """find matching <([{}])>"""
  1062. anchor = None
  1063. target = None
  1064. delta = 1
  1065. count = 0
  1066. try:
  1067. while True:
  1068. if anchor is None:
  1069. # first find anchor
  1070. try:
  1071. target, delta = _vi_dct_matching[line[index]]
  1072. anchor = line[index]
  1073. count = 1
  1074. except KeyError:
  1075. index += 1
  1076. continue
  1077. else:
  1078. # Here the anchor has been found
  1079. # Need to get corresponding target
  1080. if index < 0:
  1081. return -1
  1082. if line[index] == anchor:
  1083. count += 1
  1084. elif line[index] == target:
  1085. count -= 1
  1086. if count == 0:
  1087. return index
  1088. index += delta
  1089. except IndexError:
  1090. return -1