mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
[PowerRename]Add random string values to file names (#32836)
* Add randomizer cheat sheet texts to UI tooltip * Add randomizer icon (shuffle) + hint to main window * Add randomizer logic + helpers, regex parsing * Fix: remove unnecessary throw * Fix: remove todo comment * Fix: iffing logic * Fix: add offset to randomizer onchange * Update: guid generating to single function, handle bracket removing there * Update: toggle off enum feat when random values are selected * Update: main window UI tooltip texts to be more descriptive * Update: remove unnecessary sstream include * Fix: return empty string if chars has no value to avoid memory access violation * Add unit tests * Add PowerRename random string generating keywords * Update: generating value names to be in line with POSIX conventions * Allow to used with Enumerate at the same time * Fix spellcheck * Fix tests to take into account we no longer eat up empty expressions with randomizer --------- Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
4
.github/actions/spell-check/expect.txt
vendored
4
.github/actions/spell-check/expect.txt
vendored
@@ -1338,6 +1338,9 @@ RRF
|
|||||||
rrr
|
rrr
|
||||||
rsop
|
rsop
|
||||||
Rsp
|
Rsp
|
||||||
|
rstringalnum
|
||||||
|
rstringalpha
|
||||||
|
rstringdigit
|
||||||
Rstrtmgr
|
Rstrtmgr
|
||||||
RTB
|
RTB
|
||||||
RTLREADING
|
RTLREADING
|
||||||
@@ -1352,6 +1355,7 @@ runtimeclass
|
|||||||
runtimeobject
|
runtimeobject
|
||||||
runtimepack
|
runtimepack
|
||||||
runtimes
|
runtimes
|
||||||
|
ruuid
|
||||||
rvm
|
rvm
|
||||||
rwin
|
rwin
|
||||||
rwl
|
rwl
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace PowerRenameUI
|
|||||||
Windows.Foundation.Collections.IObservableVector<PatternSnippet> SearchRegExShortcuts { get; };
|
Windows.Foundation.Collections.IObservableVector<PatternSnippet> SearchRegExShortcuts { get; };
|
||||||
Windows.Foundation.Collections.IObservableVector<PatternSnippet> DateTimeShortcuts { get; };
|
Windows.Foundation.Collections.IObservableVector<PatternSnippet> DateTimeShortcuts { get; };
|
||||||
Windows.Foundation.Collections.IObservableVector<PatternSnippet> CounterShortcuts { get; };
|
Windows.Foundation.Collections.IObservableVector<PatternSnippet> CounterShortcuts { get; };
|
||||||
|
Windows.Foundation.Collections.IObservableVector<PatternSnippet> RandomizerShortcuts { get; };
|
||||||
|
|
||||||
String OriginalCount;
|
String OriginalCount;
|
||||||
String RenamedCount;
|
String RenamedCount;
|
||||||
|
|||||||
@@ -327,6 +327,8 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="28" />
|
<RowDefinition Height="28" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="28" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<TextBlock x:Uid="DateTimeCheatSheet_Title" FontWeight="SemiBold" />
|
<TextBlock x:Uid="DateTimeCheatSheet_Title" FontWeight="SemiBold" />
|
||||||
<ListView
|
<ListView
|
||||||
@@ -407,6 +409,47 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
</ListView>
|
</ListView>
|
||||||
|
<TextBlock
|
||||||
|
x:Uid="RandomizerCheatSheet_Title"
|
||||||
|
Grid.Row="4"
|
||||||
|
Margin="0,10,0,0"
|
||||||
|
FontWeight="SemiBold" />
|
||||||
|
<ListView
|
||||||
|
Grid.Row="5"
|
||||||
|
Margin="-4,12,0,0"
|
||||||
|
IsItemClickEnabled="True"
|
||||||
|
ItemClick="DateTimeItemClick"
|
||||||
|
ItemsSource="{x:Bind RandomizerShortcuts}"
|
||||||
|
SelectionMode="None">
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="local:PatternSnippet">
|
||||||
|
<Grid Margin="-10,0,0,0" ColumnSpacing="8">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border
|
||||||
|
Padding="8"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Background="{ThemeResource ButtonBackground}"
|
||||||
|
BorderBrush="{ThemeResource ButtonBorderBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="4">
|
||||||
|
<TextBlock
|
||||||
|
FontFamily="Consolas"
|
||||||
|
Foreground="{ThemeResource ButtonForeground}"
|
||||||
|
Text="{x:Bind Code}" />
|
||||||
|
</Border>
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontSize="12"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Text="{x:Bind Description}" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Flyout>
|
</Flyout>
|
||||||
</Button.Flyout>
|
</Button.Flyout>
|
||||||
@@ -508,6 +551,12 @@
|
|||||||
Height="32"
|
Height="32"
|
||||||
Content=""
|
Content=""
|
||||||
FontFamily="{ThemeResource SymbolThemeFontFamily}" />
|
FontFamily="{ThemeResource SymbolThemeFontFamily}" />
|
||||||
|
<ToggleButton
|
||||||
|
x:Name="toggleButton_randItems"
|
||||||
|
x:Uid="ToggleButton_RandItems"
|
||||||
|
Height="32"
|
||||||
|
Content=""
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@@ -203,6 +203,12 @@ namespace winrt::PowerRenameUI::implementation
|
|||||||
m_CounterShortcuts.Append(winrt::make<PatternSnippet>(L"${padding=8}", manager.MainResourceMap().GetValue(L"Resources/CounterCheatSheet_Padding").ValueAsString()));
|
m_CounterShortcuts.Append(winrt::make<PatternSnippet>(L"${padding=8}", manager.MainResourceMap().GetValue(L"Resources/CounterCheatSheet_Padding").ValueAsString()));
|
||||||
m_CounterShortcuts.Append(winrt::make<PatternSnippet>(L"${increment=3,padding=4,start=900}", manager.MainResourceMap().GetValue(L"Resources/CounterCheatSheet_Complex").ValueAsString()));
|
m_CounterShortcuts.Append(winrt::make<PatternSnippet>(L"${increment=3,padding=4,start=900}", manager.MainResourceMap().GetValue(L"Resources/CounterCheatSheet_Complex").ValueAsString()));
|
||||||
|
|
||||||
|
m_RandomizerShortcuts = winrt::single_threaded_observable_vector<PowerRenameUI::PatternSnippet>();
|
||||||
|
m_RandomizerShortcuts.Append(winrt::make<PatternSnippet>(L"${rstringalnum=9}", manager.MainResourceMap().GetValue(L"Resources/RandomizerCheatSheet_Alnum").ValueAsString()));
|
||||||
|
m_RandomizerShortcuts.Append(winrt::make<PatternSnippet>(L"${rstringalpha=13}", manager.MainResourceMap().GetValue(L"Resources/RandomizerCheatSheet_Alpha").ValueAsString()));
|
||||||
|
m_RandomizerShortcuts.Append(winrt::make<PatternSnippet>(L"${rstringdigit=36}", manager.MainResourceMap().GetValue(L"Resources/RandomizerCheatSheet_Digit").ValueAsString()));
|
||||||
|
m_RandomizerShortcuts.Append(winrt::make<PatternSnippet>(L"${ruuidv4}", manager.MainResourceMap().GetValue(L"Resources/RandomizerCheatSheet_Uuid").ValueAsString()));
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
listView_ExplorerItems().ApplyTemplate();
|
listView_ExplorerItems().ApplyTemplate();
|
||||||
@@ -283,6 +289,7 @@ namespace winrt::PowerRenameUI::implementation
|
|||||||
|
|
||||||
button_rename().IsEnabled(false);
|
button_rename().IsEnabled(false);
|
||||||
toggleButton_enumItems().IsChecked(true);
|
toggleButton_enumItems().IsChecked(true);
|
||||||
|
toggleButton_randItems().IsChecked(false);
|
||||||
InitAutoComplete();
|
InitAutoComplete();
|
||||||
SearchReplaceChanged();
|
SearchReplaceChanged();
|
||||||
InvalidateItemListViewState();
|
InvalidateItemListViewState();
|
||||||
@@ -749,6 +756,15 @@ namespace winrt::PowerRenameUI::implementation
|
|||||||
UpdateFlag(EnumerateItems, UpdateFlagCommand::Reset);
|
UpdateFlag(EnumerateItems, UpdateFlagCommand::Reset);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// CheckBox RandomizeItems
|
||||||
|
toggleButton_randItems().Checked([&](auto const&, auto const&) {
|
||||||
|
ValidateFlags(RandomizeItems);
|
||||||
|
UpdateFlag(RandomizeItems, UpdateFlagCommand::Set);
|
||||||
|
});
|
||||||
|
toggleButton_randItems().Unchecked([&](auto const&, auto const&) {
|
||||||
|
UpdateFlag(RandomizeItems, UpdateFlagCommand::Reset);
|
||||||
|
});
|
||||||
|
|
||||||
// ButtonSettings
|
// ButtonSettings
|
||||||
button_settings().Click([&](auto const&, auto const&) {
|
button_settings().Click([&](auto const&, auto const&) {
|
||||||
OpenSettingsApp();
|
OpenSettingsApp();
|
||||||
@@ -944,6 +960,10 @@ namespace winrt::PowerRenameUI::implementation
|
|||||||
{
|
{
|
||||||
toggleButton_enumItems().IsChecked(true);
|
toggleButton_enumItems().IsChecked(true);
|
||||||
}
|
}
|
||||||
|
if (flags & RandomizeItems)
|
||||||
|
{
|
||||||
|
toggleButton_randItems().IsChecked(true);
|
||||||
|
}
|
||||||
if (flags & ExcludeFiles)
|
if (flags & ExcludeFiles)
|
||||||
{
|
{
|
||||||
toggleButton_includeFiles().IsChecked(false);
|
toggleButton_includeFiles().IsChecked(false);
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ namespace winrt::PowerRenameUI::implementation
|
|||||||
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> SearchRegExShortcuts() { return m_searchRegExShortcuts; }
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> SearchRegExShortcuts() { return m_searchRegExShortcuts; }
|
||||||
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> DateTimeShortcuts() { return m_dateTimeShortcuts; }
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> DateTimeShortcuts() { return m_dateTimeShortcuts; }
|
||||||
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> CounterShortcuts() { return m_CounterShortcuts; }
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> CounterShortcuts() { return m_CounterShortcuts; }
|
||||||
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> RandomizerShortcuts() { return m_RandomizerShortcuts; }
|
||||||
|
|
||||||
hstring OriginalCount();
|
hstring OriginalCount();
|
||||||
void OriginalCount(hstring value);
|
void OriginalCount(hstring value);
|
||||||
@@ -107,6 +108,7 @@ namespace winrt::PowerRenameUI::implementation
|
|||||||
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_searchRegExShortcuts;
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_searchRegExShortcuts;
|
||||||
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_dateTimeShortcuts;
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_dateTimeShortcuts;
|
||||||
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_CounterShortcuts;
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_CounterShortcuts;
|
||||||
|
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUI::PatternSnippet> m_RandomizerShortcuts;
|
||||||
|
|
||||||
// Used by PowerRenameManagerEvents
|
// Used by PowerRenameManagerEvents
|
||||||
HRESULT OnRename(_In_ IPowerRenameItem* renameItem);
|
HRESULT OnRename(_In_ IPowerRenameItem* renameItem);
|
||||||
|
|||||||
@@ -151,7 +151,7 @@
|
|||||||
<value>Replace with</value>
|
<value>Replace with</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CounterCheatSheet_Title.Text" xml:space="preserve">
|
<data name="CounterCheatSheet_Title.Text" xml:space="preserve">
|
||||||
<value>Replace using advanced counter syntax.</value>
|
<value>Replace using advanced counter syntax</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CounterCheatSheet_Simple" xml:space="preserve">
|
<data name="CounterCheatSheet_Simple" xml:space="preserve">
|
||||||
<value>A simple counter that you can use anywhere in a replace string.</value>
|
<value>A simple counter that you can use anywhere in a replace string.</value>
|
||||||
@@ -295,10 +295,10 @@
|
|||||||
<value>Capitalize each word</value>
|
<value>Capitalize each word</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ToggleButton_EnumItems.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
<data name="ToggleButton_EnumItems.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||||
<value>Enumerate items</value>
|
<value>Enumeration features</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ToggleButton_EnumItems.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
<data name="ToggleButton_EnumItems.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
<value>Enumerate items</value>
|
<value>Enumeration features</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAllCheckBox.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
<data name="SelectAllCheckBox.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
<value>Select or deselect all</value>
|
<value>Select or deselect all</value>
|
||||||
@@ -363,4 +363,25 @@
|
|||||||
<data name="RenameParts_ExtensionOnly.Content" xml:space="preserve">
|
<data name="RenameParts_ExtensionOnly.Content" xml:space="preserve">
|
||||||
<value>Extension only</value>
|
<value>Extension only</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<data name="RandomizerCheatSheet_Alnum" xml:space="preserve">
|
||||||
|
<value>Random string with uppercase letters, lowercase letters and 0-9 digits, customized length.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RandomizerCheatSheet_Alpha" xml:space="preserve">
|
||||||
|
<value>Random string with uppercase letters and lowercase letters, customized length.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RandomizerCheatSheet_Digit" xml:space="preserve">
|
||||||
|
<value>Random string with 0-9 digits, customized length.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RandomizerCheatSheet_Title.Text" xml:space="preserve">
|
||||||
|
<value>Replace using random values</value>
|
||||||
|
</data>
|
||||||
|
<data name="RandomizerCheatSheet_Uuid" xml:space="preserve">
|
||||||
|
<value>Random UUID according to v4 specification.</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToggleButton_RandItems.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||||
|
<value>Random string features</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToggleButton_RandItems.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||||
|
<value>Random string features</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -661,3 +661,20 @@ bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::wstring CreateGuidStringWithoutBrackets()
|
||||||
|
{
|
||||||
|
GUID guid;
|
||||||
|
if (CoCreateGuid(&guid) == S_OK)
|
||||||
|
{
|
||||||
|
OLECHAR* guidString;
|
||||||
|
if (StringFromCLSID(guid, &guidString) == S_OK)
|
||||||
|
{
|
||||||
|
std::wstring guidStr{ guidString };
|
||||||
|
CoTaskMemFree(guidString);
|
||||||
|
return guidStr.substr(1, guidStr.length() - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
@@ -26,3 +26,4 @@ void SetRegNumber(const std::wstring& valueName, unsigned int value);
|
|||||||
bool GetRegBoolean(const std::wstring& valueName, bool defaultValue);
|
bool GetRegBoolean(const std::wstring& valueName, bool defaultValue);
|
||||||
void SetRegBoolean(const std::wstring& valueName, bool value);
|
void SetRegBoolean(const std::wstring& valueName, bool value);
|
||||||
bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime);
|
bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime);
|
||||||
|
std::wstring CreateGuidStringWithoutBrackets();
|
||||||
@@ -17,7 +17,8 @@ enum PowerRenameFlags
|
|||||||
Uppercase = 0x200,
|
Uppercase = 0x200,
|
||||||
Lowercase = 0x400,
|
Lowercase = 0x400,
|
||||||
Titlecase = 0x800,
|
Titlecase = 0x800,
|
||||||
Capitalized = 0x1000
|
Capitalized = 0x1000,
|
||||||
|
RandomizeItems = 0x2000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PowerRenameFilters
|
enum PowerRenameFilters
|
||||||
@@ -150,3 +151,12 @@ public:
|
|||||||
(_In_ IEnumShellItems * enumShellItems) = 0;
|
(_In_ IEnumShellItems * enumShellItems) = 0;
|
||||||
IFACEMETHOD(Cancel)() = 0;
|
IFACEMETHOD(Cancel)() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface __declspec(uuid("FAB18E93-2E76-436B-8E26-B1240519AF12")) IPowerRenameRand : public IUnknown
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFACEMETHOD(Start)
|
||||||
|
(_In_ IEnumShellItems * enumShellItems) = 0;
|
||||||
|
IFACEMETHOD(Cancel)
|
||||||
|
() = 0;
|
||||||
|
};
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
<ClInclude Include="PowerRenameManager.h" />
|
<ClInclude Include="PowerRenameManager.h" />
|
||||||
<ClInclude Include="PowerRenameMRU.h" />
|
<ClInclude Include="PowerRenameMRU.h" />
|
||||||
<ClInclude Include="PowerRenameRegEx.h" />
|
<ClInclude Include="PowerRenameRegEx.h" />
|
||||||
|
<ClInclude Include="Randomizer.h" />
|
||||||
<ClInclude Include="Renaming.h" />
|
<ClInclude Include="Renaming.h" />
|
||||||
<ClInclude Include="Settings.h" />
|
<ClInclude Include="Settings.h" />
|
||||||
<ClInclude Include="srwlock.h" />
|
<ClInclude Include="srwlock.h" />
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
<ClCompile Include="PowerRenameManager.cpp" />
|
<ClCompile Include="PowerRenameManager.cpp" />
|
||||||
<ClCompile Include="PowerRenameMRU.cpp" />
|
<ClCompile Include="PowerRenameMRU.cpp" />
|
||||||
<ClCompile Include="PowerRenameRegEx.cpp" />
|
<ClCompile Include="PowerRenameRegEx.cpp" />
|
||||||
|
<ClCompile Include="Randomizer.cpp" />
|
||||||
<ClCompile Include="Renaming.cpp" />
|
<ClCompile Include="Renaming.cpp" />
|
||||||
<ClCompile Include="Settings.cpp" />
|
<ClCompile Include="Settings.cpp" />
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
|
|||||||
@@ -130,23 +130,106 @@ IFACEMETHODIMP CPowerRenameRegEx::GetReplaceTerm(_Outptr_ PWSTR* replaceTerm)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CPowerRenameRegEx::_OnEnumerateItemsChanged()
|
HRESULT CPowerRenameRegEx::_OnEnumerateOrRandomizeItemsChanged()
|
||||||
{
|
{
|
||||||
m_enumerators.clear();
|
m_enumerators.clear();
|
||||||
const auto options = parseEnumOptions(m_RawReplaceTerm);
|
m_randomizer.clear();
|
||||||
for (const auto e : options)
|
|
||||||
m_enumerators.emplace_back(e);
|
|
||||||
|
|
||||||
|
if (m_flags & RandomizeItems)
|
||||||
|
{
|
||||||
|
const auto options = parseRandomizerOptions(m_RawReplaceTerm);
|
||||||
|
|
||||||
|
for (const auto& option : options)
|
||||||
|
{
|
||||||
|
m_randomizer.emplace_back(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_flags & EnumerateItems)
|
||||||
|
{
|
||||||
|
const auto options = parseEnumOptions(m_RawReplaceTerm);
|
||||||
|
for (const auto& option : options)
|
||||||
|
{
|
||||||
|
if (m_randomizer.end() ==
|
||||||
|
std::find_if(
|
||||||
|
m_randomizer.begin(),
|
||||||
|
m_randomizer.end(),
|
||||||
|
[option](const Randomizer& r) -> bool { return r.options.replaceStrSpan.offset == option.replaceStrSpan.offset; }
|
||||||
|
))
|
||||||
|
{
|
||||||
|
// Only add as enumerator if we didn't find a randomizer already at this offset.
|
||||||
|
// Every randomizer will also be a valid enumerator according to the definition of enumerators, which allows any string to mean the default enumerator, so it should be interpreted that the user wanted a randomizer if both were found at the same offset of the replace string.
|
||||||
|
m_enumerators.emplace_back(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_replaceWithRandomizerOffsets.clear();
|
||||||
m_replaceWithEnumeratorOffsets.clear();
|
m_replaceWithEnumeratorOffsets.clear();
|
||||||
|
|
||||||
|
int32_t offset = 0;
|
||||||
|
int ei = 0; // Enumerators index
|
||||||
|
int ri = 0; // Randomizer index
|
||||||
|
|
||||||
std::wstring replaceWith{ m_RawReplaceTerm };
|
std::wstring replaceWith{ m_RawReplaceTerm };
|
||||||
// Remove counter expressions and calculate their offsets in replaceWith string.
|
// Remove counter expressions and calculate their offsets in replaceWith string.
|
||||||
int32_t offset = 0;
|
|
||||||
for (const auto& e : options)
|
if ((m_flags & EnumerateItems) && (m_flags & RandomizeItems))
|
||||||
{
|
{
|
||||||
replaceWith.erase(e.replaceStrSpan.offset + offset, e.replaceStrSpan.length);
|
// Both flags are on, we need to merge which ones should be applied.
|
||||||
m_replaceWithEnumeratorOffsets.push_back(offset);
|
while ((ei < m_enumerators.size()) && (ri < m_randomizer.size()))
|
||||||
offset -= static_cast<int32_t>(e.replaceStrSpan.length);
|
{
|
||||||
|
const auto& e = m_enumerators[ei];
|
||||||
|
const auto& r = m_randomizer[ri];
|
||||||
|
if (e.replaceStrSpan.offset < r.options.replaceStrSpan.offset)
|
||||||
|
{
|
||||||
|
// if the enumerator is next in line, remove counter expression and calculate offset with it.
|
||||||
|
replaceWith.erase(e.replaceStrSpan.offset + offset, e.replaceStrSpan.length);
|
||||||
|
m_replaceWithEnumeratorOffsets.push_back(offset);
|
||||||
|
offset -= static_cast<int32_t>(e.replaceStrSpan.length);
|
||||||
|
|
||||||
|
ei++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the randomizer is next in line, remove randomizer expression and calculate offset with it.
|
||||||
|
replaceWith.erase(r.options.replaceStrSpan.offset + offset, r.options.replaceStrSpan.length);
|
||||||
|
m_replaceWithRandomizerOffsets.push_back(offset);
|
||||||
|
offset -= static_cast<int32_t>(r.options.replaceStrSpan.length);
|
||||||
|
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_flags & EnumerateItems)
|
||||||
|
{
|
||||||
|
// Continue with all remaining enumerators
|
||||||
|
while (ei < m_enumerators.size())
|
||||||
|
{
|
||||||
|
const auto& e = m_enumerators[ei];
|
||||||
|
replaceWith.erase(e.replaceStrSpan.offset + offset, e.replaceStrSpan.length);
|
||||||
|
m_replaceWithEnumeratorOffsets.push_back(offset);
|
||||||
|
offset -= static_cast<int32_t>(e.replaceStrSpan.length);
|
||||||
|
|
||||||
|
ei++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_flags & RandomizeItems)
|
||||||
|
{
|
||||||
|
// Continue with all remaining randomizer instances
|
||||||
|
while (ri < m_randomizer.size())
|
||||||
|
{
|
||||||
|
const auto& r = m_randomizer[ri];
|
||||||
|
replaceWith.erase(r.options.replaceStrSpan.offset + offset, r.options.replaceStrSpan.length);
|
||||||
|
m_replaceWithRandomizerOffsets.push_back(offset);
|
||||||
|
offset -= static_cast<int32_t>(r.options.replaceStrSpan.length);
|
||||||
|
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return SHStrDup(replaceWith.data(), &m_replaceTerm);
|
return SHStrDup(replaceWith.data(), &m_replaceTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,8 +246,8 @@ IFACEMETHODIMP CPowerRenameRegEx::PutReplaceTerm(_In_ PCWSTR replaceTerm, bool f
|
|||||||
CoTaskMemFree(m_replaceTerm);
|
CoTaskMemFree(m_replaceTerm);
|
||||||
m_RawReplaceTerm = replaceTerm;
|
m_RawReplaceTerm = replaceTerm;
|
||||||
|
|
||||||
if (m_flags & EnumerateItems)
|
if ((m_flags & RandomizeItems) || (m_flags & EnumerateItems))
|
||||||
hr = _OnEnumerateItemsChanged();
|
hr = _OnEnumerateOrRandomizeItemsChanged();
|
||||||
else
|
else
|
||||||
hr = SHStrDup(replaceTerm, &m_replaceTerm);
|
hr = SHStrDup(replaceTerm, &m_replaceTerm);
|
||||||
}
|
}
|
||||||
@@ -189,13 +272,20 @@ IFACEMETHODIMP CPowerRenameRegEx::PutFlags(_In_ DWORD flags)
|
|||||||
if (m_flags != flags)
|
if (m_flags != flags)
|
||||||
{
|
{
|
||||||
const bool newEnumerate = flags & EnumerateItems;
|
const bool newEnumerate = flags & EnumerateItems;
|
||||||
const bool refreshReplaceTerm = !!(m_flags & EnumerateItems) != newEnumerate;
|
const bool newRandomizer = flags & RandomizeItems;
|
||||||
|
const bool refreshReplaceTerm =
|
||||||
|
(!!(m_flags & EnumerateItems) != newEnumerate) ||
|
||||||
|
(!!(m_flags & RandomizeItems) != newRandomizer);
|
||||||
|
|
||||||
m_flags = flags;
|
m_flags = flags;
|
||||||
|
|
||||||
if (refreshReplaceTerm)
|
if (refreshReplaceTerm)
|
||||||
{
|
{
|
||||||
CSRWExclusiveAutoLock lock(&m_lock);
|
CSRWExclusiveAutoLock lock(&m_lock);
|
||||||
if (newEnumerate)
|
if (newEnumerate || newRandomizer)
|
||||||
_OnEnumerateItemsChanged();
|
{
|
||||||
|
_OnEnumerateOrRandomizeItemsChanged();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CoTaskMemFree(m_replaceTerm);
|
CoTaskMemFree(m_replaceTerm);
|
||||||
@@ -325,17 +415,75 @@ HRESULT CPowerRenameRegEx::Replace(_In_ PCWSTR source, _Outptr_ PWSTR* result, u
|
|||||||
static const std::wregex zeroGroupRegex(L"(([^\\$]|^)(\\$\\$)*)\\$[0]");
|
static const std::wregex zeroGroupRegex(L"(([^\\$]|^)(\\$\\$)*)\\$[0]");
|
||||||
static const std::wregex otherGroupsRegex(L"(([^\\$]|^)(\\$\\$)*)\\$([1-9])");
|
static const std::wregex otherGroupsRegex(L"(([^\\$]|^)(\\$\\$)*)\\$([1-9])");
|
||||||
|
|
||||||
if (m_flags & EnumerateItems)
|
if ((m_flags & EnumerateItems) || (m_flags & RandomizeItems))
|
||||||
{
|
{
|
||||||
|
int ei = 0; // Enumerators index
|
||||||
|
int ri = 0; // Randomizer index
|
||||||
std::array<wchar_t, MAX_PATH> buffer;
|
std::array<wchar_t, MAX_PATH> buffer;
|
||||||
int32_t offset = 0;
|
int32_t offset = 0;
|
||||||
|
|
||||||
for (size_t ei = 0; ei < m_enumerators.size(); ++ei)
|
if ((m_flags & EnumerateItems) && (m_flags & RandomizeItems))
|
||||||
{
|
{
|
||||||
const auto& e = m_enumerators[ei];
|
// Both flags are on, we need to merge which ones should be applied.
|
||||||
const auto replacementLength = static_cast<int32_t>(e.printTo(buffer.data(), buffer.size(), enumIndex));
|
while ((ei < m_enumerators.size()) && (ri < m_randomizer.size()))
|
||||||
replaceTerm.insert(e.replaceStrSpan.offset + offset + m_replaceWithEnumeratorOffsets[ei], buffer.data());
|
{
|
||||||
offset += replacementLength;
|
const auto& e = m_enumerators[ei];
|
||||||
|
const auto& r = m_randomizer[ri];
|
||||||
|
if (e.replaceStrSpan.offset < r.options.replaceStrSpan.offset)
|
||||||
|
{
|
||||||
|
// if the enumerator is next in line, apply it.
|
||||||
|
const auto replacementLength = static_cast<int32_t>(e.printTo(buffer.data(), buffer.size(), enumIndex));
|
||||||
|
replaceTerm.insert(e.replaceStrSpan.offset + offset + m_replaceWithEnumeratorOffsets[ei], buffer.data());
|
||||||
|
offset += replacementLength;
|
||||||
|
|
||||||
|
ei++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the randomizer is next in line, apply it.
|
||||||
|
std::string randomValue = r.randomize();
|
||||||
|
std::wstring wRandomValue(randomValue.begin(), randomValue.end());
|
||||||
|
replaceTerm.insert(r.options.replaceStrSpan.offset + offset + m_replaceWithRandomizerOffsets[ri], wRandomValue);
|
||||||
|
offset += static_cast<int32_t>(wRandomValue.length());
|
||||||
|
|
||||||
|
if (e.replaceStrSpan.offset == r.options.replaceStrSpan.offset)
|
||||||
|
{
|
||||||
|
// In theory, this shouldn't happen here as we were guarding against it when filling the randomizer and enumerator structures, but it's still here as a fail safe.
|
||||||
|
// Every randomizer will also be a valid enumerator according to the definition of enumerators, which allow any string to mean the default enumerator, so it should be interpreted that the user wanted a randomizer if both were found at the same offset of the replace string.
|
||||||
|
ei++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_flags & EnumerateItems)
|
||||||
|
{
|
||||||
|
// Replace all remaining enumerators
|
||||||
|
while (ei < m_enumerators.size())
|
||||||
|
{
|
||||||
|
const auto& e = m_enumerators[ei];
|
||||||
|
const auto replacementLength = static_cast<int32_t>(e.printTo(buffer.data(), buffer.size(), enumIndex));
|
||||||
|
replaceTerm.insert(e.replaceStrSpan.offset + offset + m_replaceWithEnumeratorOffsets[ei], buffer.data());
|
||||||
|
offset += replacementLength;
|
||||||
|
|
||||||
|
ei++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_flags & RandomizeItems)
|
||||||
|
{
|
||||||
|
// Replace all remaining randomizer instances
|
||||||
|
while (ri < m_randomizer.size())
|
||||||
|
{
|
||||||
|
const auto& r = m_randomizer[ri];
|
||||||
|
std::string randomValue = r.randomize();
|
||||||
|
std::wstring wRandomValue(randomValue.begin(), randomValue.end());
|
||||||
|
replaceTerm.insert(r.options.replaceStrSpan.offset + offset + m_replaceWithRandomizerOffsets[ri], wRandomValue);
|
||||||
|
offset += static_cast<int32_t>(wRandomValue.length());
|
||||||
|
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
#include "srwlock.h"
|
#include "srwlock.h"
|
||||||
|
|
||||||
#include "Enumerating.h"
|
#include "Enumerating.h"
|
||||||
|
|
||||||
|
#include "Randomizer.h"
|
||||||
|
|
||||||
#include "PowerRenameInterfaces.h"
|
#include "PowerRenameInterfaces.h"
|
||||||
|
|
||||||
#define DEFAULT_FLAGS 0
|
#define DEFAULT_FLAGS 0
|
||||||
@@ -38,7 +41,7 @@ protected:
|
|||||||
void _OnReplaceTermChanged();
|
void _OnReplaceTermChanged();
|
||||||
void _OnFlagsChanged();
|
void _OnFlagsChanged();
|
||||||
void _OnFileTimeChanged();
|
void _OnFileTimeChanged();
|
||||||
HRESULT _OnEnumerateItemsChanged();
|
HRESULT _OnEnumerateOrRandomizeItemsChanged();
|
||||||
|
|
||||||
size_t _Find(std::wstring data, std::wstring toSearch, bool caseInsensitive, size_t pos);
|
size_t _Find(std::wstring data, std::wstring toSearch, bool caseInsensitive, size_t pos);
|
||||||
|
|
||||||
@@ -59,6 +62,9 @@ protected:
|
|||||||
std::vector<Enumerator> m_enumerators;
|
std::vector<Enumerator> m_enumerators;
|
||||||
std::vector<int32_t> m_replaceWithEnumeratorOffsets;
|
std::vector<int32_t> m_replaceWithEnumeratorOffsets;
|
||||||
|
|
||||||
|
std::vector<Randomizer> m_randomizer;
|
||||||
|
std::vector<int32_t> m_replaceWithRandomizerOffsets;
|
||||||
|
|
||||||
struct RENAME_REGEX_EVENT
|
struct RENAME_REGEX_EVENT
|
||||||
{
|
{
|
||||||
IPowerRenameRegExEvents* pEvents;
|
IPowerRenameRegExEvents* pEvents;
|
||||||
|
|||||||
55
src/modules/powerrename/lib/Randomizer.cpp
Normal file
55
src/modules/powerrename/lib/Randomizer.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "Randomizer.h"
|
||||||
|
|
||||||
|
std::vector<RandomizerOptions> parseRandomizerOptions(const std::wstring& replaceWith)
|
||||||
|
{
|
||||||
|
static const std::wregex randAlnumRegex(LR"(rstringalnum=(\d+))");
|
||||||
|
static const std::wregex randAlphaRegex(LR"(rstringalpha=(-?\d+))");
|
||||||
|
static const std::wregex randDigitRegex(LR"(rstringdigit=(\d+))");
|
||||||
|
static const std::wregex randUuidRegex(LR"(ruuidv4)");
|
||||||
|
|
||||||
|
std::string buf;
|
||||||
|
std::vector<RandomizerOptions> options;
|
||||||
|
std::wregex randGroupRegex(LR"(\$\{.*?\})");
|
||||||
|
|
||||||
|
for (std::wsregex_iterator i{ begin(replaceWith), end(replaceWith), randGroupRegex }, end; i != end; ++i)
|
||||||
|
{
|
||||||
|
std::wsmatch match = *i;
|
||||||
|
std::wstring matchString = match.str();
|
||||||
|
|
||||||
|
RandomizerOptions option;
|
||||||
|
option.replaceStrSpan.offset = match.position();
|
||||||
|
option.replaceStrSpan.length = match.length();
|
||||||
|
|
||||||
|
std::wsmatch subMatch;
|
||||||
|
if (std::regex_search(matchString, subMatch, randAlnumRegex))
|
||||||
|
{
|
||||||
|
int length = std::stoi(subMatch.str(1));
|
||||||
|
option.alnum = true;
|
||||||
|
option.length = length;
|
||||||
|
}
|
||||||
|
if (std::regex_search(matchString, subMatch, randAlphaRegex))
|
||||||
|
{
|
||||||
|
int length = std::stoi(subMatch.str(1));
|
||||||
|
option.alpha = true;
|
||||||
|
option.length = length;
|
||||||
|
}
|
||||||
|
if (std::regex_search(matchString, subMatch, randDigitRegex))
|
||||||
|
{
|
||||||
|
int length = std::stoi(subMatch.str(1));
|
||||||
|
option.digit = true;
|
||||||
|
option.length = length;
|
||||||
|
}
|
||||||
|
if (std::regex_search(matchString, subMatch, randUuidRegex))
|
||||||
|
{
|
||||||
|
option.uuid = true;
|
||||||
|
}
|
||||||
|
if (option.isValid())
|
||||||
|
{
|
||||||
|
options.push_back(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
76
src/modules/powerrename/lib/Randomizer.h
Normal file
76
src/modules/powerrename/lib/Randomizer.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "Helpers.h"
|
||||||
|
|
||||||
|
#include <common\utils\string_utils.h>
|
||||||
|
|
||||||
|
struct ReplaceStrSpan
|
||||||
|
{
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RandomizerOptions
|
||||||
|
{
|
||||||
|
std::optional<int> length;
|
||||||
|
std::optional<boolean> alnum;
|
||||||
|
std::optional<boolean> alpha;
|
||||||
|
std::optional<boolean> digit;
|
||||||
|
std::optional<boolean> uuid;
|
||||||
|
ReplaceStrSpan replaceStrSpan;
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return alnum.has_value() || alpha.has_value() || digit.has_value() || uuid.has_value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<RandomizerOptions> parseRandomizerOptions(const std::wstring& replaceWith);
|
||||||
|
|
||||||
|
struct Randomizer
|
||||||
|
{
|
||||||
|
RandomizerOptions options;
|
||||||
|
|
||||||
|
inline Randomizer(RandomizerOptions opts) :
|
||||||
|
options(opts) {}
|
||||||
|
|
||||||
|
std::string randomize() const
|
||||||
|
{
|
||||||
|
std::string chars;
|
||||||
|
|
||||||
|
if (options.uuid.value_or(false))
|
||||||
|
{
|
||||||
|
return unwide(CreateGuidStringWithoutBrackets());
|
||||||
|
}
|
||||||
|
if (options.alnum.value_or(false))
|
||||||
|
{
|
||||||
|
chars += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
}
|
||||||
|
if (options.alpha.value_or(false))
|
||||||
|
{
|
||||||
|
chars += "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
}
|
||||||
|
if (options.digit.value_or(false))
|
||||||
|
{
|
||||||
|
chars += "0123456789";
|
||||||
|
}
|
||||||
|
if (chars.empty())
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 generator(rd());
|
||||||
|
std::uniform_int_distribution<> distribution(0, static_cast<int>(chars.size()) - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < options.length.value_or(10); ++i)
|
||||||
|
{
|
||||||
|
result += chars[distribution(generator)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include <ProjectTelemetry.h>
|
#include <ProjectTelemetry.h>
|
||||||
|
|
||||||
|
|||||||
@@ -466,6 +466,151 @@ TEST_METHOD (VerifyCounterAllCustomizations)
|
|||||||
CoTaskMemFree(result);
|
CoTaskMemFree(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerDefaultFlags)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = 0;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringalnum=9}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
Assert::AreEqual(L"foo$1bar_${rstringalnum=9}", result);
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerNoRegex)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
Assert::AreEqual(L"foo$1bar_${}", result);
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerNoRandomizerRegEx)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringalnum=9}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
Assert::AreEqual(L"foobar_${rstringalnum=9}", result);
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerRegEx)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems | UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringalnum=9}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
std::wstring resultStr(result);
|
||||||
|
std::wregex pattern(L"foobar_\\w{9}");
|
||||||
|
Assert::IsTrue(std::regex_match(resultStr, pattern));
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerRegExZeroValue)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems | UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringalnum=0}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
Assert::AreEqual(L"foobar_", result);
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerRegExChar)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems | UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringalpha=9}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
std::wstring resultStr(result);
|
||||||
|
std::wregex pattern(L"foobar_[A-Za-z]{9}");
|
||||||
|
Assert::IsTrue(std::regex_match(resultStr, pattern));
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerRegExNum)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems | UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringdigit=9}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
std::wstring resultStr(result);
|
||||||
|
std::wregex pattern(L"foobar_\\d{9}");
|
||||||
|
Assert::IsTrue(std::regex_match(resultStr, pattern));
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerRegExUuid)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems | UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${ruuidv4}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
std::wstring resultStr(result);
|
||||||
|
std::wregex pattern(L"foobar_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}");
|
||||||
|
Assert::IsTrue(std::regex_match(resultStr, pattern));
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (VerifyRandomizerRegExAllBackToBack)
|
||||||
|
{
|
||||||
|
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||||
|
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||||
|
DWORD flags = RandomizeItems | UseRegularExpressions;
|
||||||
|
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||||
|
PWSTR result = nullptr;
|
||||||
|
Assert::IsTrue(renameRegEx->PutSearchTerm(L"bar") == S_OK);
|
||||||
|
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"$1bar_${rstringalnum=2}${rstringalpha=2}${rstringdigit=2}${ruuidv4}") == S_OK);
|
||||||
|
unsigned long index = {};
|
||||||
|
Assert::IsTrue(renameRegEx->Replace(L"foobar", &result, index) == S_OK);
|
||||||
|
std::wstring resultStr(result);
|
||||||
|
std::wregex pattern(L"foobar_\\w{2}[A-Za-z]{2}\\d{2}[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}");
|
||||||
|
Assert::IsTrue(std::regex_match(resultStr, pattern));
|
||||||
|
CoTaskMemFree(result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef TESTS_PARTIAL
|
#ifndef TESTS_PARTIAL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user