GNU bug report logs - #34787
New defcustom to govern TAB completion

Previous Next

Package: emacs;

Reported by: Alex Branham <alex.branham <at> gmail.com>

Date: Fri, 8 Mar 2019 18:22:02 UTC

Severity: wishlist

Tags: fixed

Fixed in version 28.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 34787 in the body.
You can then email your comments to 34787 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Fri, 08 Mar 2019 18:22:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Alex Branham <alex.branham <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 08 Mar 2019 18:22:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Alex Branham <alex.branham <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: New defcustom to govern TAB completion
Date: Fri, 08 Mar 2019 12:21:20 -0600
[Message part 1 (text/plain, inline)]
Hello -

In ESS, we have 'ess-first-tab-never-complete' which governs whether TAB
offers completion. The gist of it is that if you're in a buffer (with |
representing point):

(def|var foo)

and you hit TAB, you might not want completion offered. I've put
together a patch that incorporates this into Emacs by adding a new
defcustom `tab-first-completion'. The values are currently based on
ESS's implementation, though we can certainly change that if we want.
Perhaps it should be a function that receives one argument (position)
and if it returns non-nil, then we complete?

Is this something people would be interested in adding?

Thanks,
Alex


From eb4c1a9c8bcd2f5018150b0502e8ed945c181e74 Mon Sep 17 00:00:00 2001
From: Alex Branham <alex.branham <at> gmail.com>
Date: Fri, 8 Mar 2019 12:09:04 -0600
Subject: [PATCH] New defcustom tab-first-completion

* lisp/indent.el (tab-always-indent): Mention 'tab-first-completion'.
(tab-first-completion): New defcustom.
(indent-for-tab-command): Use 'tab-first-completion'.

Bug#<TBD>
---
 lisp/indent.el | 40 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/lisp/indent.el b/lisp/indent.el
index 34757a43d7..08087effa6 100644
--- a/lisp/indent.el
+++ b/lisp/indent.el
@@ -51,6 +51,7 @@ If nil, hitting TAB indents the current line if point is at the left margin
 or in the line's indentation, otherwise it inserts a \"real\" TAB character.
 If `complete', TAB first tries to indent the current line, and if the line
 was already indented, then try to complete the thing at point.
+See also `tab-first-completion'.

 Some programming language modes have their own variable to control this,
 e.g., `c-tab-always-indent', and do not respect this variable."
@@ -60,6 +61,27 @@ e.g., `c-tab-always-indent', and do not respect this variable."
 	  (const :tag "Indent if inside indentation, else TAB" nil)
 	  (const :tag "Indent, or if already indented complete" complete)))

+(defcustom tab-first-completion nil
+  "Governs the behavior of TAB completion on the first press of the key.
+When nil, complete.  When `eol', only complete if point is at the
+end of a line.  When `word', complete unless the next character
+has word syntax (according to `syntax-after').  When
+`word-or-paren', complete unless the next character is part of a
+word or a parenthesis.  When `word-or-paren-or-punct', complete
+unless the next character is part of a word, parenthesis, or
+punctuation.  Typing TAB a second time always results in
+completion.
+
+This variable has no effect unless `tab-always-indent' is `complete'."
+  :group 'indent
+  :type '(choice
+          (const :tag "Always complete" nil)
+          (const :tag "Unless at the end of a line" 'eol)
+          (const :tag "Unless looking at a word" 'word)
+          (const :tag "Unless at a word or parenthesis" 'word-or-paren)
+          (const :tag "Unless at a word, parenthesis, or punctuation." 'word-or-paren-or-punct))
+  :version "27.1")
+

 (defun indent-according-to-mode ()
   "Indent line in proper way for current major mode.
@@ -111,7 +133,7 @@ or performs symbol completion, depending on `tab-always-indent'.
 The function called to actually indent the line or insert a tab
 is given by the variable `indent-line-function'.

-If a prefix argument is given, after this function indents the
+If a prefix argument is given (ARG), after this function indents the
 current line or inserts a tab, it also rigidly indents the entire
 balanced expression which starts at the beginning of the current
 line, to reflect the current line's indentation.
@@ -139,7 +161,8 @@ prefix argument is ignored."
    (t
     (let ((old-tick (buffer-chars-modified-tick))
           (old-point (point))
-	  (old-indent (current-indentation)))
+	  (old-indent (current-indentation))
+          (syn (syntax-after (point))))

       ;; Indent the line.
       (or (not (eq (indent--funcall-widened indent-line-function) 'noindent))
@@ -152,7 +175,18 @@ prefix argument is ignored."
        ;; If the text was already indented right, try completion.
        ((and (eq tab-always-indent 'complete)
              (eq old-point (point))
-             (eq old-tick (buffer-chars-modified-tick)))
+             (eq old-tick (buffer-chars-modified-tick))
+             (or (null tab-first-completion)
+                 (eq last-command this-command)
+                 (and (equal tab-first-completion 'eol)
+                      (eolp))
+                 (and (member tab-first-completion '(word word-or-paren word-or-paren-or-punct))
+                      (not (member 2 syn)))
+                 (and (member tab-first-completion '(word-or-paren word-or-paren-or-punct))
+                      (not (or (member 4 syn)
+                               (member 5 syn))))
+                 (and (equal tab-first-completion 'word-or-paren-or-punct)
+                      (not (member 1 syn)))))
         (completion-at-point))

        ;; If a prefix argument was given, rigidly indent the following
--
2.19.2
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Fri, 08 Mar 2019 19:30:02 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Alex Branham <alex.branham <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: Re: New defcustom to govern TAB completion
Date: Fri, 08 Mar 2019 13:29:03 -0600
On Fri 08 Mar 2019 at 12:21, Alex Branham <alex.branham <at> gmail.com> wrote:

> @@ -139,7 +161,8 @@ prefix argument is ignored."
>     (t
>      (let ((old-tick (buffer-chars-modified-tick))
>            (old-point (point))
> -	  (old-indent (current-indentation)))
> +	  (old-indent (current-indentation))
> +          (syn (syntax-after (point))))
             ^^^^^ should be (syn `(,(syntax-after (point))))

I accidentally sent the wrong patch; this part needs to be quoted.

Alex




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Sat, 25 May 2019 13:08:01 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Alex Branham <alex.branham <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: Re: New defcustom to govern TAB completion
Date: Sat, 25 May 2019 08:05:59 -0500
Hi -

Just following up on this since I didn't hear back. If people are
interested, great. If not, I can close this bug report.

As a quick reminder/TLDR - the proposal is to add a defcustom that
governs whether TAB offers completion when hit the first time. The
thinking is that if point is in the middle of a word, you may not want
completion.

Thanks,
Alex

On Fri 08 Mar 2019 at 12:21, Alex Branham <alex.branham <at> gmail.com> wrote:

> Hello -
>
> In ESS, we have 'ess-first-tab-never-complete' which governs whether TAB
> offers completion. The gist of it is that if you're in a buffer (with |
> representing point):
>
> (def|var foo)
>
> and you hit TAB, you might not want completion offered. I've put
> together a patch that incorporates this into Emacs by adding a new
> defcustom `tab-first-completion'. The values are currently based on
> ESS's implementation, though we can certainly change that if we want.
> Perhaps it should be a function that receives one argument (position)
> and if it returns non-nil, then we complete?
>
> Is this something people would be interested in adding?
>
> Thanks,
> Alex
>
>
> From eb4c1a9c8bcd2f5018150b0502e8ed945c181e74 Mon Sep 17 00:00:00 2001
> From: Alex Branham <alex.branham <at> gmail.com>
> Date: Fri, 8 Mar 2019 12:09:04 -0600
> Subject: [PATCH] New defcustom tab-first-completion
>
> * lisp/indent.el (tab-always-indent): Mention 'tab-first-completion'.
> (tab-first-completion): New defcustom.
> (indent-for-tab-command): Use 'tab-first-completion'.
>
> Bug#<TBD>
> ---
>  lisp/indent.el | 40 +++++++++++++++++++++++++++++++++++++---
>  1 file changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/lisp/indent.el b/lisp/indent.el
> index 34757a43d7..08087effa6 100644
> --- a/lisp/indent.el
> +++ b/lisp/indent.el
> @@ -51,6 +51,7 @@ If nil, hitting TAB indents the current line if point is at the left margin
>  or in the line's indentation, otherwise it inserts a \"real\" TAB character.
>  If `complete', TAB first tries to indent the current line, and if the line
>  was already indented, then try to complete the thing at point.
> +See also `tab-first-completion'.
>
>  Some programming language modes have their own variable to control this,
>  e.g., `c-tab-always-indent', and do not respect this variable."
> @@ -60,6 +61,27 @@ e.g., `c-tab-always-indent', and do not respect this variable."
>  	  (const :tag "Indent if inside indentation, else TAB" nil)
>  	  (const :tag "Indent, or if already indented complete" complete)))
>
> +(defcustom tab-first-completion nil
> +  "Governs the behavior of TAB completion on the first press of the key.
> +When nil, complete.  When `eol', only complete if point is at the
> +end of a line.  When `word', complete unless the next character
> +has word syntax (according to `syntax-after').  When
> +`word-or-paren', complete unless the next character is part of a
> +word or a parenthesis.  When `word-or-paren-or-punct', complete
> +unless the next character is part of a word, parenthesis, or
> +punctuation.  Typing TAB a second time always results in
> +completion.
> +
> +This variable has no effect unless `tab-always-indent' is `complete'."
> +  :group 'indent
> +  :type '(choice
> +          (const :tag "Always complete" nil)
> +          (const :tag "Unless at the end of a line" 'eol)
> +          (const :tag "Unless looking at a word" 'word)
> +          (const :tag "Unless at a word or parenthesis" 'word-or-paren)
> +          (const :tag "Unless at a word, parenthesis, or punctuation." 'word-or-paren-or-punct))
> +  :version "27.1")
> +
>
>  (defun indent-according-to-mode ()
>    "Indent line in proper way for current major mode.
> @@ -111,7 +133,7 @@ or performs symbol completion, depending on `tab-always-indent'.
>  The function called to actually indent the line or insert a tab
>  is given by the variable `indent-line-function'.
>
> -If a prefix argument is given, after this function indents the
> +If a prefix argument is given (ARG), after this function indents the
>  current line or inserts a tab, it also rigidly indents the entire
>  balanced expression which starts at the beginning of the current
>  line, to reflect the current line's indentation.
> @@ -139,7 +161,8 @@ prefix argument is ignored."
>     (t
>      (let ((old-tick (buffer-chars-modified-tick))
>            (old-point (point))
> -	  (old-indent (current-indentation)))
> +	  (old-indent (current-indentation))
> +          (syn (syntax-after (point))))
>
>        ;; Indent the line.
>        (or (not (eq (indent--funcall-widened indent-line-function) 'noindent))
> @@ -152,7 +175,18 @@ prefix argument is ignored."
>         ;; If the text was already indented right, try completion.
>         ((and (eq tab-always-indent 'complete)
>               (eq old-point (point))
> -             (eq old-tick (buffer-chars-modified-tick)))
> +             (eq old-tick (buffer-chars-modified-tick))
> +             (or (null tab-first-completion)
> +                 (eq last-command this-command)
> +                 (and (equal tab-first-completion 'eol)
> +                      (eolp))
> +                 (and (member tab-first-completion '(word word-or-paren word-or-paren-or-punct))
> +                      (not (member 2 syn)))
> +                 (and (member tab-first-completion '(word-or-paren word-or-paren-or-punct))
> +                      (not (or (member 4 syn)
> +                               (member 5 syn))))
> +                 (and (equal tab-first-completion 'word-or-paren-or-punct)
> +                      (not (member 1 syn)))))
>          (completion-at-point))
>
>         ;; If a prefix argument was given, rigidly indent the following




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Sat, 25 May 2019 13:38:02 GMT) Full text and rfc822 format available.

Message #14 received at 34787 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> gmail.com>
To: Alex Branham <alex.branham <at> gmail.com>
Cc: 34787 <at> debbugs.gnu.org
Subject: Re: bug#34787: New defcustom to govern TAB completion
Date: Sat, 25 May 2019 09:37:35 -0400
Alex Branham <alex.branham <at> gmail.com> writes:

> As a quick reminder/TLDR - the proposal is to add a defcustom that
> governs whether TAB offers completion when hit the first time. The
> thinking is that if point is in the middle of a word, you may not want
> completion.

How would it interact with the existing tab-always-indent?  Would it
make sense to combine them?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Sat, 25 May 2019 13:44:01 GMT) Full text and rfc822 format available.

Message #17 received at 34787 <at> debbugs.gnu.org (full text, mbox):

From: Alex Branham <alex.branham <at> gmail.com>
To: Noam Postavsky <npostavs <at> gmail.com>
Cc: 34787 <at> debbugs.gnu.org
Subject: Re: bug#34787: New defcustom to govern TAB completion
Date: Sat, 25 May 2019 08:43:02 -0500
[Message part 1 (text/plain, inline)]
On Sat 25 May 2019 at 08:37, Noam Postavsky <npostavs <at> gmail.com> wrote:

> Alex Branham <alex.branham <at> gmail.com> writes:
>
>> As a quick reminder/TLDR - the proposal is to add a defcustom that
>> governs whether TAB offers completion when hit the first time. The
>> thinking is that if point is in the middle of a word, you may not want
>> completion.
>
> How would it interact with the existing tab-always-indent?  Would it
> make sense to combine them?

The way we have it in ESS currently is that they're two separate
variables. One (our version of tab-always-indent) governs whether TAB
offers completion and another (what I'm proposing adding to Emacs)
governs whether the first press of TAB should offer completion based on
context.

Alex
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Wed, 05 Jun 2019 01:51:01 GMT) Full text and rfc822 format available.

Message #20 received at 34787 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> gmail.com>
To: Alex Branham <alex.branham <at> gmail.com>
Cc: 34787 <at> debbugs.gnu.org
Subject: Re: bug#34787: New defcustom to govern TAB completion
Date: Tue, 04 Jun 2019 21:50:11 -0400
Alex Branham <alex.branham <at> gmail.com> writes:

> On Sat 25 May 2019 at 08:37, Noam Postavsky <npostavs <at> gmail.com> wrote:
>
>> Alex Branham <alex.branham <at> gmail.com> writes:
>>
>>> As a quick reminder/TLDR - the proposal is to add a defcustom that
>>> governs whether TAB offers completion when hit the first time. The
>>> thinking is that if point is in the middle of a word, you may not want
>>> completion.
>>
>> How would it interact with the existing tab-always-indent?  Would it
>> make sense to combine them?
>
> The way we have it in ESS currently is that they're two separate
> variables. One (our version of tab-always-indent) governs whether TAB
> offers completion and another (what I'm proposing adding to Emacs)
> governs whether the first press of TAB should offer completion based on
> context.

Oh, I see, it only affects people who have already customized
tab-always-indent to a non-default value (specifically, `complete').

So I guess the idea is that (setq tab-always-indent 'complete) triggers
too many accidental completions to be a reasonable setting?  I think it
would be nicer if the option's values could be `(word paren)', `(word
paren punct) instead of `word-or-paren', `word-or-paren-or-punct', etc.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Mon, 24 Aug 2020 19:23:01 GMT) Full text and rfc822 format available.

Message #23 received at 34787 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefan <at> marxist.se>
To: Noam Postavsky <npostavs <at> gmail.com>
Cc: 34787 <at> debbugs.gnu.org, Alex Branham <alex.branham <at> gmail.com>
Subject: Re: bug#34787: New defcustom to govern TAB completion
Date: Mon, 24 Aug 2020 12:22:20 -0700
Noam Postavsky <npostavs <at> gmail.com> writes:

> Alex Branham <alex.branham <at> gmail.com> writes:
>
>> On Sat 25 May 2019 at 08:37, Noam Postavsky <npostavs <at> gmail.com> wrote:
>>
>>> Alex Branham <alex.branham <at> gmail.com> writes:
>>>
>>>> As a quick reminder/TLDR - the proposal is to add a defcustom that
>>>> governs whether TAB offers completion when hit the first time. The
>>>> thinking is that if point is in the middle of a word, you may not want
>>>> completion.
>>>
>>> How would it interact with the existing tab-always-indent?  Would it
>>> make sense to combine them?
>>
>> The way we have it in ESS currently is that they're two separate
>> variables. One (our version of tab-always-indent) governs whether TAB
>> offers completion and another (what I'm proposing adding to Emacs)
>> governs whether the first press of TAB should offer completion based on
>> context.
>
> Oh, I see, it only affects people who have already customized
> tab-always-indent to a non-default value (specifically, `complete').
>
> So I guess the idea is that (setq tab-always-indent 'complete) triggers
> too many accidental completions to be a reasonable setting?  I think it
> would be nicer if the option's values could be `(word paren)', `(word
> paren punct) instead of `word-or-paren', `word-or-paren-or-punct', etc.

(That was one year ago.)

Are you still working on this?

Best regards,
Stefan Kangas




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#34787; Package emacs. (Wed, 14 Oct 2020 05:31:02 GMT) Full text and rfc822 format available.

Message #26 received at 34787 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Alex Branham <alex.branham <at> gmail.com>
Cc: 34787 <at> debbugs.gnu.org
Subject: Re: bug#34787: New defcustom to govern TAB completion
Date: Wed, 14 Oct 2020 07:29:52 +0200
Alex Branham <alex.branham <at> gmail.com> writes:

> On Fri 08 Mar 2019 at 12:21, Alex Branham <alex.branham <at> gmail.com> wrote:
>
>> @@ -139,7 +161,8 @@ prefix argument is ignored."
>>     (t
>>      (let ((old-tick (buffer-chars-modified-tick))
>>            (old-point (point))
>> -	  (old-indent (current-indentation)))
>> +	  (old-indent (current-indentation))
>> +          (syn (syntax-after (point))))
>              ^^^^^ should be (syn `(,(syntax-after (point))))
>
> I accidentally sent the wrong patch; this part needs to be quoted.

I played around with this a bit, and it seems to work very well, and
quite naturally.  So I've applied this to Emacs 28.

Noam made the suggestion of making this a list of values like (word
paren) instead of word-or-paren, and that does seem like a good idea,
but either works.  I guess somebody might want (word punct) and not
word-and-paren-and-punct, for instance?  So if somebody were to change
this to work that way instead, I wouldn't mind, but I think it's
probably fine as is.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Added tag(s) fixed. Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Wed, 14 Oct 2020 05:31:02 GMT) Full text and rfc822 format available.

bug marked as fixed in version 28.1, send any further explanations to 34787 <at> debbugs.gnu.org and Alex Branham <alex.branham <at> gmail.com> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Wed, 14 Oct 2020 05:31:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Wed, 11 Nov 2020 12:24:10 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 138 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.