• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

使用IDEA进行Lua代码调试、自动提示、代码跳转、智能重命名

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

试了几个Lua IDE后,Lua Studio、Lua Glider、VS+babelua插件、Sublime都不是特别满意。直到发现了国人自创的另一个神奇工具:基于IDEA的EmmyLua插件。该插件功能非常完整:断点调试、自动提示、代码跳转、智能重命名等,可以极大地提高Lua编程的速度。界面也比较舒服。

安装步骤

下载、安装并**IntelliJ IDEA(我的版本是目前最新的2017.3.4)
安装EmmyLua插件
建议直接在IDEA工具内搜索插件安装(当然也可以下载插件到硬盘安装)。
(1)在启动界面点击Configure-Plugins:

(2)搜索EmmyLua,然后点Search in repositories:

(3)点击右边的Install绿色按钮。安装完需要重启IDEA。

Intellij Idea设置

首先需要配置Lua的SDK路径(上文的Lua环境)

目录需要选中到可以找到 lua.exe 那一层

创建新的Lua工程
方法:File–New–Project–Lua

选择好你的SDK,Next, 选择你的项目路径和名字。

右键项目目录,New–LuaFile
填入要新建的脚本名字,后缀lua可以加也可以不加。

输入简单的Lua语句,等待测试。

3.设置默认的Lua解释器路径
菜单栏 Run

如果设置正确,以后就可以直接运行Lua程序了。

配置其他事项。

(1)将*.txt识别成lua文件:

(2)忽略代码提示大小写差别:

创建项目

创建普通Lua项目(不依赖其他程序,如游戏引擎):
New-Project,然后next,填项目名、路径,点击finish。
在项目视图的src文件夹New一个Lua文件,可以自己print()一下,Run一下,看看有没有输出,有的话,说明SDK配置正确。


创建Unity引擎Lua项目
New-Modules from existing sources(注意不要选错,这里创建的是Modules,不是Project,否则等下导入不了api自动提示的library)。【这里有一个IDE Bug:第一次创建Modules,会在文件夹里生成一个.iml文件。但是如果文件夹里本来就有.iml文件,以后再点Modules from existing sources就会无法生成Modules,也就无法导入library。这个Bug我折腾了一晚上才发现的!必须删掉.iml文件,才可以重新创建Modules】
然后选择Unity文件夹的Lua访问根目录,我选的是Resources文件夹,因为可以从Resources作为根目录搜索lua文件。
然后我们测试一下断点调试功能。打开其中一个Lua文件,设置断点:

然后Run-Attach To Local Process:

选择Unity进程,触发断点,说明能断点调试:

Unity API代码提示

现在Unity API代码提示是没有的,因为我们还没导入API描述的library。这个library根据你选择的Lua中间件不同而不同,所以建议是自己导出。我的Lua中间件是SLua。这里以SLua为例。
1.打开SLua官方自带的Unity项目,在Slua-Editor下面,新建一个SLuaApiExporter.cs脚本:

2.输入如下代码:

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using SLua;
using System.IO;
using UnityEngine;

namespace Slua
{
    public static class EmmyLuaApiExporter
    {
        [MenuItem("SLua/导出EmmyLuaApi", false, 14)]
        static void Gen()
        {
            string path = "./EmmyApi/";
            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);
            }
            Directory.CreateDirectory(path);
            //UnityEngine
            GenAssembly("UnityEngine", path);
            //GenAssembly("UnityEngine.UI", path);
            GenCustom(path);
        }

        public static void GenAssembly(string name, string path)
        {
            List<string> excludeList;
            List<string> includeList;
            CustomExport.OnGetNoUseList(out excludeList);
            CustomExport.OnGetUseList(out includeList);
            Type[] types = Assembly.Load(name).GetTypes();
            foreach (Type t in types)
            {
                if (LuaCodeGen.filterType(t, excludeList, includeList))
                {
                    GenType(t, false, path);
                }
            }
        }

        public static void GenCustom(string path)
        {
            Type[] types = Assembly.Load("Assembly-CSharp-firstpass").GetTypes();
            foreach (Type t in types)
            {
                if (t.IsDefined(typeof(CustomLuaClassAttribute), false))
                {
                    GenType(t, true, path);
                }
            }

            types = Assembly.Load("Assembly-CSharp").GetTypes();
            foreach (Type t in types)
            {
                if (t.IsDefined(typeof(CustomLuaClassAttribute), false))
                {
                    GenType(t, true, path);
                }
            }
        }
        public static void GenType(Type t, bool custom, string path)
        {
            if (!CheckType(t, custom))
                return;
            //TODO System.MulticastDelegate
            var sb = new StringBuilder();
            if (!CheckType(t.BaseType, custom))
                sb.AppendFormat("[email protected] {0}\n", t.Name);
            else
                sb.AppendFormat("[email protected] {0} : {1}\n", t.Name, t.BaseType.Name);
            GenTypeField(t, sb);
            sb.AppendFormat("local {0}={{ }}\n", t.Name);

            GenTypeMehod(t, sb);

            sb.AppendFormat("{0}.{1} = {2}", t.Namespace, t.Name, t.Name);

            File.WriteAllText(path + t.FullName + ".lua", sb.ToString(), Encoding.UTF8);
        }

        static bool CheckType(Type t, bool custom)
        {
            if (t == null)
                return false;
            if (t == typeof(System.Object))
                return false;
            if (t.IsGenericTypeDefinition)
                return false;
            if (t.IsDefined(typeof(ObsoleteAttribute), false))
                return false;
            if (t == typeof(YieldInstruction))
                return false;
            if (t == typeof(Coroutine))
                return false;
            if (t.IsNested)
                return false;
            if (custom && !t.IsDefined(typeof(CustomLuaClassAttribute), false))
                return false;
            return true;
        }

        public static void GenTypeField(Type t, StringBuilder sb)
        {
            FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            foreach(var field in fields)
            {
                if (field.IsDefined(typeof(DoNotToLuaAttribute), false))
                    continue;
                sb.AppendFormat("[email protected] public {0} {1}\n", field.Name, GetLuaType(field.FieldType));
            }
            PropertyInfo[] properties = t.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            foreach (var pro in properties)
            {
                if (pro.IsDefined(typeof(DoNotToLuaAttribute), false))
                    continue;
                sb.AppendFormat("[email protected] public {0} {1}\n", pro.Name, GetLuaType(pro.PropertyType));
            }
        }

        public static void GenTypeMehod(Type t, StringBuilder sb)
        {
            MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            foreach (var method in methods)
            {
                if (method.IsGenericMethod)
                    continue;
                if (method.IsDefined(typeof(DoNotToLuaAttribute), false))
                    continue;
                if(method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
                    continue;
                sb.AppendLine("[email protected]");
                var paramstr = new StringBuilder();
                foreach (var param in method.GetParameters())
                {
                    sb.AppendFormat("[email protected] {0} {1}\n", param.Name, GetLuaType(param.ParameterType));
                    if (paramstr.Length != 0)
                    {
                        paramstr.Append(", ");
                    }
                    paramstr.Append(param.Name);
                }
                sb.AppendFormat("[email protected] {0}\n", method.ReturnType == null ? "void" : GetLuaType(method.ReturnType));
                if( method.IsStatic)
                {
                    sb.AppendFormat("function {0}.{1}({2}) end\n", t.Name, method.Name, paramstr);
                }
                else
                {
                    sb.AppendFormat("function {0}:{1}({2}) end\n", t.Name, method.Name, paramstr);
                }
            }
        }

        static string GetLuaType(Type t)
        {
            if (t.IsEnum
                //|| t == typeof(ulong)
                //|| t == typeof(long)
                //|| t == typeof(int)
                //|| t == typeof(uint)
                //|| t == typeof(float)
                || t == typeof(double)
                //|| t == typeof(byte)
                //|| t == typeof(ushort)
                //|| t == typeof(short)
                )
                return "number";
            if (t == typeof(bool))
                return "bool";
            if (t == typeof(string))
                return "string";
            if (t == typeof(void))
                return "void";

            return t.Name;
        }
    }
}

3.在Unity编辑器中点击SLua-导出EmmyLuaApi

4.看到Unity工程项目会多出一个EmmyApi文件夹:

5.将其打包成zip文件(注意不能是rar、7z其它压缩格式!)

6.在IDEA中点击File-Project Structure,Modules-选择我们的Modules-Dependencies,+号-Library-Lua Zip Library,选择我们刚才打包的zip文件。然后一直OK保存就行了。


7.测试Unity API提示功能:

成功!

其它功能

代码跳转:

智能重命名:

后续

本教程就到这里结束了,但是该插件还有许多有用的功能,可以自行探索,也可以加入EmmyLua的官方QQ群:29850775。群里面有许多教程,本文所用的API导出代码也是从群文件里拿出来改的。

github: https://github.com/tangzx/IntelliJ-EmmyLua
oschina: http://git.oschina.net/tangzx/IntelliJ-Lua
IDEA Plugins : https://plugins.jetbrains.com/plugin/9768-emmylua

最后感谢EmmyLua的作者们无私开源编写了这个强大的插件。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
理解Lua的那些坑爹特性发布时间:2022-07-22
下一篇:
lua学习之路发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap