about summary refs log tree commit diff
path: root/users/Profpatsch/lyric/extension
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2024-09-29T13·56+0200
committerProfpatsch <mail@profpatsch.de>2024-10-05T13·49+0000
commit48d021de1559db2a41bcc3a971afb448796e9371 (patch)
treed1efeafbb9dc854c6380b4bcfe0c18ac91238d51 /users/Profpatsch/lyric/extension
parentfa18fea20e0c67bdebed0e98e333ffee7532ed26 (diff)
feat(users/Profpatsch/lyric/ext): add lyric shifting r/8762
Change-Id: I1b52e2a295ae81d5d9bf488b1e584dda4d5aac9b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12550
Reviewed-by: Profpatsch <mail@profpatsch.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'users/Profpatsch/lyric/extension')
-rw-r--r--users/Profpatsch/lyric/extension/package.json10
-rw-r--r--users/Profpatsch/lyric/extension/src/extension.ts134
2 files changed, 137 insertions, 7 deletions
diff --git a/users/Profpatsch/lyric/extension/package.json b/users/Profpatsch/lyric/extension/package.json
index 722da81b4719..389df271cf5a 100644
--- a/users/Profpatsch/lyric/extension/package.json
+++ b/users/Profpatsch/lyric/extension/package.json
@@ -19,6 +19,16 @@
         "command": "extension.jumpToLrcPosition",
         "title": "Jump to .lrc Position",
         "category": "LRC"
+      },
+      {
+        "command": "extension.shiftLyricsDown",
+        "title": "Shift Lyrics Down from Current Line",
+        "category": "LRC"
+      },
+      {
+        "command": "extension.shiftLyricsUp",
+        "title": "Shift Lyrics Up from Current Line",
+        "category": "LRC"
       }
     ],
     "languages": [
diff --git a/users/Profpatsch/lyric/extension/src/extension.ts b/users/Profpatsch/lyric/extension/src/extension.ts
index ded2a8ab0d9c..83b4ab093eda 100644
--- a/users/Profpatsch/lyric/extension/src/extension.ts
+++ b/users/Profpatsch/lyric/extension/src/extension.ts
@@ -5,9 +5,20 @@ export function activate(context: vscode.ExtensionContext) {
   context.subscriptions.push(...registerCheckLineTimestamp(context));
   context.subscriptions.push(
     vscode.commands.registerCommand('extension.jumpToLrcPosition', jumpToLrcPosition),
+    vscode.commands.registerCommand('extension.shiftLyricsDown', shiftLyricsDown),
+    vscode.commands.registerCommand('extension.shiftLyricsUp', shiftLyricsUp),
   );
 }
 
+/**
+ * Jumps to the position in the lyric file corresponding to the current cursor position in the active text editor.
+ * Sends a command to a socket to seek to the specified position in mpv at the socket path `~/tmp/mpv-socket`.
+ * @remarks
+ * This function requires the following dependencies:
+ * - `vscode` module for accessing the active text editor and displaying messages.
+ * - `net` module for creating a socket connection.
+ * @throws {Error} If there is an error sending the command to the socket.
+ */
 function jumpToLrcPosition() {
   const editor = vscode.window.activeTextEditor;
 
@@ -18,7 +29,7 @@ function jumpToLrcPosition() {
 
   const ext = new Ext(editor.document);
   const position = editor.selection.active;
-  const res = ext.getTimestampFromLine(position);
+  const res = ext.getTimestampFromLine(position.line);
 
   if (!res) {
     return;
@@ -47,6 +58,108 @@ function jumpToLrcPosition() {
   });
 }
 
+/**
+ * Shifts the lyrics down by one line starting from the current cursor position in the active text editor.
+ * @remarks
+ * This function requires the following dependencies:
+ * - `vscode` module for accessing the active text editor and displaying messages.
+ */
+async function shiftLyricsDown() {
+  const editor = vscode.window.activeTextEditor;
+
+  if (!editor) {
+    vscode.window.showInformationMessage('No active editor found.');
+    return;
+  }
+
+  const ext = new Ext(editor.document);
+
+  const getLine = (line: number) => ({
+    number: line,
+    range: editor.document.lineAt(line),
+  });
+
+  // get the document range from the beginning of the current line to the end of the file
+  const documentRange = new vscode.Range(
+    getLine(editor.selection.active.line).range.range.start,
+    editor.document.lineAt(editor.document.lineCount - 1).range.end,
+  );
+
+  let newLines: string = '';
+  // iterate through all lines under the current line, save the lyric text from the current line, and replace it with the lyric text from the previous line
+  let previousLineText = '';
+  for (
+    // get the current line range
+    let line = getLine(editor.selection.active.line);
+    line.number < editor.document.lineCount - 1;
+    // next line as position from line number
+    line = getLine(line.number + 1)
+  ) {
+    const timestamp = ext.getTimestampFromLine(line.number);
+    if (timestamp === undefined) {
+      newLines += line.range.text + '\n';
+      continue;
+    }
+    newLines += `[${formatTimestamp(timestamp.milliseconds)}]` + previousLineText + '\n';
+    previousLineText = timestamp.text;
+  }
+  // replace documentRange with newLines
+  await editor.edit(editBuilder => {
+    editBuilder.replace(documentRange, newLines);
+  });
+}
+
+/**
+ * Shifts the lyrics up by one line starting from the current cursor position in the active text editor.
+ * @remarks
+ * This function requires the following dependencies:
+ * - `vscode` module for accessing the active text editor and displaying messages.
+ */
+async function shiftLyricsUp() {
+  const editor = vscode.window.activeTextEditor;
+
+  if (!editor) {
+    vscode.window.showInformationMessage('No active editor found.');
+    return;
+  }
+
+  const ext = new Ext(editor.document);
+
+  const getLine = (line: number) => ({
+    number: line,
+    range: editor.document.lineAt(line),
+  });
+
+  // get the document range from the beginning of the current line to the end of the file
+  const documentRange = new vscode.Range(
+    getLine(editor.selection.active.line).range.range.start,
+    editor.document.lineAt(editor.document.lineCount - 1).range.end,
+  );
+
+  let newLines: string = '';
+  // iterate through all lines under the current line, save the lyric text from the current line, and replace it with the lyric text from the next line
+  for (
+    // get the current line range
+    let line = getLine(editor.selection.active.line);
+    line.number < editor.document.lineCount - 2;
+    // next line as position from line number
+    line = getLine(line.number + 1)
+  ) {
+    const nextLineText =
+      ext.getTimestampFromLine(line.number + 1)?.text ??
+      ext.document.lineAt(line.number + 1).text;
+    const timestamp = ext.getTimestampFromLine(line.number);
+    if (timestamp === undefined) {
+      continue;
+    }
+    newLines += `[${formatTimestamp(timestamp.milliseconds)}]` + nextLineText + '\n';
+  }
+  // replace documentRange with newLines
+  await editor.edit(editBuilder => {
+    editBuilder.replace(documentRange, newLines);
+  });
+}
+
 // If the difference to the timestamp on the next line is larger than 10 seconds, underline the next line and show a warning message on hover
 export function registerCheckLineTimestamp(_context: vscode.ExtensionContext) {
   const changesToCheck: Set<vscode.TextDocument> = new Set();
@@ -154,10 +267,8 @@ class Ext {
   constructor(public document: vscode.TextDocument) {}
 
   getTimeDifferenceToNextLineTimestamp(position: vscode.Position) {
-    const thisLineTimestamp = this.getTimestampFromLine(position);
-    const nextLineTimestamp = this.getTimestampFromLine(
-      position.with({ line: position.line + 1 }),
-    );
+    const thisLineTimestamp = this.getTimestampFromLine(position.line);
+    const nextLineTimestamp = this.getTimestampFromLine(position.line + 1);
     if (!thisLineTimestamp || !nextLineTimestamp) {
       return;
     }
@@ -167,9 +278,18 @@ class Ext {
     };
   }
 
-  getTimestampFromLine(position: vscode.Position) {
-    const lineText = this.document.lineAt(position.line).text;
+  /**
+   * Retrieves the timestamp and text from the line at the given position in the active text editor.
+   *
+   * @param position - The position of the line in the editor.
+   * @returns An object containing the milliseconds, seconds, and text extracted from the line.
+   */
+  getTimestampFromLine(line: number) {
+    const lineText = this.document.lineAt(line).text;
+    return this.getTimestampFromLineText(lineText);
+  }
 
+  getTimestampFromLineText(lineText: string) {
     // Extract timestamp [mm:ss.ms] from the current line
     const match = lineText.match(/\[(\d+:\d+\.\d+)\](.*)/);
     if (!match) {