node-printf icon indicating copy to clipboard operation
node-printf copied to clipboard

string formatting - truncate, pad left and pad right

Open mscalora opened this issue 8 years ago • 5 comments

It would be very useful to be able to truncate strings to a certain length and also pad left and right, currently only padding left appears to be supported. maybe upper case S could support traditional extended string formatting like

%10S       - pad right
%-10S      - pad left
%.10S      - truncate right
%-.10S     - truncate left
%10.10S    - pad and truncate right
%-10.10S   - pad and truncate left

I would consider creating a patch request if the idea is palatable

mscalora avatar Jan 21 '18 23:01 mscalora

I'm ok with the idea. Is there some standart directed by printf relative to right padding ?

wdavidw avatar Jan 23 '18 20:01 wdavidw

@wdavidw the spec does cover padding: http://www.cplusplus.com/reference/cstdio/printf/

Having said that, from example above, I couldn't understand what would %-10S for example mean from it. Because % is always there, - stands for left-justify within given field; now hard part - 10 is width and S would be specifier, but I can't find specifier with capital S, only lowercase...

revelt avatar Apr 18 '18 09:04 revelt

The C standard docs I have seen are a bit vague about how some features like precision apply to strings. Using Apple's clang/LLVM, not sure whose runtime, gnu maybe:

#include <stdio.h>

int main(void) {
   printf("12345678901234567890\n");

   printf("\n%%s|\n\n");
   printf("%s|\n", "short");
   printf("%s|\n", "really-long-string");

   printf("\n%%10s|\n\n");
   printf("%10s|\n", "short");
   printf("%10s|\n", "really-long-string");

   printf("\n%%-10s|\n\n");
   printf("%-10s|\n", "short");
   printf("%-10s|\n", "really-long-string");

   printf("\n%%.10s|\n\n");
   printf("%.10s|\n", "short");
   printf("%.10s|\n", "really-long-string");

   printf("\n%%-.10s|\n\n");
   printf("%-.10s|\n", "short");
   printf("%-.10s|\n", "really-long-string");

   printf("\n%%10.10s|\n\n");
   printf("%10.10s|\n", "short");
   printf("%10.10s|\n", "really-long-string");

   printf("%%-10.10s|\n\n");
   printf("%-10.10s|\n", "short");
   printf("%-10.10s|\n", "really-long-string");

   return 0;
}

I get:

$ ./test
12345678901234567890

%s|

short|
really-long-string|

%10s|

     short|
really-long-string|

%-10s|

short     |
really-long-string|

%.10s|

short|
really-lon|

%-.10s|

short|
really-lon|

%10.10s|

     short|
really-lon|
%-10.10s|

short     |
really-lon|
$

The only places my suggestion differs are %-.10s and %-10.10s where clib truncates right. I tried negative precision like %.-10s but clang produces an "invalid specifier" error though this could allow pad-left-truc-right or pad-right-truc-left like %-10.10s and %10.-10s while %-10.-10s would then need to be used for pad-left-trunc-left but I don't think that is really very useful to mix left and right in the same format specifier.

I think I suggested uppercase S to preserve current behaviour for s. It is sometimes used as an extension for double byte strings where the C standard uses %ls.

For reference:

sprintf = require('printf');

function printf() {
  process.stdout.write(sprintf.apply(this, arguments));
}

printf("12345678901234567890\n");

printf("\n%%s|\n\n");
printf("%s|\n", "short");
printf("%s|\n", "really-long-string");

printf("\n%%10s|\n\n");
printf("%10s|\n", "short");
printf("%10s|\n", "really-long-string");

printf("\n%%-10s|\n\n");
printf("%-10s|\n", "short");
printf("%-10s|\n", "really-long-string");

printf("\n%%.10s|\n\n");
printf("%.10s|\n", "short");
printf("%.10s|\n", "really-long-string");

printf("\n%%-.10s|\n\n");
printf("%-.10s|\n", "short");
printf("%-.10s|\n", "really-long-string");

printf("\n%%10.10s|\n\n");
printf("%10.10s|\n", "short");
printf("%10.10s|\n", "really-long-string");

printf("%%-10.10s|\n\n");
printf("%-10.10s|\n", "short");
printf("%-10.10s|\n", "really-long-string");

produces:

$ node test.js
12345678901234567890

%s|

short|
really-long-string|

%10s|

     short|
really-long-string|

%-10s|

short     |
really-long-string|

%.10s|

short|
really-long-string|

%-.10s|

short|
really-long-string|

%10.10s|

     short|
really-long-string|
%-10.10s|

short     |
really-long-string|

mscalora avatar Apr 18 '18 12:04 mscalora

Any suggestion on this issue ?

wdavidw avatar Sep 03 '18 22:09 wdavidw

@wdavidw If you meant me, sorry I'm completely out of touch with this issue; this library is working fine for my needs currently, I'm using it daily, all is fine. Thank you for great work, I should have written it myself if you haven't created it because I have to deliver code in both Nunjucks (Node) and Jinja (Python) and "out-of-box", this filter is missing outside Python. Thank you!

revelt avatar Sep 04 '18 04:09 revelt