[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


Hi,
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-
completion.
This is good for auto-completion that will complete both:
In [15]: "".jo

and

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 
methods.
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))])) \
#PYTHON-MODE SILENT\n")

;; 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'))])) \
#PYTHON_MODE SILENT\n")

(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-
eol)))
	(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)))
    tmp-line))

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

(defalias 'ipython-try-greedy-completion
  'ipython-build-greedy-completion-request)

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

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

(defalias 'ipython-try-normal-completion
  'ipython-build-regular-completion-request)

(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 
completions.")

;; 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-
greedy-completion))

(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 ()
  (interactive)
  (let* ((ugly-return nil)
	 (python-process (or (get-buffer-process (current-buffer))
					;XXX hack for .py buffers
			     (get-process py-which-bufname)))
	 (comint-preoutput-filter-functions
	  (append comint-preoutput-filter-functions
		  '(ansi-color-filter-apply
		    (lambda (string)
		      (setq ugly-return (concat ugly-return string))
		      ""))))
	 (functions ipython-completion-functions)
	 (completions '(""))
	 seed
	 completions-table)
    (while (and (string= (car completions) "") functions)
      (process-send-string python-process (funcall (car functions)))
      (accept-process-output python-process)
      (setq completions
	    (split-string
	     (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)
	   (ding))
	  ((> (length completions) 1)
	   (message "Making completion list...")
	   (with-output-to-temp-buffer "*IPython Completions*"
	     (display-completion-list completions))
	   (message "Making completion list...%s" "done")))))

Regards,
Oren Bar




More information about the IPython-dev mailing list