diff 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
line wrap: on
line diff
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -68,6 +68,9 @@ ex_vim9script(exarg_T *eap UNUSED)
 #ifdef FEAT_EVAL
     int		    sid = current_sctx.sc_sid;
     scriptitem_T    *si;
+    int		    found_noclear = FALSE;
+    int		    found_autoload = FALSE;
+    char_u	    *p;
 
     if (!getline_equal(eap->getline, eap->cookie, getsourceline))
     {
@@ -81,12 +84,40 @@ ex_vim9script(exarg_T *eap UNUSED)
 	emsg(_(e_vim9script_must_be_first_command_in_script));
 	return;
     }
-    if (!IS_WHITE_OR_NUL(*eap->arg) && STRCMP(eap->arg, "noclear") != 0)
+
+    for (p = eap->arg; !IS_WHITE_OR_NUL(*p); p = skipwhite(skiptowhite(p)))
     {
-	semsg(_(e_invalid_argument_str), eap->arg);
-	return;
+	if (STRNCMP(p, "noclear", 7) == 0 && IS_WHITE_OR_NUL(p[7]))
+	{
+	    if (found_noclear)
+	    {
+		semsg(_(e_duplicate_argument_str), p);
+		return;
+	    }
+	    found_noclear = TRUE;
+	}
+	else if (STRNCMP(p, "autoload", 8) == 0 && IS_WHITE_OR_NUL(p[8]))
+	{
+	    if (found_autoload)
+	    {
+		semsg(_(e_duplicate_argument_str), p);
+		return;
+	    }
+	    found_autoload = TRUE;
+	    if (script_name_after_autoload(si) == NULL)
+	    {
+		emsg(_(e_using_autoload_in_script_not_under_autoload_directory));
+		return;
+	    }
+	}
+	else
+	{
+	    semsg(_(e_invalid_argument_str), eap->arg);
+	    return;
+	}
     }
-    if (si->sn_state == SN_STATE_RELOAD && IS_WHITE_OR_NUL(*eap->arg))
+
+    if (si->sn_state == SN_STATE_RELOAD && !found_noclear)
     {
 	hashtab_T	*ht = &SCRIPT_VARS(sid);
 
@@ -101,6 +132,8 @@ ex_vim9script(exarg_T *eap UNUSED)
     }
     si->sn_state = SN_STATE_HAD_COMMAND;
 
+    si->sn_is_autoload = found_autoload;
+
     current_sctx.sc_version = SCRIPT_VERSION_VIM9;
     si->sn_version = SCRIPT_VERSION_VIM9;
 
@@ -366,6 +399,7 @@ handle_import(
 {
     char_u	*arg = arg_start;
     char_u	*nextarg;
+    int		is_autoload = FALSE;
     int		getnext;
     char_u	*expr_end;
     int		ret = FAIL;
@@ -377,6 +411,12 @@ handle_import(
     garray_T	*import_gap;
     int		i;
 
+    if (STRNCMP(arg, "autoload", 8) == 0 && VIM_ISWHITE(arg[8]))
+    {
+	is_autoload = TRUE;
+	arg = skipwhite(arg + 8);
+    }
+
     // The name of the file can be an expression, which must evaluate to a
     // string.
     ret = eval0_retarg(arg, &tv, NULL, evalarg, &expr_end);
@@ -402,23 +442,48 @@ handle_import(
 	char_u		*tail = gettail(si->sn_name);
 	char_u		*from_name;
 
-	// Relative to current script: "./name.vim", "../../name.vim".
-	len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2;
-	from_name = alloc((int)len);
-	if (from_name == NULL)
-	    goto erret;
-	vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
-	add_pathsep(from_name);
-	STRCAT(from_name, tv.vval.v_string);
-	simplify_filename(from_name);
+	if (is_autoload)
+	    res = FAIL;
+	else
+	{
 
-	res = do_source(from_name, FALSE, DOSO_NONE, &sid);
-	vim_free(from_name);
+	    // Relative to current script: "./name.vim", "../../name.vim".
+	    len = STRLEN(si->sn_name) - STRLEN(tail)
+						+ STRLEN(tv.vval.v_string) + 2;
+	    from_name = alloc((int)len);
+	    if (from_name == NULL)
+		goto erret;
+	    vim_strncpy(from_name, si->sn_name, tail - si->sn_name);
+	    add_pathsep(from_name);
+	    STRCAT(from_name, tv.vval.v_string);
+	    simplify_filename(from_name);
+
+	    res = do_source(from_name, FALSE, DOSO_NONE, &sid);
+	    vim_free(from_name);
+	}
     }
     else if (mch_isFullName(tv.vval.v_string))
     {
 	// Absolute path: "/tmp/name.vim"
-	res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid);
+	if (is_autoload)
+	    res = FAIL;
+	else
+	    res = do_source(tv.vval.v_string, FALSE, DOSO_NONE, &sid);
+    }
+    else if (is_autoload)
+    {
+	size_t	    len = 9 + STRLEN(tv.vval.v_string) + 1;
+	char_u	    *from_name;
+
+	// Find file in "autoload" subdirs in 'runtimepath'.
+	from_name = alloc((int)len);
+	if (from_name == NULL)
+	    goto erret;
+	vim_snprintf((char *)from_name, len, "autoload/%s", tv.vval.v_string);
+	// we need a scriptitem without loading the script
+	sid = find_script_in_rtp(from_name);
+	vim_free(from_name);
+	res = SCRIPT_ID_VALID(sid) ? OK : FAIL;
     }
     else
     {
@@ -428,9 +493,7 @@ handle_import(
 	// Find file in "import" subdirs in 'runtimepath'.
 	from_name = alloc((int)len);
 	if (from_name == NULL)
-	{
 	    goto erret;
-	}
 	vim_snprintf((char *)from_name, len, "import/%s", tv.vval.v_string);
 	res = source_in_path(p_rtp, from_name, DIP_NOAFTER, &sid);
 	vim_free(from_name);
@@ -438,7 +501,9 @@ handle_import(
 
     if (res == FAIL || sid <= 0)
     {
-	semsg(_(e_could_not_import_str), tv.vval.v_string);
+	semsg(_(is_autoload && sid <= 0
+		    ? e_autoload_import_cannot_use_absolute_or_relative_path
+		    : e_could_not_import_str), tv.vval.v_string);
 	goto erret;
     }
 
@@ -451,7 +516,7 @@ handle_import(
 	{
 	    if (import->imp_flags & IMP_FLAGS_RELOAD)
 	    {
-		// encountering same script first ime on a reload is OK
+		// encountering same script first time on a reload is OK
 		import->imp_flags &= ~IMP_FLAGS_RELOAD;
 		break;
 	    }
@@ -513,7 +578,7 @@ handle_import(
     {
 	imported_T  *imported;
 
-	imported = find_imported(as_name, STRLEN(as_name), cctx);
+	imported = find_imported(as_name, FALSE, STRLEN(as_name), cctx);
 	if (imported != NULL && imported->imp_sid != sid)
 	{
 	    semsg(_(e_name_already_defined_str), as_name);
@@ -529,6 +594,8 @@ handle_import(
 	imported->imp_name = as_name;
 	as_name = NULL;
 	imported->imp_sid = sid;
+	if (is_autoload)
+	    imported->imp_flags = IMP_FLAGS_AUTOLOAD;
     }
 
 erret: