Op wo 15 jun. 2022 13:49 schreef vim-dev ML <[email protected]>:
> Hi,
>
> Op wo 15 jun. 2022 12:55 schreef Bram Moolenaar ***@***.***>:
>
> > A generic solution would be to make the "%1$s" form work with
> > vim_snprintf(). I don't know how complicated this is, getting the right
> > argument from through va_arg().
> >
>
> I'll try to see if I can come up with something...
>
> Christ van Willegen
I didn't realize this was on my to do list so long ago already!
Anyway, I'm (finally!) working on this, and got quite a bit working
already. Here are a few of my test cases:
in src/message_test.c
n = vim_snprintf(buf, bsize, "%1$*2$ld", 1234567L, -9);
n = vim_snprintf(buf, bsize, "%1$*2$.*3$ld", 1234567L, -9, 5);
n = vim_snprintf(buf, bsize, "%1$*3$.*2$ld", 1234567L, 5, -9);
n = vim_snprintf(buf, bsize, "%3$*1$.*2$ld", -9, 5, 1234567L);
n = vim_snprintf(buf, bsize, "%1$ld", 1234567L);
n = vim_snprintf(buf, bsize, "%1$*2$ld", 1234567L, 9);
n = vim_snprintf(buf, bsize, "%2$s %1$s %2$s", "one", "two", "three");
n = vim_snprintf(buf, bsize, "%3$s %1$s %2$s", "one", "two", "three");
n = vim_snprintf(buf, bsize, "%1$d", 1234567);
n = vim_snprintf(buf, bsize, "%1$x", 0xdeadbeef);
n = vim_snprintf(buf, bsize, "%01$.*2$b", (uvarnumber_T)12, 6);
n = vim_snprintf(buf, bsize, "%1$s %2$s", "one", "two");
in src/testdit/test_format.vim
call assert_equal('123', printf('%1$d', 123))
call assert_equal('00005', printf('%1$*1$.*1$d', 5))
call assert_equal('123', printf('%1$i', 123))
call assert_equal('123', printf('%1$D', 123))
call assert_equal('123', printf('%1$U', 123))
call assert_equal('173', printf('%1$o', 123))
call assert_equal('173', printf('%1$O', 123))
call assert_equal('7b', printf('%1$x', 123))
call assert_equal('7B', printf('%1$X', 123))
call assert_equal('123', printf('%1$hd', 123))
call assert_equal('-123', printf('%1$hd', -123))
call assert_equal('-1', printf('%1$hd', 0xFFFF))
call assert_equal('-1', printf('%1$hd', 0x1FFFFF))
call assert_equal('123', printf('%1$hu', 123))
call assert_equal('65413', printf('%1$hu', -123))
call assert_equal('65535', printf('%1$hu', 0xFFFF))
call assert_equal('65535', printf('%1$hu', 0x1FFFFF))
call assert_equal('123', printf('%1$ld', 123))
call assert_equal('-123', printf('%1$ld', -123))
call assert_equal('65535', printf('%1$ld', 0xFFFF))
call assert_equal('131071', printf('%1$ld', 0x1FFFF))
call assert_equal('{', printf('%1$c', 123))
call assert_equal('abc', printf('%1$s', 'abc'))
call assert_equal('abc', printf('%1$S', 'abc'))
call assert_equal('+123', printf('%+1$d', 123))
call assert_equal('-123', printf('%+1$d', -123))
call assert_equal('+123', printf('%+ 1$d', 123))
call assert_equal(' 123', printf('% 1$d', 123))
call assert_equal(' 123', printf('% 1$d', 123))
call assert_equal('-123', printf('% 1$d', -123))
call assert_equal(' 123', printf('%2$*1$d', 5, 123))
call assert_equal('123 ', printf('%2$*1$d', -5, 123))
call assert_equal('00123', printf('%2$.*1$d', 5, 123))
call assert_equal(' 123', printf('% 2$*1$d', 5, 123))
call assert_equal(' +123', printf('%+ 2$*1$d', 5, 123))
call assert_equal(' 123', printf('%1$*2$d', 123, 5))
call assert_equal('123 ', printf('%1$*2$d', 123, -5))
call assert_equal('00123', printf('%1$.*2$d', 123, 5))
call assert_equal(' 123', printf('% 1$*2$d', 123, 5))
call assert_equal(' +123', printf('%+ 1$*2$d', 123, 5))
call assert_equal('foobar', printf('%2$.*1$s', 9, 'foobar'))
call assert_equal('foo', printf('%2$.*1$s', 3, 'foobar'))
call assert_equal('', printf('%2$.*1$s', 0, 'foobar'))
call assert_equal('foobar', printf('%2$.*1$s', -1, 'foobar'))
#" Unrecognized format specifier kept as-is.
call assert_equal('_123', printf("%_%1$d", 123))
#" Test alternate forms.
call assert_equal('0x7b', printf('%#1$x', 123))
call assert_equal('0X7B', printf('%#1$X', 123))
call assert_equal('0173', printf('%#1$o', 123))
call assert_equal('0173', printf('%#1$O', 123))
call assert_equal('abc', printf('%#1$s', 'abc'))
call assert_equal('abc', printf('%#1$S', 'abc'))
#" Try argument re-use and argument swapping
call assert_equal('one two one', printf('%1$s %2$s %1$s', "one", "two"))
call assert_equal('Screen height: 400', printf('%1$s height: %2$d',
"Screen", 400))
call assert_equal('400 is: Screen height', printf('%2$d is: %1$s height',
"Screen", 400))
call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1400:")
call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1400:")
call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1401:")
call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1402:")
call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"],
"E1402:")
call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1403:")
call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1404:")
call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1405:")
call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"],
"E1405:")
//// Errors are defined as:
EXTERN char e_cannot_mix_positional_and_non_positional_str[]
INIT(= N_("E1400: Cannot mix positional and non-positional
arguments: %s"));
EXTERN char e_fmt_arg_nr_unused_str[]
INIT(= N_("E1401: format argument %d unused in $-style format:
%s"));
EXTERN char e_positional_num_field_spec_reused_str_str[]
INIT(= N_("E1402: Positional argument %d used as field width reused
as different type: %s/%s"));
EXTERN char e_positional_nr_out_of_bounds_str[]
INIT(= N_("E1403: Positional argument %d out of bounds: %s"));
EXTERN char e_positional_arg_num_type_inconsistent_str_str[]
INIT(= N_("E1404: Positional argument %d type used inconsistently:
%s/%s"));
EXTERN char e_invalid_format_specifier_str[]
INIT(= N_("E1405: Invalid format specifier: %s"));
//// End of error definitions
call assert_equal('1.000000', printf('%1$f', 1))
call assert_equal('1.230000', printf('%1$f', 1.23))
call assert_equal('1.230000', printf('%1$F', 1.23))
call assert_equal('9999999.9', printf('%1$g', 9999999.9))
call assert_equal('9999999.9', printf('%1$G', 9999999.9))
call assert_equal('1.230000e+00', printf('%1$e', 1.23))
call assert_equal('1.230000E+00', printf('%1$E', 1.23))
call assert_equal('1.200000e-02', printf('%1$e', 0.012))
call assert_equal('-1.200000e-02', printf('%1$e', -0.012))
call assert_equal('0.33', printf('%1$.2f', 1.0 / 3.0))
#" Float zero can be signed.
call assert_equal('+0.000000', printf('%+1$f', 0.0))
call assert_equal('0.000000', printf('%1$f', 1.0 / (1.0 / 0.0)))
call assert_equal('-0.000000', printf('%1$f', 1.0 / (-1.0 / 0.0)))
call assert_equal('0.0', printf('%1$s', 1.0 / (1.0 / 0.0)))
call assert_equal('-0.0', printf('%1$s', 1.0 / (-1.0 / 0.0)))
call assert_equal('0.0', printf('%1$S', 1.0 / (1.0 / 0.0)))
call assert_equal('-0.0', printf('%1$S', 1.0 / (-1.0 / 0.0)))
#" Float infinity can be signed.
call assert_equal('inf', printf('%1$f', 1.0 / 0.0))
call assert_equal('-inf', printf('%1$f', -1.0 / 0.0))
call assert_equal('inf', printf('%1$g', 1.0 / 0.0))
call assert_equal('-inf', printf('%1$g', -1.0 / 0.0))
call assert_equal('inf', printf('%1$e', 1.0 / 0.0))
call assert_equal('-inf', printf('%1$e', -1.0 / 0.0))
call assert_equal('INF', printf('%1$F', 1.0 / 0.0))
call assert_equal('-INF', printf('%1$F', -1.0 / 0.0))
call assert_equal('INF', printf('%1$E', 1.0 / 0.0))
call assert_equal('-INF', printf('%1$E', -1.0 / 0.0))
call assert_equal('INF', printf('%1$E', 1.0 / 0.0))
call assert_equal('-INF', printf('%1$G', -1.0 / 0.0))
call assert_equal('+inf', printf('%+1$f', 1.0 / 0.0))
call assert_equal('-inf', printf('%+1$f', -1.0 / 0.0))
call assert_equal(' inf', printf('% 1$f', 1.0 / 0.0))
There are more tests, but this is the largest set with the best coverage I
can find at the moment.
Of course, the 'normal' format strings without positional arguments are
still supported...
Before sending a PR, I would like to have more test cases, both valid ones,
and ones being invalid.
Can the Vim community help me to cover more test cases?
Christ van Willegen
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/CA%2BOt1Oy_mmS03xt7WwiC--DhUzhseo-UrtpyH-wb-nV_CUX1-A%40mail.gmail.com.