From 90060f5d28a33723e9a7ec7e78948275dfc8e967 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 16 Sep 2020 11:08:01 -0400 Subject: [PATCH 01/41] Added DictionaryAPI (Merriam-Webster) Lookup --- .../backends/dictionary_api_com_lookup.py | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 autoload/thesaurus_query/backends/dictionary_api_com_lookup.py diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py new file mode 100644 index 0000000..ff5e702 --- /dev/null +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -0,0 +1,91 @@ +# python wrapper for word query from dictionaryapi.com +# Author: Aaron Hayman [[ahayman@gmail.com][E-mail]] + +try: + from urllib2 import urlopen + from urllib2 import URLError, HTTPError +except ImportError: + from urllib.request import urlopen + from urllib.error import URLError, HTTPError +import json +import socket +import codecs +from ..tq_common_lib import fixurl, decode_utf_8, get_variable + +identifier="dictionary_api_com" +language="en" + +_timeout_period_default = 1.0 + +def query(target, query_method="synonym"): + ''' return result as list. relavance from high to low in each PoS. +Lookup routine for datamuse.com. When query_from_source is called, return: + [status, [[PoS, [word_0, word_1, ...]], [PoS, [word_0, word_1, ...]], ...]] +status: + 0: normal, result found, list will be returned as a nested list + 1: normal, result not found, return empty list + -1: unexpected result from query, return empty list +nested list = [PoS, list wordlist] + Classifier('str'): Identifier to classify the resulting wordlist suits. + wordlist = [word_0, word_1, ...]: list of words belonging to a same definition + ''' + target=target.replace(u" ", u"+") + result_list=_dictionary_api_wrapper(target, query_method=query_method) + if result_list == -1: + return [-1,[]] + elif result_list == 1: + return [1, []] + else: + return _parser(result_list) + + +def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc): + api_key = get_variable('tq_dictionary_api_key', '') + if api_key == '': + return [-1, []] + time_out_choice = float(get_variable( + 'tq_online_backends_timeout', _timeout_period_default)) + case_mapper={"synonym":u"words?rel_syn=", + "suggest":u"sug?s=", + "antonym":u"words?rel_ant=", + "right_content":u"words?rc=", + "left_content":u"words?lc=" + } + try: + response = urlopen(fixurl( + u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?{1}'.format( + target, api_key + )).decode('utf-8'), timeout = time_out_choice) + result_list = json.load(response) + response.close() + except HTTPError: + return 1 + except URLError as err: + if isinstance(err.reason, socket.timeout): + return 1 +# print(u"Internet Error. The word \"{0}\" has not been found on datamuse!\n".format(target)) + return -1 + except socket.timeout: # timeout only means underperforming + return 1 + return result_list + + +def _parser(result): + result_dict = result[0] + if not result_dict: + return [1, []] + syns = [syn for arr in result_dict[u'meta'][u'syns'] for syn in arr] + ants = [ant for arr in result_dict[u'meta'][u'ants']for ant in arr] + sseqs = [d[u'sseq'] for d in result_dict[u'def'] if d[u'sseq']] + flattened = [d for a in sseqs for b in a for c in b for d in c if isinstance(d,dict)] + near_lists = [d[u'near_list'] for d in flattened if d[u'near_list']] + rel_lists = [d[u'rel_list'] for d in flattened if d[u'rel_list']] + nears = [d[u'wd'] for arr in near_lists for c in arr for d in c if d[u'wd']] + rels = [d[u'wd'] for arr in rel_lists for c in arr for d in c if d[u'wd']] + results = syns + rels + nears + ants + l = len(results) + if l == 0: + return [1, []] + if l > 100: + return [0, results[:100]] + return [0, results] \ No newline at end of file From 7e173f7c7b3ef22afcf9c106cd411aa94127d68f Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 16 Sep 2020 11:14:05 -0400 Subject: [PATCH 02/41] Added back query_result_trunc --- autoload/thesaurus_query/backends/dictionary_api_com_lookup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index ff5e702..4758e90 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -1,6 +1,7 @@ # python wrapper for word query from dictionaryapi.com # Author: Aaron Hayman [[ahayman@gmail.com][E-mail]] + try: from urllib2 import urlopen from urllib2 import URLError, HTTPError @@ -12,6 +13,7 @@ import codecs from ..tq_common_lib import fixurl, decode_utf_8, get_variable +query_result_trunc=100 identifier="dictionary_api_com" language="en" From f12da7136370b419cd9368c8f9a25688c39be9d8 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 16 Sep 2020 11:43:47 -0400 Subject: [PATCH 03/41] Fixed https error in DictionaryAPI --- .../backends/dictionary_api_com_lookup.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 4758e90..ada215e 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -11,7 +11,8 @@ import json import socket import codecs -from ..tq_common_lib import fixurl, decode_utf_8, get_variable +import ssl +from ..tq_common_lib import fixurl, get_variable query_result_trunc=100 identifier="dictionary_api_com" @@ -54,17 +55,15 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) "left_content":u"words?lc=" } try: - response = urlopen(fixurl( - u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?{1}'.format( - target, api_key - )).decode('utf-8'), timeout = time_out_choice) - result_list = json.load(response) - response.close() + url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') + response = urlopen(url, context=ssl.SSLContext(), timeout = time_out_choice).read() + result_list = json.loads(response.decode('utf-8')) except HTTPError: return 1 except URLError as err: if isinstance(err.reason, socket.timeout): return 1 + print(err) # print(u"Internet Error. The word \"{0}\" has not been found on datamuse!\n".format(target)) return -1 except socket.timeout: # timeout only means underperforming @@ -90,4 +89,4 @@ def _parser(result): return [1, []] if l > 100: return [0, results[:100]] - return [0, results] \ No newline at end of file + return [0, results] From e44e54d504a0b4dd879606af09956df3b40d0319 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 16 Sep 2020 11:53:01 -0400 Subject: [PATCH 04/41] Tentative output format change --- .../backends/dictionary_api_com_lookup.py | 13 ++++----- test.py | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 test.py diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index ada215e..876fe5e 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -83,10 +83,9 @@ def _parser(result): rel_lists = [d[u'rel_list'] for d in flattened if d[u'rel_list']] nears = [d[u'wd'] for arr in near_lists for c in arr for d in c if d[u'wd']] rels = [d[u'wd'] for arr in rel_lists for c in arr for d in c if d[u'wd']] - results = syns + rels + nears + ants - l = len(results) - if l == 0: - return [1, []] - if l > 100: - return [0, results[:100]] - return [0, results] + return [0, + [ 'Synonyms', syns], + [ 'Related', rels], + [ 'Near', nears], + [ 'Antonyms', ants] + ] diff --git a/test.py b/test.py new file mode 100644 index 0000000..4115a56 --- /dev/null +++ b/test.py @@ -0,0 +1,28 @@ +import json +def _parser(target_list): + target_list.sort(key=lambda x: x[u'score'], reverse=True) + result = {} + for word in target_list: + if u'partsOfSpeech' in word: + for i in word[u'partsOfSpeech']: + if i in result: + result[i].append(word[u'word']) + else: + result[i]=[word[u'word']] + elif u'' in result: + result[u''].append(word[u'word']) + else: + result[u''] = [word[u'word']] + if not result: + return [1, []] + if u'' in result: + output = [0, [[u'',result.pop(u'')]]] + else: + output = [0,[]] + for item in result: + output[1].insert(0,[item,result[item]]) + return output + +result_string='[{"word":"content","score":3310},{"word":"bright","score":1804},{"word":"halcyon","score":1706},{"word":"blessed","score":1223},{"word":"prosperous","score":1183},{"word":"glad","score":1164},{"word":"golden","score":1020},{"word":"blissful","score":953},{"word":"euphoric","score":863},{"word":"pleased","score":845},{"word":"expansive","score":828},{"word":"felicitous","score":804},{"word":"joyful","score":780},{"word":"fortunate","score":755},{"word":"elysian","score":496},{"word":"joyous","score":492},{"word":"contented","score":491},{"word":"riant","score":433},{"word":"paradisal","score":181},{"word":"paradisiacal","score":174},{"word":"euphoriant","score":131},{"word":"paradisiac","score":116},{"word":"paradisaical","score":100},{"word":"paradisaic","score":83},{"word":"paradisial","score":71},{"word":"well-chosen","score":56}]' +r_json=json.loads(result_string) +print(_parser(r_json)) \ No newline at end of file From 680c834982624c80b90c9a55853d3df8642acc09 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 16 Sep 2020 11:59:01 -0400 Subject: [PATCH 05/41] Tentative output format change --- .../backends/dictionary_api_com_lookup.py | 4 ++-- test1.py | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 test1.py diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 876fe5e..e787e83 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -83,9 +83,9 @@ def _parser(result): rel_lists = [d[u'rel_list'] for d in flattened if d[u'rel_list']] nears = [d[u'wd'] for arr in near_lists for c in arr for d in c if d[u'wd']] rels = [d[u'wd'] for arr in rel_lists for c in arr for d in c if d[u'wd']] - return [0, + return [0, [ [ 'Synonyms', syns], [ 'Related', rels], [ 'Near', nears], [ 'Antonyms', ants] - ] + ]] diff --git a/test1.py b/test1.py new file mode 100644 index 0000000..4b7105d --- /dev/null +++ b/test1.py @@ -0,0 +1,24 @@ +import json + +def _parser(result): + result_dict = result[0] + if not result_dict: + return [1, []] + syns = [syn for arr in result_dict[u'meta'][u'syns'] for syn in arr] + ants = [ant for arr in result_dict[u'meta'][u'ants']for ant in arr] + sseqs = [d[u'sseq'] for d in result_dict[u'def'] if d[u'sseq']] + flattened = [d for a in sseqs for b in a for c in b for d in c if isinstance(d,dict)] + near_lists = [d[u'near_list'] for d in flattened if d[u'near_list']] + rel_lists = [d[u'rel_list'] for d in flattened if d[u'rel_list']] + nears = [d[u'wd'] for arr in near_lists for c in arr for d in c if d[u'wd']] + rels = [d[u'wd'] for arr in rel_lists for c in arr for d in c if d[u'wd']] + return [0,[ + [ 'Synonyms', syns], + [ 'Related', rels], + [ 'Near', nears], + [ 'Antonyms', ants] + ]] + +result_string='[{"meta":{"id":"laughter","uuid":"d5568d3d-0a4b-4ad9-a7fa-ef61c4a3aa2b","src":"coll_thes","section":"alpha","target":{"tuuid":"3a26c05a-c942-4c40-8358-14abec28e469","tsrc":"collegiate"},"stems":["laughter","laughters"],"syns":[["belly laugh","boff","boffola","cachinnation","cackle","chortle","chuckle","giggle","guffaw","hee-haw","horselaugh","laugh","snicker","snigger","titter","twitter"]],"ants":[],"offensive":false},"hwi":{"hw":"laughter"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","an explosive sound that is a sign of amusement "],["vis",[{"t":"the nervous producers were reassured by the sounds of {it}laughter{\/it} coming from the theater"}]]],"syn_list":[[{"wd":"belly laugh"},{"wd":"boff","wvrs":[{"wvl":"or","wva":"boffo"}]},{"wd":"boffola"},{"wd":"cachinnation"},{"wd":"cackle"},{"wd":"chortle"},{"wd":"chuckle"},{"wd":"giggle"},{"wd":"guffaw"},{"wd":"hee-haw"},{"wd":"horselaugh"},{"wd":"laugh"},{"wd":"snicker"},{"wd":"snigger"},{"wd":"titter"},{"wd":"twitter"}]],"rel_list":[[{"wd":"crow"},{"wd":"whoop"}],[{"wd":"grin"},{"wd":"simper"},{"wd":"smile"},{"wd":"smirk"}]],"near_list":[[{"wd":"cry"},{"wd":"groan"},{"wd":"moan"},{"wd":"sob"},{"wd":"wail"}],[{"wd":"face"},{"wd":"frown"},{"wd":"grimace"},{"wd":"lower","wvrs":[{"wvl":"also","wva":"lour"}]},{"wd":"mouth"},{"wd":"pout"},{"wd":"scowl"}]]}]]]}],"shortdef":["an explosive sound that is a sign of amusement"]}]' +r_json=json.loads(result_string) +print(_parser(r_json)) \ No newline at end of file From f66545c6424197b860a94f19330bdb40b47ffb46 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 16 Sep 2020 12:02:17 -0400 Subject: [PATCH 06/41] Removed Test Files --- test.py | 28 ---------------------------- test1.py | 24 ------------------------ 2 files changed, 52 deletions(-) delete mode 100644 test.py delete mode 100644 test1.py diff --git a/test.py b/test.py deleted file mode 100644 index 4115a56..0000000 --- a/test.py +++ /dev/null @@ -1,28 +0,0 @@ -import json -def _parser(target_list): - target_list.sort(key=lambda x: x[u'score'], reverse=True) - result = {} - for word in target_list: - if u'partsOfSpeech' in word: - for i in word[u'partsOfSpeech']: - if i in result: - result[i].append(word[u'word']) - else: - result[i]=[word[u'word']] - elif u'' in result: - result[u''].append(word[u'word']) - else: - result[u''] = [word[u'word']] - if not result: - return [1, []] - if u'' in result: - output = [0, [[u'',result.pop(u'')]]] - else: - output = [0,[]] - for item in result: - output[1].insert(0,[item,result[item]]) - return output - -result_string='[{"word":"content","score":3310},{"word":"bright","score":1804},{"word":"halcyon","score":1706},{"word":"blessed","score":1223},{"word":"prosperous","score":1183},{"word":"glad","score":1164},{"word":"golden","score":1020},{"word":"blissful","score":953},{"word":"euphoric","score":863},{"word":"pleased","score":845},{"word":"expansive","score":828},{"word":"felicitous","score":804},{"word":"joyful","score":780},{"word":"fortunate","score":755},{"word":"elysian","score":496},{"word":"joyous","score":492},{"word":"contented","score":491},{"word":"riant","score":433},{"word":"paradisal","score":181},{"word":"paradisiacal","score":174},{"word":"euphoriant","score":131},{"word":"paradisiac","score":116},{"word":"paradisaical","score":100},{"word":"paradisaic","score":83},{"word":"paradisial","score":71},{"word":"well-chosen","score":56}]' -r_json=json.loads(result_string) -print(_parser(r_json)) \ No newline at end of file diff --git a/test1.py b/test1.py deleted file mode 100644 index 4b7105d..0000000 --- a/test1.py +++ /dev/null @@ -1,24 +0,0 @@ -import json - -def _parser(result): - result_dict = result[0] - if not result_dict: - return [1, []] - syns = [syn for arr in result_dict[u'meta'][u'syns'] for syn in arr] - ants = [ant for arr in result_dict[u'meta'][u'ants']for ant in arr] - sseqs = [d[u'sseq'] for d in result_dict[u'def'] if d[u'sseq']] - flattened = [d for a in sseqs for b in a for c in b for d in c if isinstance(d,dict)] - near_lists = [d[u'near_list'] for d in flattened if d[u'near_list']] - rel_lists = [d[u'rel_list'] for d in flattened if d[u'rel_list']] - nears = [d[u'wd'] for arr in near_lists for c in arr for d in c if d[u'wd']] - rels = [d[u'wd'] for arr in rel_lists for c in arr for d in c if d[u'wd']] - return [0,[ - [ 'Synonyms', syns], - [ 'Related', rels], - [ 'Near', nears], - [ 'Antonyms', ants] - ]] - -result_string='[{"meta":{"id":"laughter","uuid":"d5568d3d-0a4b-4ad9-a7fa-ef61c4a3aa2b","src":"coll_thes","section":"alpha","target":{"tuuid":"3a26c05a-c942-4c40-8358-14abec28e469","tsrc":"collegiate"},"stems":["laughter","laughters"],"syns":[["belly laugh","boff","boffola","cachinnation","cackle","chortle","chuckle","giggle","guffaw","hee-haw","horselaugh","laugh","snicker","snigger","titter","twitter"]],"ants":[],"offensive":false},"hwi":{"hw":"laughter"},"fl":"noun","def":[{"sseq":[[["sense",{"dt":[["text","an explosive sound that is a sign of amusement "],["vis",[{"t":"the nervous producers were reassured by the sounds of {it}laughter{\/it} coming from the theater"}]]],"syn_list":[[{"wd":"belly laugh"},{"wd":"boff","wvrs":[{"wvl":"or","wva":"boffo"}]},{"wd":"boffola"},{"wd":"cachinnation"},{"wd":"cackle"},{"wd":"chortle"},{"wd":"chuckle"},{"wd":"giggle"},{"wd":"guffaw"},{"wd":"hee-haw"},{"wd":"horselaugh"},{"wd":"laugh"},{"wd":"snicker"},{"wd":"snigger"},{"wd":"titter"},{"wd":"twitter"}]],"rel_list":[[{"wd":"crow"},{"wd":"whoop"}],[{"wd":"grin"},{"wd":"simper"},{"wd":"smile"},{"wd":"smirk"}]],"near_list":[[{"wd":"cry"},{"wd":"groan"},{"wd":"moan"},{"wd":"sob"},{"wd":"wail"}],[{"wd":"face"},{"wd":"frown"},{"wd":"grimace"},{"wd":"lower","wvrs":[{"wvl":"also","wva":"lour"}]},{"wd":"mouth"},{"wd":"pout"},{"wd":"scowl"}]]}]]]}],"shortdef":["an explosive sound that is a sign of amusement"]}]' -r_json=json.loads(result_string) -print(_parser(r_json)) \ No newline at end of file From 23ba1431dfd2915da97f920d02a562ca8bbcdb71 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 08:42:01 -0400 Subject: [PATCH 07/41] Fixed Dictionary API Parser errors on missing values --- .../backends/dictionary_api_com_lookup.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index e787e83..c90711e 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -72,20 +72,24 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) def _parser(result): + if result is None or len(result) == 0: + return [1, []] result_dict = result[0] if not result_dict: return [1, []] - syns = [syn for arr in result_dict[u'meta'][u'syns'] for syn in arr] - ants = [ant for arr in result_dict[u'meta'][u'ants']for ant in arr] - sseqs = [d[u'sseq'] for d in result_dict[u'def'] if d[u'sseq']] + syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] + ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] + sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] flattened = [d for a in sseqs for b in a for c in b for d in c if isinstance(d,dict)] - near_lists = [d[u'near_list'] for d in flattened if d[u'near_list']] - rel_lists = [d[u'rel_list'] for d in flattened if d[u'rel_list']] - nears = [d[u'wd'] for arr in near_lists for c in arr for d in c if d[u'wd']] - rels = [d[u'wd'] for arr in rel_lists for c in arr for d in c if d[u'wd']] + near_lists = [d.get(u'near_list', []) for d in flattened] + rel_lists = [d.get(u'rel_list', []) for d in flattened] + nears = [d.get(u'wd', []) for arr in near_lists for c in arr for d in c] + rels = [d.get(u'wd', []) for arr in rel_lists for c in arr for d in c] + defs = result_dict.get(u'shortdef', []) return [0, [ [ 'Synonyms', syns], [ 'Related', rels], [ 'Near', nears], - [ 'Antonyms', ants] + [ 'Antonyms', ants], + [ 'Definitions', defs] ]] From c34f47cf1895f416a40147c7cd9929532ad039b0 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 08:57:09 -0400 Subject: [PATCH 08/41] Fixed word guessing for unknown words in Dictionary API --- .../thesaurus_query/backends/dictionary_api_com_lookup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index c90711e..91543c7 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -70,13 +70,16 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) return 1 return result_list - def _parser(result): if result is None or len(result) == 0: return [1, []] result_dict = result[0] if not result_dict: return [1, []] + if isinstance(result_dict, str): + return [1, [['Unknown word (did you mean):', [result_dict]]]] + if isinstance(result_dict, list): + return [1, [['Unknown word (did you mean):', result_dict]]] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] From 6794ee3d73dafad8d1f1ca9357720c6a6159b4d5 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 09:03:27 -0400 Subject: [PATCH 09/41] Fixed - Dictionary API parser returned wrong code for unknown word --- .../thesaurus_query/backends/dictionary_api_com_lookup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 91543c7..bd73730 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -77,9 +77,13 @@ def _parser(result): if not result_dict: return [1, []] if isinstance(result_dict, str): - return [1, [['Unknown word (did you mean):', [result_dict]]]] + return [0, [ + ['Unknown word (did you mean):', [result_dict]] + ]] if isinstance(result_dict, list): - return [1, [['Unknown word (did you mean):', result_dict]]] + return [0, [ + ['Unknown word (did you mean):', result_dict] + ]] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] From b3798491d836e31bca3aa5b3dd0c28531df979aa Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 09:21:46 -0400 Subject: [PATCH 10/41] Fixed - Dictionary API parser did not return full correction list --- .../thesaurus_query/backends/dictionary_api_com_lookup.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index bd73730..0ea94aa 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -77,13 +77,7 @@ def _parser(result): if not result_dict: return [1, []] if isinstance(result_dict, str): - return [0, [ - ['Unknown word (did you mean):', [result_dict]] - ]] - if isinstance(result_dict, list): - return [0, [ - ['Unknown word (did you mean):', result_dict] - ]] + return [1, [['Unknown word (did you mean):', result]]] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] From 849ec7643db422dbba3e923cb9af27ebd596d5a8 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 09:22:46 -0400 Subject: [PATCH 11/41] Fixed - Dictionary API parser returned wrong code for unknown word --- autoload/thesaurus_query/backends/dictionary_api_com_lookup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 0ea94aa..a8ca2f0 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -77,7 +77,7 @@ def _parser(result): if not result_dict: return [1, []] if isinstance(result_dict, str): - return [1, [['Unknown word (did you mean):', result]]] + return [0, [['Unknown word (did you mean):', result]]] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] From 3bd32ad7039c06526363105563d893707c647afb Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 09:42:58 -0400 Subject: [PATCH 12/41] Updated Readme with Back end info --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index 5069361..43a34f2 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,30 @@ quality source is either the OpenOffice Thesaurus source or mthesaur.txt. I am s ------- +Added new English back end: [dictionary_api_com](https://dictionaryapi.com/). This is the Merriam-Webster API and +as such is a very high-quality back end. However, it does require registration on their website as a developer in order to +gain access to the API Keys. They do explicitly state that it is free for non-commercial use up to 1,000 queries a day, which +should be sufficient for most needs. Make sure you select the `Thesaurus` api key, as that is what you will need in order for this +backend to work. + +In order to use this backend, add `dictionary_api_com` to `g:tq_enabled_backend` and set your api key to `g:tq_dictionary_api_key`, ex: +``` +let g:tq_dictionary_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' +``` +**This backend cannot work without an API key.** + +The DictionaryApi.com backend returns several categories of information in this order: + - Synonyms: The most relevant synonyms. + - Related: Words that are no exactly synonyms, but can be considered related to the word in question. + - Near: Words that are neither synonyms or antonyms, but are near by words. + - Antonyms: The most relevant antonyms + - Definitions: Short definitions. You _can_ replace your word with these, but they're mostly there for information purposes. + +Also, if the word cannot be found, the API may sometimes return a list of word suggestions. These will be returned as `Unknown word` +and allow you to choose a replacement from the list. + +------- + Added two new French backend based on [synonymo.fr](http://www.synonymo.fr/) and [cnrtl.fr](https://cnrtl.fr/). To activate them, add `fr` to variable `g:tq_language` and `synonymo_fr` and/or `cnrtl_fr` to `g:tq_enabled_backends`. From cf8d392bba5175b4f2825dcf9499ea074ea4d8d8 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 10:15:55 -0400 Subject: [PATCH 13/41] Added by_def format to dictionary api backend --- README.md | 8 ++++++-- .../backends/dictionary_api_com_lookup.py | 14 +++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 43a34f2..96f7f1e 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,17 @@ let g:tq_dictionary_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' ``` **This backend cannot work without an API key.** -The DictionaryApi.com backend returns several categories of information in this order: +The Back end can return data in two formats: + +By default, the DictionaryApi.com backend returns several categories of information in this order: - Synonyms: The most relevant synonyms. - - Related: Words that are no exactly synonyms, but can be considered related to the word in question. + - Related: Words that are not exactly synonyms, but can be considered related to the word in question. - Near: Words that are neither synonyms or antonyms, but are near by words. - Antonyms: The most relevant antonyms - Definitions: Short definitions. You _can_ replace your word with these, but they're mostly there for information purposes. +Or, it can break up the synonyms by their short definitions. To do this, set `g:tq_dictionary_api_format='by_def'` + Also, if the word cannot be found, the API may sometimes return a list of word suggestions. These will be returned as `Unknown word` and allow you to choose a replacement from the list. diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index a8ca2f0..fd48c62 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -34,12 +34,13 @@ def query(target, query_method="synonym"): ''' target=target.replace(u" ", u"+") result_list=_dictionary_api_wrapper(target, query_method=query_method) + format = get_variable('tq_dictionary_api_format', None) if result_list == -1: return [-1,[]] elif result_list == 1: return [1, []] else: - return _parser(result_list) + return _parser(result_list, format) def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc): @@ -70,7 +71,7 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) return 1 return result_list -def _parser(result): +def _parser(result, format = None): if result is None or len(result) == 0: return [1, []] result_dict = result[0] @@ -78,6 +79,14 @@ def _parser(result): return [1, []] if isinstance(result_dict, str): return [0, [['Unknown word (did you mean):', result]]] + defs = result_dict.get(u'shortdef', []) + + if format == 'by_def': + syns_list = result_dict.get(u'meta', {}).get(u'syns', []) + length = min(len(defs), len(syns_list)) + return [0, [ + [ [ defs[idx], syns_list[idx] ] for idx in range(length)] + ]] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] @@ -86,7 +95,6 @@ def _parser(result): rel_lists = [d.get(u'rel_list', []) for d in flattened] nears = [d.get(u'wd', []) for arr in near_lists for c in arr for d in c] rels = [d.get(u'wd', []) for arr in rel_lists for c in arr for d in c] - defs = result_dict.get(u'shortdef', []) return [0, [ [ 'Synonyms', syns], [ 'Related', rels], From 2756b14b2fbc39ac2ad93f631ca9ef2c2fc4fbcd Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 10:28:28 -0400 Subject: [PATCH 14/41] dictionary api - removed extra bracked (list) for by_def format --- .../thesaurus_query/backends/dictionary_api_com_lookup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index fd48c62..083595c 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -84,9 +84,9 @@ def _parser(result, format = None): if format == 'by_def': syns_list = result_dict.get(u'meta', {}).get(u'syns', []) length = min(len(defs), len(syns_list)) - return [0, [ - [ [ defs[idx], syns_list[idx] ] for idx in range(length)] - ]] + return [0, + [ [ defs[idx], syns_list[idx] ] for idx in range(length) ] + ] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] From 7fbeb30371c3113822af98a2312ab42890910267 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Mon, 21 Sep 2020 12:12:35 -0400 Subject: [PATCH 15/41] dictionary api - default return for to break up synonyms by def --- README.md | 12 ++++++++++-- .../backends/dictionary_api_com_lookup.py | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 96f7f1e..4d2b465 100644 --- a/README.md +++ b/README.md @@ -41,14 +41,22 @@ let g:tq_dictionary_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' The Back end can return data in two formats: -By default, the DictionaryApi.com backend returns several categories of information in this order: +*by_def* (default): +`g:tq_dictionary_api_format='by_def'` + +By default, the synonyms grouped by the short definition of the word. + +*by_type*: +`g:tq_dictionary_api_format='by_type'` + +The DictionaryApi.com backend as much data as it can, grouped into several categories of information in this order: - Synonyms: The most relevant synonyms. - Related: Words that are not exactly synonyms, but can be considered related to the word in question. - Near: Words that are neither synonyms or antonyms, but are near by words. - Antonyms: The most relevant antonyms - Definitions: Short definitions. You _can_ replace your word with these, but they're mostly there for information purposes. -Or, it can break up the synonyms by their short definitions. To do this, set `g:tq_dictionary_api_format='by_def'` +Note: While *by_type* returns the most data, it is not grouped by the word definitions. Also, if the word cannot be found, the API may sometimes return a list of word suggestions. These will be returned as `Unknown word` and allow you to choose a replacement from the list. diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 083595c..a0efe4c 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -34,7 +34,7 @@ def query(target, query_method="synonym"): ''' target=target.replace(u" ", u"+") result_list=_dictionary_api_wrapper(target, query_method=query_method) - format = get_variable('tq_dictionary_api_format', None) + format = get_variable('tq_dictionary_api_format', 'by_def') if result_list == -1: return [-1,[]] elif result_list == 1: @@ -81,7 +81,7 @@ def _parser(result, format = None): return [0, [['Unknown word (did you mean):', result]]] defs = result_dict.get(u'shortdef', []) - if format == 'by_def': + if format != 'by_type': syns_list = result_dict.get(u'meta', {}).get(u'syns', []) length = min(len(defs), len(syns_list)) return [0, From 3657aef0583c87d946f1b67a1c5cc4063b4a9949 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 23 Sep 2020 20:58:46 -0400 Subject: [PATCH 16/41] Updated dictionary api parser to handle multiple result sets --- .../backends/dictionary_api_com_lookup.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index a0efe4c..8739c7b 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -71,22 +71,12 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) return 1 return result_list -def _parser(result, format = None): - if result is None or len(result) == 0: - return [1, []] - result_dict = result[0] - if not result_dict: - return [1, []] - if isinstance(result_dict, str): - return [0, [['Unknown word (did you mean):', result]]] +def _parseResultDict(result_dict, parse_by = None): defs = result_dict.get(u'shortdef', []) - - if format != 'by_type': + if parse_by == 'by_def': syns_list = result_dict.get(u'meta', {}).get(u'syns', []) length = min(len(defs), len(syns_list)) - return [0, - [ [ defs[idx], syns_list[idx] ] for idx in range(length) ] - ] + return [ [ defs[idx], syns_list[idx] ] for idx in range(length) ] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] @@ -95,10 +85,20 @@ def _parser(result, format = None): rel_lists = [d.get(u'rel_list', []) for d in flattened] nears = [d.get(u'wd', []) for arr in near_lists for c in arr for d in c] rels = [d.get(u'wd', []) for arr in rel_lists for c in arr for d in c] - return [0, [ + return [ [ 'Synonyms', syns], [ 'Related', rels], [ 'Near', nears], [ 'Antonyms', ants], [ 'Definitions', defs] - ]] + ] + +def _parser(result, parse_by = None): + if result is None or len(result) == 0: + return [1, []] + result_dict = result[0] + if not result_dict: + return [1, []] + if isinstance(result_dict, str): + return [0, [['Unknown word (did you mean):', result]]] + return [ 0, [ pair for r_dict in result for pair in _parseResultDict(r_dict, parse_by) ] ] From d95f8f63179284c6923fa96722834d84fc2d6a68 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Wed, 23 Sep 2020 21:02:22 -0400 Subject: [PATCH 17/41] Updated dictionary api parser to handle multiple result sets --- autoload/thesaurus_query/backends/dictionary_api_com_lookup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 8739c7b..7b2a359 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -76,7 +76,7 @@ def _parseResultDict(result_dict, parse_by = None): if parse_by == 'by_def': syns_list = result_dict.get(u'meta', {}).get(u'syns', []) length = min(len(defs), len(syns_list)) - return [ [ defs[idx], syns_list[idx] ] for idx in range(length) ] + return [ [ defs[idx]+' ('+ result_dict.get(u'fl', '') +')', syns_list[idx] ] for idx in range(length) ] syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] From 5e3c2fd55e4789f24b078b987ac2d4a224287bbb Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 09:38:15 -0400 Subject: [PATCH 18/41] Updated Core code to handle antonyms using a separate list --- autoload/thesaurus_query.vim | 7 ++- .../backends/dictionary_api_com_lookup.py | 59 +++++++------------ autoload/thesaurus_query/thesaurus_query.py | 39 ++++++++---- plugin/thesaurus_query.vim | 19 ++++-- 4 files changed, 70 insertions(+), 54 deletions(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index b5d58e2..81c9553 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -223,11 +223,14 @@ function! thesaurus_query#Thesaurus_Query_Restore_Handler() exec s:tq_use_python.'tq_framework.restore_thesaurus_query_handler()' endfunction -function! thesaurus_query#Thesaurus_Query_Lookup(word, replace) " {{{ +function! thesaurus_query#Thesaurus_Query_Lookup(word, replace, type) " {{{ " a:word word to be looked up " a:replace flag: " 0 - don't replace word under cursor " 1 - replace word under cursor +" a:type flag: +" 0 - synonyms +" 1 - antonyms let l:replace = a:replace let l:trimmed_word = s:Trim(a:word) let l:word = substitute(tolower(l:trimmed_word), '"', '', 'g') @@ -255,7 +258,7 @@ while tq_continue_query>0: tq_continue_query = 0 # if replace flag is on, prompt user to choose after populating candidate list elif vim.eval('l:replace') != '0': - tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1]) + tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], type) else: tq_continue_query = 0 tq_framework.session_terminate() diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py index 7b2a359..2b22dd4 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py @@ -21,26 +21,18 @@ _timeout_period_default = 1.0 def query(target, query_method="synonym"): - ''' return result as list. relavance from high to low in each PoS. -Lookup routine for datamuse.com. When query_from_source is called, return: - [status, [[PoS, [word_0, word_1, ...]], [PoS, [word_0, word_1, ...]], ...]] -status: - 0: normal, result found, list will be returned as a nested list - 1: normal, result not found, return empty list - -1: unexpected result from query, return empty list -nested list = [PoS, list wordlist] + ''' Classifier('str'): Identifier to classify the resulting wordlist suits. wordlist = [word_0, word_1, ...]: list of words belonging to a same definition ''' target=target.replace(u" ", u"+") result_list=_dictionary_api_wrapper(target, query_method=query_method) - format = get_variable('tq_dictionary_api_format', 'by_def') if result_list == -1: - return [-1,[]] + return [-1, [], []] elif result_list == 1: - return [1, []] + return [1, [], []] else: - return _parser(result_list, format) + return _parser(result_list) def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc): @@ -71,34 +63,27 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) return 1 return result_list -def _parseResultDict(result_dict, parse_by = None): +def _parseAntonyms(result_dict): defs = result_dict.get(u'shortdef', []) - if parse_by == 'by_def': - syns_list = result_dict.get(u'meta', {}).get(u'syns', []) - length = min(len(defs), len(syns_list)) - return [ [ defs[idx]+' ('+ result_dict.get(u'fl', '') +')', syns_list[idx] ] for idx in range(length) ] - syns = [syn for arr in result_dict.get(u'meta', {}).get(u'syns', []) for syn in arr] - ants = [ant for arr in result_dict.get(u'meta', {}).get(u'ants', []) for ant in arr] - sseqs = [d.get(u'sseq', []) for d in result_dict.get(u'def', [])] - flattened = [d for a in sseqs for b in a for c in b for d in c if isinstance(d,dict)] - near_lists = [d.get(u'near_list', []) for d in flattened] - rel_lists = [d.get(u'rel_list', []) for d in flattened] - nears = [d.get(u'wd', []) for arr in near_lists for c in arr for d in c] - rels = [d.get(u'wd', []) for arr in rel_lists for c in arr for d in c] - return [ - [ 'Synonyms', syns], - [ 'Related', rels], - [ 'Near', nears], - [ 'Antonyms', ants], - [ 'Definitions', defs] - ] + ants_list = result_dict.get(u'meta', {}).get(u'ants', []) + length = min(len(defs), len(ants_list)) + return [ [ defs[idx]+' ('+ result_dict.get(u'fl', '') +')', ants_list[idx] ] for idx in range(length) if len(ants_list) > 0 ] -def _parser(result, parse_by = None): +def _parseSynonyms(result_dict): + defs = result_dict.get(u'shortdef', []) + syns_list = result_dict.get(u'meta', {}).get(u'syns', []) + length = min(len(defs), len(syns_list)) + return [ [ defs[idx]+' ('+ result_dict.get(u'fl', '') +')', syns_list[idx] ] for idx in range(length) if len(syns_list) > 0 ] + +def _parser(result): if result is None or len(result) == 0: - return [1, []] + return [1, [], []] result_dict = result[0] if not result_dict: - return [1, []] + return [1, [], []] if isinstance(result_dict, str): - return [0, [['Unknown word (did you mean):', result]]] - return [ 0, [ pair for r_dict in result for pair in _parseResultDict(r_dict, parse_by) ] ] + return [0, [['Unknown word (did you mean):', result]], [['Unknown word (did you mean):', result]]] + return [ 0, + [pair for r_dict in result for pair in _parseSynonyms(r_dict)], + [pair for r_dict in result for pair in _parseAntonyms(r_dict)] + ] diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 01b6913..f419801 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -20,6 +20,7 @@ _double_width_type = ["Lo"] query_session=list() +cache=list() class Thesaurus_Query_Handler: ''' Handler for thesaurus_query @@ -41,7 +42,8 @@ def session_init(self): self.good_backends = [] self.bad_backends = [] self.backend_in_line = self.query_backend_priority[:] - self.last_valid_result = [] + self.last_valid_synonyms = [] + self.last_valid_antonyms = [] self._session_inited = True def session_terminate(self): @@ -62,7 +64,7 @@ def session_terminate(self): del self.backend_in_line self._session_inited = False - def query(self, word, next=True, use_cache=True): + def query(self, word, next=True, type=0, use_cache=True): """ Query from enabled backend one by one until synonym found return: synonym_list @@ -72,17 +74,23 @@ def query(self, word, next=True, use_cache=True): self.session_init() # start a session if not started # word not found, start searching error_encountered = 0 + + # Check cache first + if use_cache: + for cache_result in cache: + if cache_result[0] == word: + return cache_result[1] if type == 0 else cache_result[2] # use session-wise backend management to prepare for current query if next: to_use_list = self.backend_in_line[:] success_list = self.good_backends[:] if len(to_use_list)==0: - return self.last_valid_result + return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms else: to_use_list = self.good_backends[::-1] success_list = self.backend_in_line[::-1] if len(to_use_list)<=1: - return self.last_valid_result + return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms success_list.append(to_use_list.pop(0)) local_bad_backends=[] for query_backend_curr in to_use_list: # query each of the backend list till found @@ -91,7 +99,15 @@ def query(self, word, next=True, use_cache=True): (self.query_backends[query_backend_curr].language not in \ specified_language): continue - [state, synonym_list]=self.query_backends[query_backend_curr].query(word) + query_result = self.query_backends[query_backend_curr].query(word) + if (len(query_result) >= 3): + [state, synonym_list, antonym_list] = query_result + else: + [state, synonym_list] = query_result + if type == 1: + state = 1 + antonym_list = [] + cache.append([word, synonym_list, antonym_list]) if state == -1: error_encountered = 1 local_bad_backends.append( @@ -120,15 +136,16 @@ def query(self, word, next=True, use_cache=True): self.good_backends = to_use_list[::-1] self.backend_in_line = success_list[::-1] if 'state' not in locals(): - if not self.last_valid_result: + if (type == 0 and not self.last_valid_synonyms) or not self.last_valid_antonyms: vim_command('echohl WarningMSG | echon "WARNING: " | echohl None | echon "No thesaurus source is used. Please check on your configuration on g:tq_enabled_backends and g:tq_language or b:tq_language.\n"') - return self.last_valid_result + return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms if not synonym_list: # update last valid result if positive result is found - return self.last_valid_result + return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms else: - self.last_valid_result=synonym_list + self.last_valid_synonyms=synonym_list + self.last_valid_antonyms=antonym_list - return synonym_list + return synonym_list if type == 0 else antonym_list def restore_thesaurus_query_handler(self): self.query_backend_priority = get_variable( @@ -208,7 +225,7 @@ def _double_width_char_count(word): dw_count += 1 return dw_count -def tq_replace_cursor_word_from_candidates(candidate_list, source_backend=None): +def tq_replace_cursor_word_from_candidates(candidate_list, source_backend=None, type=0): ''' populate candidate list, replace target word/phrase with candidate Description: Using vim's color message box to populate a candidate list from found diff --git a/plugin/thesaurus_query.vim b/plugin/thesaurus_query.vim index 89fe206..d3fa6c7 100644 --- a/plugin/thesaurus_query.vim +++ b/plugin/thesaurus_query.vim @@ -30,14 +30,20 @@ endif " Expose our commands to the user " -------------------------------- " -command! ThesaurusQueryReplaceCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1) -command! ThesaurusQueryLookupCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0) +command! ThesaurusQueryReplaceCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 0) +command! ThesaurusQueryLookupCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 0) command! ThesaurusQueryReset :call thesaurus_query#Thesaurus_Query_Restore_Handler() -command! -nargs=1 Thesaurus :call thesaurus_query#Thesaurus_Query_Lookup(, 0) +command! -nargs=1 Thesaurus :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 0) -command! -nargs=1 ThesaurusQueryReplace :call thesaurus_query#Thesaurus_Query_Lookup(, 1) +command! -nargs=1 ThesaurusQueryReplace :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 0) +command! ThesaurusQueryReplaceCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 1) +command! ThesaurusQueryLookupCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 1) + +command! -nargs=1 ThesaurusAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 1) + +command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 1) " -------------------------------- " Map keys @@ -48,6 +54,11 @@ if g:tq_map_keys vnoremap cs "ky:ThesaurusQueryReplace k nnoremap cs :ThesaurusQueryReplaceCurrentWord vnoremap cs "ky:ThesaurusQueryReplace k + + nnoremap ca :ThesaurusQueryReplaceCurrentWordAntonym + vnoremap ca "ky:ThesaurusQueryReplaceAntonym k + nnoremap ca :ThesaurusQueryReplaceCurrentWordAntonym + vnoremap ca "ky:ThesaurusQueryReplaceAntonym k endif if g:tq_use_vim_autocomplete From fdd15992847d79a57eef60d1b24fe5b54b9eef6f Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 09:50:46 -0400 Subject: [PATCH 19/41] Updated Core code to handle antonyms using a separate list --- autoload/thesaurus_query/thesaurus_query.py | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index f419801..9324710 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -64,7 +64,7 @@ def session_terminate(self): del self.backend_in_line self._session_inited = False - def query(self, word, next=True, type=0, use_cache=True): + def query(self, word, next=True, query_type=0, use_cache=True): """ Query from enabled backend one by one until synonym found return: synonym_list @@ -79,18 +79,18 @@ def query(self, word, next=True, type=0, use_cache=True): if use_cache: for cache_result in cache: if cache_result[0] == word: - return cache_result[1] if type == 0 else cache_result[2] + return cache_result[1] if query_type == 0 else cache_result[2] # use session-wise backend management to prepare for current query if next: to_use_list = self.backend_in_line[:] success_list = self.good_backends[:] if len(to_use_list)==0: - return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms + return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms else: to_use_list = self.good_backends[::-1] success_list = self.backend_in_line[::-1] if len(to_use_list)<=1: - return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms + return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms success_list.append(to_use_list.pop(0)) local_bad_backends=[] for query_backend_curr in to_use_list: # query each of the backend list till found @@ -104,7 +104,7 @@ def query(self, word, next=True, type=0, use_cache=True): [state, synonym_list, antonym_list] = query_result else: [state, synonym_list] = query_result - if type == 1: + if query_type == 1: state = 1 antonym_list = [] cache.append([word, synonym_list, antonym_list]) @@ -136,16 +136,16 @@ def query(self, word, next=True, type=0, use_cache=True): self.good_backends = to_use_list[::-1] self.backend_in_line = success_list[::-1] if 'state' not in locals(): - if (type == 0 and not self.last_valid_synonyms) or not self.last_valid_antonyms: + if (query_type == 0 and not self.last_valid_synonyms) or not self.last_valid_antonyms: vim_command('echohl WarningMSG | echon "WARNING: " | echohl None | echon "No thesaurus source is used. Please check on your configuration on g:tq_enabled_backends and g:tq_language or b:tq_language.\n"') - return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms + return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms if not synonym_list: # update last valid result if positive result is found - return self.last_valid_synonyms if type == 0 else self.last_valid_antonyms + return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms else: self.last_valid_synonyms=synonym_list self.last_valid_antonyms=antonym_list - return synonym_list if type == 0 else antonym_list + return synonym_list if query_type == 0 else antonym_list def restore_thesaurus_query_handler(self): self.query_backend_priority = get_variable( @@ -225,7 +225,7 @@ def _double_width_char_count(word): dw_count += 1 return dw_count -def tq_replace_cursor_word_from_candidates(candidate_list, source_backend=None, type=0): +def tq_replace_cursor_word_from_candidates(candidate_list, source_backend=None, candidate_type=0): ''' populate candidate list, replace target word/phrase with candidate Description: Using vim's color message box to populate a candidate list from found @@ -385,7 +385,7 @@ def scan_current_layer(find_tail): ]) return 0 -def tq_generate_thesaurus_buffer(candidates): +def tq_generate_thesaurus_buffer(candidates, candidate_type): ''' generate a buffer in Vim to show all found synonyms from query ''' if independent_session: # this module don't work in Vim independent session return None @@ -411,13 +411,13 @@ def tq_generate_thesaurus_buffer(candidates): tq_thesaurus_buffer = vim.current.buffer del tq_thesaurus_buffer[:] - def candidate_list_printing(word_list): + def candidate_list_printing(word_list, candidate_type): """ Append a list of synonyms to the end of buffer, Acceptable structure: [ word1, word2, word3, ... ] """ tq_thesaurus_buffer.append([""]) - tq_thesaurus_buffer[-1]='Synonyms:' + tq_thesaurus_buffer[-1]='Synonyms:' if candidate_type == 0 else 'Antonyms:' column_curr = 10 word_list_size = len(word_list) @@ -437,11 +437,11 @@ def candidate_list_printing(word_list): for case in candidates: tq_thesaurus_buffer.append([""]) if not case[0]: - candidate_list_printing(case[1]) + candidate_list_printing(case[1], candidate_type) continue tq_thesaurus_buffer.append([""]) tq_thesaurus_buffer[-1]='Found_as: {0}'.format(send_string_to_vim(case[0])) - candidate_list_printing(case[1]) + candidate_list_printing(case[1], candidate_type) vim_command("setlocal bufhidden=") vim_command("exec 'resize ' . (line('$'))") vim_command("nnoremap q :q") From fda15bf4a5e1ef03460c00bb437b32a18d421a7f Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 09:57:42 -0400 Subject: [PATCH 20/41] Updated Core code to handle antonyms using a separate list --- autoload/thesaurus_query/thesaurus_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 9324710..45bda85 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -107,13 +107,13 @@ def query(self, word, next=True, query_type=0, use_cache=True): if query_type == 1: state = 1 antonym_list = [] - cache.append([word, synonym_list, antonym_list]) if state == -1: error_encountered = 1 local_bad_backends.append( self.query_backends[query_backend_curr].identifier) continue if state == 0: + cache.append([word, synonym_list or [], antonym_list or []]) found = True if next: success_list.append( From 064f0e78810ef824f0ec33a3cb18ed51208d775a Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:01:12 -0400 Subject: [PATCH 21/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query/thesaurus_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 45bda85..5df9006 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -417,7 +417,7 @@ def candidate_list_printing(word_list, candidate_type): [ word1, word2, word3, ... ] """ tq_thesaurus_buffer.append([""]) - tq_thesaurus_buffer[-1]='Synonyms:' if candidate_type == 0 else 'Antonyms:' + tq_thesaurus_buffer[-1]= 'Antonyms:' column_curr = 10 word_list_size = len(word_list) From 952115728ab2ef96df98272a6bf1ee218b1c5591 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:03:04 -0400 Subject: [PATCH 22/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query/thesaurus_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 5df9006..790c626 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -249,7 +249,7 @@ def candidate_list_printing(result_IDed): for case in result_IDed: if case[0] != u"": vim_command('call thesaurus_query#echo_HL("Keyword|Found as: |Directory|{0}|None|\\n")'.format(send_string_to_vim(case[0]))) - vim_command('call thesaurus_query#echo_HL("Keyword|Synonyms: |None|")') + vim_command(f'call thesaurus_query#echo_HL("Keyword|Antonyms: |None|")') col_count = 10 col_count_max = int(vim.eval("&columns")) for synonym_i in case[1]: From 1f03c8796a9b72f67a51db2518a14c28e0224a13 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:05:45 -0400 Subject: [PATCH 23/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query/thesaurus_query.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 790c626..aa6d272 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -249,7 +249,7 @@ def candidate_list_printing(result_IDed): for case in result_IDed: if case[0] != u"": vim_command('call thesaurus_query#echo_HL("Keyword|Found as: |Directory|{0}|None|\\n")'.format(send_string_to_vim(case[0]))) - vim_command(f'call thesaurus_query#echo_HL("Keyword|Antonyms: |None|")') + vim_command(f'call thesaurus_query#echo_HL("Keyword|{"Synonyms" if type == 0 else "Antonyms"}: |None|")') col_count = 10 col_count_max = int(vim.eval("&columns")) for synonym_i in case[1]: @@ -417,7 +417,7 @@ def candidate_list_printing(word_list, candidate_type): [ word1, word2, word3, ... ] """ tq_thesaurus_buffer.append([""]) - tq_thesaurus_buffer[-1]= 'Antonyms:' + tq_thesaurus_buffer[-1]= 'Synonyms:' if type == 0 else 'Antonyms:' column_curr = 10 word_list_size = len(word_list) From d7d34331596b403306bf6677b83b819d5f3a45b8 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:08:29 -0400 Subject: [PATCH 24/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query/thesaurus_query.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index aa6d272..5197016 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -249,7 +249,7 @@ def candidate_list_printing(result_IDed): for case in result_IDed: if case[0] != u"": vim_command('call thesaurus_query#echo_HL("Keyword|Found as: |Directory|{0}|None|\\n")'.format(send_string_to_vim(case[0]))) - vim_command(f'call thesaurus_query#echo_HL("Keyword|{"Synonyms" if type == 0 else "Antonyms"}: |None|")') + vim_command(f'call thesaurus_query#echo_HL("Keyword|{"Synonyms" if candidate_type == 0 else "Antonyms"}: |None|")') col_count = 10 col_count_max = int(vim.eval("&columns")) for synonym_i in case[1]: @@ -291,7 +291,7 @@ def obtain_user_choice(trunc_flag): if not thesaurus_user_choice: return 0 elif thesaurus_user_choice == "A": - tq_generate_thesaurus_buffer(candidate_list) + tq_generate_thesaurus_buffer(candidate_list, candidate_type) return 0 elif thesaurus_user_choice == "n": return 1 From 247b7e5d28556180cb13467715d870a46b58b89f Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:12:30 -0400 Subject: [PATCH 25/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query/thesaurus_query.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 5197016..1f24596 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -76,10 +76,10 @@ def query(self, word, next=True, query_type=0, use_cache=True): error_encountered = 0 # Check cache first - if use_cache: - for cache_result in cache: - if cache_result[0] == word: - return cache_result[1] if query_type == 0 else cache_result[2] + # if use_cache: + # for cache_result in cache: + # if cache_result[0] == word: + # return cache_result[1] if query_type == 0 else cache_result[2] # use session-wise backend management to prepare for current query if next: to_use_list = self.backend_in_line[:] @@ -113,7 +113,7 @@ def query(self, word, next=True, query_type=0, use_cache=True): self.query_backends[query_backend_curr].identifier) continue if state == 0: - cache.append([word, synonym_list or [], antonym_list or []]) + # cache.append([word, synonym_list or [], antonym_list or []]) found = True if next: success_list.append( @@ -145,7 +145,7 @@ def query(self, word, next=True, query_type=0, use_cache=True): self.last_valid_synonyms=synonym_list self.last_valid_antonyms=antonym_list - return synonym_list if query_type == 0 else antonym_list + return antonym_list #synonym_list if query_type == 0 else antonym_list def restore_thesaurus_query_handler(self): self.query_backend_priority = get_variable( From ccb538a4f17a01d44784336db7cbd25b2ce56e11 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:17:11 -0400 Subject: [PATCH 26/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query.vim | 8 ++++---- autoload/thesaurus_query/thesaurus_query.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index 81c9553..ac69bfd 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -223,12 +223,12 @@ function! thesaurus_query#Thesaurus_Query_Restore_Handler() exec s:tq_use_python.'tq_framework.restore_thesaurus_query_handler()' endfunction -function! thesaurus_query#Thesaurus_Query_Lookup(word, replace, type) " {{{ +function! thesaurus_query#Thesaurus_Query_Lookup(word, replace, query_type) " {{{ " a:word word to be looked up " a:replace flag: " 0 - don't replace word under cursor " 1 - replace word under cursor -" a:type flag: +" a:query_type flag: " 0 - synonyms " 1 - antonyms let l:replace = a:replace @@ -248,7 +248,7 @@ tq_continue_query = 1 while tq_continue_query>0: vim.command("redraw") tq_next_query_direction = True if tq_continue_query==1 else False - tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction) + tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, query_type) # Use Python environment for handling candidate displaying {{{ # mark for exit function if no candidate is found if not tq_synonym_result: @@ -258,7 +258,7 @@ while tq_continue_query>0: tq_continue_query = 0 # if replace flag is on, prompt user to choose after populating candidate list elif vim.eval('l:replace') != '0': - tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], type) + tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], query_type) else: tq_continue_query = 0 tq_framework.session_terminate() diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 1f24596..e360664 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -145,7 +145,7 @@ def query(self, word, next=True, query_type=0, use_cache=True): self.last_valid_synonyms=synonym_list self.last_valid_antonyms=antonym_list - return antonym_list #synonym_list if query_type == 0 else antonym_list + return synonym_list if query_type == 0 else antonym_list def restore_thesaurus_query_handler(self): self.query_backend_priority = get_variable( @@ -417,7 +417,7 @@ def candidate_list_printing(word_list, candidate_type): [ word1, word2, word3, ... ] """ tq_thesaurus_buffer.append([""]) - tq_thesaurus_buffer[-1]= 'Synonyms:' if type == 0 else 'Antonyms:' + tq_thesaurus_buffer[-1]= 'Synonyms:' if candidate_type == 0 else 'Antonyms:' column_curr = 10 word_list_size = len(word_list) From 7668f06ea92d786e65ece088033645f82b564edb Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:19:29 -0400 Subject: [PATCH 27/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query/thesaurus_query.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index e360664..4d6730f 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -76,10 +76,10 @@ def query(self, word, next=True, query_type=0, use_cache=True): error_encountered = 0 # Check cache first - # if use_cache: - # for cache_result in cache: - # if cache_result[0] == word: - # return cache_result[1] if query_type == 0 else cache_result[2] + if use_cache: + for cache_result in cache: + if cache_result[0] == word: + return cache_result[1] if query_type == 0 else cache_result[2] # use session-wise backend management to prepare for current query if next: to_use_list = self.backend_in_line[:] From ba8df57b304c9bcef8a059a54521e27a161e8867 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:23:21 -0400 Subject: [PATCH 28/41] Attempt to fix antonyms not showing --- autoload/thesaurus_query.vim | 4 ++-- plugin/thesaurus_query.vim | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index ac69bfd..4053793 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -248,7 +248,7 @@ tq_continue_query = 1 while tq_continue_query>0: vim.command("redraw") tq_next_query_direction = True if tq_continue_query==1 else False - tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, query_type) + tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 1) # Use Python environment for handling candidate displaying {{{ # mark for exit function if no candidate is found if not tq_synonym_result: @@ -258,7 +258,7 @@ while tq_continue_query>0: tq_continue_query = 0 # if replace flag is on, prompt user to choose after populating candidate list elif vim.eval('l:replace') != '0': - tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], query_type) + tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 1) else: tq_continue_query = 0 tq_framework.session_terminate() diff --git a/plugin/thesaurus_query.vim b/plugin/thesaurus_query.vim index d3fa6c7..52e821f 100644 --- a/plugin/thesaurus_query.vim +++ b/plugin/thesaurus_query.vim @@ -43,7 +43,7 @@ command! ThesaurusQueryLookupCurrentWordAntonym :call thesaurus_query#Thesaurus_ command! -nargs=1 ThesaurusAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 1) -command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 1) +command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#(, 1, 1) " -------------------------------- " Map keys From c9c45df031701ec5bab5ec2b12a86f7a966ede88 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:28:44 -0400 Subject: [PATCH 29/41] Attempt to fix missing query_type variable --- autoload/thesaurus_query.vim | 2 +- plugin/thesaurus_query.vim | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index 4053793..9757df9 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -248,7 +248,7 @@ tq_continue_query = 1 while tq_continue_query>0: vim.command("redraw") tq_next_query_direction = True if tq_continue_query==1 else False - tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 1) + tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 0 if query_type=='synonym' else 1) # Use Python environment for handling candidate displaying {{{ # mark for exit function if no candidate is found if not tq_synonym_result: diff --git a/plugin/thesaurus_query.vim b/plugin/thesaurus_query.vim index 52e821f..2bb0491 100644 --- a/plugin/thesaurus_query.vim +++ b/plugin/thesaurus_query.vim @@ -30,20 +30,20 @@ endif " Expose our commands to the user " -------------------------------- " -command! ThesaurusQueryReplaceCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 0) -command! ThesaurusQueryLookupCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 0) +command! ThesaurusQueryReplaceCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 'synonym') +command! ThesaurusQueryLookupCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 'synonym') command! ThesaurusQueryReset :call thesaurus_query#Thesaurus_Query_Restore_Handler() -command! -nargs=1 Thesaurus :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 0) +command! -nargs=1 Thesaurus :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 'synonym') -command! -nargs=1 ThesaurusQueryReplace :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 0) +command! -nargs=1 ThesaurusQueryReplace :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 'synonym') -command! ThesaurusQueryReplaceCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 1) -command! ThesaurusQueryLookupCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 1) +command! ThesaurusQueryReplaceCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 'antonym') +command! ThesaurusQueryLookupCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 'antonym') -command! -nargs=1 ThesaurusAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 1) +command! -nargs=1 ThesaurusAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 'antonym') -command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#(, 1, 1) +command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#(, 1, 'antonym') " -------------------------------- " Map keys From 23f54b5f48905a1b92c9c428e0e860c38e5ad74b Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:30:46 -0400 Subject: [PATCH 30/41] Attempt to fix missing query_type variable --- autoload/thesaurus_query.vim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index 9757df9..49f2100 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -232,6 +232,7 @@ function! thesaurus_query#Thesaurus_Query_Lookup(word, replace, query_type) " {{ " 0 - synonyms " 1 - antonyms let l:replace = a:replace + let l:query_type = a:query_type let l:trimmed_word = s:Trim(a:word) let l:word = substitute(tolower(l:trimmed_word), '"', '', 'g') let l:word_fname = fnameescape(l:word) @@ -258,7 +259,7 @@ while tq_continue_query>0: tq_continue_query = 0 # if replace flag is on, prompt user to choose after populating candidate list elif vim.eval('l:replace') != '0': - tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 1) + tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 0 if query_type=='synonym' else 1) else: tq_continue_query = 0 tq_framework.session_terminate() From 68daff5eafc5ba0ec08f28e351df5a4b5182b8bf Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:34:17 -0400 Subject: [PATCH 31/41] Attempt to fix missing query_type variable --- autoload/thesaurus_query.vim | 6 +++--- plugin/thesaurus_query.vim | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index 49f2100..6c0f23a 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -231,8 +231,8 @@ function! thesaurus_query#Thesaurus_Query_Lookup(word, replace, query_type) " {{ " a:query_type flag: " 0 - synonyms " 1 - antonyms - let l:replace = a:replace let l:query_type = a:query_type + let l:replace = a:replace let l:trimmed_word = s:Trim(a:word) let l:word = substitute(tolower(l:trimmed_word), '"', '', 'g') let l:word_fname = fnameescape(l:word) @@ -249,7 +249,7 @@ tq_continue_query = 1 while tq_continue_query>0: vim.command("redraw") tq_next_query_direction = True if tq_continue_query==1 else False - tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 0 if query_type=='synonym' else 1) + tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 0 if vim.eval('l:replace') == '0' else 1) # Use Python environment for handling candidate displaying {{{ # mark for exit function if no candidate is found if not tq_synonym_result: @@ -259,7 +259,7 @@ while tq_continue_query>0: tq_continue_query = 0 # if replace flag is on, prompt user to choose after populating candidate list elif vim.eval('l:replace') != '0': - tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 0 if query_type=='synonym' else 1) + tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 0 if vim.eval('l:replace') == '0' else 1) else: tq_continue_query = 0 tq_framework.session_terminate() diff --git a/plugin/thesaurus_query.vim b/plugin/thesaurus_query.vim index 2bb0491..52e821f 100644 --- a/plugin/thesaurus_query.vim +++ b/plugin/thesaurus_query.vim @@ -30,20 +30,20 @@ endif " Expose our commands to the user " -------------------------------- " -command! ThesaurusQueryReplaceCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 'synonym') -command! ThesaurusQueryLookupCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 'synonym') +command! ThesaurusQueryReplaceCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 0) +command! ThesaurusQueryLookupCurrentWord :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 0) command! ThesaurusQueryReset :call thesaurus_query#Thesaurus_Query_Restore_Handler() -command! -nargs=1 Thesaurus :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 'synonym') +command! -nargs=1 Thesaurus :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 0) -command! -nargs=1 ThesaurusQueryReplace :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 'synonym') +command! -nargs=1 ThesaurusQueryReplace :call thesaurus_query#Thesaurus_Query_Lookup(, 1, 0) -command! ThesaurusQueryReplaceCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 'antonym') -command! ThesaurusQueryLookupCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 'antonym') +command! ThesaurusQueryReplaceCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 1, 1) +command! ThesaurusQueryLookupCurrentWordAntonym :call thesaurus_query#Thesaurus_Query_Lookup(expand(''), 0, 1) -command! -nargs=1 ThesaurusAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 'antonym') +command! -nargs=1 ThesaurusAntonym :call thesaurus_query#Thesaurus_Query_Lookup(, 0, 1) -command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#(, 1, 'antonym') +command! -nargs=1 ThesaurusQueryReplaceAntonym :call thesaurus_query#(, 1, 1) " -------------------------------- " Map keys From 207ce40a69302cc9294f90904a04a9c1ce5c5814 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:35:16 -0400 Subject: [PATCH 32/41] Attempt to fix missing query_type variable --- autoload/thesaurus_query.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index 6c0f23a..6238a14 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -249,7 +249,7 @@ tq_continue_query = 1 while tq_continue_query>0: vim.command("redraw") tq_next_query_direction = True if tq_continue_query==1 else False - tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 0 if vim.eval('l:replace') == '0' else 1) + tq_synonym_result = tq_framework.query(decode_utf_8(vim.eval("l:word")), tq_next_query_direction, 0 if vim.eval('l:query_type') == '0' else 1) # Use Python environment for handling candidate displaying {{{ # mark for exit function if no candidate is found if not tq_synonym_result: @@ -259,7 +259,7 @@ while tq_continue_query>0: tq_continue_query = 0 # if replace flag is on, prompt user to choose after populating candidate list elif vim.eval('l:replace') != '0': - tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 0 if vim.eval('l:replace') == '0' else 1) + tq_continue_query = tq_interface.tq_replace_cursor_word_from_candidates(tq_synonym_result, tq_framework.good_backends[-1], 0 if vim.eval('l:query_type') == '0' else 1) else: tq_continue_query = 0 tq_framework.session_terminate() From 42cdc996378a4df61e8f5b874e8001305d26bfc8 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Thu, 24 Sep 2020 10:41:03 -0400 Subject: [PATCH 33/41] Updated Readme to reflect antonyms --- README.md | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4d2b465..91a2a9e 100644 --- a/README.md +++ b/README.md @@ -39,24 +39,18 @@ let g:tq_dictionary_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' ``` **This backend cannot work without an API key.** -The Back end can return data in two formats: - -*by_def* (default): -`g:tq_dictionary_api_format='by_def'` - -By default, the synonyms grouped by the short definition of the word. +This particular backend can also return antonyms using a different command: +``` +:ThesaurusQueryReplaceCurrentWordAntonym +``` -*by_type*: -`g:tq_dictionary_api_format='by_type'` +By default, this is bound to: -The DictionaryApi.com backend as much data as it can, grouped into several categories of information in this order: - - Synonyms: The most relevant synonyms. - - Related: Words that are not exactly synonyms, but can be considered related to the word in question. - - Near: Words that are neither synonyms or antonyms, but are near by words. - - Antonyms: The most relevant antonyms - - Definitions: Short definitions. You _can_ replace your word with these, but they're mostly there for information purposes. +```vim +nnoremap ca :ThesaurusQueryReplaceCurrentWord +``` -Note: While *by_type* returns the most data, it is not grouped by the word definitions. +See **Usage** below for changing the bindings. Also, if the word cannot be found, the API may sometimes return a list of word suggestions. These will be returned as `Unknown word` and allow you to choose a replacement from the list. From eae6023ef7b0603776d555d8a2f2b0173d1f71c8 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Fri, 2 Oct 2020 07:46:28 -0400 Subject: [PATCH 34/41] Edits --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4d2b465..2210023 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ should be sufficient for most needs. Make sure you select the `Thesaurus` api ke backend to work. In order to use this backend, add `dictionary_api_com` to `g:tq_enabled_backend` and set your api key to `g:tq_dictionary_api_key`, ex: + ``` let g:tq_dictionary_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' ``` From 8582be4b3447494e3bcc65443c17e32e419e7a79 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Fri, 2 Oct 2020 11:20:02 -0400 Subject: [PATCH 35/41] Caching, Rename, cleanup - Caching logic is finished - Renamed dictionary_api backend to merriam_webster for clarity - Cleaned up docs and code --- README.md | 49 ++++++++---- autoload/thesaurus_query.vim | 10 ++- ...om_lookup.py => merriam_webster_lookup.py} | 32 ++++---- autoload/thesaurus_query/thesaurus_query.py | 75 ++++++++++++------- doc/thesaurus_query.txt | 12 ++- 5 files changed, 121 insertions(+), 57 deletions(-) rename autoload/thesaurus_query/backends/{dictionary_api_com_lookup.py => merriam_webster_lookup.py} (72%) diff --git a/README.md b/README.md index dfafa30..e96bf4c 100644 --- a/README.md +++ b/README.md @@ -19,28 +19,20 @@ required**. ## What's new -Deleted `thesaurus_com` backend due to the legal warning from Thesaurus.com on -the upstream package [thesarus](https://github.com/Manwholikespie/thesaurus). -For existing users that still have `thesaurus_com` explicitly enabled, the -backend now always return exception. For English users, currently the highest -quality source is either the OpenOffice Thesaurus source or mthesaur.txt. I am sorry for any inconvenience caused. - -------- - -Added new English back end: [dictionary_api_com](https://dictionaryapi.com/). This is the Merriam-Webster API and +Added new English back end: [merriam_webster](https://dictionaryapi.com/). This is the Merriam-Webster API and as such is a very high-quality back end. However, it does require registration on their website as a developer in order to gain access to the API Keys. They do explicitly state that it is free for non-commercial use up to 1,000 queries a day, which should be sufficient for most needs. Make sure you select the `Thesaurus` api key, as that is what you will need in order for this backend to work. -In order to use this backend, add `dictionary_api_com` to `g:tq_enabled_backend` and set your api key to `g:tq_dictionary_api_key`, ex: +In order to use this backend, add `merriam_webster` to `g:tq_enabled_backend` and set your api key to `g:tq_merriam_webster_api_key`, ex: ``` -let g:tq_dictionary_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' +let g:tq_merriam_webster_api_key='cxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxa' ``` **This backend cannot work without an API key.** -This particular backend can also return antonyms using a different command: +The backend also returns antonyms using a different command: ``` :ThesaurusQueryReplaceCurrentWordAntonym ``` @@ -53,11 +45,19 @@ nnoremap ca :ThesaurusQueryReplaceCurrentWord See **Usage** below for changing the bindings. -Also, if the word cannot be found, the API may sometimes return a list of word suggestions. These will be returned as `Unknown word` +If the word cannot be found, the API may sometimes return a list of word suggestions. These will be returned as `Unknown word` and allow you to choose a replacement from the list. ------- +Deleted `thesaurus_com` backend due to the legal warning from Thesaurus.com on +the upstream package [thesarus](https://github.com/Manwholikespie/thesaurus). +For existing users that still have `thesaurus_com` explicitly enabled, the +backend now always return exception. For English users, currently the highest +quality source is either the OpenOffice Thesaurus source or mthesaur.txt. I am sorry for any inconvenience caused. + +------- + Added two new French backend based on [synonymo.fr](http://www.synonymo.fr/) and [cnrtl.fr](https://cnrtl.fr/). To activate them, add `fr` to variable `g:tq_language` and `synonymo_fr` and/or `cnrtl_fr` to `g:tq_enabled_backends`. @@ -233,6 +233,13 @@ backends is behaving properly. website didn't provide standard API to use. Hence functionality of this backend depends on whether the website owner will change the webpage design. This backend requires `bs4` *BeautifulSoup* dependency. +* **merriam\_webster** is an *English* thesaurus backend. It queries + [dictionaryapi.com](https://dictionaryapi.com/) for both synonym and antonym resources. + The api requires an api key that can be obtained by registering on their [website](https://dictionaryapi.com/). + Registration is free, but limits requests to 1,000 queries a day, which should be fine + for most users. When registering, make sure to select the "Thesaurus" api key. You will need + to assign that api key to `g:tq_merriam_webster_api_key` and manually add the + backend to `g:tq_enabled_backends` in your vimrc file. The thesaurus query plugin will go through the list `g:tq_enabled_backends` in sequence until a match is found. Unless user explicitly instruct, Next query @@ -270,6 +277,22 @@ originally defined priority, simply invoke command :ThesaurusQueryReset ``` +#### Caching + +In order to speed up results and avoid hitting the backend for repeated requests, the results +of a query can be cached. This is off by default. + +To enable caching, set the `tq_cache_results` value to some number. + +- `let g:tq_cache_results=-1`: (_Default_) Query results are not cached. +- `let g:tq_cache_results=0`: Query results are cached without limit. +- `let g:tq_cache_results=10`: The last 10 results are cached. You can set this to any positive number. + +Note: Separate caches are maintained for synonyms and antonyms (if the back end supports it). The cache setting +will apply to each cache separately. So if you specify `let g:tq_cache_results=10`, then the last 10 synonym and +antonym requests will be stored. Also, some back ends (Merriam-Webster, for example) always return both and will thus +be cached. + #### Online Backends Timeout Mechanism Timeout mechanism (configurable with `g:tq_online_backends_timeout`) is added diff --git a/autoload/thesaurus_query.vim b/autoload/thesaurus_query.vim index 6238a14..84b3000 100644 --- a/autoload/thesaurus_query.vim +++ b/autoload/thesaurus_query.vim @@ -123,6 +123,14 @@ if !exists("g:tq_raise_backend_priority_if_synonym_found") let g:tq_raise_backend_priority_if_synonym_found=0 endif +" this variable sets whether the results will be cached +" -1: Results will not be cached +" 0: All results will be cached with no limit +" >=1: X results will be cached (Fifo logic) +if !exists("g:tq_cache_results") + let g:tq_cache_results=-1 +endif + " this variable is offered by core query handler. It's a list of " query_backends user want to enable, with the sequence of user prefered " priority. @@ -253,7 +261,7 @@ while tq_continue_query>0: # Use Python environment for handling candidate displaying {{{ # mark for exit function if no candidate is found if not tq_synonym_result: - vim.command("echom \"No synonym found for \\\"{0}\\\".\"".format(vim.eval("l:trimmed_word").replace('\\','\\\\').replace('"','\\"'))) + vim.command("echom \"No results found for \\\"{0}\\\".\"".format(vim.eval("l:trimmed_word").replace('\\','\\\\').replace('"','\\"'))) vim.command("let l:syno_found=0") tq_framework.session_terminate() tq_continue_query = 0 diff --git a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py similarity index 72% rename from autoload/thesaurus_query/backends/dictionary_api_com_lookup.py rename to autoload/thesaurus_query/backends/merriam_webster_lookup.py index 2b22dd4..609510c 100644 --- a/autoload/thesaurus_query/backends/dictionary_api_com_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -10,23 +10,31 @@ from urllib.error import URLError, HTTPError import json import socket -import codecs import ssl from ..tq_common_lib import fixurl, get_variable query_result_trunc=100 -identifier="dictionary_api_com" +identifier="merriam_webster" language="en" _timeout_period_default = 1.0 +time_out_choice = float(get_variable('tq_online_backends_timeout', _timeout_period_default)) +api_key = get_variable('tq_merriam_webster_api_key', '') -def query(target, query_method="synonym"): +def query(target): ''' - Classifier('str'): Identifier to classify the resulting wordlist suits. - wordlist = [word_0, word_1, ...]: list of words belonging to a same definition + Queries the Merriam Webster API to retrieve thesaurus results for the target word. + Requires the `tq_merriam_webster_api_key` to be set to an appropriate value. + Returns Status code and two lists: synonyms and antonyms. Both lists are broken up into their + appropriate word definitions. + + Note: If no word matches the target, the API may return substitute words. If this happens, both + synonyms and antonyms will list those words under the "Unknown Word" heading. ''' + if not target or target == '': + return [1, [], []] target=target.replace(u" ", u"+") - result_list=_dictionary_api_wrapper(target, query_method=query_method) + result_list=_dictionary_api_wrapper(target) if result_list == -1: return [-1, [], []] elif result_list == 1: @@ -35,18 +43,9 @@ def query(target, query_method="synonym"): return _parser(result_list) -def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc): - api_key = get_variable('tq_dictionary_api_key', '') +def _dictionary_api_wrapper(target): if api_key == '': return [-1, []] - time_out_choice = float(get_variable( - 'tq_online_backends_timeout', _timeout_period_default)) - case_mapper={"synonym":u"words?rel_syn=", - "suggest":u"sug?s=", - "antonym":u"words?rel_ant=", - "right_content":u"words?rc=", - "left_content":u"words?lc=" - } try: url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') response = urlopen(url, context=ssl.SSLContext(), timeout = time_out_choice).read() @@ -57,7 +56,6 @@ def _dictionary_api_wrapper(target, query_method, max_return=query_result_trunc) if isinstance(err.reason, socket.timeout): return 1 print(err) -# print(u"Internet Error. The word \"{0}\" has not been found on datamuse!\n".format(target)) return -1 except socket.timeout: # timeout only means underperforming return 1 diff --git a/autoload/thesaurus_query/thesaurus_query.py b/autoload/thesaurus_query/thesaurus_query.py index 4d6730f..efdafc4 100644 --- a/autoload/thesaurus_query/thesaurus_query.py +++ b/autoload/thesaurus_query/thesaurus_query.py @@ -20,7 +20,9 @@ _double_width_type = ["Lo"] query_session=list() -cache=list() + +cache_results = int(get_variable('tq_cache_results', '-1')) +specified_language = get_variable("tq_language", ['en']) class Thesaurus_Query_Handler: ''' Handler for thesaurus_query @@ -33,6 +35,8 @@ def __init__(self): ''' Initialize handler, load all available backends. ''' self.restore_thesaurus_query_handler() self.query_backends = tq_backends.query_backends + self.synonym_cache=[] + self.antonym_cache=[] self._session_inited=False def session_init(self): @@ -45,6 +49,7 @@ def session_init(self): self.last_valid_synonyms = [] self.last_valid_antonyms = [] self._session_inited = True + self.cached_used = False def session_terminate(self): ''' Terminate a query session, adjust query backend priority according @@ -63,24 +68,30 @@ def session_terminate(self): del self.bad_backends del self.backend_in_line self._session_inited = False + self.cached_used = False - def query(self, word, next=True, query_type=0, use_cache=True): + def query(self, word, next=True, query_type=0): """ Query from enabled backend one by one until synonym found return: - synonym_list + result list for synonyms or antonyms, depending on query_type """ - found = False if not self._session_inited: self.session_init() # start a session if not started - # word not found, start searching - error_encountered = 0 + + found = False + local_bad_backends=[] + antonym_list=[] + synonym_list=[] # Check cache first - if use_cache: - for cache_result in cache: + if not self.cached_used and cache_results > -1: + current_cache = self.synonym_cache if query_type == 0 else self.antonym_cache + for cache_result in current_cache: if cache_result[0] == word: - return cache_result[1] if query_type == 0 else cache_result[2] -# use session-wise backend management to prepare for current query + self.cached_used = True + self.good_backends = [cache_result[2] + ' (cached)'] + return cache_result[1] + # use session-wise backend management to prepare for current query if next: to_use_list = self.backend_in_line[:] success_list = self.good_backends[:] @@ -92,32 +103,30 @@ def query(self, word, next=True, query_type=0, use_cache=True): if len(to_use_list)<=1: return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms success_list.append(to_use_list.pop(0)) - local_bad_backends=[] for query_backend_curr in to_use_list: # query each of the backend list till found - specified_language = get_variable("tq_language", ['en']) - if specified_language!="All" and \ - (self.query_backends[query_backend_curr].language not in \ - specified_language): + query_backend = self.query_backends.get(query_backend_curr, None) + if not query_backend: continue - query_result = self.query_backends[query_backend_curr].query(word) + if specified_language!="All" and query_backend.language not in specified_language: + continue + query_result = query_backend.query(word) if (len(query_result) >= 3): [state, synonym_list, antonym_list] = query_result else: [state, synonym_list] = query_result + antonym_list = [] if query_type == 1: state = 1 - antonym_list = [] if state == -1: - error_encountered = 1 - local_bad_backends.append( - self.query_backends[query_backend_curr].identifier) + local_bad_backends.append(query_backend.identifier) continue if state == 0: - # cache.append([word, synonym_list or [], antonym_list or []]) + # Update caches + update_cache(self.antonym_cache, word, antonym_list, query_backend.identifier) + update_cache(self.synonym_cache, word, synonym_list, query_backend.identifier) found = True if next: - success_list.append( - self.query_backends[query_backend_curr].identifier) + success_list.append(query_backend.identifier) break if found and next: to_use_list.remove(success_list[-1]) @@ -139,7 +148,7 @@ def query(self, word, next=True, query_type=0, use_cache=True): if (query_type == 0 and not self.last_valid_synonyms) or not self.last_valid_antonyms: vim_command('echohl WarningMSG | echon "WARNING: " | echohl None | echon "No thesaurus source is used. Please check on your configuration on g:tq_enabled_backends and g:tq_language or b:tq_language.\n"') return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms - if not synonym_list: # update last valid result if positive result is found + if (query_type == 0 and not synonym_list) or (query_type == 1 and not antonym_list): # update last valid result if positive result is found return self.last_valid_synonyms if query_type == 0 else self.last_valid_antonyms else: self.last_valid_synonyms=synonym_list @@ -157,6 +166,22 @@ def restore_thesaurus_query_handler(self): self.query_backend_priority.remove("mthesaur_txt") self.query_backend_priority.insert(0,"mthesaur_txt") +def update_cache(cache, word, results, backend): + """ Takes a cache, a word, and the results returned by a query for a backend and adds + them to the cache. + Will remove existing word results if it exists. + Will truncate the cache if cache_results has been set to a postive number + Will not cache results if results is empty + """ + if cache_results == -1 or not results: + return + index = next((i for i, v in enumerate(cache) if v[0] == word), None) + if index is not None: + cache.pop(index) + cache.append((word, results, backend)) + if cache_results > 0 and len(cache) > cache_results: + cache.pop(0) + def truncate_synonym_list(synonym_list): """ Truncate synonym_list according to user truncation settings return: @@ -249,7 +274,7 @@ def candidate_list_printing(result_IDed): for case in result_IDed: if case[0] != u"": vim_command('call thesaurus_query#echo_HL("Keyword|Found as: |Directory|{0}|None|\\n")'.format(send_string_to_vim(case[0]))) - vim_command(f'call thesaurus_query#echo_HL("Keyword|{"Synonyms" if candidate_type == 0 else "Antonyms"}: |None|")') + vim_command('call thesaurus_query#echo_HL("Keyword|{0}: |None|")'.format(send_string_to_vim("Synonyms" if candidate_type == 0 else "Antonyms"))) col_count = 10 col_count_max = int(vim.eval("&columns")) for synonym_i in case[1]: diff --git a/doc/thesaurus_query.txt b/doc/thesaurus_query.txt index 067e006..fe68d84 100644 --- a/doc/thesaurus_query.txt +++ b/doc/thesaurus_query.txt @@ -23,6 +23,7 @@ CONTENTS *thesaurus_query.vim* `g:tq_truncation_on_relavance` `g:tq_truncation_on_definition_num` `g:tq_truncation_on_syno_list_size` + `g:tq_cache_results` 4.2 Make Your Own Backend ........................... |tq-backend-format| 5. Licence.................................................. |tq-licence| =============================================================================== @@ -156,7 +157,7 @@ g:tq_enabled_backends~ query_backends user want to enable, with the sequence of user prefered priority. Please be careful not to mis-spell when setting this variable. available options: `openthesaurus_de`, `woxikon_de`, `jeck_ru`, `thesaurus_com`, - `datamuse_com`, `mthesaur_txt`, `cilin_txt` + `datamuse_com`, `mthesaur_txt`, `cilin_txt`, `merriam_webster` > let g:tq_enabled_backends = ["cilin_txt", \ "openthesaurus_de", \ @@ -267,6 +268,15 @@ g:tq_truncation_on_syno_list_size~ interface, thesaurus split will NOT be truncated. > let g:tq_truncation_on_syno_list_size = -1 < +g:tq_cache_results~ + This defined the behavior for caching query results. If value is + -1: results are not cached + 0: All results are cached + n>0: Only the last n results are cached + Note that caching limits apply to antonym and synonym results + separately. + let g:tq_cache_results = -1 +< ------------------------------------------------------------------------------- 4.2 Make Your Own Backend *tq-backend-format* From 7cc2f0abcd5db6d3673954e8741b49da7fe6334c Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Fri, 2 Oct 2020 11:47:18 -0400 Subject: [PATCH 36/41] Fixed exceptions in case of missing or incorrect api key for merriam-webster --- autoload/thesaurus_query/backends/merriam_webster_lookup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/backends/merriam_webster_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py index 609510c..a5d741b 100644 --- a/autoload/thesaurus_query/backends/merriam_webster_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -9,6 +9,7 @@ from urllib.request import urlopen from urllib.error import URLError, HTTPError import json +from json.decoder import JSONDecodeError import socket import ssl from ..tq_common_lib import fixurl, get_variable @@ -45,7 +46,7 @@ def query(target): def _dictionary_api_wrapper(target): if api_key == '': - return [-1, []] + return -1 try: url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') response = urlopen(url, context=ssl.SSLContext(), timeout = time_out_choice).read() @@ -59,6 +60,8 @@ def _dictionary_api_wrapper(target): return -1 except socket.timeout: # timeout only means underperforming return 1 + except JSONDecodeError: + return -1 return result_list def _parseAntonyms(result_dict): From d25162dcd787fe1c1db639bdc49c57e13cc88f94 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Fri, 18 Dec 2020 10:30:58 -0500 Subject: [PATCH 37/41] Fixes for newer version of Python/Vim --- autoload/thesaurus_query/backends/merriam_webster_lookup.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/autoload/thesaurus_query/backends/merriam_webster_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py index a5d741b..0665745 100644 --- a/autoload/thesaurus_query/backends/merriam_webster_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -9,9 +9,7 @@ from urllib.request import urlopen from urllib.error import URLError, HTTPError import json -from json.decoder import JSONDecodeError import socket -import ssl from ..tq_common_lib import fixurl, get_variable query_result_trunc=100 @@ -49,7 +47,7 @@ def _dictionary_api_wrapper(target): return -1 try: url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') - response = urlopen(url, context=ssl.SSLContext(), timeout = time_out_choice).read() + response = urlopen(url, timeout = time_out_choice).read() result_list = json.loads(response.decode('utf-8')) except HTTPError: return 1 @@ -60,7 +58,7 @@ def _dictionary_api_wrapper(target): return -1 except socket.timeout: # timeout only means underperforming return 1 - except JSONDecodeError: + except ValueError: return -1 return result_list From 1519552d4353a258516269017abecc56b279813a Mon Sep 17 00:00:00 2001 From: root Date: Sun, 24 Jan 2021 22:29:58 +0000 Subject: [PATCH 38/41] Revert "Fixed exceptions in case of missing or incorrect api key for merriam-webster" This reverts commit 7cc2f0abcd5db6d3673954e8741b49da7fe6334c. --- autoload/thesaurus_query/backends/merriam_webster_lookup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/backends/merriam_webster_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py index 0665745..754e928 100644 --- a/autoload/thesaurus_query/backends/merriam_webster_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -44,7 +44,7 @@ def query(target): def _dictionary_api_wrapper(target): if api_key == '': - return -1 + return [-1, []] try: url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') response = urlopen(url, timeout = time_out_choice).read() From 6a31f25a93b5a8b6da9586a2b61b45464cd7c766 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 24 Jan 2021 22:35:55 +0000 Subject: [PATCH 39/41] Fixed iOS need for explicit SSL (not required for later version of Python) --- autoload/thesaurus_query/backends/merriam_webster_lookup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/thesaurus_query/backends/merriam_webster_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py index 754e928..2c5723b 100644 --- a/autoload/thesaurus_query/backends/merriam_webster_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -47,7 +47,7 @@ def _dictionary_api_wrapper(target): return [-1, []] try: url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') - response = urlopen(url, timeout = time_out_choice).read() + response = urlopen(url, context=ssl.SSLContext(), timeout = time_out_choice).read() result_list = json.loads(response.decode('utf-8')) except HTTPError: return 1 From c47f860c6de42df08d94a6879e36226abb0e113d Mon Sep 17 00:00:00 2001 From: root Date: Sun, 24 Jan 2021 23:32:45 +0000 Subject: [PATCH 40/41] forgot to add SSL import --- autoload/thesaurus_query/backends/merriam_webster_lookup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/thesaurus_query/backends/merriam_webster_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py index 2c5723b..ae40903 100644 --- a/autoload/thesaurus_query/backends/merriam_webster_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -9,6 +9,7 @@ from urllib.request import urlopen from urllib.error import URLError, HTTPError import json +import ssl import socket from ..tq_common_lib import fixurl, get_variable From c39f4aada95958f35583ff7f9b0add4a6337cfc2 Mon Sep 17 00:00:00 2001 From: Aaron Hayman Date: Fri, 25 Mar 2022 10:01:43 -0400 Subject: [PATCH 41/41] Removed SSL in urlopen, which was causing issues --- autoload/thesaurus_query/backends/merriam_webster_lookup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/autoload/thesaurus_query/backends/merriam_webster_lookup.py b/autoload/thesaurus_query/backends/merriam_webster_lookup.py index ae40903..754e928 100644 --- a/autoload/thesaurus_query/backends/merriam_webster_lookup.py +++ b/autoload/thesaurus_query/backends/merriam_webster_lookup.py @@ -9,7 +9,6 @@ from urllib.request import urlopen from urllib.error import URLError, HTTPError import json -import ssl import socket from ..tq_common_lib import fixurl, get_variable @@ -48,7 +47,7 @@ def _dictionary_api_wrapper(target): return [-1, []] try: url = fixurl(u'https://www.dictionaryapi.com/api/v3/references/thesaurus/json/{0}?key={1}'.format(target, api_key)).decode('ASCII') - response = urlopen(url, context=ssl.SSLContext(), timeout = time_out_choice).read() + response = urlopen(url, timeout = time_out_choice).read() result_list = json.loads(response.decode('utf-8')) except HTTPError: return 1