├── .gitignore ├── .travis.yml ├── LICENSE.md ├── composer.json ├── phpunit.xml ├── readme.md ├── src └── SteveEdson │ └── BitBar.php └── tests └── BitbarTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | ### JetBrains template 2 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 3 | 4 | *.iml 5 | 6 | ## Directory-based project format: 7 | .idea/ 8 | # if you remove the above rule, at least ignore the following: 9 | 10 | # User-specific stuff: 11 | # .idea/workspace.xml 12 | # .idea/tasks.xml 13 | # .idea/dictionaries 14 | 15 | # Sensitive or high-churn files: 16 | # .idea/dataSources.ids 17 | # .idea/dataSources.xml 18 | # .idea/sqlDataSources.xml 19 | # .idea/dynamic.xml 20 | # .idea/uiDesigner.xml 21 | 22 | # Gradle: 23 | # .idea/gradle.xml 24 | # .idea/libraries 25 | 26 | # Mongo Explorer plugin: 27 | # .idea/mongoSettings.xml 28 | 29 | ## File-based project format: 30 | *.ipr 31 | *.iws 32 | 33 | ## Plugin-specific files: 34 | 35 | # IntelliJ 36 | /out/ 37 | 38 | # mpeltonen/sbt-idea plugin 39 | .idea_modules/ 40 | 41 | # JIRA plugin 42 | atlassian-ide-plugin.xml 43 | 44 | # Crashlytics plugin (for Android Studio and IntelliJ) 45 | com_crashlytics_export_strings.xml 46 | crashlytics.properties 47 | crashlytics-build.properties 48 | ### Composer template 49 | composer.phar 50 | vendor/ 51 | 52 | # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file 53 | # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file 54 | # composer.lock 55 | 56 | # Created by .ignore support plugin (hsz.mobi) 57 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - '5.6' 4 | - '7.0' 5 | - '7.1' 6 | - '7.2' 7 | - nightly 8 | script: 9 | - composer install 10 | - phpunit -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Steve Edson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "steveedson/bitbar-php", 3 | "description": "PHP Formatter for BitBar plugins", 4 | "license": "MIT", 5 | "autoload": { 6 | "psr-4": { 7 | "SteveEdson\\": "src/SteveEdson" 8 | } 9 | }, 10 | "require": { 11 | "php": ">=5.6.0" 12 | }, 13 | "require-dev": { 14 | "phpunit/phpunit": "^5.7" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # BitBar PHP Formatter 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/steveedson/bitbar-php/v/stable)](https://packagist.org/packages/steveedson/bitbar-php) [![Total Downloads](https://poser.pugx.org/steveedson/bitbar-php/downloads)](https://packagist.org/packages/steveedson/bitbar-php) [![Latest Unstable Version](https://poser.pugx.org/steveedson/bitbar-php/v/unstable)](https://packagist.org/packages/steveedson/bitbar-php) [![License](https://poser.pugx.org/steveedson/bitbar-php/license)](https://packagist.org/packages/steveedson/bitbar-php) 4 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FSteveEdson%2Fbitbar-php.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FSteveEdson%2Fbitbar-php?ref=badge_shield) 5 | 6 | ## Installing 7 | 8 | Currently, BitBar reads any file in your directory a plugin, and tries to execute it. To workaround this, create a hidden folder, beginning with a dot, for example `.bitbar/`. In this directory create or edit your `composer.json` to include the library: 9 | 10 | 11 | ```json 12 | { 13 | "require": { 14 | "steveedson/bitbar-php": "dev-master" 15 | } 16 | } 17 | ``` 18 | 19 | or run `$ composer require "steveedson/bitbar-php"` 20 | 21 | ### File Structure 22 | 23 | You file structure inside your plugins directory, should look something like: 24 | 25 | ``` 26 | . 27 | ├── .bitbar/ 28 | │   ├── composer.json 29 | │   └── vendor/ 30 | └── test.5m.php 31 | ``` 32 | 33 | ## Usage 34 | 35 | In your BitBar plugins directory, create a file, e.g. `test.5m.php`. Don't forget to add the shebang at the beginning. 36 | 37 | ```php 38 | #!/usr/bin/php 39 | 40 | newLine(); 51 | 52 | // Set the text and formatting 53 | $line 54 | ->setText("Hello World") 55 | ->setColour("yellow") 56 | ->setUrl("https://steveedson.co.uk") 57 | ->show(); 58 | ``` 59 | 60 | ### Examples 61 | 62 | #### Using Sub Menus 63 | 64 | ```php 65 | // Create BitBar formatter 66 | $bb = new BitBar(); 67 | 68 | // Create the first line 69 | $line = $bb->newLine(); 70 | 71 | // Set the text and formatting 72 | $mainMenu = $line 73 | ->setText("Servers") 74 | ->setColour("yellow"); 75 | 76 | $mainMenu = $mainMenu->addSubMenu() 77 | ->newLine() 78 | ->setText("Server 1") 79 | ->setUrl('http://server1.com'); 80 | 81 | $mainMenu = $mainMenu->addSubMenu() 82 | ->newLine() 83 | ->setText("Server 2") 84 | ->setUrl('http://server2.com'); 85 | 86 | $mainMenu->show(); 87 | ``` 88 | 89 | 90 | ## License 91 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FSteveEdson%2Fbitbar-php.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FSteveEdson%2Fbitbar-php?ref=badge_large) -------------------------------------------------------------------------------- /src/SteveEdson/BitBar.php: -------------------------------------------------------------------------------- 1 | show(); 14 | } 15 | } 16 | 17 | class BitBarLine { 18 | protected $withinSubMenu = false; 19 | protected $usedPipe = false; 20 | protected $text; 21 | protected $colour; 22 | protected $url; 23 | protected $fontSize; 24 | protected $fontFace; 25 | protected $length; 26 | protected $terminal; 27 | protected $bash; 28 | protected $params = array(); 29 | protected $dropdown; 30 | protected $image; 31 | protected $imageIsTemplate = false; 32 | protected $trim = true; 33 | protected $refresh = false; 34 | protected $alternate = false; 35 | protected $disableEmoji = false; 36 | protected $disableAnsi = false; 37 | 38 | /** 39 | * BitBarLine constructor. 40 | * @param bool $withinSubMenu 41 | */ 42 | public function __construct($withinSubMenu = false) { 43 | $this->withinSubMenu = $withinSubMenu; 44 | } 45 | 46 | /** 47 | * @param mixed $text 48 | * @return $this 49 | */ 50 | public function setText($text) { 51 | $this->text = $text; 52 | return $this; 53 | } 54 | 55 | /** 56 | * @param $color 57 | * @return BitBarLine 58 | */ 59 | public function setColor($color) { 60 | return $this->setColour($color); 61 | } 62 | 63 | /** 64 | * @param mixed $colour 65 | * @return $this 66 | */ 67 | public function setColour($colour) { 68 | $this->colour = $colour; 69 | return $this; 70 | } 71 | 72 | /** 73 | * @param mixed $url 74 | * @return $this 75 | */ 76 | public function setUrl($url) { 77 | $this->url = $url; 78 | return $this; 79 | } 80 | 81 | /** 82 | * @param $length 83 | * @return $this 84 | */ 85 | public function setLength($length) { 86 | $this->length = $length; 87 | return $this; 88 | } 89 | 90 | /** 91 | * @param mixed $fontSize 92 | * @return $this 93 | */ 94 | public function setFontSize($fontSize) { 95 | $this->fontSize = $fontSize; 96 | return $this; 97 | } 98 | 99 | /** 100 | * @param mixed $fontFace 101 | * @return $this 102 | */ 103 | public function setFontFace($fontFace) { 104 | $this->fontFace = $fontFace; 105 | return $this; 106 | } 107 | 108 | /** 109 | * Trim leading/trailing whitespace from the title. 110 | * @return $this 111 | */ 112 | public function disableTrim() { 113 | $this->trim = false; 114 | return $this; 115 | } 116 | 117 | /** 118 | * @param $boolean 119 | * @return $this 120 | */ 121 | public function setTerminal($boolean) { 122 | $this->terminal = (boolean) $boolean; 123 | return $this; 124 | } 125 | 126 | 127 | /** 128 | * @param string $command Command to run when selected 129 | * @param array $params specify arguments to the script 130 | * @return $this 131 | */ 132 | public function setBash($command, array $params = array()) 133 | { 134 | $this->bash = $command; 135 | $this->params = $params; 136 | return $this; 137 | } 138 | 139 | /** 140 | * @param $boolean 141 | * @return $this 142 | */ 143 | public function setDropdown($boolean) { 144 | $this->dropdown = (boolean) $boolean; 145 | return $this; 146 | } 147 | 148 | /** 149 | * @param $boolean 150 | * @return $this 151 | */ 152 | public function setRefresh($boolean) { 153 | $this->refresh = (boolean) $boolean; 154 | return $this; 155 | } 156 | 157 | 158 | /** 159 | * @param $boolean 160 | * @return $this 161 | */ 162 | public function setAlternate($boolean) { 163 | $this->alternate = (boolean) $boolean; 164 | return $this; 165 | } 166 | 167 | /** 168 | * @return BitBarLine 169 | */ 170 | public function enableRefresh() { 171 | return $this->setRefresh(true); 172 | } 173 | 174 | /** 175 | * Base 64 encoded image, or path to image 176 | * @param $image 177 | * @param bool $isImageTemplate 178 | * @return $this 179 | */ 180 | public function setImage($image, $isImageTemplate = false) { 181 | $this->image = $image; 182 | $this->imageIsTemplate = $isImageTemplate; 183 | return $this; 184 | } 185 | 186 | /** 187 | * Disable converting :beer: -> Emoji 188 | * @param $disable 189 | * @return $this 190 | */ 191 | public function disableEmoji($disable = true) { 192 | $this->disableEmoji = $disable; 193 | return $this; 194 | } 195 | 196 | /** 197 | * Create a sub menu 198 | * 199 | * @return BitBarSubMenu 200 | */ 201 | public function addSubMenu() { 202 | $this->show(false); 203 | return new BitBarSubMenu(); 204 | } 205 | 206 | /** 207 | * Disable converting :beer: -> Emoji 208 | * @param $disable 209 | * @return $this 210 | */ 211 | public function disableAnsi($disable = true) { 212 | $this->disableAnsi = $disable; 213 | return $this; 214 | } 215 | 216 | /** 217 | * 218 | */ 219 | public function format() { 220 | if($this->withinSubMenu) { 221 | $string = '-- ' . $this->text; 222 | } else { 223 | $string = $this->text; 224 | } 225 | 226 | $this->usedPipe = false; 227 | 228 | if ($this->fontSize) { 229 | if (!$this->usedPipe) { 230 | $string .= '|'; 231 | $this->usedPipe = true; 232 | } 233 | 234 | $string .= ' size=' . $this->fontSize; 235 | } 236 | 237 | 238 | if ($this->fontFace) { 239 | if (!$this->usedPipe) { 240 | $string .= '|'; 241 | $this->usedPipe = true; 242 | } 243 | 244 | $string .= ' font=\'' . $this->fontFace . '\''; 245 | } 246 | 247 | if ($this->colour) { 248 | if (!$this->usedPipe) { 249 | $string .= '|'; 250 | $this->usedPipe = true; 251 | } 252 | 253 | $string .= ' color=' . $this->colour; 254 | } 255 | 256 | if ($this->url) { 257 | if (!$this->usedPipe) { 258 | $string .= '|'; 259 | $this->usedPipe = true; 260 | } 261 | 262 | $string .= ' href=' . $this->url; 263 | } 264 | 265 | if ($this->trim === false) { 266 | if (!$this->usedPipe) { 267 | $string .= '|'; 268 | $this->usedPipe = true; 269 | } 270 | 271 | $string .= ' trim=false'; 272 | } 273 | 274 | if ($this->alternate === true) { 275 | if (!$this->usedPipe) { 276 | $string .= '|'; 277 | $this->usedPipe = true; 278 | } 279 | 280 | $string .= ' alternate=true'; 281 | } 282 | 283 | if ($this->bash) { 284 | if (!$this->usedPipe) { 285 | $string .= '|'; 286 | $this->usedPipe = true; 287 | } 288 | 289 | $string .= sprintf(' bash="%s"', $this->bash); 290 | 291 | foreach(array_values($this->params) as $k => $param) 292 | $string .= sprintf(' param%s="%s"', ++$k, $param); 293 | } 294 | 295 | if ($this->refresh) { 296 | if (!$this->usedPipe) { 297 | $string .= '|'; 298 | $this->usedPipe = true; 299 | } 300 | 301 | $string .= ' refresh=true'; 302 | } 303 | 304 | if($this->disableEmoji) { 305 | if (!$this->usedPipe) { 306 | $string .= '|'; 307 | $this->usedPipe = true; 308 | } 309 | 310 | $string .= ' emojize=false'; 311 | } 312 | 313 | if($this->disableAnsi) { 314 | if (!$this->usedPipe) { 315 | $string .= '|'; 316 | $this->usedPipe = true; 317 | } 318 | 319 | $string .= ' ansi=false'; 320 | } 321 | 322 | if($this->image) { 323 | if (!$this->usedPipe) { 324 | $string .= '|'; 325 | $this->usedPipe = true; 326 | } 327 | 328 | // If file exists on system, or is a url 329 | if(is_file($this->image) || !filter_var($this->image, FILTER_VALIDATE_URL) === false) { 330 | $this->image = base64_encode(file_get_contents($this->image)); 331 | } 332 | 333 | if($this->imageIsTemplate) { 334 | $string .= ' templateImage="' . $this->image . '"'; 335 | } else { 336 | $string .= ' image="' . $this->image . '"'; 337 | } 338 | } 339 | 340 | if($this->terminal !== null) { 341 | if (!$this->usedPipe) { 342 | $string .= '|'; 343 | $this->usedPipe = true; 344 | } 345 | 346 | $string .= ' terminal='.json_encode($this->terminal); 347 | } 348 | 349 | if($this->dropdown !== null) { 350 | if (!$this->usedPipe) { 351 | $string .= '|'; 352 | $this->usedPipe = true; 353 | } 354 | 355 | $string .= ' dropdown='.json_encode($this->dropdown); 356 | } 357 | 358 | if ($this->length) { 359 | if (!$this->usedPipe) { 360 | $string .= '|'; 361 | $this->usedPipe = true; 362 | } 363 | 364 | $string .= ' length=' . $this->length; 365 | } 366 | 367 | return $string; 368 | } 369 | 370 | public function show($withDivide = true) { 371 | echo $this->format(); 372 | 373 | if(!$this->withinSubMenu && $withDivide) { 374 | echo "\n---\n"; 375 | } else { 376 | echo "\n"; 377 | } 378 | } 379 | } 380 | 381 | class BitBarSubMenu { 382 | public function newLine() { 383 | return new BitbarLine(true); 384 | } 385 | } -------------------------------------------------------------------------------- /tests/BitbarTest.php: -------------------------------------------------------------------------------- 1 | newLine() 12 | ->setText("Hello World") 13 | ->show(); 14 | 15 | $this->expectOutputString("Hello World\n---\n"); 16 | } 17 | } --------------------------------------------------------------------------------