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

Allow input stream termination by sending end-of-transmission character #937

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
341b233
Add end-of-transmission control character constant
caendesilva Feb 8, 2023
ef2a4df
Allow termination by sending EOT signal
caendesilva Feb 8, 2023
5383ceb
Update console output message on how to terminate input
caendesilva Feb 8, 2023
28edc6d
Return \x04 if stream pointer matches EOT signal
caendesilva Feb 8, 2023
5128ff8
Flip order of termination options
caendesilva Feb 8, 2023
0566d4f
Fix wrong namespace in test annotation
caendesilva Feb 8, 2023
7796355
Move terminationMessage to static helper so it can be reused
caendesilva Feb 8, 2023
dc1605f
Capitalize initial letter
caendesilva Feb 8, 2023
70e8cc1
Convert concatenation to 'sprintf()' call
caendesilva Feb 8, 2023
6011ccb
Replace string literal with sprintf injected constant value
caendesilva Feb 8, 2023
5a25e93
Extract helper method
caendesilva Feb 8, 2023
804ba69
Apply fixes from StyleCI
StyleCIBot Feb 8, 2023
f35c18c
Write that enter needs to be pressed when on Windows
caendesilva Feb 8, 2023
b7e564d
Add missing output instruction on how to exit input
caendesilva Feb 8, 2023
01098b1
Update to display the new termination message
caendesilva Feb 8, 2023
027b937
Convert concatenation to 'sprintf()' call
caendesilva Feb 8, 2023
a232f49
Apply fixes from StyleCI
StyleCIBot Feb 8, 2023
4daa5d0
Run smoke tests in parallel
caendesilva Feb 8, 2023
504f189
Update to expect terminationMessage
caendesilva Feb 8, 2023
6ff1453
Revert "Update to expect terminationMessage"
caendesilva Feb 8, 2023
3baaff7
Expect output to contain as expectation does not seem to like formatting
caendesilva Feb 8, 2023
2a36a26
Update test for changed output
caendesilva Feb 8, 2023
f7fa1db
Test can terminate with EOT sequence
caendesilva Feb 8, 2023
58e15d0
Test the termination message
caendesilva Feb 8, 2023
d18b4e5
Convert concatenation to string interpolation
caendesilva Feb 8, 2023
b60b017
Update local test variable name
caendesilva Feb 8, 2023
992eccd
Add tests for the constants
caendesilva Feb 8, 2023
7864de5
Merge branch 'publications-feature' into change-input-string-handler-…
caendesilva Feb 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions packages/publications/src/Commands/Helpers/InputStreamHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use function explode;
use function fgets;
use Hyde\Hyde;
use function str_contains;
use function trim;

/**
Expand All @@ -20,6 +21,7 @@
class InputStreamHandler
{
public const TERMINATION_SEQUENCE = '<<<';
public const END_OF_TRANSMISSION = "\x04";

private static ?array $mockedStreamBuffer = null;

Expand Down Expand Up @@ -49,7 +51,7 @@ protected function getLinesFromInputStream(): array

protected function shouldTerminate(string $line): bool
{
return $line === self::TERMINATION_SEQUENCE;
return $line === self::TERMINATION_SEQUENCE || str_contains($line, self::END_OF_TRANSMISSION);
}

/** @codeCoverageIgnore Allows for mocking of the standard input stream */
Expand All @@ -59,12 +61,22 @@ protected function readInputStream(): string
return array_shift(self::$mockedStreamBuffer) ?? '';
}

return fgets(STDIN);
return fgets(STDIN) ?: self::END_OF_TRANSMISSION;
}

/** @internal Allows for mocking of the standard input stream */
public static function mockInput(string $input): void
{
self::$mockedStreamBuffer = explode("\n", $input);
}

public static function terminationMessage(): string
{
return sprintf('Terminate with <comment>%s</comment> or press %s to finish', self::TERMINATION_SEQUENCE, self::getShortcut());
}

protected static function getShortcut(): string
{
return '<comment>Ctrl+D</comment>'.(PHP_OS_FAMILY === 'Windows' ? ' then <comment>Enter</comment>' : '');
}
}
4 changes: 2 additions & 2 deletions packages/publications/src/Commands/MakePublicationCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,14 @@ protected function captureFieldInput(PublicationFieldDefinition $field): ?Public

protected function captureTextFieldInput(PublicationFieldDefinition $field): PublicationFieldValue
{
$this->infoComment("Enter lines for field [$field->name] <fg=gray>(terminate with '<<<')</>");
$this->infoComment(sprintf("Enter lines for field [$field->name] (%s)", InputStreamHandler::terminationMessage()));

return new PublicationFieldValue(PublicationFieldTypes::Text, implode("\n", InputStreamHandler::call()));
}

protected function captureArrayFieldInput(PublicationFieldDefinition $field): PublicationFieldValue
{
$this->infoComment("Enter values for field [$field->name]");
$this->infoComment(sprintf("Enter values for field [$field->name] (%s)", InputStreamHandler::terminationMessage()));

return new PublicationFieldValue(PublicationFieldTypes::Array, InputStreamHandler::call());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected function validateTagName(): void

protected function collectTags(): void
{
$this->info('Enter the tag values: (end with an empty line)');
$this->info(sprintf('Enter the tag values: (%s)', InputStreamHandler::terminationMessage()));
$this->tags = [$this->tagName => InputStreamHandler::call()];
}

Expand Down
28 changes: 28 additions & 0 deletions packages/publications/tests/Feature/InputStreamHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public function testCanTerminateWithHereSequenceAfterCarriageReturns()
$this->assertSame(0, $this->makeCommand(['foo', 'bar', 'baz'])->handle());
}

public function testCanTerminateWithEndOfTransmissionSequence()
{
InputStreamHandler::mockInput("foo\nbar\nbaz\n\x04");

$this->assertSame(0, $this->makeCommand(['foo', 'bar', 'baz'])->handle());
}

public function testCanCollectMultipleInputLines()
{
InputStreamHandler::mockInput("foo\nbar\nbaz\n<<<");
Expand All @@ -57,6 +64,27 @@ public function testCanEnterMultipleUnixEndings()
$this->assertSame(0, $this->makeCommand(['foo', 'bar', 'baz'])->handle());
}

public function testTerminationMessage()
{
$message = 'Terminate with <comment><<<</comment> or press <comment>Ctrl+D</comment>';
if (PHP_OS_FAMILY === 'Windows') {
$message .= ' then <comment>Enter</comment>';
}
$expected = "$message to finish";

$this->assertSame($expected, InputStreamHandler::terminationMessage());
}

public function testTerminationSequenceConstant()
{
$this->assertSame('<<<', InputStreamHandler::TERMINATION_SEQUENCE);
}

public function testEndOfTransmissionConstant()
{
$this->assertSame("\x04", InputStreamHandler::END_OF_TRANSMISSION);
}

protected function makeCommand(array $expected): TestCommand
{
$command = new TestCommand;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function testCanCreateNewPublicationTag()

$this->artisan('make:publicationTag')
->expectsQuestion('Tag name', 'foo')
->expectsOutput('Enter the tag values: (end with an empty line)')
->expectsOutputToContain('Enter the tag values:')
->expectsOutput('Adding the following tags:')
->expectsOutput(' foo: foo, bar, baz')
->expectsOutput('Saving tag data to [file://'.str_replace('\\', '/', Hyde::path('tags.yml')).']')
Expand All @@ -53,7 +53,7 @@ public function testCanCreateNewPublicationTagWithTagNameArgument()

$this->artisan('make:publicationTag foo')
->expectsOutput('Using tag name [foo] from command line argument')
->expectsOutput('Enter the tag values: (end with an empty line)')
->expectsOutputToContain('Enter the tag values:')
->expectsOutput('Adding the following tags:')
->expectsOutput(' foo: foo, bar, baz')
->expectsOutput('Saving tag data to [file://'.str_replace('\\', '/', Hyde::path('tags.yml')).']')
Expand Down