plumb.el (7073B)
1 ;;; plumb.el --- Interactively select how to use a URL -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2020 Jamie Beardslee 4 5 ;; Author: Jamie Beardslee <jdb@jamzattack.xyz> 6 ;; URL: https://git.jamzattack.xyz/plumb 7 ;; Keywords: convenience 8 ;; Package-Requires: ((emacs "26.1")) 9 ;; Version: 2020.11.17 10 11 ;; This file is not part of GNU Emacs. 12 13 ;; This program is free software; you can redistribute it and/or modify 14 ;; it under the terms of the GNU General Public License as published by 15 ;; the Free Software Foundation, either version 3 of the License, or 16 ;; (at your option) any later version. 17 18 ;; This program is distributed in the hope that it will be useful, 19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 ;; GNU General Public License for more details. 22 23 ;; You should have received a copy of the GNU General Public License 24 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 25 26 ;;; Commentary: 27 28 ;; This package defines a few functions to handle a URL. The main 29 ;; entry-point `plumb' prompts for an action to run on the URL at 30 ;; point. 31 32 ;;; Code: 33 34 (require 'url) 35 (require 'pcase) 36 (require 'thingatpt) 37 (require 'shr) 38 39 (defgroup plumb () 40 "URL Menu." 41 :link '(url-link "https://git.jamzattack.xyz/plumb") 42 :group 'comm) 43 44 (defcustom plumb-audio-directory "~/Music/" 45 "The directory in which to download music using `plumb'." 46 :type 'directory 47 :group 'plumb) 48 49 (defcustom plumb-video-directory "~/Videos/" 50 "The directory in which to download videos using `plumb'." 51 :type 'directory 52 :group 'plumb) 53 54 (defcustom plumb-image-directory "~/Pictures/" 55 "The directory in which do download images using `plumb'." 56 :type 'directory 57 :group 'plumb) 58 59 (defcustom plumb-pdf-directory "~/Documents/" 60 "The directory in which do download pdfs using `plumb'." 61 :type 'directory 62 :group 'plumb) 63 64 (defcustom plumb-mpv-default-flags 65 '("--ytdl-format=22,best" 66 "--ytdl-raw-options=all-subs=" 67 "--speed=1.30") 68 "The default flags to use for mpv when calling `plumb-stream'. 69 You can choose different flags by passing a prefix argument to 70 `plumb-stream'." 71 :type '(repeat string) 72 :group 'plumb) 73 74 ;;;###autoload 75 (defun plumb-stream (url &optional flags) 76 "Plays video with mpv, provided URL is supported by youtube-dl. 77 Optional argument FLAGS sets mpv flags; interactively, a prefix 78 arg prompts for these flags." 79 (interactive (list 80 (plumb-get-url "Stream video: ") 81 (when current-prefix-arg 82 (read-string "mpv flags: ")))) 83 (let ((flags 84 (if (stringp flags) 85 (split-string flags " ") 86 plumb-mpv-default-flags))) 87 (eval 88 `(start-process "mpv stream" ,(format " *mpv stream %s*" url) 89 "mpv" 90 ,@flags 91 ,url))) 92 (message "%s is being streamed" url)) 93 94 ;;;###autoload 95 (defun plumb-download-video (url &optional directory) 96 "Download the video of URL using youtube-dl. 97 With prefix arg DIRECTORY, specify a download directory." 98 (interactive (list 99 (plumb-get-url "Download video: ") 100 (when current-prefix-arg 101 (read-directory-name "Download video where? " 102 plumb-video-directory)))) 103 (let ((default-directory (or directory plumb-video-directory))) 104 (start-process "youtube-dl download" " *youtube-dl download*" 105 "youtube-dl" 106 "--all-subs" 107 "--format=22,best" 108 "--add-metadata" 109 "--output=%(title)s.%(ext)s" 110 url)) 111 (message "%s downloaded in %s" url (or directory plumb-video-directory))) 112 113 ;;;###autoload 114 (defun plumb-audio (url &optional directory) 115 "Downloads the audio of URL using youtube-dl. 116 With prefix arg DIRECTORY, specify a download directory." 117 (interactive (list 118 (plumb-get-url "Download audio: ") 119 (when current-prefix-arg 120 (read-directory-name "Download audio where? " 121 plumb-audio-directory)))) 122 (let ((default-directory (or directory plumb-audio-directory))) 123 (start-process "youtube-dl audio" " *youtube-dl audio*" 124 "youtube-dl" 125 "--extract-audio" 126 "--add-metadata" 127 "--output=%(title)s.%(ext)s" 128 url)) 129 (message "%s downloaded in %s" url (or directory plumb-audio-directory))) 130 131 (defun plumb-save-to-register (url) 132 "Copies URL into a register." 133 (set-register 134 (register-read-with-preview "Copy URL to register: ") 135 url)) 136 137 (defun plumb-download-and-view (url &optional directory) 138 "Download URL in either DIRECTORY or ~/Downloads, and then open it. 139 Used by `plumb-image' and `plumb-pdf'." 140 (let* ((file (expand-file-name 141 (file-name-nondirectory url) 142 (or directory "~/Downloads")))) 143 (url-retrieve url 144 (lambda (_status) 145 (goto-char (point-min)) 146 (re-search-forward "\r?\n\r?\n") 147 (write-region (point) (point-max) file) 148 (find-file file))) 149 file)) 150 151 (defun plumb-plain (url) 152 "Download and open URL directly. This should work with any 153 filetype in `auto-mode-alist'." 154 (plumb-download-and-view url)) 155 156 (defun plumb-image (url) 157 "View URL as an image within Emacs." 158 (plumb-download-and-view url plumb-image-directory)) 159 160 (defun plumb-pdf (url) 161 "View URL as a pdf within Emacs." 162 (plumb-download-and-view url plumb-pdf-directory)) 163 164 (defun plumb-view-as-org (url) 165 "View URL in org-mode. Requires `org-web-tools'." 166 (unless (fboundp 'org-web-tools-read-url-as-org) 167 (user-error "The package `org-web-tools' is not installed")) 168 (org-web-tools-read-url-as-org url)) 169 170 (defun plumb-read (prompt) 171 "Reads input for `plumb'" 172 (completing-read (concat prompt " : ") 173 '("Save to register" 174 "eww" 175 "external browser" 176 "View as image" 177 "Stream" 178 "View in org-mode" 179 "Download and open" 180 "Download video" 181 "Download audio" 182 "View as pdf"))) 183 184 (defun plumb-get-url (&optional prompt) 185 "Get URL at point or from minibuffer" 186 (or (get-char-property (point) 'bug-reference-url) 187 (shr-url-at-point nil) 188 (thing-at-point 'url t) 189 (and (derived-mode-p 'org-mode) 190 (eq 'org-link (get-text-property (point) 'face)) 191 (let ((link 192 (replace-regexp-in-string 193 "\\`LINK: " "" 194 (get-text-property (point) 'help-echo)))) 195 (when (string-match-p (regexp-opt thing-at-point-uri-schemes) link) 196 link))) 197 (read-string (or prompt 198 "URL: ")))) 199 200 ;;;###autoload 201 (defun plumb (url) 202 "Select a way to use a URL" 203 (interactive (list (plumb-get-url))) 204 (let ((choice (plumb-read url))) 205 (pcase choice 206 ("Save to register" 207 (plumb-save-to-register url)) 208 ("eww" 209 (eww url)) 210 ("external browser" 211 (eww-browse-with-external-browser url)) 212 ("View as image" 213 (plumb-image url)) 214 ("View as pdf" 215 (plumb-pdf url)) 216 ("View in org-mode" 217 (plumb-view-as-org url)) 218 ("Download and open" 219 (plumb-plain url)) 220 ("Stream" 221 (plumb-stream url)) 222 ("Download video" 223 (plumb-download-video url)) 224 ("Download audio" 225 (plumb-audio url))))) 226 227 (provide 'plumb) 228 ;;; plumb.el ends here