Mercurial > vim
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 /* |