Using Spookfox to scroll Firefox up and down from Emacs

| web, emacs

I open lots of pages in the process of making Emacs News. I like to open the pages in Mozilla Firefox, but I want the keyboard focus to stay with Emacs so that I can quickly categorize the links. I also sometimes want to scroll the page up or down. While reading the Reading, and not forgetting post, I came across Spookfox, which bridges Emacs and Firefox using an Firefox add-on and websockets. After I started spookfox and connected to it by clicking on the extension in Firefox, I was able to interact with it from Emacs Lisp. I feel a little nervous about it security-wise, but at least it's only listening on the local port. There might be another way to do it with the Marionette support in Firefox, but I haven't looked into it yet.

(use-package spookfox
  :quelpa (spookfox :fetcher github :repo "bitspook/spookfox"
                    :files ("lisp/*.el" "lisp/apps/*.el"))
  :when my-laptop-p
  :config
  (require 'spookfox-tabs)
  (require 'spookfox-org-tabs)
  (require 'spookfox-js-injection)
  (add-to-list 'spookfox-enabled-apps 'spookfox-tabs)
  (add-to-list 'spookfox-enabled-apps 'spookfox-org-tabs)
  (add-to-list 'spookfox-enabled-apps 'spookfox-js-injection)
  ;; (spookfox-init) ; don't automatically enable it; run (spookfox-init) to manually enable
  )

Anyway, this code seems to do the job of scrolling my Firefox window:

(defun my-spookfox-scroll-down ()
  (interactive)
  (spookfox-eval-js-in-active-tab "window.scrollBy(0, document.documentElement.clientHeight);"))

(defun my-spookfox-scroll-up ()
  (interactive)
  (spookfox-eval-js-in-active-tab "window.scrollBy(0, -document.documentElement.clientHeight);"))

(global-set-key (kbd "C-s-v") 'my-spookfox-scroll-down)
(global-set-key (kbd "C-s-S-v") 'my-spookfox-scroll-up)

This code opens a tab without switching keyboard focus away from Emacs:

(defun my-spookfox-background-tab (url &rest args)
  "Open URL as a background tab."
  (if spookfox--connected-clients
      (spookfox-tabs--request (cl-first spookfox--connected-clients) "OPEN_TAB" `(:url ,url))
    (browse-url url)))

My Emacs News code for processing my upvoted Reddit posts can automatically grab the links from Reddit link posts, but sometimes people post Reddit text or image posts and then include the link to the actual project in the post body or a comment instead.

(defun my-spookfox-get-links ()
  (seq-uniq
   (spookfox-eval-js-in-active-tab "[...(document.querySelector('[data-testid=post-container]')?.parentElement || document).querySelectorAll('a')].map(a => a.href).filter(a => a && !a.match(/redd\.?it/) && !a.match(window.location.host))" t)))
;;https://emacs.stackexchange.com/questions/41801/how-to-stop-completing-read-ivy-completing-read-from-sorting
(defun my-presorted-completion-table (completions)
  (lambda (string pred action)
    (if (eq action 'metadata)
        '(metadata
         (cycle-sort-function . identity)
         (display-sort-function . identity))
      (complete-with-action action completions string pred))))

(defun my-spookfox-insert-link-from-page ()
  (interactive)
  (let* ((links (my-spookfox-get-links))
         (link (completing-read
                "Link: "
                (my-presorted-completion-table
                 links))))
    (insert (org-link-make-string link (my-page-title link)))))
This is part of my Emacs configuration.
You can comment with Disqus or you can e-mail me at sacha@sachachua.com.