Skip to content

Commit 41ceff8

Browse files
committed
le-python.el: Allow to chain method calls in Jython completion
* le-python.el (lispy-python-symbol-bnd): New defun. (lispy-python-completion-at-point): Update. * lispy-test.el (lispy-python-symbol-bnd): Add. Suppose I want to end up with this: detector.getDetectorProperties ().getOwner ().getProbeProperties () Previously, completion would work only here: det| and here: detector.get| Now, completion also works here: detector.getDetectorProperties ().g| How it works: 1. Store the longest complete method chain into a variable: # Assume no side effects for eval, lol. # Would be cool to statically derive the class. __t__ = detector.getDetectorProperties () 2. Request completions for e.g. "__t__.g". 3. Remove "__t__" from the resulting completions.
1 parent 4336326 commit 41ceff8

File tree

3 files changed

+46
-11
lines changed

3 files changed

+46
-11
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
\#*#
77
.#*
88
*~
9+
*$py.class

le-python.el

+35-11
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,23 @@ it at one time."
272272
nil
273273
(string< a b))))
274274

275+
(defun lispy-python-symbol-bnd ()
276+
(let ((bnd (or (bounds-of-thing-at-point 'symbol)
277+
(cons (point) (point)))))
278+
(save-excursion
279+
(goto-char (car bnd))
280+
(while (progn
281+
(skip-chars-backward " ")
282+
(lispy-after-string-p "."))
283+
(backward-char 1)
284+
(skip-chars-backward " ")
285+
(if (lispy-after-string-p ")")
286+
(backward-sexp 2)
287+
(backward-sexp)))
288+
(skip-chars-forward " ")
289+
(setcar bnd (point)))
290+
bnd))
291+
275292
(defun lispy-python-completion-at-point ()
276293
(cond ((looking-back "^\\(import\\|from\\) .*" (line-beginning-position))
277294
(let* ((line (buffer-substring-no-properties
@@ -300,18 +317,25 @@ it at one time."
300317
(cl-sort (delete "./" (all-completions str #'read-file-name-internal))
301318
#'lispy-dir-string<))))
302319
(t
303-
(let ((comp (python-shell-completion-at-point (lispy--python-proc))))
304-
(list (nth 0 comp)
305-
(nth 1 comp)
320+
(let* ((bnd (lispy-python-symbol-bnd))
321+
(str (buffer-substring-no-properties
322+
(car bnd) (cdr bnd))))
323+
(when (string-match "\\()\\)[^)]*\\'" str)
324+
(let ((expr (format "__t__ = %s" (substring str 0 (match-end 1)))))
325+
(setq str (concat "__t__" (substring str (match-end 1))))
326+
(cl-incf (car bnd) (match-end 1))
327+
(lispy--eval-python expr t)))
328+
(list (car bnd)
329+
(cdr bnd)
306330
(mapcar (lambda (s)
307-
(if (string-match "(\\'" s)
308-
(substring s 0 (match-beginning 0))
309-
s))
310-
(all-completions
311-
(buffer-substring-no-properties
312-
(nth 0 comp)
313-
(nth 1 comp))
314-
(nth 2 comp))))))))
331+
(replace-regexp-in-string
332+
"__t__" ""
333+
(if (string-match "(\\'" s)
334+
(substring s 0 (match-beginning 0))
335+
s)))
336+
(python-shell-completion-get-completions
337+
(lispy--python-proc)
338+
nil str)))))))
315339

316340
(defvar lispy--python-arg-key-re "\\`\\(\\(?:\\sw\\|\\s_\\)+\\) ?= ?\\(.*\\)\\'"
317341
"Constant regexp for matching function keyword spec.")

lispy-test.el

+10
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,16 @@ Insert KEY if there's no command."
30353035
(lispy--eval-python "print \"one\"\nprint \"two\"\nx = 2 + 1"))
30363036
"one\ntwo\n3"))))
30373037

3038+
(ert-deftest lispy-python-symbol-bnd ()
3039+
(should (equal (lispy-with-python "def test_detector ():\n detector.getChannelCount ().|"
3040+
(lispy--string-dwim
3041+
(lispy-python-symbol-bnd)))
3042+
"detector.getChannelCount ()."))
3043+
(should (equal (lispy-with-python "def test_detector ():\n detector.getDetectorProperties ().getOwner ().|"
3044+
(lispy--string-dwim
3045+
(lispy-python-symbol-bnd)))
3046+
"detector.getDetectorProperties ().getOwner ().")))
3047+
30383048
(provide 'lispy-test)
30393049

30403050
;;; lispy-test.el ends here

0 commit comments

Comments
 (0)