Cause
前一篇写了反射类生成php速查表。过年了在家也没事,想完成自己想要实现的sublime自动完成文件生成。就是sublime里输入关键字后按tab自动补全一个全的函数名和参数的,按tab可以切换一致到最后的。也是给别人的承诺,今年肯定会实现sublime的tp5插件的。
Address in https://github.com/yangweijie/SublimeThinkPHP5.0
The idea of figuring out the sublime finish
"Html_file_suffix", "Template_name", {"trigger": "_ad", "Contents": "Protected function _after_delete (\ \ $da ta,\\ $options) {\ n ${1:}\n}$0 "}, {" Trigger ":" _af "," Contents ":" Protected function _after_find (&\\ $result, \ \ $options) {\ n ${1:}\n}$0 "}, {" Trigger ":" _ai "," Contents ":" Protected function _after_insert (\ \ $data, \ \ $option s) {\ n ${1:}\n}$0 "}, {" Trigger ":" _as "," Contents ":" Protected function _after_select (&\\ $result, \ \ $options {\ n ${1:foreach (\ $result as &\\ $record) \\{\n ${2:\\ $this->_after_find (\ \ $record, \ \ $options);} \ \\}}\n}$0 "}, {" Trigger ":" _au "," Contents ":" Protected function _after_update (\ \ $data, \ \ $options) {\ n ${1:} \n}$0 "}, {" Trigger ":" _bi "," Contents ":" Protected function _before_insert (&\\ $data, \ \ $options) {\ n ${1:}\n}$ 0 "}, {" Trigger ":" _bu "," Contents ":" Protected function _before_update (&\\ $data, \ \ $options) {\ n ${1:}\n}$0 "} , {"Trigger": "->_empty", "Contents ":" \ \ $this->_empty () "}, {" Trigger ":" _get "," Contents ":" _get (' ${1:\\ $name} ') $ "}, {" Trigg ER ":" _post "," Contents ":" _post (' ${1:\\ $name} ') "}, {" Trigger ":"->_sql "," Contents ":"->_sql (' ${1:\\ $nam e} ') $ "}, {" Trigger ":"->addall "," Contents ":"->addall (\\$${1:datalist},\\$${2:options},\\$${3:replace}) $ " },
This is written in the Php.sublime-completions file in Sublime's thinkphp plugin.
The difference between completion and snippet is that snippet can only be a single complement to a file. There are hints in the command panel.
String
Direct string in JSON
tab-Placeholder
$0
The last cursor completed
tab-Select Cursor ${1:XX}
1 increment subscript: Selected content
Trigger Trigger
Indicates what text at the end of the Press TAB will trigger completion.
Watch out.
$ line break or something to escape.
how PHP gets
First, the core code:
<?phpnamespace util;class snippetbuilder{public $cme; Public function __construct ($classes) {//if (false = = defined (' think_version ')) {//throw new \exc Eption (' Please perform this class in the thinkphp application ', 1); } $this->cme = new Classmethodextractor (); $this->framework_type = Version_compare (think_version, ' 5 ') >= 0? 5:3; $this->classes = $classes; The Public Function Buildall ($path) {$consts = $this->getconsts (); $functions = $this->getfunctions (); $classes = $this->classes; $this->ret = []; if ($consts) {$this->buildconsts ($consts); } if ($functions) {$this->buildfunction ($functions); if ($classes) {foreach ($classes as $class) {$class 2 = $this->cme->getclassanno Tation (New \reflectionclass ($class)); $this->buildclass ($class 2); } } if ($this->ret) {file_put_contents ($path, $this->parseall ($this->ret)); } else {exit (' no content to generate '); }}//Get constant array public function getconsts () {$all _consts = Get_defined_constants (true); Return Array_keys ($all _consts[' user '); }//Generate constant Complete public function buildconsts ($consts) {foreach ($consts as $key = & $const) { $this->ret[] = $const; }}//Generate the completion of the class public function Buildclass ($classes) {}//get the function defined public function getfunctions () { $arr = Get_defined_functions (); $ret = []; foreach ($arr [' user '] as $key = + $name) {$foo = []; $refFunc = new \reflectionfunction ($name); $foo [' args '] = $refFunc->getparameters (); $ret [$name] = $foo; } return $ret; }//Generate function Public function buildfunction ($functions) {}}
Constant
// 获取常量数组public function getConsts(){ $all_consts = get_defined_constants(true); return array_keys($all_consts[‘user‘]);}
PHP has functions that distinguish between the core user and the extended one. We only need the user definition, which is defined by the TP framework.
Function
// 获取定义的函数public function getFunctions(){ $arr = get_defined_functions(); $ret = []; foreach ($arr[‘user‘] as $key => $name) { $foo = []; $refFunc = new \ReflectionFunction($name); $foo[‘args‘] = $refFunc->getParameters(); $ret[$name] = $foo; } return $ret;}
PHP also has a way to get all the function names. Also only take user
Then the new function reflects the classnew \ReflectionFunction($name);
Get its parameters $refFunc->getparameters ();
Class
$all_class = get_declared_classes();
This time there is no user good, but can reflect the class isinternal distinguish.
// 获取全部用户定义的类 public function getAllUserClasses(){ $all_class = get_declared_classes(); $ret = []; foreach ($all_class as $class) { $rf = new \ReflectionClass($class); if(false == $rf->isInternal()){ if(‘app\index\controller\Index‘ == $class){ continue; } $ret[] = $class; } } return $ret; }
if ($classes) { foreach ($classes as $class) { $class2 = $this->cme->getClassAnnotation(new \ReflectionClass($class)); $this->buildClass($class2); } }
The class and corresponding methods and parameters are extracted by CME class.
Generated
I wrote sublimesnippetbuilder to inherit my previous snippetbuilder, because what I wanted to do was to complete the creation of all the text editors. First, the structure is good, slowly pits later.
First overall code:
<?phpnamespace util;class Sublimesnippetbuilder extends snippetbuilder{//Generate function Public function buildfunction ($fu nctions) {foreach ($functions as $name = = $fun) {$args _arr = [$name, ' (', ') ']; if ($fun [' args ']) {$args _arr = [$name, ' (']; $index = 1; foreach ($fun [' args '] as $key = + $arg) {$p = new \reflectionparameter ($name, $key); if ($p->ispassedbyreference ()) {$arg _str_new = ' \&\\$ '. $p->getname (); } else {$arg _str_new = ' \\$ '. $p->getname (); } if ($p->isoptional () && $p->isdefaultvalueavailable ()) {//Get some The parameters of the inner class throw an exception, and the $class changes when the exception is not the class method we want to know. try {$defaul = $p->getdefau Ltvalue (); $arg _str_new. = Is_array ($defaUL)? ' = [] ': ' = '. Var_export ($defaul, 1); } catch (\exception $e) {Trace ($p->isvariadic ()); Trace ($name. ‘_‘ . $key); }} if ($index = = 1) {$p _str = sprintf (' ${%d:%s} ', $index, $ Arg_str_new); } else {$p _str = sprintf (' ${%d:,%s} ', $index, $arg _str_new); } $args _arr[] = $p _str; $index + +; } $args _arr[] = ') '; } $contens = Implode ("', $args _arr). ' $ A '; $foo = [' Trigger ' = $name, ' contents ' and $contens,]; $this->ret[] = $foo; }} Public Function Buildclass ($class) {if ($class [' methods ']) {foreach ($class [' methods '] as $ Name = $fun) {SWITCH ($fun [' type ']) {case ' public_static ': Case ' private_static ': $trigger _name = ":: {$name}"; Break Case ' public_public ': Case ' private_public ': $trigger _name = "->{$name}"; Break Default: $trigger _name = "; Break } $args _arr = [$trigger _name, ' (', ') ']; if (Empty ($fun [' args ']) = = False) {$args _arr = [$trigger _name, ' (']; $index = 1; foreach ($fun [' args '] as $key = + $p) {if ($p->ispassedbyreference ()) { $arg _str_new = ' \&\\$ '. $p->getname (); } else {$arg _str_new = ' \\$ '. $p->getname (); } if ($p->isoptional () && $p->isdefaultvalueavailable ()) {//Get the parameters of some inner classes thrown out of the exception and vary Often $class change is not what we want to know which class method is a try {$defaul = $p->getdefaultval UE (); $arg _str_new. = Is_array ($defaul)? ' = [] ': ' = '. Var_export ($defaul, 1); } catch (\exception $e) {Trace ($p->isvariadic ()); Trace ($name. ‘_‘ . $key); }} if ($index = = 1) {$p _str = sprintf (' ${%d:%s} ', $index, $arg _str_new); } else {$p _str = sprintf (' ${%d:,%s} ', $index, $arg _str_new); } $args _arr[] = $p _str; $index + +; } $args _arr[] = ') '; } $contens = Implode (", $args _arr). ' $ A '; $foo = [' Trigger ' = $trigger _name, ' contents ' and $contens, ]; $this->ret[] = $foo; }}} Public function Parseall ($ret) {//dump ($ret); $ret = ["Scope" = "source.php-variable.other.php", "completions" +-$ret,]; Return Json_encode ($ret, json_pretty_print); }}
In fact, the corresponding multidimensional array is generated, the numeric index is constant, and the function method is a multidimensional array.
The function's trigger is the function name, the class is nothing ::
, ->
followed by the method name
It then distinguishes between the argument and the parameter, and the reference and default values. Using the sprintf method stitching ${index:content} This format.
Finally, JSON is generated, and the output is written using the Json_pretty_print format.
The whole idea is still very clear.
Other languages can be used for reference.
Effect:
2000 lines in a row, handwriting was exhausted.
In fact, you just need to expand getalluserclasses to generate other classes, such as Swoole.
digression, the new plugin submitted wbond started with branch results are not recommended to tag. I had to toss it a few times to pass CI. I'm not happy anymore. Do not give me, have the ability to direct git clone it. The view didn't find the rules to write.
PHP class Library to sublime complete