emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Org, Hyperbole, and eev


From: Robert Weiner
Subject: Re: Org, Hyperbole, and eev
Date: Sun, 26 Jun 2022 20:49:47 -0400

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=" 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")
     ((= num-of-parts 1)
      (concat (nth 0 time-parts) "s"))
     ((= num-of-parts 2)
      (format "%sm%ss" (nth 0 time-parts) (nth 1 time-parts)))
     ((= 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=%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}:

<youtube-play-from-time "WKwZHSbHmPg" "2:44">
<youtube-play-from-time "www.youtube.com/watch?v=WKwZHSbHmPg" "2:44">
<youtube-play-from-time "https://www.youtube.com/watch?v=WKwZHSbHmPg" "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 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 /| | (_| |  __/ (_) |
;;;  \__, |\___/ \__,_|\__|\__,_|_.__/ \___|      \_/ |_|\__,_|\___|\___/
;;;  |___/                                                                
;;
;; «find-youtube-video»  (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=%s%s"
          youtubeid (or (ee-time-to-youtube-time (or time "")) "")))

;; «youtube-time»  (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=1m23s\".
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=%ss" c (match-string 1 str)))
          ((string-match "^\\([0-9]+\\):\\([0-9][0-9]\\)$" str)
           (format "%st=%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=%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)
    ""))


reply via email to

[Prev in Thread] Current Thread [Next in Thread]