annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/autoexpand.py @ 69:33d812a61356

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 17:55:14 -0400
parents
children
rev   line source
jpayne@69 1 '''Complete the current word before the cursor with words in the editor.
jpayne@69 2
jpayne@69 3 Each menu selection or shortcut key selection replaces the word with a
jpayne@69 4 different word with the same prefix. The search for matches begins
jpayne@69 5 before the target and moves toward the top of the editor. It then starts
jpayne@69 6 after the cursor and moves down. It then returns to the original word and
jpayne@69 7 the cycle starts again.
jpayne@69 8
jpayne@69 9 Changing the current text line or leaving the cursor in a different
jpayne@69 10 place before requesting the next selection causes AutoExpand to reset
jpayne@69 11 its state.
jpayne@69 12
jpayne@69 13 There is only one instance of Autoexpand.
jpayne@69 14 '''
jpayne@69 15 import re
jpayne@69 16 import string
jpayne@69 17
jpayne@69 18
jpayne@69 19 class AutoExpand:
jpayne@69 20 wordchars = string.ascii_letters + string.digits + "_"
jpayne@69 21
jpayne@69 22 def __init__(self, editwin):
jpayne@69 23 self.text = editwin.text
jpayne@69 24 self.bell = self.text.bell
jpayne@69 25 self.state = None
jpayne@69 26
jpayne@69 27 def expand_word_event(self, event):
jpayne@69 28 "Replace the current word with the next expansion."
jpayne@69 29 curinsert = self.text.index("insert")
jpayne@69 30 curline = self.text.get("insert linestart", "insert lineend")
jpayne@69 31 if not self.state:
jpayne@69 32 words = self.getwords()
jpayne@69 33 index = 0
jpayne@69 34 else:
jpayne@69 35 words, index, insert, line = self.state
jpayne@69 36 if insert != curinsert or line != curline:
jpayne@69 37 words = self.getwords()
jpayne@69 38 index = 0
jpayne@69 39 if not words:
jpayne@69 40 self.bell()
jpayne@69 41 return "break"
jpayne@69 42 word = self.getprevword()
jpayne@69 43 self.text.delete("insert - %d chars" % len(word), "insert")
jpayne@69 44 newword = words[index]
jpayne@69 45 index = (index + 1) % len(words)
jpayne@69 46 if index == 0:
jpayne@69 47 self.bell() # Warn we cycled around
jpayne@69 48 self.text.insert("insert", newword)
jpayne@69 49 curinsert = self.text.index("insert")
jpayne@69 50 curline = self.text.get("insert linestart", "insert lineend")
jpayne@69 51 self.state = words, index, curinsert, curline
jpayne@69 52 return "break"
jpayne@69 53
jpayne@69 54 def getwords(self):
jpayne@69 55 "Return a list of words that match the prefix before the cursor."
jpayne@69 56 word = self.getprevword()
jpayne@69 57 if not word:
jpayne@69 58 return []
jpayne@69 59 before = self.text.get("1.0", "insert wordstart")
jpayne@69 60 wbefore = re.findall(r"\b" + word + r"\w+\b", before)
jpayne@69 61 del before
jpayne@69 62 after = self.text.get("insert wordend", "end")
jpayne@69 63 wafter = re.findall(r"\b" + word + r"\w+\b", after)
jpayne@69 64 del after
jpayne@69 65 if not wbefore and not wafter:
jpayne@69 66 return []
jpayne@69 67 words = []
jpayne@69 68 dict = {}
jpayne@69 69 # search backwards through words before
jpayne@69 70 wbefore.reverse()
jpayne@69 71 for w in wbefore:
jpayne@69 72 if dict.get(w):
jpayne@69 73 continue
jpayne@69 74 words.append(w)
jpayne@69 75 dict[w] = w
jpayne@69 76 # search onwards through words after
jpayne@69 77 for w in wafter:
jpayne@69 78 if dict.get(w):
jpayne@69 79 continue
jpayne@69 80 words.append(w)
jpayne@69 81 dict[w] = w
jpayne@69 82 words.append(word)
jpayne@69 83 return words
jpayne@69 84
jpayne@69 85 def getprevword(self):
jpayne@69 86 "Return the word prefix before the cursor."
jpayne@69 87 line = self.text.get("insert linestart", "insert")
jpayne@69 88 i = len(line)
jpayne@69 89 while i > 0 and line[i-1] in self.wordchars:
jpayne@69 90 i = i-1
jpayne@69 91 return line[i:]
jpayne@69 92
jpayne@69 93
jpayne@69 94 if __name__ == '__main__':
jpayne@69 95 from unittest import main
jpayne@69 96 main('idlelib.idle_test.test_autoexpand', verbosity=2)