livie/livie.el

157 lines
3.9 KiB
EmacsLisp

;;; livie.el --- Livie is Video in Emacs -*- lexical-binding: t; -*-
;; Copyright (C) 2018
;;; Authors:
;; Charlie Ritter <chewzerita@posteo.net>
;; Jesus E. <heckyel@hyperbola.info>
;;; 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 "<tab>") 'livie-next-video)
(define-key livie-mode-map (kbd "<backtab>") '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 "<return>") 'livie-watch-this-video)
(provide 'livie)
;;; livie.el ends here