diff 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
line wrap: on
line diff
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -275,18 +275,30 @@ linelen(has_tab)
 static char_u	*sortbuf1;
 static char_u	*sortbuf2;
 
-static int	sort_ic;		/* ignore case */
-static int	sort_nr;		/* sort on number */
-static int	sort_rx;		/* sort on regex instead of skipping it */
-
-static int	sort_abort;		/* flag to indicate if sorting has been interrupted */
+static int	sort_ic;	/* ignore case */
+static int	sort_nr;	/* sort on number */
+static int	sort_rx;	/* sort on regex instead of skipping it */
+#ifdef FEAT_FLOAT
+static int	sort_flt;	/* sort on floating number */
+#endif
+
+static int	sort_abort;	/* flag to indicate if sorting has been interrupted */
 
 /* Struct to store info to be sorted. */
 typedef struct
 {
     linenr_T	lnum;			/* line number */
-    long	start_col_nr;		/* starting column number or number */
-    long	end_col_nr;		/* ending column number */
+    union {
+	struct
+	{
+	    long	start_col_nr;		/* starting column number */
+	    long	end_col_nr;		/* ending column number */
+	} line;
+	long	value;		/* value if sorting by integer */
+#ifdef FEAT_FLOAT
+	float_T value_flt;	/* value if sorting by float */
+#endif
+    } st_u;
 } sorti_T;
 
 static int
@@ -319,19 +331,24 @@ sort_compare(s1, s2)
     /* When sorting numbers "start_col_nr" is the number, not the column
      * number. */
     if (sort_nr)
-	result = l1.start_col_nr == l2.start_col_nr ? 0
-				 : l1.start_col_nr > l2.start_col_nr ? 1 : -1;
+	result = l1.st_u.value == l2.st_u.value ? 0
+				 : l1.st_u.value > l2.st_u.value ? 1 : -1;
+#ifdef FEAT_FLOAT
+    else if (sort_flt)
+	result = l1.st_u.value_flt == l2.st_u.value_flt ? 0
+			     : l1.st_u.value_flt > l2.st_u.value_flt ? 1 : -1;
+#endif
     else
     {
 	/* We need to copy one line into "sortbuf1", because there is no
 	 * guarantee that the first pointer becomes invalid when obtaining the
 	 * second one. */
-	STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.start_col_nr,
-					 l1.end_col_nr - l1.start_col_nr + 1);
-	sortbuf1[l1.end_col_nr - l1.start_col_nr] = 0;
-	STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.start_col_nr,
-					 l2.end_col_nr - l2.start_col_nr + 1);
-	sortbuf2[l2.end_col_nr - l2.start_col_nr] = 0;
+	STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr,
+		     l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1);
+	sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0;
+	STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr,
+		     l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1);
+	sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0;
 
 	result = sort_ic ? STRICMP(sortbuf1, sortbuf2)
 						 : STRCMP(sortbuf1, sortbuf2);
@@ -382,6 +399,9 @@ ex_sort(eap)
 	goto sortend;
 
     sort_abort = sort_ic = sort_rx = sort_nr = 0;
+#ifdef FEAT_FLOAT
+    sort_flt = 0;
+#endif
 
     for (p = eap->arg; *p != NUL; ++p)
     {
@@ -393,9 +413,16 @@ ex_sort(eap)
 	    sort_rx = TRUE;
 	else if (*p == 'n')
 	{
-	    sort_nr = 2;
+	    sort_nr = 1;
 	    ++format_found;
 	}
+#ifdef FEAT_FLOAT
+	else if (*p == 'f')
+	{
+	    sort_flt = 1;
+	    ++format_found;
+	}
+#endif
 	else if (*p == 'b')
 	{
 	    sort_what = STR2NR_BIN + STR2NR_FORCE;
@@ -460,7 +487,8 @@ ex_sort(eap)
 	goto sortend;
     }
 
-    /* From here on "sort_nr" is used as a flag for any number sorting. */
+    /* From here on "sort_nr" is used as a flag for any integer number
+     * sorting. */
     sort_nr += sort_what;
 
     /*
@@ -494,7 +522,7 @@ ex_sort(eap)
 	    if (regmatch.regprog != NULL)
 		end_col = 0;
 
-	if (sort_nr)
+	if (sort_nr || sort_flt)
 	{
 	    /* Make sure vim_str2nr doesn't read any digits past the end
 	     * of the match, by temporarily terminating the string there */
@@ -503,27 +531,45 @@ ex_sort(eap)
 	    *s2 = NUL;
 	    /* Sorting on number: Store the number itself. */
 	    p = s + start_col;
-	    if (sort_what & STR2NR_HEX)
-		s = skiptohex(p);
-	    else if (sort_what & STR2NR_BIN)
-		s = skiptobin(p);
+	    if (sort_nr)
+	    {
+		if (sort_what & STR2NR_HEX)
+		    s = skiptohex(p);
+		else if (sort_what & STR2NR_BIN)
+		    s = skiptobin(p);
+		else
+		    s = skiptodigit(p);
+		if (s > p && s[-1] == '-')
+		    --s;  /* include preceding negative sign */
+		if (*s == NUL)
+		    /* empty line should sort before any number */
+		    nrs[lnum - eap->line1].st_u.value = -MAXLNUM;
+		else
+		    vim_str2nr(s, NULL, NULL, sort_what,
+			       &nrs[lnum - eap->line1].st_u.value, NULL, 0);
+	    }
+#ifdef FEAT_FLOAT
 	    else
-		s = skiptodigit(p);
-	    if (s > p && s[-1] == '-')
-		--s;  /* include preceding negative sign */
-	    if (*s == NUL)
-		/* empty line should sort before any number */
-		nrs[lnum - eap->line1].start_col_nr = -MAXLNUM;
-	    else
-		vim_str2nr(s, NULL, NULL, sort_what,
-			       &nrs[lnum - eap->line1].start_col_nr, NULL, 0);
+	    {
+		s = skipwhite(p);
+		if (*s == '+')
+		    s = skipwhite(s + 1);
+
+		if (*s == NUL)
+		    /* empty line should sort before any number */
+		    nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX;
+		else
+		    nrs[lnum - eap->line1].st_u.value_flt =
+						      strtod((char *)s, NULL);
+	    }
+#endif
 	    *s2 = c;
 	}
 	else
 	{
 	    /* Store the column to sort at. */
-	    nrs[lnum - eap->line1].start_col_nr = start_col;
-	    nrs[lnum - eap->line1].end_col_nr = end_col;
+	    nrs[lnum - eap->line1].st_u.line.start_col_nr = start_col;
+	    nrs[lnum - eap->line1].st_u.line.end_col_nr = end_col;
 	}
 
 	nrs[lnum - eap->line1].lnum = lnum;