blob: 27c23ce0d39bf8d5a817f273b33bc739f85bdc87 (
plain) (
tree)
|
|
;;; my-help.el -- Help related extensions for emacs core -*- lexical-binding: t -*-
;; Copyright (C) 2023 Free Software Foundation.
;; Author: Yuchen Pei <id@ypei.org>
;; Package-Requires: ((emacs "28.2"))
;; This file is part of dotfiles.
;; dotfiles is free software: you can redistribute it and/or modify it under
;; the terms of the GNU Affero General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; dotfiles is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
;; Public License for more details.
;; You should have received a copy of the GNU Affero General Public
;; License along with dotfiles. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Emacs help related extensions.
;;; Code:
;; find source of external command
(defun my-external-command-open-source (command)
(interactive
(list (completing-read
"Open source of command: "
(my-external-command-collection))))
(let ((subject
(cadr
(split-string (my-shell-command-output
(format "type %s" command))
" is "))))
(pcase subject
("a shell builtin" (error "%s is %s" command subject))
("a shell keyword" (error "%s is %s" command subject))
((guard (string-prefix-p "is aliased to " subject))
(substring subject (error "%s is %s" command subject)))
(_
(pcase-let
((`(,path ,type)
(split-string
(my-shell-command-output (format "file -Li %s" subject))
": ")))
(if (string-prefix-p "text/" type)
(progn
(message "Opening %s" path)
(find-file path))
(error "%s (%s) is not plaintext: %s" command path type)))))))
(defun my-external-command-collection ()
(mapcan
(lambda (dir)
(mapcar
(lambda (file)
(string-match "\\(?:.*\\)/\\(.*\\)" file)
(match-string 1 file))
(seq-filter
(lambda (file)
(and (not (file-directory-p file))
(file-executable-p file)))
(directory-files dir t "[^~#]$"))))
(seq-filter
'file-accessible-directory-p
(exec-path))))
(defun my-woman-man (arg)
(interactive "P")
(if arg (call-interactively 'man)
(call-interactively 'woman)))
(defun my-help-goto-symbol (symbol)
(interactive
;; copied from prompt code of help-describe-symbol
(let* ((v-or-f (symbol-at-point))
(found (if v-or-f (cl-some (lambda (x) (funcall (nth 1 x) v-or-f))
describe-symbol-backends)))
(v-or-f (if found v-or-f (function-called-at-point)))
(found (or found v-or-f))
(enable-recursive-minibuffers t)
(val (completing-read (format-prompt "Describe symbol"
(and found v-or-f))
#'help--symbol-completion-table
(lambda (vv)
(cl-some (lambda (x) (funcall (nth 1 x) vv))
describe-symbol-backends))
t nil nil
(if found (symbol-name v-or-f)))))
(list (if (equal val "")
(or v-or-f "") (intern val)))))
(help-do-xref nil #'describe-symbol (list symbol)))
(defun my-describe-local-variable (variable &optional buffer frame)
(interactive
(let ((v (variable-at-point))
(enable-recursive-minibuffers t)
(orig-buffer (current-buffer))
val)
(setq val (completing-read
(format-prompt "Describe variable" (and (symbolp v) v))
#'help--symbol-completion-table
(lambda (vv)
(and (local-variable-p vv)
(or (get vv 'variable-documentation)
(and (not (keywordp vv))
;; Since the variable may only exist in the
;; original buffer, we have to look for it
;; there.
(buffer-local-boundp vv orig-buffer)))))
t nil nil
(if (symbolp v) (symbol-name v))))
(list (if (equal val "")
v (intern val)))))
(describe-variable variable buffer frame))
(defun my-info-display-manual ()
(interactive)
(call-interactively 'info-display-manual)
(when (derived-mode-p 'Info-mode)
(rename-buffer
(generate-new-buffer-name
(format "*info %s*"
(file-name-sans-extension
(file-name-nondirectory Info-current-file)))))))
(defun my-describe-symbol-at-point ()
(interactive)
(describe-symbol (symbol-at-point)))
(provide 'my-help)
;;; my-help.el ends here
|