karaoke-lyrics-processor 0.3.1__py3-none-any.whl → 0.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,6 @@
1
1
  import re
2
2
  import logging
3
3
  import pyperclip
4
- import unicodedata
5
4
  import docx2txt
6
5
  from striprtf.striprtf import rtf_to_text
7
6
  import os
@@ -181,36 +180,52 @@ class KaraokeLyricsProcessor:
181
180
  self.logger.debug(f"Text after cleaning punctuation spacing: {cleaned_text}")
182
181
  return cleaned_text
183
182
 
183
+ def fix_commas_inside_quotes(self, text):
184
+ """
185
+ Move commas inside quotes to after the closing quote.
186
+ """
187
+ self.logger.debug(f"Fixing commas inside quotes in: {text}")
188
+ # Use regex to find patterns where a comma is inside quotes and move it outside
189
+ fixed_text = re.sub(r'(".*?)(,)(\s*")', r"\1\3\2", text)
190
+ self.logger.debug(f"Text after fixing commas inside quotes: {fixed_text}")
191
+ return fixed_text
192
+
184
193
  def process_line(self, line):
185
194
  """
186
195
  Process a single line to ensure it's within the maximum length,
187
196
  handle parentheses, and replace non-printable spaces.
188
197
  """
189
- # Replace non-printable spaces at the beginning
190
198
  line = self.replace_non_printable_spaces(line)
191
- # Clean up punctuation spacing
192
199
  line = self.clean_punctuation_spacing(line)
200
+ line = self.fix_commas_inside_quotes(line)
193
201
 
194
202
  processed_lines = []
195
203
  iteration_count = 0
196
204
  max_iterations = 100 # Failsafe limit
197
205
 
198
- while len(line) > self.max_line_length:
199
- if iteration_count > max_iterations:
200
- self.logger.error(f"Maximum iterations exceeded in process_line for line: {line}")
201
- break
202
-
206
+ while len(line) > self.max_line_length and iteration_count < max_iterations:
203
207
  # Check if the line contains parentheses
204
208
  if "(" in line and ")" in line:
205
209
  start_paren = line.find("(")
206
- end_paren = line.find(")") + 1
210
+ end_paren = self.find_matching_paren(line, start_paren)
207
211
  if end_paren < len(line) and line[end_paren] == ",":
208
212
  end_paren += 1
209
213
 
214
+ # Process text before parentheses if it exists
210
215
  if start_paren > 0:
211
- processed_lines.append(line[:start_paren].strip())
212
- processed_lines.append(line[start_paren:end_paren].strip())
213
- line = line[end_paren:].strip()
216
+ before_paren = line[:start_paren].strip()
217
+ processed_lines.extend(self.split_line(before_paren))
218
+
219
+ # Process text within parentheses
220
+ paren_content = line[start_paren : end_paren + 1].strip()
221
+ if len(paren_content) > self.max_line_length:
222
+ # Split the content within parentheses if it's too long
223
+ split_paren_content = self.split_line(paren_content)
224
+ processed_lines.extend(split_paren_content)
225
+ else:
226
+ processed_lines.append(paren_content)
227
+
228
+ line = line[end_paren + 1 :].strip()
214
229
  else:
215
230
  split_point = self.find_best_split_point(line)
216
231
  processed_lines.append(line[:split_point].strip())
@@ -218,11 +233,46 @@ class KaraokeLyricsProcessor:
218
233
 
219
234
  iteration_count += 1
220
235
 
221
- if line: # Add the remaining part if not empty
222
- processed_lines.append(line)
236
+ if line: # Add any remaining part
237
+ processed_lines.extend(self.split_line(line))
238
+
239
+ if iteration_count >= max_iterations:
240
+ self.logger.error(f"Maximum iterations exceeded in process_line for line: {line}")
223
241
 
224
242
  return processed_lines
225
243
 
244
+ def find_matching_paren(self, line, start_index):
245
+ """
246
+ Find the index of the matching closing parenthesis for the opening parenthesis at start_index.
247
+ """
248
+ stack = 0
249
+ for i in range(start_index, len(line)):
250
+ if line[i] == "(":
251
+ stack += 1
252
+ elif line[i] == ")":
253
+ stack -= 1
254
+ if stack == 0:
255
+ return i
256
+ return -1 # No matching parenthesis found
257
+
258
+ def split_line(self, line):
259
+ """
260
+ Split a line into multiple lines if it exceeds the maximum length.
261
+ """
262
+ if len(line) <= self.max_line_length:
263
+ return [line]
264
+
265
+ split_lines = []
266
+ while len(line) > self.max_line_length:
267
+ split_point = self.find_best_split_point(line)
268
+ split_lines.append(line[:split_point].strip())
269
+ line = line[split_point:].strip()
270
+
271
+ if line:
272
+ split_lines.append(line)
273
+
274
+ return split_lines
275
+
226
276
  def process(self):
227
277
  self.logger.info(f"Processing input lyrics from {self.input_filename}")
228
278
 
@@ -257,9 +307,13 @@ class KaraokeLyricsProcessor:
257
307
  processed_lyrics_text = self.clean_punctuation_spacing(processed_lyrics_text)
258
308
 
259
309
  self.processed_lyrics_text = processed_lyrics_text
260
- pyperclip.copy(processed_lyrics_text)
261
-
262
- self.logger.info(f"Processed lyrics copied to clipboard.")
310
+
311
+ # Try to copy to clipboard, but don't fail if it's not available
312
+ try:
313
+ pyperclip.copy(processed_lyrics_text)
314
+ self.logger.info("Processed lyrics copied to clipboard.")
315
+ except pyperclip.PyperclipException as e:
316
+ self.logger.warning(f"Could not copy to clipboard: {str(e)}")
263
317
 
264
318
  return processed_lyrics_text
265
319
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: karaoke-lyrics-processor
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Summary: Process song lyrics to prepare them for karaoke video production, e.g. by splitting long lines
5
5
  Home-page: https://github.com/karaokenerds/karaoke-lyrics-processor
6
6
  License: MIT
@@ -0,0 +1,8 @@
1
+ karaoke_lyrics_processor/__init__.py,sha256=rLRkJQi61qkRiNXdlTleE3ahJ1oBKcghYVkz64x7IIg,62
2
+ karaoke_lyrics_processor/cli.py,sha256=bdtseRI2jcChb1bMr92pc5mpSWpHXh4TSzA2tknbyjU,2522
3
+ karaoke_lyrics_processor/karaoke_lyrics_processor.py,sha256=Ew91yh7f0kbBy_nnWGntBClRQ1uxE9brhtWExcRl7t0,13716
4
+ karaoke_lyrics_processor-0.4.1.dist-info/LICENSE,sha256=BiPihPDxhxIPEx6yAxVfAljD5Bhm_XG2teCbPEj_m0Y,1069
5
+ karaoke_lyrics_processor-0.4.1.dist-info/METADATA,sha256=4Ut0L964ec92IuLlQiZilngjnjMr4dUm2FAIFk5uCLg,4264
6
+ karaoke_lyrics_processor-0.4.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
+ karaoke_lyrics_processor-0.4.1.dist-info/entry_points.txt,sha256=hjFp6CUxl1p-1WJYfB6TbNcI_DHEnVzX3BXAs4y_0O8,78
8
+ karaoke_lyrics_processor-0.4.1.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- karaoke_lyrics_processor/__init__.py,sha256=rLRkJQi61qkRiNXdlTleE3ahJ1oBKcghYVkz64x7IIg,62
2
- karaoke_lyrics_processor/cli.py,sha256=bdtseRI2jcChb1bMr92pc5mpSWpHXh4TSzA2tknbyjU,2522
3
- karaoke_lyrics_processor/karaoke_lyrics_processor.py,sha256=qMITsW0SbYCaacvEi9WzuZNeBMJhl2wlMck4WktzTEY,11513
4
- karaoke_lyrics_processor-0.3.1.dist-info/LICENSE,sha256=BiPihPDxhxIPEx6yAxVfAljD5Bhm_XG2teCbPEj_m0Y,1069
5
- karaoke_lyrics_processor-0.3.1.dist-info/METADATA,sha256=rCLkfq2I2QkdQlEGI0kiecLb_v5HdcBzuKT0VaNdjJw,4264
6
- karaoke_lyrics_processor-0.3.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
- karaoke_lyrics_processor-0.3.1.dist-info/entry_points.txt,sha256=hjFp6CUxl1p-1WJYfB6TbNcI_DHEnVzX3BXAs4y_0O8,78
8
- karaoke_lyrics_processor-0.3.1.dist-info/RECORD,,