Skip to content

Commit f7ca2ab

Browse files
author
Ekin Dursun
committed
Shorten CWD path
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.
1 parent 731b400 commit f7ca2ab

1 file changed

Lines changed: 128 additions & 0 deletions

File tree

Process.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,133 @@ void Process_printPercentage(float val, char* buffer, int n, int* attr) {
733733
}
734734
}
735735

736+
typedef struct ShortenCwdContext {
737+
char *cwd;
738+
size_t maxLength;
739+
size_t len;
740+
char **parts;
741+
size_t partsLen;
742+
size_t *partLengths;
743+
} ShortenCwdContext;
744+
745+
static void shortenCwdParts(ShortenCwdContext *ctx) {
746+
for (int i = ctx->partsLen - 2; i >= 0 && ctx->len > ctx->maxLength; i--) {
747+
if (ctx->partLengths[i] < 3)
748+
continue;
749+
750+
size_t extraChars = ctx->len - ctx->maxLength;
751+
size_t maxRemovableChars = ctx->partLengths[i] - 2;
752+
size_t charsToRemove = extraChars < maxRemovableChars ? extraChars : maxRemovableChars;
753+
754+
ctx->partLengths[i] -= charsToRemove;
755+
ctx->len -= charsToRemove;
756+
String_safeStrncpy(ctx->parts[i] + (ctx->partLengths[i] - 1), "~", 2);
757+
}
758+
}
759+
760+
static size_t collapseCwdParts(ShortenCwdContext *ctx, bool doActualWork) {
761+
if (ctx->len <= ctx->maxLength || ctx->partsLen <= 3)
762+
return 0;
763+
764+
size_t len = ctx->len;
765+
766+
size_t i;
767+
for (i = ctx->partsLen - 2; i > 1; i--) {
768+
if (len + (3 - ctx->partLengths[i]) <= ctx->maxLength)
769+
break;
770+
771+
len -= ctx->partLengths[i] + 1;
772+
773+
if (doActualWork) {
774+
ctx->partLengths[i] = 0;
775+
free(ctx->parts[i]);
776+
ctx->parts[i] = NULL;
777+
}
778+
}
779+
780+
len += 3 - ctx->partLengths[i];
781+
size_t diff = ctx->len - len;
782+
783+
if (doActualWork) {
784+
char newPart[] = "~~~";
785+
newPart[0] = ctx->parts[i][0];
786+
free_and_xStrdup(&ctx->parts[i], newPart);
787+
ctx->partLengths[i] = 3;
788+
ctx->len = len;
789+
}
790+
791+
return diff;
792+
}
793+
794+
static size_t shortenCwdLastPart(ShortenCwdContext *ctx, bool doActualWork) {
795+
if (ctx->len <= ctx->maxLength)
796+
return 0;
797+
798+
size_t lastPartLen = ctx->partLengths[ctx->partsLen - 1];
799+
if (lastPartLen <= 3)
800+
return 0;
801+
802+
char *lastPart = ctx->parts[ctx->partsLen - 1];
803+
size_t extraChars = ctx->len - ctx->maxLength + 1;
804+
size_t maxRemovableChars = lastPartLen - 2;
805+
size_t charsToRemove = extraChars < maxRemovableChars ? extraChars : maxRemovableChars;
806+
807+
if (doActualWork) {
808+
size_t charsAtBeginning = (lastPartLen - charsToRemove + 1) / 2;
809+
size_t charsAtEnd = lastPartLen - charsToRemove - charsAtBeginning;
810+
lastPart[charsAtBeginning] = '~';
811+
memmove(lastPart + charsAtBeginning + 1, lastPart + lastPartLen - charsAtEnd, charsAtEnd);
812+
lastPart[charsAtBeginning + charsAtEnd + 1] = '\0';
813+
ctx->partLengths[ctx->partsLen - 1] = lastPartLen - charsToRemove + 1;
814+
ctx->len -= charsToRemove - 1;
815+
}
816+
817+
return charsToRemove - 1;
818+
}
819+
820+
static void writeCwdUsingParts(ShortenCwdContext *ctx) {
821+
ctx->cwd[0] = '\0';
822+
for (size_t i = 0, writeIndex = 0; i < ctx->partsLen; i++) {
823+
if (!ctx->parts[i])
824+
continue;
825+
826+
String_safeStrncpy(ctx->cwd + writeIndex, ctx->parts[i], ctx->partLengths[i] + 1);
827+
writeIndex += ctx->partLengths[i];
828+
if (i < ctx->partsLen - 1)
829+
ctx->cwd[writeIndex++] = '/';
830+
}
831+
}
832+
833+
static void shortenCwd(char *cwd, const size_t maxLength) {
834+
size_t len = strlen(cwd);
835+
if (len <= maxLength)
836+
return;
837+
838+
ShortenCwdContext ctx = {
839+
.cwd = cwd,
840+
.maxLength = maxLength,
841+
.len = len,
842+
};
843+
ctx.parts = String_split(cwd, '/', &ctx.partsLen);
844+
ctx.partLengths = xCalloc(ctx.partsLen, sizeof(size_t));
845+
for (size_t i = 0; i < ctx.partsLen; i++)
846+
ctx.partLengths[i] = strlen(ctx.parts[i]);
847+
848+
shortenCwdParts(&ctx);
849+
if (shortenCwdLastPart(&ctx, false) > collapseCwdParts(&ctx, false)) {
850+
shortenCwdLastPart(&ctx, true);
851+
collapseCwdParts(&ctx, true);
852+
} else {
853+
collapseCwdParts(&ctx, true);
854+
shortenCwdLastPart(&ctx, true);
855+
}
856+
857+
writeCwdUsingParts(&ctx);
858+
859+
free(ctx.partLengths);
860+
String_freeArray(ctx.parts);
861+
}
862+
736863
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
737864
char buffer[256];
738865
size_t n = sizeof(buffer);
@@ -825,6 +952,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
825952
attr = CRT_colors[PROCESS_SHADOW];
826953
cwd = "main thread terminated";
827954
} else {
955+
shortenCwd(this->procCwd, 25);
828956
cwd = this->procCwd;
829957
}
830958
Process_printLeftAlignedField(str, attr, cwd, 25);

0 commit comments

Comments
 (0)