Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Suggestions to improve FileNameCompleter #413

Closed
cbeust opened this issue Jul 7, 2019 · 11 comments
Closed

Suggestions to improve FileNameCompleter #413

cbeust opened this issue Jul 7, 2019 · 11 comments
Milestone

Comments

@cbeust
Copy link

cbeust commented Jul 7, 2019

I'm currently writing a Kotlin Shell using JLine (http://github.com/cbeust/kash) and I can't seem to do what I want with either the existing Completers.FileNameCompleter or my own.

Specifically, two features I can't get to work or would like to have from FileNameCompleter:

  • Have the completer run from an arbitrary directory and not just the current directory at the time of instantiation. Right now, as soon as the completer is instantiated, it will always try to complete from whatever the current directory was. This could be implemented by having the constructor accept a lambda that returns the directory to run the completions from, defaulting to the current dir.

  • If I have a directory ~/java, typing ~/j<TAB> should complete it, but I can't get this to work. Completers.FileNameCompleter doesn't seem to support this at all and my efforts to make this work with my own completer failed because the implementation does some further pattern matching that fails on that pattern.

gnodet added a commit that referenced this issue Jul 8, 2019
@gnodet
Copy link
Member

gnodet commented Jul 8, 2019

The first part is fixed. For the second one, that's weird, because it seems to work correctly in the demo at least for the completion (some commands fail to actually resolve the file containing a ~). The relevant code is:
https://github.com/jline/jline3/blob/master/builtins/src/main/java/org/jline/builtins/Completers.java#L301-L310

@cbeust
Copy link
Author

cbeust commented Jul 8, 2019

Bonjour Guillaume,

I am familiar with that code (I've pored over the JLine 3 source code quite a bit :-)) and the problem is not here but in the caller code. Once the candidates are returned from the completer in the code you highlighted, some additional pattern matching is done and in the end, these candidates still end up being eliminated.

Try it yourself: can you get the ~/j example to successfully show ~/java as a candidate? Maybe I missed something obvious.

The first part is fixed.

Can you elaborate? Is this coming up in the next version?

Thanks!

@gnodet
Copy link
Member

gnodet commented Jul 8, 2019

Bonjour Guillaume,

I am familiar with that code (I've pored over the JLine 3 source code quite a bit :-)) and the problem is not here but in the caller code. Once the candidates are returned from the completer in the code you highlighted, some additional pattern matching is done and in the end, these candidates still end up being eliminated.

Try it yourself: can you get the ~/j example to successfully show ~/java as a candidate? Maybe I missed something obvious.

Yes, it does work for me. I'm running the ./jline-gogo.sh script
image

The first part is fixed.

Can you elaborate? Is this coming up in the next version?

Yes, the changes are here: a1f2c93. They should be part of 3.13.0.

@cbeust
Copy link
Author

cbeust commented Jul 10, 2019

Never mind, this appears to work now. Not sure what I did wrong but I did miss something. Deleting my comment above.

@gnodet
Copy link
Member

gnodet commented Jul 11, 2019

Fwiw, the reason for the completers to return all candidates unfiltered is that we allow some special matching to be done later. For example, typo correction has to be done on all candidates to be able to select close candidates, not only the ones that strictly match.

@gnodet gnodet closed this as completed Jul 11, 2019
@cbeust
Copy link
Author

cbeust commented Jul 11, 2019

Mmmh... maybe I spoke too fast. Now trying this on Windows 10, and neither my own code nor jline3-gogo.sh work in that scenario (using 3.12.1).

@cbeust
Copy link
Author

cbeust commented Jul 11, 2019

Related question: how do you debug TAB completion in IDEA? (assuming that's your IDE).

Running my shell in the IDEA console, TAB doesn't complete (probable because it's intercepted by the IDE). Is it possible to change the auto complete key to something else than TAB?

@gnodet
Copy link
Member

gnodet commented Jul 11, 2019

The problem may be specific to Windows...

In order to debug the demo, you can launch it with the debug or debugs parameter which will start the application with the debugger agent so that you can simply attach the debugger to it from your IDE.

The key bindings can be changed at will, but you can also try with Ctrl+I which should have the same effect than <tab>. If you're using the demo, you can use the keymap command to bind keys to actions and put it in the etc/gosh_profile script which is executed at the start:

keymap -M main "^I" expand-or-complete

@gnodet gnodet reopened this Jul 11, 2019
@cbeust
Copy link
Author

cbeust commented Jul 11, 2019

I can debug fine, it's just that the TAB character is being captured by IDEA before JLine can see it.

Can I remap the autocomplete character to something else than TAB? I'd like to pick something a bit complicated so that the IDE won't intercept it, which would make it easier for me to find out what's going on in the pattern matching in Windows.

@gnodet
Copy link
Member

gnodet commented Jul 11, 2019

You can use the following java code:

lineReader.getKeys().bind(new Reference(widget), keySequence);

where widget is LineReader.EXPAND_OR_COMPLETE for the completion, and keySequence is the key sequence you want to bind.

@cbeust
Copy link
Author

cbeust commented Jul 12, 2019

Spent some time debugging the issue on Windows and it appears to be caused by this line:

        String sep = getUserDir().getFileSystem().getSeparator();

The separator returned is \, but I'm using Cmder, where the separator is /. In other words, in this shell, I type "ls /Users/cedric" (same thing on cygwin, WSL, etc...).

I think this code should become separator neutral, i.e. replace all the \ with / in the line and then match only on these forward slashes.

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

3 participants