Source code for

# -*- coding: utf-8 -*-
npyscreen based application for searching shell history
from __future__ import print_function, absolute_import, unicode_literals
import curses
import os
import sys

import npyscreen

from import LocalHistory, WebHistory, ArcheloncException

[docs]class SearchResult(npyscreen.Textfield): """ Search result item """
[docs] def update(self, clear=True): """ Update search results include getting the next page. """ # pylint: disable=arguments-differ if self.highlight: results_list = self.parent.results_list current_item = results_list.cursor_line total_items = len(results_list.values) app = self.parent.parentApp if (current_item == total_items - 1) and app.more: # Grab the next set of results += 1 results = if len(results) == 0: app.more = False results_list.values.extend(results) results_list.reset_display_cache() results_list.update() super(SearchResult, self).update(clear)
[docs]class CommandBox(npyscreen.TitleText): """ Command Box widget """ def __init__(self, screen, **kwargs): """ Just add some state to the default widget to track if we have been manually edited """ self.been_edited = False super(CommandBox, self).__init__(screen, **kwargs)
[docs] def when_value_edited(self): """ Mark myself as having been edited """ self.been_edited = True
[docs]class SearchResults(npyscreen.MultiLineAction): """ MultiLine widget for displaying search results. """ _contained_widgets = SearchResult
[docs] def actionHighlighted(self, act_on_this, key_press): cmd_box = self.parent.command_box cmd_box.value = act_on_this cmd_box.been_edited = True cmd_box.update() self.parent.editw = 2 self.parent.command_box.edit()
[docs] def display_value(self, vl): """Overloaded to support unicode.""" return self.safe_string(vl)
[docs]class SearchForm(npyscreen.ActionFormWithMenus): """ Command history search form """ # pylint: disable=too-many-ancestors def __init__(self, *args, **kwargs): """ Add additional properties for use in state tracking """ super(SearchForm, self).__init__(*args, **kwargs) self.order = None
[docs] def forward_order(self): """ Change sort order to forward """ self.order = None self.search_box.when_value_edited()
[docs] def reverse_order(self): """ Change sort order to forward """ self.order = 'r' self.search_box.when_value_edited()
[docs] def create(self): """ Build the form for searching """ # Have to use the methods I'm given. # pylint: disable=invalid-name # Set default order to reverse self.order = 'r' self.search_box = self.add( SearchBox, name='Search', begin_entry_at=10 ) self.results_list = self.add( SearchResults, name='Results', scroll_exit=True, max_height=-2, values=[] ) self.command_box = self.add( CommandBox, name='Command', begin_entry_at=10, rely=-3 ) self.add_handlers({ '!o': self.on_ok, '!c': self.on_cancel, curses.ascii.ESC: self.on_cancel }) # Create our menus = self.new_menu()[ ('Forward Order', self.forward_order, '^F'), ('Reverse Order', self.reverse_order, '^R'), ])
[docs] def beforeEditing(self): """ Set the edit index to the search box and tell it to preserve the value """ # Have to use the methods I'm given. # pylint: disable=invalid-name self.preserve_selected_widget = True
[docs] def afterEditing(self): """ This is the only form to display, so set next to None """ # Have to use the methods I'm given. # pylint: disable=invalid-name self.parentApp.setNextForm(None)
[docs] def on_ok(self, *_): """ We just drop the command into a known file for the wrapper to pick up """ with open(os.path.expanduser('~/.archelon_cmd'), 'w') as cmd_file: cmd_file.write(self.command_box.value) sys.exit(0)
[docs] def on_cancel(self, *_): """ Drop out with a non 0 exit code so the wrapper doesn't execute anything """ sys.exit(1)