lineobj.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. # -*- coding: utf-8 -*-
  2. # *****************************************************************************
  3. # Copyright (C) 2006-2020 Jorgen Stenarson. <jorgen.stenarson@bostream.nu>
  4. # Copyright (C) 2020 Bassem Girgis. <brgirgis@gmail.com>
  5. #
  6. # Distributed under the terms of the BSD License. The full license is in
  7. # the file COPYING, distributed as part of this software.
  8. # *****************************************************************************
  9. import pyreadline3.clipboard as clipboard
  10. from pyreadline3.unicode_helper import biter, ensure_unicode
  11. from . import wordmatcher
  12. # set to true to copy every addition to kill ring to clipboard
  13. kill_ring_to_clipboard = False
  14. class NotAWordError(IndexError):
  15. pass
  16. def quote_char(c):
  17. if ord(c) > 0:
  18. return c
  19. # ############# Line positioner ########################
  20. class LinePositioner(object):
  21. def __call__(self, line):
  22. NotImplementedError("Base class !!!")
  23. class NextChar(LinePositioner):
  24. def __call__(self, line):
  25. if line.point < len(line.line_buffer):
  26. return line.point + 1
  27. else:
  28. return line.point
  29. NextChar = NextChar()
  30. class PrevChar(LinePositioner):
  31. def __call__(self, line):
  32. if line.point > 0:
  33. return line.point - 1
  34. else:
  35. return line.point
  36. PrevChar = PrevChar()
  37. class NextWordStart(LinePositioner):
  38. def __call__(self, line):
  39. return line.next_start_segment(line.line_buffer, line.is_word_token)[line.point]
  40. NextWordStart = NextWordStart()
  41. class NextWordEnd(LinePositioner):
  42. def __call__(self, line):
  43. return line.next_end_segment(line.line_buffer, line.is_word_token)[line.point]
  44. NextWordEnd = NextWordEnd()
  45. class PrevWordStart(LinePositioner):
  46. def __call__(self, line):
  47. return line.prev_start_segment(line.line_buffer, line.is_word_token)[line.point]
  48. PrevWordStart = PrevWordStart()
  49. class WordStart(LinePositioner):
  50. def __call__(self, line):
  51. if line.is_word_token(line.get_line_text()[Point(line) : Point(line) + 1]):
  52. if Point(line) > 0 and line.is_word_token(
  53. line.get_line_text()[Point(line) - 1 : Point(line)]
  54. ):
  55. return PrevWordStart(line)
  56. else:
  57. return line.point
  58. else:
  59. raise NotAWordError("Point is not in a word")
  60. WordStart = WordStart()
  61. class WordEnd(LinePositioner):
  62. def __call__(self, line):
  63. if line.is_word_token(line.get_line_text()[Point(line) : Point(line) + 1]):
  64. if line.is_word_token(
  65. line.get_line_text()[Point(line) + 1 : Point(line) + 2]
  66. ):
  67. return NextWordEnd(line)
  68. else:
  69. return line.point
  70. else:
  71. raise NotAWordError("Point is not in a word")
  72. WordEnd = WordEnd()
  73. class PrevWordEnd(LinePositioner):
  74. def __call__(self, line):
  75. return line.prev_end_segment(line.line_buffer, line.is_word_token)[line.point]
  76. PrevWordEnd = PrevWordEnd()
  77. class PrevSpace(LinePositioner):
  78. def __call__(self, line):
  79. point = line.point
  80. if line[point - 1 : point].get_line_text() == " ":
  81. while point > 0 and line[point - 1 : point].get_line_text() == " ":
  82. point -= 1
  83. while point > 0 and line[point - 1 : point].get_line_text() != " ":
  84. point -= 1
  85. return point
  86. PrevSpace = PrevSpace()
  87. class StartOfLine(LinePositioner):
  88. def __call__(self, line):
  89. return 0
  90. StartOfLine = StartOfLine()
  91. class EndOfLine(LinePositioner):
  92. def __call__(self, line):
  93. return len(line.line_buffer)
  94. EndOfLine = EndOfLine()
  95. class Point(LinePositioner):
  96. def __call__(self, line):
  97. return line.point
  98. Point = Point()
  99. class Mark(LinePositioner):
  100. def __call__(self, line):
  101. return line.mark
  102. k = Mark()
  103. all_positioners = sorted(
  104. [
  105. (value.__class__.__name__, value)
  106. for key, value in globals().items()
  107. if isinstance(value, LinePositioner)
  108. ]
  109. )
  110. # ############## LineSlice #################
  111. class LineSlice(object):
  112. def __call__(self, line):
  113. NotImplementedError("Base class !!!")
  114. class CurrentWord(LineSlice):
  115. def __call__(self, line):
  116. return slice(WordStart(line), WordEnd(line), None)
  117. CurrentWord = CurrentWord()
  118. class NextWord(LineSlice):
  119. def __call__(self, line):
  120. work = TextLine(line)
  121. work.point = NextWordStart
  122. start = work.point
  123. stop = NextWordEnd(work)
  124. return slice(start, stop)
  125. NextWord = NextWord()
  126. class PrevWord(LineSlice):
  127. def __call__(self, line):
  128. work = TextLine(line)
  129. work.point = PrevWordEnd
  130. stop = work.point
  131. start = PrevWordStart(work)
  132. return slice(start, stop)
  133. PrevWord = PrevWord()
  134. class PointSlice(LineSlice):
  135. def __call__(self, line):
  136. return slice(Point(line), Point(line) + 1, None)
  137. PointSlice = PointSlice()
  138. # ############## TextLine ######################
  139. class TextLine(object):
  140. def __init__(self, txtstr, point=None, mark=None):
  141. self.line_buffer = []
  142. self._point = 0
  143. self.mark = -1
  144. self.undo_stack = []
  145. self.overwrite = False
  146. if isinstance(txtstr, TextLine): # copy
  147. self.line_buffer = txtstr.line_buffer[:]
  148. if point is None:
  149. self.point = txtstr.point
  150. else:
  151. self.point = point
  152. if mark is None:
  153. self.mark = txtstr.mark
  154. else:
  155. self.mark = mark
  156. else:
  157. self._insert_text(txtstr)
  158. if point is None:
  159. self.point = 0
  160. else:
  161. self.point = point
  162. if mark is None:
  163. self.mark = -1
  164. else:
  165. self.mark = mark
  166. self.is_word_token = wordmatcher.is_word_token
  167. self.next_start_segment = wordmatcher.next_start_segment
  168. self.next_end_segment = wordmatcher.next_end_segment
  169. self.prev_start_segment = wordmatcher.prev_start_segment
  170. self.prev_end_segment = wordmatcher.prev_end_segment
  171. def push_undo(self):
  172. l_text = self.get_line_text()
  173. if self.undo_stack and l_text == self.undo_stack[-1].get_line_text():
  174. self.undo_stack[-1].point = self.point
  175. else:
  176. self.undo_stack.append(self.copy())
  177. def pop_undo(self):
  178. if len(self.undo_stack) >= 2:
  179. self.undo_stack.pop()
  180. self.set_top_undo()
  181. self.undo_stack.pop()
  182. else:
  183. self.reset_line()
  184. self.undo_stack = []
  185. def set_top_undo(self):
  186. if self.undo_stack:
  187. undo = self.undo_stack[-1]
  188. self.line_buffer = undo.line_buffer
  189. self.point = undo.point
  190. self.mark = undo.mark
  191. else:
  192. pass
  193. def __repr__(self):
  194. return 'TextLine("%s",point=%s,mark=%s)' % (
  195. self.line_buffer,
  196. self.point,
  197. self.mark,
  198. )
  199. def copy(self):
  200. return self.__class__(self)
  201. def set_point(self, value):
  202. if isinstance(value, LinePositioner):
  203. value = value(self)
  204. assert value <= len(self.line_buffer)
  205. if value > len(self.line_buffer):
  206. value = len(self.line_buffer)
  207. self._point = value
  208. def get_point(self):
  209. return self._point
  210. point = property(get_point, set_point)
  211. def visible_line_width(self, position=Point):
  212. """Return the visible width of the text up to position."""
  213. extra_char_width = len(
  214. [None for c in self[:position].line_buffer if 0x2013 <= ord(c) <= 0xFFFD]
  215. )
  216. return (
  217. len(self[:position].quoted_text())
  218. + self[:position].line_buffer.count("\t") * 7
  219. + extra_char_width
  220. )
  221. def quoted_text(self):
  222. quoted = [quote_char(c) for c in self.line_buffer]
  223. return "".join(map(ensure_unicode, quoted))
  224. def get_line_text(self):
  225. buf = self.line_buffer
  226. buf = list(map(ensure_unicode, buf))
  227. return "".join(buf)
  228. def set_line(self, text, cursor=None):
  229. self.line_buffer = [c for c in str(text)]
  230. if cursor is None:
  231. self.point = len(self.line_buffer)
  232. else:
  233. self.point = cursor
  234. def reset_line(self):
  235. self.line_buffer = []
  236. self.point = 0
  237. def end_of_line(self):
  238. self.point = len(self.line_buffer)
  239. def _insert_text(self, text, argument=1):
  240. text = text * argument
  241. if self.overwrite:
  242. for c in biter(text):
  243. # if self.point:
  244. self.line_buffer[self.point] = c
  245. self.point += 1
  246. else:
  247. for c in biter(text):
  248. self.line_buffer.insert(self.point, c)
  249. self.point += 1
  250. def __getitem__(self, key):
  251. # Check if key is LineSlice, convert to regular slice
  252. # and continue processing
  253. if isinstance(key, LineSlice):
  254. key = key(self)
  255. if isinstance(key, slice):
  256. if key.step is None:
  257. pass
  258. else:
  259. raise RuntimeError('step is not "None"')
  260. if key.start is None:
  261. start = StartOfLine(self)
  262. elif isinstance(key.start, LinePositioner):
  263. start = key.start(self)
  264. else:
  265. start = key.start
  266. if key.stop is None:
  267. stop = EndOfLine(self)
  268. elif isinstance(key.stop, LinePositioner):
  269. stop = key.stop(self)
  270. else:
  271. stop = key.stop
  272. return self.__class__(self.line_buffer[start:stop], point=0)
  273. elif isinstance(key, LinePositioner):
  274. return self.line_buffer[key(self)]
  275. elif isinstance(key, tuple):
  276. # Multiple slice not allowed
  277. raise IndexError("Cannot use step in line buffer indexing")
  278. else:
  279. # return TextLine(self.line_buffer[key])
  280. return self.line_buffer[key]
  281. def __delitem__(self, key):
  282. point = self.point
  283. if isinstance(key, LineSlice):
  284. key = key(self)
  285. if isinstance(key, slice):
  286. start = key.start
  287. stop = key.stop
  288. if isinstance(start, LinePositioner):
  289. start = start(self)
  290. elif start is None:
  291. start = 0
  292. if isinstance(stop, LinePositioner):
  293. stop = stop(self)
  294. elif stop is None:
  295. stop = EndOfLine(self)
  296. elif isinstance(key, LinePositioner):
  297. start = key(self)
  298. stop = start + 1
  299. else:
  300. start = key
  301. stop = key + 1
  302. prev = self.line_buffer[:start]
  303. rest = self.line_buffer[stop:]
  304. self.line_buffer = prev + rest
  305. if point > stop:
  306. self.point = point - (stop - start)
  307. elif point >= start and point <= stop:
  308. self.point = start
  309. def __setitem__(self, key, value):
  310. if isinstance(key, LineSlice):
  311. key = key(self)
  312. if isinstance(key, slice):
  313. start = key.start
  314. stop = key.stop
  315. elif isinstance(key, LinePositioner):
  316. start = key(self)
  317. stop = start + 1
  318. else:
  319. start = key
  320. stop = key + 1
  321. prev = self.line_buffer[:start]
  322. value = self.__class__(value).line_buffer
  323. rest = self.line_buffer[stop:]
  324. out = prev + value + rest
  325. if len(out) >= len(self):
  326. self.point = len(self)
  327. self.line_buffer = out
  328. def __len__(self):
  329. return len(self.line_buffer)
  330. def upper(self):
  331. self.line_buffer = [x.upper() for x in self.line_buffer]
  332. return self
  333. def lower(self):
  334. self.line_buffer = [x.lower() for x in self.line_buffer]
  335. return self
  336. def capitalize(self):
  337. self.set_line(self.get_line_text().capitalize(), self.point)
  338. return self
  339. def startswith(self, txt):
  340. return self.get_line_text().startswith(txt)
  341. def endswith(self, txt):
  342. return self.get_line_text().endswith(txt)
  343. def __contains__(self, txt):
  344. return txt in self.get_line_text()
  345. class ReadLineTextBuffer(TextLine):
  346. def __init__(self, txtstr, point=None, mark=None):
  347. super().__init__(txtstr, point, mark)
  348. self.enable_win32_clipboard = True
  349. self.selection_mark = -1
  350. self.enable_selection = True
  351. self.kill_ring = []
  352. def __repr__(self):
  353. return "ReadLineTextBuffer" '("%s",point=%s,mark=%s,selection_mark=%s)' % (
  354. self.line_buffer,
  355. self.point,
  356. self.mark,
  357. self.selection_mark,
  358. )
  359. def insert_text(self, char, argument=1):
  360. self.delete_selection()
  361. self.selection_mark = -1
  362. self._insert_text(char, argument)
  363. def to_clipboard(self):
  364. if self.enable_win32_clipboard:
  365. clipboard.set_clipboard_text(self.get_line_text())
  366. # Movement
  367. def beginning_of_line(self):
  368. self.selection_mark = -1
  369. self.point = StartOfLine
  370. def end_of_line(self):
  371. self.selection_mark = -1
  372. self.point = EndOfLine
  373. def forward_char(self, argument=1):
  374. if argument < 0:
  375. self.backward_char(-argument)
  376. self.selection_mark = -1
  377. for _ in range(argument):
  378. self.point = NextChar
  379. def backward_char(self, argument=1):
  380. if argument < 0:
  381. self.forward_char(-argument)
  382. self.selection_mark = -1
  383. for _ in range(argument):
  384. self.point = PrevChar
  385. def forward_word(self, argument=1):
  386. if argument < 0:
  387. self.backward_word(-argument)
  388. self.selection_mark = -1
  389. for _ in range(argument):
  390. self.point = NextWordStart
  391. def backward_word(self, argument=1):
  392. if argument < 0:
  393. self.forward_word(-argument)
  394. self.selection_mark = -1
  395. for _ in range(argument):
  396. self.point = PrevWordStart
  397. def forward_word_end(self, argument=1):
  398. if argument < 0:
  399. self.backward_word_end(-argument)
  400. self.selection_mark = -1
  401. for _ in range(argument):
  402. self.point = NextWordEnd
  403. def backward_word_end(self, argument=1):
  404. if argument < 0:
  405. self.forward_word_end(-argument)
  406. self.selection_mark = -1
  407. for _ in range(argument):
  408. self.point = NextWordEnd
  409. # Movement select
  410. def beginning_of_line_extend_selection(self):
  411. if self.enable_selection and self.selection_mark < 0:
  412. self.selection_mark = self.point
  413. self.point = StartOfLine
  414. def end_of_line_extend_selection(self):
  415. if self.enable_selection and self.selection_mark < 0:
  416. self.selection_mark = self.point
  417. self.point = EndOfLine
  418. def forward_char_extend_selection(self, argument=1):
  419. if argument < 0:
  420. self.backward_char_extend_selection(-argument)
  421. if self.enable_selection and self.selection_mark < 0:
  422. self.selection_mark = self.point
  423. for _ in range(argument):
  424. self.point = NextChar
  425. def backward_char_extend_selection(self, argument=1):
  426. if argument < 0:
  427. self.forward_char_extend_selection(-argument)
  428. if self.enable_selection and self.selection_mark < 0:
  429. self.selection_mark = self.point
  430. for _ in range(argument):
  431. self.point = PrevChar
  432. def forward_word_extend_selection(self, argument=1):
  433. if argument < 0:
  434. self.backward_word_extend_selection(-argument)
  435. if self.enable_selection and self.selection_mark < 0:
  436. self.selection_mark = self.point
  437. for _ in range(argument):
  438. self.point = NextWordStart
  439. def backward_word_extend_selection(self, argument=1):
  440. if argument < 0:
  441. self.forward_word_extend_selection(-argument)
  442. if self.enable_selection and self.selection_mark < 0:
  443. self.selection_mark = self.point
  444. for _ in range(argument):
  445. self.point = PrevWordStart
  446. def forward_word_end_extend_selection(self, argument=1):
  447. if argument < 0:
  448. self.backward_word_end_extend_selection(-argument)
  449. if self.enable_selection and self.selection_mark < 0:
  450. self.selection_mark = self.point
  451. for _ in range(argument):
  452. self.point = NextWordEnd
  453. def backward_word_end_extend_selection(self, argument=1):
  454. if argument < 0:
  455. self.forward_word_end_extend_selection(-argument)
  456. if self.enable_selection and self.selection_mark < 0:
  457. self.selection_mark = self.point
  458. for _ in range(argument):
  459. self.point = PrevWordEnd
  460. # delete
  461. def delete_selection(self):
  462. if self.enable_selection and self.selection_mark >= 0:
  463. if self.selection_mark < self.point:
  464. del self[self.selection_mark : self.point]
  465. self.selection_mark = -1
  466. else:
  467. del self[self.point : self.selection_mark]
  468. self.selection_mark = -1
  469. return True
  470. else:
  471. self.selection_mark = -1
  472. return False
  473. def delete_char(self, argument=1):
  474. if argument < 0:
  475. self.backward_delete_char(-argument)
  476. if self.delete_selection():
  477. argument -= 1
  478. for _ in range(argument):
  479. del self[Point]
  480. def backward_delete_char(self, argument=1):
  481. if argument < 0:
  482. self.delete_char(-argument)
  483. if self.delete_selection():
  484. argument -= 1
  485. for _ in range(argument):
  486. if self.point > 0:
  487. self.backward_char()
  488. self.delete_char()
  489. def forward_delete_word(self, argument=1):
  490. if argument < 0:
  491. self.backward_delete_word(-argument)
  492. if self.delete_selection():
  493. argument -= 1
  494. for _ in range(argument):
  495. del self[Point:NextWordStart]
  496. def backward_delete_word(self, argument=1):
  497. if argument < 0:
  498. self.forward_delete_word(-argument)
  499. if self.delete_selection():
  500. argument -= 1
  501. for _ in range(argument):
  502. del self[PrevWordStart:Point]
  503. def delete_current_word(self):
  504. if not self.delete_selection():
  505. del self[CurrentWord]
  506. self.selection_mark = -1
  507. def delete_horizontal_space(self):
  508. if self[Point] in " \t":
  509. del self[PrevWordEnd:NextWordStart]
  510. self.selection_mark = -1
  511. # Case
  512. def upcase_word(self):
  513. p = self.point
  514. try:
  515. self[CurrentWord] = self[CurrentWord].upper()
  516. self.point = p
  517. except NotAWordError:
  518. pass
  519. def downcase_word(self):
  520. p = self.point
  521. try:
  522. self[CurrentWord] = self[CurrentWord].lower()
  523. self.point = p
  524. except NotAWordError:
  525. pass
  526. def capitalize_word(self):
  527. p = self.point
  528. try:
  529. self[CurrentWord] = self[CurrentWord].capitalize()
  530. self.point = p
  531. except NotAWordError:
  532. pass
  533. # Transpose
  534. def transpose_chars(self):
  535. p2 = Point(self)
  536. if p2 == 0:
  537. return
  538. elif p2 == len(self):
  539. p2 = p2 - 1
  540. p1 = p2 - 1
  541. self[p2], self[p1] = self[p1], self[p2]
  542. self.point = p2 + 1
  543. def transpose_words(self):
  544. word1 = TextLine(self)
  545. word2 = TextLine(self)
  546. if self.point == len(self):
  547. word2.point = PrevWordStart
  548. word1.point = PrevWordStart(word2)
  549. else:
  550. word1.point = PrevWordStart
  551. word2.point = NextWordStart
  552. stop1 = NextWordEnd(word1)
  553. stop2 = NextWordEnd(word2)
  554. start1 = word1.point
  555. start2 = word2.point
  556. self[start2:stop2] = word1[Point:NextWordEnd]
  557. self[start1:stop1] = word2[Point:NextWordEnd]
  558. self.point = stop2
  559. # Kill
  560. def kill_line(self):
  561. self.add_to_kill_ring(self[self.point :])
  562. del self.line_buffer[self.point :]
  563. def kill_whole_line(self):
  564. self.add_to_kill_ring(self[:])
  565. del self[:]
  566. def backward_kill_line(self):
  567. del self[StartOfLine:Point]
  568. def unix_line_discard(self):
  569. del self[StartOfLine:Point]
  570. def kill_word(self):
  571. """Kills to next word ending"""
  572. del self[Point:NextWordEnd]
  573. def backward_kill_word(self):
  574. """Kills to next word ending"""
  575. if not self.delete_selection():
  576. del self[PrevWordStart:Point]
  577. self.selection_mark = -1
  578. def forward_kill_word(self):
  579. """Kills to next word ending"""
  580. if not self.delete_selection():
  581. del self[Point:NextWordEnd]
  582. self.selection_mark = -1
  583. def unix_word_rubout(self):
  584. if not self.delete_selection():
  585. del self[PrevSpace:Point]
  586. self.selection_mark = -1
  587. def kill_region(self):
  588. pass
  589. def copy_region_as_kill(self):
  590. pass
  591. def copy_backward_word(self):
  592. pass
  593. def copy_forward_word(self):
  594. pass
  595. def yank(self):
  596. self.paste_from_kill_ring()
  597. def yank_pop(self):
  598. pass
  599. # Mark
  600. def set_mark(self):
  601. self.mark = self.point
  602. def exchange_point_and_mark(self):
  603. pass
  604. def copy_region_to_clipboard(self): # ()
  605. """Copy the text in the region to the windows clipboard."""
  606. if self.enable_win32_clipboard:
  607. mark = min(self.mark, len(self.line_buffer))
  608. cursor = min(self.point, len(self.line_buffer))
  609. if self.mark == -1:
  610. return
  611. begin = min(cursor, mark)
  612. end = max(cursor, mark)
  613. toclipboard = "".join(self.line_buffer[begin:end])
  614. clipboard.set_clipboard_text(toclipboard)
  615. def copy_selection_to_clipboard(self): # ()
  616. """Copy the text in the region to the windows clipboard."""
  617. if (
  618. self.enable_win32_clipboard
  619. and self.enable_selection
  620. and self.selection_mark >= 0
  621. ):
  622. selection_mark = min(self.selection_mark, len(self.line_buffer))
  623. cursor = min(self.point, len(self.line_buffer))
  624. if self.selection_mark == -1:
  625. return
  626. begin = min(cursor, selection_mark)
  627. end = max(cursor, selection_mark)
  628. toclipboard = "".join(self.line_buffer[begin:end])
  629. clipboard.set_clipboard_text(toclipboard)
  630. def cut_selection_to_clipboard(self): # ()
  631. self.copy_selection_to_clipboard()
  632. self.delete_selection()
  633. # Paste
  634. # Kill ring
  635. def add_to_kill_ring(self, txt):
  636. self.kill_ring = [txt]
  637. if kill_ring_to_clipboard:
  638. clipboard.set_clipboard_text(txt.get_line_text())
  639. def paste_from_kill_ring(self):
  640. if self.kill_ring:
  641. self.insert_text(self.kill_ring[0])
  642. ##################################################################
  643. q = ReadLineTextBuffer("asff asFArw ewrWErhg", point=8)
  644. q = TextLine("asff asFArw ewrWErhg", point=8)
  645. def show_pos(buff, pos, chr="."):
  646. l_n = len(buff.line_buffer)
  647. def choice(is_bool):
  648. if is_bool:
  649. return chr
  650. else:
  651. return " "
  652. return "".join([choice(pos == idx) for idx in range(l_n + 1)])
  653. def test_positioner(buff, points, positioner):
  654. print((" %s " % positioner.__class__.__name__).center(40, "-"))
  655. buffstr = buff.line_buffer
  656. print('"%s"' % (buffstr))
  657. for point in points:
  658. b = TextLine(buff, point=point)
  659. out = [" "] * (len(buffstr) + 1)
  660. pos = positioner(b)
  661. if pos == point:
  662. out[pos] = "&"
  663. else:
  664. out[point] = "."
  665. out[pos] = "^"
  666. print('"%s"' % ("".join(out)))
  667. if __name__ == "__main__":
  668. print('%-15s "%s"' % ("Position", q.get_line_text()))
  669. print('%-15s "%s"' % ("Point", show_pos(q, q.point)))
  670. for name, positioner_q in all_positioners:
  671. pos_q = positioner_q(q)
  672. print('%-15s "%s"' % (name, show_pos(q, pos_q, "^")))
  673. l_t = ReadLineTextBuffer("kjjk asads asad")
  674. l_t.point = EndOfLine