Okay, this is an interface I am in love with

This commit is contained in:
Benson Chu 2026-06-06 09:26:38 -05:00
parent 1ff3ca9ca2
commit af43b2bacc
2 changed files with 46 additions and 13 deletions

View file

@ -64,6 +64,9 @@ beetslabels:
# in the future? concat: ["label:a", "label:b"] # in the future? concat: ["label:a", "label:b"]
query: "label:effortless" query: "label:effortless"
sort: "effortless + exercise" sort: "effortless + exercise"
- name: everyday
query: "label:everyday"
sort: "everyday"
smartplaylist: smartplaylist:
relative_to: ~/Music/0beets_playlists relative_to: ~/Music/0beets_playlists
@ -71,23 +74,23 @@ smartplaylist:
forward_slash: no forward_slash: no
playlists: playlists:
- name: "favorites.m3u" - name: "favorites.m3u"
query: ['plfavorites:1'] query: ['label:favorites']
- name: "everyday.m3u"
query: ['sorted_playlist:everyday']
- name: "exercise.m3u"
query: ['sorted_playlist:exercise'] # ['^plexercise::^$ plexercise-']
- name: "focus.m3u" - name: "focus.m3u"
query: ['plfocus:1'] query: ['plfocus:1']
- name: "warmth.m3u" - name: "warmth.m3u"
query: ['plwarmth:1'] query: ['plwarmth:1']
- name: "relax.m3u" - name: "relax.m3u"
query: ['plrelax:1'] query: ['plrelax:1']
- name: "everyday.m3u"
query: ['^pleveryday::^$ pleveryday-']
- name: "word.m3u" - name: "word.m3u"
query: ['plword:1'] query: ['plword:1']
- name: "control.m3u" - name: "control.m3u"
query: ['plcontrol:1'] query: ['plcontrol:1']
- name: "precision.m3u" - name: "precision.m3u"
query: ['plprecision:1'] query: ['plprecision:1']
- name: "exercise.m3u"
query: ['sorted_playlist:exercise'] # ['^plexercise::^$ plexercise-']
- name: "chiptune.m3u" - name: "chiptune.m3u"
query: ['genre:chiptune', 'genre:8-bit', 'plchiptune:1'] query: ['genre:chiptune', 'genre:8-bit', 'plchiptune:1']

View file

@ -4,6 +4,7 @@ from beets.ui.commands.modify import print_and_modify
from beets.dbcore import FieldQuery from beets.dbcore import FieldQuery
from beets.dbcore.query import SlowFieldSort from beets.dbcore.query import SlowFieldSort
import re
import json import json
import os import os
import subprocess import subprocess
@ -218,13 +219,20 @@ def edit_labels(lib, opts, args):
finally: finally:
os.remove(temp_file.name) os.remove(temp_file.name)
# Build a lookup from header string to item
def item_header(item):
if item.artist:
return f"{item.artist} - {item.title}:"
return f"{item.title}:"
item_by_header = {item_header(item): item for item in items_list}
# Parse the edited labels and apply changes # Parse the edited labels and apply changes
# Format: "Artist - Title:\n - key: value\n - key2: value2\n\n" # Format: "Artist - Title:\n - key: value\n - key2: value2\n\n"
changes = [] changes = []
i = 0 i = 0
item_idx = 0
while i < len(lines) and item_idx < len(items_list): while i < len(lines):
line = lines[i].strip() line = lines[i].strip()
# Skip blank lines # Skip blank lines
@ -234,18 +242,17 @@ def edit_labels(lib, opts, args):
# Check if this is an item header (ends with :) # Check if this is an item header (ends with :)
if line.endswith(':'): if line.endswith(':'):
item = items_list[item_idx] item = item_by_header.get(line)
item_idx += 1
i += 1 i += 1
# Now read all label lines for this item # Now read all label lines for this item
new_labels = {} new_labels = {}
while i < len(lines): while i < len(lines):
label_line = lines[i] label_line = lines[i]
# Check if this is a label line (starts with " - ") # Check if this is a label line (starts with "- ")
if label_line.startswith('- '): if label_line.startswith('- '):
# Parse: " - key: value" # Parse: "- key: value"
label_content = label_line.strip()[2:].strip() # Remove " - " label_content = label_line.strip()[2:].strip() # Remove "- "
if ':' in label_content: if ':' in label_content:
key, val = label_content.split(':', 1) key, val = label_content.split(':', 1)
key = key.strip() key = key.strip()
@ -253,7 +260,8 @@ def edit_labels(lib, opts, args):
try: try:
new_labels[key] = int(val) new_labels[key] = int(val)
except ValueError: except ValueError:
print_(f"Warning: Invalid value for label '{key}' in item '{item.title}', skipping") if item:
print_(f"Warning: Invalid value for label '{key}' in item '{item.title}', skipping")
else: else:
new_labels[label_content.strip()] = 1 new_labels[label_content.strip()] = 1
i += 1 i += 1
@ -261,6 +269,10 @@ def edit_labels(lib, opts, args):
# Not a label line, done with this item # Not a label line, done with this item
break break
if item is None:
print_(f"Warning: Header '{line}' not found in query results, skipping")
continue
# Compare with old labels # Compare with old labels
old_labels = {} old_labels = {}
if LABELS_FIELD_NAME in item and item[LABELS_FIELD_NAME]: if LABELS_FIELD_NAME in item and item[LABELS_FIELD_NAME]:
@ -272,6 +284,24 @@ def edit_labels(lib, opts, args):
# Unexpected format, skip # Unexpected format, skip
i += 1 i += 1
# Items removed from the file get their labels cleared
headers_in_file = set()
i = 0
while i < len(lines):
line = lines[i].strip()
if line.endswith(':') and line in item_by_header:
headers_in_file.add(line)
i += 1
for item in items_list:
header = item_header(item)
if header not in headers_in_file:
old_labels = {}
if LABELS_FIELD_NAME in item and item[LABELS_FIELD_NAME]:
old_labels = item[LABELS_FIELD_NAME]
if old_labels:
changes.append((item, {}))
if not changes: if not changes:
print_("No changes to make.") print_("No changes to make.")
return return