From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id WDXzOBT/uGLdUQEAbAwnHQ (envelope-from ) for ; Mon, 27 Jun 2022 02:51:32 +0200 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id 6DbaOBT/uGItCwEA9RJhRA (envelope-from ) for ; Mon, 27 Jun 2022 02:51:32 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 279962A369 for ; Mon, 27 Jun 2022 02:51:32 +0200 (CEST) Received: from localhost ([::1]:34534 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5cyP-00033Y-Py for larch@yhetil.org; Sun, 26 Jun 2022 20:51:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46330) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5cxC-000336-Gu for emacs-orgmode@gnu.org; Sun, 26 Jun 2022 20:50:14 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:56236) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5cxC-0006UJ-93 for emacs-orgmode@gnu.org; Sun, 26 Jun 2022 20:50:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=To:Subject:Date:From:In-Reply-To:References: MIME-Version; bh=vYGvpEjXqxJSvUBA3e9V6pZhoF7jidpXsQNgTTB9xQ0=; b=LzyxNon4C6Iu yXcJbsA83y0cZ7ybyRKk2qJLwW2SjMBbQ3HfyzpLYsEpA33ix7zrKphqtUb0JOdks6FGC8xjraZH+ hmwuI/JAVKw8qgVKgt6c3noS0rkW9kcoowP4Yq96Qxf/tLyfSOJjEahns4FeLmo/hfZj7aD5/qSCZ b0UbU+bJNcojja6DjVlDfDKKm02NWWWOPkd7jcmhNOLwuugoaOs/MiqygOvHQCmTI6gkG7h0t7VaX cOiHO6+zbBy41neR4h8/eobTbNk2YhqtTIBAtJ6hnztNAzEBTrQkwgWkHCBmAd368hi7fycjSt401 aFAvx4uuoaYslzS/x8gPkQ==; Received: from mail-yb1-f181.google.com ([209.85.219.181]:45866) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5cxC-0006vS-1s for emacs-orgmode@gnu.org; Sun, 26 Jun 2022 20:50:14 -0400 Received: by mail-yb1-f181.google.com with SMTP id x184so11407472ybg.12 for ; Sun, 26 Jun 2022 17:50:14 -0700 (PDT) X-Gm-Message-State: AJIora+GNCwho0n50PWLBlPSuTcKrVQcIF3tUKShXFR7f18pHAWAUox+ FF972re+/0/x/OuMhWM95AfYXFibCra7I2EKunw= X-Google-Smtp-Source: AGRyM1vHEFW+of0jYAuF+nea+3LagC1aaf2UQyo6k3Wx/RWGzptcPzcJL77bgMfuVzayBUxcuYwBMPU7Z0jO3K7pFLM= X-Received: by 2002:a25:4109:0:b0:66c:74a1:4ca7 with SMTP id o9-20020a254109000000b0066c74a14ca7mr10930977yba.600.1656291013347; Sun, 26 Jun 2022 17:50:13 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Robert Weiner Date: Sun, 26 Jun 2022 20:49:47 -0400 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: Org, Hyperbole, and eev To: Eduardo Ochs Cc: Org Mode Content-Type: multipart/alternative; boundary="0000000000007ecef405e2634d84" X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: rswgnu@gmail.com Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1656291092; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=vYGvpEjXqxJSvUBA3e9V6pZhoF7jidpXsQNgTTB9xQ0=; b=UvmOIRTunWywgN/qaYDTO2iWg+23V+OJLDC3did0Pb/R0tpTJBibe83wsxqKaUecbnJSLG EzTKeKc+noHNxMWh5vLBvuuN51bxALu8Gnbc/fkIQZOT99YVXzBA18VGokmF57OhDWfg1X mXREStcvuCNlIsqpoZLsPuGQWZy89TXKYfeA3rWTwGXqV5Qp28UeByOm8lX6mnBrXda56u DeFp5oB/uoYNQIE35H9+Sq7QokdtxR9bX/5A06RT8kAgv4F5VrT0VpVJ1LtsZI2hCbs2PR SP8+TA1wEdZ7Agd0Z/1Ij2NuWsmPKVyM07Zj0k72HzWNMLPLb4U0wmjEHVZCAg== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1656291092; a=rsa-sha256; cv=none; b=KB/pw28FaIxcVTdPmm8JAiGOVk9I4EPOgTrvkwZlBriyzRoRkEvcERnxCqk4GwrMRZeeT4 FHG8cHXApmVtDqrwjXh/qd4j5ySHE0p4GVTvy4qLCfame44fc5k+vETvJPdE2Ib/H32i+E +5IpFtbdf9J2PclAsWY0x2ldPy3Pbee/2C49AMbeWZu5YXdA4oeTw5uLHpIPsYtlZxR7B+ PwjKrr/kQ6rCn07Ddsa92n0kW5+lMVTFEuKICvT53kZ4kBKrqoiRPxf1VX+lSkiX6KoQ7s 3DjajPNUWV4JQhAUpLzCgdz0b64Z9Aow189lKnDteELkjvX6IAWWKtORXvHopg== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gnu.org header.s=fencepost-gnu-org header.b=LzyxNon4; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -8.95 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gnu.org header.s=fencepost-gnu-org header.b=LzyxNon4; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 279962A369 X-Spam-Score: -8.95 X-Migadu-Scanner: scn0.migadu.com X-TUID: wYHgz0kpjMqU --0000000000007ecef405e2634d84 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable So here is a simple implementation that is not unlike your own though the functions are a bit simpler and more clearly documented without a listing of every possible test case type and requires neither Hyperbole nor Org until you want to activate things as buttons: (require 'browse-url) (defun youtube-normalize-link (video-link) "Return a URL to a youtube video. ViDEO-LINK must be a string and can be a video identifier, e.g. WkwZHSbHmPg, or a full URL to the video." (if (or (string-prefix-p "https://" video-link) (string-prefix-p "www." video-link)) video-link (concat "https://www.youtube.com/watch?v=3D" video-link))) (defun youtube-normalize-time (time-string) "Given a colon-separated TIME-STRING, with optional hours and minutes, e.g. 1:2:44 (1 hour, two minutes, 45 seconds into a video), return the normalized time for a Youtube url. If the TIME-STRING format is invalid, return nil." (if (string-match-p ":" time-string) (let* ((time-parts (split-string time-string ":")) (num-of-parts (length time-parts))) (cond ((zerop num-of-parts) "0s") ((=3D num-of-parts 1) (concat (nth 0 time-parts) "s")) ((=3D num-of-parts 2) (format "%sm%ss" (nth 0 time-parts) (nth 1 time-parts))) ((=3D num-of-parts 3) (format "%sh%sm%ss" (nth 0 time-parts) (nth 1 time-parts) (nth 2 time-parts))))) time-string)) (defun youtube-url-from-time (video-link time-string) "Given a VIDEO-LINK and a colon-separated TIME-STRING, e.g. 2:44 (two minutes, 45 seconds into the video), return the url to play from that point in the video. Return nil if TIME-STRING is invalid." (when (setq time-string (youtube-normalize-time time-string)) (format "%s&t=3D%s" (youtube-normalize-link video-link) time-string))) (defun youtube-play-from-time (video-link time-string) "Given a VIDEO-LINK and a colon-separated TIME-STRING, e.g. 2:44 (two minutes, 45 seconds), play the video from that point." (browse-url (youtube-url-from-time video-link time-string))) ;;;;;;;;;;;;;;;;;; Then once you load the Hyperbole package, in any buffer you could use any of the 3 buttons below which all do the same thing when pressed upon with the Action Key, {M-RET}: If you added these functions to eev, I think you would simply change the <> to (): (youtube-play-from-time "WKwZHSbHmPg" "2:44") ;;;;;;;;;;;;;;;;;;;;;;;; I avoided creating implicit button and action types for this example to show you that they are not needed as you don't like specialized syntax anyway and want everything to be explicit, but in Hyperbole, we would probably create an implicit button type that recognized strings like "yt:WKwZHSbHmPg@2:44" and invoked the calls shown above. ;;;;;;;;;;;;;;;;;;;;;;;; For comparison, below is your eev code for the same purpose. You can see that it has extra arguments for little reason, uses eval where not necessary, and makes the URL assembly more complicated than needed. The differences are not major but my point is this adds up both in amounts of code and amounts of maintenance needed that you could reduce leveraging existing capabilities, like Hyperbole's ability to turn arbitrary functions into hyperbuttons. ;;; _ _ _ _ ;;; _ _ ___ _ _| |_ _ _| |__ ___ __ _(_) __| | ___ ___ ;;; | | | |/ _ \| | | | __| | | | '_ \ / _ \____\ \ / / |/ _` |/ _ \/ _ \ ;;; | |_| | (_) | |_| | |_| |_| | |_) | __/_____\ V /| | (_| | __/ (_) | ;;; \__, |\___/ \__,_|\__|\__,_|_.__/ \___| \_/ |_|\__,_|\___|\___/ ;;; |___/ ;; ;; =C2=ABfind-youtube-video=C2=BB (to ".find-youtube-video") ;; Play a video on youtube using a browser. ;; Tests: (ee-find-youtube-url "xQqWufQgzVY" nil) ;; (ee-find-youtube-url "xQqWufQgzVY" "1:23") ;; (ee-find-youtube-video "xQqWufQgzVY") ;; (ee-find-youtube-video "xQqWufQgzVY" "1:23") ;; (ee-find-youtube-video "xQqWufQgzVY" "1:23" "Bla") ;; (find-youtube-video "xQqWufQgzVY" "1:23") ;; (ee-find-youtube-video "FoAzpGzFCSE" "15:14" "nice") ;; (find-youtube-video "FoAzpGzFCSE" "15:14" "nice") ;; (defvar ee-find-youtube-video-program 'find-googlechrome) (defun find-youtube-video (youtubeid &optional time &rest rest) (eval (ee-find-youtube-video youtubeid time))) (defun ee-find-youtube-video (youtubeid &optional time &rest rest) (list ee-find-youtube-video-program (ee-find-youtube-url youtubeid time))) (defun ee-find-youtube-url (youtubeid time) (format "http://www.youtube.com/watch?v=3D%s%s" youtubeid (or (ee-time-to-youtube-time (or time "")) ""))) ;; =C2=AByoutube-time=C2=BB (to ".youtube-time") ;; Tests: (ee-time-to-youtube-time "") ;; (ee-time-to-youtube-time "!") ;; (ee-time-to-youtube-time "2") ;; (ee-time-to-youtube-time "23") ;; (ee-time-to-youtube-time "123") ;; (ee-time-to-youtube-time "1:23") ;; (ee-time-to-youtube-time "1:23:43") ;; (ee-time-to-youtube-time "1:23:43" "&") ;; (ee-time-to-youtube-time "" "&") ;; (defun ee-time-to-youtube-time (str &optional c) "Convert strings like \"1:23\" to strings like \"#t=3D1m23s\". Supports the input formats \"ss\", \"mm:ss\", and \"hh:mm:ss\". If the input does not match any of these formats, return nil. When C is non nil then use it as the prefix character. The default is \"#\", but in some situations we need \"&\" instead." (setq c (or c "#")) (save-match-data (cond ((string-match "^\\([0-9]+\\)$" str) (format "%st=3D%ss" c (match-string 1 str))) ((string-match "^\\([0-9]+\\):\\([0-9][0-9]\\)$" str) (format "%st=3D%sm%ss" c (match-string 1 str) (match-string 2 str))) ((string-match "^\\([0-9]+\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" str) (format "%st=3D%sh%sm%ss" c (match-string 1 str) (match-string 2 str) (match-string 3 str)))))) ;; Tests: (ee-time-to-arg "") ;; (ee-time-to-arg nil) ;; (ee-time-to-arg "{time}") ;; (ee-time-to-arg "1:23") ;; See: (find-efunction 'ee-time-to-youtube-time) ;; (defun ee-time-to-arg (time) (setq time (or time "")) (if (ee-time-to-youtube-time time) (format " \"%s\"" time) "")) --0000000000007ecef405e2634d84 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
So here is a simple implementation that is no= t unlike your own though the functions are a bit simpler and more clearly d= ocumented without a listing of every possible test case type and requires n= either Hyperbole nor Org until you want to activate things as buttons:
(require 'browse-url)

(defun youtube-normalize-link (video-l= ink)
=C2=A0 "Return a URL to a youtube video.=C2=A0 ViDEO-LINK must= be a string and can be a video identifier, e.g. WkwZHSbHmPg, or a full URL= to the video."
=C2=A0 (if (or (string-prefix-p "https://"= ; video-link)
=C2=A0(string-prefix-p "www." video-link))
= =C2=A0 =C2=A0 =C2=A0 video-link
=C2=A0 =C2=A0 (concat "https://www.youtube.com/watch?v=3D&q= uot; video-link)))

(defun youtube-normalize-time (time-string)
= =C2=A0 "Given a colon-separated TIME-STRING, with optional hours and m= inutes, e.g. 1:2:44 (1 hour, two minutes, 45 seconds into a video), return = the normalized time for a Youtube url.
If the TIME-STRING format is inva= lid, return nil."
=C2=A0 (if (string-match-p ":" time-str= ing)
=C2=A0 =C2=A0 =C2=A0 (let* ((time-parts (split-string time-string &= quot;:"))
=C2=A0 =C2=A0 (num-of-parts (length time-parts)))
(= cond ((zerop num-of-parts)
=C2=A0 =C2=A0 =C2=A0 "0s")
= =C2=A0 =C2=A0 =C2=A0((=3D num-of-parts 1)
=C2=A0 =C2=A0 =C2=A0 (concat= (nth 0 time-parts) "s"))
=C2=A0 =C2=A0 =C2=A0((=3D num-of-p= arts 2)
=C2=A0 =C2=A0 =C2=A0 (format "%sm%ss" (nth 0 time-pa= rts) (nth 1 time-parts)))
=C2=A0 =C2=A0 =C2=A0((=3D num-of-parts 3) =C2=A0 =C2=A0 =C2=A0 (format "%sh%sm%ss" (nth 0 time-parts) (n= th 1 time-parts) (nth 2 time-parts)))))
=C2=A0 =C2=A0 time-string))
<= br>(defun youtube-url-from-time (video-link time-string)
=C2=A0 "Gi= ven a VIDEO-LINK and a colon-separated TIME-STRING, e.g. 2:44 (two minutes,= 45 seconds into the video), return the url to play from that point in the = video.
Return nil if TIME-STRING is invalid."
=C2=A0 (when (setq= time-string (youtube-normalize-time time-string))
=C2=A0 =C2=A0 (format= "%s&t=3D%s"
=C2=A0 =C2=A0(youtube-normalize-link video-= link)
=C2=A0 =C2=A0time-string)))

(defun youtube-play-from-time= (video-link time-string)
=C2=A0 "Given a VIDEO-LINK and a colon-se= parated TIME-STRING, e.g. 2:44 (two minutes, 45 seconds), play the video fr= om that point."
=C2=A0 (browse-url (youtube-url-from-time video-lin= k time-string)))

;;;;;;;;;;;;;;;;;;

Then once you load the Hy= perbole package, in any buffer you could use any of the 3 buttons below whi= ch all do the same thing when pressed upon with the Action Key, {M-RET}:
<= br><youtube-play-from-time "WKwZHSbHmPg" "2:44"><= br><youtube-play-from-time "www.youtube.com/watch?v=3DWKwZHSbHmPg" "2:4= 4">
<youtube-play-from-time "https://www.youtube.com/watch?v=3DWKwZHSbHmP= g" "2:44">

If you added these functions to= eev, I think you would simply change the <> to ():

(youtube= -play-from-time "WKwZHSbHmPg" "2:44")

;;;;;;;;= ;;;;;;;;;;;;;;;;

I avoided creating implicit button and action types= for this example to show you that they are not needed as you don't lik= e specialized syntax anyway and want everything to be explicit, but in Hype= rbole, we would probably create
an implicit button type that recognized st= rings like "yt:WKwZHSbHmPg@2:44" and invoked the calls shown abov= e.

;;;;;;;;;;;;;;;;;;;;;;;;

For comparison, below is your ee= v code for the same purpose.=C2=A0 You can see that it has extra arguments = for little reason, uses eval where not necessary, and makes the URL assembl= y more complicated than needed.=C2=A0 The differences are not major but my = point is this adds up both in amounts of code and amounts of maintenance ne= eded that you could reduce leveraging existing capabilities,=C2=A0like Hype= rbole's ability to turn arbitrary functions into hyperbuttons.

;= ;; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0_ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 _ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 _ =C2=A0 =C2=A0 _ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0
;;; =C2=A0_ =C2=A0 _ =C2=A0___ =C2=A0_ =C2=A0 _| |_ _ =C2=A0 = _| |__ =C2=A0 ___ =C2=A0 =C2=A0 __ =C2=A0 _(_) __| | ___ =C2=A0___ =C2=A0;;; | | | |/ _ \| | | | __| | | | '_ \ / _ \____\ \ / / |/ _` |/ _ \/= _ \
;;; | |_| | (_) | |_| | |_| |_| | |_) | =C2=A0__/_____\ V /| | (_|= | =C2=A0__/ (_) |
;;; =C2=A0\__, |\___/ \__,_|\__|\__,_|_.__/ \___| =C2= =A0 =C2=A0 =C2=A0\_/ |_|\__,_|\___|\___/
;;; =C2=A0|___/ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
;;
;; = =C2=ABfind-youtube-video=C2=BB =C2=A0(to ".find-youtube-video");; Play a video on youtube using a browser.
;; Tests: (ee-find-youtube= -url =C2=A0 "xQqWufQgzVY" nil)
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(= ee-find-youtube-url =C2=A0 "xQqWufQgzVY" "1:23")
;; = =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-find-youtube-video "xQqWufQgzVY")<= br>;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-find-youtube-video "xQqWufQgzVY&q= uot; "1:23")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-find-youtube-vi= deo "xQqWufQgzVY" "1:23" "Bla")
;; =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 (find-youtube-video "xQqWufQgzVY" &qu= ot;1:23")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-find-youtube-video &quo= t;FoAzpGzFCSE" "15:14" "nice")
;; =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 (find-youtube-video "FoAzpGzFCSE" "15:= 14" "nice")
;;
(defvar ee-find-youtube-video-program &= #39;find-googlechrome)

(defun find-youtube-video (youtubeid &opt= ional time &rest rest)
=C2=A0 (eval (ee-find-youtube-video youtubeid= time)))

(defun ee-find-youtube-video (youtubeid &optional time = &rest rest)
=C2=A0 (list ee-find-youtube-video-program
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 (ee-find-youtube-url youtubeid time)))

(defun ee-f= ind-youtube-url (youtubeid time)
=C2=A0 (format "http://www.youtube.com/watch?v=3D%s%s&q= uot;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 youtubeid (or (ee-time-to-youtub= e-time (or time "")) "")))

;; =C2=AByoutube-time= =C2=BB =C2=A0(to ".youtube-time")
;; Tests: (ee-time-to-youtub= e-time "")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-t= ime "!")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-tim= e "2")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-time = "23")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-time &= quot;123")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-time &= quot;1:23")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-time = "1:23:43")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-youtube-t= ime "1:23:43" "&")
;; =C2=A0 =C2=A0 =C2=A0 =C2= =A0(ee-time-to-youtube-time "" "&")
;;
(defun= ee-time-to-youtube-time (str &optional c)
=C2=A0 "Convert stri= ngs like \"1:23\" to strings like \"#t=3D1m23s\".
Su= pports the input formats \"ss\", \"mm:ss\", and \"= hh:mm:ss\".
If the input does not match any of these formats, retur= n nil.
When C is non nil then use it as the prefix character. The
def= ault is \"#\", but in some situations we need \"&\"= instead."
=C2=A0 (setq c (or c "#"))
=C2=A0 (save-mat= ch-data
=C2=A0 =C2=A0 (cond ((string-match "^\\([0-9]+\\)$" st= r)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(format "%st=3D%ss"= ; c (match-string 1 str)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((string-m= atch "^\\([0-9]+\\):\\([0-9][0-9]\\)$" str)
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0(format "%st=3D%sm%ss" c (match-string 1 = str) (match-string 2 str)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((string-= match "^\\([0-9]+\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" str)
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(format "%st=3D%sh%sm%ss"= ; c (match-string 1 str) (match-string 2 str)
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(match-string 3 str))))))
<= br>;; Tests: (ee-time-to-arg "")
;; =C2=A0 =C2=A0 =C2=A0 =C2= =A0(ee-time-to-arg nil)
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-arg &q= uot;{time}")
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0(ee-time-to-arg "1:= 23")
;; =C2=A0 See: (find-efunction 'ee-time-to-youtube-time);;
(defun ee-time-to-arg (time)
=C2=A0 (setq time (or time "&q= uot;))
=C2=A0 (if (ee-time-to-youtube-time time)
=C2=A0 =C2=A0 =C2=A0= (format " \"%s\"" time)
=C2=A0 =C2=A0 "")= )

--0000000000007ecef405e2634d84--