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

[Console] Add Cursor class to control the cursor in the terminal #27444

Merged
merged 1 commit into from Apr 12, 2020

Conversation

pierredup
Copy link
Contributor

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets N/A
License MIT
Doc PR TBD

Add a new Cursor class to the Console component, that allows to manipulate the cursor in the terminal.

Options to move the cursor include: moveUp, moveDown, moveLeft, moveRight, show, hide, save and restore position, get current position etc.

Example usage:

$cursor = new Cursor($output);

$parts = [
    ['x' => 9, 'y' => 5, 'string' => '#'],
    ['x' => 9, 'y' => 7, 'string' => '#'],
    ['x' => 2, 'y' => 7, 'string' => '#####'],
    ['x' => 9, 'y' => 1, 'string' => '#######'],
    ['x' => 7, 'y' => 6, 'string' => '#'],
    ['x' => 9, 'y' => 2, 'string' => '#'],
    ['x' => 9, 'y' => 6, 'string' => '#'],
    ['x' => 9, 'y' => 3, 'string' => '#'],
    ['x' => 2, 'y' => 1, 'string' => '#####'],
    ['x' => 7, 'y' => 2, 'string' => '#'],
    ['x' => 9, 'y' => 4, 'string' => '#####'],
    ['x' => 1, 'y' => 2, 'string' => '#'],
    ['x' => 1, 'y' => 6, 'string' => '#'],
    ['x' => 2, 'y' => 4, 'string' => '#####'],
    ['x' => 1, 'y' => 3, 'string' => '#'],
    ['x' => 7, 'y' => 5, 'string' => '#'],
];

foreach ($parts as $part) {
    $cursor->moveToPosition($part['x'], $part['y']);
    $output->write($part['string']);

    usleep(200000);
}

$cursor->moveToPosition(1, 8);

Result:

kapture 2018-05-31 at 12 39 10

@javiereguiluz
Copy link
Member

For reference purposes, I've look for the APIs for this feature in other projects:

  1. Go libraries and .Net libraries have just a few methods:

https://godoc.org/github.com/nsf/termbox-go

func HideCursor()
func SetCursor(x, y int)

https://godoc.org/github.com/gdamore/tcell

func HideCursor()
func ShowCursor(x int, y int)

.Net (https://msdn.microsoft.com/en-us/library/system.console_methods(v=vs.110).aspx)

SetCursorPosition(Int32, Int32)

And some properties:

CursorLeft
CursorTop
CursorVisible
...
  1. On the other hand, JS libraries define a ton of methods:

https://github.com/cronvel/terminal-kit/blob/master/doc/low-level.md#ref.movingCursor

.saveCursor()
.restoreCursor()
.up(int n)
.down(int n)
.right(int n)
.left(int n)
.nextLine(int n)
.previousLine(int n)
.column(int x)
.scrollUp(int n)
.scrollDown(int n)
.scrollingRegion(top, bottom)
.resetScrollingRegion()
.moveTo(int x, int y)
.move(int x, int y)
.hideCursor()
.tabSet()
.tabClear()
.tabClearAll()
.forwardTab(int n)
.backwardTab(int n)

So we need to think if we want a simple (but enough) API or a complex (but useful) API.

@ogizanagi
Copy link
Member

ogizanagi commented Jun 1, 2018

Also see the HOA Project Console Cursor API: https://github.com/hoaproject/Console#cursor

Copy link
Member

@yceruto yceruto left a comment

Choose a reason for hiding this comment

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

Thanks for this feature! I left two minor comments.

src/Symfony/Component/Console/Cursor.php Outdated Show resolved Hide resolved
src/Symfony/Component/Console/Tests/CursorTest.php Outdated Show resolved Hide resolved
@nicolas-grekas
Copy link
Member

@pierredup see test failures :) Also, any comment when comparing the proposed API with the linked ones? Do any of them provide any idea to borrow?

@pierredup pierredup force-pushed the cursor-helper branch 2 times, most recently from 7501b0f to 2ad0290 Compare February 11, 2019 07:24
@pierredup
Copy link
Contributor Author

I prefer having a few explicit methods (E.G moveUp, moveDown) instead of just a couple generic methods, so I would much rather go the route of the JS libraries (although not as many methods as they have).

Copy link
Member

@chalasr chalasr left a comment

Choose a reason for hiding this comment

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

Can we update QuestionHelper to make it use this for autocompletion?
I'm fine with the current naming.

src/Symfony/Component/Console/Cursor.php Outdated Show resolved Hide resolved
@pierredup
Copy link
Contributor Author

Can we update QuestionHelper to make it use this for autocompletion?

@chalasr Done

Copy link
Member

@chalasr chalasr left a comment

Choose a reason for hiding this comment

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

Can you add a CHANGELOG entry and rebase to see tests green?

src/Symfony/Component/Console/Helper/QuestionHelper.php Outdated Show resolved Hide resolved
public function clearScreen()
{
$this->output->write("\x1b[2J", false);
}
Copy link
Member

Choose a reason for hiding this comment

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

Does it really belong to the cursor?

Copy link
Member

@fabpot fabpot left a comment

Choose a reason for hiding this comment

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

LGTM.

Can we also have methods to get the max x and max y of the console/cursor? I think we already have the code in Symfony, that would be good to have it here as well.

Maybe we can simplify the progress bar code as well.

src/Symfony/Component/Console/Helper/QuestionHelper.php Outdated Show resolved Hide resolved
src/Symfony/Component/Console/Helper/QuestionHelper.php Outdated Show resolved Hide resolved
src/Symfony/Component/Console/Helper/QuestionHelper.php Outdated Show resolved Hide resolved
@pierredup
Copy link
Contributor Author

I've rebased from master, and updated the Progress bar to use the Cursor class as well.

Can we also have methods to get the max x and max y of the console

This is currently available in the Terminal class for this component, so I'm not sure if it should be in the Cursor class as well

@chalasr
Copy link
Member

chalasr commented Mar 27, 2020

Agree about keeping the terminal size logic in the Terminal class.
@pierredup Some related tests are failing, can you have a look?

Copy link
Member

@chalasr chalasr left a comment

Choose a reason for hiding this comment

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

LGTM :) Missing CHANGELOG entry

@fabpot
Copy link
Member

fabpot commented Apr 12, 2020

Thanks @pierredup for working on this feature, this is much appreciated.

@fabpot fabpot merged commit d69b8bb into symfony:master Apr 12, 2020
@fabpot fabpot mentioned this pull request Apr 12, 2020
fabpot added a commit that referenced this pull request Apr 12, 2020
This PR was squashed before being merged into the 5.1-dev branch.

Discussion
----------

[Console] cursor tweaks

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Refs #27444
| License       | MIT
| Doc PR        | n/a

While playing with the new cursor class, I realized that I would like to make some changes. Mainly having a fluent interface: `$cursor->moveUp(10)->clearOutput()` for instance.

I have also separater the `clearLine()` method in two method to avoid the bool arg.

/cc @pierredup

Commits
-------

5a7b314 Make the Cursor class final
b0e7eb6 Make Cursor fluent
55fef91 Split a method
d00b5b5 Remove default value
@nicolas-grekas nicolas-grekas modified the milestones: next, 5.1 May 4, 2020
@fabpot fabpot mentioned this pull request May 5, 2020
wouterj added a commit to symfony/symfony-docs that referenced this pull request Jun 17, 2021
This PR was submitted for the 5.4 branch but it was squashed and merged into the 5.2 branch instead.

Discussion
----------

[Console] Document console cursor

fixes #13529
feature symfony/symfony#27444

ping `@wouterj` I've seen your slack recently and wanted to give it a try as I will use the feature very soon :)
feel free to comment, specialy if I need to document all the cursor features or not

text and image taken from the feature PR description
inspired by https://symfony.com/doc/current/components/console/helpers/progressbar.html

Commits
-------

232c519 [Console] Document console cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants