Adam Pippin
4 years ago
19 changed files with 510 additions and 316 deletions
@ -1,64 +1,119 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
namespace App; |
namespace App; |
||||
|
|
||||
use Symfony\Component\Yaml\Yaml; |
use Symfony\Component\Yaml\Yaml; |
||||
|
|
||||
|
/** |
||||
|
* Represent the configuration containing screens and layouts |
||||
|
* |
||||
|
* @author Adam Pippin <hello@adampippin.ca> |
||||
|
*/ |
||||
class Configuration |
class Configuration |
||||
{ |
{ |
||||
|
/** |
||||
|
* Represents the available screens and their configuration |
||||
|
* @var array<string, Screen> |
||||
|
*/ |
||||
protected $_screens; |
protected $_screens; |
||||
|
|
||||
|
/** |
||||
|
* Represents the available layouts |
||||
|
* @var array<string, Layout> |
||||
|
*/ |
||||
protected $_layouts; |
protected $_layouts; |
||||
|
|
||||
|
/** |
||||
|
* Initialize an empty config |
||||
|
*/ |
||||
public function __construct() |
public function __construct() |
||||
{ |
{ |
||||
$this->_screens = []; |
$this->_screens = []; |
||||
$this->_layouts = []; |
$this->_layouts = []; |
||||
} |
} |
||||
|
|
||||
|
/** |
||||
|
* Load a configuration from a YAML file |
||||
|
* |
||||
|
* @param string $file |
||||
|
* @return void |
||||
|
*/ |
||||
public function load(string $file): void |
public function load(string $file): void |
||||
{ |
{ |
||||
$config = Yaml::parseFile($file); |
$config = Yaml::parseFile($file); |
||||
|
|
||||
foreach ($config['screens'] as $screen_name=>$screen) |
foreach ($config['screens'] as $screen_name => $screen) |
||||
{ |
{ |
||||
$this->_screens[$screen_name] = app()->make(\App\Screen::class, [ |
$this->_screens[$screen_name] = app()->make(\App\Screen::class, [ |
||||
'outputs'=>is_array($screen['output']) ? $screen['output'] : [$screen['output']] |
'outputs' => is_array($screen['output']) ? $screen['output'] : [$screen['output']] |
||||
]); |
]); |
||||
} |
} |
||||
|
|
||||
foreach ($config['layouts'] as $layout=>$data) |
foreach ($config['layouts'] as $layout => $data) |
||||
{ |
{ |
||||
$this->_layouts[$layout] = app()->make(\App\Layout::class, ['screens'=>$data['screens'], 'links'=>$data['links']]); |
$this->_layouts[$layout] = app()->make(\App\Layout::class, ['screens' => $data['screens'], 'links' => $data['links']]); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
public function getScreen(string $screen): Screen |
/** |
||||
|
* Fetch a specific screen |
||||
|
* |
||||
|
* @param string $screen_name |
||||
|
* @return Screen |
||||
|
*/ |
||||
|
public function getScreen(string $screen_name): Screen |
||||
{ |
{ |
||||
return $this->_screens[$screen]; |
return $this->_screens[$screen_name]; |
||||
} |
} |
||||
|
|
||||
|
/** |
||||
|
* Fetch the primary screen |
||||
|
* |
||||
|
* @return Screen |
||||
|
*/ |
||||
public function getPrimaryScreen(): Screen |
public function getPrimaryScreen(): Screen |
||||
{ |
{ |
||||
return $this->getScreen($this->getPrimaryScreenName()); |
return $this->getScreen($this->getPrimaryScreenName()); |
||||
} |
} |
||||
|
|
||||
|
/** |
||||
|
* Fetch the name of the primary screen |
||||
|
* |
||||
|
* @return string |
||||
|
*/ |
||||
public function getPrimaryScreenName(): string |
public function getPrimaryScreenName(): string |
||||
{ |
{ |
||||
foreach ($this->_screens as $name=>$screen) |
foreach ($this->_screens as $name => $screen) |
||||
{ |
{ |
||||
if ($screen->isPrimary()) |
if ($screen->isPrimary()) |
||||
|
{ |
||||
return $name; |
return $name; |
||||
|
} |
||||
} |
} |
||||
|
|
||||
|
throw new \Exception("No primary screen found"); |
||||
} |
} |
||||
|
|
||||
|
/** |
||||
|
* Fetch a specific layout |
||||
|
* |
||||
|
* @param string $layout |
||||
|
* @return Layout |
||||
|
*/ |
||||
public function getLayout(string $layout): Layout |
public function getLayout(string $layout): Layout |
||||
{ |
{ |
||||
return $this->_layouts[$layout]; |
return $this->_layouts[$layout]; |
||||
} |
} |
||||
|
|
||||
|
/** |
||||
|
* Fetch all the layouts |
||||
|
* |
||||
|
* @return array<string, Layout> |
||||
|
*/ |
||||
public function getLayouts(): array |
public function getLayouts(): array |
||||
{ |
{ |
||||
return $this->_layouts; |
return $this->_layouts; |
||||
} |
} |
||||
|
|
||||
} |
} |
||||
|
@ -1,71 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App; |
|
||||
|
|
||||
class Display |
|
||||
{ |
|
||||
protected $_names; |
|
||||
protected $_output; |
|
||||
protected $_width; |
|
||||
protected $_height; |
|
||||
protected $_x; |
|
||||
protected $_y; |
|
||||
|
|
||||
public function __construct(array $names) |
|
||||
{ |
|
||||
$this->_names = $names; |
|
||||
} |
|
||||
|
|
||||
public function read() |
|
||||
{ |
|
||||
foreach ($this->_names as $name) |
|
||||
{ |
|
||||
$xrandr = trim(shell_exec('xrandr | grep "^'.$name.'"')); |
|
||||
if (!empty($xrandr)) |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
if (empty($xrandr)) |
|
||||
throw new \Exception("Cannot load display: ".end($this->_names)); |
|
||||
|
|
||||
# DVI-I-2-1 connected 1920x1080+1920+1440 (normal left inverted right x axis y axis) 521mm x 293mm |
|
||||
if (!preg_match('/^(?<output>[^ ]+) connected (?<screen_w>[0-9]+)x(?<screen_h>[0-9]+)\\+(?<screen_x>[0-9]+)\\+(?<screen_y>[0-9]+) /', $xrandr, $matches)) |
|
||||
throw new \Exception("Cannot parse xrandr response for: ".$name); |
|
||||
|
|
||||
$this->_output = $matches['output']; |
|
||||
$this->_x = $matches['screen_x']; |
|
||||
$this->_y = $matches['screen_y']; |
|
||||
$this->_width = $matches['screen_w']; |
|
||||
$this->_height = $matches['screen_h']; |
|
||||
} |
|
||||
|
|
||||
public function getX(): int |
|
||||
{ |
|
||||
return (int)$this->_x; |
|
||||
} |
|
||||
|
|
||||
public function getY(): int |
|
||||
{ |
|
||||
return (int)$this->_y; |
|
||||
} |
|
||||
|
|
||||
public function getWidth(): int |
|
||||
{ |
|
||||
return (int)$this->_width; |
|
||||
} |
|
||||
|
|
||||
public function getHeight(): int |
|
||||
{ |
|
||||
return (int)$this->_height; |
|
||||
} |
|
||||
|
|
||||
public function setOffset(int $x, int $y): void |
|
||||
{ |
|
||||
shell_exec('xrandr --output '.$this->_output.' --pos '.$x.'x'.$y); |
|
||||
} |
|
||||
|
|
||||
public function setDimensions(int $width, int $height): void |
|
||||
{ |
|
||||
shell_exec('xrandr --output '.$this->_output.' --mode '.$width.'x'.$height); |
|
||||
} |
|
||||
} |
|
@ -1,14 +1,67 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
namespace App; |
namespace App; |
||||
|
|
||||
|
/** |
||||
|
* Provide an interface to manipulating outputs |
||||
|
* |
||||
|
* @author Adam Pippin <hello@adampippin.ca> |
||||
|
*/ |
||||
interface ILayoutDriver |
interface ILayoutDriver |
||||
{ |
{ |
||||
|
|
||||
|
/** |
||||
|
* Set the offset of an output |
||||
|
* |
||||
|
* @param string $output |
||||
|
* @param int $x |
||||
|
* @param int $y |
||||
|
* @return void |
||||
|
*/ |
||||
public function setOffset(string $output, int $x, int $y): void; |
public function setOffset(string $output, int $x, int $y): void; |
||||
|
|
||||
|
/** |
||||
|
* Get the offset of an output |
||||
|
* |
||||
|
* @param string $output |
||||
|
* @return int[] x, y |
||||
|
*/ |
||||
public function getOffset(string $output): array; |
public function getOffset(string $output): array; |
||||
|
|
||||
|
/** |
||||
|
* Set the dimensions of the output |
||||
|
* |
||||
|
* @param string $output |
||||
|
* @param int $x |
||||
|
* @param int $y |
||||
|
* @return void |
||||
|
*/ |
||||
public function setDimensions(string $output, int $x, int $y): void; |
public function setDimensions(string $output, int $x, int $y): void; |
||||
|
|
||||
|
/** |
||||
|
* Get the dimensions of an output |
||||
|
* |
||||
|
* @param string $output |
||||
|
* @return int[] x, y |
||||
|
*/ |
||||
public function getDimensions(string $output): array; |
public function getDimensions(string $output): array; |
||||
|
|
||||
|
/** |
||||
|
* Check whether an output is connected |
||||
|
* |
||||
|
* @param string $output |
||||
|
* @return bool |
||||
|
*/ |
||||
public function isConnected(string $output): bool; |
public function isConnected(string $output): bool; |
||||
|
|
||||
|
/** |
||||
|
* Check whether the output is considered primary |
||||
|
* |
||||
|
* @param string $output |
||||
|
* @return bool |
||||
|
*/ |
||||
public function isPrimary(string $output): bool; |
public function isPrimary(string $output): bool; |
||||
} |
|
||||
|
|
||||
|
} |
||||
|
@ -1,28 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace App\Providers; |
|
||||
|
|
||||
use Illuminate\Support\ServiceProvider; |
|
||||
|
|
||||
class AppServiceProvider extends ServiceProvider |
|
||||
{ |
|
||||
/** |
|
||||
* Bootstrap any application services. |
|
||||
* |
|
||||
* @return void |
|
||||
*/ |
|
||||
public function boot() |
|
||||
{ |
|
||||
// |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Register any application services. |
|
||||
* |
|
||||
* @return void |
|
||||
*/ |
|
||||
public function register() |
|
||||
{ |
|
||||
// |
|
||||
} |
|
||||
} |
|
@ -1,61 +1,62 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
return [ |
return [ |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Application Name |
| Application Name |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| This value is the name of your application. This value is used when the |
| This value is the name of your application. This value is used when the |
||||
| framework needs to place the application's name in a notification or |
| framework needs to place the application's name in a notification or |
||||
| any other location as required by the application or its packages. |
| any other location as required by the application or its packages. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'name' => 'Monitor_layout', |
'name' => 'Monitor_layout', |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Application Version |
| Application Version |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| This value determines the "version" your application is currently running |
| This value determines the "version" your application is currently running |
||||
| in. You may want to follow the "Semantic Versioning" - Given a version |
| in. You may want to follow the "Semantic Versioning" - Given a version |
||||
| number MAJOR.MINOR.PATCH when an update happens: https://semver.org. |
| number MAJOR.MINOR.PATCH when an update happens: https://semver.org. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'version' => app('git.version'), |
'version' => app('git.version'), |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Application Environment |
| Application Environment |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| This value determines the "environment" your application is currently |
| This value determines the "environment" your application is currently |
||||
| running in. This may determine how you prefer to configure various |
| running in. This may determine how you prefer to configure various |
||||
| services the application utilizes. This can be overridden using |
| services the application utilizes. This can be overridden using |
||||
| the global command line "--env" option when calling commands. |
| the global command line "--env" option when calling commands. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'env' => 'development', |
'env' => 'development', |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Autoloaded Service Providers |
| Autoloaded Service Providers |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| The service providers listed here will be automatically loaded on the |
| The service providers listed here will be automatically loaded on the |
||||
| request to your application. Feel free to add your own services to |
| request to your application. Feel free to add your own services to |
||||
| this array to grant expanded functionality to your applications. |
| this array to grant expanded functionality to your applications. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'providers' => [ |
'providers' => [ |
||||
App\Providers\AppServiceProvider::class, |
|
||||
App\Providers\LayoutServiceProvider::class |
App\Providers\LayoutServiceProvider::class |
||||
], |
], |
||||
|
|
||||
]; |
]; |
||||
|
@ -1,80 +1,82 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
return [ |
return [ |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Default Command |
| Default Command |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| Laravel Zero will always run the command specified below when no command name is |
| Laravel Zero will always run the command specified below when no command name is |
||||
| provided. Consider update the default command for single command applications. |
| provided. Consider update the default command for single command applications. |
||||
| You cannot pass arguments to the default command because they are ignored. |
| You cannot pass arguments to the default command because they are ignored. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'default' => NunoMaduro\LaravelConsoleSummary\SummaryCommand::class, |
'default' => NunoMaduro\LaravelConsoleSummary\SummaryCommand::class, |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Commands Paths |
| Commands Paths |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| This value determines the "paths" that should be loaded by the console's |
| This value determines the "paths" that should be loaded by the console's |
||||
| kernel. Foreach "path" present on the array provided below the kernel |
| kernel. Foreach "path" present on the array provided below the kernel |
||||
| will extract all "Illuminate\Console\Command" based class commands. |
| will extract all "Illuminate\Console\Command" based class commands. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'paths' => [app_path('Commands')], |
'paths' => [app_path('Commands')], |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Added Commands |
| Added Commands |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| You may want to include a single command class without having to load an |
| You may want to include a single command class without having to load an |
||||
| entire folder. Here you can specify which commands should be added to |
| entire folder. Here you can specify which commands should be added to |
||||
| your list of commands. The console's kernel will try to load them. |
| your list of commands. The console's kernel will try to load them. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'add' => [ |
'add' => [ |
||||
// .. |
// .. |
||||
], |
], |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Hidden Commands |
| Hidden Commands |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| Your application commands will always be visible on the application list |
| Your application commands will always be visible on the application list |
||||
| of commands. But you can still make them "hidden" specifying an array |
| of commands. But you can still make them "hidden" specifying an array |
||||
| of commands below. All "hidden" commands can still be run/executed. |
| of commands below. All "hidden" commands can still be run/executed. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'hidden' => [ |
'hidden' => [ |
||||
NunoMaduro\LaravelConsoleSummary\SummaryCommand::class, |
NunoMaduro\LaravelConsoleSummary\SummaryCommand::class, |
||||
Symfony\Component\Console\Command\HelpCommand::class, |
Symfony\Component\Console\Command\HelpCommand::class, |
||||
Illuminate\Console\Scheduling\ScheduleRunCommand::class, |
Illuminate\Console\Scheduling\ScheduleRunCommand::class, |
||||
Illuminate\Console\Scheduling\ScheduleFinishCommand::class, |
Illuminate\Console\Scheduling\ScheduleFinishCommand::class, |
||||
Illuminate\Foundation\Console\VendorPublishCommand::class, |
Illuminate\Foundation\Console\VendorPublishCommand::class, |
||||
], |
], |
||||
|
|
||||
/* |
/* |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| Removed Commands |
| Removed Commands |
||||
|-------------------------------------------------------------------------- |
|-------------------------------------------------------------------------- |
||||
| |
| |
||||
| Do you have a service provider that loads a list of commands that |
| Do you have a service provider that loads a list of commands that |
||||
| you don't need? No problem. Laravel Zero allows you to specify |
| you don't need? No problem. Laravel Zero allows you to specify |
||||
| below a list of commands that you don't to see in your app. |
| below a list of commands that you don't to see in your app. |
||||
| |
| |
||||
*/ |
*/ |
||||
|
|
||||
'remove' => [ |
'remove' => [ |
||||
// .. |
// .. |
||||
], |
], |
||||
|
|
||||
]; |
]; |
||||
|
@ -1,22 +1,24 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
namespace Tests; |
namespace Tests; |
||||
|
|
||||
use Illuminate\Contracts\Console\Kernel; |
use Illuminate\Contracts\Console\Kernel; |
||||
|
|
||||
trait CreatesApplication |
trait CreatesApplication |
||||
{ |
{ |
||||
/** |
/** |
||||
* Creates the application. |
* Creates the application. |
||||
* |
* |
||||
* @return \Illuminate\Foundation\Application |
* @return \Illuminate\Foundation\Application |
||||
*/ |
*/ |
||||
public function createApplication() |
public function createApplication() |
||||
{ |
{ |
||||
$app = require __DIR__.'/../bootstrap/app.php'; |
$app = require __DIR__.'/../bootstrap/app.php'; |
||||
|
|
||||
$app->make(Kernel::class)->bootstrap(); |
$app->make(Kernel::class)->bootstrap(); |
||||
|
|
||||
return $app; |
return $app; |
||||
} |
} |
||||
} |
} |
||||
|
@ -1,20 +1,27 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
namespace Tests\Feature; |
namespace Tests\Feature; |
||||
|
|
||||
use Tests\TestCase; |
use Tests\TestCase; |
||||
|
|
||||
|
/** |
||||
|
* @internal |
||||
|
* @coversNothing |
||||
|
*/ |
||||
class InspiringCommandTest extends TestCase |
class InspiringCommandTest extends TestCase |
||||
{ |
{ |
||||
/** |
/** |
||||
* A basic test example. |
* A basic test example. |
||||
* |
* |
||||
* @return void |
* @return void |
||||
*/ |
*/ |
||||
public function testInspiringCommand() |
public function testInspiringCommand() |
||||
{ |
{ |
||||
$this->artisan('inspiring') |
$this->artisan('inspiring') |
||||
->expectsOutput('Simplicity is the ultimate sophistication.') |
->expectsOutput('Simplicity is the ultimate sophistication.') |
||||
->assertExitCode(0); |
->assertExitCode(0) |
||||
} |
; |
||||
|
} |
||||
} |
} |
||||
|
@ -1,10 +1,12 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
namespace Tests; |
namespace Tests; |
||||
|
|
||||
use LaravelZero\Framework\Testing\TestCase as BaseTestCase; |
use LaravelZero\Framework\Testing\TestCase as BaseTestCase; |
||||
|
|
||||
abstract class TestCase extends BaseTestCase |
abstract class TestCase extends BaseTestCase |
||||
{ |
{ |
||||
use CreatesApplication; |
use CreatesApplication; |
||||
} |
} |
||||
|
@ -1,18 +1,24 @@ |
|||||
<?php |
<?php |
||||
|
|
||||
|
declare(strict_types=1); |
||||
|
|
||||
namespace Tests\Unit; |
namespace Tests\Unit; |
||||
|
|
||||
use Tests\TestCase; |
use Tests\TestCase; |
||||
|
|
||||
|
/** |
||||
|
* @internal |
||||
|
* @coversNothing |
||||
|
*/ |
||||
class ExampleTest extends TestCase |
class ExampleTest extends TestCase |
||||
{ |
{ |
||||
/** |
/** |
||||
* A basic test example. |
* A basic test example. |
||||
* |
* |
||||
* @return void |
* @return void |
||||
*/ |
*/ |
||||
public function testBasicTest() |
public function testBasicTest() |
||||
{ |
{ |
||||
$this->assertTrue(true); |
$this->assertTrue(true); |
||||
} |
} |
||||
} |
} |
||||
|
Loading…
Reference in new issue