annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/autoexpand.py @ 68:5028fdace37b

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