mantas6 / fzf-php
Interactive fzf command line menus in PHP
Requires
- php: ^8.3.0
- symfony/console: ^7.0
- symfony/process: ^7.0
- symfony/string: ^7.0
Requires (Dev)
- laravel/pint: ^1.20.0
- nesbot/carbon: ^3.8.4
- pestphp/pest: ^3.7.4
- pestphp/pest-plugin-type-coverage: ^3.2.3
- phpstan/phpstan: ^1.12.16
- rector/rector: ^1.2.10
- symfony/var-dumper: ^7.2.3
README
This package allows you to create fzf
powered menus straight from your PHP code.
Features
- Automatic
fzf
binary download - Inline
fzf
configuration - Option list styling
- Selected option preview
- Live option list reload
- Laravel support
Installation
Install the package:
composer require mantas6/fzf-php
Usage
Options
Options can be provided in a multitude of ways.
Strings
<?php use function Mantas6\FzfPhp\fzf; $selected = fzf(['Apple', 'Orange', 'Grapefruit']); // returns 'Apple'
- Returns
null
if user cancels the prompt
Arrays
<?php $selected = fzf( options: [ ['Apples', '1kg'], ['Oranges', '2kg'], ['Grapefruits', '3kg'], ] ); // returns ['Apples', '1kg']
- Each array element represents different column in the finder
Objects
<?php $selected = fzf( options: [ new Model('Apple'), // must implement toArray or PresentsForFinder interface new Model('Orange'), new Model('Grapefruit'), ] ); // returns new Model('Apple')
To use objects as options, at least one is required:
- Implement
toArray
- Implement
PresentsForFinder
interface - Provide presenter callback
Options presentation
Callback can be provided for presentation. This will work for any options type.
<?php $selected = fzf( options: [ 'Apple', 'Orange', 'Grapefruits', ], present: fn (string $item): string => strtoupper($item), );
Multiple columns can be present by returning an array.
<?php $selected = fzf( // ... present: fn (string $item): array => [ $item, strtoupper($item), ], );
Implementing PresentsForFinder
interface
Option objects can implement a special interface, that would work the same as providing a presenter callback.
<?php use Mantas6\FzfPhp\Concerns\PresentsForFinder; class Model implements PresentsForFinder { protected string $name; public function presentForFinder(): array|string { return $this->name; } }
Styling
Option columns can be styling using cell()
helper function in the presenter callback.
<?php use function Mantas6\FzfPhp\cell; $selected = fzf( options: [ ['name' => 'Apples', 'weight' => 1000], ['name' => 'Oranges', 'weight' => 2000], ['name' => 'Grapefruits', 'weight' => 3000], ], // Styling individual items present: fn (array $item): array => [ $item['name'], cell( value: $item['weight'], fg: $item['weight'] > 2000 ? 'red' : 'green', ), ], );
Formatting options are:
<?php cell( // Text of the cell value: 'Text displayed', // Alignment in the table (left, right, center) align: 'right', // Foreground color fg: 'white', // Background color bg: 'red', // Column span colspan: 2, );
- Available colors:
red, green, yellow, blue, magenta, cyan, white, default, gray, bright-red, bright-green, bright-yellow, bright-blue, bright-magenta, bright-cyan, bright-white
More information can be found at Symfony Docs: Table
Preview
Preview window can be enabled for each selected option.
<?php $selected = fzf( options: ['Apple', 'Orange', 'Grapefruit'], preview: fn (string $item) => strtoupper($item), );
If more advanced styling is needed, style()
helper can be used.
<?php use function Mantas6\FzfPhp\style; $selected = fzf( // ... preview: function (string $item) { return style() ->table([ ['Original', $item], ['Uppercase', strtoupper($item)], ]); } );
- Use
->table()
for creating compact tables - Use
->block()
for creating text blocks
Additional variables
fzf
provides additional variables to the preview (and other) child processes.
<?php use Mantas6\FzfPhp\ValueObjects\FinderEnv; $selected = fzf( // ... preview: function (string $item, FinderEnv $env) { // ... $env->key, // The name of the last key pressed $env->action, // The name of the last action performed // ... } );
Full set of variables are available at fzf
Reference - Environment variables exported to child processes
Live reload
If options argument is callable, when input value is changed, the options list will be re-fetched.
Input query can be accessed through the FinderEnv
object.
<?php use Mantas6\FzfPhp\ValueObjects\FinderEnv; $selected = fzf( options: function (FinderEnv $env) { return [ $env->query, strtoupper($env->query), strtolower($env->query), ]; } );
Headers
Fixed header will be displayed if header list is passed.
<?php $selected = fzf( options: ['Apple', 'Orange', 'Grapefruit'], headers: ['Fruit'], );
Options as object
Instead of passing options as array, object can be used.
<?php $selected = fzf( options: new MyCustomCollection, );
The class needs to meet one of the following requirements:
- Must implement the native
Traversable
interface - Needs to implement
toArray()
method
Multi mode
Retrieve multiple options from a list.
<?php $selected = fzf( options: ['Apple', 'Orange', 'Grapefruit'], arguments: ['multi' => true], ); // ['Apple', 'Orange']
- Returns
[]
if user cancels the prompt
Arguments
Pass any other fzf
configuration arguments:
<?php $selected = fzf( options: ['Apple', 'Orange', 'Grapefruit'], arguments: [ 'height' => '40%', 'cycle' => true, ], );
- Arguments
delimiter
(ord
),with-nth
are used internally, and will be overridden if specified - Arguments that transform output may not be supported
- Consult
fzf
Reference for all available options
Reusable object approach
Class instance can be created directly for more reusable approach.
<?php use Mantas6\FzfPhp\FuzzyFinder; $finder = new FuzzyFinder; $fruit = $finder->ask(['Apple', 'Orange', 'Grapefruit']); // ... $weight = $finder->ask(['250g', '500g', '1kg']);
Additional configuration is available through the class methods.
<?php $finder->present(...); $finder->arguments(...);
Configuration
Use system fzf
binary instead of fetching it.
<?php // YourAppServiceProvider.php use Mantas6\FzfPhp\FuzzyFinder; FuzzyFinder::usingCommand(['/usr/bin/env', 'fzf']);
- Automatic binary download will be disabled when custom command is set
Set global arguments for all prompts.
<?php // YourAppServiceProvider.php FuzzyFinder::usingDefaultArguments(['pointer' => '->']);
Binary download
The fzf
binary is downloaded automatically on the first use, however you can initiate the download manually.
./vendor/bin/fzf-php-install
Automatic update
To optimize the initial start, especially when CI/CD is used, it is recommended to add this to your composer.json
file.
{ "scripts": { "post-update-cmd": [ "./vendor/bin/fzf-php-install" ], "post-install-cmd": [ "./vendor/bin/fzf-php-install" ] } }
See also: