;;; -*- lexical-binding: t; -*- ;;; Commentary: ;;; Code: (require 'fill-column) (require 'transient) (defconst bd/bookmarks nil) (defconst bd/browse-engine-list '(("ddg" . ("https://www.duckduckgo.com/?q=" 3)) ("web" . ("" 3)) ("wkpa" . ("https://en.wikipedia.org/w/index.php?search=" 3)) ("inv" . ("https://yewtu.be/search?q=" 0)) ("ud" . ("https://www.urbandictionary.com/define.php?term=" 2)) ("arch" . ("https://wiki.archlinux.org/index.php?title=Special%3ASearch&search=" 2)))) (defun bd/browse--engine-candidates () (mapcar #'car bd/browse-engine-list)) (defun bd/browse (url &optional pref &rest _) "Given PREF, launches URL in one of librewolf, torbrowser, icecat, or eww." (interactive) (pcase pref (0 (eww url)) (1 (start-process "torbrowser" nil "torbrowser" "--new-window" url)) (2 (start-process "icecat" nil "icecat" "--new-window" url)) (_ (start-process "librewolf" nil "librewolf" "--new-window" url)))) (setopt browse-url-browser-function 'bd/browse) (transient-define-argument bd/browse--engines () "Toggles which search engine to use." :description "engine" :key "C-n" :class 'transient-option :unsavable t :allow-empty nil :always-read t :argument "candidate=" :init-value (lambda (obj) (oset obj value (car (bd/browse--engine-candidates)))) :choices (bd/browse--engine-candidates)) (transient-define-suffix bd/browse--search (i) :description "search" :key "s" (interactive "sstring: ") (let ((engine (cdr (assoc (transient-arg-value "candidate=" (transient-args 'bd/browse-dispatcher)) bd/browse-engine-list)))) (browse-url (concat (car engine) i) (cadr engine)))) (transient-define-suffix bd/browse--bookmark () :description "bookmarks" :key "b" (interactive) (let ((choice (completing-read "goto: " (mapcar #'car bd/bookmarks)))) (apply #'bd/browse (cdr (assoc choice bd/bookmarks))))) (transient-define-prefix bd/browse-dispatcher () ["Dispatcher > Browse\n" [(bd/browse--engines) "" (bd/browse--search) (bd/browse--bookmark)]]) (defun rip (url) "Play URL (or search string) in mpv." (interactive "sURL or search string: ") (message "Ludu %s" url) (start-process "rip" nil "mpv" "--force-window=yes" (concat (if (string-match "https://.*" url) "ytdl://" "ytdl://ytsearch:") url))) (setopt browse-url-handlers `((,(regexp-opt '("youtube.com" "youtu.be" "deezer.page")) . (lambda (url &rest _) (rip url)))) url-privacy-level '(email os emacs lastloc cookies)) (use-package shr :defer t :config (setopt shr-use-fonts t shr-cookie-policy nil shr-max-width 85)) (use-package elpher :bind (:map elpher-mode-map ("l" . #'elpher-back) ("d" . #'elpher-download) ("w" . #'elpher-copy-current-url) ("A" . #'elpher-copy-link-url) ("E" . #'elpher-bookmark-current) ("TAB" . #'elpher-next-link) ("g" . #'elpher-reload) ("G" . #'elpher-go)) :config (defun bd/elpher (original url &optional new-window) "Handle gemini links." (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url) (elpher-go url)) (t (funcall original url new-window)))) (advice-add 'eww :around 'bd/elpher) (setopt elpher-default-url-type "gemini" elpher-connection-timeout 120 elpher-gemini-max-fill-width 85 elpher-use-emacs-bookmark-menu t)) (use-package eww :hook ((eww-after-render . (lambda () (setq-local fill-column-desired-width 90) (fill-column-mode)))) :config (setopt eww-search-prefix "https://duckduckgo.com/html/?q=" eww-auto-rename-buffer 'title eww-use-browse-url (regexp-opt '("mailto:" "youtube.com" "youtu.be")))) (use-package apropos :bind (("C-h a" . selector-apropos))) (provide 'bd--browse) ;;; bd--browse.el ends here