0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 9.1.0422: function echo_string_core() is too long

Problem:  function echo_string_core() is too long
Solution: Refactor into several smaller functions
          (Yegappan Lakshmanan)

closes: #14804

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yegappan Lakshmanan
2024-05-20 13:57:11 +02:00
committed by Christian Brabandt
parent 5f1b115afd
commit 22029edb6c
5 changed files with 308 additions and 162 deletions

View File

@@ -6449,11 +6449,292 @@ set_ref_in_item(
return abort;
}
/*
* Return a textual representation of a string in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* When both "echo_style" and "composite_val" are FALSE, put quotes around
* strings as "string()", otherwise does not put quotes around strings.
* May return NULL.
*/
static char_u *
string_tv2string(
typval_T *tv,
char_u **tofree,
int echo_style,
int composite_val)
{
char_u *r = NULL;
if (echo_style && !composite_val)
{
*tofree = NULL;
r = tv->vval.v_string;
if (r == NULL)
r = (char_u *)"";
}
else
{
*tofree = string_quote(tv->vval.v_string, FALSE);
r = *tofree;
}
return r;
}
/*
* Return a textual representation of a function in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* When "echo_style" is FALSE, put quotes around the function name as
* "function()", otherwise does not put quotes around function name.
* May return NULL.
*/
static char_u *
func_tv2string(typval_T *tv, char_u **tofree, int echo_style)
{
char_u *r = NULL;
char_u buf[MAX_FUNC_NAME_LEN];
if (echo_style)
{
r = tv->vval.v_string == NULL ? (char_u *)"function()"
: make_ufunc_name_readable(tv->vval.v_string,
buf, MAX_FUNC_NAME_LEN);
if (r == buf)
{
r = vim_strsave(buf);
*tofree = r;
}
else
*tofree = NULL;
}
else
{
*tofree = string_quote(tv->vval.v_string == NULL ? NULL
: make_ufunc_name_readable(tv->vval.v_string,
buf, MAX_FUNC_NAME_LEN), TRUE);
r = *tofree;
}
return r;
}
/*
* Return a textual representation of a partial in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* "numbuf" is used for a number. May return NULL.
*/
static char_u *
partial_tv2string(
typval_T *tv,
char_u **tofree,
char_u *numbuf,
int copyID)
{
char_u *r = NULL;
partial_T *pt;
char_u *fname;
garray_T ga;
int i;
char_u *tf;
pt = tv->vval.v_partial;
fname = string_quote(pt == NULL ? NULL : partial_name(pt), FALSE);
ga_init2(&ga, 1, 100);
ga_concat(&ga, (char_u *)"function(");
if (fname != NULL)
{
// When using uf_name prepend "g:" for a global function.
if (pt != NULL && pt->pt_name == NULL && fname[0] == '\''
&& vim_isupper(fname[1]))
{
ga_concat(&ga, (char_u *)"'g:");
ga_concat(&ga, fname + 1);
}
else
ga_concat(&ga, fname);
vim_free(fname);
}
if (pt != NULL && pt->pt_argc > 0)
{
ga_concat(&ga, (char_u *)", [");
for (i = 0; i < pt->pt_argc; ++i)
{
if (i > 0)
ga_concat(&ga, (char_u *)", ");
ga_concat(&ga, tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
vim_free(tf);
}
ga_concat(&ga, (char_u *)"]");
}
if (pt != NULL && pt->pt_dict != NULL)
{
typval_T dtv;
ga_concat(&ga, (char_u *)", ");
dtv.v_type = VAR_DICT;
dtv.vval.v_dict = pt->pt_dict;
ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
vim_free(tf);
}
// terminate with ')' and a NUL
ga_concat_len(&ga, (char_u *)")", 2);
*tofree = ga.ga_data;
r = *tofree;
return r;
}
/*
* Return a textual representation of a List in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* When "copyID" is not zero replace recursive lists with "...". When
* "restore_copyID" is FALSE, repeated items in lists are replaced with "...".
* May return NULL.
*/
static char_u *
list_tv2string(
typval_T *tv,
char_u **tofree,
int copyID,
int restore_copyID)
{
char_u *r = NULL;
if (tv->vval.v_list == NULL)
{
// NULL list is equivalent to empty list.
*tofree = NULL;
r = (char_u *)"[]";
}
else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID
&& tv->vval.v_list->lv_len > 0)
{
*tofree = NULL;
r = (char_u *)"[...]";
}
else
{
int old_copyID = tv->vval.v_list->lv_copyID;
tv->vval.v_list->lv_copyID = copyID;
*tofree = list2string(tv, copyID, restore_copyID);
if (restore_copyID)
tv->vval.v_list->lv_copyID = old_copyID;
r = *tofree;
}
return r;
}
/*
* Return a textual representation of a Dict in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* When "copyID" is not zero replace recursive dicts with "...".
* When "restore_copyID" is FALSE, repeated items in the dictionary are
* replaced with "...". May return NULL.
*/
static char_u *
dict_tv2string(
typval_T *tv,
char_u **tofree,
int copyID,
int restore_copyID)
{
char_u *r = NULL;
if (tv->vval.v_dict == NULL)
{
// NULL dict is equivalent to empty dict.
*tofree = NULL;
r = (char_u *)"{}";
}
else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID
&& tv->vval.v_dict->dv_hashtab.ht_used != 0)
{
*tofree = NULL;
r = (char_u *)"{...}";
}
else
{
int old_copyID = tv->vval.v_dict->dv_copyID;
tv->vval.v_dict->dv_copyID = copyID;
*tofree = dict2string(tv, copyID, restore_copyID);
if (restore_copyID)
tv->vval.v_dict->dv_copyID = old_copyID;
r = *tofree;
}
return r;
}
/*
* Return a textual representation of a job or a channel in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* "numbuf" is used for a number.
* When "composite_val" is FALSE, put quotes around strings as "string()",
* otherwise does not put quotes around strings.
* May return NULL.
*/
static char_u *
jobchan_tv2string(
typval_T *tv,
char_u **tofree,
char_u *numbuf,
int composite_val)
{
char_u *r = NULL;
#ifdef FEAT_JOB_CHANNEL
*tofree = NULL;
if (tv->v_type == VAR_JOB)
r = job_to_string_buf(tv, numbuf);
else
r = channel_to_string_buf(tv, numbuf);
if (composite_val)
{
*tofree = string_quote(r, FALSE);
r = *tofree;
}
#endif
return r;
}
/*
* Return a textual representation of a class in "tv".
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* May return NULL.
*/
static char_u *
class_tv2string(typval_T *tv, char_u **tofree)
{
char_u *r = NULL;
class_T *cl = tv->vval.v_class;
char *s = "class";
if (cl != NULL && IS_INTERFACE(cl))
s = "interface";
else if (cl != NULL && IS_ENUM(cl))
s = "enum";
size_t len = STRLEN(s) + 1 +
(cl == NULL ? 9 : STRLEN(cl->class_name)) + 1;
r = *tofree = alloc(len);
vim_snprintf((char *)r, len, "%s %s", s,
cl == NULL ? "[unknown]" : (char *)cl->class_name);
return r;
}
/*
* Return a string with the string representation of a variable.
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* "numbuf" is used for a number.
* When "copyID" is not NULL replace recursive lists and dicts with "...".
* When "copyID" is not zero replace recursive lists and dicts with "...".
* When both "echo_style" and "composite_val" are FALSE, put quotes around
* strings as "string()", otherwise does not put quotes around strings, as
* ":echo" displays values.
@@ -6492,155 +6773,27 @@ echo_string_core(
switch (tv->v_type)
{
case VAR_STRING:
if (echo_style && !composite_val)
{
*tofree = NULL;
r = tv->vval.v_string;
if (r == NULL)
r = (char_u *)"";
}
else
{
*tofree = string_quote(tv->vval.v_string, FALSE);
r = *tofree;
}
r = string_tv2string(tv, tofree, echo_style, composite_val);
break;
case VAR_FUNC:
{
char_u buf[MAX_FUNC_NAME_LEN];
if (echo_style)
{
r = tv->vval.v_string == NULL ? (char_u *)"function()"
: make_ufunc_name_readable(tv->vval.v_string,
buf, MAX_FUNC_NAME_LEN);
if (r == buf)
{
r = vim_strsave(buf);
*tofree = r;
}
else
*tofree = NULL;
}
else
{
*tofree = string_quote(tv->vval.v_string == NULL ? NULL
: make_ufunc_name_readable(
tv->vval.v_string, buf, MAX_FUNC_NAME_LEN),
TRUE);
r = *tofree;
}
}
r = func_tv2string(tv, tofree, echo_style);
break;
case VAR_PARTIAL:
{
partial_T *pt = tv->vval.v_partial;
char_u *fname = string_quote(pt == NULL ? NULL
: partial_name(pt), FALSE);
garray_T ga;
int i;
char_u *tf;
ga_init2(&ga, 1, 100);
ga_concat(&ga, (char_u *)"function(");
if (fname != NULL)
{
// When using uf_name prepend "g:" for a global function.
if (pt != NULL && pt->pt_name == NULL && fname[0] == '\''
&& vim_isupper(fname[1]))
{
ga_concat(&ga, (char_u *)"'g:");
ga_concat(&ga, fname + 1);
}
else
ga_concat(&ga, fname);
vim_free(fname);
}
if (pt != NULL && pt->pt_argc > 0)
{
ga_concat(&ga, (char_u *)", [");
for (i = 0; i < pt->pt_argc; ++i)
{
if (i > 0)
ga_concat(&ga, (char_u *)", ");
ga_concat(&ga,
tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
vim_free(tf);
}
ga_concat(&ga, (char_u *)"]");
}
if (pt != NULL && pt->pt_dict != NULL)
{
typval_T dtv;
ga_concat(&ga, (char_u *)", ");
dtv.v_type = VAR_DICT;
dtv.vval.v_dict = pt->pt_dict;
ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
vim_free(tf);
}
// terminate with ')' and a NUL
ga_concat_len(&ga, (char_u *)")", 2);
*tofree = ga.ga_data;
r = *tofree;
break;
}
r = partial_tv2string(tv, tofree, numbuf, copyID);
break;
case VAR_BLOB:
r = blob2string(tv->vval.v_blob, tofree, numbuf);
break;
case VAR_LIST:
if (tv->vval.v_list == NULL)
{
// NULL list is equivalent to empty list.
*tofree = NULL;
r = (char_u *)"[]";
}
else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID
&& tv->vval.v_list->lv_len > 0)
{
*tofree = NULL;
r = (char_u *)"[...]";
}
else
{
int old_copyID = tv->vval.v_list->lv_copyID;
tv->vval.v_list->lv_copyID = copyID;
*tofree = list2string(tv, copyID, restore_copyID);
if (restore_copyID)
tv->vval.v_list->lv_copyID = old_copyID;
r = *tofree;
}
r = list_tv2string(tv, tofree, copyID, restore_copyID);
break;
case VAR_DICT:
if (tv->vval.v_dict == NULL)
{
// NULL dict is equivalent to empty dict.
*tofree = NULL;
r = (char_u *)"{}";
}
else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID
&& tv->vval.v_dict->dv_hashtab.ht_used != 0)
{
*tofree = NULL;
r = (char_u *)"{...}";
}
else
{
int old_copyID = tv->vval.v_dict->dv_copyID;
tv->vval.v_dict->dv_copyID = copyID;
*tofree = dict2string(tv, copyID, restore_copyID);
if (restore_copyID)
tv->vval.v_dict->dv_copyID = old_copyID;
r = *tofree;
}
r = dict_tv2string(tv, tofree, copyID, restore_copyID);
break;
case VAR_NUMBER:
@@ -6653,16 +6806,7 @@ echo_string_core(
case VAR_JOB:
case VAR_CHANNEL:
#ifdef FEAT_JOB_CHANNEL
*tofree = NULL;
r = tv->v_type == VAR_JOB ? job_to_string_buf(tv, numbuf)
: channel_to_string_buf(tv, numbuf);
if (composite_val)
{
*tofree = string_quote(r, FALSE);
r = *tofree;
}
#endif
r = jobchan_tv2string(tv, tofree, numbuf, composite_val);
break;
case VAR_INSTR:
@@ -6671,23 +6815,11 @@ echo_string_core(
break;
case VAR_CLASS:
{
class_T *cl = tv->vval.v_class;
char *s = "class";
if (cl != NULL && IS_INTERFACE(cl))
s = "interface";
else if (cl != NULL && IS_ENUM(cl))
s = "enum";
size_t len = STRLEN(s) + 1 +
(cl == NULL ? 9 : STRLEN(cl->class_name)) + 1;
r = *tofree = alloc(len);
vim_snprintf((char *)r, len, "%s %s", s,
cl == NULL ? "[unknown]" : (char *)cl->class_name);
}
r = class_tv2string(tv, tofree);
break;
case VAR_OBJECT:
*tofree = r = object_string(tv->vval.v_object, numbuf, copyID,
*tofree = r = object2string(tv->vval.v_object, numbuf, copyID,
echo_style, restore_copyID,
composite_val);
break;
@@ -6722,7 +6854,7 @@ echo_string_core(
* If the memory is allocated "tofree" is set to it, otherwise NULL.
* "numbuf" is used for a number.
* Does not put quotes around strings, as ":echo" displays values.
* When "copyID" is not NULL replace recursive lists and dicts with "...".
* When "copyID" is not zero replace recursive lists and dicts with "...".
* May return NULL.
*/
char_u *