From 25b412d30728c07fc016993fa39264a93cb45e41 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann <10477760+JadedCtrl@users.noreply.github.com> Date: Fri, 31 May 2024 21:34:47 -0500 Subject: [PATCH] Accept HTML from stdin, instead of requiring a file This is much more handy (not to mention UNIX-y)! --- src/mirror-img.lisp | 9 +++++---- src/unix.lisp | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/mirror-img.lisp b/src/mirror-img.lisp index f31c3e3..2f4f67d 100644 --- a/src/mirror-img.lisp +++ b/src/mirror-img.lisp @@ -28,16 +28,17 @@ ;;; Mirror-img ;;; ———————————————————————————————————————— -;; pathname pathname list → string -(defun mirror-img (html-file download-dir &key (url-dir download-dir) (tags *default-tags*)) - "Attempt to mirror all remote HREF/SRC URLs of an HTML file’s tags, +;; pathname/input-stream pathname list → string +(defun mirror-img (html-source download-dir &key (url-dir download-dir) (tags *default-tags*)) + "Attempt to mirror all remote HREF/SRC URLs of an HTML document’s tags, downloading them to DOWNLOAD-DIR. For each remote URL that could be successfuly mirrored, the remote URLs will be replaced with the local version. The URL used will will be BASE-DIR plus the filename, where BASE-DIR defaults to DOWNLOAD-DIR. +HTML-SOURCE, the document, can be either a pathname or an input stream. Returns a string of the modified page’s HTML." (let* ((dom - (lquery:$ (lquery:initialize html-file))) + (lquery:$ (lquery:initialize html-source))) (url→pathname-alist (mirror-linked-urls dom :tags tags :download-dir download-dir)) (url→relative-url-alist diff --git a/src/unix.lisp b/src/unix.lisp index 3814273..e554044 100644 --- a/src/unix.lisp +++ b/src/unix.lisp @@ -38,22 +38,22 @@ ;;; Mirror-img (UNIX) ;;; ———————————————————————————————————————— -;; NIL → NIL +;; nil → nil (defun main () "Actual invocation of the program. This is what you should set as :toplevel." (error-print 99 "" (multiple-value-bind (opts free) (opts:get-opts) (when-opt opts :help (help)) - (let* ((input-file (car free)) + (let* ((input-stream (choose-input-stream (car free))) (url-base (or (getf opts :url-base) (getf opts :download-dir) "mirror/")) (download-dir (or (getf opts :download-dir) url-base))) - (when (not input-file) - (error-print 1 "No HTML file provided. Use --help for more information.")) + (when (not input-stream) + (error-print 1 "No HTML file provided. See --help for more information.")) (format 't (mirror-img:mirror-img - (pathname input-file) + input-stream download-dir :url-dir url-base)))))) @@ -77,8 +77,11 @@ ;; number stream → nil (defun help (&optional (exit-code 0) (stream *standard-output*)) "Prints help message and dies." - (unix-opts:describe :prefix "usage: mirror-img [-h] [-d DIR] [-b BASE] HTML_FILE" - :stream stream) + (unix-opts:describe + :prefix (format nil "~A~%~A" + "usage: mirror-img [-h] [-d DIR] [-b BASE] HTML_FILE" + " mirror-img [-h] [-d DIR] [-b BASE]") + :stream stream) (unix-opts:exit exit-code)) ;; number string condition → nil @@ -86,3 +89,25 @@ "Print an error-message and exit." (format *error-output* "~@[~A~%~]~@[~A~%~]" message condition) (unix-opts:exit exit-code)) + + + +;;; Input +;;; ———————————————————————————————————————— +;; list → stream +(defun choose-input-stream (file-arg) + "Select an input stream, between a file passed in free-args or stdin." + (let* ((input-file file-arg) + (input-file-p (ignore-errors (probe-file input-file))) + (stdinp (listen *standard-input*))) + (cond ((or stdinp (equal input-file "-")) ; “-” is commonly used to mean stdin. + *standard-input*) + (input-file-p (open input-file)) + ((and input-file (not input-file-p)) + (error-print 2 "File “~A” does not exist." input-file)) + ('T + ;; Warn the user, if we’re reading from stdin (without immediate input). + ;; This means they might’ve made a massive typo. ^ ^ + (format *error-output* "Reading from standard input. Hit ^D (CTRL+D) when done.~%") + (format *error-output* "Run with --help argument for details.~%") + *standard-input*))))