-
-
Notifications
You must be signed in to change notification settings - Fork 450
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
For showing the CWD path in a more compact way, this function - shortens path parts before last from right to left, until first character of the path stays (directory -> direc~ or d~) - combines parts before last from right with left (a~/b~ -> a~~) - shortens the last part from middle, preferring to keep characters from left (longdirectoryname -> long~ame) in order (of 2nd and 3rd, the one that removes more characters is applied first) until given maximum length is reached.
- Loading branch information
Showing
8 changed files
with
266 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
#include "config.h" // IWYU pragma: keep | ||
|
||
#include "CwdUtils.h" | ||
|
||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
#include <wchar.h> | ||
|
||
#include "XUtils.h" | ||
|
||
typedef struct ShortenCwdContext { | ||
size_t maxLength; | ||
size_t len; | ||
wchar_t **parts; | ||
size_t partsLen; | ||
size_t *partLengths; | ||
} ShortenCwdContext; | ||
|
||
static void shortenCwdParts(ShortenCwdContext *ctx) { | ||
for (int i = ctx->partsLen - 2; i >= 0 && ctx->len > ctx->maxLength; i--) { | ||
if (ctx->partLengths[i] < 3) | ||
continue; | ||
|
||
size_t extraChars = ctx->len - ctx->maxLength; | ||
size_t maxRemovableChars = ctx->partLengths[i] - 2; | ||
size_t charsToRemove = extraChars < maxRemovableChars ? extraChars : maxRemovableChars; | ||
|
||
ctx->partLengths[i] -= charsToRemove; | ||
ctx->len -= charsToRemove; | ||
|
||
Wstring_safeWcsncpy(ctx->parts[i] + (ctx->partLengths[i] - 1), L"~", 2); | ||
} | ||
} | ||
|
||
static size_t collapseCwdParts(ShortenCwdContext *ctx, bool doActualWork) { | ||
if (ctx->len <= ctx->maxLength || ctx->partsLen <= 3) | ||
return 0; | ||
|
||
size_t len = ctx->len; | ||
|
||
size_t i; | ||
for (i = ctx->partsLen - 2; i > 1; i--) { | ||
if (len + (3 - ctx->partLengths[i]) <= ctx->maxLength) | ||
break; | ||
|
||
len -= ctx->partLengths[i] + 1; | ||
|
||
if (doActualWork) { | ||
ctx->partLengths[i] = 0; | ||
free(ctx->parts[i]); | ||
ctx->parts[i] = NULL; | ||
} | ||
} | ||
|
||
len += 3 - ctx->partLengths[i]; | ||
size_t diff = ctx->len - len; | ||
|
||
if (doActualWork) { | ||
wchar_t newPart[] = L"~~~"; | ||
newPart[0] = ctx->parts[i][0]; | ||
free(ctx->parts[i]); | ||
ctx->parts[i] = xWcsdup(newPart); | ||
ctx->partLengths[i] = 3; | ||
ctx->len = len; | ||
} | ||
|
||
return diff; | ||
} | ||
|
||
static size_t shortenCwdLastPart(ShortenCwdContext *ctx, bool doActualWork) { | ||
if (ctx->len <= ctx->maxLength) | ||
return 0; | ||
|
||
size_t lastPartLen = ctx->partLengths[ctx->partsLen - 1]; | ||
if (lastPartLen <= 3) | ||
return 0; | ||
|
||
wchar_t *lastPart = ctx->parts[ctx->partsLen - 1]; | ||
size_t extraChars = ctx->len - ctx->maxLength + 1; | ||
size_t maxRemovableChars = lastPartLen - 2; | ||
size_t charsToRemove = extraChars < maxRemovableChars ? extraChars : maxRemovableChars; | ||
|
||
if (doActualWork) { | ||
size_t charsAtBeginning = (lastPartLen - charsToRemove + 1) / 2; | ||
size_t charsAtEnd = lastPartLen - charsToRemove - charsAtBeginning; | ||
lastPart[charsAtBeginning] = '~'; | ||
wmemmove(lastPart + charsAtBeginning + 1, lastPart + lastPartLen - charsAtEnd, charsAtEnd); | ||
lastPart[charsAtBeginning + charsAtEnd + 1] = '\0'; | ||
ctx->partLengths[ctx->partsLen - 1] = lastPartLen - charsToRemove + 1; | ||
ctx->len -= charsToRemove - 1; | ||
} | ||
|
||
return charsToRemove - 1; | ||
} | ||
|
||
static wchar_t* buildCwdFromParts(ShortenCwdContext *ctx) { | ||
size_t len = ctx->partsLen - 1; | ||
for (size_t i = 0; i < ctx->partsLen; i++) | ||
len += ctx->partLengths[i]; | ||
|
||
wchar_t *newCwd = xCalloc(len + 1, sizeof(wchar_t)); | ||
|
||
newCwd[0] = '\0'; | ||
for (size_t i = 0, writeIndex = 0; i < ctx->partsLen; i++) { | ||
if (!ctx->parts[i]) | ||
continue; | ||
|
||
Wstring_safeWcsncpy(newCwd + writeIndex, ctx->parts[i], ctx->partLengths[i] + 1); | ||
writeIndex += ctx->partLengths[i]; | ||
if (i < ctx->partsLen - 1) | ||
newCwd[writeIndex++] = L'/'; | ||
} | ||
|
||
return newCwd; | ||
} | ||
|
||
char* CwdUtils_shortenCwd(char *cwd, const size_t maxLength) { | ||
wchar_t *wcwd = xMbstowcs(cwd); | ||
size_t len = wcslen(wcwd); | ||
if (len <= maxLength) { | ||
free(wcwd); | ||
return xStrdup(cwd); | ||
} | ||
|
||
ShortenCwdContext ctx = { | ||
.maxLength = maxLength, | ||
.len = len, | ||
}; | ||
ctx.parts = Wstring_split(wcwd, L'/', &ctx.partsLen); | ||
free(wcwd); | ||
wcwd = NULL; | ||
ctx.partLengths = xCalloc(ctx.partsLen, sizeof(size_t)); | ||
for (size_t i = 0; i < ctx.partsLen; i++) | ||
ctx.partLengths[i] = wcslen(ctx.parts[i]); | ||
|
||
shortenCwdParts(&ctx); | ||
if (shortenCwdLastPart(&ctx, false) > collapseCwdParts(&ctx, false)) { | ||
shortenCwdLastPart(&ctx, true); | ||
collapseCwdParts(&ctx, true); | ||
} else { | ||
collapseCwdParts(&ctx, true); | ||
shortenCwdLastPart(&ctx, true); | ||
} | ||
|
||
wchar_t *newWcwd = buildCwdFromParts(&ctx); | ||
char *newCwd = xWcstombs(newWcwd); | ||
free(newWcwd); | ||
|
||
free(ctx.partLengths); | ||
for (size_t i = 0; i < ctx.partsLen; i++) | ||
free(ctx.parts[i]); | ||
free(ctx.parts); | ||
|
||
return newCwd; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef HEADER_CwdUtils | ||
#define HEADER_CwdUtils | ||
|
||
#include <stddef.h> | ||
|
||
char* CwdUtils_shortenCwd(char* cwd, size_t maxLength); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters