<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[How i can sort number from largest to smallest on notepad++]]></title><description><![CDATA[<p dir="auto">I’m new on Notepad++ and I want to know how can sort number from largest to smallest. Exemple :</p>
<p dir="auto">random text | 43 points</p>
<p dir="auto">Random text | 82 points</p>
<p dir="auto">Random text | 153 points</p>
<p dir="auto">And I want the numbers to be sorted from largest to smallest like that</p>
<p dir="auto">random text | 153 points</p>
<p dir="auto">Random text | 82 points</p>
<p dir="auto">Random text | 43 points</p>
<p dir="auto">Thanks you</p>
]]></description><link>https://community.notepad-plus-plus.org/topic/24325/how-i-can-sort-number-from-largest-to-smallest-on-notepad</link><generator>RSS for Node</generator><lastBuildDate>Tue, 18 Aug 2026 15:19:45 GMT</lastBuildDate><atom:link href="https://community.notepad-plus-plus.org/topic/24325.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 02 Apr 2023 00:23:02 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 14 Jan 2024 21:01:09 GMT]]></title><description><![CDATA[<p dir="auto">If you’ve used a script in this thread, you might want to double check your copy of it for a bug I’ve discovered.<br />
Look to previous postings in this topic thread where the script has been changed – find the text <code>moderator edit (2024-Jan-14)</code>.<br />
There’s a link there that describes the bug in more detail, and shows what needs to be changed in an old copy (or you can simply grab a copy of the current version).</p>
]]></description><link>https://community.notepad-plus-plus.org/post/92064</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/92064</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Sun, 14 Jan 2024 21:01:09 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Fri, 28 Jul 2023 08:32:13 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a> OK, that is clear. Thank you for the explanation.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/88187</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/88187</guid><dc:creator><![CDATA[Paul Wormer]]></dc:creator><pubDate>Fri, 28 Jul 2023 08:32:13 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Thu, 27 Jul 2023 20:41:58 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/paul-wormer" aria-label="Profile: Paul-Wormer">@<bdi>Paul-Wormer</bdi></a> said in <a href="/post/88165">How i can sort number from largest to smallest on notepad++</a>:</p>
<blockquote>
<p dir="auto">I see that you use \h, \s  and \x20 for a space in one and the same regex. Is there a deeper reason for that?</p>
</blockquote>
<p dir="auto">Yes, there are reasons for all of those decisions:</p>
<ol>
<li><code>\h</code> between <code>def</code> and the name of the function because they must be on the same line but (I believe) there can be arbitrary spacing between them</li>
<li><code>\s</code> in the region containing the arguments because the arguments can be separated by arbitrary whitespace</li>
<li><code>\x20</code> because I’m assuming that the function is indented by spaces.</li>
</ol>
]]></description><link>https://community.notepad-plus-plus.org/post/88173</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/88173</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Thu, 27 Jul 2023 20:41:58 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Thu, 27 Jul 2023 15:31:34 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a> said in <a href="/post/88155">How i can sort number from largest to smallest on notepad++</a>:</p>
<blockquote>
<p dir="auto">(?-si)^def\h+(\w+)\s*([\w:\s,]+?)\s*(?:-&gt;[^:]+)?:(?:.+$|\h*\R(?:\x20+.*\R?)+)</p>
</blockquote>
<p dir="auto">I see that you use <code>\h</code>, <code>\s</code>  and <code>\x20</code> for a space in one and the same regex. Is there a deeper reason for that? Or is it didactic in that you want to point out that there are more possibilities for a space?</p>
]]></description><link>https://community.notepad-plus-plus.org/post/88165</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/88165</guid><dc:creator><![CDATA[Paul Wormer]]></dc:creator><pubDate>Thu, 27 Jul 2023 15:31:34 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Thu, 27 Jul 2023 02:12:34 GMT]]></title><description><![CDATA[<p dir="auto">Well, I said I would wait to post again until I had a <strong>significant improvement</strong>, and I believe I do.</p>
<p dir="auto">I have now updated the script <strong>so it can sort multi-line blocks</strong>, for example, sorting a bunch of multi-line XML elements by some attribute.</p>
<p dir="auto">Normally the only way to sort multi-line blocks is to do the following:</p>
<ol>
<li>use a regex that replaces all the newlines in each block with some delimiter that is not present in the file <em>while preserving newlines outside the block.</em></li>
<li>Sort the lines of the document using the above script or one of the built-in sorts</li>
<li>replace the delimiter with newlines.</li>
</ol>
<p dir="auto">This process is annoying, so I decided to automate it.</p>
<p dir="auto">Behold!</p>
<pre><code># -*- coding: utf-8 -*-
from __future__ import print_function

#########################################
#
#  SortLinesWithRegexGroup1AsSortKey (SLWRG1ASK)
#
#########################################

# references:
#  https://community.notepad-plus-plus.org/topic/24325

#-------------------------------------------------------------------------------

from Npp import *
import inspect
import os
import re
import threading
import unicodedata
import SendKeys as sk

#-------------------------------------------------------------------------------

NUMBER_RE = r'([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?\d+)?)'
INT_RE = r'([+-]?[0-9]+)'

def ignorecase_culture_invariant(x):
    return unicodedata.normalize('NFD', x.upper())

class SLWRG1ASK(object):

    def __init__(self):

        self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0]

        self.key_and_line_content_tup_list = []
        self.matched_line_numbers = set()
        self.key_did_not_match_specified_type__ERROR = False
        self.user_did_not_specify_group1__ERROR = False
        self.not_all_lines_matched__ERROR = False
        self.last_matched_line_num = None
        self.user_line_num_of_error = None
        self.zero_matches_for_regex = True
        self.key_transform = None
        self.do_descending_sort = False
        self.each_line_must_have_regex_group1_key_match = True
        self.remove_lines_that_dont_match_regex = False
        self.sort_lines_that_dont_match_to_bottom = False
        self.multiline = False
        self.multiline_block_delim = ''
        self.eol = [ '\r\n', '\r', '\n' ][ editor.getEOLMode() ]

        rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]
        if rect_sel_mode or editor.getSelections() &gt; 1:
            self.mb('Cannot operate on a column selection or multiple selections; aborting!')
            return

        if len(editor.getSelText()) == 0:
            if not self.mb_ok_cancel('No selection active; confirm desire to sort entire file by pressing OK.'):
                return

        (search_start_line, search_end_line) = editor.getUserLineSelection()
        if editor.positionFromLine(search_end_line) == editor.getSelectionEnd(): search_end_line -= 1
        num_lines_in_user_sel = search_end_line - search_start_line + 1
        if num_lines_in_user_sel &lt; 2: return  # if selection only on 1 line, nothing to do; already sorted!

        user_regex_with_group_1 = ''
        used_DECIMAL_RE = False
        while True:
            user_regex_with_group_1 = self.prompt('Enter regex with group 1 being the sort key.\r\nIf you wish, you can use (INT) to capture an integer or (DECIMAL) to capture a decimal', user_regex_with_group_1)
            if user_regex_with_group_1 is None: return  # user cancel
            if len(user_regex_with_group_1.strip()) == 0:
                self.mb('Cannot specify an empty regex!  Try again.')
                continue
            if '(' not in user_regex_with_group_1:
                self.mb('Need to specify capture group 1 (as the sort key) in the regex!  Try again.')
                continue
            regex_err_msg = self.search_regex_is_invalid_error_msg(user_regex_with_group_1)
            if len(regex_err_msg) &gt; 0:
                self.mb('Bad regular expression!\r\n\r\n{e}\r\n\r\nTry again.'.format(e=regex_err_msg))
                continue
            used_DECIMAL_RE = '(DECIMAL)' in user_regex_with_group_1
            user_regex_with_group_1 = user_regex_with_group_1.replace('(INT)', INT_RE).replace('(DECIMAL)', NUMBER_RE)
            break

        while True:
            threading.Timer(0.25, lambda : sk.SendKeys("{RIGHT}")).start()  # clear auto-selection of prompt text when box appears
            user_options = self.prompt(
                '    Regex specified: {r}\r\n'
                'Choose options by placing 1 x in each group (no need to x to get DEFAULT choice)'.format(r=user_regex_with_group_1),
                '\r\n'.join([
                    'Group 1 transformation:  [   ]Integer(DEFAULT)      [  {0}]Decimal      [   ]String      [   ]Ignorecase-cultural'.format(' x'[used_DECIMAL_RE]),
                    'Sort order:  [   ]Ascending(DEFAULT)    [   ]Descending',
                    'Other:',
                    '[   ]Sort-only-if-all-lines-have-group-1-match(DEFAULT)',
                    '[   ]Remove-non-matching-lines',
                    '[   ]Sort-non-matching-lines-to-bottom',
                    '[   ]Multi-line-blocks',
                ])
                )
            if user_options is None: return  # user cancel
            if len(user_options.strip()) == 0:
                self.mb('Cannot specify empty options!  Try again.')
                continue
            if self.option_check(user_options, 'String'): self.key_transform = str
            elif self.option_check(user_options, 'Decimal'): self.key_transform = float
            elif self.option_check(user_options, 'Ignorecase-cultural'): self.key_transform = ignorecase_culture_invariant
            else: self.key_transform = int
            self.do_descending_sort = self.option_check(user_options, 'Descending')
            self.each_line_must_have_regex_group1_key_match = self.option_check(user_options, 'Sort-only-if-all-lines-have-group-1-match')
            self.remove_lines_that_dont_match_regex = self.option_check(user_options, 'Remove-non-matching-lines')
            self.sort_lines_that_dont_match_to_bottom = self.option_check(user_options, 'Sort-non-matching-lines-to-bottom')
            self.multiline = self.option_check(user_options, 'Multi-line')
            if not (self.remove_lines_that_dont_match_regex or self.sort_lines_that_dont_match_to_bottom):
                self.each_line_must_have_regex_group1_key_match = True
            if self.each_line_must_have_regex_group1_key_match + self.remove_lines_that_dont_match_regex + self.sort_lines_that_dont_match_to_bottom &gt; 1:
                self.mb('Can only specify one way of handling unmatched lines! Try again!')
                continue
            break

        search_start_pos = editor.positionFromLine(search_start_line)
        search_end_pos = editor.getLineEndPosition(search_end_line)
        
        if self.multiline:
            # find a character (or multi-char sequence) that is not in the document
            delim = 1
            delim_len = 1
            allText = editor.getRangePointer(search_start_pos, search_end_pos)
            while True:
                # consider only NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL
                delim = delim % 8
                if delim == 0:
                    delim += 1
                delim_str = chr(delim) * delim_len
                if delim_str not in allText:
                    self.multiline_block_delim = delim_str
                    break
                else:
                    delim += 1
                    delim_len += 1
        else:
            # enforce single-line matching and only get the FIRST match on each line:
            user_regex_with_group_1 = '(?-s)' + user_regex_with_group_1 + '.*'


        # special "seeding", in case the very first line of the selection isn't hit:
        self.last_matched_line_num = search_start_line - 1

        editor.research(user_regex_with_group_1, lambda m: self.match_found(m), 0, search_start_pos, search_end_pos)

        if self.zero_matches_for_regex:
            self.mb('No lines matched the regex; aborting!')
            return

        if self.user_did_not_specify_group1__ERROR:
            self.mb('No sort key specified (via using capture group 1) in the regex; aborting!')
            return

        if self.key_did_not_match_specified_type__ERROR:
            self.mb('Key data did not match specified type ({t}) on line {L}; aborting!'.format(L=self.user_line_num_of_error,
                t={ int : 'Integer', float : 'Decimal', str : 'String', ignorecase_culture_invariant: 'String' }[self.key_transform]))
            return

        if self.each_line_must_have_regex_group1_key_match and self.not_all_lines_matched__ERROR:
            self.mb('Not every line in the source data matched the specified regex (first non-matching line was {L}) OR there were multiple matches in at least one line; aborting!'.format(L=self.user_line_num_of_error))
            return

        if len(self.key_and_line_content_tup_list) &lt; 2:
            self.mb('Nothing (reasonable) found to sort; aborting!')
            return
        

        sorted_line_list = [tup[1] for tup in sorted(self.key_and_line_content_tup_list, reverse=self.do_descending_sort)]
        
        if self.multiline:
            sorted_line_list = [x.replace(self.multiline_block_delim, self.eol) for x in sorted_line_list]
        elif self.matched_line_numbers:
            first_unmatched_line = search_start_line + len(self.matched_line_numbers) + 1
            self.mb('Line numbers {0}-{1} in sorted text were NOT matched.'.format(first_unmatched_line, search_end_line + 1),
                title='not all lines matched')
            for line_num in range(search_start_line, search_end_line + 1):
                if line_num not in self.matched_line_numbers:
                    unmatched_line = editor.getLine(line_num)
                    sorted_line_list.append(unmatched_line.rstrip('\r\n'))

        doc_len_before = editor.getLength()

        editor.setSelection(search_end_pos, search_start_pos)
        editor.replaceSel(self.eol.join(sorted_line_list))

        doc_len_delta = editor.getLength() - doc_len_before

        # leave sorted text selected:
        editor.setSelection(search_end_pos + doc_len_delta, search_start_pos)

    def match_found(self, m):

        self.zero_matches_for_regex = False

        # we're already corrupt; don't bother processing further matches after the one where we found the problem
        if self.user_did_not_specify_group1__ERROR: return
        if self.key_did_not_match_specified_type__ERROR: return
        if self.not_all_lines_matched__ERROR: return

        (start_pos_of_match, end_pos_of_match) = m.span(0)
        line_num_of_match = editor.lineFromPosition(start_pos_of_match)
        
        try:
            g1_str = m.group(1)
        except IndexError:
            self.user_did_not_specify_group1__ERROR = True
            return

        try:
            key_with_correct_type = self.key_transform(g1_str)
        except ValueError:
            self.key_did_not_match_specified_type__ERROR = True
            self.user_line_num_of_error = line_num_of_match + 1
            return

        if self.multiline:
            line_content = m.group(0).rstrip('\n\r').replace(self.eol, self.multiline_block_delim)
        else:
            if line_num_of_match != self.last_matched_line_num + 1:
                if self.each_line_must_have_regex_group1_key_match:
                    self.not_all_lines_matched__ERROR = True
                    system_line_num_of_err = self.last_matched_line_num + 1
                    self.user_line_num_of_error = system_line_num_of_err + 1
                    return
            self.last_matched_line_num = line_num_of_match
            if self.sort_lines_that_dont_match_to_bottom:
                self.matched_line_numbers.add(line_num_of_match)
            line_content = editor.getLine(line_num_of_match).rstrip('\n\r')

        tup = (key_with_correct_type, line_content)
        self.key_and_line_content_tup_list.append(tup)

    def option_check(self, input_text, option_text):
        m = re.search(r'\\[([^]]+)\\] ?{opt}'.format(opt=option_text), input_text)
        retval = True if m and m.group(1) != ' ' * len(m.group(1)) else False
        return retval

    def search_regex_is_invalid_error_msg(self, test_regex):
        try:
            # test test_regex for validity
            editor.research(test_regex, lambda _: None)
        except RuntimeError as r:
            return str(r)
        return ''

    def mb(self, msg, flags=0, title=''):  # a message-box function
        return notepad.messageBox(msg, title if title else self.this_script_name, flags)

    def mb_ok_cancel(self, msg, title=''):  # returns True(OK) or False(Cancel)
        okay = notepad.messageBox(msg, title if title else self.this_script_name, MESSAGEBOXFLAGS.OKCANCEL) == MESSAGEBOXFLAGS.RESULTOK
        return okay

    def prompt(self, prompt_text, default_text=''):
        if '\n' not in prompt_text: prompt_text = '\r\n' + prompt_text
        prompt_text += ':'
        return notepad.prompt(prompt_text, self.this_script_name, default_text)

#-------------------------------------------------------------------------------

if __name__ == '__main__': SLWRG1ASK()
</code></pre>
<p dir="auto">EXAMPLE: sorting the functions in a Python file</p>
<pre><code>def foo(a) -&gt; ruon:
    fdnfoen
    eorjerjeon
    if neoren:
        eorneor
    for orneor in reiroewh:
        orneroej
        def xjorneo(zser):
            ornero("defoorne")
        
def zargothrax(rinonrururr: int, bozo: float, 
defrnore: rourno) -&gt; ziiron:
    oerjjeorno
def bar(b,
c,
d,
e):
    oerneorn
    erjelrkererei
    o33n4o3jo3443i3i
    043304 343kj3kj
    def noer(x):
        fnoerno
def uonreorn (x, b, z): ornepronp

def barru(rnx):
    pass
    
def ournoerno
  (fnorne
 ):
    pass
</code></pre>
<p dir="auto">can have its functions sorted using the following regex: <code>(?-si)^def\h+(\w+)\s*\([\w:\s,]+?\)\s*(?:-&gt;[^:]+)?:(?:.+$|\h*\R(?:\x20+.*\R?)+)</code> and the following options selected:</p>
<pre><code>Group 1 transformation:  [   ]Integer(DEFAULT)      [   ]Decimal      [   ]String      [   x]Ignorecase-cultural
Sort order:  [   ]Ascending(DEFAULT)    [   ]Descending
Other:
[   ]Sort-only-if-all-lines-have-group-1-match(DEFAULT)
[   ]Remove-non-matching-lines
[   ]Sort-non-matching-lines-to-bottom
[  x ]Multi-line-blocks
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/88155</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/88155</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Thu, 27 Jul 2023 02:12:34 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Thu, 27 Apr 2023 19:22:20 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a><br />
I discovered that my previous implementation of normalized case-insensitive text wasn’t quite right.</p>
<p dir="auto">I can’t edit my last post, but the function <code>ignorecase_culture_invariant</code> should be replaced with <em>this</em>:</p>
<pre><code>def ignorecase_culture_invariant(x):
    return unicodedata.normalize('NFD', x.upper())
</code></pre>
<p dir="auto">The previous implementation (using <strong><code>x.lower()</code></strong>) doesn’t work for German ß, and there are probably some other places where it fails.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85982</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85982</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Thu, 27 Apr 2023 19:22:20 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 14 Jan 2024 18:53:03 GMT]]></title><description><![CDATA[<p dir="auto">alright this is my final version based on Alan Kilborn’s suggestions. I will restrain myself from posting any other versions until I have any <em>substantial</em> new improvements</p>
<pre><code># -*- coding: utf-8 -*-
from __future__ import print_function

#########################################
#
#  SortLinesWithRegexGroup1AsSortKey (SLWRG1ASK)
#
#########################################

# references:
#  https://community.notepad-plus-plus.org/topic/24325

#-------------------------------------------------------------------------------

from Npp import *
import inspect
import os
import re
import threading
import unicodedata
import SendKeys as sk

#-------------------------------------------------------------------------------

NUMBER_RE = r'([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?\d+)?)'
INT_RE = r'([+-]?[0-9]+)'

def ignorecase_culture_invariant(x):
    return unicodedata.normalize('NFD', x.lower())

class SLWRG1ASK(object):

    def __init__(self):

        self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0]

        self.key_and_line_content_tup_list = []
        self.matched_line_numbers = set()
        self.key_did_not_match_specified_type__ERROR = False
        self.user_did_not_specify_group1__ERROR = False
        self.not_all_lines_matched__ERROR = False
        self.last_matched_line_num = None
        self.user_line_num_of_error = None
        self.zero_matches_for_regex = True
        self.key_transform = None
        self.do_descending_sort = False
        self.each_line_must_have_regex_group1_key_match = True
        self.remove_lines_that_dont_match_regex = False
        self.sort_lines_that_dont_match_to_bottom = False

        rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]
        if rect_sel_mode or editor.getSelections() &gt; 1:
            self.mb('Cannot operate on a column selection or multiple selections; aborting!')
            return

        if len(editor.getSelText()) == 0:
            if not self.mb_ok_cancel('No selection active; confirm desire to sort entire file by pressing OK.'):
                return

        (search_start_line, search_end_line) = editor.getUserLineSelection()
        if editor.positionFromLine(search_end_line) == editor.getSelectionEnd(): search_end_line -= 1
        num_lines_in_user_sel = search_end_line - search_start_line + 1
        if num_lines_in_user_sel &lt; 2: return  # if selection only on 1 line, nothing to do; already sorted!

        user_regex_with_group_1 = ''
        used_DECIMAL_RE = False
        while True:
            user_regex_with_group_1 = self.prompt('Enter regex with group 1 being the sort key.\r\nIf you wish, you can use (INT) to capture an integer or (DECIMAL) to capture a decimal', user_regex_with_group_1)
            if user_regex_with_group_1 is None: return  # user cancel
            if len(user_regex_with_group_1.strip()) == 0:
                self.mb('Cannot specify an empty regex!  Try again.')
                continue
            if '(' not in user_regex_with_group_1:
                self.mb('Need to specify capture group 1 (as the sort key) in the regex!  Try again.')
                continue
            regex_err_msg = self.search_regex_is_invalid_error_msg(user_regex_with_group_1)
            if len(regex_err_msg) &gt; 0:
                self.mb('Bad regular expression!\r\n\r\n{e}\r\n\r\nTry again.'.format(e=regex_err_msg))
                continue
            used_DECIMAL_RE = '(DECIMAL)' in user_regex_with_group_1
            user_regex_with_group_1 = user_regex_with_group_1.replace('(INT)', INT_RE).replace('(DECIMAL)', NUMBER_RE)
            break

        while True:
            threading.Timer(0.25, lambda : sk.SendKeys("{RIGHT}")).start()  # clear auto-selection of prompt text when box appears
            user_options = self.prompt(
                '    Regex specified: {r}\r\n'
                'Choose options by placing 1 x in each group (no need to x to get DEFAULT choice)'.format(r=user_regex_with_group_1),
                '\r\n'.join([
                    'Group 1 transformation:  [   ]Integer(DEFAULT)      [  {0}]Decimal      [   ]String      [   ]Ignorecase-cultural'.format(' x'[used_DECIMAL_RE]),
                    'Sort order:  [   ]Ascending(DEFAULT)    [   ]Descending',
                    'Other:',
                    '[   ]Sort-only-if-all-lines-have-group-1-match(DEFAULT)',
                    '[   ]Remove-non-matching-lines',
                    '[   ]Sort-non-matching-lines-to-bottom',
                ])
                )
            if user_options is None: return  # user cancel
            if len(user_options.strip()) == 0:
                self.mb('Cannot specify empty options!  Try again.')
                continue
            if self.option_check(user_options, 'String'): self.key_transform = str
            elif self.option_check(user_options, 'Decimal'): self.key_transform = float
            elif self.option_check(user_options, 'Ignorecase-cultural'): self.key_transform = ignorecase_culture_invariant
            else: self.key_transform = int
            self.do_descending_sort = self.option_check(user_options, 'Descending')
            self.each_line_must_have_regex_group1_key_match = self.option_check(user_options, 'Sort-only-if-all-lines-have-group-1-match')
            self.remove_lines_that_dont_match_regex = self.option_check(user_options, 'Remove-non-matching-lines')
            self.sort_lines_that_dont_match_to_bottom = self.option_check(user_options, 'Sort-non-matching-lines-to-bottom')
            if not (self.remove_lines_that_dont_match_regex or self.sort_lines_that_dont_match_to_bottom):
                self.each_line_must_have_regex_group1_key_match = True
            if self.each_line_must_have_regex_group1_key_match + self.remove_lines_that_dont_match_regex + self.sort_lines_that_dont_match_to_bottom &gt; 1:
                self.mb('Can only specify one way of handling unmatched lines! Try again!')
                continue
            break

        # enforce single-line matching and only get the FIRST match on each line:
        user_regex_with_group_1 = '(?-s)' + user_regex_with_group_1 + '.*'

        search_start_pos = editor.positionFromLine(search_start_line)
        search_end_pos = editor.getLineEndPosition(search_end_line)

        # special "seeding", in case the very first line of the selection isn't hit:
        self.last_matched_line_num = search_start_line - 1

        editor.research(user_regex_with_group_1, lambda m: self.match_found(m), 0, search_start_pos, search_end_pos)

        if self.zero_matches_for_regex:
            self.mb('No lines matched the regex; aborting!')
            return

        if self.user_did_not_specify_group1__ERROR:
            self.mb('No sort key specified (via using capture group 1) in the regex; aborting!')
            return

        if self.key_did_not_match_specified_type__ERROR:
            self.mb('Key data did not match specified type ({t}) on line {L}; aborting!'.format(L=self.user_line_num_of_error,
                t={ int : 'Integer', float : 'Decimal', str : 'String', ignorecase_culture_invariant: 'String' }[self.key_transform]))
            return

        if self.each_line_must_have_regex_group1_key_match and self.not_all_lines_matched__ERROR:
            self.mb('Not every line in the source data matched the specified regex (first non-matching line was {L}); aborting!'.format(L=self.user_line_num_of_error))
            return

        if len(self.key_and_line_content_tup_list) &lt; 2:
            self.mb('Nothing (reasonable) found to sort; aborting!')
            return

        sorted_line_list = [tup[1] for tup in sorted(self.key_and_line_content_tup_list, reverse=self.do_descending_sort)]
        
        if self.matched_line_numbers:
            first_unmatched_line = search_start_line + len(self.matched_line_numbers) + 1
            self.mb('Line numbers {0}-{1} in sorted text were NOT matched.'.format(first_unmatched_line, search_end_line + 1),
                title='not all lines matched')
            for line_num in range(search_start_line, search_end_line + 1):
                if line_num not in self.matched_line_numbers:
                    unmatched_line = editor.getLine(line_num)
                    sorted_line_list.append(unmatched_line.rstrip('\r\n'))

        eol = ['\r\n', '\r', '\n'][editor.getEOLMode()]

        doc_len_before = editor.getLength()

        editor.setSelection(search_end_pos, search_start_pos)
        editor.replaceSel(eol.join(sorted_line_list))

        doc_len_delta = editor.getLength() - doc_len_before

        # leave sorted text selected:
        editor.setSelection(search_end_pos + doc_len_delta, search_start_pos)

    def match_found(self, m):

        self.zero_matches_for_regex = False

        # we're already corrupt; don't bother processing further matches after the one where we found the problem
        if self.user_did_not_specify_group1__ERROR: return
        if self.key_did_not_match_specified_type__ERROR: return
        if self.not_all_lines_matched__ERROR: return

        (start_pos_of_match, end_pos_of_match) = m.span(0)

        line_num_of_match = editor.lineFromPosition(start_pos_of_match)

        if line_num_of_match != self.last_matched_line_num + 1:
            if self.each_line_must_have_regex_group1_key_match:
                self.not_all_lines_matched__ERROR = True
                system_line_num_of_err = self.last_matched_line_num + 1
                self.user_line_num_of_error = system_line_num_of_err + 1
                return
        self.last_matched_line_num = line_num_of_match
        if self.sort_lines_that_dont_match_to_bottom:
            self.matched_line_numbers.add(line_num_of_match)

        try:
            g1_str = m.group(1)
        except IndexError:
            self.user_did_not_specify_group1__ERROR = True
            return

        try:
            key_with_correct_type = self.key_transform(g1_str)
        except ValueError:
            self.key_did_not_match_specified_type__ERROR = True
            self.user_line_num_of_error = line_num_of_match + 1
            return

        line_content = editor.getLine(line_num_of_match).rstrip('\n\r')

        tup = (key_with_correct_type, line_content)
        self.key_and_line_content_tup_list.append(tup)

    def option_check(self, input_text, option_text):
        m = re.search(r'\[([^]]+)\] ?{opt}'.format(opt=option_text), input_text)
        retval = True if m and m.group(1) != ' ' * len(m.group(1)) else False
        return retval

    def search_regex_is_invalid_error_msg(self, test_regex):
        try:
            # test test_regex for validity
            editor.research(test_regex, lambda _: None)
        except RuntimeError as r:
            return str(r)
        return ''

    def mb(self, msg, flags=0, title=''):  # a message-box function
        return notepad.messageBox(msg, title if title else self.this_script_name, flags)

    def mb_ok_cancel(self, msg, title=''):  # returns True(OK) or False(Cancel)
        okay = notepad.messageBox(msg, title if title else self.this_script_name, MESSAGEBOXFLAGS.OKCANCEL) == MESSAGEBOXFLAGS.RESULTOK
        return okay

    def prompt(self, prompt_text, default_text=''):
        if '\n' not in prompt_text: prompt_text = '\r\n' + prompt_text
        prompt_text += ':'
        return notepad.prompt(prompt_text, self.this_script_name, default_text)

#-------------------------------------------------------------------------------

if __name__ == '__main__': SLWRG1ASK()
</code></pre>
<p dir="auto">--<br />
<em>Moderator EDIT (2024-Jan-14): The author of the script has found a fairly serious bug with the code published here for those that use Mac-style or Linux-style line-endings in their files.  The logic for Mac and Linux was reversed, and thus if the script was used on one type of file, the line-endings for the opposite type of file could end up in the file after the script is run.  This is insidious, because unless one works with visible line-endings turned on, this is likely not noticed.  Some detail on the problem is <a href="https://community.notepad-plus-plus.org/post/91918">HERE</a>.  The script above has been corrected per that instruction.</em></p>
]]></description><link>https://community.notepad-plus-plus.org/post/85667</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85667</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Sun, 14 Jan 2024 18:53:03 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Fri, 14 Apr 2023 14:19:39 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a><br />
Yep, good idea. I just added</p>
<pre><code>NUMBER_RE = r'([-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?\d+)?)'
INT_RE = r'([+-]?[0-9]+)'
</code></pre>
<p dir="auto">and <code>user_regex_with_group_1.replace('(INT)', INT_RE).replace('(DECIMAL)', NUMBER_RE)</code> after the regex is assigned but before it’s used.</p>
<p dir="auto">It’s easy to get the basic structure of integer and decimal regexes, but there are way too many edge cases that are too easily forgotten.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85666</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85666</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Fri, 14 Apr 2023 14:19:39 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Fri, 14 Apr 2023 11:29:17 GMT]]></title><description><![CDATA[<p dir="auto">One thing I didn’t get around to doing in the script was making it easier on a user to specify a “decimal” key.</p>
<p dir="auto">It probably would have been simpler for the user to specify a regex such as <code>key(DECIMAL)</code> rather than, e.g.,  <code>key([-+]?[0-9]*\.?[0-9]+)</code>.</p>
<p dir="auto">The script code could scan the user supplied regex for “DECIMAL” and replace with the somewhat hard-to-remember regex.</p>
<p dir="auto">See <a href="https://www.regular-expressions.info/floatingpoint.html" rel="nofollow ugc">HERE</a> for the origins of that decimal-number regex.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85665</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85665</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Fri, 14 Apr 2023 11:29:17 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 14 Jan 2024 18:52:10 GMT]]></title><description><![CDATA[<p dir="auto">OK, I’ve added two new options: lowercase culture-insensitive (Python can do that, it’s just <a href="https://docs.python.org/3.10/library/unicodedata.html" rel="nofollow ugc">rather obscure</a>) and sorting unmatched lines to bottom.</p>
<p dir="auto">The text:</p>
<pre><code>foo: tone bar: 27.1
foo: bLue bar: 241.3
foo: taco bar: 66.5
foo: basst bar: 281.7
foo: öyster bar: 144.0
foo: oyster bar: 164.1
foo: Spb bar: 102.1
foo: blüe bar: 203.2
foo: spä bar: 121.2
foo: spb bar: 84.2
foo: blve bar: 183.2
foo: blue bar: 222.2
foo: baßk bar: 261.3
foo: täco bar: 47.3
</code></pre>
<p dir="auto">Sorting unmatched lines to bottom (regex <code>bar: (\d\d)\D</code>, all other options default). Note that the lines with a 3-digit number all stay in the same order.</p>
<pre><code>foo: tone bar: 27.1
foo: täco bar: 47.3
foo: taco bar: 66.5
foo: spb bar: 84.2
foo: bLue bar: 241.3
foo: basst bar: 281.7
foo: öyster bar: 144.0
foo: oyster bar: 164.1
foo: Spb bar: 102.1
foo: blüe bar: 203.2
foo: spä bar: 121.2
foo: blve bar: 183.2
foo: blue bar: 222.2
foo: baßk bar: 261.3
</code></pre>
<p dir="auto">Ignorecase culture-sensitive (regex <code>foo: (\w+)</code>, all other options default)</p>
<pre><code>foo: basst bar: 281.7
foo: baßk bar: 261.3
foo: bLue bar: 241.3
foo: blue bar: 222.2
foo: blüe bar: 203.2
foo: blve bar: 183.2
foo: oyster bar: 164.1
foo: öyster bar: 144.0
foo: spä bar: 121.2
foo: Spb bar: 102.1
foo: spb bar: 84.2
foo: taco bar: 66.5
foo: täco bar: 47.3
foo: tone bar: 27.1
</code></pre>
<p dir="auto">And finally, my modification of the script:</p>
<pre><code># -*- coding: utf-8 -*-
from __future__ import print_function

#########################################
#
#  SortLinesWithRegexGroup1AsSortKey (SLWRG1ASK)
#
#########################################

# references:
#  https://community.notepad-plus-plus.org/topic/24325

#-------------------------------------------------------------------------------

from Npp import *
import inspect
import os
import re
import threading
import unicodedata
import SendKeys as sk

#-------------------------------------------------------------------------------

def ignorecase_culture_invariant(x):
    return unicodedata.normalize('NFD', x.lower())

class SLWRG1ASK(object):

    def __init__(self):

        self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0]

        self.key_and_line_content_tup_list = []
        self.matched_line_numbers = set()
        self.key_did_not_match_specified_type__ERROR = False
        self.user_did_not_specify_group1__ERROR = False
        self.not_all_lines_matched__ERROR = False
        self.last_matched_line_num = None
        self.user_line_num_of_error = None
        self.zero_matches_for_regex = True
        self.key_transform = None
        self.do_descending_sort = False
        self.each_line_must_have_regex_group1_key_match = True
        self.remove_lines_that_dont_match_regex = False
        self.sort_lines_that_dont_match_to_bottom = False

        rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]
        if rect_sel_mode or editor.getSelections() &gt; 1:
            self.mb('Cannot operate on a column selection or multiple selections; aborting!')
            return

        if len(editor.getSelText()) == 0:
            if not self.mb_ok_cancel('No selection active; confirm desire to sort entire file by pressing OK.'):
                return

        (search_start_line, search_end_line) = editor.getUserLineSelection()
        if editor.positionFromLine(search_end_line) == editor.getSelectionEnd(): search_end_line -= 1
        num_lines_in_user_sel = search_end_line - search_start_line + 1
        if num_lines_in_user_sel &lt; 2: return  # if selection only on 1 line, nothing to do; already sorted!

        user_regex_with_group_1 = ''
        while True:
            user_regex_with_group_1 = self.prompt('Enter regex with group 1 being the sort key', user_regex_with_group_1)
            if user_regex_with_group_1 is None: return  # user cancel
            if len(user_regex_with_group_1.strip()) == 0:
                self.mb('Cannot specify an empty regex!  Try again.')
                continue
            if '(' not in user_regex_with_group_1:
                self.mb('Need to specify capture group 1 (as the sort key) in the regex!  Try again.')
                continue
            regex_err_msg = self.search_regex_is_invalid_error_msg(user_regex_with_group_1)
            if len(regex_err_msg) &gt; 0:
                self.mb('Bad regular expression!\r\n\r\n{e}\r\n\r\nTry again.'.format(e=regex_err_msg))
                continue
            break

        while True:
            threading.Timer(0.25, lambda : sk.SendKeys("{RIGHT}")).start()  # clear auto-selection of prompt text when box appears
            user_options = self.prompt(
                '    Regex specified: {r}\r\n'
                'Choose options by placing 1 x in each group (no need to x to get DEFAULT choice)'.format(r=user_regex_with_group_1),
                '\r\n'.join([
                    'Group 1 transformation:  [   ]Integer(DEFAULT)      [   ]Decimal      [   ]String      [   ]Ignorecase-cultural',
                    'Sort order:  [   ]Ascending(DEFAULT)    [   ]Descending',
                    'Other:',
                    '[   ]Sort-only-if-all-lines-have-group-1-match(DEFAULT)',
                    '[   ]Remove-non-matching-lines',
                    '[   ]Sort-non-matching-lines-to-bottom',
                ])
                )
            if user_options is None: return  # user cancel
            if len(user_options.strip()) == 0:
                self.mb('Cannot specify empty options!  Try again.')
                continue
            if self.option_check(user_options, 'String'): self.key_transform = str
            elif self.option_check(user_options, 'Decimal'): self.key_transform = float
            elif self.option_check(user_options, 'Ignorecase-cultural'): self.key_transform = ignorecase_culture_invariant
            else: self.key_transform = int
            self.do_descending_sort = self.option_check(user_options, 'Descending')
            self.each_line_must_have_regex_group1_key_match = self.option_check(user_options, 'Sort-only-if-all-lines-have-group-1-match')
            self.remove_lines_that_dont_match_regex = self.option_check(user_options, 'Remove-non-matching-lines')
            self.sort_lines_that_dont_match_to_bottom = self.option_check(user_options, 'Sort-non-matching-lines-to-bottom')
            if not (self.remove_lines_that_dont_match_regex or self.sort_lines_that_dont_match_to_bottom):
                self.each_line_must_have_regex_group1_key_match = True
            if self.each_line_must_have_regex_group1_key_match + self.remove_lines_that_dont_match_regex + self.sort_lines_that_dont_match_to_bottom &gt; 1:
                self.mb('Can only specify one way of handling unmatched lines! Try again!')
                continue
            break

        # enforce single-line matching and only get the FIRST match on each line:
        user_regex_with_group_1 = '(?-s)' + user_regex_with_group_1 + '.*'

        search_start_pos = editor.positionFromLine(search_start_line)
        search_end_pos = editor.getLineEndPosition(search_end_line)

        # special "seeding", in case the very first line of the selection isn't hit:
        self.last_matched_line_num = search_start_line - 1

        editor.research(user_regex_with_group_1, lambda m: self.match_found(m), 0, search_start_pos, search_end_pos)

        if self.zero_matches_for_regex:
            self.mb('No lines matched the regex; aborting!')
            return

        if self.user_did_not_specify_group1__ERROR:
            self.mb('No sort key specified (via using capture group 1) in the regex; aborting!')
            return

        if self.key_did_not_match_specified_type__ERROR:
            self.mb('Key data did not match specified type ({t}) on line {L}; aborting!'.format(L=self.user_line_num_of_error,
                t={ int : 'Integer', float : 'Decimal', str : 'String', ignorecase_culture_invariant: 'String' }[self.key_transform]))
            return

        if self.each_line_must_have_regex_group1_key_match and self.not_all_lines_matched__ERROR:
            self.mb('Not every line in the source data matched the specified regex (first non-matching line was {L}); aborting!'.format(L=self.user_line_num_of_error))
            return

        if len(self.key_and_line_content_tup_list) &lt; 2:
            self.mb('Nothing (reasonable) found to sort; aborting!')
            return

        sorted_line_list = [tup[1] for tup in sorted(self.key_and_line_content_tup_list, reverse=self.do_descending_sort)]
        
        if self.matched_line_numbers:
            first_unmatched_line = search_start_line + len(self.matched_line_numbers) + 1
            self.mb('Line numbers {0}-{1} in sorted text were NOT matched.'.format(first_unmatched_line, search_end_line + 1),
                title='not all lines matched')
            for line_num in range(search_start_line, search_end_line + 1):
                if line_num not in self.matched_line_numbers:
                    unmatched_line = editor.getLine(line_num)
                    sorted_line_list.append(unmatched_line.rstrip('\r\n'))

        eol = ['\r\n', '\r', '\n'][editor.getEOLMode()]

        doc_len_before = editor.getLength()

        editor.setSelection(search_end_pos, search_start_pos)
        editor.replaceSel(eol.join(sorted_line_list))

        doc_len_delta = editor.getLength() - doc_len_before

        # leave sorted text selected:
        editor.setSelection(search_end_pos + doc_len_delta, search_start_pos)

    def match_found(self, m):

        self.zero_matches_for_regex = False

        # we're already corrupt; don't bother processing further matches after the one where we found the problem
        if self.user_did_not_specify_group1__ERROR: return
        if self.key_did_not_match_specified_type__ERROR: return
        if self.not_all_lines_matched__ERROR: return

        (start_pos_of_match, end_pos_of_match) = m.span(0)

        line_num_of_match = editor.lineFromPosition(start_pos_of_match)

        if line_num_of_match != self.last_matched_line_num + 1:
            if self.each_line_must_have_regex_group1_key_match:
                self.not_all_lines_matched__ERROR = True
                system_line_num_of_err = self.last_matched_line_num + 1
                self.user_line_num_of_error = system_line_num_of_err + 1
                return
        self.last_matched_line_num = line_num_of_match
        if self.sort_lines_that_dont_match_to_bottom:
            self.matched_line_numbers.add(line_num_of_match)

        try:
            g1_str = m.group(1)
        except IndexError:
            self.user_did_not_specify_group1__ERROR = True
            return

        try:
            key_with_correct_type = self.key_transform(g1_str)
        except ValueError:
            self.key_did_not_match_specified_type__ERROR = True
            self.user_line_num_of_error = line_num_of_match + 1
            return

        line_content = editor.getLine(line_num_of_match).rstrip('\n\r')

        tup = (key_with_correct_type, line_content)
        self.key_and_line_content_tup_list.append(tup)

    def option_check(self, input_text, option_text):
        m = re.search(r'\[([^]]+)\] ?{opt}'.format(opt=option_text), input_text)
        retval = True if m and m.group(1) != ' ' * len(m.group(1)) else False
        return retval

    def search_regex_is_invalid_error_msg(self, test_regex):
        try:
            # test test_regex for validity
            editor.research(test_regex, lambda _: None)
        except RuntimeError as r:
            return str(r)
        return ''

    def mb(self, msg, flags=0, title=''):  # a message-box function
        return notepad.messageBox(msg, title if title else self.this_script_name, flags)

    def mb_ok_cancel(self, msg, title=''):  # returns True(OK) or False(Cancel)
        okay = notepad.messageBox(msg, title if title else self.this_script_name, MESSAGEBOXFLAGS.OKCANCEL) == MESSAGEBOXFLAGS.RESULTOK
        return okay

    def prompt(self, prompt_text, default_text=''):
        if '\n' not in prompt_text: prompt_text = '\r\n' + prompt_text
        prompt_text += ':'
        return notepad.prompt(prompt_text, self.this_script_name, default_text)

#-------------------------------------------------------------------------------

if __name__ == '__main__': SLWRG1ASK()
</code></pre>
<p dir="auto">Maybe some day I’ll come up with a way to sort by arbitrary rearrangements of multiple groups like <code>\2\L\1\E</code>, but this is fine for now.</p>
<p dir="auto">EDIT: I suppose that sorting by <code>\2\L\1\E</code> could be accomplished by doing the find/replace with <code>\2\L\1\E🤷🤷$0</code> as replacement, then sort however you want, then find/replace <code>^.*🤷🤷</code> with nothing.</p>
<p dir="auto">--<br />
<em>Moderator EDIT (2024-Jan-14): The author of the script has found a fairly serious bug with the code published here for those that use Mac-style or Linux-style line-endings in their files.  The logic for Mac and Linux was reversed, and thus if the script was used on one type of file, the line-endings for the opposite type of file could end up in the file after the script is run.  This is insidious, because unless one works with visible line-endings turned on, this is likely not noticed.  Some detail on the problem is <a href="https://community.notepad-plus-plus.org/post/91918">HERE</a>.  The script above has been corrected per that instruction.</em></p>
]]></description><link>https://community.notepad-plus-plus.org/post/85664</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85664</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Sun, 14 Jan 2024 18:52:10 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Fri, 14 Apr 2023 02:54:20 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a> said in <a href="/post/85659">How i can sort number from largest to smallest on notepad++</a>:</p>
<blockquote>
<p dir="auto">(Yep, my ever-so-cheesy-UI)</p>
</blockquote>
<p dir="auto">Nice of you to acknowledge this. 🤓</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85663</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85663</guid><dc:creator><![CDATA[TBugReporter]]></dc:creator><pubDate>Fri, 14 Apr 2023 02:54:20 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Fri, 14 Apr 2023 02:06:52 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/alan-kilborn" aria-label="Profile: Alan-Kilborn">@<bdi>Alan-Kilborn</bdi></a><br />
Awesome! I don’t mind being upstaged at all, and it has all the features I would have wanted. I’ll play around with this and see if I can come up with improvements.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85662</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85662</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Fri, 14 Apr 2023 02:06:52 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 14 Jan 2024 18:51:01 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a> said:</p>
<blockquote>
<p dir="auto">I’m contemplating turning this script into a general-purpose thing to sort lines by the numeric or text value of any regex search result in that line.</p>
</blockquote>
<p dir="auto">Apologies to Mark for a possible upstaging, but I took this idea and ran with it, producing the following script called <code>SortLinesWithRegexGroup1AsSortKey.py</code>:</p>
<pre><code class="language-py"># -*- coding: utf-8 -*-
from __future__ import print_function

#########################################
#
#  SortLinesWithRegexGroup1AsSortKey (SLWRG1ASK)
#
#########################################

# references:
#  https://community.notepad-plus-plus.org/topic/24325

#-------------------------------------------------------------------------------

from Npp import *
import inspect
import os
import re
import threading
import SendKeys as sk

#-------------------------------------------------------------------------------

class SLWRG1ASK(object):

    def __init__(self):

        self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0]

        self.key_and_line_content_tup_list = []
        self.key_did_not_match_specified_type__ERROR = False
        self.user_did_not_specify_group1__ERROR = False
        self.not_all_lines_matched__ERROR = False
        self.last_matched_line_num = None
        self.user_line_num_of_error = None
        self.zero_matches_for_regex = True
        self.key_type__int_float_str = None
        self.do_descending_sort = False
        self.each_line_must_have_regex_group1_key_match = True
        self.remove_lines_that_dont_match_regex = False

        rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]
        if rect_sel_mode or editor.getSelections() &gt; 1:
            self.mb('Cannot operate on a column selection or multiple selections; aborting!')
            return

        if len(editor.getSelText()) == 0:
            if not self.mb_ok_cancel('No selection active; confirm desire to sort entire file by pressing OK.'):
                return

        (search_start_line, search_end_line) = editor.getUserLineSelection()
        if editor.positionFromLine(search_end_line) == editor.getSelectionEnd(): search_end_line -= 1
        num_lines_in_user_sel = search_end_line - search_start_line + 1
        if num_lines_in_user_sel &lt; 2: return  # if selection only on 1 line, nothing to do; already sorted!

        user_regex_with_group_1 = ''
        while True:
            user_regex_with_group_1 = self.prompt('Enter regex with group 1 being the sort key', user_regex_with_group_1)
            if user_regex_with_group_1 is None: return  # user cancel
            if len(user_regex_with_group_1.strip()) == 0:
                self.mb('Cannot specify an empty regex!  Try again.')
                continue
            if '(' not in user_regex_with_group_1:
                self.mb('Need to specify capture group 1 (as the sort key) in the regex!  Try again.')
                continue
            regex_err_msg = self.search_regex_is_invalid_error_msg(user_regex_with_group_1)
            if len(regex_err_msg) &gt; 0:
                self.mb('Bad regular expression!\r\n\r\n{e}\r\n\r\nTry again.'.format(e=regex_err_msg))
                continue
            break

        while True:
            threading.Timer(0.25, lambda : sk.SendKeys("{RIGHT}")).start()  # clear auto-selection of prompt text when box appears
            user_options = self.prompt(
                '    Regex specified: {r}\r\n'
                'Choose options by placing 1 x in each group (no need to x to get DEFAULT choice)'.format(r=user_regex_with_group_1),
                '\r\n'.join([
                    'Group 1 data type:  [   ]Integer(DEFAULT)      [   ]Decimal      [   ]String',
                    'Sort order:  [   ]Ascending(DEFAULT)    [   ]Descending',
                    'Other:',
                    '[   ]Sort-only-if-all-lines-have-group-1-match(DEFAULT)',
                    '[   ]Remove-non-matching-lines',
                ])
                )
            if user_options is None: return  # user cancel
            if len(user_options.strip()) == 0:
                self.mb('Cannot specify empty options!  Try again.')
                continue
            if self.option_check(user_options, 'String'): self.key_type__int_float_str = str
            elif self.option_check(user_options, 'Decimal'): self.key_type__int_float_str = float
            else: self.key_type__int_float_str = int
            self.do_descending_sort = self.option_check(user_options, 'Descending')
            self.each_line_must_have_regex_group1_key_match = self.option_check(user_options, 'Sort-only-if-all-lines-have-group-1-match')
            self.remove_lines_that_dont_match_regex = self.option_check(user_options, 'Remove-non-matching-lines')
            if not self.remove_lines_that_dont_match_regex: self.each_line_must_have_regex_group1_key_match = True
            if self.each_line_must_have_regex_group1_key_match and self.remove_lines_that_dont_match_regex:
                self.mb('Incorrect options checkmarked! Try again!')
                continue
            break

        # enforce single-line matching and only get the FIRST match on each line:
        user_regex_with_group_1 = '(?-s)' + user_regex_with_group_1 + '.*'

        search_start_pos = editor.positionFromLine(search_start_line)
        search_end_pos = editor.getLineEndPosition(search_end_line)

        # special "seeding", in case the very first line of the selection isn't hit:
        self.last_matched_line_num = search_start_line - 1

        editor.research(user_regex_with_group_1, lambda m: self.match_found(m), 0, search_start_pos, search_end_pos)

        if self.zero_matches_for_regex:
            self.mb('No lines matched the regex; aborting!')
            return

        if self.user_did_not_specify_group1__ERROR:
            self.mb('No sort key specified (via using capture group 1) in the regex; aborting!')
            return

        if self.key_did_not_match_specified_type__ERROR:
            self.mb('Key data did not match specified type ({t}) on line {L}; aborting!'.format(L=self.user_line_num_of_error,
                t={ int : 'Integer', float : 'Decimal', str : 'String' }[self.key_type__int_float_str]))
            return

        if self.each_line_must_have_regex_group1_key_match and self.not_all_lines_matched__ERROR:
            self.mb('Not every line in the source data matched the specified regex (first non-matching line was {L}); aborting!'.format(L=self.user_line_num_of_error))
            return

        if len(self.key_and_line_content_tup_list) &lt; 2:
            self.mb('Nothing (reasonable) found to sort; aborting!')
            return

        sorted_line_list = list(zip(*sorted(self.key_and_line_content_tup_list, reverse=self.do_descending_sort)))[1]

        eol = ['\r\n', '\r', '\n'][editor.getEOLMode()]
        doc_len_before = editor.getLength()

        editor.setSelection(search_end_pos, search_start_pos)
        editor.replaceSel(eol.join(sorted_line_list))

        doc_len_delta = editor.getLength() - doc_len_before

        # leave sorted text selected:
        editor.setSelection(search_end_pos + doc_len_delta, search_start_pos)

    def match_found(self, m):

        self.zero_matches_for_regex = False

        # we're already corrupt; don't bother processing further matches after the one where we found the problem
        if self.user_did_not_specify_group1__ERROR: return
        if self.key_did_not_match_specified_type__ERROR: return
        if self.not_all_lines_matched__ERROR: return

        (start_pos_of_match, end_pos_of_match) = m.span(0)

        line_num_of_match = editor.lineFromPosition(start_pos_of_match)

        if self.each_line_must_have_regex_group1_key_match:
            if line_num_of_match != self.last_matched_line_num + 1:
                self.not_all_lines_matched__ERROR = True
                system_line_num_of_err = self.last_matched_line_num + 1
                self.user_line_num_of_error = system_line_num_of_err + 1
                return
            self.last_matched_line_num = line_num_of_match

        try:
            g1_str = m.group(1)
        except IndexError:
            self.user_did_not_specify_group1__ERROR = True
            return

        try:
            key_with_correct_type = self.key_type__int_float_str(g1_str)
        except ValueError:
            self.key_did_not_match_specified_type__ERROR = True
            self.user_line_num_of_error = line_num_of_match + 1
            return

        line_content = editor.getLine(line_num_of_match).rstrip('\n\r')

        tup = (key_with_correct_type, line_content)
        self.key_and_line_content_tup_list.append(tup)

    def option_check(self, input_text, option_text):
        m = re.search(r'\[([^]]+)\] ?{opt}'.format(opt=option_text), input_text)
        retval = True if m and m.group(1) != ' ' * len(m.group(1)) else False
        return retval

    def search_regex_is_invalid_error_msg(self, test_regex):
        try:
            # test test_regex for validity
            editor.research(test_regex, lambda _: None)
        except RuntimeError as r:
            return str(r)
        return ''

    def mb(self, msg, flags=0, title=''):  # a message-box function
        return notepad.messageBox(msg, title if title else self.this_script_name, flags)

    def mb_ok_cancel(self, msg, title=''):  # returns True(OK) or False(Cancel)
        okay = notepad.messageBox(msg, title if title else self.this_script_name, MESSAGEBOXFLAGS.OKCANCEL) == MESSAGEBOXFLAGS.RESULTOK
        return okay

    def prompt(self, prompt_text, default_text=''):
        if '\n' not in prompt_text: prompt_text = '\r\n' + prompt_text
        prompt_text += ':'
        return notepad.prompt(prompt_text, self.this_script_name, default_text)

#-------------------------------------------------------------------------------

if __name__ == '__main__': SLWRG1ASK()
</code></pre>
<p dir="auto">Let’s walk thru using it on <a class="plugin-mentions-user plugin-mentions-a" href="/user/guy038" aria-label="Profile: guy038">@<bdi>guy038</bdi></a>’s data:</p>
<pre><code class="language-txt">This is a| 43 points
random | 82 points
Text to | 82 points
See how it works | 153 points
</code></pre>
<p dir="auto">Put those lines in a tab and select them and run the script.</p>
<p dir="auto">You get prompted:</p>
<p dir="auto"><img src="/assets/uploads/files/1681416543461-8707f9ef-328c-4b5c-a99c-5cf11caf8911-image.png" alt="8707f9ef-328c-4b5c-a99c-5cf11caf8911-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">Enter <code>\| (\d+) points</code> as this regex matches the desired sort key and places it in capture group 1:</p>
<p dir="auto"><img src="/assets/uploads/files/1681416605610-1aa0e2ee-32ec-4ae8-8b3a-90a4092aca6c-image.png" alt="1aa0e2ee-32ec-4ae8-8b3a-90a4092aca6c-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">and press OK/Enter.</p>
<p dir="auto">The next prompt is:</p>
<p dir="auto"><img src="/assets/uploads/files/1681416646456-f73dc53c-a24c-4dfd-b078-25969d1af90f-image.png" alt="f73dc53c-a24c-4dfd-b078-25969d1af90f-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">(Yep, my ever-so-cheesy-UI)</p>
<p dir="auto">Since we desire a high-to-low sort, “tick” the box for a <em>Descending</em> sort:</p>
<p dir="auto"><img src="/assets/uploads/files/1681416735399-c668f57c-5979-456b-808b-d27898c61d2f-image.png" alt="c668f57c-5979-456b-808b-d27898c61d2f-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">and press OK/Enter (accepting all the other “defaults” without needing to “tick” their boxes).</p>
<p dir="auto">Then the originally selected lines change to this data, the result of the specified sort:</p>
<pre><code class="language-txt">See how it works | 153 points
random | 82 points
Text to | 82 points
This is a| 43 points
</code></pre>
<p dir="auto">--<br />
<em>Moderator EDIT (2024-Jan-14): The author of the script has found a fairly serious bug with the code published here for those that use Mac-style or Linux-style line-endings in their files.  The logic for Mac and Linux was reversed, and thus if the script was used on one type of file, the line-endings for the opposite type of file could end up in the file after the script is run.  This is insidious, because unless one works with visible line-endings turned on, this is likely not noticed.  Some detail on the problem is <a href="https://community.notepad-plus-plus.org/post/91918">HERE</a>.  The script above has been corrected per that instruction.</em></p>
]]></description><link>https://community.notepad-plus-plus.org/post/85659</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85659</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Sun, 14 Jan 2024 18:51:01 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Thu, 06 Apr 2023 05:54:20 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/ling-danyelle" aria-label="Profile: ling-danyelle">@<bdi>ling-danyelle</bdi></a><br />
Yes, that would work in the specific case where the line <em>starts with</em> integers.<br />
But if the line doesn’t start with integers, as in the user’s example data, it will not work. That’s why we went to all this trouble to pre-process the text.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85525</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85525</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Thu, 06 Apr 2023 05:54:20 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Thu, 06 Apr 2023 04:35:43 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/zweafw" aria-label="Profile: zweafw">@<bdi>zweafw</bdi></a> said in <a href="/post/85399">How i can sort number from largest to smallest on notepad++</a>:</p>
<blockquote>
<p dir="auto">I’m new on Notepad++ and I want to know how can sort number from largest to smallest.</p>
</blockquote>
<p dir="auto">click on edit --&gt; line operation–&gt; sort lines as Integer descending</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85523</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85523</guid><dc:creator><![CDATA[ling danyelle]]></dc:creator><pubDate>Thu, 06 Apr 2023 04:35:43 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 21:10:31 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a>,<br />
I was thinking of taking a crack at it late this morning myself, but realized quickly…I’m not up to that kind of manipulation yet. :)</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85429</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85429</guid><dc:creator><![CDATA[Lycan Thrope]]></dc:creator><pubDate>Sun, 02 Apr 2023 21:10:31 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 14:05:17 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/guy038" aria-label="Profile: guy038">@<bdi>guy038</bdi></a><br />
I should know better than to ever count out our resident regex wizard…</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85417</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85417</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Sun, 02 Apr 2023 14:05:17 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 21:22:50 GMT]]></title><description><![CDATA[<p dir="auto">Hello, <a class="plugin-mentions-user plugin-mentions-a" href="/user/zweafw" aria-label="Profile: zweafw">@<bdi>zweafw</bdi></a>, <a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: mark-olson">@<bdi>mark-olson</bdi></a> and <strong>All</strong>,</p>
<p dir="auto">I think that a <strong>native</strong> N++ solution is possible !</p>
<p dir="auto">Let’s start with this <em>INPUT</em> text, below :</p>
<pre><code class="language-diff">This is a| 43 points
random | 82 points
Text to | 82 points
See how it works | 153 points
</code></pre>
<p dir="auto">With the following <strong>regex</strong> S/R :</p>
<p dir="auto">search <strong><code>(?x-s) ^ .+ \| \x20 ( .+ )</code></strong></p>
<p dir="auto">Replace <strong><code>\1\t$0</code></strong></p>
<p dir="auto">We get the <strong>temporary</strong> text :</p>
<pre><code class="language-diff">43 points	This is a| 43 points
82 points	random | 82 points
82 points	Text to | 82 points
153 points	See how it works | 153 points
</code></pre>
<p dir="auto">Now, run the <strong><code>Edit &gt; Line Operations &gt; Sort Lines As Integers Descending</code></strong> option</p>
<p dir="auto">We obtain this <strong>sorted</strong> file :</p>
<pre><code class="language-diff">153 points	See how it works | 153 points
82 points	random | 82 points
82 points	Text to | 82 points
43 points	This is a| 43 points
</code></pre>
<p dir="auto">Finally, with this <strong>last</strong> regex S/R :</p>
<p dir="auto">SEARCH <strong><code>^.+\t</code></strong></p>
<p dir="auto">REPLACE <strong><code>Leave EMPTY</code></strong></p>
<p dir="auto">Here is your <strong>expected</strong> <em>OUTPUT</em> text :</p>
<pre><code class="language-diff">See how it works | 153 points
random | 82 points
Text to | 82 points
This is a| 43 points
</code></pre>
<p dir="auto">Best Regards,</p>
<p dir="auto">guy038</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85415</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85415</guid><dc:creator><![CDATA[guy038]]></dc:creator><pubDate>Sun, 02 Apr 2023 21:22:50 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 05:09:24 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/zweafw" aria-label="Profile: zweafw">@<bdi>zweafw</bdi></a><br />
Since this is first and foremost a Notepad++ forum and not a forum for debugging python program, you can message me in chat <em>or</em> you can try to figure out how to solve these problems using the following references:</p>
<ul>
<li><a href="https://docs.python.org/3/howto/sorting.html" rel="nofollow ugc">how to sort lists in Python</a></li>
<li><a href="https://docs.python.org/3/library/re.html" rel="nofollow ugc">Python regular expressions</a></li>
<li><a href="https://npppythonscript.sourceforge.net/docs/latest/intro.html#notifications" rel="nofollow ugc">PythonScript plugin</a></li>
</ul>
]]></description><link>https://community.notepad-plus-plus.org/post/85410</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85410</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Sun, 02 Apr 2023 05:09:24 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 04:46:53 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a> thx its working but how i can change the script for sort number descending ( from largest to smaller )</p>
<p dir="auto">The script now its sort number ascending</p>
]]></description><link>https://community.notepad-plus-plus.org/post/85409</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85409</guid><dc:creator><![CDATA[zweafw]]></dc:creator><pubDate>Sun, 02 Apr 2023 04:46:53 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 04:42:32 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/zweafw" aria-label="Profile: zweafw">@<bdi>zweafw</bdi></a></p>
<pre><code class="language-py">from Npp import editor
import re

def number_after_pipe_in_line(line):
    numstr = re.search(r'\|\s*([+-]?\d+)\s+points?$', line)
    if not numstr:
        return float('inf')
    return float(numstr.group(1))

text = editor.getText()
linesep = re.search('\r?\n|\n', text).group(0)
lines = text.split(linesep)
sorted_by_num = sorted(lines, key=lambda x: number_after_pipe_in_line(x))
editor.setText(linesep.join(sorted_by_num))
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/85408</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85408</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Sun, 02 Apr 2023 04:42:32 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 04:39:51 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a> i have this new error :</p>
<pre><code>Traceback (most recent call last):
  File "C:\Program Files\Notepad++\plugins\PythonScript\scripts\trier.py", line 11, in &lt;module&gt;
    sorted_by_num = sorted(lines, key=lambda x: number_after_pipe_in_line(x))
  File "C:\Program Files\Notepad++\plugins\PythonScript\scripts\trier.py", line 11, in &lt;lambda&gt;
    sorted_by_num = sorted(lines, key=lambda x: number_after_pipe_in_line(x))
  File "C:\Program Files\Notepad++\plugins\PythonScript\scripts\trier.py", line 5, in number_after_pipe_in_line
    numstr = re.search(r'\|\s*([+-]?\d+)\s+points?$', line).group(1)
AttributeError: 'NoneType' object has no attribute 'group'
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/85407</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85407</guid><dc:creator><![CDATA[zweafw]]></dc:creator><pubDate>Sun, 02 Apr 2023 04:39:51 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 04:25:49 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/zweafw" aria-label="Profile: zweafw">@<bdi>zweafw</bdi></a><br />
bleh, should have read your data more carefullly.</p>
<pre><code class="language-py">from Npp import editor
import re

def number_after_pipe_in_line(line):
    numstr = re.search(r'\|\s*([+-]?\d+)\s+points?$', line).group(1)
    return float(numstr)

text = editor.getText()
linesep = re.search('\r?\n|\n', text).group(0)
lines = text.split(linesep)
sorted_by_num = sorted(lines, key=lambda x: number_after_pipe_in_line(x))
editor.setText(linesep.join(sorted_by_num))
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/85405</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85405</guid><dc:creator><![CDATA[Mark Olson]]></dc:creator><pubDate>Sun, 02 Apr 2023 04:25:49 GMT</pubDate></item><item><title><![CDATA[Reply to How i can sort number from largest to smallest on notepad++ on Sun, 02 Apr 2023 03:19:51 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/mark-olson" aria-label="Profile: Mark-Olson">@<bdi>Mark-Olson</bdi></a> hi thanks for the answer but i have this error when i start the script</p>
<pre><code>
Traceback (most recent call last):
  File "C:\Program Files\Notepad++\plugins\PythonScript\scripts\trier.py", line 11, in &lt;module&gt;
    sorted_by_num = sorted(lines, key=lambda x: number_after_pipe_in_line(x))
  File "C:\Program Files\Notepad++\plugins\PythonScript\scripts\trier.py", line 11, in &lt;lambda&gt;
    sorted_by_num = sorted(lines, key=lambda x: number_after_pipe_in_line(x))
  File "C:\Program Files\Notepad++\plugins\PythonScript\scripts\trier.py", line 6, in number_after_pipe_in_line
    return float(numstr)
ValueError: invalid literal for float(): 89 points

</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/85404</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/85404</guid><dc:creator><![CDATA[zweafw]]></dc:creator><pubDate>Sun, 02 Apr 2023 03:19:51 GMT</pubDate></item></channel></rss>