Skip to content

Commit

Permalink
Shorten CWD path
Browse files Browse the repository at this point in the history
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
Ekin Dursun committed Oct 22, 2021
1 parent 731b400 commit f4f0a2a
Showing 1 changed file with 128 additions and 0 deletions.
128 changes: 128 additions & 0 deletions Process.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,133 @@ void Process_printPercentage(float val, char* buffer, int n, int* attr) {
}
}

typedef struct shortenCwdContext {
char *cwd;
size_t maxLength;
size_t len;
char **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;
String_safeStrncpy(ctx->parts[i] + (ctx->partLengths[i] - 1), "~", 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) {
char newPart[] = "~~~";
newPart[0] = ctx->parts[i][0];
free_and_xStrdup(&ctx->parts[i], 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;

char *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] = '~';
memmove(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 void writeCwdUsingParts(shortenCwdContext *ctx) {
ctx->cwd[0] = '\0';
for (size_t i = 0, writeIndex = 0; i < ctx->partsLen; i++) {
if (!ctx->parts[i])
continue;

String_safeStrncpy(ctx->cwd + writeIndex, ctx->parts[i], ctx->partLengths[i] + 1);
writeIndex += ctx->partLengths[i];
if (i < ctx->partsLen - 1)
ctx->cwd[writeIndex++] = '/';
}
}

static void shortenCwd(char *cwd, const size_t maxLength) {
size_t len = strlen(cwd);
if (len <= maxLength)
return;

shortenCwdContext ctx = {
.cwd = cwd,
.maxLength = maxLength,
.len = len,
};
ctx.parts = String_split(cwd, '/', &ctx.partsLen);
ctx.partLengths = xCalloc(ctx.partsLen, sizeof(size_t));
for (size_t i = 0; i < ctx.partsLen; i++)
ctx.partLengths[i] = strlen(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);
}

writeCwdUsingParts(&ctx);

free(ctx.partLengths);
String_freeArray(ctx.parts);
}

void Process_writeField(const Process* this, RichString* str, ProcessField field) {
char buffer[256];
size_t n = sizeof(buffer);
Expand Down Expand Up @@ -825,6 +952,7 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
attr = CRT_colors[PROCESS_SHADOW];
cwd = "main thread terminated";
} else {
shortenCwd(this->procCwd, 25);
cwd = this->procCwd;
}
Process_printLeftAlignedField(str, attr, cwd, 25);
Expand Down

0 comments on commit f4f0a2a

Please sign in to comment.