After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 761304 - Provide auto-completion for implemented IRC commands
Provide auto-completion for implemented IRC commands
Status: RESOLVED FIXED
Product: polari
Classification: Applications
Component: general
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: Polari maintainers
Polari maintainers
Depends on:
Blocks:
 
 
Reported: 2016-01-29 17:53 UTC by Bastian Ilsø
Modified: 2016-02-16 21:31 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
autocompletion rev1 (310.64 KB, image/png)
2016-01-29 17:53 UTC, Bastian Ilsø
  Details
mockup based on current implementation (39.01 KB, image/png)
2016-01-29 22:41 UTC, Bastian Ilsø
  Details
tabCompletion: Provide auto-completion for implemented IRC commands (3.60 KB, patch)
2016-02-14 18:40 UTC, Kunaal Jain
none Details | Review
tabCompletion: Provide auto-completion for implemented IRC commands (3.67 KB, patch)
2016-02-16 10:42 UTC, Kunaal Jain
none Details | Review
tabCompletion: Provide auto-completion for implemented IRC commands (3.67 KB, patch)
2016-02-16 14:43 UTC, Kunaal Jain
none Details | Review
tabCompletion: Provide auto-completion for implemented IRC commands (3.37 KB, patch)
2016-02-16 15:13 UTC, Kunaal Jain
none Details | Review
tabCompletion: Provide auto-completion for implemented IRC commands (3.15 KB, patch)
2016-02-16 15:15 UTC, Kunaal Jain
none Details | Review
tabCompletion: Provide auto-completion for implemented IRC commands (3.12 KB, patch)
2016-02-16 15:21 UTC, Kunaal Jain
none Details | Review
tabCompletion: Provide auto-completion for implemented IRC commands (3.11 KB, patch)
2016-02-16 15:34 UTC, Kunaal Jain
committed Details | Review
tabCompletion: Don't chain for auto-completion of command (1.23 KB, patch)
2016-02-16 16:47 UTC, Kunaal Jain
none Details | Review
tabCompletion: Don't chain for auto-completion of command (2.35 KB, patch)
2016-02-16 20:50 UTC, Kunaal Jain
committed Details | Review
tabCompletion: Rename variable isIRCCommand to isCommand (1.94 KB, patch)
2016-02-16 20:50 UTC, Kunaal Jain
none Details | Review
tabCompletion: Rename variable isIRCCommand to isCommand (1.94 KB, patch)
2016-02-16 20:51 UTC, Kunaal Jain
committed Details | Review

Description Bastian Ilsø 2016-01-29 17:53:12 UTC
Created attachment 320030 [details]
autocompletion rev1

Would be cool to have some auto-completion for IRC commands. Here's how rocket does it:

https://www.youtube.com/watch?v=9swVPYHtCI0&feature=youtu.be


attached is a mockup of how it could look in Polari.
Comment 1 Florian Müllner 2016-01-29 18:06:36 UTC
As mentioned on IRC, I think initially it's good enough to just tab-complete commands - there's a good chance can already complete for just '/' + character, so the description of only really useful in corner cases anyway ...
Comment 2 Bastian Ilsø 2016-01-29 22:41:47 UTC
Created attachment 320041 [details]
mockup based on current implementation

(In reply to Florian Müllner from comment #1)
> As mentioned on IRC, I think initially it's good enough to just tab-complete
> commands - there's a good chance can already complete for just '/' +
> character, so the description of only really useful in corner cases anyway
> ...

You're thinking of keeping it similar to nick completion in the lines of this?
or literally just tab-complete?
Comment 3 Florian Müllner 2016-01-30 00:37:28 UTC
(In reply to Bastian Ilsø from comment #2)
> You're thinking of keeping it similar to nick completion in the lines of
> this?
> or literally just tab-complete?

I mean instead of completing on ['nick', 'nick-foo', 'nick-bar'], we can complete on ['nick', 'nick-foo', 'nick-bar', '/cmd', '/cmd-foo']. We'll need to adjust what we insert a bit(*), but that should be far easier than dealing with different completions competing for the same events.


(*) on line start, 'f<tab>' completes to 'fmuellner: ', and 'f<tab>b<tab>' to 'fmuellner, bastianilso: ', which doesn't work for commands.
Comment 4 Kunaal Jain 2016-02-14 09:50:18 UTC
So I started working on this. Moving in direction as discussed with Florian on IRC. 

Couple of questions :

1.) Should we use the same list as used by nicks and just add '/' commands to the list? I am in favor of this, as we can reuse all the code in tabCompletion.js :-) 

2.) If yes for same list, can IRC nicks start with '/'? As this can be problem for us, since on each event(nick change, user joins/leaves) we recreate the list of nicks from scratch. Rather than adding all the '/' commands on each update, we can add during init() and when updating, recreate the list except adding again the '/' commands.
Comment 5 Florian Müllner 2016-02-14 14:54:00 UTC
(In reply to Kunaal Jain from comment #4)
> So I started working on this. Moving in direction as discussed with Florian
> on IRC. 
> 
> Couple of questions :
> 
> 1.) Should we use the same list as used by nicks and just add '/' commands
> to the list? I am in favor of this, as we can reuse all the code in
> tabCompletion.js :-) 

I'm in favor of this as well.


> 2.) If yes for same list, can IRC nicks start with '/'?

Not according to the original specification[0], and I don't think later additions changed that.

[0] https://tools.ietf.org/html/rfc1459#section-2.3.1


> on each event(nick change, user joins/leaves) we
> recreate the list of nicks from scratch. 

Yeah, I don't think we hit quite the right balance between not doing unnecessary work and having tab completion work instantly. Maybe one option would be to store completions as a list of strings and then only create widgets for those that are actually needed (e.g. with 'a<tab>', we filter the list for entries that start with 'a', make sure we have a widget for it and fill the popup). But that's not quite in the scope of this bug :-)


> Rather than adding all the '/'
> commands on each update, we can add during init() and when updating,
> recreate the list except adding again the '/' commands.

Mmh, it's a bit ugly that the completion starts caring about what it completes, but I guess that's something we'll have to do anyway for the insertion part ...
Comment 6 Kunaal Jain 2016-02-14 18:37:11 UTC
(In reply to Florian Müllner from comment #5)
> (In reply to Kunaal Jain from comment #4)
> > So I started working on this. Moving in direction as discussed with Florian
> > on IRC. 
> > 
> > Couple of questions :
> > 
> > 1.) Should we use the same list as used by nicks and just add '/' commands
> > to the list? I am in favor of this, as we can reuse all the code in
> > tabCompletion.js :-) 
> 
> I'm in favor of this as well.
> 

:-) 

> 
> > 2.) If yes for same list, can IRC nicks start with '/'?
> 
> Not according to the original specification[0], and I don't think later
> additions changed that.
> 
> [0] https://tools.ietf.org/html/rfc1459#section-2.3.1
> 
> 
> > on each event(nick change, user joins/leaves) we
> > recreate the list of nicks from scratch. 
> 
> Yeah, I don't think we hit quite the right balance between not doing
> unnecessary work and having tab completion work instantly. Maybe one option
> would be to store completions as a list of strings and then only create
> widgets for those that are actually needed (e.g. with 'a<tab>', we filter
> the list for entries that start with 'a', make sure we have a widget for it
> and fill the popup). But that's not quite in the scope of this bug :-)
> 
> 

Will file another bug for that 

> > Rather than adding all the '/'
> > commands on each update, we can add during init() and when updating,
> > recreate the list except adding again the '/' commands.
> 
> Mmh, it's a bit ugly that the completion starts caring about what it
> completes, but I guess that's something we'll have to do anyway for the
> insertion part ...

Yes for '/' have to care whether it is at starting or not, and not to insert ": " with it.
Comment 7 Kunaal Jain 2016-02-14 18:40:53 UTC
Created attachment 321146 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly IRC commands are inserted in the beginning, and
there is no chaining of commands.
Comment 8 Florian Müllner 2016-02-15 23:38:55 UTC
Review of attachment 321146 [details] [review]:

::: src/tabCompletion.js
@@ +7,3 @@
+const IRCCommands = ["/HELP", "/INVITE", "/JOIN", "/KICK", "/ME", "/MSG",
+                     "/NAMES", "/NICK", "/PART", "/QUERY", "/QUIT", "/SAY",
+                     "/TOPIC"];

Maintaining a separate list of implemented commands is a bit ugly:

@@ +43,3 @@
         this._widgetMap = {};
+
+        for (let i = 0; i < IRCCommands.length; i++) {

You could do:

let commands = Object.keys(IrcParser.knownCommands);
for (let i = 0; i < commands.length; i++) {
    row._text = '/' + commands[i];
    ...

@@ +164,2 @@
     _getRowCompletion: function(row) {
+        if ((this._startPos == 0 || this._previousCompletion) && !this._isIRCCommand)

Commands are always followed by a space, so it makes sense to insert that. We'd have to figure out another way to disable chaining in that case though.

@@ +180,3 @@
+            return row._casefoldedText.startsWith(this._key) && row._casefoldedText.startsWith('/');
+        }
+        return row._casefoldedText.startsWith(this._key) && !row._casefoldedText.startsWith('/');

I don't understand this code - if we are completing a command, this._key is something like '/j', no? So "row._casefoldedText.startsWith(this._key);" should do the right thing in either case.

@@ +205,3 @@
         this._startPos = text.lastIndexOf(' ') + 1;
         this._key = text.toLowerCase().substr(this._startPos);
+        this._isIRCCommand = false;

Or simply:
  this._isIRCCommand = (this._startPos == 0 && this._key.startsWith('/');

Though I'd reconsider restricting command completions to the start of line - they don't actually work elsewhere, but they can still be mentioned:
 'you can get a list of supported command by typing /h<tab>'
Comment 9 Kunaal Jain 2016-02-16 09:50:42 UTC
(In reply to Florian Müllner from comment #8)
> Review of attachment 321146 [details] [review] [review]:
> 
> ::: src/tabCompletion.js
> @@ +7,3 @@
> +const IRCCommands = ["/HELP", "/INVITE", "/JOIN", "/KICK", "/ME", "/MSG",
> +                     "/NAMES", "/NICK", "/PART", "/QUERY", "/QUIT", "/SAY",
> +                     "/TOPIC"];
> 
> Maintaining a separate list of implemented commands is a bit ugly:
> 
> @@ +43,3 @@
>          this._widgetMap = {};
> +
> +        for (let i = 0; i < IRCCommands.length; i++) {
> 
> You could do:
> 
> let commands = Object.keys(IrcParser.knownCommands);
> for (let i = 0; i < commands.length; i++) {
>     row._text = '/' + commands[i];
>     ...


Thanks I was trying to do this only. But didn't know about Object.keys function :-(

> 
> @@ +164,2 @@
>      _getRowCompletion: function(row) {
> +        if ((this._startPos == 0 || this._previousCompletion) &&
> !this._isIRCCommand)
> 
> Commands are always followed by a space, so it makes sense to insert that.
> We'd have to figure out another way to disable chaining in that case though.

Yup, I deliberately didn't insert space to prevent chaining. Well there is a tradeoff between the space and code complexity to disable chaining in that case. Would again try to simplify code.

> 
> @@ +180,3 @@
> +            return row._casefoldedText.startsWith(this._key) &&
> row._casefoldedText.startsWith('/');
> +        }
> +        return row._casefoldedText.startsWith(this._key) &&
> !row._casefoldedText.startsWith('/');
> 
> I don't understand this code - if we are completing a command, this._key is
> something like '/j', no? So "row._casefoldedText.startsWith(this._key);"
> should do the right thing in either case.

Yup, but I did it for code readability. 

> 
> @@ +205,3 @@
>          this._startPos = text.lastIndexOf(' ') + 1;
>          this._key = text.toLowerCase().substr(this._startPos);
> +        this._isIRCCommand = false;
> 
> Or simply:
>   this._isIRCCommand = (this._startPos == 0 && this._key.startsWith('/');
> 
> Though I'd reconsider restricting command completions to the start of line -
> they don't actually work elsewhere, but they can still be mentioned:
>  'you can get a list of supported command by typing /h<tab>'

umm, that's a rare case about mentioning the commands in between chats. We can either support the usability case where the commands comes in starting, or for general case, where we provide auto-completion in between too. We would have to handle the case separately in that case too, as not to have ':' after completion, no chaining.
Comment 10 Kunaal Jain 2016-02-16 10:42:56 UTC
Created attachment 321354 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly IRC commands are inserted in the beginning, and
there is no chaining of commands.
Comment 11 Florian Müllner 2016-02-16 14:24:35 UTC
Review of attachment 321354 [details] [review]:

::: src/tabCompletion.js
@@ +40,2 @@
         this._widgetMap = {};
+        this._isLastIRCCompletion = false;

Bad name: "is last IRC completion" == "this is the last IRC completion, there will be no following completions".
_lastWasIRCCommandCompletion would be better, though I'd use "previous" instead of "last" for consistency with _previousCompletion and leave out superfluous bits from the name to make it more readable - my suggestion would be _previousWasCommand

@@ +41,3 @@
+        this._isLastIRCCompletion = false;
+
+        let IRCCommands = Object.keys(IrcParser.knownCommands);

Normal variables are camelCase, CamelCase is used for modules. Admittedly ircCommands looks a bit odd, but you could just use 'commands' - it's quite clear from the context what kind of commands are meant (not only because they come from a module called 'IrcParser', but also because polari is an IRC client ;-) )

@@ +166,3 @@
+            return row._text + ' ';
+        }
+        this._isLastIRCCompletion = false;

More concise as:

this._isLastIRCCompletion = this._isIRCCommand;
if (this._isIRCCommand)
    return row._text + ' ';
else if (...)

@@ +183,3 @@
+        if (this._isIRCCommand)
+            return row._casefoldedText.startsWith(this._key);
+        return row._casefoldedText.startsWith(this._key) && !row._casefoldedText.startsWith('/');

OK, so the reason you have two cases here is that you artificially restrict /command completion to the beginning of the line. You are right that it's not super common (except in combination with /SAY, where it's a primary use case), which can be a reason to not add complexity to support it - but here you *are* adding complexity to *not* support it, which doesn't make sense - remove the limitation on isIRCCommand, and you don't have to touch this code at all.
Comment 12 Kunaal Jain 2016-02-16 14:43:11 UTC
Created attachment 321391 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly IRC commands are inserted in the beginning, and
there is no chaining of commands.
Comment 13 Kunaal Jain 2016-02-16 15:13:08 UTC
Created attachment 321405 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly IRC commands are inserted in the beginning, and
there is no chaining of commands.
Comment 14 Kunaal Jain 2016-02-16 15:15:12 UTC
Created attachment 321406 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly IRC commands are inserted in the beginning, and
there is no chaining of commands.
Comment 15 Kunaal Jain 2016-02-16 15:21:48 UTC
Created attachment 321408 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly IRC commands are inserted in the beginning, and
there is no chaining of commands.
Comment 16 Kunaal Jain 2016-02-16 15:34:13 UTC
Created attachment 321412 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Provide tab based auto-completion for IRC commands,
similar to what we do for nicks with little modifications,
mainly there is no chaining of commands and no ':' is inserted
after a command.
Comment 17 Kunaal Jain 2016-02-16 15:36:54 UTC
Comment on attachment 321412 [details] [review]
tabCompletion: Provide auto-completion for implemented IRC commands

Attachment 321412 [details] pushed as 68758ea - tabCompletion: Provide auto-completion for implemented IRC commands
Comment 18 Kunaal Jain 2016-02-16 16:47:12 UTC
Created attachment 321423 [details] [review]
tabCompletion: Don't chain for auto-completion of command

In commit 68758ea we added support for auto-completion
of IRC commands. We should not chain completion if the current
or the previous completion was of command.
Comment 19 Florian Müllner 2016-02-16 17:38:57 UTC
Review of attachment 321423 [details] [review]:

Looks good, though I got a suggestion for a somewhat related cleanup, see below.

In the commit message:
 - "We should not chain completion" should be "We should not chain completions"
 - "was of command" => "was a command"

::: src/tabCompletion.js
@@ +212,3 @@
+        // In case current or the last completion was for IRC Command, don't chain.
+        let shouldChain = !this._isIRCCommand && !this._previousWasCommand;
+        this._previousCompletion = (this._endPos == this._startPos) && shouldChain;

I haven't tested it, but the code looks like it should work. There's something not quite related to the fix though: _previousCompletion has really become a misnomer now, as it may be false even when there's a preceding completion. This is probably a good opportunity to fix this by changing the above to:

  // Chain completions if the current completion directly follows a previous one,
  // except when one of them was for an IRC command
  let previousCompletion = (this._endPos == this._startPos);
  this._isChained = previousCompletion && !this._isIRCCommand && !this._previousWasCommand;

then change _previousCompletion to _isChained in the rest of the code.
Comment 20 Kunaal Jain 2016-02-16 20:50:05 UTC
Created attachment 321438 [details] [review]
tabCompletion: Don't chain for auto-completion of command

In commit 68758ea we added support for auto-completion
of IRC commands. We should not chain completions if the current
or the previous completion was a command. Also
_previousCompletion is a misnomer, use _isChained instead.
Comment 21 Kunaal Jain 2016-02-16 20:50:31 UTC
Created attachment 321439 [details] [review]
tabCompletion: Rename variable isIRCCommand to isCommand

It's quite clear from context, that by command, we mean
IRC command. Other variables in tabComplelion use Command
instead of IRCCommand, so rename the variable isIRCCommand
to isCommand.
Comment 22 Kunaal Jain 2016-02-16 20:51:46 UTC
Created attachment 321441 [details] [review]
tabCompletion: Rename variable isIRCCommand to isCommand

It's quite clear from context, that by command, we mean
IRC command. Other variables in tabCompletion use Command
instead of IRCCommand, so rename the variable isIRCCommand
to isCommand.
Comment 23 Florian Müllner 2016-02-16 21:00:35 UTC
Review of attachment 321441 [details] [review]:

Sure
Comment 24 Florian Müllner 2016-02-16 21:01:24 UTC
Review of attachment 321438 [details] [review]:

LGTM
Comment 25 Kunaal Jain 2016-02-16 21:05:10 UTC
Attachment 321438 [details] pushed as 4ee97c5 - tabCompletion: Don't chain for auto-completion of command
Attachment 321441 [details] pushed as cc93369 - tabCompletion: Rename variable isIRCCommand to isCommand