Mercurial > vim
comparison src/list.c @ 25591:ea69398b40d1 v8.2.3332
patch 8.2.3332: Vim9: cannot assign to range in list
Commit: https://github.com/vim/vim/commit/4f0884d6e24d1d45ec83fd86b372b403177d3298
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Aug 11 21:49:23 2021 +0200
patch 8.2.3332: Vim9: cannot assign to range in list
Problem: Vim9: cannot assign to range in list.
Solution: Implement overwriting a list range.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 11 Aug 2021 22:00:06 +0200 |
parents | 0082503ff2ff |
children | 0fdacd8f0cf3 |
comparison
equal
deleted
inserted
replaced
25590:db8dfe879ef8 | 25591:ea69398b40d1 |
---|---|
757 l->lv_u.mat.lv_idx_item = NULL; | 757 l->lv_u.mat.lv_idx_item = NULL; |
758 } | 758 } |
759 item->li_prev = ni; | 759 item->li_prev = ni; |
760 ++l->lv_len; | 760 ++l->lv_len; |
761 } | 761 } |
762 } | |
763 | |
764 /* | |
765 * Get the list item in "l" with index "n1". "n1" is adjusted if needed. | |
766 * In Vim9, it is at the end of the list, add an item. | |
767 * Return NULL if there is no such item. | |
768 */ | |
769 listitem_T * | |
770 check_range_index_one(list_T *l, long *n1, int quiet) | |
771 { | |
772 listitem_T *li = list_find_index(l, n1); | |
773 | |
774 if (li == NULL) | |
775 { | |
776 // Vim9: Allow for adding an item at the end. | |
777 if (in_vim9script() && *n1 == l->lv_len && l->lv_lock == 0) | |
778 { | |
779 list_append_number(l, 0); | |
780 li = list_find_index(l, n1); | |
781 } | |
782 if (li == NULL) | |
783 { | |
784 if (!quiet) | |
785 semsg(_(e_listidx), *n1); | |
786 return NULL; | |
787 } | |
788 } | |
789 return li; | |
790 } | |
791 | |
792 /* | |
793 * Check that "n2" can be used as the second index in a range of list "l". | |
794 * If "n1" or "n2" is negative it is changed to the positive index. | |
795 * "li1" is the item for item "n1". | |
796 * Return OK or FAIL. | |
797 */ | |
798 int | |
799 check_range_index_two( | |
800 list_T *l, | |
801 long *n1, | |
802 listitem_T *li1, | |
803 long *n2, | |
804 int quiet) | |
805 { | |
806 if (*n2 < 0) | |
807 { | |
808 listitem_T *ni = list_find(l, *n2); | |
809 | |
810 if (ni == NULL) | |
811 { | |
812 if (!quiet) | |
813 semsg(_(e_listidx), *n2); | |
814 return FAIL; | |
815 } | |
816 *n2 = list_idx_of_item(l, ni); | |
817 } | |
818 | |
819 // Check that n2 isn't before n1. | |
820 if (*n1 < 0) | |
821 *n1 = list_idx_of_item(l, li1); | |
822 if (*n2 < *n1) | |
823 { | |
824 if (!quiet) | |
825 semsg(_(e_listidx), *n2); | |
826 return FAIL; | |
827 } | |
828 return OK; | |
829 } | |
830 | |
831 /* | |
832 * Assign values from list "src" into a range of "dest". | |
833 * "idx1_arg" is the index of the first item in "dest" to be replaced. | |
834 * "idx2" is the index of last item to be replaced, but when "empty_idx2" is | |
835 * TRUE then replace all items after "idx1". | |
836 * "op" is the operator, normally "=" but can be "+=" and the like. | |
837 * "varname" is used for error messages. | |
838 * Returns OK or FAIL. | |
839 */ | |
840 int | |
841 list_assign_range( | |
842 list_T *dest, | |
843 list_T *src, | |
844 long idx1_arg, | |
845 long idx2, | |
846 int empty_idx2, | |
847 char_u *op, | |
848 char_u *varname) | |
849 { | |
850 listitem_T *src_li; | |
851 listitem_T *dest_li; | |
852 long idx1 = idx1_arg; | |
853 listitem_T *first_li = list_find_index(dest, &idx1); | |
854 long idx; | |
855 | |
856 /* | |
857 * Check whether any of the list items is locked before making any changes. | |
858 */ | |
859 idx = idx1; | |
860 dest_li = first_li; | |
861 for (src_li = src->lv_first; src_li != NULL && dest_li != NULL; ) | |
862 { | |
863 if (value_check_lock(dest_li->li_tv.v_lock, varname, FALSE)) | |
864 return FAIL; | |
865 src_li = src_li->li_next; | |
866 if (src_li == NULL || (!empty_idx2 && idx2 == idx)) | |
867 break; | |
868 dest_li = dest_li->li_next; | |
869 ++idx; | |
870 } | |
871 | |
872 /* | |
873 * Assign the List values to the list items. | |
874 */ | |
875 idx = idx1; | |
876 dest_li = first_li; | |
877 for (src_li = src->lv_first; src_li != NULL; ) | |
878 { | |
879 if (op != NULL && *op != '=') | |
880 tv_op(&dest_li->li_tv, &src_li->li_tv, op); | |
881 else | |
882 { | |
883 clear_tv(&dest_li->li_tv); | |
884 copy_tv(&src_li->li_tv, &dest_li->li_tv); | |
885 } | |
886 src_li = src_li->li_next; | |
887 if (src_li == NULL || (!empty_idx2 && idx2 == idx)) | |
888 break; | |
889 if (dest_li->li_next == NULL) | |
890 { | |
891 // Need to add an empty item. | |
892 if (list_append_number(dest, 0) == FAIL) | |
893 { | |
894 src_li = NULL; | |
895 break; | |
896 } | |
897 } | |
898 dest_li = dest_li->li_next; | |
899 ++idx; | |
900 } | |
901 if (src_li != NULL) | |
902 { | |
903 emsg(_(e_list_value_has_more_items_than_targets)); | |
904 return FAIL; | |
905 } | |
906 if (empty_idx2 | |
907 ? (dest_li != NULL && dest_li->li_next != NULL) | |
908 : idx != idx2) | |
909 { | |
910 emsg(_(e_list_value_does_not_have_enough_items)); | |
911 return FAIL; | |
912 } | |
913 return OK; | |
762 } | 914 } |
763 | 915 |
764 /* | 916 /* |
765 * Flatten "list" to depth "maxdepth". | 917 * Flatten "list" to depth "maxdepth". |
766 * It does nothing if "maxdepth" is 0. | 918 * It does nothing if "maxdepth" is 0. |