Core: Fix auto-fill in the text client when clicking on a hint suggestion (#3267)
This commit is contained in:
parent
8dbc8d2d41
commit
3cb5452455
|
@ -37,7 +37,7 @@ except ImportError:
|
||||||
|
|
||||||
import NetUtils
|
import NetUtils
|
||||||
import Utils
|
import Utils
|
||||||
from Utils import version_tuple, restricted_loads, Version, async_start
|
from Utils import version_tuple, restricted_loads, Version, async_start, get_intended_text
|
||||||
from NetUtils import Endpoint, ClientStatus, NetworkItem, decode, encode, NetworkPlayer, Permission, NetworkSlot, \
|
from NetUtils import Endpoint, ClientStatus, NetworkItem, decode, encode, NetworkPlayer, Permission, NetworkSlot, \
|
||||||
SlotType, LocationStore
|
SlotType, LocationStore
|
||||||
|
|
||||||
|
@ -1095,28 +1095,6 @@ def json_format_send_event(net_item: NetworkItem, receiving_player: int):
|
||||||
"item": net_item}
|
"item": net_item}
|
||||||
|
|
||||||
|
|
||||||
def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]:
|
|
||||||
picks = Utils.get_fuzzy_results(input_text, possible_answers, limit=2)
|
|
||||||
if len(picks) > 1:
|
|
||||||
dif = picks[0][1] - picks[1][1]
|
|
||||||
if picks[0][1] == 100:
|
|
||||||
return picks[0][0], True, "Perfect Match"
|
|
||||||
elif picks[0][1] < 75:
|
|
||||||
return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \
|
|
||||||
f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)"
|
|
||||||
elif dif > 5:
|
|
||||||
return picks[0][0], True, "Close Match"
|
|
||||||
else:
|
|
||||||
return picks[0][0], False, f"Too many close matches for '{input_text}', " \
|
|
||||||
f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)"
|
|
||||||
else:
|
|
||||||
if picks[0][1] > 90:
|
|
||||||
return picks[0][0], True, "Only Option Match"
|
|
||||||
else:
|
|
||||||
return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \
|
|
||||||
f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)"
|
|
||||||
|
|
||||||
|
|
||||||
class CommandMeta(type):
|
class CommandMeta(type):
|
||||||
def __new__(cls, name, bases, attrs):
|
def __new__(cls, name, bases, attrs):
|
||||||
commands = attrs["commands"] = {}
|
commands = attrs["commands"] = {}
|
||||||
|
|
35
Utils.py
35
Utils.py
|
@ -622,6 +622,41 @@ def get_fuzzy_results(input_word: str, word_list: typing.Collection[str], limit:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_intended_text(input_text: str, possible_answers) -> typing.Tuple[str, bool, str]:
|
||||||
|
picks = get_fuzzy_results(input_text, possible_answers, limit=2)
|
||||||
|
if len(picks) > 1:
|
||||||
|
dif = picks[0][1] - picks[1][1]
|
||||||
|
if picks[0][1] == 100:
|
||||||
|
return picks[0][0], True, "Perfect Match"
|
||||||
|
elif picks[0][1] < 75:
|
||||||
|
return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \
|
||||||
|
f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)"
|
||||||
|
elif dif > 5:
|
||||||
|
return picks[0][0], True, "Close Match"
|
||||||
|
else:
|
||||||
|
return picks[0][0], False, f"Too many close matches for '{input_text}', " \
|
||||||
|
f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)"
|
||||||
|
else:
|
||||||
|
if picks[0][1] > 90:
|
||||||
|
return picks[0][0], True, "Only Option Match"
|
||||||
|
else:
|
||||||
|
return picks[0][0], False, f"Didn't find something that closely matches '{input_text}', " \
|
||||||
|
f"did you mean '{picks[0][0]}'? ({picks[0][1]}% sure)"
|
||||||
|
|
||||||
|
|
||||||
|
def get_input_text_from_response(text: str, command: str) -> typing.Optional[str]:
|
||||||
|
if "did you mean " in text:
|
||||||
|
for question in ("Didn't find something that closely matches",
|
||||||
|
"Too many close matches"):
|
||||||
|
if text.startswith(question):
|
||||||
|
name = get_text_between(text, "did you mean '",
|
||||||
|
"'? (")
|
||||||
|
return f"!{command} {name}"
|
||||||
|
elif text.startswith("Missing: "):
|
||||||
|
return text.replace("Missing: ", "!hint_location ")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def open_filename(title: str, filetypes: typing.Iterable[typing.Tuple[str, typing.Iterable[str]]], suggest: str = "") \
|
def open_filename(title: str, filetypes: typing.Iterable[typing.Tuple[str, typing.Iterable[str]]], suggest: str = "") \
|
||||||
-> typing.Optional[str]:
|
-> typing.Optional[str]:
|
||||||
logging.info(f"Opening file input dialog for {title}.")
|
logging.info(f"Opening file input dialog for {title}.")
|
||||||
|
|
16
kvui.py
16
kvui.py
|
@ -64,7 +64,7 @@ from kivy.uix.popup import Popup
|
||||||
fade_in_animation = Animation(opacity=0, duration=0) + Animation(opacity=1, duration=0.25)
|
fade_in_animation = Animation(opacity=0, duration=0) + Animation(opacity=1, duration=0.25)
|
||||||
|
|
||||||
from NetUtils import JSONtoTextParser, JSONMessagePart, SlotType
|
from NetUtils import JSONtoTextParser, JSONMessagePart, SlotType
|
||||||
from Utils import async_start
|
from Utils import async_start, get_input_text_from_response
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
import CommonClient
|
import CommonClient
|
||||||
|
@ -285,16 +285,10 @@ class SelectableLabel(RecycleDataViewBehavior, TooltipLabel):
|
||||||
temp = MarkupLabel(text=self.text).markup
|
temp = MarkupLabel(text=self.text).markup
|
||||||
text = "".join(part for part in temp if not part.startswith(("[color", "[/color]", "[ref=", "[/ref]")))
|
text = "".join(part for part in temp if not part.startswith(("[color", "[/color]", "[ref=", "[/ref]")))
|
||||||
cmdinput = App.get_running_app().textinput
|
cmdinput = App.get_running_app().textinput
|
||||||
if not cmdinput.text and " did you mean " in text:
|
if not cmdinput.text:
|
||||||
for question in ("Didn't find something that closely matches, did you mean ",
|
input_text = get_input_text_from_response(text, App.get_running_app().last_autofillable_command)
|
||||||
"Too many close matches, did you mean "):
|
if input_text is not None:
|
||||||
if text.startswith(question):
|
cmdinput.text = input_text
|
||||||
name = Utils.get_text_between(text, question,
|
|
||||||
"? (")
|
|
||||||
cmdinput.text = f"!{App.get_running_app().last_autofillable_command} {name}"
|
|
||||||
break
|
|
||||||
elif not cmdinput.text and text.startswith("Missing: "):
|
|
||||||
cmdinput.text = text.replace("Missing: ", "!hint_location ")
|
|
||||||
|
|
||||||
Clipboard.copy(text.replace("&", "&").replace("&bl;", "[").replace("&br;", "]"))
|
Clipboard.copy(text.replace("&", "&").replace("&bl;", "[").replace("&br;", "]"))
|
||||||
return self.parent.select_with_touch(self.index, touch)
|
return self.parent.select_with_touch(self.index, touch)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from Utils import get_intended_text, get_input_text_from_response
|
||||||
|
|
||||||
|
|
||||||
|
class TestClient(unittest.TestCase):
|
||||||
|
def test_autofill_hint_from_fuzzy_hint(self) -> None:
|
||||||
|
tests = (
|
||||||
|
("item", ["item1", "item2"]), # Multiple close matches
|
||||||
|
("itm", ["item1", "item21"]), # No close match, multiple option
|
||||||
|
("item", ["item1"]), # No close match, single option
|
||||||
|
("item", ["\"item\" 'item' (item)"]), # Testing different special characters
|
||||||
|
)
|
||||||
|
|
||||||
|
for input_text, possible_answers in tests:
|
||||||
|
item_name, usable, response = get_intended_text(input_text, possible_answers)
|
||||||
|
self.assertFalse(usable, "This test must be updated, it seems get_fuzzy_results behavior changed")
|
||||||
|
|
||||||
|
hint_command = get_input_text_from_response(response, "hint")
|
||||||
|
self.assertIsNotNone(hint_command,
|
||||||
|
"The response to fuzzy hints is no longer recognized by the hint autofill")
|
||||||
|
self.assertEqual(hint_command, f"!hint {item_name}",
|
||||||
|
"The hint command autofilled by the response is not correct")
|
Loading…
Reference in New Issue