From a3fff1ddc87d644e4850bf1ff73815e616ef41f2 Mon Sep 17 00:00:00 2001 From: mousebot Date: Thu, 10 Jun 2021 22:18:21 +0200 Subject: [PATCH 1/3] handle trimming of subtitles that overlap --- subed/subed-common.el | 98 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/subed/subed-common.el b/subed/subed-common.el index e53d98e..2ba5db2 100644 --- a/subed/subed-common.el +++ b/subed/subed-common.el @@ -1294,5 +1294,103 @@ be run in `after-change-functions'." 'after-string (propertize (format " %.1f CPS" cps) 'face 'shadow 'display '(height 0.9))))))) +;;; handle overlapping subtitle timecodes + +(defcustom subed-trim-overlapping-subtitle-times-on-save nil + "Whether all overlapping subtitles should be trimmed on saving. A string of either 'start', to adjust the start time of the following subtitle or 'end', to adjust the end of the current subtitle. Defaults to nil." + :type 'string + :group 'subed) + +(defcustom subed-trim-overlapping-use-subed-subtitle-spacing t + "Whether `subed-subtitle-spacing' should be used when trimming overlapping subtitles. If nil, subtitles will trimmed to one millisecond less than adjacent one. Defaults to nil." + :type 'boolean + :group 'subed) + +(defun subed-sanitize-overlaps (&optional arg) + "Adjust all overlapping times in current file. + +Uses either `subed-trim-overlap-start-times' or `subed-trim-overlapping-end-times', the latter being the default. See `subed-trim-overlapping-subtitle-times-on-save' to customize this option." + (interactive "P") + (goto-char (point-min)) + (save-excursion + (while (subed-forward-subtitle-time-start) + (if (equal subed-trim-overlapping-subtitle-times-on-save "start") + (subed-trim-overlap-start-times arg) + (if (equal subed-trim-overlapping-subtitle-times-on-save "end") + (subed-trim-overlap-end-times arg)))))) + +(defun subed-trim-overlap-end-times (&optional arg) + "Check if end time of current subtitle is after start time of next. + +If so, trim the end time of current subtitle to 1 millisecond less than the start time of the next one. +With a non-numerical prefix arg, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. +With a numerical prefix arg, make the gap that many milliseconds." + (interactive "P") + (let ((next-sub-start-time (save-excursion + (subed-forward-subtitle-time-start) + (subed-subtitle-msecs-start)))) + (if (>= (subed-subtitle-msecs-stop) next-sub-start-time) + (subed-set-subtitle-time-stop + (cond + ;; if plain C-u or custom option set: + ((or (consp arg) + subed-trim-overlapping-use-subed-subtitle-spacing) + (- next-sub-start-time subed-subtitle-spacing)) + ;; if numeric prefix arg, use it as gap in ms: + ((integerp arg) + (- next-sub-start-time arg)) + ;; else just make 1 ms difference: + (t + (1- next-sub-start-time))))))) + +(defun subed-trim-overlap-start-times (&optional arg) + "Check if end time of current subtitle is after start time of next. + +If so, trim the start time of current subtitle to 1 millisecond less than the end time of the current one. +With a non-numerical prefix arg, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. +With a numerical prefix arg, make the gap that many miliseconds." + (interactive "P") + (let ((this-sub-stop-time (subed-subtitle-msecs-stop)) + (next-sub-start-time (save-excursion + (subed-forward-subtitle-time-start) + (subed-subtitle-msecs-start)))) + (if (>= this-sub-stop-time next-sub-start-time) + (save-excursion + (subed-forward-subtitle-time-start) + (subed-set-subtitle-time-start + (cond + ;; if plain C-u or custom option set: + ((or (consp arg) + subed-trim-overlapping-use-subed-subtitle-spacing) + (+ this-sub-stop-time subed-subtitle-spacing)) + ;; if numeric prefix arg, use it as gap in ms: + ((integerp arg) + (+ this-sub-stop-time arg)) + ;; else just make 1 ms difference: + (t + (1+ this-sub-stop-time)))))))) + +;; mod subed-sort fun to run santize-overlaps if enabled: +(defun subed-sort () + "Sanitize, then sort subtitles by start time and re-number them." + (interactive) + (atomic-change-group + (subed-sanitize) + (when subed-trim-overlapping-subtitle-times-on-save + (subed-sanitize-overlaps)) + (subed-validate) + (subed-save-excursion + (goto-char (point-min)) + (sort-subr nil + ;; nextrecfun (move to next record/subtitle or to end-of-buffer + ;; if there are no more records) + (lambda () (unless (subed-forward-subtitle-id) + (goto-char (point-max)))) + ;; endrecfun (move to end of current record/subtitle) + #'subed-jump-to-subtitle-end + ;; startkeyfun (return sort value of current record/subtitle) + #'subed-subtitle-msecs-start)) + (subed-regenerate-ids))) + (provide 'subed-common) ;;; subed-common.el ends here From 6d72ef70ed506637f3f44b14ab08ed346b7a1d13 Mon Sep 17 00:00:00 2001 From: mousebot Date: Sat, 12 Jun 2021 10:55:17 +0200 Subject: [PATCH 2/3] add fully configurable trimming of subtitle overlaps: - option to check and ask to trim on load - option to always trim on save - trim end of current or start of next subtitle - custom or prefix args to trim by: - any number of milliseconds - the value of subed-subtitle-spacing, or - 1 millisecond --- subed/subed-common.el | 86 ++++++++++++++++++++++++++++--------------- subed/subed-config.el | 21 +++++++++++ subed/subed.el | 2 + 3 files changed, 80 insertions(+), 29 deletions(-) diff --git a/subed/subed-common.el b/subed/subed-common.el index 2ba5db2..d9df3a3 100644 --- a/subed/subed-common.el +++ b/subed/subed-common.el @@ -1296,35 +1296,62 @@ be run in `after-change-functions'." ;;; handle overlapping subtitle timecodes -(defcustom subed-trim-overlapping-subtitle-times-on-save nil - "Whether all overlapping subtitles should be trimmed on saving. A string of either 'start', to adjust the start time of the following subtitle or 'end', to adjust the end of the current subtitle. Defaults to nil." - :type 'string - :group 'subed) +;; NB: runs in a hook, so this version cannot send prefix arg +;; to subed-sanitize-overlaps! +(defun subed-check-overlaps () + "Test all subtitles for overlapping timecodes. -(defcustom subed-trim-overlapping-use-subed-subtitle-spacing t - "Whether `subed-subtitle-spacing' should be used when trimming overlapping subtitles. If nil, subtitles will trimmed to one millisecond less than adjacent one. Defaults to nil." - :type 'boolean - :group 'subed) +Creates a list of the ids of overlapping subtitles, moves point to the to the end time of the first one, and prompts to trim them. +Designed to be run as a subed-mode-hook." + (interactive) + (let ((overlap-ids ())) + (save-excursion + (goto-char (point-min)) + (while (save-excursion (subed-forward-subtitle-time-start)) + (let ((next-sub-start-time (save-excursion + (subed-forward-subtitle-time-start) + (subed-subtitle-msecs-start)))) + (if (>= (subed-subtitle-msecs-stop) next-sub-start-time) + (progn (subed-jump-to-subtitle-id) + (push (string-to-number (word-at-point)) + overlap-ids)))) + (subed-forward-subtitle-time-start))) + (when overlap-ids + (setq overlap-ids (nreverse overlap-ids)) + (subed-jump-to-subtitle-id (car overlap-ids)) + (subed-jump-to-subtitle-time-stop) + (when (yes-or-no-p "Overlapping subtitles found. Trim them? ") + (subed-sanitize-overlaps))))) (defun subed-sanitize-overlaps (&optional arg) "Adjust all overlapping times in current file. -Uses either `subed-trim-overlap-start-times' or `subed-trim-overlapping-end-times', the latter being the default. See `subed-trim-overlapping-subtitle-times-on-save' to customize this option." - (interactive "P") - (goto-char (point-min)) - (save-excursion - (while (subed-forward-subtitle-time-start) - (if (equal subed-trim-overlapping-subtitle-times-on-save "start") - (subed-trim-overlap-start-times arg) - (if (equal subed-trim-overlapping-subtitle-times-on-save "end") - (subed-trim-overlap-end-times arg)))))) +Uses either `subed-trim-overlap-start-times' or `subed-trim-overlapping-end-times', the latter being the default. See `subed-trim-overlapping-subtitle-trim-start' to customize this option. -(defun subed-trim-overlap-end-times (&optional arg) +With a non-numerical prefix ARG, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. +With a numerical prefix ARG, make the gap that many milliseconds." + (interactive "P") + (let ((cpsp (subed-show-cps-p))) + (when cpsp + (subed-disable-show-cps t)) + (switch-to-buffer (current-buffer)) + (save-excursion + (goto-char (point-min)) + (while (save-excursion (subed-forward-subtitle-time-start)) + (if subed-trim-overlapping-subtitle-trim-start + (subed-trim-overlap-start-time arg) + (subed-trim-overlap-end-time arg)) + (subed-forward-subtitle-time-start))) + (when cpsp + (subed-enable-show-cps t)))) + +(defun subed-trim-overlap-end-time (&optional arg) "Check if end time of current subtitle is after start time of next. If so, trim the end time of current subtitle to 1 millisecond less than the start time of the next one. -With a non-numerical prefix arg, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. -With a numerical prefix arg, make the gap that many milliseconds." + +With a non-numerical prefix ARG, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. +With a numerical prefix ARG, make the gap that many milliseconds." (interactive "P") (let ((next-sub-start-time (save-excursion (subed-forward-subtitle-time-start) @@ -1332,23 +1359,24 @@ With a numerical prefix arg, make the gap that many milliseconds." (if (>= (subed-subtitle-msecs-stop) next-sub-start-time) (subed-set-subtitle-time-stop (cond + ;; if numeric prefix arg, use it as gap in ms: + ((integerp arg) + (- next-sub-start-time arg)) ;; if plain C-u or custom option set: ((or (consp arg) subed-trim-overlapping-use-subed-subtitle-spacing) (- next-sub-start-time subed-subtitle-spacing)) - ;; if numeric prefix arg, use it as gap in ms: - ((integerp arg) - (- next-sub-start-time arg)) ;; else just make 1 ms difference: (t (1- next-sub-start-time))))))) -(defun subed-trim-overlap-start-times (&optional arg) +(defun subed-trim-overlap-start-time (&optional arg) "Check if end time of current subtitle is after start time of next. If so, trim the start time of current subtitle to 1 millisecond less than the end time of the current one. -With a non-numerical prefix arg, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. -With a numerical prefix arg, make the gap that many miliseconds." + +With a non-numerical prefix ARG, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. +With a numerical prefix ARG make the gap that many miliseconds." (interactive "P") (let ((this-sub-stop-time (subed-subtitle-msecs-stop)) (next-sub-start-time (save-excursion @@ -1359,13 +1387,13 @@ With a numerical prefix arg, make the gap that many miliseconds." (subed-forward-subtitle-time-start) (subed-set-subtitle-time-start (cond + ;; if numeric prefix arg, use it as gap in ms: + ((integerp arg) + (+ this-sub-stop-time arg)) ;; if plain C-u or custom option set: ((or (consp arg) subed-trim-overlapping-use-subed-subtitle-spacing) (+ this-sub-stop-time subed-subtitle-spacing)) - ;; if numeric prefix arg, use it as gap in ms: - ((integerp arg) - (+ this-sub-stop-time arg)) ;; else just make 1 ms difference: (t (1+ this-sub-stop-time)))))))) diff --git a/subed/subed-config.el b/subed/subed-config.el index de5d221..bf58766 100644 --- a/subed/subed-config.el +++ b/subed/subed-config.el @@ -210,6 +210,27 @@ hardcoded." "Return base name of buffer file name or a default name." (file-name-nondirectory (or (buffer-file-name) "unnamed"))) +;; checked by subed-sort +(defcustom subed-trim-overlapping-subtitle-times-on-save nil + "Whether all overlapping subtitles should be trimmed on saving. Subtitles are trimmed according to `subed-trim-overlapping-subtitle-start-or-end'." + :type 'boolean + :group 'subed) + +;; checked by subed mode hook +(defcustom subed-check-overlapping-subtitle-times-on-load nil + "Whether to check for, and optionally trim, overlapping subtitles on entering subed mode. Subtitles are trimmed according to `subed-trim-overlapping-subtitle-start-or-end'." + :type 'boolean + :group 'subed) + +(defcustom subed-trim-overlapping-subtitle-trim-start nil + "How overlapping subtitles should be trimmed. If t, adjust the start time of the following subtitle, if nil, adjust the end of the current subtitle. Defaults to nil." + :type 'boolean + :group 'subed) + +(defcustom subed-trim-overlapping-use-subed-subtitle-spacing nil + "Whether `subed-subtitle-spacing' should be used when trimming overlapping subtitles. If nil, subtitles will trimmed to one millisecond less than adjacent one. Defaults to nil. You can also set the spacing by using a prefix arg when calling `subed-sanitize-overlaps', which see." + :type 'boolean + :group 'subed) ;; Hooks diff --git a/subed/subed.el b/subed/subed.el index cdb9842..4826c05 100644 --- a/subed/subed.el +++ b/subed/subed.el @@ -197,6 +197,8 @@ Key bindings: (add-hook 'after-save-hook #'subed-mpv-reload-subtitles :append :local) (add-hook 'kill-buffer-hook #'subed-mpv-kill :append :local) (add-hook 'kill-emacs-hook #'subed-mpv-kill :append :local) + (when subed-check-overlapping-subtitle-times-on-load + (add-hook 'subed-mode-hook #'subed-check-overlaps :append :local)) (when subed-auto-find-video (let ((video-file (subed-guess-video-file))) (when video-file From 0a1c54f377adfb7edbf9c983733d6aeeed3d2627 Mon Sep 17 00:00:00 2001 From: mousebot Date: Tue, 21 Dec 2021 18:27:11 +0100 Subject: [PATCH 3/3] docstrings whitespace --- subed/subed-common.el | 38 +++++++++++++++++++++++++------------- subed/subed-config.el | 19 +++++++++++++++---- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/subed/subed-common.el b/subed/subed-common.el index d9df3a3..97edf7a 100644 --- a/subed/subed-common.el +++ b/subed/subed-common.el @@ -1296,13 +1296,14 @@ be run in `after-change-functions'." ;;; handle overlapping subtitle timecodes -;; NB: runs in a hook, so this version cannot send prefix arg -;; to subed-sanitize-overlaps! +;; NB: runs in a hook, so this version cannot send prefix arg to +;; subed-sanitize-overlaps (defun subed-check-overlaps () "Test all subtitles for overlapping timecodes. -Creates a list of the ids of overlapping subtitles, moves point to the to the end time of the first one, and prompts to trim them. -Designed to be run as a subed-mode-hook." +Creates a list of the ids of overlapping subtitles, moves point +to the to the end time of the first one, and prompts to trim +them. Designed to be run as a subed-mode-hook." (interactive) (let ((overlap-ids ())) (save-excursion @@ -1326,10 +1327,15 @@ Designed to be run as a subed-mode-hook." (defun subed-sanitize-overlaps (&optional arg) "Adjust all overlapping times in current file. -Uses either `subed-trim-overlap-start-times' or `subed-trim-overlapping-end-times', the latter being the default. See `subed-trim-overlapping-subtitle-trim-start' to customize this option. +Uses either `subed-trim-overlap-start-times' or +`subed-trim-overlapping-end-times', the latter being the default. +See `subed-trim-overlapping-subtitle-trim-start' to customize +this option. -With a non-numerical prefix ARG, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. -With a numerical prefix ARG, make the gap that many milliseconds." +With a non-numerical prefix ARG, or if +`subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the +between subtitles the length of `subed-subtitle-spacing'. With a numerical +prefix ARG, make the gap that many milliseconds." (interactive "P") (let ((cpsp (subed-show-cps-p))) (when cpsp @@ -1348,10 +1354,14 @@ With a numerical prefix ARG, make the gap that many milliseconds." (defun subed-trim-overlap-end-time (&optional arg) "Check if end time of current subtitle is after start time of next. -If so, trim the end time of current subtitle to 1 millisecond less than the start time of the next one. +If so, trim the end time of current subtitle to 1 millisecond +less than the start time of the next one. -With a non-numerical prefix ARG, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. -With a numerical prefix ARG, make the gap that many milliseconds." +With a non-numerical prefix ARG, or if +`subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a +gap the between subtitles the length of `subed-subtitle-spacing'. +With a numerical prefix ARG, make the gap that many +milliseconds." (interactive "P") (let ((next-sub-start-time (save-excursion (subed-forward-subtitle-time-start) @@ -1373,9 +1383,12 @@ With a numerical prefix ARG, make the gap that many milliseconds." (defun subed-trim-overlap-start-time (&optional arg) "Check if end time of current subtitle is after start time of next. -If so, trim the start time of current subtitle to 1 millisecond less than the end time of the current one. +If so, trim the start time of current subtitle to 1 millisecond +less than the end time of the current one. -With a non-numerical prefix ARG, or if `subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a gap the between subtitles the length of `subed-subtitle-spacing'. +With a non-numerical prefix ARG, or if +`subed-trim-overlapping-use-subed-subtitle-spacing' is t, make a +gap the between subtitles the length of `subed-subtitle-spacing'. With a numerical prefix ARG make the gap that many miliseconds." (interactive "P") (let ((this-sub-stop-time (subed-subtitle-msecs-stop)) @@ -1398,7 +1411,6 @@ With a numerical prefix ARG make the gap that many miliseconds." (t (1+ this-sub-stop-time)))))))) -;; mod subed-sort fun to run santize-overlaps if enabled: (defun subed-sort () "Sanitize, then sort subtitles by start time and re-number them." (interactive) diff --git a/subed/subed-config.el b/subed/subed-config.el index bf58766..25b77dc 100644 --- a/subed/subed-config.el +++ b/subed/subed-config.el @@ -212,23 +212,34 @@ hardcoded." ;; checked by subed-sort (defcustom subed-trim-overlapping-subtitle-times-on-save nil - "Whether all overlapping subtitles should be trimmed on saving. Subtitles are trimmed according to `subed-trim-overlapping-subtitle-start-or-end'." + "Whether all overlapping subtitles should be trimmed on saving. +Subtitles are trimmed according to +`subed-trim-overlapping-subtitle-start-or-end'." :type 'boolean :group 'subed) ;; checked by subed mode hook (defcustom subed-check-overlapping-subtitle-times-on-load nil - "Whether to check for, and optionally trim, overlapping subtitles on entering subed mode. Subtitles are trimmed according to `subed-trim-overlapping-subtitle-start-or-end'." + "Whether to check for, and optionally trim, overlapping +subtitles on entering subed mode. Subtitles are trimmed according +to `subed-trim-overlapping-subtitle-start'. Defaults to nil." :type 'boolean :group 'subed) (defcustom subed-trim-overlapping-subtitle-trim-start nil - "How overlapping subtitles should be trimmed. If t, adjust the start time of the following subtitle, if nil, adjust the end of the current subtitle. Defaults to nil." + "How overlapping subtitles should be trimmed. If t, adjust the +start time of the following subtitle, if nil, adjust the end of +the current subtitle. Defaults to nil." :type 'boolean :group 'subed) (defcustom subed-trim-overlapping-use-subed-subtitle-spacing nil - "Whether `subed-subtitle-spacing' should be used when trimming overlapping subtitles. If nil, subtitles will trimmed to one millisecond less than adjacent one. Defaults to nil. You can also set the spacing by using a prefix arg when calling `subed-sanitize-overlaps', which see." + "Whether `subed-subtitle-spacing' should be used when trimming +overlapping subtitles. If nil, subtitles will trimmed to one +millisecond less than adjacent one. Defaults to nil. + +Spacing can also be set by using a prefix arg when calling +`subed-sanitize-overlaps', which see." :type 'boolean :group 'subed)