This is a version that omitted the '_' support.
(Please see #4491 (comment))
If Bram really want to '_', let's discuss again at #4491 :D
ย ย https://github.com/vim/vim/pull/4634
โ
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
@k-takata commented on this pull request.
> @@ -769,6 +769,7 @@ a user-defined command. This can only happen when changing the source code, when adding a command in src/ex_cmds.h. The lookup table then needs to be updated, by running: > make cmdidxs +<
This should be removed.
Please also check my comments in this commit: aiya000@e4e7d0d.
@mattn commented on this pull request.
> +'${}' into a string. For example
+>
+ " Embeding literals
+ echo $'I have ${10}' " I have 10
+ echo $'I ${{"love": 1000}}' " I {'love': 1000}
+<
+These are same as
+>
+ echo 'I have ' . string(10)
+ echo 'I ' . string({"love": 1000})
+<
+'string-interpolations' helps you to write complex string. Also _ is same as
+$. This is useful to avoid confusing a lot of repeated $.
+>
+ echo $'${10} ${20} ${30}' " unreadable
+ echo _'${10} ${20} ${30}' " readable!
should be removed.
> +'string-interpolations' helps you to write complex string. Also _ is same as
+$. This is useful to avoid confusing a lot of repeated $.
+>
+ echo $'${10} ${20} ${30}' " unreadable
+ echo _'${10} ${20} ${30}' " readable!
+<
+Other rules:
+>
+ " Only strings or literal strings doesn't apply string()
+ echo $'I am a ${"vim"}' " I am a vim
+ " not: I am a 'vim'
+ echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
ditto
> + echo $'${10} ${20} ${30}' " unreadable
+ echo _'${10} ${20} ${30}' " readable!
+<
+Other rules:
+>
+ " Only strings or literal strings doesn't apply string()
+ echo $'I am a ${"vim"}' " I am a vim
+ " not: I am a 'vim'
+ echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
+
+ " In template-string, you can write '$' as $$
+ echo _'$$' " $
ditto
> +Other rules:
+>
+ " Only strings or literal strings doesn't apply string()
+ echo $'I am a ${"vim"}' " I am a vim
+ " not: I am a 'vim'
+ echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
+
+ " In template-string, you can write '$' as $$
+ echo _'$$' " $
+
+ " Escaping in template (non-literal) string
+ echo _"${10} \\ \"" " 10 \ "
ditto
> + echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
+
+ " In template-string, you can write '$' as $$
+ echo _'$$' " $
+
+ " Escaping in template (non-literal) string
+ echo _"${10} \\ \"" " 10 \ "
+<
+Exceptions:
+>
+ echo $'${var' " E1000: Unterminated template literal: $'${var'
+ echo _'... $ ...' " E1000: Missing variable name on a $: $'... $ ...'
ditto
In src/eval.c:
> @@ -4569,6 +4613,39 @@ eval7(
case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
break;
+ /*
+ * Template string constant: $"string ${var}", $'literal string ${var}', _"", _''
Template string constant: $"string ${var}"
In src/eval.c:
> + }
+
+ return FALSE;
+}
+
+/*
+ * NOTICE: x[-1] must be readable.
+ */
+ static int
+is_closing_double_quote(char_u* x)
+{
+ return (x[0] == '"') && (x[-1] != '\\');
+}
+
+/*
+ * Allocate a variable for a $'string ${var} $x', $"", _'', _"" constant.
Allocate a variable for a $'string ${var} $x', $"" constant.
In src/eval.c:
> +
+/*
+ * Parse a `template` string into a (non template) string.
+ *
+ * The result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+parse_template(
+ char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u* template,
+ int evaluate)
+{
+ const size_t QUOTES_LENGTH = 3; // a number of strlen("$''"), strlen("$\"\""), strlen("_''"), or strlen("_\"\"")
// a number of strlen("$''"), strlen("$""")
@aiya000 commented on this pull request.
> @@ -769,6 +769,7 @@ a user-defined command. This can only happen when changing the source code, when adding a command in src/ex_cmds.h. The lookup table then needs to be updated, by running: > make cmdidxs +<
done ๐
โ
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.![]()
@aiya000 commented on this pull request.
> +'${}' into a string. For example
+>
+ " Embeding literals
+ echo $'I have ${10}' " I have 10
+ echo $'I ${{"love": 1000}}' " I {'love': 1000}
+<
+These are same as
+>
+ echo 'I have ' . string(10)
+ echo 'I ' . string({"love": 1000})
+<
+'string-interpolations' helps you to write complex string. Also _ is same as
+$. This is useful to avoid confusing a lot of repeated $.
+>
+ echo $'${10} ${20} ${30}' " unreadable
+ echo _'${10} ${20} ${30}' " readable!
done ๐
โ
You are receiving this because you are subscribed to this thread.
> +'string-interpolations' helps you to write complex string. Also _ is same as
+$. This is useful to avoid confusing a lot of repeated $.
+>
+ echo $'${10} ${20} ${30}' " unreadable
+ echo _'${10} ${20} ${30}' " readable!
+<
+Other rules:
+>
+ " Only strings or literal strings doesn't apply string()
+ echo $'I am a ${"vim"}' " I am a vim
+ " not: I am a 'vim'
+ echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
I replaced to $'x' ๐
โ
You are receiving this because you are subscribed to this thread.
> + echo $'${10} ${20} ${30}' " unreadable
+ echo _'${10} ${20} ${30}' " readable!
+<
+Other rules:
+>
+ " Only strings or literal strings doesn't apply string()
+ echo $'I am a ${"vim"}' " I am a vim
+ " not: I am a 'vim'
+ echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
+
+ " In template-string, you can write '$' as $$
+ echo _'$$' " $
I replaced to $'$$', thanks :D
> +Other rules:
+>
+ " Only strings or literal strings doesn't apply string()
+ echo $'I am a ${"vim"}' " I am a vim
+ " not: I am a 'vim'
+ echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
+
+ " In template-string, you can write '$' as $$
+ echo _'$$' " $
+
+ " Escaping in template (non-literal) string
+ echo _"${10} \\ \"" " 10 \ "
I replaced to
echo $"${10} \\ \"" " 10 \ "
> + echo $"I am a ${'vim'}" " I am a vim
+
+ " Only unscoped variables can omit {}
+ let x = 10
+ echo _'$x' " 10
+
+ " In template-string, you can write '$' as $$
+ echo _'$$' " $
+
+ " Escaping in template (non-literal) string
+ echo _"${10} \\ \"" " 10 \ "
+<
+Exceptions:
+>
+ echo $'${var' " E1000: Unterminated template literal: $'${var'
+ echo _'... $ ...' " E1000: Missing variable name on a $: $'... $ ...'
Thanks!
echo $'... $ ...' " E1000: Missing variable name on a $: $'... $ ...'
@aiya000 commented on this pull request.
In src/eval.c:
> @@ -4569,6 +4613,39 @@ eval7(
case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
break;
+ /*
+ * Template string constant: $"string ${var}", $'literal string ${var}', _"", _''
* Template string constant: $"string ${var}", $'literal string ${var}'
๐
โ
You are receiving this because you are subscribed to this thread.
> + }
+
+ return FALSE;
+}
+
+/*
+ * NOTICE: x[-1] must be readable.
+ */
+ static int
+is_closing_double_quote(char_u* x)
+{
+ return (x[0] == '"') && (x[-1] != '\\');
+}
+
+/*
+ * Allocate a variable for a $'string ${var} $x', $"", _'', _"" constant.
๐
* Allocate a variable for a $'string ${var} $x' constant.
โ
You are receiving this because you are subscribed to this thread.
> +
+/*
+ * Parse a `template` string into a (non template) string.
+ *
+ * The result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+parse_template(
+ char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u* template,
+ int evaluate)
+{
+ const size_t QUOTES_LENGTH = 3; // a number of strlen("$''"), strlen("$\"\""), strlen("_''"), or strlen("_\"\"")
๐
const size_t QUOTES_LENGTH = 3; // a number of strlen("$''") (or strlen("$\"\""))
โ
You are receiving this because you are subscribed to this thread.
@k-takata commented on this pull request.
> @@ -1331,6 +1331,49 @@ to be doubled. These two commands are equivalent: > if a =~ '\s*' +template-string *template-string* *E1000* +--------------- + +$"string" template string *expr-$quote* +$'string' template literal string *expr-$'* + +Note that either single quotes or double quotes are used. + +These strings supports 'string-interpolations'. That embeds any expressions by
s/supports/support/
In src/eval.c:
> + char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u **arg,
+ typval_T *rettv,
+ int evaluate)
+{
+ char_u* string;
+ char_u* origin_string;
+ char_u* template;
+
+ // NOTE: At here, "${}" of "${" "expr" "}", that called 'embedding', and "expr" called 'embedded'.
+
+ template = read_template_string(is_closing_quote, *arg);
+ if (template == NULL) {
This { should be the next line. (or should be removed, because this block is only one line.)
In src/eval.c:
> +/*
+ * Get a string between a opening "$'" and a closing "'" (or "$\"" and "\""),
+ * and check a taken string is not missing a closing "'".
+ *
+ * This result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+read_template_string(int (*is_closing_quote)(char_u*), char_u* source)
+{
+ const size_t OPENING_QUOTE_LENGTH = 2; // "$'"
+ char_u* p;
+ char_u* template;
+ size_t template_length;
+
+ for (p = source + OPENING_QUOTE_LENGTH; !(is_closing_quote(p) || *p == NUL); MB_PTR_ADV(p)) {}
+ if (*p == NUL) {
This { should be the next line.
In src/eval.c:
> + }
+ else if (to_source[0] == '$') // Do embed to $var
+ {
+ size_t embedding_start_length = embedded[finished]->is_embedded_literal
+ ? LITERAL_EMBEDDING_START_LENGTH
+ : VAR_EMBEDDING_START_LENGTH;
+ size_t embedding_close_length = embedded[finished]->is_embedded_literal
+ ? 1
+ : 0;
+
+ memcpy(to_dest, embedded[finished]->stringified, STRLEN(embedded[finished]->stringified));
+ mb_ptr_adv_nth(&to_source, embedding_start_length + STRLEN(embedded[finished]->expr) + embedding_close_length - 1); // 1 is increased by for's effect later!
+ mb_ptr_adv_nth(&to_dest, STRLEN(embedded[finished]->stringified) - 1); // same
+ ++finished;
+ continue;
+ } else if (MB_PTR2LEN(to_source) > 1) {
else should be the next line.
{ should be the next of the else line.
In src/eval.c:
> +
+ // If entered with the closing quote of a template string into this function
+ if (whole_string[1] == NUL)
+ {
+ semsg(_("E1000: Unterminated template literal: %s"), template);
+ return -1;
+ }
+
+ p = whole_string + 1; // Skip the head of '"' (or '\'')
+ is_closing_quote = expect_literal_string
+ ? is_closing_single_quote
+ : is_closing_double_quote;
+
+ for (; !is_closing_quote(p); MB_PTR_ADV(p))
+ {
+ switch (*p) {
This { should be the next line.
Can we use if (*p == NUL)?
In src/eval.c:
> + * Does the taken char match /[a-zA-Z_]/ ?
+ */
+ static int
+is_sneak_case_char(char_u x)
+{
+ const char_u SNEAK_CHARS[] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '_'
+ };
+ const size_t SNEAK_CHARS_SIZE = 27;
+ size_t i;
+
+ for (i = 0; i < SNEAK_CHARS_SIZE; ++i)
+ {
+ if (SNEAK_CHARS[i] == x) {
This { should be the next line.
@k-takata commented on this pull request.
In src/eval.c:
> @@ -203,6 +203,29 @@ static struct vimvar
{VV_NAME("versionlong", VAR_NUMBER), VV_RO},
};
+/*
+ * A type for template literals.
+ * e.g. "${some_literal}", "$var".
+ */
+typedef struct {
+ /*
+ * Does this have a form "${some_literal}" ?
+ * (if this is FALSE, this have a form "$var".)
+ */
+ int is_embedded_literal;
+
+ /*
+ * "some_literal" or "var" or else.
+ */
+ char_u* expr;
โฌ๏ธ Suggested change
- char_u* expr; + char_u *expr;
* should be prepended before a variable. Same for other declarations.
โ
You are receiving this because you are subscribed to this thread.
@aiya000 commented on this pull request.
> @@ -1331,6 +1331,49 @@ to be doubled. These two commands are equivalent: > if a =~ '\s*' +template-string *template-string* *E1000* +--------------- + +$"string" template string *expr-$quote* +$'string' template literal string *expr-$'* + +Note that either single quotes or double quotes are used. + +These strings supports 'string-interpolations'. That embeds any expressions by
๐
โ
You are receiving this because you are subscribed to this thread.
@aiya000 commented on this pull request.
In src/eval.c:
> + }
+ else if (to_source[0] == '$') // Do embed to $var
+ {
+ size_t embedding_start_length = embedded[finished]->is_embedded_literal
+ ? LITERAL_EMBEDDING_START_LENGTH
+ : VAR_EMBEDDING_START_LENGTH;
+ size_t embedding_close_length = embedded[finished]->is_embedded_literal
+ ? 1
+ : 0;
+
+ memcpy(to_dest, embedded[finished]->stringified, STRLEN(embedded[finished]->stringified));
+ mb_ptr_adv_nth(&to_source, embedding_start_length + STRLEN(embedded[finished]->expr) + embedding_close_length - 1); // 1 is increased by for's effect later!
+ mb_ptr_adv_nth(&to_dest, STRLEN(embedded[finished]->stringified) - 1); // same
+ ++finished;
+ continue;
+ } else if (MB_PTR2LEN(to_source) > 1) {
๐
โ
You are receiving this because you are subscribed to this thread.
> +
+ // If entered with the closing quote of a template string into this function
+ if (whole_string[1] == NUL)
+ {
+ semsg(_("E1000: Unterminated template literal: %s"), template);
+ return -1;
+ }
+
+ p = whole_string + 1; // Skip the head of '"' (or '\'')
+ is_closing_quote = expect_literal_string
+ ? is_closing_single_quote
+ : is_closing_double_quote;
+
+ for (; !is_closing_quote(p); MB_PTR_ADV(p))
+ {
+ switch (*p) {
!!
I fixed!
> @@ -203,6 +203,29 @@ static struct vimvar
{VV_NAME("versionlong", VAR_NUMBER), VV_RO},
};
+/*
+ * A type for template literals.
+ * e.g. "${some_literal}", "$var".
+ */
+typedef struct {
+ /*
+ * Does this have a form "${some_literal}" ?
+ * (if this is FALSE, this have a form "$var".)
+ */
+ int is_embedded_literal;
+
+ /*
+ * "some_literal" or "var" or else.
+ */
+ char_u* expr;
Thanks a lot!
I did :%s/\v([a-zA-Z_]+)\* ([a-zA-Z_])/\1 *\2/gc :D
> + char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u **arg,
+ typval_T *rettv,
+ int evaluate)
+{
+ char_u* string;
+ char_u* origin_string;
+ char_u* template;
+
+ // NOTE: At here, "${}" of "${" "expr" "}", that called 'embedding', and "expr" called 'embedded'.
+
+ template = read_template_string(is_closing_quote, *arg);
+ if (template == NULL) {
๐ ๐
I did /\v\) \{/ and f s<CR> all!
โ
You are receiving this because you are subscribed to this thread.
> +/*
+ * Get a string between a opening "$'" and a closing "'" (or "$\"" and "\""),
+ * and check a taken string is not missing a closing "'".
+ *
+ * This result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+read_template_string(int (*is_closing_quote)(char_u*), char_u* source)
+{
+ const size_t OPENING_QUOTE_LENGTH = 2; // "$'"
+ char_u* p;
+ char_u* template;
+ size_t template_length;
+
+ for (p = source + OPENING_QUOTE_LENGTH; !(is_closing_quote(p) || *p == NUL); MB_PTR_ADV(p)) {}
+ if (*p == NUL) {
๐
โ
You are receiving this because you are subscribed to this thread.
> + * Does the taken char match /[a-zA-Z_]/ ?
+ */
+ static int
+is_sneak_case_char(char_u x)
+{
+ const char_u SNEAK_CHARS[] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '_'
+ };
+ const size_t SNEAK_CHARS_SIZE = 27;
+ size_t i;
+
+ for (i = 0; i < SNEAK_CHARS_SIZE; ++i)
+ {
+ if (SNEAK_CHARS[i] == x) {
Appveyor says
gcc -c -I. -Iproto -DWIN32 -DWINVER=0x0600 -D_WIN32_WINNT=0x0600 -DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -DHAVE_GETTEXT -DHAVE_LOCALE_H -DDYNAMIC_GETTEXT -DFEAT_CSCOPE -DFEAT_MBYTE_IME -DDYNAMIC_IME -DDYNAMIC_ICONV -pipe -march=i686 -Wall -O2 iscygpty.c -o obji686/iscygpty.o -U_WIN32_WINNT -D_WIN32_WINNT=0x0600 -DUSE_DYNFILEID -DENABLE_STUB_IMPL
gcc -I. -Iproto -DWIN32 -DWINVER=0x0600 -D_WIN32_WINNT=0x0600 -DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -DHAVE_GETTEXT -DHAVE_LOCALE_H -DDYNAMIC_GETTEXT -DFEAT_CSCOPE -DFEAT_MBYTE_IME -DDYNAMIC_IME -DDYNAMIC_ICONV -pipe -march=i686 -Wall -O2 -s -municode -o vim.exe obji686/arabic.o obji686/autocmd.o obji686/beval.o obji686/blob.o obji686/blowfish.o obji686/buffer.o obji686/change.o obji686/charset.o obji686/crypt.o obji686/crypt_zip.o obji686/debugger.o obji686/dict.o obji686/diff.o obji686/digraph.o obji686/edit.o obji686/eval.o obji686/evalfunc.o obji686/ex_cmds.o obji686/ex_cmds2.o obji686/ex_docmd.o obji686/ex_eval.o obji686/ex_getln.o obji686/fileio.o obji686/findfile.o obji686/fold.o obji686/getchar.o obji686/hardcopy.o obji686/hashtab.o obji686/indent.o obji686/insexpand.o obji686/json.o obji686/list.o obji686/main.o obji686/mark.o obji686/memfile.o obji686/memline.o obji686/menu.o obji686/message.o obji686/misc1.o obji686/misc2.o obji686/move.o obji686/mbyte.o obji686/normal.o obji686/ops.o obji686/option.o obji686/os_mswin.o obji686/os_win32.o obji686/pathdef.o obji686/popupmnu.o obji686/popupwin.o obji686/quickfix.o obji686/regexp.o obji686/screen.o obji686/search.o obji686/sha256.o obji686/sign.o obji686/spell.o obji686/spellfile.o obji686/syntax.o obji686/tag.o obji686/term.o obji686/textprop.o obji686/ui.o obji686/undo.o obji686/usercmd.o obji686/userfunc.o obji686/version.o obji686/winclip.o obji686/window.o obji686/os_w32exe.o obji686/vimrc.o obji686/if_cscope.o obji686/xdiffi.o obji686/xemit.o obji686/xprepare.o obji686/xutils.o obji686/xhistogram.o obji686/xpatience.o obji686/iscygpty.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomdlg32 -lcomctl32 -lnetapi32 -lversion -lole32 -luuid
obji686/popupwin.o:popupwin.c:(.text+0x2ee1): undefined reference to `ch_log'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe: *** [Make_cyg_ming.mak:1022: vim.exe] Error 1
But I don't have any ideas about this.
Is this my problem? X)
โ
You are receiving this because you are subscribed to this thread.
@k-takata commented on this pull request.
In src/eval.c:
> @@ -6115,10 +6119,9 @@ read_next_string_length(char_u* whole_string, int expect_literal_string, char_u*
for (; !is_closing_quote(p); MB_PTR_ADV(p))
{
- switch (*p) {
- case NUL:
- semsg(_("E115: Missing quote: %s"), template);
- return -1;
+ if (*p == NUL) {
{ should be the next line.
โ
But I don't have any ideas about this.
Is this my problem? X)
Maybe no.
ref: https://groups.google.com/d/msg/vim_dev/zGy72qFwvYc/ZN9tZUpKBAAJ
@aiya000 commented on this pull request.
In src/eval.c:
> @@ -6115,10 +6119,9 @@ read_next_string_length(char_u* whole_string, int expect_literal_string, char_u*
for (; !is_closing_quote(p); MB_PTR_ADV(p))
{
- switch (*p) {
- case NUL:
- semsg(_("E115: Missing quote: %s"), template);
- return -1;
+ if (*p == NUL) {
Oh my hands... lol
Thanks!
@k-takata commented on this pull request.
In src/eval.c:
> + *
+ * The result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+parse_template(
+ char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u *template,
+ int evaluate)
+{
+ const size_t QUOTES_LENGTH = 3; // a number of strlen("$''") (or strlen("$\"\""))
+ const size_t OPNEING_QUOTE_LENGTH = 2; // a number of strlen("$'")
+ size_t i;
+ char_u* result;
Could you move this * before the variable name?
(And there are similar cases remaining.)
In src/eval.c:
> + */
+ static char_u*
+parse_template(
+ char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u *template,
+ int evaluate)
+{
+ const size_t QUOTES_LENGTH = 3; // a number of strlen("$''") (or strlen("$\"\""))
+ const size_t OPNEING_QUOTE_LENGTH = 2; // a number of strlen("$'")
+ size_t i;
+ char_u* result;
+ size_t embedded_size; // a size of embedded
+ embedded_t** embedded = read_embedded(template, &embedded_size);
Same for this **.
In src/eval.c:
> + */
+ static void
+escape_quotes(char_u** source, char_u* (*fix_quote)(char_u))
+{
+ char_u* result = alloc_terminated(STRLEN(*source));
+ char_u* to_dest = result;
+ char_u* to_source = *source;
+
+ for (; *to_source != NUL; MB_PTR_ADV(to_dest), MB_PTR_ADV(to_source))
+ {
+ char_u* fixed = fix_quote(*to_source);
+ size_t fixed_size = STRLEN(fixed);
+
+ memcpy(to_dest, fixed, fixed_size);
+ free(fixed);
+ mb_ptr_adv_nth(&to_dest, fixed_size - 1); // 1 incresed by next for's effect
s/incresed/increased/
In src/eval.c:
> +
+/*
+ * Get a string between a opening "$'" and a closing "'" (or "$\"" and "\""),
+ * and check a taken string is not missing a closing "'".
+ *
+ * This result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+read_template_string(int (*is_closing_quote)(char_u*), char_u *source)
+{
+ const size_t OPENING_QUOTE_LENGTH = 2; // "$'"
+ char_u* p;
+ char_u* template;
+ size_t template_length;
+
+ for (p = source + OPENING_QUOTE_LENGTH; !(is_closing_quote(p) || *p == NUL); MB_PTR_ADV(p));
It might be better to move the last ; to the next line (with indent) to emphasize that this is an empty loop.
In src/eval.c:
> + */
+ static char_u*
+alloc_terminated(size_t size)
+{
+ char_u* p = alloc(size + 1);
+ p[size] = NUL;
+ return p;
+}
+
+/*
+ * Allocate a `embedded_t*`.
+ */
+ static embedded_t*
+new_embedded(int is_embedded_literal, char_u *expr, size_t expr_size)
+{
+ embedded_t *x = alloc(sizeof(embedded_t));
ALLOC_ONE can be used.
s/alloc(sizeof(embedded_t))/ALLOC_ONE(embedded_t)/
In src/eval.c:
> + if (template == NULL)
+ {
+ return FAIL;
+ }
+
+ // Parse a template string into a plain string
+ string = parse_template(enclose, disclose, fix_quote, is_closing_quote, template, evaluate);
+ if (string == NULL)
+ {
+ return FAIL;
+ }
+
+ // Eval the result (non template) string
+ origin_string = string;
+ eval1(&string, rettv, evaluate);
+ free(origin_string);
vim_free() should be better than free() in Vim's source code.
In src/eval.c:
> +
+ // Allow to refer -1 at later
+ if (p[0] == '$' && p[1] != '$')
+ {
+ ++count;
+ }
+ MB_PTR_ADV(p);
+
+ for (; *p != NUL; MB_PTR_ADV(p))
+ {
+ // Is `p` an independent '$'? e.g. "x$x". not "$$x" nor "x$$".
+ if (p[-1] != '$' && p[0] == '$' && p[1] != '$')
+ {
+ ++count;
+ ++p; // a part of "$"
+ continue; // a part of "{" (incresing)
s/incresing/increasing/
In src/eval.c:
> +is_closing_double_quote(char_u *x)
+{
+ return (x[0] == '"') && (x[-1] != '\\');
+}
+
+/*
+ * Allocate a variable for a $'string ${var} $x' constant.
+ * Return OK or FAIL.
+ *
+ * enclose() encloses a content by '' (or "").
+ * fix_quote() fixes quotes ' to ''. this fixes a problem that string() stringifies {"x": 10} to {'x': 10}, ["a", "b"] to ['a', 'b'].
+ * is_closing_quote() checks a char is ' (or ").
+ */
+ static int
+get_template_string_tv(
+ char_u* (*enclose)(char_u*),
s/char_u* (/char_u *(/
In src/eval.c:
> + for (; !is_closing_quote(p); MB_PTR_ADV(p))
+ {
+ if (*p == NUL)
+ {
+ semsg(_("E115: Missing quote: %s"), template);
+ return -1;
+ }
+ }
+
+ return p - whole_string;
+}
+
+/*
+ * Get a first "expr" of "${" "expr" "}" from `whole_embedding`.
+ *
+ * whole_embedding starts with "${": e.g. "${10}`", "${var} Hello :D`".
The two backquotes can be removed?
In src/eval.c:
> + break;
+ }
+ case NUL:
+ semsg(_("E1000: Unterminated template literal: %s"), template);
+ return NULL; // failed! a closing "}" couldn't be found.
+ }
+ ++expr_length;
+ }
+
+ return new_embedded(TRUE, embedded_start, expr_length);
+}
+
+/*
+ * Get a first "var" of "$" "var" from `whole_embedding`.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
The backquote can be removed?
In src/eval.c:
> + static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_char(expr_start[0]))
+ {
+ semsg(_("E1000: Missing variable name on a $: %s"), template);
+ return NULL;
+ }
+
+ for (p = expr_start + 1; *p != NUL; MB_PTR_ADV(p))
+ {
+ if (!is_sneak_case_char(*p))
Does this mean that numbers cannot be used for a variable name?
> @@ -283,7 +283,8 @@ NEW_TESTS = \ test_xxd \ test_alot_latin \ test_alot_utf8 \ - test_alot + test_alot \ + test_string_interpolation
This list should be in the alphabetical order (except the last test_alot tests).
@aiya000 commented on this pull request.
In src/eval.c:
> + *
+ * The result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+parse_template(
+ char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u *template,
+ int evaluate)
+{
+ const size_t QUOTES_LENGTH = 3; // a number of strlen("$''") (or strlen("$\"\""))
+ const size_t OPNEING_QUOTE_LENGTH = 2; // a number of strlen("$'")
+ size_t i;
+ char_u* result;
Sorry, I didn't replace it.
I'll :%s/\v([a-zA-Z_]+)(\*+)([ ])([\(a-zA-Z_])/\1\3\2\4/gc!
> + */
+ static char_u*
+parse_template(
+ char_u* (*enclose)(char_u*),
+ char_u* (*disclose)(char_u*),
+ char_u* (*fix_quote)(char_u),
+ int (*is_closing_quote)(char_u*),
+ char_u *template,
+ int evaluate)
+{
+ const size_t QUOTES_LENGTH = 3; // a number of strlen("$''") (or strlen("$\"\""))
+ const size_t OPNEING_QUOTE_LENGTH = 2; // a number of strlen("$'")
+ size_t i;
+ char_u* result;
+ size_t embedded_size; // a size of embedded
+ embedded_t** embedded = read_embedded(template, &embedded_size);
I'll %s/\v([a-zA-Z_]+)(\*+)([ ])([\(a-zA-Z_])/\1\3\2\4/gc ๐
โ
You are receiving this because you are subscribed to this thread.
> + */
+ static void
+escape_quotes(char_u** source, char_u* (*fix_quote)(char_u))
+{
+ char_u* result = alloc_terminated(STRLEN(*source));
+ char_u* to_dest = result;
+ char_u* to_source = *source;
+
+ for (; *to_source != NUL; MB_PTR_ADV(to_dest), MB_PTR_ADV(to_source))
+ {
+ char_u* fixed = fix_quote(*to_source);
+ size_t fixed_size = STRLEN(fixed);
+
+ memcpy(to_dest, fixed, fixed_size);
+ free(fixed);
+ mb_ptr_adv_nth(&to_dest, fixed_size - 1); // 1 incresed by next for's effect
I'll fix ๐
> +
+/*
+ * Get a string between a opening "$'" and a closing "'" (or "$\"" and "\""),
+ * and check a taken string is not missing a closing "'".
+ *
+ * This result MUST BE `free`d later! (if it is not NULL.)
+ */
+ static char_u*
+read_template_string(int (*is_closing_quote)(char_u*), char_u *source)
+{
+ const size_t OPENING_QUOTE_LENGTH = 2; // "$'"
+ char_u* p;
+ char_u* template;
+ size_t template_length;
+
+ for (p = source + OPENING_QUOTE_LENGTH; !(is_closing_quote(p) || *p == NUL); MB_PTR_ADV(p));
I'll do it :D
> + */
+ static char_u*
+alloc_terminated(size_t size)
+{
+ char_u* p = alloc(size + 1);
+ p[size] = NUL;
+ return p;
+}
+
+/*
+ * Allocate a `embedded_t*`.
+ */
+ static embedded_t*
+new_embedded(int is_embedded_literal, char_u *expr, size_t expr_size)
+{
+ embedded_t *x = alloc(sizeof(embedded_t));
๐
โ
You are receiving this because you are subscribed to this thread.
> + if (template == NULL)
+ {
+ return FAIL;
+ }
+
+ // Parse a template string into a plain string
+ string = parse_template(enclose, disclose, fix_quote, is_closing_quote, template, evaluate);
+ if (string == NULL)
+ {
+ return FAIL;
+ }
+
+ // Eval the result (non template) string
+ origin_string = string;
+ eval1(&string, rettv, evaluate);
+ free(origin_string);
Great!
I'll :%s/\<free\>/vim_free/gc for my codes ๐
> +
+ // Allow to refer -1 at later
+ if (p[0] == '$' && p[1] != '$')
+ {
+ ++count;
+ }
+ MB_PTR_ADV(p);
+
+ for (; *p != NUL; MB_PTR_ADV(p))
+ {
+ // Is `p` an independent '$'? e.g. "x$x". not "$$x" nor "x$$".
+ if (p[-1] != '$' && p[0] == '$' && p[1] != '$')
+ {
+ ++count;
+ ++p; // a part of "$"
+ continue; // a part of "{" (incresing)
I'll fix!
> +is_closing_double_quote(char_u *x)
+{
+ return (x[0] == '"') && (x[-1] != '\\');
+}
+
+/*
+ * Allocate a variable for a $'string ${var} $x' constant.
+ * Return OK or FAIL.
+ *
+ * enclose() encloses a content by '' (or "").
+ * fix_quote() fixes quotes ' to ''. this fixes a problem that string() stringifies {"x": 10} to {'x': 10}, ["a", "b"] to ['a', 'b'].
+ * is_closing_quote() checks a char is ' (or ").
+ */
+ static int
+get_template_string_tv(
+ char_u* (*enclose)(char_u*),
๐
โ
You are receiving this because you are subscribed to this thread.
> + for (; !is_closing_quote(p); MB_PTR_ADV(p))
+ {
+ if (*p == NUL)
+ {
+ semsg(_("E115: Missing quote: %s"), template);
+ return -1;
+ }
+ }
+
+ return p - whole_string;
+}
+
+/*
+ * Get a first "expr" of "${" "expr" "}" from `whole_embedding`.
+ *
+ * whole_embedding starts with "${": e.g. "${10}`", "${var} Hello :D`".
I'll :%s/MUST BE freed/MUST BE EXECUTED BY free()/gc, and I'll search via /\v`[a-zA-Z_]``` and remove enclosing !
> + break;
+ }
+ case NUL:
+ semsg(_("E1000: Unterminated template literal: %s"), template);
+ return NULL; // failed! a closing "}" couldn't be found.
+ }
+ ++expr_length;
+ }
+
+ return new_embedded(TRUE, embedded_start, expr_length);
+}
+
+/*
+ * Get a first "var" of "$" "var" from `whole_embedding`.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
๐
โ
You are receiving this because you are subscribed to this thread.
> + static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_char(expr_start[0]))
+ {
+ semsg(_("E1000: Missing variable name on a $: %s"), template);
+ return NULL;
+ }
+
+ for (p = expr_start + 1; *p != NUL; MB_PTR_ADV(p))
+ {
+ if (!is_sneak_case_char(*p))
No! I don't intend x)
I'll add tests, And fix this!
@aiya000 commented on this pull request.
> @@ -283,7 +283,8 @@ NEW_TESTS = \ test_xxd \ test_alot_latin \ test_alot_utf8 \ - test_alot + test_alot \ + test_string_interpolation
I'll fix this ๐
โ
You are receiving this because you are subscribed to this thread.
@k-takata Thanks a lot!
I might resolve problems ๐
โ
You are receiving this because you are subscribed to this thread.
@k-takata commented on this pull request.
In src/eval.c:
> @@ -244,6 +267,28 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); +static int get_template_string_tv(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u **arg, typval_T *rettv, int evaluate); +static char_u* disclose_quote(char_u *quoted);
Please adjust the place of *.
In src/eval.c:
> +is_started_with_quote(char_u *x)
+{
+ return
+ x[0] == '\'' ||
+ x[0] == '"';
+}
+
+/*
+ * This result MUST BE EXECUTED BY free() later!
+ */
+ static char_u*
+disclose_quote(char_u *quoted)
+{
+ const size_t QUOTES_LENGTH = 2; // strlen("''")
+ size_t result_length = STRLEN(quoted) - QUOTES_LENGTH;
+ char_u* result;
ditto
In src/eval.c:
> + vim_free(template);
+
+ return OK;
+}
+
+/*
+ * Get a string between a opening "$'" and a closing "'" (or "$\"" and "\""),
+ * and check a taken string is not missing a closing "'".
+ *
+ * This result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static char_u*
+read_template_string(int (*is_closing_quote)(char_u*), char_u *source)
+{
+ const size_t OPENING_QUOTE_LENGTH = 2; // "$'"
+ char_u* p;
ditto
In src/eval.c:
> +
+/*
+ * Replace ' to ".
+ * this fixes a string() problem that doesn't save string({"x": 10})'s ".
+ * (It is stringified to {'x': 10}.)
+ */
+ static void
+escape_quotes(char_u **source, char_u *(*fix_quote)(char_u))
+{
+ char_u *result = alloc_terminated(STRLEN(*source));
+ char_u *to_dest = result;
+ char_u *to_source = *source;
+
+ for (; *to_source != NUL; MB_PTR_ADV(to_dest), MB_PTR_ADV(to_source))
+ {
+ char_u* fixed = fix_quote(*to_source);
ditto
In src/eval.c:
> + {
+ MB_PTR_ADV(*p);
+ }
+}
+
+/*
+ * Replace all "${...}" of dest by each actual values.
+ * source is a template string.
+ * By `read_embedded()` or else, source must be checked that have no unterminated embedding.
+ */
+ static void
+embed_embedded(int (*is_closing_quote)(char_u*), char_u **dest, char_u *source, embedded_t **embedded, size_t embedded_size)
+{
+ const size_t LITERAL_EMBEDDING_START_LENGTH = 2; // a number of "${"
+ const size_t VAR_EMBEDDING_START_LENGTH = 1; // a number of head "$"
+ char_u* to_dest;
ditto
In src/eval.c:
> +/*
+ * Read all embedded from template,
+ * and check a passed template string is terminated.
+ *
+ * Return got an array of all embedded.
+ *
+ * This result MUST BE EXECUTED BY free() later! (if it is not NUL.)
+ */
+ static embedded_t**
+read_embedded(char_u *template, size_t *embedded_size)
+{
+ const size_t LITERAL_EMBEDDING_START_LENGTH = 2; // a number of "${"
+ const size_t VAR_EMBEDDING_START_LENGTH = 1; // a number of "$"
+ embedded_t **embedded;
+ size_t finished = 0;
+ char_u* p;
ditto
In src/eval.c:
> +
+ return p - whole_string;
+}
+
+/*
+ * Get a first "expr" of "${" "expr" "}" from whole_embedding.
+ *
+ * whole_embedding starts with "${": e.g. "${10}'", "${var} Hello :D'".
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_lit(char_u *whole_embedding, char_u *template)
+{
+ const size_t LITERAL_EMBEDDING_START_LENGTH = 2; // "${"
+ char_u* embedded_start = whole_embedding + LITERAL_EMBEDDING_START_LENGTH;
ditto
In src/eval.c:
> + return new_embedded(TRUE, embedded_start, expr_length);
+}
+
+/*
+ * Get a first "var" of "$" "var" from whole_embedding.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
+ * (like "$x[0]" and "$x.y" only parses the part of "$x".)
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
ditto
> + break;
+ }
+ case NUL:
+ semsg(_("E1000: Unterminated template literal: %s"), template);
+ return NULL; // failed! a closing "}" couldn't be found.
+ }
+ ++expr_length;
+ }
+
+ return new_embedded(TRUE, embedded_start, expr_length);
+}
+
+/*
+ * Get a first "var" of "$" "var" from `whole_embedding`.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
I meant that "$var`" isn't a mistake of "$var"?
> *
- * whole_embedding starts with "${": e.g. "${10}`", "${var} Hello :D`".
+ * whole_embedding starts with "${": e.g. "${10}'", "${var} Hello :D'".
Are the changes of this line really correct?
Shouldn't be "${10}" and "${var} Hello :D"?
> +/*
+ * Get a first "var" of "$" "var" from whole_embedding.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
+ * (like "$x[0]" and "$x.y" only parses the part of "$x".)
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_head_char(expr_start[0]))
I wonder if we really need this function.
Isn't !ASCII_ISALPHA(expr_start[0]) && expr_start[0] != '_' enough?
In src/eval.c:
> + static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_head_char(expr_start[0]))
+ {
+ semsg(_("E1000: Missing variable name on a $: %s"), template);
+ return NULL;
+ }
+
+ for (p = expr_start + 1; *p != NUL; MB_PTR_ADV(p))
+ {
+ if (!is_sneak_case_char(*p))
I wonder if we really need this function.
Isn't !ASCII_ISALNUM(*p) && *p != '_' enough?
@aiya000 commented on this pull request.
In src/eval.c:
> + break;
+ }
+ case NUL:
+ semsg(_("E1000: Unterminated template literal: %s"), template);
+ return NULL; // failed! a closing "}" couldn't be found.
+ }
+ ++expr_length;
+ }
+
+ return new_embedded(TRUE, embedded_start, expr_length);
+}
+
+/*
+ * Get a first "var" of "$" "var" from `whole_embedding`.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
Sorry, my reply was too meaningless x(
"$var` is not intended, but "$var'" is intended.
I replaced to
* whole_embedding starts with "$": e.g. "$var", "$var'", "$v_i_m".
๐
โ
You are receiving this because you are subscribed to this thread.
> @@ -244,6 +267,28 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); +static int get_template_string_tv(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u **arg, typval_T *rettv, int evaluate); +static char_u* disclose_quote(char_u *quoted);
Sorry, what do you mean?
static char_u *disclose_quote(char_u *quoted); ?
> +is_started_with_quote(char_u *x)
+{
+ return
+ x[0] == '\'' ||
+ x[0] == '"';
+}
+
+/*
+ * This result MUST BE EXECUTED BY free() later!
+ */
+ static char_u*
+disclose_quote(char_u *quoted)
+{
+ const size_t QUOTES_LENGTH = 2; // strlen("''")
+ size_t result_length = STRLEN(quoted) - QUOTES_LENGTH;
+ char_u* result;
Oh x(
Fixed ๐
โ
You are receiving this because you are subscribed to this thread.
> + {
+ MB_PTR_ADV(*p);
+ }
+}
+
+/*
+ * Replace all "${...}" of dest by each actual values.
+ * source is a template string.
+ * By `read_embedded()` or else, source must be checked that have no unterminated embedding.
+ */
+ static void
+embed_embedded(int (*is_closing_quote)(char_u*), char_u **dest, char_u *source, embedded_t **embedded, size_t embedded_size)
+{
+ const size_t LITERAL_EMBEDDING_START_LENGTH = 2; // a number of "${"
+ const size_t VAR_EMBEDDING_START_LENGTH = 1; // a number of head "$"
+ char_u* to_dest;
wa!?
Sorry, I failed replacing...
I did :%s/\v([a-zA-Z_]+)(\*+)([ ]+)/\1\3\2/gc again!
> +/*
+ * Read all embedded from template,
+ * and check a passed template string is terminated.
+ *
+ * Return got an array of all embedded.
+ *
+ * This result MUST BE EXECUTED BY free() later! (if it is not NUL.)
+ */
+ static embedded_t**
+read_embedded(char_u *template, size_t *embedded_size)
+{
+ const size_t LITERAL_EMBEDDING_START_LENGTH = 2; // a number of "${"
+ const size_t VAR_EMBEDDING_START_LENGTH = 1; // a number of "$"
+ embedded_t **embedded;
+ size_t finished = 0;
+ char_u* p;
๐
โ
You are receiving this because you are subscribed to this thread.
> +
+ return p - whole_string;
+}
+
+/*
+ * Get a first "expr" of "${" "expr" "}" from whole_embedding.
+ *
+ * whole_embedding starts with "${": e.g. "${10}'", "${var} Hello :D'".
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_lit(char_u *whole_embedding, char_u *template)
+{
+ const size_t LITERAL_EMBEDDING_START_LENGTH = 2; // "${"
+ char_u* embedded_start = whole_embedding + LITERAL_EMBEDDING_START_LENGTH;
> + return new_embedded(TRUE, embedded_start, expr_length);
+}
+
+/*
+ * Get a first "var" of "$" "var" from whole_embedding.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
+ * (like "$x[0]" and "$x.y" only parses the part of "$x".)
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
> *
- * whole_embedding starts with "${": e.g. "${10}`", "${var} Hello :D`".
+ * whole_embedding starts with "${": e.g. "${10}'", "${var} Hello :D'".
Yes, I intended this :D
e.g. $'hello ${var} and ${10}' passes "${var} and ${10}' and "${10}' to this function!
> + vim_free(template);
+
+ return OK;
+}
+
+/*
+ * Get a string between a opening "$'" and a closing "'" (or "$\"" and "\""),
+ * and check a taken string is not missing a closing "'".
+ *
+ * This result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static char_u*
+read_template_string(int (*is_closing_quote)(char_u*), char_u *source)
+{
+ const size_t OPENING_QUOTE_LENGTH = 2; // "$'"
+ char_u* p;
๐
โ
You are receiving this because you are subscribed to this thread.
> +
+/*
+ * Replace ' to ".
+ * this fixes a string() problem that doesn't save string({"x": 10})'s ".
+ * (It is stringified to {'x': 10}.)
+ */
+ static void
+escape_quotes(char_u **source, char_u *(*fix_quote)(char_u))
+{
+ char_u *result = alloc_terminated(STRLEN(*source));
+ char_u *to_dest = result;
+ char_u *to_source = *source;
+
+ for (; *to_source != NUL; MB_PTR_ADV(to_dest), MB_PTR_ADV(to_source))
+ {
+ char_u* fixed = fix_quote(*to_source);
@k-takata commented on this pull request.
In src/eval.c:
> @@ -244,6 +267,28 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); +static int get_template_string_tv(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u **arg, typval_T *rettv, int evaluate); +static char_u* disclose_quote(char_u *quoted);
yes
@aiya000 commented on this pull request.
In src/eval.c:
> +/*
+ * Get a first "var" of "$" "var" from whole_embedding.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
+ * (like "$x[0]" and "$x.y" only parses the part of "$x".)
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_head_char(expr_start[0]))
In my opinion, it allows "0aaa" and else (cases starts with [0-9]),
and doesn't allow _name (cases starts with _).
( Sorry if this is wrong x( )
But I want to allow only cases of [a-zA-Z_][a-zA-Z0-9_]+.
๐
โ
You are receiving this because you are subscribed to this thread.
@aiya000 commented on this pull request.
In src/eval.c:
> +/*
+ * Get a first "var" of "$" "var" from whole_embedding.
+ *
+ * whole_embedding starts with "$": e.g. "$var`", "$v_i_m".
+ * (like "$x[0]" and "$x.y" only parses the part of "$x".)
+ *
+ * The result MUST BE EXECUTED BY free() later! (if it is not NULL.)
+ */
+ static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_head_char(expr_start[0]))
Sorry, I understood. this is not needed!
I used ASCII_ISALPHA instead of this function!
> + static embedded_t*
+read_next_embedded_var(char_u *whole_embedding, char_u *template)
+{
+ const size_t NUM_LAST_NON_SNEAK_CHAR = 1;
+ char_u* expr_start = whole_embedding + 1; // skip a head '$'
+ char_u* p;
+
+ if (!is_sneak_case_head_char(expr_start[0]))
+ {
+ semsg(_("E1000: Missing variable name on a $: %s"), template);
+ return NULL;
+ }
+
+ for (p = expr_start + 1; *p != NUL; MB_PTR_ADV(p))
+ {
+ if (!is_sneak_case_char(*p))
Exactly xD
I fixed!
> @@ -244,6 +267,28 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); +static int get_template_string_tv(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u **arg, typval_T *rettv, int evaluate); +static char_u* disclose_quote(char_u *quoted);
Thanks!
I fixed!
@k-takata Thanks ๐
I might fixed again :D
โ
You are receiving this because you are subscribed to this thread.
Merging #4634 into master will decrease coverage by
0.16%.
The diff coverage is1.32%.
@@ Coverage Diff @@ ## master #4634 +/- ## ========================================== - Coverage 81.33% 81.17% -0.17% ========================================== Files 111 111 Lines 144972 145278 +306 ========================================== + Hits 117918 117923 +5 - Misses 27054 27355 +301
| Impacted Files | Coverage ฮ | |
|---|---|---|
| src/eval.c | 81.44% <1.32%> (-5.07%) |
โฌ๏ธ |
| src/gui_gtk_x11.c | 57.96% <0%> (-0.15%) |
โฌ๏ธ |
| src/ex_cmds2.c | 88.29% <0%> (-0.12%) |
โฌ๏ธ |
| src/gui.c | 63.73% <0%> (-0.06%) |
โฌ๏ธ |
| src/term.c | 79.14% <0%> (-0.06%) |
โฌ๏ธ |
| src/channel.c | 83.91% <0%> (-0.04%) |
โฌ๏ธ |
| src/normal.c | 80.79% <0%> (-0.01%) |
โฌ๏ธ |
| src/version.c | 91.89% <0%> (รธ) |
โฌ๏ธ |
| src/popupwin.c | 94.55% <0%> (+0.01%) |
โฌ๏ธ |
| ... and 3 more |
Continue to review full report at Codecov.
Legend - Click here to learn more
ฮ = absolute <relative> (impact),รธ = not affected,? = missing data
Powered by Codecov. Last update 7ba343e...a375ec8. Read the comment docs.
According to the result of codecov, it seems that your test is not executed on CI.
You also need to add
source test_string_interpolation.vim
in src/testdir/test_alot.vim (or add test_string_interpolation.res in the NEW_TESTS_RES variable in src/testdir/Make_all.mak).
@k-takata commented on this pull request.
In src/testdir/test_string_interpolation.vim:
> @@ -0,0 +1,123 @@
+" Test for string-interpolations $'${x} ${y.z}'
+
+scriptencoding utf-8
+
+func Test_string_interpolation()
+ call s:basic()
+ call s:appendix()
+ call s:illformed()
+endfunc
+
+func s:basic() abort
It might be better to make this function global. E.g. Test_string_interpolation_basic.
If it is global, you can run a specific test. See:
https://github.com/vim/vim/blob/e28cfb28126c07abd9e9ba04e36b3789433201b6/src/testdir/runtest.vim#L5-L7
In src/testdir/test_string_interpolation.vim:
> + let F = {x -> x}
+ call assert_equal(string(F), $'${F}')
+
+ " Partial
+ call assert_equal(
+ \ string(function("has_key", [{"x": 10}])),
+ \ $'${function("has_key", [{"x": 10}])}'
+ \ )
+
+ " echo
+ echo $'${10}'
+ " let
+ let x = $'${10}'
+endfunc
+
+func s:appendix() abort
ditto
In src/testdir/test_string_interpolation.vim:
> +
+ " Escape '}'
+ call assert_equal("}", $'${"}"}')
+
+ " Independent '$'
+ call assert_equal('$', $'$$')
+
+ " Multi byte string
+ call assert_equal('ใใใซใกใฏ Vim', $'ใใใซใกใฏ ${"Vim"}')
+
+ " Double quoted
+ call assert_equal("10 \\ \"", $"${10} \\ \"")
+endfunc
+
+" These should be an exception, should not be a 'Segmentation fault'.
+func s:illformed() abort
ditto
In src/testdir/test_string_interpolation.vim:
> @@ -0,0 +1,123 @@
+" Test for string-interpolations $'${x} ${y.z}'
+
+scriptencoding utf-8
+
+func Test_string_interpolation()
This function is not needed, if you make all the static functions global.
โ
You are receiving this because you are subscribed to this thread.
@aiya000 commented on this pull request.
In src/testdir/test_string_interpolation.vim:
> @@ -0,0 +1,123 @@
+" Test for string-interpolations $'${x} ${y.z}'
+
+scriptencoding utf-8
+
+func Test_string_interpolation()
+ call s:basic()
+ call s:appendix()
+ call s:illformed()
+endfunc
+
+func s:basic() abort
I'll add it ๐
> +
+ " Escape '}'
+ call assert_equal("}", $'${"}"}')
+
+ " Independent '$'
+ call assert_equal('$', $'$$')
+
+ " Multi byte string
+ call assert_equal('ใใใซใกใฏ Vim', $'ใใใซใกใฏ ${"Vim"}')
+
+ " Double quoted
+ call assert_equal("10 \\ \"", $"${10} \\ \"")
+endfunc
+
+" These should be an exception, should not be a 'Segmentation fault'.
+func s:illformed() abort
> @@ -0,0 +1,123 @@
+" Test for string-interpolations $'${x} ${y.z}'
+
+scriptencoding utf-8
+
+func Test_string_interpolation()
func Test_string_interpolation()
call s:basic()
call s:appendix()
call s:illformed()
endfunc
> + let F = {x -> x}
+ call assert_equal(string(F), $'${F}')
+
+ " Partial
+ call assert_equal(
+ \ string(function("has_key", [{"x": 10}])),
+ \ $'${function("has_key", [{"x": 10}])}'
+ \ )
+
+ " echo
+ echo $'${10}'
+ " let
+ let x = $'${10}'
+endfunc
+
+func s:appendix() abort
๐
โ
You are receiving this because you are subscribed to this thread.
@aiya000 pushed 7 commits.
โ
You are receiving this because you are subscribed to this thread.
@k-takata Sorry, Now I'm working to fix problems.
Please wait for re-checking ๐
โ
You are receiving this because you are subscribed to this thread.
Closed #4634.
Reopened #4634.
Sorry, accidentally I closed this x(
I reopened!
According to the result of codecov, it seems that your test is not executed on CI.
You also need to addsource test_string_interpolation.vim
in src/testdir/test_alot.vim (or add test_string_interpolation.res in the NEW_TESTS_RES variable in src/testdir/Make_all.mak).
Thanks! I added! (as test_template_string.vim. please see below ๐)
I made these commits!
For detail:
โ๏ธ
These renames test_string_interpolation to test_template_string,
then adds it to Make_all.mak.
โ๏ธ
mattn tell me a sensitive case ($'${}').
This adds it as a test, then fixes it.
Also adds a help.
โ๏ธ Adds a minimum test
+ call assert_equal('10 and me', $'$x and me')
โ๏ธ Suddenly, I met two test failing after test_string_interpolation renamed to test_template_string.
This first is ๐
From test_template_string.vim:
Executed Test_template_string_appendix() in 0.000358 seconds
Executed Test_template_string_basic() in 0.000271 seconds
Executed Test_template_string_illformed() in 0.000232 seconds
Executed abort in 0.000279 seconds
Executed abort in 0.000279 seconds
Executed abort in 0.000328 seconds
Executed 6 tests in 1.008782 seconds
3 FAILED:
Found errors in abort:
Caught exception in abort: Vim(call):E107: Missing parentheses: abort @ function RunTheTest, line 40
Found errors in abort:
Caught exception in abort: Vim(call):E107: Missing parentheses: abort @ function RunTheTest, line 40
Found errors in abort:
Caught exception in abort: Vim(call):E107: Missing parentheses: abort @ function RunTheTest, line 40
make: *** [Makefile:78: test_template_string] Error 1
This commit fixes it.
โ๏ธ The rest one is ๐
Found errors in Test_template_string_basic():
function RunTheTest[40]..Test_template_string_basic line 3: Expected 'function(''function'')' but got 'function(''function'')ct\x01\x01'
This commit fixes it!
Thanks ๐
@k-takata
Sorry for your waiting.
I might fix mentioned terms!
Please check again ๐
โ
You are receiving this because you are subscribed to this thread.
wa!? test failure!?
@k-takata Hi, thanks for your waiting :D
I did
VALGRIND = valgrind --tool=memcheck --leak-check=yes --num-callers=25 --log-file=valgrind.$* --track-origins=yes
The 'current status' has a lot of 'possibly lost'.
But in my opinion, these are not my get_template_string_tv()'s memory leaks.
...Is this right?
I might completely fix problems!
I'll git-squash all commits if it is truth and if needed.
Thanks ๐
โ
You are receiving this because you are subscribed to this thread.
@k-takata commented on this pull request.
In src/eval.c:
> @@ -244,6 +267,28 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); +static int get_template_string_tv(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), int (*should_be_escaped)(char_u), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u **arg, typval_T *rettv, int evaluate); +static int is_single_quote(char_u x); +static int nothing_to_escape(char_u); +static char_u *disclose_quote(char_u *quoted); +static int is_started_with_quote(char_u *x); +static void mb_ptr_adv_nth(char_u **p, size_t n); +static char_u *read_template_string(int (*is_closing_quote)(char_u*), char_u *source); +static char_u *enclose_by_single_quote(char_u *content); +static char_u *enclose_by_double_quote(char_u *content); +static int is_closing_single_quote(char_u *x); +static int is_closing_double_quote(char_u *x); +static char_u *duplicate_single_quote(char_u x); +static char_u *dont_fix(char_u x); +static char_u* parse_template(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), int (*should_be_escaped)(char_u), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u *template, int evaluate);
s/char_u* /char */
In src/eval.c:
> + {
+ ++count;
+ ++p; // a part of "$"
+ continue; // a part of "{" (increasing)
+ }
+ }
+
+ return count;
+}
+
+/*
+ * Allocate `size + 1` memory,
+ * also set the last and all to NUL.
+ */
+ static char_u*
+alloc_terminated(size_t size)
Is this function really needed?
Isn't this the same as (char_u*)alloc_clear(size + 1)?
In src/testdir/test_template_string.vim:
> + call assert_equal("10 \\ \"", $"${10} \\ \"")
+endfunc
+
+" These should be an exception, should not be a 'Segmentation fault'.
+func Test_template_string_illformed()
+ try
+ let _ = $'missing closing quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
+ " Good
+ endtry
+
+ try
+ let _ = $"missing closing double quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
s/E115/E115:
In src/testdir/test_template_string.vim:
> + catch /^Vim(let):E1000: Empty template literal/
+ " Good
+ endtry
+
+ try
+ let _ = $'I have ${nothing}'
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E121: Undefined variable: nothing$/
+ " Good
+ endtry
+
+ try
+ " syntax error in a embedding
+ let _ = $'missing closing of ${function(}'
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E119/
s/E119/E119:
In src/testdir/test_template_string.vim:
> + " Independent '$'
+ call assert_equal('$', $'$$')
+
+ " Multi byte string
+ call assert_equal('ใใใซใกใฏ Vim', $'ใใใซใกใฏ ${"Vim"}')
+
+ " Double quoted
+ call assert_equal("10 \\ \"", $"${10} \\ \"")
+endfunc
+
+" These should be an exception, should not be a 'Segmentation fault'.
+func Test_template_string_illformed()
+ try
+ let _ = $'missing closing quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
s/E115/E115:
In src/testdir/test_template_string.vim:
> + call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
+ " Good
+ endtry
+
+ try
+ let _ = $"missing closing double quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
+ " Good
+ endtry
+
+ try
+ let _ = $'$10'
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E1000: Missing variable name/
Error messages can be translated. This will fail when the language is not English.
@aiya000 commented on this pull request.
In src/eval.c:
> @@ -244,6 +267,28 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); +static int get_template_string_tv(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), int (*should_be_escaped)(char_u), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u **arg, typval_T *rettv, int evaluate); +static int is_single_quote(char_u x); +static int nothing_to_escape(char_u); +static char_u *disclose_quote(char_u *quoted); +static int is_started_with_quote(char_u *x); +static void mb_ptr_adv_nth(char_u **p, size_t n); +static char_u *read_template_string(int (*is_closing_quote)(char_u*), char_u *source); +static char_u *enclose_by_single_quote(char_u *content); +static char_u *enclose_by_double_quote(char_u *content); +static int is_closing_single_quote(char_u *x); +static int is_closing_double_quote(char_u *x); +static char_u *duplicate_single_quote(char_u x); +static char_u *dont_fix(char_u x); +static char_u* parse_template(char_u *(*enclose)(char_u*), char_u *(*disclose)(char_u*), int (*should_be_escaped)(char_u), char_u *(*fix_quote)(char_u), int (*is_closing_quote)(char_u*), char_u *template, int evaluate);
๐
> + {
+ ++count;
+ ++p; // a part of "$"
+ continue; // a part of "{" (increasing)
+ }
+ }
+
+ return count;
+}
+
+/*
+ * Allocate `size + 1` memory,
+ * also set the last and all to NUL.
+ */
+ static char_u*
+alloc_terminated(size_t size)
I'll remove it!
@aiya000 commented on this pull request.
In src/testdir/test_template_string.vim:
> + call assert_equal("10 \\ \"", $"${10} \\ \"")
+endfunc
+
+" These should be an exception, should not be a 'Segmentation fault'.
+func Test_template_string_illformed()
+ try
+ let _ = $'missing closing quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
+ " Good
+ endtry
+
+ try
+ let _ = $"missing closing double quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
๐
โ
You are receiving this because you are subscribed to this thread.
> + catch /^Vim(let):E1000: Empty template literal/
+ " Good
+ endtry
+
+ try
+ let _ = $'I have ${nothing}'
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E121: Undefined variable: nothing$/
+ " Good
+ endtry
+
+ try
+ " syntax error in a embedding
+ let _ = $'missing closing of ${function(}'
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E119/
> + call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
+ " Good
+ endtry
+
+ try
+ let _ = $"missing closing double quote
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E115/
+ " Good
+ endtry
+
+ try
+ let _ = $'$10'
+ call assert_report('Should throw an exception.')
+ catch /^Vim(let):E1000: Missing variable name/
Good! I'll remove messages!
@k-takata Thank you as always ๐
I might apply all review!
โ
You are receiving this because you are subscribed to this thread.
I did git-squash into only 3-commits :)
I love a number 1000.
Please don't change E1000 to any another number if Bram is ok ๐
If Bram doesn't agree this, I agree changing ๐ญ
โ
You are receiving this because you are subscribed to this thread.
I'm afraid that this is too much code for functionality that can also be done with string concatenation. Without adding $"" plugin authors can do the same thing, perhaps not that nice, but it's not worth so much code for something that is just a bit nicer syntax.
โ
You are receiving this because you are subscribed to this thread.
In my opinion, this is useful because $"" style strings is easier to read than concat style .. strings :)
This means (I think) $"" seems nearly to the result text!
@brammool
sorry, I misunderstood your message x(
How much do you expect code volume that you suppose?
(I'll do my best for it๐๏ธ)
โ
You are receiving this because you are subscribed to this thread.