Mercurial > vim
comparison src/cmdexpand.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 | 6582dda76821 |
children | 0a5c615cd949 |
comparison
equal
deleted
inserted
replaced
17834:6170a2c5faaf | 17835:fd6c8dc33152 |
---|---|
957 return; | 957 return; |
958 } | 958 } |
959 set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, TRUE); | 959 set_cmd_context(xp, ccline->cmdbuff, ccline->cmdlen, ccline->cmdpos, TRUE); |
960 } | 960 } |
961 | 961 |
962 /* | |
963 * This is all pretty much copied from do_one_cmd(), with all the extra stuff | |
964 * we don't need/want deleted. Maybe this could be done better if we didn't | |
965 * repeat all this stuff. The only problem is that they may not stay | |
966 * perfectly compatible with each other, but then the command line syntax | |
967 * probably won't change that much -- webb. | |
968 */ | |
969 static char_u * | |
970 set_one_cmd_context( | |
971 expand_T *xp, | |
972 char_u *buff) // buffer for command string | |
973 { | |
974 char_u *p; | |
975 char_u *cmd, *arg; | |
976 int len = 0; | |
977 exarg_T ea; | |
978 int compl = EXPAND_NOTHING; | |
979 int delim; | |
980 int forceit = FALSE; | |
981 int usefilter = FALSE; // filter instead of file name | |
982 | |
983 ExpandInit(xp); | |
984 xp->xp_pattern = buff; | |
985 xp->xp_context = EXPAND_COMMANDS; // Default until we get past command | |
986 ea.argt = 0; | |
987 | |
988 // 1. skip comment lines and leading space, colons or bars | |
989 for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++) | |
990 ; | |
991 xp->xp_pattern = cmd; | |
992 | |
993 if (*cmd == NUL) | |
994 return NULL; | |
995 if (*cmd == '"') // ignore comment lines | |
996 { | |
997 xp->xp_context = EXPAND_NOTHING; | |
998 return NULL; | |
999 } | |
1000 | |
1001 // 3. Skip over the range to find the command. | |
1002 cmd = skip_range(cmd, &xp->xp_context); | |
1003 xp->xp_pattern = cmd; | |
1004 if (*cmd == NUL) | |
1005 return NULL; | |
1006 if (*cmd == '"') | |
1007 { | |
1008 xp->xp_context = EXPAND_NOTHING; | |
1009 return NULL; | |
1010 } | |
1011 | |
1012 if (*cmd == '|' || *cmd == '\n') | |
1013 return cmd + 1; // There's another command | |
1014 | |
1015 // Isolate the command and search for it in the command table. | |
1016 // Exceptions: | |
1017 // - the 'k' command can directly be followed by any character, but | |
1018 // do accept "keepmarks", "keepalt" and "keepjumps". | |
1019 // - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' | |
1020 if (*cmd == 'k' && cmd[1] != 'e') | |
1021 { | |
1022 ea.cmdidx = CMD_k; | |
1023 p = cmd + 1; | |
1024 } | |
1025 else | |
1026 { | |
1027 p = cmd; | |
1028 while (ASCII_ISALPHA(*p) || *p == '*') // Allow * wild card | |
1029 ++p; | |
1030 // a user command may contain digits | |
1031 if (ASCII_ISUPPER(cmd[0])) | |
1032 while (ASCII_ISALNUM(*p) || *p == '*') | |
1033 ++p; | |
1034 // for python 3.x: ":py3*" commands completion | |
1035 if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3') | |
1036 { | |
1037 ++p; | |
1038 while (ASCII_ISALPHA(*p) || *p == '*') | |
1039 ++p; | |
1040 } | |
1041 // check for non-alpha command | |
1042 if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) | |
1043 ++p; | |
1044 len = (int)(p - cmd); | |
1045 | |
1046 if (len == 0) | |
1047 { | |
1048 xp->xp_context = EXPAND_UNSUCCESSFUL; | |
1049 return NULL; | |
1050 } | |
1051 | |
1052 ea.cmdidx = excmd_get_cmdidx(cmd, len); | |
1053 | |
1054 if (cmd[0] >= 'A' && cmd[0] <= 'Z') | |
1055 while (ASCII_ISALNUM(*p) || *p == '*') // Allow * wild card | |
1056 ++p; | |
1057 } | |
1058 | |
1059 // If the cursor is touching the command, and it ends in an alpha-numeric | |
1060 // character, complete the command name. | |
1061 if (*p == NUL && ASCII_ISALNUM(p[-1])) | |
1062 return NULL; | |
1063 | |
1064 if (ea.cmdidx == CMD_SIZE) | |
1065 { | |
1066 if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) | |
1067 { | |
1068 ea.cmdidx = CMD_substitute; | |
1069 p = cmd + 1; | |
1070 } | |
1071 else if (cmd[0] >= 'A' && cmd[0] <= 'Z') | |
1072 { | |
1073 ea.cmd = cmd; | |
1074 p = find_ucmd(&ea, p, NULL, xp, &compl); | |
1075 if (p == NULL) | |
1076 ea.cmdidx = CMD_SIZE; // ambiguous user command | |
1077 } | |
1078 } | |
1079 if (ea.cmdidx == CMD_SIZE) | |
1080 { | |
1081 // Not still touching the command and it was an illegal one | |
1082 xp->xp_context = EXPAND_UNSUCCESSFUL; | |
1083 return NULL; | |
1084 } | |
1085 | |
1086 xp->xp_context = EXPAND_NOTHING; // Default now that we're past command | |
1087 | |
1088 if (*p == '!') // forced commands | |
1089 { | |
1090 forceit = TRUE; | |
1091 ++p; | |
1092 } | |
1093 | |
1094 // 6. parse arguments | |
1095 if (!IS_USER_CMDIDX(ea.cmdidx)) | |
1096 ea.argt = excmd_get_argt(ea.cmdidx); | |
1097 | |
1098 arg = skipwhite(p); | |
1099 | |
1100 if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) | |
1101 { | |
1102 if (*arg == '>') // append | |
1103 { | |
1104 if (*++arg == '>') | |
1105 ++arg; | |
1106 arg = skipwhite(arg); | |
1107 } | |
1108 else if (*arg == '!' && ea.cmdidx == CMD_write) // :w !filter | |
1109 { | |
1110 ++arg; | |
1111 usefilter = TRUE; | |
1112 } | |
1113 } | |
1114 | |
1115 if (ea.cmdidx == CMD_read) | |
1116 { | |
1117 usefilter = forceit; // :r! filter if forced | |
1118 if (*arg == '!') // :r !filter | |
1119 { | |
1120 ++arg; | |
1121 usefilter = TRUE; | |
1122 } | |
1123 } | |
1124 | |
1125 if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) | |
1126 { | |
1127 while (*arg == *cmd) // allow any number of '>' or '<' | |
1128 ++arg; | |
1129 arg = skipwhite(arg); | |
1130 } | |
1131 | |
1132 // Does command allow "+command"? | |
1133 if ((ea.argt & EX_CMDARG) && !usefilter && *arg == '+') | |
1134 { | |
1135 // Check if we're in the +command | |
1136 p = arg + 1; | |
1137 arg = skip_cmd_arg(arg, FALSE); | |
1138 | |
1139 // Still touching the command after '+'? | |
1140 if (*arg == NUL) | |
1141 return p; | |
1142 | |
1143 // Skip space(s) after +command to get to the real argument | |
1144 arg = skipwhite(arg); | |
1145 } | |
1146 | |
1147 // Check for '|' to separate commands and '"' to start comments. | |
1148 // Don't do this for ":read !cmd" and ":write !cmd". | |
1149 if ((ea.argt & EX_TRLBAR) && !usefilter) | |
1150 { | |
1151 p = arg; | |
1152 // ":redir @" is not the start of a comment | |
1153 if (ea.cmdidx == CMD_redir && p[0] == '@' && p[1] == '"') | |
1154 p += 2; | |
1155 while (*p) | |
1156 { | |
1157 if (*p == Ctrl_V) | |
1158 { | |
1159 if (p[1] != NUL) | |
1160 ++p; | |
1161 } | |
1162 else if ( (*p == '"' && !(ea.argt & EX_NOTRLCOM)) | |
1163 || *p == '|' || *p == '\n') | |
1164 { | |
1165 if (*(p - 1) != '\\') | |
1166 { | |
1167 if (*p == '|' || *p == '\n') | |
1168 return p + 1; | |
1169 return NULL; // It's a comment | |
1170 } | |
1171 } | |
1172 MB_PTR_ADV(p); | |
1173 } | |
1174 } | |
1175 | |
1176 if (!(ea.argt & EX_EXTRA) && *arg != NUL | |
1177 && vim_strchr((char_u *)"|\"", *arg) == NULL) | |
1178 // no arguments allowed but there is something | |
1179 return NULL; | |
1180 | |
1181 // Find start of last argument (argument just before cursor): | |
1182 p = buff; | |
1183 xp->xp_pattern = p; | |
1184 len = (int)STRLEN(buff); | |
1185 while (*p && p < buff + len) | |
1186 { | |
1187 if (*p == ' ' || *p == TAB) | |
1188 { | |
1189 // argument starts after a space | |
1190 xp->xp_pattern = ++p; | |
1191 } | |
1192 else | |
1193 { | |
1194 if (*p == '\\' && *(p + 1) != NUL) | |
1195 ++p; // skip over escaped character | |
1196 MB_PTR_ADV(p); | |
1197 } | |
1198 } | |
1199 | |
1200 if (ea.argt & EX_XFILE) | |
1201 { | |
1202 int c; | |
1203 int in_quote = FALSE; | |
1204 char_u *bow = NULL; // Beginning of word | |
1205 | |
1206 // Allow spaces within back-quotes to count as part of the argument | |
1207 // being expanded. | |
1208 xp->xp_pattern = skipwhite(arg); | |
1209 p = xp->xp_pattern; | |
1210 while (*p != NUL) | |
1211 { | |
1212 if (has_mbyte) | |
1213 c = mb_ptr2char(p); | |
1214 else | |
1215 c = *p; | |
1216 if (c == '\\' && p[1] != NUL) | |
1217 ++p; | |
1218 else if (c == '`') | |
1219 { | |
1220 if (!in_quote) | |
1221 { | |
1222 xp->xp_pattern = p; | |
1223 bow = p + 1; | |
1224 } | |
1225 in_quote = !in_quote; | |
1226 } | |
1227 // An argument can contain just about everything, except | |
1228 // characters that end the command and white space. | |
1229 else if (c == '|' || c == '\n' || c == '"' || (VIM_ISWHITE(c) | |
1230 #ifdef SPACE_IN_FILENAME | |
1231 && (!(ea.argt & EX_NOSPC) || usefilter) | |
1232 #endif | |
1233 )) | |
1234 { | |
1235 len = 0; // avoid getting stuck when space is in 'isfname' | |
1236 while (*p != NUL) | |
1237 { | |
1238 if (has_mbyte) | |
1239 c = mb_ptr2char(p); | |
1240 else | |
1241 c = *p; | |
1242 if (c == '`' || vim_isfilec_or_wc(c)) | |
1243 break; | |
1244 if (has_mbyte) | |
1245 len = (*mb_ptr2len)(p); | |
1246 else | |
1247 len = 1; | |
1248 MB_PTR_ADV(p); | |
1249 } | |
1250 if (in_quote) | |
1251 bow = p; | |
1252 else | |
1253 xp->xp_pattern = p; | |
1254 p -= len; | |
1255 } | |
1256 MB_PTR_ADV(p); | |
1257 } | |
1258 | |
1259 // If we are still inside the quotes, and we passed a space, just | |
1260 // expand from there. | |
1261 if (bow != NULL && in_quote) | |
1262 xp->xp_pattern = bow; | |
1263 xp->xp_context = EXPAND_FILES; | |
1264 | |
1265 // For a shell command more chars need to be escaped. | |
1266 if (usefilter || ea.cmdidx == CMD_bang || ea.cmdidx == CMD_terminal) | |
1267 { | |
1268 #ifndef BACKSLASH_IN_FILENAME | |
1269 xp->xp_shell = TRUE; | |
1270 #endif | |
1271 // When still after the command name expand executables. | |
1272 if (xp->xp_pattern == skipwhite(arg)) | |
1273 xp->xp_context = EXPAND_SHELLCMD; | |
1274 } | |
1275 | |
1276 // Check for environment variable | |
1277 if (*xp->xp_pattern == '$' | |
1278 #if defined(MSWIN) | |
1279 || *xp->xp_pattern == '%' | |
1280 #endif | |
1281 ) | |
1282 { | |
1283 for (p = xp->xp_pattern + 1; *p != NUL; ++p) | |
1284 if (!vim_isIDc(*p)) | |
1285 break; | |
1286 if (*p == NUL) | |
1287 { | |
1288 xp->xp_context = EXPAND_ENV_VARS; | |
1289 ++xp->xp_pattern; | |
1290 // Avoid that the assignment uses EXPAND_FILES again. | |
1291 if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST) | |
1292 compl = EXPAND_ENV_VARS; | |
1293 } | |
1294 } | |
1295 // Check for user names | |
1296 if (*xp->xp_pattern == '~') | |
1297 { | |
1298 for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p) | |
1299 ; | |
1300 // Complete ~user only if it partially matches a user name. | |
1301 // A full match ~user<Tab> will be replaced by user's home | |
1302 // directory i.e. something like ~user<Tab> -> /home/user/ | |
1303 if (*p == NUL && p > xp->xp_pattern + 1 | |
1304 && match_user(xp->xp_pattern + 1) >= 1) | |
1305 { | |
1306 xp->xp_context = EXPAND_USER; | |
1307 ++xp->xp_pattern; | |
1308 } | |
1309 } | |
1310 } | |
1311 | |
1312 // 6. Switch on command name. | |
1313 switch (ea.cmdidx) | |
1314 { | |
1315 case CMD_find: | |
1316 case CMD_sfind: | |
1317 case CMD_tabfind: | |
1318 if (xp->xp_context == EXPAND_FILES) | |
1319 xp->xp_context = EXPAND_FILES_IN_PATH; | |
1320 break; | |
1321 case CMD_cd: | |
1322 case CMD_chdir: | |
1323 case CMD_tcd: | |
1324 case CMD_tchdir: | |
1325 case CMD_lcd: | |
1326 case CMD_lchdir: | |
1327 if (xp->xp_context == EXPAND_FILES) | |
1328 xp->xp_context = EXPAND_DIRECTORIES; | |
1329 break; | |
1330 case CMD_help: | |
1331 xp->xp_context = EXPAND_HELP; | |
1332 xp->xp_pattern = arg; | |
1333 break; | |
1334 | |
1335 // Command modifiers: return the argument. | |
1336 // Also for commands with an argument that is a command. | |
1337 case CMD_aboveleft: | |
1338 case CMD_argdo: | |
1339 case CMD_belowright: | |
1340 case CMD_botright: | |
1341 case CMD_browse: | |
1342 case CMD_bufdo: | |
1343 case CMD_cdo: | |
1344 case CMD_cfdo: | |
1345 case CMD_confirm: | |
1346 case CMD_debug: | |
1347 case CMD_folddoclosed: | |
1348 case CMD_folddoopen: | |
1349 case CMD_hide: | |
1350 case CMD_keepalt: | |
1351 case CMD_keepjumps: | |
1352 case CMD_keepmarks: | |
1353 case CMD_keeppatterns: | |
1354 case CMD_ldo: | |
1355 case CMD_leftabove: | |
1356 case CMD_lfdo: | |
1357 case CMD_lockmarks: | |
1358 case CMD_noautocmd: | |
1359 case CMD_noswapfile: | |
1360 case CMD_rightbelow: | |
1361 case CMD_sandbox: | |
1362 case CMD_silent: | |
1363 case CMD_tab: | |
1364 case CMD_tabdo: | |
1365 case CMD_topleft: | |
1366 case CMD_verbose: | |
1367 case CMD_vertical: | |
1368 case CMD_windo: | |
1369 return arg; | |
1370 | |
1371 case CMD_filter: | |
1372 if (*arg != NUL) | |
1373 arg = skip_vimgrep_pat(arg, NULL, NULL); | |
1374 if (arg == NULL || *arg == NUL) | |
1375 { | |
1376 xp->xp_context = EXPAND_NOTHING; | |
1377 return NULL; | |
1378 } | |
1379 return skipwhite(arg); | |
1380 | |
1381 #ifdef FEAT_SEARCH_EXTRA | |
1382 case CMD_match: | |
1383 if (*arg == NUL || !ends_excmd(*arg)) | |
1384 { | |
1385 // also complete "None" | |
1386 set_context_in_echohl_cmd(xp, arg); | |
1387 arg = skipwhite(skiptowhite(arg)); | |
1388 if (*arg != NUL) | |
1389 { | |
1390 xp->xp_context = EXPAND_NOTHING; | |
1391 arg = skip_regexp(arg + 1, *arg, p_magic, NULL); | |
1392 } | |
1393 } | |
1394 return find_nextcmd(arg); | |
1395 #endif | |
1396 | |
1397 // All completion for the +cmdline_compl feature goes here. | |
1398 | |
1399 case CMD_command: | |
1400 return set_context_in_user_cmd(xp, arg); | |
1401 | |
1402 case CMD_delcommand: | |
1403 xp->xp_context = EXPAND_USER_COMMANDS; | |
1404 xp->xp_pattern = arg; | |
1405 break; | |
1406 | |
1407 case CMD_global: | |
1408 case CMD_vglobal: | |
1409 delim = *arg; // get the delimiter | |
1410 if (delim) | |
1411 ++arg; // skip delimiter if there is one | |
1412 | |
1413 while (arg[0] != NUL && arg[0] != delim) | |
1414 { | |
1415 if (arg[0] == '\\' && arg[1] != NUL) | |
1416 ++arg; | |
1417 ++arg; | |
1418 } | |
1419 if (arg[0] != NUL) | |
1420 return arg + 1; | |
1421 break; | |
1422 case CMD_and: | |
1423 case CMD_substitute: | |
1424 delim = *arg; | |
1425 if (delim) | |
1426 { | |
1427 // skip "from" part | |
1428 ++arg; | |
1429 arg = skip_regexp(arg, delim, p_magic, NULL); | |
1430 } | |
1431 // skip "to" part | |
1432 while (arg[0] != NUL && arg[0] != delim) | |
1433 { | |
1434 if (arg[0] == '\\' && arg[1] != NUL) | |
1435 ++arg; | |
1436 ++arg; | |
1437 } | |
1438 if (arg[0] != NUL) // skip delimiter | |
1439 ++arg; | |
1440 while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL) | |
1441 ++arg; | |
1442 if (arg[0] != NUL) | |
1443 return arg; | |
1444 break; | |
1445 case CMD_isearch: | |
1446 case CMD_dsearch: | |
1447 case CMD_ilist: | |
1448 case CMD_dlist: | |
1449 case CMD_ijump: | |
1450 case CMD_psearch: | |
1451 case CMD_djump: | |
1452 case CMD_isplit: | |
1453 case CMD_dsplit: | |
1454 arg = skipwhite(skipdigits(arg)); // skip count | |
1455 if (*arg == '/') // Match regexp, not just whole words | |
1456 { | |
1457 for (++arg; *arg && *arg != '/'; arg++) | |
1458 if (*arg == '\\' && arg[1] != NUL) | |
1459 arg++; | |
1460 if (*arg) | |
1461 { | |
1462 arg = skipwhite(arg + 1); | |
1463 | |
1464 // Check for trailing illegal characters | |
1465 if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL) | |
1466 xp->xp_context = EXPAND_NOTHING; | |
1467 else | |
1468 return arg; | |
1469 } | |
1470 } | |
1471 break; | |
1472 | |
1473 case CMD_autocmd: | |
1474 return set_context_in_autocmd(xp, arg, FALSE); | |
1475 case CMD_doautocmd: | |
1476 case CMD_doautoall: | |
1477 return set_context_in_autocmd(xp, arg, TRUE); | |
1478 case CMD_set: | |
1479 set_context_in_set_cmd(xp, arg, 0); | |
1480 break; | |
1481 case CMD_setglobal: | |
1482 set_context_in_set_cmd(xp, arg, OPT_GLOBAL); | |
1483 break; | |
1484 case CMD_setlocal: | |
1485 set_context_in_set_cmd(xp, arg, OPT_LOCAL); | |
1486 break; | |
1487 case CMD_tag: | |
1488 case CMD_stag: | |
1489 case CMD_ptag: | |
1490 case CMD_ltag: | |
1491 case CMD_tselect: | |
1492 case CMD_stselect: | |
1493 case CMD_ptselect: | |
1494 case CMD_tjump: | |
1495 case CMD_stjump: | |
1496 case CMD_ptjump: | |
1497 if (*p_wop != NUL) | |
1498 xp->xp_context = EXPAND_TAGS_LISTFILES; | |
1499 else | |
1500 xp->xp_context = EXPAND_TAGS; | |
1501 xp->xp_pattern = arg; | |
1502 break; | |
1503 case CMD_augroup: | |
1504 xp->xp_context = EXPAND_AUGROUP; | |
1505 xp->xp_pattern = arg; | |
1506 break; | |
1507 #ifdef FEAT_SYN_HL | |
1508 case CMD_syntax: | |
1509 set_context_in_syntax_cmd(xp, arg); | |
1510 break; | |
1511 #endif | |
1512 #ifdef FEAT_EVAL | |
1513 case CMD_let: | |
1514 case CMD_if: | |
1515 case CMD_elseif: | |
1516 case CMD_while: | |
1517 case CMD_for: | |
1518 case CMD_echo: | |
1519 case CMD_echon: | |
1520 case CMD_execute: | |
1521 case CMD_echomsg: | |
1522 case CMD_echoerr: | |
1523 case CMD_call: | |
1524 case CMD_return: | |
1525 case CMD_cexpr: | |
1526 case CMD_caddexpr: | |
1527 case CMD_cgetexpr: | |
1528 case CMD_lexpr: | |
1529 case CMD_laddexpr: | |
1530 case CMD_lgetexpr: | |
1531 set_context_for_expression(xp, arg, ea.cmdidx); | |
1532 break; | |
1533 | |
1534 case CMD_unlet: | |
1535 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) | |
1536 arg = xp->xp_pattern + 1; | |
1537 | |
1538 xp->xp_context = EXPAND_USER_VARS; | |
1539 xp->xp_pattern = arg; | |
1540 | |
1541 if (*xp->xp_pattern == '$') | |
1542 { | |
1543 xp->xp_context = EXPAND_ENV_VARS; | |
1544 ++xp->xp_pattern; | |
1545 } | |
1546 | |
1547 break; | |
1548 | |
1549 case CMD_function: | |
1550 case CMD_delfunction: | |
1551 xp->xp_context = EXPAND_USER_FUNC; | |
1552 xp->xp_pattern = arg; | |
1553 break; | |
1554 | |
1555 case CMD_echohl: | |
1556 set_context_in_echohl_cmd(xp, arg); | |
1557 break; | |
1558 #endif | |
1559 case CMD_highlight: | |
1560 set_context_in_highlight_cmd(xp, arg); | |
1561 break; | |
1562 #ifdef FEAT_CSCOPE | |
1563 case CMD_cscope: | |
1564 case CMD_lcscope: | |
1565 case CMD_scscope: | |
1566 set_context_in_cscope_cmd(xp, arg, ea.cmdidx); | |
1567 break; | |
1568 #endif | |
1569 #ifdef FEAT_SIGNS | |
1570 case CMD_sign: | |
1571 set_context_in_sign_cmd(xp, arg); | |
1572 break; | |
1573 #endif | |
1574 case CMD_bdelete: | |
1575 case CMD_bwipeout: | |
1576 case CMD_bunload: | |
1577 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) | |
1578 arg = xp->xp_pattern + 1; | |
1579 // FALLTHROUGH | |
1580 case CMD_buffer: | |
1581 case CMD_sbuffer: | |
1582 case CMD_checktime: | |
1583 xp->xp_context = EXPAND_BUFFERS; | |
1584 xp->xp_pattern = arg; | |
1585 break; | |
1586 | |
1587 case CMD_USER: | |
1588 case CMD_USER_BUF: | |
1589 if (compl != EXPAND_NOTHING) | |
1590 { | |
1591 // EX_XFILE: file names are handled above | |
1592 if (!(ea.argt & EX_XFILE)) | |
1593 { | |
1594 #ifdef FEAT_MENU | |
1595 if (compl == EXPAND_MENUS) | |
1596 return set_context_in_menu_cmd(xp, cmd, arg, forceit); | |
1597 #endif | |
1598 if (compl == EXPAND_COMMANDS) | |
1599 return arg; | |
1600 if (compl == EXPAND_MAPPINGS) | |
1601 return set_context_in_map_cmd(xp, (char_u *)"map", | |
1602 arg, forceit, FALSE, FALSE, CMD_map); | |
1603 // Find start of last argument. | |
1604 p = arg; | |
1605 while (*p) | |
1606 { | |
1607 if (*p == ' ') | |
1608 // argument starts after a space | |
1609 arg = p + 1; | |
1610 else if (*p == '\\' && *(p + 1) != NUL) | |
1611 ++p; // skip over escaped character | |
1612 MB_PTR_ADV(p); | |
1613 } | |
1614 xp->xp_pattern = arg; | |
1615 } | |
1616 xp->xp_context = compl; | |
1617 } | |
1618 break; | |
1619 | |
1620 case CMD_map: case CMD_noremap: | |
1621 case CMD_nmap: case CMD_nnoremap: | |
1622 case CMD_vmap: case CMD_vnoremap: | |
1623 case CMD_omap: case CMD_onoremap: | |
1624 case CMD_imap: case CMD_inoremap: | |
1625 case CMD_cmap: case CMD_cnoremap: | |
1626 case CMD_lmap: case CMD_lnoremap: | |
1627 case CMD_smap: case CMD_snoremap: | |
1628 case CMD_tmap: case CMD_tnoremap: | |
1629 case CMD_xmap: case CMD_xnoremap: | |
1630 return set_context_in_map_cmd(xp, cmd, arg, forceit, | |
1631 FALSE, FALSE, ea.cmdidx); | |
1632 case CMD_unmap: | |
1633 case CMD_nunmap: | |
1634 case CMD_vunmap: | |
1635 case CMD_ounmap: | |
1636 case CMD_iunmap: | |
1637 case CMD_cunmap: | |
1638 case CMD_lunmap: | |
1639 case CMD_sunmap: | |
1640 case CMD_tunmap: | |
1641 case CMD_xunmap: | |
1642 return set_context_in_map_cmd(xp, cmd, arg, forceit, | |
1643 FALSE, TRUE, ea.cmdidx); | |
1644 case CMD_mapclear: | |
1645 case CMD_nmapclear: | |
1646 case CMD_vmapclear: | |
1647 case CMD_omapclear: | |
1648 case CMD_imapclear: | |
1649 case CMD_cmapclear: | |
1650 case CMD_lmapclear: | |
1651 case CMD_smapclear: | |
1652 case CMD_tmapclear: | |
1653 case CMD_xmapclear: | |
1654 xp->xp_context = EXPAND_MAPCLEAR; | |
1655 xp->xp_pattern = arg; | |
1656 break; | |
1657 | |
1658 case CMD_abbreviate: case CMD_noreabbrev: | |
1659 case CMD_cabbrev: case CMD_cnoreabbrev: | |
1660 case CMD_iabbrev: case CMD_inoreabbrev: | |
1661 return set_context_in_map_cmd(xp, cmd, arg, forceit, | |
1662 TRUE, FALSE, ea.cmdidx); | |
1663 case CMD_unabbreviate: | |
1664 case CMD_cunabbrev: | |
1665 case CMD_iunabbrev: | |
1666 return set_context_in_map_cmd(xp, cmd, arg, forceit, | |
1667 TRUE, TRUE, ea.cmdidx); | |
1668 #ifdef FEAT_MENU | |
1669 case CMD_menu: case CMD_noremenu: case CMD_unmenu: | |
1670 case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu: | |
1671 case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu: | |
1672 case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu: | |
1673 case CMD_omenu: case CMD_onoremenu: case CMD_ounmenu: | |
1674 case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu: | |
1675 case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: | |
1676 case CMD_tlmenu: case CMD_tlnoremenu: case CMD_tlunmenu: | |
1677 case CMD_tmenu: case CMD_tunmenu: | |
1678 case CMD_popup: case CMD_tearoff: case CMD_emenu: | |
1679 return set_context_in_menu_cmd(xp, cmd, arg, forceit); | |
1680 #endif | |
1681 | |
1682 case CMD_colorscheme: | |
1683 xp->xp_context = EXPAND_COLORS; | |
1684 xp->xp_pattern = arg; | |
1685 break; | |
1686 | |
1687 case CMD_compiler: | |
1688 xp->xp_context = EXPAND_COMPILER; | |
1689 xp->xp_pattern = arg; | |
1690 break; | |
1691 | |
1692 case CMD_ownsyntax: | |
1693 xp->xp_context = EXPAND_OWNSYNTAX; | |
1694 xp->xp_pattern = arg; | |
1695 break; | |
1696 | |
1697 case CMD_setfiletype: | |
1698 xp->xp_context = EXPAND_FILETYPE; | |
1699 xp->xp_pattern = arg; | |
1700 break; | |
1701 | |
1702 case CMD_packadd: | |
1703 xp->xp_context = EXPAND_PACKADD; | |
1704 xp->xp_pattern = arg; | |
1705 break; | |
1706 | |
1707 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) | |
1708 case CMD_language: | |
1709 p = skiptowhite(arg); | |
1710 if (*p == NUL) | |
1711 { | |
1712 xp->xp_context = EXPAND_LANGUAGE; | |
1713 xp->xp_pattern = arg; | |
1714 } | |
1715 else | |
1716 { | |
1717 if ( STRNCMP(arg, "messages", p - arg) == 0 | |
1718 || STRNCMP(arg, "ctype", p - arg) == 0 | |
1719 || STRNCMP(arg, "time", p - arg) == 0) | |
1720 { | |
1721 xp->xp_context = EXPAND_LOCALES; | |
1722 xp->xp_pattern = skipwhite(p); | |
1723 } | |
1724 else | |
1725 xp->xp_context = EXPAND_NOTHING; | |
1726 } | |
1727 break; | |
1728 #endif | |
1729 #if defined(FEAT_PROFILE) | |
1730 case CMD_profile: | |
1731 set_context_in_profile_cmd(xp, arg); | |
1732 break; | |
1733 #endif | |
1734 case CMD_behave: | |
1735 xp->xp_context = EXPAND_BEHAVE; | |
1736 xp->xp_pattern = arg; | |
1737 break; | |
1738 | |
1739 case CMD_messages: | |
1740 xp->xp_context = EXPAND_MESSAGES; | |
1741 xp->xp_pattern = arg; | |
1742 break; | |
1743 | |
1744 case CMD_history: | |
1745 xp->xp_context = EXPAND_HISTORY; | |
1746 xp->xp_pattern = arg; | |
1747 break; | |
1748 #if defined(FEAT_PROFILE) | |
1749 case CMD_syntime: | |
1750 xp->xp_context = EXPAND_SYNTIME; | |
1751 xp->xp_pattern = arg; | |
1752 break; | |
1753 #endif | |
1754 | |
1755 case CMD_argdelete: | |
1756 while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL) | |
1757 arg = xp->xp_pattern + 1; | |
1758 xp->xp_context = EXPAND_ARGLIST; | |
1759 xp->xp_pattern = arg; | |
1760 break; | |
1761 | |
1762 default: | |
1763 break; | |
1764 } | |
1765 return NULL; | |
1766 } | |
1767 | |
962 void | 1768 void |
963 set_cmd_context( | 1769 set_cmd_context( |
964 expand_T *xp, | 1770 expand_T *xp, |
965 char_u *str, // start of command line | 1771 char_u *str, // start of command line |
966 int len, // length of command line (excl. NUL) | 1772 int len, // length of command line (excl. NUL) |
1111 file[i][len] = NUL; | 1917 file[i][len] = NUL; |
1112 } | 1918 } |
1113 } | 1919 } |
1114 } | 1920 } |
1115 #endif | 1921 #endif |
1922 | |
1923 /* | |
1924 * Function given to ExpandGeneric() to obtain the possible arguments of the | |
1925 * ":behave {mswin,xterm}" command. | |
1926 */ | |
1927 static char_u * | |
1928 get_behave_arg(expand_T *xp UNUSED, int idx) | |
1929 { | |
1930 if (idx == 0) | |
1931 return (char_u *)"mswin"; | |
1932 if (idx == 1) | |
1933 return (char_u *)"xterm"; | |
1934 return NULL; | |
1935 } | |
1936 | |
1937 /* | |
1938 * Function given to ExpandGeneric() to obtain the possible arguments of the | |
1939 * ":messages {clear}" command. | |
1940 */ | |
1941 static char_u * | |
1942 get_messages_arg(expand_T *xp UNUSED, int idx) | |
1943 { | |
1944 if (idx == 0) | |
1945 return (char_u *)"clear"; | |
1946 return NULL; | |
1947 } | |
1948 | |
1949 static char_u * | |
1950 get_mapclear_arg(expand_T *xp UNUSED, int idx) | |
1951 { | |
1952 if (idx == 0) | |
1953 return (char_u *)"<buffer>"; | |
1954 return NULL; | |
1955 } | |
1116 | 1956 |
1117 /* | 1957 /* |
1118 * Do the expansion based on xp->xp_context and "pat". | 1958 * Do the expansion based on xp->xp_context and "pat". |
1119 */ | 1959 */ |
1120 static int | 1960 static int |