4

The question here is related (but NOT identical) and complementary to Change the "send code to interpreter" (C-c |) command in python-mode .

I work on a Mac 10.9.5, Emacs 24.4, Python 2.7.8 and IPython 2.2.0.

My idea is to change the C-c C-r emacs command to send a region/line of code in IPython mode to C-RET, as when using R. This is because I usually work with R, but from now on, I am going to be using R and Python (IPython in particular, which I really like), and C-RET --already the send code command in R-- seems more comfortable to me.

In the link cited at the beginning of this question they suggest to add the following lines to the .emacs file to change the C-c | command into C-c C-r:

(eval-after-load "python"
  '(progn
     (define-key python-mode-map (kbd "C-c C-r") 'python-shell-send-region)))

At the moment, my python/IPython configuration in my .emacs file looks like this:

;; Enable Python
(add-to-list 'load-path "/sw/lib/python-mode-1.0")
(load "python-mode")
(setq auto-mode-alist
      (cons '("\\.py$" . python-mode) auto-mode-alist))
(setq interpreter-mode-alist
  (cons '("python" . python-mode)
        interpreter-mode-alist))
(autoload 'python-mode "python-mode" "Python editing mode." t)

;; Ipython. This python-mode takes the Key-map and the menu
(when (executable-find "ipython")
  (setq
   python-shell-interpreter "ipython"
   python-shell-interpreter-args ""
   python-shell-prompt-regexp "In \\[[0-9]+\\]: "
   python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
   python-shell-completion-setup-code
   "from IPython.core.completerlib import module_completion"
   python-shell-completion-module-string-code
   "';'.join(module_completion('''%s'''))\n"
   python-shell-completion-string-code
   "';'.join(get_ipython().Completer.all_completions('''%s'''))\n"))

Which are two python modes running in parallel and the second one (IPython, the one I use all the time) takes the key-map and the menu (by the way, any suggestion for a better configuration is welcome. The IPython section is based on: How to open IPython interpreter in emacs?).

I have tried to add the (eval-after-load "python" '(progn ... command described before at the end of my python configuration (of course, changing C-c C-r to C-RET or C-ret or even C-<return>).

I have also tried within the when (executable-find "ipython") ... chunk in different forms (such as simply (define-key python-mode-map (kbd "C-c C-r") 'python-shell-send-region) ). But nothing seems to work.

Therefore, my question would be: Given my Python/IPython configuration, what do I have to include in my .emacs file to change the C-c C-r command into (C-RET)

Many thanks in advance!

Community
  • 1
  • 1
Javier
  • 1,530
  • 4
  • 21
  • 48

3 Answers3

6

Use (kbd "RET")

Try this with python.el

(eval-after-load "python"
  '(define-key python-mode-map [(control c)(kbd "RET")] 'python-shell-send-region))

WRT python-mode.el:

(eval-after-load "python-mode"
  '(define-key python-mode-map [(control c) (kbd "RET")] 'py-execute-region))

BTW unless IPython-exclusiv features are needed, recommend to execute code from Emacs through a common Python. IPython implements a bunch of cool things, which might appear orthogonal to Emacs, which also implements a bunch of cool things.

Andreas Röhler
  • 4,804
  • 14
  • 18
  • Hi Andreas, thanks (again!). Unfortunately, it doesn't work (surely the problem is on my side). I have tried your `(eval-after-load "python-mode" '(define-key python-mode-map [(control c) (kbd "RET")] 'py-execute-region))` just after my `(load "python-mode")`, at the end of the configuration, everywhere, and it did not work. I always get the error message `C- undefined`. Also tried (just in case :) ) `C-c RET` and same result. In fact, I started from "scratch" and downloaded python-mode using marmalade. Did not work either. – Javier Jan 06 '15 at 12:02
  • After installing python-mode with marmalade, the first line of the configuration looks `(add-to-list 'load-path "~/.emacs.d/elpa/python-mode-6.1.3/")`, the rest is the same. When I type `M-x run-python` I obtain a series of indentation errors (this perhaps deserves another question) but IPython seems to run ok. Still, the `C-RET` does not work – Javier Jan 06 '15 at 12:08
  • @Javier py-execute-region is not meant to be used from shell, not from source-buffer. Also python-mode-map resides in source only: in py-shell its py-python-shell-mode-map resp. py-ipython-shell-mode-map. They provide edit-commands while sending is done by RET. – Andreas Röhler Jan 06 '15 at 17:57
4

Here is something that was quickly cooked up to send a python line to python-shell. I tend to do it in R a lot as well. It's not completely automated yet but I might be useful.

Here are some that still remain to be made:

  1. Send line to dedicated process if necessary

  2. Assign a local key

    (defun my-python-line ()
     (interactive)
      (save-excursion
      (setq the_script_buffer (format (buffer-name)))
      (end-of-line)
      (kill-region (point) (progn (back-to-indentation) (point)))
      ;(setq the_py_buffer (format "*Python[%s]*" (buffer-file-name)))
      (setq the_py_buffer "*Python*")
      (switch-to-buffer-other-window  the_py_buffer)
      (goto-char (buffer-end 1))
      (yank)
      (comint-send-input)
      (switch-to-buffer-other-window the_script_buffer)
      (yank))
    )
    
    (global-set-key  (kbd "C-c n") 'my-python-line)
    

Update

I have improved the code a little bit more:

  1. possible to use the code directly to even if a python shell is not running yet.

  2. A local set key have been set

    Only the dedicated process remain to be made. Feel free to improve in the answer below

    (defun my-python-line ()
    (interactive)
    (save-excursion
      (setq the_script_buffer (format (buffer-name)))
      (end-of-line)
      (kill-region (point) (progn (back-to-indentation) (point)))
      (if  (get-buffer  "*Python*")
      (message "")
      (run-python "ipython" nil nil))
      ;; (setq the_py_buffer (format "*Python[%s]*" (buffer-file-name)))
      (setq the_py_buffer "*Python*")
      (switch-to-buffer-other-window  the_py_buffer)
      (goto-char (buffer-end 1))
      (yank)
      (comint-send-input)
      (switch-to-buffer-other-window the_script_buffer)
      (yank))
      (end-of-line)
      (next-line)
      )
    
    (add-hook 'python-mode-hook
        (lambda ()
      (define-key python-mode-map "\C-cn" 'my-python-line)))
    
Community
  • 1
  • 1
DJJ
  • 2,481
  • 2
  • 28
  • 53
  • is there a way to send `lines` till a `line` is completed. e.g., it does not make sense to send "if True:", but to send "if True:" and its following lines in the indented block as well – shelper Jun 07 '16 at 20:46
  • Nice suggestion! basically we only need to recognize an indented block. I'm not that fluent in elisp to give you an answer straight away ,but I'll think about it and keep you posted. – DJJ Jun 08 '16 at 10:14
  • please see my below reply – shelper Jun 08 '16 at 17:10
1

i did some hacking and here is what i have: by reading the code you should be able to tell how it works.

(defun block-line-end ()
    (setq indentation (current-indentation))
    (forward-line)
    (while (> (current-indentation) indentation)
      (forward-line))
    (forward-line -1)
    (line-end-position))  
(defun my-python-shell-send-region (&optional beg end)
    (interactive)
    (let ((beg (cond (beg beg)
                ((region-active-p) (region-beginning))
                (t (line-beginning-position))))
          (end (cond (end end)
                ((region-active-p) 
                 (copy-marker (region-end)))
                (t (block-line-end)))))
      (python-shell-send-region beg end))
    (forward-line))
shelper
  • 10,053
  • 8
  • 41
  • 67