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)