Skip to content

Commit

Permalink
[PowerRename] Don't treat extensions for folders (#14908)
Browse files Browse the repository at this point in the history
* Dont treat extensions for folders

* Simplify fix and add test

* Add try/catch

* Update test to avoid updating spellcheck
  • Loading branch information
stefansjfw committed Dec 14, 2021
1 parent f5d2f86 commit d359b3a
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 65 deletions.
98 changes: 60 additions & 38 deletions src/modules/powerrename/lib/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,46 @@ HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source)
return hr;
}

HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags)
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags, bool isFolder)
{
std::locale::global(std::locale(""));
HRESULT hr = E_INVALIDARG;
if (source && flags)
{
if (flags & Uppercase)
{
if (flags & NameOnly)
if (isFolder)
{
std::wstring stem = fs::path(source).stem().wstring();
std::transform(stem.begin(), stem.end(), stem.begin(), ::towupper);
hr = StringCchPrintf(result, cchMax, L"%s%s", stem.c_str(), fs::path(source).extension().c_str());
hr = StringCchCopy(result, cchMax, source);
if (SUCCEEDED(hr))
{
std::transform(result, result + wcslen(result), result, ::towupper);
}
}
else if (flags & ExtensionOnly)
else
{
std::wstring extension = fs::path(source).extension().wstring();
if (!extension.empty())
if (flags & NameOnly)
{
std::transform(extension.begin(), extension.end(), extension.begin(), ::towupper);
hr = StringCchPrintf(result, cchMax, L"%s%s", fs::path(source).stem().c_str(), extension.c_str());
std::wstring stem = fs::path(source).stem().wstring();
std::transform(stem.begin(), stem.end(), stem.begin(), ::towupper);
hr = StringCchPrintf(result, cchMax, L"%s%s", stem.c_str(), fs::path(source).extension().c_str());
}
else if (flags & ExtensionOnly)
{
std::wstring extension = fs::path(source).extension().wstring();
if (!extension.empty())
{
std::transform(extension.begin(), extension.end(), extension.begin(), ::towupper);
hr = StringCchPrintf(result, cchMax, L"%s%s", fs::path(source).stem().c_str(), extension.c_str());
}
else
{
hr = StringCchCopy(result, cchMax, source);
if (SUCCEEDED(hr))
{
std::transform(result, result + wcslen(result), result, ::towupper);
}
}
}
else
{
Expand All @@ -73,30 +92,41 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour
}
}
}
else
}
else if (flags & Lowercase)
{
if (isFolder)
{
hr = StringCchCopy(result, cchMax, source);
if (SUCCEEDED(hr))
{
std::transform(result, result + wcslen(result), result, ::towupper);
std::transform(result, result + wcslen(result), result, ::towlower);
}
}
}
else if (flags & Lowercase)
{
if (flags & NameOnly)
{
std::wstring stem = fs::path(source).stem().wstring();
std::transform(stem.begin(), stem.end(), stem.begin(), ::towlower);
hr = StringCchPrintf(result, cchMax, L"%s%s", stem.c_str(), fs::path(source).extension().c_str());
}
else if (flags & ExtensionOnly)
else
{
std::wstring extension = fs::path(source).extension().wstring();
if (!extension.empty())
if (flags & NameOnly)
{
std::transform(extension.begin(), extension.end(), extension.begin(), ::towlower);
hr = StringCchPrintf(result, cchMax, L"%s%s", fs::path(source).stem().c_str(), extension.c_str());
std::wstring stem = fs::path(source).stem().wstring();
std::transform(stem.begin(), stem.end(), stem.begin(), ::towlower);
hr = StringCchPrintf(result, cchMax, L"%s%s", stem.c_str(), fs::path(source).extension().c_str());
}
else if (flags & ExtensionOnly)
{
std::wstring extension = fs::path(source).extension().wstring();
if (!extension.empty())
{
std::transform(extension.begin(), extension.end(), extension.begin(), ::towlower);
hr = StringCchPrintf(result, cchMax, L"%s%s", fs::path(source).stem().c_str(), extension.c_str());
}
else
{
hr = StringCchCopy(result, cchMax, source);
if (SUCCEEDED(hr))
{
std::transform(result, result + wcslen(result), result, ::towlower);
}
}
}
else
{
Expand All @@ -107,22 +137,14 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour
}
}
}
else
{
hr = StringCchCopy(result, cchMax, source);
if (SUCCEEDED(hr))
{
std::transform(result, result + wcslen(result), result, ::towlower);
}
}
}
else if (flags & Titlecase)
{
if (!(flags & ExtensionOnly))
{
std::vector<std::wstring> exceptions = { L"a", L"an", L"to", L"the", L"at", L"by", L"for", L"in", L"of", L"on", L"up", L"and", L"as", L"but", L"or", L"nor" };
std::wstring stem = fs::path(source).stem().wstring();
std::wstring extension = fs::path(source).extension().wstring();
std::wstring stem = isFolder ? source : fs::path(source).stem().wstring();
std::wstring extension = isFolder ? L"" : fs::path(source).extension().wstring();

size_t stemLength = stem.length();
bool isFirstWord = true;
Expand Down Expand Up @@ -171,8 +193,8 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour
{
if (!(flags & ExtensionOnly))
{
std::wstring stem = fs::path(source).stem().wstring();
std::wstring extension = fs::path(source).extension().wstring();
std::wstring stem = isFolder ? source : fs::path(source).stem().wstring();
std::wstring extension = isFolder ? L"" : fs::path(source).extension().wstring();

size_t stemLength = stem.length();

Expand Down
2 changes: 1 addition & 1 deletion src/modules/powerrename/lib/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <string>

HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source);
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags);
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags, bool isFolder);
HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SYSTEMTIME fileTime);
bool isFileTimeUsed(_In_ PCWSTR source);
bool DataObjectContainsRenamableItem(_In_ IUnknown* dataSource);
Expand Down
72 changes: 48 additions & 24 deletions src/modules/powerrename/lib/PowerRenameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,8 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
winrt::check_hresult(spItem->GetIsSubFolderContent(&isSubFolderContent));
if ((isFolder && (flags & PowerRenameFlags::ExcludeFolders)) ||
(!isFolder && (flags & PowerRenameFlags::ExcludeFiles)) ||
(isSubFolderContent && (flags & PowerRenameFlags::ExcludeSubfolders)))
(isSubFolderContent && (flags & PowerRenameFlags::ExcludeSubfolders)) ||
(isFolder && (flags & PowerRenameFlags::ExtensionOnly)))
{
// Exclude this item from renaming. Ensure new name is cleared.
winrt::check_hresult(spItem->PutNewName(nullptr));
Expand All @@ -984,22 +985,31 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
winrt::check_hresult(spItem->GetNewName(&currentNewName));

wchar_t sourceName[MAX_PATH] = { 0 };
if (flags & NameOnly)

if (isFolder)
{
StringCchCopy(sourceName, ARRAYSIZE(sourceName), fs::path(originalName).stem().c_str());
StringCchCopy(sourceName, ARRAYSIZE(sourceName), originalName);

}
else if (flags & ExtensionOnly)
else
{
std::wstring extension = fs::path(originalName).extension().wstring();
if (!extension.empty() && extension.front() == '.')
if (flags & NameOnly)
{
extension = extension.erase(0, 1);
StringCchCopy(sourceName, ARRAYSIZE(sourceName), fs::path(originalName).stem().c_str());
}
else if (flags & ExtensionOnly)
{
std::wstring extension = fs::path(originalName).extension().wstring();
if (!extension.empty() && extension.front() == '.')
{
extension = extension.erase(0, 1);
}
StringCchCopy(sourceName, ARRAYSIZE(sourceName), extension.c_str());
}
else
{
StringCchCopy(sourceName, ARRAYSIZE(sourceName), originalName);
}
StringCchCopy(sourceName, ARRAYSIZE(sourceName), extension.c_str());
}
else
{
StringCchCopy(sourceName, ARRAYSIZE(sourceName), originalName);
}

SYSTEMTIME fileTime = { 0 };
Expand Down Expand Up @@ -1037,26 +1047,34 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
if (newName != nullptr)
{
newNameToUse = resultName;
if (flags & NameOnly)

if (isFolder)
{
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s%s", newName, fs::path(originalName).extension().c_str());
StringCchCopy(resultName, ARRAYSIZE(resultName), newName);
}
else if (flags & ExtensionOnly)
else
{
std::wstring extension = fs::path(originalName).extension().wstring();
if (!extension.empty())
if (flags & NameOnly)
{
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s.%s", fs::path(originalName).stem().c_str(), newName);
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s%s", newName, fs::path(originalName).extension().c_str());
}
else if (flags & ExtensionOnly)
{
std::wstring extension = fs::path(originalName).extension().wstring();
if (!extension.empty())
{
StringCchPrintf(resultName, ARRAYSIZE(resultName), L"%s.%s", fs::path(originalName).stem().c_str(), newName);
}
else
{
StringCchCopy(resultName, ARRAYSIZE(resultName), originalName);
}
}
else
{
StringCchCopy(resultName, ARRAYSIZE(resultName), originalName);
StringCchCopy(resultName, ARRAYSIZE(resultName), newName);
}
}
else
{
StringCchCopy(resultName, ARRAYSIZE(resultName), newName);
}
}

wchar_t trimmedName[MAX_PATH] = { 0 };
Expand All @@ -1069,7 +1087,13 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
wchar_t transformedName[MAX_PATH] = { 0 };
if (newNameToUse != nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase || flags & Capitalized))
{
winrt::check_hresult(GetTransformedFileName(transformedName, ARRAYSIZE(transformedName), newNameToUse, flags));
try
{
winrt::check_hresult(GetTransformedFileName(transformedName, ARRAYSIZE(transformedName), newNameToUse, flags, isFolder));
}
catch (...)
{
}
newNameToUse = transformedName;
}

Expand Down
5 changes: 3 additions & 2 deletions src/modules/powerrename/unittests/PowerRenameManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,9 @@ namespace PowerRenameManagerTests
TEST_METHOD (VerifyExtensionOnlyTransform)
{
rename_pairs renamePairs[] = {
{ L"foo.FOO", L"foo.bar", false, true, 0 },
{ L"foo.bar", L"foo.bar_norename", false, false, 0 }
{ L"foo.FOO", L"foo.bar", true, true, 0 },
{ L"bar.FOO", L"bar.FOO_norename", false, false, 0 },
{ L"foo.bar", L"foo.bar_norename", true, false, 0 }
};

RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Lowercase | ExtensionOnly);
Expand Down

0 comments on commit d359b3a

Please sign in to comment.