comparison src/ex_cmds2.c @ 20818:a0b147774bd4 v8.2.0961

patch 8.2.0961: MS-Windows: no completion for locales Commit: https://github.com/vim/vim/commit/ec68028604b6ee799b2ef5fc861ec5163e82914f Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jun 12 19:35:32 2020 +0200 patch 8.2.0961: MS-Windows: no completion for locales Problem: MS-Windows: no completion for locales. Solution: Use the directories in $VIMRUNTIME/lang to complete locales. (Christian Brabandt, closes 36248)
author Bram Moolenaar <Bram@vim.org>
date Fri, 12 Jun 2020 19:45:04 +0200
parents 5788b78a1af0
children 69055d27e85e
comparison
equal deleted inserted replaced
20817:ed270e2a7a64 20818:a0b147774bd4
1186 # endif 1186 # endif
1187 set_vim_var_string(VV_LC_TIME, loc, -1); 1187 set_vim_var_string(VV_LC_TIME, loc, -1);
1188 } 1188 }
1189 #endif 1189 #endif
1190 1190
1191 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) \ 1191 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
1192 /* 1192 /*
1193 * ":language": Set the language (locale). 1193 * ":language": Set the language (locale).
1194 */ 1194 */
1195 void 1195 void
1196 ex_language(exarg_T *eap) 1196 ex_language(exarg_T *eap)
1198 char *loc; 1198 char *loc;
1199 char_u *p; 1199 char_u *p;
1200 char_u *name; 1200 char_u *name;
1201 int what = LC_ALL; 1201 int what = LC_ALL;
1202 char *whatstr = ""; 1202 char *whatstr = "";
1203 #ifdef LC_MESSAGES 1203 # ifdef LC_MESSAGES
1204 # define VIM_LC_MESSAGES LC_MESSAGES 1204 # define VIM_LC_MESSAGES LC_MESSAGES
1205 #else 1205 # else
1206 # define VIM_LC_MESSAGES 6789 1206 # define VIM_LC_MESSAGES 6789
1207 #endif 1207 # endif
1208 1208
1209 name = eap->arg; 1209 name = eap->arg;
1210 1210
1211 // Check for "messages {name}", "ctype {name}" or "time {name}" argument. 1211 // Check for "messages {name}", "ctype {name}" or "time {name}" argument.
1212 // Allow abbreviation, but require at least 3 characters to avoid 1212 // Allow abbreviation, but require at least 3 characters to avoid
1234 } 1234 }
1235 } 1235 }
1236 1236
1237 if (*name == NUL) 1237 if (*name == NUL)
1238 { 1238 {
1239 #ifndef LC_MESSAGES 1239 # ifndef LC_MESSAGES
1240 if (what == VIM_LC_MESSAGES) 1240 if (what == VIM_LC_MESSAGES)
1241 p = get_mess_env(); 1241 p = get_mess_env();
1242 else 1242 else
1243 #endif 1243 # endif
1244 p = (char_u *)setlocale(what, NULL); 1244 p = (char_u *)setlocale(what, NULL);
1245 if (p == NULL || *p == NUL) 1245 if (p == NULL || *p == NUL)
1246 p = (char_u *)"Unknown"; 1246 p = (char_u *)"Unknown";
1247 smsg(_("Current %slanguage: \"%s\""), whatstr, p); 1247 smsg(_("Current %slanguage: \"%s\""), whatstr, p);
1248 } 1248 }
1249 else 1249 else
1250 { 1250 {
1251 #ifndef LC_MESSAGES 1251 # ifndef LC_MESSAGES
1252 if (what == VIM_LC_MESSAGES) 1252 if (what == VIM_LC_MESSAGES)
1253 loc = ""; 1253 loc = "";
1254 else 1254 else
1255 #endif 1255 # endif
1256 { 1256 {
1257 loc = setlocale(what, (char *)name); 1257 loc = setlocale(what, (char *)name);
1258 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC) 1258 # if defined(FEAT_FLOAT) && defined(LC_NUMERIC)
1259 // Make sure strtod() uses a decimal point, not a comma. 1259 // Make sure strtod() uses a decimal point, not a comma.
1260 setlocale(LC_NUMERIC, "C"); 1260 setlocale(LC_NUMERIC, "C");
1261 #endif 1261 # endif
1262 } 1262 }
1263 if (loc == NULL) 1263 if (loc == NULL)
1264 semsg(_("E197: Cannot set language to \"%s\""), name); 1264 semsg(_("E197: Cannot set language to \"%s\""), name);
1265 else 1265 else
1266 { 1266 {
1267 #ifdef HAVE_NL_MSG_CAT_CNTR 1267 # ifdef HAVE_NL_MSG_CAT_CNTR
1268 // Need to do this for GNU gettext, otherwise cached translations 1268 // Need to do this for GNU gettext, otherwise cached translations
1269 // will be used again. 1269 // will be used again.
1270 extern int _nl_msg_cat_cntr; 1270 extern int _nl_msg_cat_cntr;
1271 1271
1272 ++_nl_msg_cat_cntr; 1272 ++_nl_msg_cat_cntr;
1273 #endif 1273 # endif
1274 // Reset $LC_ALL, otherwise it would overrule everything. 1274 // Reset $LC_ALL, otherwise it would overrule everything.
1275 vim_setenv((char_u *)"LC_ALL", (char_u *)""); 1275 vim_setenv((char_u *)"LC_ALL", (char_u *)"");
1276 1276
1277 if (what != LC_TIME) 1277 if (what != LC_TIME)
1278 { 1278 {
1294 # endif 1294 # endif
1295 } 1295 }
1296 if (what != LC_CTYPE) 1296 if (what != LC_CTYPE)
1297 { 1297 {
1298 char_u *mname; 1298 char_u *mname;
1299 #ifdef MSWIN 1299 # ifdef MSWIN
1300 mname = gettext_lang(name); 1300 mname = gettext_lang(name);
1301 #else 1301 # else
1302 mname = name; 1302 mname = name;
1303 #endif 1303 # endif
1304 vim_setenv((char_u *)"LC_MESSAGES", mname); 1304 vim_setenv((char_u *)"LC_MESSAGES", mname);
1305 #ifdef FEAT_MULTI_LANG 1305 # ifdef FEAT_MULTI_LANG
1306 set_helplang_default(mname); 1306 set_helplang_default(mname);
1307 #endif 1307 # endif
1308 } 1308 }
1309 } 1309 }
1310 1310
1311 # ifdef FEAT_EVAL 1311 # ifdef FEAT_EVAL
1312 // Set v:lang, v:lc_time and v:ctype to the final result. 1312 // Set v:lang, v:lc_time and v:ctype to the final result.
1319 } 1319 }
1320 } 1320 }
1321 1321
1322 static char_u **locales = NULL; // Array of all available locales 1322 static char_u **locales = NULL; // Array of all available locales
1323 1323
1324 # ifndef MSWIN
1325 static int did_init_locales = FALSE; 1324 static int did_init_locales = FALSE;
1326 1325
1327 /* 1326 /*
1328 * Return an array of strings for all available locales + NULL for the 1327 * Return an array of strings for all available locales + NULL for the
1329 * last element. Return NULL in case of error. 1328 * last element. Return NULL in case of error.
1331 static char_u ** 1330 static char_u **
1332 find_locales(void) 1331 find_locales(void)
1333 { 1332 {
1334 garray_T locales_ga; 1333 garray_T locales_ga;
1335 char_u *loc; 1334 char_u *loc;
1335 char_u *locale_list;
1336 # ifdef MSWIN
1337 size_t len = 0;
1338 # endif
1336 1339
1337 // Find all available locales by running command "locale -a". If this 1340 // Find all available locales by running command "locale -a". If this
1338 // doesn't work we won't have completion. 1341 // doesn't work we won't have completion.
1339 char_u *locale_a = get_cmd_output((char_u *)"locale -a", 1342 # ifndef MSWIN
1343 locale_list = get_cmd_output((char_u *)"locale -a",
1340 NULL, SHELL_SILENT, NULL); 1344 NULL, SHELL_SILENT, NULL);
1341 if (locale_a == NULL) 1345 # else
1346 // Find all available locales by examining the directories in
1347 // $VIMRUNTIME/lang/
1348 {
1349 int options = WILD_SILENT|WILD_USE_NL|WILD_KEEP_ALL;
1350 expand_T xpc;
1351 char_u *p;
1352
1353 ExpandInit(&xpc);
1354 xpc.xp_context = EXPAND_DIRECTORIES;
1355 locale_list = ExpandOne(&xpc, (char_u *)"$VIMRUNTIME/lang/*",
1356 NULL, options, WILD_ALL);
1357 ExpandCleanup(&xpc);
1358 if (locale_list == NULL)
1359 // Add a dummy input, that will be skipped lated but we need to
1360 // have something in locale_list so that the C locale is added at
1361 // the end.
1362 locale_list = vim_strsave((char_u *)".\n");
1363 p = locale_list;
1364 // find the last directory delimiter
1365 while (p != NULL && *p != NUL)
1366 {
1367 if (*p == '\n')
1368 break;
1369 if (*p == '\\')
1370 len = p - locale_list;
1371 p++;
1372 }
1373 }
1374 # endif
1375 if (locale_list == NULL)
1342 return NULL; 1376 return NULL;
1343 ga_init2(&locales_ga, sizeof(char_u *), 20); 1377 ga_init2(&locales_ga, sizeof(char_u *), 20);
1344 1378
1345 // Transform locale_a string where each locale is separated by "\n" 1379 // Transform locale_list string where each locale is separated by "\n"
1346 // into an array of locale strings. 1380 // into an array of locale strings.
1347 loc = (char_u *)strtok((char *)locale_a, "\n"); 1381 loc = (char_u *)strtok((char *)locale_list, "\n");
1348 1382
1349 while (loc != NULL) 1383 while (loc != NULL)
1350 { 1384 {
1351 if (ga_grow(&locales_ga, 1) == FAIL) 1385 int ignore = FALSE;
1352 break; 1386
1353 loc = vim_strsave(loc); 1387 # ifdef MSWIN
1354 if (loc == NULL) 1388 if (len > 0)
1355 break; 1389 loc += len + 1;
1356 1390 // skip locales with a dot (which indicates the charset)
1357 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] = loc; 1391 if (vim_strchr(loc, '.') != NULL)
1392 ignore = TRUE;
1393 # endif
1394 if (!ignore)
1395 {
1396 if (ga_grow(&locales_ga, 1) == FAIL)
1397 break;
1398
1399 loc = vim_strsave(loc);
1400 if (loc == NULL)
1401 break;
1402
1403 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] = loc;
1404 }
1358 loc = (char_u *)strtok(NULL, "\n"); 1405 loc = (char_u *)strtok(NULL, "\n");
1359 } 1406 }
1360 vim_free(locale_a); 1407
1408 # ifdef MSWIN
1409 // Add the C locale
1410 if (ga_grow(&locales_ga, 1) == OK)
1411 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] =
1412 vim_strsave((char_u *)"C");
1413 # endif
1414
1415 vim_free(locale_list);
1361 if (ga_grow(&locales_ga, 1) == FAIL) 1416 if (ga_grow(&locales_ga, 1) == FAIL)
1362 { 1417 {
1363 ga_clear(&locales_ga); 1418 ga_clear(&locales_ga);
1364 return NULL; 1419 return NULL;
1365 } 1420 }
1366 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; 1421 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
1367 return (char_u **)locales_ga.ga_data; 1422 return (char_u **)locales_ga.ga_data;
1368 } 1423 }
1369 # endif
1370 1424
1371 /* 1425 /*
1372 * Lazy initialization of all available locales. 1426 * Lazy initialization of all available locales.
1373 */ 1427 */
1374 static void 1428 static void
1375 init_locales(void) 1429 init_locales(void)
1376 { 1430 {
1377 # ifndef MSWIN
1378 if (!did_init_locales) 1431 if (!did_init_locales)
1379 { 1432 {
1380 did_init_locales = TRUE; 1433 did_init_locales = TRUE;
1381 locales = find_locales(); 1434 locales = find_locales();
1382 } 1435 }
1383 # endif 1436 }
1384 } 1437
1385 1438 # if defined(EXITFREE) || defined(PROTO)
1386 # if defined(EXITFREE) || defined(PROTO)
1387 void 1439 void
1388 free_locales(void) 1440 free_locales(void)
1389 { 1441 {
1390 int i; 1442 int i;
1391 if (locales != NULL) 1443 if (locales != NULL)
1393 for (i = 0; locales[i] != NULL; i++) 1445 for (i = 0; locales[i] != NULL; i++)
1394 vim_free(locales[i]); 1446 vim_free(locales[i]);
1395 VIM_CLEAR(locales); 1447 VIM_CLEAR(locales);
1396 } 1448 }
1397 } 1449 }
1398 # endif 1450 # endif
1399 1451
1400 /* 1452 /*
1401 * Function given to ExpandGeneric() to obtain the possible arguments of the 1453 * Function given to ExpandGeneric() to obtain the possible arguments of the
1402 * ":language" command. 1454 * ":language" command.
1403 */ 1455 */