from .base import BasePrompt import os from sqlalchemy.exc import NoResultFound from textwrap import dedent, wrap from groove import db from groove.exceptions import PlaylistValidationError class _playlist(BasePrompt): """ """ def __init__(self, parent, manager=None): super().__init__(manager=manager, parent=parent) self._parent = parent self._commands = None @property def help_text(self): synopsis = ( f"You are currently editing the [b]{self.parent.playlist.name}[/b]" f" playlist. From this prompt you can quickly append new tracks " f"to the playlist. You can invoke your editor " f"([link]{os.environ['EDITOR']}[/link]) to change the playlist " f"name and description, or reorder or remove tracks. You can also " f"delete the playlist." ) try: width = int(os.environ.get('CONSOLE_WIDTH', '80')) except ValueError: width = 80 synopsis = '\n '.join(wrap(synopsis, width=width)) return dedent(f""" [title]WORKING WITH PLAYLISTS[/title] {synopsis} [title]USAGE[/title] [link]playlist> COMMAND [ARG ..][/link] [title]COMMANDS[/title] [help] [b]add[/b] Add one or more tracks to the playlist [b]edit[/b] Open the playlist in the system editor [b]show[/b] Display the complete playlist [b]delete[/b] Delete the playlist [b]help[/b] This message Try 'help command' for command-specific help.[/help] """) @property def prompt(self): return [ "", "[help]Available commands: add, edit, show, delete, help. Hit Enter to return.[/help]", f"[prompt]{self.parent.playlist.slug}[/prompt]", ] @property def values(self): return self.commands.keys() @property def commands(self): if not self._commands: self._commands = { 'delete': self.delete, 'add': self.add, 'show': self.show, 'edit': self.edit, 'help': self.help } return self._commands def process(self, cmd, *parts): if cmd in self.commands: return True if self.commands[cmd](parts) else False self.parent.console.error(f"Command not understood: {cmd}") return True def edit(self, *parts): try: self.parent.playlist.edit() except PlaylistValidationError as e: self.parent.console.error(f"Changes were not saved: {e}") else: self.show() return True def show(self, *parts): self.parent.console.print(self.parent.playlist.as_richtext) return True def add(self, *parts): self.parent.console.print( "Add tracks one at a time by title. Hit Enter to finish." ) added = False while True: text = self.parent.console.prompt( [' ?'], completer=self.manager.fuzzy_table_completer( db.track, db.track.c.relpath, lambda row: row.relpath ), complete_in_thread=True, complete_while_typing=True ) if not text: if added: self.show() return True self._add_track(text) added = True def _add_track(self, text): sess = self.parent.manager.session try: track = sess.query(db.track).filter(db.track.c.relpath == text).one() self.parent.playlist.create_entries([track]) except NoResultFound: self.parent.console.error("No match for '{text}'") return return text def delete(self, *parts): res = self.parent.console.prompt([ f"[error]Type [b]DELETE[/b] to permanently delete the playlist " f'"{self.parent.playlist.record.name}".[/error]', f"[prompt]DELETE {self.parent.playlist.slug}[/prompt]", ]) if res != 'DELETE': self.parent.console.error("Delete aborted. No changes have been made.") return True self.parent.playlist.delete() self.parent.console.print("Deleted the playlist.") self.parent._playlist = None return False def start(self): self.show() super().start()