@@ -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+
736863void 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