diff -r 28665dc3a696 Lib/idlelib/AutoExpand.py --- a/Lib/idlelib/AutoExpand.py Mon Jun 02 20:42:56 2014 -0400 +++ b/Lib/idlelib/AutoExpand.py Tue Jun 03 17:02:15 2014 +0530 @@ -1,3 +1,17 @@ +'''Complete the current word before the cursor with words in the editor. + +Each menu selection or shortcut key selection replaces the word with a +different word with the same prefix. The search for matches begins +before the target and moves toward the top of the editor. It then starts +after the cursor and moves down. It then returns to the original word and +the cycle starts again. + +Changing the current text line or leaving the cursor in a different +place before requesting the next selection causes AutoExpand to reset +its state. + +This is an extension file and there is only one instance of AutoExpand. +''' import string import re @@ -20,6 +34,8 @@ self.state = None def expand_word_event(self, event): + '''Replace the current word with the next expansion. + ''' curinsert = self.text.index("insert") curline = self.text.get("insert linestart", "insert lineend") if not self.state: @@ -46,6 +62,7 @@ return "break" def getwords(self): + "Return a list of words that match the prefix before the cursor." word = self.getprevword() if not word: return [] @@ -76,8 +93,14 @@ return words def getprevword(self): + "Return the word prefix before the cursor." line = self.text.get("insert linestart", "insert") i = len(line) while i > 0 and line[i-1] in self.wordchars: i = i-1 return line[i:] + +if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_autoexpand', + verbosity=2, exit=False) diff -r 28665dc3a696 Lib/idlelib/idle_test/test_autoexpand.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/idlelib/idle_test/test_autoexpand.py Tue Jun 03 17:02:15 2014 +0530 @@ -0,0 +1,149 @@ +"""Unit tests for idlelib.AutoExpand""" +import unittest +from test.support import requires +from tkinter import Text, Tk +#from idlelib.idle_test.mock_tk import Text +from idlelib.AutoExpand import AutoExpand + + +class Dummy_Editwin: + # AutoExpand.__init__ only needs .text + def __init__(self, text): + self.text = text + +class AutoExpandTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + if 'tkinter' in str(Text): + requires('gui') + cls.tk = Tk() + cls.text = Text(cls.tk) + else: + cls.text = Text() + cls.editwin = Dummy_Editwin(cls.text) + cls.auto_expand = AutoExpand(cls.editwin) + + @classmethod + def tearDownClass(cls): + if hasattr(cls, 'tk'): + cls.tk.destroy() + del cls.tk + + def tearDown(self): + self.text.delete('1.0', 'end') + + def test_get_prevword(self): + text = self.editwin.text + previous = self.auto_expand.getprevword + equal = self.assertEqual + + equal(previous(), '') + + text.insert('insert', 't') + equal(previous(), 't') + + text.insert('insert', 'his') + equal(previous(), 'this') + + text.insert('insert', ' ') + equal(previous(), '') + + text.insert('insert', 'is') + equal(previous(), 'is') + + text.insert('insert', '\nsample\nstring') + equal(previous(), 'string') + + text.delete('3.0', 'insert') + equal(previous(), '') + + text.delete('1.0', 'end') + equal(previous(), '') + + def test_get_words(self): + text = self.editwin.text + words = self.auto_expand.getwords + equal = self.assertEqual + + equal(words(), []) + + text.insert('insert', 'a ab') + equal(words(), []) + text.delete('1.0', 'end') + + text.insert('insert', 'ab a') + equal(words(), ['ab', 'a']) + text.delete('1.0', 'end') + + text.insert('insert', 'aab aba\n acb\n') + text.insert('insert', 'a') + equal(words(), ['acb', 'aba', 'aab', 'a']) + text.insert('insert', 'a') + equal(words(), ['aab', 'aa']) + text.insert('insert', 'b') + equal(words(), []) + text.delete('1.0', 'end') + + text.insert('insert', 'a\nb\nc\nd') + text.insert('insert', 'abc') + equal(words(), []) + text.delete('1.0', 'end') + + def test_expand_event(self): + text = self.editwin.text + expand = self.auto_expand.expand_word_event + previous = self.auto_expand.getprevword + equal = self.assertEqual + + expand('event') + equal(previous(), '') + text.delete('1.0', 'end') + + # candidates only before 'insert' + text.insert('insert', 'ab ac xy ab ad yz\na') + expand('event') + equal(previous(), 'ad') + expand('event') + equal(previous(), 'ab') + expand('event') + equal(previous(), 'ac') + expand('event') + equal(previous(), 'a') + text.delete('1.0', 'end') + + # candidates both before and after 'insert' + text.insert('insert', 'ab xy ac yz ad\n') + text.insert('insert', 'a \n') + text.insert('insert', 'ax az bx ay az') + text.mark_set('insert', '2.1') + expand('event') + expand('event') + expand('event') + expand('event') + equal(previous(), 'ax') + expand('event') + equal(previous(), 'az') + expand('event') + equal(previous(), 'ay') + expand('event') + equal(previous(), 'a') + expand('event') + equal(previous(), 'ad') + text.delete('1.0', 'end') + + # candidates only after 'insert' + text.insert('insert', 'a \n') + text.insert('insert', 'ax by ay ax az') + text.mark_set('insert', '2.1') + expand('event') + equal(previous(), 'ay') + expand('event') + equal(previous(), 'ax') + expand('event') + equal(previous(), 'az') + expand('event') + equal(previous(), 'a') + +if __name__ == '__main__': + unittest.main(verbosity=2, exit=False)