Skip to content

Commit 011a077

Browse files
authored
Merge pull request chubin#264 from chubin/fixes
Show multiple cheat sheets when found (chubin#147)
2 parents ada2785 + 9e8baaf commit 011a077

File tree

9 files changed

+219
-68
lines changed

9 files changed

+219
-68
lines changed

lib/cheat_wrapper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import re
1212
import json
1313

14-
from routing import get_answer_dict, get_topics_list
14+
from routing import get_answers, get_topics_list
1515
from search import find_answers_by_keyword
1616
from languages_data import LANGUAGE_ALIAS, rewrite_editor_section_name
1717
import postprocessing
@@ -98,7 +98,7 @@ def _parse_query(query):
9898
answers = find_answers_by_keyword(
9999
topic, keyword, options=search_options, request_options=request_options)
100100
else:
101-
answers = [get_answer_dict(topic, request_options=request_options)]
101+
answers = get_answers(topic, request_options=request_options)
102102

103103
answers = [
104104
postprocessing.postprocess(

lib/frontend/ansi.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ def _visualize(answers, request_options, search_mode=False):
101101
if color_style not in CONFIG['frontend.styles']:
102102
color_style = ''
103103

104+
# if there is more than one answer,
105+
# show the source of the answer
106+
multiple_answers = len(answers) > 1
107+
104108
found = True
105109
result = ""
106110
for answer_dict in answers:
@@ -109,14 +113,16 @@ def _visualize(answers, request_options, search_mode=False):
109113
answer = answer_dict['answer']
110114
found = found and not topic_type == 'unknown'
111115

112-
if search_mode and topic != 'LIMITED':
116+
if multiple_answers and topic != 'LIMITED':
117+
section_name = f"{topic_type}:{topic}"
118+
113119
if not highlight:
114-
result += "\n[%s]\n" % topic
120+
result += f"#[{section_name}]\n"
115121
else:
116-
result += "\n%s%s %s %s%s\n" % (
117-
colored.bg('dark_gray'), colored.attr("res_underlined"),
118-
topic,
119-
colored.attr("res_underlined"), colored.attr('reset'))
122+
result += "".join([
123+
"\n", colored.bg('dark_gray'), colored.attr("res_underlined"),
124+
f" {section_name} ",
125+
colored.attr("res_underlined"), colored.attr('reset'), "\n"])
120126

121127
if answer_dict['format'] in ['ansi', 'text']:
122128
result += answer

lib/routing.py

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
Exports:
55
66
get_topics_list()
7-
get_answer_dict()
7+
get_answers()
88
"""
9-
from __future__ import print_function
109

11-
import re
1210
import random
11+
import re
12+
from typing import Any, Dict, List
13+
1314
import cache
1415
import adapter.cheat_sheets
1516
import adapter.cmd
@@ -83,20 +84,28 @@ def get_topics_list(self, skip_dirs=False, skip_internal=False):
8384
self._cached_topics_list = answer
8485
return answer
8586

86-
def get_topic_type(self, topic):
87+
def get_topic_type(self, topic: str) -> List[str]:
8788
"""
88-
Return topic type for `topic` or "unknown" if topic can't be determined.
89+
Return list of topic types for `topic`
90+
or ["unknown"] if topic can't be determined.
8991
"""
9092

91-
def __get_topic_type(topic):
93+
def __get_topic_type(topic: str) -> List[str]:
94+
result = []
9295
for regexp, route in self.routing_table:
9396
if re.search(regexp, topic):
9497
if route in self._adapter:
9598
if self._adapter[route].is_found(topic):
96-
return route
99+
result.append(route)
97100
else:
98-
return route
99-
return CONFIG["routing.default"]
101+
result.append(route)
102+
if not result:
103+
return [CONFIG["routing.default"]]
104+
105+
# cut the default route off, if there are more than one route found
106+
if len(result) > 1:
107+
return result[:-1]
108+
return result
100109

101110
if topic not in self._cached_topic_type:
102111
self._cached_topic_type[topic] = __get_topic_type(topic)
@@ -111,7 +120,9 @@ def _get_page_dict(self, query, topic_type, request_options=None):
111120

112121
def handle_if_random_request(self, topic):
113122
"""
114-
Check if the `query` if a :random one, if yes we check its correctness and then randomly select a topic, based on the provided prefix.
123+
Check if the `query` is a :random one,
124+
if yes we check its correctness and then randomly select a topic,
125+
based on the provided prefix.
115126
116127
"""
117128

@@ -152,60 +163,80 @@ def __select_random_topic(prefix, topic_list):
152163
#Here if not a random requst, we just forward the topic
153164
return topic
154165

155-
def get_answer_dict(self, topic, request_options=None):
166+
def get_answers(self, topic: str, request_options:Dict[str, str] = None) -> List[Dict[str, Any]]:
156167
"""
157-
Find cheat sheet for the topic.
168+
Find cheat sheets for the topic.
158169
159170
Args:
160171
`topic` (str): the name of the topic of the cheat sheet
161172
162173
Returns:
163-
answer_dict: the answer dictionary
174+
[answer_dict]: list of answers (dictionaries)
164175
"""
165176

177+
# if topic specified as <topic_type>:<topic>,
178+
# cut <topic_type> off
179+
topic_type = ""
180+
if re.match("[^/]+:", topic):
181+
topic_type, topic = topic.split(":", 1)
182+
166183
topic = self.handle_if_random_request(topic)
167-
topic_type = self.get_topic_type(topic)
184+
topic_types = self.get_topic_type(topic)
185+
186+
# if topic_type is specified explicitly,
187+
# show pages only of that type
188+
if topic_type and topic_type in topic_types:
189+
topic_types = [topic_type]
168190

169191
# 'question' queries are pretty expensive, that's why they should be handled
170192
# in a special way:
171193
# we do not drop the old style cache entries and try to reuse them if possible
172-
if topic_type == 'question':
194+
if topic_types == ['question']:
173195
answer = cache.get('q:' + topic)
174196
if answer:
175197
if isinstance(answer, dict):
176-
return answer
177-
return {
198+
return [answer]
199+
return [{
178200
'topic': topic,
179201
'topic_type': 'question',
180202
'answer': answer,
181203
'format': 'text+code',
182-
}
204+
}]
183205

184-
answer = self._get_page_dict(topic, topic_type, request_options=request_options)
206+
answer = self._get_page_dict(topic, topic_types[0], request_options=request_options)
185207
if answer.get("cache", True):
186208
cache.put('q:' + topic, answer)
187-
return answer
209+
return [answer]
188210

189211
# Try to find cacheable queries in the cache.
190212
# If answer was not found in the cache, resolve it in a normal way and save in the cache
191-
cache_needed = self._adapter[topic_type].is_cache_needed()
192-
if cache_needed:
193-
answer = cache.get(topic)
194-
if not isinstance(answer, dict):
195-
answer = None
196-
if answer:
197-
return answer
213+
answers = []
214+
for topic_type in topic_types:
198215

199-
answer = self._get_page_dict(topic, topic_type, request_options=request_options)
200-
if isinstance(answer, dict):
201-
if "cache" in answer:
202-
cache_needed = answer["cache"]
216+
cache_entry_name = f"{topic_type}:{topic}"
217+
cache_needed = self._adapter[topic_type].is_cache_needed()
203218

204-
if cache_needed and answer:
205-
cache.put(topic, answer)
206-
return answer
219+
if cache_needed:
220+
answer = cache.get(cache_entry_name)
221+
if not isinstance(answer, dict):
222+
answer = None
223+
if answer:
224+
answers.append(answer)
225+
continue
226+
227+
answer = self._get_page_dict(topic, topic_type, request_options=request_options)
228+
if isinstance(answer, dict):
229+
if "cache" in answer:
230+
cache_needed = answer["cache"]
231+
232+
if cache_needed and answer:
233+
cache.put(cache_entry_name, answer)
234+
235+
answers.append(answer)
236+
237+
return answers
207238

208239
# pylint: disable=invalid-name
209240
_ROUTER = Router()
210241
get_topics_list = _ROUTER.get_topics_list
211-
get_answer_dict = _ROUTER.get_answer_dict
242+
get_answers = _ROUTER.get_answers

lib/search.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import re
2323

2424
from config import CONFIG
25-
from routing import get_answer_dict, get_topics_list
25+
from routing import get_answers, get_topics_list
2626

2727
def _limited_entry():
2828
return {
@@ -100,10 +100,11 @@ def find_answers_by_keyword(directory, keyword, options="", request_options=None
100100
if not options_dict["recursive"] and '/' in subtopic:
101101
continue
102102

103-
answer_dict = get_answer_dict(topic, request_options=request_options)
104-
answer_text = answer_dict.get('answer', '')
105-
if match(answer_text, keyword, options_dict=options_dict):
106-
answers_found.append(answer_dict)
103+
answer_dicts = get_answers(topic, request_options=request_options)
104+
for answer_dict in answer_dicts:
105+
answer_text = answer_dict.get('answer', '')
106+
if match(answer_text, keyword, options_dict=options_dict):
107+
answers_found.append(answer_dict)
107108

108109
if len(answers_found) > CONFIG['search.limit']:
109110
answers_found.append(

0 commit comments

Comments
 (0)