mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-05 18:49:23 +01:00
Autocomplete: return only the common prefix + one word.
This commit is contained in:
parent
efb4d476a5
commit
6f34f377e5
@ -45,30 +45,55 @@ REQUEST_TAG = "+draft/autocomplete-request"
|
||||
RESPONSE_TAG = "+draft/autocomplete-response"
|
||||
|
||||
|
||||
def _commonPrefix(L):
|
||||
"""Takes a list of lists, and returns their longest common prefix."""
|
||||
assert L
|
||||
if len(L) == 1:
|
||||
return L[0]
|
||||
|
||||
for n in range(1, max(map(len, L)) + 1):
|
||||
prefix = L[0][:n]
|
||||
for item in L[1:]:
|
||||
if prefix != item[:n]:
|
||||
return prefix[0:-1]
|
||||
|
||||
assert False
|
||||
|
||||
|
||||
def _getAutocompleteResponse(irc, msg, payload):
|
||||
"""Returns the value of the +draft/autocomplete-response tag for the given
|
||||
+draft/autocomplete-request payload."""
|
||||
tokens = callbacks.tokenize(payload, channel=msg.channel, network=irc.network)
|
||||
normalized_payload = " ".join(tokens)
|
||||
|
||||
candidates = _getCandidates(irc, normalized_payload)
|
||||
candidate_commands = _getCandidates(irc, normalized_payload)
|
||||
|
||||
if not candidates:
|
||||
return ""
|
||||
if len(candidate_commands) == 0:
|
||||
# No result
|
||||
return None
|
||||
elif len(candidate_commands) == 1:
|
||||
# One result, return it directly
|
||||
commands = candidate_commands
|
||||
else:
|
||||
# Multiple results, return only the longest common prefix + one word
|
||||
|
||||
tokenized_candidates = [
|
||||
callbacks.tokenize(c, channel=msg.channel, network=irc.network)
|
||||
for c in candidate_commands
|
||||
]
|
||||
|
||||
common_prefix = _commonPrefix(tokenized_candidates)
|
||||
|
||||
words_after_prefix = {
|
||||
candidate[len(common_prefix)] for candidate in tokenized_candidates
|
||||
}
|
||||
|
||||
commands = [" ".join(common_prefix + [word]) for word in words_after_prefix]
|
||||
|
||||
# strip what the user already typed
|
||||
assert all(candidate.startswith(normalized_payload) for candidate in candidates)
|
||||
assert all(command.startswith(normalized_payload) for command in commands)
|
||||
normalized_payload_length = len(normalized_payload)
|
||||
candidate_commands = [
|
||||
candidate[normalized_payload_length:] for candidate in candidates
|
||||
]
|
||||
|
||||
tokenized_candidates = [
|
||||
callbacks.tokenize(c, channel=msg.channel, network=irc.network)
|
||||
for c in candidate_commands
|
||||
]
|
||||
|
||||
response_items = {candidate[0] for candidate in tokenized_candidates}
|
||||
response_items = [command[normalized_payload_length:] for command in commands]
|
||||
|
||||
return "\t".join(sorted(response_items))
|
||||
|
||||
|
@ -63,17 +63,41 @@ class AutocompleteTestCase(PluginTestCase):
|
||||
)
|
||||
|
||||
def testResponse(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||
self._assertAutocompleteResponse("apro", "pos")
|
||||
|
||||
def testSingleCommandName(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||
self._assertAutocompleteResponse("apro", "pos")
|
||||
self._assertAutocompleteResponse("apr", "opos")
|
||||
self._assertAutocompleteResponse("te", "ll\tstplugin")
|
||||
self._assertAutocompleteResponse("tel", "l")
|
||||
self._assertAutocompleteResponse("mi", "sc")
|
||||
|
||||
def testTwoResults(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||
self._assertAutocompleteResponse("te", "ll\tstplugin")
|
||||
|
||||
def testCommandNameAndPluginName(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||
self._assertAutocompleteResponse("misc t", "ell")
|
||||
self._assertAutocompleteResponse("misc c", "learmores\tompletenick")
|
||||
self._assertAutocompleteResponse("lat", "er")
|
||||
self._assertAutocompleteResponse("later", "notes\tremove\ttell\tundo")
|
||||
|
||||
def testSinglePluginName(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||
self._assertAutocompleteResponse(
|
||||
"lat", "er notes\ter remove\ter tell\ter undo"
|
||||
)
|
||||
|
||||
def testNextWord(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||
self._assertAutocompleteResponse(
|
||||
"later", " notes\t remove\t tell\t undo"
|
||||
)
|
||||
|
||||
def testNoResponse(self):
|
||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||
|
Loading…
Reference in New Issue
Block a user