sublime怎么导入php网站项目,php类库到sublime完成 Web程序 - 贪吃蛇学院-专业IT技术平台...

本文介绍了一个PHP开发者如何利用反射类和自定义的`SublimeSnippetBuilder`类来生成Sublime Text的ThinkPHP函数补全文件。通过获取用户定义的常量、函数和类,构建触发器和内容模板,实现按需补全功能。文章还展示了如何处理函数和类方法的参数,包括可选参数和默认值。作者分享了代码实现,并指出此方法可应用于其他文本编辑器的补全生成。
摘要由CSDN通过智能技术生成

likes.svg?style=flat-square

起因 前一篇写了反射类生成php速查表。过年了在家也没事,想完成自己想要实现的sublime自动完成文件生成。就是sublime里输入关键字后按tab自动补全一个全的函数名和参数的,按tab可以切换一致到最后的。也是给别人的承诺,今年肯定会实现sublime的tp5插件的。

18b76effb4a24f1005305635fbbdd548.png

思路

搞清sublime 完成的写法 "HTML_FILE_SUFFIX",

"TEMPLATE_NAME",

{ "trigger": "_ad", "contents": "protected function _after_delete(\\$data,\\$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,\\$options) {\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 \\}}\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()$0" },

{ "trigger": "_get", "contents": "_get(‘${1:\\$name}‘)$0" },

{ "trigger": "_post", "contents": "_post(‘${1:\\$name}‘)$0" },

{ "trigger": "->_sql", "contents": "->_sql(‘${1:\\$name}‘)$0" },

{ "trigger": "->addAll", "contents": "->addAll(\\$${1:dataList},\\$${2:options},\\$${3:replace})$0" },

这个是写在Sublime的ThinkPHP 插件里 php.sublime-completions 文件里的。

completion 和snippet的区别在于 snippet只能一个文件一个补全。命令面版里有提示。

字符串

json 里直接字符串

tab占位

$0 完成的最后光标

tab 选中光标 ${1:XX} 1自增下标,: 选中的内容

trigger 触发器

表示什么文本末按tab会触发完成。

注意点

$ 换行之类的要转义

php如何获取

先上核心代码: <?php

namespace util;

class SnippetBuilder

{

public $cme;

public function __construct($classes)

{

// if (false == defined(‘THINK_VERSION‘)) {

// throw new \Exception(‘请在thinkphp应用中执行本类‘, 1);

// }

$this->cme = new ClassMethodExtractor();

// $this->framework_type = version_compare(THINK_VERSION, ‘5‘) >= 0 ? 5 : 3;

$this->classes = $classes;

}

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) {

$class2 = $this->cme->getClassAnnotation(new \ReflectionClass($class));

$this->buildClass($class2);

}

}

if ($this->ret) {

file_put_contents($path, $this->parseAll($this->ret));

} else {

exit(‘没有可生成的内容‘);

}

}

// 获取常量数组

public function getConsts()

{

$all_consts = get_defined_constants(true);

return array_keys($all_consts[‘user‘]);

}

// 生成常量完成

public function buildConsts($consts)

{

foreach ($consts as $key => &$const) {

$this->ret[] = $const;

}

}

// 生成类的完成

public function buildClass($classes)

{

}

// 获取定义的函数

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;

}

// 生成函数

public function buildFunction($functions)

{

}

}

常量 // 获取常量数组

public function getConsts()

{

$all_consts = get_defined_constants(true);

return array_keys($all_consts[‘user‘]);

}

php有函数,且会区分core user 和扩展的。我们只需要user定义,也就是tp框架定义的。

函数 // 获取定义的函数

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也有个获取全部函数名的方法。同样只拿user

然后新的函数反射类 new \ReflectionFunction($name);

获取它的参数 $refFunc->getParameters();

$all_class = get_declared_classes();

这回没有user好事了,不过可以反射类isInternal区分。 // 获取全部用户定义的类

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);

}

}

用cme类提取出类和对应方法及参数。

生成

我写了 SublimeSnippetBuilder来继承我之前的 SnippetBuilder,因为我想做的是所有文本编辑器的完成生成。先架构好结构,以后慢慢填坑。

先整体代码: <?php

namespace util;

class SublimeSnippetBuilder extends SnippetBuilder

{

// 生成函数

public function buildFunction($functions)

{

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()) {

// 获取某些内部类的参数会抛异常,且异常时$class会变化不是我们想知道的哪个类方法一场了

try {

$defaul = $p->getDefaultValue();

$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) . ‘$0‘;

$foo = [

‘trigger‘ => $name,

‘contents‘ => $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()) {

// 获取某些内部类的参数会抛异常,且异常时$class会变化不是我们想知道的哪个类方法一场了

try {

$defaul = $p->getDefaultValue();

$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) . ‘$0‘;

$foo = [

‘trigger‘ => $trigger_name,

‘contents‘ => $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);

}

}

其实 就是生成对应的多维数组,数字索引为常量,函数方法为多维数组。

函数的trigger就是函数名,类无非::、->后跟方法名

然后区分代参不带参,带参再遍历参数,区分引用和默认值的情况。用了sprintf 方法拼接${index:content} 这种格式。

最终生成json,用了JSON_PRETTY_PRINT 格式化输出后写文件。

整体思路还是很清晰的。

其他语言的可以借鉴。

6d9e1d9644a189475221cfed2bf8db89.png

效果:

6cb1c5461e8de6d2517ad2d8450ed363.png

一下子两千行,手写得累死。

其实,大家只需扩展getAllUserClasses 就可以生成其他类的,比如swoole的。

题外话,新插件提交wbond 开始用branch 结果不推荐了要tag。我折腾了几次才通过ci。人家不高兴了。不给我过,有能力的直接git clone吧。视图那没找到规律先手写的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值