peterh / liner

Pure Go line editor with history, inspired by linenoise
MIT License
1.05k stars 132 forks source link

should tabComplete return when only one completion candidate is returned? #36

Closed abates closed 9 years ago

abates commented 9 years ago

Should the tab completion function return control back to the main loop in Prompt if the completer only returns a single completion candidate?

This would be here: line.go L255-L259

and look something like

head, list, tail := s.completer(string(line), pos)
if len(list) <= 0 {
     return line, pos, rune(esc), nil
}
hl := utf8.RuneCountInString(head)

if (len(list) == 1) {
     return []rune(head + list[0] + tail), hl + utf8.RuneCountInString(list[0]), rune(esc), nil
}

Doing this will allow multiple successive tab completions. If I'm writing a prompt that can change directories, then I'm going to (possibly) successively tab through directory completions without typing a key other than TAB.

I'm not sure if the current behavior (exiting tabComplete only on another keypress) is expected when there is only a single completion or not.

Thanks! Andrew

abates commented 9 years ago

Actually, I just realized that it still wouldn't quite work as expected since I would expect to fall out of tabComplete the moment there is an exact match, not just when there is only one match... Seems like the behavior I'm talking about would be incompatible with the circular tab completer, since each tab brings up another exact match.

Andrew

peterh commented 9 years ago

Falling out of tab when there is a single match (to let the completion function run again for the next path component or whatever) sounds reasonable to me.

Falling out on an exact match isn't the right thing. Bash doesn't fall out on an exact match either. Given a directory with "foo", "food", and "foot", pressing fooTAB causes a beep, and the next tab prints foo food foot.

Pressing fTAB in bash (GNU bash, version 4.3.30(1) as installed with Ubuntu 14.10) is weird ; the first tab fills in "foo" and beeps, the 2nd tab just beeps, and the third tab prints foo food foot. I would have expected the 1st tab to beep, and the 2nd tab to print. Upon further testing, removing "foo" still results in the same behaviour. Looks like you either need numTabs to count up to 3, or some way to fall out of tabComplete and restart only if there's a common prefix that is longer than the match token. Either way, if you find this behaviour desirable, the match token probably needs to be calculated and passed into printedTabs().

abates commented 9 years ago

I tested this tonight and it works more closely to what I would expect. I've submitted PR #37 for review. I can make the changes regarding 1 tab = longest common prefix/beep, 2 tabs = nothing, 3 tabs = print candidates if that's something you'd like to pursue

peterh commented 9 years ago

No, that's not something I'd like to pursue. I prefer the current behaviour (but it's a really mild preference, since I don't usually use TabPrints). I only mentioned it in case you care.

Thanks for the pull request. It sounds like nobody is interested in three tabs, so I'm going to close this. Feel free to re-open (or better yet, submit a pull request) if I have misunderstood.