python-auto-import.el 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. (defun python-auto-import (only-first-component)
  2. "automatically import the required symbol under the cursor. With prefix argument, only takes first module path component (so 'os.path.exists' will cause importing of 'os' alone)"
  3. (interactive "P")
  4. (let ((temp-point (point))
  5. (prev-size (buffer-size)))
  6. (python-insert-import-line-at-beginning-of-buffer (python-get-needed-import-string only-first-component))
  7. (goto-char (+ temp-point (- (buffer-size) prev-size)))))
  8. (defun python-get-needed-import-string (only-first-component)
  9. (let ((symbol (--python-info-current-symbol)))
  10. (let ((parts (split-string symbol "\\.")))
  11. (if (<= (list-length parts) 1)
  12. (format "from %s import %s" (read-string (format "import %s from? " symbol)) symbol)
  13. (format "import %s" (if (or
  14. only-first-component
  15. (python-autoimport--is-first-component-enough symbol))
  16. (car parts)
  17. (mapconcat 'identity (nbutlast parts 1) ".")))))))
  18. (defun --python-info-current-symbol ()
  19. (if (< emacs-major-version 24)
  20. (with-syntax-table python-dotty-syntax-table
  21. (current-word))
  22. (python-info-current-symbol)))
  23. (defun python-autoimport--is-first-component-enough (symbol)
  24. (or
  25. (s-starts-with? "os.path." symbol)
  26. ))
  27. (defun python-insert-import-line-at-beginning-of-buffer (import-string)
  28. (save-excursion
  29. (beginning-of-buffer)
  30. (--skip-comments-and-strings)
  31. (--ensure-import-block)
  32. (newline)
  33. (forward-line -1)
  34. (insert-string import-string)
  35. (forward-paragraph)
  36. (my/isort-buffer)
  37. ))
  38. (defun --ensure-import-block ()
  39. (if (not (or (looking-at "import ") (looking-at "from ")))
  40. (progn
  41. (newline-and-indent)
  42. (previous-line))))
  43. (defun --skip-comments-and-strings ()
  44. (while (--looking-at-comment-or-string)
  45. (forward-line)))
  46. (defun --looking-at-comment-or-string ()
  47. (let ((face (get-text-property (point) 'face)))
  48. (message (format "face is %s" face))
  49. (or (eq face 'font-lock-comment-face)
  50. (eq face 'font-lock-comment-delimiter-face)
  51. (eq face 'font-lock-string-face))))
  52. (defun uniquify-all-lines-region (start end)
  53. (save-excursion
  54. (let ((end (copy-marker end)))
  55. (while
  56. (progn
  57. (goto-char start)
  58. (re-search-forward "^\\(.*\\)\n\\(\\(.*\n\\)*\\)\\1\n" end t))
  59. (replace-match "\\1\n\\2")))))
  60. (defun --end-of-chunk ()
  61. (goto-char (point-at-eol))
  62. (let ((limit (point-at-bol))
  63. temp
  64. expr-beg)
  65. (while (and (setq temp (nth 1 (syntax-ppss)))
  66. (<= limit temp))
  67. (goto-char temp)
  68. (setq expr-beg (point)))
  69. (when expr-beg
  70. (goto-char expr-beg)
  71. (forward-sexp))))
  72. (defun my/sort-lines-as-exprs (reverse beg end) ; credit goes to http://bit.ly/VbW9AJ
  73. "sort lines, or whole expression if line ends mid-expression."
  74. (interactive "P\nr")
  75. (save-excursion
  76. (save-restriction
  77. (narrow-to-region beg end)
  78. (goto-char (point-min))
  79. (sort-subr reverse
  80. 'forward-line
  81. '--end-of-chunk))))
  82. (defun my/isort-buffer ()
  83. (interactive)
  84. (save-excursion
  85. (beginning-of-buffer)
  86. (push-mark)
  87. (end-of-buffer)
  88. (shell-command-on-region (point) (mark) "isort -" nil t)
  89. (pop-mark)
  90. ))
  91. (global-set-key (kbd "C-c i") 'python-auto-import)
  92. (provide 'python-auto-import)