;;; +link-hint.el -*- lexical-binding: t; -*- ;;; Code: (require 'cl-lib) (require 'link-hint) (defgroup +link-hint nil "Extra customizations for `link-hint'." :group 'link-hint) (defcustom +link-hint-open-secondary-types '(gnus-w3m-image-url gnus-w3m-url markdown-link mu4e-attachment mu4e-url notmuch-hello nov-link org-link shr-url text-url w3m-link w3m-message-link) "Link types to define `:open-secondary' for.") (defvar +link-hint-map (make-sparse-keymap) "Keymap for `link-hint' functionality.") (cl-defmacro +link-hint-define-keyword (keyword handler docstring &optional (types 'link-hint-types) &rest rest &key multiple &allow-other-keys) "Set up a `link-hint' KEYWORD, with optional TYPES. If TYPES is not present, use `link-hint-types'. KEYWORD defines the link-hint type. It will be used to create a function for opening links of the form \"link-hint-openKEYWORD\". HANDLER is the function to open a link with. DOCSTRING is the macro's documentation. Keyword arguments are passed to `link-hint-define-type' prefixed with the KEYWORD." (declare (indent 2) (doc-string 3)) (let ((types (symbol-value types)) (func-sym (intern (format "+link-hint-open%s" keyword))) (mult-sym (intern (format "%s-multiple" keyword))) (expr)) ;; Define the type (push `(dolist (type ',types) (link-hint-define-type type ,keyword ,handler ,@(mapcar (lambda (el) (if (eq el :multiple) mult-sym el)) rest))) expr) ;; Define an opener (push `(defun ,func-sym () ,(format "%s\n\nDefined by `+link-hint-define'." docstring) (interactive) (avy-with link-hint-open-link (link-hint--one ,keyword))) expr) ;; Handle `:multiple' (when multiple (push `(defun ,(intern (format "+link-hint-open-multiple%s" keyword)) () ,(format "Open multiple links with `%s'.\n\nDefined by `+link-hint-define'." func-sym) (avy-with link-hint-open-multiple-links (link-hint--multiple ,keyword))) expr) (push `(defun ,(intern (format "+link-hint-open-all%s" keyword)) () ,(format "Open all visible links with `%s'.\n\nDefined by `+link-hint-define'." func-sym) (avy-with link-hint-open-all-links (link-hint--all ,keyword))) expr)) ;; Return the built expression `(progn ,@(nreverse expr)))) (+link-hint-define-keyword :secondary browse-url-secondary-browser-function "Open a link in the secondary browser." +link-hint-open-secondary-types :multiple t) (defun +link-hint-open-secondary-setup (&optional types) "Define the `:open-secondary' link-hint type for TYPES. If TYPES is nil, define it for `+link-hint-open-secondary-types'." (dolist (type (or types +link-hint-open-secondary-types)) (link-hint-define-type type :open-secondary browse-url-secondary-browser-function :open-secondary-multiple t))) (defun +link-hint-open-secondary () "Open a link in the secondary browser." (interactive) (avy-with link-hint-open-link (link-hint--one :open-secondary))) (defun +link-hint-open-chrome-setup (&optional types) "Define the `:open-chrome' link-hint type for TYPES. If TYPES is nil, define it for `+link-hint-open-secondary-types'." (dolist (type (or types +link-hint-open-secondary-types)) (link-hint-define-type type :open-chrome #'browse-url-chrome :open-chrome-multiple t))) (defun +link-hint-open-chrome () "Open a link with chrome." (interactive) (avy-with link-hint-open-link (link-hint--one :open-chrome))) ;; (cl-defmacro +link-hint-add-type (keyword ) ;; "Define link-hint type KEYWORD to operate on TYPES. ;; If TYPES is nil or absent, define KEYWORD for all ;; `link-hint-types'." ;; (let (forms) ;; (dolist (type (or types link-hint-types)) ;; (push `(link-hint-define-type ,type ,keyword ,function) forms)) ;; (push `(defun ,(intern (format "+link-hint%s" ,keyword)) ;; )))) (defun +link-hint-open-link (prefix) "Open a link. Without a PREFIX, open using `browse-url-browser-function'; with a PREFIX, use `browse-url-secondary-browser-function'." (interactive "P") (avy-with link-hint-open-link (link-hint--one (if prefix :open-secondary :open)))) (defun +link-hint-open-multiple-links (prefix) "Open multiple links. Without a PREFIX, open using `browse-url-browser-function'; with a PREFIX, use `browse-url-secondary-browser-function'." (interactive "P") (avy-with link-hint-open-multiple-links (link-hint--one (if prefix :open-secondary :open)))) (defun +link-hint-open-all-links (prefix) "Open all visible links. Without a PREFIX, open using `browse-url-browser-function'; with a PREFIX, use `browse-url-secondary-browser-function'." (interactive "P") (avy-with link-hint-open-all-links (link-hint--one (if prefix :open-secondary :open)))) ;;; Pocket-reader.el integration (defun +link-hint-pocket-add-setup (&optional types) "Define the `:pocket-add' link-hint type for TYPES. If TYPES is nil, define it for `link-hint-types'." (dolist (type (or types link-hint-types)) (link-hint-define-type type :pocket-add #'pocket-reader-generic-add-link :pocket-add-multiple t))) (defun +link-hint-pocket-add () "Add a link to the Pocket reader." (interactive) (avy-with link-hint-open-link (link-hint--one :pocket-add))) (provide '+link-hint) ;;; +link-hint.el ends here