org-eldoc.el 6.6 KB

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