|
27 | 27 |
|
28 | 28 | #include "vim.h" |
29 | 29 |
|
| 30 | + |
| 31 | +#ifdef FEAT_EVAL |
| 32 | +// Determines how deeply nested %{} blocks will be evaluated in statusline. |
| 33 | +# define MAX_STL_EVAL_DEPTH 100 |
| 34 | +#endif |
| 35 | + |
30 | 36 | static void enter_buffer(buf_T *buf); |
31 | 37 | static void buflist_getfpos(void); |
32 | 38 | static char_u *buflist_match(regmatch_T *rmp, buf_T *buf, int ignore_case); |
@@ -4113,6 +4119,9 @@ build_stl_str_hl( |
4113 | 4119 | int group_end_userhl; |
4114 | 4120 | int group_start_userhl; |
4115 | 4121 | int groupdepth; |
| 4122 | +#ifdef FEAT_EVAL |
| 4123 | + int evaldepth; |
| 4124 | +#endif |
4116 | 4125 | int minwid; |
4117 | 4126 | int maxwid; |
4118 | 4127 | int zeropad; |
@@ -4187,6 +4196,9 @@ build_stl_str_hl( |
4187 | 4196 | byteval = (*mb_ptr2char)(p + wp->w_cursor.col); |
4188 | 4197 |
|
4189 | 4198 | groupdepth = 0; |
| 4199 | +#ifdef FEAT_EVAL |
| 4200 | + evaldepth = 0; |
| 4201 | +#endif |
4190 | 4202 | p = out; |
4191 | 4203 | curitem = 0; |
4192 | 4204 | prevchar_isflag = TRUE; |
@@ -4447,6 +4459,15 @@ build_stl_str_hl( |
4447 | 4459 | curitem++; |
4448 | 4460 | continue; |
4449 | 4461 | } |
| 4462 | +#ifdef FEAT_EVAL |
| 4463 | + // Denotes end of expanded %{} block |
| 4464 | + if (*s == '}' && evaldepth > 0) |
| 4465 | + { |
| 4466 | + s++; |
| 4467 | + evaldepth--; |
| 4468 | + continue; |
| 4469 | + } |
| 4470 | +#endif |
4450 | 4471 | if (vim_strchr(STL_ALL, *s) == NULL) |
4451 | 4472 | { |
4452 | 4473 | s++; |
@@ -4482,16 +4503,27 @@ build_stl_str_hl( |
4482 | 4503 | break; |
4483 | 4504 |
|
4484 | 4505 | case STL_VIM_EXPR: // '{' |
| 4506 | + { |
| 4507 | +#ifdef FEAT_EVAL |
| 4508 | + char_u *block_start = s - 1; |
| 4509 | +#endif |
| 4510 | + int reevaluate = (*s == '%'); |
| 4511 | + |
| 4512 | + if (reevaluate) |
| 4513 | + s++; |
4485 | 4514 | itemisflag = TRUE; |
4486 | 4515 | t = p; |
4487 | | - while (*s != '}' && *s != NUL && p + 1 < out + outlen) |
| 4516 | + while ((*s != '}' || (reevaluate && s[-1] != '%')) |
| 4517 | + && *s != NUL && p + 1 < out + outlen) |
4488 | 4518 | *p++ = *s++; |
4489 | 4519 | if (*s != '}') // missing '}' or out of space |
4490 | 4520 | break; |
4491 | 4521 | s++; |
4492 | | - *p = 0; |
| 4522 | + if (reevaluate) |
| 4523 | + p[-1] = 0; // remove the % at the end of %{% expr %} |
| 4524 | + else |
| 4525 | + *p = 0; |
4493 | 4526 | p = t; |
4494 | | - |
4495 | 4527 | #ifdef FEAT_EVAL |
4496 | 4528 | vim_snprintf((char *)buf_tmp, sizeof(buf_tmp), |
4497 | 4529 | "%d", curbuf->b_fnum); |
@@ -4525,9 +4557,42 @@ build_stl_str_hl( |
4525 | 4557 | itemisflag = FALSE; |
4526 | 4558 | } |
4527 | 4559 | } |
| 4560 | + |
| 4561 | + // If the output of the expression needs to be evaluated |
| 4562 | + // replace the %{} block with the result of evaluation |
| 4563 | + if (reevaluate && str != NULL && *str != 0 |
| 4564 | + && strchr((const char *)str, '%') != NULL |
| 4565 | + && evaldepth < MAX_STL_EVAL_DEPTH) |
| 4566 | + { |
| 4567 | + size_t parsed_usefmt = (size_t)(block_start - usefmt); |
| 4568 | + size_t str_length = strlen((const char *)str); |
| 4569 | + size_t fmt_length = strlen((const char *)s); |
| 4570 | + size_t new_fmt_len = parsed_usefmt |
| 4571 | + + str_length + fmt_length + 3; |
| 4572 | + char_u *new_fmt = (char_u *)alloc(new_fmt_len * sizeof(char_u)); |
| 4573 | + char_u *new_fmt_p = new_fmt; |
| 4574 | + |
| 4575 | + new_fmt_p = (char_u *)memcpy(new_fmt_p, usefmt, parsed_usefmt) |
| 4576 | + + parsed_usefmt; |
| 4577 | + new_fmt_p = (char_u *)memcpy(new_fmt_p , str, str_length) |
| 4578 | + + str_length; |
| 4579 | + new_fmt_p = (char_u *)memcpy(new_fmt_p, "%}", 2) + 2; |
| 4580 | + new_fmt_p = (char_u *)memcpy(new_fmt_p , s, fmt_length) |
| 4581 | + + fmt_length; |
| 4582 | + *new_fmt_p = 0; |
| 4583 | + new_fmt_p = NULL; |
| 4584 | + |
| 4585 | + if (usefmt != fmt) |
| 4586 | + vim_free(usefmt); |
| 4587 | + VIM_CLEAR(str); |
| 4588 | + usefmt = new_fmt; |
| 4589 | + s = usefmt + parsed_usefmt; |
| 4590 | + evaldepth++; |
| 4591 | + continue; |
| 4592 | + } |
4528 | 4593 | #endif |
4529 | 4594 | break; |
4530 | | - |
| 4595 | + } |
4531 | 4596 | case STL_LINE: |
4532 | 4597 | num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) |
4533 | 4598 | ? 0L : (long)(wp->w_cursor.lnum); |
|
0 commit comments