Mercurial > vim
comparison src/eval.c @ 23604:1816ea68c022 v8.2.2344
patch 8.2.2344: using inclusive index for slice is not always desired
Commit: https://github.com/vim/vim/commit/6601b62943a19d4f8818c3638440663d67a17b6a
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Jan 13 21:47:15 2021 +0100
patch 8.2.2344: using inclusive index for slice is not always desired
Problem: Using inclusive index for slice is not always desired.
Solution: Add the slice() method, which has an exclusive index. (closes
#7408)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 13 Jan 2021 22:00:04 +0100 |
parents | f4347a61ed38 |
children | b26bbc03126a |
comparison
equal
deleted
inserted
replaced
23603:483d395694b0 | 23604:1816ea68c022 |
---|---|
3875 } | 3875 } |
3876 | 3876 |
3877 if (evaluate) | 3877 if (evaluate) |
3878 { | 3878 { |
3879 int res = eval_index_inner(rettv, range, | 3879 int res = eval_index_inner(rettv, range, |
3880 empty1 ? NULL : &var1, empty2 ? NULL : &var2, | 3880 empty1 ? NULL : &var1, empty2 ? NULL : &var2, FALSE, |
3881 key, keylen, verbose); | 3881 key, keylen, verbose); |
3882 | |
3882 if (!empty1) | 3883 if (!empty1) |
3883 clear_tv(&var1); | 3884 clear_tv(&var1); |
3884 if (range) | 3885 if (range) |
3885 clear_tv(&var2); | 3886 clear_tv(&var2); |
3886 return res; | 3887 return res; |
3936 } | 3937 } |
3937 return OK; | 3938 return OK; |
3938 } | 3939 } |
3939 | 3940 |
3940 /* | 3941 /* |
3942 * slice() function | |
3943 */ | |
3944 void | |
3945 f_slice(typval_T *argvars, typval_T *rettv) | |
3946 { | |
3947 if (check_can_index(argvars, TRUE, FALSE) == OK) | |
3948 { | |
3949 copy_tv(argvars, rettv); | |
3950 eval_index_inner(rettv, TRUE, argvars + 1, | |
3951 argvars[2].v_type == VAR_UNKNOWN ? NULL : argvars + 2, | |
3952 TRUE, NULL, 0, FALSE); | |
3953 } | |
3954 } | |
3955 | |
3956 /* | |
3941 * Apply index or range to "rettv". | 3957 * Apply index or range to "rettv". |
3942 * "var1" is the first index, NULL for [:expr]. | 3958 * "var1" is the first index, NULL for [:expr]. |
3943 * "var2" is the second index, NULL for [expr] and [expr: ] | 3959 * "var2" is the second index, NULL for [expr] and [expr: ] |
3960 * "exclusive" is TRUE for slice(): second index is exclusive, use character | |
3961 * index for string. | |
3944 * Alternatively, "key" is not NULL, then key[keylen] is the dict index. | 3962 * Alternatively, "key" is not NULL, then key[keylen] is the dict index. |
3945 */ | 3963 */ |
3946 int | 3964 int |
3947 eval_index_inner( | 3965 eval_index_inner( |
3948 typval_T *rettv, | 3966 typval_T *rettv, |
3949 int is_range, | 3967 int is_range, |
3950 typval_T *var1, | 3968 typval_T *var1, |
3951 typval_T *var2, | 3969 typval_T *var2, |
3970 int exclusive, | |
3952 char_u *key, | 3971 char_u *key, |
3953 int keylen, | 3972 int keylen, |
3954 int verbose) | 3973 int verbose) |
3955 { | 3974 { |
3956 long n1, n2 = 0; | 3975 varnumber_T n1, n2 = 0; |
3957 long len; | 3976 long len; |
3958 | 3977 |
3959 n1 = 0; | 3978 n1 = 0; |
3960 if (var1 != NULL && rettv->v_type != VAR_DICT) | 3979 if (var1 != NULL && rettv->v_type != VAR_DICT) |
3961 n1 = tv_get_number(var1); | 3980 n1 = tv_get_number(var1); |
3962 | 3981 |
3966 { | 3985 { |
3967 if (verbose) | 3986 if (verbose) |
3968 emsg(_(e_cannot_slice_dictionary)); | 3987 emsg(_(e_cannot_slice_dictionary)); |
3969 return FAIL; | 3988 return FAIL; |
3970 } | 3989 } |
3971 if (var2 == NULL) | 3990 if (var2 != NULL) |
3972 n2 = -1; | 3991 n2 = tv_get_number(var2); |
3973 else | 3992 else |
3974 n2 = tv_get_number(var2); | 3993 n2 = VARNUM_MAX; |
3975 } | 3994 } |
3976 | 3995 |
3977 switch (rettv->v_type) | 3996 switch (rettv->v_type) |
3978 { | 3997 { |
3979 case VAR_UNKNOWN: | 3998 case VAR_UNKNOWN: |
3992 case VAR_STRING: | 4011 case VAR_STRING: |
3993 { | 4012 { |
3994 char_u *s = tv_get_string(rettv); | 4013 char_u *s = tv_get_string(rettv); |
3995 | 4014 |
3996 len = (long)STRLEN(s); | 4015 len = (long)STRLEN(s); |
3997 if (in_vim9script()) | 4016 if (in_vim9script() || exclusive) |
3998 { | 4017 { |
3999 if (is_range) | 4018 if (is_range) |
4000 s = string_slice(s, n1, n2); | 4019 s = string_slice(s, n1, n2, exclusive); |
4001 else | 4020 else |
4002 s = char_from_string(s, n1); | 4021 s = char_from_string(s, n1); |
4003 } | 4022 } |
4004 else if (is_range) | 4023 else if (is_range) |
4005 { | 4024 { |
4013 } | 4032 } |
4014 if (n2 < 0) | 4033 if (n2 < 0) |
4015 n2 = len + n2; | 4034 n2 = len + n2; |
4016 else if (n2 >= len) | 4035 else if (n2 >= len) |
4017 n2 = len; | 4036 n2 = len; |
4037 if (exclusive) | |
4038 --n2; | |
4018 if (n1 >= len || n2 < 0 || n1 > n2) | 4039 if (n1 >= len || n2 < 0 || n1 > n2) |
4019 s = NULL; | 4040 s = NULL; |
4020 else | 4041 else |
4021 s = vim_strnsave(s + n1, n2 - n1 + 1); | 4042 s = vim_strnsave(s + n1, n2 - n1 + 1); |
4022 } | 4043 } |
4049 n1 = 0; | 4070 n1 = 0; |
4050 } | 4071 } |
4051 if (n2 < 0) | 4072 if (n2 < 0) |
4052 n2 = len + n2; | 4073 n2 = len + n2; |
4053 else if (n2 >= len) | 4074 else if (n2 >= len) |
4054 n2 = len - 1; | 4075 n2 = len - (exclusive ? 0 : 1); |
4076 if (exclusive) | |
4077 --n2; | |
4055 if (n1 >= len || n2 < 0 || n1 > n2) | 4078 if (n1 >= len || n2 < 0 || n1 > n2) |
4056 { | 4079 { |
4057 clear_tv(rettv); | 4080 clear_tv(rettv); |
4058 rettv->v_type = VAR_BLOB; | 4081 rettv->v_type = VAR_BLOB; |
4059 rettv->vval.v_blob = NULL; | 4082 rettv->vval.v_blob = NULL; |
4101 | 4124 |
4102 case VAR_LIST: | 4125 case VAR_LIST: |
4103 if (var1 == NULL) | 4126 if (var1 == NULL) |
4104 n1 = 0; | 4127 n1 = 0; |
4105 if (var2 == NULL) | 4128 if (var2 == NULL) |
4106 n2 = -1; | 4129 n2 = VARNUM_MAX; |
4107 if (list_slice_or_index(rettv->vval.v_list, | 4130 if (list_slice_or_index(rettv->vval.v_list, |
4108 is_range, n1, n2, rettv, verbose) == FAIL) | 4131 is_range, n1, n2, exclusive, rettv, verbose) == FAIL) |
4109 return FAIL; | 4132 return FAIL; |
4110 break; | 4133 break; |
4111 | 4134 |
4112 case VAR_DICT: | 4135 case VAR_DICT: |
4113 { | 4136 { |