import base import std/[os,strutils,sequtils,times] const note_dir = getHomeDir() & "Nextcloud/.notes.dmenu/" # Putting it in Nextcloud so it can sync :-) const default_bg = white const default_fg = black type Note = object id: string text: string proc startNotes() proc displayOptionMenu(option: string) var notes: seq[Note] = @[] proc readNotes(): seq[Note] = if len(notes) == 0: if existsOrCreateDir(note_dir): for note_file in walkDir(note_dir): try: var note = Note() note.id = note_file[1] note.text = readFile(note_file[1]) notes.add(note) except: echo "Unable to read note : ", note_file, " : ", getCurrentExceptionMsg() return notes proc removeNote(note: Note) = try: removeFile(note.id) for idx, a_note in notes: if note.id == a_note.id: notes.delete(idx) except: echo "Unable to delete file : ", note.id, " : ", getCurrentExceptionMsg() proc getNoteStrings(): seq[string] = var note_list: seq[string] = @[] if len(notes) == 0: discard readNotes() for note in notes: note_list.add(note.text) return note_list proc writeNote(note: Note, is_new: bool = false) = if note.text == "": return try: writeFile(note.id, note.text) if is_new: notes.add(note) else: for idx, a_note in notes: if a_note.id == note.id: notes[idx].text = note.text except: echo "write_note, Unable to write note : ", note.id, " : ", getCurrentExceptionMsg() proc getNotes(): (Info, seq[string]) = var info = newInfo("Notes") info.selected_bg = default_bg info.selected_fg = default_fg let notes = getNoteStrings() return (info,notes) proc getNote(text: string): Note = for note in notes: if note.text == text: return note return Note() proc displayDeleteConfirmationMenu(note: string) = var yes_no = newInfo("Confirm Delete note : " & note) yes_no.selected_bg = default_bg yes_no.selected_fg = default_fg let args = @["yes", "no"] let choice = outputData(yes_no, args) case choice: of "yes": let rm_note = getNote(note) if rm_note.text == note: removeNote(rm_note) of "no": displayOptionMenu(note) proc replaceNote(new_text: string, old_text: string) = for idx, note in notes: if note.text == old_text: var new_note = note new_note.text = new_text notes[idx] = new_note writeNote(new_note) return proc displayOptionMenu(option: string) = var select = newInfo("Note") select.selected_bg = default_bg select.selected_fg = default_fg let note_choices = @["rm","back"] let args = concat(@[option],note_choices) let chosen = outputData(select,args) if chosen in note_choices: case chosen: of "rm": displayDeleteConfirmationMenu(option) startNotes() of "back": startNotes() elif chosen != "" and chosen != option: replaceNote(chosen, option) displayOptionMenu(chosen) else: displayOptionMenu(option) proc newNote(text: string) = var new_note = Note() let note_id = times.now().format("yyyyMMddHHmmssffffff") new_note.id = note_dir & note_id new_note.text = text writeNote(new_note, is_new = true) proc startNotes() = let (info,all_notes) = getNotes() let all_choices = @["exit"] let args = concat(all_notes, all_choices) let option = outputData(info, args) if option in all_choices: case option: of "exit": return if option in all_notes: displayOptionMenu(option) elif option != "": newNote(option) startNotes() proc main() = echo "Note dir : ", note_dir if not dmenu and not rofi: echo "Can only be run in dmenu or rofi mode. Exiting..." return startNotes() if isMainModule: main()