;;; livie.el --- Livie is Video in Emacs -*- lexical-binding: t; -*- ;; Copyright (C) 2018 ;;; Authors: ;; Charlie Ritter ;; Jesus E. ;;; Commentary: ;; livie grabs a list of youtube videos based on a search. the user ;; can then select a video to watch through `livie-player' ;;; Code: (require 'f) (defgroup livie '() "Livie is Video in Emacs" :prefix "livie-" :group 'livie) (defcustom livie-player "mpv" "Default video player to use with livie." :group 'livie :type 'string) (defcustom livie-player-args '() "Command line arguments for `livie-player'." :group 'livie :type '(list) :tag "Livie Player Arguments") (defcustom livie-python-name "python3" "Name of the python executable." :group 'livie :type 'string) (defcustom livie-script-path nil "Full path of livie.py." :group 'livie :type 'file) (defcustom livie-buffer-name "*livie*" "Name of the buffer to show results." :group 'livie :type 'string) (defvar livie-youtube-regexp "https://www.youtube.com/watch\\?v=[A-Za-z0-9_\\-]\\{11\\}") (define-derived-mode livie-mode special-mode "livie" "Major mode for livie.") (defun livie-close-window () "Close the livie window and bury the buffer." (interactive) (bury-buffer) (delete-window) (message nil)) (defun livie-next-video () "Goto the next video in the buffer." (interactive) (forward-line 1) (search-forward-regexp livie-youtube-regexp) (livie-prev-video)) (defun livie-prev-video () "Goto the previous video in the buffer." (interactive) (search-backward-regexp livie-youtube-regexp)) (defun livie-this-video () "Go to the start of the current video." (interactive) (move-beginning-of-line nil) (ignore-errors (forward-line -1)) (livie-next-video)) (defun livie-copy-video () "Copy the currently selected video into the kill ring." (interactive) (livie-this-video) (push-mark) (move-end-of-line nil) (kill-ring-save nil nil t) (livie-this-video)) (defun livie-watch-this-video () "Watch video under the cursor." (interactive) (livie-copy-video) (livie-watch (car kill-ring)) (delete-other-windows)) (defun livie-watch (url) "Watch video at URL using `livie-player' and `livie-player-args'." (interactive "sURL: ") (apply 'start-process (cl-concatenate 'list (list "livie" nil livie-player) livie-player-args (list url))) (message "Loading video...")) (defun livie (query) "Livie is Video in Emacs. Livie will prompt the user for a QUERY. This is fed into a python script that scrapes youtube.com for search results. The results are displayed in an Emacs buffer. See also: `livie-mode'." (interactive "sSearch: ") (unless livie-script-path (error "Please set `livie-script-path'")) (if (equal (buffer-name) livie-buffer-name) (progn (read-only-mode -1) (erase-buffer)) (progn (select-window (split-window)) (ignore-errors (kill-buffer livie-buffer-name)) (switch-to-buffer (generate-new-buffer livie-buffer-name)))) (call-process livie-python-name nil t t livie-script-path query) (livie-mode) (font-lock-ensure) (goto-char (point-min)) (message (concat "Results for: " query))) (font-lock-add-keywords 'livie-mode `((,livie-youtube-regexp . 'link) ("title: \\(.*\\)" 1 'bold) ("channel: \\(.*\\)" 1 'italic) ("^ +[a-zA-Z]+:" . 'shadow))) (define-key livie-mode-map "s" 'livie) (define-key livie-mode-map "q" 'livie-close-window) (define-key livie-mode-map (kbd "") 'livie-next-video) (define-key livie-mode-map (kbd "") 'livie-prev-video) (define-key livie-mode-map "n" 'livie-next-video) (define-key livie-mode-map "p" 'livie-prev-video) (define-key livie-mode-map (kbd "") 'livie-watch-this-video) (provide 'livie) ;;; livie.el ends here