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

feat(cli): add the feature to turn of WRAP for CLI output #3341

Merged
merged 5 commits into from
Sep 24, 2019

Conversation

agavra
Copy link
Contributor

@agavra agavra commented Sep 12, 2019

fixes #3336

Description

  • custom CLI settings are set using Oracle-like SET CLI PROPERTY VALUE syntax (which is different from SET property=value KSQL syntax)... perhaps this is confusing so I'm open to suggestions
  • SET CLI WRAP ON/OFF toggles line wrapping (see example below)
ksql> SELECT * FROM FOOZ EMIT CHANGES;
+------------------------------------+------------------------------------+------------------------------------+------------------------------------+------------------------------------+
|ROWTIME                             |ROWKEY                              |FOO                                 |BAR                                 |BAZ                                 |
+------------------------------------+------------------------------------+------------------------------------+------------------------------------+------------------------------------+
|1568310477336                       |null                                |hello                               |world                               |no clip                             |
|1568311062781                       |null                                |hello                               |world                               |clip all the things because this is |
|                                    |                                    |                                    |                                    |such a long string!                 |
|1568311085195                       |null                                |what about also clipping something t|world                               |clip all the things because this is |
|                                    |                                    |hat is in the beginning?            |                                    |such a long string!                 |
ksql> SET CLI WRAP OFF;
ksql> SELECT * FROM FOOZ EMIT CHANGES;
+------------------------------------+------------------------------------+------------------------------------+------------------------------------+------------------------------------+
|ROWTIME                             |ROWKEY                              |FOO                                 |BAR                                 |BAZ                                 |
+------------------------------------+------------------------------------+------------------------------------+------------------------------------+------------------------------------+
|1568310477336                       |null                                |hello                               |world                               |no clip                             |
|1568311062781                       |null                                |hello                               |world                               |clip all the things because this ...|
|1568311085195                       |null                                |what about also clipping somethin...|world                               |clip all the things because this ...|
^CQuery terminated

The help message:

set cli <property> <value>:
	Sets a CLI local property. NOTE that this differs from setting a KSQL property with 'SET property=value' in that it does not affect the server.

TODO

  • @JimGalasyn @rmoff - how do you suggest we show all available CLI settings? I think we should be able to link to some documentation that is auto-generated by CliConfig, but I'm not sure how to get that working

Testing done

  • Some unit tests
  • E2E CLI testing (see output above)

Reviewer checklist

  • Ensure docs are updated if necessary. (eg. if a user visible feature is being added or changed).
  • Ensure relevant issues are linked (description should include text like "Fixes #")

@agavra agavra requested a review from rmoff September 12, 2019 19:55
@agavra agavra requested a review from a team as a code owner September 12, 2019 19:55
@vcrfxia
Copy link
Contributor

vcrfxia commented Sep 16, 2019

custom CLI settings are set using Oracle-like SET PROPERTY VALUE syntax (which is different from SET property=value KSQL syntax)... perhaps this is confusing so I'm open to suggestions

My gut says this is confusing. Maybe we can have another command such as cli-config to display available CLI properties and their current values, and then use cli-config set wrap <on/off> in order to set configs, to make explicit that we're setting a CLI property rather than a KSQL property? I don't love this suggestion either, but I hope we can agree on something since we do have quite a few CLI properties (output, request-pipelining, and maybe even server) so I like the suggestion of centralizing these properties and normalizing how they're set.

@rmoff
Copy link
Contributor

rmoff commented Sep 17, 2019

Yeah, I think this is going to be confusing:

SET 'auto.offset.reset' = 'earliest';
SET WRAP OFF;

Do we need to introduce a SERVER keyword?

SET SERVER 'auto.offset.reset' = 'earliest';
SET WRAP OFF;

Or inverted and probably easier to add on top of what we've got:

SET 'auto.offset.reset' = 'earliest';
SET CLI WRAP OFF;

@agavra
Copy link
Contributor Author

agavra commented Sep 17, 2019

thanks for the suggestions @rmoff @vcrfxia! I'm happy with SET CLI WRAP OFF, I think it's intuitive and backwards compatible.

@big-andy-coates
Copy link
Contributor

big-andy-coates commented Sep 18, 2019

Thinking into the future... we are likely at some point to allow people to set their own date and time formats. This is pretty common functionality.

SET DATEFORMAT yyyy-MM-dd

What's interesting here is that this would likely be both a client setting, as we'd use it in the CLI to format dates, and also potentially a server setting, i.e. it's passed to the server to allow it to parse supplied date.

So... do we really want to differentiate?

Also, why should the user care if the property is affecting the client or the server? Take WRAP - should the user care if its the server doing the wrapping before sending the output to the client, of the client doing it locally?

Just throwing that out there for thought! ;)

Copy link
Contributor

@big-andy-coates big-andy-coates left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @agavra

LGTM, 'cept I'm left wondering what was gained by moving the maybeHandleCliSpecificCommands call into the CLI aside from more code and having to take the line the console returned and immediately ask that same console if this is actually an internal command it should handle... I don't get it.

Plus see comment above about syntax.

@big-andy-coates big-andy-coates requested a review from a team September 18, 2019 16:14
@agavra
Copy link
Contributor Author

agavra commented Sep 18, 2019

Thanks for the review @big-andy-coates!

LGTM, 'cept I'm left wondering what was gained by moving the maybeHandleCliSpecificCommands call into the CLI aside from more code and having to take the line the console returned and immediately ask that same console if this is actually an internal command it should handle... I don't get it.

Every single time I've looked at this code, I have to dig through and find where we handle the CLI specific commands. I think it makes a lot of sense to have the code be:

  1. read line
  2. handle line

instead of

  1. read and maybe handle some lines
  2. handle the other lines

IMO, whether a command is CLI-specific or not should be part of "handling" not "reading".

@agavra
Copy link
Contributor Author

agavra commented Sep 18, 2019

@big-andy-coates - with regards to syntax, I suppose it doesn't matter except that otherwise I need to dig into the contents of the command to figure out whether it's a CLI property or not. That seems... undesirable.

@big-andy-coates
Copy link
Contributor

Thanks for the review @big-andy-coates!

LGTM, 'cept I'm left wondering what was gained by moving the maybeHandleCliSpecificCommands call into the CLI aside from more code and having to take the line the console returned and immediately ask that same console if this is actually an internal command it should handle... I don't get it.

Every single time I've looked at this code, I have to dig through and find where we handle the CLI specific commands. I think it makes a lot of sense to have the code be:

  1. read line
  2. handle line

instead of

  1. read and maybe handle some lines
  2. handle the other lines

IMO, whether a command is CLI-specific or not should be part of "handling" not "reading".

IMHO the change makes the code worse, not better. As I see it you've changed:

Cli -> get next line to execute from Console
Console -> read input, handle any internal commands, return any non-internal
Cli -> handle not internal line

To

Cli -> get next line to execute from Console
Console -> read line and return it
Cli -> call into Console to see it its an internal command and if it is have the console handle it.
-> otherwise execute it

IMHO this is breaking encapsulation. Previously only the Console knew about the internal commands. It dealt with them. Now the Cli needs to know about them too, but only in so much as to ask the console to handle any of the lines the console just returned.

To put it another way - previously the Console returned any lines it couldn't handle to the Cli. Now the Console returns all lines, only for the Cli to have to immediately pass them back to the Console to see if it can handle them. What's the point?

Maybe if you were to revert this change and then rename Console.readLine to getNextStatement or something it would make more sense to you?

I totally agree the architecture of the CLI is questionable. But I don't think this change helps. It actually couples code more, rather than less.

Copy link
Contributor

@big-andy-coates big-andy-coates left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @agavra

I'm still not liking the move of the Cli specific command handling as I noted above.

Also, just a thought... but in terms of the functionality this PR provides I'm not sure WRAP is the right name. Maybe this is a standard thing, but for me I would not expect any clipping of output to be controlled by WRAP. I would of expected WRAP ON to cause long lines to be wrapped over multiple lines and WRAP OFF to mean long lines mean wide columns.

The functionalty feels to me like it would be better called CLIPPING. OFF means long output and ON means truncated/clipped.

Don't know if the WRAP was inspired by other similar features on other DBs, but I think its a poor name.

@agavra
Copy link
Contributor Author

agavra commented Sep 19, 2019

@big-andy-coates - okay, I will change the readline method back. This syntax was inspired by Oracles SqlPlus: https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12040.htm where they use WRAP OFF:

Controls whether to truncate the display of a selected row if it is too long for the current line width. OFF truncates the selected row; ON enables the selected row to wrap to the next line.

@agavra agavra requested a review from a team September 19, 2019 16:52
@big-andy-coates
Copy link
Contributor

@big-andy-coates - okay, I will change the readline method back. This syntax was inspired by Oracles SqlPlus: https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12040.htm where they use WRAP OFF:

Fair enough, I wondered if that was the case.

Though... I thought you always looked to Postgres for inspiration - what's with following SqlPlus?!?!? :p

Copy link
Contributor

@big-andy-coates big-andy-coates left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @agavra LGTM 'cept for a possible put in the clipping

&& parts.subList(rowsToPrint, parts.size())
.stream()
.map(String::trim)
.noneMatch(String::isEmpty);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// clip if there are more than one line and any of the remaining lines are non-empty

Isn't this check "if there are more than one line and NO LINES ARE EMPTY". So it would return false if there are multiple lines and one is empty.

I think maybe you want '! parts....allMatch(String::isEmpty)'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! added a test for it

ksql-cli/src/test/java/io/confluent/ksql/cli/CliTest.java Outdated Show resolved Hide resolved
@agavra agavra merged commit 3814c71 into confluentinc:master Sep 24, 2019
@agavra agavra deleted the clip_cli branch September 24, 2019 15:38
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

Successfully merging this pull request may close these issues.

CLI needs option to truncate field output instead of wrapping it
4 participants