aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2023-06-16 12:37:07 +0200
committerMattias EngdegÄrd2023-06-16 12:58:57 +0200
commit8657afac774f36777d0fdd368e0bec64beca22ae (patch)
treebe7d0013e0a0732b2849c14f920d8c98a2fafb58 /src
parentf2aae8b879baa4986b69af7ee54fe4eb987b99d6 (diff)
downloademacs-8657afac774f36777d0fdd368e0bec64beca22ae.tar.gz
emacs-8657afac774f36777d0fdd368e0bec64beca22ae.zip
Correct conversion of strings to tree-sitter query syntax
The treesitter query syntax for string literals differs from that of Elisp so we cannot just use the Lisp printer (bug#64017). * src/treesit.c (treesit_query_string_string): New function. (Ftreesit_pattern_expand): Use it. * test/src/treesit-tests.el (treesit-query-api): Add test case.
Diffstat (limited to 'src')
-rw-r--r--src/treesit.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/treesit.c b/src/treesit.c
index 0af0e347694..680e510b74d 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -2299,6 +2299,47 @@ produced by tree-sitter. */)
2299 2299
2300/*** Query functions */ 2300/*** Query functions */
2301 2301
2302/* Convert a Lisp string to its printed representation in the tree-sitter
2303 query syntax. */
2304static Lisp_Object
2305treesit_query_string_string (Lisp_Object str)
2306{
2307 /* Strings in the treesit query syntax only have the escapes
2308 \n \r \t \0 and any other escaped char stands for that character.
2309 Literal LF, NUL and " are forbidden. */
2310 ptrdiff_t nbytes = SBYTES (str);
2311 ptrdiff_t escapes = 0;
2312 for (ptrdiff_t i = 0; i < nbytes; i++)
2313 {
2314 unsigned char c = SREF (str, i);
2315 escapes += (c == '\0' || c == '\n' || c == '\r' || c == '\t' || c == '"');
2316 }
2317 ptrdiff_t nchars = SCHARS (str);
2318 ptrdiff_t extra = escapes + 2; /* backslashes + double quotes */
2319 Lisp_Object dst = (STRING_MULTIBYTE (str)
2320 ? make_uninit_multibyte_string (nchars + extra,
2321 nbytes + extra)
2322 : make_uninit_string (nbytes + extra));
2323 unsigned char *d = SDATA (dst);
2324 *d++ = '"';
2325 for (ptrdiff_t i = 0; i < nbytes; i++)
2326 {
2327 unsigned char c = SREF (str, i);
2328 switch (c)
2329 {
2330 case '\0': *d++ = '\\'; *d++ = '0'; break;
2331 case '\n': *d++ = '\\'; *d++ = 'n'; break;
2332 case '\r': *d++ = '\\'; *d++ = 'r'; break;
2333 case '\t': *d++ = '\\'; *d++ = 't'; break;
2334 case '"': *d++ = '\\'; *d++ = '"'; break;
2335 default: *d++ = c; break;
2336 }
2337 }
2338 *d++ = '"';
2339 eassert (d == SDATA (dst) + SBYTES (dst));
2340 return dst;
2341}
2342
2302DEFUN ("treesit-pattern-expand", 2343DEFUN ("treesit-pattern-expand",
2303 Ftreesit_pattern_expand, 2344 Ftreesit_pattern_expand,
2304 Streesit_pattern_expand, 1, 1, 0, 2345 Streesit_pattern_expand, 1, 1, 0,
@@ -2349,6 +2390,9 @@ See Info node `(elisp)Pattern Matching' for detailed explanation. */)
2349 pattern, 2390 pattern,
2350 Vtreesit_str_space), 2391 Vtreesit_str_space),
2351 closing_delimiter); 2392 closing_delimiter);
2393 if (STRINGP (pattern))
2394 return treesit_query_string_string (pattern);
2395
2352 return Fprin1_to_string (pattern, Qnil, Qt); 2396 return Fprin1_to_string (pattern, Qnil, Qt);
2353} 2397}
2354 2398