Skip to content

Commit cf0d054

Browse files
committed
Handle import aliases more intelligently
1 parent e49a848 commit cf0d054

File tree

2 files changed

+57
-23
lines changed

2 files changed

+57
-23
lines changed

pyimport.el

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,35 @@ To terminate the loop early, throw 'break."
117117
(goto-char (point-min))
118118
(insert line "\n")))))
119119

120-
(defun pyimport--import-simplify (line symbol)
121-
"Given LINE 'from foo import bar, baz', and SYMBOL 'baz', simplify to
122-
'from foo import baz'.
123-
124-
Preserves pyimport text properties on LINE."
125-
;; TODO: simplify "from foo import bar, baz as biz" -> "from foo import baz as biz"
126-
(let ((simplified
127-
(cond ((string-match "from .* import .* as .*" line)
128-
line)
129-
((s-starts-with-p "from " line)
130-
(let ((parts (s-split " " line)))
131-
(format "from %s import %s" (nth 1 parts) symbol)))
132-
(t
133-
line))))
134-
(propertize simplified 'pyimport-path
135-
(get-text-property 0 'pyimport-path line))))
120+
(defun pyimport--get-alias (import-as symbol)
121+
"Return the original symbol name, the aliased name, or nil, if
122+
SYMBOL is in IMPORT-AS."
123+
(let ((parts (s-split " as " import-as)))
124+
(cond
125+
((equal (nth 0 parts) symbol) symbol)
126+
((equal (nth 1 parts) symbol) import-as))))
127+
128+
(defun pyimport--extract-simple-import (line symbol)
129+
"Given LINE 'from foo import x, y as z', if SYMBOL is 'z',
130+
return 'from foo import y as z'."
131+
(let ((parts (s-split " " (s-collapse-whitespace line))))
132+
(cond
133+
((s-starts-with-p "from " line)
134+
(let* ((raw-aliases (nth 1 (s-split " import " line)))
135+
(aliases (s-split "," raw-aliases))
136+
(matching-aliases (--map (pyimport--get-alias (s-trim it) symbol) aliases)))
137+
(setq matching-aliases (-non-nil matching-aliases))
138+
(when matching-aliases
139+
(format "from %s import %s"
140+
(nth 1 parts)
141+
(nth 0 matching-aliases)))))
142+
((s-starts-with-p "import " line)
143+
(let* ((raw-aliases (nth 1 (s-split "import " line)))
144+
(aliases (s-split "," raw-aliases))
145+
(matching-aliases (--map (pyimport--get-alias (s-trim it) symbol) aliases)))
146+
(setq matching-aliases (-non-nil matching-aliases))
147+
(when matching-aliases
148+
(format "import %s" (nth 0 matching-aliases))))))))
136149

137150
(defun pyimport--buffers-in-mode (mode)
138151
"Return a list of all the buffers with major mode MODE."
@@ -167,13 +180,8 @@ This is a simple heuristic: we just look for imports in all open Python buffers.
167180
;; Find all the import lines in all Python buffers
168181
(dolist (buffer (pyimport--buffers-in-mode 'python-mode))
169182
(dolist (line (pyimport--import-lines buffer))
170-
;; If any of them contain the current symbol:
171-
(when (string-match (rx-to-string `(seq symbol-start ,symbol symbol-end)) line)
172-
(push line matching-lines))))
173-
174-
;; Simplify imports so we don't show irrelevant symbols.
175-
(setq matching-lines
176-
(--map (pyimport--import-simplify it symbol) matching-lines))
183+
(-if-let (import (pyimport--extract-simple-import line symbol))
184+
(push import matching-lines))))
177185

178186
;; Remove duplicates.
179187
(setq matching-lines (-uniq matching-lines))

test/pyimport-test.el

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,29 @@
151151
(should
152152
(equal (buffer-string)
153153
"from foo import x\n"))))
154+
155+
(ert-deftest extract-simple-import ()
156+
(should
157+
(equal
158+
(pyimport--extract-simple-import "from foo import bar, xxx" "bar")
159+
"from foo import bar"))
160+
(should
161+
(equal
162+
(pyimport--extract-simple-import "from foo import bar,xxx" "xxx")
163+
"from foo import xxx"))
164+
(should
165+
(equal
166+
(pyimport--extract-simple-import "from foo import xxx as bar, yyy" "bar")
167+
"from foo import xxx as bar"))
168+
(should
169+
(equal
170+
(pyimport--extract-simple-import "import foo" "foo")
171+
"import foo"))
172+
(should
173+
(equal
174+
(pyimport--extract-simple-import "import foo as bar" "foo")
175+
"import foo"))
176+
(should
177+
(equal
178+
(pyimport--extract-simple-import "import foo as bar" "bar")
179+
"import foo as bar")))

0 commit comments

Comments
 (0)