diff --git a/bin/phpl-config b/bin/phpl-config index 37844ea..58df479 100755 --- a/bin/phpl-config +++ b/bin/phpl-config @@ -17,6 +17,7 @@ function print_help() { printf(" -E Open configuration file in text editor\n"); printf(" --theme Change the color theme\n"); printf(" -h,--help Show this help\n"); + printf(" -c,--config Set a global configuration option\n"); printf("\n"); printf("Options: -b,--before Insert before specified item\n"); printf(" -a,--after Insert after specified item\n"); @@ -28,7 +29,7 @@ function print_help() { printf(" Add the git module to the prompt, include tag and branch, place before status\n"); } -$opts = cmdl_parse("hvi:d:e:a:b:s:t:n:lLE",[ +$opts = cmdl_parse("hvi:d:e:a:b:s:t:n:lLEc:",[ "h" => "help", "i" => "insert:", "d" => "delete:", @@ -42,7 +43,8 @@ $opts = cmdl_parse("hvi:d:e:a:b:s:t:n:lLE",[ "N" => "no-reload", "l" => "list", "L" => "list-modules", - "theme:" + "theme:", + "c" => "config:", ]); if (cmdl_get($opts,'help')) { @@ -148,13 +150,13 @@ if (cmdl_get($opts,'list')) { foreach ($themes as $theme) { $_CONFIG['theme'] = basename($theme,".theme"); config_write(); - $example = trim(exec("phpl-reload --theme; phpl-generate -r")); + $example = trim(exec(escapeshellcmd(__DIR__."/phpl-reload")." --theme -q; ".escapeshellcmd(__DIR__."/phpl-generate")." -r")); printf("%20s %s\n", basename($theme,".theme"), $example); } printf("\n"); $_CONFIG['theme']=$current; config_write(); - exec("phpl-reload --theme"); + exec(escapeshellcmd(__DIR__."/phpl-reload")." --theme"); exit(0); } if (!file_exists(PHPL_THEMES."/{$theme}.theme")) { @@ -164,6 +166,22 @@ if (cmdl_get($opts,'list')) { $_CONFIG['theme'] = $theme; config_write(); if (RELOAD) passthru("phpl-reload --theme"); +} elseif (($config = cmdl_get($opts,'config'))) { + if ($config == 'list') { + $help = config_option_gethelp(); + $vals = config_option_getall(); + printf("Options:\n"); + foreach ($vals as $key=>$value) { + printf(" \e[34;1m%15s\e[0m=\e[36m%-15s \e[32m# %s\e[0m\n", $key, var_export($value,true), $help[$key]); + } + return; + } + if (strpos($config,"=")===false) { + printf("Error: The --config option requires a key=value pair\n"); + return; + } + list ($key,$value) = explode("=",$config,2); + config_option_set($key, $value); } else { print_help(); return; diff --git a/bin/phpl-reload b/bin/phpl-reload index 841fa38..a353343 100755 --- a/bin/phpl-reload +++ b/bin/phpl-reload @@ -157,19 +157,23 @@ function reload_theme() { } } } + */ - if ($pragma_truecolor) { - $head = 'define("PRAGMA_TRUECOLOR", true);'; - } elseif ($pragma_256color) { - $head = 'define("PRAGMA_256COLOR", true);'; - } else { - $head = null; + $head = null; + switch (config_option_get('term.colormode')) { + case 1: + $head.= 'define("PRAGMA_256COLOR", true);'; + break; + case 2: + $head.= 'define("PRAGMA_TRUECOLOR", true);'; + break; + } + if (config_option_get('term.forceutf8')) { + $head.= 'define("PRAGMA_FORCE_UTF8",true);'; } - */ $themeLoader = new Theme(); $themeLoader->readTheme($theme_file); - $head = null; $rules = $themeLoader->getRulesets(); $icons = $themeLoader->getIcons(); diff --git a/lib/bootstrap.php b/lib/bootstrap.php index a572542..dc02b4e 100644 --- a/lib/bootstrap.php +++ b/lib/bootstrap.php @@ -63,6 +63,9 @@ class PHPL { } function icon($name) { - return array_key_exists($name,PHPL::$THEMEICONS)?PHPL::$THEMEICONS[$name]: + $val = array_key_exists($name,PHPL::$THEMEICONS)?PHPL::$THEMEICONS[$name]: (array_key_exists($name,PHPL::$ICONS)?PHPL::$ICONS[$name]:null); + if ((ord($val[0])>0x80) && IS_TTY && !defined('PRAGMA_FORCE_UTF8')) + return ""; + return $val; } diff --git a/lib/config.php b/lib/config.php index 8c42833..af266c3 100644 --- a/lib/config.php +++ b/lib/config.php @@ -1,6 +1,8 @@ [ 0, VarType::enum(0,[0,1,2]), "Terminal color mode: 0=16 color, 1=256 color mode and 2=true color mode" ], + "term.forceutf8" => [ false, VarType::bool(false), "If true, always output UTF-8 even if running on a console" ], +]; function config_read() { assert(PHPL_CONFIG); - global $_CONFIG; + global $_CONFIG,$_OPTIONS; if (!file_exists(PHPL_CONFIG)) { config_write(); @@ -36,14 +43,14 @@ function config_read() { $root = SdlParser::parseFile(PHPL_CONFIG); - $items = $root->getChildrenByTagName('items')[0]; - if (!$items) { - fprintf(STDERR, "Error: No items defined in configuration file!\n"); + $items = $root->getChildrenByTagName('items'); + if (count($items)==0) { + fprintf(STDERR, "Error: No items block in configuration file!\n"); exit(1); } $_CONFIG['items'] = []; - foreach ($items->getChildren() as $item) { + foreach ($items[0]->getChildren() as $item) { $type = $item->getTagName(); $name = $item->getValue()?:$type; $attr = $item->getAttributeStrings(); @@ -51,6 +58,18 @@ function config_read() { $name, $type, $attr ]; } + $options = $root->getChildrenByTagName('options'); + if (count($options)>0) { + foreach ($options[0]->getChildren() as $option) { + $key = $option->getValue(); + $value = $option->getAttribute("value"); + if (!array_key_exists($key, $_OPTIONS)) { + printf("Warning: No such global option %s\n", $key); + continue; + } + $_OPTIONS[$key][0] = $value; + } + } $theme = $root->getChildrenByTagName('theme'); $theme = end($theme); @@ -61,7 +80,7 @@ function config_read() { function config_write() { assert(PHPL_CONFIG); - global $_CONFIG, $_MODULES; + global $_CONFIG, $_OPTIONS, $_MODULES; $root = new SdlTag(); @@ -77,13 +96,57 @@ function config_write() { printf("Warning: No such option %s for %s\n", $k, $item[0]); } } - + $options = $root->createChild("options"); + foreach ($_OPTIONS as $key=>$option) { + $val = $options->createChild("set"); + $val->setValue($key); + $val->setAttribute("value", $option[0]); + } $root->createChild("theme")->setValue($_CONFIG['theme']); file_put_contents(PHPL_CONFIG, $root->encode()); config_read(); } + +function config_option_getall() { + global $_OPTIONS; + $ret = []; + foreach ($_OPTIONS as $k=>$v) { + $ret[$k] = $v[0]; + } + return $ret; +} +function config_option_gethelp() { + global $_OPTIONS; + $ret = []; + foreach ($_OPTIONS as $k=>$v) { + $ret[$k] = $v[2]; + } + return $ret; +} +function config_option_get($key) { + global $_OPTIONS; + if (!array_key_exists($key,$_OPTIONS)) { + throw new \Exception("No such global option {$key}"); + } + return $_OPTIONS[$key][0]; +} +function config_option_set($key,$value) { + global $_OPTIONS; + if (!array_key_exists($key,$_OPTIONS)) { + throw new \Exception("No such global option {$key}"); + } + $opt = $_OPTIONS[$key]; + if (!$opt[1]->isValid($value)) { + throw new \InvalidArgumentException("Invalid value for option {$key}"); + return; + } + $cast = $opt[1]->cast($value); + $_OPTIONS[$key][0] = $cast; + +} + function config_item_delete($name) { global $_CONFIG; $filtered = []; diff --git a/lib/generate.php b/lib/generate.php index 296cce4..b73bd43 100644 --- a/lib/generate.php +++ b/lib/generate.php @@ -106,7 +106,7 @@ function generate(...$items) { if (!($item instanceof Panel)) continue; theme($item); - $show[] = $item; + $show[] = (string)$item; } $generated = join("",$show); echo $generated; @@ -213,3 +213,5 @@ function style($fg=NONE,$bg=NONE,$attr=NONE) { return "{$pre}{$text}{$post}"; }; } + +define("IS_TTY",(strpos(exec("tty"),"/dev/tty")===0)); \ No newline at end of file diff --git a/lib/vartype.php b/lib/vartype.php new file mode 100644 index 0000000..c94c2be --- /dev/null +++ b/lib/vartype.php @@ -0,0 +1,90 @@ +0)?$args[0]:null; + $conf=(count($args)>1)?$args[1]:null; + if (!array_key_exists($method,self::$TYPES)) { + throw new \Exception("No such var type: {$method}"); + } + return new VarType($method,$def,$conf); + } + + public function __construct($type,$def,$conf) + { + $this->type = $type; + $this->def = $def; + $this->conf = $conf; + } + + public function isValid($value) + { + $func = self::$TYPES[$this->type][0]; + if ($func instanceof \Closure) { + return call_user_func($func, $value, $this->conf); + } else { + return call_user_func($func, $value); + } + } + + /** + * Returns the string value cast to the variable type. Throws + * an error on invalid data. + * + */ + public function cast($value) + { + $func = self::$TYPES[$this->type][1]; + try { + $ret = call_user_func($func, $value); + return $ret; + } catch (\Exception $e) { + return $this->def; + } + } + + public function getType() + { + return $this->type; + } + + public function getDefault() + { + return $this->def; + } + + public function getNullable() + { + return $this->nullable; + } +} + +VarType::bindType("int", "is_numeric", "intval"); +VarType::bindType("float", "is_numeric", "floatval"); +VarType::bindType("string", "is_string", "strval"); + +VarType::bindType("bool", + function($v) { return in_array($v,[1,0,"yes","no","true","false","on","off",true,false]); }, + function($v) { return in_array($v,[1,"yes","true","on",true],true); } +); + +VarType::bindType("enum", + function($v,$c) { return in_array($v,(array)$c); }, + function($v) { return $v; } +); diff --git a/modules/git.php b/modules/git.php index e825485..60fafe9 100644 --- a/modules/git.php +++ b/modules/git.php @@ -43,7 +43,9 @@ function _git(array $opts) { $marks[] = icon("git.tag").(strpos($tag,'-')?substr($tag,0,strpos($tag,'-')).'+':$tag); } - return panel(sprintf("%s%s %s", icon('git.branch'), $branch, join(" ",$marks)), ['class'=>'vcs'], 'git'); + $out = sprintf("%s%s %s", icon('git.branch'), $branch, join(" ",$marks)); + + return panel($out, ['class'=>'vcs'], 'git'); } module("git", "Show status from git repositories", [ "git", "vcs" ]); diff --git a/powerline.fish b/powerline.fish new file mode 100644 index 0000000..30fcddc --- /dev/null +++ b/powerline.fish @@ -0,0 +1,3 @@ +function fish_prompt + phpl-generate -r -s $status +end