Rename the [Ee]xts dir to ext (#38852)

**WARNING:** This PR will probably blow up all in-flight PRs

at some point in the early days of CmdPal, two of us created seperate
`Exts` and `exts` dirs. Depending on what the casing was on the branch
that you checked one of those out from, it'd get stuck like that on your
PC forever.

Windows didn't care, so we never noticed.

But GitHub does care, and now browsing the source on GitHub is basically
impossible.

Closes #38081
This commit is contained in:
Mike Griese
2025-04-15 06:07:22 -05:00
committed by GitHub
parent 60f50d853b
commit 2b5181b4c9
379 changed files with 35 additions and 35 deletions

View File

@@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.CompilerServices;
using Microsoft.CommandPalette.Extensions.Toolkit;
[assembly: InternalsVisibleTo("Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests")]
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
internal class AvailableResult
{
/// <summary>
/// Gets or sets the time/date value
/// </summary>
internal string Value { get; set; }
/// <summary>
/// Gets or sets the text used for the subtitle and as search term
/// </summary>
internal string Label { get; set; }
/// <summary>
/// Gets or sets an alternative search tag that will be evaluated if label doesn't match. For example we like to show the era on searches for 'year' too.
/// </summary>
internal string AlternativeSearchTag { get; set; }
/// <summary>
/// Gets or sets a value indicating the type of result
/// </summary>
internal ResultIconType IconType { get; set; }
/// <summary>
/// Returns the path to the icon
/// </summary>
/// <param name="theme">Theme</param>
/// <returns>Path</returns>
public IconInfo GetIconInfo()
{
return IconType switch
{
ResultIconType.Time => ResultHelper.TimeIcon,
ResultIconType.Date => ResultHelper.CalendarIcon,
ResultIconType.DateTime => ResultHelper.TimeDateIcon,
_ => null,
};
}
public ListItem ToListItem()
{
return new ListItem(new CopyTextCommand(this.Value))
{
Title = this.Value,
Subtitle = this.Label,
Icon = this.GetIconInfo(),
};
}
public int Score(string query, string label, string tags)
{
// Get match for label (or for tags if label score is <1)
var score = StringMatcher.FuzzySearch(query, label).Score;
if (score < 1)
{
foreach (var t in tags.Split(";"))
{
var tagScore = StringMatcher.FuzzySearch(query, t.Trim()).Score / 2;
if (tagScore > score)
{
score = tagScore / 2;
}
}
}
return score;
}
}
public enum ResultIconType
{
Time,
Date,
DateTime,
}

View File

@@ -0,0 +1,284 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
internal static class AvailableResultsList
{
/// <summary>
/// Returns a list with all available date time formats
/// </summary>
/// <param name="timeLongFormat">Required for UnitTest: Show time in long format</param>
/// <param name="dateLongFormat">Required for UnitTest: Show date in long format</param>
/// <param name="timestamp">Use custom <see cref="DateTime"/> object to calculate results instead of the system date/time</param>
/// <param name="firstWeekOfYear">Required for UnitTest: Use custom first week of the year instead of the plugin setting.</param>
/// <param name="firstDayOfWeek">Required for UnitTest: Use custom first day of the week instead the plugin setting.</param>
/// <returns>List of results</returns>
internal static List<AvailableResult> GetList(bool isKeywordSearch, SettingsManager settings, bool? timeLongFormat = null, bool? dateLongFormat = null, DateTime? timestamp = null, CalendarWeekRule? firstWeekOfYear = null, DayOfWeek? firstDayOfWeek = null)
{
var results = new List<AvailableResult>();
var calendar = CultureInfo.CurrentCulture.Calendar;
var timeExtended = timeLongFormat ?? settings.TimeWithSecond;
var dateExtended = dateLongFormat ?? settings.DateWithWeekday;
var isSystemDateTime = timestamp == null;
var dateTimeNow = timestamp ?? DateTime.Now;
var dateTimeNowUtc = dateTimeNow.ToUniversalTime();
var firstWeekRule = firstWeekOfYear ?? TimeAndDateHelper.GetCalendarWeekRule(settings.FirstWeekOfYear);
var firstDayOfTheWeek = firstDayOfWeek ?? TimeAndDateHelper.GetFirstDayOfWeek(settings.FirstDayOfWeek);
results.AddRange(new[]
{
// This range is reserved for the following three results: Time, Date, Now
// Don't add any new result in this range! For new results, please use the next range.
new AvailableResult()
{
Value = dateTimeNow.ToString(TimeAndDateHelper.GetStringFormat(FormatStringType.Time, timeExtended, dateExtended), CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Time,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, string.Empty, "Microsoft_plugin_timedate_SearchTagTimeNow"),
IconType = ResultIconType.Time,
},
new AvailableResult()
{
Value = dateTimeNow.ToString(TimeAndDateHelper.GetStringFormat(FormatStringType.Date, timeExtended, dateExtended), CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Date,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, string.Empty, "Microsoft_plugin_timedate_SearchTagDateNow"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.ToString(TimeAndDateHelper.GetStringFormat(FormatStringType.DateTime, timeExtended, dateExtended), CultureInfo.CurrentCulture),
Label = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_DateAndTime", "Microsoft_plugin_timedate_Now"),
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
});
if (isKeywordSearch || !settings.OnlyDateTimeNowGlobal)
{
// We use long instead of int for unix time stamp because int is too small after 03:14:07 UTC 2038-01-19
var unixTimestamp = ((DateTimeOffset)dateTimeNowUtc).ToUnixTimeSeconds();
var unixTimestampMilliseconds = ((DateTimeOffset)dateTimeNowUtc).ToUnixTimeMilliseconds();
var weekOfYear = calendar.GetWeekOfYear(dateTimeNow, firstWeekRule, firstDayOfTheWeek);
var era = DateTimeFormatInfo.CurrentInfo.GetEraName(calendar.GetEra(dateTimeNow));
var eraShort = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedEraName(calendar.GetEra(dateTimeNow));
results.AddRange(new[]
{
new AvailableResult()
{
Value = dateTimeNowUtc.ToString(TimeAndDateHelper.GetStringFormat(FormatStringType.Time, timeExtended, dateExtended), CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_TimeUtc,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, string.Empty, "Microsoft_plugin_timedate_SearchTagTimeNow"),
IconType = ResultIconType.Time,
},
new AvailableResult()
{
Value = dateTimeNowUtc.ToString(TimeAndDateHelper.GetStringFormat(FormatStringType.DateTime, timeExtended, dateExtended), CultureInfo.CurrentCulture),
Label = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_DateAndTimeUtc", "Microsoft_plugin_timedate_NowUtc"),
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = unixTimestamp.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Unix,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = unixTimestampMilliseconds.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Unix_Milliseconds,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNow.Hour.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Hour,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagTime"),
IconType = ResultIconType.Time,
},
new AvailableResult()
{
Value = dateTimeNow.Minute.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Minute,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagTime"),
IconType = ResultIconType.Time,
},
new AvailableResult()
{
Value = dateTimeNow.Second.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Second,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagTime"),
IconType = ResultIconType.Time,
},
new AvailableResult()
{
Value = dateTimeNow.Millisecond.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Millisecond,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagTime"),
IconType = ResultIconType.Time,
},
new AvailableResult()
{
Value = DateTimeFormatInfo.CurrentInfo.GetDayName(dateTimeNow.DayOfWeek),
Label = Resources.Microsoft_plugin_timedate_Day,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = TimeAndDateHelper.GetNumberOfDayInWeek(dateTimeNow, firstDayOfTheWeek).ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_DayOfWeek,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.Day.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_DayOfMonth,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.DayOfYear.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_DayOfYear,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = TimeAndDateHelper.GetWeekOfMonth(dateTimeNow, firstDayOfTheWeek).ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_WeekOfMonth,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = weekOfYear.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_WeekOfYear,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = DateTimeFormatInfo.CurrentInfo.GetMonthName(dateTimeNow.Month),
Label = Resources.Microsoft_plugin_timedate_Month,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.Month.ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_MonthOfYear,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.ToString("M", CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_DayMonth,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = calendar.GetYear(dateTimeNow).ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_Year,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = era,
Label = Resources.Microsoft_plugin_timedate_Era,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagEra"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = era != eraShort ? eraShort : string.Empty, // Setting value to empty string if 'era == eraShort'. This result will be filtered later.
Label = Resources.Microsoft_plugin_timedate_EraAbbreviation,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagEra"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.ToString("Y", CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_MonthYear,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
IconType = ResultIconType.Date,
},
new AvailableResult()
{
Value = dateTimeNow.ToFileTime().ToString(CultureInfo.CurrentCulture),
Label = Resources.Microsoft_plugin_timedate_WindowsFileTime,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNowUtc.ToString("u"),
Label = Resources.Microsoft_plugin_timedate_UniversalTime,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNow.ToString("s"),
Label = Resources.Microsoft_plugin_timedate_Iso8601,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNowUtc.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture),
Label = Resources.Microsoft_plugin_timedate_Iso8601Utc,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNow.ToString("yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture),
Label = Resources.Microsoft_plugin_timedate_Iso8601Zone,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNowUtc.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture),
Label = Resources.Microsoft_plugin_timedate_Iso8601ZoneUtc,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNow.ToString("R"),
Label = Resources.Microsoft_plugin_timedate_Rfc1123,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
new AvailableResult()
{
Value = dateTimeNow.ToString("yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture),
Label = Resources.Microsoft_plugin_timedate_filename_compatible,
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
IconType = ResultIconType.DateTime,
},
});
}
// Return only results where value is not empty
// This can happen, for example, when we can't read the 'era' or when 'era == era abbreviation' and we set value explicitly to an empty string.
return results.Where(x => !string.IsNullOrEmpty(x.Value)).ToList();
}
}

View File

@@ -0,0 +1,53 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.IO;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
internal static class ResultHelper
{
/// <summary>
/// Get the string based on the requested type
/// </summary>
/// <param name="isSystemTimeDate">Does the user search for system date/time?</param>
/// <param name="stringId">Id of the string. (Example: `MyString` for `MyString` and `MyStringNow`)</param>
/// <param name="stringIdNow">Optional string id for now case</param>
/// <returns>The string from the resource file, or <see cref="string.Empty"/> otherwise.</returns>
internal static string SelectStringFromResources(bool isSystemTimeDate, string stringId, string stringIdNow = default)
{
return !isSystemTimeDate
? Resources.ResourceManager.GetString(stringId, CultureInfo.CurrentUICulture) ?? string.Empty
: !string.IsNullOrEmpty(stringIdNow)
? Resources.ResourceManager.GetString(stringIdNow, CultureInfo.CurrentUICulture) ?? string.Empty
: Resources.ResourceManager.GetString(stringId + "Now", CultureInfo.CurrentUICulture) ?? string.Empty;
}
public static IconInfo TimeIcon { get; } = new IconInfo("\uE823");
public static IconInfo CalendarIcon { get; } = new IconInfo("\uE787");
public static IconInfo TimeDateIcon { get; } = new IconInfo("\uEC92");
/// <summary>
/// Gets a result with an error message that only numbers can't be parsed
/// </summary>
/// <returns>Element of type <see cref="Result"/>.</returns>
internal static ListItem CreateNumberErrorResult() => new ListItem(new NoOpCommand())
{
Title = Resources.Microsoft_plugin_timedate_ErrorResultTitle,
Subtitle = Resources.Microsoft_plugin_timedate_ErrorResultSubTitle,
Icon = IconHelpers.FromRelativePaths("Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.light.png", "Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.dark.png"),
};
internal static ListItem CreateInvalidInputErrorResult() => new ListItem(new NoOpCommand())
{
Title = Resources.Microsoft_plugin_timedate_InvalidInput_ErrorMessageTitle,
Subtitle = Resources.Microsoft_plugin_timedate_InvalidInput_ErrorMessageSubTitle,
Icon = IconHelpers.FromRelativePaths("Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.light.png", "Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.dark.png"),
};
}

View File

@@ -0,0 +1,170 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
public class SettingsManager : JsonSettingsManager
{
private static readonly string _namespace = "timeDate";
private static string Namespaced(string propertyName) => $"{_namespace}.{propertyName}";
private static readonly List<ChoiceSetSetting.Choice> _firstWeekOfYearChoices = new()
{
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_Setting_UseSystemSetting, "-1"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstDay, "0"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstFullWeek, "1"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstFourDayWeek, "2"),
};
private static readonly List<ChoiceSetSetting.Choice> _firstDayOfWeekChoices = GetFirstDayOfWeekChoices();
private static List<ChoiceSetSetting.Choice> GetFirstDayOfWeekChoices()
{
// List (Sorted for first day is Sunday)
var list = new List<ChoiceSetSetting.Choice>
{
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_Setting_UseSystemSetting, "-1"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Sunday, "0"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Monday, "1"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Tuesday, "2"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Wednesday, "3"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Thursday, "4"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Friday, "5"),
new ChoiceSetSetting.Choice(Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek_Saturday, "6"),
};
// Order Rules
var orderRuleSaturday = new string[] { "-1", "6", "0", "1", "2", "3", "4", "5" };
var orderRuleMonday = new string[] { "-1", "1", "2", "3", "4", "5", "6", "0" };
switch (DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek)
{
case DayOfWeek.Saturday:
return list.OrderBy(x => Array.IndexOf(orderRuleSaturday, x.Value)).ToList();
case DayOfWeek.Monday:
return list.OrderBy(x => Array.IndexOf(orderRuleMonday, x.Value)).ToList();
default:
// DayOfWeek.Sunday
return list;
}
}
private readonly ChoiceSetSetting _firstWeekOfYear = new(
Namespaced(nameof(FirstWeekOfYear)),
Resources.Microsoft_plugin_timedate_SettingFirstWeekRule,
Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_Description,
_firstWeekOfYearChoices);
private readonly ChoiceSetSetting _firstDayOfWeek = new(
Namespaced(nameof(FirstDayOfWeek)),
Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek,
Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek,
_firstDayOfWeekChoices);
private readonly ToggleSetting _onlyDateTimeNowGlobal = new(
Namespaced(nameof(OnlyDateTimeNowGlobal)),
Resources.Microsoft_plugin_timedate_SettingOnlyDateTimeNowGlobal,
Resources.Microsoft_plugin_timedate_SettingOnlyDateTimeNowGlobal_Description,
true); // TODO -- double check default value
private readonly ToggleSetting _timeWithSeconds = new(
Namespaced(nameof(TimeWithSecond)),
Resources.Microsoft_plugin_timedate_SettingTimeWithSeconds,
Resources.Microsoft_plugin_timedate_SettingTimeWithSeconds_Description,
false); // TODO -- double check default value
private readonly ToggleSetting _dateWithWeekday = new(
Namespaced(nameof(DateWithWeekday)),
Resources.Microsoft_plugin_timedate_SettingDateWithWeekday,
Resources.Microsoft_plugin_timedate_SettingDateWithWeekday_Description,
false); // TODO -- double check default value
private readonly ToggleSetting _hideNumberMessageOnGlobalQuery = new(
Namespaced(nameof(HideNumberMessageOnGlobalQuery)),
Resources.Microsoft_plugin_timedate_SettingHideNumberMessageOnGlobalQuery,
Resources.Microsoft_plugin_timedate_SettingHideNumberMessageOnGlobalQuery,
true); // TODO -- double check default value
public int FirstWeekOfYear
{
get
{
if (_firstWeekOfYear.Value == null || string.IsNullOrEmpty(_firstWeekOfYear.Value))
{
return -1;
}
var success = int.TryParse(_firstWeekOfYear.Value, out var result);
if (!success)
{
return -1;
}
return result;
}
}
public int FirstDayOfWeek
{
get
{
if (_firstDayOfWeek.Value == null || string.IsNullOrEmpty(_firstDayOfWeek.Value))
{
return -1;
}
var success = int.TryParse(_firstDayOfWeek.Value, out var result);
if (!success)
{
return -1;
}
return result;
}
}
public bool OnlyDateTimeNowGlobal => _onlyDateTimeNowGlobal.Value;
public bool TimeWithSecond => _timeWithSeconds.Value;
public bool DateWithWeekday => _dateWithWeekday.Value;
public bool HideNumberMessageOnGlobalQuery => _hideNumberMessageOnGlobalQuery.Value;
internal static string SettingsJsonPath()
{
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
Directory.CreateDirectory(directory);
// now, the state is just next to the exe
return Path.Combine(directory, "settings.json");
}
public SettingsManager()
{
FilePath = SettingsJsonPath();
Settings.Add(_firstWeekOfYear);
Settings.Add(_firstDayOfWeek);
Settings.Add(_onlyDateTimeNowGlobal);
Settings.Add(_timeWithSeconds);
Settings.Add(_dateWithWeekday);
Settings.Add(_hideNumberMessageOnGlobalQuery);
// Load settings from file upon initialization
LoadSettings();
Settings.SettingsChanged += (s, a) => this.SaveSettings();
}
}

View File

@@ -0,0 +1,189 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
internal static class TimeAndDateHelper
{
/// <summary>
/// Get the format for the time string
/// </summary>
/// <param name="targetFormat">Type of format</param>
/// <param name="timeLong">Show date with weekday and name of month (long format)</param>
/// <param name="dateLong">Show time with seconds (long format)</param>
/// <returns>String that identifies the time/date format (<see href="https://learn.microsoft.com/dotnet/api/system.datetime.tostring"/>)</returns>
internal static string GetStringFormat(FormatStringType targetFormat, bool timeLong, bool dateLong)
{
switch (targetFormat)
{
case FormatStringType.Time:
return timeLong ? "T" : "t";
case FormatStringType.Date:
return dateLong ? "D" : "d";
case FormatStringType.DateTime:
if (timeLong & dateLong)
{
return "F"; // Friday, October 31, 2008 5:04:32 PM
}
else if (timeLong & !dateLong)
{
return "G"; // 10/31/2008 5:04:32 PM
}
else if (!timeLong & dateLong)
{
return "f"; // Friday, October 31, 2008 5:04 PM
}
else
{
// (!timeLong & !dateLong)
return "g"; // 10/31/2008 5:04 PM
}
default:
return string.Empty; // Windows default based on current culture settings
}
}
/// <summary>
/// Returns the number week in the month (Used code from 'David Morton' from <see href="https://social.msdn.microsoft.com/Forums/vstudio/bf504bba-85cb-492d-a8f7-4ccabdf882cb/get-week-number-for-month"/>)
/// </summary>
/// <param name="date">date</param>
/// <returns>Number of week in the month</returns>
internal static int GetWeekOfMonth(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
{
var beginningOfMonth = new DateTime(date.Year, date.Month, 1);
var adjustment = 1; // We count from 1 to 7 and not from 0 to 6
while (date.Date.AddDays(1).DayOfWeek != formatSettingFirstDayOfWeek)
{
date = date.AddDays(1);
}
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + adjustment;
}
/// <summary>
/// Returns the number of the day in the week
/// </summary>
/// <param name="date">Date</param>
/// <returns>Number of the day in the week</returns>
internal static int GetNumberOfDayInWeek(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
{
var daysInWeek = 7;
var adjustment = 1; // We count from 1 to 7 and not from 0 to 6
return ((date.DayOfWeek + daysInWeek - formatSettingFirstDayOfWeek) % daysInWeek) + adjustment;
}
/// <summary>
/// Convert input string to a <see cref="DateTime"/> object in local time
/// </summary>
/// <param name="input">String with date/time</param>
/// <param name="timestamp">The new <see cref="DateTime"/> object</param>
/// <returns>True on success, otherwise false</returns>
internal static bool ParseStringAsDateTime(in string input, out DateTime timestamp)
{
if (DateTime.TryParse(input, out timestamp))
{
// Known date/time format
return true;
}
else if (Regex.IsMatch(input, @"^u[\+-]?\d{1,10}$") && long.TryParse(input.TrimStart('u'), out var secondsU))
{
// Unix time stamp
// We use long instead of int, because int is too small after 03:14:07 UTC 2038-01-19
timestamp = DateTimeOffset.FromUnixTimeSeconds(secondsU).LocalDateTime;
return true;
}
else if (Regex.IsMatch(input, @"^ums[\+-]?\d{1,13}$") && long.TryParse(input.TrimStart("ums".ToCharArray()), out var millisecondsUms))
{
// Unix time stamp in milliseconds
// We use long instead of int because int is too small after 03:14:07 UTC 2038-01-19
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(millisecondsUms).LocalDateTime;
return true;
}
else if (Regex.IsMatch(input, @"^ft\d+$") && long.TryParse(input.TrimStart("ft".ToCharArray()), out var secondsFt))
{
// Windows file time
// DateTime.FromFileTime returns as local time.
timestamp = DateTime.FromFileTime(secondsFt);
return true;
}
else
{
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
return false;
}
}
/// <summary>
/// Test if input is special parsing for Unix time, Unix time in milliseconds or File time.
/// </summary>
/// <param name="input">String with date/time</param>
/// <returns>True if yes, otherwise false</returns>
internal static bool IsSpecialInputParsing(string input)
{
return Regex.IsMatch(input, @"^.*(u|ums|ft)\d");
}
/// <summary>
/// Returns a CalendarWeekRule enum value based on the plugin setting.
/// </summary>
internal static CalendarWeekRule GetCalendarWeekRule(int pluginSetting)
{
switch (pluginSetting)
{
case 0:
return CalendarWeekRule.FirstDay;
case 1:
return CalendarWeekRule.FirstFullWeek;
case 2:
return CalendarWeekRule.FirstFourDayWeek;
default:
// Wrong json value and system setting (-1).
return DateTimeFormatInfo.CurrentInfo.CalendarWeekRule;
}
}
/// <summary>
/// Returns a DayOfWeek enum value based on the FirstDayOfWeek plugin setting.
/// </summary>
internal static DayOfWeek GetFirstDayOfWeek(int pluginSetting)
{
switch (pluginSetting)
{
case 0:
return DayOfWeek.Sunday;
case 1:
return DayOfWeek.Monday;
case 2:
return DayOfWeek.Tuesday;
case 3:
return DayOfWeek.Wednesday;
case 4:
return DayOfWeek.Thursday;
case 5:
return DayOfWeek.Friday;
case 6:
return DayOfWeek.Saturday;
default:
// Wrong json value and system setting (-1).
return DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
}
}
}
/// <summary>
/// Type of time/date format
/// </summary>
internal enum FormatStringType
{
Time,
Date,
DateTime,
}

View File

@@ -0,0 +1,108 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
public sealed partial class TimeDateCalculator
{
/// <summary>
/// Var that holds the delimiter between format and date
/// </summary>
private const string InputDelimiter = "::";
/// <summary>
/// A list of conjunctions that we ignore on search
/// </summary>
private static readonly string[] _conjunctionList = Resources.Microsoft_plugin_timedate_Search_ConjunctionList.Split("; ");
/// <summary>
/// Searches for results
/// </summary>
/// <param name="query">Search query object</param>
/// <returns>List of Wox <see cref="Result"/>s.</returns>
public static List<ListItem> ExecuteSearch(SettingsManager settings, string query)
{
var isEmptySearchInput = string.IsNullOrEmpty(query);
List<AvailableResult> availableFormats = new List<AvailableResult>();
List<ListItem> results = new List<ListItem>();
// currently, all of the search in V2 is keyword search.
var isKeywordSearch = true;
// Switch search type
if (isEmptySearchInput || (!isKeywordSearch && settings.OnlyDateTimeNowGlobal))
{
// Return all results for system time/date on empty keyword search
// or only time, date and now results for system time on global queries if the corresponding setting is enabled
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings));
}
else if (Regex.IsMatch(query, @".+" + Regex.Escape(InputDelimiter) + @".+"))
{
// Search for specified format with specified time/date value
var userInput = query.Split(InputDelimiter);
if (TimeAndDateHelper.ParseStringAsDateTime(userInput[1], out DateTime timestamp))
{
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings, null, null, timestamp));
query = userInput[0];
}
}
else if (TimeAndDateHelper.ParseStringAsDateTime(query, out DateTime timestamp))
{
// Return all formats for specified time/date value
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings, null, null, timestamp));
query = string.Empty;
}
else
{
// Search for specified format with system time/date (All other cases)
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings));
}
// Check searchTerm after getting results to select type of result list
if (string.IsNullOrEmpty(query))
{
// Generate list with all results
foreach (var f in availableFormats)
{
results.Add(f.ToListItem());
}
}
else
{
// Generate filtered list of results
foreach (var f in availableFormats)
{
var score = f.Score(query, f.Label, f.AlternativeSearchTag);
if (score > 0)
{
results.Add(f.ToListItem());
}
}
}
// If search term is only a number that can't be parsed return an error message
if (!isEmptySearchInput && results.Count == 0 && Regex.IsMatch(query, @"\w+\d+.*$") && !query.Any(char.IsWhiteSpace) && (TimeAndDateHelper.IsSpecialInputParsing(query) || !Regex.IsMatch(query, @"\d+[\.:/]\d+")))
{
// Without plugin key word show only if message is not hidden by setting
if (!settings.HideNumberMessageOnGlobalQuery)
{
results.Add(ResultHelper.CreateNumberErrorResult());
}
}
if (results.Count == 0)
{
results.Add(ResultHelper.CreateInvalidInputErrorResult());
}
return results;
}
}