[IPython-dev] Trying to enhance auto-completion of IPython in emacs - need help with debugging

Oren Bar orenbaracha at gmail.com
Fri Feb 17 07:34:30 EST 2012

Deriving from the ipython-complete implementation in ipython.el, i tried to 
implement "greedy-completion" and i think it works pretty well.
Now I try to combine both: 1. try regular completion 2. if none, try greedy-
This is good for auto-completion that will complete both:
In [15]: "".jo


In [16]: print(os.pa

When combining, It seems to me that the result string from IPython for greedy-
completion (2) skips the comint-preoutput-filter-functions, and write it to 
buffer. strange. the code works smoothly if i use only one of the completion 
I can't debug it, since if I debug it using Edebug - accept-process-output seems 
to get stuck. I'm not so experienced in emacs, so i don't know how to attack 
this issue.

If anyone has tips for debugging this, or may see my bug in the code below, it 
would be great:
;; my requests strings are a bit different, i dont ask only for completions - i 
ask for the seed also, and append the completions to it.

;; Greedy completion - complete by whole line and position of cursor
(setq ipython-greedy-completion-command-string
      "print(';'.join([elem if i == 0 else ';'.join(elem) \
for (i,elem) in enumerate(get_ipython().complete('', '%s', %d))])) \

;; Regular completion - complete only by the symbol before point
(setq ipython-regular-completion-command-string
      "print('\\f'.join([elem if i == 0 else '\\f'.join(elem) \
for (i,elem) in enumerate(get_ipython().complete('%s'))])) \

(defun get-current-line-for-ipython-completion ()
  "Get current line, make sure that all \"'\" and \"\\\" are properly quoted"
  (let ((tmp-line (buffer-substring-no-properties (point-at-bol) (point-at-
	(i 0))
    (while (setq i (string-match "\\\\" tmp-line i))
      (setq tmp-line (replace-match "\\\\" nil t tmp-line))
      (setq i (+ i 2)))
    (setq i 0)
    (while (setq i (string-match "'" tmp-line i))
      (setq tmp-line (replace-match "\\\'" nil t tmp-line))
      (setq i (+ i 2)))

(defun ipython-build-greedy-completion-request ()
  "Build the string to be past to IPython for greedy completion"
  (format ipython-greedy-completion-command-string
	  (- (point) (point-at-bol))))

(defalias 'ipython-try-greedy-completion

(defun get-pattern-for-ipython-completion ()
  "Get the largest valid symbol from point and backwards"
   (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol))

(defun ipython-build-regular-completion-request ()
  "Build the string to be past to IPython for regular completion"
  (format ipython-regular-completion-command-string

(defalias 'ipython-try-normal-completion

(defvar ipython-completion-functions nil
  "List IPython completion methods that are allowed to run.\
Will be executed one-by-one according to their order until we get any 

;; if ipython-completion-functions contains only one function, it all works as 
expected (either normal or greedy)
(setq ipython-completion-functions '(ipython-try-normal-completion ipython-try-

(defun gcp-completion (completions-table seed)
  "Completion at point to the Greatest-Common-Prefix"
  (let ((completion (try-completion seed completions-table)))
    (when (and completion (not (eq completion t)))
      (insert (substring completion (length seed))))))

(defun my-ipython-complete-2 ()
  (let* ((ugly-return nil)
	 (python-process (or (get-buffer-process (current-buffer))
					;XXX hack for .py buffers
			     (get-process py-which-bufname)))
	  (append comint-preoutput-filter-functions
		    (lambda (string)
		      (setq ugly-return (concat ugly-return string))
	 (functions ipython-completion-functions)
	 (completions '(""))
    (while (and (string= (car completions) "") functions)
      (process-send-string python-process (funcall (car functions)))
      (accept-process-output python-process)
      (setq completions
	     (substring ugly-return 0 (position ?\n ugly-return))
      (setq seed (car completions))
      (setq completions (cdr completions))
      (setq functions (cdr functions)))
    (setq completions-table (loop for str in completions
				  collect (list str nil)))
    (gcp-completion completions-table seed)
    (cond ((or (not completions)
	       (eq (length (car completions)) 0))
	   (message "Can't find completion for '%s'" seed)
	  ((> (length completions) 1)
	   (message "Making completion list...")
	   (with-output-to-temp-buffer "*IPython Completions*"
	     (display-completion-list completions))
	   (message "Making completion list...%s" "done")))))

Oren Bar

More information about the IPython-dev mailing list