dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

org-eldoc.el (8024B)


      1 ;;; org-eldoc.el --- display org header and src block info using eldoc -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (c) 2014-2021 Free Software Foundation, Inc.
      4 
      5 ;; Author: Łukasz Gruner <lukasz@gruner.lu>
      6 ;; Maintainer: Łukasz Gruner <lukasz@gruner.lu>
      7 ;; Version: 6
      8 ;; Package-Requires: ((org "8"))
      9 ;; Homepage: https://git.sr.ht/~bzg/org-contrib
     10 ;; Created: 25/05/2014
     11 ;; Keywords: eldoc, outline, breadcrumb, org, babel, minibuffer
     12 
     13 ;; This file is not part of Emacs.
     14 
     15 ;; GNU Emacs is free software: you can redistribute it and/or modify
     16 ;; it under the terms of the GNU General Public License as published by
     17 ;; the Free Software Foundation, either version 3 of the License, or
     18 ;; (at your option) any later version.
     19 
     20 ;; GNU Emacs is distributed in the hope that it will be useful,
     21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     23 ;; GNU General Public License for more details.
     24 
     25 ;; You should have received a copy of the GNU General Public License
     26 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
     27 
     28 ;;; Commentary:
     29 
     30 ;;; Changelog:
     31 
     32 ;; As of 01/11/14 switching license to GPL3 to allow submission to org-mode.
     33 ;; 08/11/14 switch code to automatically define eldoc-documentation-function, but don't autostart eldoc-mode.
     34 
     35 ;;; Code:
     36 
     37 (require 'org)
     38 (require 'ob-core)
     39 (require 'eldoc)
     40 
     41 (declare-function org-element-at-point "org-element" ())
     42 (declare-function org-element-property "org-element" (property element))
     43 (declare-function org-element-type "org-element" (element))
     44 
     45 (defgroup org-eldoc nil "" :group 'org)
     46 
     47 (defcustom org-eldoc-breadcrumb-separator "/"
     48   "Breadcrumb separator."
     49   :group 'org-eldoc
     50   :type 'string)
     51 
     52 (defcustom org-eldoc-test-buffer-name " *Org-eldoc test buffer*"
     53   "Name of the buffer used while testing for mode-local variable values."
     54   :group 'org-eldoc
     55   :type 'string)
     56 
     57 (eldoc-add-command 'org-self-insert-command)
     58 
     59 (defun org-eldoc-get-breadcrumb ()
     60   "Return breadcrumb if on a headline or nil."
     61   (let ((case-fold-search t) cur)
     62     (save-excursion
     63       (beginning-of-line)
     64       (save-match-data
     65         (when (looking-at org-complex-heading-regexp)
     66           (setq cur (match-string 4))
     67           (org-format-outline-path
     68            (append (org-get-outline-path) (list cur))
     69            (frame-width) "" org-eldoc-breadcrumb-separator))))))
     70 
     71 (defun org-eldoc-get-src-header ()
     72   "Returns lang and list of header properties if on src definition line and nil otherwise."
     73   (let ((case-fold-search t) info lang hdr-args)
     74     (save-excursion
     75       (beginning-of-line)
     76       (save-match-data
     77         (when (looking-at "^[ \t]*#\\+\\(begin\\|end\\)_src")
     78           (setq info (org-babel-get-src-block-info 'light)
     79                 lang (propertize (or (nth 0 info) "no lang") 'face 'font-lock-string-face)
     80                 hdr-args (nth 2 info))
     81           (concat
     82            lang
     83            ": "
     84            (mapconcat
     85             (lambda (elem)
     86               (when-let* ((val (and (cdr elem)
     87                                     (format "%s" (cdr elem))))
     88                           (_ (not (string-empty-p val))))
     89                 (concat
     90                  (propertize (symbol-name (car elem)) 'face 'org-list-dt)
     91                  " "
     92                  (propertize val 'face 'org-verbatim)
     93                  " ")))
     94             hdr-args " ")))))))
     95 
     96 (defun org-eldoc-get-src-lang ()
     97   "Return value of lang for the current block if in block body and nil otherwise."
     98   (let ((element (save-match-data (org-element-at-point))))
     99     (and (eq (org-element-type element) 'src-block)
    100 	 (>= (line-beginning-position)
    101 	     (org-element-property :post-affiliated element))
    102 	 (<=
    103 	  (line-end-position)
    104 	  (org-with-wide-buffer
    105 	   (goto-char (org-element-property :end element))
    106 	   (skip-chars-backward " \t\n")
    107 	   (line-end-position)))
    108 	 (org-element-property :language element))))
    109 
    110 (defvar org-eldoc-local-functions-cache (make-hash-table :size 40 :test 'equal)
    111   "Cache of major-mode's eldoc-documentation-functions,
    112  used by \\[org-eldoc-get-mode-local-documentation-function].")
    113 
    114 (defun org-eldoc-get-mode-local-documentation-function (lang)
    115   "Check if LANG-mode sets eldoc-documentation-function and return its value."
    116   (let ((cached-func (gethash lang org-eldoc-local-functions-cache 'empty))
    117         (mode-func (org-src-get-lang-mode lang))
    118         doc-func)
    119     (if (eq 'empty cached-func)
    120         (when (fboundp mode-func)
    121 	  (with-temp-buffer
    122 	    (funcall mode-func)
    123 	    (setq doc-func (if (boundp 'eldoc-documentation-functions)
    124 			       (let ((doc-funs eldoc-documentation-functions))
    125 				 (lambda (callback)
    126 				   (let ((eldoc-documentation-functions doc-funs))
    127 				     (run-hook-with-args-until-success
    128 				      'eldoc-documentation-functions
    129 				      callback))))
    130 			     (and eldoc-documentation-function
    131 				  (symbol-value 'eldoc-documentation-function))))
    132 	    (puthash lang doc-func org-eldoc-local-functions-cache))
    133           doc-func)
    134       cached-func)))
    135 
    136 (declare-function c-eldoc-print-current-symbol-info "c-eldoc" ())
    137 (declare-function css-eldoc-function "css-eldoc" ())
    138 (declare-function php-eldoc-function "php-eldoc" ())
    139 (declare-function go-eldoc--documentation-function "go-eldoc" ())
    140 
    141 (defun org-eldoc-documentation-function (&rest args)
    142   "Return breadcrumbs when on a headline, args for src block header-line,
    143   calls other documentation functions depending on lang when inside src body."
    144   (or
    145    (org-eldoc-get-breadcrumb)
    146    (org-eldoc-get-src-header)
    147    (let ((lang (org-eldoc-get-src-lang)))
    148      (cond
    149       ((string= lang "org")       ;Prevent inf-loop for Org src blocks
    150        nil)
    151       ((or
    152         (string= lang "emacs-lisp")
    153         (string= lang "elisp"))
    154        (cond ((and (boundp 'eldoc-documentation-functions) ; Emacs>=28
    155                    (fboundp 'elisp-eldoc-var-docstring)
    156                    (fboundp 'elisp-eldoc-funcall))
    157               (let ((eldoc-documentation-functions
    158                      '(elisp-eldoc-var-docstring elisp-eldoc-funcall)))
    159                 (eldoc-print-current-symbol-info)))
    160              ((fboundp 'elisp-eldoc-documentation-function)
    161               (elisp-eldoc-documentation-function))
    162              (t            ; Emacs<25
    163               (let (eldoc-documentation-function)
    164                 (eldoc-print-current-symbol-info)))))
    165       ((or
    166         (string= lang "c") ;; https://github.com/nflath/c-eldoc
    167         (string= lang "C"))
    168        (when (require 'c-eldoc nil t)
    169          (c-eldoc-print-current-symbol-info)))
    170       ;; https://github.com/zenozeng/css-eldoc
    171       ((string= lang "css") (when (require 'css-eldoc nil t)
    172                               (css-eldoc-function)))
    173       ;; https://github.com/zenozeng/php-eldoc
    174       ((string= lang "php") (when (require 'php-eldoc nil t)
    175                               (php-eldoc-function)))
    176       ((or
    177         (string= lang "go")
    178         (string= lang "golang"))
    179        (when (require 'go-eldoc nil t)
    180          (go-eldoc--documentation-function)))
    181       (t
    182        (let ((doc-fun (org-eldoc-get-mode-local-documentation-function lang))
    183              (callback (car args)))
    184          (when (functionp doc-fun)
    185            (if (functionp callback)
    186                (funcall doc-fun callback)
    187              (funcall doc-fun)))))))))
    188 
    189 ;;;###autoload
    190 (defun org-eldoc-load ()
    191   "Set up org-eldoc documentation function."
    192   (interactive)
    193   ;; This approach is taken from python.el.
    194   (with-no-warnings
    195     (cond
    196      ((null eldoc-documentation-function) ; Emacs<25
    197       (setq-local eldoc-documentation-function
    198 		  #'org-eldoc-documentation-function))
    199      ((boundp 'eldoc-documentation-functions) ; Emacs>=28
    200       (add-hook 'eldoc-documentation-functions
    201 		#'org-eldoc-documentation-function nil t))
    202      (t
    203       (add-function :before-until (local 'eldoc-documentation-function)
    204 		    #'org-eldoc-documentation-function)))))
    205 
    206 ;;;###autoload
    207 (add-hook 'org-mode-hook #'org-eldoc-load)
    208 
    209 (provide 'org-eldoc)
    210 
    211 ;; -*- coding: utf-8-emacs; -*-
    212 
    213 ;;; org-eldoc.el ends here