branch: elpa/subed commit 619b1704709160ba3a39ec3566df0a8c86f08e11 Author: Random User <rnd...@posteo.de> Commit: Random User <rnd...@posteo.de>
subed-for-each-subtitle: Add reverse argument --- subed/subed.el | 42 +++++++++++----- tests/test-subed.el | 139 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 129 insertions(+), 52 deletions(-) diff --git a/subed/subed.el b/subed/subed.el index a641165..b68035f 100644 --- a/subed/subed.el +++ b/subed/subed.el @@ -133,10 +133,11 @@ subtitles) as long the subtitle IDs don't change." ('beginning-of-buffer nil) ('end-of-buffer nil))))) -(defmacro subed-for-each-subtitle (&optional beg end &rest body) +(defmacro subed-for-each-subtitle (&optional beg end reverse &rest body) "Run BODY for each subtitle between the region specified by BEG and END. If END is nil, it defaults to `point-max'. If BEG and END are both nil, run BODY only on the subtitle at point. +If REVERSE is non-nil, start on the subtitle at END and move backwards. Before BODY is run, point is placed on the subtitle's ID." (declare (indent defun)) `(atomic-change-group @@ -144,17 +145,34 @@ Before BODY is run, point is placed on the subtitle's ID." ;; Run body on subtitle at point (save-excursion (subed-jump-to-subtitle-id) ,@body) - ;; Run body on multiple subtitles - (save-excursion - (goto-char ,beg) - (subed-jump-to-subtitle-id) - (catch 'last-subtitle-reached - (while t - (when (> (point) (or ,end (point-max))) - (throw 'last-subtitle-reached t)) - (progn ,@body) - (unless (subed-forward-subtitle-id) - (throw 'last-subtitle-reached t)))))))) + (let ((begm (make-marker)) + (endm (make-marker))) + (set-marker begm ,beg) + (set-marker endm (or ,end (point-max))) + ;; Run body on multiple subtitles + (if ,reverse + ;; Iterate backwards + (save-excursion (goto-char endm) + (subed-jump-to-subtitle-id) + (catch 'first-subtitle-reached + (while t + ;; The subtitle includes every character up to the next subtitle's ID (or eob) + (let ((sub-end (save-excursion (subed-jump-to-subtitle-end)))) + (when (< sub-end begm) + (throw 'first-subtitle-reached t))) + (progn ,@body) + (unless (subed-backward-subtitle-id) + (throw 'first-subtitle-reached t))))) + ;; Iterate forwards + (save-excursion (goto-char begm) + (subed-jump-to-subtitle-id) + (catch 'last-subtitle-reached + (while t + (when (> (point) endm) + (throw 'last-subtitle-reached t)) + (progn ,@body) + (unless (subed-forward-subtitle-id) + (throw 'last-subtitle-reached t)))))))))) (defmacro subed-with-subtitle-replay-disabled (&rest body) "Run BODY while automatic subtitle replay is disabled." diff --git a/tests/test-subed.el b/tests/test-subed.el index 2adfd40..a950ce5 100644 --- a/tests/test-subed.el +++ b/tests/test-subed.el @@ -3,11 +3,11 @@ (require 'subed-srt) (describe "Iterating over subtitles" - (it "without beginning and end." + (it "without providing beginning and end." (with-temp-buffer (insert mock-srt-data) (subed-jump-to-subtitle-time-stop 1) - (subed-for-each-subtitle nil nil + (subed-for-each-subtitle nil nil nil (expect (looking-at "^[0-9]$") :to-be t) (forward-line 2) (kill-line) @@ -17,7 +17,7 @@ (expect (subed-srt--subtitle-text 3) :to-equal "Baz.") (expect (point) :to-equal 20) (subed-jump-to-subtitle-time-stop 2) - (subed-for-each-subtitle nil nil + (subed-for-each-subtitle nil nil nil (expect (looking-at "^[0-9]$") :to-be t) (forward-line 2) (kill-line) @@ -27,7 +27,7 @@ (expect (subed-srt--subtitle-text 3) :to-equal "Baz.") (expect (point) :to-equal 60) (subed-jump-to-subtitle-time-stop 3) - (subed-for-each-subtitle nil nil + (subed-for-each-subtitle nil nil nil (expect (looking-at "^[0-9]$") :to-be t) (forward-line 2) (kill-line) @@ -36,47 +36,106 @@ (expect (subed-srt--subtitle-text 2) :to-equal "HEllo.") (expect (subed-srt--subtitle-text 3) :to-equal "HELlo.") (expect (point) :to-equal 99))) - (it "with only the beginning." - (with-temp-buffer - (insert mock-srt-data) - (subed-jump-to-subtitle-time-start 1) - (expect (point) :to-equal 3) - (subed-for-each-subtitle 71 nil - (expect (looking-at "^[0-9]$") :to-be t) - (forward-line 2) - (kill-line) - (insert "Hello.")) - (expect (subed-srt--subtitle-text 1) :to-equal "Foo.") - (expect (subed-srt--subtitle-text 2) :to-equal "Hello.") - (expect (subed-srt--subtitle-text 3) :to-equal "Hello.") - (expect (point) :to-equal 3))) - (describe "with beginning and end," - (it "excluding subtitles above." + (describe "providing only the beginning" + (it "forwards." (with-temp-buffer (insert mock-srt-data) - (subed-jump-to-subtitle-time-stop 1) - (subed-for-each-subtitle 71 79 - (expect (looking-at "^[0-9]$") :to-be t) - (forward-line 2) - (kill-line) - (insert "Hello.")) - (expect (subed-subtitle-text 1) :to-equal "Foo.") - (expect (subed-subtitle-text 2) :to-equal "Hello.") - (expect (subed-subtitle-text 3) :to-equal "Hello.") - (expect (point) :to-equal 20))) - (it "excluding subtitles below." + (subed-jump-to-subtitle-time-start 1) + (expect (point) :to-equal 3) + (let ((new-texts (list "A" "B" "C"))) + (subed-for-each-subtitle 71 nil nil + (expect (looking-at "^[0-9]$") :to-be t) + (forward-line 2) + (kill-line) + (insert (pop new-texts)))) + (expect (subed-srt--subtitle-text 1) :to-equal "Foo.") + (expect (subed-srt--subtitle-text 2) :to-equal "A") + (expect (subed-srt--subtitle-text 3) :to-equal "B") + (expect (point) :to-equal 3))) + (it "backwards." (with-temp-buffer (insert mock-srt-data) (subed-jump-to-subtitle-time-stop 3) - (subed-for-each-subtitle 5 76 - (expect (looking-at "^[0-9]$") :to-be t) - (forward-line 2) - (kill-line) - (insert "Hello.")) - (expect (subed-subtitle-text 1) :to-equal "Hello.") - (expect (subed-subtitle-text 2) :to-equal "Hello.") - (expect (subed-subtitle-text 3) :to-equal "Baz.") - (expect (point) :to-equal 99))) + (expect (point) :to-equal 95) + (let ((new-texts (list "A" "B" "C"))) + (subed-for-each-subtitle 75 nil :reverse + (expect (looking-at "^[0-9]$") :to-be t) + (forward-line 2) + (kill-line) + (insert (pop new-texts)))) + (message (buffer-string)) + (expect (subed-srt--subtitle-text 1) :to-equal "Foo.") + (expect (subed-srt--subtitle-text 2) :to-equal "B") + (expect (subed-srt--subtitle-text 3) :to-equal "A") + (expect (point) :to-equal 92))) + ) + (describe "providing beginning and end," + (describe "excluding subtitles above" + (it "forwards." + (with-temp-buffer + (insert mock-srt-data) + (subed-jump-to-subtitle-time-stop 1) + (expect (point) :to-equal 20) + (let ((new-texts (list "A" "B" "C"))) + (subed-for-each-subtitle 71 79 nil + (expect (looking-at "^[0-9]$") :to-be t) + (forward-line 2) + (kill-line) + (insert (pop new-texts)))) + (expect (subed-srt--subtitle-text 1) :to-equal "Foo.") + (expect (subed-srt--subtitle-text 2) :to-equal "A") + (expect (subed-srt--subtitle-text 3) :to-equal "B") + (expect (point) :to-equal 20))) + (it "backwards." + (with-temp-buffer + (insert mock-srt-data) + (subed-jump-to-subtitle-time-start 3) + (expect (point) :to-equal 79) + (let ((new-texts (list "A" "B" "C"))) + (subed-for-each-subtitle 39 77 :reverse + (expect (looking-at "^[0-9]$") :to-be t) + (forward-line 2) + (kill-line) + (insert (pop new-texts)))) + (message (buffer-string)) + (expect (subed-srt--subtitle-text 1) :to-equal "Foo.") + (expect (subed-srt--subtitle-text 2) :to-equal "B") + (expect (subed-srt--subtitle-text 3) :to-equal "A") + (expect (point) :to-equal 76))) + ) + (describe "excluding subtitles below" + (it "forwards." + (with-temp-buffer + (insert mock-srt-data) + (subed-jump-to-subtitle-text 3) + (expect (point) :to-equal 106) + (let ((new-texts (list "A" "B" "C"))) + (subed-for-each-subtitle 5 76 nil + (expect (looking-at "^[0-9]$") :to-be t) + (forward-line 2) + (kill-line) + (insert (pop new-texts)))) + (expect (subed-srt--subtitle-text 1) :to-equal "A") + (expect (subed-srt--subtitle-text 2) :to-equal "B") + (expect (subed-srt--subtitle-text 3) :to-equal "Baz.") + (expect (point) :to-equal 100))) + (it "backwards." + (with-temp-buffer + (insert mock-srt-data) + (subed-jump-to-subtitle-time-stop 2) + (expect (point) :to-equal 58) + (let ((new-texts (list "A" "B" "C"))) + (subed-for-each-subtitle 20 76 :reverse + (expect (looking-at "^[0-9]$") :to-be t) + (forward-line 2) + (kill-line) + (insert (pop new-texts)))) + (message (buffer-string)) + (expect (subed-srt--subtitle-text 1) :to-equal "B") + (expect (subed-srt--subtitle-text 2) :to-equal "A") + (expect (subed-srt--subtitle-text 3) :to-equal "Baz.") + (expect (point) :to-equal 55))) + ) ) )