1import string
2import re
3
4###$ event <<expand-word>>
5###$ win <Alt-slash>
6###$ unix <Alt-slash>
7
8class AutoExpand:
9
10    menudefs = [
11        ('edit', [
12            ('E_xpand Word', '<<expand-word>>'),
13         ]),
14    ]
15
16    wordchars = string.ascii_letters + string.digits + "_"
17
18    def __init__(self, editwin):
19        self.text = editwin.text
20        self.state = None
21
22    def expand_word_event(self, event):
23        curinsert = self.text.index("insert")
24        curline = self.text.get("insert linestart", "insert lineend")
25        if not self.state:
26            words = self.getwords()
27            index = 0
28        else:
29            words, index, insert, line = self.state
30            if insert != curinsert or line != curline:
31                words = self.getwords()
32                index = 0
33        if not words:
34            self.text.bell()
35            return "break"
36        word = self.getprevword()
37        self.text.delete("insert - %d chars" % len(word), "insert")
38        newword = words[index]
39        index = (index + 1) % len(words)
40        if index == 0:
41            self.text.bell()            # Warn we cycled around
42        self.text.insert("insert", newword)
43        curinsert = self.text.index("insert")
44        curline = self.text.get("insert linestart", "insert lineend")
45        self.state = words, index, curinsert, curline
46        return "break"
47
48    def getwords(self):
49        word = self.getprevword()
50        if not word:
51            return []
52        before = self.text.get("1.0", "insert wordstart")
53        wbefore = re.findall(r"\b" + word + r"\w+\b", before)
54        del before
55        after = self.text.get("insert wordend", "end")
56        wafter = re.findall(r"\b" + word + r"\w+\b", after)
57        del after
58        if not wbefore and not wafter:
59            return []
60        words = []
61        dict = {}
62        # search backwards through words before
63        wbefore.reverse()
64        for w in wbefore:
65            if dict.get(w):
66                continue
67            words.append(w)
68            dict[w] = w
69        # search onwards through words after
70        for w in wafter:
71            if dict.get(w):
72                continue
73            words.append(w)
74            dict[w] = w
75        words.append(word)
76        return words
77
78    def getprevword(self):
79        line = self.text.get("insert linestart", "insert")
80        i = len(line)
81        while i > 0 and line[i-1] in self.wordchars:
82            i = i-1
83        return line[i:]
84