nncli

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

commit 7a9c626399ca52d4bc2ca1646a6b4c9a2d386ae4
parent a99afd0ef61360028f22a13300f472e8195de68b
Author: Eric Davis <edavis@insanum.com>
Date:   Thu,  2 Apr 2015 15:59:18 -0700

Merge pull request #14 from axs221/search_note

Search notes view
Diffstat:
A.gitignore | 2++
Msimplenote_cli/config.py | 12++++++++++--
Msimplenote_cli/sncli.py | 42++++++++++++++++++++++++++++++++++++------
Msimplenote_cli/view_note.py | 47++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +.ropeproject diff --git a/simplenote_cli/config.py b/simplenote_cli/config.py @@ -59,6 +59,10 @@ def __init__(self): 'kb_select_version' : '#', 'kb_search_gstyle' : '/', 'kb_search_regex' : 'meta /', + 'kb_search_prev_gstyle' : '?', + 'kb_search_prev_regex' : 'meta ?', + 'kb_search_next' : 'n', + 'kb_search_prev' : 'N', 'kb_clear_search' : 'A', 'kb_sort_date' : 'd', 'kb_sort_alpha' : 'a', @@ -172,8 +176,12 @@ def __init__(self): self.keybinds['restore_version'] = [ cp.get(cfg_sec, 'kb_restore_version'), [ 'notes' ], 'Restore version of note' ] self.keybinds['latest_version'] = [ cp.get(cfg_sec, 'kb_latest_version'), [ 'notes' ], 'View latest version' ] self.keybinds['select_version'] = [ cp.get(cfg_sec, 'kb_select_version'), [ 'notes' ], 'Select version' ] - 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['search_gstyle'] = [ cp.get(cfg_sec, 'kb_search_gstyle'), [ 'titles', 'notes' ], 'Search using gstyle' ] + self.keybinds['search_prev_gstyle'] = [ cp.get(cfg_sec, 'kb_search_prev_gstyle'), [ 'notes' ], 'Search backwards using gstyle' ] + self.keybinds['search_regex'] = [ cp.get(cfg_sec, 'kb_search_regex'), [ 'titles', 'notes' ], 'Search using regex' ] + self.keybinds['search_prev_regex'] = [ cp.get(cfg_sec, 'kb_search_prev_regex'), [ 'notes' ], 'Search backwards using regex' ] + self.keybinds['search_next'] = [ cp.get(cfg_sec, 'kb_search_next'), [ 'notes' ], 'Go to next search result' ] + self.keybinds['search_prev'] = [ cp.get(cfg_sec, 'kb_search_prev'), [ 'notes' ], 'Go to previous search result' ] 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/simplenote_cli/sncli.py b/simplenote_cli/sncli.py @@ -322,7 +322,7 @@ def gui_yes_no_input(self, args, yes_no): self.gui_body_focus() self.master_frame.keypress = self.gui_frame_keypress args[0](args[1], - True if yes_no in [ 'YES', 'Yes', 'yes', 'Y', 'y' ] + True if yes_no in [ 'YES', 'Yes', 'yes', 'Y', 'y' ] else False) def gui_search_input(self, args, search_string): @@ -330,8 +330,12 @@ def gui_search_input(self, args, search_string): self.gui_body_focus() self.master_frame.keypress = self.gui_frame_keypress if search_string: - self.view_titles.update_note_list(search_string, args[0]) - self.gui_body_set(self.view_titles) + if (self.gui_body_get() == self.view_note): + self.search_direction = args[1] + self.view_note.search_note_view_next(search_string=search_string, search_mode=args[0]) + else: + self.view_titles.update_note_list(search_string, args[0]) + self.gui_body_set(self.view_titles) def gui_version_input(self, args, version): self.gui_footer_input_clear() @@ -780,10 +784,20 @@ def gui_frame_keypress(self, size, key): self.master_frame.keypress = self.gui_footer_input_get().keypress 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: + key == self.config.get_keybind('search_regex') or \ + key == self.config.get_keybind('search_prev_gstyle') or \ + key == self.config.get_keybind('search_prev_regex'): + if self.gui_body_get().__class__ != view_titles.ViewTitles and \ + self.gui_body_get().__class__ != view_note.ViewNote: return key + if self.gui_body_get().__class__ == view_note.ViewNote: + if key == self.config.get_keybind('search_prev_gstyle') or \ + key == self.config.get_keybind('search_prev_regex'): + self.view_note.search_direction = 'backward' + else: + self.view_note.search_direction = 'forward' + self.gui_footer_input_set( urwid.AttrMap( user_input.UserInput( @@ -792,11 +806,27 @@ def gui_frame_keypress(self, size, key): '', self.gui_search_input, [ 'gstyle' if key == self.config.get_keybind('search_gstyle') - else 'regex' ]), + or key == self.config.get_keybind('search_prev_gstyle') + else 'regex', + 'backward' if key == self.config.get_keybind('search_prev_gstyle') + or key == self.config.get_keybind('search_prev_regex') + else 'forward' ]), 'user_input_bar')) self.gui_footer_focus_input() self.master_frame.keypress = self.gui_footer_input_get().keypress + elif key == self.config.get_keybind('search_next'): + if self.gui_body_get().__class__ != view_note.ViewNote: + return key + + self.view_note.search_note_view_next() + + elif key == self.config.get_keybind('search_prev'): + if self.gui_body_get().__class__ != view_note.ViewNote: + return key + + self.view_note.search_note_view_prev() + elif key == self.config.get_keybind('clear_search'): if self.gui_body_get().__class__ != view_titles.ViewTitles: return key diff --git a/simplenote_cli/view_note.py b/simplenote_cli/view_note.py @@ -4,6 +4,7 @@ import time, urwid import utils +import re class ViewNote(urwid.ListBox): @@ -12,6 +13,9 @@ def __init__(self, config, args): self.ndb = args['ndb'] self.key = args['key'] self.log = args['log'] + self.search_string = '' + self.search_mode = 'gstyle' + self.search_direction = '' self.note = self.ndb.get_note(self.key) if self.key else None self.old_note = None self.tabstop = int(self.config.get_config('tabstop')) @@ -69,7 +73,48 @@ def update_note_view(self, key=None, version=None): self.body[:] = \ urwid.SimpleFocusListWalker(self.get_note_content_as_list()) - self.focus_position = 0 + if not self.search_string: + self.focus_position = 0 + + def lines_after_current_position(self): + lines_after_current_position = range(self.focus_position + 1, len(self.body.positions()) - 1) + return lines_after_current_position + + def lines_before_current_position(self): + lines_before_current_position = range(0, self.focus_position) + lines_before_current_position.reverse() + return lines_before_current_position + + def search_note_view_next(self, search_string=None, search_mode=None): + if search_string: + self.search_string = search_string + if search_mode: + self.search_mode = search_mode + note_range = self.lines_after_current_position() if self.search_direction == 'forward' else self.lines_before_current_position() + self.search_note_range(note_range) + + def search_note_view_prev(self, search_string=None, search_mode=None): + if search_string: + self.search_string = search_string + if search_mode: + self.search_mode = search_mode + note_range = self.lines_after_current_position() if self.search_direction == 'backward' else self.lines_before_current_position() + self.search_note_range(note_range) + + def search_note_range(self, note_range): + for line in note_range: + line_content = self.note['content'].split('\n')[line] + if (self.is_match(self.search_string, line_content)): + self.focus_position = line + break + self.update_note_view() + + def is_match(self, term, full_text): + if self.search_mode == 'gstyle': + return term in full_text + else: + results = re.search(term, full_text) + return ( results is not None ) def get_status_bar(self): if not self.key: