import npyscreen import bisect class RemovableMulti(npyscreen.MultiLineAction): def actionHighlighted(self, act_on_this, keypress): self.remove_item() def register_oppisite(self, opposite): self.opposite = opposite opposite.opposite = self def remove_item(self): selected_value = self.values[self.cursor_line] del self.values[self.cursor_line] bisect.insort(self.opposite.values, selected_value) self.opposite.display() self.display() class BoxedRemovableMulti(npyscreen.BoxTitle): _contained_widget = RemovableMulti class AddRemoveForm(npyscreen.ActionFormV2): def create(self): self.keepers = self.add( BoxedRemovableMulti, values=sorted(self.parentApp.starting_values), name="Words to keep", max_height=10 ) self.to_remove = self.add( BoxedRemovableMulti, values=[], name="Words to remove", max_height=10 ) self.keepers.entry_widget.register_oppisite( self.to_remove.entry_widget) def on_cancel(self): self.canceled = True def on_ok(self): self.canceled = False def afterEditing(self): self.parentApp.setNextForm(None) class RemoveWordsActivity(npyscreen.NPSAppManaged): def __init__(self, starting_values, *args, **kwargs): super().__init__(*args, **kwargs) self.starting_values = starting_values def onStart(self): self.addForm('MAIN', AddRemoveForm, name="Exclude Words", minimum_lines=0, minimum_columns=0) def get_results(self): form = self.getForm('MAIN') vals = form.to_remove.entry_widget.values canceled = form.canceled return canceled, vals if __name__ == "__main__": values = [ 'hello', 'return', 'butt', 'fuck', 'abcdefghijklmnopqrstuvwxyz' ] app = RemoveWordsActivity(values) app.run()