0

Is it possible to lexicographically sort lines (ascending/descending) with TeXstudio's editor? Switching to a third-party text editor is, of course, an option, but it seems weird to me that I cannot find the way to perform such a simple task in TeXstudio.

I have a separate list with glossary entries (over a thousand lines), but for the sake of simplicity consider the following example:

Unsorted list:

\newacronym{cba}{cba}{reversed alphabetic sequence}    
\newacronym{123}{123}{first, second, third}
\newacronym{ABC}{ABC}{alphabetic sequence}

Ascendingly sorted lines:

\newacronym{123}{123}{first, second, third}
\newacronym{ABC}{ABC}{alphabetic sequence}
\newacronym{cba}{cba}{reversed alphabetic sequence}
  • 2
    There's a script for this on TeXstudio wiki: sourceforge.net/p/texstudio/wiki/Scripts/#sorting – Troy Sep 21 '17 at 14:59
  • @Troy Thank you, that looks like an option, though for a person without a background in CS it's not entirely obvious how to tweak the script for ascending/descending sorting. Does it also mean that there is no native option in the program to sort lines? – andselisk Sep 21 '17 at 15:03
  • @andselisk For ascending order you don't have to tweak anything. – user36296 Sep 21 '17 at 15:08
  • @samcarter Indeed, but I have no idea how to reverse the order and add additional options such as numbers first/last; capital letters first/last etc. Practically every standalone text editor has tons of easily accessible options for sorting, but I cannot find those in TeXstudio, which bothers be. – andselisk Sep 21 '17 at 15:12
  • 2
    @andselisk for descending: use a.reverse() after the sorting. If you need more fine control over the sorting, consider the usage of custom sorting function, see w3schools.com/jsref/jsref_sort.asp for details. – user36296 Sep 21 '17 at 15:16
4

A simplistic script is provided in the TeXstudio wiki: https://sourceforge.net/p/texstudio/wiki/Scripts/#sorting

If you would like to implement this, go to Macros -> Edit Macros.

%SCRIPT
var a = new Array();
for (var i=0;i<editor.document().lineCount();i++)
  a.push(editor.text(i));
a.sort();
var t = "";
for (var l in a) t+= a[l]+"\n";
editor.setText(t);

Highlight the portion of your file which you would like to sort, then call the macro. (By default, the keyboard shortcut for this is Shift+F1 (or other function keys).)

Note that the sorting happens at a.sort();, which is a built-in sorting function from QTScript (TeXstudio macros are interpreted in QTscript (closely related to Javascript). Thus, if you would like to customize this sorting capability (like capital letters last, etc.) it would not be so straightforward.

Implementing the reverse (descending) order is relatively easy, however.


Disclaimer: I'm not an expert in QTScript, but the below should serve your purpose for a descending order.

That is, the result would be:

\newacronym{cba}{cba}{reversed alphabetic sequence}    
\newacronym{ABC}{ABC}{alphabetic sequence}
\newacronym{123}{123}{first, second, third}

The script is a minor change from the one above:

%SCRIPT
var a = new Array();
for (var i=0;i<editor.document().lineCount();i++)
  a.push(editor.text(i));
a.sort();
var t = "";
for (var l in a) t+= a[a.length-1-l]+"\n";
editor.setText(t);

Ninja edit: @samcarter's solution for descending order is better.

%SCRIPT
var a = new Array();
for (var i=0;i<editor.document().lineCount();i++)
  a.push(editor.text(i));
a.sort();
a.reverse();
var t = "";
for (var l in a) t+= a[l]+"\n";
editor.setText(t);
1

The code below will also expand the current selection to match entire lines and then sort it. The other scripts here were not taking into account the selection, so I fixed it.

%SCRIPT
function expandSelection() {
/* Will expand the selection to match entire lines
    or the entire document if nothing is selected.
    This could be easily altered by removing the Else clause.
*/
    if (cursor.hasSelection()) {
        // Gets the first and last line of selection
        // (can be done upwards or downwards)
        var selectBeg = Math.min(cursor.lineNumber(), cursor.anchorLineNumber());
        var selectEnd = Math.max(cursor.lineNumber(), cursor.anchorLineNumber());

        // Expands the selection 
        cursor = editor.document().cursor(selectBeg, 0, selectEnd);
    } else {
        // Expands the selection to all the lines   
        cursor = editor.document().cursor(0, 0, editor.document().lineCount());
    }
}

var mySorting = function(A, B) {
/* This function returns -1 when A is first in alphabetical order than B
    1 when B is first
    0 when they're the same
*/
    A = A.toLowerCase();
    B = B.toLowerCase();

    if (A < B) {
        return -1;
    } else if (B < A) {
        return 1;
    } else {
        0
    }
}

expandSelection();

var eol       = editor.document().lineEndingString(); //'\n' probably would've worked just fine, but I wanted to be fancy
var inputText = cursor.selectedText().split(eol).sort(mySorting).join(eol);

cursor.replaceSelectedText(inputText);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.