Home Download Buy Blog Forum Support

Sort lines numeric

Sort lines numeric

Postby nick. on Mon May 14, 2012 4:25 pm

Am I just not seeing this?
nick.
 
Posts: 266
Joined: Wed Jan 18, 2012 3:45 am

Re: Sort lines numeric

Postby C0D312 on Tue May 15, 2012 7:31 pm

Do you mean alphabetically?
C0D312
 
Posts: 1063
Joined: Sun Jul 10, 2011 3:23 am

Re: Sort lines numeric

Postby nick. on Tue May 15, 2012 7:45 pm

No... I mean numerically.

Given:
Code: Select all
100
20
2
10
5
1


Sublime sorts to the following:
Code: Select all
1
10
100
2
20
5


I expect (or want an option for):
Code: Select all
1
2
5
10
20
100
nick.
 
Posts: 266
Joined: Wed Jan 18, 2012 3:45 am

Re: Sort lines numeric

Postby qwertyuiop on Wed May 16, 2012 7:28 am

Coming from Notepad2, I couldn't find this feature as well.

In Notepad2, there's a sort dialog that implements this option with "Logical number comparison". Here's a screenshot: Image
qwertyuiop
 
Posts: 2
Joined: Wed May 16, 2012 7:21 am

Re: Sort lines numeric

Postby nick. on Fri Aug 03, 2012 4:49 pm

Implemented this today. Code is near verbatim from this StackOverflow answer .

Modifying the default sort.py means changes will be lost on upgrade. Maybe Jon will include this in a future build. ;)

Open /Packages/Default/sort.py . Add an import:
Code: Select all
import re


Then look for the case_insensitive_sort and case_sensitive_sort functions, and modify them to convert to int's when necessary:
Code: Select all
def case_insensitive_sort(txt):
#   txt.sort(lambda a, b: cmp(a.lower(), b.lower()))
#   return txt
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9.,]+)', key) ]
    return sorted(txt, key=alphanum_key)

def case_sensitive_sort(txt):
#   txt.sort(lambda a, b: cmp(a, b))
#   return txt
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9.,]+)', key) ]
    return sorted(txt, key=alphanum_key)


Here is the full file:
Code: Select all
import sublime, sublime_plugin
import random
import re

# Uglyness needed until SelectionRegions will happily compare themselves
def srcmp(a, b):
    aa = a.begin();
    ba = b.begin();

    if aa < ba:
        return -1;
    elif aa == ba:
        return cmp(a.end(), b.end())
    else:
        return 1;

def srtcmp(ta, tb):
    return srcmp(ta[0], tb[0])

def permute_selection(f, v, e):
    regions = [s for s in v.sel() if not s.empty()]
    regions.sort(srcmp)
    txt = [v.substr(s) for s in regions]
    txt = f(txt)

    # no sane way to handle this case
    if len(txt) != len(regions):
        return

    # Do the replacement in reverse order, so the character offsets don't get
    # invalidated
    combined = zip(regions, txt)
    combined.sort(srtcmp, reverse=True)

    for x in combined:
        [r, t] = x
        v.replace(e, r, t)

def case_insensitive_sort(txt):
#   txt.sort(lambda a, b: cmp(a.lower(), b.lower()))
#   return txt
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9.,]+)', key) ]
    return sorted(txt, key=alphanum_key)

def case_sensitive_sort(txt):
#   txt.sort(lambda a, b: cmp(a, b))
#   return txt
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9.,]+)', key) ]
    return sorted(txt, key=alphanum_key)

def reverse_list(l):
    l.reverse()
    return l

def shuffle_list(l):
    random.shuffle(l)
    return l

def uniquealise_list(l):
    table = {}
    res = []
    for x in l:
        if x not in table:
            table[x] = x
            res.append(x)
    return res

permute_funcs = { "reverse" : reverse_list,
                  "shuffle" : shuffle_list,
                  "unique"  : uniquealise_list }

def unique_selection(v):
    regions = [s for s in v.sel() if not s.empty()]
    regions.sort(srcmp)

    dupregions = []
    table = {}
    for r in regions:
        txt = v.substr(r)
        if txt not in table:
            table[txt] = r
        else:
            dupregions.append(r)

    dupregions.reverse()
    for r in dupregions:
        v.erase(e, r)

def shrink_wrap_region( view, region ):
    a, b = region.begin(), region.end()

    for a in xrange(a, b):
        if not view.substr(a).isspace():
            break

    for b in xrange(b-1, a, -1):
        if not view.substr(b).isspace():
            b += 1
            break

    return sublime.Region(a, b)

def shrinkwrap_and_expand_non_empty_selections_to_entire_line(v):
    sw = shrink_wrap_region
    regions = []

    for sel in v.sel():
        if not sel.empty():
            regions.append(v.line(sw(v, v.line(sel))))
            v.sel().subtract(sel)

    for r in regions:
        v.sel().add(r)

def permute_lines(f, v, e):
    shrinkwrap_and_expand_non_empty_selections_to_entire_line(v)

    regions = [s for s in v.sel() if not s.empty()]
    if not regions:
        regions = [sublime.Region(0, v.size())]

    regions.sort(srcmp, reverse=True)

    for r in regions:
        txt = v.substr(r)
        lines = txt.splitlines()
        lines = f(lines)

        v.replace(e, r, u"\n".join(lines))

def has_multiple_non_empty_selection_region(v):
    return len([s for s in v.sel() if not s.empty()]) > 1

class SortLinesCommand(sublime_plugin.TextCommand):
    def run(self, edit, case_sensitive=False,
                        reverse=False,
                        remove_duplicates=False):
        view = self.view

        if case_sensitive:
            permute_lines(case_sensitive_sort, view, edit)
        else:
            permute_lines(case_insensitive_sort, view, edit)

        if reverse:
            permute_lines(reverse_list, view, edit)

        if remove_duplicates:
            permute_lines(uniquealise_list, view, edit)

class SortSelectionCommand(sublime_plugin.TextCommand):
    def run(self, edit, case_sensitive=False,
                        reverse=False,
                        remove_duplicates=False):

        view = self.view

        permute_selection(
            case_sensitive_sort if case_sensitive else case_insensitive_sort,
            view, edit)

        if reverse:
            permute_selection(reverse_list, view, edit)

        if remove_duplicates:
            unique_selection(view, edit)

    def is_enabled(self, **kw):
        return has_multiple_non_empty_selection_region(self.view)

class PermuteLinesCommand(sublime_plugin.TextCommand):
    def run(self, edit, operation='shuffle'):
        permute_lines(permute_funcs[operation], self.view, edit)

class PermuteSelectionCommand(sublime_plugin.TextCommand):
    def run(self, edit, operation='shuffle'):
        view = self.view

        if operation == "reverse":
            permute_selection(reverse_list, view, edit)

        elif operation == "shuffle":
            permute_selection(shuffle_list, view, edit)

        elif operation == "unique":
            unique_selection(view, edit)

    def is_enabled(self, **kw):
        return has_multiple_non_empty_selection_region(self.view)
nick.
 
Posts: 266
Joined: Wed Jan 18, 2012 3:45 am

Re: Sort lines numeric

Postby kaushik1401 on Wed Oct 03, 2012 7:49 pm

I made changes in sort.py accordingly but didn't work for me.
Anyone, have any idea what to do ???
Please Reply soon ...
Thanks
kaushik1401
 
Posts: 5
Joined: Wed Oct 03, 2012 7:39 pm

Re: Sort lines numeric

Postby kaushik1401 on Wed Oct 03, 2012 8:09 pm

Sorry, my mistake. I got this. it only works for numerical values.
I need to do it for css Properties
Like:
#topbar{
background-image:url("images/abc.png");
background-position: 12px 13px;
border-style: solid;
font-size: 1px;
left: 36px;
margin-top: 10px;
top: 23px;
vertical-align: center;
z-index: 1;
}
should convert into:
#topbar{
left: 36px;
top: 23px;
z-index: 1;
font-size: 1px;
margin-top: 10px;
border-style: solid;
vertical-align: center;
background-position: 12px 13px;
background-image:url("images/abc.png");
}


please, anyone can help me....

Thanks
kaushik1401
 
Posts: 5
Joined: Wed Oct 03, 2012 7:39 pm

Re: Sort lines numeric

Postby dave.c on Tue Nov 27, 2012 2:19 am

Here's a method I used to sort numerically. Given the data:

Code: Select all
100
20
2
10
5
1


Get insertion points at the start of each line (Windows: Ctrl+A, Ctrl+Shift+L, Home), then insert at least as many spaces at the start of the lines as your widest number (here it's 100, so at least 3 spaces). Should now look like this (| are the insertion points):

Code: Select all
   |100
   |20
   |2
   |10
   |5
   |1


Now press End:

Code: Select all
   100|
   20|
   2|
   10|
   5|
   1|


Cursor back to the left past the digits:

Code: Select all
   |100
  | 20
|   2
  | 10
|   5
|   1


Selected the leading space and delete it (Ctrl+Shift+Left, Del). Because the insertion points were relative to the length of the numbers, all the numbers should now line up on the right (now . represents space because I couldn't get it to render right otherwise):

Code: Select all
100
.20
..2
.10
..5
..1


So now you can just do a normal Edit - Sort Lines, and you'll get a numeric sorting:

Code: Select all
..1
..2
..5
.10
.20
100


If you want decending you can then do Edit - Permute Lines - Reverse. To get rid of the leading space, Ctrl+A, Ctrl+Shift+L, Home, Home, Ctrl+Shift+Right, Ctrl+Shift+Left, Del.
dave.c
 
Posts: 1
Joined: Tue Nov 27, 2012 1:57 am

Re: Sort lines numeric

Postby markus.magnuson on Mon Feb 04, 2013 12:54 pm

Hey,

I wrote a simple plugin that adds the command "Sort Numerically" to the palette:

https://github.com/alimony/sublime-sort-numerically

(It's my first ever ST plugin so I would really appreciate some testing.)
markus.magnuson
 
Posts: 5
Joined: Mon Feb 04, 2013 12:50 pm


Return to Ideas and Feature Requests

Who is online

Users browsing this forum: No registered users and 9 guests