0

I am running python3 in eshell.

When I use import pdb; pdb.set_trace() in my code, pdb opens within eshell.

Everything works in pdb but the up/down keys don't work for running the previous command. I get not found as the message if I press the arrow keys. How can I make them work?

  • I believe the default for the arrow keys in shell are to navigate and not for history. Do M-n and M-p work? Those are the usual defaults for comint buffers for comint-next-input and comint-previous-input. If those work, you can just rebind them to the arrow keys with something like (define-key comint-mode-map (kbd "<up>") 'comint-previous-input) – Lorem Ipsum Apr 29 '19 at 12:26
  • The command "not found" message is unusual, though. Do you experience this behavior when running things from a clean emacs -Q? – Lorem Ipsum Apr 29 '19 at 12:28
  • OP is using eshell, not shell. – nega Apr 29 '19 at 14:38
  • As @nega pointed out its on an eshell and not shell maybe just using shell is the right answer. – Rahul Apr 29 '19 at 15:22
2
+25

This isn't so much an answer, as a clue for someone else...

When I run emacs -Q followed by M-x eshell and do:

Welcome to the Emacs shell

~ $ python3
Python 3.7.2 (default, Jan 13 2019, 12:50:15) 
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) 

At this point run M-x toggle-debug-on-error and hit <up>. This triggers a backtrace:

Debugger entered--Lisp error: (error "Not found")
  signal(error ("Not found"))
  error("Not found")
  eshell-previous-matching-input("^(Pdb) " 1)
  eshell-previous-matching-input-from-input(1)
  funcall-interactively(eshell-previous-matching-input-from-input 1)
  call-interactively(eshell-previous-matching-input-from-input nil nil)
  command-execute(eshell-previous-matching-input-from-input)

Ok. Fine. I didn't do anything in PDB, so there's no history.

(Pdb) ?

Documented commands (type help <topic>):
========================================
EOF    c          d        h         list      q        rv       undisplay
a      cl         debug    help      ll        quit     s        unt      
alias  clear      disable  ignore    longlist  r        source   until    
args   commands   display  interact  n         restart  step     up       
b      condition  down     j         next      return   tbreak   w        
break  cont       enable   jump      p         retval   u        whatis   
bt     continue   exit     l         pp        run      unalias  where    

Miscellaneous help topics:
==========================
exec  pdb

(Pdb) up
*** Oldest frame
(Pdb) down
*** Newest frame
(Pdb) 

At this point I hit up and python3 is added to the (Pdb) input line, a la

[...]
(Pdb) down
*** Newest frame
(Pdb) python3

and History: 1 is displayed in the mini-buffer. Deleting "python3", and adding more pdb acceptable input, and hitting <up> (or <down>) again triggers the same backtrace.

Quitting pdb, and returning to the python3 repl, we run a command and hit <up>

(Pdb)q
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/bdb.py", line 92, in trace_dispatch
    return self.dispatch_return(frame, arg)
  File "/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/bdb.py", line 154, in dispatch_return
    if self.quitting: raise BdbQuit
bdb.BdbQuit
>>> print("foo")
foo
>>> 

Again, a similar backtrace

Debugger entered--Lisp error: (error "Not found")
  signal(error ("Not found"))
  error("Not found")
  eshell-previous-matching-input("^>>> " 1)
  eshell-previous-matching-input-from-input(1)
  funcall-interactively(eshell-previous-matching-input-from-input 1)
  call-interactively(eshell-previous-matching-input-from-input nil nil)
  command-execute(eshell-previous-matching-input-from-input)

tl;dr

It looks like eshell is getting confused by the subprocess. Either it understands it's in a sub-process and doesn't know how to record history, or it has no idea it's in a sub-process and is trying to count the prompt as part of the input and again getting confused. Either way, not being an eshell user, I'd chalk this up as a bug (or a missing feature).

Maybe using M-x shell and @LoremIpsum's suggestion to remap <up> you'll have better luck.

  • Interesting analysis. Seems like a missing feature to me too. – Rahul Apr 29 '19 at 15:21
0

As implied by the research @nega has done, it looks like eshell doesn't capture the input of the pdb subprocess. This can also be seen in how eshell-previous-matching-input-from-input, the function bound to <up>, behaves. It essentially pulls from the eshell-history-ring. If you look at the eshell-list-history, which parses the eshell-history-ring, it only shows the eshell history, not the history of the pdb subprocess.

Sad horn.

Fortunately, you have options. There is shell, term, and ansi-term1. Overall, I've found shell to be the best middle ground.

In shell, input history is accessed via comint-previous-input (M-p) and comint-next-input (M-n). Subprocesses, in my experience, are included in this history. You can rebind the history commands to the up/down arrows with something like

(define-key comint-mode-map (kbd "<up>") 'comint-previous-input)

I would like to give you more advice on using shell with Python, however, without knowing your specific use-case, I'd only be guessing. I recommend giving shell a try, see how it suits you, and ask specifically about anything you feel it lacks out-of-the-box.

Hopefully that gives you a path forward!

1. Of course, since Emacs is free software, the option to implement the feature yourself is always there.

  • You are right. I will give shell a try and see how it goes. – Rahul Apr 29 '19 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.