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"]
query: "label:effortless"
sort: "effortless + exercise"
- name: everyday
query: "label:everyday"
sort: "everyday"
smartplaylist:
relative_to: ~/Music/0beets_playlists
@ -71,23 +74,23 @@ smartplaylist:
forward_slash: no
playlists:
- 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"
query: ['plfocus:1']
- name: "warmth.m3u"
query: ['plwarmth:1']
- name: "relax.m3u"
query: ['plrelax:1']
- name: "everyday.m3u"
query: ['^pleveryday::^$ pleveryday-']
- name: "word.m3u"
query: ['plword:1']
- name: "control.m3u"
query: ['plcontrol:1']
- name: "precision.m3u"
query: ['plprecision:1']
- name: "exercise.m3u"
query: ['sorted_playlist:exercise'] # ['^plexercise::^$ plexercise-']
- name: "chiptune.m3u"
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.query import SlowFieldSort
import re
import json
import os
import subprocess
@ -218,13 +219,20 @@ def edit_labels(lib, opts, args):
finally:
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
# Format: "Artist - Title:\n - key: value\n - key2: value2\n\n"
changes = []
i = 0
item_idx = 0
while i < len(lines) and item_idx < len(items_list):
while i < len(lines):
line = lines[i].strip()
# Skip blank lines
@ -234,18 +242,17 @@ def edit_labels(lib, opts, args):
# Check if this is an item header (ends with :)
if line.endswith(':'):
item = items_list[item_idx]
item_idx += 1
item = item_by_header.get(line)
i += 1
# Now read all label lines for this item
new_labels = {}
while i < len(lines):
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('- '):
# Parse: " - key: value"
label_content = label_line.strip()[2:].strip() # Remove " - "
# Parse: "- key: value"
label_content = label_line.strip()[2:].strip() # Remove "- "
if ':' in label_content:
key, val = label_content.split(':', 1)
key = key.strip()
@ -253,7 +260,8 @@ def edit_labels(lib, opts, args):
try:
new_labels[key] = int(val)
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:
new_labels[label_content.strip()] = 1
i += 1
@ -261,6 +269,10 @@ def edit_labels(lib, opts, args):
# Not a label line, done with this item
break
if item is None:
print_(f"Warning: Header '{line}' not found in query results, skipping")
continue
# Compare with old labels
old_labels = {}
if LABELS_FIELD_NAME in item and item[LABELS_FIELD_NAME]:
@ -272,6 +284,24 @@ def edit_labels(lib, opts, args):
# Unexpected format, skip
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:
print_("No changes to make.")
return