1. Jon Waltman
  2. pydoc-info

Source

pydoc-info / pydoc-info.el

;;; pydoc-info.el --- Search and browse the Python documentation in Info

;; Copyright (C) 2011  Jonathan Waltman

;; Author: Jonathan Waltman <jonathan.waltman@gmail.com>
;; Keywords:

;; 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 of the License, 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 this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:
;; This package provides routines to better search and browse the
;; Python documentation in Info.
;;
;;; Features:
;; - Enable `info-lookup-symbol' to work with the new Python docs
;; - Improve browsing of Python Info docs by hiding *note: references.

;;; Install:
;; To use this package, you will need to have a recent version of the
;; Python documentation in the Info format on your machine.  It can be
;; downloaded at:
;;
;; https://bitbucket.org/jonwaltman/pydoc-info/downloads/python.info.gz
;;
;; Then add this file to your load-path and put the following
;; expression into your ~/.emacs.d/init.el.
;;
;;     (require 'pydoc-info)

;;; Usage:
;;   C-h S : info-lookup-symbol

;;; Code:

(require 'python)
(require 'info-look)

(defcustom pydoc-info-hide-note-references t
  "*Non-nil if note references should be hidden in Python Info
documents."
  :group 'pydoc-info)

;; Is there a better way to do this?
(defadvice info-insert-file-contents (after
                                      pydoc-info-info-insert-file-contents
                                      activate)
  "Hack to make `Info-hide-note-references' buffer-local and
automatically set to `hide' iff it can be determined that this
file was created from a Texinfo file generated by Docutils or
Sphinx.

This is only performed if `pydoc-info-hide-note-references' is
non-nil."
  (when pydoc-info-hide-note-references
    (set (make-local-variable 'Info-hide-note-references)
         (default-value 'Info-hide-note-references))
    (save-excursion
      (save-restriction
        (widen) (goto-char (point-min))
        (when (re-search-forward
               "^Generated by \\(Sphinx\\|Docutils\\)"
               (save-excursion (search-forward "\x1f" nil t)) t)
          (set (make-local-variable 'Info-hide-note-references)
               'hide))))))

;; This replaces the Info-look support in `python.el' which is based
;; on the old Python docs and no longer works.
(info-lookup-add-help
 :mode 'python-mode
 :parse-rule 'pydoc-info-python-symbol-at-point
 :doc-spec
 '(("(python)Python Module Index" pydoc-info-lookup-transform-entry)
   ("(python)Index" pydoc-info-lookup-transform-entry)))

(defun pydoc-info-python-symbol-at-point ()
  (with-syntax-table python-dotty-syntax-table
    (current-word)))

(defun pydoc-info-lookup-transform-entry (item)
  "Transform a Python index entry to a help item."
  (let* ((py-re "\\([[:alnum:]_.]+\\)(?)?"))
    (cond
     ;; keyword; foo --> foo
     ;; statement; foo --> foo
     ((string-match (concat "\\`\\(keyword\\|statement\\);? " py-re) item)
      (replace-regexp-in-string " " "." (match-string 2 item)))

     ;; foo (built-in ...) --> foo
     ((string-match (concat "\\`" py-re " (built-in .+)") item)
      (replace-regexp-in-string " " "." (match-string 1 item)))

     ;; foo.bar (module) --> foo.bar
     ((string-match (concat "\\`" py-re " (module)") item)
      (replace-regexp-in-string " " "." (match-string 1 item)))

     ;; baz (in module foo.bar) --> foo.bar.baz
     ((string-match (concat "\\`" py-re " (in module \\(.+\\))") item)
      (replace-regexp-in-string " " "." (concat (match-string 2 item) " "
                                                (match-string 1 item))))
     ;; Bar (class in foo.bar) --> foo.bar.Bar
     ((string-match (concat "\\`" py-re " (class in \\(.+\\))") item)
      (replace-regexp-in-string " " "." (concat (match-string 2 item) " "
                                                (match-string 1 item))))
     ;; bar (foo.Foo method) --> foo.Foo.bar
     ((string-match
       (concat "\\`" py-re " (\\(.+\\) \\(method\\|attribute\\))") item)
      (replace-regexp-in-string " " "." (concat (match-string 2 item) " "
                                                (match-string 1 item))))
     (t
      item))))

(provide 'pydoc-info)
;;; pydoc-info.el ends here