Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4068186
CompletionInput.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
CompletionInput.php
View Options
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace
Symfony\Component\Console\Completion
;
use
Symfony\Component\Console\Exception\RuntimeException
;
use
Symfony\Component\Console\Input\ArgvInput
;
use
Symfony\Component\Console\Input\InputDefinition
;
use
Symfony\Component\Console\Input\InputOption
;
/**
* An input specialized for shell completion.
*
* This input allows unfinished option names or values and exposes what kind of
* completion is expected.
*
* @author Wouter de Jong <wouter@wouterj.nl>
*/
final
class
CompletionInput
extends
ArgvInput
{
public
const
TYPE_ARGUMENT_VALUE
=
'argument_value'
;
public
const
TYPE_OPTION_VALUE
=
'option_value'
;
public
const
TYPE_OPTION_NAME
=
'option_name'
;
public
const
TYPE_NONE
=
'none'
;
private
array
$tokens
;
private
int
$currentIndex
;
private
string
$completionType
;
private
?
string
$completionName
=
null
;
private
string
$completionValue
=
''
;
/**
* Converts a terminal string into tokens.
*
* This is required for shell completions without COMP_WORDS support.
*/
public
static
function
fromString
(
string
$inputStr
,
int
$currentIndex
):
self
{
preg_match_all
(
'/(?<=^|
\s
)([
\'
"]?)(.+?)(?<!
\\\\
)
\1
(?=$|
\s
)/'
,
$inputStr
,
$tokens
);
return
self
::
fromTokens
(
$tokens
[
0
],
$currentIndex
);
}
/**
* Create an input based on an COMP_WORDS token list.
*
* @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv)
* @param int $currentIndex the index of the cursor (e.g. COMP_CWORD)
*/
public
static
function
fromTokens
(
array
$tokens
,
int
$currentIndex
):
self
{
$input
=
new
self
(
$tokens
);
$input
->
tokens
=
$tokens
;
$input
->
currentIndex
=
$currentIndex
;
return
$input
;
}
public
function
bind
(
InputDefinition
$definition
):
void
{
parent
::
bind
(
$definition
);
$relevantToken
=
$this
->
getRelevantToken
();
if
(
'-'
===
$relevantToken
[
0
])
{
// the current token is an input option: complete either option name or option value
[
$optionToken
,
$optionValue
]
=
explode
(
'='
,
$relevantToken
,
2
)
+
[
''
,
''
];
$option
=
$this
->
getOptionFromToken
(
$optionToken
);
if
(
null
===
$option
&&
!
$this
->
isCursorFree
())
{
$this
->
completionType
=
self
::
TYPE_OPTION_NAME
;
$this
->
completionValue
=
$relevantToken
;
return
;
}
if
(
$option
?->
acceptValue
())
{
$this
->
completionType
=
self
::
TYPE_OPTION_VALUE
;
$this
->
completionName
=
$option
->
getName
();
$this
->
completionValue
=
$optionValue
?:
(!
str_starts_with
(
$optionToken
,
'--'
)
?
substr
(
$optionToken
,
2
)
:
''
);
return
;
}
}
$previousToken
=
$this
->
tokens
[
$this
->
currentIndex
-
1
];
if
(
'-'
===
$previousToken
[
0
]
&&
''
!==
trim
(
$previousToken
,
'-'
))
{
// check if previous option accepted a value
$previousOption
=
$this
->
getOptionFromToken
(
$previousToken
);
if
(
$previousOption
?->
acceptValue
())
{
$this
->
completionType
=
self
::
TYPE_OPTION_VALUE
;
$this
->
completionName
=
$previousOption
->
getName
();
$this
->
completionValue
=
$relevantToken
;
return
;
}
}
// complete argument value
$this
->
completionType
=
self
::
TYPE_ARGUMENT_VALUE
;
foreach
(
$this
->
definition
->
getArguments
()
as
$argumentName
=>
$argument
)
{
if
(!
isset
(
$this
->
arguments
[
$argumentName
]))
{
break
;
}
$argumentValue
=
$this
->
arguments
[
$argumentName
];
$this
->
completionName
=
$argumentName
;
if
(
\is_array
(
$argumentValue
))
{
$this
->
completionValue
=
$argumentValue
?
$argumentValue
[
array_key_last
(
$argumentValue
)]
:
null
;
}
else
{
$this
->
completionValue
=
$argumentValue
;
}
}
if
(
$this
->
currentIndex
>=
\count
(
$this
->
tokens
))
{
if
(!
isset
(
$this
->
arguments
[
$argumentName
])
||
$this
->
definition
->
getArgument
(
$argumentName
)->
isArray
())
{
$this
->
completionName
=
$argumentName
;
}
else
{
// we've reached the end
$this
->
completionType
=
self
::
TYPE_NONE
;
$this
->
completionName
=
null
;
}
$this
->
completionValue
=
''
;
}
}
/**
* Returns the type of completion required.
*
* TYPE_ARGUMENT_VALUE when completing the value of an input argument
* TYPE_OPTION_VALUE when completing the value of an input option
* TYPE_OPTION_NAME when completing the name of an input option
* TYPE_NONE when nothing should be completed
*
* TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component.
*
* @return self::TYPE_*
*/
public
function
getCompletionType
():
string
{
return
$this
->
completionType
;
}
/**
* The name of the input option or argument when completing a value.
*
* @return string|null returns null when completing an option name
*/
public
function
getCompletionName
():
?
string
{
return
$this
->
completionName
;
}
/**
* The value already typed by the user (or empty string).
*/
public
function
getCompletionValue
():
string
{
return
$this
->
completionValue
;
}
public
function
mustSuggestOptionValuesFor
(
string
$optionName
):
bool
{
return
self
::
TYPE_OPTION_VALUE
===
$this
->
getCompletionType
()
&&
$optionName
===
$this
->
getCompletionName
();
}
public
function
mustSuggestArgumentValuesFor
(
string
$argumentName
):
bool
{
return
self
::
TYPE_ARGUMENT_VALUE
===
$this
->
getCompletionType
()
&&
$argumentName
===
$this
->
getCompletionName
();
}
protected
function
parseToken
(
string
$token
,
bool
$parseOptions
):
bool
{
try
{
return
parent
::
parseToken
(
$token
,
$parseOptions
);
}
catch
(
RuntimeException
)
{
// suppress errors, completed input is almost never valid
}
return
$parseOptions
;
}
private
function
getOptionFromToken
(
string
$optionToken
):
?
InputOption
{
$optionName
=
ltrim
(
$optionToken
,
'-'
);
if
(!
$optionName
)
{
return
null
;
}
if
(
'-'
===
(
$optionToken
[
1
]
??
' '
))
{
// long option name
return
$this
->
definition
->
hasOption
(
$optionName
)
?
$this
->
definition
->
getOption
(
$optionName
)
:
null
;
}
// short option name
return
$this
->
definition
->
hasShortcut
(
$optionName
[
0
])
?
$this
->
definition
->
getOptionForShortcut
(
$optionName
[
0
])
:
null
;
}
/**
* The token of the cursor, or the last token if the cursor is at the end of the input.
*/
private
function
getRelevantToken
():
string
{
return
$this
->
tokens
[
$this
->
isCursorFree
()
?
$this
->
currentIndex
-
1
:
$this
->
currentIndex
];
}
/**
* Whether the cursor is "free" (i.e. at the end of the input preceded by a space).
*/
private
function
isCursorFree
():
bool
{
$nrOfTokens
=
\count
(
$this
->
tokens
);
if
(
$this
->
currentIndex
>
$nrOfTokens
)
{
throw
new
\LogicException
(
'Current index is invalid, it must be the number of input tokens or one more.'
);
}
return
$this
->
currentIndex
>=
$nrOfTokens
;
}
public
function
__toString
():
string
{
$str
=
''
;
foreach
(
$this
->
tokens
as
$i
=>
$token
)
{
$str
.=
$token
;
if
(
$this
->
currentIndex
===
$i
)
{
$str
.=
'|'
;
}
$str
.=
' '
;
}
if
(
$this
->
currentIndex
>
$i
)
{
$str
.=
'|'
;
}
return
rtrim
(
$str
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Aug 16 2026, 19:43 (11 w, 6 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e9/92/4b307f800a415e72a8d8422e7d9a
Default Alt Text
CompletionInput.php (7 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment