How to sort networkmanager-dmenu output

I freely admit my ignorance with dmenu and rofi, however i did do some googlin on this. I like to use this script from polybar. I would like the list to be alphabetized which at this point it is not. I have a longer list due to my VPN. When i access the list from nm-applet it is in alphabetical order.

so i tried to add | sort; to the end but it didnt seem to work: ie

dmenu_command = rofi -l 20 -columns 3 -width 70 -location 2 -font “Ubuntu Light 10”

to:

dmenu_command = rofi -l 20 -columns 3 -width 70 -location 2 -font “Ubuntu Light 10” | sort;

so has this anything to do with the -levenshtein-sort option?

any suggestions or a link would be greatly appreciated

Hello, I was bored and did some research for this topic.
The workaround is the following:

  1. Locate to /usr/bin/ in a root-elevated File Manager
  2. Open networkmanager_dmenu (the python script)
  3. Find the following line:

aps_all = sorted(adapter.get_access_points(),
key=lambda a: a.get_strength(), reverse=True)

it should be located in the function called def create_ap_list(adapter, active_connections):

  1. Replace this line with the following

aps_all = sorted(adapter.get_access_points(),
key=lambda a: ssid_to_utf8(a), reverse=True)

Notice how only one part changed? Namely the ssid_to_utf8(a) part that I wrote bold.

  1. Save and retry.

It worked for me, however the output was reverse (From Z to A). Set the reverse=True to reverse=False in case you want it different.

This is weird, first I fixed shell script and now Python script, I only programmed in Python once… Anyways, let me know if this worked.

This reminded me of how much I dislike object oriented code… I had to google all the class inheritance and whatnot. And this duck typing by Python makes matters even worse, because you don’t know WHAT type it is… Luckily they used some special long function names like, you won’t get smarter about the class name/type if you see the typical

a.get_name()

Ah well, just my usual rant…

@MuradTroll Lol, nice job once again :slight_smile:

Correct me if I am wrong but isn’t the list sorted by signal strength? This make most sense, regardless of the ssid you want the ones closest and with the best signal strength listed first.

1 Like

I also thought this was the case.

Hmm, I thought he wanted to have the list alphabetized (and only that, without taking the signal strength into account). According to

https://lazka.github.io/pgi-docs/#NM-1.0/classes/AccessPoint.html#NM.AccessPoint.get_strength

the strength is an integer between 0 and 100. That means that the likelihood of two networks having the same strength approaches 0. Therefore, trying to sort by strength first and then by name would probably result in the same output as if it were sorted only by strength (because each AccessPoint has its own strength like 81, 82, 64, 22, etc). A better way would be to map them.

The asterisks indicating the strength are made by the function NM.utils_wifi_strength_bars( *strength* ). The function returns a string that has asterisks from 0 to 4. Now there are multiple ways to fix this issue, here is one:

  1. Locate to /usr/bin/ in a root-elevated File Manager (or you can’t save the new script)
  2. Open networkmanager_dmenu (the python script)
  3. Find the following line:

aps_all = sorted(adapter.get_access_points(),
key=lambda a: a.get_strength(), reverse=True)

it should be located in the function called def create_ap_list(adapter, active_connections):

  1. Replace this line with the following

aps_all = sorted(adapter.get_access_points(),
key=lambda a: mysort(a) , reverse=False)

The bold parts changed.

  1. Before the function def create_ap_list(adapter, active_connections): copy and paste this new sorting function:

def mysort(a):
bars = NM.utils_wifi_strength_bars(a.get_strength()) # asterisks from 0 to 4 characters
strength = bars.count(’*’) # count the ammount of asterisks
return str(4-strength) + ssid_to_utf8(a)

I don’t know how to insert tabs here but you have to align the last the lines with 1 tab.

  1. Save and retry (editor needs root privileges to save)
    Result (first sorted by strenght, and then by name):

EDIT: Or if you don’t like adding a seperate function, you could change the sorting lambda itself by replacing it with another one liner. Go to step 4 and replace with this insetead:

aps_all = sorted(adapter.get_access_points(),key=lambda a: str(4-(NM.utils_wifi_strength_bars(a.get_strength())).count(’*’)) + ssid_to_utf8(a) , reverse=False)

yes, this is all one line.

1 Like

You like fiddling with stuff eh?

You can linebreak in function calls just like C, best practice is after a ,

aps_all = sorted(adapter.get_access_points(), key=lambda a: str(4-(
    NM.utils_wifi_strength_bars(
        a.get_strength())).count(’*’)) + ssid_to_utf8(a), reverse=False)

In python you can concatenate strings with + or use the format() method, tabs are the usual \t

s = "some"
print(s + "\ttext")  # works with " or ' python doesn't care

s = "some{0}{val}".format("\t", val="text") # can be keyword or positional args
print(s)

Ah no, I meant inserting tab in the forum, specifically im the blockquote :smile: Look at the mysort() function I wrote, in my editor the last 3 lines are tabbed (because they belong to a function) but here it doesn’t look tabbed. People that copy this from here will probably get errors, that’s why I wanted to insert some tabs inside the “blockquote”