Re: tab completion in the curses ui
Eugene <[email protected]> Tue, 01 Mar 2005 08:42:33 +0300
| Newsgroups | gmane.comp.games.mud.client.lyntin |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 28 Feb 2005 12:50:18 -0600 (CST) will guaraldi <[email protected]> wrote: > > I'm tossing around adding tab-completion to the curses >ui. I think I'm going to do it via a callback so people >can add their own tab-completion plugins that return >possibilities of what the term expands to. Theoretically >it could be used for the tkui as well, but I haven't >touched that in a year, so I don't know for sure. > > Anyhow, so my question is two-fold: > > 1. does anyone have tab completion already coded? I think it's checked in some time ago. Some basic support is in the cursesui and in the tkui already. Also, additional module is needed - I did not include it into the distribution yet, but it was sent to the list. I send it again here. The first file in the attachment is the manager itself; the second is an example of how real completion hooks could be coded. -- Eugene --- Professional hosting for everyone - http://www.host.ru
completion.py
(text/x-python, 2.5 KB)
####################################################################### # This file is part of Lyntin. # copyright (c) Free Software Foundation 2004 # copyright (c) glasssnake <[email protected]> 2004 # # Lyntin is distributed under the GNU General Public License license. See the # file LICENSE for distribution details. # $Id$ ####################################################################### """ This module defines a manager for input line completion. A user interface module could call this manager to receive a list of possible completions for any given user input. Real completion work is being done by hooks registered for "completer_hook". The hook receives a tuple of (text, position) and returns a list [(completion_text1, completion_position1)... ]. The manager gathers all the lists from all registered hooks and returns to UI module completion tuples one by one. """ from lyntin import exported, manager class CompletionManager(manager.Manager): """ This manager should help to an UI module to build a completion list for given user input. """ def __init__(self, *args, **kargs): manager.Manager.__init__(self, *args, **kargs) self.reset() def reset(self): """ Resets the completer object, so the completion list will be rebuilt on next get_completion call. """ self.list_ = [] def _mapping(self, x, y): self.list_ += y return x def get_completion(self, text='', position=None): """ This method should be called when some hotkey (usually "Tab", but it is up to the UI module) is being pressed. @param text: the text to be completed @type text: string @param position: cursor position in the text @type position: int @returns: next possible completion pair (newtext, newposition) @rtype: (string, int) """ if not self.list_: # # Rebuild the completion list if it is empty after reset. # if position==None or position<0 or position>len(text): position = len(text) # # Gather all the completions from registered completers: # exported.hook_spam("completer_hook", { 'text': text, 'position': position }, self._mapping ) self.list_.append((text, position)) # put an anchor at the end of list completion = self.list_[0] self.list_[:1] = [] self.list_.append(completion) return completion def load(): exported.add_manager("completion", CompletionManager()) def unload(): exported.remove_manager("completion")
completer.py
(text/x-python, 2.7 KB)
from lyntin import exported
def make_alias_completer(args):
"""Builds and returns the alias completion list."""
text = args['text']
position = args['position']
cmdchar = exported.get_config("commandchar")
if not text.startswith(cmdchar):
al = exported.get_manager("alias")
aliases = filter(lambda x: x.startswith(text[:position]),
al.getAliasData(exported.get_current_session()).getAliases() )
return [ (x+' ', len(x)+1) for x in aliases ]
return []
def make_command_completer(args):
"""Builds and returns the command completion list."""
text = args['text']
position = args['position']
cmdchar = exported.get_config("commandchar")
if text.startswith(cmdchar):
cm = exported.get_manager("command")
return map(lambda x: (''.join( (cmdchar, x, ' ') ), len(x)+2),
filter(lambda x: x.startswith(text[1:]),
cm.getCommands()))
return []
import re
def make_var_completer(args):
"""
Builds and returns the variable completion list,
if the text at the given position looks like a variable
"""
text = args['text']
position = args['position']
#
# Checking for "#showme $foo" form:
#
mch = re.match('(.*)\$(\S*)', text[:position])
if mch:
tail = re.match('(\S*)(.*)$', text[position:])
varname = mch.group(2)+tail.group(1)
list = []
for var in filter( lambda x: x.startswith(varname),
exported.get_current_session()._vars.keys() ):
start = ''.join( (mch.group(1), '$', var) )
list.append( (start+tail.group(2), len(start)) )
return list
#
# TODO process the "#showme ${foo}" form
#
#
# Processing the "#unvar" command:
#
cmdchar = exported.get_config("commandchar")
mch = re.match(cmdchar+'unvariable (\S*)$', text)
if mch:
list = []
for var in filter( lambda x: x.startswith(mch.group(1)),
exported.get_current_session()._vars.keys() ):
command = '#unvariable ' + var
list.append( (command, len(command)) )
return list
return []
def load():
"""
These 3 completer hooks below could be united into one big hook function
as well, but for demonstration purposes they are divided.
Later they could be moved in their own modules.
"""
exported.hook_register("completer_hook", make_command_completer)
exported.hook_register("completer_hook", make_alias_completer)
exported.hook_register("completer_hook", make_var_completer)
def unload():
exported.hook_unregister("completer_hook", make_var_completer)
exported.hook_unregister("completer_hook", make_command_completer)
exported.hook_unregister("completer_hook", make_alias_completer)