#!/usr/bin/env python from Tkinter import * import Pmw class HistoryCombo(Pmw.ComboBox): def __init__(self, parent = None, **kw): optiondefs = ( ('completion', 1, None), ) self.defineoptions(kw, optiondefs) Pmw.ComboBox.__init__(self, parent) # Initialize instance _registerWidget(self.component('entry'), self) # Construct keybindings self.bindkeys() self.component('entry').bindtags(self.component('entry').bindtags() + ('HistoryPost',)) # Check keywords and initialise options. self.initialiseoptions(HistoryCombo) def destroy(self): _deregisterEntryField(self.component('entry')) Pmw.ComboBox.destroy(self) def bindkeys(self): self.bind_class('HistoryPost', '', _postProcess) def _postProcess(self, event): if not self['completion']: return if not event.char or `event.char`[1] == '\\': return currentstr = self.get() if not currentstr: # Don't complete on empty string return # Sort by length, so that shorter matches show up first history_list = list(self.get(0, 'end')) history_list.sort(lambda x, y: cmp(len(x), len(y))) for item in history_list: if currentstr == item[:len(currentstr)]: completion = item[len(currentstr):] here = self.component('entry').index('end') self.component('entry').insert('end', completion) self.component('entry').selection_range(here, 'end') self.component('entry').icursor('end') return _entryCache = {} def _registerWidget(entrywidget, parentwidget): # Register a parent widget for an Entry widget _entryCache[entrywidget] = parentwidget def _deregisterEntryField(entrywidget): # Deregister an Entry widget del _entryCache[entrywidget] def _postProcess(event, *args): # Forward postprocess events for an Entry to its HistoryCombo # The function specified by the 'command' option may have destroyed # the megawidget in a binding earlier in bindtags, so need to check. if _entryCache.has_key(event.widget): _entryCache[event.widget]._postProcess(event) def main(): a = HistoryCombo() a.pack() b = HistoryCombo() b.pack(side=TOP) a.mainloop() if __name__ == '__main__': main()