aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/cmdexpand.c41
-rw-r--r--src/nvim/cmdexpand_defs.h4
-rw-r--r--src/nvim/ex_docmd.c82
-rw-r--r--src/nvim/optionstr.c11
4 files changed, 130 insertions, 8 deletions
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index aef471a17b..bf0aa54bdd 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -1567,6 +1567,20 @@ static void set_context_for_wildcard_arg(exarg_T *eap, const char *arg, bool use
}
}
+/// Set the completion context for the "++opt=arg" argument. Always returns NULL.
+static const char *set_context_in_argopt(expand_T *xp, const char *arg)
+{
+ char *p = vim_strchr(arg, '=');
+ if (p == NULL) {
+ xp->xp_pattern = (char *)arg;
+ } else {
+ xp->xp_pattern = p + 1;
+ }
+
+ xp->xp_context = EXPAND_ARGOPT;
+ return NULL;
+}
+
/// Set the completion context for the :filter command. Returns a pointer to the
/// next command after the :filter command.
static const char *set_context_in_filter_cmd(expand_T *xp, const char *arg)
@@ -2238,13 +2252,23 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
const char *arg = skipwhite(p);
- // Skip over ++argopt argument
- if ((ea.argt & EX_ARGOPT) && *arg != NUL && strncmp(arg, "++", 2) == 0) {
- p = arg;
- while (*p && !ascii_isspace(*p)) {
- MB_PTR_ADV(p);
+ // Does command allow "++argopt" argument?
+ if (ea.argt & EX_ARGOPT) {
+ while (*arg != NUL && strncmp(arg, "++", 2) == 0) {
+ p = arg + 2;
+ while (*p && !ascii_isspace(*p)) {
+ MB_PTR_ADV(p);
+ }
+
+ // Still touching the command after "++"?
+ if (*p == NUL) {
+ if (ea.argt & EX_ARGOPT) {
+ return set_context_in_argopt(xp, arg + 2);
+ }
+ }
+
+ arg = skipwhite(p);
}
- arg = skipwhite(p);
}
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
@@ -2786,6 +2810,8 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
ret = ExpandSettingSubtract(xp, &regmatch, numMatches, matches);
} else if (xp->xp_context == EXPAND_MAPPINGS) {
ret = ExpandMappings(pat, &regmatch, numMatches, matches);
+ } else if (xp->xp_context == EXPAND_ARGOPT) {
+ ret = expand_argopt(pat, xp, &regmatch, matches, numMatches);
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
} else {
@@ -2883,7 +2909,8 @@ void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch, ch
&& xp->xp_context != EXPAND_MENUNAMES
&& xp->xp_context != EXPAND_STRING_SETTING
&& xp->xp_context != EXPAND_MENUS
- && xp->xp_context != EXPAND_SCRIPTNAMES;
+ && xp->xp_context != EXPAND_SCRIPTNAMES
+ && xp->xp_context != EXPAND_ARGOPT;
// <SNR> functions should be sorted to the end.
const bool funcsort = xp->xp_context == EXPAND_EXPRESSION
diff --git a/src/nvim/cmdexpand_defs.h b/src/nvim/cmdexpand_defs.h
index 7c422aca18..0e830a016f 100644
--- a/src/nvim/cmdexpand_defs.h
+++ b/src/nvim/cmdexpand_defs.h
@@ -17,7 +17,8 @@ enum { EXPAND_BUF_LEN = 256, };
/// used for completion on the command line
typedef struct expand {
- char *xp_pattern; ///< start of item to expand
+ char *xp_pattern; ///< start of item to expand, guaranteed
+ ///< to be part of xp_line
int xp_context; ///< type of expansion
size_t xp_pattern_len; ///< bytes in xp_pattern before cursor
xp_prefix_T xp_prefix;
@@ -104,6 +105,7 @@ enum {
EXPAND_RUNTIME,
EXPAND_STRING_SETTING,
EXPAND_SETTING_SUBTRACT,
+ EXPAND_ARGOPT,
EXPAND_CHECKHEALTH,
EXPAND_LUA,
};
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 279d14f001..664b06108a 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4087,6 +4087,22 @@ int get_bad_opt(const char *p, exarg_T *eap)
return OK;
}
+/// Function given to ExpandGeneric() to obtain the list of bad= names.
+static char *get_bad_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ // Note: Keep this in sync with get_bad_opt().
+ static char *(p_bad_values[]) = {
+ "?",
+ "keep",
+ "drop",
+ };
+
+ if (idx < (int)ARRAY_SIZE(p_bad_values)) {
+ return p_bad_values[idx];
+ }
+ return NULL;
+}
+
/// Get "++opt=arg" argument.
///
/// @return FAIL or OK.
@@ -4096,6 +4112,8 @@ static int getargopt(exarg_T *eap)
int *pp = NULL;
int bad_char_idx;
+ // Note: Keep this in sync with get_argopt_name.
+
// ":edit ++[no]bin[ary] file"
if (strncmp(arg, "bin", 3) == 0 || strncmp(arg, "nobin", 5) == 0) {
if (*arg == 'n') {
@@ -4174,6 +4192,70 @@ static int getargopt(exarg_T *eap)
return OK;
}
+/// Function given to ExpandGeneric() to obtain the list of ++opt names.
+static char *get_argopt_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ // Note: Keep this in sync with getargopt().
+ static char *(p_opt_values[]) = {
+ "fileformat=",
+ "encoding=",
+ "binary",
+ "nobinary",
+ "bad=",
+ "edit",
+ "p",
+ };
+
+ if (idx < (int)ARRAY_SIZE(p_opt_values)) {
+ return p_opt_values[idx];
+ }
+ return NULL;
+}
+
+/// Command-line expansion for ++opt=name.
+int expand_argopt(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
+{
+ if (xp->xp_pattern > xp->xp_line && *(xp->xp_pattern - 1) == '=') {
+ CompleteListItemGetter cb = NULL;
+
+ char *name_end = xp->xp_pattern - 1;
+ if (name_end - xp->xp_line >= 2
+ && strncmp(name_end - 2, "ff", 2) == 0) {
+ cb = get_fileformat_name;
+ } else if (name_end - xp->xp_line >= 10
+ && strncmp(name_end - 10, "fileformat", 10) == 0) {
+ cb = get_fileformat_name;
+ } else if (name_end - xp->xp_line >= 3
+ && strncmp(name_end - 3, "enc", 3) == 0) {
+ cb = get_encoding_name;
+ } else if (name_end - xp->xp_line >= 8
+ && strncmp(name_end - 8, "encoding", 8) == 0) {
+ cb = get_encoding_name;
+ } else if (name_end - xp->xp_line >= 3
+ && strncmp(name_end - 3, "bad", 3) == 0) {
+ cb = get_bad_name;
+ }
+
+ if (cb != NULL) {
+ ExpandGeneric(pat, xp, rmp, matches, numMatches, cb, false);
+ return OK;
+ }
+ return FAIL;
+ }
+
+ // Special handling of "ff" which acts as a short form of
+ // "fileformat", as "ff" is not a substring of it.
+ if (strcmp(xp->xp_pattern, "ff") == 0) {
+ *matches = xmalloc(sizeof(char *));
+ *numMatches = 1;
+ (*matches)[0] = xstrdup("fileformat=");
+ return OK;
+ }
+
+ ExpandGeneric(pat, xp, rmp, matches, numMatches, get_argopt_name, false);
+ return OK;
+}
+
/// Handle the argument for a tabpage related ex command.
/// When an error is encountered then eap->errmsg is set.
///
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 6f41bba99b..88e7ebd991 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -1490,6 +1490,17 @@ int expand_set_fileformat(optexpand_T *args, int *numMatches, char ***matches)
matches);
}
+/// Function given to ExpandGeneric() to obtain the possible arguments of the
+/// fileformat options.
+char *get_fileformat_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ if (idx >= (int)ARRAY_SIZE(p_ff_values)) {
+ return NULL;
+ }
+
+ return p_ff_values[idx];
+}
+
/// The 'fileformats' option is changed.
const char *did_set_fileformats(optset_T *args)
{