branch: elpa/subed commit 9796a77c60cfdf8b027d3920b89b61cc2c4cff96 Merge: d3df6f2 5b8c23a Author: Random User <rnd...@posteo.de> Commit: Random User <rnd...@posteo.de>
Merge branch 'sacha' --- subed/subed-common.el | 9 +++++++++ subed/subed-mpv.el | 37 ++++++++++++++++++++++++------------- subed/subed-srt.el | 17 +++++++++++++++++ subed/subed-vtt.el | 40 +++++++++++++++++++++++++++------------- subed/subed.el | 6 +++++- 5 files changed, 82 insertions(+), 27 deletions(-) diff --git a/subed/subed-common.el b/subed/subed-common.el index 6f866cb..d501331 100644 --- a/subed/subed-common.el +++ b/subed/subed-common.el @@ -621,6 +621,15 @@ following manner: (subed-regenerate-ids-soon)) (point)) +;;; Merging + +(defun subed-merge-with-previous () + "Merge the current subtitle with the previous subtitle. +Update the end timestamp accordingly." + (interactive) + (if (subed-backward-subtitle-id) + (subed-merge-with-next) + (error "No previous subtitle to merge into"))) ;;; Replay time-adjusted subtitle diff --git a/subed/subed-mpv.el b/subed/subed-mpv.el index 4bdf3d8..bd706bc 100644 --- a/subed/subed-mpv.el +++ b/subed/subed-mpv.el @@ -335,26 +335,37 @@ See \"List of events\" in mpv(1)." (or (file-directory-p filepath) (member (file-name-extension filename) subed-video-extensions))))) -(defun subed-mpv-find-video (file) - "Open video file FILE in mpv. - -Video files are expected to have any of the extensions listed in -`subed-video-extensions'." - (interactive (list (read-file-name "Find video: " nil nil t nil #'subed-mpv--is-video-file-p))) - (let ((filepath (expand-file-name file))) - (when (subed-mpv--server-started-p) - (subed-mpv-kill)) - (when (apply #'subed-mpv--server-start subed-mpv-arguments) - (subed-debug "Opening video file: %s" filepath) +(defun subed-mpv--play (video) + "Open VIDEO and play it in MPV." + (when (subed-mpv--server-started-p) + (subed-mpv-kill)) + (when (apply #'subed-mpv--server-start subed-mpv-arguments) + (subed-debug "Opening video: %s" video) (subed-mpv--client-connect subed-mpv--retry-delays) - (subed-mpv--client-send `(loadfile ,filepath replace)) + (subed-mpv--client-send `(loadfile ,video replace)) ;; mpv won't add the subtitles if the file doesn't exist yet, so we add it ;; via after-save-hook. (if (file-exists-p (buffer-file-name)) (subed-mpv-add-subtitles (buffer-file-name)) (add-hook 'after-save-hook #'subed-mpv--add-subtitle-after-first-save :append :local)) (subed-mpv--client-send `(observe_property 1 time-pos)) - (subed-mpv-playback-speed subed-playback-speed-while-not-typing)))) + (subed-mpv-playback-speed subed-playback-speed-while-not-typing))) + +(defun subed-mpv-play-video-from-url (url) + "Open video file from URL in mpv. +See the MPV manual for a list of supported URL types. If you have +youtube-dl installed, MPV can open videos from a variety of +hosting providers." + (interactive "MURL: ") + (subed-mpv--play url)) + +(defun subed-mpv-find-video (file) + "Open video file FILE in mpv. + +Video files are expected to have any of the extensions listed in +`subed-video-extensions'." + (interactive (list (read-file-name "Find video: " nil nil t nil #'subed-mpv--is-video-file-p))) + (subed-mpv--play (expand-file-name file))) (defun subed-mpv--add-subtitle-after-first-save () "Tell mpv to load subtitles from function `buffer-file-name'. diff --git a/subed/subed-srt.el b/subed/subed-srt.el index b00760c..0341a92 100644 --- a/subed/subed-srt.el +++ b/subed/subed-srt.el @@ -419,6 +419,23 @@ Return new point." (delete-region beg end)) (subed-srt--regenerate-ids-soon)) +(defun subed-srt--merge-with-next () + "Merge the current subtitle with the next subtitle. +Update the end timestamp accordingly." + (interactive) + (save-excursion + (subed-srt--jump-to-subtitle-end) + (let ((pos (point)) new-end) + (if (subed-srt--forward-subtitle-time-stop) + (progn + (when (looking-at subed-srt--regexp-timestamp) + (setq new-end (subed-srt--timestamp-to-msecs (match-string 0)))) + (subed-srt--jump-to-subtitle-text) + (delete-region pos (point)) + (insert "\n") + (subed-srt--set-subtitle-time-stop new-end) + (subed-srt--regenerate-ids-soon)) + (error "No subtitle to merge into"))))) ;;; Maintenance diff --git a/subed/subed-vtt.el b/subed/subed-vtt.el index c736a7c..dbdb282 100644 --- a/subed/subed-vtt.el +++ b/subed/subed-vtt.el @@ -148,14 +148,14 @@ If SUB-ID is not given, use subtitle on point." "Move to the ID of a subtitle and return point. If SUB-ID is not given, focus the current subtitle's ID. Return point or nil if no subtitle ID could be found. -WebVTT doesn't use IDs, so we use the starting timestamp instead" +WebVTT doesn't use IDs, so we use the starting timestamp instead." (interactive) (save-match-data - (if sub-id + (if (stringp sub-id) ;; Look for a line that contains only the ID, preceded by one or more ;; blank lines or the beginning of the buffer. (let* ((orig-point (point)) - (regex (concat "\\(" subed-srt--regexp-separator "\\|\\`\\)\\(" (regexp-quote (string-to-number sub-id)) "\\)")) + (regex (concat "\\(" subed-srt--regexp-separator "\\|\\`\\)\\(" (regexp-quote sub-id) "\\)")) (match-found (progn (goto-char (point-min)) (re-search-forward regex nil t)))) (if match-found @@ -179,7 +179,7 @@ Return point or nil if point is still on the same subtitle. See also `subed-vtt--subtitle-id-at-msecs'." (let ((current-sub-id (subed-vtt--subtitle-id)) (target-sub-id (subed-vtt--subtitle-id-at-msecs msecs))) - (when (and target-sub-id current-sub-id (not (= target-sub-id current-sub-id))) + (when (and target-sub-id current-sub-id (not (equal target-sub-id current-sub-id))) (subed-vtt--jump-to-subtitle-id target-sub-id)))) (defun subed-vtt--jump-to-subtitle-text-at-msecs (msecs) @@ -232,7 +232,7 @@ can be found." ;; `subed-vtt--regexp-separator' here because if subtitle text is empty, ;; it may be the only empty line in the separator, i.e. there's only one ;; "\n". - (let ((regex (concat "\\([[:blank:]]*\n+[0-9]+\n\\|\\([[:blank:]]*\n*\\)\\'\\)"))) + (let ((regex (concat "\\([[:blank:]]*\n+" subed-vtt--regexp-timestamp "\\|\\([[:blank:]]*\n*\\)\\'\\)"))) (when (re-search-forward regex nil t) (goto-char (match-beginning 0)))) (unless (= (point) orig-point) @@ -252,7 +252,7 @@ Return point or nil if there is no previous subtitle." (interactive) (let ((orig-point (point))) (when (subed-vtt--jump-to-subtitle-id) - (if (re-search-backward (concat "\\(" subed-vtt--regexp-separator "\\|\\`[[:space:]]*\\)" "\\([0-9]+\\)\n") nil t) + (if (re-search-backward (concat "\\(" subed-vtt--regexp-separator "\\|\\`[[:space:]]*\\)\\(" subed-vtt--regexp-timestamp "\\)") nil t) (progn (goto-char (match-beginning 2)) (point)) @@ -369,7 +369,7 @@ Return new point." (subed-vtt--jump-to-subtitle-id) (insert (subed-vtt--make-subtitle id start stop text)) (save-match-data - (when (looking-at "\\([[:space:]]*\\|^\\)[0-9]+$") + (when (looking-at (concat "\\([[:space:]]*\\|^\\)" subed-vtt--regexp-timestamp)) (insert "\n"))) (forward-line -2) (subed-vtt--jump-to-subtitle-text)) @@ -414,8 +414,24 @@ Return new point." (subed-vtt--backward-subtitle-end) (1+ (point))) end (save-excursion (goto-char (point-max))))) - (delete-region beg end)) - (subed-vtt--regenerate-ids-soon)) + (delete-region beg end))) + +(defun subed-vtt--merge-with-next () + "Merge the current subtitle with the next subtitle. +Update the end timestamp accordingly." + (interactive) + (save-excursion + (subed-vtt--jump-to-subtitle-end) + (let ((pos (point)) new-end) + (if (subed-vtt--forward-subtitle-time-stop) + (progn + (when (looking-at subed-vtt--regexp-timestamp) + (setq new-end (subed-vtt--timestamp-to-msecs (match-string 0)))) + (subed-vtt--jump-to-subtitle-text) + (delete-region pos (point)) + (insert "\n") + (subed-vtt--set-subtitle-time-stop new-end)) + (error "No subtitle to merge into"))))) ;;; Maintenance @@ -484,8 +500,7 @@ Return new point." (save-match-data (let ((orig-point (point))) (goto-char (point-min)) - (while (and (re-search-forward (format "\\(%s[[^\\']]\\|\\`\\)" subed-vtt--regexp-separator) nil t) - (looking-at "[[:alnum:]]")) + (while (and (re-search-forward (format "\\(%s[[^\\']]\\|\\`\\)%s" subed-vtt--regexp-separator subed-vtt--regexp-timestamp) nil t) (goto-char (match-beginning 2))) ;; This regex is stricter than `subed-vtt--regexp-timestamp' (unless (looking-at "^[0-9]\\{2\\}:[0-9]\\{2\\}:[0-9]\\{2\\}\\.[0-9]\\{3\\}") (error "Found invalid start time: %S" (substring (or (thing-at-point 'line :no-properties) "\n") 0 -1))) @@ -517,8 +532,7 @@ Return new point." ;; endrecfun (move to end of current record/subtitle) #'subed-vtt--jump-to-subtitle-end ;; startkeyfun (return sort value of current record/subtitle) - #'subed-vtt--subtitle-msecs-start)) - (subed-vtt--regenerate-ids))) + #'subed-vtt--subtitle-msecs-start)))) (defun subed-vtt--init () "This function is called when subed-mode is entered for a SRT file." diff --git a/subed/subed.el b/subed/subed.el index 2d1b5cb..7ae7807 100644 --- a/subed/subed.el +++ b/subed/subed.el @@ -36,6 +36,7 @@ (require 'subed-debug) (require 'subed-common) (require 'subed-srt) +(require 'subed-vtt) (require 'subed-mpv) (setq subed-mode-map @@ -55,10 +56,13 @@ (define-key subed-mode-map (kbd "M-i") #'subed-insert-subtitle) (define-key subed-mode-map (kbd "C-M-i") #'subed-insert-subtitle-adjacent) (define-key subed-mode-map (kbd "M-k") #'subed-kill-subtitle) + (define-key subed-mode-map (kbd "M-m") #'subed-merge-with-next) + (define-key subed-mode-map (kbd "M-M") #'subed-merge-with-previous) (define-key subed-mode-map (kbd "M-s") #'subed-sort) (define-key subed-mode-map (kbd "M-SPC") #'subed-mpv-toggle-pause) (define-key subed-mode-map (kbd "C-c C-d") #'subed-toggle-debugging) (define-key subed-mode-map (kbd "C-c C-v") #'subed-mpv-find-video) + (define-key subed-mode-map (kbd "C-c C-u") #'subed-mpv-play-video-from-url) (define-key subed-mode-map (kbd "C-c C-p") #'subed-toggle-pause-while-typing) (define-key subed-mode-map (kbd "C-c C-l") #'subed-toggle-loop-over-current-subtitle) (define-key subed-mode-map (kbd "C-c C-r") #'subed-toggle-replay-adjusted-subtitle) @@ -96,7 +100,7 @@ "forward-subtitle-time-start" "backward-subtitle-time-start" "forward-subtitle-time-stop" "backward-subtitle-time-stop" "set-subtitle-time-start" "set-subtitle-time-stop" - "prepend-subtitle" "append-subtitle" "kill-subtitle" + "prepend-subtitle" "append-subtitle" "kill-subtitle" "merge-with-next" "regenerate-ids" "regenerate-ids-soon" "sanitize" "validate" "sort"))