nncli

NextCloud Notes Command Line Interface
git clone git://git.danielmoch.com/nncli.git
Log | Files | Refs | LICENSE

commit ea9051f592ec9a13458e19d65b2d1a98bf34a3ec
parent cf3b825ef32323ca6ce49afbd0a2126001a2183b
Author: Eric Davis <edavis@insanum.com>
Date:   Thu,  3 Jul 2014 02:15:13 -0700

single view objects now initialized and tweaked as needed based on input

Diffstat:
Msncli.py | 122+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Mview_help.py | 5++++-
Mview_log.py | 5++++-
Mview_note.py | 47+++++++++++++++++++++++++++++++----------------
Mview_titles.py | 69++++++++++++++++++---------------------------------------------------
5 files changed, 136 insertions(+), 112 deletions(-)

diff --git a/sncli.py b/sncli.py @@ -2,9 +2,9 @@ import os, sys, re, signal, time, datetime, logging import subprocess, thread, threading -import copy, json, urwid, datetime, tempfile +import copy, json, urwid, datetime import view_titles, view_note, view_help, view_log, user_input -import utils +import utils, temp from config import Config from simplenote import Simplenote from notes_db import NotesDB, SyncError, ReadError, WriteError @@ -19,8 +19,6 @@ def __init__(self, do_sync): if not os.path.exists(self.config.get_config('db_path')): os.mkdir(self.config.get_config('db_path')) - self.tempfile = None - # configure the logging module self.logfile = os.path.join(self.config.get_config('db_path'), 'sncli.log') self.loghandler = RotatingFileHandler(self.logfile, maxBytes=100000, backupCount=1) @@ -55,6 +53,24 @@ def __init__(self, do_sync): self.ndb.add_observer('change:note-status', self.observer_notes_db_change_note_status) self.ndb.add_observer('progress:sync_full', self.observer_notes_db_sync_full) + self.view_titles = \ + view_titles.ViewTitles(self.config, + { + 'ndb' : self.ndb, + 'search_string' : None, + 'status_message' : self.status_message_set + }) + self.view_note = \ + view_note.ViewNote(self.config, + { + 'ndb' : self.ndb, + 'key' : None, + 'status_message' : self.status_message_set + }) + + self.view_log = view_log.ViewLog(self.config) + self.view_help = view_help.ViewHelp(self.config) + def start_threads(self): self.thread_save.start() self.thread_sync.start() @@ -170,19 +186,18 @@ def update_status_bar(self): else: self.header_set(self.body_get().get_status_bar()) - def switch_frame_body(self, args): - if args == None: + def switch_frame_body(self, new_view, save_current_view=True): + if new_view == None: if len(self.last_view) == 0: # XXX verify all notes saved... - self.sncli_loop.widget = None raise urwid.ExitMainLoop() else: self.body_set(self.last_view.pop()) - return - - if self.body_get().__class__ != args['view']: - self.last_view.append(self.body_get()) - self.body_set(args['view'](self.config, args)) + else: + if self.body_get().__class__ != new_view.__class__: + if save_current_view: + self.last_view.append(self.body_get()) + self.body_set(new_view) def search_quit(self): self.footer_clear() @@ -194,23 +209,17 @@ def search_input(self, search_string): self.body_focus() self.master_frame.keypress = self.frame_keypress if search_string: - self.body_set( - view_titles.ViewTitles(self.config, - { - 'ndb' : self.ndb, - 'search_string' : search_string, - 'body_changer' : self.switch_frame_body, - 'status_message' : self.status_message_set - })) + self.view_titles.update_note_list(search_string) + self.body_set(self.view_titles) def tags_input(self, tags): self.footer_clear() self.body_focus() self.master_frame.keypress = self.frame_keypress if tags != None: - lb = self.body_get() - self.ndb.set_note_tags(lb.all_notes[lb.focus_position].note['key'], tags) - lb.update_note_title(None, lb.focus_position) + self.ndb.set_note_tags( + self.view_titles.note_list[self.view_titles.focus_position].note['key'], tags) + self.view_titles.update_note_title(None) def frame_keypress(self, size, key): @@ -220,10 +229,10 @@ def frame_keypress(self, size, key): self.switch_frame_body(None) elif key == self.config.get_keybind('help'): - self.switch_frame_body({ 'view' : view_help.ViewHelp }) + self.switch_frame_body(self.view_help) elif key == self.config.get_keybind('view_log'): - self.switch_frame_body({ 'view' : view_log.ViewLog }) + self.switch_frame_body(self.view_log) elif key == self.config.get_keybind('down'): if len(lb.body.positions()) <= 0: @@ -312,6 +321,33 @@ def frame_keypress(self, size, key): else: self.status_bar = self.config.get_config('status_bar') + elif key == self.config.get_keybind('view_note'): + # only when viewing the note list + if self.body_get().__class__ == view_titles.ViewTitles: + self.view_note.update_note(lb.note_list[lb.focus_position].note['key']) + self.switch_frame_body(self.view_note) + + elif key == self.config.get_keybind('view_note_ext'): + # only when viewing the note list + if self.body_get().__class__ == view_titles.ViewTitles: + pager = None + if self.config.get_config('pager'): + pager = self.config.get_config('pager') + if not pager and os.environ['PAGER']: + pager = os.environ['PAGER'] + if not pager: + self.status_message(u'No pager configured!') + return None + + tf = temp.tempfile_create(lb.note_list[lb.focus_position].note) + try: + subprocess.check_call(pager + u' ' + temp.tempfile_name(tf), shell=True) + except Exception, e: + self.status_message_set(u'Pager error: ' + str(e)) + + # XXX check if modified, if so update it + temp.tempfile_delete(tf) + elif key == self.config.get_keybind('search'): # search when viewing the note list if self.body_get().__class__ == view_titles.ViewTitles: @@ -324,6 +360,20 @@ def frame_keypress(self, size, key): self.footer_focus() self.master_frame.keypress = self.footer_get().keypress + elif key == self.config.get_keybind('note_pin'): + # pin note when viewing the note list + if self.body_get().__class__ == view_titles.ViewTitles: + self.ndb.set_note_pinned( + lb.note_list[lb.focus_position].note['key'], 1) + lb.update_note_title(None) + + elif key == self.config.get_keybind('note_unpin'): + # unpin note when viewing the note list + if self.body_get().__class__ == view_titles.ViewTitles: + self.ndb.set_note_pinned( + lb.note_list[lb.focus_position].note['key'], 0) + lb.update_note_title(None) + elif key == self.config.get_keybind('note_tags'): # edit tags when viewing the note list if self.body_get().__class__ == view_titles.ViewTitles: @@ -332,21 +382,15 @@ def frame_keypress(self, size, key): urwid.AttrMap( user_input.UserInput(self.config, 'Tags: ', - '%s' % ','.join(lb.all_notes[lb.focus_position].note['tags']), + '%s' % ','.join(lb.note_list[lb.focus_position].note['tags']), self.tags_input), 'search_bar')) self.footer_focus() self.master_frame.keypress = self.footer_get().keypress elif key == self.config.get_keybind('clear_search'): - self.body_set( - view_titles.ViewTitles(self.config, - { - 'ndb' : self.ndb, - 'search_string' : None, - 'body_changer' : self.switch_frame_body, - 'status_message' : self.status_message_set - })) + self.view_titles.update_note_list(None) + self.body_set(self.view_titles) else: return lb.keypress(size, key) @@ -356,15 +400,7 @@ def frame_keypress(self, size, key): def init_view(self, loop, arg): self.master_frame.keypress = self.frame_keypress - self.body_set( - view_titles.ViewTitles(self.config, - { - 'ndb' : self.ndb, - 'search_string' : None, - 'body_changer' : self.switch_frame_body, - 'status_message' : self.status_message_set - })) - + self.body_set(self.view_titles) self.start_threads() if self.do_sync: diff --git a/view_help.py b/view_help.py @@ -3,7 +3,7 @@ class ViewHelp(urwid.ListBox): - def __init__(self, config, args): + def __init__(self, config): self.config = config lines = [] @@ -147,3 +147,6 @@ def create_color_help_lines(self): )) return lines + def keypress(self, size, key): + return key + diff --git a/view_log.py b/view_log.py @@ -3,7 +3,7 @@ class ViewLog(urwid.ListBox): - def __init__(self, config, args): + def __init__(self, config): self.config = config f = open(self.config.logfile) lines = [] @@ -38,3 +38,6 @@ def get_status_bar(self): urwid.AttrMap(urwid.Columns([ status_title, status_index ]), 'status_bar') + def keypress(self, size, key): + return key + diff --git a/view_note.py b/view_note.py @@ -6,22 +6,37 @@ class ViewNote(urwid.ListBox): def __init__(self, config, args): self.config = config - self.note = args['note'] + self.ndb = args['ndb'] + self.key = args['key'] + self.note = self.ndb.get_note(self.key) if self.key else None + self.tabstop = int(self.config.get_config('tabstop')) super(ViewNote, self).__init__( - urwid.SimpleFocusListWalker( - self.get_note_content_as_list( - int(self.config.get_config('tabstop'))))) + urwid.SimpleFocusListWalker(self.get_note_content_as_list())) - def get_note_content_as_list(self, tabstop): + def get_note_content_as_list(self): lines = [] + if not self.key: + return lines for l in self.note['content'].split('\n'): lines.append( - urwid.AttrMap(urwid.Text(l.replace('\t', ' ' * tabstop)), + urwid.AttrMap(urwid.Text(l.replace('\t', ' ' * self.tabstop)), 'note_content', 'note_content_focus')) return lines + def update_note(self, key): + self.key = key + self.note = self.ndb.get_note(self.key) if self.key else None + self.body[:] = \ + urwid.SimpleFocusListWalker(self.get_note_content_as_list()) + self.focus_position = 0 + def get_status_bar(self): + if not self.key: + return \ + urwid.AttrMap(urwid.Text(u'No note...'), + 'status_bar') + cur = -1 total = 0 if len(self.body.positions()) > 0: @@ -62,22 +77,22 @@ def get_status_bar(self): def keypress(self, size, key): if key == self.config.get_keybind('tabstop2'): + self.tabstop = 2 self.body[:] = \ - urwid.SimpleFocusListWalker( - self.get_note_content_as_list(2)) - return None + urwid.SimpleFocusListWalker(self.get_note_content_as_list()) elif key == self.config.get_keybind('tabstop4'): + self.tabstop = 4 self.body[:] = \ - urwid.SimpleFocusListWalker( - self.get_note_content_as_list(4)) - return None + urwid.SimpleFocusListWalker(self.get_note_content_as_list()) elif key == self.config.get_keybind('tabstop8'): + self.tabstop = 8 self.body[:] = \ - urwid.SimpleFocusListWalker( - self.get_note_content_as_list(8)) - return None + urwid.SimpleFocusListWalker(self.get_note_content_as_list()) + + else: + return key - return key + return None diff --git a/view_titles.py b/view_titles.py @@ -1,6 +1,6 @@ import re, time, datetime, urwid, subprocess -import utils, view_note, temp +import utils, view_note class ViewTitles(urwid.ListBox): @@ -8,15 +8,22 @@ def __init__(self, config, args): self.config = config self.ndb = args['ndb'] self.search_string = args['search_string'] - self.body_changer = args['body_changer'] self.status_message = args['status_message'] - self.all_notes, match_regex, self.all_notes_cnt = \ + self.note_list, match_regex, self.all_notes_cnt = \ self.ndb.filter_notes(self.search_string) - if len(self.all_notes) == 0: + if len(self.note_list) == 0: self.status_message(u'No notes found!') super(ViewTitles, self).__init__( urwid.SimpleFocusListWalker(self.get_note_titles())) + def update_note_list(self, search_string): + self.search_string = search_string + self.note_list, match_regex, self.all_notes_cnt = \ + self.ndb.filter_notes(self.search_string) + self.body[:] = \ + urwid.SimpleFocusListWalker(self.get_note_titles()) + self.focus_position = 0 + def format_title(self, note): """ Various formatting tags are supporting for dynamically building @@ -136,7 +143,7 @@ def get_note_title(self, note): def get_note_titles(self): lines = [] - for n in self.all_notes: + for n in self.note_list: lines.append(self.get_note_title(n.note)) return lines @@ -165,55 +172,15 @@ def get_status_bar(self): urwid.AttrMap(urwid.Columns([ status_title, status_index ]), 'status_bar') - def update_note_title(self, key, pos): + def update_note_title(self, key): if not key: - self.body[pos] = self.get_note_title(self.all_notes[pos].note) + self.body[self.focus_position] = \ + self.get_note_title(self.note_list[self.focus_position].note) else: - for i in xrange(len(self.all_notes)): - if self.all_notes[i].note['key'] == key: - self.body[i] = self.get_note_title(self.all_notes[i].note) + for i in xrange(len(self.note_list)): + if self.note_list[i].note['key'] == key: + self.body[i] = self.get_note_title(self.note_list[i].note) def keypress(self, size, key): - if key == self.config.get_keybind('note_pin'): - if len(self.body.positions()) > 0: - self.ndb.set_note_pinned( - self.all_notes[self.focus_position].note['key'], 1) - self.update_note_title(None, self.focus_position) - return None - - elif key == self.config.get_keybind('note_unpin'): - if len(self.body.positions()) > 0: - self.ndb.set_note_pinned( - self.all_notes[self.focus_position].note['key'], 0) - self.update_note_title(None, self.focus_position) - return None - - elif key == self.config.get_keybind('view_note'): - if len(self.body.positions()) > 0: - self.body_changer({ 'view' : view_note.ViewNote, - 'note' : self.all_notes[self.focus_position].note }) - return None - - elif key == self.config.get_keybind('view_note_ext'): - if len(self.body.positions()) > 0: - pager = None - if self.config.get_config('pager'): - pager = self.config.get_config('pager') - if not pager and os.environ['PAGER']: - pager = os.environ['PAGER'] - if not pager: - self.status_message(u'No pager configured!') - return None - - tf = temp.tempfile_create(self.all_notes[self.focus_position].note) - try: - subprocess.check_call(pager + u' ' + temp.tempfile_name(tf), shell=True) - except Exception, e: - self.status_message(u'Pager error: ' + str(e)) - - # XXX check if modified, if so update it - temp.tempfile_delete(tf) - return None - return key