BIND 10 #2254: bindctl tab completion confusing output
BIND 10 Development
do-not-reply at isc.org
Mon Oct 1 19:40:28 UTC 2012
#2254: bindctl tab completion confusing output
-------------------------------------+-------------------------------------
Reporter: jreed | Owner: jinmei
Type: | Status: reviewing
defect | Milestone:
Priority: | Sprint-20121009
medium | Resolution:
Component: bind- | Sensitive: 0
ctl | Sub-Project: Core
Keywords: | Estimated Difficulty: 6
Defect Severity: N/A | Total Hours: 0
Feature Depending on Ticket: |
Add Hours to Ticket: 0 |
Internal?: 0 |
-------------------------------------+-------------------------------------
Comment (by jinmei):
I have some more points, but considering the amount of time we've
spent for this ticket and the importance of these points, my last
suggestion is the following two:
- add some clarification comment to the following part of complete():
{{{#!python
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)
}}}
(see the long discussion below)
- `_get_list_items`: the cases where values is None don't seem to be
tested.
> added
Which one? I cannot easily identify it.
With addressing these please merge and close.
Now the discussion part:
'''complete()'''
Let me check my understanding. In the original version:
{{{#!python
hints = self._get_param_startswith(cmd.module,
cmd.command,
text)
if cmd.module == CONFIG_MODULE_NAME:
# grm text has been stripped of slashes...
my_text = self.location + "/" +
cur_line.rpartition(" ")[2]
list =
self.config_data.get_config_item_list(my_text.rpartition("/")[0], True)
hints.extend([val for val in list if
val.startswith(my_text[1:])])
# remove the common prefix from the hints so we
don't get it twice
hints = self.remove_prefix(hints,
my_text.rpartition("/")[0])
}}}
`_get_param_startswith()` collects all possible command parameters,
regardless of whether it's a configuration related command. If it's a
configuration related command, the returned hints contain special
parameter names like IDENTIFIER_PARAM itself, or "value" or
"argument". While keeping them in hints, this code then checks the
module name, and if it's for configuration get_config_item_list()
collects configuration item identifiers and add them to the hints.
This is why we had the very original problem of this ticket, having
"identifier" and "argument" in the completion list.
This branch fixes the problem as follows:
{{{#!python
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)
}}}
In this version, instead of unconditionally builds command parameter
names, it first checks if the command has a special name of parameter
IDENTIFIER_PARAM. And, if it does, it only collects config item
identifiers, ignoring all command parameter names. In effect, this
does this check in the original version:
{{{#!python
if cmd.module == CONFIG_MODULE_NAME:
}}}
before doing `_get_param_startswith()`. Is my understanding correct?
If my understanding so far is correct, I now see what was wrong with
the original version and the revised version would fix that particular
issue. But I think we still need to discuss a few points.
- If the command has the special parameter named IDENTIFIER_PARAM,
the new version now ignores all other command parameters that the
command possibly has. In fact, the new version now cannot suggest
"help" after "config show".
- some part of the original code logic now seems to be missing:
{{{#!python
my_text = self.location + "/" +
cur_line.rpartition(" ")[2]
...
# remove the common prefix from the hints so we
don't get it twice
hints = self.remove_prefix(hints,
my_text.rpartition("/")[0])
}}}
According to your previous response comment, I at least understand
that the first line is somehow related to "config go", and removing
it would break that scenario (but that we'd rather defer it as
"config go" itself is quite broken). That's fine to me (I don't
want to do any more stuff in this ticket especially if it's already
broken), but what about remove_prefix()?
- A minor point, the comment in the new version ("For
tab-completion...") doesn't seem to be really correct in that it
actually doesn't "replace" anything (this is the first creation of
hints)
To address the first point more comprehensively, I guess we need some
concept of "command parameter type" (which might just be recognized
via the parameter name like IDENTIFIER_PARAM), and introduce a
mechanism of how to expand various types of parameters (including just
ignoring some). On top of that, we always expand all parameters of
the command.
Also, not related to this branch, but another issue with complete() in
terms of understandability is that it mixes if-else and try-except to
implement a single set of conditions:
{{{#!python
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.
}}}
(btw this documentation helps, thanks). The "if no module is given"
part is caught in an `except`:
{{{#!python
except CmdModuleNameFormatError:
if not text:
hints = self.get_module_names()
}}}
(right?) while the rest is generally handled in the if-else logic
above this. It would be very difficult for a first-time reader to
understand the whole logic flow of this method without the detailed
documentation. The documentation helps, but it then reveals that the
implementation is really ugly.
That said, I don't think it's productive to spend even more time for
addressing these issues case by case basis. My suggestion for this
ticket is: just adding some comments about the restriction here:
{{{#!python
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)
}}}
(that "config go" may not work, "help" won't appear in some cases, and
if the missing remove_prefix() has some adversary effect, mention that
too), and close the ticket hoping we'll address these in a cleaner way
in the next generation.
Some specific suggestions:
- revise the comment
- maybe rename IDENTIFIER_PARAM to something like CFGITEM_IDENTIFIER_PARAM
'''config_data.py'''
- `_get_list_items` docstring has a duplicate:
{{{#!python
"""This method is used in get_config_item_list, to add list
...
_get_list_items("Module/list")
where the list contains 2 elements, returns
[ "Module/list[0]", "Module/list[1]" ]
_get_list_items("Module/list")
where the list contains 2 elements, returns
[ "Module/list[0]", "Module/list[1]" ]
"""
}}}
--
Ticket URL: <http://bind10.isc.org/ticket/2254#comment:14>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list