@@ -713,7 +713,6 @@ async def add_factoid(
713713
714714 # Removes the factoid from the cache
715715 await self .handle_cache (guild , name )
716-
717716 await auxiliary .send_confirm_embed (
718717 message = f"Successfully { fmt } the factoid `{ factoid_name } `" ,
719718 channel = ctx .channel ,
@@ -1900,34 +1899,64 @@ async def send_factoids_as_file(
19001899
19011900 def search_content_and_bold (
19021901 self : Self , original : str , search_string : str
1903- ) -> list [ str ] :
1904- """Searches a string for a substring and bolds it
1902+ ) -> str | None :
1903+ """Finds all starting indices of the search_string in the original string.
19051904
19061905 Args:
1907- original (str): The original content to search through
1908- search_string (str): The string we are searching for
1906+ original (str): The original content to search through.
1907+ search_string (str): The string we are searching for.
19091908
19101909 Returns:
1911- list[str]: Snippets that have been modified with the search string
1910+ str | None: A single string with bolded matches and surrounding context,
1911+ or None if no matches exist.
19121912 """
1913- # Compile the regular expression for the substring
1914- pattern = re .compile (re .escape (search_string ))
1915- matches = list (pattern .finditer (original ))
1916-
1917- matches_list = []
1918-
1919- # Print all instances with 20 characters before and after each occurrence
1920- for match in matches :
1921- start = max (match .start () - 20 , 0 )
1922- end = min (match .end () + 20 , len (original ))
1923- context = original [start :end ]
1924- # Replace the substring in the context with the formatted version
1925- context_with_formatting = context .replace (
1926- search_string , f"**{ search_string } **"
1913+
1914+ original = original .replace (search_string , f"**{ search_string } **" )
1915+
1916+ show_range = 20
1917+
1918+ indices = []
1919+ search_len = len (search_string )
1920+ for i in range (len (original ) - search_len + 1 ):
1921+ if original [i : i + search_len ] == search_string :
1922+ indices .append (i )
1923+
1924+ if len (indices ) == 0 :
1925+ return None
1926+
1927+ # Generate ranges to include
1928+ ranges_to_include = []
1929+ for start in indices :
1930+ ranges_to_include .append (
1931+ (
1932+ max (0 , start - show_range - 2 ),
1933+ min (len (original ), start + search_len + show_range + 2 ),
1934+ )
19271935 )
1928- matches_list .append (context_with_formatting .replace ("****" , "" ))
19291936
1930- return matches_list
1937+ # Minimize ranges by merging overlapping or adjacent ranges
1938+ minimized_ranges = []
1939+ for start , end in sorted (ranges_to_include ):
1940+ if minimized_ranges and start <= minimized_ranges [- 1 ][1 ]:
1941+ minimized_ranges [- 1 ] = (
1942+ min (minimized_ranges [- 1 ][0 ], start ),
1943+ max (minimized_ranges [- 1 ][1 ], end ),
1944+ )
1945+ else :
1946+ minimized_ranges .append ((start , end ))
1947+
1948+ ranges_to_strs = []
1949+
1950+ if minimized_ranges [0 ][0 ] != 0 :
1951+ ranges_to_strs .append ("" )
1952+
1953+ for include_range in minimized_ranges :
1954+ ranges_to_strs .append (original [include_range [0 ] : include_range [1 ]])
1955+
1956+ if minimized_ranges [len (minimized_ranges ) - 1 ][1 ] != len (original ):
1957+ ranges_to_strs .append ("" )
1958+
1959+ return "..." .join (ranges_to_strs )
19311960
19321961 @auxiliary .with_typing
19331962 @commands .guild_only ()
@@ -1956,43 +1985,45 @@ async def search(self: Self, ctx: commands.Context, *, query: str) -> None:
19561985
19571986 factoids = await self .get_all_factoids (guild , list_hidden = False )
19581987 matches = {}
1959-
19601988 for factoid in factoids :
1989+ if factoid .alias :
1990+ continue
1991+
19611992 factoid_key = ", " .join (await self .get_list_of_aliases (factoid .name , guild ))
1962- if query in factoid .name .lower ():
1993+
1994+ # Name string
1995+ name_highlight = self .search_content_and_bold (factoid_key .lower (), query )
1996+ if name_highlight :
19631997 if factoid_key in matches :
1964- matches [factoid_key ].append (
1965- f"Name: { factoid .name .lower ().replace (query , f'**{ query } **' )} "
1966- )
1998+ matches [factoid_key ].append (f"Name: { name_highlight } " )
19671999 else :
1968- matches [factoid_key ] = [
1969- f"Name: { factoid .name .lower ().replace (query , f'**{ query } **' )} "
1970- ]
2000+ matches [factoid_key ] = [f"Name: { name_highlight } " ]
19712001
1972- if query in factoid . message . lower ():
1973- matches_list = self .search_content_and_bold (
1974- factoid .message .lower (), query
1975- )
1976- for match in matches_list :
1977- if factoid_key in matches :
1978- matches [factoid_key ].append (f"Content: { match } " )
1979- else :
1980- matches [factoid_key ] = [f"Content: { match } " ]
2002+ # Content
2003+ content_highlight = self .search_content_and_bold (
2004+ factoid .message .lower (), query
2005+ )
2006+ if content_highlight :
2007+ if factoid_key in matches :
2008+ matches [factoid_key ].append (f"Content: { content_highlight } " )
2009+ else :
2010+ matches [factoid_key ] = [f"Content: { content_highlight } " ]
19812011
1982- if (
1983- factoid .embed_config is not None
1984- and query in factoid .embed_config .lower ()
1985- ):
1986- matches_list = self .search_content_and_bold (
2012+ # Embed
2013+ if factoid .embed_config is not None :
2014+ embed_highlight = self .search_content_and_bold (
19872015 factoid .embed_config .lower (), query
19882016 )
1989- for match in matches_list :
2017+ if embed_highlight :
19902018 if factoid_key in matches :
19912019 matches [factoid_key ].append (
1992- f"Embed: { match .replace ('_' , '`_`' )} "
2020+ f"Embed: { embed_highlight .replace ('_' , '`_`' )} "
19932021 )
19942022 else :
1995- matches [factoid_key ] = [f"Embed: { match .replace ('_' , '`_`' )} " ]
2023+ matches [factoid_key ] = [
2024+ f"Embed: { embed_highlight .replace ('_' , '`_`' )} "
2025+ ]
2026+
19962027 if len (matches ) == 0 :
19972028 embed = auxiliary .prepare_deny_embed (
19982029 f"No factoids could be found matching `{ query } `"
0 commit comments