@@ -317,7 +317,7 @@ a new kernel will be started."
317317
318318(defun ob-ipython--extract-status (msgs )
319319 (->> msgs
320- (-filter (lambda (msg ) (-contains? '(" execute_reply" " inspect_reply" )
320+ (-filter (lambda (msg ) (-contains? '(" execute_reply" " inspect_reply" " complete_reply " )
321321 (cdr (assoc 'msg_type msg)))))
322322 car
323323 (assoc 'content )
@@ -340,7 +340,7 @@ a new kernel will be started."
340340 (with-temp-buffer
341341 (let ((ret (apply 'call-process-region input nil
342342 (ob-ipython--get-python) nil t nil
343- ; ; TODO: hardcoded default
343+ ; ; TODO: hardcoded default -- can use local org-src--babel-info
344344 (list " --" ob-ipython-client-path " --conn-file" " default" " --inspect" ))))
345345 (if (> ret 0 )
346346 (ob-ipython--dump-error (buffer-string ))
@@ -368,19 +368,76 @@ a new kernel will be started."
368368 " Ask a kernel for documentation on the thing at POS in BUFFER."
369369 (interactive (list (current-buffer ) (point )))
370370 (-if-let (result (->> (ob-ipython--inspect buffer pos) (assoc 'text/plain ) cdr ))
371- (ob-ipython--create-inspect-buffer result)
372- (message " No documentation was found. " )))
371+ (ob-ipython--create-inspect-buffer result)
372+ (message " No documentation was found. " )))
373+
374+ ; ; completion
375+
376+ (defun ob-ipython--complete-request (code &optional pos )
377+ (let ((input (json-encode `((code . , code )
378+ (pos . ,(or pos (length code)))))))
379+ (with-temp-buffer
380+ (let ((ret (apply 'call-process-region input nil
381+ (ob-ipython--get-python) nil t nil
382+ ; ; TODO: hardcoded default
383+ (list " --" ob-ipython-client-path " --conn-file" " default" " --complete" ))))
384+ (if (> ret 0 )
385+ (ob-ipython--dump-error (buffer-string ))
386+ (goto-char (point-min ))
387+ (ob-ipython--collect-json))))))
388+
389+ (defun ob-ipython-completions (buffer pos )
390+ " Ask a kernel for completions on the thing at POS in BUFFER."
391+ (let* ((code (with-current-buffer buffer
392+ (buffer-substring-no-properties (point-min ) (point-max ))))
393+ (resp (ob-ipython--complete-request code pos))
394+ (status (ob-ipython--extract-status resp)))
395+ (if (not (string= " ok" status))
396+ '()
397+ (->> resp
398+ (-filter (lambda (msg )
399+ (-contains? '(" complete_reply" )
400+ (cdr (assoc 'msg_type msg)))))
401+ (-mapcat (lambda (msg )
402+ (->> msg
403+ (assoc 'content )
404+ cdr )))))))
405+
406+ (defun company-ob-ipython (command &optional arg &rest ignored )
407+ (interactive (list 'interactive ))
408+ (cl-case command
409+ (interactive (company-begin-backend 'company-ob-ipython ))
410+ (prefix (and
411+ ob-ipython-mode
412+ (let ((res (ob-ipython-completions (current-buffer ) (1- (point )))))
413+ (substring (buffer-string ) (cdr (assoc 'cursor_start res))
414+ (cdr (assoc 'cursor_end res))))))
415+ (candidates (let ((res (ob-ipython-completions (current-buffer ) (1- (point )))))
416+ (cdr (assoc 'matches res))))
417+ (sorted t )))
418+
419+ ; ; mode
420+
421+ (define-minor-mode ob-ipython-mode
422+ " "
423+ nil
424+ " ipy"
425+ '())
373426
374427; ; babel framework
375428
376429(add-to-list 'org-src-lang-modes '(" ipython" . python))
377430
378431(defvar org-babel-default-header-args:ipython '())
379432
433+ (defun org-babel-edit-prep:ipython (info )
434+ ; ; TODO: based on kernel, should change the mode
435+ (ob-ipython-mode +1 ))
436+
380437(defun ob-ipython--normalize-session (session )
381438 (if (string= " default" session)
382- (error " default is reserved for when no name is provided. Please use a different session name. " )
383- (or session " default" )))
439+ (error " default is reserved for when no name is provided. Please use a different session name. " )
440+ (or session " default" )))
384441
385442(defun org-babel-execute:ipython (body params )
386443 " Execute a block of IPython code with Babel.
0 commit comments