Mercurial > vim
comparison src/ex_cmds.c @ 7689:20dc2763a3b9 v7.4.1143
commit https://github.com/vim/vim/commit/f7edf40448a09e04eec3bd05e043f7fea93b07c9
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Jan 19 23:36:15 2016 +0100
patch 7.4.1143
Problem: Can't sort on floating point numbers.
Solution: Add the "f" flag to ":sort". (Alex Jakushev) Also add the "f"
flag to sort().
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 19 Jan 2016 23:45:05 +0100 |
parents | 1fded31d9e04 |
children | fd4175b669e2 |
comparison
equal
deleted
inserted
replaced
7688:f56cebad5ba2 | 7689:20dc2763a3b9 |
---|---|
273 /* Buffer for two lines used during sorting. They are allocated to | 273 /* Buffer for two lines used during sorting. They are allocated to |
274 * contain the longest line being sorted. */ | 274 * contain the longest line being sorted. */ |
275 static char_u *sortbuf1; | 275 static char_u *sortbuf1; |
276 static char_u *sortbuf2; | 276 static char_u *sortbuf2; |
277 | 277 |
278 static int sort_ic; /* ignore case */ | 278 static int sort_ic; /* ignore case */ |
279 static int sort_nr; /* sort on number */ | 279 static int sort_nr; /* sort on number */ |
280 static int sort_rx; /* sort on regex instead of skipping it */ | 280 static int sort_rx; /* sort on regex instead of skipping it */ |
281 | 281 #ifdef FEAT_FLOAT |
282 static int sort_abort; /* flag to indicate if sorting has been interrupted */ | 282 static int sort_flt; /* sort on floating number */ |
283 #endif | |
284 | |
285 static int sort_abort; /* flag to indicate if sorting has been interrupted */ | |
283 | 286 |
284 /* Struct to store info to be sorted. */ | 287 /* Struct to store info to be sorted. */ |
285 typedef struct | 288 typedef struct |
286 { | 289 { |
287 linenr_T lnum; /* line number */ | 290 linenr_T lnum; /* line number */ |
288 long start_col_nr; /* starting column number or number */ | 291 union { |
289 long end_col_nr; /* ending column number */ | 292 struct |
293 { | |
294 long start_col_nr; /* starting column number */ | |
295 long end_col_nr; /* ending column number */ | |
296 } line; | |
297 long value; /* value if sorting by integer */ | |
298 #ifdef FEAT_FLOAT | |
299 float_T value_flt; /* value if sorting by float */ | |
300 #endif | |
301 } st_u; | |
290 } sorti_T; | 302 } sorti_T; |
291 | 303 |
292 static int | 304 static int |
293 #ifdef __BORLANDC__ | 305 #ifdef __BORLANDC__ |
294 _RTLENTRYF | 306 _RTLENTRYF |
317 sort_abort = TRUE; | 329 sort_abort = TRUE; |
318 | 330 |
319 /* When sorting numbers "start_col_nr" is the number, not the column | 331 /* When sorting numbers "start_col_nr" is the number, not the column |
320 * number. */ | 332 * number. */ |
321 if (sort_nr) | 333 if (sort_nr) |
322 result = l1.start_col_nr == l2.start_col_nr ? 0 | 334 result = l1.st_u.value == l2.st_u.value ? 0 |
323 : l1.start_col_nr > l2.start_col_nr ? 1 : -1; | 335 : l1.st_u.value > l2.st_u.value ? 1 : -1; |
336 #ifdef FEAT_FLOAT | |
337 else if (sort_flt) | |
338 result = l1.st_u.value_flt == l2.st_u.value_flt ? 0 | |
339 : l1.st_u.value_flt > l2.st_u.value_flt ? 1 : -1; | |
340 #endif | |
324 else | 341 else |
325 { | 342 { |
326 /* We need to copy one line into "sortbuf1", because there is no | 343 /* We need to copy one line into "sortbuf1", because there is no |
327 * guarantee that the first pointer becomes invalid when obtaining the | 344 * guarantee that the first pointer becomes invalid when obtaining the |
328 * second one. */ | 345 * second one. */ |
329 STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.start_col_nr, | 346 STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr, |
330 l1.end_col_nr - l1.start_col_nr + 1); | 347 l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1); |
331 sortbuf1[l1.end_col_nr - l1.start_col_nr] = 0; | 348 sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0; |
332 STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.start_col_nr, | 349 STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr, |
333 l2.end_col_nr - l2.start_col_nr + 1); | 350 l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1); |
334 sortbuf2[l2.end_col_nr - l2.start_col_nr] = 0; | 351 sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0; |
335 | 352 |
336 result = sort_ic ? STRICMP(sortbuf1, sortbuf2) | 353 result = sort_ic ? STRICMP(sortbuf1, sortbuf2) |
337 : STRCMP(sortbuf1, sortbuf2); | 354 : STRCMP(sortbuf1, sortbuf2); |
338 } | 355 } |
339 | 356 |
380 nrs = (sorti_T *)lalloc((long_u)(count * sizeof(sorti_T)), TRUE); | 397 nrs = (sorti_T *)lalloc((long_u)(count * sizeof(sorti_T)), TRUE); |
381 if (nrs == NULL) | 398 if (nrs == NULL) |
382 goto sortend; | 399 goto sortend; |
383 | 400 |
384 sort_abort = sort_ic = sort_rx = sort_nr = 0; | 401 sort_abort = sort_ic = sort_rx = sort_nr = 0; |
402 #ifdef FEAT_FLOAT | |
403 sort_flt = 0; | |
404 #endif | |
385 | 405 |
386 for (p = eap->arg; *p != NUL; ++p) | 406 for (p = eap->arg; *p != NUL; ++p) |
387 { | 407 { |
388 if (vim_iswhite(*p)) | 408 if (vim_iswhite(*p)) |
389 ; | 409 ; |
391 sort_ic = TRUE; | 411 sort_ic = TRUE; |
392 else if (*p == 'r') | 412 else if (*p == 'r') |
393 sort_rx = TRUE; | 413 sort_rx = TRUE; |
394 else if (*p == 'n') | 414 else if (*p == 'n') |
395 { | 415 { |
396 sort_nr = 2; | 416 sort_nr = 1; |
397 ++format_found; | 417 ++format_found; |
398 } | 418 } |
419 #ifdef FEAT_FLOAT | |
420 else if (*p == 'f') | |
421 { | |
422 sort_flt = 1; | |
423 ++format_found; | |
424 } | |
425 #endif | |
399 else if (*p == 'b') | 426 else if (*p == 'b') |
400 { | 427 { |
401 sort_what = STR2NR_BIN + STR2NR_FORCE; | 428 sort_what = STR2NR_BIN + STR2NR_FORCE; |
402 ++format_found; | 429 ++format_found; |
403 } | 430 } |
458 { | 485 { |
459 EMSG(_(e_invarg)); | 486 EMSG(_(e_invarg)); |
460 goto sortend; | 487 goto sortend; |
461 } | 488 } |
462 | 489 |
463 /* From here on "sort_nr" is used as a flag for any number sorting. */ | 490 /* From here on "sort_nr" is used as a flag for any integer number |
491 * sorting. */ | |
464 sort_nr += sort_what; | 492 sort_nr += sort_what; |
465 | 493 |
466 /* | 494 /* |
467 * Make an array with all line numbers. This avoids having to copy all | 495 * Make an array with all line numbers. This avoids having to copy all |
468 * the lines into allocated memory. | 496 * the lines into allocated memory. |
492 } | 520 } |
493 else | 521 else |
494 if (regmatch.regprog != NULL) | 522 if (regmatch.regprog != NULL) |
495 end_col = 0; | 523 end_col = 0; |
496 | 524 |
497 if (sort_nr) | 525 if (sort_nr || sort_flt) |
498 { | 526 { |
499 /* Make sure vim_str2nr doesn't read any digits past the end | 527 /* Make sure vim_str2nr doesn't read any digits past the end |
500 * of the match, by temporarily terminating the string there */ | 528 * of the match, by temporarily terminating the string there */ |
501 s2 = s + end_col; | 529 s2 = s + end_col; |
502 c = *s2; | 530 c = *s2; |
503 *s2 = NUL; | 531 *s2 = NUL; |
504 /* Sorting on number: Store the number itself. */ | 532 /* Sorting on number: Store the number itself. */ |
505 p = s + start_col; | 533 p = s + start_col; |
506 if (sort_what & STR2NR_HEX) | 534 if (sort_nr) |
507 s = skiptohex(p); | 535 { |
508 else if (sort_what & STR2NR_BIN) | 536 if (sort_what & STR2NR_HEX) |
509 s = skiptobin(p); | 537 s = skiptohex(p); |
538 else if (sort_what & STR2NR_BIN) | |
539 s = skiptobin(p); | |
540 else | |
541 s = skiptodigit(p); | |
542 if (s > p && s[-1] == '-') | |
543 --s; /* include preceding negative sign */ | |
544 if (*s == NUL) | |
545 /* empty line should sort before any number */ | |
546 nrs[lnum - eap->line1].st_u.value = -MAXLNUM; | |
547 else | |
548 vim_str2nr(s, NULL, NULL, sort_what, | |
549 &nrs[lnum - eap->line1].st_u.value, NULL, 0); | |
550 } | |
551 #ifdef FEAT_FLOAT | |
510 else | 552 else |
511 s = skiptodigit(p); | 553 { |
512 if (s > p && s[-1] == '-') | 554 s = skipwhite(p); |
513 --s; /* include preceding negative sign */ | 555 if (*s == '+') |
514 if (*s == NUL) | 556 s = skipwhite(s + 1); |
515 /* empty line should sort before any number */ | 557 |
516 nrs[lnum - eap->line1].start_col_nr = -MAXLNUM; | 558 if (*s == NUL) |
517 else | 559 /* empty line should sort before any number */ |
518 vim_str2nr(s, NULL, NULL, sort_what, | 560 nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX; |
519 &nrs[lnum - eap->line1].start_col_nr, NULL, 0); | 561 else |
562 nrs[lnum - eap->line1].st_u.value_flt = | |
563 strtod((char *)s, NULL); | |
564 } | |
565 #endif | |
520 *s2 = c; | 566 *s2 = c; |
521 } | 567 } |
522 else | 568 else |
523 { | 569 { |
524 /* Store the column to sort at. */ | 570 /* Store the column to sort at. */ |
525 nrs[lnum - eap->line1].start_col_nr = start_col; | 571 nrs[lnum - eap->line1].st_u.line.start_col_nr = start_col; |
526 nrs[lnum - eap->line1].end_col_nr = end_col; | 572 nrs[lnum - eap->line1].st_u.line.end_col_nr = end_col; |
527 } | 573 } |
528 | 574 |
529 nrs[lnum - eap->line1].lnum = lnum; | 575 nrs[lnum - eap->line1].lnum = lnum; |
530 | 576 |
531 if (regmatch.regprog != NULL) | 577 if (regmatch.regprog != NULL) |