« get me outta code hell

mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--ui.js77
2 files changed, 79 insertions, 1 deletions
diff --git a/README.md b/README.md
index b410956..b760230 100644
--- a/README.md
+++ b/README.md
@@ -32,12 +32,13 @@ You're also welcome to share any ideas, suggestions, and questions through there
 * <kbd>Enter</kbd> - play the selected track
 * <kbd><kbd>Ctrl</kbd>+<kbd>Up</kbd></kbd> or <kbd>p</kbd> - play previous track
 * <kbd><kbd>Ctrl</kbd>+<kbd>Down</kbd></kbd> or <kbd>n</kbd> - play next track
+* <kbd><kbd>Shift</kbd>+<kbd>Up</kbd>/<kbd>Down</kbd></kbd> or drag - select multiple items at once
 * <kbd>Space</kbd> - toggle pause
 * <kbd>Escape</kbd> - stop playing the current track
 * <kbd>l</kbd> - toggle track loop
 * <kbd>Right</kbd> - seek ahead
 * <kbd>Left</kbd> - seek back
-* <kbd>m</kbd> or <kbd>f</kbd> - open a menu of actions related to the selected track or group
+* <kbd>m</kbd> or <kbd>f</kbd> - open a menu of actions related to the selected track/group/item(s)
 * <kbd>v</kbd> and <kbd>V</kbd> - increase and decrease playback volume
 * <kbd><kbd>Ctrl</kbd>+<kbd>F</kbd></kbd> or <kbd>/</kbd> - jump to a track or group by entering (part of) its name
 * <kbd><kbd>Ctrl</kbd>+<kbd>O</kbd></kbd> - open a playlist from a source (like a /path/to/a/folder or a YouTube playlist URL) (you can also just pass this source to `mtui`)
diff --git a/ui.js b/ui.js
index 13f115b..0d17fb8 100644
--- a/ui.js
+++ b/ui.js
@@ -79,6 +79,8 @@ const keyBindings = [
   ['isClearQueue', 'c'],
   ['isFocusMenubar', ';'],
   ['isFocusLabels', 'l'], // *** conflicts with isToggleLoop!!! must change this
+  ['isSelectUp', telc.isShiftUp],
+  ['isSelectDown', telc.isShiftDown],
 
   // Number pad
   ['isUp', '8'],
@@ -1204,6 +1206,8 @@ class GrouplikeListingElement extends Form {
   }
 
   selectNone() {
+    // nb: this is unrelated to the actual track selection system!
+    // just clears the form selection
     this.pathElement.showItem(null)
     this.form.curIndex = 0
     this.form.scrollItems = 0
@@ -1413,9 +1417,24 @@ class GrouplikeListingForm extends ListScrollForm {
 
     this.app = app
     this.dragInputs = []
+    this.selectMode = null
+    this.keyboardDragDirection = null
     this.captureTab = false
   }
 
+  keyPressed(keyBuf) {
+    if (input.isSelectUp(keyBuf)) {
+      this.selectUp()
+    } else if (input.isSelectDown(keyBuf)) {
+      this.selectDown()
+    } else {
+      if (telc.isUp(keyBuf) || telc.isDown(keyBuf)) {
+        this.keyboardDragDirection = null
+      }
+      return super.keyPressed(keyBuf)
+    }
+  }
+
   set curIndex(newIndex) {
     this._curIndex = newIndex
     this.emit('selected input', this.inputs[this.curIndex])
@@ -1521,6 +1540,64 @@ class GrouplikeListingForm extends ListScrollForm {
       }
     }
   }
+
+  selectUp() {
+    this.handleKeyboardSelect(-1)
+  }
+
+  selectDown() {
+    this.handleKeyboardSelect(+1)
+  }
+
+  handleKeyboardSelect(direction) {
+    const move = () => {
+      if (direction === +1) {
+        this.nextInput()
+      } else {
+        this.previousInput()
+      }
+    }
+
+    const getItem = () => {
+      const input = this.inputs[this.curIndex]
+      if (input instanceof InteractiveGrouplikeItemElement) {
+        return input.item
+      } else {
+        return null
+      }
+    }
+
+    if (!this.keyboardDragDirection) {
+      const item = getItem()
+      if (!item) {
+        return
+      }
+      this.keyboardDragDirection = direction
+      this.oldMarkedItems = this.app.markGrouplike.items.slice()
+      if (this.app.markGrouplike.items.includes(item)) {
+        this.selectMode = 'deselect'
+      } else {
+        this.selectMode = 'select'
+      }
+      this.dragEnteredRange(item)
+    }
+
+    if (direction === this.keyboardDragDirection) {
+      move()
+      const item = getItem()
+      if (!item) {
+        return
+      }
+      this.dragEnteredRange(item)
+    } else {
+      const item = getItem()
+      if (!item) {
+        return
+      }
+      this.dragLeftRange(item)
+      move()
+    }
+  }
 }
 
 class BasicGrouplikeItemElement extends Button {