| 1 | import string
|
|---|
| 2 | import re
|
|---|
| 3 |
|
|---|
| 4 | ###$ event <<expand-word>>
|
|---|
| 5 | ###$ win <Alt-slash>
|
|---|
| 6 | ###$ unix <Alt-slash>
|
|---|
| 7 |
|
|---|
| 8 | class 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:]
|
|---|