[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