[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/subed a1c61d7d4d: Parse and retain comments in VTT files,
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/subed a1c61d7d4d: Parse and retain comments in VTT files, and simplify creating files |
Date: |
Thu, 17 Nov 2022 09:59:40 -0500 (EST) |
branch: elpa/subed
commit a1c61d7d4d303dcc6fe7b7dbd20264cda146b639
Author: Sacha Chua <sacha@sachachua.com>
Commit: Sacha Chua <sacha@sachachua.com>
Parse and retain comments in VTT files, and simplify creating files
* subed/subed-common.el (subtitle-comment): New function to get the
comment before the current subtitle.
(make-subtitle): Add comment.
(prepend-subtitle): Add comment.
(append-subtitle): Add comment.
(subed-subtitle): New function.
(subed-create-file): New function to simplify creating a file with
subtitles in it.
(subed-convert): Handle buffers that are not visiting files. Use
subed-create-file if visiting a file.
* subed/subed-vtt.el (subed--make-subtitle): Add comment.
(subed--prepend-subtitle): Add comment.
(subed--append-subtitle): Add comment.
(subed--subtitle-comment): Parse comments before the current subtitle.
(subed-vtt--format-comment): New function.
(subed--sanitize-format): Do not remove comments when sanitizing.
* subed/subed-ass.el, subed/subed-srt.el,
subed/subed-tsv.el (subed--make-subtitle): Add comment.
(subed--prepend-subtitle): Add comment.
(subed--append-subtitle): Add comment.
* tests/test-subed-common.el ("COMMON"): Add comment to subtitle list
output.
* tests/test-subed-vtt.el ("VTT"): Test that comments are retained.
---
NEWS.org | 17 +++++++++
subed/subed-ass.el | 11 +++---
subed/subed-common.el | 87 ++++++++++++++++++++++++++++++----------------
subed/subed-srt.el | 6 ++--
subed/subed-tsv.el | 15 ++++----
subed/subed-vtt.el | 42 +++++++++++++++++-----
subed/subed.el | 2 +-
tests/test-subed-common.el | 11 +++---
tests/test-subed-vtt.el | 15 +++++++-
9 files changed, 148 insertions(+), 58 deletions(-)
diff --git a/NEWS.org b/NEWS.org
index 2ca917fd27..f2f17e03ce 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -2,6 +2,22 @@
* subed news
+** Version 1.0.22 - 2022-11-17 - Sacha Chua
+
+VTT comments are now parsed and returned as part of ~subed-subtitle~
+and ~subed-subtitle-list~. This makes it easier to build workflows
+that use the comment information, such as adding NOTE lines for
+chapters and then creating a new file based on those lines and the
+subtitles following them.
+
+A new function ~subed-create-file~ helps create a file with a list of
+subtitles.
+
+Sanitizing VTT files with ~subed-sanitize~ should retain comments now.
+
+~subed-convert~ should now create a buffer instead of a file if the
+source is a buffer that isn't a file.
+
** Version 1.0.21 - 2022-11-16 - Sacha Chua
- subed-align-options is a new variable that will be passed to aeneas
@@ -143,3 +159,4 @@ you have any code that refers to functions like
=subed-vtt--timestamp-to-msecs=, you will need to change your code to
use generic functions such as =subed-timestamp-to-msecs=.
+
diff --git a/subed/subed-ass.el b/subed/subed-ass.el
index b31a2a4638..f2ca52ccd9 100644
--- a/subed/subed-ass.el
+++ b/subed/subed-ass.el
@@ -205,12 +205,13 @@ format-specific function for MAJOR-MODE."
;;; Manipulation
-(cl-defmethod subed--make-subtitle (&context (major-mode subed-ass-mode)
&optional id start stop text)
+(cl-defmethod subed--make-subtitle (&context (major-mode subed-ass-mode)
&optional id start stop text comment)
"Generate new subtitle string.
ID, START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT is ignored.
A newline is appended to TEXT, meaning you'll get two trailing
newlines if TEXT is nil or empty. Use the format-specific
@@ -218,15 +219,16 @@ function for MAJOR-MODE."
(format "Dialogue: 0,%s,%s,Default,,0,0,0,,%s\n"
(subed-msecs-to-timestamp (or start 0))
(subed-msecs-to-timestamp (or stop (+ (or start 0)
-
subed-default-subtitle-length)))
+
subed-default-subtitle-length)))
(replace-regexp-in-string "\n" "\\n" (or text ""))))
-(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-ass-mode)
&optional id start stop text)
+(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-ass-mode)
&optional id start stop text comment)
"Insert new subtitle before the subtitle at point.
ID and START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT is ignored.
Move point to the text of the inserted subtitle. Return new
point. Use the format-specific function for MAJOR-MODE."
@@ -235,12 +237,13 @@ point. Use the format-specific function for MAJOR-MODE."
(forward-line -1)
(subed-jump-to-subtitle-text))
-(cl-defmethod subed--append-subtitle (&context (major-mode subed-ass-mode)
&optional id start stop text)
+(cl-defmethod subed--append-subtitle (&context (major-mode subed-ass-mode)
&optional id start stop text comment)
"Insert new subtitle after the subtitle at point.
ID, START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT is ignored.
Move point to the text of the inserted subtitle. Return new
point. Use the format-specific function for MAJOR-MODE."
diff --git a/subed/subed-common.el b/subed/subed-common.el
index 62c1267d1a..84c17f6487 100644
--- a/subed/subed-common.el
+++ b/subed/subed-common.el
@@ -257,6 +257,10 @@ If SUB-ID is not given, set the text of the current
subtitle."
(when start-point
(- (point) start-point))))
+(subed-define-generic-function subtitle-comment (&optional sub-id)
+ "Return the comment preceding this subtitle."
+ nil)
+
(subed-define-generic-function set-subtitle-time-start (msecs &optional sub-id)
"Set subtitle start time to MSECS milliseconds.
@@ -283,31 +287,34 @@ Return the new subtitle stop time in milliseconds."
(replace-match
(save-match-data (subed-msecs-to-timestamp msecs))))))
-(subed-define-generic-function make-subtitle (&optional id start stop text)
+(subed-define-generic-function make-subtitle (&optional id start stop text
comment)
"Generate new subtitle string.
ID, START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
-TEXT defaults to an empty string."
+TEXT defaults to an empty string.
+COMMENT defaults to nil."
(interactive "P"))
-(subed-define-generic-function prepend-subtitle (&optional id start stop text)
+(subed-define-generic-function prepend-subtitle (&optional id start stop text
comment)
"Insert new subtitle before the subtitle at point.
ID and START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT defaults to nil.
Move point to the text of the inserted subtitle.
Return new point."
(interactive "P"))
-(subed-define-generic-function append-subtitle (&optional id start stop text)
+(subed-define-generic-function append-subtitle (&optional id start stop text
comment)
"Insert new subtitle after the subtitle at point.
ID, START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT defaults to nil.
Move point to the text of the inserted subtitle.
Return new point."
@@ -347,9 +354,19 @@ Otherwise, initialize the mode based on the filename."
(subed-tsv-mode))))
(subed-subtitle-list))))
+(defun subed-subtitle ()
+ "Return the subtitle at point as a list.
+The list is of the form (id start stop text comment)."
+ (list
+ (subed-subtitle-id)
+ (subed-subtitle-msecs-start)
+ (subed-subtitle-msecs-stop)
+ (subed-subtitle-text)
+ (subed-subtitle-comment)))
+
(defun subed-subtitle-list (&optional beg end)
"Return the subtitles from BEG to END as a list.
-The list will contain entries of the form (id start stop text).
+The list will contain entries of the form (id start stop text comment).
If BEG and END are not specified, use the whole buffer."
(let (result)
(subed-for-each-subtitle
@@ -357,14 +374,7 @@ If BEG and END are not specified, use the whole buffer."
(or end (point-max))
nil
(when (subed-subtitle-msecs-start)
- (setq result
- (cons
- (list
- (subed-subtitle-id)
- (subed-subtitle-msecs-start)
- (subed-subtitle-msecs-stop)
- (subed-subtitle-text))
- result))))
+ (setq result (cons (subed-subtitle) result))))
(nreverse result)))
(subed-define-generic-function sanitize ()
@@ -1920,28 +1930,47 @@ If LIST is nil, use the subtitles in the current
buffer."
(interactive)
nil)
+(defun subed-create-file (filename subtitles &optional ok-if-exists mode)
+ "Create FILENAME, set it to MODE, and prepopulate it with SUBTITLES.
+Overwrites existing files."
+ (when (and (file-exists-p filename) (not ok-if-exists))
+ (error "File %s already exists." filename))
+ (let ((subed-auto-play-media nil))
+ (find-file filename)
+ (erase-buffer)
+ (if mode (funcall mode))
+ (subed-auto-insert)
+ (mapc (lambda (sub) (apply #'subed-append-subtitle nil (cdr sub)))
subtitles)))
+
(defun subed-convert (format)
"Create a buffer with the current subtitles converted to FORMAT.
You may need to add some extra information to the buffer."
(interactive (list (completing-read "To format: " '("VTT" "SRT" "ASS" "TSV"
"TXT"))))
(let* ((subtitles (subed-subtitle-list))
- (new-filename (concat (file-name-base (or (buffer-file-name)
(buffer-name))) "." (downcase format)))
- buf)
- (when (or (not (file-exists-p new-filename))
- (yes-or-no-p (format "%s exists. Overwrite? " new-filename)))
- (find-file new-filename)
+ (new-filename (concat (file-name-base (or (buffer-file-name)
(buffer-name))) "."
+ (downcase format)))
+ (mode-func (pcase format
+ ("VTT" (require 'subed-vtt) 'subed-vtt-mode)
+ ("SRT" (require 'subed-srt) 'subed-srt-mode)
+ ("ASS" (require 'subed-ass) 'subed-ass-mode)
+ ("TSV" (require 'subed-tsv) 'subed-tsv-mode))))
+ (if (buffer-file-name)
+ ;; Create a new file
+ (when (or (not (file-exists-p new-filename))
+ (yes-or-no-p (format "%s exists. Overwrite? " new-filename)))
+ (if (string= format "TXT")
+ (progn
+ (with-temp-file new-filename
+ (insert (mapconcat (lambda (o) (elt o 3)) subtitles "\n")))
+ (find-file new-filename))
+ (subed-create-file new-filename subtitles t mode-func))
+ (current-buffer))
+ ;; Create a temporary buffer
+ (switch-to-buffer (get-buffer-create new-filename))
(erase-buffer)
- (save-excursion
- (if (string= format "TXT")
- (insert (mapconcat (lambda (o) (elt o 3)) subtitles "\n"))
- (pcase format
- ("VTT" (require 'subed-vtt) (subed-vtt-mode))
- ("SRT" (require 'subed-srt) (subed-srt-mode))
- ("ASS" (require 'subed-ass) (subed-ass-mode))
- ("TSV" (require 'subed-tsv) (subed-tsv-mode)))
- (subed-auto-insert)
- (mapc (lambda (sub) (apply #'subed-append-subtitle nil (cdr sub)))
subtitles)
- (subed-regenerate-ids)))
+ (funcall mode-func)
+ (subed-auto-insert)
+ (mapc (lambda (sub) (apply #'subed-append-subtitle nil (cdr sub)))
subtitles)
(current-buffer))))
(provide 'subed-common)
diff --git a/subed/subed-srt.el b/subed/subed-srt.el
index eeb52e5b44..51412b8a20 100644
--- a/subed/subed-srt.el
+++ b/subed/subed-srt.el
@@ -196,7 +196,7 @@ Use the format-specific function for MAJOR-MODE."
;;; Manipulation
-(cl-defmethod subed--make-subtitle (&context (major-mode subed-srt-mode)
&optional id start stop text)
+(cl-defmethod subed--make-subtitle (&context (major-mode subed-srt-mode)
&optional id start stop text comment)
"Generate new subtitle string.
ID, START default to 0.
@@ -213,7 +213,7 @@ function for MAJOR-MODE."
subed-default-subtitle-length)))
(or text "")))
-(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-srt-mode)
&optional id start stop text)
+(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-srt-mode)
&optional id start stop text comment)
"Insert new subtitle before the subtitle at point.
ID and START default to 0.
@@ -229,7 +229,7 @@ Return new point. Use the format-specific function for
MAJOR-MODE."
(forward-line -2)
(subed-jump-to-subtitle-text))
-(cl-defmethod subed--append-subtitle (&context (major-mode subed-srt-mode)
&optional id start stop text)
+(cl-defmethod subed--append-subtitle (&context (major-mode subed-srt-mode)
&optional id start stop text comment)
"Insert new subtitle after the subtitle at point.
ID, START default to 0.
diff --git a/subed/subed-tsv.el b/subed/subed-tsv.el
index b9f5295d61..33ee1784f3 100644
--- a/subed/subed-tsv.el
+++ b/subed/subed-tsv.el
@@ -348,12 +348,13 @@ Use the format-specific function for MAJOR-MODE."
(when (looking-at subed-tsv--regexp-timestamp)
(replace-match (subed-msecs-to-timestamp msecs))))))
-(cl-defmethod subed--make-subtitle (&context (major-mode subed-tsv-mode)
&optional id start stop text)
+(cl-defmethod subed--make-subtitle (&context (major-mode subed-tsv-mode)
&optional id start stop text comment)
"Generate new subtitle string.
ID, START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT is ignored.
A newline is appended to TEXT, meaning you'll get two trailing
newlines if TEXT is nil or empty.
@@ -361,30 +362,32 @@ Use the format-specific function for MAJOR-MODE."
(format "%s\t%s\t%s\n"
(subed-msecs-to-timestamp (or start 0))
(subed-msecs-to-timestamp (or stop (+ (or start 0)
-
subed-default-subtitle-length)))
+
subed-default-subtitle-length)))
(replace-regexp-in-string "\n" " " (or text ""))))
-(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-tsv-mode)
&optional id start stop text)
+(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-tsv-mode)
&optional id start stop text comment)
"Insert new subtitle before the subtitle at point.
ID and START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT is ignored.
Move point to the text of the inserted subtitle.
Return new point.
Use the format-specific function for MAJOR-MODE."
(subed-jump-to-subtitle-id)
- (insert (subed-make-subtitle id start stop text))
+ (insert (subed-make-subtitle id start stop text comment))
(forward-line -1)
(subed-jump-to-subtitle-text))
-(cl-defmethod subed--append-subtitle (&context (major-mode subed-tsv-mode)
&optional id start stop text)
+(cl-defmethod subed--append-subtitle (&context (major-mode subed-tsv-mode)
&optional id start stop text comment)
"Insert new subtitle after the subtitle at point.
ID, START default to 0.
STOP defaults to (+ START `subed-subtitle-spacing')
TEXT defaults to an empty string.
+COMMENT is ignored.
Move point to the text of the inserted subtitle.
Return new point.
@@ -393,7 +396,7 @@ Use the format-specific function for MAJOR-MODE."
;; Point is on last subtitle or buffer is empty
(subed-jump-to-subtitle-end)
(unless (bolp) (insert "\n")))
- (insert (subed-make-subtitle id start stop text))
+ (insert (subed-make-subtitle id start stop text comment))
(forward-line -1)
(subed-jump-to-subtitle-text))
diff --git a/subed/subed-vtt.el b/subed/subed-vtt.el
index 6dd8842775..6d77ad2693 100644
--- a/subed/subed-vtt.el
+++ b/subed/subed-vtt.el
@@ -102,6 +102,18 @@ format-specific function for MAJOR-MODE."
(unless (subed-forward-subtitle-id)
(throw 'subtitle-id nil))))))
+(cl-defmethod subed--subtitle-comment (&context (major-mode subed-vtt-mode)
&optional sub-id)
+ "Return the comment or comments before the current subtitle.
+If SUB-ID is specified, jump to that subtitle first.
+Use the format-specific function for MAJOR-MODE."
+ (save-excursion
+ (subed-jump-to-subtitle-id sub-id)
+ (let ((sub-start-point (point))
+ (prev-end (or (subed-backward-subtitle-end)
+ (goto-char (point-min)))))
+ (when (re-search-forward "^\\(NOTE\\(.*\n\\)+\n+\\)" sub-start-point t)
+ (match-string 0)))))
+
;;; Traversing
(cl-defmethod subed--jump-to-subtitle-id (&context (major-mode subed-vtt-mode)
&optional sub-id)
@@ -223,7 +235,19 @@ format-specific function for MAJOR-MODE."
;;; Manipulation
-(cl-defmethod subed--make-subtitle (&context (major-mode subed-vtt-mode)
&optional id start stop text)
+(defun subed-vtt--format-comment (comment)
+ "Return COMMENT formatted for insertion.
+If COMMENT starts with NOTE, keep it as is. If not, add a NOTE header to it.
+Make sure COMMENT ends with a blank line."
+ (cond ((null comment) "")
+ ((string-match "\\`NOTE"
+ (concat comment
+ (if (string-match "\n\n\\'" comment)
+ "" "\n\n"))))
+ ((string-match "\n" comment) (concat "NOTE\n" comment "\n\n"))
+ (t (concat "NOTE " comment))))
+
+(cl-defmethod subed--make-subtitle (&context (major-mode subed-vtt-mode)
&optional id start stop text comment)
"Generate new subtitle string.
ID, START default to 0.
@@ -233,13 +257,14 @@ TEXT defaults to an empty string.
A newline is appended to TEXT, meaning you'll get two trailing
newlines if TEXT is nil or empty. Use the format-specific
function for MAJOR-MODE."
- (format "%s --> %s\n%s\n"
+ (format "%s%s --> %s\n%s\n"
+ (subed-vtt--format-comment comment)
(subed-msecs-to-timestamp (or start 0))
(subed-msecs-to-timestamp (or stop (+ (or start 0)
subed-default-subtitle-length)))
(or text "")))
-(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-vtt-mode)
&optional id start stop text)
+(cl-defmethod subed--prepend-subtitle (&context (major-mode subed-vtt-mode)
&optional id start stop text comment)
"Insert new subtitle before the subtitle at point.
ID and START default to 0.
@@ -249,13 +274,13 @@ TEXT defaults to an empty string.
Move point to the text of the inserted subtitle. Return new
point. Use the format-specific function for MAJOR-MODE."
(subed-jump-to-subtitle-id)
- (insert (subed-make-subtitle id start stop text))
+ (insert (subed-make-subtitle id start stop text comment))
(when (looking-at (concat "\\([[:space:]]*\\|^\\)" subed--regexp-timestamp))
(insert "\n"))
(forward-line -2)
(subed-jump-to-subtitle-text))
-(cl-defmethod subed--append-subtitle (&context (major-mode subed-vtt-mode)
&optional id start stop text)
+(cl-defmethod subed--append-subtitle (&context (major-mode subed-vtt-mode)
&optional id start stop text comment)
"Insert new subtitle after the subtitle at point.
ID, START default to 0.
@@ -274,7 +299,7 @@ point. Use the format-specific function for MAJOR-MODE."
(save-excursion (insert ?\n)))
;; Move to end of separator
(goto-char (match-end 0)))
- (insert (subed-make-subtitle id start stop text))
+ (insert (subed-make-subtitle id start stop text comment))
(unless (eolp)
;; Complete separator with another newline unless we inserted at the end
(insert ?\n))
@@ -319,13 +344,14 @@ Use the format-specific function for MAJOR-MODE."
(while (looking-at "\\`\n+")
(replace-match ""))
- ;; Replace separators between subtitles with double newlines
+ ;; Replace blank separators between subtitles with double newlines
(goto-char (point-min))
(while (subed-forward-subtitle-id)
(let ((prev-sub-end (save-excursion (when (subed-backward-subtitle-end)
(point)))))
(when (and prev-sub-end
- (not (string= (buffer-substring prev-sub-end (point))
"\n\n")))
+ (not (string= (buffer-substring prev-sub-end (point))
"\n\n"))
+ (string-match "\\`\n+\\'" (buffer-substring prev-sub-end
(point))))
(delete-region prev-sub-end (point))
(insert "\n\n"))))
diff --git a/subed/subed.el b/subed/subed.el
index e5f340109f..b5831de850 100644
--- a/subed/subed.el
+++ b/subed/subed.el
@@ -1,6 +1,6 @@
;;; subed.el --- A major mode for editing subtitles -*- lexical-binding: t;
-*-
-;; Version: 1.0.21
+;; Version: 1.0.22
;; Maintainer: Sacha Chua <sacha@sachachua.com>
;; Author: Random User
;; Keywords: convenience, files, hypermedia, multimedia
diff --git a/tests/test-subed-common.el b/tests/test-subed-common.el
index 3cc3db05a7..a256ef2ad5 100644
--- a/tests/test-subed-common.el
+++ b/tests/test-subed-common.el
@@ -3131,9 +3131,9 @@ This is another.
(with-temp-srt-buffer
(insert mock-srt-data)
(expect (subed-subtitle-list) :to-equal
- '((1 61000 65123 "Foo.")
- (2 122234 130345 "Bar.")
- (3 183450 195500 "Baz.")))))
+ '((1 61000 65123 "Foo." nil)
+ (2 122234 130345 "Bar." nil)
+ (3 183450 195500 "Baz." nil)))))
(it "returns a subset when bounds are specified."
(with-temp-srt-buffer
(insert mock-srt-data)
@@ -3141,9 +3141,8 @@ This is another.
(backward-char 1)
(expect (subed-subtitle-list (point-min) (point))
:to-equal
- '((1 61000 65123 "Foo.")
- (2 122234 130345 "Bar.")))))
- )
+ '((1 61000 65123 "Foo." nil)
+ (2 122234 130345 "Bar." nil))))))
(describe "Sorting"
(it "detects sorted lists."
(expect (subed--sorted-p '((1 1000 2000 "Test")
diff --git a/tests/test-subed-vtt.el b/tests/test-subed-vtt.el
index b846360a6e..8b00cd6887 100644
--- a/tests/test-subed-vtt.el
+++ b/tests/test-subed-vtt.el
@@ -1083,10 +1083,23 @@ Baz.
(goto-char (point-min))
(forward-line 2)
(while (re-search-forward "\n\n" nil t)
- (replace-match "\n \n \t \t\t \n\n \t\n"))
+ (replace-match "\n\n\n\n\n\n"))
(expect (buffer-string) :not :to-equal mock-vtt-data)
(subed-sanitize)
(expect (buffer-string) :to-equal mock-vtt-data)))
+ (it "retains comments"
+ (with-temp-vtt-buffer
+ (insert (concat "WEBVTT\n\n"
+ "00:01:01.000 --> 00:01:05.123\n"
+ "Foo.\n\nNOTE This is a test\n\n"
+ "00:02:02.234 --> 00:02:10.345\n"
+ "Bar.\n\n"
+ "NOTE\nAnother comment\n\n"
+ "00:03:03.45 --> 00:03:15.5\n"
+ "Baz.\n"))
+ (subed-sanitize)
+ (expect (buffer-string) :to-match "NOTE This is a test")
+ (expect (buffer-string) :to-match "Another comment")))
(it "ensures double newline between subtitles if text of previous subtitle
is empty."
(with-temp-vtt-buffer
(insert mock-vtt-data)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [nongnu] elpa/subed a1c61d7d4d: Parse and retain comments in VTT files, and simplify creating files,
ELPA Syncer <=