mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-29 22:29:24 +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"
|
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):
|
def _getAutocompleteResponse(irc, msg, payload):
|
||||||
"""Returns the value of the +draft/autocomplete-response tag for the given
|
"""Returns the value of the +draft/autocomplete-response tag for the given
|
||||||
+draft/autocomplete-request payload."""
|
+draft/autocomplete-request payload."""
|
||||||
tokens = callbacks.tokenize(payload, channel=msg.channel, network=irc.network)
|
tokens = callbacks.tokenize(payload, channel=msg.channel, network=irc.network)
|
||||||
normalized_payload = " ".join(tokens)
|
normalized_payload = " ".join(tokens)
|
||||||
|
|
||||||
candidates = _getCandidates(irc, normalized_payload)
|
candidate_commands = _getCandidates(irc, normalized_payload)
|
||||||
|
|
||||||
if not candidates:
|
if len(candidate_commands) == 0:
|
||||||
return ""
|
# 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
|
# 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)
|
normalized_payload_length = len(normalized_payload)
|
||||||
candidate_commands = [
|
response_items = [command[normalized_payload_length:] for command in 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}
|
|
||||||
|
|
||||||
return "\t".join(sorted(response_items))
|
return "\t".join(sorted(response_items))
|
||||||
|
|
||||||
|
@ -63,17 +63,41 @@ class AutocompleteTestCase(PluginTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def testResponse(self):
|
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.protocols.irc.experimentalExtensions.context(True):
|
||||||
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
with conf.supybot.plugins.Autocomplete.enabled.context(True):
|
||||||
self._assertAutocompleteResponse("apro", "pos")
|
self._assertAutocompleteResponse("apro", "pos")
|
||||||
self._assertAutocompleteResponse("apr", "opos")
|
self._assertAutocompleteResponse("apr", "opos")
|
||||||
self._assertAutocompleteResponse("te", "ll\tstplugin")
|
|
||||||
self._assertAutocompleteResponse("tel", "l")
|
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 t", "ell")
|
||||||
self._assertAutocompleteResponse("misc c", "learmores\tompletenick")
|
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):
|
def testNoResponse(self):
|
||||||
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
|
||||||
|
Loading…
Reference in New Issue
Block a user