;;; ol-elisp-symbol.el --- Links to Emacs-lisp symbols -*- lexical-binding: t; -*- ;; ;; Copyright 2007-2021 Free Software Foundation, Inc. ;; ;; Author: Bastien Guerry ;; Version: 0.2 ;; Keywords: org, remember, lisp ;; Homepage: https://git.sr.ht/~bzg/org-contrib ;; ;; This file is not part of GNU Emacs. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; ;; This program 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 General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; ;; Org-mode already lets you store/insert links to emacs-lisp files, ;; just like any other file. This package lets you precisely link to ;; any emacs-lisp symbol and access useful information about the symbol. ;; ;; Here is the list of available properties when linking from a elisp-symbol: ;; ;; :name The symbol's name. ;; :stype The symbol's type (commandp, function, etc.) ;; :def The function used to set the symbol's value (defun, etc.) ;; :keys The keys associated with the command. ;; :args The arguments of the function. ;; :docstring The docstring of the symbol. ;; :doc The first line of the dostring. ;; :comment A comment line just above the sexp, if any. ;; :fixme A FIXME comment line just above the sexp, if any. ;; ;; Let's say we have a defun like this one: ;; ;; ;; FIXME update docstring ;; (defun org-export-latex-lists () ;; "Convert lists to LaTeX." ;; (goto-char (point-min)) ;; (while (re-search-forward org-export-latex-list-beginning-re nil t) ;; (beginning-of-line) ;; (insert (org-list-to-latex (org-list-parse-list t)) "\n"))) ;; ;; And a remember template like: ;; ;; (setq org-remember-templates ;; '((?s "* DEBUG `%:name' (%:args)\n\n%?\n\nFixme: %:fixme\n \ ;; Doc: \"%:doc\"\n\n%a"))) ;; ;; Then M-x `org-remember' on this sexp will produce this buffer: ;; ;; ===================================================================== ;; * DEBUG `org-export-latex-lists' () ;; ;; <== point ;; ;; Fixme: update the docstring ;; Doc: "Convert lists to LaTeX." ;; ;; [[file:~/path/file.el::defun%20my-func][Function: my-func]] ;; ===================================================================== ;; ;; Put this file into your load-path and the following into your ~/.emacs: ;; (require 'org-elisp-symbol) ;;; Code: (provide 'ol-elisp-symbol) (require 'ol) (require 'org) (org-link-set-parameters "elisp-symbol" :follow #'org-elisp-symbol-open :store #'org-elisp-symbol-store-link) (defun org-elisp-symbol-open (symbol arg) (org-link-open-as-file symbol arg)) (defun org-elisp-symbol-store-link () "Store a link to an emacs-lisp elisp-symbol." (when (eq major-mode 'emacs-lisp-mode) (save-excursion (or (looking-at "^(") (beginning-of-defun)) (looking-at "^(\\([a-z]+\\) \\([^)\n ]+\\) ?\n?[ \t]*\\(?:(\\(.*\\))\\)?") (let* ((end (save-excursion (save-match-data (end-of-defun) (point)))) (def (match-string 1)) (name (match-string 2)) (sym-name (intern-soft name)) (stype (cond ((commandp sym-name) "Command") ((functionp sym-name) "Function") ((custom-variable-p sym-name) "User variable") ((string= def "defvar") "Variable") ((string= def "defmacro") "Macro") ((string= def "defun") "Function or command") (t "Symbol"))) (args (if (match-string 3) (mapconcat (lambda (a) (unless (string-match "^&" a) a)) (split-string (match-string 3)) " ") "no arg")) (docstring (cond ((functionp sym-name) (or (documentation sym-name) "[no documentation]")) ((string-match "[Vv]ariable" stype) (documentation-property sym-name 'variable-documentation)) (t "no documentation"))) (doc (and (string-match "^\\([^\n]+\\)$" docstring) (match-string 1 docstring))) (fixme (save-excursion (beginning-of-defun) (end-of-defun) (if (re-search-forward "^;+ ?FIXME[ :]*\\(.*\\)$" end t) (match-string 1) "nothing to fix"))) (comment (save-excursion (beginning-of-defun) (end-of-defun) (if (re-search-forward "^;;+ ?\\(.*\\)$" end t) (match-string 1) "no comment"))) keys keys-desc link description) (if (equal stype "Command") (setq keys (where-is-internal sym-name) keys-desc (if keys (mapconcat 'key-description keys " ") "none"))) (setq link (concat "file:" (abbreviate-file-name buffer-file-name) "::" def " " name)) (setq description (concat stype ": " name)) (org-link-store-props :type "elisp-symbol" :link link :description description :def def :name name :stype stype :args args :keys keys-desc :docstring docstring :doc doc :fixme fixme :comment comment))))) (provide 'org-elisp-symbol) ;;;;########################################################################## ;;;; User Options, Variables ;;;;########################################################################## ;;; ol-elisp-symbol.el ends here