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