comparison src/tag.c @ 15016:c338c91086b9 v8.1.0519

patch 8.1.0519: cannot save and restore the tag stack commit https://github.com/vim/vim/commit/f49cc60aa802862c595ff619dccc11271633a94b Author: Bram Moolenaar <Bram@vim.org> Date: Sun Nov 11 15:21:05 2018 +0100 patch 8.1.0519: cannot save and restore the tag stack Problem: Cannot save and restore the tag stack. Solution: Add gettagstack() and settagstack(). (Yegappan Lakshmanan, closes #3604)
author Bram Moolenaar <Bram@vim.org>
date Sun, 11 Nov 2018 15:30:07 +0100
parents 27b9a84395b5
children 7903dce131d4
comparison
equal deleted inserted replaced
15015:abcfa9dcc93f 15016:c338c91086b9
4014 } 4014 }
4015 vim_free(matches); 4015 vim_free(matches);
4016 } 4016 }
4017 return ret; 4017 return ret;
4018 } 4018 }
4019 #endif 4019
4020 /*
4021 * Return information about 'tag' in dict 'retdict'.
4022 */
4023 static void
4024 get_tag_details(taggy_T *tag, dict_T *retdict)
4025 {
4026 list_T *pos;
4027 fmark_T *fmark;
4028
4029 dict_add_string(retdict, "tagname", tag->tagname);
4030 dict_add_number(retdict, "matchnr", tag->cur_match + 1);
4031 dict_add_number(retdict, "bufnr", tag->cur_fnum);
4032
4033 if ((pos = list_alloc_id(aid_tagstack_from)) == NULL)
4034 return;
4035 dict_add_list(retdict, "from", pos);
4036
4037 fmark = &tag->fmark;
4038 list_append_number(pos,
4039 (varnumber_T)(fmark->fnum != -1 ? fmark->fnum : 0));
4040 list_append_number(pos, (varnumber_T)fmark->mark.lnum);
4041 list_append_number(pos, (varnumber_T)(fmark->mark.col == MAXCOL ?
4042 MAXCOL : fmark->mark.col + 1));
4043 list_append_number(pos, (varnumber_T)fmark->mark.coladd);
4044 }
4045
4046 /*
4047 * Return the tag stack entries of the specified window 'wp' in dictionary
4048 * 'retdict'.
4049 */
4050 void
4051 get_tagstack(win_T *wp, dict_T *retdict)
4052 {
4053 list_T *l;
4054 int i;
4055 dict_T *d;
4056
4057 dict_add_number(retdict, "length", wp->w_tagstacklen);
4058 dict_add_number(retdict, "curidx", wp->w_tagstackidx + 1);
4059 l = list_alloc_id(aid_tagstack_items);
4060 if (l == NULL)
4061 return;
4062 dict_add_list(retdict, "items", l);
4063
4064 for (i = 0; i < wp->w_tagstacklen; i++)
4065 {
4066 if ((d = dict_alloc_id(aid_tagstack_details)) == NULL)
4067 return;
4068 list_append_dict(l, d);
4069
4070 get_tag_details(&wp->w_tagstack[i], d);
4071 }
4072 }
4073
4074 /*
4075 * Free all the entries in the tag stack of the specified window
4076 */
4077 static void
4078 tagstack_clear(win_T *wp)
4079 {
4080 int i;
4081
4082 // Free the current tag stack
4083 for (i = 0; i < wp->w_tagstacklen; ++i)
4084 vim_free(wp->w_tagstack[i].tagname);
4085 wp->w_tagstacklen = 0;
4086 wp->w_tagstackidx = 0;
4087 }
4088
4089 /*
4090 * Remove the oldest entry from the tag stack and shift the rest of
4091 * the entires to free up the top of the stack.
4092 */
4093 static void
4094 tagstack_shift(win_T *wp)
4095 {
4096 taggy_T *tagstack = wp->w_tagstack;
4097 int i;
4098
4099 vim_free(tagstack[0].tagname);
4100 for (i = 1; i < wp->w_tagstacklen; ++i)
4101 tagstack[i - 1] = tagstack[i];
4102 wp->w_tagstacklen--;
4103 }
4104
4105 /*
4106 * Push a new item to the tag stack
4107 */
4108 static void
4109 tagstack_push_item(
4110 win_T *wp,
4111 char_u *tagname,
4112 int cur_fnum,
4113 int cur_match,
4114 pos_T mark,
4115 int fnum)
4116 {
4117 taggy_T *tagstack = wp->w_tagstack;
4118 int idx = wp->w_tagstacklen; // top of the stack
4119
4120 // if the tagstack is full: remove the oldest entry
4121 if (idx >= TAGSTACKSIZE)
4122 {
4123 tagstack_shift(wp);
4124 idx = TAGSTACKSIZE - 1;
4125 }
4126
4127 wp->w_tagstacklen++;
4128 tagstack[idx].tagname = tagname;
4129 tagstack[idx].cur_fnum = cur_fnum;
4130 tagstack[idx].cur_match = cur_match;
4131 if (tagstack[idx].cur_match < 0)
4132 tagstack[idx].cur_match = 0;
4133 tagstack[idx].fmark.mark = mark;
4134 tagstack[idx].fmark.fnum = fnum;
4135 }
4136
4137 /*
4138 * Add a list of items to the tag stack in the specified window
4139 */
4140 static void
4141 tagstack_push_items(win_T *wp, list_T *l)
4142 {
4143 listitem_T *li;
4144 dictitem_T *di;
4145 dict_T *itemdict;
4146 char_u *tagname;
4147 pos_T mark;
4148 int fnum;
4149
4150 // Add one entry at a time to the tag stack
4151 for (li = l->lv_first; li != NULL; li = li->li_next)
4152 {
4153 if (li->li_tv.v_type != VAR_DICT || li->li_tv.vval.v_dict == NULL)
4154 continue; // Skip non-dict items
4155 itemdict = li->li_tv.vval.v_dict;
4156
4157 // parse 'from' for the cursor position before the tag jump
4158 if ((di = dict_find(itemdict, (char_u *)"from", -1)) == NULL)
4159 continue;
4160 if (list2fpos(&di->di_tv, &mark, &fnum, NULL) != OK)
4161 continue;
4162 if ((tagname =
4163 get_dict_string(itemdict, (char_u *)"tagname", TRUE)) == NULL)
4164 continue;
4165
4166 if (mark.col > 0)
4167 mark.col--;
4168 tagstack_push_item(wp, tagname,
4169 (int)get_dict_number(itemdict, (char_u *)"bufnr"),
4170 (int)get_dict_number(itemdict, (char_u *)"matchnr") - 1,
4171 mark, fnum);
4172 }
4173 }
4174
4175 /*
4176 * Set the current index in the tag stack. Valid values are between 0
4177 * and the stack length (inclusive).
4178 */
4179 static void
4180 tagstack_set_curidx(win_T *wp, int curidx)
4181 {
4182 wp->w_tagstackidx = curidx;
4183 if (wp->w_tagstackidx < 0) // sanity check
4184 wp->w_tagstackidx = 0;
4185 if (wp->w_tagstackidx > wp->w_tagstacklen)
4186 wp->w_tagstackidx = wp->w_tagstacklen;
4187 }
4188
4189 /*
4190 * Set the tag stack entries of the specified window.
4191 * 'action' is set to either 'a' for append or 'r' for replace.
4192 */
4193 int
4194 set_tagstack(win_T *wp, dict_T *d, int action)
4195 {
4196 dictitem_T *di;
4197 list_T *l;
4198
4199 if ((di = dict_find(d, (char_u *)"items", -1)) != NULL)
4200 {
4201 if (di->di_tv.v_type != VAR_LIST)
4202 {
4203 EMSG(_(e_listreq));
4204 return FAIL;
4205 }
4206 l = di->di_tv.vval.v_list;
4207
4208 if (action == 'r')
4209 tagstack_clear(wp);
4210
4211 tagstack_push_items(wp, l);
4212 }
4213
4214 if ((di = dict_find(d, (char_u *)"curidx", -1)) != NULL)
4215 tagstack_set_curidx(wp, (int)get_tv_number(&di->di_tv) - 1);
4216
4217 return OK;
4218 }
4219 #endif