Definition: sequence res = shorten(sequence s, string what="digits", integer ml=20, string fmt=""))
Description: Crops longer output when necessary.

s: the sequence/string to be shortened (when needed).
what: a name to use in any added suffix.
ml: the start/end length, as in half the total number of digits/characters/elements, to always keep.
fmt: for non-string s only, a format to apply to each element as part of the joining process.

The original text/sequence is returned unaltered if it is already shorter than 2*ml, or if it would be longer with "..." and the suffix.
Obviously you might want to replace "digits" with "chars"/"elements"/etc, and keep more/less of the first/last, as per examples below.
If what is specified as "" then there is no suffix, eg shorten("0123456789","",1) returns "0...9".
If fmt is not "" then sprintf is applied to each element returned, rather than having to do so to all of them, and except of course for any "..." in the middle or "(NNN what)" at the end. A fatal crash occcurs if s is a string and fmt is not "".

If s is not a string then a sequence of strings is assumed (doubly so if a non-empty fmt is supplied), the "..." and final suffix are inserted as string elements, more suitable for say join() or join_by(), and giving a default (unflattened) max result length of 42.

See also mpz_get_short_str(), which may be significantly faster for million-digit-plus numbers, since it doesn’t even build the middle part of the string in the first place.
pwa/p2js: Supported.
?shorten(repeat('1',9999)) -- prints "11111111111111111111...11111111111111111111 (9,999 digits)"
?shorten(repeat('1',9999),"ones",4) -- prints "1111...1111 (9,999 ones)"
?shorten(get_primes_le(100),"primes",2) -- prints {"2","3","...","89","97"," (25 primes)"}
Implementation: See builtins\ptrim.e (an autoinclude) for details of the actual implementation.