From 70aa706eac589124c7b77001dac4b3716f67e01c Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Fri, 12 Feb 2016 17:21:03 -0600 Subject: [PATCH] WIP Moving CLI to command-like input. --- .../wdiwtlt/cli/CommandLineInterface.groovy | 261 +++++++++++------- 1 file changed, 154 insertions(+), 107 deletions(-) diff --git a/cli/src/main/groovy/com/jdbernard/wdiwtlt/cli/CommandLineInterface.groovy b/cli/src/main/groovy/com/jdbernard/wdiwtlt/cli/CommandLineInterface.groovy index 122f235..f6c77b4 100644 --- a/cli/src/main/groovy/com/jdbernard/wdiwtlt/cli/CommandLineInterface.groovy +++ b/cli/src/main/groovy/com/jdbernard/wdiwtlt/cli/CommandLineInterface.groovy @@ -64,7 +64,7 @@ Configuration: private synchronized boolean running private String titleStyle, normalStyle, statusStyle, promptStyle, - artistStyle, albumStyle, fileStyle, errorStyle + artistStyle, albumStyle, fileStyle, errorStyle, playlistStyle private String clearLine = new ANSI().eraseLine(Erase.All).toString() private String afterInput = new ANSI().eraseLine(Erase.All).scrollUp().cursorUp().toString() @@ -73,7 +73,8 @@ Configuration: private String afterLeader = new ANSI().restoreCursor().eraseLine(Erase.ToEnd).toString() private String eraseLeader = - new ANSI().cursorPrevLine().eraseLine(Erase.All).cursorPrevLine().eraseLine(Erase.All).toString() + new ANSI().cursorPrevLine().eraseLine(Erase.All).cursorPrevLine() + .eraseLine(Erase.All).toString() private int displayWidth = 79 private long msgTimeout @@ -216,109 +217,7 @@ Configuration: if (new Date() > dismissMsgDate) resetStatus() if (consoleReadBuffer.size() > 0) { line = consoleReadBuffer.remove(0) - switch(line) { - case ~/quit|exit|.+\u0004$/: - running = false - consoleReaderThread.interrupt() - break - - case 'scan': - scanMediaLibrary() - break - - case 'debug': - outStream.println( - "\n\nConfig: \n" + - cliConfig.collect { "\t${it.key}: ${it.value}" } - .join("\n") + - "\n\n\n") - drawLeader(true) - break - - case "artist": - selection.artist = null - resetStatus() - break - - case ~/artist (.+)/: - def input = Matcher.lastMatcher[0][1]?.trim() - def match = library.getByIdOrName(input, Artist) - if (!match) setErr("No artist matches '$input'.") - else if (match.size() > 1) - setErr("Multiple artists match '$input': " + - match.collect { "${it.id}: ${it.name}" } - .join(", ")) - else { - selection.artist = match[0] - resetStatus() } - break - - case "album": - selection.album = null - resetStatus() - break - - case ~/album (.+)/: - def input = Matcher.lastMatcher[0][1]?.trim() - def match = library.getByIdOrName(input, Album) - if (!match) setErr("No album matches '$input'.") - else if (match.size() > 1) - setErr("Multiple albums match '$input': " + - match.collect { "${it.id}: ${it.name}" } - .join(", ")) - else { - selection.album = match[0] - resetStatus() } - break - - case "list artists for album": - if (!selection.album) { - setErr("No album is selected.") - break } - outStream.println(makeArtistList( - library.getArtistsByAlbumId(selection.album.id), - selection.album)) - drawLeader(true) - break - - case ~/list artists( .+)?/: - def name = Matcher.lastMatcher[0][1]?.trim() - def artists - if (name) artists = library.getArtistsByName(name) - else artists = library.getArtists() - - outStream.println(makeArtistList(artists)) - drawLeader(true) - break - - case "list albums for artist": - if (!selection.artist) { - setErr("No artist selected.") - break } - outStream.println(makeAlbumList( - library.getAlbumsByArtistId(selection.artist.id), - selection.artist)) - drawLeader(true) - break - - case ~/list albums( .+)?/: - def name = Matcher.lastMatcher[0][1]?.trim() - def albums - if (name) albums = library.getAlbumsByName(name) - else albums = library.getAlbums() - - outStream.println(makeAlbumList(albums)) - drawLeader(true) - break - - default: - status.text = errorStyle + - "Unrecognized command: '$line'${normalStyle}" - dismissMsgDate = new Date(new Date().time + msgTimeout) - drawLeader() - Thread.sleep(250) - break - } + processInput(line.split(/\w/) as LinkedList) } else { drawLeader() Thread.sleep(250) @@ -326,11 +225,144 @@ Configuration: } } - private void scanMediaLibrary() { + private def processInput(LinkedList line) { + String command = line.poll() + switch(command.toLowerCase()) { + case 'album': return selectAlbum(line) + case 'artist': return selectArtist(line) + case 'scan': return scanMediaLibrary() + + case 'list': + String nextArg = line.poll() + if (nextArg.toLowerCase() == 'all') + return processList(line, true) + else { + if (nextArg) line.push(nextArg) + return processList(line, false) } + + case 'debug': + outStream.println( + "\n\nConfig: \n" + + cliConfig.collect { "\t${it.key}: ${it.value}" } + .join("\n") + + "\n\n\n") + drawLeader(true) + return + + case 'q': case 'quit': case ':q': case 'exit': case '\u0004': + running = false + consoleReaderThread.interrupt() + return + + selection.album = null + resetStatus() + break + + case "list artists for album": + if (!selection.album) { + setErr("No album is selected.") + break } + outStream.println(makeArtistList( + library.getArtistsByAlbumId(selection.album.id), + selection.album)) + drawLeader(true) + break + + case ~/list artists( .+)?/: + def name = Matcher.lastMatcher[0][1]?.trim() + def artists + if (name) artists = library.getArtistsByName(name) + else artists = library.getArtists() + + outStream.println(makeArtistList(artists)) + drawLeader(true) + break + + case "list albums for artist": + if (!selection.artist) { + setErr("No artist selected.") + break } + outStream.println(makeAlbumList( + library.getAlbumsByArtistId(selection.artist.id), + selection.artist)) + drawLeader(true) + break + + case ~/list albums( .+)?/: + def name = Matcher.lastMatcher[0][1]?.trim() + def albums + if (name) albums = library.getAlbumsByName(name) + else albums = library.getAlbums() + + outStream.println(makeAlbumList(albums)) + drawLeader(true) + break + + default: + status.text = errorStyle + + "Unrecognized command: '$line'${normalStyle}" + dismissMsgDate = new Date(new Date().time + msgTimeout) + drawLeader() + Thread.sleep(250) + break + } + + } + + private def processList(LinkedList options, boolean all) { + def option = options.poll() + switch(option) { + case 'albums': + case 'artists': + case 'bookmarks': + case 'playlists': + default: + printLongMessage("Unrecognized option to the ${promptStyle}" + + "list${normalStyle} command. Use ${promptStyle}help list" + + "to see a list of valid options.") + return null + } + } + + public Album selectAlbum(LinkedList input) { + String criteria = input.join(" ") + + if (!criteria) { selection.album = null; resetStatus(); return null } + + Album match = library.getByIdOrName(Album, criteria) + + if (!match) { setErr("No album matches '$input'."); return null } + else if (match.size() > 1) { + setErr("Multiple albums match '$input': " + + match.collect { "${it.id}: ${it.name}" }.join(", ")) + return null } + + selection.album = match[0] + resetStatus() + return match[0] } + + public void selectArtist(LinkedList input) { + String criteria = input.join(" ") + + if (!criteria) { selection.artist = null; resetStatus(); return null } + + Artist match = library.getByIdOrName(Artist, criteria) + + if (!match) { setErr("No artist matches '$input'."); return null } + else if (match.size() > 1) { + setErr("Multiple artists match '$input': " + + match.collect { "${it.id}: ${it.name}" }.join(", ")) + return null } + selection.artist = match[0] + resetStatus() + return match[0] } + + public MediaLibrary scanMediaLibrary() { status.text = "Scanning media library..." library.rescanLibrary() status.text = "Scanned ? files." - dismissMsgDate = new Date(new Date().time + msgTimeout) } + dismissMsgDate = new Date(new Date().time + msgTimeout) + return library } private void drawLeader(afterOutput = false) { @@ -342,6 +374,16 @@ Configuration: outStream.print(leader) outStream.flush() } + private void printLongMessage(String msg) { + String result = new StringBuilder() + .append(eraseLeader) + .append(msg) + .append("\n\n") + .toString() + + outStream.println result + drawLeader(true) } + private String getLeader() { StringBuilder leader = new StringBuilder() .append(clearLine) @@ -393,6 +435,11 @@ Configuration: private String resetStatus() { StringBuilder s = new StringBuilder() + if (selection.playlist) s.append(playlistStyle) + .append(selection.playlist) + .append(normalStyle) + .append(": ") + if (selection.artist) s.append(artistStyle) .append(selection.artist) .append(normalStyle)