[r200]: trunk / doc / eval.txt Maximize Restore History

Download this file

eval.txt    7232 lines (6163 with data), 297.6 kB

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
*eval.txt* For Vim version 7.3. 最近更新: 2010年8月
VIM 参考手册 by Bram Moolenaar
译者: Willis
http://vimcdoc.sf.net
表达式求值 *expression* *expr* *E15* *eval*
用户手册第 41 章 |usr_41.txt| 有使用表达式的介绍。
注意: 表达式求值可以在编译时关闭。如果你这么做,本文档介绍的特性就不复存在。见
|+eval| 和 |no-eval-feature|。
1. 变量 |variables|
1.1 变量类型
1.2 函数引用 |Funcref|
1.3 列表 |Lists|
1.4 字典 |Dictionaries|
1.5 变量的更多细节 |more-variables|
2. 表达式语法 |expression-syntax|
3. 内部变量 |internal-variables|
4. 内建函数 |functions|
5. 定义函数 |user-functions|
6. 花括号名字 |curly-braces-names|
7. 命令 |expression-commands|
8. 例外处理 |exception-handling|
9. 示例 |eval-examples|
10. 不包含 +eval 特性 |no-eval-feature|
11. 沙盘 (sandbox) |eval-sandbox|
12. 文本锁 |textlock|
{Vi 无此功能}
==============================================================================
1. 变量 *variables*
1.1 变量类型 ~
*E712*
有六种类型的变量:
数值 32 位带符号整数。|expr-number| *Number*
示例: -123 0x10 0177
浮点数 带小数的数值。|floating-point-format| *Float*
{仅当编译时加入 |+float| 特性才有效}
示例: 123.456 1.15e-6 -1.1e3
字符串 NUL 结尾的 8 位无符号字符 (即字节) 的串。|expr-string|
示例: "ab\txx\"--" 'x-z''a,c'
函数引用 指向一个函数的引用 |Funcref|。
示例: function("strlen")
列表 项目的有序的序列 |List|。
示例: [1, 2, ['a', 'b']]
字典 关联的无序数组: 每个项目包含一个键和一个值。|Dictionary|
示例: {'blue': "#0000ff", 'red': "#ff0000"}
数值和字符串类型之间会根据使用的情况自动转换。
数值到字符串的转换使用数值的 ASCII 表示。例如: >
数值 123 --> 字符串 "123"
数值 0 --> 字符串 "0"
数值 -1 --> 字符串 "-1"
<
*octal*
字符串到数值的转换则把字符串开头的一系列数字位转换成数值。十六进制 "0xf9" 和八
进制 "017" 形式的数值可以识别。如果字符串不以数字开始,则结果为零。例如: >
字符串 "456" --> 数值 456
字符串 "6bar" --> 数值 6
字符串 "foo" --> 数值 0
字符串 "0xf1" --> 数值 241
字符串 "0100" --> 数值 64
字符串 "-8" --> 数值 -8
字符串 "+8" --> 数值 0
要强制从字符串转换到数值,给它加零: >
:echo "0100" + 0
< 64 ~
要避免开头的零导致八进制的转换,或者想换不同的基底,用 |str2nr()|。
布尔型的操作使用数值类型。零代表假值 (FALSE),非零代表真值 (TRUE)。
注意 在命令 >
:if "foo"
里,"foo" 被转换成 0,也就是假值。要测试字符串非空,应该使用 strlen(): >
:if strlen("foo")
< *E745* *E728* *E703* *E729* *E730* *E731*
列表、字典和函数引用类型不会自动进行转换。
*E805* *E806* *E808*
混合数值和浮点数的计算时,数值转换为浮点数。否则没有自动到浮点数的转换。用
str2float() 可转换字符串到浮点数,printf() 从浮点数到字符串,float2nr() 则从浮
点数到数值。
*E706* *sticky-type-checking*
如果你试图改变变量类型,你会得到错误。先 |:unlet| 可以避免此错误。不过,字符串
和数值被认为是等价的类型,浮点数和数值之间也是如此。考虑如下的命令序列: >
:let l = "string"
:let l = 44 " 类型从字符串改为数值
:let l = [1, 2, 3] " 出错!l 仍为数值
:let l = 4.4 " 类型从数值改为浮点数
:let l = "string" " 出错!
1.2 函数引用 ~
*Funcref* *E695* *E718*
函数引用变量可以通过 |function()| 函数得到。可以在表达式里用它来代替函数名,在
围绕参数的括号之前,以调用它引用的函数。例如: >
:let Fn = function("MyFunc")
:echo Fn()
< *E704* *E705* *E707*
函数引用变量必须以大写字母、"s:"、"w:"、"t:" 或 "b:" 开始。函数引用变量不能和
任何函数重名。
特例是可以定义函数并直接把它的函数引用赋给字典的一个项目。例如: >
:function dict.init() dict
: let self.val = 0
:endfunction
该字典的键可以用小写字母开始。这里不用实际的函数名。另见 |numbered-function|。
函数引用可以用 |:call| 命令调用: >
:call Fn()
:call dict.init()
所引用的函数的名字可以用 |string()| 得到, >
:let func = string(Fn)
你可以用 |call()| 来调用函数引用并用一个列表变量来传递参数: >
:let r = call(Fn, mylist)
1.3 列表 ~
*List* *Lists* *E686*
列表是项目的有序序列。项目可以是任何类型,用索引号可以进行访问。可以在序列的任
何位置上增加或者删除项目。
列表建立 ~
*E696* *E697*
列表用方括号里逗号分隔的项目序列建立。例如: >
:let mylist = [1, two, 3, "four"]
:let emptylist = []
项目可以是任何表达式。用列表作为项目就能建立列表的列表: >
:let nestlist = [[11, 12], [21, 22], [31, 32]]
忽略末项之后额外的逗号。
列表索引 ~
*list-index* *E684*
在列表之后的方括号中放上索引号可以访问列表项目。索引从零开始,也就是说,第一个
项目的索引值为零。 >
:let item = mylist[0] " 得到第一个项目: 1
:let item = mylist[2] " 得到第三个项目: 3
如果返回的项目本身是列表,可以重复这样的操作: >
:let item = nestlist[0][1] " 得到第一个列表的第二个项目: 12
<
负索引从尾端开始计算。索引 -1 指向列表的最后一个项目,-2 指向倒数第二个项目,
依此类推。 >
:let last = mylist[-1] " 得到最后一个项目: "four"
要避免非法索引值产生的错误,用 |get()| 函数。如果项目不存在,它返回零或者你指
定的缺省值: >
:echo get(mylist, idx)
:echo get(mylist, idx, "NONE")
列表连接 ~
两个列表可以用 "+" 操作符连接: >
:let longlist = mylist + [5, 6]
:let mylist += [7, 8]
要在前面或后面附加项目,在项目外面加上 [] 从而把它变为一个列表。要改变列表内部
的值,见下 |list-modification|。
子列表~
列表的一部分可以通过指定首末两个索引获得,方括号内以冒号分隔两者: >
:let shortlist = mylist[2:-1] " 得到列表 [3, "four"]
首索引的省略类似于用 0。末索引的省略类似于用 -1。 >
:let endlist = mylist[2:] " 从项目 2 到结束: [3, "four"]
:let shortlist = mylist[2:2] " 单个项目的列表: [3]
:let otherlist = mylist[:] " 复制列表
如果首索引在列表末项之后或者末索引小于首索引,返回空列表。没有错误信息。
如果末索引大于等于列表的长度,使用列表长度减一: >
:let mylist = [0, 1, 2, 3]
:echo mylist[2:8] " 返回: [2, 3]
<
注意: mylist[s:e] 意味着用变量 "s:e" 作为索引。在 ":" 之前用单个字母作为变量要
小心。需要的话加上空格: mylist[s : e]。
列表同一 ~
*list-identity*
如果变量 "aa" 是列表,把它赋给另一个变量 "bb" 后,两个变量指向同一列表。因此,
对列表 "aa" 的修改也同时修改了 "bb": >
:let aa = [1, 2, 3]
:let bb = aa
:call add(aa, 4)
:echo bb
< [1, 2, 3, 4]
|copy()| 函数可以复制列表。如上所述,用 [:] 也可。这种方式建立列表的浅备份: 改
变列表中的列表项目仍然会修改复制列表的相应项目: >
:let aa = [[1, 'a'], 2, 3]
:let bb = copy(aa)
:call add(aa, 4)
:let aa[0][1] = 'aaa'
:echo aa
< [[1, aaa], 2, 3, 4] >
:echo bb
< [[1, aaa], 2, 3]
要建立一个完全独立的列表,用 |deepcopy()|。它递归地建立列表值的备份。最深可达
100 层。
可用操作符 "is" 检查两个变量是否指向同一个列表。"isnot" 刚好相反。与此对照,
"==" 比较两个列表的值是否相同。 >
:let alist = [1, 2, 3]
:let blist = [1, 2, 3]
:echo alist is blist
< 0 >
:echo alist == blist
< 1
比较列表时 注意: 如果长度相同,所有项目用 "==" 的比较的结果也相同,两个列表就
认为相同。有一个例外: 数值和字符串总被认为不相同。这里不进行自动类型转换,而在
变量间直接用 "==" 却不是如此。例如: >
echo 4 == "4"
< 1 >
echo [4] == ["4"]
< 0
因此可以说,列表的比较比数值和字符串的比较更严格。你同样可以用这种方式比较简单
类型的值,把它们放到列表里就行了: >
:let a = 5
:let b = "5"
:echo a == b
< 1 >
:echo [a] == [b]
< 0
列表解包 ~
要给列表项目解包,即把它们分别存入单独的变量,用方括号把变量括起来,如同把它们
当作列表项目: >
:let [var1, var2] = mylist
如果变量和列表的项目数量不同,报错。要处理列表中所有额外的项目,加上 ";" 和单
个变量: >
:let [var1, var2; rest] = mylist
它的工作方式就像: >
:let var1 = mylist[0]
:let var2 = mylist[1]
:let rest = mylist[2:]
如果只有两个项目,不会报错。这时 "rest" 成为空表。
列表修改 ~
*list-modification*
要修改列表的指定项目,用 |:let|: >
:let list[4] = "four"
:let listlist[0][3] = item
要修改列表的一部分,可以指定要修改的首末项目。提供的值的个数必须不少于该范围内
的项目数: >
:let list[3:5] = [3, 4, 5]
给列表增加和删除项目可以通过函数完成。一些例子如下: >
:call insert(list, 'a') " 在最前面插入 'a'
:call insert(list, 'a', 3) " 在 list[3] 前插入项目 'a'
:call add(list, "new") " 在最后附加字符串项目
:call add(list, [1, 2]) " 在最后附加新的列表项目
:call extend(list, [1, 2]) " 在最后扩展列表,使之多包含两个项目
:let i = remove(list, 3) " 删除项目 3
:unlet list[3] " 同上
:let l = remove(list, 3, -1) " 从项目 3 删除到最后
:unlet list[3 : ] " 同上
:call filter(list, 'v:val !~ "x"') " 删除有 'x' 的项目
改变列表项目的顺序: >
:call sort(list) " 按字母给列表排序
:call reverse(list) " 反转项目的顺序
For 循环 ~
|:for| 循环为每个列表项目执行命令。一个变量被依次设为每个列表项目。例如: >
:for item in mylist
: call Doit(item)
:endfor
它的工作方式就像: >
:let index = 0
:while index < len(mylist)
: let item = mylist[index]
: :call Doit(item)
: let index = index + 1
:endwhile
注意 所有列表项目必须是相同类型,不然会报错 |E706|。要避免这一点,在循环尾部
|:unlet| 该变量。
如果你只是想要修改每个列表项目,|map()| 函数比 for 循环简单得多。
就像 |:let| 命令,|:for| 也可以接受变量的列表。这需要参数是列表的列表。 >
:for [lnum, col] in [[1, 3], [2, 8], [3, 0]]
: call Doit(lnum, col)
:endfor
这就像对列表的每个项目使用了 |:let| 命令。重复一次,类型必须相同,否则会报错。
也可以用变量保存列表变量的其余项目: >
:for [i, j; rest] in listlist
: call Doit(i, j)
: if !empty(rest)
: echo "remainder: " . string(rest)
: endif
:endfor
列表的相关函数 ~
*E714*
可用于列表的函数: >
:let r = call(funcname, list) " 调用带参数列表的函数
:if empty(list) " 检查 list 是否为空
:let l = len(list) " list 项目的数量
:let big = max(list) " list 项目的最大值
:let small = min(list) " list 项目的最小值
:let xs = count(list, 'x') " 计算 list 里 'x' 出现的次数
:let i = index(list, 'x') " list 第一个 'x' 的位置
:let lines = getline(1, 10) " 得到缓冲区十行文本行
:call append('$', lines) " 附加若干文本行到缓冲区尾部
:let list = split("a b c") " 用字符串中的项目建立列表
:let string = join(list, ', ') " 用 list 项目构造字符串
:let s = string(list) " list 的字符串表示
:call map(list, '">> " . v:val') " 在每个项目前加上 ">> "
不要忘记组合使用不同功能可以简化任务。例如,要计算列表中所有数值的总和: >
:exe 'let sum = ' . join(nrlist, '+')
1.4 字典 ~
*Dictionaries* *Dictionary*
字典是关联数组: 每个项目有一个键和一个值。用键可以定位项目,而项目的存储不能确
定任何特定顺序。
字典建立 ~
*E720* *E721* *E722* *E723*
字典通过花括号里逗号分隔的项目列表建立。每个项目包含以冒号分隔的键和值。一个键
只能出现一次。例如: >
:let mydict = {1: 'one', 2: 'two', 3: 'three'}
:let emptydict = {}
< *E713* *E716* *E717*
键必须是字符串。用数值也可以,但它总被自动转换为字符串。所以字符串 '4' 和数值
4 总会找到相同的项目。注意 字符串 '04' 和数值 04 是不一样的,因为后者被转换成
字符串 '4'。
值可以是任何表达式。如果值本身是字典,就可以建立嵌套的字典: >
:let nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}}
忽略末项之后的逗号。
访问项目 ~
常见的访问项目的方式是把键放入方括号: >
:let val = mydict["one"]
:let mydict["four"] = 4
用这种方式可以给已存在的字典增加新项目,这和列表不同。
如果键只包含字母、数字和下划线,可以使用如下形式 |expr-entry|: >
:let val = mydict.one
:let mydict.four = 4
因为项目可以是包括列表和字典的任何类型,你可以反复使用索引和键进行访问: >
:echo dict.key[idx].key
字典到列表的转换 ~
你可以循环遍历字典的所有项目。为此,你需要把字典转为列表,然后把它传递给
|:for|。
通常,你期望遍历所有的键,用 |keys()| 函数就可以了: >
:for key in keys(mydict)
: echo key . ': ' . mydict[key]
:endfor
键列表没有经过排序。你可能希望先进行排序: >
:for key in sort(keys(mydict))
要遍历所有的值,用 |values()| 函数: >
:for v in values(mydict)
: echo "value: " . v
:endfor
如果你想同时得到键和值,用 |items()| 函数。它返回一个列表,其中每个项目是两个
项目的列表: 键和值: >
:for [key, value] in items(mydict)
: echo key . ': ' . value
:endfor
字典同一 ~
*dict-identity*
就像列表那样,你需要用 |copy()| 和 |deepcopy()| 来构造字典的备份。否则,赋值产
生的结果会引用同一个字典: >
:let onedict = {'a': 1, 'b': 2}
:let adict = onedict
:let adict['a'] = 11
:echo onedict['a']
11
如果所有的键-值组对的比较结果相同,两个字典比较的结果也相同。详情见
|list-identity|。
字典修改 ~
*dict-modification*
要修改字典已经存在的项目或者增加新的项目,用 |:let|: >
:let dict[4] = "four"
:let dict['one'] = item
从字典里删除项目可以通过 |remove()| 或 |:unlet| 完成。
从 dict 里删除键 "aaa" 的项目有三种方法: >
:let i = remove(dict, 'aaa')
:unlet dict.aaa
:unlet dict['aaa']
两个字典的合并可以用 |extend()|: >
:call extend(adict, bdict)
这使得 adict 得到扩展,加入所有的 bdict 项目。对于重复的键,adict 项目被覆盖。
可选的第三个参数可以改变这一点。
注意 这不影响字典项目的顺序,不要希望 ":echo adict" 会先显示原有 adict 项目,
然后再显示 bdict 的项目。
从字典里删除多个项目可以用 |filter()| 完成: >
:call filter(dict, 'v:val =~ "x"')
删除 "dict" 里所有值不匹配 "x" 的项目。
字典函数 ~
*Dictionary-function* *self* *E725*
定义函数时,如果带有 "dict" 属性,可以以一种特殊方式使用字典。例如: >
:function Mylen() dict
: return len(self.data)
:endfunction
:let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
:echo mydict.len()
这类似于面向对象编程的方法。字典项目用作 |Funcref|。局部变量 "self" 引用函数所
在的字典。
字典里也可以加入指向没有 "dict" 属性的函数的函数引用,不过这时无法使用 "self"
变量。
*numbered-function* *anonymous-function*
要避免额外的函数名,可以定义时直接赋给字典: >
:let mydict = {'data': [0, 1, 2, 3]}
:function mydict.len() dict
: return len(self.data)
:endfunction
:echo mydict.len()
该函数会得到一个编号,而 dict.len 的值是指向此函数的 |Funcref|。该函数只能通过
|Funcref| 访问。如果没有任何 |Funcref| 引用,它会被自动删除。
编号函数不一定要有 "dict" 属性。
如果你的编号函数有错,可以用一个技巧知道它是什么内容。假定函数是 42,命令为: >
:function {42}
字典相关函数 ~
*E715*
可以用于字典的函数: >
:if has_key(dict, 'foo') " 如果 dict 有带 "foo" 键的项目则为真
:if empty(dict) " 如果 dict 为空则为真
:let l = len(dict) " dict 项目的数量
:let big = max(dict) " dict 项目的最大值
:let small = min(dict) " dict 项目的最小值
:let xs = count(dict, 'x') " 统计 dict 里 'x' 出现的数目
:let s = string(dict) " dict 的字符串表示
:call map(dict, '">> " . v:val') " 在每个项目前加上 ">> "
1.5 变量的更多细节 ~
*more-variables*
如果你需要知道变量或表达式的类型,使用 |type()| 函数。
如果 'viminfo' 选项包含 '!' 标志位,大写开头且不包含小写字母的全局变量被保存在
viminfo 文件里 |viminfo-file|。
如果 'sessionoptions' 选项包含 "global",大写开头且包含至少一个小写字母的全局
变量被保存在会话文件里 |session-file|。
变量名 可以保存的位置 ~
my_var_6 无
My_Var_6 会话文件
MY_VAR_6 viminfo 文件
可以使用花括号来构造变量名,见 |curly-braces-names|。
==============================================================================
2. 表达式语法 *expression-syntax*
表达式语法小结,优先级从低到高排列:
|expr1| expr2 ? expr1 : expr1 if-then-else
|expr2| expr3 || expr3 .. 逻辑或
|expr3| expr4 && expr4 .. 逻辑与
|expr4| expr5 == expr5 等于
expr5 != expr5 不等于
expr5 > expr5 大于
expr5 >= expr5 大于等于
expr5 < expr5 小于
expr5 <= expr5 小于等于
expr5 =~ expr5 匹配正规表达式
expr5 !~ expr5 不匹配正规表达式
expr5 ==? expr5 等于,忽略大小写
expr5 ==# expr5 等于,匹配大小写
等等 如上,? 忽略大小写,# 则匹配之
expr5 is expr5 相同的 |List| 实例
expr5 isnot expr5 不同的 |List| 实例
|expr5| expr6 + expr6 .. 数值加法或列表连接
expr6 - expr6 .. 数值减法
expr6 . expr6 .. 字符串连接
|expr6| expr7 * expr7 .. 数值乘法
expr7 / expr7 .. 数值除法
expr7 % expr7 .. 数值求余
|expr7| ! expr7 逻辑非
- expr7 一元减法: 取反
+ expr7 一元加法: 原值
|expr8| expr8[expr1] 字符串里的字节或者 |List| 的项目
expr8[expr1 : expr1] 字符串子串或 |List| 的子列表
expr8.name |Dictionary| 的项目
expr8(expr1, ...) 使用 |Funcref| 变量的函数调用
|expr9| number 数值常数
"string" 字符串常数,反斜杠有特殊含义
'string' 字符串常数,' 加倍
[expr1, ...] |List|
{expr1: expr1, ...} |Dictionary|
&option 选项值
(expr1) 嵌套表达式
variable 内部变量
va{ria}ble 带花括号的内部变量
$VAR 环境变量
@r 寄存器 'r' 的值
function(expr1, ...) 函数调用
func{ti}on(expr1, ...) 带花括号的函数调用
".." 标明这一层上的操作可以连接。比如: >
&nu || &list && &shell == "csh"
同一层的表达式从左到右进行分析。
expr1 *expr1* *E109*
-----
expr2 ? expr1 : expr1
'?' 之前的表达式作为数值求值。如果结果非零,最终的结果是 '?' 和 ':' 之间的表达
式的值,不然最终的结果是 ':' 之后的表达式的值。例如: >
:echo lnum == 1 ? "top" : lnum
因为第一个表达式是 "expr2",它不能包含另一个 ?:。另外两个表达式则没有这个限
制,从而使得递归使用 ?: 成为可能。例如: >
:echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum
要使之可读,建议使用续行符 |line-continuation|: >
:echo lnum == 1
:\ ? "top"
:\ : lnum == 1000
:\ ? "last"
:\ : lnum
在 ':' 前,你总是应该加上空格,否则它可能被错误用在如 "a:1" 这样的变量里。
expr2 和 expr3 *expr2* *expr3*
---------------
*expr-barbar* *expr-&&*
"||" 和 "&&" 操作符左右两边各接受一个参数。参数是 (或转化为) 数值。运算结果是:
输入 输出 ~
n1 n2 n1 || n2 n1 && n2 ~
零 零 零 零
零 非零 非零 零
非零 零 非零 零
非零 非零 非零 非零
操作符可以连接。比如: >
&nu || &list && &shell == "csh"
注意 "&&" 比 "||" 优先级高,所以这等价于: >
&nu || (&list && &shell == "csh")
一旦结果可以确定,表达式使用 "短路" 计算,也就是,不再计算后面的参数,这和 C
的情形类似。比如: >
let a = 1
echo a || b
这是合法的,即使没有叫 "b" 的变量也是如此。因为 "a" 已经是非零值,结果必然是非
零。下面的情形类似: >
echo exists("b") && b == "yes"
无论 "b" 定义与否,这是合法的。第二个子句只有在 "b" 定义的时候才会被计算。
expr4 *expr4*
-----
expr5 {cmp} expr5
比较两个 expr 表达式,如果结果为假,返回 0,如果结果为真,返回 1。
*expr-==* *expr-!=* *expr->* *expr->=*
*expr-<* *expr-<=* *expr-=~* *expr-!~*
*expr-==#* *expr-!=#* *expr->#* *expr->=#*
*expr-<#* *expr-<=#* *expr-=~#* *expr-!~#*
*expr-==?* *expr-!=?* *expr->?* *expr->=?*
*expr-<?* *expr-<=?* *expr-=~?* *expr-!~?*
*expr-is*
使用 'ignorecase' 匹配大小写 忽略大小写 ~
等于 == ==# ==?
不等于 != !=# !=?
大于 > ># >?
大于等于 >= >=# >=?
小于 < <# <?
小于等于 <= <=# <=?
匹配正规表达式 =~ =~# =~?
不匹配正规表达式 !~ !~# !~?
相同实例 is
不同实例 isnot
示例:
"abc" ==# "Abc" 结果为 0
"abc" ==? "Abc" 结果为 1
"abc" == "Abc" 如果置位了 'ignorecase',结果为 1,不然结果为 0
*E691* *E692*
|List| 只能和 |List| 比较,而且只能用 "等于"、"不等于" 和 "is"。比较针对列表的
值,递归进行。忽略大小写意味着比较项目的值时忽略大小写。
*E735* *E736*
|Dictionary| 只能和 |Dictionary| 比较,而且只能用 "等于"、"不等于" 和 "is"。比
较针对 |Dictionary| 的键/值,递归进行。忽略大小写意味着比较项目的值时忽略大小
写。
*E693* *E694*
|Funcref| 只能和 |Funcref| 比较,而且只能用 "等于" 和 "不等于"。这里永不忽略大
小写。
|List| 用 "is" 或 "isnot" 时,检查表达式是否指向同一个 |List| 实例。|List| 的
备份和原来的 |List| 不同。如果不是 |List|,用 "is" 等价于用 "等于",而 "isnot"
等价于 "不等于",有一点区别: 不同的类型总认为有不同的值。"4 == '4'" 为真,而
"4 is '4'" 为假。
如果比较字符串和数值,字符串被转化成数值,而比较是在数值之间进行的。这意味着
"0 == 'x'" 为真,因为 'x' 被转化成数值 0。
如果比较两个字符串,使用 strcmp() 或 stricmp()。因而,比较的是数学上的差异 (比
较字节码),而不必然是本地语言的字母的差异。
如果操作符后带上 '#',或者 'ignorecase' 关闭时使用无 '#' 的版本时,比较使用
strcmp(): 大小写相关。
如果操作符后带上 '?',或者 'ignorecase' 打开时使用无 '?' 的版本时,比较使用
stricmp(): 大小写无关。
这里 'smartcase' 不适用。
"=~" 和 "!~" 操作符使用右边的参数作为模式来匹配左边的参数。模式的定义见
|pattern|。匹配进行时,总是假设置位了 'magic' 并且 'cpoptions' 为空,无论
'magic' 或 'cpoptions' 实际的值为何。这使得脚本可移植。要避免在正规表达式里使
用的反斜杠需要加倍的问题,可以使用单引号的字符串,见 |literal-string|。
既然字符串假定为单行,多行的模式 (包含 \n,即反斜杠-n) 不会被匹配。不过,按本
义出现的单个 NL 字符可以像普通字符一样匹配。比如:
"foo\nbar" =~ "\n" 结果为 1
"foo\nbar" =~ "\\n" 结果为 0
expr5 和 expr6 *expr5* *expr6*
---------------
expr6 + expr6 .. 数值加法或 |List| 连接 *expr-+*
expr6 - expr6 .. 数值减法 *expr--*
expr6 . expr6 .. 字符串连接 *expr-.*
|Lists| 只能用 "+",而且两个 expr6 必须都是列表。返回两者连接以后的新列表。
expr7 * expr7 .. 数值乘法 *expr-star*
expr7 / expr7 .. 数值除法 *expr-/*
expr7 % expr7 .. 数值求余 *expr-%*
除了 "." 以外,这里所有的操作都把字符串转化成数值。
注意 "+" 和 "." 的差异:
"123" + "456" = 579
"123" . "456" = "123456"
因为 '.' 和 '+' 与 '-' 的优先级相同,你需要把: >
1 . 90 + 90.0
看作: >
(1 . 90) + 90.0
这没问题,因为字符串 "190" 被自动转换为数值 190,然后和浮点数 90.0 相加。不
过: >
1 . 90 * 90.0
应被看作: >
1 . (90 * 90.0)
因为 '.' 的优先级比 '*' 低,这_不能_工作,因为它试图连接浮点数和字符串。
数值除以零时,结果取决于该值:
0 / 0 = -0x80000000 (类似于浮点数的 NaN)
>0 / 0 = 0x7fffffff (类似于正无穷大)
<0 / 0 = -0x7fffffff (类似于负无穷大)
(Vim 7.2 之前,总是返回 0x7fffffff)
如果 '%' 的右边为零,结果为 0。
这些操作不适用于 |Funcref|。
而 % 也不适用于浮点数。 *E804*
expr7 *expr7*
-----
! expr7 逻辑非 *expr-!*
- expr7 一元减法: 取反 *expr-unary--*
+ expr7 一元加法: 原值 *expr-unary-+*
'!' 把非零变为零,零变为 1。
'-' 改变数值的符号。
'+' 保持原值。
字符串会先转化为数值。
可以重复和混合这三种运算。例如:
!-1 == 0
!!8 == 1
--9 == 9
expr8 *expr8*
-----
expr8[expr1] 字符串或 |List| 的项目 *expr-[]* *E111*
如果 expr8 是数值或字符串,结果是字符串,包含 expr8 里第 expr1 个字节。expr8
视作字符串,expr1 视作数值。这里不识别多字节编码,但可考虑使用 |byteidx()|。
索引 0 给出第一个字符。这和 C 类同。要小心: 文本列号可是从 1 开始的!例如,要
得到光标所在的字符: >
:let c = getline(line("."))[col(".") - 1]
如果字符串的长度小于索引值,结果为空字符串。负索引总是给出空字符串 (原因: 反向
兼容)。用 [-1:] 得到最后一个字节。
如果 expr8 是 |List|,返回索引值为 expr1 的项目。可用的索引值见 |list-index|。
如果索引越界,产生错误。例如: >
:let item = mylist[-1] " 得到最后一个项目
一般的,如果 |List| 索引大于等于 |List| 的长度,或者比 |List| 的长度更负,产生
错误。
expr8[expr1a : expr1b] 子字符串或子列表 *expr-[:]*
如果 expr8 是数值或字符串,结果是子字符串,包含第 expr1a 到第 expr1b (包含) 个
字节。expr8 视作字符串,expr1a 和 expr1b 视作数值。这里不识别多字节编码,需用
|byteidx()| 来计算索引值。
如果省略 expr1a,用零。如果省略 expr1b,用字符串的长度减一。
可以用负数来从字符串尾部开始计算位置。-1 代表最后一个字符,-2 倒数第二个,依此
类推。
如果索引越界,忽略这些字符。如果 expr1b 小于 expr1a,结果是空字符串。
例如: >
:let c = name[-1:] " 字符串最后一个字节
:let c = name[-2:-2] " 字符串倒数第二个字节
:let s = line(".")[4:] " 从第五个字节到最后
:let s = s[:-3] " 删除最后两个字节
<
*sublist* *slice*
如果 expr8 是 |List|,结果是新的 |List|,包含 expr1 和 expr1b 索引指定的项目。
和上面描述的字符串情形类似,除了越界的索引会报错以外。例如: >
:let l = mylist[:3] " 前四个项目
:let l = mylist[4:4] " 单个项目的列表
:let l = mylist[:] " 列表的浅备份
在 |Funcref| 上用 expr8[expr1] 或 expr8[expr1a : expr1b] 出错。
expr8.name |Dictionary| 的项目 *expr-entry*
如果 expr8 是一个 |Dictionary| 且后跟句号再跟一个名字,该名字用作 |Dictionary|
的键。这相当于: expr8[name]。
该名字必须由字母数字字符组成。这和变量名一样,不过这里可以用数字开始。但不能用
花括号。
句号前后不能用空白。
例如: >
:let dict = {"one": 1, 2: "two"}
:echo dict.one
:echo dict .2
注意 句号也用于字符串连接。要避免混淆,用于字符串连接的句号前后加上空白。
expr8(expr1, ...) |Funcref| 函数调用
如果 expr8 是 |Funcref| 类型的变量,调用它指向的函数。
*expr9*
number
------
number 数值常数 *expr-number*
十进制、十六进制 (0x 或 0X 开始)、或八进制 (0 开始)。
*floating-point-format*
浮点数可用两种形式给出:
[-+]{N}.{M}
[-+]{N}.{M}e[-+]{exp}
{N} 和 {M} 都是数值。{N} 和 {M} 都必须存在,且只能包含数位。
[-+] 意味着有一个可选的正负号。
{exp} 是指数部分,以 10 为基。
只能接受小数点,逗号不行。这和当前的 locale 无关。
{仅当编译时加入 |+float| 特性才有效}
示例:
123.456
+0.0001
55.0
-0.123
1.234e03
1.0E-6
-3.1416e+88
下面的形式是_非法的_:
3. {M} 为空
1e40 {M} 为空
*float-pi* *float-e*
可以复制-粘贴的一些常用值: >
:let pi = 3.14159265359
:let e = 2.71828182846
逻辑:
浮点数引入之前,文本 "123.456" 被解释为两个数值 "123" 和 "456",转换为字符串,
然后进行连接而生成字符串 "123456"。这被认为没有意义,也没有找到有意使用此特性
的 Vim 脚本,因此我们采纳了这种普遍的浮点数记法,而接受其后向不兼容性。
*floating-point-precision*
浮点数的精度和取值范围取决于 Vim 编译时使用的库如何理解 "double"。运行时无法改
变。
浮点数 |Float| 的显示缺省使用 6 位十进制位,类似于 printf("%g", f)。使用
|printf()| 函数时可以指定其它位数。例如: >
:echo printf('%.15e', atan(1))
< 7.853981633974483e-01
string *expr-string* *E114*
------
"string" 字符串常数 *expr-quote*
注意 使用的是双引号。
字符串常数接受以下特殊字符:
\... 三位八进制数 (例如,"\316")
\.. 两位八进制数 (必须后跟非数字)
\. 一位八进制数 (必须后跟非数字)
\x.. 两位十六进制数指定的字节 (例如,"\x1f")
\x. 一位十六进制数指定的字节 (必须后跟非十六进制数字)
\X.. 等同于 \x..
\X. 等同于 \x.
\u.... 四位十六进制指定的字符。根据 'encoding' 的当前值决定的编码进行存贮 (例
如,"\u02a4")
\U.... 等同于 \u.....
\b 退格 <BS>
\e escape <Esc>
\f 换页 <FF>
\n 换行 <NL>
\r 回车 <CR>
\t 制表 <Tab>
\\ 反斜杠
\" 双引号
\<xxx> "xxx" 命名的特殊字符,例如 "\<C-W>" 代表 CTRL-W。用于映射,0x80 字节被
转义。不要用 <Char-xxxx> 来得到 utf-8 字符,用上面提到的 \uxxxxx。
注意 "\xff" 保存为字节 255,在某些编码中它是不合法的。使用 "\u00ff" 可以按照
'encoding' 的当前值保存字符 255。
注意 "\000" 和 "\x00" 强制字符串结束。
literal-string *literal-string* *E115*
---------------
'string' 字符串常数 *expr-'*
注意 使用的是单引号。
字符串这里按原义出现。不去掉反斜杠,它也没有特殊含义。唯一的特例是两个单引号代
表一个单引号。
单引号字符串有助于模式的使用,因为反斜杠不再需要加倍。以下两个命令等价: >
if a =~ "\\s*"
if a =~ '\s*'
option *expr-option* *E112* *E113*
------
&option 选项值,如有存在,使用局部值
&g:option 全局选项值
&l:option 局部选项值
例如: >
echo "tabstop is " . &tabstop
if &insertmode
这里可以使用任何选项值。见 |options|。如果指定要使用局部值,但不存在局部于缓冲
区或局部于窗口的选项,则还是使用全局值。
register *expr-register* *@r*
--------
@r 寄存器 'r' 的值
结果是命名寄存器的内容,以单个字符串表达。换行符在需要时会被插入。要得到无名寄
存器的内容,使用 @" 或 @@。可用寄存器的相关解释可见 |registers|。
如果用 '=' 寄存器,你得到表达式自身,而不是它计算的结果。用 |eval()| 来进行计
算。
nesting *expr-nesting* *E110*
-------
(expr1) 嵌套表达式
environment variable *expr-env*
--------------------
$VAR 环境变量
任何环境变量的字符串值。如果该环境变量没有定义,结果为空字符串。
*expr-env-expand*
注意 直接使用 $VAR 和使用 expand("$VAR") 有区别。直接使用的形式只能扩展当前
Vim 会话所知的环境变量。使用 expand() 会先尝试当前 Vim 会话所知的环境变量,如
果不成功,则使用外壳扩展该变量。这会变慢,但可以用来扩展只有外壳知道的变量。
例如: >
:echo $version
:echo expand("$version")
前者可能不会回显任何内容,后者会回显 $version 变量 (如果你的外壳支持的话)。
internal variable *expr-variable*
-----------------
variable 内部变量
见下面的 |internal-variables|。
function call *expr-function* *E116* *E118* *E119* *E120*
-------------
function(expr1, ...) 函数调用
见下面的 |functions|。
==============================================================================
3. 内部变量 *internal-variables* *E121*
*E461*
内部变量的名字由字母、数字和 '_' 组成。但不能由数字开始。可以使用花括号,见
|curly-braces-names|。
内部变量通过 ":let" 命令建立 |:let|。
内部变量通过 ":unlet" 命令显式删除 |:unlet|。
使用非内部变量的名字或引用已经删除的内部变量会产生错误。
变量有不同的命名空间,根据附加的前缀决定:
(无) 函数内: 局部于函数;否则: 全局
|buffer-variable| b: 局部于当前缓冲区。
|window-variable| w: 局部于当前窗口。
|tabpage-variable| t: 局部于当前标签页。
|global-variable| g: 全局。
|local-variable| l: 局部于函数。
|script-variable| s: 局部于 |:source| 的 Vim 脚本。
|function-argument| a: 函数参数 (只限于函数内使用)。
|vim-variable| v: Vim 预定义的全局变量。
作用域本身可以用作 |Dictionary|。例如,要删除所有局部于脚本的变量: >
:for k in keys(s:)
: unlet s:[k]
:endfor
<
*buffer-variable* *b:var*
"b:" 开头的变量名局部于当前缓冲区。这样,你可以为每个缓冲区定义不同的 "b:foo"
变量。这种变量在缓冲区被删除时 (:bwipeout 或 :bdelete |:bdelete|) 同时被删除。
预定义了如下的缓冲区局部变量:
*b:changedtick-variable* *changetick*
b:changedtick 当前缓冲区的改变次数。每次改变都会递增。撤销命令在此情形下也被
视作一次改变。这可用来在缓冲区发生改变时执行一些动作。比如: >
:if my_changedtick != b:changedtick
: let my_changedtick = b:changedtick
: call My_Update()
:endif
<
*window-variable* *w:var*
"w:" 开头的变量名局部于当前窗口。窗口关闭时被删除。
*tabpage-variable* *t:var*
"t" 开始的变量名局部于当前标签页。标签页关闭时,这些变量被删除。{仅当编译时加
入 |+windows| 特性才有效}
*global-variable* *g:var*
函数内部,全局变量可以通过 "g:" 访问。如果不提供前缀,会使用函数的局部变量。在
其他地方,如果你想的话。也可以使用 "g:"。
*local-variable* *l:var*
访问函数的局部变量无需任何前缀。但如果你想要,可以使用 "l:"。不过,如果没有
"l:" 前缀,你可能会和保留的变量名冲突。例如 "count"。它本身指代 "v:count"。但
使用了 "l:count" 你就可以使用同名的局部变量。
*script-variable* *s:var*
Vim 脚本里,可以使用 "s:" 开头的变量。它们不能在脚本之外访问,因而可以称为局部
于脚本的变量。
它们可以用于:
- 载入脚本时执行的命令
- 脚本定义的函数
- 脚本定义的自动命令
- 脚本定义的函数和自动命令里定义的函数和自动命令 (递归)
- 脚本里定义的用户定义命令
但不能用在:
- 该脚本载入的其它脚本
- 映射
- 菜单
- 等等
脚本变量可以用来防止和全局变量名的冲突。看看这个例子: >
let s:counter = 0
function MyCounter()
let s:counter = s:counter + 1
echo s:counter
endfunction
command Tick call MyCounter()
你可以从任何脚本里启动 "Tick",但那个脚本里的 "s:counter" 变量不会被改变,只有
在 "Tick" 定义所在脚本的 "s:counter" 才会。
另一个完成相同功能的例子: >
let s:counter = 0
command Tick let s:counter = s:counter + 1 | echo s:counter
如果调用函数或者启动用户定义命令,脚本变量的上下文设置为函数和命令定义所在的脚
本。
脚本变量也可用于脚本里定义的函数里定义的函数。例如: >
let s:counter = 0
function StartCounting(incr)
if a:incr
function MyCounter()
let s:counter = s:counter + 1
endfunction
else
function MyCounter()
let s:counter = s:counter - 1
endfunction
endif
endfunction
调用 StartCounting() 时,定义 MyCounter() 函数或者递增或者递减计数器。不管
StartCounting() 在哪里调用,s:counter 变量总可以在 MyCounter() 里访问。
如果相同的脚本多次执行,使用的是同一个脚本变量。只要 Vim 还在运行,就保持有
效。这可以用于维护计数: >
if !exists("s:counter")
let s:counter = 1
echo "脚本首次执行"
else
let s:counter = s:counter + 1
echo "脚本现在执行了 " . s:counter . " 次"
endif
注意 这意味着 filetype 插件不能为每个缓冲区提供不同的脚本变量。这时应使用缓冲
区的局部变量 |b:var|。
预定义的 Vim 变量: *vim-variable* *v:var*
*v:beval_col* *beval_col-variable*
v:beval_col 鼠标指针所在的列号,即 |v:beval_lnum| 行中的字节位置。
仅当计算 'balloonexpr' 选项时有效。
*v:beval_bufnr* *beval_bufnr-variable*
v:beval_bufnr 鼠标指针所在的缓冲区号。仅当计算 'balloonexpr' 选项时有效。
*v:beval_lnum* *beval_lnum-variable*
v:beval_lnum 鼠标指针所在的行号。仅当计算 'balloonexpr' 选项时有效。
*v:beval_text* *beval_text-variable*
v:beval_text 鼠标指针所在或之后的文本。通常是一个单词,可用于调试 C 程序。
此处用到 'iskeyword',但也包括此位置之前的句号和 "->"。如果在
']' 上,使用它之前的文本,包括匹配的 '[' 和它之前的单词。如果
在单行的可视区域上,使用高亮文本。
仅当计算 'balloonexpr' 选项时有效。
*v:beval_winnr* *beval_winnr-variable*
v:beval_winnr 鼠标指针所在的窗口号。仅当计算 'balloonexpr' 选项时有效。
*v:char* *char-variable*
v:char 计算 'formatexpr' 时使用的参数和用于带 <expr> 的缩写中输入的字
符 |:map-<expr>|。
*v:charconvert_from* *charconvert_from-variable*
v:charconvert_from
要转换的文件字符编码名。只在计算 'charconvert' 选项时有效。
*v:charconvert_to* *charconvert_to-variable*
v:charconvert_to
转换后的文件字符编码名。只在计算 'charconvert' 选项时有效。
*v:cmdarg* *cmdarg-variable*
v:cmdarg 该变量有两个目的:
1. 文件读写命令的额外参数。目前,它们包括 "++enc=" 和
"++ff="。该变量在文件读写命令的自动命令事件激活之前设置。开
头有一个空格,以便直接把该变量附加到读写命令之后。注意: 这
里不包括 "+cmd" 参数,因为它总要被执行的。
2. 使用 ":hardcopy" 打印 PostScript 文件时,":hardcopy" 命令的
参数。在 'printexpr' 里用得到。
*v:cmdbang* *cmdbang-variable*
v:cmdbang 文件读写命令时,和 v:cmdarg 设置的时间类似。如果使用了 "!",其
值为 1,不然为 0。注意 它只能用于自动命令。用户命令里可以用
|<bang>|。
*v:count* *count-variable*
v:count 最近的普通模式命令使用的计数。在映射前可用于得到计数。只读。
例如: >
:map _x :<C-U>echo "计数为 " . v:count<CR>
< 注意: <C-U> 是必要的,它删除紧跟在计数之后 ':' 所给出的行范
围。
如果有两个计数,如 "3d2w",它们进行相乘,如同命令行实际发生的
那样,等同于 "d6w"。
也用于计算 'formatexpr' 选项。
为了后向兼容,这里也可以用 "count"。
*v:count1* *count1-variable*
v:count1 类似于 "v:count",但没有给出计数时,缺省为 1。
*v:ctype* *ctype-variable*
v:ctype 运行环境当前的字符 locale 设置。它使得 Vim 脚本能得到当前的
locale 编码。技术细节: 这就是 LC_CTYPE 的值。如果没有使用
locale,其值为 "C"。
该变量不能直接设置,请使用 |:language| 命令。
见 |multi-lang|。
*v:dying* *dying-variable*
v:dying 通常为零。如果捕获到某个 "致命" 的 signal,设为 1。如果同时捕
获到多个 signal,其值相应增加。在自动命令里可以用来检查 Vim
是否被异常终止。{仅限于 Unix}
例如: >
:au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
< 备注: 如果 v:dying 为一而同时又捕捉到另一个致命的 signal,不执
行 VimLeave 自动命令。
*v:errmsg* *errmsg-variable*
v:errmsg 最近给出的错误信息。该变量可以设置。
例如: >
:let v:errmsg = ""
:silent! next
:if v:errmsg != ""
: ... handle error
< 为了后向兼容,这里也可以用 "errmsg"。
*v:exception* *exception-variable*
v:exception 最近捕获且没有完成的例外的值。见 |v:throwpoint| 和
|throw-variables|。
例如: >
:try
: throw "oops"
:catch /.*/
: echo "caught" v:exception
:endtry
< 输出: "caught oops"。
*v:fcs_reason* *fcs_reason-variable*
v:fcs_reason 激活 |FileChangedShell| 事件的原因。
可以在自动命令里用来决定该做什么和/或如何设置 v:fcs_choice。可
能的值是:
deleted 文件不再存在
conflict 文件内容、模式或修改时间被改变,而缓冲
区同时被修改
changed 文件内容被改变
mode 文件模式被改变
time 文件修改时间被改变
*v:fcs_choice* *fcs_choice-variable*
v:fcs_choice |FileChangedShell| 事件激活后该做什么。可以在自动命令里用来告
诉 Vim 如何处理涉及的缓冲区:
reload 重新载入缓冲区 (如果文件已删除,不能工
作)。
ask 询问用户该做什么,就像没有自动命令一
样。不过,如果只有修改时间被改变,不做
任何事。
<空> 不做任何事。自动命令应该已经处理完毕。
缺省为空。如果使用别的 (非法的) 值,Vim 的行为就像它为空一样。
不会有警告信息。
*v:fname_in* *fname_in-variable*
v:fname_in 输入文件名。在计算以下选项时合法:
选项 用于 ~
'charconvert' 要转换的文件
'diffexpr' 原始文件
'patchexpr' 原始文件
'printexpr' 要打印的文件
|SwapExists| 里设为交换文件名。
*v:fname_out* *fname_out-variable*
v:fname_out 输出文件名。只有在计算以下选项时才合法:
选项 用于 ~
'charconvert' 生成的转换完成的文件 (*)
'diffexpr' diff 的结果
'patchexpr' 产生的补丁文件
(*) 如果用于为写入命令进行转换 (比如,":w file"),等价于
v:fname_in。如果用于为读入命令进行转换 (比如,":e file"),它是
一个临时文件名,和 v:fname_in 不同。
*v:fname_new* *fname_new-variable*
v:fname_new 文件新版本的名字。只有在计算 'diffexpr' 的时候才有效。
*v:fname_diff* *fname_diff-variable*
v:fname_diff 比较结果 (或补丁) 的文件名。只有在计算 'patchexpr' 的时候才有
效。
*v:folddashes* *folddashes-variable*
v:folddashes 用于 'foldtext': 反映关闭的折叠的折叠级别的连字符。
|sandbox| 里只读。|fold-foldtext|
*v:foldlevel* *foldlevel-variable*
v:foldlevel 用于 'foldtext': 关闭的折叠的折叠级别。
|sandbox| 里只读。|fold-foldtext|
*v:foldend* *foldend-variable*
v:foldend 用于 'foldtext': 关闭的折叠的最后一行。
|sandbox| 里只读。|fold-foldtext|
*v:foldstart* *foldstart-variable*
v:foldstart 用于 'foldtext': 关闭的折叠的第一行。
|sandbox| 里只读。|fold-foldtext|
*v:insertmode* *insertmode-variable*
v:insertmode 用于 |InsertEnter| 和 |InsertChange| 自动命令事件。取值:
i 插入模式
r 替换模式
v 虚拟替换模式
*v:key* *key-variable*
v:key |Dictionary| 里当前项目的键。只有在 |map()| 和 |filter()| 里计
算表达式时有效。
只读。
*v:lang* *lang-variable*
v:lang 运行环境当前的消息 locale 设置。它使得 Vim 脚本能得到当前使用
的语言。技术细节: 这就是 LC_MESSAGES 的值。该值和系统有关。
该变量不能直接设置,请使用 |:language| 命令。
它和 |v:ctype| 不同,因为消息可能使用不同于字符编码的语言。见
|multi-lang|。
*v:lc_time* *lc_time-variable*
v:lc_time 运行环境当前的时间消息 locale 设置。它使得 Vim
脚本能得到当前使用的语言。技术细节: 这就是 LC_TIME 的值。
该变量不能直接设置,请使用 |:language| 命令。见 |multi-lang|。
*v:lnum* *lnum-variable*
v:lnum 'foldexpr' |fold-expr|、'formatexpr' 和 'indentexpr' 表达式中
的行号和 'guitablevel' 和 'guitabtooltip' 中的标签页号。只有在
计算这些表达式时才合法。在 |sandbox| 里时只读。
*v:mouse_win* *mouse_win-variable*
v:mouse_win 用 |getchar()| 得到鼠标点击时所在的窗口号。首个窗口的编号为
1 ,就像 |winnr()| 那样。如果那时没有鼠标点击,该值为零。
*v:mouse_lnum* *mouse_lnum-variable*
v:mouse_lnum 用 |getchar()| 得到鼠标点击时所在的行号。这是文本行号,不是屏
幕行号。如果那时没有鼠标点击,该值为零。
*v:mouse_col* *mouse_col-variable*
v:mouse_col 用 |getchar()| 得到鼠标点击时所在的列号。这是屏幕列号,就像
|virtcol()| 那样。如果那时没有鼠标点击,该值为零。
*v:oldfiles* *oldfiles-variable*
v:oldfiles 启动时从 |viminfo| 文件载入的文件名列表。Vim 记住的位置标记所
在的就是这些文件。列表长度的上限由 'viminfo' 选项的 ' 参数定义
(缺省是 100)。
另见 |:oldfiles| 和 |c_#<|。
此列表可修改,但并不影响之后 |viminfo| 文件保存什么。同时,如
果使用非字符串的值,会有问题。
{仅当编译时加入 |+viminfo| 特性才有效}
*v:operator* *operator-variable*
v:operator 普通模式给出的最近的操作符。除了 <g> 或 <z> 开始的命令是两个
字符外,这是单个字符。最好和 |v:prevcount| 和 |v:register| 一
起使用。常常,先中止操作符等待模式,然后使用操作符,例如: >
:omap O <Esc>:call MyMotion(v:operator)<CR>
< 直到输入下一个操作符之前,该值保持不变。因此不要期待该值会为
空。
|:delete|、|:yank| 或其它 Ex 命令不改变 v:operator。
只读。
*v:prevcount* *prevcount-variable*
v:prevcount 倒数第二次的普通模式命令使用的计数,也就是再上一个命令用的
v:count 的值。可以用来先中止可视模式或操作符等待模式,然后使用
计数。 >
:vmap % <Esc>:call MyFilter(v:prevcount)<CR>
< 只读。
*v:profiling* *profiling-variable*
v:profiling 通常为零。开始用 ":profile start" 之后设为一。见 |profiling|。
*v:progname* *progname-variable*
v:progname 包含 Vim 启动时使用的名字 (路径已被去掉)。可以用来为 "view"、
"evim" 等符号链接到 Vim 的名字提供特殊的设置。
只读。
*v:register* *register-variable*
v:register 最近的普通模式命令使用的寄存器名字。如果没有使用过,为空。
|getreg()| |setreg()|
*v:scrollstart* *scrollstart-variable*
v:scrollstart 指示使屏幕上滚的脚本或函数的字符串。只有在原来为空时才设置,因
此只记住第一个原因。如果来自输入的命令,设为 "Unknown"。
可以用来发现你的脚本为什么产生 hit-enter 提示。
*v:servername* *servername-variable*
v:servername 如果有的话,注册过的 |x11-clientserver| 名字。
只读。
v:searchforward *v:searchforward* *searchforward-variable*
搜索方向: 正向搜索后为 1,反向搜索后为 0。直接设置最近搜索模式
会复位此值为正向,见 |quote/|。
注意 从函数返回时该值被复原 |function-search-undo|。
可读写。
*v:shell_error* *shell_error-variable*
v:shell_error 最近一次外壳命令的返回值。如果非零,最近一次外壳命令有错。如果
为零,则该命令成功返回。这只有在外壳把错误代码返回给 Vim 的时
候才工作。-1 通常用来告知该命令无法执行。只读。
例如: >
:!mv foo bar
:if v:shell_error
: echo '不能把 "foo" 换名为 "bar"!'
:endif
< 为了后向兼容,这里也可以用 "shell_error"。
*v:statusmsg* *statusmsg-variable*
v:statusmsg 最近给出的状态消息。可以设置该变量。
*v:swapname* *swapname-variable*
v:swapname 只有在执行 |SwapExists| 自动命令时才合法: 找到的交换文件名。只
读。
*v:swapchoice* *swapchoice-variable*
v:swapchoice |SwapExists| 自动命令可以设置此值,以选择如何处理已有交换文件:
'o' 以只读方式打开
'e' 仍然编辑
'r' 恢复
'd' 删除交换文件
'q' 退出
'a' 中止
该值应是单个字符的字符串。如果为空,用户会被询问,就像没有
SwapExists 自动命令那样。缺省为空。
*v:swapcommand* *swapcommand-variable*
v:swapcommand 打开文件后执行的普通模式命令。可以用于 |SwapExists| 自动命令,
用以让另一个 Vim 打开文件并跳转到合适的位置。例如,要跳转到某
标签,用的值是 ":tag tagname\r"。":edit +cmd file" 用的值是
":cmd\r"。
*v:termresponse* *termresponse-variable*
v:termresponse 使用 |t_RV| termcap 项目返回的终端的转义序列。Vim 收到 ESC [
或者 CSI 开始,以一个 'c' 结束,并且其间只包含数字,';' 和 '.'
的转义序列的时候,会设置该值。
如果设置该选项,会激活 TermResponse 自动命令事件,这样你就可以
对终端的应答做出反应。
新的 xterm 的应答是: "<Esc>[ Pp ; Pv ; Pc c"。 Pp 是终端类型:
0 代表 vt100,而 1 代表 vt220。 Pv 是补丁号 (因为这是 patch 95
引入的,补丁号应该总是 95 会更高)。Pc 总是零。
{仅当编译时加入 |+termresponse| 特性才有效}
*v:this_session* *this_session-variable*
v:this_session 最近载入或者保存的会话文件的文件名 |:mksession|。可以设置该变
量。如果没有保存过会话文件,该变量为空。
为了后向兼容,这里也可以用 "this_session"。
*v:throwpoint* *throwpoint-variable*
v:throwpoint 最近捕获且未完成的例外的抛出位置。输入的命令不会设置此变量。另
见 |v:exception| 和 |throw-variables|。
例如: >
:try
: throw "oops"
:catch /.*/
: echo "Exception from" v:throwpoint
:endtry
< 输出: "Exception from test.vim, line 2"
*v:val* *val-variable*
v:val |List| 或 |Dictionary| 当前项目的值。只有在计算 |map()| 和
|filter()| 里的表达式时才有效。只读。
*v:version* *version-variable*
v:version Vim 的版本号: 主版本号乘以 100 加上副版本号。5.0 版本对应的是
500。5.1 版本 (5.01) 则是 501。只读。为了后向兼容,这里也可以
用 "version"。
用 |has()| 可以检查是否包含某补丁,例如: >
if has("patch123")
< 注意 补丁号和版本有关,5.0 和 5.1 版本都有补丁号 123,但完全不
同。
*v:warningmsg* *warningmsg-variable*
v:warningmsg 最近给出的警告消息。该变量可以设置。
==============================================================================
4. 内建函数 *functions*
|function-list| 提供了按功能分组的一个函数列表。
(在函数名上使用 CTRL-] 跳转到完整的功能说明。)
用法 结果 描述 ~
abs( {expr}) 浮点或数值 {expr} 的绝对值
acos( {expr}) 浮点 {expr} 的反余弦值
add( {list}, {item}) 列表 在 |List| {list} 最后附加 {item}
append( {lnum}, {string}) 数值 在第 {lnum} 行下附加字符串 {string}
append( {lnum}, {list}) 数值 在第 {lnum} 行下附加行 {list}
argc() 数值 参数列表的文件数目
argidx() 数值 参数列表的当前索引
argv( {nr}) 字符串 参数列表第 {nr} 个参数
argv( ) 列表 参数列表
asin( {expr}) 浮点 {expr} 的反正弦值
atan( {expr}) 浮点 {expr} 的反正切值
atan2( {expr}, {expr}) 浮点 {expr1} / {expr2} 的反正切值
browse( {save}, {title}, {initdir}, {default})
字符串 启动文件请求窗口
browsedir( {title}, {initdir}) 字符串 启动目录请求窗口
bufexists( {expr}) 数值 如果缓冲区 {expr} 存在则为真
buflisted( {expr}) 数值 如果缓冲区 {expr} 在列表内则为真
bufloaded( {expr}) 数值 如果缓冲区 {expr} 被载入则为真
bufname( {expr}) 字符串 缓冲区 {expr} 的名字
bufnr( {expr}) 数值 缓冲区 {expr} 的数目
bufwinnr( {expr}) 数值 缓冲区 {expr} 的窗口号
byte2line( {byte}) 数值 第 {byte} 个字节所在的行号
byteidx( {expr}, {nr}) 数值 {expr} 里第 {nr} 个字符的字节位置
call( {func}, {arglist} [, {dict}])
可变 调用函数 {func},使用参数 {arglist}
ceil( {expr}) 浮点 {expr} 向上取整
changenr() 数值 当前改变号
char2nr( {expr}) 数值 {expr} 里第一个字符串的 ASCII 值
cindent( {lnum}) 数值 第 {lnum} 行的 C 缩进
clearmatches() 无 清除所有的匹配
col( {expr}) 数值 光标或位置标记的列号
complete( {startcol}, {matches}) 无 设置插入模式补全
complete_add( {expr}) 数值 增加补全匹配
complete_check() 数值 补全时检查输入的键
confirm( {msg} [, {choices} [, {default} [, {type}]]])
数值 用户选择的序号
copy( {expr}) 可变 提供 {expr} 的浅备份
cos( {expr}) 浮点 {expr} 的余弦值
cosh( {expr}) 浮点 {expr} 的双曲余弦值
count( {list}, {expr} [, {start} [, {ic}]])
数值 计算 {list} 里有多少个 {expr}
cscope_connection( [{num} , {dbpath} [, {prepend}]])
数值 检查 cscope 连接是否存在
cursor( {lnum}, {col} [, {coladd}])
数值 移动光标到 {lnum},{col},{coladd}
cursor( {list}) 数值 移动光标到 {list} 里的位置
deepcopy( {expr}) 可变 提供 {expr} 的完整备份
delete( {fname}) 数值 删除文件 {fname}
did_filetype() 数值 如果使用过 FileType 自动命令事件则为真
diff_filler( {lnum}) 数值 {lnum} 行之上的 diff 填充行数
diff_hlID( {lnum}, {col}) 数值 {lnum}/{col} 位置的 diff 高亮
empty( {expr}) 数值 如果 {expr} 为空则为真
escape( {string}, {chars}) 字符串 在 {string} 里用 '\' 转义 {chars}
eval( {string}) 可变 计算 {string},返回结果
eventhandler( ) 数值 如果在事件处理中则为真
executable( {expr}) 数值 如果可执行文件 {expr} 存在则为 1
exists( {expr}) 数值 如果 {expr} 存在则为真
extend( {expr1}, {expr2} [, {expr3}])
列表/字典 把 {expr2} 里的项目插入 {expr1}
exp( {expr}) 浮点 {expr} 的指数函数值
(译者注: 以 e 为底)
expand( {expr} [, {flag}]) 字符串 扩展 {expr} 里的特殊关键字
feedkeys( {string} [, {mode}]) 数值 给预输入缓冲区加入键序列
filereadable( {file}) 数值 如果 {file} 是个可读文件则为真
filewritable( {file}) 数值 如果 {file} 是个可写文件则为真
filter( {expr}, {string}) 列表/字典 删除 {expr} 里 {string} 为 0 的项目
finddir( {name}[, {path}[, {count}]])
字符串 在 {path} 里寻找目录 {name}
findfile( {name}[, {path}[, {count}]])
字符串 在 {path} 里寻找文件 {name}
float2nr( {expr}) 数值 转换浮点数 {expr} 为数值
floor( {expr}) 浮点 {expr} 向下取整
fmod( {expr1}, {expr2}) 浮点 {expr1} / {expr2} 的浮点余数
fnameescape( {fname}) 字符串 转义 {fname} 中的特殊字符
fnamemodify( {fname}, {mods}) 字符串 修改文件名
foldclosed( {lnum}) 数值 {lnum} 所在折叠的首行,如果是关闭的话
foldclosedend( {lnum}) 数值 {lnum} 所在折叠的末行,如果是关闭的话
foldlevel( {lnum}) 数值 {lnum} 的折叠级别
foldtext( ) 字符串 关闭的折叠显示的行
foldtextresult( {lnum}) 字符串 {lnum} 所在的关闭的折叠的文本
foreground( ) 数值 把 Vim 窗口带到前台
function( {name}) 函数引用 函数 {name} 的引用
garbagecollect( [at_exit]) 无 释放内存,打破循环引用
get( {list}, {idx} [, {def}]) 可变 得到 {list} 或 {def} 的项目 {idx}
get( {dict}, {key} [, {def}]) 可变 得到 {dict} 或 {def} 的项目 {idx}
getbufline( {expr}, {lnum} [, {end}])
列表 缓冲区 {expr} 第 {lnum} 到 {end} 行
getbufvar( {expr}, {varname}) 可变 缓冲区 {expr} 的变量 {varname}
getchar( [expr]) 数值 让用户输入一个字符
getcharmod( ) 数值 最近输入字符的修饰符
getcmdline() 字符串 返回当前命令行
getcmdpos() 数值 返回命令行的光标位置
getcmdtype() 字符串 返回当前命令行类型
getcwd() 字符串 当前工作目录
getfperm( {fname}) 字符串 文件 {fname} 的文件权限
getfsize( {fname}) 数值 字节计算的文件 {fname} 大小
getfontname( [{name}]) 字符串 使用的字体名
getftime( {fname}) 数值 文件的最新修改时间
getftype( {fname}) 字符串 文件 {fname} 类型的描述
getline( {lnum}) 字符串 当前缓冲区的第 {lnum} 行
getline( {lnum}, {end}) 列表 当前缓冲区第 {lnum} 到 {end} 行
getloclist( {nr}) 列表 位置列表项目的列表
getmatches() 列表 当前匹配的列表
getpid() 数值 Vim 的进程号
getpos( {expr}) 列表 光标、位置标记等的位置
getqflist() 列表 quickfix 项目的列表
getreg( [{regname} [, 1]]) 字符串 寄存器内容
getregtype( [{regname}]) 字符串 寄存器类型
gettabvar( {nr}, {varname}) 可变 {tabnr} 标签页的 {varname} 变量
gettabwinvar( {tabnr}, {winnr}, {name})
可变 {tabnr} 标签页 {winnr} 窗口的 {name}
getwinposx() 数值 GUI Vim 窗口以像素计的 X 坐标
getwinposy() 数值 GUI Vim 窗口以像素计的 Y 坐标
getwinvar( {nr}, {varname}) 可变 窗口 {expr} 的变量 {varname}
glob( {expr} [, {flag}]) 字符串 扩展 {expr} 里的文件通配符
globpath( {path}, {expr} [, {flag}])
字符串 在 {path} 所有目录下执行 glob({expr})
has( {feature}) 数值 如果支持特性 {feature} 则为真
has_key( {dict}, {key}) 数值 如果 {dict} 有项目 {key} 则为真
haslocaldir() 数值 如果当前窗口执行过 |:lcd|
hasmapto( {what} [, {mode} [, {abbr}]])
数值 如果 {what} 的映射存在则为真
histadd( {history},{item}) 字符串 在历史里增加项目
histdel( {history} [, {item}]) 字符串 从历史里删除项目
histget( {history} [, {index}]) 字符串 得到历史的第 {index} 项
histnr( {history}) 数值 历史里最高的项目号
hlexists( {name}) 数值 如果高亮组 {name} 存在则为真
hlID( {name}) 数值 高亮组 {name} 的语法 ID
hostname() 字符串 Vim 运行的机器名字
iconv( {expr}, {from}, {to}) 字符串 转换 {expr} 的编码
indent( {lnum}) 数值 第 {lnum} 行的缩进
index( {list}, {expr} [, {start} [, {ic}]])
数值 {list} 列表里出现 {expr} 的项目的索引
input( {prompt} [, {text} [, {completion}]])
字符串 从用户得到输入
inputdialog( {p} [, {t} [, {c}]]) 字符串 类似于 input(),但使用 GUI 对话框
inputlist( {textlist}) 数值 让用户从选择列表里挑选
inputrestore() 数值 恢复预输入
inputsave() 数值 保存和清除预输入
inputsecret( {prompt} [, {text}]) 字符串 类似于 input(),但隐藏文本
insert( {list}, {item} [, {idx}]) 列表 在 {list} 里插入 {item} [{idx} 之前]
isdirectory( {directory}) 数值 如果 {directory} 是目录则为真
islocked( {expr}) 数值 如果 {expr} 被锁住则为真
items( {dict}) 列表 {dict} 里的键-值组对
join( {list} [, {sep}]) 字符串 连接 {list} 的项目成为一个字符串
keys( {dict}) 列表 {dict} 的所有键
len( {expr}) 数值 {expr} 的长度
libcall( {lib}, {func}, {arg}) 字符串 调用库 {lib} 的函数 {func},使用参数
{arg}
libcallnr( {lib}, {func}, {arg}) 数值 同上,但返回数值
line( {expr}) 数值 光标所在、末行或者位置标记所在的行号
line2byte( {lnum}) 数值 行 {lnum} 的字节位置
lispindent( {lnum}) 数值 行 {lnum} 的 Lisp 缩进
localtime() 数值 当前时间
log( {expr}) 浮点 {expr} 的自然对数 (以 e 为底)
log10( {expr}) 浮点 {expr} 以 10 为底的对数
map( {expr}, {string}) 列表/字典 {expr} 的每个项目改变为 {string}
maparg( {name}[, {mode} [, {abbr}]])
字符串 模式 {mode} 的映射 {name} 的右边
mapcheck( {name}[, {mode} [, {abbr}]])
字符串 检查匹配 {name} 的映射
match( {expr}, {pat}[, {start}[, {count}]])
数值 {expr} 里 {pat} 的匹配位置
matchadd( {group}, {pattern}[, {priority}[, {id}]])
数值 用 {group} 高亮 {pattern}
matcharg( {nr}) 列表 |:match| 的参数
matchdelete( {id}) 数值 删除 {id} 指定的匹配
matchend( {expr}, {pat}[, {start}])
数值 {expr} 里 {pat} 的结束位置
matchlist( {expr}, {pat}[, {start}[, {count}]])
列表 {expr} 里 {pat} 的匹配和子匹配
matchstr( {expr}, {pat}[, {start}[, {count}]])
字符串 第 {count} 个 {expr} 里 {pat} 的匹配文
max( {list}) 数值 {list} 的项目的最大值
min( {list}) 数值 {list} 的项目的最小值
mkdir( {name} [, {path} [, {prot}]])
数值 建立目录 {name}
mode( [expr]) 字符串 当前编辑模式
mzeval( {expr}) 可变 计算 |MzScheme| 表达式
nextnonblank( {lnum}) 数值 第一个 >= {lnum} 的非空白行的行号
nr2char( {expr}) 字符串 ASCII 值为 {expr} 的单个字符
pathshorten( {expr}) 字符串 缩短路径里的目录名
pow( {x}, {y}) 浮点 {x} 的 {y} 次方
prevnonblank( {lnum}) 数值 最后一个 <= {lnum} 的非空白行的行号
printf( {fmt}, {expr1}...) 字符串 排版文本
pumvisible() 数值 弹出窗口是否可见
range( {expr} [, {max} [, {stride}]])
列表 从 {expr} 到 {max} 的序列
readfile( {fname} [, {binary} [, {max}]])
列表 得到文件 {fname} 的行列表
reltime( [{start} [, {end}]]) 列表 得到时间值
reltimestr( {time}) 字符串 把时间值转化为字符串
remote_expr( {server}, {string} [, {idvar}])
字符串 发送表达式
remote_foreground( {server}) 数值 把 Vim 服务器带到前台
remote_peek( {serverid} [, {retvar}])
数值 检查应答字符串
remote_read( {serverid}) 字符串 读入应答字符串
remote_send( {server}, {string} [, {idvar}])
字符串 发送键序列
remove( {list}, {idx} [, {end}]) 可变 从 {list} 里删除项目 {idx}-{end}
remove( {dict}, {key}) 可变 从 {dict} 里删除项目 {key}
rename( {from}, {to}) 数值 换名 (移动) 文件,从 {from} 到 {to}
repeat( {expr}, {count}) 字符串 重复 {expr} {count} 次
resolve( {filename}) 字符串 解析快捷方式对应的文件名
reverse( {list}) 列表 反转 {list},直接修改 {list}
round( {expr}) 浮点 {expr} 四舍五入
search( {pattern} [, {flags} [, {stopline} [, {timeout}]]])
数值 搜索 {pattern}
searchdecl( {name} [, {global} [, {thisblock}]])
数值 搜索变量声明
searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [...]]])
数值 搜索 start/end 对的另一侧
searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [...]]])
列表 搜索 start/end 队的另一侧
searchpos( {pattern} [, {flags} [, {stopline} [, {timeout}]]])
列表 搜索 {pattern}
server2client( {clientid}, {string})
数值 发送应答字符串
serverlist() 字符串 得到可用的服务器列表
setbufvar( {expr}, {varname}, {val}) 设置缓冲区 {expr} 的 {varname} 为
{val}
setcmdpos( {pos}) 数值 设置命令行的光标位置
setline( {lnum}, {line}) 数值 设置第 {lnum} 行的内容为 {line}
setloclist( {nr}, {list}[, {action}])
数值 用 {list} 修改位置列表
setmatches( {list}) 数值 还原匹配列表
setpos( {expr}, {list}) 数值 设置 {expr} 的位置为 {list}
setqflist( {list}[, {action}]) 数值 用 {list} 修改 quickfix 列表
setreg( {n}, {v}[, {opt}]) 数值 设置寄存器的值和类型
settabvar( {nr}, {varname}, {val})
无 设置标签页 {nr} 的 {varname} 变量为
{val}
settabwinvar( {tabnr}, {winnr}, {varname}, {val})
无 设置标签页 {tabnr} 窗口 {winnr} 的
{varname} 变量为 {val}
setwinvar( {nr}, {varname}, {val}) 设置窗口 {expr} 的 {varname} 为 {val}
shellescape( {string} [, {special}])
字符串 转义 {string} 以便用作外壳命令的参数
simplify( {filename}) 字符串 尽可能简化文件名
sin( {expr}) 浮点 {expr} 的正弦值
sinh( {expr}) 浮点 {expr} 的双曲正弦值
sort( {list} [, {func}]) 列表 排序 {list},用比较函数 {func}
soundfold( {word}) 字符串 按发音折叠 {word}
spellbadword() 字符串 光标所在的拼写错误的单词
spellsuggest( {word} [, {max} [, {capital}]])
列表 拼写建议
split( {expr} [, {pat} [, {keepempty}]])
列表 从 {pat} 分割的 {expr} 里构造 |List|
sqrt( {expr} 浮点 {expr} 的平方根
str2float( {expr}) 浮点 转换字符串为浮点数
str2nr( {expr} [, {base}]) 数值 把字符串转换为数值
strchars( {expr}) 数值 {expr} 字符串的字符长度
strdisplaywidth( {expr} [, {col}]) 数值 {expr} 字符串的显示长度
strftime( {format}[, {time}]) 字符串 指定格式的时间
stridx( {haystack}, {needle}[, {start}])
数值 {haystack} 里 {needle} 的位置
string( {expr}) 字符串 {expr} 值得字符串表示
strlen( {expr}) 数值 字符串 {expr} 的长度
strpart( {src}, {start}[, {len}])
字符串 {src} 从 {start} 开始的 {len} 个字节
strridx( {haystack}, {needle} [, {start}])
数值 {haystack} 里最后一个 {needle} 的位置
strtrans( {expr}) 字符串 翻译字符串,使之可以显示
strwidth( {expr}) 数值 {expr} 字符串的显示单元长度
submatch( {nr}) 字符串 ":substitute" 的特定匹配
substitute( {expr}, {pat}, {sub}, {flags})
字符串 {expr} 里的所有 {pat} 被 {sub} 替代
synID( {lnum}, {col}, {trans}) 数值 {lnum} 行 {col} 列所在的语法 ID
synIDattr( {synID}, {what} [, {mode}])
字符串 syntax ID {synID} 的 {what} 属性
synIDtrans( {synID}) 数值 {synID} 经过翻译的语法 ID
synstack( {lnum}, {col}) 列表 {lnum} 行 {col} 列所在的语法 ID 堆栈
system( {expr} [, {input}]) 字符串 外壳命令/过滤 {expr} 的输出
tabpagebuflist( [{arg}]) 列表 标签页里的缓冲区号列表
tabpagenr( [{arg}]) 数值 当前或最后标签页的编号
tabpagewinnr( {tabarg}[, {arg}])
数值 标签页里当前窗口的编号
taglist( {expr}) 列表 匹配 {expr} 的标签列表
tagfiles() 列表 使用的标签文件
tan( {expr}) 浮点 {expr} 的正切值
tanh( {expr}) 浮点 {expr} 的双曲正切值
tempname() 字符串 临时文件的文件名
tolower( {expr}) 字符串 字符串 {expr} 变为小写
toupper( {expr}) 字符串 字符串 {expr} 变为大写
tr( {src}, {fromstr}, {tostr}) 字符串 把 {src} 里的 {fromstr} 字符翻译为
{tostr} 字符
trunc( {expr} 浮点 浮点数 {expr} 截断小数点
type( {name}) 数值 变量 {name} 的类型
undofile( {name}) 字符串 对应 {name} 的撤销文件名
undotree() 列表 撤销文件树
values( {dict}) 列表 {dict} 的所有值
virtcol( {expr}) 数值 光标或位置标记的屏幕列
visualmode( [expr]) 字符串 最近使用的可视模式
winbufnr( {nr}) 数值 窗口 {nr} 的缓冲区号
wincol() 数值 光标所在的窗口列
winheight( {nr}) 数值 窗口 {nr} 的高度
winline() 数值 光标所在的窗口行
winnr( [{expr}]) 数值 当前窗口的编号
winrestcmd() 字符串 返回恢复窗口大小的命令
winrestview( {dict}) 无 恢复当前窗口的视图
winsaveview() 字典 保存当前窗口的视图
winwidth( {nr}) 数值 窗口 {nr} 的宽度
writefile( {list}, {fname} [, {binary}])
数值 把行列表写到文件 {fname}
abs({expr}) *abs()*
返回 {expr} 的绝对值。如果 {expr} 计算结果为浮点数,abs() 返回
浮点数。如果 {expr} 可以转换为数值,abs() 返回数值。否则报错并
返回 -1。
示例: >
echo abs(1.456)
< 1.456 >
echo abs(-5.456)
< 5.456 >
echo abs(-4)
< 4
{仅当编译时加入 |+float| 特性才有效}
acos({expr}) *acos()*
返回以弧度表示的 {expr} 的反余弦值,返回值为 [0, pi] 区间内的
浮点数。
{expr} 的计算结果必须是 [-1, 1] 区间内的浮点数或数值。
示例: >
:echo acos(0)
< 1.570796 >
:echo acos(-0.5)
< 2.094395
{仅当编译时加入 |+float| 特性才有效}
add({list}, {expr}) *add()*
在 |List| {list} 最后附加项目 {expr}。返回新产生的 |List|。例
如: >
:let alist = add([1, 2, 3], item)
:call add(mylist, "woodstock")
< 注意 如果 {expr} 是 |List|,它被作为单个项目附加进去。
|extend()| 可以用来连接 |List|。
|insert()| 可以用来把一个项目加到其它的位置上。
append({lnum}, {expr}) *append()*
当 {expr} 为 |List|: 把每个 |List| 项目作为文本行,附加到当前
缓冲区第 {lnum} 行之下。
否则,把 {expr} 作为单个文本行,附加于当前缓冲区第 {lnum} 行之
下。
{lnum} 可以为零,用于在第一行前插入一行。如果失败 ({lnum} 越
界),返回 1,成功则返回 0。例如: >
:let failed = append(line('$'), "# THE END")
:let failed = append(0, ["Chapter 1", "the beginning"])
<
*argc()*
argc() 返回当前窗口参数列表的文件数目。见 |arglist|。
*argidx()*
argidx() 返回参数列表的当前索引。0 是第一个文件。argc() - 1 是最后一
个。见 |arglist|。
*argv()*
argv([{nr}]) 返回当前窗口参数列表第 {nr} 个参数。见 |arglist|。"argv(0)" 是
第一个参数。
例如: >
:let i = 0
:while i < argc()
: let f = escape(fnameescape(argv(i)), '. ')
: exe 'amenu Arg.' . f . ' :e ' . f . '<CR>'
: let i = i + 1
:endwhile
< 如果没有 {nr} 参数,返回完整的 {arglist} 的 |List|。
asin({expr}) *asin()*
返回以弧度表示的 {expr} 的反正弦值,返回值为 [-pi/2, pi/2] 区
间内的浮点数。
{expr} 的计算结果必须是 [-1, 1] 区间内的浮点数或数值。
示例: >
:echo asin(0.8)
< 0.927295 >
:echo asin(-0.5)
< -0.523599
{仅当编译时加入 |+float| 特性才有效}
atan({expr}) *atan()*
返回 {expr} 反正切的主值,返回值为 [-pi/2, +pi/2] 区间内的弧度
值浮点数。
{expr} 计算结果必须为浮点数或数值。
示例: >
:echo atan(100)
< 1.560797 >
:echo atan(-4.01)
< -1.326405
{仅当编译时加入 |+float| 特性才有效}
atan2({expr1}, {expr2}) *atan2()*
返回 {expr1} / {expr2} 的反正切值,以弧度计算,返回值为 [-pi,
+pi] 区间内的浮点数。
{expr1} 和 {expr2} 计算结果必须为浮点数或数值。
示例: >
:echo atan2(-1, 1)
< -0.785398 >
:echo atan2(1, -1)
< 2.356194
{仅当编译时加入 |+float| 特性才有效}
*browse()*
browse({save}, {title}, {initdir}, {default})
启动文件请求窗口。只有在 "has("browse")" 返回非零时 (只有在一
些 GUI 版本里) 才可以。
输入的字段包括:
{save} 非零时,选择要写入的文件
{title} 请求窗口的标题
{initdir} 开始浏览的目录
{default} 缺省文件名
如果按了 "Cancel" 按钮、出错、或者无法浏览,返回空字符串。
*browsedir()*
browsedir({title}, {initdir})
启动目录请求窗口。只有在 "has("browse")" 返回非零时 (只有在一
些 GUI 版本里) 才能工作。
有的系统上不支持目录浏览器,这时使用文件浏览器。此时: 选择要用
的目录里的文件。
输入的字段包括:
{title} 请求窗口的标题
{initdir} 开始浏览的目录
如果按了 "Cancel" 按钮、出错、或者无法浏览,返回空字符串。
bufexists({expr}) *bufexists()*
返回数值,如果名为 {expr} 的缓冲区存在的话,返回非零。
如果 {expr} 参数是数值,指定缓冲区号。
如果 {expr} 参数是字符串,缓冲区的名字必须与其完全匹配。该名字
可以是:
- 相对于当前目录。
- 完整路径。
- 'buftype' 设为 "nofile" 的缓冲区名。
- URL 名。
列表外缓冲区也会被找到。
注意 帮助文件在 |:buffers| 里列出的是它们的短名字。但
bufexists() 需要它们的长名字才能找到它们。
bufexists() 可能报告缓冲区存在,但要使其名字可用于 |:buffer|
命令,可能需用到 |expand()|。尤其 MS-Windows 8.3 名字可能形
如 "c:\DOCUME~1"。
使用 "bufexists(0)" 可以测试是否存在轮换文件名。
*buffer_exists()*
已废弃的名字: buffer_exists()。
buflisted({expr}) *buflisted()*
返回数值,如果名为 {expr} 的缓冲区在列表内的话 (置位了
'buflisted' 选项),返回非零。
{expr} 参数用法同 |bufexists()|。
bufloaded({expr}) *bufloaded()*
返回数值,如果名为 {expr} 的缓冲区存在且已载入的话 (在窗口显
示,或者至少被隐藏),返回非零。
{expr} 参数用法同 |bufexists()|。
bufname({expr}) *bufname()*
返回缓冲区的名字,如同 ":ls" 命令显示的那样。
如果 {expr} 参数是数值,指定缓冲区号。数值零代表当前窗口的轮换
缓冲区。
如果 {expr} 参数是字符串,它用作 |file-pattern| 来匹配缓冲区名
字。这里总假设置位 'magic' 而 'cpoptions' 为空。如果有超过一个
匹配,返回空字符串。
"" 或 "%" 可用来指定当前缓冲区,"#" 指定轮换缓冲区。
完整的匹配优先,如果没有,也接受在缓冲区名的开始,结束和中间的
匹配。如果你只愿意接受完整的匹配,在模式的开始放上 "^",在结尾
放上 "$"。
先查找列表内缓冲区。如果列出缓冲区有唯一的匹配,返回之。不然,
再查找列表外的缓冲区。
如果 {expr} 是字符串,但你想用作缓冲区号,给它加零可以强制转化
为数值型: >
:echo bufname("3" + 0)
< 如果缓冲区不存在,或者没有名字,返回空字符串。 >
bufname("#") 轮换缓冲区名
bufname(3) 缓冲区 3 的名字
bufname("%") 当前缓冲区名
bufname("file2") 匹配 "file2" 的缓冲区名。
< *buffer_name()*
已废弃的名字: buffer_name()。
*bufnr()*
bufnr({expr} [, {create}])
返回缓冲区的编号,如同 ":ls" 命令显示的那样。关于 {expr} 的使
用,见上 |bufname()|。
如果不存在符合的缓冲区,返回 -1。或者,如果提供了 {create} 参
数而且非零,建立一个新的列表外缓冲区,并返回其编号。
bufnr("$") 是最后一个缓冲区: >
:let last_buffer = bufnr("$")
< 返回数值,即最大的已有的缓冲区的编号。注意 较小的编号不一定都
对应存在的缓冲区,因为 ":bwipeout" 可能永久地删除了部分的缓冲
区。用 bufexists() 可以测试缓冲区是否存在。
*buffer_number()*
已废弃的名字: buffer_number()。
*last_buffer_nr()*
bufnr("$") 已废弃的名字: last_buffer_nr()。
bufwinnr({expr}) *bufwinnr()*
返回数值,即缓冲区 {expr} 对应的第一个窗口的编号。{expr} 的使
用方式见上 |bufname()|。如果缓冲区 {expr} 不存在或者没有对应的
窗口,返回 -1。例如: >
echo "包含缓冲区 1 的窗口是 " . (bufwinnr(1))
< 该编号可用于 |CTRL-W_w| 和 ":wincmd w" |:wincmd|。
只处理当前标签页。
byte2line({byte}) *byte2line()*
返回当前缓冲区第 {byte} 个字节所在的行号。取决于当前缓冲区的
'fileformat' 选项,这可以包括不同的换行符。第一个字符的字节编
号为 1。
另见 |line2byte()|、|go| 和 |:goto|。
{仅当编译时加入 |+byte_offset| 特性才有效}
byteidx({expr}, {nr}) *byteidx()*
返回字符串 {expr} 里第 {nr} 个字符的字节位置。零代表第一个字
符,此时返回零。
该函数只对多字节字符有用,不然返回值总是等于 {nr}。
合成用字符作为单个字符计算。
例如: >
echo matchstr(str, ".", byteidx(str, 3))
< 显示第四个字符。另一个方法也能达到相同的效果: >
let s = strpart(str, byteidx(str, 3))
echo strpart(s, 0, byteidx(s, 1))
< 如果字符数不足 {nr},返回 -1。
如果刚好 {nr} 个字符,返回字符串的长度。
call({func}, {arglist} [, {dict}]) *call()* *E699*
调用函数 {func},使用 |List| {arglist} 项目作为参数。
{func} 可以是 |Funcref| 或函数名。
a:firstline 和 a:lastline 设为当前行。
返回调用的函数的结果。
{dict} 用于为函数指定 "dict" 属性。其目的是设置局部变量
"self"。|Dictionary-function|
ceil({expr}) *ceil()*
返回浮点数,即大于等于 {expr} 的最小整数 (向上取整)。
{expr} 的计算结果必须是浮点数或数值。
示例: >
echo ceil(1.456)
< 2.0 >
echo ceil(-5.456)
< -5.0 >
echo ceil(4.0)
< 4.0
{仅当编译时加入 |+float| 特性才有效}
changenr() *changenr()*
返回最近改变的编号。这和 |:undolist| 显示的编号相同,可用于
|:undo| 命令。
如果发生了改变,返回的是此改变的编号。在重做以后,返回的是重做
的改变的编号。在撤销以后,返回撤销的改变的编号减一。
char2nr({expr}) *char2nr()*
返回 {expr} 第一个字符的数值结果。例如: >
char2nr(" ") 返回 32
char2nr("ABC") 返回 65
< 使用当前的 'encoding'。比如对 "utf-8" 来说: >
char2nr("á") 返回 225
char2nr("á"[0]) 返回 195
< |nr2char()| 是它的逆操作。
cindent({lnum}) *cindent()*
得到第 {lnum} 行根据 C 缩进规则应有的缩进距离,见 'cindent'。
缩进的计算以空格计,因而和 'tabstop' 的值是有关系的。{lnum} 的
使用方式和 |getline()| 相同。
如果 {lnum} 非法或者 Vim 编译时不带 |+cindent| 特性,返回 -1。
见 |C-indenting|。
clearmatches() *clearmatches()*
清除之前 |matchadd()| 和 |:match| 命令定义的匹配。
*col()*
col({expr}) 返回数值,即 {expr} 给定的列位置的字节索引。可接受的位置是:
. 光标位置
$ 光标行的行尾 (返回光标行的字符数加 1)
'x 位置标记 x 的位置 (如果该位置标记没有设置,返回 0)
另外,{expr} 可以是 [lnum, col]: 包含行号和列号的 |List|。常用
于指定列号为 "$" 以得到特定行的末列列号。如果 "lnum" 或 "col"
超出范围,col() 返回零。
要得到行号用 |line()|。两者都要用 |getpos()|。
要得到屏幕列的位置,用 |virtcol()|。
注意 只能使用当前文件的位置标记。
例如: >
col(".") 光标所在列
col("$") 光标行的长度加 1
col("'t") 位置标记 t 的列号
col("'" . markname) 等于 markname 的位置标记的列号
< 第一列为 1。0 用来返回错误。
大写位置标记的对应列可能在另一个缓冲区中。
如果激活了 'virtualedit' 并且如果光标在行尾之后的话,计算光标
位置得到的列号比实际的多 1。可用来在插入模式得到列数: >
:imap <F2> <C-O>:let save_ve = &ve<CR>
\<C-O>:set ve=all<CR>
\<C-O>:echo col(".") . "\n" <Bar>
\let &ve = save_ve<CR>
<
complete({startcol}, {matches}) *complete()* *E785*
设置插入模式补全的匹配。
只能用于插入模式。需要使用 CTRL-R = 的映射 |i_CTRL-R|。不能在
CTRL-O 之后或者在表达式映射里使用。
{startcol} 是行内待补全文本开始的字节偏移。直到光标为止的文本
就是原始的文本,它将要被匹配所替代。用 col('.') 会得到空串。而
"col('.') - 1" 将用匹配替换单个字符。
{matches} 必须是 |List|。每个 |List| 项目是一个匹配。
|complete-items| 说明可能的项目类型。
注意 调用此函数后,你不应插入任何使补全停止的内容。
用 CTRL-N 和 CTRL-P 选择匹配,就像普通的插入模式补全那样。如果
指定,会出现弹出菜单,见 |ins-completion-menu|。
示例: >
inoremap <F5> <C-R>=ListMonths()<CR>
func! ListMonths()
call complete(col('.'), ['January', 'February', 'March',
\ 'April', 'May', 'June', 'July', 'August', 'September',
\ 'October', 'November', 'December'])
return ''
endfunc
< 此例并不很有用,但可以说明功能。注意这里返回空串,以免插入零。
complete_add({expr}) *complete_add()*
把 {expr} 加到匹配的列表里。只能用于 'completefunc' 选项指定的
函数里。
返回 0 代表失败 (空字符串或者内存不足),1 代表加入了匹配,2 代
表匹配已经在列表里。
|complete-functions| 解释 {expr}。它和 'omnifunc' 应该返回的列
表中单个项目相同。
complete_check() *complete_check()*
寻找补全匹配时,检查输入的键。如果寻找匹配需要一定时间时有用。
如果匹配的搜索被中止,返回非零。否则返回零。
只能用于 'completefunc' 选项指定的函数里。
*confirm()*
confirm({msg} [, {choices} [, {default} [, {type}]]])
confirm() 提供用户一个对话框,从中可以作出选择。返回选择的序
号。第一个选择为 1。
注意: confirm() 只有在编译时加入对话框支持才存在,见
|+dialog_con| 和 |+dialog_gui|。
在 |dialog| 里显示 {msg} 消息,并提供可能的选择 {choices}。如
果 {choices} 不存在或者为空,使用 "&OK" (经过翻译)。
{msg} 是字符串,'\n' 用来包含换行符。在有些系统上该字符串在放
不下时被回绕,但并非所有系统都如此。
{choices} 是一个字符串,用 '\n' 分隔各个选择,例如 >
confirm("Save changes?", "&Yes\n&No\n&Cancel")
< '&' 之后的字符提供该选择的快捷键。这样,你可以输入 'c' 来选择
"Cancel"。快捷键不一定是第一个字符: >
confirm("file has been modified", "&Save\nSave &All")
< 控制台里,每个选择的第一个字符用作缺省的快捷键。
可选的 {default} 参数是用户按 <CR> 使用的选择号。设定 1 使得第
一个选项成为缺省,如果是 0,则不设定任何缺省。如果不提供
{default},假设为 1。
可选的 {type} 参数指定对话框的类型。只有在 GTK、Mac、Motif 和
Win32 GUI 上才用得上,它用以指定图标。可以取的值是: "Error"、
"Question"、 "Info"、 "Warning" 或 "Generic"。只有第一个字符是
重要的。如果忽略 {type},使用 "Generic"。
如果用户用 <Esc>、CTRL-C 或者别的合法的中断键中止对话框,
confirm() 返回 0。
一个例子: >
:let choice = confirm("你要吃什么?", "&苹果\n&桔子\n&香蕉", 2)
:if choice == 0
: echo "快下定决心!"
:elseif choice == 3
: echo "好吃"
:else
: echo "我本人喜欢香蕉。"
:endif
< GUI 的对话框使用按钮。按钮的排放方式取决于 'guioptions' 里的
'v' 标志位。如果包含该标志位,按钮总是竖排的。不然,confirm()
试图把按钮放在一行里。如果放不下,那么还是使用竖排的方式。在有
的系统上,无论如何总是使用横排。
*copy()*
copy({expr}) 构造 {expr} 的备份。对数值和字符串而言,这和直接使用 {expr}
并无不同。
如果 {expr} 是 |List|,建立一个浅备份。这意味着,原来的 |List|
可以被改变,而不会影响新建的备份。反之亦然。不过,其中的项目只
有一份,所以修改项目同时修改两个 |List| 的内容。另见
|deepcopy()|。
cos({expr}) *cos()*
返回浮点数,即以弧度测量的 {expr} 的余弦值。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo cos(100)
< 0.862319 >
:echo cos(-4.01)
< -0.646043
{仅当编译时加入 |+float| 特性才有效}
cosh({expr}) *cosh()*
返回 {expr} 的双曲余弦值,返回值为 [1, inf] 区间内的浮点数。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo cosh(0.5)
< 1.127626 >
:echo cosh(-0.5)
< -1.127626
{仅当编译时加入 |+float| 特性才有效}
count({comp}, {expr} [, {ic} [, {start}]]) *count()*
返回 |List| 或 |Dictionary| {comp} 里值为 {expr} 的项目出现的
次数。
如果给出 {start},从该索引指定的项目开始。{start} 只能用于
|List|。
如果给出 {ic} 并且非零,忽略大小写。
*cscope_connection()*
cscope_connection([{num} , {dbpath} [, {prepend}]])
检查 |cscope| 连接是否存在。如果没有参数,则函数返回:
0,如果 cscope 不存在 (编译没有带该特性),或者不存在
cscope 连接;
1,如果至少有一个 cscope 连接。
如果指定了参数,那么 {num} 的值指定如何检查 cscope 连接存在与
否的方式:
{num} 存在检查的方式描述 ~
----- ------------------------------
0 等同于无参数 (例如,"cscope_connection()")。
1 忽略 {prepend},使用 {dbpath} 的字符串部分匹配。
2 忽略 {prepend},使用 {dbpath} 的字符串完整匹配。
3 使用 {prepend},使用 {dbpath} 和 {prepend} 的字符串部
分匹配。
4 使用 {prepend},使用 {dbpath} 和 {prepend} 的字符串完
整匹配。
注意: 所有的字符串比较都对大小写敏感!
示例。假定我们有如下设置 (":cs show" 的输出): >
# pid database name prepend path
0 27664 cscope.out /usr/local
<
启动方式 返回值 ~
---------- ---------- >
cscope_connection() 1
cscope_connection(1, "out") 1
cscope_connection(2, "out") 0
cscope_connection(3, "out") 0
cscope_connection(3, "out", "local") 1
cscope_connection(4, "out") 0
cscope_connection(4, "out", "local") 0
cscope_connection(4, "cscope.out", "/usr/local") 1
<
cursor({lnum}, {col} [, {off}]) *cursor()*
cursor({list})
把光标定位在第 {lnum} 行的第 {col} 列 (字节计数)。第一列为 1。
如果只有一个参数 {list},它被看作带两个或三个参数 {lnum}、
{col} 和 {off} 的 |List|。和 |getpos()| 的返回值类似,但没有第
一项。
不改变跳转表。
如果 {lnum} 超过缓冲区的行数,光标定位在缓冲区的末行。
如果 {lnum} 为零,光标留在当前行。
如果 {col} 超过该行的字节数,光标定位在该行的最后一个字符上。
如果 {col} 为零,光标留在当前列。
如果使用 'virtualedit',{off} 指定从该字符开始以屏幕列计算的偏
移。例如,在制表里或者在最后一个字符之后的某个位置。
如果定位成功,返回 0,否则返回 -1。
deepcopy({expr}[, {noref}]) *deepcopy()* *E698*
构造 {expr} 的备份。对数值和字符串而言,这和直接使用 {expr}
并无不同。
如果 {expr} 是 |List|,建立一个完整的备份。这意味着,原来的
|List| 可以被改变,而不会影响新建的备份。反之亦然。如果某个项
目是 |List|,递归地建立它的备份。这样,备份里项目的修改也不会
影响到原来 |List| 的内容。
如果省略 {noref} 或为零,包含的 |List| 或 |Dictionary| 只复制
一次。所有指向它的引用指向此一备份。如果 {noref} 设为 1,每次
|List| 或 |Dictionary| 的出现会导致建立一个新的备份。这意味着
循环引用会使得 deepcopy() 失败。
*E724*
嵌套可达 100 层。如果有指向较高层的引用,{noref} 为 1 的深备份
会失败。
另见 |copy()|。
delete({fname}) *delete()*
删除名为 {fname} 的文件。返回类型为数值。如果成功删除文件,返
回 0,如果删除失败,返回非零。
从 |List| 里删除项目请用 |remove()|。
*did_filetype()*
did_filetype() 如果执行自动命令时,激活 FileType 事件至少一次,则返回非零。可
以用于防止在检测文件类型的脚本里再次激活 FileType 事件。
|FileType|
如果编辑另外一个文件,该计数被复位,因而这只能检查 FileType 事
件是否在当前缓冲区里激活过。它允许开始编辑另一个缓冲区的自动命
令设置 'filetype' 并载入语法文件。
diff_filler({lnum}) *diff_filler()*
返回第 {lnum} 行之上的填充行的数目。
这些是在另一个进行比较的窗口里在此位置插入的行。这些填充行在屏
幕上显示,但缓冲区里并不存在。
{lnum} 的用法类似于 |getline()|。所以 "." 是当前行,"'m" 是位
置标记 m,等等。
如果当前窗口不处于 diff 模式,返回 0。
diff_hlID({lnum}, {col}) *diff_hlID()*
返回 diff 模式行 {lnum} 和列 {col} (字节位置) 所在的高亮 ID。
如果当前行没有差异,返回零。
{lnum} 的用法类似于 |getline()|。所以 "." 是当前行,"'m" 是位
置标记 m,等等。
最左列的 {col} 为 1,第一行的 {lnum} 为 1。
高亮 ID 可以用于 |synIDattr()|,以得到高亮对应的语法信息。
empty({expr}) *empty()*
如果 {expr} 为空,返回数值 1,否则返回 0。
|List| 或 |Dictionary| 没有项目时为空。数值的值为零时为空。
如果 |List| 很大,这比把长度和零比较要快得多。
escape({string}, {chars}) *escape()*
在 {string} 里用反斜杠转义 {chars} 里的字符。例如: >
:echo escape('c:\program files\vim', ' \')
< 返回: >
c:\\program\ files\\vim
< 另见 |shellescape()|。
*eval()*
eval({string}) 计算 {string} 并返回其结果。这对把 |string()| 的结果转换为原来
的值尤其有用。适用于数值、浮点数、字符串和两者的复合类型。也可
用于指向已有函数的 |Funcref|。
eventhandler() *eventhandler()*
如果在事件处理中则返回 1。此时,Vim 在等待用户输入一个字符的时
候被中断,比如,在 Vim 上拖放了一个文件。这也意味着此时不能使
用交互的命令。如果不是,返回零。
executable({expr}) *executable()*
本函数检查名字由 {expr} 指定的可执行文件存在与否。{expr} 必须
是程序不带任何参数的名字。
executable() 使用 $PATH 的值和/或程序的普通的搜索路径。
*PATHEXT*
MS-DOS 和 MS-Windows 上,可以可选地包含 ".exe"、".bat" 等。为
此,$PATHEXT 里的扩展名会被尝试。这样,如果 "foo.exe" 不存在,
可能会找到 "foo.exe.bat"。如果没有设置 $PATHEXT,使用的是
".exe;.com;.bat;.cmd"。$PATHEXT 里可以使用单独的句号,以尝试没
有扩展名的名字。如果 'shell' 看起来像 Unix 外壳,那么也尝试没
有扩展名的名字。
MS-DOS 和 MS-Windows 上,只检查是否文件存在且不是目录,并不检
查它是否真的可以执行。
MS-Windows 上,和 Vim 在同一目录的可执行文件总能找到。因为这个
目录加到了 $PATH 里,执行应该也没有问题 |win32-PATH|。
返回数值:
1 存在
0 不存在
-1 此系统中没有实现
*exists()*
exists({expr}) 返回数值,如果 {expr} 被定义,返回非零,不然返回零。{expr} 参
数是字符串,可以使用以下选择之一:
&option-name Vim 选项 (只检查是否存在,而不是是否工
作)
+option-name 能工作的 Vim 选项。
$ENVNAME 环境变量 (也可以通过和空字符串比较完
成)
*funcname 内建函数 (见 |functions|) 或者用户定义
的函数 (见 |user-functions|)。
varname 内部变量 (见 |internal-variables|)。也
适用于 |curly-braces-names|、
|Dictionary| 项目、|List| 项目等等。
小心计算索引时可能会因为非法的表达式产
生错误信息。例如: >
:let l = [1, 2, 3]
:echo exists("l[5]")
< 0 >
:echo exists("l[xx]")
< E121: Undefined variable: xx
0
:cmdname Ex 命令: 内建命令、用户命令或者命令修
饰符 |:command|。
返回:
1 匹配命令的开始
2 完整匹配命令
3 匹配多个用户命令
要检查命令是否支持,检查返回值是否为
2。
:2match |:2match| 命令。
:3match |:3match| 命令。
#event 符合此事件的自动命令
#event#pattern 符合此事件和此模式的自动命令 (模式按本
义出现,和自动命令的模式逐字符比较)
#group 存在自动命令组
#group#event 在该组里定义并符合此事件的自动命令。
#group#event#pattern
为该组定义、符合事件和模式的自动命令。
##event 支持此事件的自动命令。
要检查某特性是否支持,用 |has()|。
例如: >
exists("&shortname")
exists("$HOSTNAME")
exists("*strftime")
exists("*s:MyFunc")
exists("bufcount")
exists(":Make")
exists("#CursorHold")
exists("#BufReadPre#*.gz")
exists("#filetypeindent")
exists("#filetypeindent#FileType")
exists("#filetypeindent#FileType#*")
exists("##ColorScheme")
< 符号 (&/$/*/#) 和名字之间不能有空格。
名字之后不能有附加字符,虽然现在有一些情况下会忽略这些字符,但
将来的检查可能更严格。所以不要依赖此行为!
可以通过的例子: >
exists(":make")
< _不_能通过的例子: >
exists(":make install")
< 注意 参数必须是字符串,不是变量的名字本身。例如: >
exists(bufcount)
< 不检查 "bufcount" 变量是否存在,而是提取 "bufcount" 的值,并检
查其 (根据此处的语法) 是否存在。
exp({expr}) *exp()*
返回 {expr} 的指数函数值,返回值为 [0, inf] 区间内的浮点数。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo exp(2)
< 7.389056 >
:echo exp(-1)
< 0.367879
{仅当编译时加入 |+float| 特性才有效}
expand({expr} [, {flag}]) *expand()*
扩展 {expr} 里的通配符和下列特殊关键字。返回的是字符串。
如果返回多个匹配,以 <NL> 字符分隔 [备注: 5.0 版本使用空格。但
是文件名如果也包含空格就会有问题]。
如果扩展失败,返回空字符串。这不包括不存在文件的名字。
如果 {expr} 以 '%'、'#' 或 '<' 开始,以类似于
|cmdline-special| 变量的方式扩展,包括相关的修饰符。这里是一个
简短的小结:
% 当前文件名
# 轮换文件名
#n 轮换文件名 n
<cfile> 光标所在的文件名
<afile> 自动命令文件名
<abuf> 自动命令缓冲区号 (以字符串形式出现!)
<amatch> 自动命令匹配的名字
<sfile> 载入的脚本文件名
<cword> 光标所在的单词
<cWORD> 光标所在的字串 (WORD)
<client> 最近收到的消息的 {clientid}
|server2client()|
修饰符:
:p 扩展为完整的路径
:h 头部 (去掉最后一个部分)
:t 尾部 (只保留最后一个部分)
:r 根部 (去掉一个扩展名)
:e 只有扩展名
例如: >
:let &tags = expand("%:p:h") . "/tags"
< 注意 扩展 '%'、'#' 或者 '<' 开头的字符串的时候,其后的文本被忽
略。这样_不_行: >
:let doesntwork = expand("%:h.bak")
< 应该这样: >
:let doeswork = expand("%:h") . ".bak"
< 还要 注意 扩展 "<cfile>" 和其它形式只能返回被引用的文件名,而
不会进一步扩展。如果 "<cfile>" 是 "~/.cshrc",你需要执行另一个
expand() 把 "~/" 扩展为主目录的路径: >
:echo expand(expand("<cfile>"))
<
变量名和其后的修饰符之间不能有空白。|fnamemodify()| 函数可以用
来修改普通的文件名。
使用 '%' 或 '#' 但当前或轮换文件名没有定义的时候,使用空字符
串。在无名缓冲区使用 "%:p" 生成当前目录,后加一个 '/'。
如果 {expr} 不以 '%'、'#' 或 '<' 开始,它以命令行上的文件名那
样被扩展。使用 'suffixes' 和 'wildignore',除非给出可选的
{flag} 参数而且非零。这里可以有不存在的文件的名字。"**" 项目可
以用来在目录树里查找。例如,要寻找当前目录及其下目录的所有的
"README": >
:echo expand("**/README")
<
expand() 也可用来扩展变量和只有外壳知道的环境变量。但这会很
慢,因为需要启动外壳。见 |expr-env-expand|。扩展后的变量还是被
当作文件名的列表处理。如果不能扩展环境变量,保留其不变。这样,
":echo expand('$FOOBAR')" 返回的还是 "$FOOBAR"。
|glob()| 说明如何找到存在的文件。|system()| 说明如何得到外部命
令的原始输出。
extend({expr1}, {expr2} [, {expr3}]) *extend()*
{expr1} 和 {expr2} 必须都是 |List| 或者都是 |Dictionary|。
如果都是 |List|: 把 {expr2} 附加到 {expr1} 之后。
如果给出 {expr3},把 {expr2} 里的项目加到 {expr1} 的第 {expr3}
个项目之前。如果 {expr3} 为零,插在第一个项目之前。如果
{expr3} 等于 len({expr1}),那么 {expr2} 会附加在最后。
例如: >
:echo sort(extend(mylist, [7, 5]))
:call extend(mylist, [2, 3], 1)
< 如果 {expr1} 和 {expr2} 是同一个列表,复制的项目数等于列表原来
的长度。例如,如果 {expr} 为 1,则复制列表首值 N 次 (N 是列表
原来的长度)。
用 |add()| 把一个项目加入列表。要连接两个列表成为一个新列表,
用 + 操作符: >
:let newlist = [1, 2, 3] + [4, 5]
<
如果都是 |Dictionary|: 把 {expr2} 里的所有项目加入 {expr1}。
如果 {expr1} 和 {expr2} 包含相同的键,那么 {expr3} 决定应该怎
么做:
{expr3} = "keep": 保持 {expr1} 的值
{expr3} = "force": 使用 {expr2} 的值
{expr3} = "error": 给出错误信息 *E737*
如果省略 {expr3},假设使用 "force"。
只要 {expr2} 非空,{expr1} 就被改变。如果需要,给 {expr1} 先做
个备份。
{expr2} 保持不变。
返回 {expr1}。
feedkeys({string} [, {mode}]) *feedkeys()*
将 {string} 里的字符放在队列里等候处理,就像它们来自映射或者用
户输入一样。它们加在预输入 (typeahead) 缓冲区的尾端,所以如果
仍然在执行映射,这些字符出现在映射内容之后。
该函数不会等待 {string} 包含的键处理完毕。
{string} 如果要包含特殊键,可以使用双引号和 "\..." 记法
|expr-quote|。例如,feedkeys("\<CR>") 会模拟 <Enter> 键击。但
feedkeys('\<CR>') 却实际压入五个字符。
如果不给出 {mode},这些键会经过重映射。
{mode} 是字符串,包含以下字符标志位:
'm' 对键重映射。缺省。
'n' 不对键重映射。
't' 像用户输入那样处理键;如果不包含,像来自映射一样处理。
这会影响撤销、打开折叠等行为。
返回值总为 0。
filereadable({file}) *filereadable()*
返回数值,如果名为 {file} 的文件存在且可读,则为真。如果
{file} 不存在,或者是一个目录,返回假。{file} 可以是任何返回字
符串的表达式。
如果你不关心文件是否可读,可用 |glob()|。
*file_readable()*
已废弃的名字: file_readable()。
filewritable({file}) *filewritable()*
返回数值,如果名为 {file} 的文件存在且可写,则为 1。如果
{file} 不存在,或者不可写,返回 0。如果 {file} 是一个目录但是
可写,返回 2。
filter({expr}, {string}) *filter()*
{expr} 必须是 |List| 或者 |Dictionary|。
对 {expr} 里的每个项目计算 {string},如果结果为零,从该 |List|
或 |Dictionary| 里删除该项目。
{string} 计算时,|v:val| 包含当前项目的值。
|Dictionary| 中 |v:key| 也包含当前项目的键。
例如: >
:call filter(mylist, 'v:val !~ "OLD"')
< 删除所有出现 "OLD" 的项目。 >
:call filter(mydict, 'v:key >= 8')
< 删除所有键小于 8 的值。 >
:call filter(var, 0)
< 删除所有的值,从而清除该 |List| 或 |Dictionary|。
finddir({name}[, {path}[, {count}]]) *finddir()*
在 {path} 里查找目录 {name}。支持向下和向上的递归目录搜索。
{path} 的语法参见 |file-searching|。
返回第一个找到的路径。如果找到的
路径在当前目录之下,返回相对路径。否则,返回完整路径。
如果省略 {path},使用 'path'。
如果给出可选的 {count},寻找 {path} 里 {name} 第 {count} 次出
现,而不是第一次。
如果 {count} 为负,返回所有的匹配的列表。
这和 ex 命令 |:find| 非常类似。
{仅当编译时加入 |+file_in_path| 特性才有效}
findfile({name}[, {path}[, {count}]]) *findfile()*
类似于 |finddir()|,不过寻找文件而不是目录。
使用 'suffixesadd'。
例如: >
:echo findfile("tags.vim", ".;")
< 从当前文件所在的目录开始往上搜索,直到找到文件 "tags.vim" 为
止。
float2nr({expr}) *float2nr()*
返回数值,即 {expr} 省略小数点部分的结果。
{expr} 的计算结果必须是浮点数或数值。
如果 {expr} 的值超出 |Number| 的范围,结果为 0x7fffffff 或
-0x7fffffff。而 NaN 转换为 -0x80000000。
示例: >
echo float2nr(3.95)
< 3 >
echo float2nr(-23.45)
< -23 >
echo float2nr(1.0e100)
< 2147483647 >
echo float2nr(-1.0e150)
< -2147483647 >
echo float2nr(1.0e-100)
< 0
{仅当编译时加入 |+float| 特性才有效}
floor({expr}) *floor()*
返回浮点数,即小于等于 {expr} 的最大整数 (向下取整)。
{expr} 的计算结果必须是浮点数或数值。
示例: >
echo floor(1.856)
< 1.0 >
echo floor(-5.456)
< -6.0 >
echo floor(4.0)
< 4.0
{仅当编译时加入 |+float| 特性才有效}
fmod({expr1}, {expr2}) *fmod()*
返回 {expr1} / {expr2} 的余数,该除法可能实际无法表达出来。选
择某整数 i,返回 {expr1} - i * {expr2},使得如果 {expr2} 非
零,结果和 {expr1} 同号而绝对值小于 {expr2} 的绝对值。如果
{expr2} 为零,返回零。返回值为浮点数。
{expr1} 和 {expr2} 的计算结果必须是浮点数或数值。
示例: >
:echo fmod(12.33, 1.22)
< 0.13 >
:echo fmod(-12.33, 1.22)
< -0.13
{仅当编译时加入 |+float| 特性才有效}
fnameescape({string}) *fnameescape()*
转义 {string} 以便用作命令的文件名参数。有特殊意义的字符,如
'%' 和 '|',会用反斜杠转义。
多数系统上,会转义的字符是 " \t\n*?[{`$\\%#'\"|!<"。在反斜杠可
以出现在文件名中的系统上,此字符集取决于 'isfname'。
也转义出现在开头的 '+' 和 '>' 字符 (|:edit| 和 |:write| 之后有
特殊意义),还有单个出现的 "-" (|:cd| 之后有特殊意义)。
示例: >
:let fname = '+some str%nge|name'
:exe "edit " . fnameescape(fname)
< 则会执行: >
edit \+some\ str\%nge\|name
fnamemodify({fname}, {mods}) *fnamemodify()*
根据 {mods} 修改文件名 {fname}。{mods} 是一个字符序列组成的字
符串,就像命令行上使用的文件名那样。见 |filename-modifiers|。
例如: >
:echo fnamemodify("main.c", ":p:h")
< 返回: >
/home/mool/vim/vim/src
< 注意: 环境变量不能用于 {fname},需要先用 |expand()| 扩展。
foldclosed({lnum}) *foldclosed()*
返回数值,如果行 {lnum} 在关闭的折叠中,返回该折叠开始的行号。
如果行 {lnum} 不在关闭的折叠中,返回 -1。
foldclosedend({lnum}) *foldclosedend()*
返回数值,如果行 {lnum} 在关闭的折叠中,返回该折叠结束的行号。
如果行 {lnum} 不在关闭的折叠中,返回 -1。
foldlevel({lnum}) *foldlevel()*
返回数值,当前缓冲区第 {lnum} 行的折叠级别。如果在嵌套的折叠
里,返回最深的那层。如果行 {lnum} 没有折叠,返回零。这和折叠是
打开还是关闭无关。在更新折叠时 (在 'foldexpr' 里),如果折叠还
在更新而相应的折叠级别未知,返回 -1。一个特例是前一行的级别通
常总是知道的。
*foldtext()*
foldtext() 返回关闭的折叠所显示的行。这是 'foldtext' 选项使用的缺省函数,
而且也只应该在计算 'foldtext' 时使用。它使用 |v:foldstart|、
|v:foldend| 和 |v:folddashes| 变量。
返回的字符串看起来像: >
+-- 45 lines: abcdef
< 连字符的数目取决于折叠级别。"45" 是折叠的行数。"abcdef" 是折叠
第一个非空白行的文本。开头的空白、"//" 和 "/*" 还有
'foldmarker' 和 'commentstring' 选项的文本都被去除。
{仅当编译时加入 |+folding| 特性才有效}
foldtextresult({lnum}) *foldtextresult()*
返回行 {lnum} 所在的关闭的折叠显示的文本。在合适的上下文里计算
'foldtext'。
如果 {lnum} 没有关闭的折叠,返回空字符串。
{lnum} 的用法类似于 |getline()|。所以 "." 是当前行,"'m" 是位
置标记 m,等等。
可用于输出折叠文本,例如,到 HTML 格式。
{仅当编译时加入 |+folding| 特性才有效}
*foreground()*
foreground() 把 Vim 窗口带到前台。用于从客户发送到 Vim 服务器的时候。
|remote_send()|
在 Win32 系统上,可能不行,操作系统并不总能允许窗口把自己带到
前台。这时应使用 |remote_foreground()|。
{仅当使用 Win32、Athena、Motif 和 GTK GUI 版本和 Win32 控制台
版本时才有效}
function({name}) *function()* *E700*
返回指向函数 {name} 的 |Funcref| 变量。{name} 可以是用户定义的
函数或者内部函数。
garbagecollect([at_exit]) *garbagecollect()*
清理不再使用但有循环引用的 |List| 和 |Dictionary|。几乎没有需
要调用这个函数,因为 Vim 内存不足或者 'updatetime' 之后等待用
户按键时会自动执行此功能。没有循环引用的项目总是在不再使用的时
候就被立即释放了。
可用于删除很大的 |List| 和/或 |Dictionary| 而且有循环引用的时
候,尤其是在要运行很长时间的脚本里。
如果可选的 "at_exit" 参数为一,并且之前还没做过的话,Vim 即使
在退出时也会执行垃圾回收。可用于检查内存泄漏。
get({list}, {idx} [, {default}]) *get()*
获取 |List| {list} 的第 {idx} 个项目。如果不存在此项目,返回
{default}。如果省略 {default},返回零。
get({dict}, {key} [, {default}])
获取 |Dictionary| {dict} 键为 {key} 的项目。如果不存在此项目,
返回 {default}。如果省略 {default},返回零。
*getbufline()*
getbufline({expr}, {lnum} [, {end}])
返回 {expr} 缓冲区的第 {lnum} 到 {end} (包含) 行的 |List|。如
果省略 {end},返回只有一行 {lnum} 的 |List|。
关于 {expr} 的用法,见上 |bufname()|。
{lnum} 和 {end} 可以使用 "$" 来表示缓冲区的最后一行。除此以
外,必须用数值。
如果 {lnum} 小于 1 或大于缓冲区的行数,返回空 |List|。
如果 {end} 大于缓冲区的行数,就把它当成缓冲区的行数。如果
{end} 在 {lnum} 之前,返回空 |List|。
此函数只能用于已经载入的缓冲区。未载入或不存在的缓冲区总是返回
空 |List|。
例如: >
:let lines = getbufline(bufnr("myfile"), 1, "$")
getbufvar({expr}, {varname}) *getbufvar()*
返回缓冲区 {expr} 里的选项或者局部变量 {varname} 的值。注意 必
须使用不带 "b:" 的名字。
如果 {varname} 为空,返回包含所有局部于缓冲区变量的字典。
也可用于全局或者局部于缓冲区的选项,但不能用于全局或者局部于窗
口的变量,还有局部于窗口的选项。
关于 {expr} 的使用方式,见上 |bufname()|。
如果缓冲区或者变量不存在,返回空字符串。不会有错误消息。
示例: >
:let bufmodified = getbufvar(1, "&mod")
:echo "todo myvar = " . getbufvar("todo", "myvar")
<
getchar([expr]) *getchar()*
从用户或输入流中提取单个字符。
如果忽略 [expr],等待直到有字符输入为止。
如果 [expr] 为 0,只有在有字符可用时才取得字符,否则返回零。
如果 [expr] 为 1,只检查是否有字符可用,并不消耗该字符。如果没
有字符,返回零。
如果没有 {expr} 或者 {expr} 为零,返回整个字符或者特殊键。如果
是 8 位字符,以数值形式返回。用 nr2char() 把它转化成字符串。否
则返回经过编码的字符构成的字符串。如果是特殊键,返回一串字节,
以 0x80 (十进制: 128) 开始。它和字符串 "\<Key>" 等值,例如
"\<Left>"。如果用带修饰符 (Shift,Control, Alt) 的字符而字符
本身不包含该修饰符时,返回值也用字符串类型。
如果 {expr} 为 1,只返回第一个字节。如果是单字节字符,返回的就
是该字符自身的数值形式。用 nr2char() 把它转化为字符串。
用户点击鼠标时,返回鼠标事件。所在的位置可以在 |v:mouse_col|、
|v:mouse_lnum| 和 |v:mouse_win| 里找到。下例用通常的处理方法定
位鼠标: >
let c = getchar()
if c == "\<LeftMouse>" && v:mouse_win > 0
exe v:mouse_win . "wincmd w"
exe v:mouse_lnum
exe "normal " . v:mouse_col . "|"
endif
<
There is no prompt, you will somehow have to make clear to the
user that a character has to be typed.
There is no mapping for the character.
Key codes are replaced, thus when the user presses the <Del>
key you get the code for the <Del> key, not the raw character
sequence. Examples: >
getchar() == "\<Del>"
getchar() == "\<S-Left>"
< This example redefines "f" to ignore case: >
:nmap f :call FindChar()<CR>
:function FindChar()
: let c = nr2char(getchar())
: while col('.') < col('$') - 1
: normal l
: if getline('.')[col('.') - 1] ==? c
: break
: endif
: endwhile
:endfunction
这里没有提示,你需要想办法告诉用户,需要输入一个字符。
字符不通过映射。
键码被替换。因而,用户输入 <Del> 键时,你得到 <Del> 的键码,而
不是原始的字符序列。比如: >
getchar() == "\<Del>"
getchar() == "\<S-Left>"
< 下例重新定义 "f",使它忽略大小写: >
:nmap f :call FindChar()<CR>
:function FindChar()
: let c = nr2char(getchar())
: while col('.') < col('$') - 1
: normal l
: if getline('.')[col('.') - 1] ==? c
: break
: endif
: endwhile
:endfunction
getcharmod() *getcharmod()*
返回数值,反映最近用 getchar() 或其它方式输入字符的修饰符状
态。这些值可以相加:
2 Shift
4 Control
8 Alt (Meta)
16 鼠标双击
32 鼠标三击
64 鼠标四击
128 仅限于 Macintosh: command
只有没有包含字符本身的修饰符被返回。因而,Shift-a 产生没有修饰
符的 "A"。
getcmdline() *getcmdline()*
返回当前命令行。只有在编辑命令行时有效,所以必须在
|c_CTRL-\_e| 或 |c_CTRL-R_=| 里使用。
例如: >
:cmap <F7> <C-\>eescape(getcmdline(), ' \')<CR>
< 另见 |getcmdtype()|、|getcmdpos()| 和 |setcmdpos()|。
getcmdpos() *getcmdpos()*
返回命令行的字节计算的光标位置。第一列为 1。
只有在编辑命令行时有效,所以必须在 |c_CTRL-\_e| 或
|c_CTRL-R_=| 里使用。不然,返回 0。
另见 |getcmdtype()|、|setcmdpos()| 和 |getcmdline()|。
getcmdtype() *getcmdtype()*
返回当前命令行类型。可能的返回值是:
: 普通 Ex 命令
> 调试模式命令 |debug-mode|
/ 正向搜索命令
? 反向搜索命令
@ |input()| 命令
- |:insert| 或 |:append| 命令
只能在编辑命令行时调用,因而必须在 |c_CTRL-\_e| 或
|c_CTRL-R_=| 里使用。否则,返回空字符串。
另见 |getcmdpos()|、|setcmdpos()| 和 |getcmdline()|。
*getcwd()*
getcwd() 返回字符串,当前工作目录的名字。
getfsize({fname}) *getfsize()*
返回数值,文件 {fname} 以字节数计算的大小。
如果 {fname} 是目录,返回 0。
如果找不到文件 {fname},返回 -1。
如果 {fname} 文件过大,超出了 Vim 的数值的范围,返回 -2。
getfontname([{name}]) *getfontname()*
如果没有参数,返回使用的正常字体的名字,也就是 Normal 高亮组
|hl-Normal| 使用的。
如果带了参数,检查 {name} 是否合法的字体名。如果不是,返回空字
符串。否则,返回实际的字体名,或者如果 GUI 不支持取得真正的名
字,返回 {name}。
只有在 GUI 运行的时候才能用,所以不能用于你的 vimrc 和 gvimrc
文件。用 |GUIEnter| 自动命令可以在 GUI 刚开始之后使用此函数。
注意 GTK 2 GUI 接受任何字体名,所以不会检查名字是否合法。
getfperm({fname}) *getfperm()*
返回字符串,给定文件 {fname} 的读、写、执行权限。
如果 {fname} 不存在或者它所在的目录无法读取,返回空字符串。
返回值的形式是 "rwxrwxrwx",其中每组 "rwx" 标志位分别代表文件
所有者、文件所属组和其它用户的权限。如果用户没有某权限,相应的
标志位被字符串 "-" 代替。例如: >
:echo getfperm("/etc/passwd")
< 希望它会 (从安全角度而言) 显示字符串 "rw-r--r--" 或者甚至
"rw-------"。
getftime({fname}) *getftime()*
返回数值,给定文件 {fname} 的最新修改时间。该时间为 1970 年 1
月 1 日开始计算的秒数,可以传给 strftime()。
另见 |localtime()| 和 |strftime()|。
如果找不到文件 {fname},返回 -1。
getftype({fname}) *getftype()*
返回字符串,给定文件 {fname} 的文件类型的描述。
如果 {fname} 不存在,返回空字符串。
下表列出各种不同文件类型的返回值:
普通文件 "file"
目录 "dir"
符号链接 "link"
块设备 "bdev"
字符设备 "cdev"
套接字 "socket"
FIFO "fifo"
其它 "other"
例如: >
getftype("/home")
< 注意 只有在能支持的系统上才会返回 "link" 这样的类型。有的系统
只支持 "dir" 和 "file"。
*getline()*
getline({lnum} [, {end}])
如果没有 {end},返回字符串,即当前缓冲区第 {lnum} 行文本。
例如: >
getline(1)
< 如果 {lnum} 是不以数字开始的字符串,调用 line() 来把该字符串转
化成数值。要得到光标所在的行: >
getline(".")
< 如果 {lnum} 小于 1 或者大于缓冲区的总行数,返回空字符串。
如果给出 {end},返回 |List|,其中每个项目是当前缓冲区从 {lnum}
到 {end} (包含) 范围的一行。
{end} 的用法同 {lnum}。
安静地忽略不存在的行。
如果 {end} 在 {lnum} 之前,返回空 |List|。
例如: >
:let start = line('.')
:let end = search("^$") - 1
:let lines = getline(start, end)
< 要获取其它缓冲区的文本行,见 |getbufline()|。
getloclist({nr}) *getloclist()*
返回列表,包含窗口 {nr} 的位置列表的所有项目。如果 {nr} 为 0,
使用当前窗口。
如果是位置列表窗口,返回其显示的位置列表。如果窗口号 {nr} 非
法,返回空列表。其它的情况和 |getqflist()| 相同。
getmatches() *getmatches()*
返回之前 |matchadd()| 和 |:match| 命令定义的所有匹配组成的列表
|List|。 |getmatches()| 常和 |setmatches()| 组合使用,因为
|setmatches()| 可以恢复 |getmatches()| 保存的匹配列表。
示例: >
:echo getmatches()
< [{'group': 'MyGroup1', 'pattern': 'TODO',
'priority': 10, 'id': 1}, {'group': 'MyGroup2',
'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
:let m = getmatches()
:call clearmatches()
:echo getmatches()
< [] >
:call setmatches(m)
:echo getmatches()
< [{'group': 'MyGroup1', 'pattern': 'TODO',
'priority': 10, 'id': 1}, {'group': 'MyGroup2',
'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
:unlet m
<
getqflist() *getqflist()*
返回列表,包含所有当前 quickfix 错误。列表的每个项目是包含以下
项目的字典:
bufnr 有此文件名的缓冲区号,bufname() 得到缓冲区名
lnum 缓冲区里的行号 (第一行是 1)
col 列号 (第一列是 1)
vcol 非零: "col" 是可视列
零: "col" 是字节位置
nr 错误号
pattern 用于定位错误的搜索模式
text 错误描述
type 错误类型,'E'、'1' 等。
valid 非零: 能识别该错误信息
如果没有错误列表或者它为空,返回空列表。quickfix 列表项目如果
包含不存在的缓冲区号,返回的 "bufnr" 置为零。
应用: 在多个文件里寻找模式的匹配,并对之进行处理: >
:vimgrep /theword/jg *.c
:for d in getqflist()
: echo bufname(d.bufnr) ':' d.lnum '=' d.text
:endfor
getreg([{regname} [, 1]]) *getreg()*
返回字符串,寄存器 {regname} 的内容。例如: >
:let cliptext = getreg('*')
< getreg('=') 返回最近一次表达式寄存器计算的返回值 (用于映射)。
getreg('=', 1) 返回表达式自身,以便用 |setreg()| 恢复。对于其
它寄存器,这个额外的参数被忽略,所以给出此参数总是无妨。
如果没有指定 {regname},使用 |v:register|。
getregtype([{regname}]) *getregtype()*
返回字符串,寄存器 {regname} 的类型。
该值会是以下可能之一:
"v" |characterwise| (面向字符) 的文本
"V" |linewise| (面向行) 的文本
"<CTRL-V>{width}" |blockwise-visual| (面向列块) 的文本
0 空或者未知的寄存器
<CTRL-V> 是一个字符,其值为 0x16。
如果没有指定 {regname},使用 |v:register|。
gettabvar({tabnr}, {varname}) *gettabvar()*
得到标签页 {tabnr} 的标签页局部变量 {varname} 的值。|t:var|
标签页的编号从一开始。
注意 必须使用不带 "t:" 的名字。
gettabwinvar({tabnr}, {winnr}, {varname}) *gettabwinvar()*
得到标签页 {tabnr} 的窗口 {winnr} 的窗口局部变量 {varname} 的
值。
如果 {varname} 以 "&" 打头,得到窗口局部选项的值。
标签页的编号从一开始。|getwinvar()| 总是使用当前标签页。
如果 {winnr} 为零,使用当前窗口。
也可用于全局或者局部于缓冲区或局部于窗口的选项,但不能用于全局
或者局部于缓冲区的变量。
如果 {varname} 为空,返回一个包含所有窗口局部变量的字典。
注意 {varname} 必须为不带 "w:" 的名字。
例如: >
:let list_is_on = gettabwinvar(1, 2, '&list')
:echo "myvar = " . gettabwinvar(3, 1, 'myvar')
<
*getwinposx()*
getwinposx() 返回数值,即 GUI Vim 窗口以像素计从左起算的 X 坐标。如果该信息
得不到,返回 -1。
*getwinposy()*
getwinposy() 返回数值,即 GUI Vim 窗口以像素计从顶部起算的 Y 坐标。如果该信
息得不到,返回 -1。
getwinvar({nr}, {varname}) *getwinvar()*
类似于 |gettabwinvar()|,只用当前标签页。
例如: >
:let list_is_on = getwinvar(2, '&list')
:echo "myvar = " . getwinvar(1, 'myvar')
<
glob({expr} [, {flag}]) *glob()*
扩展 {expr} 里的文件通配符。|wildcards| 说明其中特殊字符的使用
方法。
结果是字符串。
如果返回多个匹配,以 <NL> 字符分隔。
除非给出可选的 {flag} 参数且非零,应用 'suffixes' 和
'wildignore' 选项: 跳过匹配任何 'wildignore' 模式的名字,而
'suffixes' 影响匹配结果的排序。
如果扩展失败,返回空字符串。
扩展结果不包含不存在文件的名字。
多数系统上,可以用反引号从外部命令得到文件名。例如: >
:let tagfiles = glob("`find . -name tags -print`")
:let &tags = substitute(tagfiles, "\n", ",", "g")
< 反引号包围的程序的输出结果必须每个项目一行。项目内部可以使用空
格。
特殊 Vim 变量的扩展见 |expand()|。|system()| 说明如何得到外部
命令的原始输出。
globpath({path}, {expr} [, {flag}]) *globpath()*
在 {path} 的所有目录下执行 glob() 并连接所有的返回结果。例
如: >
:echo globpath(&rtp, "syntax/c.vim")
< {path} 是逗号分隔的目录名的列表。每个目录名都附加在 {expr} 之
前,然后如同 |glob()| 那样被扩展。必要的话,插入路径分隔符。
要在目录名字里加上逗号,可以使用反斜杠转义。注意 在 MS-Windows
上目录的最后可能有一个反斜杠。如果你要在后面加上逗号进行分隔,
先把反斜杠去掉。
如果某个目录下的扩展失败,不会有错误信息。
除非给出可选的 {flag} 参数且非零,应用 'suffixes' 和
'wildignore' 选项: 跳过匹配任何 'wildignore' 模式的名字,而
'suffixes' 影响匹配结果的排序。
可以用 "**" 项目来搜索目录树。例如,寻找在 'runtimepath' 和它
之下所有目录里的 "README.txt" 文件: >
:echo globpath(&rtp, "**/README.txt")
< 不支持向上搜索和 "**" 的深度限制,所以 'path' 的使用不一定总能
正确工作。
*has()*
has({feature}) 返回数值,如果支持特性 {feature} 则为 1,不然为零。
{feature} 参数是字符串。见下面的 |feature-list|。
另见 |exists()|。
has_key({dict}, {key}) *has_key()*
返回数值,如果 |Dictionary| {dict} 有键为 {key} 的项目则为 1,
不然为零。
haslocaldir() *haslocaldir()*
返回数值,如果当前窗口用 |:lcd| 设置过本地路径则为 1,不然为
零。
hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()*
返回数值,如果存在某映射,其右边的表达式 (被映射到的部分) 的某
处包含 {what},并且该映射在 {mode} 指定的模式下存在,返回 1。
如果提供 {abbr} 且非零,使用缩写而不是映射。不要忘记指定插入
和/或命令行模式。
同时检查全局映射和局部于当前缓冲区的映射以寻找匹配。
如果没有匹配的映射,返回 0。
{mode} 识别下列字符:
n 普通模式
v 可视模式
o 操作符等待模式
i 插入模式
l Language-Argument ("r"、 "f"、"t" 等等) 模式
c 命令行模式
如果没有提供 {mode},使用 "nvo"。
该函数可用于检查是否存在映射到 Vim 脚本的某个函数的映射。例
如: >
:if !hasmapto('\ABCdoit')
: map <Leader>d \ABCdoit
:endif
< 这样,到 "\ABCdoit" 的映射只有在到 "\ABCdoit" 的映射还不存在的
时候才会进行。
histadd({history}, {item}) *histadd()*
把字符串 {item} 加到历史 {history} 里。后者可以是:
*hist-names*
"cmd" 或 ":" 命令行历史
"search" 或 "/" 搜索模式历史
"expr" 或 "=" 输入表达式历史
"input" 或 "@" 输入行历史
如果 {item} 已经在历史里存在,它会被调整位置,从而成为最新的一
项。
返回结果为数值: 如果操作成功则为 1,不然返回 0。
例如: >
:call histadd("input", strftime("%Y %b %d"))
:let date=input("Enter date: ")
< 该函数在沙盘里不可用 |sandbox|。
histdel({history} [, {item}]) *histdel()*
清除 {history},换而言之,删除它所有的项目。|hist-names| 解释
{history} 的所有可能值。
如果 {item} 计算结果为字符串,它被看作正规表达式。从历史里删除
所有匹配该模式的项目 (如果有的话)。
必须匹配大小写,除非使用 "\c" |/\c|。
如果 {item} 的计算结果为数值,它被解释为索引值,见
|:history-indexing|。如果该索引存在,删除相应的项目。
返回结果为数值: 如果操作成功则为 1,不然返回 0。
例如:
清除表达式寄存器历史: >
:call histdel("expr")
<
删除所有 "*" 开始的搜索历史: >
:call histdel("/", '^\*')
<
下面三者是等价的: >
:call histdel("search", histnr("search"))
:call histdel("search", -1)
:call histdel("search", '^'.histget("search", -1).'$')
<
要删除最后的搜索模式,并在 "n" 命令和 'hlsearch' 里使用倒数第
二个模式: >
:call histdel("search", -1)
:let @/ = histget("search", -1)
histget({history} [, {index}]) *histget()*
返回字符串,即 {history} 历史的第 {index} 项。|hist-names| 解
释 {history} 的所有可能值,而 |:history-indexing| 解释
{index}。如果没有这个项目,返回空字符串。如果忽略 {index},返
回历史里最近使用的项目。
例如:
重做历史里的倒数第二个搜索 >
:execute '/' . histget("search", -2)
< 定义 Ex 命令 ":H {num}",以重新执行 |:history| 输出的第 {num}
项。 >
:command -nargs=1 H execute histget("cmd", 0+<args>)
<
histnr({history}) *histnr()*
返回当前项目在 {history} 里的编号。|hist-names| 解释 {history}
的所有可能值。
如果有错,返回 -1。
例如: >
:let inp_index = histnr("expr")
<
hlexists({name}) *hlexists()*
返回数值。只要名为 {name} 的高亮组用某种方法定义过,返回非零。
不一定要为该组定义过高亮属性。一些语法项目可能已经使用该组。
*highlight_exists()*
已废弃的名字: highlight_exists()。
*hlID()*
hlID({name}) 返回数值,即名为 {name} 的高亮组的 ID。如果该高亮组不存在,返
回零。
可用于提取高亮组的信息。比如,要得到 "Comment" 组的背景颜色: >
:echo synIDattr(synIDtrans(hlID("Comment")), "bg")
< *highlightID()*
已废弃的名字: highlightID()。
hostname() *hostname()*
返回字符串,即 Vim 运行的机器名字。超过 256 字符串长度的机器名
被截短。
iconv({expr}, {from}, {to}) *iconv()*
返回字符串,即文本 {expr} 从 {from} 编码转到 {to} 编码以后的文
本。
如果转换完全失败,返回空字符串。如果部分字符无法转换,以 "?"
代替之。
编码名字可以是任何 iconv() 库函数接受的名字,见
":!man 3 iconv"。
大多数转换需要 Vim 编译时加入 |+iconv| 特性。不然,只支持
UTF-8 和 latin1 的相互转换。
这可以用来显示包含特殊字符的消息。不管 'encoding' 设为何值,总
可以用 UTF-8 书写消息,然后使用: >
echo iconv(utf8_str, "utf-8", &enc)
< 注意 Vim 使用 UTF-8 进行所有的 Unicode 编码,从/到 UCS-2 的转
换都自动转为 UTF-8。你不能在字符串里使用 UCS-2,因为那里有 NUL
字节。
{仅当编译时加入 |+multi_byte| 特性才有效}
*indent()*
indent({lnum}) 返回数值,第 {lnum} 行的缩进距离。缩进的计算以空格计,因而它和
'tabstop' 的值是有关系的。{lnum} 的使用方式和 |getline()| 相
同。
如果 {lnum} 非法,返回 -1。
index({list}, {expr} [, {start} [, {ic}]]) *index()*
返回 |List| {list} 里值等于 {expr} 的最小项目索引。这里不进行
自动转换,字符串 "4" 不同于数值 4,数值 4 也不等同于浮点数
4.0。'ignorecase' 的值此处也不适用,大小写不忽略。
如果给出 {start},从索引为 {start} 的项目开始寻找 (可以为负,
指定相对于尾部的项目)。
如果给出 {ic} 且非零,忽略大小写。否则,必须匹配大小写。
如果在 {list} 里找不到 {expr},返回 -1。
示例: >
:let idx = index(words, "the")
:if index(numbers, 123) >= 0
input({prompt} [, {text} [, {completion}]]) *input()*
返回字符串,即用户在命令行上的输入内容,可以为任何值。参数
{prompt} 或者是一个提示字符串,或者是一个空白字符串 (没有提
示)。'\n' 可以在提示里使用,以开始新行。
该提示使用 |:echohl| 设置的高亮。
输入方法和命令行相似,也使用相同的编辑命令和映射。但 input()
输入的行使用另外的历史。
示例: >
:if input("咖啡还是啤酒?") == "啤酒"
: echo "干杯!"
:endif
<
如果给出可选的 {text} 参数,它被用作缺省的回答,就像是用户输入
的那样。例如: >
:let color = input("Color? ", "white")
< 可选的 {completion} 参数指定输入支持的补全类型。如果不给出,不
使用补全。支持的补全类型和用户定义命令用 "-complete=" 参数能给
出的类型相同。详情见 |:command-completion|。例如: >
let fname = input("File: ", "", "file")
<
注意: 在只能运行于 GUI 模式的版本里 (比如 Win32 GUI),此函数不
能在启动文件里使用。
注意: input() 在映射里调用时,它会消耗该映射余下的字符,因为映
射的处理就像那些字符被键盘输入一样。在 input() 前使用
|inputsave()| 然后在 input() 输入之后 |inputrestore()| 可以避
免这一点。另一个方法是避免在映射的后面提供任何字符,比如,使用
|:execute| 或 |:normal|。
使用映射的例子: >
:nmap \x :call GetFoo()<CR>:exe "/" . Foo<CR>
:function GetFoo()
: call inputsave()
: let g:Foo = input("enter search pattern: ")
: call inputrestore()
:endfunction
inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()*
类似于 |input()|,但如果运行 GUI 且支持文本对话框,弹出一个对
话框窗口来输入文本。
例如: >
:let n = inputdialog("value for shiftwidth", &sw)
:if n != ""
: let &sw = n
:endif
< 如果对话框被取消,返回 {cancelreturn}。如果忽略,返回空字符
串。
输入 <Enter> 和按 OK 按钮相同。按 <Esc> 和按 Cancel 按钮相同。
备注: 不支持命令行补全。
inputlist({textlist}) *inputlist()*
{textlist} 必须是字符串的 |List|。显示此 |List|,每个字符串一
行。用户得到提示要输入一个数值,返回此值。
用户也可以用鼠标点击项目来进行选择。第一个字符串返回 0。在第一
个项目之上点击返回负数。在提示行上点击返回 {textlist} 的长度加
一。
确保 {textlist} 不超过 'lines' 个项目,否则无法使用。建议把项
目编号放在每个字符串的开始处,并在第一项上加上提示。例如: >
let color = inputlist(['Select color:', '1. red',
\ '2. green', '3. blue'])
inputrestore() *inputrestore()*
恢复前一个 |inputsave()| 保存的预输入。应该和 |inputsave()| 调
用的次数相同,不过调用更多次也无妨。
如果没有可以恢复的,返回 1,不然返回 0。
inputsave() *inputsave()*
保存预输入 (也包括映射的) 并清除之,使得下一个提示能从用户得到
输入。在提示之后应该跟上配套的 inputrestore()。可以多次使用,
此时应该有同样多次的 inputrestore() 调用。
如果内存不足,返回 1,不然返回 0。
inputsecret({prompt} [, {text}]) *inputsecret()*
该函数和 |input()| 函数类似,但有两个例外:
a) 用户的应答显示为一串星号 ("*"),从而输入可以保密,还有
b) 用户的应答不会记录在输入 |history| 栈中。
返回字符串,即用户在命令行上根据提示输入的应答。
备注: 不支持命令行补全。
insert({list}, {item} [, {idx}]) *insert()*
在 |List| {list} 的开始处插入 {item}。
如果指定 {idx},{item} 的插入位置在索引 {idx} 之前。如果
{idx} 为零,插入在第一个项目之前,和省略 {idx} 效果相同。也可
用负的 {idx},见 |list-index|。-1 插入在最后一个项目之前。
返回新产生的 |List|。例如: >
:let mylist = insert([2, 3, 5], 1)
:call insert(mylist, 4, -1)
:call insert(mylist, 6, len(mylist))
< 用 |add()| 可以更简单的完成最后一个例子。
注意 如 {item} 是 |List|,它被作为单个项目来插入。 |extend()|
用来连接多个 |List|。
isdirectory({directory}) *isdirectory()*
返回数值,如果名为 {directory} 的目录存在,返回非零。如果
{directory} 不存在或者不是目录,返回假值。{directory} 可以是任
何表达式,最终用作字符串。
islocked({expr}) *islocked()* *E786*
返回数值,如果 {expr} 是某个加锁的变量名,返回非零。
{expr} 必须是变量名、|List| 项目,或 |Dictionary| 项目,不是变
量本身!例如: >
:let alist = [0, ['a', 'b'], 2, 3]
:lockvar 1 alist
:echo islocked('alist') " 1
:echo islocked('alist[1]') " 0
< 如果 {expr} 是不存在的变量,得到错误信息。用 |exists()| 可以检
查它是否存在。
items({dict}) *items()*
返回 |List|,{dict} 的所有键-值组对。每个 |List| 项目是两个项
目的列表: {dict} 项目的键和此项目的值。|List| 项目的顺序不定。
join({list} [, {sep}]) *join()*
连接所有 {list} 项目成为字符串。
如果指定 {sep},该分隔符出现在项目之间。如果省略 {sep},用单个
空格。
注意 尾部不加 {sep}。如果你坚持要加入: >
let lines = join(mylist, "\n") . "\n"
< 字符串项目照原样使用。用类似 |string()| 的方式把 |List| 和
|Dictionary| 转化为字符串。
逆函数是 |split()|。
keys({dict}) *keys()*
返回 |List|,{dict} 的所有键。|List| 项目的顺序不定。
*len()* *E701*
len({expr}) 返回数值,参数的长度。
如果 {expr} 为字符串或数值,返回它使用的字节数,和 |strlen()|
相同。
如果 {expr} 为 |List|,返回 |List| 的项目数量。
如果 {expr} 为 |Dictionary|,返回 |Dictionary| 的项目数量。
否则给出错误。
*libcall()* *E364* *E368*
libcall({libname}, {funcname}, {argument})
在运行库 {libname} 里调用函数 {funcname} 并给出单个参数
{argument}。
这可以用于调用库里的函数,尤其是 Vim 里用到的那些。因为只能使
用单个参数,所以可以调用的标准库函数相当有限。
结果是函数返回的字符串。如果函数返回 NULL,在 Vim 里会以空字符
串 "" 出现。
如果函数返回数值,请使用 |libcallnr()|!
如果 {argument} 是数值,它以 int 类型传给函数;如果 {argument}
是字符串,它以 null 结尾的字符串类型传入。
在 |restricted-mode| 里,该函数不能运行。
libcall() 允许你写自己的 Vim '插件' 扩展,而无须重新编译程序。
它并_不_是用来调用系统函数的一个方法!如果你试图这么做,Vim 很
有可能会崩溃。
Win32 上,你写的函数必须在 DLL 里提供,而且必须使用普通的 C 调
用惯例 (_不是_ Windows 系统 DLL 使用的 Pascal 惯例)。函数必须
只能接受单个参数,或者是字符指针,或者是长整数,而且必须返回字
符指针或者 NULL。返回的字符指针必须指向在函数返回之后仍然指向
合法的内存 (比如 DLL 的静态区域)。如果指向分配的区域,那么内存
会发生泄漏。在函数里使用静态缓冲区应该可以,在 DLL 卸载时会被
释放。
警 告: 如果函数返回不合法的指针,Vim 会崩溃!如果函数返回数值
也会发生同样的问题,因为 Vim 把它当作指针看待。
Win32 系统上,{libname} 必须是不带 ".DLL" 后缀的 DLL 文件名。
只有 DLL 不在常见的位置的时候,才需要指定完整的路径名。
Unix 上: 如果编译你自己的插件,记住目标代码必须生成位置无关代
码 ('PIC')。
{仅当使用 Win32 和一些 Unix 版本且带有 |+libcall| 特性时才有
效}
例如: >
:echo libcall("libc.so", "getenv", "HOME")
<
*libcallnr()*
libcallnr({libname}, {funcname}, {argument})
和 |libcall()| 类似,但函数返回 int,而不是字符串。
{仅当使用 Win32 和一些 Unix 版本且带有 |+libcall| 特性时才有
效}
例如: >
:echo libcallnr("/usr/lib/libc.so", "getpid", "")
:call libcallnr("libc.so", "printf", "Hello World!\n")
:call libcallnr("libc.so", "sleep", 10)
<
*line()*
line({expr}) 返回数值,即 {expr} 给定的文件位置的行号。可接受的位置是:
. 光标位置
$ 缓冲区的最后一行
'x 位置标记 x 的位置 (如果该位置标记没有设置,返回 0)
w0 当前窗口可见部分的首行
w$ 当前窗口可见部分的末行
v 可视模式下: 可视区域的起始行 (光标在尾部)。如果不
在可视模式下,返回光标位置。不同于 |'<|,可以得到
立即的更新。
注意 可以使用其它文件的位置标记。此时行号应用于那个缓冲区。
要得到列号用 |col()|。两者都要可用 |getpos()|。
例如: >
line(".") 光标所在的行号
line("'t") 位置标记 t 的行号
line("'" . marker) 名为 marker 的位置标记的行号
< *last-position-jump*
如果设置了 '" 位置标记的话,下面的自动命令在打开文件后跳转到最
后已知的文件位置: >
:au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
<
line2byte({lnum}) *line2byte()*
返回当前缓冲区第 {lnum} 行从缓冲区开始计算的字节数。这里包括换
行符,但它具体的值取决于当前缓冲区的 'fileformat' 选项,第一行
返回 1。
这也可以用来得到最后一行之后的 "那行" 的字节计数: >
line2byte(line("$") + 1)
< 这就等于文件大小加 1。
如果 {lnum} 非法或者编译时关闭了 |+byte_offset| 特性,返回
-1。另见 |byte2line()|、|go| 和 |:goto|。
lispindent({lnum}) *lispindent()*
得到第 {lnum} 行根据 lisp 缩进规则应有的缩进距离,见 'lisp'。
缩进的计算以空格计,因而和 'tabstop' 的值是有关系的。
{lnum} 的使用方式和 |getline()| 相同。
如果 {lnum} 非法或者 Vim 编译时不带 |+lispindent| 特性,返回
-1。
localtime() *localtime()*
返回当前时间,以 1970 年 1 月 1 日开始的秒数计算。另见
|strftime()| 和 |getftime()|。
log({expr}) *log()*
返回浮点数,即浮点数 {expr} 的自然对数 (即以 e 为底)。
{expr} 计算结果必须为 (0, inf] 区间内的浮点数或数值。
示例: >
:echo log(10)
< 2.302585 >
:echo log(exp(5))
< 5.0
{仅当编译时加入 |+float| 特性才有效}
log10({expr}) *log10()*
返回浮点数,即浮点数 {expr} 以 10 为底的对数。
{expr} 计算结果必须为浮点数或数值。
示例: >
:echo log10(1000)
< 3.0 >
:echo log10(0.01)
< -2.0
{仅当编译时加入 |+float| 特性才有效}
map({expr}, {string}) *map()*
{expr} 必须是 |List| 或 |Dictionary|。
{expr} 里的每个项目被 {string} 的计算结果替代。
在 {string} 里,|v:val| 包含当前项目的值。
对 |Dictionary| 而言,|v:key| 也包含当前项目的键。
对 |List| 而言,|v:key| 包含当前项目的索引。
例如: >
:call map(mylist, '"> " . v:val . " <"')
< "mylist" 里的每个项目之前放上 "> ",而之后放上 " <"。
注意 {string} 是表达式的计算结果,而它本身又用作表达式。通常,
最好用 |literal-string| 来避免反斜杠加倍。当然,你仍然需要加倍
' 引号。
本操作直接修改输入。如果你不希望修改 |List| 或 |Dictionary|,
先构建一个备份: >
:let tlist = map(copy(mylist), ' & . "\t"')
< 返回 {expr},过滤过的 |List| 或 |Dictionary|。
如果 {string} 计算时有错误,{expr} 的其余项目不再处理。
maparg({name}[, {mode} [, {abbr}]]) *maparg()*
返回模式 {mode} 名为 {name} 的映射的右边。如果没有名为 {name}
的映射,返回空字符串。
{mode} 可以使用下列字符串之一:
n 普通模式
v 可视模式
o 操作符等待模式
i 插入模式
c 命令行模式
l Language-Argument ("r"、 "f"、"t" 等等) 模式
"" 普通、可视和操作符等待模式。
如果没有提供 {mode},使用 "" 指定的模式。
如果提供 {abbr} 且非零,使用缩写而不是映射。
{name} 可以使用特殊键名,如同 ":map" 命令那样。返回的字符串会
把特殊的字符翻译成和 ":map" 命令所列出输出结果一样的格式。
先检查局部于当前缓冲区的映射,然后再检查全局映射。
此函数可以用来给键映射。如果已经映射过,还可以使用原来映射的内
容。大意: >
exe 'nnoremap <Tab> ==' . maparg('<Tab>', 'n')
mapcheck({name}[, {mode} [, {abbr}]]) *mapcheck()*
检查是否有模式 {mode} 下匹配 {name} 的映射。|maparg()| 说明
{mode} 和 {name} 里的特殊键名。
如果提供 {abbr} 且非零,使用缩写而不是映射。
匹配在映射名以 {name} 开始或者映射名等于 {name} 的开始部分时候
发生。
匹配映射 "a" "ab" "abc" ~
mapcheck("a") 是 是 是
mapcheck("abc") 是 是 是
mapcheck("ax") 是 否 否
mapcheck("b") 否 否 否
和 maparg() 的差别是,mapcheck() 查找匹配 {name} 的映射,而
maparg() 只查找名字完全符合 {name} 的映射。
如果没有 {name} 开始的映射,返回空字符串。如果有一个,返回该映
射的右边。如果有多个,返回其中某一个的右边。
先检查局部于当前缓冲区的映射,然后再检查全局映射。
该函数用于检查是否可以无二义性地添加映射。例如: >
:if mapcheck("_vv") == ""
: map _vv :set guifont=7x13<CR>
:endif
< 就避免了在已有 "_v" 或者 "_vvv" 映射的时候添加 "_vv" 映射。
match({expr}, {pat}[, {start}[, {count}]]) *match()*
如果 {expr} 是 |List|,返回匹配 {pat} 的第一个项目的索引。每个
项目用作字符串,|List| 和 |Dictionary| 使用回显的形式。
否则,{expr} 用作字符串。返回数值,给出 {expr} 里 {pat} 匹配的
(字节计算的偏移量) 位置。
在第一个字符或 |List| 项目上的匹配返回零。若无匹配,返回 -1。
例如: >
:echo match("testing", "ing") " 返回 4
:echo match([1, 'x'], '\a') " 返回 1
< |string-match| 说明如何使用 {pat}。
*strpbrk()*
Vim 没有 strpbrk() 函数。但你可以这么做: >
:let sepidx = match(line, '[.,;: \t]')
< *strcasestr()*
Vim 没有 strcasestr() 函数。但你可以在模式里加入 "\c" 以忽略大
小写: >
:let idx = match(haystack, '\cneedle')
<
如果给出 {start},搜索从字符串的字节位置 {start} 或 |List| 索
引为 {start} 的项目开始。
不过,结果仍然从第一个字符/项目开始算起。比如: >
:echo match("testing", "ing", 2)
< 返回结果是 "4"。 >
:echo match("testing", "ing", 4)
< 返回结果还是 "4"。 >
:echo match("testing", "t", 2)
< 返回 "3"。
对字符串而言,如果 {start} > 0,其行为就像该字符串在 {start}
个字节后开始,因而 "^" 会从 {start} 开始匹配。如果给出 {count}
时则不是如此,此时忽略 {start} 字节前的匹配 (有一点复杂,这是
为了后向兼容)。
对字符串而言,如果 {start} < 0,它被置为 0。对列表而言,此索引
从尾部起算。
如果 {start} 越界 (字符串 {start} > strlen({expr}),而 |List|
{start} > len({expr})),返回 -1。
如果给出 {count},使用第 {count} 个匹配。如果字符串里找到一个
匹配,下一匹配从此匹配之后一个字符开始寻找。所以下例返回 1: >
echo match("testing", "..", 0, 2)
< |List| 里,搜索从下一个项目开始。
注意 如果加入 {count},{start} 使用的方式有所改变。见上。
|pattern| 说明可以接受的模式。
'ignorecase' 选项用来设定模式是否忽略大小写。_不_使用
'smartcase'。匹配总是假定置位了 'magic' 而 'cpoptions' 为空。
*matchadd()* *E798* *E799* *E801*
matchadd({group}, {pattern}[, {priority}[, {id}]])
定义模式 (一个 "匹配"), 在当前窗口用高亮组 {group} 高亮。返回
标识号 (ID),|matchdelete()| 可用该 ID 来删除匹配。
可选的 {priority} 参数指定匹配的优先级。高优先级的匹配的高亮会
否决低优先级匹配的高亮。优先级用整数指定 (负整数也无不可)。如
果未指定 {priority} 参数,缺省优先级为 10。'hlsearch' 的优先级
为零,这样所有正优先级的匹配都可以否决它。语法高亮 (见
'syntax') 采用不同的机制,无论选择的优先级如何,匹配总会否决语
法的高亮。
可选的 {id} 参数请求特定的匹配 ID。如果指定的 ID 已用,报错,
并不加入该匹配。ID 用正整数指定 (不含零)。ID 1、2 和 3 分别为
|:match|、|:2match| 和 |:3match| 命令保留。如果 {id} 未指定,
|matchadd()| 自动选择一个可用的 ID。
匹配的数目不限,|:match| 诸命令则有此局限。
示例: >
:highlight MyGroup ctermbg=green guibg=green
:let m = matchadd("MyGroup", "TODO")
< 要删除该模式: >
:call matchdelete(m)
< 用 |getmatches()| 可以得到 |matchadd()| 和 |:match| 定义的匹配
列表。|clearmatches()| 可一次删除所有的匹配。
matcharg({nr}) *matcharg()*
选择 {nr} 号匹配的项目,它们分别用 |:match|、|:2match| 或
|:3match| 命令设置。
返回两个项目的 |List|:
使用的高亮组名
使用的模式。
如果 {nr} 不是 1、2 或 3,返回空 |List|。
如果没有匹配的项目,返回 ['', '']。
这用来保存和恢复 |:match|。
用 |:match| 命令高亮的匹配限于三个。|matchadd()| 无此限制。
matchdelete({id}) *matchdelete()* *E802* *E803*
删除之前用 |matchadd()| 或 |:match| 诸命令定义的 ID 为 {id} 的
匹配。如果成功,返回 0,不然返回 -1。示例见 |matchadd()|。
|clearmatches()| 可一次删除所有的匹配。
matchend({expr}, {pat}[, {start}[, {count}]]) *matchend()*
和 |match()| 相同,但返回匹配之后的第一个字符的位置。比如: >
:echo matchend("testing", "ing")
< 返回 "7"。
*strspn()* *strcspn()*
Vim 没有 strspn() 或 strcspn() 函数,但可用 matchend() 实现: >
:let span = matchend(line, '[a-zA-Z]')
:let span = matchend(line, '[^a-zA-Z]')
< 不过没有匹配时,它返回 -1。
如果给出 {start},和 |match()| 里的用法相同。 >
:echo matchend("testing", "ing", 2)
< 返回 "7"。 >
:echo matchend("testing", "ing", 5)
< 返回 "-1"。
如果 {expr} 是 |List|,结果和 |match()| 相同。
matchlist({expr}, {pat}[, {start}[, {count}]]) *matchlist()*
和 |match()| 相同,但返回 |List|。列表第一项是匹配的字符串,和
|matchstr()| 返回值相同。其后的项目是子匹配,类似
|:substitute| 的 "\1"、"\2" 等。如果某个可选的子匹配不匹配,用
空字符串代替。例如: >
echo matchlist('acd', '\(a\)\?\(b\)\?\(c\)\?\(.*\)')
< 返回: ['acd', 'a', '', 'c', 'd', '', '', '', '', '']
如果没有匹配,返回空列表。
matchstr({expr}, {pat}[, {start}[, {count}]]) *matchstr()*
和 |match()| 相同,但返回匹配的字符串。例如: >
:echo matchstr("testing", "ing")
< 返回 "ing"。
如果没有匹配,返回 ""。
如果给出 {start},它和 |match()| 里的用法相同。 >
:echo matchstr("testing", "ing", 2)
< 返回 "ing"。 >
:echo matchstr("testing", "ing", 5)
< 返回 ""。
如果 {expr} 是 |List|,返回匹配的项目。其类型不改变,因而不一
定是字符串。
*max()*
max({list}) 返回 {list} 所有项目的最大值。
如果 {list} 不是列表,或者其中某个项目不能用作数值,出错。
空 |List| 返回零。
*min()*
min({list}) 返回 {list} 所有项目的最小值。
如果 {list} 不是列表,或者其中某个项目不能用作数值,出错。
空 |List| 返回零。
*mkdir()* *E739*
mkdir({name} [, {path} [, {prot}]])
建立目录 {name}。
如果 {path} 为 "p",必要时建立中间的目录。否则它必须是 ""。
如果给出 {prot},它用于设置新目录的权限。缺省为 0755
(rwxr-xr-x: 用户自己可读写,其它人可读)。用 0700 使其它人不可
读。这只用于 {name} 的最后部分。所以,如果建立 /tmp/foo/bar,
/tmp/foo 创建时的权限是 0755。
示例: >
:call mkdir($HOME . "/tmp/foo/bar", "p", 0700)
< 该函数在沙盘里不可用 |sandbox|。
不一定在所有系统上都可用。要检查这一点,使用: >
:if exists("*mkdir")
<
*mode()*
mode([expr]) 返回指示当前模式的字符串。
如果指定 [expr] 并且其值为非零的数值或非空的字符串
(|non-zero-arg|),返回完整模式,不然,返回第一个字母。注意 " "
和 "0" 都是非空字符串。
n 普通模式
no 操作符等待模式
v 面向字符的可视模式
V 面向行的可视模式
CTRL-V 面向列块的可视模式
s 面向字符的选择模式
S 面向行的选择模式
CTRL-S 面向列块的选择模式
i 插入模式
R 替换模式 |R|
Rv 虚拟替换模式 |gR|
c 命令行模式
cv Vim Ex 模式 |gQ|
ce 普通 Ex 模式 |Q|
r 输入回车的提示
rm -- more -- 提示
r? |:confirm| 等等的询问
! 执行外壳或外部命令时
可用于 'statusline' 选项或 |remote_expr()|。在其它的多数地方,
它总是返回 "c" 或 "n"。
另见 |visualmode()|。
mzeval({expr}) *mzeval()*
计算 MzScheme 表达式 {expr} 并返回计算结果,转换为 Vim 本身的
数据结构。
数值和字符串返回本身。
组对 (pair) (包含列表 (list) 和非常规列表 (improper list)) 和
向量 (vector) 以 Vim |List| 形式返回。
哈希表 (hash table) 以 Vim |Dictionary| 形式返回,其键转换成字
符串。
所有其它类型依 display 函数调用的结果转换为字符串。
示例: >
:mz (define l (list 1 2 3))
:mz (define h (make-hash)) (hash-set! h "list" l)
:echo mzeval("l")
:echo mzeval("h")
<
{仅当编译时带 |+mzscheme| 特性才有效}
nextnonblank({lnum}) *nextnonblank()*
返回第一个从 {lnum} 开始的非空白行的行号。例如: >
if getline(nextnonblank(1)) =~ "Java"
< 如果 {lnum} 非法或者在从该行开始都没有非空白行,返回零。
另见 |prevnonblank()|。
nr2char({expr}) *nr2char()*
返回单个字符组成的字符串,该字符的数值为 {expr}。例如: >
nr2char(64) 返回 "@"
nr2char(32) 返回 " "
< 使用当前的 'encoding'。比如对 "utf-8" 来说: >
nr2char(300) 返回带有弓形的 I
< 注意 文件里的 NUL 字符须用 nr2char(10) 指定。因为 Vim 用换行符
来表示 NUL。真正的 NUL 是 nr2char(0),而它会终结字符串,因而返
回空串。
*getpid()*
getpid() 返回数值,即 Vim 进程的进程号。Unix 和 MS-Windows 上这是个唯一
的数值,直到 Vim 退出为止。MS-DOS 上该值总为零。
*getpos()*
getpos({expr}) 得到 {expr} 的位置。可用的 {expr} 的值见 |line()|。
返回 |List|,包含四个数值:
[bufnum, lnum, col, off]
"bufnum" 为零,除非使用了 '0 或 'A 这样的位置标记,这时它是此
位置标记所在的缓冲区号。
"lnum" 和 "col" 是缓冲区里的位置。第一列为 1。
除非使用了 'virtualedit'。"off" 值为零,这是从对应字符开始位置
计算的屏幕列。例如,在制表之中或最后一个字符之后的某个位置。可
以用来保存和恢复光标位置: >
let save_cursor = getpos(".")
移动光标
call setpos('.', save_cursor)
< 另见 |setpos()|。
pathshorten({expr}) *pathshorten()*
缩短路径 {expr} 里的目录名,返回其结果。路径的尾部,即文件名,
保持不变。路径的其余部分被缩短为单个字符。保持每个部分引导的
'~' 和 '.' 字符不变。例如: >
:echo pathshorten('~/.vim/autoload/myfile.vim')
< ~/.v/a/myfile.vim ~
该路径实际存在与否并不相干。
pow({x}, {y}) *pow()*
返回浮点数,即 {x} 的 {y} 次方。
{x} 和 {y} 的计算结果必须是浮点数或数值。
示例: >
:echo pow(3, 3)
< 27.0 >
:echo pow(2, 16)
< 65536.0 >
:echo pow(32, 0.20)
< 2.0
{仅当编译时加入 |+float| 特性才有效}
prevnonblank({lnum}) *prevnonblank()*
返回第一个 {lnum} 所在或之上的非空白行的行号。例如: >
let ind = indent(prevnonblank(v:lnum - 1))
< 如果 {lnum} 非法或者在该行和它之前都没有非空白行,返回零。
另见 |nextnonblank()|。
printf({fmt}, {expr1} ...) *printf()*
返回 {fmt} 指定的字符串,其中每个 "%" 项目被它们对应的参数排版
后的形式取代。例如: >
printf("%4d: E%d %.30s", lnum, errno, msg)
< 可能的返回结果:
" 99: E42 asdfasdfasdfasdfasdfasdfasdfas" ~
常用的项目有:
%s 字符串
%6s 右对齐到 6 个字节的字符串
%.9s 截短到 9 个字节的字符串
%c 单个字节
%d 十进制数
%5d 十进制数,用空格补足到 5 个字符
%x 十六进制数
%04x 十六进制数,用 0 补足到 4 个字符
%X 十六进制数,用大写字母的十六进制字母
%o 八进制数
%f 浮点数,形如 123.456
%e 浮点数,形如 1.234e3
%E 浮点数,形如 1.234E3
%g 浮点数,根据不同的值,使用合适的 %f 或 %e
%G 浮点数,根据不同的值,使用合适的 %f 或 %E
%% % 字符本身
转换规格说明以 '%' 开始,以转换类型结束。所有其它的字符按原样
复制到结果中。
"%" 开始转换规格说明。其后的参数依序如下:
% [flags] [field-width] [.precision] type
flags
零或多个下面的标志位:
# 转换值为 "替换形式"。对 c、d 和 s 转换,此选项无
效。对 o 转换,增加数值的精度,使得输出字符串的
第一个字符总是 0 (除非打印零值,且显式地使用精度
0)。
对 x 和 X 转换,非零值在前面加上字符串 "0x" (X
转换用 "0X")。
0 (零) 以 0 填充。对所有的转换,左侧用 0 而非空格填充。
如果对数值的转换给出精度 (d、o、x 和 X),忽略 0
标志位。
- 负域宽度标志位;转换后的值被左对齐到域边界上。该
值右侧用空格填充,而不是在左侧用空格或 0 填充。
如果两个标志位同时给出,- 否决 0。
' ' (空格) 带符号转换 (d) 产生的正数左侧加上空格。
+ 带符号转换产生的数值之前总加上符号。如果两个标志
位同时给出,+ 否决空格。
field-width
可选的十进制数位字符串,指定最小的字段宽度。如果转换后
的值的字节数小于字段宽度,在左侧 (或右侧,如果给定左对
齐标志位的话) 用空格填充到字段宽度。
.precision
可选的精度,形式为句号 '.' 后跟一个可选的数位字符串。
如果省略了数位字符串,假设精度为零。
它给出 d、o、x 和 X 转换显示的最小数位数量,或 s 转换
显示的字符串的字节的最大数量。
对浮点数而言,指定小数点后的数位个数。
type
指定要进行的转换类型的单个字符,见下。
字段宽度、精度 (两者都有亦可) 可以用星号 '*' 代替数位字符串。
此情形下,一个数值参数指定字段宽度或精度。负的字段宽度被理解为
带左对齐的标志位后跟一个正数字段宽度;负的精度被理解为就像不存
在一样。例如: >
:echo printf("%d: %.*s", nr, width, line)
< 限制 "line" 文本的长度为 "width" 个字节。
转换标识符和它们的含义如下:
*printf-d* *printf-o* *printf-x* *printf-X*
doxX 数值参数被转换为带符号十进制 (d),无符号八进制 (o) 或
无符号十六进制 (x 和 X) 记法。x 转换用字母 "abcdef";X
转换用 "ABCDEF" 字母。
如果提供了精度,它给出必须出现的数位的最少数目;如果转
换后的值需要更少的数位,左侧用 0 填充。
任何情况下数值字段都不会被不存在或者更小的字段宽度所截
短;如果转换的结果宽于字段宽度,字段被扩展,以包含转换
后的结果。
*printf-c*
c 数值参数被转换为字节,写入产生的字符。
*printf-s*
s 使用字符串参数的文本。如果指定精度,使用不多于给定数目
的字节数。
*printf-f* *E807*
f 浮点数参数被转换为形如 123.456 的字符串。精度指定小数
点后面的位数。如果精度为零,则省略小数点本身。如果未指
定精度,缺省为 6。那个很大很大的数 (超出返回或除以零的
结果) 显示 "inf"。
"0.0 / 0.0" 显示 "nan"。
示例: >
echo printf("%.2f", 12.115)
< 12.12
注意 截断方式取决于系统库。如不确定,使用 |round()|。
*printf-e* *printf-E*
e E 浮点数参数被转换为形如 1.234e+03 或用 'E' 的话
1.234E+03 的字符串。精度指定小数点后面的位数,和 'f'
一样。
*printf-g* *printf-G*
g G 如果浮点数参数在 0.001 (含) 和 10000000.0 (不含) 之
间,则其转换同 'f',不然,'g' 同 'e' 而 'G' 同 'E'。如
果未指定精度,除了小数点之后的那个零以外,不显示多余的
零和 '+' 负号。因而,10000000.0 显示为 1.0e7。
*printf-%*
% 写入 '%'。不转换参数。这里完整的转换规格说明是 "%%"。
如果期待数值参数,字符串参数也被接受并自动转换。
如果期待浮点数或字符串参数,数值参数也被接受并自动转换。
其它参数类型产生错误信息。
*E766* *E767*
{exprN} 参数的数量必须和 "%" 项目的数量完全匹配。不论参数不足
还是过多,都会给出错误。至多可用 18 个参数。
pumvisible() *pumvisible()*
如果弹出菜单可见,返回非零,不然返回零。见
|ins-completion-menu|。
可以用来避免一些会删除弹出菜单的动作。
*E726* *E727*
range({expr} [, {max} [, {stride}]]) *range()*
返回数值的 |List|:
- 如果只有指定 {expr}: [0, 1, ..., {expr} - 1]
- 如果指定了 {max}: [{expr}, {expr} + 1, ..., {max}]
- 如果指定了 {stride}: [{expr}, {expr} + {stride}, ...,
{max}] (每次给 {expr} 递增 {stride},但不会产生超过 {max} 的
值)。
如果最大值比开始值小一,返回空列表。如果更小,报错。
例如: >
range(4) " [0, 1, 2, 3]
range(2, 4) " [2, 3, 4]
range(2, 9, 3) " [2, 5, 8]
range(2, -2, -1) " [2, 1, 0, -1, -2]
range(0) " []
range(2, 0) " 出错!
<
*readfile()*
readfile({fname} [, {binary} [, {max}]])
读入文件 {fname} 并返回 |List|。,文件每行一项。在 NL 字符处断
开行。以 CR 分隔的 Macintosh 文件会返回单个长行 (除非某处出现
了 NL)。
所有的 NUL 字符被 NL 字符替代。
如果 {binary} 等于 "b",使用二进制模式:
- 如果末行以 NL 结尾,附加额外的一个空列表项。
- 不删除 CR 字符。
否则:
- NL 之前的 CR 字符被删除。
- 末行是否以 NL 结尾没有影响。
- 'encoding' 如是 Unicode 编码,删除文本可能有的 UTF-8 字节顺
序标识。
如果给出 {max},指定读入的最大行数。可用于只想检查文件开始十行
这样的场合: >
:for line in readfile(fname, '', 10)
: if line =~ 'Date' | echo line | endif
:endfor
< 如果 {max} 为负,返回从文件尾部起算 -{max} 行,有多少算多少。
如果 {max} 为零,返回空列表。
注意 如果没有 {max},把整个文件读到内存。
也要 注意 这里不识别编码。如果需要,把文件读到缓冲区里。
如果文件不能打开,给出错误信息,并返回空列表。
另见 |writefile()|。
reltime([{start} [, {end}]]) *reltime()*
返回代表时间值的项目。项目的格式取决于不同的系统。可以把它传递
给 |reltimestr()| 来转换为字符串。
没有参数,返回当前时间。
带一个参数,返回参数指定的时间以来的时间。
带两个参数,返回 {start} 和 {end} 之间跨越的时间。
{start} 和 {end} 参数必须是 reltime() 返回的值。
{仅当编译时加入 |+reltime| 特性才有效}
reltimestr({time}) *reltimestr()*
返回字符串,代表 {time} 的时间值。
形式是秒数、句号和毫秒数。例如: >
let start = reltime()
call MyFunction()
echo reltimestr(reltime(start))
< 注意 命令本身额外的开销也计算在时间里。时间的准确度取决于系
统。
返回结果包含引导的空格,使字符串能很好地对齐。如果你不需要,用
split() 可以删掉。 >
echo split(reltimestr(reltime(start)))[0]
< 另见 |profiling|。
{仅当编译时加入 |+reltime| 特性才有效}
*remote_expr()* *E449*
remote_expr({server}, {string} [, {idvar}])
发送 {string} 到 {server}。该发送的字符串是一个表达式,而返回
的是远端执行的结果。这个结果必然是字符串或 |List|。|List| 被转
换成字符串,转换方法是把项目用换行符连接起来 (末项之后没有),
就像用 join(expr, "\n") 那样。
如果给出 {idvar},将 {serverid} 保存在以它命令的变量里,此后的
remote_read() 需要使用此值。
另见 |clientserver| |RemoteReply|。
该函数在沙盘里不可用 |sandbox|。
{仅当编译时加入 |+clientserver| 特性才有效}
注意: 任何错误会在本地产生错误信息,但返回的结果只是一个空字符
串。
例如: >
:echo remote_expr("gvim", "2+2")
:echo remote_expr("gvim1", "b:current_syntax")
<
remote_foreground({server}) *remote_foreground()*
把名为 {server} 的 Vim 服务器带到前台。
这类似于: >
remote_expr({server}, "foreground()")
< Win32 系统除外。那里,客户端完成实际的工作。因为操作系统不
总能允许服务器把自己带到前台。
注意: 如果窗口最小化,并不恢复之,foreground() 会这么做。
该函数在沙盘里不可用 |sandbox|。
{仅可用在 Win32、Athena、Motif 和 GTK 的 GUI 版本和 Win32 的控
制台版本}
remote_peek({serverid} [, {retvar}]) *remote_peek()*
如果 {serverid} 有可用的字符串,返回正数。如果指定了
{retvar},复制任何应答字符串到 {retvar} 指定的变量。{retvar}
必须是一个用来指定变量名的字符串。
如果没有可用的应答,返回 0。
如果出错,返回 -1。
另见 |clientserver|。
该函数在沙盘里不可用 |sandbox|。
{仅当编译时加入 |+clientserver| 特性才有效}
示例: >
:let repl = ""
:echo "PEEK: ".remote_peek(id, "repl").": ".repl
remote_read({serverid}) *remote_read()*
返回从 {serverid} 发送的存在时间最长的应答,并删除之。该调用会
等待直到有应答为止。
另见 |clientserver|。
该函数在沙盘里不可用 |sandbox|。
{仅当编译时加入 |+clientserver| 特性才有效}
例如: >
:echo remote_read(id)
<
*remote_send()* *E241*
remote_send({server}, {string} [, {idvar}])
发送 {string} 到 {server}。发送的字符串是输入键的序列。函数立
即返回。Vim 的服务器端不对键进行映射 |:map|。
如果给出 {idvar},将 {serverid} 保存在以它命令的变量里,此后的
remote_read() 需要使用此值。
另见 |clientserver| |RemoteReply|。
该函数在沙盘里不可用 |sandbox|。
{仅当编译时加入 |+clientserver| 特性才有效}
注意: 任何错误会在服务器端报告,从而影响那里的显示。
例如: >
:echo remote_send("gvim", ":DropAndReply ".file, "serverid").
\ remote_read(serverid)
:autocmd NONE RemoteReply *
\ echo remote_read(expand("<amatch>"))
:echo remote_send("gvim", ":sleep 10 | echo ".
\ 'server2client(expand("<client>"), "HELLO")<CR>')
<
remove({list}, {idx} [, {end}]) *remove()*
没有 {end}: 删除 |List| {list} 里索引为 {idx} 的项目并返回之。
有 {end}: 删除从 {idx} 到 {end} (包含) 的项目,并返回这些项目
的列表。如果 {idx} 指向和 {end} 相同的项目,返回单个项目的列
表。如果 {end} 指向 {idx} 之前的项目,报错。
|list-index| 说明 {idx} 和 {end} 可能的取值。
例如: >
:echo "last item: " . remove(mylist, -1)
:call remove(mylist, 0, 9)
remove({dict}, {key})
删除 {dict} 里键为 {key} 的项目。例如: >
:echo "removed " . remove(dict, "one")
< 如果 {dict} 里没有键 {key},报错。
|delete()| 用来删除文件。
rename({from}, {to}) *rename()*
把文件名 {from} 换成 {to}。这也可用来在文件系统间移动文件。返
回数值,如果文件成功换名,返回零,如果换名失败,返回非零。
注意 如果 {to} 已存在,它被覆盖且没有提示。
该函数在沙盘里不可用 |sandbox|。
repeat({expr}, {count}) *repeat()*
重复 {expr} {count} 次,并返回连接后的结果。例如: >
:let separator = repeat('-', 80)
< 如果 {count} 为零或负,返回空。
如果 {expr} 是 |List| 类型,返回连接 {expr} {count} 次的结果。
例如: >
:let longlist = repeat(['a', 'b'], 3)
< 返回 ['a', 'b', 'a', 'b', 'a', 'b']。
resolve({filename}) *resolve()* *E655*
在 MS-Windows 上,如果 {filename} 是一个快捷方式 (.lnk 文件),
返回简化的快捷方式指向的路径。
在 Unix 上,反复分析 {filename} 的所有路径部分的符号链接的真正
路径,直到返回最简化的结果为止。为了处理循环链接的问题,符号链
接的分析在 100 次叠代之后停止。
在其它系统上,返回简化了的 {filename}。
简化的工作通过 |simplify()| 完成。
resolve() 保留指向当前目录的首个路径部分 (保证结果仍然是相对路
径名),也保留出现在尾部的路径分隔符。
*reverse()*
reverse({list}) 反转 {list} 项目的顺序,直接对 {list} 进行修改。返回 {list}。
如果你不想修改列表,先构建一个备份: >
:let revlist = reverse(copy(mylist))
round({expr}) *round()*
返回浮点数,即最接近于 {expr} 的整数。如果 {expr} 在两个整数的
正中间,使用 (译者注: 绝对值) 较大 (远离零的) 那个。
{expr} 的计算结果必须是浮点数或数值。
示例: >
echo round(0.456)
< 0.0 >
echo round(4.5)
< 5.0 >
echo round(-4.5)
< -5.0
{仅当编译时加入 |+float| 特性才有效}
search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()*
搜索正规表达式模式 {pattern}。搜索从光标位置 (用 |cursor()| 可
以得到) 开始。
{flags} 是字符串,可以包含以下字符标志位:
'b' 反向搜索,而不是正向搜索
'c' 接受光标位置上的匹配
'e' 移到匹配的尾部
'n' 不 (Not) 移动光标
'p' 返回匹配的子模式号 (见下)
's' 在光标上次的位置上设置 ' 位置标记
'w' 在文件尾部处回绕到文件开始处
'W' 不在文件尾部处回绕
如果 'w' 和 'W' 都没有给出,根据 'wrapscan' 选项决定。
如果提供 's' 标志位,只有在光标移动的时候才设置 ' 位置标记。
's' 标志位不能和 'n' 标志位一起使用。
适用 'ignorecase'、'smartcase' 和 'magic' 标志位。
如果给出 {stopline} 参数,搜索在搜索完该行后结束。可用于限制搜
索在给出的行范围内。例如: >
let match = search('(', 'b', line("w0"))
let end = search('END', '', line("w$"))
< 如果使用了 {stopline} 且非零,隐含意味着搜索不会在文件尾回绕。
零就相当于没给出该参数。
如果给出 {timeout} 参数,搜索在超过给出的毫秒数后中止。这样,
如果 {timeout} 为 500,搜索在半秒钟后中止。该值不能为负。
零就相当于没给出该参数。
{仅当在编译时加入 |+reltime| 特性才有效}
如果找不到匹配,返回 0 并且光标位置不改变。不会给出错误信息。
如果找到了匹配,返回其所在的行号。
*search()-sub-match*
如果有 'p' 标志位,返回值比第一个匹配的 \(\) 里的子模式的编号
多一。如果所有子模式都不匹配但整个模式匹配,返回一。
要得到列号,使用 |searchpos()|。
光标定位在匹配的文本上,除非使用了 'n' 标志位。
示例 (遍历参数列表里的所有文件): >
:let n = 1
:while n <= argc() " 循环遍历参数列表的每个文件
: exe "argument " . n
: " 从文件最后一个字符开始并回绕,这样第一个搜索可以找到
: " 文件开始的匹配
: normal G$
: let flags = "w"
: while search("foo", flags) > 0
: s/foo/bar/g
: let flags = "W"
: endwhile
: update " 如果修改过,写入文件
: let n = n + 1
:endwhile
<
searchdecl({name} [, {global} [, {thisblock}]]) *searchdecl()*
搜索 {name} 的声明。
如果 {global} 参数非零,使用 |gD| 的工作方式,寻找文件的第一个
匹配。否则使用 |gd| 的工作方式,寻找函数里的第一个匹配。
如果 {thisblock} 参数非零,忽略光标位置前结束的 {} 块里的匹
配。可以避免只有在别的作用域里才有效的变量声明。
移动光标到找到的匹配上。
返回零代表成功,非零代表失败。
例如: >
if searchdecl('myvar') == 0
echo getline('.')
endif
<
*searchpair()*
searchpair({start}, {middle}, {end} [, {flags} [, {skip}
[, {stopline} [, {timeout}]]]])
搜索嵌套的 start-end 组对的匹配。这可以用来查找匹配 "if" 的
"endif"。在这里面的其它的 if/endif 组对被忽略。搜索从光标开
始。缺省正向搜索,在 {flags} 里包含 'b' 的时候反向搜索。
如果找到一个匹配,光标移动到那里并返回行号。如果没有匹配,
返回 0 或者 -1,光标不移动。不会给出错误信息。
{start}、{middle} 和 {end} 都是模式,见 |pattern|。它们不能包
含 \( \) 对,但可以使用 \%( \)。如果 {middle} 非空,在相应的方
向试图寻找它 (如果找到,停留在哪里),但在嵌套的 start-end 组对
里面的不算。一个典型的应用是: >
searchpair('\<if\>', '\<else\>', '\<endif\>')
< 如果 {middle} 为空,跳过 "else"。
{flags} 'b'、'c'、'n'、's'、'w' 和 'W' 的使用方式和 |search()|
类似。此外,还可用:
'r' 重复 (Repeat) 直到没有更多匹配位置;会找到最外层的组
对。隐含 'W' 标志位。
'm' 返回匹配 (Match) 的数目而不是匹配的行号;使用 'r' 时会
> 1。
备注: 最好使用 'W' 标志位,避免在文件尾回绕。
如果找到 {start}、{middle} 或 {end} 的匹配,计算 {skip} 表达
式,此时假定光标定位在匹配的开始处。如果返回零,该匹配被跳过。
比如,可能是出现在注释里的匹配。
如果 {skip} 不提供或者为空,接受每一个匹配。如果计算 {skip} 时
出现错误,搜索被中止,并返回 -1。
{stopline} 和 {timeout} 见 |search()|。
使用 'ignorecase' 的值。忽略 'magic',使用模式时假设它总是置位
的。
搜索从准确的光标处开始。根据搜索方向,寻找从下一个字符开始的
{start}、{middle} 或 {end}。比如: >
if 1
if 2
endif 2
endif 1
< 如果从 "if 2" 开始且光标在 "i" 上并正向搜索,找到的是
"endif 2"。如果刚好在 "if 2" 之前开始,找到的是 "endif 1"。因
为先找到的了 "if 2",而它被认为是嵌套的 if/endif,以 "if 2"
开始,以 "endif 2" 结束。
如果反向搜索且 {end} 多于一个字符,在模式的最后加上 "\zs" 可能
有用,这样光标在 end 匹配的中间某位置的时候,仍然可以找到匹配
的 start 匹配。
例如,要找到 Vim 脚本里的 "endif" 命令: >
:echo searchpair('\<if\>', '\<el\%[seif]\>', '\<en\%[dif]\>', 'W',
\ 'getline(".") =~ "^\\s*\""')
< 光标必须在要寻找匹配的 "if" 之上或之后。注意 单引号字符串的使
用,它避免了反斜杠的麻烦。skip 表达式只用来发现行首的注释,命
令之后的不行。另外,一行中间的单词 "en" 或 "if" 也被认为是匹
配。
另一个例子,搜索匹配 "}" 的 "{": >
:echo searchpair('{', '', '}', 'bW')
< 只需要光标在需要匹配的 "}" 之上或之前就可以了。要拒绝语法高亮
识别为字符串的匹配: >
:echo searchpair('{', '', '}', 'bW',
\ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')
<
*searchpairpos()*
searchpairpos({start}, {middle}, {end} [, {flags} [, {skip}
[, {stopline} [, {timeout}]]]])
和 |searchpair()| 相同,但返回 |List|,包含匹配的行号和列号。
|List| 的第一个元素是行号,而第二个元素是匹配所在的列位置的字
节位置。如果没有匹配,返回 [0, 0]。 >
:let [lnum,col] = searchpairpos('{', '', '}', 'n')
<
|match-parens| 提供一个更复杂更有用的例子。
searchpos({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *searchpos()*
和 |search()| 相同,但返回 |List|,包含匹配的行号和列号。
|List| 的第一个元素是行号,而第二个元素是匹配所在的列位置的字
节位置。如果没有匹配,返回 [0, 0]。
例如: >
:let [lnum, col] = searchpos('mypattern', 'n')
< 如果给出 'p' 标志位,返回值里有一个附加项目,包含匹配的子模式
号 |search()-sub-match|。例如: >
:let [lnum, col, submatch] = searchpos('\(\l\)\|\(\u\)', 'np')
< 此例中如果找到小写字母 |/\l| "submatch" 为 2,如果找到大写字母
|/\u| 则为 3。
server2client( {clientid}, {string}) *server2client()*
发送应答字符串到 {clientid}。最近刚发送过字符串的 {clientid}
可以通过 expand("<client>") 得到。
{仅当在编译时加入 |+clientserver| 特性才有效}
备注:
该 id 应在接受下一个命令前保存。也就是,在接收命令返回之前 (译
者注: 似应为 "之后") 和任何等待输入的命令之前。
另见 |clientserver|。
示例: >
:echo server2client(expand("<client>"), "HELLO")
<
serverlist() *serverlist()*
返回可用的服务器名字列表,每行一个。如果没有服务器或者该信息
无法得到,返回空字符串。另见 |clientserver|。
{仅当编译时加入 |+clientserver| 特性才有效}
示例: >
:echo serverlist()
<
setbufvar({expr}, {varname}, {val}) *setbufvar()*
设置缓冲区 {expr} 的选项或局部变量 {varname} 的值为 {val}。
也可用于全局或者局部于窗口的选项,但不能用于全局或者局部于窗口
的变量。
如果设置局部于窗口的选项,全局值不会改变。
{expr} 的使用方式见上 |bufname()|。
注意必须使用不带 "b:" 的变量名。
示例: >
:call setbufvar(1, "&mod", 1)
:call setbufvar("todo", "myvar", "foobar")
< 该命令在沙盘里不可用 |sandbox|。
setcmdpos({pos}) *setcmdpos()*
设置命令行的光标位置到字节位置 {pos}。第一个位置为 1。
用 |getcmdpos()| 得到当前的位置。
只有在编辑命令行时有效,所以必须在 |c_CTRL-\_e|、|c_CTRL-R_=|
或带 '=' 的 |c_CTRL-R_CTRL-R| 里使用。对于 |c_CTRL-\_e| 和带
'=' 的 |c_CTRL-R_CTRL-R|,在命令行设为表达式的内容之后才设置位
置。对于 |c_CTRL-R_=|,在计算表达式之后但在插入返回的文本之前
设置位置。
如果数值太大,光标放在行尾。如果小于 1,结果没有定义。
如果成功,返回 0,如果不在编辑命令行,返回 1。
setline({lnum}, {text}) *setline()*
设置当前缓冲区第 {lnum} 行的内容为 {text}。
{lnum} 的用法同 |getline()|。
如果 {lnum} 刚刚在末行之下,{text} 用来增加新行。
如果成功,返回 0。如果失败 (多数是因为 {lnum} 不合法) 返回 1。
例如: >
:call setline(5, strftime("%c"))
< 如果 {text} 为 |List|,那么第 {lnum} 行和其后的行被设为列表里
的项目。例如: >
:call setline(5, ['aaa', 'bbb', 'ccc'])
< 等价于: >
:for [n, l] in [[5, 6, 7], ['aaa', 'bbb', 'ccc']]
: call setline(n, l)
:endfor
< 注意: 这里不会设置 '[ 和 '] 位置标记。
setloclist({nr}, {list} [, {action}]) *setloclist()*
创建或替代或加入到窗口 {nr} 的位置列表。
如果 {nr} 为零,使用当前窗口。如果是位置列表窗口,修改所显示的
位置列表。如果窗口号 {nr} 非法,返回 -1。
其它同 |setqflist()|。
另见 |location-list|。
setmatches({list}) *setmatches()*
恢复 |getmatches()| 保存的匹配列表。如果成功,返回 0,否则返回
-1。原有的所有匹配都被清除。示例见 |getmatches()|。
*setpos()*
setpos({expr}, {list})
设置 {expr} 的位置。可能的值:
. 光标
'x 位置标记 x
{list} 必须是带四个数值的 |List|:
[bufnum, lnum, col, off]
"bufnum" 是缓冲区号。零代表当前缓冲区。只能为当前缓冲区设置光
标。要设置别的缓冲区里的位置标记,可以用 |bufnr()| 函数把文件
名转化为缓冲区号。
不修改跳转表。
"lnum" 和 "col" 是缓冲区里的位置。第一列为 1。"lnum" 为零则删
除位置标记。"col" 如小于 1,则以 1 代替。
除非使用了 'virtualedit'。不用 "off" 值。这是从对应字符开始位置
计算的屏幕列。例如,在制表之中或最后一个字符之后的某个位置。
如果位置可以设置,返回 0,否则返回 -1。如果 {expr} 不合法,报
错。
另见 |getpos()|
这并不能恢复垂直移动使用的列。为此,可见 |winrestview()|。
setqflist({list} [, {action}]) *setqflist()*
用 {list} 的项目来创建或替代或加入到 quickfix 表。每个 {list}
项目是一个字典。
{list} 里非字典的项目被忽略。每个字典项目可以包含以下的项目:
bufnr 缓冲区号;必须为某个合法缓冲区的编号
filename 文件名;仅当 "bufnr" 不存在或者不合法时才使用
lnum 缓冲区里的行号
pattern 用于定位错误的模式
col 列号
vcol 非零: "col" 是可视列
零: "col" 是字节位置
nr 错误号
text 错误描述
type 错误类型,'E'、'W' 等。
"col"、"vcol"、"nr"、"type" 和 "text" 项目是可选的。"lnum" 或
"pattern" 项目用来定位匹配的错误行。
如果 "filename" 和 "bufnr" 项目都不存在或者 "lnum" 和
"pattern" 项目都不存在,那么此项目不被当作错误行处理。
如果 "pattern" 和 "lnum" 都存在,使用 "pattern"。
如果 {list} 为空,quickfix 列表被清除。
注意 此列表和 |getqflist()| 返回之值不尽相同。
如果 {action} 设为 'a',把 {list} 项目加入已有的 quickfix 列
表。如果该列表尚不存在,建立新表。如果 {action} 设为 'r',
{list} 项目替换当前 quickfix 列表项目。如果 {action} 不存在或
者设为 ' ',那么建立新表。
返回零代表成功,-1 代表失败。
该函数用来独立于 'errorformat' 的设置建立 quickfix 列表。
":cc 1" 这样的命令可以跳转到第一个位置上。
*setreg()*
setreg({regname}, {value} [,{options}])
设置寄存器 {regname} 的值为 {value}。
如果 {options} 包含 "a" 或者 {regname} 为大写,该值被附加于现
有值之后。
{options} 还可以指定寄存器新类型的规格:
"c" 或 "v" |characterwise| (面向字符) 模式
"l" 或 "V" |linewise| (面向行) 模式
"b" 或 "<CTRL-V>" |blockwise-visual| (面向列块) 模式
如果 "b" 或 "<CTRL-V>" 之后紧跟数值,那么该数值用作选择的宽度
- 如果没有指定,那么列块的宽度设为最长的行字符数 (把 <Tab>
看作一个字符)。
如果 {options} 没有寄存器的设置,那么缺省使用面向字符模式,除
非 {value} 以 <NL> 结尾。
不能设置 '=' 寄存器。
返回零代表成功,非零代表失败。
示例: >
:call setreg(v:register, @*)
:call setreg('*', @%, 'ac')
:call setreg('a', "1\n2\n3", 'b5')
< 本例说明如何使用函数来保存和恢复寄存器 >
:let var_a = getreg('a', 1)
:let var_amode = getregtype('a')
....
:call setreg('a', var_a, var_amode)
< 你可以通过附加空串来改变寄存器的类型: >
:call setreg('a', '', 'al')
settabvar({tabnr}, {varname}, {val}) *settabvar()*
设置标签页 {tabnr} 的标签页局部变量 {varname} 的值为 {val}。
注意 必须使用不带 "t:" 的名字。
标签页的编号从一开始。
Vim 短暂地进入标签页 {tabnr},所以会激活 TabLeave 和 TabEnter
自动命令。
该命令在沙盘里不可用 |sandbox|。
settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()*
设置窗口 {nr} 的选项或局部变量 {varname} 的值为 {val}。
标签页的编号从一开始。|setwinvar()| 总是使用当前标签页。
如果 {winnr} 为零,使用当前窗口。
也可用于全局或者局部于缓冲区的选项,但不能用于全局或者局部于缓
冲区的变量。
如果设置局部于缓冲区的选项,全局值不会改变。
注意 必须使用不带 "w:" 的变量名。
Vim 短暂地进入标签页 {tabnr},所以会激活 TabLeave 和 TabEnter
自动命令。
示例: >
:call settabwinvar(1, 1, "&list", 0)
:call settabwinvar(3, 2, "myvar", "foobar")
< 该命令在沙盘里不可用 |sandbox|。
setwinvar({nr}, {varname}, {val}) *setwinvar()*
类似于 |settabwinvar()|,只用当前标签页。
示例: >
:call setwinvar(1, "&list", 0)
:call setwinvar(2, "myvar", "foobar")
shellescape({string} [, {special}]) *shellescape()*
转义 {string} 以便用作外壳命令的参数。
在 MS-Windows 和 MS-DOS 上,如果未设定 'shellslash',用双引号
包围 {string},并给 {string} 内的双引号加倍。
在其它系统上,用单引号包围,并把所有的 "'" 替换为 "'\''"。
如果给出 {special} 参数且它是非零的数值或非空的字符串
(|non-zero-arg|),则特殊项目如 "!"、"%"、"#" 和 "<cword>" 等会
在前面加上反斜杠。|:!| 命令会再把反斜杠删除。
如果 'shell' 以 "csh" 结尾,"!" 字符会被转义 (仍是当 {special}
为 |non-zero-arg| 时)。这是因为 csh 和 tcsh 即使在单引号内仍然
使用 "!" 用于历史替换。
<NL> 也被转义。如果 {special} 为 |non-zero-arg| 且 'shell' 以
"csh" 结尾时,转义两次。
|:!| 命令的示例: >
:exe '!dir ' . shellescape(expand('<cfile>'), 1)
< 返回光标所在文件给出的目录列表。|system()| 的示例: >
:call system("chmod +w -- " . shellescape(expand("%")))
simplify({filename}) *simplify()*
在不改变含义的前提下,尽可能简化文件名。快捷方式 (MS-Windows
上) 或者符号链接 (Unix 上) 不会被解析。如果 {filename} 第一个
路径部分指定了当前目录,结果也会是如此。而结尾的路径分隔符也不
会被删除。
示例: >
simplify("./dir/.././/file/") == "./file/"
< 注意: 组合 "dir/.." 只有在 "dir" 是可以遍历的或者不存在的目录
才会被删掉。Unix 上,如果 "dir" 是同一目录下的符号链接,也会删
除该组合。为了在简化路径名之前解析所有牵涉到的符号链接,使用
|resolve()|。
sin({expr}) *sin()*
返回浮点数,即以弧度测量的 {expr} 的正弦值。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo sin(100)
< -0.506366 >
:echo sin(-4.01)
< 0.763301
{仅当编译时加入 |+float| 特性才有效}
sinh({expr}) *sinh()*
返回 {expr} 的双曲正弦值,返回值为 [-inf, inf] 区间内的浮点
数。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo sinh(0.5)
< 0.521095 >
:echo sinh(-0.9)
< -1.026517
{仅当编译时加入 |+float| 特性才有效}
sort({list} [, {func}]) *sort()* *E702*
给 {list} 项目排序,直接修改列表。返回 {list}。如果你不想修改
列表,先构建一个备份: >
:let sortedlist = sort(copy(mylist))
< 每个项目使用字符串表示形式进行排序。
数值排在字符串之后,|Lists| 排在数值之后。
要给当前缓冲区的文本排序,用 |:sort|。
如果给出 {func} 且为一,忽略大小写。
如果 {func} 为 |Funcref| 或函数名,调用该函数来比较项目。函数
调用时使用两个项目作为参数,函数返回时,0 代表相等,1 或更高代
表第一个排在第二个之后,-1 或更小代表第一个排在第二个之前。
例如: >
func MyCompare(i1, i2)
return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1
endfunc
let sortedlist = sort(mylist, "MyCompare")
< 对这个简单的例子,有更简短的一个比较版本,不考虑溢出情况: >
func MyCompare(i1, i2)
return a:i1 - a:i2
endfunc
<
*soundfold()*
soundfold({word})
返回 {word} 按发音折叠的等价形式。使用当前窗口的 'spelllang'
中第一个支持按发音折叠的语言。 'spell' 必须置位。如果不能按发
音折叠,按原样返回 {word}。
可用来提供拼写建议。注意 此方法可能很慢。
*spellbadword()*
spellbadword([{sentence}])
没有参数: 返回光标所在或之后的拼写错误的单词。光标移动到这个坏
词的开始处。如果光标行上没有坏词,返回空字符串,不移动光标。
有参数: 返回 {sentence} 里第一个拼写错误的单词。如果没有拼写错
误,返回空字符串。
返回值是两个项目的列表:
- 错误拼写的单词,或空字符串。
- 拼写错误的类型:
"bad" 拼写错误
"rare" 偏僻词
"local" 只在其它区域里合法的单词
"caps" 单词应该大写开头
例如: >
echo spellbadword("the quik brown fox")
< ['quik', 'bad'] ~
使用当前窗口的拼写信息。'spell' 选项必须置位,也用到
'spelllang' 的值。
*spellsuggest()*
spellsuggest({word} [, {max} [, {capital}]])
返回 |List|,包含替代 {word} 的拼写建议。
如果给出 {max},返回的建议不超过此数目。否则,返回不超过 25 个
建议。
如果给出 {capital} 参数且非零,只给出大写开头的拼写建议。
'spellcapcheck' 匹配后再使用此功能。
{word} 可以是后跟其它文本的错误拼写单词。这样可以对两个被分开
的单词进行连接。建议里也包含附加文本,以便你替换整行。
{word} 也可以是个好词。返回和它类似的单词。建议里不包含 {word}
自身,但可能会出现其大写开头的形式。
使用当前窗口的拼写信息。'spell' 选项必须置位,也用到
'spelllang' 和 'spellsuggest' 的值。
split({expr} [, {pattern} [, {keepempty}]]) *split()*
从 {expr} 构造 |List|。
如果 {pattern} 省略或为空,用每个空白分隔的字符序列构造一个项
目。否则,在匹配 {pattern} 的地方分割字符串,删除匹配部分的字
符。
如果列表的首末项目为空,省略它们,除非 {keepempty} 参数给出且
非零。其它空项目在 {pattern} 匹配至少一个字符或者 {keepempty}
非零的时候被保留。
例如: >
:let words = split(getline('.'), '\W\+')
< 要把字符串分割到每个字符: >
:for c in split(mystring, '\zs')
< 如果你想保留分隔符,可以用 '\zs': >
:echo split('abc:def:ghi', ':\zs')
< ['abc:', 'def:', 'ghi'] ~
分割首项可能为空的表格: >
:let items = split(line, ':', 1)
< 逆函数是 |join()|。
sqrt({expr}) *sqrt()*
返回浮点数,即 {expr} 的非负平方根。
{expr} 的计算结果必须是浮点数或数值。如果 {expr} 为负,返回
NaN (Not a Number,非数)。
示例: >
:echo sqrt(100)
< 10.0 >
:echo sqrt(-4.01)
< nan
"nan" 可能不同,取决于系统库。
{仅当编译时加入 |+float| 特性才有效}
str2float( {expr}) *str2float()*
把字符串 {expr} 转换为浮点数。这和使用浮点数的工作方式一样,见
|floating-point-format|,但稍稍宽松一点。例如,接受 "1e40",而
表达式中你必须书写 "1.0e40"。
安静地忽略数值之后的文本。
小数点必须是 '.',和当前的 locale 无关。逗号会使数值转换结束:
"12,345.67" 转换为 12.0。用 |substitute()| 可以拿掉千分位分
隔符: >
let f = str2float(substitute(text, ',', '', 'g'))
< {仅当编译时加入 |+float| 特性才有效}
str2nr( {expr} [, {base}]) *str2nr()*
把字符串 {expr} 转化为数值。
{base} 是转换的基底,可以为 8、10 或 16。
如果省略 {base},使用基底 10。这也意味着开头的零不会导致八进制
的转换,缺省的字符串到数值的转化并非如此。
如果 {base} 为 16,忽略开头的 "0x" 或 "0X"。如果使用别的基底,
返回零。
安静地忽略数值之后的文本。
strchars({expr}) *strchars()*
返回数值,给出字符串 {expr} 占据的字符数。组合用字符也算一个字
符。
另见 |strlen()|、|strdisplaywidth()| 和 |strwidth()|。
strdisplaywidth({expr}[, {col}]) *strdisplaywidth()*
返回数值,给出字符串 {expr} 在屏幕上占据的显示单元的数目。
如果省略 {col},假定为零。 否则给出开始计算的屏幕列号。该值对
包含制表符的计算有影响。
使用当前窗口的选项设置。其中影响显示的选项也对返回值有影响,如
'tabstop' 和 'display'。
{expr} 如包含东亚二义性宽度字符类,'ambiwidth' 也会影响返回结
果。
另见 |strlen()|、|strwidth()| 和 |strchars()|。
strftime({format} [, {time}]) *strftime()*
返回字符串,即经过 {format} 字符串的格式转换的日期和时间。使用
给定的 {time},如果没有给出时间,使用当前时间。可以接受的
{format} 取决于你的系统。这意味着该函数不是可移植的!
可用的格式参见 C 函数 strftime() 的参考手册。返回结果的最大长
度是 80 个字符。另见 |localtime()| 和 |getftime()|。
可以用 |:language| 命令改变语言。
示例: >
:echo strftime("%c") Sun Apr 27 11:49:23 1997
:echo strftime("%Y %b %d %X") 1997 Apr 27 11:53:25
:echo strftime("%y%m%d %T") 970427 11:53:55
:echo strftime("%H:%M") 11:55
:echo strftime("%c", getftime("file.c"))
显示 file.c 的修改时间。
< 并非所有系统都可以用。要检查这一点,用: >
:if exists("*strftime")
stridx({haystack}, {needle} [, {start}]) *stridx()*
返回数值,给出字符串 {haystack} 里第一个字符串 {needle} 出现的
字节位置。
如果给出 {start},搜索从 {start} 位置开始。可用来寻找第二个匹
配: >
:let comma1 = stridx(line, ",")
:let comma2 = stridx(line, ",", comma1 + 1)
< 搜索对大小写敏感。
模式搜索可用 |match()|。
如果 {needle} 不出现在 {haystack} 里,返回 -1。
另见 |strridx()|。示例: >
:echo stridx("An Example", "Example") 3
:echo stridx("Starting point", "Start") 0
:echo stridx("Starting point", "start") -1
< *strstr()* *strchr()*
stridx() 和 C 函数 strstr() 类似。如果使用单个字符,和
strchr() 类似。
*string()*
string({expr}) 返回 {expr} 转换后的字符串。如果 {expr} 为数值、浮点数、字符串
或它们的复合形式,那么用 |eval()| 可以把结果转回去。
{expr} 类型 返回值 ~
字符串 'string'
数值 123
浮点数 123.123456 或 1.23456e8
函数引用 function('name')
列表 [item, item]
字典 {key: value, key: value}
注意 字符串的值里 ' 字符加倍。
另见 |strtrans()|。
*strlen()*
strlen({expr}) 返回数值,即字符串 {expr} 的字节长度。
如果你要计算多字节字符的数目 (不计算合成用字符),可以这么用: >
:let len = strlen(substitute(str, ".", "x", "g"))
< 如果参数为数值,先把它转化为字符串。其它类型报错。
另见 |len()|、|strchars()|、|strdisplaywidth()| 和
|strwidth()|。
strpart({src}, {start}[, {len}]) *strpart()*
返回字符串,{src} 从第 {start} 个字节开始字节长度为 {len} 的子
串。
如果包含不存在的字节,不会产生错误。只是那些字节被忽略而已。
如果没有提供 {len},子串从 {start} 开始直到 {src} 的结尾。 >
strpart("abcdefg", 3, 2) == "de"
strpart("abcdefg", -2, 4) == "ab"
strpart("abcdefg", 5, 4) == "fg"
strpart("abcdefg", 3) == "defg"
< 注意: 要得到第一个字符,{start} 必须是零。比如,要得到光标开始
的三个字节: >
strpart(getline("."), col(".") - 1, 3)
<
strridx({haystack}, {needle} [, {start}]) *strridx()*
返回数值,给出字符串 {haystack} 里最后一个字符串 {needle} 出现
的字节位置。
如果给出 {start},此位置之外的匹配被忽略。可用来寻找上次匹配之
前的匹配: >
:let lastcomma = strridx(line, ",")
:let comma2 = strridx(line, ",", lastcomma - 1)
< 搜索对大小写敏感。
模式搜索可用 |match()|。
如果 {needle} 不出现在 {haystack} 里,返回 -1。
如果 {needle} 为空,返回 {haystack} 的长度。
另见 |stridx()|。示例: >
:echo strridx("an angry armadillo", "an") 3
< *strrchr()*
如果使用单个字符,和 C 函数 strrchr() 类似。
strtrans({expr}) *strtrans()*
返回等于 {expr} 的字符串,但所有的不可显示字符被翻译成可显示的
字符序列 |'isprint'|,类似于窗口里显示的形式。例如: >
echo strtrans(@a)
< 会显示寄存器里的换行符为 "^@" 而不是开启新行。
strwidth({expr}) *strwidth()*
返回数值,给出字符串 {expr} 在屏幕上占据的显示单元的数目。制表
符算作一个单元。如果不想这样,可用 |strdisplaywidth()|。
{expr} 如包含东亚二义性宽度字符类,'ambiwidth' 也会影响返回结
果。
另见 |strlen()|、|strdisplaywidth()| 和 |strchars()|。
submatch({nr}) *submatch()*
只用于 |:substitute| 命令里的表达式。返回匹配文本的第 {nr} 个
子匹配。如果 {nr} 为 0,返回整个匹配的文本。
例如: >
:s/\d\+/\=submatch(0) + 1/
< 找到行内第一个数值并加 1。
使用 <NL> 可以包含换行符。
substitute({expr}, {pat}, {sub}, {flags}) *substitute()*
返回等于 {expr} 的字符串,但其中第一个 {pat} 的匹配被替代成
{sub}。
和 ":substitute" 命令类似 (不带任何标志位)。但 {pat} 的匹配总
假定置位了 'magic' 选项而且 'cpoptions' 为空 (为了脚本的可移植
性)。
'ignorecase' 仍然适用,但 'smartcase' 不适用。
|string-match| 说明如何使用 {pat}。
{sub} 里的 '~' 不会被换成前一个 {sub}。
注意 {sub} 里的一些代码有特殊含义 |sub-replace-special|。比
如,要替换一些文本为 "\n" (两个字符),使用 "\\\\n" 或 '\\n'。
如果 {pat} 在 {expr} 里不能匹配,返回没有修改的 {expr}。
如果 {flags} 为 "g",{expr} 里的所有 {pat} 匹配都被替换。否
则,{flags} 应该为 ""。
示例: >
:let &path = substitute(&path, ",\\=[^,]*$", "", "")
< 删除 'path' 选项的最后一部分。 >
:echo substitute("testing", ".*", "\\U\\0", "")
< 返回 "TESTING"。
synID({lnum}, {col}, {trans}) *synID()*
返回数值,即当前窗口 {lnum} 行 {col} 列所在的语法 ID。
语法 ID 可以用在 |synIDattr()| 和 |synIDtrans()|,以得到文本
的语法信息。
最左列的 {col} 为 1。第一行的 {lnum} 为 1。适用 'synmaxcol' 的
值,如果行比它更长,就返回零。
如果 {trans} 非零,透明的项目被简约为它们实际显露的项目。这可
以用于你想知道实际使用的颜色的情形。如果 {trans} 为零,返回透
明的项目本身。这可用于想知道实际有效的语法项目的情形 (比如,在
括号内部)。
警告: 本函数可能很慢。最佳速度可以通过正向遍历文件获得。
例如 (回显光标所在的语法项目的名字): >
:echo synIDattr(synID(line("."), col("."), 1), "name")
<
synconcealed({lnum}, {col}) *synconcealed()*
返回列表。如果 {lnum} 和 {col} 所在位置的字符不在可隐藏区域,
列表的第一个项目为 0,否则为 1。列表的第二个项目为字符串。如果
第一个值为 1,第二个值包含代替被隐藏文本实际显示的文本,视乎
'conceallevel' 的当前值而定。列表的第三个,也即最后一个项目是
代表匹配的特定语法区域的唯一的数值。这用于在有两个连续的使用相
同替代字符的区域时,检测此处是否是一个新的可隐藏区域的开始。
示例可见 $VIMRUNTIME/syntax/2html.vim。
synIDattr({synID}, {what} [, {mode}]) *synIDattr()*
返回字符串,syntax ID {synID} 的 {what} 属性。可用于得到语法项
目的相关信息。
{mode} 可以是 "gui"、"cterm" 或 "term",从而得到的是该模式下的
属性。如果忽略 {mode} 或者指定了非法的值,使用当前激活的高亮方
式的属性 (GUI、cterm 或 term)。
使用 synIDtrans() 来跟随链接的高亮组。
{what} 结果 ~
"name" 语法项目的名字
"fg" 前景色 (GUI: 用于设置颜色的色彩名,cterm: 色彩
号,以字符串形式出现,term: 空字符串)
"bg" 背景色 (细节同 "fg")
"font" 字体名 (只适用于 GUI) |highlight-font|
"sp" 特殊颜色 (细节同 "fg") |highlight-guisp|
"fg#" 类似于 "fg",但只适用于 GUI,而且 GUI 使用的名
字形如 "#RRGGBB"。
"bg#" "bg",细节同 "fg#"
"sp#" "sp",细节同 "fg#"
"bold" "1" 如果粗体
"italic" "1" 如果斜体
"reverse" "1" 如果反显
"inverse" "1" 如果反显 (= reverse)
"standout" "1" 如果突出
"underline" "1" 如果下划线
"undercurl" "1" 如果下曲线
示例 (回显光标所在的语法项目的颜色): >
:echo synIDattr(synIDtrans(synID(line("."), col("."), 1)), "fg")
<
synIDtrans({synID}) *synIDtrans()*
返回数值,即 {synID} 经过翻译的语法 ID。这是用于高亮字符的语法
组的 ID。":highlight link" 给出的高亮组被跟随,以找到实际使用
的组。
synstack({lnum}, {col}) *synstack()*
返回 |List|,即当前窗口在 {lnum} 行 {col} 列语法项目的堆栈。列
表的每个项目是像 |synID()| 返回那样的 ID。
列表的第一个项目是最外层区域,其后依次是包含在内的项目。末项即
|synID()| 返回的项目,除非不是整个项目都被高亮,或者它是一个透
明项目。
此函数可用于调试语法文件。
显示光标所在的语法项目栈的示例: >
for id in synstack(line("."), col("."))
echo synIDattr(id, "name")
endfor
< 如果 {lnum} 和 {col} 指定的位置非法,不返回任何值。行末字符之
后的位置以及空行的第一个位置是合法的位置。
system({expr} [, {input}]) *system()* *E677*
得到外壳命令 {expr} 的输出结果。
如果给出 {input},该字符串被写到文件里,并传给外壳命令作为标准
输入。字符串照原样写入,你需要自己注意使用合适的换行符。不使用
管道。
注意: |shellescape()| 可以转义命令参数里的特殊字符。{expr} 里
的换行可能会使命令失败。'shellquote' 和 'shellxquote' 里的字符
也可能会引起麻烦。
这不是用来执行交互命令的。
返回字符串。示例: >
:let files = system("ls " . shellescape(expand('%:h')))
< 要使结果更独立于所用的系统,外壳输出的结果被过滤,Macintosh 的
<CR> 被换成 <NL>,而 DOS 系列的系统上 <CR><NL> 也被换成 <NL>。
使用若干选项,以下面的方法构造要执行的命令:
'shell' 'shellcmdflag' 'shellxquote' {expr} 'shellredir' {tmp} 'shellxquote'
({tmp} 是自动生成的一个文件名)。
Unix 和 OS/2 上,{expr} 用大括号包围,以便支持连接的多条命令。
以加工 ("cooked") 模式执行命令,这样 CTRL-C 可以用来中止命令
(至少在 Unix 上是如此)。
返回的错误代码可以在 |v:shell_error| 里找到。
该函数不能运行于 |restricted-mode|。
注意 上面提到的选项值如有错误,该函数就会失败。使用若干安全代
理应用时也有报告说它会失败。
不同于 ":!cmd",没有自动对改变过的文件的检查。使用
|:checktime| 来强制这种检查。
tabpagebuflist([{arg}]) *tabpagebuflist()*
返回 |List|,每个项目是当前标签页里每个窗口相关联的缓冲区的编
号。
{arg} 指定使用的标签页的编号。如果省略,使用当前标签页。
如果 {arg} 非法,返回数值零。
要得到所有标签页里的所有缓冲区的列表,这样用: >
tablist = []
for i in range(tabpagenr('$'))
call extend(tablist, tabpagebuflist(i + 1))
endfor
< 注意 缓冲区可能出现于多于一个窗口里。
tabpagenr([{arg}]) *tabpagenr()*
返回数值,当前标签页号。第一个标签页的编号为 1。
如果可选参数为 "$",返回最后一个标签页的编号 (即标签页总数)。
该数值可用于 |:tab| 命令。
tabpagewinnr({tabarg}, [{arg}]) *tabpagewinnr()*
类似于 |winnr()|,但使用标签页 {tabarg}。
{tabarg} 指定要使用的标签页号。
{arg} 的用法类似于 |winnr()|:
- 如果省略,返回当前窗口号,也就是转到该标签页时会使用的窗口。
- 如果是 "$",返回窗口的总数。
- 如果是 "#",返回上次的窗口编号。
用于的例子: >
tabpagewinnr(1) " 标签页 1 的当前窗口
tabpagewinnr(4, '$') " 标签页 4 的窗口总数
< 如果 {tabarg} 非法,返回零。
*tagfiles()*
tagfiles() 返回 |List|,当前缓冲区用于搜索的标签文件名。这是 'tags' 选项
扩展后的内容。
taglist({expr}) *taglist()*
返回匹配正规表达式 {expr} 的标签列表。每个列表项目是一个至少包
含以下项目的字典:
name 标签名。
filename 标签定义的文件名。它或者相对于当前目
录,或者包含完整路径。
cmd 用于在文件里定位标签的 Ex 命令。
kind 标签类型。该项目的值取决于特定于语言的
类型值。只在 Exuberant ctags 或 hdrtag
生成的标签文件里存在。
static 特定于文件的标签。详见 |static-tag|。
可能还有一些其它项目,取决于标签文件的内容: access、
implementation、inherits 和 signature。这些字段的信息参见
ctags 文档。C 代码里可能出现字段 "struct"、"class" 和 "enum",
它们给出标签所在的实体的名字。
ex 命令 'cmd' 可以是 ex 搜索模式、行号或者行号后跟字节位置。
如果没有匹配的标签,返回空列表。
要得到标签的准确匹配,{expr} 里必须使用 '^' 和 '$'。 关于标签
搜索正规表达式模式的详情见 |tag-regexp|。
|'tags'| 提供 Vim 如何定位标签文件的信息。|tags-file-format|
说明不同的 ctags 工具生成的标签文件的格式。
tempname() *tempname()* *temp-file-name*
返回字符串,它是一个不存在的文件名。可以用作临时文件。该文件在
至少 26 个接连的调用内不会重复。例如: >
:let tmpfile = tempname()
:exe "redir > " . tmpfile
< Unix 上,文件会在用户个人的目录中 |tempfile|。
MS-Windows 上,如果置位了 'shellslash' 选项或者 'shellcmdflag'
以 '-' 开始的时候,使用正斜杠。
tan({expr}) *tan()*
返回以弧度测量的 {expr} 的正切值。返回值是 [-inf, inf] 区间内
的浮点数。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo tan(10)
< 0.648361 >
:echo tan(-4.01)
< -1.181502
{仅当编译时加入 |+float| 特性才有效}
tanh({expr}) *tanh()*
返回 {expr} 的双曲正切值,返回值为 [-1, 1] 区间内的浮点数。
{expr} 的计算结果必须是浮点数或数值。
示例: >
:echo tanh(0.5)
< 0.462117 >
:echo tanh(-1)
< -0.761594
{仅当编译时加入 |+float| 特性才有效}
tolower({expr}) *tolower()*
返回给出字符串的备份,但所有的大写字符变为小写 (就如同在字符串
上应用了 |gu| 一样)。
toupper({expr}) *toupper()*
返回给出字符串的备份,但所有的小写字符变为大写 (就如同在字符串
上应用了 |gU| 一样)。
tr({src}, {fromstr}, {tostr}) *tr()*
返回 {src} 字符串的备份,其中 {fromstr} 里的每个字符被 {tostr}
字符串里同样的位置的字符替代。也就是,{fromstr} 的第一个字符被
翻译成 {tostr} 的第一个字符,依此类推。和 unix 命令 "tr" 完全
相同。
能正确处理多字节字符。
例如: >
echo tr("hello there", "ht", "HT")
< 返回 "Hello THere" >
echo tr("<blob>", "<>", "{}")
< 返回 "{blob}"
trunc({expr}) *trunc()*
返回浮点数,即绝对值小于等于 {expr} 的最大整数 (向零取整)。
{expr} 的计算结果必须是浮点数或数值。
示例: >
echo trunc(1.456)
< 1.0 >
echo trunc(-5.456)
< -5.0 >
echo trunc(4.0)
< 4.0
{仅当编译时加入 |+float| 特性才有效}
*type()*
type({expr}) 返回数值,取决于 {expr} 的类型:
数值: 0
字符串: 1
函数引用: 2
列表: 3
字典: 4
浮点数: 5
要避免使用这些魔术数,应该这样使用: >
:if type(myvar) == type(0)
:if type(myvar) == type("")
:if type(myvar) == type(function("tr"))
:if type(myvar) == type([])
:if type(myvar) == type({})
:if type(myvar) == type(0.0)
undofile({name}) *undofile()*
返回用于名为 {name} 的文件的撤销文件名。使用 'undodir' 选项并
寻找实际存在的目录。并不检查该撤销文件是否存在。
{name} 总是扩展为完整路径,因为内部是这么使用的。
可用于 |:wundo| 和 |:rundo|。
如果编译时没有 +persistent_undo 选项,总是返回空字符串。
undotree() *undotree()*
返回撤销树的当前状态。返回值是包含以下项目的字典:
"seq_last" 最大使用的撤销序列号。
"seq_cur" 撤销树中当前位置的序列号。如果有撤销过的改变,
和 "seq_last" 会有不同。
"time_cur" 最近用于 |:earlier| 和相关命令的时间。
可用 |strftime()| 转换成可读的格式。
"save_last" 最后的文件写入编号。如果没有写入,返回零。
"save_cur" 撤销树当前位置的编号。
"synced" 如果最后的撤销块已经同步,返回非零值。等待用户
输入时会发生。见 |undo-blocks|。
"entries" 关于撤销块的信息的字典的列表。
"entries" 列表的第一个值是最老的撤销项目。每个列表项目是一个包
含以下项目的字典:
"seq" 撤销序列号。和 |:undolist| 显示的相同。
"time" 改变发生的时间。可用 |strftime()| 转换成可读的
格式。
"newhead" 只出现在最后加入的项目。标识最后的改变,并指示
将来的改变加入所在的位置。
"curhead" 只出现在最后撤销的项目。表示撤销树当前的位置,
该块可用于 redo 命令。如果最后改变之后没有撤销
动作,此项目不出现。
"save" 只出现在文件写入前最后的块。该值为写入计数。首
次写入的编号为 1,最后一次是上面提及的
"save_last"。
"alt" 替代项。这又是一个撤销块的列表。每个项目又可以
有 "alt" 项目。
values({dict}) *values()*
返回 |List|,{dict} 的所有值。|List| 项目的顺序不定。
virtcol({expr}) *virtcol()*
要得到屏幕列的位置,用 |virtcol()|。
注意 只能使用当前文件的位置标记。
返回数值,即 {expr} 给定的文件位置的屏幕列号。也就是,该位置的
字符占据的最后一个屏幕位置,这里假设屏幕有无限的宽度。如果该位
置是一个 <Tab>,返回的数值是 <Tab> 占据的最后一列。比如,如果
<Tab> 在第 1 列,而 'ts' 设为 8 的话,返回 8。
关于字节位置,见 |col()|。
{expr} 用法见 |col()|。
如果使用 'virtualedit',{expr} 可以用 [lnum, col, off],其中
"off" 是字符位置开始计算的屏幕列。例如,制表中或最后一个字符之
后的某个位置。
如果在当前模式下使用了虚拟编辑,也可能返回行尾之后的位置。
|'virtualedit'|
可接受的位置是:
. 光标位置
$ 光标行的行尾 (返回光标行显示的字符数加 1)
'x 位置标记 x 的位置 (如果该位置标记没有设置,返回 0)
注意 只能使用当前文件的位置标记。
示例: >
virtcol(".") 文本 "foo^Lbar",光标在 "^L" 上,返回 5
virtcol("$") 文本 "foo^Lbar",返回 9
virtcol("'t") 文本 " there",'t 在 'h' 上,返回 6
< 第一列为 1。返回 0 代表错误。
一个更高级的示例,显示所有行的最大长度: >
echo max(map(range(1, line('$')), "virtcol([v:val, '$'])"))
visualmode([expr]) *visualmode()*
返回字符串,它描述当前缓冲区最近使用的可视模式。一开始,它返回
空字符串,一旦使用了可视模式,返回 "v"、"V" 或 "<CTRL-V>" (单
个 CTRL-V 字符),分别代表面向字符、面向行、和面向列块的可视模
式。
例如: >
:exe "normal " . visualmode()
< 进入和上次相同的可视模式。也可以用于在脚本里根据最近的可视模式
采取不同的行动。
如果当前正处于可视模式中,|mode()| 可得到具体的可视模式 (例如
在 |:vmap| 中可用)。
*non-zero-arg*
如果提供 [expr] 并且计算结果是非零数值或者是非空字符串,那么将
清除可视模式,并返回旧的值。注意 " " 和 "0" 也是非空字符串,所
以也会清除该模式。列表、字典或浮点数不是数值或字符串,所以不会
清除该模式。
*winbufnr()*
winbufnr({nr}) 返回数值,即窗口 {nr} 相关联的缓冲区号。如果 {nr} 为零,返回当
前窗口的缓冲区号。如果窗口 {nr} 不存在,返回 -1。
示例: >
:echo "当前窗口的文件是 " . bufname(winbufnr(0))
<
*wincol()*
wincol() 返回数值,窗口光标的虚拟列。亦即从窗口左侧起算的屏幕列数。最左
列为第一列。
winheight({nr}) *winheight()*
返回数值,窗口 {nr} 的高度。如果 {nr} 为零,返回当前窗口的高
度。如果窗口 {nr} 不存在,返回 -1。存在的窗口的宽度至少为零。
示例: >
:echo "当前窗口有 " . winheight(0) . " 行。"
<
*winline()*
winline() 返回数值,窗口光标所在的屏幕行,亦即,从窗口顶部起算的屏幕行
数。第一行返回 1。
如果光标移动,文件的视图会先更新,这可能会导致滚动。
*winnr()*
winnr([{arg}]) 返回数值,当前窗口的编号。最上面的窗口的编号为 1。
如果可选的参数为 "$",返回最后一个窗口的编号 (即窗口的总数)。
如果可选的参数为 "#",返回最近访问的窗口号 (|CTRL-W_p| 到的地
方)。如果没有上次窗口或它在另一个标签页中,返回 0。
该数值可以用于 |CTRL-W_w| 和 ":wincmd w" |:wincmd|。
另见 |tabpagewinnr()|。
*winrestcmd()*
winrestcmd() 返回 |:resize| 命令序列,该序列应该能够恢复当前窗口的大小。只
有在没有窗口被打开或关闭且当前窗口和标签页都没有改变的时候才能
正确工作。
示例: >
:let cmd = winrestcmd()
:call MessWithWindowSizes()
:exe cmd
<
*winrestview()*
winrestview({dict})
使用 |winsaveview()| 返回的 |Dictionary| 来恢复当前窗口的视
图。
如果你改变了其中的值,结果无法预测。如果窗口大小改变了,结果不
会完全一样。
*winsaveview()*
winsaveview() 返回 |Dictionary|,包含当前窗口的信息,这些信息可用来恢复视
图。
|winrestview()| 进行视图的恢复。
可用于定义在缓冲区里跳转后想恢复的原来视图的映射。
这里不保存折叠的信息。用 'foldenable' 选项来暂时关闭折叠功能,
这样在移动时折叠就不会打开。
返回值包括:
lnum 光标行号
col 光标列号
coladd 'virtualedit' 使用的光标列偏移
curswant 垂直移动使用的列
topline 窗口的第一行
topfill 填充行,只用于 diff 模式
leftcol 显示的第一列
skipcol 跳过的列数
注意 这里不保存任何选项值。
winwidth({nr}) *winwidth()*
返回数值,窗口 {nr} 的宽度。如果 {nr} 为零,返回当前窗口的宽
度。如果窗口 {nr} 不存在,返回 -1。存在的窗口的宽度至少为零。
示例: >
:echo "当前窗口有 " . winwidth(0) . " 列。"
:if winwidth(0) <= 50
: exe "normal 50\<C-W>|"
:endif
<
*writefile()*
writefile({list}, {fname} [, {binary}])
把 |List| {list} 写到文件 {fname} 里。列表的项目间以 NL 分隔。
每个列表项必须是字符串或数值。
如果 {binary} 等于 "b",使用二进制模式: 最后一个列表项目之后没
有 NL,最后的空项目使得文件的末行以 NL 结尾。
所有的 NL 字符被 NUL 字符代替。
CR 字符的插入需要在把 {list} 传递给 writefile() 之前先做好。
如果可能,覆盖已有的文件。
如果写入失败,返回 -1,否则返回 0。如果文件不能建立或者写入失
败,会有错误信息。
另见 |readfile()|。
要按字节复制文件: >
:let fl = readfile("foo", "b")
:call writefile(fl, "foocopy", "b")
<
*feature-list*
有三种类型的特性:
1. 只有在 Vim 编译时加入才会支持的特性 |+feature-list|。例如: >
:if has("cindent")
2. 只有特定条件满足才会支持的特性。例如: >
:if has("gui_running")
< *has-patch*
3. 包含的补丁。先检查 |v:version| 确定 Vim 的版本。然后形如 "patch123" 的特性
意味着补丁 123 已经在本版本里包含了。例如 (确定是 version 6.2.148 或更新的
版本): >
:if v:version > 602 || v:version == 602 && has("patch148")
< 注意 包含了补丁 148 但不包含补丁 147 是可能的。
all_builtin_terms 编译时打开了所有的内建终端。
amiga Vim 的 Amiga 版本。
arabic 编译时加入了阿拉伯语的支持。|Arabic|。
arp 编译时加入了 ARP 的支持。(Amiga)。
autocmd 编译时加入了自动命令的支持。|autocommand|
balloon_eval 编译时加入了 |balloon-eval| 的支持。
balloon_multiline GUI 支持多行气泡。
beos Vim 的 BeOS 版本。
browse 编译时加入了 |:browse| 的支持。因而 browse() 可以工作。
builtin_terms 编译时打开了一些内建终端。
byte_offset 编译时加入了的支持。for 'o' in 'statusline'
cindent 编译时加入了 'cindent' 的支持。
clientserver 编译时加入了远程调用的支持。|clientserver|。
clipboard 编译时加入了 'clipboard' 的支持。
cmdline_compl 编译时加入了 |cmdline-completion| 的支持。
cmdline_hist 编译时加入了 |cmdline-history| 的支持。
cmdline_info 编译时加入了 'showcmd' and 'ruler' 的支持。
comments 编译时加入了 |'comments'| 的支持。
cryptv 编译时加入了加密的支持。|encryption|。
cscope 编译时加入了 |cscope| 的支持。
compatible 编译时确保和 Vi 非常兼容。
debug 编译时定义了 "DEBUG"。
dialog_con 编译时加入了控制台对话框的支持。
dialog_gui 编译时加入了 GUI 对话框的支持。
diff 编译时加入了 |vimdiff| 和 'diff' 的支持。
digraphs 编译时加入了二合字母的支持。
dnd 编译时加入了 "~ 寄存器的支持 |quote_~|。
dos32 Vim 的 32 位 DOS 的 (DJGPP) 版本。
dos16 Vim 的 16 位的 DOS 版本。
ebcdic 在使用 ebcdic 字符集的机器上编译。
emacs_tags 编译时加入了 Emcac 标签的支持。
eval 编译时加入了表达式计算的支持。当然总要打开啦!
ex_extra 编译时加入了附加的 Ex 命令 |+ex_extra|。
extra_search 编译时加入了 |'incsearch'| 和 |'hlsearch'| 的支持。
farsi 编译时加入了波斯语的支持。|farsi|。
file_in_path 编译时加入了 |gf| 和 |<cfile>| 的支持。
filterpipe 'shelltemp' 关闭时,外壳读/写/过滤命令使用管道
find_in_path 编译时加入了头文件搜索 |+find_in_path| 的支持。
float 编译时加入了 |Float| 的支持。
fname_case 文件名大小写敏感 (在 Amiga、MS-DOS 和 Windows 本特性不
存在)。
folding 编译时加入了 |folding| 的支持。
footer 编译时加入了 GUI 信息页脚的支持。|gui-footer|
fork 编译时决定使用 fork()/exec() 而不是 system()。
gettext 编译时加入了信息翻译 |multi-lang|。
gui 编译时加入了 GUI 的支持。
gui_athena 编译时加入了 Athena GUI。
gui_gtk 编译时加入了 GTK+ GUI (任何版本)。
gui_gtk2 编译时加入了 GTK+ 2 GUI (同时也定义了 gui_gtk)。
gui_gnome 编译时加入了 Gnome 支持 (同时也定义了 gui_gtk)。
gui_mac 编译时加入了 Macintosh GUI。
gui_motif 编译时加入了 Motif GUI。
gui_photon 编译时加入了 Photon GUI。
gui_win32 编译时加入了 MS Windows Win32 GUI。
gui_win32s 同上,使用了 Win32s 系统 (Windows 3.1)
gui_running Vim 在 GUI 上运行,或者 GUI 将很快启动。
hangul_input 编译时加入了韩语 (Hangul) 输入的支持。 |hangul|
iconv 可以使用 iconv() 进行转换。
insert_expand 编译时加入了插入模式中 CTRL-X 扩展命令的支持。
jumplist 编译时加入了 |jumplist| 的支持。
keymap 编译时加入了 'keymap' 的支持。
langmap 编译时加入了 'langmap' 的支持。
libcall 编译时加入了 |libcall()| 的支持。
linebreak 编译时加入了 'linebreak'、'breakat' 和 'showbreak' 的
支持。
lispindent 编译时加入了 lisp 缩进的支持。
listcmds 编译时加入了缓冲区列表 |:files| 和参数列表 |arglist|
的命令。
localmap 编译时加入了局部映射和缩写。|:map-local|
lua 编译时加入了 Lua 接口 |Lua|。
mac Vim 的 Macintosh 版本。
macunix Vim 的 Macintosh 版本,使用 Unix 文件命名 (OS-X)。
menu 编译时加入了 |:menu| 的支持。
mksession 编译时加入了 |:mksession| 的支持。
modify_fname 编译时加入了文件名的修饰符支持。|filename-modifiers|
mouse 编译时加入了鼠标的支持。
mouseshape 编译时加入了 'mouseshape' 的支持。
mouse_dec 编译时加入了 Dec 终端的鼠标支持。
mouse_gpm 编译时加入了 gpm (Linux 控制台鼠标) 的支持。
mouse_netterm 编译时加入了 netterm 的鼠标支持。
mouse_pterm 编译时加入了 qnx 的鼠标支持。
mouse_sysmouse 编译时加入了 sysmouse 支持 (*BSD 控制台鼠标)
mouse_xterm 编译时加入了 xterm 的鼠标支持。
multi_byte 编译时加入了 'encoding' 的支持。
multi_byte_encoding 'encoding' 设为某个多字节的编码。
multi_byte_ime 编译时加入了 IME 输入方法的支持。
multi_lang 编译时加入了多语言的支持。
mzscheme 编译时加入了 MzScheme 接口支持 |mzscheme|。
netbeans_intg 编译时加入了 |netbeans| 的支持。
netbeans_enabled 编译时加入了 |netbeans| 的支持并且已连接上。
ole 编译时加入了 Win32 OLE automation 的支持。
os2 Vim 的 OS/2 版本。
osfiletype 编译时加入了 osfiletypes 的支持。|+osfiletype|
path_extra 编译时加入了 'path' 和 'tags' 上下搜索的支持。
perl 编译时加入了 Perl 接口。
persistent_undo 编译时加入了持久化撤销历史的支持。
postscript 编译时加入了 PostScript 文件打印的支持。
printer 编译时加入了 |:hardcopy| 的支持。
profile 编译时加入了 |:profile| 的支持。
python 编译时加入了 Python 接口。
qnx Vim 的 QNX 版本。
quickfix 编译时加入了 |quickfix| 的支持。
reltime 编译时加入了 |reltime()| 的支持。
rightleft 编译时加入了 'rightleft' 的支持。
ruby 编译时加入了 Ruby 接口 |ruby|。
scrollbind 编译时加入了 'scrollbind' 的支持。
showcmd 编译时加入了 'showcmd' 的支持。
signs 编译时加入了 |:sign| 的支持。
smartindent 编译时加入了 'smartindent' 的支持。
sniff 编译时加入了 SNiFF interface 的支持。
startuptime 编译时加入了 |--startuptime| 支持。
statusline 编译时加入了 'statusline' 和 'rulerformat' 还有
'titlestring' 和 'iconstring' 的特殊格式的支持。
sun_workshop 编译时加入了 Sun |workshop| 的支持。
spell 编译时加入了拼写检查的支持 |spell|。
syntax 编译时加入了语法高亮的支持 |syntax|。
syntax_items 当前缓冲区有激活的语法高亮项目。
system 编译时决定使用 system() 而不是 fork()/exec()。
tag_binary 编译时加入了标签文件的二分搜索 |tag-binary-search|。
tag_old_static 编译时加入了老的静态标签的支持。|tag-old-static|。
tag_any_white 编译时加入了允许标签文件使用任何空白字符的支持。
|tag-any-white|。
tcl 编译时加入了 Tcl 接口。
terminfo 编译时决定使用 terminfo 而不是 termcap。
termresponse 编译时加入了 |t_RV| 和 |v:termresponse| 的支持。
textobjects 编译时加入了 |text-objects| 的支持。
tgetent 编译时加入了 tgetent 的支持,可以使用外部 termcap 或
terminfo 文件。
title 编译时加入了窗口标题的支持。|'title'|。
toolbar 编译时加入了 |gui-toolbar| 的支持。
unix Vim 的 Unix 版本。
user_commands 用户定义命令支持。
viminfo 编译时加入了 viminfo 的支持。
vim_starting 如果在启动载入脚本的阶段则为真。
vertsplit 编译时加入了垂直分割窗口的支持 |:vsplit|。
virtualedit 编译时加入了 'virtualedit' 选项支持。
visual 编译时加入了可视模式的支持。
visualextra 编译时加入了附加的可视模式命令支持。
|blockwise-operators|。
vms Vim 的 VMS 版本。
vreplace 编译时加入了 |gR| and |gr| 命令支持。
wildignore 编译时加入了 'wildignore' 选项支持。
wildmenu 编译时加入了 'wildmenu' 选项支持。
windows 编译时加入了多窗口的支持。
winaltkeys 编译时加入了 'winaltkeys' 选项。
win16 Vim 的 Win16 版本。(MS-Windows 3.1)。
win32 Vim 的 Win32 版本。(MS-Windows 95/98/ME/NT/2000/XP)。
win64 Vim 的 Win64 版本。(MS-Windows 64 位)。
win32unix Vim 的 Win32 版本。使用 Unix 文件命名 (Cygwin)
win95 支持 MS-Windows 95/98/ME 的 Win32 版本。
writebackup 编译时决定缺省打开 'writebackup'。
xfontset 编译时加入了 X 字体集 的支持。|xfontset|。
xim 编译时加入了 X 输入法 的支持。|xim|。
xsmp 编译时加入了 X 会话管理 的支持。
xsmp_interact 编译时加入了交互的 X 会话管理 的支持。
xterm_clipboard 编译时加入了 xterm 剪贴板的支持。
xterm_save 编译时加入了保存和恢复 xterm 屏幕的支持。
x11 编译时加入了 X11 的支持。
*string-match*
字符串里的模式匹配
|pattern| 说明的正规表达式通常用于寻找缓冲区行的匹配。如果匹配用来在字符串里寻
找匹配,几乎所有的功能都相同。唯一的区别是,字符串是作为单行处理的。如果字符串
里包含了 "\n" 字符,它并不看作是模式里的换行。它可以匹配模式里的 "\n",甚至于
"."。示例: >
:let a = "aaaa\nxxxx"
:echo matchstr(a, "..\n..")
aa
xx
:echo matchstr(a, "a.x")
a
x
不要忘记 "^" 只会在字符串的第一个字符匹配,而 "$" 在字符串的最后一个字符匹配。
它们不会匹配 "\n" 之后和之前的位置。
==============================================================================
5. 定义函数 *user-functions*
可以定义新的函数。调用的方式就像内建函数一样。函数执行一系列 Ex 命令。普通模式
下的命令可以用 |:normal| 命令执行。
函数名须以大写字母开始,以免和内建函数引起混淆。要避免在不同脚本使用相同的名
字,避免显见的或者过短的名字。一个好习惯是使用脚本名字作为函数名字的开头,比如
"HTMLcolor()"。
也可以使用花括号,见 |curly-braces-names|。|autoload| 机制可用于在调用时才提供
函数的定义。
*local-function*
局部于脚本的函数必须以 "s:" 开始。局部于脚本的函数只能在同一脚本和脚本中定义的
函数、用户命令和自动命令里调用。也可以在脚本定义的映射里调用该函数,但必须使用
|<SID>| 而不是 "s:",如果映射会在脚本之外被扩展的话。
*:fu* *:function* *E128* *E129* *E123*
:fu[nction] 列出所有函数和它们的参数。
:fu[nction] {name} 列出 {name} 命名的函数。
{name} 也可以是 |Funcref| 类型的 |Dictionary| 项目: >
:function dict.init
:fu[nction] /{pattern} 列出名字匹配 {pattern} 的函数。
列出所有以 "File" 结束的函数的例子: >
:function /File$
<
*:function-verbose*
如果 'verbose' 非零,列出函数的同时也显示它上次定义的位置。例如: >
:verbose function SetFileTypeSH
function SetFileTypeSH(name)
Last set from /usr/share/vim/vim-7.0/filetype.vim
<
|:verbose-cmd| 有更多信息。
*E124* *E125*
:fu[nction][!] {name}([arguments]) [range] [abort] [dict]
定义 {name} 命名的新函数。名字必须由字母数字和 '_' 字
符组成,而且必须以大写字母或者 "s:" 开头 (见上)。
{name} 也可以是 |Funcref| 类型的 |Dictionary| 项目: >
:function dict.init(arg)
< "dict" 必须是一个已经存在的字典。如果还不存在,项目
"init" 被加入此字典。否则必须提供 [!] 以覆盖已经存在的
函数。返回指向一个编号函数的 |Funcref|。该函数只能通过
|Funcref| 引用,没有引用指向它时,该函数会被删除。
*E127* *E122*
如果同名的函数已经存在而且没有使用 [!],给出错误信息。
如果给出 [!],已有的函数被悄然替代。如果该函数正在执行
期间除外。此时,这是一个错误。
{arguments} 参见 |function-argument|。
*a:firstline* *a:lastline*
如果给出 [range] 参数,则该函数自己能理解并处理行范
围。该范围通过 "a:firstline" 和 "a:lastline" 定义。如
果没有 [range],":{range}call" 会在该范围的每一行分别
执行该函数,每次光标都定位在处理行的行首。见
|function-range-example|。
如果给出 [abort] 参数,该函数在遇到错误时立即中止。
如果给出 [dict] 参数,该函数必须通过 |Dictionary| 的项
目才能调用。局部变量 "self" 这时设为该字典。见
|Dictionary-function|。
*function-search-undo*
最近使用的搜索模式和重做命令 "." 不会受到函数的影响。
这也意味着 |:nohlsearch| 的效果在函数返回时会被撤销。
*:endf* *:endfunction* *E126* *E193*
:endf[unction] 结束函数定义。必须单起一行,没有任何其它命令。
*:delf* *:delfunction* *E130* *E131*
:delf[unction] {name} 删除 {name} 命名的函数。
{name} 也可以是 |Funcref| 类型的 |Dictionary| 项目: >
:delfunc dict.init
< 会删除 "dict" 的 "init" 项目。如果没有更多指向它的引
用,该函数被删除。
*:retu* *:return* *E133*
:retu[rn] [expr] 从函数返回。如果给出 "[expr]",计算该表达式的结果成为
函数的返回值。如果没有给出 "[expr]",返回 0。
如果函数退出时没有显式的调用 ":return",返回 0。
注意 没有不可到达行的检查,因而,如果有命令在
":return" 之后,不会给出警告。
如果 ":return" 在 |:try| 之后使用但在匹配的 |:finally|
(如果有的话) 之前的话,":finally" 之后直到匹配的
|:endtry| 的命令会先执行。该过程反复应用于所有函数内的
嵌套 ":try" 块。在最外层 ":endtry" 结束之后才真正返
回。
*function-argument* *a:var*
参数的定义只要给出它的名字。在函数里,可以使用 "a:name" 来访问 ("a:" 代表参数
(argument))。
*a:0* *a:1* *a:000* *E740* *...*
可以给出不超过 20 个参数,以逗号分隔。最后,可以给出参数 "...",意味着可以有更
多的参数。在函数里,可以通过 "a:1"、"a:2" 等等访问它们。"a:0" 设为这些附加参数
的数目 (可以为 0)。"a:000" 设为包含这些参数的 |List|。注意 "a:1" 等同于
"a:000[0]"。
*E742*
a: 作用域和其中的变量不能修改,它们是固定的。不过,如果使用了 |List| 或
|Dictionary|,你可以改变它们的内容。 所以你可以传递给函数一个 |List|,让该函数
在里面增加项目。如果要确保函数不能修改 |List| 或 |Dictionary|,用 |:lockvar|。
如果不使用 "...",实际给出的参数数目必须等于命名参数的数目。如果使用 "...",参
数的数目可以更多。
可以定义没有参数的函数。但你这时仍然需要提供 ()。函数体在之后的行给出,直到匹
配的 |:endfunction| 为止。可以在函数体里定义别的函数。
*local-variables*
在函数里,可以使用变量。它们是局部变量,在函数返回时就会消失。全局变量的访问需
要通过 "g:"。
例如: >
:function Table(title, ...)
: echohl Title
: echo a:title
: echohl None
: echo a:0 . " items:"
: for s in a:000
: echon ' ' . s
: endfor
:endfunction
该函数这时可以这样调用: >
call Table("Table", "line1", "line2")
call Table("Empty Table")
要返回多于一个值,返回一个 |List|: >
:function Compute(n1, n2)
: if a:n2 == 0
: return ["fail", 0]
: endif
: return ["ok", a:n1 / a:n2]
:endfunction
该函数这时可以这样调用: >
:let [success, div] = Compute(102, 6)
:if success == "ok"
: echo div
:endif
<
*:cal* *:call* *E107* *E117*
:[range]cal[l] {name}([arguments])
调用函数。函数名和参数通过 |:function| 指定。可以使用不超过 20
个参数。忽略返回值。
如果没有给出范围而函数又接受范围,该函数被调用一次。如果给出范
围,光标在执行函数前定位在该范围的第一行的开始。
如果给出范围但函数自己不能处理之,该函数在范围里的每一行分别执
行。光标定位在每个处理行的第一列。光标留在最后一行 (但可能被最
后一个函数调用移动)。每一行上,参数被重新计算。所以这是可以的:
*function-range-example* >
:function Mynumber(arg)
: echo line(".") . " " . a:arg
:endfunction
:1,5call Mynumber(getline("."))
<
"a:firstline" 和 "a:lastline" 总是有定义的。它们可以用来在范围
的开始或结束处进行一些不同的处理。
能处理范围本身的函数示例: >
:function Cont() range
: execute (a:firstline + 1) . "," . a:lastline . 's/^/\t\\ '
:endfunction
:4,8call Cont()
<
该函数在范围里的每行开头插入续行符 "\",除了第一行以外。
如果函数返回复合值,该值可被进一步解除参照 (译者注: 调用其上的
方法),但该范围不能被继续使用。例如: >
:4,8call GetDict().method()
< 这里 GetDict() 得到范围值,method() 不会。
*E132*
用户函数的递归调用受到 |'maxfuncdepth'| 选项的限制。
自 动 载 入 函 数 ~
*autoload-functions*
如果使用很多或者很大的函数,可以在需要使用它们的时候才自动提供其定义。有两个方
法: 用自动命令,还有用 'runtimepath' 里的 "autoload" 目录。
使用自动命令 ~
用户手册 |41.14| 一节有介绍。
自动命令可用于很长的 Vim 脚本的插件。你可以定义自动命令然后用 |:finish| 快速退
出脚本。这使得 Vim 启动快得多。这时,自动命令应该再次载入相同的文件,并设置变
量使得 |:finish| 命令被跳过。
使用 FuncUndefined 自动命令事件,它需要一个能匹配等待定义的函数的模式。例如: >
:au FuncUndefined BufNet* source ~/vim/bufnetfuncs.vim
文件 "~/vim/bufnetfuncs.vim" 这时应该定义 "BufNet" 开始的函数。另见
|FuncUndefined|。
使用 autoload 脚本 ~
*autoload* *E746*
用户手册 |41.15| 一节有介绍。
在 "autoload" 目录里定义脚本更简单,但需要使用准确的文件名。能够自动载入的函数
的名字形如: >
:call filename#funcname()
这样的函数如果调用时还没有定义,Vim 在 'runtimepath' 里的 "autoload" 目录搜索
脚本文件 "filename.vim"。例如 "~/.vim/autoload/filename.vim"。该文件这时应该这
样定义函数: >
function filename#funcname()
echo "Done!"
endfunction
文件名和函数的 # 之前的名字必须完全匹配,而定义的函数名也必须和调用时使用的形
式完全一致。
可以使用子目录。函数名每个 # 相当于路径分隔符。这样,调用函数: >
:call foo#bar#func()
的时候,Vim 寻找 'runtimepath' 里的文件 "autoload/foo/bar.vim"。
也适用于读取还没有设置的变量: >
:let l = foo#bar#lvar
不过,如果 autoload 脚本已经载入,不会为未知的变量再次载入该脚本。
给这样的变量赋值并没有什么特别。这可以用于在载入 autoload 脚本之前给它传递一些
设置: >
:let foo#bar#toggle = 1
:call foo#bar#func()
<
注意 如果你不小心调用了应该在 autoload 脚本里定义,但该脚本实际没有定义的函数
时,每次试图对该函数的调用都会重新载入一次脚本。从而每次都会得到错误信息。
还有,注意 如果你有两个脚本文件,不能在使用的函数定义之前同时从一个文件里调用
另一个文件里的函数并且从那个文件里调用这个文件的函数。
避免在顶层使用自动载入功能。
提示: 如果你发布很多脚本,可以用 |vimball| 工具把它们捆绑在一起。另请阅读用户
手册 |distribute-script|。
==============================================================================
6. 花括号名字 *curly-braces-names*
使用变量的任何地方可以改用 "花括号名字" 变量。和常规的变量名类似,但可以包含一
到多个花括号 {} 包围的表达式,形如: >
my_{adjective}_variable
如果 Vim 遇到这种情形,它会计算花括号内的表达式,把结果放在表达式所在的位置,
然后重新解释整个字符串为完整的变量名。所以在上例中,如果变量 "adjective" 设为
"noisy",那么引用的将是 "my_noisy_variable"。如果 "adjective" 设为 "quiet",那
么引用的将是 "my_quiet_variable"。
一个这种形式的应用是建立一系列变量,由一个选项管理。比如,语句 >
echo my_{&background}_message
会显示 "my_dark_message" 或者 "my_light_message" 的内容,取决于 'background'
的当前值。
你可以使用多个花括号对: >
echo my_{adverb}_{adjective}_message
..甚至嵌套使用: >
echo my_{ad{end_of_word}}_message
其中 "end_of_word" 可以是 "verb" 或者 "jective"。
不过,花括号里的表达式必须计算出合法的单个变量名,比如,这不行: >
:let foo='a + b'
:echo c{foo}d
.. 因为扩展的结果是 "ca + bd",这不是合法的变量名。
*curly-braces-function-names*
类似的,你可以调用和定义计算的出的函数名。比如: >
:let func_end='whizz'
:call my_func_{func_end}(parameter)
会调用函数 "my_func_whizz(parameter)"。
==============================================================================
7. 命令 *expression-commands*
:let {var-name} = {expr1} *:let* *E18*
设置内部变量 {var-name} 为表达式 {expr1} 的计算结果。
该变量也会得到 {expr} 的类型。如果 {var-name} 不存在,
它会被创立。
:let {var-name}[{idx}] = {expr1} *E689*
设置列表项目为表达式 {expr1} 的返回值。{var-name} 必须
引用列表而 {idx} 必须是该列表里合法的索引值。嵌套的列
表可以重复使用索引。
不能用于给列表 |List| 增加项目。
不能用来给字符串改变个别字节。为此你可以这么做: >
:let var = var[0:2] . 'X' . var[4:]
<
*E711* *E719*
:let {var-name}[{idx1}:{idx2}] = {expr1} *E708* *E709* *E710*
设置 |List| 的一系列项目为表达式 {expr1} 的返回值,后
者必须是正确数量项目的列表。
{idx1} 可以省略,这时以零代替。
{idx2} 可以省略,这时意味着到列表尾部。
如果选择的项目范围部分越过列表的尾部,会加入新的项目。
*:let+=* *:let-=* *:let.=* *E734*
:let {var} += {expr1} 类似于 ":let {var} = {var} + {expr1}"。
:let {var} -= {expr1} 类似于 ":let {var} = {var} - {expr1}"。
:let {var} .= {expr1} 类似于 ":let {var} = {var} . {expr1}"。
如果 {var} 还没有设置或者 {var} 和 {expr1} 的类型不符
合操作符的要求,失败。
:let ${env-name} = {expr1} *:let-environment* *:let-$*
设置环境变量 {env-name} 为表达式 {expr1} 的计算结果。
它总是字符串型。
:let ${env-name} .= {expr1}
把 {expr1} 附加到环境变量 {env-name} 之后。如果该环境
变量还不存在,相当于 "="。
:let @{reg-name} = {expr1} *:let-register* *:let-@*
把表达式 {expr1} 的计算结果写到寄存器 {reg-name} 里。
{reg-name} 必须是单个字符,而且是一个可以写入的寄存器
(见 |registers|)。"@@" 可以用来访问无名寄存器,而 "@/"
设置搜索模式。
如果 {expr1} 的结果以 <CR> 或 <NL> 结束,该寄存器会成
为面向行类型,不然,它会成为面向字符类型。
这可以用来清除最近的搜索模式: >
:let @/ = ""
< 这和搜索空字符串不同,后者会在任何地方得到匹配。
:let @{reg-name} .= {expr1}
把 {expr1} 附加到寄存器 {reg-name} 之后。如果寄存器为
空,相当于把它设为 {expr1} 的值。
:let &{option-name} = {expr1} *:let-option* *:let-&*
设置选项 {option-name} 为表达式 {expr1} 的计算结果。字
符串或数值类型的值总会被转化为选项需要的类型。
对于局部于窗口或者缓冲区的选项而言,这和 |:set| 命令的
效果相同: 局部值和全局值都被改变。
例如: >
:let &path = &path . ',/usr/local/include'
:let &{option-name} .= {expr1}
对字符串选项: 附加 {expr1} 到选项值之后。和 |:set+=|
不同,不会插入逗号。
:let &{option-name} += {expr1}
:let &{option-name} -= {expr1}
对数值或布尔选项: 加减 {expr1}。
:let &l:{option-name} = {expr1}
:let &l:{option-name} .= {expr1}
:let &l:{option-name} += {expr1}
:let &l:{option-name} -= {expr1}
同上,但只设置选项的局部值 (如果有的话)。和
|:setlocal| 类似。
:let &g:{option-name} = {expr1}
:let &g:{option-name} .= {expr1}
:let &g:{option-name} += {expr1}
:let &g:{option-name} -= {expr1}
同上,但只设置选项的全局值 (如果有的话)。和
|:setglobal| 类似。
:let [{name1}, {name2}, ...] = {expr1} *:let-unpack* *E687* *E688*
{expr1} 计算结果必须是 |List|。该列表的第一项赋给
{name1},第二项给 {name2},依此类推。
命名的数量必须匹配 |List| 项目的数量。
每个名字必须是上面提到的 ":let" 命令的项目之一。
例如: >
:let [s, item] = GetItem(s)
< 细节: 先计算 {expr1},然后按顺序依次进行赋值。如果
{name2} 依赖于 {name1},该细节就有关系。例如: >
:let x = [0, 1]
:let i = 0
:let [i, x[i]] = [1, 2]
:echo x
< 结果是 [0, 2]。
:let [{name1}, {name2}, ...] .= {expr1}
:let [{name1}, {name2}, ...] += {expr1}
:let [{name1}, {name2}, ...] -= {expr1}
同上,但附加/加/减值到每个 |List| 项目。
:let [{name}, ..., ; {lastname}] = {expr1}
类似于上面的 |:let-unpack|,但 |List| 可以包含比给出名
字的数量更多的项目。列表其余项目赋给 {lastname}。
如果没有余下的项目,{lastname} 设为空列表。
例如: >
:let [a, b; rest] = ["aval", "bval", 3, 4]
<
:let [{name}, ..., ; {lastname}] .= {expr1}
:let [{name}, ..., ; {lastname}] += {expr1}
:let [{name}, ..., ; {lastname}] -= {expr1}
同上,但附加/加/减值到每个 |List| 项目。
*E106*
:let {var-name} .. 列出变量 {var-name} 的值。可以给出多个变量的名字。这里
识别特殊的名字包括: *E738*
g: 全局变量
b: 缓冲区的局部变量
w: 窗口的局部变量
t: 标签页的局部变量
s: 脚本的局部变量
l: 函数的局部变量
v: Vim 变量。
:let 列出所有变量的值。变量的类型在值之前给出:
<空> 字符串
# 数值
* 函数引用
:unl[et][!] {name} ... *:unlet* *:unl* *E108* *E795*
删除内部变量 {var-name}。可以给出多个变量的名字。它们
都被删除。该名字也可以是 |List| 或 |Dictionary| 项目。
如果使用 [!],即使变量不存在也不会给出错误。
|List| 里可以删除一到多个项目: >
:unlet list[3] " remove fourth item
:unlet list[3:] " remove fourth item to last
< |Dictionary| 里一次只能删除一个项目: >
:unlet dict['two']
:unlet dict.two
< 这对于清除全局和脚本局部变量很有用 (脚本结束时并不自动
删除这些变量)。函数局部变量在函数结束时是自动清除的。
:lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv*
给内部变量 {name} 加锁。加锁意味着不能再修改该变量 (直
到它被解锁为止)。
加锁的变量可以删除: >
:lockvar v
:let v = 'asdf' " fails!
:unlet v
< *E741*
如果试图修改加锁的变量,你会得到错误信息: "E741: Value
of {name} is locked"
给 |List| 或 |Dictionary| 加锁时用到 [depth]。它决定加
锁到达的深度:
1 给 |List| 或 |Dictionary| 自身加锁。不
能增加或者删除项目,但你可以修改它们的
值。
2 给这些值加也锁,不能修改项目。如果项目
是 |List| 或 |Dictionary|,不能增加或
删除其中项目,但仍然可以修改项目值。
3 同 2,但又适用于 |List| / |Dictionary|
中的 |List| / |Dictionary| 项目,更深
一层。
缺省的 [depth] 为 2,{name} 是 |List| 或 |Dictionary|
时,不能修改项目值。
*E743*
要使用没有限制的深度,用 [!] 并省略 [depth]。不过,为
了捕获循环,设定最大深度为 100。
注意 如果两个变量引用同一个 |List| 而你锁住其中一个,
通过另一个变量来访问 |List| 也同时被锁住。
例如: >
:let l = [0, 1, 2, 3]
:let cl = l
:lockvar l
:let cl[1] = 99 " won't work!
< 为了避免这一点,可以给列表建立备份。见 |deepcopy()|。
:unlo[ckvar][!] [depth] {name} ... *:unlockvar* *:unlo*
给内部变量 {name} 解锁。和 |:lockvar| 刚好相反。
:if {expr1} *:if* *:endif* *:en* *E171* *E579* *E580*
:en[dif] 如果 {expr} 计算为非零,执行命令直到其后匹配的 ":else"
或者 ":endif" 为止。
从 Vim 版本 4.5 到 5.0,":if" 和 ":endif" 之间的 Ex 命
令被忽略。提供这两个命令只是为了后向兼容 (译者注,原文
如此),以方便未来的扩展。可以嵌套。注意 任何的 ":else"
或 ":elseif" 也被忽略,"else" 部分也一样不会执行。
利用这一点,你可以保持和旧版本的兼容: >
:if version >= 500
: 版本 5 专用的命令
:endif
< 为了找到 "endif",仍然需要分析命令。有时,旧版本的 Vim
不能识别新的命令。比如, ":silent" 被识别为
":substitute" 命令。这种情形可以用 ":execute" 来避
免: >
:if version >= 600
: execute "silent 1,$delete"
:endif
<
注意: ":append" 和 ":insert" 命令在 ":if" 和 ":endif"
之间不能正常工作。
*:else* *:el* *E581* *E583*
:el[se] 如果这之前的命令没有被执行,执行命令直到其后匹配的
":else" 或 ":endif"。
*:elseif* *:elsei* *E582* *E584*
:elsei[f] {expr1} ":else" ":if" 的缩写,而且无需另一个 ":endif"。
:wh[ile] {expr1} *:while* *:endwhile* *:wh* *:endw*
*E170* *E585* *E588* *E733*
:endw[hile] 只要 {expr1} 计算的结果非零,重复 ":while" 和
":endwhile" 之间的命令。
如果发现循环里有命令出错,从 "endwhile" 之后继续执行。
例如: >
:let lnum = 1
:while lnum <= line("$")
:call FixLine(lnum)
:let lnum = lnum + 1
:endwhile
<
注意: ":append" 和 ":insert" 命令在 ":while" 和 ":for"
循环里不能正常工作。
:for {var} in {list} *:for* *E690* *E732*
:endfo[r] *:endfo* *:endfor*
为每个 {list} 项目重复执行 ":for" 和 ":endfor" 之间的
命令。变量 {var} 设为每个项目的值。
如果循环里某个命令出错,从 "endfor" 之后继续执行。
在循环里修改 {list} 影响使用的项目。如果不希望如此,构
建一个备份: >
:for item in copy(mylist)
< 如果不备份,Vim 在为当前项目执行命令前保存列表里下一个
项目的引用。这样,删除当前项目不会影响循环的继续。而删
除任何后来的项目也会使循环跳过它。这意味着下例可以工作
(一个效率低下的清空列表的方法): >
for item in mylist
call remove(mylist, 0)
endfor
< 注意 给列表调整顺序 (例如用 sort() 或 reverse()) 可能
会有意想不到的效果。
注意 每个列表的类型必须完全相同,以免改变 {var} 类型时
产生的错误。不过,在循环体的尾部 unlet 变量就可以使用
多种项目类型: >
for item in ["foo", ["bar"]]
echo item
unlet item " 如果没有,会报错 E706
endfor
:for [{var1}, {var2}, ...] in {listlist}
:endfo[r]
和上面 ":for" 类似,但每个 {listlist} 项目必须是列表,
其中每个项目被依次赋予 {var1}、{var2} 等。例如: >
:for [lnum, col] in [[1, 3], [2, 5], [3, 8]]
:echo getline(lnum)[col]
:endfor
<
*:continue* *:con* *E586*
:con[tinue] 在 ":while" 或 ":for" 循环的内部,跳回循环开始的地方。
如果在循环内部的 |:try| 之后但在匹配的 |:finally| (如
果有的话) 之前,":finally" 之后,匹配的 |:endtry| 之前
的命令会被先执行。该过程反复应用于所有函数内的嵌套
":try" 块。在最外层 ":endtry" 结束之后才跳回循环的开始
处。
*:break* *:brea* *E587*
:brea[k] 在 ":while" 或 ":for" 循环的内部,跳到相匹配的
":endwhile" 或 ":endfor" 之后的命令。
如果在循环内部的 |:try| 之后但在匹配的 |:finally| (如
果有的话) 之前,":finally" 之后,匹配的 |:endtry| 之前
的命令会被先执行。该过程反复应用于所有函数内的嵌套
":try" 块。在最外层 ":endtry" 结束之后才跳到循环之后的
命令。
:try *:try* *:endt* *:endtry* *E600* *E601* *E602*
:endt[ry] 改变 ":try" 和 ":endtry" 之间命令的错误处理,包括所有
执行的内容,":source" 里的命令,函数调用,或者自动命令
的激活等。
如果检测到错误或者中断,而其后又跟随了 |:finally| 命
令,执行从 ":finally" 之后继续。否则,或者在那以后遇到
了 ":endtry",则检查是否存在 (动态的) 往外一层的
":try" 以及其相应的 ":finally" 等等。然后,脚本的处理
被终止。(函数定义里是否有 "abort" 参数都不相干。)
示例: >
:try | edit too much | finally | echo "cleanup" | endtry
:echo "impossible" " 到不了这里,脚本在上面已经终止
<
另外,":try" 和 ":endtry" 之间的错误或者中断 (动态地)
被转换成一个例外。它的捕获过程如同它被 |:throw| 命令抛
出那样 (见 |:catch|)。这种情况下,脚本的处理不会被终
止。
"Vim:Interrupt" 的值用于中断例外。Vim 命令的错误被转换
成形如 "Vim({command}):{errmsg}" 的值,其它错误被转换
成形如 "Vim:{errmsg}"。这里,{command} 是完整的命令
名,而 {errmsg} 是错误例外如果没有被捕获的时候会显示的
消息,它总以错误号开始。
示例: >
:try | sleep 100 | catch /^Vim:Interrupt$/ | endtry
:try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry
<
*:cat* *:catch* *E603* *E604* *E605*
:cat[ch] /{pattern}/ 匹配 {pattern} 的例外抛出时,如果它没有被前一个
":catch" 捕获,则执行本语句之后的命令,直到遇到和本
":catch" 处于同一 |:try| 块的下一个 |:catch|、
|:finally| 或者 |:endtry| 为止。否则,这些命令被跳过。
如果没有提供 {pattern},所有的错误都会被捕获。
示例: >
:catch /^Vim:Interrupt$/ " 捕获中断 (CTRL-C)
:catch /^Vim\%((\a\+)\)\=:E/ " 捕获所有的 Vim 错误
:catch /^Vim\%((\a\+)\)\=:/ " 捕获错误和中断
:catch /^Vim(write):/ " 捕获所有 :write 的错误
:catch /^Vim\%((\a\+)\)\=:E123/ " 捕获错误 E123
:catch /my-exception/ " 捕获用户例外
:catch /.*/ " 捕获一切
:catch " 等同于 /.*/
<
除了 / 以外,也可以用别的字符包围 {pattern},只要它没
有特殊含义 (比如 '|' 或 '"') 而且不出现在 {pattern}
里。
注意: 依赖 ":catch" 去捕获错误信息的_文本_是不可靠的,
因为不同的 locale 的信息可以不同。
*:fina* *:finally* *E606* *E607*
:fina[lly] 任何匹配的 |:try| 和本 ":finally" 之间的部分要离开的时
候都执行本语句之后的命令,直到遇到匹配的 |:endtry| 为
止。包括这些情形: 正常完成且要执行到 ":finally",通过
|:continue|、|:break|、|:finish| 或 |:return|,或者由
于错误或者中断或者例外 (见 |:throw|)。
*:th* *:throw* *E608*
:th[row] {expr1} 计算 {expr1} 然后抛出例外。如果 ":throw" 在 |:try| 之
后但在第一个对应的 |:catch| 之前使用,它之后的命令被跳
过,直到遇到第一个匹配 {expr1} 为止。如果没有这样的
":catch",或者如果 ":throw" 在 ":catch" 之后
|:finally| 之前使用,执行 ":finally" (如果有的话) 之后
直到匹配的 |:endtry| 为止的命令。如果本 ":throw" 在
":finally" 之后之后出现,直到 ":endtry" 为止的命令都被
跳过。到达 ":endtry" 的时候,在动态计算的往外一层的
":try" 块上再次重复本过程 (这可能出现在外层调用的函数
或者执行的脚本上),直到找到一个匹配的 ":catch"。如果最
终该例外没有被捕获,命令处理被终止。
示例: >
:try | throw "oops" | catch /^oo/ | echo "caught" | endtry
<
*:ec* *:echo*
:ec[ho] {expr1} .. 回显每个 {expr1},以空格分隔。第一个 {expr1} 开启一个
新行。另见 |:comment|。
使用 "\n" 来开启新行。使用 "\r" 把光标移到第一列。
使用 |:echohl| 命令的高亮设置。
后面不能跟注释。
示例: >
:echo "'shell' 的值是 " &shell
< *:echo-redraw*
后来的重画可能使消息再次消失。因为 Vim 常常会推迟重画
直到整个命令序列执行完为止,这个问题会频繁出现。要避免
":echo" 之前的命令引起它之后的重画 (通常,重画被延迟到
有输入的时候才进行),使用 |:redraw| 命令强制重画。例
如: >
:new | redraw | echo "这里有一个新窗口"
<
*:echon*
:echon {expr1} .. 回显每个 {expr1},不附加其它字符。另见 |:comment|。
使用 |:echohl| 命令的高亮设置。
后面不能跟注释。
例如: >
:echon "'shell' 的值是 " &shell
<
注意 两者的区别: ":echo" 是一个 Vim 命令,而 ":!echo"
是一个外部的外壳命令: >
:!echo % --> filename
< ":!" 的参数被扩展,见 |:_%|。 >
:!echo "%" --> filename or "filename"
< 和前例类似,你是否会看到双引号取决于你的 'shell'。 >
:echo % --> nothing
< '%' 不是一个表达式合法的字符。 >
:echo "%" --> %
< 只会回显 '%' 字符。 >
:echo expand("%") --> filename
< 调用 expand() 函数来扩展 '%'。
*:echoh* *:echohl*
:echoh[l] {name} 让其后的 |:echo|、|:echon| 和 |:echomsg| 命令使用高亮
组 {name}。也可用于 |input()| 的提示。示例: >
:echohl WarningMsg | echo "Don't panic!" | echohl None
< 不要忘记把组设回 "None"。不然其后的 echo 都会被高亮。
*:echom* *:echomsg*
:echom[sg] {expr1} .. 回显表达式的结果,将其作为一个真正的消息,并把该消息保
存在 |message-history| 里。
参数之间加入空格,和 |:echo| 类似。但不可显示的字符只
是回显而不会被解释。
这里的分析过程和 |:echo| 略有不同,而更像 |:execute|。
所有的表达式都先经计算后进行连接,然后再进行回显。
表达式必须返回数值或字符串,返回字典和列表会出错。
使用 |:echohl| 命令的高亮设置。
示例: >
:echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."
< |:echo-redraw| 说明如何避免屏幕重画时消息的消失问题。
*:echoe* *:echoerr*
:echoe[rr] {expr1} .. 回显表达式的结果,将其作为一个错误消息,并把该消息保
存在 |message-history| 里。如果用在脚本或函数里,会加
入行号。
参数之间加入空格,和 |:echo| 类似。如果在 try 条件句里
使用,该消息会抛出一个错误例外 (见 |try-echoerr|)。
示例: >
:echoerr "This script just failed!"
< 如果你只想要使用 |:echohl| 高亮的消息。
要得到铃声: >
:exe "normal \<Esc>"
<
*:exe* *:execute*
:exe[cute] {expr1} .. 计算 {expr1},返回的字符串作为 Ex 命令执行。
多个参数用空格连接。如果不想有额外的空格,使用 "." 操
作符来连接字符串使之成为一个参数。
{expr1} 用作被处理的命令,命令行编辑的键不会被识别。
后面不能跟注释。
示例: >
:execute "buffer" nextbuf
:execute "normal" count . "w"
<
":execute" 可以用来把命令附加到不能接受 '|' 的命令后
面。比如: >
:execute '!ls' | echo "theend"
< ":execute" 也是一个避免在 Vim 脚本里为 ":normal" 命令
输入控制字符的好方法: >
:execute "normal ixxx\<Esc>"
< 这里给出一个 <Esc> 字符,见 |expr-string|。
要谨慎对待文件名中特殊字符的正确转义。|fnameescape()|
可用于 Vim 命令,|shellescape()| 可用于 |:!| 命令。示
例: >
:execute "e " . fnameescape(filename)
:execute "!ls " . shellescape(expand('%:h'), 1)
<
注意: 执行的字符串可以是任何命令行,但不能开始或结束一
个 "while"、"for" 或 "if" 命令。所以,这样不行: >
:execute 'while i > 5'
:execute 'echo "test" | break'
<
但如果执行的字符串里有完整的 "while" 和 "if" 命令就没
有问题: >
:execute 'while i < 5 | echo i | let i = i + 1 | endwhile'
<
*:exe-comment*
":execute"、":echo" 和 ":echon" 后面不能直接跟注释。
因它们把 '"' 看成字符串的开始。但你可以把注释加到 '|'
后面。例如: >
:echo "foo" | "这是一个注释
==============================================================================
8. 例外处理 *exception-handling*
Vim 脚本语言包含了例外处理特性。本节解释如何在 Vim 脚本里应用该机制。
Vim 在出错或者中断的时候可以抛出例外。见 |catch-errors| 和 |catch-interrupt|。
你也可以显式地使用 ":throw" 命令抛出例外。见 |throw-catch|。
TRY 条 件 句 *try-conditionals*
例外可以被捕获或者用来激发清理代码的运行。你可以使用 try 条件句来指定 catch 子
句 (捕获例外) 和/或 finally 子句 (执行清理)。
try 条件句以 |:try| 命令开始,以匹配的 |:endtry| 命令结束。两者之间,你可以
使用 |:catch| 命令开始 catch 子句,或者用 |:finally| 命令开始 finally 子句。
catch 子句可有零到多个,但 finally 子句至多只有一个,且它之后不能再有 catch 子
句。catch 子句和 finally 子句之前的行称为 try 块。
:try
: ...
: ... TRY 块
: ...
:catch /{pattern}/
: ...
: ... CATCH 子 句
: ...
:catch /{pattern}/
: ...
: ... CATCH 子 句
: ...
:finally
: ...
: ... FINALLY 子 句
: ...
:endtry
try 子句允许观察代码里是否有例外,并采取合适的行动。try 块里的例外可能被捕获。
try 块和 catch 子句里的例外可能引起清理动作。
如果 try 块的执行过程中没有抛出例外,控制转移到 finally 子句。在它执行后,
脚本从 ":endtry" 之后的行继续。
如果 try 块的执行过程中抛出了例外,该 try 块其余的行被跳过。例外和 ":catch"
命令的模式参数一一比较。第一个匹配的 ":catch" 之后的 catch 子句被采用,其余的
catch 子句则不会执行。catch 子句在下一个最早遇到的 ":catch"、":finally" 或
":endtry" 命令结束。这时,finally 子句 (如果有的话) 被执行。当遇到 ":endtry"
的时候,脚本从后面的行继续,一如往常。
如果 try 块抛出的例外不能匹配任何 ":catch" 命令的模式,该例外不能由本 try
条件句捕获,因而不会执行任何的 catch 子句。只有 finally 子句,如果有的话,被采
用。该例外在 finally 子句的执行时被暂时搁置。在 ":endtry" 之后才继续。这样,
":endtry" 之后的命令不会被执行,而该例外可以在别的地方捕获,见 |try-nesting|。
如果在 catch 子句的执行过程中抛出了另一个错误,catch 子句的其余部分不再执
行。新的例外不会和试图和同一个 try 条件句的任何 ":catch" 命令的模式匹配,因而
也不会执行任何它的 catch 子句。不过,如果有 finally 子句,它还是会被执行,而在
它的执行过程中暂时搁置新的例外。":endtry" 之后的命令也不会执行。而新的例外仍可
能在别的地方捕获,见 |try-nesting|。
如果在 finally 子句 (如果有的话) 的执行过程中抛出了另一个错误,finally 子句
的其余部分不再执行。如果 finally 子句是因为 try 块或者某个 catch 子句里产生的
例外引起的,原先的 (被暂时搁置的) 例外被放弃。":endtry" 之后的命令也不会执行。
而 finally 子句的这个例外被传播,而可以在别的地方捕获,见 |try-nesting|。
在 ":while" 循环包含的完整的 try 条件句里的 try 块或者某个 catch 子句里遇到
":break" 或 ":continue" 时,或者在函数或者被执行的脚本里的 try 条件句里的 try
块或者某个 catch 子句里执行 ":return" (函数) 或者 ":finish" (脚本) 的时候,也
会执行 finally 子句。":break"、":continue"、":return" 或者 ":finish" 在
finally 子句的执行时被暂停,而在遇到 ":endtry" 时继续。不过,如果在执行
finally 子句时抛出例外,它们都被抛弃。
在 ":while" 循环包含的完整的 try 条件句里的 finally 子句里遇到 ":break" 或
":continue" 时,或者在函数或者被执行的脚本里的 finally 子句里执行 ":return" (
函数) 或者 ":finish" (脚本) 的时候,finally 子句的其余部分被跳过,而
":break"、":continue"、":return" 或 ":finish" 会如常继续执行。如果 finally 的
执行是因为例外或者早先的 try 块或者 catch 子句的 ":break"、":continue"、
":return" 或者 ":finish" 引起的,暂停的例外或者命令被放弃。
例子可见 |throw-catch| 和 |try-finally|。
TRY 条 件 句 的 嵌 套 *try-nesting*
try 条件句可以任意嵌套。也就是说,完整的 try 条件句可以在另一个 try 条件句的
try 块、某个 catch 子句或者 finally 子句里出现。如果内层的 try 条件句不能捕获
它的 try 块抛出的例外,或者在它的某个 catch 子句后者 finally 子句里抛出新的例
外的话,那么根据上述规则由外层的 try 条件句继续检查是否能捕获该例外。如果内层
try 条件句在外层 try 条件句的 try 块里,检查外层的 catch 子句,不然只有
finally 子句会被执行。对嵌套的处理而言,内层 try 条件句是直接包含在外层里面,
还是外层执行了脚本或者调用了函数,而后者又包含了内层 try 条件句,无关紧要。
如果没有活动的 try 条件句能捕获某个例外,只有它们的 finally 子句会执行。最后,
脚本结束它的处理。如果是 ":throw" 命令显式地抛出的未捕获的例外,显示错误信息。
对于 Vim 隐含抛出的未捕获的错误或者中断例外,错误信息或者中断信息也会像平常一
样显示。
例子可见 |throw-catch|。
检 查 例 外 处 理 代 码 *except-examine*
例外处理的代码的编写可能很麻烦。如果你不知道发生了什么,把 'verbose' 设为 13,
或者在执行脚本文件时使用 ":13verbose" 命令修饰符。这样,你能看到什么时候例外被
抛出、放弃、捕获、或者最终处理。如果详细程度大于等于 14,finally 子句暂停什么
也会显示。这些信息在调试模式里也会给出 (见 |debug-scripts|)。
抛 出 和 捕 获 例 外 *throw-catch*
你可以抛出任何数值或者字符串作为例外。使用 |:throw| 命令然后把要抛出的值作为参
数传入: >
:throw 4711
:throw "string"
< *throw-expression*
你可以指定表达式参数。该表达式先进行计算,然后抛出其结果: >
:throw 4705 + strlen("string")
:throw strpart("strings", 0, 6)
在计算 ":throw" 命令的参数的时候,也可能会抛出例外。除非它被捕获,不然表达式的
计算会被放弃。":throw" 命令这时不会抛出新的例外。
例如: >
:function! Foo(arg)
: try
: throw a:arg
: catch /foo/
: endtry
: return 1
:endfunction
:
:function! Bar()
: echo "in Bar"
: return 4710
:endfunction
:
:throw Foo("arrgh") + Bar()
这里抛出了 "arrgh",而不会显示 "in Bar",因为 Bar() 没有执行。 >
:throw Foo("foo") + Bar()
却显示 "in Bar" 并且抛出 4711。
别的接受表达式作为参数的命令也可能因为表达式计算过程的 (未捕获的) 例外而被放
弃。例外这时被传播给该命令的调用者。
例如: >
:if Foo("arrgh")
: echo "then"
:else
: echo "else"
:endif
这里 "then" 和 "else" 都不会显示。
*catch-order*
try 条件句里的例外可以用一个或多个 |:catch| 命令捕获,见 |try-conditionals|。
每个 ":catch" 命令可以捕获的值通过模式参数指定。捕获匹配的例外时,执行其后的
catch 子句。
例如: >
:function! Foo(value)
: try
: throw a:value
: catch /^\d\+$/
: echo "Number thrown"
: catch /.*/
: echo "String thrown"
: endtry
:endfunction
:
:call Foo(0x1267)
:call Foo('string')
第一个 Foo() 的调用显示 "Number thrown",第二个 "String thrown"。
按照 ":catch" 命令本身的顺序,依次匹配例外。只用第一个成功匹配。所以,你应该把
更专门的 ":catch" 放在前面。下面的顺序并不合理: >
: catch /.*/
: echo "String thrown"
: catch /^\d\+$/
: echo "Number thrown"
这里,第一个 ":catch" 总是会被匹配,所以第二个子句永远不可能被采用。
*throw-variables*
如果你使用通用的模式捕获到例外,可以通过变量 |v:exception| 得到准确的例外值: >
: catch /^\d\+$/
: echo "Number thrown. Value is" v:exception
你也许会对在什么地方抛出例外也感兴趣。它被保存在 |v:throwpoint| 里。注意
"v:exception" 和 "v:throwpoint" 可用于最近捕获的例外,只要该例外还没有完成处
理。
例如: >
:function! Caught()
: if v:exception != ""
: echo 'Caught "' . v:exception . '" in ' . v:throwpoint
: else
: echo 'Nothing caught'
: endif
:endfunction
:
:function! Foo()
: try
: try
: try
: throw 4711
: finally
: call Caught()
: endtry
: catch /.*/
: call Caught()
: throw "oops"
: endtry
: catch /.*/
: call Caught()
: finally
: call Caught()
: endtry
:endfunction
:
:call Foo()
会显示 >
Nothing caught
Caught "4711" in function Foo, line 4
Caught "oops" in function Foo, line 10
Nothing caught
更实际的例子: 下面的命令 ":LineNumber" 显示调用它时,脚本或者函数里的行号: >
:function! LineNumber()
: return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "")
:endfunction
:command! LineNumber try | throw "" | catch | echo LineNumber() | endtry
<
*try-nested*
try 条件句没有捕获的例外可以在包围它的 try 条件句中捕获: >
:try
: try
: throw "foo"
: catch /foobar/
: echo "foobar"
: finally
: echo "inner finally"
: endtry
:catch /foo/
: echo "foo"
:endtry
内层的 try 条件句没有捕获例外,只执行了 finally 子句。例外在外层得到捕获。本例
显示 "inner finally" 然后是 "foo"。
*throw-from-catch*
你可以捕获某例外,然后抛出另一个。它在该 catch 子句之外捕获: >
:function! Foo()
: throw "foo"
:endfunction
:
:function! Bar()
: try
: call Foo()
: catch /foo/
: echo "Caught foo, throw bar"
: throw "bar"
: endtry
:endfunction
:
:try
: call Bar()
:catch /.*/
: echo "Caught" v:exception
:endtry
显示 "Caught foo, throw bar" 然后是 "Caught bar"。
*rethrow*
Vim 脚本语言没有真正的 rethrow。但可以抛出 "v:exception" 来代替: >
:function! Bar()
: try
: call Foo()
: catch /.*/
: echo "Rethrow" v:exception
: throw v:exception
: endtry
:endfunction
< *try-echoerr*
注意 这个方法不能用来 "rethrow" Vim 错误或者中断例外,因为不能伪造 Vim 的内部
例外。试图这么做会产生一个错误例外。你应该抛出自己的例外来说明这种情形。如果你
想产生 Vim 的错误例外并包含原来的错误例外的值,可以使用 |:echoerr| 命令: >
:try
: try
: asdf
: catch /.*/
: echoerr v:exception
: endtry
:catch /.*/
: echo v:exception
:endtry
本代码会显示
Vim(echoerr):Vim:E492: Not an editor command: asdf ~
清 理 代 码 *try-finally*
脚本经常需要改变全局设定然后结束时恢复之。不过,如果用户按了 CTRL-C 中止脚本,
这些设定会处于不一致的状态。如果你处于某脚本的开发阶段而发生了错误或者你显式地
抛出例外而没有试图捕获之,也会有相同的情况。用带有 finally 子句的 try 条件句,
可以恢复设置,从而解决这个问题。可以保证无论是正常的控制流、出错或者显式的例外
":throw"、还是被中断,都会执行 finally 子句 (注意 try 条件句的错误和中断被转换
成例外。如果没有捕获,它们在 finally 子句执行完之后会终止脚本。)
例如: >
:try
: let s:saved_ts = &ts
: set ts=17
:
: " 这里执行重要的任务。
:
:finally
: let &ts = s:saved_ts
: unlet s:saved_ts
:endtry
无论任何函数还是脚本的一部分,只要它需要修改全局设置,而在失败或者成功退出该函
数或者脚本部分时需要恢复这些设置,就应该在本地应用本方法。
*break-finally*
清理代码也适用于 ":continue"、":break"、":return" 或 ":finish" 退出的 try 块或
catch 子句。
例如: >
:let first = 1
:while 1
: try
: if first
: echo "first"
: let first = 0
: continue
: else
: throw "second"
: endif
: catch /.*/
: echo v:exception
: break
: finally
: echo "cleanup"
: endtry
: echo "still in while"
:endwhile
:echo "end"
会显示 "first"、"cleanup"、"second"、"cleanup" 和 "end"。 >
:function! Foo()
: try
: return 4711
: finally
: echo "cleanup\n"
: endtry
: echo "Foo still active"
:endfunction
:
:echo Foo() "returned by Foo"
会显示 "cleanup" 和 "4711 returned by Foo"。你不需要在 finally 子句里加上附加
的 ":return"。(最终,它会覆盖原来的返回值。)
*except-from-finally*
finally 子句里可以使用 ":continue"、":break"、":return"、":finish" 或
":throw",但不推荐,因为它放弃了 try 条件句的清理工作。不过当然了,finally 子
句里仍然可能有中断或者错误例外。
finally 子句的错误引起中断不能正常工作的例子: >
:try
: try
: echo "Press CTRL-C for interrupt"
: while 1
: endwhile
: finally
: unlet novar
: endtry
:catch /novar/
:endtry
:echo "Script still running"
:sleep 1
如果你需要在 finally 里放入可能出错的命令,考虑捕获或者忽略这些命令的错误,见
|catch-errors| 和 |ignore-errors|。
捕 获 错 误 *catch-errors*
如果你想捕获特定的错误,你需要把要关注的代码放到 try 块里,然后为该错误消息加
入 catch 子句。try 条件句的存在使得所有的错误被转换为例外。不会显示消息,而
|v:errmsg| 也不会设置。要找到 ":catch" 命令右边的模式,你需要知道错误例外的格
式。
错误例外使用如下的格式: >
Vim({cmdname}):{errmsg}
或 >
Vim:{errmsg}
{cmdname} 是失败的命令名;第二种形式用于命令名未知的场合。{errmsg} 是错误在
try 条件句发生时,本应产生的错误消息。它总是以大写的 "E" 开始,后面跟两或者三
位的错误号,一个冒号和一个空格。
例如:
命令 >
:unlet novar
通常产生错误信息 >
E108: No such variable: "novar"
它在 try 条件句里被转换为例外 >
Vim(unlet):E108: No such variable: "novar"
命令 >
:dwim
通常产生错误信息 >
E492: Not an editor command: dwim
它在 try 条件句里被转换为例外 >
Vim:E492: Not an editor command: dwim
你可以这样捕获所有的 ":unlet" 错误 >
:catch /^Vim(unlet):/
或者这样捕获所有拼错命令名字的错误 >
:catch /^Vim:E492:/
有的错误信息可能由不同的命令产生: >
:function nofunc
和 >
:delfunction nofunc
都会产生错误信息 >
E128: Function name must start with a capital: nofunc
它在 try 条件句里被分别转换为例外 >
Vim(function):E128: Function name must start with a capital: nofunc
或 >
Vim(delfunction):E128: Function name must start with a capital: nofunc
使用下面的模式,你可以根据其号码捕获错误,而不管产生的命令是什么: >
:catch /^Vim(\a\+):E128:/
有些命令,比如 >
:let x = novar
产生多个错误信息,这里: >
E121: Undefined variable: novar
E15: Invalid expression: novar
只有第一个会用做例外的值,因为它是最专门的那个 (见 |except-several-errors|)。
所以你应该这样捕获它 >
:catch /^Vim(\a\+):E121:/
你可以这样捕获所有和名字 "nofunc" 相关的错误 >
:catch /\<nofunc\>/
你可以这样捕获 ":write" 和 ":read" 命令产生的所有 Vim 的错误 >
:catch /^Vim(\(write\|read\)):E\d\+:/
你可以这样捕获所有的 Vim 错误 >
:catch /^Vim\((\a\+)\)\=:E\d\+:/
<
*catch-text*
注意: 永远不要根据错误信息文本本身捕获错误: >
:catch /No such variable/
只适用于英语的 locale,如果用户用 |:language| 命令使用别的语言就不行了。不过,
在注释里引用该消息或许有帮助: >
:catch /^Vim(\a\+):E108:/ " No such variable
忽 略 错 误 *ignore-errors*
你可以通过在本地捕获来忽略某个 Vim 命令的错误: >
:try
: write
:catch
:endtry
但强烈建议,_不要_使用这种简单的形式,因为它捕获的东西超过你的想象。":write"
命令里,会执行一些自动命令,它们可能引起与写入无关的错误。例如: >
:au BufWritePre * unlet novar
作为脚本的作者,你不应该负责处理这些错误: 使用你书写的脚本的用户可能定义了这些
自动命令。而你这么做只会屏蔽用户自己的错误。
更好的方法是用 >
:try
: write
:catch /^Vim(write):/
:endtry
这样,只捕获真正的 write 错误。总之,只应该捕获你有意忽略的错误。
对于单个不会执行自动命令的命令,你可以用 ":silent!" 命令来关闭错误到例外的转
换: >
:silent! nunmap k
即使在活动的 try 条件句里也能这么用。
捕 获 中 断 *catch-interrupt*
如果有活动的 try 条件句,中断 (CTRL-C) 被转换为例外 "Vim:Interrupt"。你可以和
其他例外一样捕获它。那样,脚本就不会中止。
例如: >
:function! TASK1()
: sleep 10
:endfunction
:function! TASK2()
: sleep 20
:endfunction
:while 1
: let command = input("Type a command: ")
: try
: if command == ""
: continue
: elseif command == "END"
: break
: elseif command == "TASK1"
: call TASK1()
: elseif command == "TASK2"
: call TASK2()
: else
: echo "\nIllegal command:" command
: continue
: endif
: catch /^Vim:Interrupt$/
: echo "\nCommand interrupted"
: " Caught the interrupt. Continue with next prompt.
: endtry
:endwhile
这里,你可以用 CTRL-C 中止任务;脚本会询问新的命令。如果你在提示上按 CTRL-C,
脚本就会中止。
要测试在你脚本的某一行上如果按了 CTRL-C 会发生什么,使用调试模式,然后在那行上
执行 |>quit| 或 |>interrupt|。见 |debug-scripts|。
捕 获 一 切 *catch-all*
命令 >
:catch /.*/
:catch //
:catch
会捕获一切: 错误例外,中断例外和 |:throw| 命令显式抛出的例外。脚本的顶层可用此
捕获所有意料不到的问题。
示例: >
:try
:
: " 这里做重要的工作
:
:catch /MyException/
:
: " 处理未知的问题
:
:catch /^Vim:Interrupt$/
: echo "脚本被中断"
:catch /.*/
: echo "内部错误 (" . v:exception . ")"
: echo " - 发生在 " . v:throwpoint
:endtry
:" 脚本结束
<
注意: 捕获一切可能会捕获到比你想得到的更多的错误。所以,强烈建议你只用指定模式
参数的 ":catch" 来捕获你真正处理的错误。
例如: 捕获一切会使得按 CTRL-C 来中断脚本几乎没有办法: >
:while 1
: try
: sleep 1
: catch
: endtry
:endwhile
例 外 和 自 动 命 令 *except-autocmd*
执行自动命令的过程中可以使用例外。例如: >
:autocmd User x try
:autocmd User x throw "Oops!"
:autocmd User x catch
:autocmd User x echo v:exception
:autocmd User x endtry
:autocmd User x throw "Arrgh!"
:autocmd User x echo "Should not be displayed"
:
:try
: doautocmd User x
:catch
: echo v:exception
:endtry
会显示 "Oops!" 和 "Arrgh!"。
*except-autocmd-Pre*
有些命令里,自动命令在命令执行的主要动作之前执行。如果在自动命令的序列中抛
出没有捕获的例外,该序列和导致其执行的命令本身被放弃,而例外被传播到命令的调用
者那里。
例如: >
:autocmd BufWritePre * throw "FAIL"
:autocmd BufWritePre * echo "应该不会显示"
:
:try
: write
:catch
: echo "Caught:" v:exception "from" v:throwpoint
:endtry
这里,":write" 命令不会写入当前编辑的文件 (你可以通过查看 'modified' 发现)。因
为例外来自 BufWritePre 自动命令,它放弃了 ":write"。然后,该例外被捕获而脚本会
显示: >
Caught: FAIL from BufWrite Auto commands for "*"
<
*except-autocmd-Post*
有些命令里,自动命令在命令执行的主要动作之后执行。如果主要动作失败,而命令包含
在活动的 try 条件句里,将跳过这些自动命令并抛出错误例外,该命令的调用者可以捕
获这些例外。
例如: >
:autocmd BufWritePost * echo "文件被成功写入!"
:
:try
: write /i/m/p/o/s/s/i/b/l/e
:catch
: echo v:exception
:endtry
只会显示: >
Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e)
如果你真想在主要动作失败的时候也执行自动命令的话,在 catch 子句里激活自动命令
事件。
例如: >
:autocmd BufWritePre * set noreadonly
:autocmd BufWritePost * set readonly
:
:try
: write /i/m/p/o/s/s/i/b/l/e
:catch
: doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e
:endtry
<
你也可以用 ":silent!": >
:let x = "ok"
:let v:errmsg = ""
:autocmd BufWritePost * if v:errmsg != ""
:autocmd BufWritePost * let x = "after fail"
:autocmd BufWritePost * endif
:try
: silent! write /i/m/p/o/s/s/i/b/l/e
:catch
:endtry
:echo x
会显示 "after fail"。
如果命令的主要动作没有失败,可以在命令的调用者那里捕获自动命令产生的例外: >
:autocmd BufWritePost * throw ":-("
:autocmd BufWritePost * echo "这里不应该被显示"
:
:try
: write
:catch
: echo v:exception
:endtry
<
*except-autocmd-Cmd*
有的命令的正常动作可以被自动命令的序列代替。可以在命令的调用者那里捕获该序列产
生的例外。
例如: 对于 ":write" 命令,调用者并不知道发生例外时,文件是不是已经被写入。
你需要想办法告知调用者。 >
:if !exists("cnt")
: let cnt = 0
:
: autocmd BufWriteCmd * if &modified
: autocmd BufWriteCmd * let cnt = cnt + 1
: autocmd BufWriteCmd * if cnt % 3 == 2
: autocmd BufWriteCmd * throw "BufWriteCmdError"
: autocmd BufWriteCmd * endif
: autocmd BufWriteCmd * write | set nomodified
: autocmd BufWriteCmd * if cnt % 3 == 0
: autocmd BufWriteCmd * throw "BufWriteCmdError"
: autocmd BufWriteCmd * endif
: autocmd BufWriteCmd * echo "File successfully written!"
: autocmd BufWriteCmd * endif
:endif
:
:try
: write
:catch /^BufWriteCmdError$/
: if &modified
: echo "Error on writing (file contents not changed)"
: else
: echo "Error after writing"
: endif
:catch /^Vim(write):/
: echo "Error on writing"
:endtry
如果脚本在修改后执行了多次,它先显示 >
File successfully written!
然后 >
Error on writing (file contents not changed)
然后 >
Error after writing
等等。
*except-autocmd-ill*
你不能把一个 try 条件句分散到不同事件的自动命令。
下面的代码是非法的构造: >
:autocmd BufWritePre * try
:
:autocmd BufWritePost * catch
:autocmd BufWritePost * echo v:exception
:autocmd BufWritePost * endtry
:
:write
例 外 层 次 和 参 数 化 的 例 外 *except-hier-param*
有些编程语言支持使用例外类的层次结构,或者在例外类的对象里传入附加的信息。你可
以在 Vim 里完成类似的工作。
为了抛出属于某层次的例外,只要抛出完整的类名,部件之间用冒号分隔。比如,在
某个数学库里的溢出错误可以抛出字符串 "EXCEPT:MATHERR:OVERFLOW"。
如果你想给例外类传递附加的信息,把它加到括号里。比如写入文件 "myfile" 时的
错误,可以抛出字符串 "EXCEPT:IO:WRITEERR(myfile)"。
在 ":catch" 命令里使用合适的模式,可以捕获你的层次中的基本类或者派生类。括
号里的附加信息也可以运用 ":substitute" 命令从 |v:exception| 里切出。
例如: >
:function! CheckRange(a, func)
: if a:a < 0
: throw "EXCEPT:MATHERR:RANGE(" . a:func . ")"
: endif
:endfunction
:
:function! Add(a, b)
: call CheckRange(a:a, "Add")
: call CheckRange(a:b, "Add")
: let c = a:a + a:b
: if c < 0
: throw "EXCEPT:MATHERR:OVERFLOW"
: endif
: return c
:endfunction
:
:function! Div(a, b)
: call CheckRange(a:a, "Div")
: call CheckRange(a:b, "Div")
: if (a:b == 0)
: throw "EXCEPT:MATHERR:ZERODIV"
: endif
: return a:a / a:b
:endfunction
:
:function! Write(file)
: try
: execute "write" fnameescape(a:file)
: catch /^Vim(write):/
: throw "EXCEPT:IO(" . getcwd() . ", " . a:file . "):WRITEERR"
: endtry
:endfunction
:
:try
:
: " 一些算术和 I/O
:
:catch /^EXCEPT:MATHERR:RANGE/
: let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "")
: echo "Range error in" function
:
:catch /^EXCEPT:MATHERR/ " 捕获 OVERFLOW 和 ZERODIV
: echo "Math error"
:
:catch /^EXCEPT:IO/
: let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "")
: let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "")
: if file !~ '^/'
: let file = dir . "/" . file
: endif
: echo 'I/O error for "' . file . '"'
:
:catch /^EXCEPT/
: echo "Unspecified error"
:
:endtry
Vim 自己抛出的例外 (错误或者按了 CTRL-C) 使用扁平的层次: 它们都在 "Vim" 类里。
你自己不能抛出带有 "Vim" 前缀的例外;它们是 Vim 保留的。
如果已知失败的命令名,Vim 错误例外使用该命令名作为参数。见 |catch-errors|。
特 别 之 处
*except-compat*
例外处理的概念需要产生例外的命令序列被立即中止,而控制转移到 finally 子句和/或
catch 子句。
在 Vim 脚本语言里,有一些情况下脚本和函数在错误后还会继续: 在没有 "abort" 标志
位的函数或者 ":silent!" 之后的命令里,控制流转到下一行。而在函数外,控制流转到
最外层 ":endwhile" 或者 ":endif" 之后的行。另一方面,错误应该可以作为例外被捕
获 (因而,需要立即被中止)。
这个问题的解决方法是把仅在有活动 try 条件句的时候,把错误转化为例外,并立即中
止 (如果没有用 ":silent!" 抑制的话)。这不是一个限制,因为 (错误) 例外只能在活
动的 try 条件句里被捕获。如果你需要立即终止而不需要捕获错误的话,只要用一个没
有 catch 子句的 try 子句就可以了 (你可以用 finally 子句指定终止前执行的清理代
码。)
如果没有活动的 try 条件句,使用通常的中止和继续行为,而不是立即中止。这样,保
证了与 Vim 6.1 和之前版本编写的脚本的兼容性。
不过,如果在活动的 try 条件句里执行已有的不使用例外处理命令的脚本 (或者调用它
的一个函数),你也许会改变已有脚本发生错误时的控制流。你会在错误时立即中止并且
在新的脚本里捕获错误。如果被执行的脚本通过 ":silent!" 命令抑制了错误 (在合适的
时候测试 |v:errmsg| 来检查错误),它的执行路径没有改变。错误也不会转换为例外。
(见 |:silent|。) 所以唯一留下的可能是不关心错误并产生错误信息的脚本。可能,你
也不希望在新的脚本里使用这样的代码吧。
*except-syntax-err*
例外处理命令的语法错误永远不会被它所属的 try 条件句的任何 ":catch" 命令所捕
获。不过,还是会执行它的 finally 子句。
例如: >
:try
: try
: throw 4711
: catch /\(/ " 有语法错误
: echo "in catch with syntax error"
: catch
: echo "inner catch-all"
: finally
: echo "inner finally"
: endtry
:catch
: echo 'outer catch-all caught "' . v:exception . '"'
: finally
: echo "outer finally"
:endtry
会显示: >
inner finally
outer catch-all caught "Vim(catch):E54: Unmatched \("
outer finally
原来的例外被丢弃了,抛出的是取而代之的语法错误的错误例外。
*except-single-line*
":try"、":catch"、":finally" 和 ":endtry" 命令可以放在一行里,但这样如果有语法
错误,可能使得 "catch" 行无法被识别。所以,最好不要这么做。
例如: >
:try | unlet! foo # | catch | endtry
":unlet!" 参数之后的拖尾字符抛出了错误例外,但因此无法看到 ":catch" 和
":endtry" 命令,从而只能丢弃该错误例外并且显示消息 "E488: Trailing
characters"。
*except-several-errors*
如果多个错误在一个命令里出现,第一个错误信息通常是最专门的,因而它被转换为错误
例外。
例如: >
echo novar
产生 >
E121: Undefined variable: novar
E15: Invalid expression: novar
try 条件句里错误例外的值是: >
Vim(echo):E121: Undefined variable: novar
< *except-syntax-error*
不过,如果同一命令在普通错误之后发现了语法错误,语法错误被用作抛出的例外。
例如: >
unlet novar #
产生 >
E108: No such variable: "novar"
E488: Trailing characters
try 条件句里错误例外的值是: >
Vim(unlet):E488: Trailing characters
这么做是因为语法错误可能会以用户意想不到的方式改变执行的路径。例如: >
try
try | unlet novar # | catch | echo v:exception | endtry
catch /.*/
echo "outer catch:" v:exception
endtry
显示 "outer catch: Vim(unlet):E488: Trailing characters",然后给出错误信息
"E600: Missing :endtry",见 |except-single-line|。
==============================================================================
9. 示例 *eval-examples*
用二进制显示 ~
>
:" 函数 Nr2Bin() 返回数值的二进制字符串。
:func Nr2Bin(nr)
: let n = a:nr
: let r = ""
: while n
: let r = '01'[n % 2] . r
: let n = n / 2
: endwhile
: return r
:endfunc
:" 函数 String2Hex() 把字符串里的每个字符转换成二进制字符串,用连字符分隔字
:" 符。
:func String2Bin(str)
: let out = ''
: for ix in range(strlen(a:str))
: let out = out . '-' . Nr2Bin(char2nr(a:str[ix]))
: endfor
: return out[1:]
:endfunc
使用示例: >
:echo Nr2Bin(32)
返回: "100000" >
:echo String2Bin("32")
返回: "110011-110010"
给行排序 ~
下例用特定比较函数给行排序。 >
:func SortBuffer()
: let lines = getline(1, '$')
: call sort(lines, function("Strcmp"))
: call setline(1, lines)
:endfunction
可写为一行程序: >
:call setline(1, sort(getline(1, '$'), function("Strcmp")))
scanf() 的替代 ~
*sscanf*
Vim 里没有 sscanf() 函数。如果你需要提取一行的部分内容,可以使用 matchstr() 和
substitute() 完成。本例子说明如何得到从类似 "foobar.txt, 123, 45" 的行里提取文
件名,行号和列号。 >
:" 设置匹配模式
:let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)'
:"取得匹配整个表达式的文本部分
:let l = matchstr(line, mx)
:"从匹配中提取每个项目
:let file = substitute(l, mx, '\1', '')
:let lnum = substitute(l, mx, '\2', '')
:let col = substitute(l, mx, '\3', '')
这里,输入是变量 "line",返回值放在变量 "file"、"lnum" 和 "col" 里。(Michael
Geddes 提供的方法)
输出 scriptnames 到字典 ~
*scriptnames-dictionary*
|:scriptnames| 命令可用于得到执行过的所有脚本文件的列表。没有等价的函数或变量
(因为很少用到)。如果需要操作此列表,可以使用下面的代码: >
" 把 ":scriptnames" 的输出存放到 scriptnames_output 变量中。
let scriptnames_output = ''
redir => scriptnames_output
silent scriptnames
redir END
" 把输出分拆为行,并对每行进行分析。在 "script" 字典中加入项目。
let scripts = {}
for line in split(scriptnames_output, "\n")
" 只处理非空白行。
if line =~ '\S'
" 获取每行的第一个数字。
let nr = matchstr(line, '\d\+')
" 获取文件名,删除脚本号 " 123: "。
let name = substitute(line, '.\+:\s*', '', '')
" 在字典中加入项目
let scripts[nr] = name
endif
endfor
unlet scriptnames_output
==============================================================================
10. 不包含 +eval 特性 *no-eval-feature*
如果编译时关闭了 |+eval| 特性,以上的表达式计算命令都不可用。为了避免因此导致
你的 Vim 脚本产生各种错误,":if" 和 ":endif" 命令仍然得到识别。不过 ":if" 的参
数和一切 ":if" 和匹配的 ":endif" 之间的内容都被忽略。可以嵌套 ":if" 块,但只
允许出现在行首。不识别 ":else" 命令。
下例演示如何在不存在 |+eval| 特性时不执行命令: >
:if 1
: echo "编译加入了表达式求值"
:else
: echo "你_永远_看不到这条消息"
:endif
==============================================================================
11. 沙盘 (sandbox) *eval-sandbox* *sandbox* *E48*
'foldexpr'、'formatexpr'、'includeexpr'、'indentexpr'、'statusline' 和
'foldtext' 选项在沙盘 (sandbox) 里进行计算。这意味着这些表达式不会产生可怕的副
作用。在模式行上设置这些选项时,以及在标签文件里和命令行上的 CTRL-R = 执行命令
时,这项措施提供了一定的安全性。
沙盘也用于 |:sandbox| 命令。
沙盘里,不允许以下操作:
- 修改缓冲区文本
- 定义或者改变映射、自动命令、函数和用户命令
- 设置若干选项 (见 |option-summary|)
- 设置若干 v: 变量 (见 |v:var|) *E794*
- 执行外壳命令
- 读入或者写到文件
- 跳转到另一缓冲区或者去编辑文件
- 执行 Python、Perl 等命令
这并不能保证 100% 安全,但应该可以挡住大多数攻击。
*:san* *:sandbox*
:san[dbox] {cmd} 在沙盘里执行 {cmd}。用于计算可能在模式行里设置的选项,
比如 'foldexpr'。
*sandbox-option*
一些选项包含表达式。对这些表达式进行计算时可能要使用沙盘才能避免安全性的威胁。
但沙盘限制较多,所以只有在从不安全的位置设置选项时才会如此。在此上下文中,不安
全的位置指:
- 执行当前目录的 .vimrc 或 .exrc 时
- 在沙盘里执行时
- 来自模式行的值
注意 如果在沙盘里保存选项值然后恢复之,该选项仍然标记为在沙盘里设置。
==============================================================================
12. 文本锁 *textlock*
在一些情况下,不允许修改缓冲区里的文本、跳转到其它窗口和一些其它会引起混淆或打
断 Vim 正在进行的操作的动作。这主要适用于和 Vim 实际正在进行其它操作的同时发生
的事情。例如,'balloonexpr' 的计算可能发生在鼠标指针定位在若干位置的任何时候。
文本锁激活时,不允许:
- 修改缓冲区文本
- 跳转到其它缓冲区或窗口
- 编辑其它文件
- 关闭窗口或者退出 Vim
- 其它
vim:tw=78:ts=8:ft=help:norl: