From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Fabian Ezequiel Gallina Newsgroups: gmane.emacs.devel Subject: Re: Comint: handle raw tab Date: Sun, 25 Sep 2011 22:30:06 -0300 Message-ID: References: <87vcsw1rev.fsf@gmail.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=bcaec520e83556c1af04adce19f4 X-Trace: dough.gmane.org 1317000620 15272 80.91.229.12 (26 Sep 2011 01:30:20 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 26 Sep 2011 01:30:20 +0000 (UTC) Cc: =?UTF-8?B?xaB0xJtww6FuIE7Em21lYw==?= , Emacs-Devel devel To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Sep 26 03:30:16 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1R801P-0007G2-II for ged-emacs-devel@m.gmane.org; Mon, 26 Sep 2011 03:30:15 +0200 Original-Received: from localhost ([::1]:44688 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R801O-0002D9-Vp for ged-emacs-devel@m.gmane.org; Sun, 25 Sep 2011 21:30:14 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:57442) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R801K-0002Cz-MO for emacs-devel@gnu.org; Sun, 25 Sep 2011 21:30:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R801J-0000Ok-1S for emacs-devel@gnu.org; Sun, 25 Sep 2011 21:30:10 -0400 Original-Received: from mail-pz0-f47.google.com ([209.85.210.47]:63582) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R801I-0000O2-JX for emacs-devel@gnu.org; Sun, 25 Sep 2011 21:30:08 -0400 Original-Received: by pzk4 with SMTP id 4so14438266pzk.6 for ; Sun, 25 Sep 2011 18:30:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=lIBZ3wrfNnYwPqVBcPl0b3kRac19+OwwdwPyV9ylmGc=; b=wsw9SXSFR94d/pbepWAqilUwo63mqWpwbvQEipWICNBFL+NRDW0jLrRW/voLIN+jxF eJiL0SyzOn6vZ9FIHaA3/2E/WS7wbDwG2cd0Jh4muLMo80N5KnViNpGAH6j0y1bMDiMG taD9AT/QcyMFuUMNVSOvSQU0GVJWf/JOQrX/w= Original-Received: by 10.68.16.65 with SMTP id e1mr18314595pbd.27.1317000606826; Sun, 25 Sep 2011 18:30:06 -0700 (PDT) Original-Received: by 10.68.60.10 with HTTP; Sun, 25 Sep 2011 18:30:06 -0700 (PDT) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.210.47 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:144289 Archived-At: --bcaec520e83556c1af04adce19f4 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hi all, 2011/9/13 Stefan Monnier > >> IMO native tab completion for subprocess REPLs is a common enough need > >> that the basic machinery should be handled by Emacs itself, i.e. > >> probably the comint library. I'm somewhat surprised there is no such > >> code yet (or is there, outside Emacs perhaps?). > > I agree with the exposed above, many modern REPLs comint can interact > with > > have TAB completion out of the box. We should use that when it's > available > > instead of duplicating efforts. > > I agree that would be good. > You can check the gdb completion code in gud.el for an example. > > The current shell completion machinery of my python.el works pretty much like the gdb does, the thing is that on the python shell this approach is likely to break on multi-line statements. Good news is that this weekend I got back to try stuff again to get native TAB support on the comint process, and while travelling back to my hometown from the PyCon Argentina (the Bus ride was getting boring) I found somethin= g that made the shell react pretty much like the real thing when sending a ra= w tab: I started the comint process in the same way ansi-term would, using sh + stty. Here is the quick snippet: (defun python-shell-make-comint (cmd proc-name &optional pop) "Create a python shell comint buffer. CMD is the python command to be executed and PROC-NAME is the process name the comint buffer will get. After the comint buffer is created the `inferior-python-mode' is activated. If POP is non-nil the buffer is shown." (save-excursion (let* ((proc-buffer-name (format "*%s*" proc-name)) (process-environment (python-shell-calculate-process-environment)) (exec-path (python-shell-calculate-exec-path))) (when (not (comint-check-proc proc-buffer-name)) (let* ((cmdlist (split-string-and-unquote cmd)) (sh-executable (executable-find "sh")) (stty-executable (executable-find "stty")) (buffer (if (and sh-executable stty-executable) (apply 'make-comint proc-name sh-executable nil "-c" (format "%s -nl echo rows %d columns %d sane 2>/dev/null;\ if [ $1 =3D .. ]; then shift; fi; exec \"$@\"" stty-executable (window-height) (1- (window-width))) ".." (car cmdlist) (cdr cmdlist)) (apply 'make-comint proc-name (car cmdlist) ni= l (cdr cmdlist)))) (current-buffer (current-buffer))) (with-current-buffer buffer (inferior-python-mode) (python-util-clone-local-variables current-buffer)))) (when pop (pop-to-buffer proc-buffer-name)) proc-buffer-name))) After that, when I evaled: (process-send-string (get-buffer-process (current-buffer)) "Tru ") The shell got updated and said True. If I evaled: (process-send-string (get-buffer-process (current-buffer)) "T ") TabError True TypeError Got returned and the shell displayed correctly as it does on a full feature= d terminal. I need to work a little more on the extra bookkeeping involved into getting comint know about the stuff that got inserted in the process but this got m= e really close to have it working as intended. What worries me is the Window support for this, is there something similar like stty there? What I'm thinking is a good approach would be that when sh and stty are not found via `executable-find', fallback to the old style completion. I'll continue working on this in the following days (hopefully I'll get lucky). After that we can see if there is some kind of improvement we can d= o in the comint library itself. Regards, Fabi=E1n E. Gallina --bcaec520e83556c1af04adce19f4 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Hi all,

2011/9/13 Stefan Monnier <monnier@iro.umont= real.ca>
>> IMO native tab completion for subprocess REPLs i= s a common enough need
>> that the basic machinery should be handled by Emacs itself, i.e. >> probably the comint library. I'm somewhat surprised there is n= o such
>> code yet (or is there, outside Emacs perhaps?).
> I agree with the exposed above, many modern REPLs comint can interact = with
> have TAB completion out of the box. =A0We should use that when it'= s available
> instead of duplicating efforts.

I agree that would be good.
You can check the gdb completion code in gud.el for an example.


The current shell completion machinery of my python.el wo= rks pretty much like the gdb does, the thing is that on the python shell th= is approach is likely to break on multi-line statements.

Good news is that this weekend I got back to try stuff again to get nat= ive TAB support on the comint process, and while travelling back to my home= town from the PyCon Argentina (the Bus ride was getting boring) I found som= ething that made the shell react pretty much like the real thing when sendi= ng a raw tab: I started the comint process in the same way ansi-term would,= using sh + stty.

Here is the quick snippet:

=A0=A0=A0 (defun python-shell-make-co= mint (cmd proc-name &optional pop)
=A0=A0=A0=A0=A0 "Create a py= thon shell comint buffer.
=A0=A0=A0 CMD is the python command to be exec= uted and PROC-NAME is the
=A0=A0=A0 process name the comint buffer will get.=A0 After the comint buff= er
=A0=A0=A0 is created the `inferior-python-mode' is activated.=A0 = If POP is
=A0=A0=A0 non-nil the buffer is shown."
=A0=A0=A0=A0= =A0 (save-excursion
=A0=A0=A0=A0=A0=A0=A0 (let* ((proc-buffer-name (form= at "*%s*" proc-name))
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (process-environment (python-she= ll-calculate-process-environment))
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 (exec-path (python-shell-calculate-exec-path)))
=A0=A0=A0=A0=A0= =A0=A0=A0=A0 (when (not (comint-check-proc proc-buffer-name))
=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 (let* ((cmdlist (split-string-and-unquote cmd)) =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (sh-executable (exec= utable-find "sh"))
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 (stty-executable (executable-find "stty"))
=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (buffer (if (and sh-execut= able stty-executable)
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (apply 'make-comint proc-nam= e
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 sh-executable nil "-c"
= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (format "%s -nl echo rows %d colu= mns %d sane 2>/dev/null;\
=A0=A0=A0 if [ $1 =3D .. ]; then shift; fi;= exec \"$@\""
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 stty-executabl= e
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (window-= height) (1- (window-width)))
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "= ;.."
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (car cmdlist) (cdr cmdl= ist))
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 (apply 'make-comint proc-name (car cmdlist) nil
=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 (cdr cmdlist))))
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 (current-buffer (current-buffer)))
=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 (with-current-buffer buffer
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (inferior-python-mode)
=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (python-util-clone-local-variabl= es current-buffer))))
=A0=A0=A0=A0=A0=A0=A0=A0=A0 (when pop
=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 (pop-to-buffer proc-buffer-name))
=A0=A0=A0=A0= =A0=A0=A0=A0=A0 proc-buffer-name)))

After that, when I evaled:

(process-send-string (get-buffer-process = (current-buffer)) "Tru=A0=A0=A0 ")

The shell got updated a= nd said True.

If I evaled:

(process-send-string (get-buffer-process (current-buffer)) "T=A0=A0=A0= ")

TabError=A0=A0 True=A0=A0=A0=A0=A0=A0 TypeError=A0

Got returned= and the shell displayed correctly as it does on a full featured terminal.<= br>
I need to work a little more on the extra bookkeeping involved into = getting comint know about the stuff that got inserted in the process but th= is got me really close to have it working as intended.

What worries me is the Window support for this, is there something simi= lar like stty there? What I'm thinking is a good approach would be that= when sh and stty are not found via `executable-find', fallback to the = old style completion.

I'll continue working on this in the following days (hopefully I= 9;ll get lucky). After that we can see if there is some kind of improvement= we can do in the comint library itself.


Regards,
Fabi=E1n E. Gallina
--bcaec520e83556c1af04adce19f4--