summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/default_config.cfg13
-rw-r--r--doc/en/configure.txt17
-rw-r--r--src/roster.py61
-rw-r--r--src/windows.py3
4 files changed, 75 insertions, 19 deletions
diff --git a/data/default_config.cfg b/data/default_config.cfg
index d674e098..aedd2413 100644
--- a/data/default_config.cfg
+++ b/data/default_config.cfg
@@ -223,6 +223,19 @@ show_roster_jids = true
# If set to true, the roster will display the offline contacts too
roster_show_offline = false
+# How to sort the contacts inside the roster groups.
+# They are used sequentially, (from left to right)
+# Available sorting methods are:
+# - reverse: reverse the sorting
+# - jid: sort by JID (alphabetical order)
+# - show: sort by show (available/away/xa/…)
+# - name: Sort by roster name (if no name, then the bare jid is used)
+# - resource: Sort by resource number
+# You can arrange them however you like, and you have to separate them with
+# underscores "_". Keep in mind that if there are more than 3 or 4 your sorting
+# is most likely inefficient.
+roster_sort = jid_show
+
# The terminal can beep on various event. Put the event you want in a list
# (separated by spaces).
# The events can be
diff --git a/doc/en/configure.txt b/doc/en/configure.txt
index f72d1627..aa880d7b 100644
--- a/doc/en/configure.txt
+++ b/doc/en/configure.txt
@@ -279,6 +279,23 @@ section of this documentation.
Set this to true if you want to display the offline contacts too.
+*roster_sort*:: jid_show
+
+ How you want the contacts to be sorted inside the roster groups. The given
+ methods are used sequentially (from left to right), so the last one is the
+ one on the far right.
+
+ Available methods are :
+ * reverse: reverse the current sorting
+ * jid: sort by JID (alphabetical order)
+ * show: sort by show (available/away/xa/…)
+ * name: Sort by roster name (if no name, then the bare jid is used)
+ * resource: Sort by resource number
+
+ Those methods can be arranged however you like, and they have to be
+ separated by underscores ("_"). If there are more than 3 or 4 chained
+ sorting methods, your sorting is most likely inefficient.
+
*beep_on*:: highlight private
The terminal can beep on various event. Put the event you want in a list
diff --git a/src/roster.py b/src/roster.py
index 56c65d8f..84771678 100644
--- a/src/roster.py
+++ b/src/roster.py
@@ -198,12 +198,37 @@ class Roster(object):
except IOError:
return
-PRESENCE_PRIORITY = {'unavailable': 0,
- 'xa': 1,
- 'away': 2,
- 'dnd': 3,
- '': 4,
- 'available': 4}
+PRESENCE_PRIORITY = {'unavailable': 5,
+ 'xa': 4,
+ 'away': 3,
+ 'dnd': 2,
+ '': 1,
+ 'available': 1}
+
+def sort_jid(contact):
+ return contact.bare_jid
+
+def sort_show(contact):
+ res = contact.get_highest_priority_resource()
+ if not res:
+ return 0
+ show = res.presence
+ if show not in PRESENCE_PRIORITY:
+ return 0
+ return PRESENCE_PRIORITY[show]
+
+def sort_resource_nb(contact):
+ return - len(contact)
+
+def sort_name(contact):
+ return contact.name.lower() or contact.bare_jid
+
+SORTING_METHODS = {
+ 'jid': sort_jid,
+ 'show': sort_show,
+ 'resource': sort_resource_nb,
+ 'name': sort_name,
+}
class RosterGroup(object):
"""
@@ -244,20 +269,19 @@ class RosterGroup(object):
if contact in self.contacts:
self.contacts.remove(contact)
- def get_contacts(self, contact_filter):
+ def get_contacts(self, contact_filter=None, sort=''):
"""Return the group contacts, filtered and sorted"""
- def compare_contact(a):
- res = a.get_highest_priority_resource()
- if not res:
- return 0
- show = res.presence
- if show not in PRESENCE_PRIORITY:
- return 5
- return PRESENCE_PRIORITY[show]
- contact_list = self.contacts if not contact_filter\
+ contact_list = self.contacts.copy() if not contact_filter\
else [contact for contact in self.contacts.copy() if contact_filter[0](contact, contact_filter[1])]
- contact_list = sorted(contact_list, key=lambda x: x.bare_jid)
- return sorted(contact_list, key=compare_contact, reverse=True)
+
+ for sorting in sort.split('_'):
+ method = SORTING_METHODS.get(sorting, lambda x: 0)
+ if sorting == 'reverse':
+ contact_list = list(reversed(contact_list))
+ else:
+ contact_list = sorted(contact_list, key=method)
+ return contact_list
+
def toggle_folded(self):
"""Fold/unfold the group in the roster"""
@@ -273,5 +297,6 @@ class RosterGroup(object):
"""Return the number of connected contacts"""
return len([1 for contact in self.contacts if contact.resources])
+
# Shared roster object
roster = Roster()
diff --git a/src/windows.py b/src/windows.py
index a46edb1e..da80c989 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -1609,6 +1609,7 @@ class RosterWin(Win):
self.draw_roster_information(roster)
y = 1
show_offline = config.get('roster_show_offline', 'false') == 'true'
+ sort = config.get('roster_sort', 'jid_show') or 'jid_show'
for group in roster.get_groups()[:]:
contacts_filtered = group.get_contacts(roster.contact_filter)
if (not show_offline and group.get_nb_connected_contacts() == 0) or not contacts_filtered:
@@ -1621,7 +1622,7 @@ class RosterWin(Win):
y += 1
if group.folded:
continue
- for contact in group.get_contacts(roster.contact_filter)[:]:
+ for contact in group.get_contacts(roster.contact_filter, sort):
if not show_offline and len(contact) == 0:
continue
if y-1 == self.pos: