diff options
| author | Sacha Chua <sacha@sachachua.com> | 2021-12-13 15:33:51 -0500 | 
|---|---|---|
| committer | Sacha Chua <sacha@sachachua.com> | 2021-12-13 15:33:51 -0500 | 
| commit | ba37c841dfbe8bec8e303055a40a6bc30c6cab57 (patch) | |
| tree | f7f5b4d6568585c10a38421ae291fb9212f2f168 | |
| parent | cf3ab315f2df9f4548bec5fcd336a839a68291ec (diff) | |
| download | emacsconf-el-ba37c841dfbe8bec8e303055a40a6bc30c6cab57.tar.xz emacsconf-el-ba37c841dfbe8bec8e303055a40a6bc30c6cab57.zip | |
Got multilingual captions to work again
Diffstat (limited to '')
| -rw-r--r-- | emacsconf-publish.el | 15 | ||||
| -rw-r--r-- | emacsconf-upcoming.el | 129 | ||||
| -rw-r--r-- | emacsconf.el | 188 | 
3 files changed, 324 insertions, 8 deletions
| diff --git a/emacsconf-publish.el b/emacsconf-publish.el index 7a54f03..55b3458 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -165,7 +165,7 @@                 (if (eq (plist-get talk :format) 'wiki)                     (concat s "  \n")                   (concat "<li>" s "</li>"))) -             (emacsconf-link-file-formats-as-list talk (or extensions emacsconf-published-extensions)) +             (emacsconf-link-file-formats-as-list talk (or extensions emacsconf-main-extensions))               "")              :poster (and video-file (format "https://media.emacsconf.org/%s/%s.png" (plist-get talk :conf-year) (file-name-base video-file)))              :toobnix-info (if (plist-get talk :toobnix-url) @@ -384,7 +384,7 @@ ${info}              (pcase emacsconf-publishing-phase                ('program "<tr><th>Status</th><th>Title<th><th>Speaker(s)</th></tr>")                ('schedule "<tr><th>Status</th><th>Start</th><th>Title</th><th>Speaker(s)</th></tr>") -              ('resources "<tr><th>Title</th><th>Speaker(s)</th><th>Resources</th></tr>"))  +              ('resources "<tr><th>Title</th><th>Speaker(s)</th><th>Resources</th></tr>"))              (mapconcat               (lambda (o)                 (let* ((time-fmt "%l:%M %p") @@ -430,7 +430,7 @@ ${info}                                           (emacsconf-link-file-formats-as-list                                            (append o                                                    (list :base-url (format "%s%s/" emacsconf-media-base-url emacsconf-year))) -                                          (append emacsconf-published-extensions '("--main.webm"))) +                                          (append emacsconf-main-extensions '("--main.webm")))                                           "")))))))               (seq-remove (lambda (o) (string= (plist-get o :status) "CANCELLED"))                           (cdr info)) @@ -538,7 +538,7 @@ ${info}                                       :track-base-url                                       (format "/%s/captions/" (plist-get f :conf-year)))                                 f) -                       emacsconf-published-extensions) +                       emacsconf-main-extensions)                      "")                    (if (plist-get f :qa-public)                        (emacsconf-index-card @@ -595,13 +595,12 @@ ${info}       "")     (mapconcat      (lambda (lang) -      (let ((lang-file (concat (file-name-sans-extension filename) "_" (car lang) (file-name-extension filename)))) +      (let ((lang-file (concat (file-name-sans-extension filename) "_" (car lang) "." (file-name-extension filename))))          (if (file-exists-p lang-file) -            (format "<track label=\"%s\" kind=\"captions\" srclang=\"%s\" src=\"%s--main_%s.vtt\" />" +            (format "<track label=\"%s\" kind=\"captions\" srclang=\"%s\" src=\"%s\" />"                      (cdr lang)                      (car lang) -                    (concat (or track-base-url "") (file-name-nondirectory lang-file)) -                    (car lang)) +                    (concat (or track-base-url "") (file-name-nondirectory lang-file)))            "")))      '(("fr" . "French") ("ja" . "Japanese"))      ""))) diff --git a/emacsconf-upcoming.el b/emacsconf-upcoming.el new file mode 100644 index 0000000..b94dc00 --- /dev/null +++ b/emacsconf-upcoming.el @@ -0,0 +1,129 @@ +;;; emacsconf-upcoming.el --- Update upcoming.org with information about the next talks  -*- lexical-binding: t; -*- + +;; Copyright (C) 2021  Sacha Chua + +;; Author: Sacha Chua <sacha@sachachua.com> +;; Keywords: data + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program.  If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;;  + +;;; Code: + +(defun emacsconf-upcoming-update-file () +  (interactive) +  (with-current-buffer (find-file-noselect emacsconf-upcoming-file) +    (save-excursion +      (org-map-entries #'emacsconf-upcoming-insert-or-update "SLUG={.}") +))) + +(defun emacsconf-upcoming-add-subtree () +  (interactive) +  (org-map-entries #'emacsconf-upcoming-insert-or-update "SLUG={.}" 'tree) +  (save-excursion +    (with-current-buffer (find-file-noselect emacsconf-upcoming-file) +      (emacsconf-upcoming-sort)))) + +(defun emacsconf-upcoming-sort () +  (interactive) +  ;; Sort +  (goto-char (point-min)) +  (when (looking-at "\\*") (save-excursion (insert "\n"))) ;; Need to be before the first heading. +  (org-sort-entries +   nil ?f +   (lambda () (cons (org-entry-is-done-p) (org-entry-get (point) "SCHEDULED"))) +   (lambda (a b) +     (cond +      ((and (car a) (car b)) (string< (cdr a) (cdr b))) +      ((car b) t) +      ((car a) nil)                   ; move done things to the bottom +      (t (string< (cdr a) (cdr b))))))) + +(defun emacsconf-upcoming-insert-or-update-from-slug (slug) +  (interactive (list (emacsconf-complete-talk))) +  (save-excursion +    (emacsconf-with-talk-heading slug +      (emacsconf-upcoming-insert-or-update nil nil)))) + +(defun emacsconf-upcoming-insert-or-update (&optional info sort) +  (interactive (list nil nil)) +  (let ((info +         (or info +             (when (buffer-file-name) +               (if (string= (expand-file-name (buffer-file-name)) emacsconf-org-file) +                   (emacsconf-get-talk-info-for-subtree) +                 (let ((slug (org-entry-get (point) "SLUG"))) +                   (emacsconf-with-talk-heading slug +                     (emacsconf-get-talk-info-for-subtree))))))) +        pos) +    (when (and (plist-get info :slug) emacsconf-upcoming-file) +      (with-current-buffer (find-file-noselect emacsconf-upcoming-file) +        (setq pos (org-find-property "SLUG" (plist-get info :slug))) +        (if pos +            (goto-char pos) +          (goto-char (point-max)) +          (unless (bolp) (insert "\n")) +          (insert (format "* TODO %s: %s - %s\n" +                          (plist-get info :slug) +                          (plist-get info :title) +                          (plist-get info :speakers)))) +        (org-todo (plist-get info :status)) +        (org-entry-put (point) "SLUG" (plist-get info :slug)) +        (org-entry-put (point) "URL" (concat emacsconf-base-url emacsconf-year "/talks/" (plist-get info :slug))) +        (org-set-property "SCHEDULED" (plist-get info :scheduled)) +        (unless (org-entry-get (point) "INTRO_NOTE") +          (org-entry-put (point) "INTRO_NOTE" (plist-get info :intro-note))) +        (when (or (plist-get info :pronouns) (plist-get info :pronunciation)) +          (unless (org-entry-get (point) "OTHER_INFO") +            (org-entry-put (point) "OTHER_INFO" +                           (string-join (delq nil (list (plist-get info :pronouns) (plist-get info :pronunciation))) " ")))) +        (org-entry-put (point) "PRESENT" (or (plist-get info :present) "?")) +        (org-entry-put (point) "DURATION" +                       (or (plist-get info :video-duration) +                           (concat "~ " (plist-get info :duration)))) +        (org-entry-put (point) "BUFFER" +                       (format "%s (ending ~ %s)" +                               (plist-get info :buffer) +                               (format-time-string +                                "%l:%M%p" +                                (seconds-to-time +                                 (+ +                                  (time-to-seconds +                                   (org-timestamp-to-time (org-timestamp-split-range (org-timestamp-from-string (plist-get info :scheduled))))) +                                  (* 60 (string-to-number (plist-get info :duration))) +                                  (* 60 (string-to-number (plist-get info :buffer))))) +                                emacsconf-timezone))) +        (org-entry-put (point) "Q_AND_A"  +                       (or (plist-get info :bbb-room) +                           (plist-get info :q-and-a) +                           "?")) +        ;(org-entry-put (point) "IRC" +        ;               (or (plist-get info :irc) "?")) +        (org-entry-put (point) "CHECK_IN" +                       (or (plist-get info :check-in) "?")) +        (org-entry-put (point) "EMAIL" (plist-get info :email)) +        (if (plist-get info :contact) +            (org-entry-put (point) "CONTACT" (plist-get info :check-in))) +        (if sort (emacsconf-upcoming-sort)))))) + + + + + + +(provide 'emacsconf-upcoming) +;;; emacsconf-upcoming.el ends here diff --git a/emacsconf.el b/emacsconf.el index 8f2be80..357b271 100644 --- a/emacsconf.el +++ b/emacsconf.el @@ -75,5 +75,193 @@    "Return the newest file in PATH. Optionally filter by FILTER."    (car (sort (seq-remove #'file-directory-p (directory-files path 'full filter t)) #'file-newer-than-file-p))) + +(defun emacsconf-get-slug-from-string (search) +  (if (listp search) (setq search (car search))) +  (if (and search (string-match "\\(.*?\\) - " search)) +      (match-string 1 search) +    search)) +(defun emacsconf-go-to-talk (&optional search) +  (interactive (list (emacsconf-complete-talk))) +  (when search +    (setq search (emacsconf-get-slug-from-string search)) +    (pop-to-buffer (find-file-noselect emacsconf-org-file)) +    (let ((choices +           (save-excursion +             (delq nil +                   (org-map-entries +                    (lambda () +                      (when (org-entry-get (point) "SLUG") +                        (cons +                         (concat (org-entry-get (point) "SLUG") " - " +                                 (org-entry-get (point) "ITEM") " - " +                                 (org-entry-get (point) "NAME") " - " +                                 (org-entry-get (point) "EMAIL")) +                         (point))))))))) +      (goto-char +       (if search +           (or (org-find-property "SLUG" search) +               (cdr (seq-find (lambda (s) (string-match search (car s))) choices))) +         (assoc-default (completing-read "Find: " choices) +                        choices))) +      (org-reveal)))) + +(defmacro emacsconf-with-talk-heading (search &rest body) +  (declare (indent 1) (debug t)) +  `(progn +     (emacsconf-go-to-talk ,search) +     ,@body)) + +(defun emacsconf-status-types () +  ;; TODO +  ) + +(defun emacsconf-get-talk-info-from-properties (o) +  (let ((heading (org-heading-components)) +        (field-props '((:title "ITEM") +                       (:talk-id "TALK_ID") +                       (:slug "SLUG") +                       (:video-slug "VIDEO_SLUG") +                       (:public "PUBLIC") +                       (:qa-public "QA_PUBLIC") +                       (:scheduled "SCHEDULED") +                       (:uuid "UUID") +                       (:email "EMAIL") +                       (:caption-note "CAPTION_NOTE") +                       (:duration "TIME") +                       (:q-and-a "Q_AND_A") +                       (:bbb-room "ROOM") +                       (:irc "IRC") +                       (:intro-note "INTRO_NOTE") +                       (:check-in "CHECK_IN") +                       (:contact "CONTACT") +                       (:captioner "CAPTIONER") +                       (:youtube-url "YOUTUBE_URL") +                       (:toobnix-url "TOOBNIX_URL") +                       (:pronunciation "PRONUNCIATION") +                       (:pronouns "PRONOUNS") +                       (:buffer "BUFFER") +                       (:time "MIN_TIME") +                       (:present "PRESENT") +                       (:speakers "NAME") +                       (:speakers-short "NAME_SHORT") +                       (:video-file "VIDEO_FILE") +                       (:video-file-size "VIDEO_FILE_SIZE") +                       (:video-duration "VIDEO_DURATION") +                       (:alternate-apac "ALTERNATE_APAC") +                       (:extra-live-time "EXTRA_LIVE_TIME")))) +    (apply +     'append +     o +     (list +      :type (if (org-entry-get (point) "SLUG") 'talk 'headline) +      :status (elt heading 2) +      :level (car heading) +      :url (concat emacsconf-base-url emacsconf-year "/talks/" (org-entry-get (point) "SLUG")) +      :schedule-group  +      (org-entry-get-with-inheritance "SCHEDULE_GROUP") +      :wiki-file-path (expand-file-name  +                       (concat (org-entry-get (point) "SLUG") ".md") +                       (expand-file-name "captions" (expand-file-name emacsconf-year emacsconf-directory))) +      :conf-year emacsconf-year +      :start-time (when (org-entry-get (point) "SCHEDULED") +                    (org-timestamp-to-time +                     (org-timestamp-split-range +                      (org-timestamp-from-string +                       (org-entry-get (point) "SCHEDULED"))))) +      :end-time (when (org-entry-get (point) "SCHEDULED") +                  (org-timestamp-to-time +                   (org-timestamp-split-range +                    (org-timestamp-from-string +                     (org-entry-get (point) "SCHEDULED")) +                    t)))) +     (mapcar  +      (lambda (o) (list (car o) (org-entry-get (point) (cadr o)))) +      field-props)))) + +(defun emacsconf-get-abstract-from-wiki (o) +  (plist-put o :markdown (emacsconf-talk-markdown-from-wiki (plist-get o :slug)))) + +(defun emacsconf-add-talk-status (o) +  (plist-put o :status-label +             (assoc-default (plist-get o :status)  +                            (emacsconf-status-types) 'string= ""))) + +(defvar emacsconf-talk-info-functions '(emacsconf-get-talk-info-from-properties emacsconf-add-talk-status)) + +(defun emacsconf-get-talk-info-for-subtree () +  (seq-reduce (lambda (prev val) (funcall val prev)) +              emacsconf-talk-info-functions +              nil)) + +(defun emacsconf-get-talk-info (&optional description-source) +  (with-current-buffer (find-file-noselect emacsconf-org-file) +    (save-excursion +      (let (talk results (status-types (emacsconf-status-types))) +        (org-map-entries +         (lambda () +           (when (or (org-entry-get (point) "SLUG") +                     (org-entry-get (point) "INCLUDE_IN_INFO")) +             (setq results +                   (cons (emacsconf-get-talk-info-for-subtree) +                         results))))) +        (nreverse results))))) + +(defun emacsconf-filter-talks (list) +  "Return only talk info in LIST." +  (seq-filter +   (lambda (talk) (eq (plist-get talk :type) 'talk)) +   list)) + +(defun emacsconf-get-talk-info-from-file (&optional filename) +  (with-temp-buffer +    (insert-file-contents (or filename "conf.org")) +    (org-mode) +    (org-show-all) +    (goto-char (point-min)) +    (goto-char (org-find-property "ID" "talks")) +    (emacsconf-get-talk-info 'wiki))) + + +(defun emacsconf-find-talk-info (filter &optional info) +  (setq info (or info (emacsconf-filter-talks (emacsconf-get-talk-info)))) +  (when (stringp filter) (setq filter (list filter))) +  (or (seq-find (lambda (o) (string= (plist-get o :slug) (car filter))) info) +      (seq-find (lambda (o) +                  (let ((case-fold-search t) +                        (all (mapconcat (lambda (f) (plist-get o f)) '(:title :speakers :slug) " "))) +                    (null (seq-contains-p +                           (mapcar (lambda (condition) (string-match condition all)) filter) +                           nil)))) +                info))) + +(defun emacsconf-goto-talk-id (id) +  (goto-char (org-find-property "TALK_ID" id))) + +(defun emacsconf-talk-markdown-from-wiki (slug) +  "Return the markdown from SLUG." +  (when (file-exists-p (expand-file-name (format "%s/talks/%s.md" emacsconf-year slug) emacsconf-directory)) +    (with-temp-buffer +      (insert-file-contents (expand-file-name (format "%s/talks/%s.md" emacsconf-year slug) emacsconf-directory)) +      (goto-char (point-min)) +      (while (re-search-forward "<!--" nil t) +        (let ((start (match-beginning 0))) +          (when (re-search-forward "-->" nil t) +            (delete-region start (match-end 0))))) +      (goto-char (point-min)) +      (while (re-search-forward "\\[\\[![^]]+\\]\\]" nil t) +        (replace-match "")) +      (string-trim (buffer-string))))) + +(defun emacsconf-replace-plist-in-string (attrs string) +  "Replace ${keyword} from ATTRS in STRING." +  (let ((a attrs)) +    (while a +      (setq string +            (replace-regexp-in-string (regexp-quote (concat "${" (substring (symbol-name (pop a)) 1) "}")) +                                      (pop a) +                                      string t t))) +    string)) +  (provide 'emacsconf)  ;;; emacsconf.el ends here | 
