bug fixes, console themes, help interface

This commit is contained in:
evilchili
2022-12-16 23:24:05 -08:00
parent 335d67c9d2
commit b7ec4259a6
6 changed files with 247 additions and 39 deletions
+19 -2
View File
@@ -1,10 +1,13 @@
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit import print_formatted_text, HTML
from groove.console import Console
class BasePrompt(Completer):
def __init__(self, manager=None, parent=None):
def __init__(self, manager=None, console=None, parent=None):
super(BasePrompt, self).__init__()
if (not manager and not parent): # pragma: no cover
@@ -14,6 +17,14 @@ class BasePrompt(Completer):
self._values = []
self._parent = parent
self._manager = manager
self._console = None
self._theme = None
@property
def console(self):
if not self._console:
self._console = Console(color_system='truecolor')
return self._console
@property
def usage(self):
@@ -56,10 +67,16 @@ class BasePrompt(Completer):
except NotImplementedError:
pass
def help(self, parts):
self.console.print(
getattr(self, parts[0]).__doc__ if parts else self.help_text
)
return True
def start(self, cmd=''):
while True:
if not cmd:
cmd = prompt(f'{self.prompt} ', completer=self)
cmd = self.console.prompt(self.prompt, completer=self)
if not cmd:
return
cmd, *parts = cmd.split()
+4 -1
View File
@@ -11,9 +11,12 @@ class CommandPrompt(BasePrompt):
def __init__(self, manager):
super().__init__(manager=manager)
self._playlist = None
self._prompt = "Groove on Demand interactive shell. Try 'help' for help.\ngroove>"
self._completer = None
self._commands = None
self._prompt = [
"[help]Groove on Demand interactive shell. Try 'help' for help.[/help]",
"groove"
]
@property
def playlist(self):
+83 -22
View File
@@ -1,23 +1,67 @@
from .base import BasePrompt
from prompt_toolkit import prompt
from rich import print
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._prompt = ''
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 f"{self.parent.playlist}\n{self.parent.playlist.slug}> "
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):
@@ -27,32 +71,41 @@ class _playlist(BasePrompt):
def commands(self):
if not self._commands:
self._commands = {
'show': self.show,
'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
print(f"Command not understood: {cmd}")
self.parent.console.error(f"Command not understood: {cmd}")
return True
def show(self, parts):
print(self.parent.playlist)
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 edit(self, parts):
self.parent.playlist.edit()
def show(self, *parts):
self.parent.console.print(self.parent.playlist.as_richtext)
return True
def add(self, parts):
print("Add tracks one at a time by title. ENTER to finish.")
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 = prompt(
' ?',
text = self.parent.console.prompt(
[' ?'],
completer=self.manager.fuzzy_table_completer(
db.track,
db.track.c.relpath,
@@ -61,8 +114,11 @@ class _playlist(BasePrompt):
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
@@ -70,20 +126,25 @@ class _playlist(BasePrompt):
track = sess.query(db.track).filter(db.track.c.relpath == text).one()
self.parent.playlist.create_entries([track])
except NoResultFound:
print("No match for '{text}'")
self.parent.console.error("No match for '{text}'")
return
return text
def delete(self, parts):
res = prompt(
'Type DELETE to permanently delete the playlist '
f'"{self.parent.playlist.record.name}".\nDELETE {self.prompt}'
)
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':
print("Delete aborted. No changes have been made.")
self.parent.console.error("Delete aborted. No changes have been made.")
return True
self.parent.playlist.delete()
print("Deleted the playlist.")
self.parent.console.print("Deleted the playlist.")
self.parent._playlist = None
return False
def start(self):
self.show()
super().start()