feat: print plain lyrics without tags
This commit is contained in:
+24
-3
@@ -18,7 +18,7 @@ from .models import TrackMeta, CacheStatus
|
||||
from .mpris import get_current_track
|
||||
from .core import LrcManager
|
||||
from .fetchers import FetcherMethodType
|
||||
from .lrc import get_sidecar_path
|
||||
from .lrc import get_sidecar_path, print_lyrics, to_plain
|
||||
|
||||
|
||||
app = cyclopts.App(
|
||||
@@ -94,6 +94,12 @@ def fetch(
|
||||
name="--only-synced", negative="", help="Only accept synced (timed) lyrics."
|
||||
),
|
||||
] = False,
|
||||
plain: Annotated[
|
||||
bool,
|
||||
cyclopts.Parameter(
|
||||
name="--plain", negative="", help="Output only the raw lyrics without tags."
|
||||
),
|
||||
] = False,
|
||||
):
|
||||
"""Fetch and print lyrics for the currently playing track."""
|
||||
track = get_current_track(_player)
|
||||
@@ -114,7 +120,7 @@ def fetch(
|
||||
logger.error("Only unsynced lyrics available (--only-synced requested).")
|
||||
sys.exit(1)
|
||||
|
||||
print(result.lyrics)
|
||||
print_lyrics(result.lyrics, plain=plain)
|
||||
|
||||
|
||||
# search
|
||||
@@ -165,6 +171,12 @@ def search(
|
||||
name="--only-synced", negative="", help="Only accept synced (timed) lyrics."
|
||||
),
|
||||
] = False,
|
||||
plain: Annotated[
|
||||
bool,
|
||||
cyclopts.Parameter(
|
||||
name="--plain", negative="", help="Output only the raw lyrics without tags."
|
||||
),
|
||||
] = False,
|
||||
):
|
||||
"""Search for lyrics by metadata (bypasses MPRIS)."""
|
||||
if url and path:
|
||||
@@ -196,7 +208,7 @@ def search(
|
||||
logger.error("Only unsynced lyrics available (--only-synced requested).")
|
||||
sys.exit(1)
|
||||
|
||||
print(result.lyrics)
|
||||
print_lyrics(result.lyrics, plain=plain)
|
||||
|
||||
|
||||
# export
|
||||
@@ -224,6 +236,12 @@ def export(
|
||||
name=["--overwrite", "-f"], negative="", help="Overwrite existing file."
|
||||
),
|
||||
] = False,
|
||||
plain: Annotated[
|
||||
bool,
|
||||
cyclopts.Parameter(
|
||||
name="--plain", negative="", help="Export only the raw lyrics without tags."
|
||||
),
|
||||
] = False,
|
||||
):
|
||||
"""Export lyrics of the current track to a .lrc file."""
|
||||
track = get_current_track(_player)
|
||||
@@ -263,6 +281,9 @@ def export(
|
||||
|
||||
try:
|
||||
with open(output, "w", encoding="utf-8") as f:
|
||||
if plain:
|
||||
f.write(to_plain(result.lyrics))
|
||||
else:
|
||||
f.write(result.lyrics)
|
||||
logger.info(f"Exported lyrics to {output}")
|
||||
except Exception as e:
|
||||
|
||||
@@ -27,6 +27,9 @@ _LRC_LINE_RE = re.compile(r"^\[\d{2,}:\d{2}\.\d{2}\]", re.MULTILINE)
|
||||
# [offset:+/-xxx] tag — value in milliseconds
|
||||
_OFFSET_RE = re.compile(r"^\[offset:\s*([+-]?\d+)\]\s*$", re.MULTILINE | re.IGNORECASE)
|
||||
|
||||
# Matches any number of tags at the start of a line
|
||||
_LINE_START_TAGS_RE = re.compile(r"^(?:\[[^\]]*\])+")
|
||||
|
||||
|
||||
def _raw_tag_to_cs(mm: str, ss: str, frac: Optional[str]) -> str:
|
||||
"""Convert parsed time tag components to standard [mm:ss.cc] string."""
|
||||
@@ -176,3 +179,41 @@ def get_sidecar_path(
|
||||
if ensure_exists and not lrc_path.exists():
|
||||
return None
|
||||
return lrc_path
|
||||
|
||||
|
||||
def to_plain(
|
||||
text: str,
|
||||
) -> str:
|
||||
"""Convert lyrics to plain text with all tags stripped.
|
||||
|
||||
Assumes text has been normalized by normalize_tags.
|
||||
"""
|
||||
|
||||
lines = []
|
||||
first = True
|
||||
for line in text.splitlines():
|
||||
cleaned = _LINE_START_TAGS_RE.sub("", line).strip()
|
||||
# Ignore the leading empty lines that is likely caused by tag lines
|
||||
if not cleaned and not first:
|
||||
lines.append("")
|
||||
elif cleaned:
|
||||
lines.append(cleaned)
|
||||
first = False
|
||||
# Remove trailing empty lines that are meaningless
|
||||
while lines and not lines[-1]:
|
||||
lines.pop()
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def print_lyrics(
|
||||
text: str,
|
||||
plain: bool = False,
|
||||
) -> None:
|
||||
"""Print lyrics, optionally stripping tags.
|
||||
|
||||
Assumes text has been normalized by normalize_tags.
|
||||
"""
|
||||
if plain:
|
||||
print(to_plain(text))
|
||||
else:
|
||||
print(text)
|
||||
|
||||
Reference in New Issue
Block a user