Skip to content

Commit

Permalink
Re-work sorting of notes in list index
Browse files Browse the repository at this point in the history
This somewhat goes all the back to commit:
729f151 where I somewhat lazily made
Python 3 compatible by using the `cmp_to_key` function.

Finally getting around to looking into #97 I realised the only way to
fix that issue was moving the sorting to an iterative based approach
where, say if we are sorting on "pinned, tags, modifydate", we first sort
the notes on modifydate, then go through them again and sort on tags and
finally on the primary key of pinned.

The `cmp_to_key` based function can't do this as it's only really doing
a single iteration through the notes, but trying to check all the
criteria (by iterating through the criteria) at once. This is why we
ended up with little groups within tags sorted by modified date.

Anyway, as a result of all this it's actually a lot simpler.

- Sort by tag is purely on existence of tags now (no alpha sort or
  number of tags sort)
- We are sorting tags within a note by alpha for display purposes; This
  should be moved to Simplenote.py

I've probably not explained any of that well.

Fixes: #97
  • Loading branch information
atomicules committed Mar 4, 2018
1 parent 30f48f7 commit 29d52cc
Showing 1 changed file with 21 additions and 74 deletions.
95 changes: 21 additions & 74 deletions autoload/SimplenoteUtilities.py
Expand Up @@ -670,7 +670,24 @@ def list_note_index_in_scratch_buffer(self, since=None, tags=[]):
if status == 0:
note_titles = []
notes = self.get_notes_from_keys([n['key'] for n in note_list])
notes.sort(key=functools.cmp_to_key(compare_notes))
# Iterate through sorts here, need to reverse this because we finish with the primary sort
sortorder = list(reversed(vim.eval("s:sortorder").split(",")))
sorted_notes = notes
for compare_type in sortorder:
compare_type = compare_type.strip()
if compare_type == "pinned":
sorted_notes = sorted(sorted_notes, key=lambda n: "pinned" in n["systemtags"], reverse=True)
elif compare_type == "modifydate":
sorted_notes = sorted(sorted_notes, key=lambda n: float(n["modifydate"]), reverse=True)
elif compare_type == "createdate":
sorted_notes = sorted(sorted_notes, key=lambda n: float(n["createdate"]), reverse=True)
elif compare_type == "tags":
# existence of a tag only
sorted_notes = sorted(sorted_notes, key=lambda n: len(n["tags"]) == 0)
elif compare_type == "title":
# Ignore case
sorted_notes = sorted(sorted_notes, key=lambda n: str.lower(get_note_title(n)))
notes = sorted_notes
note_titles = [self.format_title(n) for n in notes]
self.note_index = [n["key"] for n in notes]
buffer[:] = note_titles
Expand All @@ -691,79 +708,6 @@ def get_note_title(note):
return str(note_lines[0] if len(note_lines) > 0 else note["key"])


def compare_notes(note1, note2):
""" determine the sort order for two passed in notes
Parameters:
note1 - first note object
note2 - second note object
Returns -1 if the first note is considered smaller, 0 for equal
notes and 1 if the first note is considered larger
"""
# setup compare functions
def compare_pinned(note1, note2):
if ("pinned" in note1["systemtags"] and
"pinned" not in note2["systemtags"]):
return -1
elif ("pinned" in note2["systemtags"] and
"pinned" not in note1["systemtags"]):
return 1
else:
return 0


def compare_modified(note1, note2):
if float(note1["modifydate"]) < float(note2["modifydate"]):
return 1
elif float(note1["modifydate"]) > float(note2["modifydate"]):
return -1
else:
return 0

def compare_created(note1, note2):
if float(note1["createdate"]) < float(note2["createdate"]):
return 1
elif float(note1["createdate"]) > float(note2["createdate"]):
return -1
else:
return 0

def compare_tags(note1, note2):
if note1["tags"] < note2["tags"]:
return 1
if note1["tags"] > note2["tags"]:
return -1
else:
return 0

def compare_alpha(note1, note2):
title1 = get_note_title(note1)
title2 = get_note_title(note2)
return (title1 > title2) - (title1 < title2)

# dict for dynamically calling compare functions
sortfuncs = {
"pinned": compare_pinned,
"createdate": compare_created,
"modifydate": compare_modified,
"tags": compare_tags,
"title": compare_alpha,
}

sortorder = vim.eval("s:sortorder").split(",")

for key in sortorder:
res = sortfuncs.get(key.strip(),lambda x,y: 0)(note1, note2)
if res != 0:
return res

# return equal if no comparison hit
return 0




class NoteFetcher(Thread):
""" class to fetch a note running in a thread
Expand All @@ -780,6 +724,9 @@ def __init__(self, queue, note_list, simplenote):
def run(self):
key = self.queue.get()
note, status = self.simplenote.get_note(key)
# Sort tags alphabetically
# TODO: Move this to simplenote.py
note["tags"] = sorted(note["tags"])
if status != -1:
self.note_list.append(note)

Expand Down

3 comments on commit 29d52cc

@Viqsi
Copy link

@Viqsi Viqsi commented on 29d52cc Mar 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: you'll want to move that "sort tags alphabetically" bit into the status check block, because if a note couldn't be retrieved from the SimpleNote server, assuming that the "tags" field is present will cause Vim to hang as a result of that unhandled KeyError. (For some reason there's a nonexistent note in my account that constantly returns 404 Not Found any time one tries to retrieve the note itself that nonetheless shows up in listings, so I was getting hangs every time I tried to do a note listing that included said note.)

@atomicules
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drat... thanks for letting me know... I'll try to do what I've said todo and move that to simplenote.py soon.

@atomicules
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Viqsi Should be fixed now. Hopefully. Sorry about that.

Please sign in to comment.