emacs-btap

Emacs library to browse thing at point
Log | Files | Refs

emacs-btap.el (5096B)


      1 ;;; -*- lexical-binding: t -*-
      2 ;;;
      3 ;;; emacs-btap.el
      4 ;;;
      5 ;;; Browse thing at point.
      6 ;;;
      7 ;;; Copyright (C) 2020 Tomas Hlavaty <tom at logand dot com>
      8 ;;;
      9 ;;; License: GPLv3 or later
     10 ;;;
     11 ;;; Download: git clone https://logand.com/git/emacs-btap.git
     12 ;;;
     13 ;;; Example configuration:
     14 ;;;
     15 ;;; (add-to-list 'load-path "~/git/emacs-btap")
     16 ;;; (require 'emacs-btap)
     17 ;;; (global-set-key "\M-f" 'btap)
     18 ;;;
     19 ;;; Example usage:
     20 ;;;
     21 ;;; M-x btap will browse the thing at point.
     22 ;;;
     23 ;;; Some variables can be customized in the btap group.
     24 ;;;
     25 ;;; To see a few examples, evaluate: (occur "example:")
     26 
     27 (require 'browse-url)
     28 (require 'cl-lib)
     29 (require 'ffap)
     30 (require 'thingatpt)
     31 
     32 (defcustom btap-try-functions '(
     33                                 ;; global
     34                                 btap-try-notmuch
     35                                 btap-try-man
     36                                 btap-try-url
     37                                 btap-try-file
     38                                 btap-try-wild-file
     39                                 btap-try-clhs
     40                                 btap-try-sbcl-bug
     41                                 ;; mode specific
     42                                 btap-try-cc-mode
     43                                 btap-try-lisp-mode
     44                                 ;; nothing matched
     45                                 btap-try-missing
     46                                 )
     47   "List of functions to try to handle btap action.
     48 Functions accept optional string argument and should return nil if not
     49 applicable for the given string.  If no string is given, the function
     50 should guess from the thing at point.  The first applicable function
     51 handles the btap action."
     52   :type '(repeat symbol)
     53   :group 'btap)
     54 
     55 (defvar btap--ffap-guesser-thunk)
     56 (defun btap-ffap-guesser ()
     57   (funcall btap--ffap-guesser-thunk))
     58 
     59 (defun btap-try-notmuch (&optional string)
     60   (when (fboundp 'notmuch-show)
     61     (let ((x (or string (btap-ffap-guesser))))
     62       (when (and x (string-match "^id:" x))
     63         (funcall 'notmuch-show x)
     64         x))))
     65 
     66 (defun btap-try-man (&optional string)
     67   (when browse-url-man-function
     68     (let ((x (or string (btap-ffap-guesser))))
     69       (when (and x (string-match "^man:" x))
     70         (funcall browse-url-man-function x)
     71         x))))
     72 ;; example: man:printf
     73 
     74 (defun btap-try-url (&optional string)
     75   (when ffap-url-fetcher
     76     (let ((x (or string (btap-ffap-guesser))))
     77       (when x
     78         (let ((url (ffap-url-p x)))
     79           (when url
     80             (let (current-prefix-arg)
     81               (funcall ffap-url-fetcher url)
     82               url)))))))
     83 ;; example: https://logand.com
     84 
     85 (defun btap-try-cc-mode (&optional string)
     86   (when (and (boundp 'c-buffer-is-cc-mode)
     87              c-buffer-is-cc-mode)
     88     (let ((x (or string (thing-at-point 'word t))))
     89       (when x
     90         ;; TODO includes e.g. limits.h
     91         (btap-try-man (concat "man:" x))))))
     92 
     93 (defun btap-try-file (&optional string)
     94   (when ffap-file-finder
     95     (let ((x (or string (btap-ffap-guesser))))
     96       (when x
     97         (let ((url (ffap-url-p x)))
     98           (unless url
     99             (when (file-exists-p x)
    100               (funcall ffap-file-finder (expand-file-name x))
    101               x)))))))
    102 ;; example: ~/.emacs
    103 ;; example: ~/.emacs.d
    104 
    105 (defun btap-try-wild-file (&optional string)
    106   (when (and ffap-dired-wildcards
    107              find-file-wildcards
    108              ffap-file-finder)
    109     (let ((x (or string (btap-ffap-guesser))))
    110       (when x
    111         (let ((url (ffap-url-p x)))
    112           (unless url
    113             (when (and (string-match ffap-dired-wildcards x)
    114                        ;; Check if it's find-file that supports wildcards arg
    115 	               (memq ffap-file-finder '(find-file find-alternate-file)))
    116               (funcall ffap-file-finder (expand-file-name x) t)
    117               x)))))))
    118 
    119 (defun btap-try-clhs (&optional string)
    120   (when (fboundp 'hyperspec-lookup)
    121     (let ((x (or string (btap-ffap-guesser))))
    122       (when (and x (string-match "^clhs:" x))
    123         (funcall 'hyperspec-lookup (substring x 5))
    124         x))))
    125 ;; example: clhs:delete-if
    126 
    127 (defun btap-try-lisp-mode (&optional string)
    128   (when (and (fboundp 'hyperspec-lookup)
    129              (eq major-mode 'lisp-mode))
    130     (let ((x (or string (thing-at-point 'word t)))) ;; TODO include - etc
    131       (when x
    132         (funcall 'hyperspec-lookup x)
    133         x))))
    134 
    135 (defun btap-try-sbcl-bug (&optional string)
    136   (let ((x (or string (thing-at-point 'filename t))))
    137     (when (and x (string-match "^lp#" x))
    138       (btap-try-url (concat "https://bugs.launchpad.net/bugs/" (substring x 3))))))
    139 ;; example: lp#1903901
    140 
    141 (defun btap-try-missing ()
    142   (signal 'btap-try-missing (list "Nothing at point to browse")))
    143 ;; example: /does-not-exist
    144 
    145 (defun btap--memoize-thunk (thunk)
    146   (let (z)
    147     (lambda ()
    148       (when thunk
    149         (setq z (funcall thunk)
    150               thunk nil))
    151       z)))
    152 
    153 (defun btap ()
    154   "Browse thing at point.  See also the variable `btap-try-functions'."
    155   (interactive)
    156   (let (z
    157         (btap--ffap-guesser-thunk (btap--memoize-thunk 'ffap-guesser))
    158         (x btap-try-functions))
    159     (while (and x (not (setq z (funcall (pop x))))))
    160     z))
    161 
    162 (provide 'emacs-btap)