You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.5 KiB

  1. import re
  2. import fmt.comments
  3. def postprocess(answer, keyword, options, request_options=None):
  4. answer = _answer_add_comments(answer, request_options=request_options)
  5. answer = _answer_filter_by_keyword(answer, keyword, options, request_options=request_options)
  6. return answer
  7. def _answer_add_comments(answer, request_options=None):
  8. if answer['format'] != 'text+code':
  9. return answer
  10. topic = answer['topic']
  11. filetype = 'bash'
  12. if '/' in topic:
  13. filetype = topic.split('/', 1)[0]
  14. if filetype.startswith('q:'):
  15. filetype = filetype[2:]
  16. answer['answer'] = fmt.comments.beautify(
  17. answer['answer'], filetype, request_options)
  18. answer['format'] = 'code'
  19. return answer
  20. def _answer_filter_by_keyword(answer, keyword, options, request_options=None):
  21. answer['answer'] = _filter_by_keyword(answer['answer'], keyword, options)
  22. return answer
  23. def _filter_by_keyword(answer, keyword, options):
  24. def _join_paragraphs(paragraphs):
  25. answer = "\n".join(paragraphs)
  26. return answer
  27. def _split_paragraphs(text):
  28. answer = []
  29. paragraph = ""
  30. for line in text.splitlines():
  31. if line == "":
  32. answer.append(paragraph)
  33. paragraph = ""
  34. else:
  35. paragraph += line+"\n"
  36. answer.append(paragraph)
  37. return answer
  38. def _paragraph_contains(paragraph, keyword, insensitive=False, word_boundaries=True):
  39. """
  40. Check if `paragraph` contains `keyword`.
  41. Several keywords can be joined together using ~
  42. For example: ~ssh~passphrase
  43. """
  44. answer = True
  45. if '~' in keyword:
  46. keywords = keyword.split('~')
  47. else:
  48. keywords = [keyword]
  49. for kwrd in keywords:
  50. regex = re.escape(kwrd)
  51. if not word_boundaries:
  52. regex = r"\b%s\b" % kwrd
  53. if insensitive:
  54. answer = answer and bool(re.search(regex, paragraph, re.IGNORECASE))
  55. else:
  56. answer = answer and bool(re.search(regex, paragraph))
  57. return answer
  58. if not keyword:
  59. return answer
  60. search_options = {
  61. 'insensitive': 'i' in options,
  62. 'word_boundaries': 'b' in options
  63. }
  64. paragraphs = [p for p in _split_paragraphs(answer)
  65. if _paragraph_contains(p, keyword, **search_options)]
  66. if not paragraphs:
  67. return ""
  68. return _join_paragraphs(paragraphs)