Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Tab sizes in LineReader and System.out.println() are not the same (with LineReader.Option.INSERT_TAB) #861

Closed
aaroncarsonart opened this issue Aug 30, 2023 · 1 comment
Milestone

Comments

@aaroncarsonart
Copy link

Using an implementation such as the following:

private LineReader buildLineReader() {
    return LineReaderBuilder.builder()
            .parser(new CustomJLineParser())
            .completer(NullCompleter.INSTANCE)
            .option(LineReader.Option.DISABLE_EVENT_EXPANSION, true)
            .option(LineReader.Option.INSERT_TAB, true)
            .variable(LineReader.SECONDARY_PROMPT_PATTERN, REPL_SECONDARY_PROMPT)
            .build();
    }

I have two questions:

1. LineReader representation of tab character

My REPL supports inserting indentation using the tab character. And, I can verify that the actual program input received from jline is in fact a tab character. However, jline presents the tab as 4 space characters on the command line. This causes issues with my error reporting mechanism, which assumes the user input's tab spacing is the same as System.out.println("\t") which formats a tab as a single character spanning 8 characters on my machine (macOS 12.6 Terminal app). I know this setting may vary across environments (even my shell zsh displays a tab as 8 spaces, but treats them as tabs when backspacing), so I would prefer not to alter my error reporting output to convert tabs to a set number of spaces for REPL output.

So is there a way to configure what actual character(s) are inserted/displayed when the tab character is pressed? Can it be an actual tab, instead of spaces? Also, are tabs guaranteed to always be 4 spaces, no matter what environment or OS my program utilizing jline is executed?

2. Typing a tab after non-whitespace characters

And also, a second, related issue. I see no way to type a tab character after a non-whitespace character has been typed. It simply beeps, and does nothing. However, a copied tab character can still be pasted. So is there a way to enable typing of a tab at any arbitrary point of user input?

@gnodet
Copy link
Member

gnodet commented Oct 23, 2023

I have two questions:

1. LineReader representation of tab character

My REPL supports inserting indentation using the tab character. And, I can verify that the actual program input received from jline is in fact a tab character. However, jline presents the tab as 4 space characters on the command line. This causes issues with my error reporting mechanism, which assumes the user input's tab spacing is the same as System.out.println("\t") which formats a tab as a single character spanning 8 characters on my machine (macOS 12.6 Terminal app). I know this setting may vary across environments (even my shell zsh displays a tab as 8 spaces, but treats them as tabs when backspacing), so I would prefer not to alter my error reporting output to convert tabs to a set number of spaces for REPL output.

So is there a way to configure what actual character(s) are inserted/displayed when the tab character is pressed? Can it be an actual tab, instead of spaces? Also, are tabs guaranteed to always be 4 spaces, no matter what environment or OS my program utilizing jline is executed?

2. Typing a tab after non-whitespace characters

And also, a second, related issue. I see no way to type a tab character after a non-whitespace character has been typed. It simply beeps, and does nothing. However, a copied tab character can still be pasted. So is there a way to enable typing of a tab at any arbitrary point of user input?

Tab key is bound by default to expand-or-complete widget. If you bind it to self-insert, the tab character should be inserted in all cases. If you hit backspace, the tab character will be deleted.
But you'll loose completion. Is that what you want ?

As for displaying, tabs are hard-coded to 4 spaces:
https://github.com/jline/jline3/blob/master/reader/src/main/java/org/jline/reader/impl/LineReaderImpl.java#L73
But that should only be for display, the returned string should contain a tab.
There's currently no way to change that.

Proper handling of tabulations has never been implemented. The AttributedStringBuilder does support any kind of tabs. Terminals are theoretically able to support setting tabs using set_tab and clear_all_tabs, but as you've seen, the LineReader does not actually use those tabulations during editing. I don't really plan to change that, however, adding a constant to specify the tab width (i.e. be able to change from 4 to 8 spaces for tabs) during edition, is definitely something that can be considered.

gnodet added a commit to gnodet/jline3 that referenced this issue Oct 23, 2023
@gnodet gnodet closed this as completed Oct 24, 2023
@gnodet gnodet added this to the 3.24.0 milestone Oct 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants