comparison src/ex_docmd.c @ 17835:fd6c8dc33152 v8.1.1914

patch 8.1.1914: command line expansion code is spread out Commit: https://github.com/vim/vim/commit/d019039ccd7cbeae8923db20383a241d7fc77e2c Author: Bram Moolenaar <Bram@vim.org> Date: Fri Aug 23 21:17:35 2019 +0200 patch 8.1.1914: command line expansion code is spread out Problem: Command line expansion code is spread out. Solution: Move set_one_cmd_context(). (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/4855)
author Bram Moolenaar <Bram@vim.org>
date Fri, 23 Aug 2019 21:30:04 +0200
parents 7e6b7a4f13bc
children 46f95606b9ec
comparison
equal deleted inserted replaced
17834:6170a2c5faaf 17835:fd6c8dc33152
42 static void ex_bnext(exarg_T *eap); 42 static void ex_bnext(exarg_T *eap);
43 static void ex_bprevious(exarg_T *eap); 43 static void ex_bprevious(exarg_T *eap);
44 static void ex_brewind(exarg_T *eap); 44 static void ex_brewind(exarg_T *eap);
45 static void ex_blast(exarg_T *eap); 45 static void ex_blast(exarg_T *eap);
46 static char_u *getargcmd(char_u **); 46 static char_u *getargcmd(char_u **);
47 static char_u *skip_cmd_arg(char_u *p, int rembs);
48 static int getargopt(exarg_T *eap); 47 static int getargopt(exarg_T *eap);
49 #ifndef FEAT_QUICKFIX 48 #ifndef FEAT_QUICKFIX
50 # define ex_make ex_ni 49 # define ex_make ex_ni
51 # define ex_cbuffer ex_ni 50 # define ex_cbuffer ex_ni
52 # define ex_cc ex_ni 51 # define ex_cc ex_ni
3305 return 0; /* trailing garbage */ 3304 return 0; /* trailing garbage */
3306 return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1)); 3305 return (ea.cmdidx == CMD_SIZE ? 0 : (full ? 2 : 1));
3307 } 3306 }
3308 #endif 3307 #endif
3309 3308
3310 /* 3309 cmdidx_T
3311 * This is all pretty much copied from do_one_cmd(), with all the extra stuff 3310 excmd_get_cmdidx(char_u *cmd, int len)
3312 * we don't need/want deleted. Maybe this could be done better if we didn't 3311 {
3313 * repeat all this stuff. The only problem is that they may not stay 3312 cmdidx_T idx;
3314 * perfectly compatible with each other, but then the command line syntax 3313
3315 * probably won't change that much -- webb. 3314 for (idx = (cmdidx_T)0; (int)idx < (int)CMD_SIZE;
3316 */ 3315 idx = (cmdidx_T)((int)idx + 1))
3317 char_u * 3316 if (STRNCMP(cmdnames[(int)idx].cmd_name, cmd, (size_t)len) == 0)
3318 set_one_cmd_context(
3319 expand_T *xp,
3320 char_u *buff) /* buffer for command string */
3321 {
3322 char_u *p;
3323 char_u *cmd, *arg;
3324 int len = 0;
3325 exarg_T ea;
3326 int compl = EXPAND_NOTHING;
3327 int delim;
3328 int forceit = FALSE;
3329 int usefilter = FALSE; /* filter instead of file name */
3330
3331 ExpandInit(xp);
3332 xp->xp_pattern = buff;
3333 xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */
3334 ea.argt = 0;
3335
3336 /*
3337 * 1. skip comment lines and leading space, colons or bars
3338 */
3339 for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
3340 ;
3341 xp->xp_pattern = cmd;
3342
3343 if (*cmd == NUL)
3344 return NULL;
3345 if (*cmd == '"') /* ignore comment lines */
3346 {
3347 xp->xp_context = EXPAND_NOTHING;
3348 return NULL;
3349 }
3350
3351 /*
3352 * 3. Skip over the range to find the command.
3353 */
3354 cmd = skip_range(cmd, &xp->xp_context);
3355 xp->xp_pattern = cmd;
3356 if (*cmd == NUL)
3357 return NULL;
3358 if (*cmd == '"')
3359 {
3360 xp->xp_context = EXPAND_NOTHING;
3361 return NULL;
3362 }
3363
3364 if (*cmd == '|' || *cmd == '\n')
3365 return cmd + 1; /* There's another command */
3366
3367 /*
3368 * Isolate the command and search for it in the command table.
3369 * Exceptions:
3370 * - the 'k' command can directly be followed by any character, but
3371 * do accept "keepmarks", "keepalt" and "keepjumps".
3372 * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
3373 */
3374 if (*cmd == 'k' && cmd[1] != 'e')
3375 {
3376 ea.cmdidx = CMD_k;
3377 p = cmd + 1;
3378 }
3379 else
3380 {
3381 p = cmd;
3382 while (ASCII_ISALPHA(*p) || *p == '*') /* Allow * wild card */
3383 ++p;
3384 /* a user command may contain digits */
3385 if (ASCII_ISUPPER(cmd[0]))
3386 while (ASCII_ISALNUM(*p) || *p == '*')
3387 ++p;
3388 /* for python 3.x: ":py3*" commands completion */
3389 if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3')
3390 {
3391 ++p;
3392 while (ASCII_ISALPHA(*p) || *p == '*')
3393 ++p;
3394 }
3395 /* check for non-alpha command */
3396 if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
3397 ++p;
3398 len = (int)(p - cmd);
3399
3400 if (len == 0)
3401 {
3402 xp->xp_context = EXPAND_UNSUCCESSFUL;
3403 return NULL;
3404 }
3405 for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE;
3406 ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1))
3407 if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd,
3408 (size_t)len) == 0)
3409 break;
3410
3411 if (cmd[0] >= 'A' && cmd[0] <= 'Z')
3412 while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card
3413 ++p;
3414 }
3415
3416 /*
3417 * If the cursor is touching the command, and it ends in an alpha-numeric
3418 * character, complete the command name.
3419 */
3420 if (*p == NUL && ASCII_ISALNUM(p[-1]))
3421 return NULL;
3422
3423 if (ea.cmdidx == CMD_SIZE)
3424 {
3425 if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL)
3426 {
3427 ea.cmdidx = CMD_substitute;
3428 p = cmd + 1;
3429 }
3430 else if (cmd[0] >= 'A' && cmd[0] <= 'Z')
3431 {
3432 ea.cmd = cmd;
3433 p = find_ucmd(&ea, p, NULL, xp, &compl);
3434 if (p == NULL)
3435 ea.cmdidx = CMD_SIZE; // ambiguous user command
3436 }
3437 }
3438 if (ea.cmdidx == CMD_SIZE)
3439 {
3440 /* Not still touching the command and it was an illegal one */
3441 xp->xp_context = EXPAND_UNSUCCESSFUL;
3442 return NULL;
3443 }
3444
3445 xp->xp_context = EXPAND_NOTHING; /* Default now that we're past command */
3446
3447 if (*p == '!') /* forced commands */
3448 {
3449 forceit = TRUE;
3450 ++p;
3451 }
3452
3453 /*
3454 * 6. parse arguments
3455 */
3456 if (!IS_USER_CMDIDX(ea.cmdidx))
3457 ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt;
3458
3459 arg = skipwhite(p);
3460
3461 if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
3462 {
3463 if (*arg == '>') /* append */
3464 {
3465 if (*++arg == '>')
3466 ++arg;
3467 arg = skipwhite(arg);
3468 }
3469 else if (*arg == '!' && ea.cmdidx == CMD_write) /* :w !filter */
3470 {
3471 ++arg;
3472 usefilter = TRUE;
3473 }
3474 }
3475
3476 if (ea.cmdidx == CMD_read)
3477 {
3478 usefilter = forceit; /* :r! filter if forced */
3479 if (*arg == '!') /* :r !filter */
3480 {
3481 ++arg;
3482 usefilter = TRUE;
3483 }
3484 }
3485
3486 if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
3487 {
3488 while (*arg == *cmd) /* allow any number of '>' or '<' */
3489 ++arg;
3490 arg = skipwhite(arg);
3491 }
3492
3493 /* Does command allow "+command"? */
3494 if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+')
3495 {
3496 /* Check if we're in the +command */
3497 p = arg + 1;
3498 arg = skip_cmd_arg(arg, FALSE);
3499
3500 /* Still touching the command after '+'? */
3501 if (*arg == NUL)
3502 return p;
3503
3504 /* Skip space(s) after +command to get to the real argument */
3505 arg = skipwhite(arg);
3506 }
3507
3508 /*
3509 * Check for '|' to separate commands and '"' to start comments.
3510 * Don't do this for ":read !cmd" and ":write !cmd".
3511 */
3512 if ((ea.argt & EX_TRLBAR) && !usefilter)
3513 {
3514 p = arg;
3515 /* ":redir @" is not the start of a comment */
3516 if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"')
3517 p += 2;
3518 while (*p)
3519 {
3520 if (*p == Ctrl_V)
3521 {
3522 if (p[1] != NUL)
3523 ++p;
3524 }
3525 else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM))
3526 || *p == '|' || *p == '\n')
3527 {
3528 if (*(p - 1) != '\\')
3529 {
3530 if (*p == '|' || *p == '\n')
3531 return p + 1;
3532 return NULL; /* It's a comment */
3533 }
3534 }
3535 MB_PTR_ADV(p);
3536 }
3537 }
3538
3539 if (!(ea.argt & EX_EXTRA) && *arg != NUL
3540 && vim_strchr((char_u *)"|\"", *arg) == NULL)
3541 // no arguments allowed but there is something
3542 return NULL;
3543
3544 /* Find start of last argument (argument just before cursor): */
3545 p = buff;
3546 xp->xp_pattern = p;
3547 len = (int)STRLEN(buff);
3548 while (*p && p < buff + len)
3549 {
3550 if (*p == ' ' || *p == TAB)
3551 {
3552 /* argument starts after a space */
3553 xp->xp_pattern = ++p;
3554 }
3555 else
3556 {
3557 if (*p == '\\' && *(p + 1) != NUL)
3558 ++p; /* skip over escaped character */
3559 MB_PTR_ADV(p);
3560 }
3561 }
3562
3563 if (ea.argt & EX_XFILE)
3564 {
3565 int c;
3566 int in_quote = FALSE;
3567 char_u *bow = NULL; /* Beginning of word */
3568
3569 /*
3570 * Allow spaces within back-quotes to count as part of the argument
3571 * being expanded.
3572 */
3573 xp->xp_pattern = skipwhite(arg);
3574 p = xp->xp_pattern;
3575 while (*p != NUL)
3576 {
3577 if (has_mbyte)
3578 c = mb_ptr2char(p);
3579 else
3580 c = *p;
3581 if (c == '\\' && p[1] != NUL)
3582 ++p;
3583 else if (c == '`')
3584 {
3585 if (!in_quote)
3586 {
3587 xp->xp_pattern = p;
3588 bow = p + 1;
3589 }
3590 in_quote = !in_quote;
3591 }
3592 /* An argument can contain just about everything, except
3593 * characters that end the command and white space. */
3594 else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c)
3595 #ifdef SPACE_IN_FILENAME
3596 && (!(ea.argt & EX_NOSPC) || usefilter)
3597 #endif
3598 ))
3599 {
3600 len = 0; /* avoid getting stuck when space is in 'isfname' */
3601 while (*p != NUL)
3602 {
3603 if (has_mbyte)
3604 c = mb_ptr2char(p);
3605 else
3606 c = *p;
3607 if (c == '`' || vim_isfilec_or_wc(c))
3608 break;
3609 if (has_mbyte)
3610 len = (*mb_ptr2len)(p);
3611 else
3612 len = 1;
3613 MB_PTR_ADV(p);
3614 }
3615 if (in_quote)
3616 bow = p;
3617 else
3618 xp->xp_pattern = p;
3619 p -= len;
3620 }
3621 MB_PTR_ADV(p);
3622 }
3623
3624 /*
3625 * If we are still inside the quotes, and we passed a space, just
3626 * expand from there.
3627 */
3628 if (bow != NULL && in_quote)
3629 xp->xp_pattern = bow;
3630 xp->xp_context = EXPAND_FILES;
3631
3632 /* For a shell command more chars need to be escaped. */
3633 if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal)
3634 {
3635 #ifndef BACKSLASH_IN_FILENAME
3636 xp->xp_shell = TRUE;
3637 #endif
3638 /* When still after the command name expand executables. */
3639 if (xp->xp_pattern == skipwhite(arg))
3640 xp->xp_context = EXPAND_SHELLCMD;
3641 }
3642
3643 /* Check for environment variable */
3644 if (*xp->xp_pattern == '$'
3645 #if defined(MSWIN)
3646 || *xp->xp_pattern == '%'
3647 #endif
3648 )
3649 {
3650 for (p = xp->xp_pattern + 1; *p != NUL; ++p)
3651 if (!vim_isIDc(*p))
3652 break;
3653 if (*p == NUL)
3654 {
3655 xp->xp_context = EXPAND_ENV_VARS;
3656 ++xp->xp_pattern;
3657 /* Avoid that the assignment uses EXPAND_FILES again. */
3658 if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
3659 compl = EXPAND_ENV_VARS;
3660 }
3661 }
3662 /* Check for user names */
3663 if (*xp->xp_pattern == '~')
3664 {
3665 for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p)
3666 ;
3667 /* Complete ~user only if it partially matches a user name.
3668 * A full match ~user<Tab> will be replaced by user's home
3669 * directory i.e. something like ~user<Tab> -> /home/user/ */
3670 if (*p == NUL && p > xp->xp_pattern + 1
3671 && match_user(xp->xp_pattern + 1) >= 1)
3672 {
3673 xp->xp_context = EXPAND_USER;
3674 ++xp->xp_pattern;
3675 }
3676 }
3677 }
3678
3679 /*
3680 * 6. Switch on command name.
3681 */
3682 switch (ea.cmdidx)
3683 {
3684 case CMD_find:
3685 case CMD_sfind:
3686 case CMD_tabfind:
3687 if (xp->xp_context == EXPAND_FILES)
3688 xp->xp_context = EXPAND_FILES_IN_PATH;
3689 break; 3317 break;
3690 case CMD_cd: 3318
3691 case CMD_chdir: 3319 return idx;
3692 case CMD_tcd: 3320 }
3693 case CMD_tchdir: 3321
3694 case CMD_lcd: 3322 long
3695 case CMD_lchdir: 3323 excmd_get_argt(cmdidx_T idx)
3696 if (xp->xp_context == EXPAND_FILES) 3324 {
3697 xp->xp_context = EXPAND_DIRECTORIES; 3325 return (long)cmdnames[(int)idx].cmd_argt;
3698 break;
3699 case CMD_help:
3700 xp->xp_context = EXPAND_HELP;
3701 xp->xp_pattern = arg;
3702 break;
3703
3704 /* Command modifiers: return the argument.
3705 * Also for commands with an argument that is a command. */
3706 case CMD_aboveleft:
3707 case CMD_argdo:
3708 case CMD_belowright:
3709 case CMD_botright:
3710 case CMD_browse:
3711 case CMD_bufdo:
3712 case CMD_cdo:
3713 case CMD_cfdo:
3714 case CMD_confirm:
3715 case CMD_debug:
3716 case CMD_folddoclosed:
3717 case CMD_folddoopen:
3718 case CMD_hide:
3719 case CMD_keepalt:
3720 case CMD_keepjumps:
3721 case CMD_keepmarks:
3722 case CMD_keeppatterns:
3723 case CMD_ldo:
3724 case CMD_leftabove:
3725 case CMD_lfdo:
3726 case CMD_lockmarks:
3727 case CMD_noautocmd:
3728 case CMD_noswapfile:
3729 case CMD_rightbelow:
3730 case CMD_sandbox:
3731 case CMD_silent:
3732 case CMD_tab:
3733 case CMD_tabdo:
3734 case CMD_topleft:
3735 case CMD_verbose:
3736 case CMD_vertical:
3737 case CMD_windo:
3738 return arg;
3739
3740 case CMD_filter:
3741 if (*arg != NUL)
3742 arg = skip_vimgrep_pat(arg, NULL, NULL);
3743 if (arg == NULL || *arg == NUL)
3744 {
3745 xp->xp_context = EXPAND_NOTHING;
3746 return NULL;
3747 }
3748 return skipwhite(arg);
3749
3750 #ifdef FEAT_SEARCH_EXTRA
3751 case CMD_match:
3752 if (*arg == NUL || !ends_excmd(*arg))
3753 {
3754 /* also complete "None" */
3755 set_context_in_echohl_cmd(xp, arg);
3756 arg = skipwhite(skiptowhite(arg));
3757 if (*arg != NUL)
3758 {
3759 xp->xp_context = EXPAND_NOTHING;
3760 arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
3761 }
3762 }
3763 return find_nextcmd(arg);
3764 #endif
3765
3766 /*
3767 * All completion for the +cmdline_compl feature goes here.
3768 */
3769
3770 case CMD_command:
3771 return set_context_in_user_cmd(xp, arg);
3772
3773 case CMD_delcommand:
3774 xp->xp_context = EXPAND_USER_COMMANDS;
3775 xp->xp_pattern = arg;
3776 break;
3777
3778 case CMD_global:
3779 case CMD_vglobal:
3780 delim = *arg; /* get the delimiter */
3781 if (delim)
3782 ++arg; /* skip delimiter if there is one */
3783
3784 while (arg[0] != NUL && arg[0] != delim)
3785 {
3786 if (arg[0] == '\\' && arg[1] != NUL)
3787 ++arg;
3788 ++arg;
3789 }
3790 if (arg[0] != NUL)
3791 return arg + 1;
3792 break;
3793 case CMD_and:
3794 case CMD_substitute:
3795 delim = *arg;
3796 if (delim)
3797 {
3798 /* skip "from" part */
3799 ++arg;
3800 arg = skip_regexp(arg, delim, p_magic, NULL);
3801 }
3802 /* skip "to" part */
3803 while (arg[0] != NUL && arg[0] != delim)
3804 {
3805 if (arg[0] == '\\' && arg[1] != NUL)
3806 ++arg;
3807 ++arg;
3808 }
3809 if (arg[0] != NUL) /* skip delimiter */
3810 ++arg;
3811 while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
3812 ++arg;
3813 if (arg[0] != NUL)
3814 return arg;
3815 break;
3816 case CMD_isearch:
3817 case CMD_dsearch:
3818 case CMD_ilist:
3819 case CMD_dlist:
3820 case CMD_ijump:
3821 case CMD_psearch:
3822 case CMD_djump:
3823 case CMD_isplit:
3824 case CMD_dsplit:
3825 arg = skipwhite(skipdigits(arg)); /* skip count */
3826 if (*arg == '/') /* Match regexp, not just whole words */
3827 {
3828 for (++arg; *arg && *arg != '/'; arg++)
3829 if (*arg == '\\' && arg[1] != NUL)
3830 arg++;
3831 if (*arg)
3832 {
3833 arg = skipwhite(arg + 1);
3834
3835 /* Check for trailing illegal characters */
3836 if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
3837 xp->xp_context = EXPAND_NOTHING;
3838 else
3839 return arg;
3840 }
3841 }
3842 break;
3843
3844 case CMD_autocmd:
3845 return set_context_in_autocmd(xp, arg, FALSE);
3846 case CMD_doautocmd:
3847 case CMD_doautoall:
3848 return set_context_in_autocmd(xp, arg, TRUE);
3849 case CMD_set:
3850 set_context_in_set_cmd(xp, arg, 0);
3851 break;
3852 case CMD_setglobal:
3853 set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
3854 break;
3855 case CMD_setlocal:
3856 set_context_in_set_cmd(xp, arg, OPT_LOCAL);
3857 break;
3858 case CMD_tag:
3859 case CMD_stag:
3860 case CMD_ptag:
3861 case CMD_ltag:
3862 case CMD_tselect:
3863 case CMD_stselect:
3864 case CMD_ptselect:
3865 case CMD_tjump:
3866 case CMD_stjump:
3867 case CMD_ptjump:
3868 if (*p_wop != NUL)
3869 xp->xp_context = EXPAND_TAGS_LISTFILES;
3870 else
3871 xp->xp_context = EXPAND_TAGS;
3872 xp->xp_pattern = arg;
3873 break;
3874 case CMD_augroup:
3875 xp->xp_context = EXPAND_AUGROUP;
3876 xp->xp_pattern = arg;
3877 break;
3878 #ifdef FEAT_SYN_HL
3879 case CMD_syntax:
3880 set_context_in_syntax_cmd(xp, arg);
3881 break;
3882 #endif
3883 #ifdef FEAT_EVAL
3884 case CMD_let:
3885 case CMD_if:
3886 case CMD_elseif:
3887 case CMD_while:
3888 case CMD_for:
3889 case CMD_echo:
3890 case CMD_echon:
3891 case CMD_execute:
3892 case CMD_echomsg:
3893 case CMD_echoerr:
3894 case CMD_call:
3895 case CMD_return:
3896 case CMD_cexpr:
3897 case CMD_caddexpr:
3898 case CMD_cgetexpr:
3899 case CMD_lexpr:
3900 case CMD_laddexpr:
3901 case CMD_lgetexpr:
3902 set_context_for_expression(xp, arg, ea.cmdidx);
3903 break;
3904
3905 case CMD_unlet:
3906 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
3907 arg = xp->xp_pattern + 1;
3908
3909 xp->xp_context = EXPAND_USER_VARS;
3910 xp->xp_pattern = arg;
3911
3912 if (*xp->xp_pattern == '$')
3913 {
3914 xp->xp_context = EXPAND_ENV_VARS;
3915 ++xp->xp_pattern;
3916 }
3917
3918 break;
3919
3920 case CMD_function:
3921 case CMD_delfunction:
3922 xp->xp_context = EXPAND_USER_FUNC;
3923 xp->xp_pattern = arg;
3924 break;
3925
3926 case CMD_echohl:
3927 set_context_in_echohl_cmd(xp, arg);
3928 break;
3929 #endif
3930 case CMD_highlight:
3931 set_context_in_highlight_cmd(xp, arg);
3932 break;
3933 #ifdef FEAT_CSCOPE
3934 case CMD_cscope:
3935 case CMD_lcscope:
3936 case CMD_scscope:
3937 set_context_in_cscope_cmd(xp, arg, ea.cmdidx);
3938 break;
3939 #endif
3940 #ifdef FEAT_SIGNS
3941 case CMD_sign:
3942 set_context_in_sign_cmd(xp, arg);
3943 break;
3944 #endif
3945 case CMD_bdelete:
3946 case CMD_bwipeout:
3947 case CMD_bunload:
3948 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
3949 arg = xp->xp_pattern + 1;
3950 /* FALLTHROUGH */
3951 case CMD_buffer:
3952 case CMD_sbuffer:
3953 case CMD_checktime:
3954 xp->xp_context = EXPAND_BUFFERS;
3955 xp->xp_pattern = arg;
3956 break;
3957
3958 case CMD_USER:
3959 case CMD_USER_BUF:
3960 if (compl != EXPAND_NOTHING)
3961 {
3962 // EX_XFILE: file names are handled above
3963 if (!(ea.argt & EX_XFILE))
3964 {
3965 #ifdef FEAT_MENU
3966 if (compl == EXPAND_MENUS)
3967 return set_context_in_menu_cmd(xp, cmd, arg, forceit);
3968 #endif
3969 if (compl == EXPAND_COMMANDS)
3970 return arg;
3971 if (compl == EXPAND_MAPPINGS)
3972 return set_context_in_map_cmd(xp, (char_u *)"map",
3973 arg, forceit, FALSE, FALSE, CMD_map);
3974 // Find start of last argument.
3975 p = arg;
3976 while (*p)
3977 {
3978 if (*p == ' ')
3979 // argument starts after a space
3980 arg = p + 1;
3981 else if (*p == '\\' && *(p + 1) != NUL)
3982 ++p; // skip over escaped character
3983 MB_PTR_ADV(p);
3984 }
3985 xp->xp_pattern = arg;
3986 }
3987 xp->xp_context = compl;
3988 }
3989 break;
3990
3991 case CMD_map: case CMD_noremap:
3992 case CMD_nmap: case CMD_nnoremap:
3993 case CMD_vmap: case CMD_vnoremap:
3994 case CMD_omap: case CMD_onoremap:
3995 case CMD_imap: case CMD_inoremap:
3996 case CMD_cmap: case CMD_cnoremap:
3997 case CMD_lmap: case CMD_lnoremap:
3998 case CMD_smap: case CMD_snoremap:
3999 case CMD_tmap: case CMD_tnoremap:
4000 case CMD_xmap: case CMD_xnoremap:
4001 return set_context_in_map_cmd(xp, cmd, arg, forceit,
4002 FALSE, FALSE, ea.cmdidx);
4003 case CMD_unmap:
4004 case CMD_nunmap:
4005 case CMD_vunmap:
4006 case CMD_ounmap:
4007 case CMD_iunmap:
4008 case CMD_cunmap:
4009 case CMD_lunmap:
4010 case CMD_sunmap:
4011 case CMD_tunmap:
4012 case CMD_xunmap:
4013 return set_context_in_map_cmd(xp, cmd, arg, forceit,
4014 FALSE, TRUE, ea.cmdidx);
4015 case CMD_mapclear:
4016 case CMD_nmapclear:
4017 case CMD_vmapclear:
4018 case CMD_omapclear:
4019 case CMD_imapclear:
4020 case CMD_cmapclear:
4021 case CMD_lmapclear:
4022 case CMD_smapclear:
4023 case CMD_tmapclear:
4024 case CMD_xmapclear:
4025 xp->xp_context = EXPAND_MAPCLEAR;
4026 xp->xp_pattern = arg;
4027 break;
4028
4029 case CMD_abbreviate: case CMD_noreabbrev:
4030 case CMD_cabbrev: case CMD_cnoreabbrev:
4031 case CMD_iabbrev: case CMD_inoreabbrev:
4032 return set_context_in_map_cmd(xp, cmd, arg, forceit,
4033 TRUE, FALSE, ea.cmdidx);
4034 case CMD_unabbreviate:
4035 case CMD_cunabbrev:
4036 case CMD_iunabbrev:
4037 return set_context_in_map_cmd(xp, cmd, arg, forceit,
4038 TRUE, TRUE, ea.cmdidx);
4039 #ifdef FEAT_MENU
4040 case CMD_menu: case CMD_noremenu: case CMD_unmenu:
4041 case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu:
4042 case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu:
4043 case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu:
4044 case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu:
4045 case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu:
4046 case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu:
4047 case CMD_tlmenu: case CMD_tlnoremenu: case CMD_tlunmenu:
4048 case CMD_tmenu: case CMD_tunmenu:
4049 case CMD_popup: case CMD_tearoff: case CMD_emenu:
4050 return set_context_in_menu_cmd(xp, cmd, arg, forceit);
4051 #endif
4052
4053 case CMD_colorscheme:
4054 xp->xp_context = EXPAND_COLORS;
4055 xp->xp_pattern = arg;
4056 break;
4057
4058 case CMD_compiler:
4059 xp->xp_context = EXPAND_COMPILER;
4060 xp->xp_pattern = arg;
4061 break;
4062
4063 case CMD_ownsyntax:
4064 xp->xp_context = EXPAND_OWNSYNTAX;
4065 xp->xp_pattern = arg;
4066 break;
4067
4068 case CMD_setfiletype:
4069 xp->xp_context = EXPAND_FILETYPE;
4070 xp->xp_pattern = arg;
4071 break;
4072
4073 case CMD_packadd:
4074 xp->xp_context = EXPAND_PACKADD;
4075 xp->xp_pattern = arg;
4076 break;
4077
4078 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
4079 case CMD_language:
4080 p = skiptowhite(arg);
4081 if (*p == NUL)
4082 {
4083 xp->xp_context = EXPAND_LANGUAGE;
4084 xp->xp_pattern = arg;
4085 }
4086 else
4087 {
4088 if ( STRNCMP(arg, "messages", p - arg) == 0
4089 || STRNCMP(arg, "ctype", p - arg) == 0
4090 || STRNCMP(arg, "time", p - arg) == 0)
4091 {
4092 xp->xp_context = EXPAND_LOCALES;
4093 xp->xp_pattern = skipwhite(p);
4094 }
4095 else
4096 xp->xp_context = EXPAND_NOTHING;
4097 }
4098 break;
4099 #endif
4100 #if defined(FEAT_PROFILE)
4101 case CMD_profile:
4102 set_context_in_profile_cmd(xp, arg);
4103 break;
4104 #endif
4105 case CMD_behave:
4106 xp->xp_context = EXPAND_BEHAVE;
4107 xp->xp_pattern = arg;
4108 break;
4109
4110 case CMD_messages:
4111 xp->xp_context = EXPAND_MESSAGES;
4112 xp->xp_pattern = arg;
4113 break;
4114
4115 case CMD_history:
4116 xp->xp_context = EXPAND_HISTORY;
4117 xp->xp_pattern = arg;
4118 break;
4119 #if defined(FEAT_PROFILE)
4120 case CMD_syntime:
4121 xp->xp_context = EXPAND_SYNTIME;
4122 xp->xp_pattern = arg;
4123 break;
4124 #endif
4125
4126 case CMD_argdelete:
4127 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
4128 arg = xp->xp_pattern + 1;
4129 xp->xp_context = EXPAND_ARGLIST;
4130 xp->xp_pattern = arg;
4131 break;
4132
4133 default:
4134 break;
4135 }
4136 return NULL;
4137 } 3326 }
4138 3327
4139 /* 3328 /*
4140 * Skip a range specifier of the form: addr [,addr] [;addr] .. 3329 * Skip a range specifier of the form: addr [,addr] [;addr] ..
4141 * 3330 *
5194 } 4383 }
5195 4384
5196 /* 4385 /*
5197 * Find end of "+command" argument. Skip over "\ " and "\\". 4386 * Find end of "+command" argument. Skip over "\ " and "\\".
5198 */ 4387 */
5199 static char_u * 4388 char_u *
5200 skip_cmd_arg( 4389 skip_cmd_arg(
5201 char_u *p, 4390 char_u *p,
5202 int rembs) /* TRUE to halve the number of backslashes */ 4391 int rembs) /* TRUE to halve the number of backslashes */
5203 { 4392 {
5204 while (*p && !vim_isspace(*p)) 4393 while (*p && !vim_isspace(*p))
9160 } 8349 }
9161 else 8350 else
9162 semsg(_(e_invarg2), eap->arg); 8351 semsg(_(e_invarg2), eap->arg);
9163 } 8352 }
9164 8353
9165 /*
9166 * Function given to ExpandGeneric() to obtain the possible arguments of the
9167 * ":behave {mswin,xterm}" command.
9168 */
9169 char_u *
9170 get_behave_arg(expand_T *xp UNUSED, int idx)
9171 {
9172 if (idx == 0)
9173 return (char_u *)"mswin";
9174 if (idx == 1)
9175 return (char_u *)"xterm";
9176 return NULL;
9177 }
9178
9179 /*
9180 * Function given to ExpandGeneric() to obtain the possible arguments of the
9181 * ":messages {clear}" command.
9182 */
9183 char_u *
9184 get_messages_arg(expand_T *xp UNUSED, int idx)
9185 {
9186 if (idx == 0)
9187 return (char_u *)"clear";
9188 return NULL;
9189 }
9190
9191 char_u *
9192 get_mapclear_arg(expand_T *xp UNUSED, int idx)
9193 {
9194 if (idx == 0)
9195 return (char_u *)"<buffer>";
9196 return NULL;
9197 }
9198
9199 static int filetype_detect = FALSE; 8354 static int filetype_detect = FALSE;
9200 static int filetype_plugin = FALSE; 8355 static int filetype_plugin = FALSE;
9201 static int filetype_indent = FALSE; 8356 static int filetype_indent = FALSE;
9202 8357
9203 /* 8358 /*