comparison src/vim9script.c @ 27043:15f40772e10a v8.2.4050

patch 8.2.4050: Vim9: need to prefix every item in an autoload script Commit: https://github.com/vim/vim/commit/dc4451df61a6aa12a0661817b7094fb32f09e11d Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 9 21:36:37 2022 +0000 patch 8.2.4050: Vim9: need to prefix every item in an autoload script Problem: Vim9: need to prefix every item in an autoload script. Solution: First step in supporting "vim9script autoload" and "import autoload".
author Bram Moolenaar <Bram@vim.org>
date Sun, 09 Jan 2022 22:45:04 +0100
parents c8809b8d19de
children 140102677c12
comparison
equal deleted inserted replaced
27042:8fc14d120630 27043:15f40772e10a
66 ex_vim9script(exarg_T *eap UNUSED) 66 ex_vim9script(exarg_T *eap UNUSED)
67 { 67 {
68 #ifdef FEAT_EVAL 68 #ifdef FEAT_EVAL
69 int sid = current_sctx.sc_sid; 69 int sid = current_sctx.sc_sid;
70 scriptitem_T *si; 70 scriptitem_T *si;
71 int found_noclear = FALSE;
72 int found_autoload = FALSE;
73 char_u *p;
71 74
72 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 75 if (!getline_equal(eap->getline, eap->cookie, getsourceline))
73 { 76 {
74 emsg(_(e_vim9script_can_only_be_used_in_script)); 77 emsg(_(e_vim9script_can_only_be_used_in_script));
75 return; 78 return;
79 if (si->sn_state == SN_STATE_HAD_COMMAND) 82 if (si->sn_state == SN_STATE_HAD_COMMAND)
80 { 83 {
81 emsg(_(e_vim9script_must_be_first_command_in_script)); 84 emsg(_(e_vim9script_must_be_first_command_in_script));
82 return; 85 return;
83 } 86 }
84 if (!IS_WHITE_OR_NUL(*eap->arg) && STRCMP(eap->arg, "noclear") != 0) 87
85 { 88 for (p = eap->arg; !IS_WHITE_OR_NUL(*p); p = skipwhite(skiptowhite(p)))
86 semsg(_(e_invalid_argument_str), eap->arg); 89 {
87 return; 90 if (STRNCMP(p, "noclear", 7) == 0 && IS_WHITE_OR_NUL(p[7]))
88 } 91 {
89 if (si->sn_state == SN_STATE_RELOAD && IS_WHITE_OR_NUL(*eap->arg)) 92 if (found_noclear)
93 {
94 semsg(_(e_duplicate_argument_str), p);
95 return;
96 }
97 found_noclear = TRUE;
98 }
99 else if (STRNCMP(p, "autoload", 8) == 0 && IS_WHITE_OR_NUL(p[8]))
100 {
101 if (found_autoload)
102 {
103 semsg(_(e_duplicate_argument_str), p);
104 return;
105 }
106 found_autoload = TRUE;
107 if (script_name_after_autoload(si) == NULL)
108 {
109 emsg(_(e_using_autoload_in_script_not_under_autoload_directory));
110 return;
111 }
112 }
113 else
114 {
115 semsg(_(e_invalid_argument_str), eap->arg);
116 return;
117 }
118 }
119
120 if (si->sn_state == SN_STATE_RELOAD && !found_noclear)
90 { 121 {
91 hashtab_T *ht = &SCRIPT_VARS(sid); 122 hashtab_T *ht = &SCRIPT_VARS(sid);
92 123
93 // Reloading a script without the "noclear" argument: clear 124 // Reloading a script without the "noclear" argument: clear
94 // script-local variables and functions. 125 // script-local variables and functions.
98 129
99 // old imports and script variables are no longer valid 130 // old imports and script variables are no longer valid
100 free_imports_and_script_vars(sid); 131 free_imports_and_script_vars(sid);
101 } 132 }
102 si->sn_state = SN_STATE_HAD_COMMAND; 133 si->sn_state = SN_STATE_HAD_COMMAND;
134
135 si->sn_is_autoload = found_autoload;
103 136
104 current_sctx.sc_version = SCRIPT_VERSION_VIM9; 137 current_sctx.sc_version = SCRIPT_VERSION_VIM9;
105 si->sn_version = SCRIPT_VERSION_VIM9; 138 si->sn_version = SCRIPT_VERSION_VIM9;
106 139
107 if (STRCMP(p_cpo, CPO_VIM) != 0) 140 if (STRCMP(p_cpo, CPO_VIM) != 0)
364 evalarg_T *evalarg, 397 evalarg_T *evalarg,
365 void *cctx) 398 void *cctx)
366 { 399 {
367 char_u *arg = arg_start; 400 char_u *arg = arg_start;
368 char_u *nextarg; 401 char_u *nextarg;
402 int is_autoload = FALSE;
369 int getnext; 403 int getnext;
370 char_u *expr_end; 404 char_u *expr_end;
371 int ret = FAIL; 405 int ret = FAIL;
372 char_u *as_name = NULL; 406 char_u *as_name = NULL;
373 typval_T tv; 407 typval_T tv;
375 int res; 409 int res;
376 long start_lnum = SOURCING_LNUM; 410 long start_lnum = SOURCING_LNUM;
377 garray_T *import_gap; 411 garray_T *import_gap;
378 int i; 412 int i;
379 413
414 if (STRNCMP(arg, "autoload", 8) == 0 && VIM_ISWHITE(arg[8]))
415 {
416 is_autoload = TRUE;
417 arg = skipwhite(arg + 8);
418 }
419
380 // The name of the file can be an expression, which must evaluate to a 420 // The name of the file can be an expression, which must evaluate to a
381 // string. 421 // string.
382 ret = eval0_retarg(arg, &tv, NULL, evalarg, &expr_end); 422 ret = eval0_retarg(arg, &tv, NULL, evalarg, &expr_end);
383 if (ret == FAIL) 423 if (ret == FAIL)
384 goto erret; 424 goto erret;
400 size_t len; 440 size_t len;
401 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); 441 scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
402 char_u *tail = gettail(si->sn_name); 442 char_u *tail = gettail(si->sn_name);
403 char_u *from_name; 443 char_u *from_name;
404 444
405 // Relative to current script: "./name.vim", "../../name.vim". 445 if (is_autoload)
406 len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; 446 res = FAIL;
447 else
448 {
449
450 // Relative to current script: "./name.vim", "../../name.vim".
451 len = STRLEN(si->sn_name) - STRLEN(tail)
452 + STRLEN(tv.vval.v_string) + 2;
453 from_name = alloc((int)len);
454 if (from_name == NULL)
455 goto erret;
456 vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
457 add_pathsep(from_name);
458 STRCAT(from_name, tv.vval.v_string);
459 simplify_filename(from_name);
460
461 res = do_source(from_name, FALSE, DOSO_NONE, &sid);
462 vim_free(from_name);
463 }
464 }
465 else if (mch_isFullName(tv.vval.v_string))
466 {
467 // Absolute path: "/tmp/name.vim"
468 if (is_autoload)
469 res = FAIL;
470 else
471 res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid);
472 }
473 else if (is_autoload)
474 {
475 size_t len = 9 + STRLEN(tv.vval.v_string) + 1;
476 char_u *from_name;
477
478 // Find file in "autoload" subdirs in 'runtimepath'.
407 from_name = alloc((int)len); 479 from_name = alloc((int)len);
408 if (from_name == NULL) 480 if (from_name == NULL)
409 goto erret; 481 goto erret;
410 vim_strncpy(from_name, si->sn_name, tail - si->sn_name); 482 vim_snprintf((char *)from_name, len, "autoload/%s", tv.vval.v_string);
411 add_pathsep(from_name); 483 // we need a scriptitem without loading the script
412 STRCAT(from_name, tv.vval.v_string); 484 sid = find_script_in_rtp(from_name);
413 simplify_filename(from_name);
414
415 res = do_source(from_name, FALSE, DOSO_NONE, &sid);
416 vim_free(from_name); 485 vim_free(from_name);
417 } 486 res = SCRIPT_ID_VALID(sid) ? OK : FAIL;
418 else if (mch_isFullName(tv.vval.v_string))
419 {
420 // Absolute path: "/tmp/name.vim"
421 res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid);
422 } 487 }
423 else 488 else
424 { 489 {
425 size_t len = 7 + STRLEN(tv.vval.v_string) + 1; 490 size_t len = 7 + STRLEN(tv.vval.v_string) + 1;
426 char_u *from_name; 491 char_u *from_name;
427 492
428 // Find file in "import" subdirs in 'runtimepath'. 493 // Find file in "import" subdirs in 'runtimepath'.
429 from_name = alloc((int)len); 494 from_name = alloc((int)len);
430 if (from_name == NULL) 495 if (from_name == NULL)
431 {
432 goto erret; 496 goto erret;
433 }
434 vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string); 497 vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string);
435 res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid); 498 res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid);
436 vim_free(from_name); 499 vim_free(from_name);
437 } 500 }
438 501
439 if (res == FAIL || sid <= 0) 502 if (res == FAIL || sid <= 0)
440 { 503 {
441 semsg(_(e_could_not_import_str), tv.vval.v_string); 504 semsg(_(is_autoload && sid <= 0
505 ? e_autoload_import_cannot_use_absolute_or_relative_path
506 : e_could_not_import_str), tv.vval.v_string);
442 goto erret; 507 goto erret;
443 } 508 }
444 509
445 import_gap = gap != NULL ? gap : &SCRIPT_ITEM(import_sid)->sn_imports; 510 import_gap = gap != NULL ? gap : &SCRIPT_ITEM(import_sid)->sn_imports;
446 for (i = 0; i < import_gap->ga_len; ++i) 511 for (i = 0; i < import_gap->ga_len; ++i)
449 514
450 if (import->imp_sid == sid) 515 if (import->imp_sid == sid)
451 { 516 {
452 if (import->imp_flags & IMP_FLAGS_RELOAD) 517 if (import->imp_flags & IMP_FLAGS_RELOAD)
453 { 518 {
454 // encountering same script first ime on a reload is OK 519 // encountering same script first time on a reload is OK
455 import->imp_flags &= ~IMP_FLAGS_RELOAD; 520 import->imp_flags &= ~IMP_FLAGS_RELOAD;
456 break; 521 break;
457 } 522 }
458 semsg(_(e_cannot_import_same_script_twice_str), tv.vval.v_string); 523 semsg(_(e_cannot_import_same_script_twice_str), tv.vval.v_string);
459 goto erret; 524 goto erret;
511 576
512 if (as_name != NULL) 577 if (as_name != NULL)
513 { 578 {
514 imported_T *imported; 579 imported_T *imported;
515 580
516 imported = find_imported(as_name, STRLEN(as_name), cctx); 581 imported = find_imported(as_name, FALSE, STRLEN(as_name), cctx);
517 if (imported != NULL && imported->imp_sid != sid) 582 if (imported != NULL && imported->imp_sid != sid)
518 { 583 {
519 semsg(_(e_name_already_defined_str), as_name); 584 semsg(_(e_name_already_defined_str), as_name);
520 goto erret; 585 goto erret;
521 } 586 }
527 if (imported == NULL) 592 if (imported == NULL)
528 goto erret; 593 goto erret;
529 imported->imp_name = as_name; 594 imported->imp_name = as_name;
530 as_name = NULL; 595 as_name = NULL;
531 imported->imp_sid = sid; 596 imported->imp_sid = sid;
597 if (is_autoload)
598 imported->imp_flags = IMP_FLAGS_AUTOLOAD;
532 } 599 }
533 600
534 erret: 601 erret:
535 clear_tv(&tv); 602 clear_tv(&tv);
536 vim_free(as_name); 603 vim_free(as_name);