jline / jline3

JLine is a Java library for handling console input.
Other
1.49k stars 218 forks source link

Nesting RegexCompleters only completes first word #1069

Closed maxbechtold closed 1 month ago

maxbechtold commented 2 months ago

I'm having trouble getting nested RegexCompleters to work even though I've read nothing that speaks against it. Here's a reproduction example, I'm using JLine 3.26.3 on Windows 10, JDK 17. The LineReader options don't seem to make a difference.

Initially, Tab completes the line to "Word-A", but following this there's no further suggestion/candidate, although the grammar "a b" implies "Word-B" as the only viable text to follow.

What am I missing?

import org.jline.builtins.Completers;
import org.jline.reader.Completer;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) throws IOException {
        Terminal terminal = TerminalBuilder.builder()
            .system(true)
            .build();

        LineReader lineReader = LineReaderBuilder.builder()
            .terminal(terminal)
            .option(LineReader.Option.CASE_INSENSITIVE, true)
            .option(LineReader.Option.DISABLE_EVENT_EXPANSION, true)
            .completer(buildCompleter())
            .build();
        lineReader.readLine();
    }

    private static Completer buildCompleter() {
        Map<String, Completer> map = new HashMap<>();
        map.put("0", new Completers.RegexCompleter("a b", s -> {
            if ("a".equals(s)) {
                return new StringsCompleter("Word-A");
            }
            return new StringsCompleter("Word-B");
        }));
        return new Completers.RegexCompleter("0", map::get);
    }

}
maxbechtold commented 2 months ago

One more note, my intent is to split a command system of about 30 commands into separate RegexCompleters. But I guess just chaining all in a long <C1-syntax> | <C2-syntax> |... <C30-syntax> syntax for a single RegexCompleter is also feasible

gnodet commented 2 months ago

@maxbechtold I'm not sure exactly why your example does not work, but here's a working one: https://github.com/jline/jline3/blob/4ccf282c91daa0fc96ed6030e053dd28a4aba342/builtins/src/test/java/org/jline/example/Example.java#L328-L335

The fact that you're using 2 regex completers seems problematic.

gnodet commented 2 months ago

One more note, my intent is to split a command system of about 30 commands into separate RegexCompleters. But I guess just chaining all in a long <C1-syntax> | <C2-syntax> |... <C30-syntax> syntax for a single RegexCompleter is also feasible

You should try the TreeCompleter which is more user friendly than the RegexCompleter, it actually uses it underneath, but the tree structure makes it easier to deal with.