123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- # Copyright Materialize, Inc. and contributors. All rights reserved.
- #
- # Use of this software is governed by the Business Source License
- # included in the LICENSE file at the root of this repository.
- #
- # As of the Change Date specified in that file, in accordance with
- # the Business Source License, use of this software will be governed
- # by the Apache License, Version 2.0.
- import re
- from materialize.terminal import COLOR_GREEN, STYLE_BOLD, with_formattings
- def _search_value_to_pattern(search_value: str, use_regex: bool) -> re.Pattern[str]:
- regex_pattern = _search_value_to_regex(search_value, use_regex)
- return re.compile(f"({regex_pattern})", re.IGNORECASE | re.DOTALL)
- def _search_value_to_regex(search_value: str, use_regex: bool) -> str:
- if use_regex:
- return search_value
- return re.escape(search_value)
- def highlight_match(
- input: str,
- search_value: str,
- use_regex: bool,
- style: list[str] = [COLOR_GREEN, STYLE_BOLD],
- ) -> str:
- case_insensitive_pattern = _search_value_to_pattern(search_value, use_regex)
- match_replacement = with_formattings(r"\1", style)
- return case_insensitive_pattern.sub(match_replacement, input)
- def trim_match(
- match_text: str,
- search_value: str,
- use_regex: bool,
- one_line_match_presentation: bool,
- max_chars_before_match: int = 300,
- max_chars_after_match: int = 300,
- search_offset: int = 0,
- ) -> str:
- match_text = match_text.strip()
- case_insensitive_pattern = _search_value_to_pattern(search_value, use_regex)
- match = case_insensitive_pattern.search(match_text, pos=search_offset)
- assert match is not None
- match_begin_index = match.start()
- match_end_index = match.end()
- if one_line_match_presentation:
- match_text, (match_begin_index, match_end_index) = _trim_match_to_one_line(
- match_text, match_begin_index, match_end_index
- )
- match_text = _trim_match_to_max_length(
- match_text,
- match_begin_index,
- match_end_index,
- max_chars_after_match,
- max_chars_before_match,
- )
- return match_text
- def _trim_match_to_one_line(
- input: str, match_begin_index: int, match_end_index: int
- ) -> tuple[str, tuple[int, int]]:
- """
- :return: trimmed text, new match_begin_index, new match_end_index
- """
- cut_off_index_begin = input.rfind("\n", 0, match_begin_index)
- if cut_off_index_begin == -1:
- cut_off_index_begin = 0
- cut_off_index_end = input.find("\n", match_end_index)
- if cut_off_index_end == -1:
- cut_off_index_end = len(input)
- input = input[cut_off_index_begin:cut_off_index_end]
- return input, (
- match_begin_index - cut_off_index_begin,
- match_end_index - cut_off_index_begin,
- )
- def _trim_match_to_max_length(
- input: str,
- match_begin_index: int,
- match_end_index: int,
- max_chars_after_match: int,
- max_chars_before_match: int,
- ) -> str:
- # identify cut-off point before first match
- if match_begin_index > max_chars_before_match:
- cut_off_index_begin = input.find(
- " ", match_begin_index - max_chars_before_match, match_begin_index
- )
- if cut_off_index_begin == -1:
- cut_off_index_begin = match_begin_index - max_chars_before_match
- else:
- cut_off_index_begin = 0
- # identify cut-off point after first match
- if len(input) > match_end_index + max_chars_after_match:
- cut_off_index_end = input.rfind(
- " ", match_end_index, match_end_index + max_chars_after_match
- )
- if cut_off_index_end == -1:
- cut_off_index_end = match_end_index + max_chars_after_match
- else:
- cut_off_index_end = len(input)
- result = input[cut_off_index_begin:cut_off_index_end]
- result = result.strip()
- if cut_off_index_begin > 0:
- result = f"[...] {result}"
- if cut_off_index_end != len(input):
- result = f"{result} [...]"
- return result
- def determine_line_number(input: str, position: int) -> int:
- return 1 + input[:position].count("\n")
- def determine_position_in_line(input: str, position: int) -> int:
- position_line_start = input[:position].rfind("\n")
- return position - position_line_start
|