nncli

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

commit 807f2f595a5e8e14c370501597b999961ccff0fe
parent 1af3e7da8323693e622b5ffbf803daddf17ffd97
Author: Eric Davis <edavis@insanum.com>
Date:   Thu, 10 Jul 2014 15:55:56 -0700

new keybind command for searching using a regex

Diffstat:
Mconfig.py | 10++++++----
Mnotes_db.py | 33++++++++++++++-------------------
Msncli.py | 28++++++++++++++++++----------
Muser_input.py | 9+++++----
Mview_titles.py | 4++--
5 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/config.py b/config.py @@ -10,8 +10,8 @@ def __init__(self): 'cfg_sn_username' : '', 'cfg_sn_password' : '', 'cfg_db_path' : os.path.join(self.home, '.sncli'), - 'cfg_search_tags' : 'yes', # with regex searches - 'cfg_sort_mode' : 'date', # 'alpha' or 'date' + 'cfg_search_tags' : 'yes', # with regex searches + 'cfg_sort_mode' : 'date', # 'alpha' or 'date' 'cfg_pinned_ontop' : 'yes', 'cfg_tabstop' : '4', 'cfg_format_strftime' : '%Y/%m/%d', @@ -46,7 +46,8 @@ def __init__(self): 'kb_tabstop2' : '2', 'kb_tabstop4' : '4', 'kb_tabstop8' : '8', - 'kb_search' : '/', + 'kb_search_gstyle' : '/', + 'kb_search_regex' : 'meta /', 'kb_clear_search' : 'A', 'kb_sort_date' : 'd', 'kb_sort_alpha' : 'a', @@ -149,7 +150,8 @@ def __init__(self): self.keybinds['tabstop2'] = [ cp.get(cfg_sec, 'kb_tabstop2'), [ 'notes' ], 'View with tabstop=2' ] self.keybinds['tabstop4'] = [ cp.get(cfg_sec, 'kb_tabstop4'), [ 'notes' ], 'View with tabstop=4' ] self.keybinds['tabstop8'] = [ cp.get(cfg_sec, 'kb_tabstop8'), [ 'notes' ], 'View with tabstop=8' ] - self.keybinds['search'] = [ cp.get(cfg_sec, 'kb_search'), [ 'titles' ], 'Search notes' ] + self.keybinds['search_gstyle'] = [ cp.get(cfg_sec, 'kb_search_gstyle'), [ 'titles' ], 'Search using gstyle' ] + self.keybinds['search_regex'] = [ cp.get(cfg_sec, 'kb_search_regex'), [ 'titles' ], 'Search using regex' ] self.keybinds['clear_search'] = [ cp.get(cfg_sec, 'kb_clear_search'), [ 'titles' ], 'Show all notes' ] self.keybinds['sort_date'] = [ cp.get(cfg_sec, 'kb_sort_date'), [ 'titles' ], 'Sort notes by date' ] self.keybinds['sort_alpha'] = [ cp.get(cfg_sec, 'kb_sort_alpha'), [ 'titles' ], 'Sort notes by alpha' ] diff --git a/notes_db.py b/notes_db.py @@ -121,6 +121,7 @@ def _helper_gstyle_tagmatch(self, tag_pats, note): if t.startswith(tp): tag_pats_matched += 1 break + if tag_pats_matched == len(tag_pats): # all tag patterns specified matched a tag on this note return 1 @@ -129,26 +130,20 @@ def _helper_gstyle_tagmatch(self, tag_pats, note): return 0 def _helper_gstyle_wordmatch(self, word_pats, content): - """If all words / multi-words in word_pats are found in the content, - the note goes through, otherwise not. - - @param word_pats: - @param content: - @return: - """ - - # no search patterns, so note goes through if not word_pats: return True - # search for the first p that does NOT occur in content - if next((p for p in word_pats if p not in content), None) is None: - # we only found pats that DO occur in content so note goes through - return True + word_pats_matched = 0 + lowercase_content = content.lower() # case insensitive search + for wp in word_pats: + wp = wp.lower() # case insensitive search + if wp in lowercase_content: + word_pats_matched += 1 - else: - # we found the first p that does not occur in content - return False + if word_pats_matched == len(word_pats): + return True; + + return False def filter_notes_gstyle(self, search_string=None): @@ -206,7 +201,7 @@ def filter_notes_gstyle(self, search_string=None): return filtered_notes, '|'.join(all_pats[1] + all_pats[2]), active_notes - def filter_notes_regexp(self, search_string=None): + def filter_notes_regex(self, search_string=None): """ Return a list of notes filtered using the regex search_string. Each element in the list is a tuple (local_key, note). @@ -234,10 +229,10 @@ def filter_notes_regexp(self, search_string=None): filtered_notes.append(utils.KeyValueObject(key=k, note=n, tagfound=0)) continue - if self.config.search_tags == 'yes': + if self.config.get_config('search_tags') == 'yes': tag_matched = False for t in n.get('tags'): - if sspat.seatch(t): + if sspat.search(t): tag_matched = True filtered_notes.append(utils.KeyValueObject(key=k, note=n, tagfound=1)) break diff --git a/sncli.py b/sncli.py @@ -189,15 +189,15 @@ def gui_switch_frame_body(self, new_view, save_current_view=True): self.last_view.append(self.gui_body_get()) self.gui_body_set(new_view) - def gui_search_input(self, search_string): + def gui_search_input(self, args, search_string): self.gui_footer_input_clear() self.gui_body_focus() self.master_frame.keypress = self.gui_frame_keypress if search_string: - self.view_titles.update_note_list(search_string) + self.view_titles.update_note_list(search_string, args[0]) self.gui_body_set(self.view_titles) - def gui_tags_input(self, tags): + def gui_tags_input(self, args, tags): self.gui_footer_input_clear() self.gui_body_focus() self.master_frame.keypress = self.gui_frame_keypress @@ -216,7 +216,7 @@ def gui_tags_input(self, tags): self.gui_update_status_bar() - def gui_pipe_input(self, cmd): + def gui_pipe_input(self, args, cmd): self.gui_footer_input_clear() self.gui_body_focus() self.master_frame.keypress = self.gui_frame_keypress @@ -480,8 +480,10 @@ def gui_frame_keypress(self, size, key): self.gui_footer_input_set( urwid.AttrMap( user_input.UserInput(self.config, - key, '', - self.gui_pipe_input), + key, + '', + self.gui_pipe_input, + None), 'search_bar')) self.gui_footer_focus_input() self.master_frame.keypress = self.gui_footer_input_get().keypress @@ -513,15 +515,20 @@ def gui_frame_keypress(self, size, key): self.view_titles.note_list[self.view_titles.focus_position].note['key']) self.gui_switch_frame_body(self.view_note) - elif key == self.config.get_keybind('search'): + elif key == self.config.get_keybind('search_gstyle') or \ + key == self.config.get_keybind('search_regex'): if self.gui_body_get().__class__ != view_titles.ViewTitles: return key self.gui_footer_input_set( urwid.AttrMap( user_input.UserInput(self.config, - key, '', - self.gui_search_input), + key, + '', + self.gui_search_input, + [ 'gstyle' \ + if key == self.config.get_keybind('search_gstyle') + else 'regex' ]), 'search_bar')) self.gui_footer_focus_input() self.master_frame.keypress = self.gui_footer_input_get().keypress @@ -608,7 +615,8 @@ def gui_frame_keypress(self, size, key): user_input.UserInput(self.config, 'Tags: ', '%s' % ','.join(note['tags']), - self.gui_tags_input), + self.gui_tags_input, + None), 'search_bar')) self.gui_footer_focus_input() self.master_frame.keypress = self.gui_footer_input_get().keypress diff --git a/user_input.py b/user_input.py @@ -3,9 +3,10 @@ class UserInput(urwid.Edit): - def __init__(self, config, caption, edit_text, callback_func): + def __init__(self, config, caption, edit_text, callback_func, args): self.config = config - self.callback_func = callback_func + self.callback_func = callback_func + self.callback_func_args = args super(UserInput, self).__init__(caption=caption, edit_text=edit_text, wrap='clip') @@ -13,9 +14,9 @@ def __init__(self, config, caption, edit_text, callback_func): def keypress(self, size, key): size = (size[0],) # if this isn't here then urwid freaks out... if key == 'esc': - self.callback_func(None) + self.callback_func(self.callback_func_args, None) elif key == 'enter': - self.callback_func(self.edit_text) + self.callback_func(self.callback_func_args, self.edit_text) else: return super(UserInput, self).keypress(size, key) return None diff --git a/view_titles.py b/view_titles.py @@ -14,10 +14,10 @@ def __init__(self, config, args): super(ViewTitles, self).__init__( urwid.SimpleFocusListWalker(self.get_note_titles())) - def update_note_list(self, search_string): + def update_note_list(self, search_string, search_mode='gstyle'): self.search_string = search_string self.note_list, self.match_regex, self.all_notes_cnt = \ - self.ndb.filter_notes(self.search_string) + self.ndb.filter_notes(self.search_string, search_mode) self.body[:] = \ urwid.SimpleFocusListWalker(self.get_note_titles()) if len(self.note_list) == 0: