Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Flow.Launcher.Infrastructure/IAlphabet.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Flow.Launcher.Infrastructure
namespace Flow.Launcher.Infrastructure
{
/// <summary>
/// Translate a language to English letters using a given rule.
Expand All @@ -9,14 +9,22 @@ public interface IAlphabet
/// Translate a string to English letters, using a given rule.
/// </summary>
/// <param name="stringToTranslate">String to translate.</param>
/// <returns></returns>
/// <summary>
/// Translates the input string into English letters according to the implementing alphabet's rules.
/// </summary>
/// <param name="stringToTranslate">The string to be translated.</param>
/// <returns>A tuple containing the translated string and a <see cref="TranslationMapping"/> representing the mapping details.</returns>
public (string translation, TranslationMapping map) Translate(string stringToTranslate);

/// <summary>
/// Determine if a string can be translated to English letter with this Alphabet.
/// </summary>
/// <param name="stringToTranslate">String to translate.</param>
/// <returns></returns>
/// <summary>
/// Determines whether the specified string is eligible for translation to English letters using this alphabet's rules.
/// </summary>
/// <param name="stringToTranslate">The input string to evaluate for translation eligibility.</param>
/// <returns>True if the string should be translated; otherwise, false.</returns>
public bool ShouldTranslate(string stringToTranslate);
}
}
46 changes: 45 additions & 1 deletion Flow.Launcher.Infrastructure/PinyinAlphabet.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
Expand All @@ -21,6 +21,9 @@ public class PinyinAlphabet : IAlphabet

private ReadOnlyDictionary<string, string> currentDoublePinyinTable;

/// <summary>
/// Initializes a new instance of the <see cref="PinyinAlphabet"/> class, loading the double Pinyin table based on current settings and subscribing to setting changes to reload the table and clear the cache as needed.
/// </summary>
public PinyinAlphabet()
{
_settings = Ioc.Default.GetRequiredService<Settings>();
Expand All @@ -36,12 +39,22 @@ public PinyinAlphabet()
};
}

/// <summary>
/// Reloads the double Pinyin mapping table and clears the translation cache.
/// </summary>
public void Reload()
{
LoadDoublePinyinTable();
_pinyinCache.Clear();
}

/// <summary>
/// Loads the double Pinyin mapping table for the current schema from a JSON stream.
/// </summary>
/// <param name="jsonStream">A stream containing the double Pinyin tables in JSON format.</param>
/// <exception cref="InvalidOperationException">
/// Thrown if the current double Pinyin schema is invalid or the table is missing from the JSON.
/// </exception>
private void CreateDoublePinyinTableFromStream(Stream jsonStream)
{
Dictionary<string, Dictionary<string, string>> table = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(jsonStream);
Expand All @@ -52,6 +65,9 @@ private void CreateDoublePinyinTableFromStream(Stream jsonStream)
currentDoublePinyinTable = new ReadOnlyDictionary<string, string>(value);
}

/// <summary>
/// Loads the double Pinyin mapping table from a JSON file if enabled in settings; sets an empty table if loading fails or double Pinyin is disabled.
/// </summary>
private void LoadDoublePinyinTable()
{
if (_settings.UseDoublePinyin)
Expand All @@ -74,13 +90,28 @@ private void LoadDoublePinyinTable()
}
}

/// <summary>
/// Determines whether the specified string should be translated based on current settings and its content.
/// </summary>
/// <param name="stringToTranslate">The string to evaluate for translation eligibility.</param>
/// <returns>
/// True if the string contains no Chinese characters and, when double Pinyin is enabled, has an even length; otherwise, false.
/// </returns>
public bool ShouldTranslate(string stringToTranslate)
{
return _settings.UseDoublePinyin ?
(!WordsHelper.HasChinese(stringToTranslate) && stringToTranslate.Length % 2 == 0) :
!WordsHelper.HasChinese(stringToTranslate);
}

/// <summary>
/// Translates the input string to Pinyin, returning the translated string and its mapping.
/// </summary>
/// <param name="content">The string to translate.</param>
/// <returns>
/// A tuple containing the translated Pinyin string and a <see cref="TranslationMapping"/> object.
/// If Pinyin translation is disabled or the input contains no Chinese characters, returns the original string and null mapping.
/// </returns>
public (string translation, TranslationMapping map) Translate(string content)
{
if (!_settings.ShouldUsePinyin || !WordsHelper.HasChinese(content))
Expand All @@ -91,6 +122,13 @@ public bool ShouldTranslate(string stringToTranslate)
: BuildCacheFromContent(content);
}

/// <summary>
/// Generates the Pinyin or double Pinyin translation and mapping for the given content.
/// </summary>
/// <param name="content">The input string to translate.</param>
/// <returns>
/// A tuple containing the translated string and a <see cref="TranslationMapping"/> correlating original and translated indices.
/// </returns>
private (string translation, TranslationMapping map) BuildCacheFromContent(string content)
{
var resultList = WordsHelper.GetPinyinList(content);
Expand Down Expand Up @@ -138,6 +176,12 @@ public bool ShouldTranslate(string stringToTranslate)

#region Double Pinyin

/// <summary>
/// Converts a full Pinyin syllable to its double Pinyin equivalent using the current mapping table.
/// Returns the original Pinyin if no mapping exists.
/// </summary>
/// <param name="fullPinyin">The full Pinyin syllable to convert.</param>
/// <returns>The double Pinyin equivalent if found; otherwise, the original full Pinyin.</returns>
private string ToDoublePin(string fullPinyin)
{
if (currentDoublePinyinTable.TryGetValue(fullPinyin, out var doublePinyinValue))
Expand Down
21 changes: 19 additions & 2 deletions Flow.Launcher.Infrastructure/StringMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Plugin.SharedModels;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -29,7 +29,7 @@

public static MatchResult FuzzySearch(string query, string stringToCompare)
{
return Ioc.Default.GetRequiredService<StringMatcher>().FuzzyMatch(query, stringToCompare);

Check warning on line 32 in Flow.Launcher.Infrastructure/StringMatcher.cs

View workflow job for this annotation

GitHub Actions / Check Spelling

`Ioc` is not a recognized word. (unrecognized-spelling)
}

public MatchResult FuzzyMatch(string query, string stringToCompare)
Expand Down Expand Up @@ -60,7 +60,13 @@
/// 5. Once the previous character is verified, move on to the next character in the query substring.
/// 6. Move onto the next substring's characters until all substrings are checked.
/// 7. Consider success and move onto scoring if every char or substring without whitespaces matched
/// <summary>
/// Performs fuzzy and acronym-based matching between a query and a target string, returning match details and a relevance score.
/// </summary>
/// <param name="query">The search query to match against the target string.</param>
/// <param name="stringToCompare">The string to be compared with the query.</param>
/// <param name="opt">Options that control matching behavior, such as case sensitivity.</param>
/// <returns>A <see cref="MatchResult"/> indicating whether a match was found, the indices of matched characters, and the computed match score.</returns>
public MatchResult FuzzyMatch(string query, string stringToCompare, MatchOption opt)
{
if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query))
Expand Down Expand Up @@ -228,6 +234,12 @@
return new MatchResult(false, UserSettingSearchPrecision);
}

/// <summary>
/// Determines whether the character at the specified index in the string is considered part of an acronym, either by being an acronym character or a digit.
/// </summary>
/// <param name="stringToCompare">The string to evaluate.</param>
/// <param name="compareStringIndex">The index of the character to check.</param>
/// <returns>True if the character is an acronym character or a digit; otherwise, false.</returns>
private static bool IsAcronym(string stringToCompare, int compareStringIndex)
{
if (IsAcronymChar(stringToCompare, compareStringIndex) || IsAcronymNumber(stringToCompare, compareStringIndex))
Expand All @@ -236,7 +248,12 @@
return false;
}

// When counting acronyms, treat a set of numbers as one acronym ie. Visual 2019 as 2 acronyms instead of 5
/// <summary>
/// Determines whether the character at the specified index should be counted as a distinct acronym character, treating consecutive numbers as a single acronym.
/// </summary>
/// <param name="stringToCompare">The string being analyzed for acronym characters.</param>
/// <param name="compareStringIndex">The index of the character to evaluate.</param>
/// <returns>True if the character is an acronym character or the start of a numeric sequence; otherwise, false.</returns>
private static bool IsAcronymCount(string stringToCompare, int compareStringIndex)
{
if (IsAcronymChar(stringToCompare, compareStringIndex))
Expand Down
18 changes: 17 additions & 1 deletion Flow.Launcher.Infrastructure/TranslationMapping.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;

Expand All @@ -13,6 +13,13 @@ public class TranslationMapping

private int translatedLength = 0;

/// <summary>
/// Adds a mapping between an original index and a translated index range.
/// </summary>
/// <param name="originalIndex">The index in the original sequence.</param>
/// <param name="translatedIndex">The starting index of the corresponding range in the translated sequence.</param>
/// <param name="length">The length of the translated index range.</param>
/// <exception cref="InvalidOperationException">Thrown if the mapping has already been finalized.</exception>
public void AddNewIndex(int originalIndex, int translatedIndex, int length)
{
if (constructed)
Expand All @@ -24,6 +31,11 @@ public void AddNewIndex(int originalIndex, int translatedIndex, int length)
translatedLength += length - 1;
}

/// <summary>
/// Maps a translated index back to its corresponding original index based on stored translation ranges.
/// </summary>
/// <param name="translatedIndex">The index in the translated sequence to map.</param>
/// <returns>The corresponding index in the original sequence. If the translated index falls outside known ranges, returns an adjusted index based on accumulated translation lengths.</returns>
public int MapToOriginalIndex(int translatedIndex)
{
if (translatedIndex > translatedIndexes.Last())
Expand Down Expand Up @@ -86,6 +98,10 @@ public int MapToOriginalIndex(int translatedIndex)
}
}

/// <summary>
/// Finalizes the mapping, preventing any further modifications.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if the mapping has already been finalized.</exception>
public void endConstruct()
{
if (constructed)
Expand Down
Loading