# if we have readline support, use that, otherwise use normal stdio
try:
import readline
- # Only consider whitespace as word boundaries
- readline.set_completer_delims(' \t\n')
+ # Only consider spaces as word boundaries; identifiers can contain
+ # '/' and '[]', and configuration item names can in theory use any
+ # printable character. See the discussion in tickets #1345 and
+ # #2254 for more information.
+ readline.set_completer_delims(' ')
my_readline = readline.get_line_buffer
except ImportError:
def _get_identifier_startswith(self, id_text):
"""Return the tab-completion hints for identifiers starting with
- id_text"""
- # First get all items from the given module (up to the first /)
+ id_text.
+
+ Parameters:
+ id_text (string): the currently entered identifier part, which
+ is to be completed.
+ """
+ # Strip starting "/" from id_text
+ if id_text.startswith('/'):
+ id_text = id_text[1:]
+ # Get all items from the given module (up to the first /)
list = self.config_data.get_config_item_list(
- id_text.rpartition("/")[0], True)
- hints = [val for val in list if val.startswith(id_text[1:])]
+ id_text.rpartition("/")[0], recurse=True)
+ # filter out all possibilities that don't match currently entered
+ # text part
+ hints = [val for val in list if val.startswith(id_text)]
return hints
def _cmd_has_identifier_param(self, cmd):
return command.has_param_with_name(IDENTIFIER_PARAM)
def complete(self, text, state):
+ """
+ Returns tab-completion hints. See the python documentation of the
+ readline and Cmd modules for more information.
+
+ The first time this is called (within one 'completer' action), it
+ has state 0, and a list of possible completions is made. This list
+ is stored; complete() will then be called with increasing values of
+ state, until it returns None. For each call it returns the state'th
+ element of the hints it collected in the first call.
+
+ The hints list contents depend on which part of the full command
+ line; if no module is given yet, it will list all modules. If a
+ module is given, but no command, it will complete with module
+ commands. If both have been given, it will create the hints based on
+ the command parameters.
+
+ If module and command have already been specified, and the command
+ has a parameter 'identifier', the configuration data is used to
+ create the hints list.
+
+ Parameters:
+ text (string): The text entered so far in the 'current' part of
+ the command (module, command, parameters)
+ state (int): state used in the readline tab-completion logic;
+ 0 on first call, increasing by one until there are
+ no (more) hints to return.
+
+ Returns the string value of the hints list with index 'state',
+ or None if no (more) hints are available.
+ """
if 0 == state:
self._update_all_modules_info()
text = text.strip()
cmd = BindCmdParse(cur_line)
if not cmd.params and text:
hints = self._get_command_startswith(cmd.module, text)
+ elif self._cmd_has_identifier_param(cmd):
+ # For tab-completion of identifiers, replace hardcoded
+ # hints with hints derived from the config data
+ hints = self._get_identifier_startswith(text)
else:
hints = self._get_param_startswith(cmd.module, cmd.command,
text)
- if self._cmd_has_identifier_param(cmd):
- # For tab-completion of identifiers, replace hardcoded
- # hints with hints derived from the config data
- id_text = self.location + "/" +\
- cur_line.rpartition(" ")[2]
- hints = self._get_identifier_startswith(id_text)
except CmdModuleNameFormatError:
if not text: