mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 11:46:30 +02:00
Convert calculator numbers from/to user locale.
Tries to convert numbers in query string to invariant culture format before passing to YAMP, and the other way around when presenting result from YAMP. Nothing fancy, just a regular expression scanning for substrings consisting of number, decimal separator and group separator, trying a parse and convert on them. Translation is skipped if no conversion between user locale and invariant culture number format is necessary. Closes #436.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
@@ -20,6 +21,7 @@ namespace Wox.Plugin.Caculator
|
||||
private static Regex regBrackets = new Regex(@"[\(\)\[\]]", RegexOptions.Compiled);
|
||||
private static ParseContext yampContext;
|
||||
private PluginInitContext context { get; set; }
|
||||
private NumberTranslator _numberTranslator;
|
||||
|
||||
static Main()
|
||||
{
|
||||
@@ -36,34 +38,37 @@ namespace Wox.Plugin.Caculator
|
||||
|
||||
try
|
||||
{
|
||||
var result = yampContext.Run(query.Search);
|
||||
var result = yampContext.Run(this._numberTranslator?.Translate(query.Search) ?? query.Search);
|
||||
if (result.Output != null && !string.IsNullOrEmpty(result.Result))
|
||||
{
|
||||
string resultValue = this._numberTranslator?.TranslateBack(result.Result) ?? result.Result;
|
||||
return new List<Result>
|
||||
{ new Result
|
||||
{
|
||||
Title = result.Result,
|
||||
IcoPath = "Images/calculator.png",
|
||||
Score = 300,
|
||||
SubTitle = "Copy this number to the clipboard",
|
||||
Action = c =>
|
||||
{
|
||||
new Result
|
||||
{
|
||||
try
|
||||
Title = resultValue,
|
||||
IcoPath = "Images/calculator.png",
|
||||
Score = 300,
|
||||
SubTitle = "Copy this number to the clipboard",
|
||||
Action = c =>
|
||||
{
|
||||
Clipboard.SetText(result.Result);
|
||||
return true;
|
||||
}
|
||||
catch (ExternalException e)
|
||||
{
|
||||
MessageBox.Show("Copy failed, please try later");
|
||||
return false;
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(resultValue);
|
||||
return true;
|
||||
}
|
||||
catch (ExternalException e)
|
||||
{
|
||||
MessageBox.Show("Copy failed, please try later");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} };
|
||||
};
|
||||
}
|
||||
}
|
||||
catch
|
||||
{}
|
||||
{ }
|
||||
|
||||
return new List<Result>();
|
||||
}
|
||||
@@ -90,6 +95,7 @@ namespace Wox.Plugin.Caculator
|
||||
public void Init(PluginInitContext context)
|
||||
{
|
||||
this.context = context;
|
||||
this._numberTranslator = NumberTranslator.Create(CultureInfo.CurrentCulture, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
|
||||
95
Plugins/Wox.Plugin.Calculator/NumberTranslator.cs
Normal file
95
Plugins/Wox.Plugin.Calculator/NumberTranslator.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wox.Plugin.Caculator
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to convert all numbers in a text from one culture format to another.
|
||||
/// </summary>
|
||||
public class NumberTranslator
|
||||
{
|
||||
private readonly CultureInfo sourceCulture;
|
||||
private readonly CultureInfo targetCulture;
|
||||
private readonly Regex splitRegexForSource;
|
||||
private readonly Regex splitRegexForTarget;
|
||||
|
||||
private NumberTranslator(CultureInfo sourceCulture, CultureInfo targetCulture)
|
||||
{
|
||||
this.sourceCulture = sourceCulture;
|
||||
this.targetCulture = targetCulture;
|
||||
|
||||
this.splitRegexForSource = GetSplitRegex(this.sourceCulture);
|
||||
this.splitRegexForTarget = GetSplitRegex(this.targetCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="NumberTranslator"/> - returns null if no number conversion
|
||||
/// is required between the cultures.
|
||||
/// </summary>
|
||||
/// <param name="sourceCulture">source culture</param>
|
||||
/// <param name="targetCulture">target culture</param>
|
||||
/// <returns></returns>
|
||||
public static NumberTranslator Create(CultureInfo sourceCulture, CultureInfo targetCulture)
|
||||
{
|
||||
bool conversionRequired = sourceCulture.NumberFormat.NumberDecimalSeparator != targetCulture.NumberFormat.NumberDecimalSeparator
|
||||
|| sourceCulture.NumberFormat.PercentGroupSeparator != targetCulture.NumberFormat.PercentGroupSeparator
|
||||
|| sourceCulture.NumberFormat.NumberGroupSizes != targetCulture.NumberFormat.NumberGroupSizes;
|
||||
return conversionRequired
|
||||
? new NumberTranslator(sourceCulture, targetCulture)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate from source to target culture.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public string Translate(string input)
|
||||
{
|
||||
return this.Translate(input, this.sourceCulture, this.targetCulture, this.splitRegexForSource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate from target to source culture.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public string TranslateBack(string input)
|
||||
{
|
||||
return this.Translate(input, this.targetCulture, this.sourceCulture, this.splitRegexForTarget);
|
||||
}
|
||||
|
||||
private string Translate(string input, CultureInfo cultureFrom, CultureInfo cultureTo, Regex splitRegex)
|
||||
{
|
||||
var outputBuilder = new StringBuilder();
|
||||
|
||||
string[] tokens = splitRegex.Split(input);
|
||||
foreach (string token in tokens)
|
||||
{
|
||||
decimal number;
|
||||
outputBuilder.Append(
|
||||
decimal.TryParse(token, NumberStyles.Number, cultureFrom, out number)
|
||||
? number.ToString(cultureTo)
|
||||
: token);
|
||||
}
|
||||
|
||||
return outputBuilder.ToString();
|
||||
}
|
||||
|
||||
private Regex GetSplitRegex(CultureInfo culture)
|
||||
{
|
||||
var splitPattern = $"((?:\\d|{Regex.Escape(culture.NumberFormat.NumberDecimalSeparator)}";
|
||||
if (!string.IsNullOrEmpty(culture.NumberFormat.NumberGroupSeparator))
|
||||
{
|
||||
splitPattern += $"|{Regex.Escape(culture.NumberFormat.NumberGroupSeparator)}";
|
||||
}
|
||||
splitPattern += ")+)";
|
||||
return new Regex(splitPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@
|
||||
<Compile Include="..\..\SolutionAssemblyInfo.cs">
|
||||
<Link>Properties\SolutionAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="NumberTranslator.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user