composer require php-school/cli-menu
Please refer to the Upgrade Documentation documentation to see what is required to upgrade your installedcli-menu
version.
Here is a super basic example menu which will echo out the text of the selected item to get you started.
<?php
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
require_once(__DIR__ . '/../vendor/autoload.php');
$itemCallable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->setBorder(1, 2, 'yellow')
->setPadding(2, 4)
->setMarginAuto()
->build();
$menu->open();
Check out the examples directory and run them to see what is possible! The best way to run the examples is to git clone the repository:
git clone https://github.com/php-school/cli-menu.git
cd cli-menu
composer install --no-dev
cd examples
php basic.php
Want to see something really cool? Well you can use cli-menu to create a drawing canvas on your terminal. Check it out!:
The CliMenu
object is constructed via the Builder class
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
/**
* Customise
**/
->build();
Once you have a menu object, you can open and close it like so:
$menu->open();
$menu->close();
You can give your menu a title and you can customise the separator, a line which displays under the title.Whatever string you pass to setTitleSeparator
will be repeated for the width of the Menu.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setTitle('One Menu to rule them all!')
->setTitleSeparator('*-')
->build();
You can change the foreground and background colour of the menu to any of the following colours:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setForegroundColour('green')
->setBackgroundColour('black')
->build();
If your terminal supports 256 colours then you can also use any of those by specifying the code, like 230
. You can find a listof the colours and codes here. If you specify a code and the terminal does not support 256 coloursit will automatically fallback to a sane default, using a generated map you can see in src/Util/ColourUtil.php. You can also manually specify thefallback colour as the second argument to setForegroundColour
and `setBackgroundColour.
In this example if no 256 colour support is found it will automatically fall back to green
and blue
.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setForegroundColour('40')
->setBackgroundColour('92')
->build();
In this example if no 256 colour support is found it will fall back to yellow
and magenta
.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setForegroundColour('40', 'yellow')
->setBackgroundColour('92', 'magenta')
->build();
Customise the width of the menu. Setting a value larger than the size of the terminal will result inthe width being the same as the terminal size. The width will include the padding and the border. So with a width of 100and all around border of 5 and all around padding of 5 will leave for a content width of 80 (5 + 5 + 80 + 5 + 5).
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setWidth(1000) //if terminal is only 400, width will also be 400
->build();
If you want to use the full width of the terminal, you can grab the terminal object and ask/set it from there like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = ($builder = new CliMenuBuilder)
->setWidth($builder->getTerminal()->getWidth())
->build();
If you want to use the full width of the terminal and apply a margin, use the terminal width, and we will do the calculationsautomatically (shrink the width based on the margin).
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = ($builder = new CliMenuBuilder)
->setWidth($builder->getTerminal()->getWidth())
->setMargin(2)
->build();
The padding can be set for all sides with one value or can be set individually for top/bottom and left/right.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setPadding(10) //10 padding top/bottom/left/right
->build();
Different values can also be set for the top/bottom and the left/right padding:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setPaddingTopBottom(10)
->setPaddingLeftRight(5)
->build();
Configure top/bottom and left/right padding using the shorthand method:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setPadding(10, 5) //top/bottom = 10, left/right = 5
->build();
The margin can be customised as one value. It can also be set automatically which will center the menu nicely in theterminal.
Automatically center menu:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setWidth(200)
->setMarginAuto()
->build();
Arbitrary margin:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setWidth(200)
->setMargin(5)
->build();
Borders can be customised just like CSS borders. We can add any amount of border to either side, left, right top orbottom and we can apply a colour to it.
Set universal red border of 2:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setWidth(200)
->setBorder(2, 'red')
->build();
Configure each border separately:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setWidth(200)
->setBorderTopWidth(2)
->setBorderRightWidth(4)
->setBorderBottomWidth(2)
->setBorderLeftWidth(4)
->setBorderColour('42', 'red') //SpringGreen2 fallback to red
->build();
Configure each border separately using the shorthand method, like CSS:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setWidth(200)
->setBorder(3, 4, 'red') //top/bottom = 3, left/right = 4
->setBorder(3, 4, 5, 'red') //top = 3, left/right = 4, bottom = 5
->setBorder(3, 4, 5, 6, 'red') //top = 3, left = 4, bottom = 5, right = 6
->build();
Modify the exit button text:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->setExitButtonText("Don't you want me baby?")
->build();
You can remove the exit button altogether:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->disableDefaultItems()
->build();
Note: This will also disable the Go Back button for sub menus.
You can manually add exit and go back buttons using the following:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\Action\ExitAction;
use PhpSchool\CliMenu\Action\GoBackAction;
$menu = (new CliMenuBuilder)
->disableDefaultItems()
->addSubMenu('Super Sub Menu', function (CliMenuBuilder $b) {
$b->disableDefaultItems()
->setTitle('Behold the awesomeness')
->addItem('Return to parent menu', new GoBackAction); //add a go back button
})
->addItem('Leave this place now !', new ExitAction) //add an exit button
->build();
There a few different types of items you can add to your menu
CliMenu
level.<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$menu = (new CliMenuBuilder)
->addItem('The Item Text', function (CliMenu $menu) {
echo 'I am alive!';
})
->build();
You can add multiple items at once like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$callable = function (CliMenu $menu) {
echo 'I am alive!';
};
$menu = (new CliMenuBuilder)
->addItems([
['Item 1', $callable],
['Item 2', $callable],
['Item 3', $callable],
])
->build();
Note: You can add as many items as you want and they can all have a different action. The action is the second parameterand must be a valid PHP callable
. Try using an Invokable
class to keep your actions easily testable.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$callable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
->addCheckboxItem('Item 1', $callable)
->addCheckboxItem('Item 2', $callable)
->addCheckboxItem('Item 3', $callable)
->build();
You can add multiple checkbox items at once like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$callable = function (CliMenu $menu) {
echo 'I am alive!';
};
$menu = (new CliMenuBuilder)
->addCheckboxItems([
['Item 1', $callable],
['Item 2', $callable],
['Item 3', $callable],
])
->build();
When selecting an item, it will be toggled. Notice at first each item is unchecked. After selecting one it will becomechecked.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$callable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
->addRadioItem('Item 1', $callable)
->addRadioItem('Item 2', $callable)
->addRadioItem('Item 3', $callable)
->build();
You can add multiple radio items at once like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$callable = function (CliMenu $menu) {
echo 'I am alive!';
};
$menu = (new CliMenuBuilder)
->addRadioItems([
['Item 1', $callable],
['Item 2', $callable],
['Item 3', $callable],
])
->build();
When selecting an item, it will be toggled. Notice at first each item is unchecked. After selecting one it will becomechecked and all other RadioItem
within the same level will be unchecked.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->addLineBreak('<3', 2)
->build();
The above would repeat the character sequence <3
across the Menu for 2 lines
Static items are similar to Line Breaks, however, they don't repeat and fill. It is output as is.If the text is longer than the width of the Menu, it will be continued on the next line.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$menu = (new CliMenuBuilder)
->addStaticItem('AREA 1')
//add some items here
->addStaticItem('AREA 2')
//add some boring items here
->addStaticItem('AREA 51')
//add some top secret items here
->build();
The following will place the Ascii art in the centre of your menu. Use these constants to alter thealignment:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\MenuItem\AsciiArtItem;
$art = <<<ART
_ __ _
/ |..| \
\/ || \/
|_''_|
PHP SCHOOL
LEARNING FOR ELEPHANTS
ART;
$menu = (new CliMenuBuilder)
->addAsciiArt($art, AsciiArtItem::POSITION_CENTER)
->build();
The third optional parameter to addAsciiArt
is alternate text. If the ascii art is too wide for the terminal, thenit will not be displayed at all. However, if you pass a string to the third argument, in the case that the ascii art is toowide for the terminal the alternate text will be displayed instead.
Sub Menus are really powerful! You can add Menus to Menus, whattttt?? You can have your main menu and then an options menu.The options item will look like a normal item except when you hit it, you will enter to another menu, whichcan have different styles and colours!
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$callable = function (CliMenu $menu) {
echo "I'm just a boring selectable item";
};
$menu = (new CliMenuBuilder)
->addItem('Normal Item', $callable)
->addSubMenu('Super Sub Menu', function (CliMenuBuilder $b) {
$b->setTitle('Behold the awesomeness')
->addItem(/** **/);
})
->build();
In this example a single sub menu will be created. Upon entering the sub menu, you will be able to return to the main menuor exit completely. A Go Back button will be automatically added. You can customise this text using the ->setGoBackButtonText()
method on the CliMenuBuilder
instance for the sub menu.
There are a few things to note about the syntax and builder process here
addSubMenu
is the text to be displayed on the menu which you select to enter the submenu.CliMenuBuilder
which you can use to customise the sub menu exactly the same way you would the parentIf you have already have a configured menu builder you can just pass that to addSubMenuFromBuilder
and be done:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
$subMenuBuilder = (new CliMenuBuilder)
->setTitle('Behold the awesomeness')
->addItem(/** **/);
$menu = (new CliMenuBuilder)
->addSubMenuFromBuilder('Super Sub Menu', $subMenuBuilder)
->build();
Note: The submenu menu item will be an instance of \PhpSchool\CliMenu\MenuItem\MenuMenuItem
. If you need access to the submenu,you can get it via $menuMenuItem->getSubMenu()
.
Split Items allows you to add multiple items on the same row. The full width of the menu will be split evenly between all items. You can move between those items using left/right arrows.
You can set the number of spaces separating items using ->setGutter()
(defaults to 2).
Only Selectable, Checkbox, Radio, Static and SubMenu items are currently allowed inside a Split Item.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\Builder\SplitItemBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
->setWidth(150)
->addStaticItem('Below is a SplitItem')
->addSplitItem(function (SplitItemBuilder $b) use ($itemCallable) {
$b->setGutter(5)
->addSubMenu('Sub Menu on a split item', function (CliMenuBuilder $b) {
$b->setTitle('Behold the awesomeness')
->addItem('This is awesome', function() { print 'Yes!'; });
})
->addItem('Item 2', $itemCallable)
->addStaticItem('Item 3 - Static');
})
->build();
$menu->open();
There are a few things to note about the syntax and builder process here:
addSplitItem
is a closure, which will be invoked with a new instance of SplitItemBuilder
which you can use to add items to the split item.addItem
, addCheckboxItem
, addRadioItem
, addSubMenu
and addStaticItem
on the SplitItemBuilder
.SplitItemBuilder
has a fluent interface so you can chain method calls.In this example we are disabling certain items and a submenu but still having them shown in the menu.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu Disabled Items')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable, false, true)
->addItem('Third Item', $itemCallable, false, true)
->addSubMenu('Submenu', function (CliMenuBuilder $b) use ($itemCallable) {
$b->setTitle('Basic CLI Menu Disabled Items > Submenu')
->addItem('You can go in here!', $itemCallable);
})
->addSubMenu('Disabled Submenu', function (CliMenuBuilder $b) use ($itemCallable) {
$b->setTitle('Basic CLI Menu Disabled Items > Disabled Submenu')
->addItem('Nope can\'t see this!', $itemCallable)
->disableMenu();
})
->addLineBreak('-')
->build();
The third param on the ->addItem
call is what disables an item while the ->disableMenu()
call disables the relevant menu.
The outcome is a full menu with dimmed rows to denote them being disabled. When a user navigates the menu these items are jumped over to the next available selectable item.
The marker displayed by the side of the currently active item can be modified, UTF-8 characters are supported.The marker for un-selected items can also be modified. If you want to disable it, just set it to an empty string. Itemmarkers only display on selectable items, which are: \PhpSchool\CliMenu\MenuItem\SelectableItem
& \PhpSchool\CliMenu\MenuItem\MenuMenuItem
.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\Style\SelectableStyle;
$menu = (new CliMenuBuilder)
->modifySelectableStyle(function (SelectableStyle $style) {
$style->setUnselectedMarker('❅ ')
->setSelectedMarker('✏ ')
// disable unselected marker
->setUnselectedMarker('')
;
})
->build();
You may also change the marker for \PhpSchool\CliMenu\MenuItem\CheckboxItem
:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\Style\CheckboxStyle;
$menu = (new CliMenuBuilder)
->modifyCheckboxStyle(function (CheckboxStyle $style) {
$style->setUncheckedMarker('[○] ')
->setCheckedMarker('[●] ');
})
->addCheckboxItem('Orange juice', function () {})
->addCheckboxItem('Bread', function () {})
->build();
and for \PhpSchool\CliMenu\MenuItem\RadioItem
:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\Style\RadioStyle;
$menu = (new CliMenuBuilder)
->modifyRadioStyle(function (RadioStyle $style) {
$style->setUncheckedMarker('[ ] ')
->setCheckedMarker('[✔] ');
})
->addRadioItem('Go shopping', function () {})
->addRadioItem('Go camping', function () {})
->build();
You can optionally display some arbitrary text on the right hand side of an item. You can customise this text andyou indicate which items to display it on. We use it to display [COMPLETED]
on completed exercises, where the menu listsexercises for a workshop application.
Item Extra is currently limited to only selectable items (menus, checkboxes & radios included)
The third parameter to addItem
is a boolean whether to show the item extra or not. It defaults to false.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Style\SelectableStyle;
$menu = (new CliMenuBuilder)
->modifySelectableStyle(function (SelectableStyle $style) {
$style->setItemExtra('✔');
})
->addItem('Exercise 1', function (CliMenu $menu) { echo 'I am complete!'; }, true)
->build();
If no items have display extra set to true, then the item extra will not be displayed. If you toggle the item to showit's item extra in a callback or at runtime it will render incorrectly.
In order to fix that you need to tell the menu to display item extra explicitly. You can do this when constructing themenu like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$menu = (new CliMenuBuilder)
->setItemExtra('✔')
->addItem('Exercise 1', function (CliMenu $menu) {
$selectedItem = $menu->getSelectedItem();
if ($selectedItem->showsItemExtra()) {
$selectedItem->hideItemExtra();
} else {
$selectedItem->showItemExtra();
}
})
->displayExtra()
->build();
The next set of documentation applies to methods available directly on the \PhpSchool\CliMenu\CliMenu
instance. Typicallyyou will invoke these methods whilst your menu is open in you action callbacks.
You can modify the menu and its style when executing an action and then you can redraw it! In this example we will toggle the backgroundcolour in an action.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$menu->getStyle()->setBg($menu->getStyle()->getBg() === 'red' ? 'blue' : 'red');
$menu->redraw();
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
If you change the menu drastically, such as making the width smaller, when it redraws you might see artifacts of the previous drawas redraw
only draws over the top of the terminal. If this happens you can pass true
to redraw
and it will first clearthe terminal before redrawing.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$menu->getStyle()->setWidth($menu->getStyle()->getWidth() === 100 ? 80 : 100);
$menu->redraw(true);
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
You can also interact with the menu items in an action. You can add, remove and replace items. If you do this, youwill likely want to redraw the menu as well so the new list is rendered.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\MenuItem\LineBreakItem;
$itemCallable = function (CliMenu $menu) {
foreach ($menu->getItems() as $item) {
$menu->removeItem($item);
}
//add single item
$menu->addItem(new LineBreakItem('-'));
//add multiple items
$menu->addItems([new LineBreakItem('-'), new LineBreakItem('*')]);
//replace all items
$menu->setItems([new LineBreakItem('+'), new LineBreakItem('-')]);
$menu->redraw();
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
This functionality allows to map custom key presses to a callable. For example we can set the key press "x" to close the menu:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$exit = function(CliMenu $menu) {
$menu->close();
};
$menu = (new CliMenuBuilder)
->addItem('Item 1', function(CliMenu $menu) {})
->build();
$menu->addCustomControlMapping("x", $exit);
$menu->open();
Another example is mapping shortcuts to a list of items:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$myCallback = function(CliMenu $menu) {
echo "Client 1\nClient 2\nClient 3\n";
};
$menu = (new CliMenuBuilder)
->addItem('List of [C]lients', $myCallback)
->build();
// Now, pressing Uppercase C (it's case sensitive) will call $myCallback
$menu->addCustomControlMapping('C', $myCallback);
$menu->open();
If you enable auto shortcuts CliMenuBuilder
will parse the items text and check for shortcuts. Any single character inside square bracketswill be treated as a shortcut. Pressing that character when the menu is open will trigger that items callable.
This functionality works for split items as well as sub menus. The same characters can be used inside sub menus and thecallable which is invoked will depend on which menu is currently open.
Note: all shortcuts are lower cased.
To enable this automatic keyboard shortcut mapping simply call ->enableAutoShortcuts()
:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$myCallback = function(CliMenu $menu) {
echo "Client 1\nClient 2\nClient 3\n";
};
$menu = (new CliMenuBuilder)
->enableAutoShortcuts()
->addItem('List of [C]lients', $myCallback)
->build();
$menu->open();
//Pressing c will execute $myCallback.
You can customise the shortcut matching by passing your own regex to enableAutoShortcuts
. Be careful to only matchone character in the first capture group or an exception will be thrown.
Show a one line message over the top of the menu. It has a separate style object which is colored by default differentto the menu. It can be modified to suit your own style. The dialogue is dismissed with any key press. In the examplebelow we change the background color on the flash to green.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
require_once(__DIR__ . '/../vendor/autoload.php');
$itemCallable = function (CliMenu $menu) {
$flash = $menu->flash("PHP School FTW!!");
$flash->getStyle()->setBg('green');
$flash->display();
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
Prompts are very similar to flashes except that a button is shown which has to be selected to dismiss them. The buttontext can be customised.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$menu->confirm('PHP School FTW!')
->display('OK!');
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
Inputs - added in version 3.0 of cli-menu
allow to prompt the user for input and validate it. The following types are supported:text, number and password. Inputs can be executed in any item callback. They have separate style objects which are colored by default different to the menu.They can be modified to suit your own style.
Each input is created by calling one of the ask*
methods which will return aninstance of the input you requested. To execute the prompt and wait for the input you mustcall ask()
on the input. When the input has been received and validated, ask()
will returnan instance of InputResult
. InputResult
exposes the method fetch
to grab the raw input.
The text input will prompt for a string and when the enter key is hit it will validate thatthe string is not empty. As well as the style you can modify the prompt text (the default is 'Enter text:'), theplaceholder text (the default is empty) and the validation failed text (the default is 'Invalid, try again').
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$result = $menu->askText()
->setPromptText('Enter your name')
->setPlaceholderText('Jane Doe')
->setValidationFailedText('Please enter your name')
->ask();
var_dump($result->fetch());
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('Enter text', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
The number input will prompt for an integer value (signed or not) and when the enter key is hit it will validate thatthe input is actually a number (/^-?\d+$/
). As well as the style you can modify the prompt text (the default is 'Enter a number:'), theplaceholder text (the default is empty) and the validation failed text (the default is 'Not a valid number, try again').
When entering a number you can use the up/down keys to increment and decrement the number.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$result = $menu->askNumber()
->setPromptText('Enter your age')
->setPlaceholderText(10)
->setValidationFailedText('Invalid age, try again')
->ask();
var_dump($result->fetch());
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('Enter number', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
The password input will prompt for a text value and when the enter key is hit it will validate that the input is 16 characters or longer.As well as the style you can modify the prompt text (the default is 'Enter password:'), theplaceholder text (the default is empty) and the validation failed text (the default is 'Invalid password, try again'). You can also seta custom password validator as a PHP callable. When typing passwords they are echo'd back to the user as an asterisk.
Ask for a password with the default validation:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$result = $menu->askPassword()
->setPromptText('Please enter your password')
->setValidationFailedText('Invalid password, try again')
->setPlaceholderText('')
->ask();
var_dump($result->fetch());
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('Enter password', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
Validators can be any PHP callable. The callable will be passed the input value and must return a boolean, false indicatingvalidation failure and true indicating validation success. If validation fails then the validation failure text will be shown.
It is also possible to customise the validation failure message dynamically, but only when using a Closure
as a validator.The closure will be binded to the Password
input class which will allow you to call setValidationFailedText
inside the closure.
Ask for a password with custom validation. Here we validate the password is not equal to password
and that thepassword is longer than 20 characters.
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$result = $menu->askPassword()
->setPromptText('Please enter your password')
->setValidationFailedText('Invalid password, try again')
->setPlaceholderText('')
->setValidator(function ($password) {
return $password !== 'password' && strlen($password) > 20;
})
->ask();
var_dump($result->fetch());
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('Enter password', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
Ask for a password with custom validation and set the validation failure message dynamically:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
$itemCallable = function (CliMenu $menu) {
$result = $menu->askPassword()
->setPromptText('Please enter your password')
->setValidationFailedText('Invalid password, try again')
->setPlaceholderText('')
->setValidator(function ($password) {
if ($password === 'password') {
$this->setValidationFailedText('Password is too weak');
return false;
} else if (strlen($password) <= 20) {
$this->setValidationFailedText('Password is not long enough');
return false;
}
return true;
})
->ask();
var_dump($result->fetch());
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('Enter password', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
If you need a new type of input which is not covered by the bundled selection then you can create your own by implementing\PhpSchool\CliMenu\Input\Input
- take a look at existing implementations to see how they are built. If all you need is some customvalidation - extend the \PhpSchool\CliMenu\Input\Text
class and overwrite the validate
method. You can then use it inyour menu item actions like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\MenuStyle;
use PhpSchool\CliMenu\Input\Text;
use PhpSchool\CliMenu\Input\InputIO;
$itemCallable = function (CliMenu $menu) {
$style = (new MenuStyle())
->setBg('yellow')
->setFg('black');
$input = new class (new InputIO($menu, $menu->getTerminal()), $style) extends Text {
public function validate(string $value) : bool
{
//some validation
return true;
}
};
$result = $input->ask();
var_dump($result->fetch());
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('Enter password', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
All of the dialogues and inputs expose a getStyle()
method which you can use to customise the appearance of them. However, ifyou want to create a consistent style for all your dialogues and inputs without configuring it for each oneyou can build up a MenuStyle
object and pass it to the dialogue and input methods like so:
<?php
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\MenuStyle;
$popupStyle = (new MenuStyle)
->setBg('green')
->setFg('magenta');
$itemCallable = function (CliMenu $menu) use ($popupStyle) {
$menu->flash("PHP School FTW!!", $popupStyle)->display();
$menu->confirm('PHP School FTW!', $popupStyle)->display('OK!');
$menu->askNumber($popupStyle)->ask();
};
$menu = (new CliMenuBuilder)
->setTitle('Basic CLI Menu')
->addItem('First Item', $itemCallable)
->addItem('Second Item', $itemCallable)
->addItem('Third Item', $itemCallable)
->addLineBreak('-')
->build();
$menu->open();
Once you get going you might just end up with something that looks a little like this...
You can see the construction code here for more clarity on how to perform advanced configuration:PHP School
1. 安装依赖包 npm install electron electron-updater vue-cli-plugin-electron-builder --save-dev 2. package.json修改 1、scripts中添加 “electron:build”: “vue-cli-service electron:build”, “electron:serve”: “vue-cli-
Vue cli3 多级菜单的实现 仅用作本人学习的记录,及在项目中用到的组件。 // menu-tree 子组件 <template> <el-submenu v-if="menu.children.length > 0" popper-class="popper_menu" :index="menu.index"> <template slot="title"> <i
vue中,动态菜单-NavMenu导航菜单——el-menu动态导航菜单(二) 4、动态菜单文件 src\components\console\sideBar.vue <template> <div class="sideBar"> <el-menu class="el-menu-vertical-demo" background-color="#242731" text-color=
终端执行 chmod 777 /Users/apple/Desktop/management/node_modules/.bin/vue-cli-service
fis. cli 命令行相关的信息和工具类方法暴露在此模块中。 Source: cli.js, line 1 Members (static) colors 指向 colors 模块。 Source: cli.js, line 20 (static) info package.json 中的信息 Source: cli.js, line 30 (static) name 命令行工具名字 Defau
Run Prettier through the CLI with this script. Run it without any arguments to see the options. To format a file in-place, use --write. You may want to consider committing your code before doing that,
命令行界面(CLI)可用于创建我们的Angular JS应用程序。 它还有助于为应用程序创建单元和端到端测试。 Angular CLI的官方网站是https://cli.angular.io/ 如果单击“启动”选项,您将被定向到CLI的github存储库https://github.com/angular/angular-cli 现在让我们看一下使用Angular CLI可以做的一些事情。 安装C
Angular CLI使您可以轻松地开始使用任何Angular项目。 Angular CLI附带的命令可以帮助我们快速创建和启动项目。 现在让我们来看看可用于创建项目,组件和服务,更改端口等的命令。 要使用Angular CLI,我们需要在我们的系统上安装它。 让我们使用以下命令 - npm install -g @angular/cli 要创建新项目,我们可以在命令行中运行以下命令,然后将创建
在本章中,我们将了解CLI如何在Grav中工作。 CLI代表存储在bin/Grav命令行界面。 它执行一些任务,例如clearing cache ,创建backup副本等。 在不同平台上访问CLI是不同的。 在Windows上,您可以通过cmd访问,在Mac上可以通过Terminal访问,在Linux上可以使用shell。 在Windows中,您不能使用UNIX样式命令。 要使用它们,只需安装提供
概述 为了帮助用户管理他们的项目,已经创建了 CLI 工具。它同时在很多方面都有帮助,从搭建项目到构建结构良好的应用程序。嵌套CLI基于 @ angular - devkit 软件包。此外,还有专门用于嵌套开发 @ nestjs / schematics 的特殊示意图 安装 使用 NPM 安装 CLI: $ npm install -g @nestjs/cli 使用 Docker Hub 安装CL