|
| 1 | +;;; org-link-pydef.el --- Support for links to python defintions in Org mode |
| 2 | +;; Copyright (C) 2020 |
| 3 | + |
| 4 | +;; Author: George Moutsopoulos <[email protected]> |
| 5 | +;; Version: 1.0 |
| 6 | +;; Package-Requires: ((org-mode) (org-annotate-code)) |
| 7 | +;; Keywords: annotate, capture, code, comments, python |
| 8 | + |
| 9 | +;;; Commentary: |
| 10 | + |
| 11 | +;; This package provides links that point to python definitions. |
| 12 | +;; It integrates with org-annotate-code to provide annotations to them. |
| 13 | + |
| 14 | +;;; Code: |
| 15 | + |
| 16 | +(require 'ol) |
| 17 | +(org-link-set-parameters "pydef" |
| 18 | + :follow 'org-link-pydef-follow |
| 19 | + :export #'org-link-pydef-export |
| 20 | + :store #'org-link-pydef-store) |
| 21 | + |
| 22 | +(defun org-link-pydef-get-pydef (&optional with-variable no-module) |
| 23 | + (let* ((filename (gm/get-relative-pyroot-filename)) |
| 24 | + (dotted-filename (string-replace "/" "." filename)) |
| 25 | + (module (replace-regexp-in-string "\\.py$" "" dotted-filename)) |
| 26 | + (module (replace-regexp-in-string "^.*python\\.ev\\." "ev." module)) |
| 27 | + (funname (python-info-current-defun)) |
| 28 | + (varname (save-excursion (python-nav-beginning-of-statement) |
| 29 | + (python-info-current-symbol))) |
| 30 | + (pydef-no-module (if with-variable |
| 31 | + (cond ((not funname) varname) |
| 32 | + ((not varname) funname) |
| 33 | + ((concat funname "." varname))) |
| 34 | + (or funname varname) |
| 35 | + )) |
| 36 | + (pydef-with-module (concat module "::" pydef-no-module)) |
| 37 | + (pydef (if no-module pydef-no-module pydef-with-module))) |
| 38 | + pydef |
| 39 | + )) |
| 40 | + |
| 41 | +(defun org-link-pydef-store (&optional with-variable without-file) |
| 42 | + "Store a link to a man page." |
| 43 | + (when (memq major-mode '(python-mode)) |
| 44 | + (let* ((link (org-link-pydef-get-pydef with-variable without-file)) |
| 45 | + (description nil)) |
| 46 | + (org-link-store-props |
| 47 | + :type "pydef" |
| 48 | + :link link |
| 49 | + :description description)))) |
| 50 | + |
| 51 | +(defun org-link-pydef-export (link) |
| 52 | + "Export LINK with DESCRIPTION into FORMAT." |
| 53 | + (let ((path link) |
| 54 | + (desc (or description link))) |
| 55 | + (pcase format |
| 56 | + (`html (format "%s" path)) |
| 57 | + (`latex (format "\\href{%s}{%s}" path desc)) |
| 58 | + (`texinfo (format "@uref{%s,%s}" path desc)) |
| 59 | + (`ascii (format "%s (%s)" desc path)) |
| 60 | + (_ (if description (format "%s (%s)" desc path) path))))) |
| 61 | + |
| 62 | +(defun org-link-pydef-split (link) |
| 63 | + "Return cons of file and dotted pydef from pydef LINK." |
| 64 | + (string-match "^\\(?1:.*\\)::\\(?2:.*\\)$" link) |
| 65 | + (cons (match-string-no-properties 1 link) (match-string-no-properties 2 link))) |
| 66 | + |
| 67 | +(defun org-link-pydef-get-dotted-point (dotted) |
| 68 | + "Goto DOTTED definition." |
| 69 | + (save-excursion |
| 70 | + (let* ((names (split-string dotted "\\.")) |
| 71 | + (first-names (butlast names 1)) |
| 72 | + (last-name (car (last names))) |
| 73 | + (beg (point-min)) |
| 74 | + (end (point-max))) |
| 75 | + (dolist (name first-names) |
| 76 | + (goto beg) |
| 77 | + (search-forward-regexp |
| 78 | + (format "\\(?:def\\|class\\) *%s\\)(" name) end) |
| 79 | + (save-excursion (setq beg (python-nav-beginning-of-defun))) |
| 80 | + (save-excursion (setq end (python-nav-end-of-defun)))) |
| 81 | + (goto beg) |
| 82 | + (search-forward-regexp |
| 83 | + (format "\\(?:\\(?:def\\|class\\) *%s\\)(\\|\\(?:%s *=\\)" last-name) end) |
| 84 | + (python-nav-beginning-of-statement) |
| 85 | + (point)))) |
| 86 | + |
| 87 | +(defun org-link-pydef-follow (link) |
| 88 | + (let* ((splitlink (org-link-pydef-split link)) |
| 89 | + (filename (car splitlink)) |
| 90 | + (dotted (cdr splitlink))) |
| 91 | + (if filename (find-file filename)) |
| 92 | + (goto (org-link-pydef-get-dotted-point dotted)))) |
| 93 | + |
| 94 | +(provide 'org-link-pydef) |
0 commit comments