« get me outta code hell

Add way to search whole playlist for a particular name - http-music - Command-line music player + utils (not a server!)
about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2017-10-25 09:44:31 -0300
committerFlorrie <towerofnix@gmail.com>2017-10-25 09:44:34 -0300
commit6b53e886d9183d077a88f77f4b3ae18fbaba5a60 (patch)
tree74d1eb7944539e2592fdb7737af80252f6bbd1bb
parentaac119f2162dc981fa4b6fcba5e8301e7625a011 (diff)
Add way to search whole playlist for a particular name
Try play -c -k '?My Album Name' to make http-music only play the group
with the name 'My Album Name', no matter where it is in the playlist!
-rw-r--r--src/playlist-utils.js49
-rw-r--r--todo.txt5
2 files changed, 50 insertions, 4 deletions
diff --git a/src/playlist-utils.js b/src/playlist-utils.js
index d19c571..013f56a 100644
--- a/src/playlist-utils.js
+++ b/src/playlist-utils.js
@@ -141,6 +141,29 @@ function flattenGrouplike(grouplike) {
   }
 }
 
+function collectGrouplikeChildren(grouplike, filter = null) {
+  // Collects all descendants of a grouplike into a single flat array.
+  // Can be passed a filter function, which will decide whether or not to add
+  // an item to the return array. However, note that all descendants will be
+  // checked against this function; a group will be descended through even if
+  // the filter function checks false against it.
+  // Returns an array, not a grouplike.
+
+  const items = []
+
+  for (const item of grouplike.items) {
+    if (filter === null || filter(item) === true) {
+      items.push(item)
+    }
+
+    if (isGroup(item)) {
+      items.push(...collectGrouplikeChildren(item, filter))
+    }
+  }
+
+  return items
+}
+
 function partiallyFlattenGrouplike(grouplike, resultDepth) {
   // Flattens a grouplike so that it is never more than a given number of
   // groups deep, INCLUDING the "top" group -- e.g. a resultDepth of 2
@@ -234,9 +257,27 @@ function filterGrouplikeByPath(grouplike, pathParts) {
     return grouplike
   }
 
+  let firstPart = pathParts[0]
+  let possibleMatches
+
+  if (firstPart.startsWith('?')) {
+    // TODO: Note to self - remove isGroup here to let this match anything, not
+    // just groups. Definitely want to do that in the future, but there'll need
+    // to be some preparing first - for example, what if a group contains a
+    // track which is the same name as the group? Then there are two possible
+    // matches; how should http-music know which to pick? Probably be biased to
+    // pick a group before a track, but.. that doesn't seem perfect either. And
+    // it doesn't solve the problem where there might be two descendants of the
+    // same name (groups or otherwise).
+    possibleMatches = collectGrouplikeChildren(grouplike, isGroup)
+    firstPart = firstPart.slice(1)
+  } else {
+    possibleMatches = grouplike.items
+  }
+
   const titleMatch = (group, caseInsensitive = false) => {
     let a = group.name
-    let b = pathParts[0]
+    let b = firstPart
 
     if (caseInsensitive) {
       a = a.toLowerCase()
@@ -246,10 +287,10 @@ function filterGrouplikeByPath(grouplike, pathParts) {
     return a === b || a === b + '/'
   }
 
-  let match = grouplike.items.find(g => titleMatch(g, false))
+  let match = possibleMatches.find(g => titleMatch(g, false))
 
   if (!match) {
-    match = grouplike.items.find(g => titleMatch(g, true))
+    match = possibleMatches.find(g => titleMatch(g, true))
   }
 
   if (match) {
@@ -260,7 +301,7 @@ function filterGrouplikeByPath(grouplike, pathParts) {
       return match
     }
   } else {
-    console.warn(`Not found: "${pathParts[0]}"`)
+    console.warn(`Not found: "${firstPart}"`)
     return null
   }
 }
diff --git a/todo.txt b/todo.txt
index 48f06b2..ef87e09 100644
--- a/todo.txt
+++ b/todo.txt
@@ -398,3 +398,8 @@ TODO: Let playlists be passed to `play` by an actual string argument; e.g.
       music and use /dev/stdin as the --playlist-file value.. which obviously
       isn't cross-platform or practical!
       (Done!)
+
+TODO: A way to search the playlist for a path. Probably best to modify the
+      function which filters a grouplike by a path. I think I'll hide this
+      feature behind a special prefix, e.g. -c -k '?72 Minutes of Fame'.
+      (Done!)