Mercurial > vim
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); |