├── .gitattributes ├── .gitignore ├── .gitmodules ├── ConfigConvertTool.py ├── LICENSE ├── README.md ├── client ├── cfg_array_example1.xml ├── cfg_array_example2.xml ├── cfg_array_example3.xml ├── cfg_object.xml └── cfg_object1_cfg_object.xml ├── color_print.py ├── config_excel ├── A_array表示例--cfg_array.xlsx └── A_object表示例--cfg_object.xlsx ├── decoder.py ├── lancher.bat ├── lancher.sh ├── server ├── cfg_array.erl ├── cfg_array.ex ├── cfg_array.json ├── cfg_array.lua ├── cfg_array_example1.erl ├── cfg_array_example1.ex ├── cfg_array_example1.hrl ├── cfg_array_example1.json ├── cfg_array_example1.lua ├── cfg_array_example2.erl ├── cfg_array_example2.ex ├── cfg_array_example2.hrl ├── cfg_array_example2.json ├── cfg_array_example2.lua ├── cfg_array_example3.erl ├── cfg_array_example3.ex ├── cfg_array_example3.json ├── cfg_array_example3.lua ├── cfg_object.erl ├── cfg_object.ex ├── cfg_object.json ├── cfg_object.lua └── cfg_object1_cfg_object.ex ├── slpp ├── .gitignore ├── LICENSE ├── README.markdown ├── __init__.py ├── setup.py ├── slpp-c4d7f69af338f973c0ef21a9a06a145936367229.zip ├── slpp-c4d7f69af338f973c0ef21a9a06a145936367229 │ ├── .gitignore │ ├── LICENSE │ ├── README.markdown │ ├── __init__.py │ ├── setup.py │ ├── slpp.py │ └── tests.py ├── slpp.py └── tests.py ├── writer.py ├── writer_elixir.py ├── writer_erlang_erl.py ├── writer_erlang_hrl.py ├── writer_json_array.py ├── writer_json_object.py ├── writer_lua.py ├── writer_python.py └── writer_xml.py /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.zip binary 3 | *.tar.gz binary 4 | *.tar.bz2 binary 5 | *.xlsx binary 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # yongzhong office temp file 10 | $* 11 | 12 | # xlsx temp file 13 | ~*.xlsx 14 | .~*.xlsx 15 | 16 | 17 | # Distribution / packaging 18 | .Python 19 | env/ 20 | build/ 21 | develop-eggs/ 22 | dist/ 23 | downloads/ 24 | eggs/ 25 | .eggs/ 26 | lib/ 27 | lib64/ 28 | parts/ 29 | sdist/ 30 | var/ 31 | wheels/ 32 | *.egg-info/ 33 | .installed.cfg 34 | *.egg 35 | 36 | # PyInstaller 37 | # Usually these files are written by a python script from a template 38 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 39 | *.manifest 40 | *.spec 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .coverage 50 | .coverage.* 51 | .cache 52 | nosetests.xml 53 | coverage.xml 54 | *.cover 55 | .hypothesis/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # pyenv 82 | .python-version 83 | 84 | # celery beat schedule file 85 | celerybeat-schedule 86 | 87 | # SageMath parsed files 88 | *.sage.py 89 | 90 | # dotenv 91 | .env 92 | 93 | # virtualenv 94 | .venv 95 | venv/ 96 | ENV/ 97 | 98 | # Spyder project settings 99 | .spyderproject 100 | .spyproject 101 | 102 | # Rope project settings 103 | .ropeproject 104 | 105 | # mkdocs documentation 106 | /site 107 | 108 | # mypy 109 | .mypy_cache/ 110 | 111 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "slpp"] 2 | path = slpp 3 | url = https://github.com/changnet/slpp.git 4 | -------------------------------------------------------------------------------- /ConfigConvertTool.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import time 6 | from writer import * 7 | from writer_erlang_erl import * 8 | from writer_erlang_hrl import * 9 | from writer_elixir import * 10 | from writer_lua import * 11 | from writer_xml import * 12 | from writer_json_object import * 13 | from writer_json_array import * 14 | from writer_python import * 15 | from optparse import OptionParser 16 | 17 | from decoder import ExcelDoc 18 | 19 | class Reader: 20 | # @input_path:excel文件所在目录 21 | # @srv_path :server输出目录 22 | # @clt_path :客户端输出目录 23 | # @timeout :只处理文档最后更改时间在N秒内的文档 24 | # @suffix :excel文件后缀 25 | def __init__(self,input_path, 26 | srv_path,clt_path,timeout,suffix,srv_writer,clt_writer): 27 | self.input_path = input_path 28 | self.srv_path = srv_path 29 | self.clt_path = clt_path 30 | self.timeout = timeout 31 | self.suffix = suffix 32 | 33 | self.srv_writer = None 34 | self.clt_writer = None 35 | 36 | if None != srv_writer : 37 | self.srv_writer = eval( srv_writer.capitalize() + "Writer" ) 38 | if None != clt_writer : 39 | self.clt_writer = eval( clt_writer.capitalize() + "Writer" ) 40 | 41 | def attention(self): 42 | print("*****************************开始导表*****************************\n") 43 | 44 | def can_read(self,file,abspath): 45 | if not os.path.isfile( abspath ): return False 46 | # ~开头的excel文件是临时文件,linux下wps临时文件以.~开头 47 | if file.startswith( "~" ) \ 48 | or file.startswith( "." ) or file.startswith( "$" ): return False 49 | if "" != self.suffix and not file.endswith( self.suffix ): return False 50 | 51 | if self.timeout > 0: 52 | now = time.time() 53 | mtime = os.path.getmtime( abspath ) 54 | 55 | if now - mtime > self.timeout: return False 56 | 57 | return True 58 | 59 | def read(self): 60 | if self.timeout > 0 : 61 | print("read %s files from %s modified \ 62 | within %d seconds" % (self.suffix,self.input_path,self.timeout)) 63 | else : 64 | print("read %s files from %s" % (self.suffix,self.input_path)) 65 | 66 | if None != self.srv_path and not os.path.exists( self.srv_path ) : 67 | os.makedirs( self.srv_path ) 68 | if None != self.clt_path and not os.path.exists( self.clt_path ) : 69 | os.makedirs( self.clt_path ) 70 | 71 | now = time.time() 72 | file_list = os.listdir( options.input_path ) 73 | for file in file_list: 74 | abspath = os.path.join( self.input_path,file ) 75 | if self.can_read( file,abspath ) : 76 | self.read_one( file,abspath ) 77 | 78 | print( "done,%d seconds elapsed" % ( time.time() - now ) ) 79 | 80 | def read_one(self,file,abspath): 81 | doc = ExcelDoc( file,abspath ) 82 | doc.decode( self.srv_path, 83 | self.clt_path,self.srv_writer,self.clt_writer ) 84 | 85 | if __name__ == '__main__': 86 | 87 | parser = OptionParser() 88 | 89 | parser.add_option( "-i", "--input", dest="input_path", 90 | default="xls/", 91 | help="read all files from this path" ) 92 | parser.add_option( "-s", "--srv", dest="srv_path", 93 | help="write all server file to this path" ) 94 | parser.add_option( "-c", "--clt", dest="clt_path", 95 | help="write all client file to this path" ) 96 | parser.add_option( "-t", "--timeout", dest="timeout",type="int", 97 | default="-1", 98 | help="only converte files modified within seconds" ) 99 | parser.add_option( "-f", "--suffix", dest="suffix", 100 | default="", 101 | help="what type of file will be readed.empty mean all files" ) 102 | parser.add_option( "-w","--swriter", dest="srv_writer", 103 | help="which server writer you wish to use:lua xml json" ) 104 | parser.add_option( "-l","--cwriter", dest="clt_writer", 105 | help="which client writer you wish to use:lua xml json" ) 106 | 107 | options, args = parser.parse_args() 108 | 109 | reader = Reader( options.input_path,options.srv_path,options.clt_path, 110 | options.timeout,options.suffix,options.srv_writer,options.clt_writer ) 111 | reader.attention() 112 | reader.read() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 AICells 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # py_exceltools 2 | python3 基于openpyxl的excel转换工具。支持xlsx文件转换为erlang,elixir,lua,json,xml,python等配置文件。 3 | 4 | 关于openpyxl库:https://pypi.python.org/pypi/openpyxl。 5 | 6 | ## python和openpyxl安装 7 | linux安装 8 | apt-get install python-pip 9 | pip install openpyxl 10 | 11 | win安装 12 | 13 | 安装python(同时安装pip并添加到Path) 14 | 安装openpyxl, 在安装python后在cmd中运行: pip install openpyxl 15 | 16 | # 使用 17 | lancher.bat(win)和lancher.sh(linux)为对应运行脚本。 18 | 当前配置了用于参考的参数来转换example.xlsx, 19 | 可在对应server、client输出文件夹查看生成配置效果。 20 | 21 | 参数: 22 | --input :需要转换的excel文件所在目录 23 | --srv : 服务端配置文件输出目录 24 | --clt : 客户端配置文件输出目录 25 | --timeout : 需要转换的excel文件最后更新时间距当前时间秒数。-1转换所有 26 | --suffix :excel文件后缀,通常为.xlsx 27 | --swriter : 服务端配置文件转换器,可以指定为: erlanghrl,erlangerl,elixir,lua,jsonarray,jsonobject,xml,python 28 | --cwriter : 客户端配置文件转换器,可以指定为: erlanghrl,erlangerl,elixir,lua,jsonarray,jsonobject,xml,python 29 | 30 | 注:对于client和server,如果未配置输出目录或转换器,则不会导出。 31 | 32 | # 数据类型 33 | 支持int(int64), number(float), string, tuple, list, dict, json、lua 34 | 其中tuple, list, dict 为 python原生数据结构 json 为json数据类型 Lua为 lua table 35 | # 数据格式示范(可以参考本工具自带的示例配置表) 36 | int 整数 1,2,1000 64位 37 | number 整数或者小数都OK 38 | string 字符串 excel表中配置时不需要额外加双引号 39 | tuple (元素, 元素, ...) 元素可以为 int number string tuple list dict 40 | list [元素, 元素, ...] 元素可以为 int number string tuple list dict 41 | dict [key:value, key:value, ...] key可以为 int number string tuple value可以为 int number string tuple list dict 42 | 特别注意该类型的使用 因为在一些语言中 对应dict类似的类型的key不支持 int 比如 jsonarray和xml,如果在转成jsonarray和xml时key不能配置为int和number 43 | json {key:value, key:value, ...}该类型为json的对象类型 Key为字符串, Value可以为任意Json数据类型即可以是对象,数字,基本数据类型。 44 | lua 该类型为lua的table类型 45 | 其中 list dict json 三种数据格式可以互相嵌套 46 | 转换时会将这些数据类型转换为其他语言支持的数据类型,另外注意点是一些其他语言的一些限制 47 | 比如 json不能用数字做为对象的Key(), xml的也不能用数字作为标签, 在配置的时候需要注意 48 | 而且导出xml和jsonjsonarray都是用的库,出错的时候不太好找到对应配置错误的数据,需要配置前 49 | 就额外注意,以免不必要的懵逼和浪费时间,策划不太明白的可以请教程序或者百度 50 | 51 | # 打包exe 52 | 部署时,可以将python打包成exe。建议使用pyinstaller。 53 | pyinstaller3.2.1尚不支持python3.6.1,建议使用python 3.5。 54 | 55 | pip install pyinstaller 56 | pyinstaller -F -c ConfigConvertTool.py 57 | 58 | excel文件名命名格式 59 | 为了表名的可视化和可理解性,文件命名支持 MMM-NNN.xlsx的方式。MMM可以是任意字符(一般为文件中文名,但是不用下划线结尾), 60 | 作为文件名的注释性描述。NNN只能是数字,字母和下划线(不能以下划线开头和数字开头),作为导出的配置以NNN做为表名前缀 61 | excel sheet命名格式 62 | 为了考虑策划会使用一个excel配置同一的功能的多个配置子表,且方便导出和查看,sheet命名为YYY-XXX或者 YYY+XXX, 63 | 或者YYY (里面不包含 "+"""-"), YYY可以为任意字符(一般为中文描述),XXX为导出配置的表名后缀, 64 | 当sheet命名为 YYY-XXX或者 YYY+XXX时 导出文件名为: NNN_XXX.lang(此种命名一般用于 一个excel配置多个需要导出的sheet页签) 65 | 当sheet命名为 YYY 时 导出文件名为: NNN.lang (此种命名用法仅仅用于一个excel只配置一个需要导出的sheet页签) 66 | lang为目标语言的后缀名 67 | 具体示例 68 | A_arrary表示例--cfg_array.xlsx 前缀Y可以用方便排序显示 更多具体参见配置excel示例 69 | * 在string中无法直接使用换行等特殊称号。请用\n等转义字符替代。 70 | * 由于xml并不存在数组等结构,不建议使用。 71 | * 工具会检测server和client标识。如果不存在,则不导出些表。方便策划做备注 72 | -------------------------------------------------------------------------------- /client/cfg_array_example1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1 7 | 700 8 | 9 | 10 | 2 11 | 800 12 | 13 | 14 | 3 15 | 900 16 | 17 | 18 | 从小城镇 19 | 1001 20 | 88 21 | 黑切+蓝盾 22 | pos1 23 | 1 24 | 25 | 26 | 27 | 28 | 1 29 | 700 30 | 31 | 32 | 2 33 | 800 34 | 35 | 36 | 3 37 | 900 38 | 39 | 40 | 有钱就可以买 41 | 1001 42 | 88 43 | 黑切+蓝盾 44 | pos1 45 | 2 46 | 47 | 48 | 49 | 50 | 1 51 | 700 52 | 53 | 54 | 2 55 | 800 56 | 57 | 58 | 3 59 | 900 60 | 61 | 62 | 有钱就可以买 63 | 1001 64 | 89 65 | 黑切+蓝盾 66 | pos1 67 | 89 68 | 69 | 70 | 71 | 72 | 1 73 | 700 74 | 75 | 76 | 2 77 | 800 78 | 79 | 80 | 3 81 | 900 82 | 83 | 84 | 有钱就可以买 85 | 1001 86 | 88 87 | 黑切+蓝盾 88 | pos2 89 | 88.9 90 | 91 | 92 | 93 | 94 | 1 95 | 700 96 | 97 | 98 | 2 99 | 800 100 | 101 | 102 | 3 103 | 900 104 | 105 | 106 | 有钱就可以买 107 | 1001 108 | 89 109 | 黑切+蓝盾 110 | pos2 111 | 89 112 | 113 | 114 | 115 | 116 | 1 117 | 700 118 | 119 | 120 | 2 121 | 800 122 | 123 | 124 | 3 125 | 901 126 | 127 | 128 | 有钱就可以买 129 | 1002 130 | 88 131 | 黑切+蓝盾 132 | pos1 133 | 88 134 | 135 | 136 | 137 | 138 | 1 139 | 700 140 | 141 | 142 | 2 143 | 800 144 | 145 | 146 | 3 147 | 900 148 | 149 | 150 | 有钱就可以买 151 | 1002 152 | 89 153 | 黑切+蓝盾 154 | pos1 155 | 89 156 | 157 | 158 | 159 | 160 | 1 161 | 700 162 | 163 | 164 | 2 165 | 800 166 | 167 | 168 | 3 169 | 901 170 | 171 | 172 | 有钱就可以买 173 | 1002 174 | 90 175 | 黑切+蓝盾 176 | pos1 177 | 90 178 | 179 | 180 | 181 | 182 | 1 183 | 700 184 | 185 | 186 | 2 187 | 800 188 | 189 | 190 | 3 191 | 901 192 | 193 | 194 | 有钱就可以买 195 | 1002 196 | 88 197 | 黑切+蓝盾 198 | pos2 199 | 88 200 | 201 | 202 | 203 | 204 | 1 205 | 700 206 | 207 | 208 | 2 209 | 800 210 | 211 | 212 | 3 213 | 900 214 | 215 | 216 | 有钱就可以买 217 | 1002 218 | 89 219 | 黑切+蓝盾 220 | pos2 221 | 89 222 | 223 | 224 | 225 | 226 | 1 227 | 700 228 | 229 | 230 | 2 231 | 800 232 | 233 | 234 | 3 235 | 901 236 | 237 | 238 | 有钱就可以买 239 | 1002 240 | 90 241 | 黑切+蓝盾 242 | pos2 243 | 90 244 | 245 | 246 | 247 | 248 | 1 249 | 700 250 | 251 | 252 | 2 253 | 800 254 | 255 | 256 | 3 257 | 902 258 | 259 | 260 | 有钱就可以买 261 | 1003 262 | 85 263 | 黑切+蓝盾 264 | pos1 265 | 85 266 | 267 | 268 | 269 | 270 | 1 271 | 700 272 | 273 | 274 | 2 275 | 800 276 | 277 | 278 | 3 279 | 903 280 | 281 | 282 | 有钱就可以买 283 | 1004 284 | 80 285 | 黑切+蓝盾 286 | pos1 287 | 80 288 | 289 | 290 | -------------------------------------------------------------------------------- /client/cfg_array_example2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1 7 | 700 8 | 9 | 10 | 2 11 | 800 12 | 13 | 14 | 3 15 | 900 16 | 17 | 18 | 19 | 4 20 | 100 21 | 22 | 23 | 24 | 25 | 1 26 | 2 27 | 3 28 | 29 | 30 | 1 31 | 3 32 | 2 33 | 34 | 35 | 来源1 36 | 来源2 37 | 来源4 38 | 39 | 1 40 | 41 | 42 | 1 43 | 10001 44 | 1 45 | 46 | 47 | 1 48 | 10001 49 | 1 50 | 51 | 52 | examp1001 53 | 54 | 55 | 56 | 57 | 1 58 | 700 59 | 60 | 61 | 2 62 | 800 63 | 64 | 65 | 3 66 | 901 67 | 68 | 69 | 70 | 5 71 | 100 72 | 73 | 74 | 75 | 76 | 1 77 | 2 78 | 3 79 | 80 | 81 | 1 82 | 3 83 | 2 84 | 85 | 86 | 来源1 87 | 来源2 88 | 来源4 89 | 90 | 2 91 | 92 | 1 93 | 10001 94 | 1 95 | 96 | examp1002 97 | 98 | 99 | 100 | 101 | 1 102 | 700 103 | 104 | 105 | 2 106 | 800 107 | 108 | 109 | 3 110 | 902 111 | 112 | 113 | 114 | 6 115 | 100 116 | 117 | 118 | 119 | 120 | 1 121 | 2 122 | 3 123 | 124 | 125 | 1 126 | 3 127 | 2 128 | 129 | 130 | 来源1 131 | 来源2 132 | 来源5 133 | 134 | 3 135 | 136 | 1 137 | 2 138 | 3 139 | 4 140 | 5 141 | 6 142 | 7 143 | 8 144 | 9 145 | 9 146 | 9 147 | 9 148 | 9 149 | 9 150 | 9 151 | 9 152 | 9 153 | 9 154 | 155 | examp1003 156 | 157 | 158 | 159 | 160 | 1 161 | 700 162 | 163 | 164 | 2 165 | 800 166 | 167 | 168 | 3 169 | 903 170 | 171 | 172 | 173 | 7 174 | 100 175 | 176 | 177 | 178 | 179 | 1 180 | 2 181 | 3 182 | 183 | 184 | 1 185 | 3 186 | 2 187 | 188 | 189 | 来源1 190 | 来源2 191 | 来源6 192 | 193 | 4 194 | 195 | 测试数据 196 | 测试数据2 197 | 测试数据3 198 | 199 | examp1004 200 | 201 | 202 | 203 | 204 | 1 205 | 700 206 | 207 | 208 | 2 209 | 800 210 | 211 | 212 | 3 213 | 903 214 | 215 | 216 | 217 | 7 218 | 100 219 | 220 | 221 | 222 | 223 | 1 224 | 2 225 | 3 226 | 227 | 228 | 1 229 | 3 230 | 2 231 | 232 | 233 | 来源1 234 | 来源2 235 | 来源6 236 | 237 | 5 238 | 239 | test 240 | 241 | examp1004 242 | 243 | 244 | -------------------------------------------------------------------------------- /client/cfg_array_example3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 啦啦啦!!! 4 | 5 | -------------------------------------------------------------------------------- /client/cfg_object.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1001 4 | 100.1 5 | 100 6 | 7 | 8 | 1001 9 | 20 10 | 11 | 12 | 1002 13 | 20 14 | 15 | 16 | 1003 17 | 30 18 | 19 | 20 | 21 | 22 | 1001 23 | 10 24 | 25 | 26 | 1002 27 | 20 28 | 29 | 30 | 31 | 32 | 7003 33 | 1 34 | 35 | 36 | 3006 37 | 99 38 | 39 | 40 | 1001 41 | 20 42 | 43 | 这就是一个测试 44 | 45 | 46 | 47 | 1001 48 | 20 49 | 50 | 51 | 3006 52 | 99 53 | 54 | 55 | 7003 56 | 1 57 | 58 | 59 | 60 | 12356 61 | 654321 62 | 63 | 64 | 65 | 66 | 1 67 | 2 68 | 3 69 | 4 70 | 5 71 | 6 72 | 7 73 | 8 74 | 9 75 | 9 76 | 9 77 | 9 78 | 9 79 | 9 80 | 9 81 | 9 82 | 9 83 | 9 84 | 85 | 前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了) 86 | 18:00:0 87 | 90 88 | 89 | -------------------------------------------------------------------------------- /client/cfg_object1_cfg_object.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1001 4 | 100.1 5 | 100 6 | 7 | 8 | 1001 9 | 20 10 | 11 | 12 | 1002 13 | 20 14 | 15 | 16 | 1003 17 | 30 18 | 19 | 20 | 21 | 22 | 1001 23 | 10 24 | 25 | 26 | 1002 27 | 20 28 | 29 | 30 | 31 | 32 | 7003 33 | 1 34 | 35 | 36 | 3006 37 | 99 38 | 39 | 40 | 1001 41 | 20 42 | 43 | 这就是一个测试 44 | 45 | 46 | 47 | 1001 48 | 20 49 | 50 | 51 | 3006 52 | 99 53 | 54 | 55 | 7003 56 | 1 57 | 58 | 59 | 60 | 12356 61 | 654321 62 | 63 | 64 | 65 | 66 | 1 67 | 2 68 | 3 69 | 4 70 | 5 71 | 6 72 | 7 73 | 8 74 | 9 75 | 9 76 | 9 77 | 9 78 | 9 79 | 9 80 | 9 81 | 9 82 | 9 83 | 9 84 | 85 | 前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了) 86 | fgfdg 87 | 90 88 | 89 | -------------------------------------------------------------------------------- /color_print.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlyshare/ConfigConvertTool/3ac2b7fdd8b09cd98e75fac03f589e0cd5881741/color_print.py -------------------------------------------------------------------------------- /config_excel/A_array表示例--cfg_array.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlyshare/ConfigConvertTool/3ac2b7fdd8b09cd98e75fac03f589e0cd5881741/config_excel/A_array表示例--cfg_array.xlsx -------------------------------------------------------------------------------- /config_excel/A_object表示例--cfg_object.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlyshare/ConfigConvertTool/3ac2b7fdd8b09cd98e75fac03f589e0cd5881741/config_excel/A_object表示例--cfg_object.xlsx -------------------------------------------------------------------------------- /decoder.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import re 6 | import sys 7 | import json 8 | import openpyxl 9 | import color_print 10 | 11 | from slpp.slpp import slpp as lua 12 | 13 | # array数组模式下,各个栏的分布 14 | # 1、2行是文档注释,不导出 15 | ACMT_ROW = 3 # comment row 注释 16 | ATPE_ROW = 4 # type row 类型 17 | ASRV_ROW = 5 # server row 服务器 18 | ACLT_ROW = 6 # client row 客户端 19 | AKEY_COL = 1 # key column key所在列 20 | 21 | # object(kv)模式下,各个栏的分布 22 | OCMT_COL = 1 # comment column 注释 23 | OTPE_COL = 2 # type column 类型 24 | OSRV_COL = 3 # server column 服务器 25 | OCLT_COL = 4 # client column 客户端 26 | OCTX_COL = 5 # content column 内容所在列 27 | 28 | # 1、2行是文档注释,不导出 29 | OFLG_ROW = 3 # flag row server client所在行 30 | 31 | SRV_FLAG = "server" 32 | CLT_FLAG = "client" 33 | 34 | SHEET_FLAG_ROW = 3 # 3列1行表示是array 还是object 或者是不用导出的表 35 | SHEET_FLAG_COL = 1 # 3列1行表示是array 还是object 或者是不用导出的表 36 | 37 | # 用于标识表的类型 不是这两种就不会导出数据 38 | ARRAY_FLAG = "array" # 标识表的是array类型的表 39 | OBJECT_FLAG = "object" # 标识表的是object类型的表 40 | 41 | KEY_FLAG = "$key_" # array表的 作为Key字段的前缀标识 42 | KEY_FLAG_LEN = 5 # array表的 作为Key字段的前缀标识长度 用于分割字符串 43 | 44 | # 支持的数据类型 45 | # "int":1,"number":2,"int64":3,"string":4, "tuple":5, "list":6, "dict":7 为python原生数据格式 46 | # "json":8,"lua":9 为json和lua的数据格式 47 | # excel配置的时候 对应类型字段 填入对应数据类型的有效数据格式的数据就OK 48 | TYPES = { "int":1,"number":2,"int64":3,"string":4, "tuple":5, "list":6, "dict":7, "json":8,"lua":9} 49 | 50 | try: 51 | basestring 52 | except NameError: 53 | basestring = str 54 | 55 | # python3中没有uincode了,int能表示int64 56 | try: 57 | long 58 | except NameError: 59 | long = int 60 | 61 | # python3中没有unicode了 62 | try: 63 | unicode 64 | except NameError: 65 | unicode = str 66 | 67 | # 类型转换器 68 | class ValueConverter(object): 69 | def __init__(self): 70 | pass 71 | 72 | # 在python中,字符串和unicode是不一样的。默认从excel读取的数据都是unicode。 73 | # str可以通过decode转换为unicode 74 | # ascii' codec can't encode characters 75 | # 这个函数在python3中没用 76 | def to_unicode_str( self,val ): 77 | if isinstance( val,str ) : 78 | return val 79 | elif isinstance( val,unicode ) : 80 | return val 81 | else : 82 | return str( val ).decode("utf8") 83 | 84 | def to_value(self,val_type,val): 85 | if "int" == val_type : 86 | return int( val ) 87 | elif "int64" == val_type : 88 | return long( val ) 89 | elif "number" == val_type : 90 | # 去除带小数时的小数点,100.0 ==>> 100 91 | # number就让它带小数点吧,不然强类型的配置无法正确识别出来 92 | # if long( val ) == float( val ) : return long( val ) 93 | return float( val ) 94 | elif "string" == val_type : 95 | return self.to_unicode_str( val ) 96 | elif "json" == val_type : 97 | return json.loads( val ) 98 | elif "lua" == val_type : 99 | return lua.decode( val ) 100 | elif "tuple" == val_type : 101 | return tuple(eval(val)) 102 | elif "list" == val_type : 103 | return list(eval(val)) 104 | elif "dict" == val_type : 105 | return dict(eval(val)) 106 | else : 107 | self.raise_error( "invalid type",value ) 108 | 109 | class Sheet(object): 110 | 111 | def __init__(self,base_name,wb_sheet,srv_writer,clt_writer): 112 | 113 | self.types = [] # 记录各列字段的类型 114 | 115 | self.srv_writer = srv_writer 116 | self.clt_writer = clt_writer 117 | 118 | self.srv_fields = [] #服务端各列字段名 119 | self.clt_fields = [] #客户端各列字段名 120 | self.srv_comment = {} # 服务器字段注释 121 | self.clt_comment = {} # 客户端字段注释 122 | 123 | self.srv_keys = {} # 服务器key 124 | self.clt_keys = {} # 客户端key 125 | 126 | 127 | self.converter = ValueConverter() 128 | 129 | self.wb_sheet = wb_sheet 130 | self.base_name = base_name 131 | 132 | match_list = re.findall("[a-zA-Z0-9_]+$",base_name) 133 | if None == match_list or 1 != len(match_list): 134 | Exception( base_name,"not a legal file name" ) 135 | 136 | self.base_file_name = match_list[0] 137 | 138 | # 记录出错时的行列,方便策划定位问题 139 | self.error_row = 0 140 | self.error_col = 0 141 | 142 | # 记录出错位置 143 | def mark_error_pos(self,row,col): 144 | if row > 0 : self.error_row = row 145 | if col > 0 : self.error_col = col 146 | 147 | # 发起一个解析错误 148 | def raise_error(self,what,val): 149 | excel_info = format("DOC:%s,SHEET:%s,ROW:%d,COLUMN:%d" % \ 150 | (self.base_name,self.wb_sheet.title,self.error_row,self.error_col)) 151 | raise Exception( what,val,excel_info ) 152 | 153 | def to_value(self,val_type,val): 154 | try: 155 | return self.converter.to_value(val_type,val) 156 | except Exception : 157 | t, e = sys.exc_info()[:2] 158 | self.raise_error( "ConverError",e ) 159 | 160 | # 解析一个表格 161 | def decode_sheet(self): 162 | wb_sheet = self.wb_sheet 163 | 164 | self.decode_type () 165 | self.decode_field() 166 | self.decode_ctx () 167 | 168 | color_print.printGreen( " covert successfully... sheet name -> %s \n" % wb_sheet.title ) 169 | return True 170 | 171 | # 写入配置到文件 172 | def write_one_file(self,ctx,base_path,writer, keys_list, comment_text): 173 | # 有些配置可能只导出客户端或只导出服务器 174 | if not any(ctx) : 175 | return 176 | 177 | write_file_name = self.base_file_name 178 | if self.wb_sheet.title.find("+") >= 0 or self.wb_sheet.title.find("-") >= 0 : 179 | match_list = re.findall("[a-zA-Z0-9_]+$", self.wb_sheet.title) 180 | if 1 == len(match_list): 181 | write_file_name = write_file_name + '_' + match_list[0] 182 | 183 | wt = writer(self.base_name,self.wb_sheet.title, write_file_name, keys_list, comment_text) 184 | ctx = wt.context( ctx ) 185 | suffix = wt.suffix() 186 | if None != ctx : 187 | path = base_path + write_file_name + suffix 188 | 189 | #必须为wb,不然无法写入utf-8 190 | file = open( path, 'wb' ) 191 | file.write( ctx.encode( "utf-8" ) ) 192 | file.close() 193 | 194 | # 分别写入到服务端、客户端的配置文件 195 | def write_files(self,srv_path,clt_path): 196 | if None != srv_path and None != self.srv_writer : 197 | self.write_one_file( self.srv_ctx,srv_path,self.srv_writer, self.srv_keys, self.srv_comment) 198 | if None != clt_path and None != self.clt_writer : 199 | self.write_one_file( self.clt_ctx,clt_path,self.clt_writer, self.clt_keys, self.clt_comment ) 200 | 201 | # 导出数组类型配置,A1格子的内容有array标识 202 | class ArraySheet(Sheet): 203 | 204 | def __init__(self,base_name,wb_sheet,srv_writer,clt_writer): 205 | # 记录导出各行的内容 206 | self.srv_ctx = [] 207 | self.clt_ctx = [] 208 | 209 | super( ArraySheet, self ).__init__( 210 | base_name,wb_sheet,srv_writer,clt_writer ) 211 | 212 | # 解析各列的类型(string、number...) 213 | def decode_type(self): 214 | # 第一列没数据,类型可以不填,默认为None,但是这里要占个位 215 | self.types.append( None ) 216 | 217 | for col_idx in range( AKEY_COL + 1,self.wb_sheet.max_column + 1 ): 218 | self.mark_error_pos(ATPE_ROW,col_idx) 219 | value = self.wb_sheet.cell( row = ATPE_ROW, column = col_idx ).value 220 | 221 | # 单元格为空的时候,wb_sheet.cell(row=1, column=2).value == None 222 | # 类型那一行必须连续,空白表示后面的数据都不导出了 223 | if value == None : 224 | break 225 | if value not in TYPES : 226 | self.raise_error( "invalid type",value ) 227 | 228 | self.types.append( value ) 229 | 230 | # 解析客户端、服务器的字段名(server、client)那两行 231 | def decode_one_field(self,fields,row_index, keys): 232 | key_index = 1 233 | for col_index in range( AKEY_COL,len( self.types ) + 1 ): 234 | value = self.wb_sheet.cell( 235 | row = row_index, column = col_index ).value 236 | # 对于array类型的表 一条数据可以有多个值作为KEY 需要处理一下 237 | if None != value and value.find(KEY_FLAG) >= 0 : 238 | value = value[KEY_FLAG_LEN:] 239 | keys[value] = key_index 240 | key_index = key_index + 1 241 | 242 | # 对于不需要导出的field,可以为空。即value为None 243 | fields.append( value ) 244 | 245 | # 解析注释那一行 246 | def decode_one_comment(self,fields,row_index, key_index): 247 | for col_index in range( AKEY_COL + 1,len( self.types ) + 1 ): 248 | value = self.wb_sheet.cell( 249 | row = row_index, column = col_index ).value 250 | 251 | key = self.wb_sheet.cell( 252 | row = key_index, column = col_index ).value 253 | 254 | if None == key : 255 | continue 256 | 257 | # 对于不需要导出的field,可以为空。即value为None 258 | if key.find(KEY_FLAG) >= 0 : 259 | key = key[KEY_FLAG_LEN:] 260 | fields[key] = value 261 | else : 262 | fields[key] = value 263 | 264 | # 导出客户端、服务端字段名(server、client)那一列 265 | def decode_field(self): 266 | self.decode_one_field( self.srv_fields,ASRV_ROW, self.srv_keys ) 267 | self.decode_one_field( self.clt_fields,ACLT_ROW, self.clt_keys ) 268 | # 导出服务器和客户端对用字段的注释, 导表的时候可能用到 269 | self.decode_one_comment( self.srv_comment, ACMT_ROW, ASRV_ROW) 270 | self.decode_one_comment( self.clt_comment, ACMT_ROW, ACLT_ROW) 271 | 272 | # 解析出一个格子的内容 273 | def decode_cell(self,row_idx,col_idx): 274 | value = self.wb_sheet.cell( row = row_idx, column = col_idx ).value 275 | if None == value: 276 | return None 277 | 278 | # 类型是从0下标开始,但是excel的第一列从1开始 279 | self.mark_error_pos( row_idx,col_idx ) 280 | return self.to_value( self.types[col_idx - 1],value ) 281 | 282 | # 解析出一行的内容 283 | def decode_row(self,row_idx): 284 | srv_row = {} 285 | clt_row = {} 286 | 287 | # 第一列没数据,从第二列开始解析 288 | for col_idx in range( AKEY_COL + 1,len( self.types ) + 1 ): 289 | value = self.decode_cell( row_idx,col_idx ) 290 | if None == value : continue 291 | 292 | srv_key = self.srv_fields[col_idx - 1] 293 | clt_key = self.clt_fields[col_idx - 1] 294 | 295 | 296 | if srv_key : 297 | srv_row[srv_key] = value 298 | if clt_key : 299 | clt_row[clt_key] = value 300 | return srv_row,clt_row # 返回一个tuple 301 | 302 | # 解析导出的内容 303 | def decode_ctx(self): 304 | for row_idx in range( ACLT_ROW + 1,self.wb_sheet.max_row + 1 ): 305 | srv_row,clt_row = self.decode_row( row_idx ) 306 | 307 | if row_idx > 57 : 308 | break 309 | 310 | # 不为空才追加 311 | if any( srv_row ) : 312 | self.srv_ctx.append( srv_row ) 313 | if any( clt_row ) : 314 | self.clt_ctx.append( clt_row ) 315 | 316 | # 导出object类型的结构,A1格子有object标识 317 | class ObjectSheet(Sheet): 318 | 319 | def __init__(self,base_name,wb_sheet,srv_writer,clt_writer): 320 | # 记录导出各行的内容 321 | self.srv_ctx = {} 322 | self.clt_ctx = {} 323 | 324 | super( ObjectSheet, self ).__init__( 325 | base_name,wb_sheet,srv_writer,clt_writer ) 326 | 327 | # 解析各字段的类型 328 | def decode_type(self): 329 | for row_idx in range( OFLG_ROW + 1,self.wb_sheet.max_row + 1 ): 330 | self.mark_error_pos( row_idx,OTPE_COL) 331 | value = self.wb_sheet.cell( row = row_idx, column = OTPE_COL ).value 332 | 333 | # 类型必须连续,遇到空则认为后续数据不再导出 334 | if value == None : 335 | break 336 | if value not in TYPES : 337 | self.raise_error( "invalid type",value ) 338 | 339 | self.types.append( value ) 340 | 341 | # 导出客户端、服务端字段名(server、client)那一列 342 | def decode_one_field(self,fields,col_idx): 343 | for row_idx in range( OFLG_ROW + 1,len( self.types ) + OFLG_ROW + 1 ): 344 | value = self.wb_sheet.cell( row = row_idx, column = col_idx ).value 345 | 346 | # 对于不需要导出的field,可以为空。即value为None 347 | fields.append( value ) 348 | 349 | # 解析注释那一行 350 | def decode_one_comment(self,fields,col_idx, key_index): 351 | for row_idx in range( OFLG_ROW + 1,len( self.types ) + OFLG_ROW + 1 ): 352 | value = self.wb_sheet.cell( row = row_idx, column = col_idx ).value 353 | 354 | key = self.wb_sheet.cell( row = row_idx, column = key_index ).value 355 | 356 | if None == value: 357 | continue 358 | # 导出存在值的fields的注释 359 | fields[key] = value 360 | 361 | # 导出客户端、服务端字段名(server、client)那一列 362 | def decode_field(self): 363 | self.decode_one_field( self.srv_fields,OSRV_COL ) 364 | self.decode_one_field( self.clt_fields,OCLT_COL ) 365 | # 导出服务器和客户端对用字段的注释, 导表的时候可能用到 366 | self.decode_one_comment( self.srv_comment, OCMT_COL, OSRV_COL) 367 | self.decode_one_comment( self.clt_comment, OCMT_COL, OCLT_COL ) 368 | 369 | # 解析一个单元格内容 370 | def decode_cell(self,row_idx): 371 | value = self.wb_sheet.cell( row = row_idx, column = OCTX_COL ).value 372 | if None == value : return None 373 | 374 | # 在object的结构中,数据是从第二行开始的,所以types的下标偏移2 375 | self.mark_error_pos( row_idx,OCTX_COL ) 376 | return self.to_value( self.types[row_idx - OFLG_ROW - 1],value ) 377 | 378 | # 解析表格的所有内容 379 | def decode_ctx(self): 380 | for row_idx in range( OFLG_ROW + 1,len( self.types ) + OFLG_ROW + 1 ): 381 | value = self.decode_cell( row_idx ) 382 | 383 | if row_idx > 54 : 384 | break 385 | 386 | if None == value : 387 | continue 388 | 389 | srv_key = self.srv_fields[row_idx - OFLG_ROW - 1] 390 | clt_key = self.clt_fields[row_idx - OFLG_ROW - 1] 391 | 392 | if srv_key : self.srv_ctx[srv_key] = value 393 | if clt_key : self.clt_ctx[clt_key] = value 394 | 395 | class ExcelDoc: 396 | 397 | def __init__(self, file,abspath): 398 | self.file = file 399 | self.abspath = abspath 400 | 401 | # 是否需要解析 402 | # 返回解析的对象类型 403 | def need_decode(self,wb_sheet): 404 | sheet_val = wb_sheet.cell( 405 | row = SHEET_FLAG_ROW, column = SHEET_FLAG_COL ).value 406 | 407 | sheeter = None 408 | srv_value = None 409 | clt_value = None 410 | if ARRAY_FLAG == sheet_val : 411 | if wb_sheet.max_row <= ACLT_ROW or wb_sheet.max_column <= AKEY_COL: 412 | return None 413 | 414 | sheeter = ArraySheet 415 | srv_value = wb_sheet.cell( row = ASRV_ROW, column = AKEY_COL ).value 416 | clt_value = wb_sheet.cell( row = ACLT_ROW, column = AKEY_COL ).value 417 | elif OBJECT_FLAG == sheet_val : 418 | sheeter = ObjectSheet 419 | srv_value = wb_sheet.cell( row = OFLG_ROW, column = OSRV_COL ).value 420 | clt_value = wb_sheet.cell( row = OFLG_ROW, column = OCLT_COL ).value 421 | else : 422 | return None 423 | 424 | # 没有这两个标识就不是配置表。可能是策划的一些备注说明 425 | if SRV_FLAG != srv_value or CLT_FLAG != clt_value : 426 | return None 427 | return sheeter 428 | 429 | def decode(self,srv_path,clt_path,srv_writer,clt_writer): 430 | color_print.printYellow( " start covert: %s \n" % self.file.ljust(44, "*") ) 431 | base_name = os.path.splitext( self.file )[0] 432 | wb = openpyxl.load_workbook( self.abspath ) 433 | 434 | for wb_sheet in wb.worksheets: 435 | Sheeter = self.need_decode( wb_sheet ) 436 | if None == Sheeter : 437 | color_print.printPink( " covert skip........... sheet name -> %s\n" % wb_sheet.title ) 438 | continue 439 | 440 | sheet = Sheeter( base_name,wb_sheet,srv_writer,clt_writer ) 441 | if sheet.decode_sheet() : 442 | sheet.write_files( srv_path,clt_path ) -------------------------------------------------------------------------------- /lancher.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter lua --cwriter lua 4 | :python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter erlanghrl 5 | :python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter erlangerl 6 | :python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter elixir 7 | :python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter jsonobject 8 | :python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --cwriter jsonarray 9 | python ConfigConvertTool.py --input ./config_excel --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter elixir --cwriter xml 10 | 11 | 12 | pause 13 | -------------------------------------------------------------------------------- /lancher.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python reader.py --input ./ --srv server/ --clt client/ --timeout -1 --suffix .xlsx --swriter lua --cwriter json 4 | python reader.py --input ./ --srv server/ --clt client/ --timeout -1 --suffix .xlsx --cwriter xml 5 | python reader.py --input ./ --srv server/ --clt client/ --timeout -1 --suffix .xlsx --cwriter lua 6 | 7 | -------------------------------------------------------------------------------- /server/cfg_array.erl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_object表示例--cfg_array 3 | %% excel sheet name : +example3 4 | 5 | -module(cfg_array). 6 | 7 | -compile(export_all). 8 | 9 | %% 演示 10 | get('level') -> 11 | "啦啦啦!!!"; 12 | 13 | get(_) -> 14 | undefined. -------------------------------------------------------------------------------- /server/cfg_array.ex: -------------------------------------------------------------------------------- 1 | ## Automatic generation from -->> 2 | ## excel file name: A_object表示例--cfg_array 3 | ## excel sheet name: +example3 4 | 5 | defmodule Cfg_Array do 6 | 7 | ## 演示 8 | def get(:level) do 9 | "啦啦啦!!!" 10 | end 11 | 12 | def get(_) do 13 | :undefined 14 | end 15 | 16 | end -------------------------------------------------------------------------------- /server/cfg_array.json: -------------------------------------------------------------------------------- 1 | { 2 | "level":"啦啦啦!!!" 3 | } -------------------------------------------------------------------------------- /server/cfg_array.lua: -------------------------------------------------------------------------------- 1 | -- Automatic generation from -->> 2 | -- excel file name: A_object表示例--cfg_array 3 | -- excel sheet name: +example3 4 | 5 | local cfg_array = 6 | { 7 | -- 演示 8 | level = '啦啦啦!!!' 9 | } 10 | return cfg_array -------------------------------------------------------------------------------- /server/cfg_array_example1.erl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_array表示例--cfg_array 3 | %% excel sheet name : 示例1-example1 4 | 5 | -module(cfg_array_example1). 6 | 7 | -include("cfg_array_example1.hrl"). 8 | -compile(export_all). 9 | 10 | get(1001, "pos1", 88, 1) -> 11 | #cfg_array_example1{ 12 | 'id' = 1001 13 | ,'str' = "pos1" 14 | ,'level' = 88 15 | ,'sub_level' = 1 16 | ,'name' = "黑切+蓝盾" 17 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 18 | ,'desc1' = "从小城镇" 19 | }; 20 | 21 | get(1001, "pos1", 88, 2) -> 22 | #cfg_array_example1{ 23 | 'id' = 1001 24 | ,'str' = "pos1" 25 | ,'level' = 88 26 | ,'sub_level' = 2 27 | ,'name' = "黑切+蓝盾" 28 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 29 | ,'desc1' = "有钱就可以买" 30 | }; 31 | 32 | get(1001, "pos1", 89, 89) -> 33 | #cfg_array_example1{ 34 | 'id' = 1001 35 | ,'str' = "pos1" 36 | ,'level' = 89 37 | ,'sub_level' = 89 38 | ,'name' = "黑切+蓝盾" 39 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 40 | ,'desc1' = "有钱就可以买" 41 | }; 42 | 43 | get(1001, "pos2", 88, 88.9) -> 44 | #cfg_array_example1{ 45 | 'id' = 1001 46 | ,'str' = "pos2" 47 | ,'level' = 88 48 | ,'sub_level' = 88.9 49 | ,'name' = "黑切+蓝盾" 50 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 51 | ,'desc1' = "有钱就可以买" 52 | }; 53 | 54 | get(1001, "pos2", 89, 89) -> 55 | #cfg_array_example1{ 56 | 'id' = 1001 57 | ,'str' = "pos2" 58 | ,'level' = 89 59 | ,'sub_level' = 89 60 | ,'name' = "黑切+蓝盾" 61 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 62 | ,'desc1' = "有钱就可以买" 63 | }; 64 | 65 | get(1002, "pos1", 88, 88) -> 66 | #cfg_array_example1{ 67 | 'id' = 1002 68 | ,'str' = "pos1" 69 | ,'level' = 88 70 | ,'sub_level' = 88 71 | ,'name' = "黑切+蓝盾" 72 | ,'attr' = [[1, 700], [2, 800], [3, 901]] 73 | ,'desc1' = "有钱就可以买" 74 | }; 75 | 76 | get(1002, "pos1", 89, 89) -> 77 | #cfg_array_example1{ 78 | 'id' = 1002 79 | ,'str' = "pos1" 80 | ,'level' = 89 81 | ,'sub_level' = 89 82 | ,'name' = "黑切+蓝盾" 83 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 84 | ,'desc1' = "有钱就可以买" 85 | }; 86 | 87 | get(1002, "pos1", 90, 90) -> 88 | #cfg_array_example1{ 89 | 'id' = 1002 90 | ,'str' = "pos1" 91 | ,'level' = 90 92 | ,'sub_level' = 90 93 | ,'name' = "黑切+蓝盾" 94 | ,'attr' = [[1, 700], [2, 800], [3, 901]] 95 | ,'desc1' = "有钱就可以买" 96 | }; 97 | 98 | get(1002, "pos2", 88, 88) -> 99 | #cfg_array_example1{ 100 | 'id' = 1002 101 | ,'str' = "pos2" 102 | ,'level' = 88 103 | ,'sub_level' = 88 104 | ,'name' = "黑切+蓝盾" 105 | ,'attr' = [[1, 700], [2, 800], [3, 901]] 106 | ,'desc1' = "有钱就可以买" 107 | }; 108 | 109 | get(1002, "pos2", 89, 89) -> 110 | #cfg_array_example1{ 111 | 'id' = 1002 112 | ,'str' = "pos2" 113 | ,'level' = 89 114 | ,'sub_level' = 89 115 | ,'name' = "黑切+蓝盾" 116 | ,'attr' = [[1, 700], [2, 800], [3, 900]] 117 | ,'desc1' = "有钱就可以买" 118 | }; 119 | 120 | get(1002, "pos2", 90, 90) -> 121 | #cfg_array_example1{ 122 | 'id' = 1002 123 | ,'str' = "pos2" 124 | ,'level' = 90 125 | ,'sub_level' = 90 126 | ,'name' = "黑切+蓝盾" 127 | ,'attr' = [[1, 700], [2, 800], [3, 901]] 128 | ,'desc1' = "有钱就可以买" 129 | }; 130 | 131 | get(1003, "pos1", 85, 85) -> 132 | #cfg_array_example1{ 133 | 'id' = 1003 134 | ,'str' = "pos1" 135 | ,'level' = 85 136 | ,'sub_level' = 85 137 | ,'name' = "黑切+蓝盾" 138 | ,'attr' = [[1, 700], [2, 800], [3, 902]] 139 | ,'desc1' = "有钱就可以买" 140 | }; 141 | 142 | get(1004, "pos1", 80, 80) -> 143 | #cfg_array_example1{ 144 | 'id' = 1004 145 | ,'str' = "pos1" 146 | ,'level' = 80 147 | ,'sub_level' = 80 148 | ,'name' = "黑切+蓝盾" 149 | ,'attr' = [[1, 700], [2, 800], [3, 903]] 150 | ,'desc1' = "有钱就可以买" 151 | }; 152 | 153 | get(_, _, _, _) -> 154 | undefined. 155 | 156 | get_all() -> 157 | [ 158 | {1001, "pos1", 88, 1} 159 | ,{1001, "pos1", 88, 2} 160 | ,{1001, "pos1", 89, 89} 161 | ,{1001, "pos2", 88, 88.9} 162 | ,{1001, "pos2", 89, 89} 163 | ,{1002, "pos1", 88, 88} 164 | ,{1002, "pos1", 89, 89} 165 | ,{1002, "pos1", 90, 90} 166 | ,{1002, "pos2", 88, 88} 167 | ,{1002, "pos2", 89, 89} 168 | ,{1002, "pos2", 90, 90} 169 | ,{1003, "pos1", 85, 85} 170 | ,{1004, "pos1", 80, 80} 171 | ]. 172 | 173 | get_list() -> 174 | get_all(). 175 | 176 | get_list(1001) -> 177 | [ 178 | {1001, "pos1", 88, 1} 179 | ,{1001, "pos1", 88, 2} 180 | ,{1001, "pos1", 89, 89} 181 | ,{1001, "pos2", 88, 88.9} 182 | ,{1001, "pos2", 89, 89} 183 | ]; 184 | 185 | get_list(1002) -> 186 | [ 187 | {1002, "pos1", 88, 88} 188 | ,{1002, "pos1", 89, 89} 189 | ,{1002, "pos1", 90, 90} 190 | ,{1002, "pos2", 88, 88} 191 | ,{1002, "pos2", 89, 89} 192 | ,{1002, "pos2", 90, 90} 193 | ]; 194 | 195 | get_list(1003) -> 196 | [ 197 | {1003, "pos1", 85, 85} 198 | ]; 199 | 200 | get_list(1004) -> 201 | [ 202 | {1004, "pos1", 80, 80} 203 | ]; 204 | 205 | get_list(_) -> 206 | []. 207 | 208 | get_list(1001, "pos1") -> 209 | [ 210 | {1001, "pos1", 88, 1} 211 | ,{1001, "pos1", 88, 2} 212 | ,{1001, "pos1", 89, 89} 213 | ]; 214 | 215 | get_list(1001, "pos2") -> 216 | [ 217 | {1001, "pos2", 88, 88.9} 218 | ,{1001, "pos2", 89, 89} 219 | ]; 220 | 221 | get_list(1002, "pos1") -> 222 | [ 223 | {1002, "pos1", 88, 88} 224 | ,{1002, "pos1", 89, 89} 225 | ,{1002, "pos1", 90, 90} 226 | ]; 227 | 228 | get_list(1002, "pos2") -> 229 | [ 230 | {1002, "pos2", 88, 88} 231 | ,{1002, "pos2", 89, 89} 232 | ,{1002, "pos2", 90, 90} 233 | ]; 234 | 235 | get_list(1003, "pos1") -> 236 | [ 237 | {1003, "pos1", 85, 85} 238 | ]; 239 | 240 | get_list(1004, "pos1") -> 241 | [ 242 | {1004, "pos1", 80, 80} 243 | ]; 244 | 245 | get_list(_, _) -> 246 | []. 247 | 248 | get_list(1001, "pos1", 88) -> 249 | [ 250 | {1001, "pos1", 88, 1} 251 | ,{1001, "pos1", 88, 2} 252 | ]; 253 | 254 | get_list(1001, "pos1", 89) -> 255 | [ 256 | {1001, "pos1", 89, 89} 257 | ]; 258 | 259 | get_list(1001, "pos2", 88) -> 260 | [ 261 | {1001, "pos2", 88, 88.9} 262 | ]; 263 | 264 | get_list(1001, "pos2", 89) -> 265 | [ 266 | {1001, "pos2", 89, 89} 267 | ]; 268 | 269 | get_list(1002, "pos1", 88) -> 270 | [ 271 | {1002, "pos1", 88, 88} 272 | ]; 273 | 274 | get_list(1002, "pos1", 89) -> 275 | [ 276 | {1002, "pos1", 89, 89} 277 | ]; 278 | 279 | get_list(1002, "pos1", 90) -> 280 | [ 281 | {1002, "pos1", 90, 90} 282 | ]; 283 | 284 | get_list(1002, "pos2", 88) -> 285 | [ 286 | {1002, "pos2", 88, 88} 287 | ]; 288 | 289 | get_list(1002, "pos2", 89) -> 290 | [ 291 | {1002, "pos2", 89, 89} 292 | ]; 293 | 294 | get_list(1002, "pos2", 90) -> 295 | [ 296 | {1002, "pos2", 90, 90} 297 | ]; 298 | 299 | get_list(1003, "pos1", 85) -> 300 | [ 301 | {1003, "pos1", 85, 85} 302 | ]; 303 | 304 | get_list(1004, "pos1", 80) -> 305 | [ 306 | {1004, "pos1", 80, 80} 307 | ]; 308 | 309 | get_list(_, _, _) -> 310 | []. 311 | 312 | -------------------------------------------------------------------------------- /server/cfg_array_example1.ex: -------------------------------------------------------------------------------- 1 | ## Automatic generation from -->> 2 | ## excel file name: A_array表示例--cfg_array 3 | ## excel sheet name: 示例1-example1 4 | 5 | defmodule Cfg_Array_Example1 do 6 | 7 | defstruct [ 8 | :id, ## 唯一id 9 | :str, ## 佩戴位置 10 | :level, ## 等级 11 | :sub_level, ## 等级 12 | :name, ## 装备名字 13 | :attr, ## 装备增加属性 14 | :desc1 ## 装备来源描述 15 | ] 16 | 17 | def get(1001, "pos1", 88, 1) do 18 | %Cfg_Array_Example1{ 19 | :id => 1001, 20 | :str => "pos1", 21 | :level => 88, 22 | :sub_level => 1, 23 | :name => "黑切+蓝盾", 24 | :attr => [[1, 700], [2, 800], [3, 900]], 25 | :desc1 => "从小城镇" 26 | } 27 | end 28 | 29 | def get(1001, "pos1", 88, 2) do 30 | %Cfg_Array_Example1{ 31 | :id => 1001, 32 | :str => "pos1", 33 | :level => 88, 34 | :sub_level => 2, 35 | :name => "黑切+蓝盾", 36 | :attr => [[1, 700], [2, 800], [3, 900]], 37 | :desc1 => "有钱就可以买" 38 | } 39 | end 40 | 41 | def get(1001, "pos1", 89, 89) do 42 | %Cfg_Array_Example1{ 43 | :id => 1001, 44 | :str => "pos1", 45 | :level => 89, 46 | :sub_level => 89, 47 | :name => "黑切+蓝盾", 48 | :attr => [[1, 700], [2, 800], [3, 900]], 49 | :desc1 => "有钱就可以买" 50 | } 51 | end 52 | 53 | def get(1001, "pos2", 88, 88.9) do 54 | %Cfg_Array_Example1{ 55 | :id => 1001, 56 | :str => "pos2", 57 | :level => 88, 58 | :sub_level => 88.9, 59 | :name => "黑切+蓝盾", 60 | :attr => [[1, 700], [2, 800], [3, 900]], 61 | :desc1 => "有钱就可以买" 62 | } 63 | end 64 | 65 | def get(1001, "pos2", 89, 89) do 66 | %Cfg_Array_Example1{ 67 | :id => 1001, 68 | :str => "pos2", 69 | :level => 89, 70 | :sub_level => 89, 71 | :name => "黑切+蓝盾", 72 | :attr => [[1, 700], [2, 800], [3, 900]], 73 | :desc1 => "有钱就可以买" 74 | } 75 | end 76 | 77 | def get(1002, "pos1", 88, 88) do 78 | %Cfg_Array_Example1{ 79 | :id => 1002, 80 | :str => "pos1", 81 | :level => 88, 82 | :sub_level => 88, 83 | :name => "黑切+蓝盾", 84 | :attr => [[1, 700], [2, 800], [3, 901]], 85 | :desc1 => "有钱就可以买" 86 | } 87 | end 88 | 89 | def get(1002, "pos1", 89, 89) do 90 | %Cfg_Array_Example1{ 91 | :id => 1002, 92 | :str => "pos1", 93 | :level => 89, 94 | :sub_level => 89, 95 | :name => "黑切+蓝盾", 96 | :attr => [[1, 700], [2, 800], [3, 900]], 97 | :desc1 => "有钱就可以买" 98 | } 99 | end 100 | 101 | def get(1002, "pos1", 90, 90) do 102 | %Cfg_Array_Example1{ 103 | :id => 1002, 104 | :str => "pos1", 105 | :level => 90, 106 | :sub_level => 90, 107 | :name => "黑切+蓝盾", 108 | :attr => [[1, 700], [2, 800], [3, 901]], 109 | :desc1 => "有钱就可以买" 110 | } 111 | end 112 | 113 | def get(1002, "pos2", 88, 88) do 114 | %Cfg_Array_Example1{ 115 | :id => 1002, 116 | :str => "pos2", 117 | :level => 88, 118 | :sub_level => 88, 119 | :name => "黑切+蓝盾", 120 | :attr => [[1, 700], [2, 800], [3, 901]], 121 | :desc1 => "有钱就可以买" 122 | } 123 | end 124 | 125 | def get(1002, "pos2", 89, 89) do 126 | %Cfg_Array_Example1{ 127 | :id => 1002, 128 | :str => "pos2", 129 | :level => 89, 130 | :sub_level => 89, 131 | :name => "黑切+蓝盾", 132 | :attr => [[1, 700], [2, 800], [3, 900]], 133 | :desc1 => "有钱就可以买" 134 | } 135 | end 136 | 137 | def get(1002, "pos2", 90, 90) do 138 | %Cfg_Array_Example1{ 139 | :id => 1002, 140 | :str => "pos2", 141 | :level => 90, 142 | :sub_level => 90, 143 | :name => "黑切+蓝盾", 144 | :attr => [[1, 700], [2, 800], [3, 901]], 145 | :desc1 => "有钱就可以买" 146 | } 147 | end 148 | 149 | def get(1003, "pos1", 85, 85) do 150 | %Cfg_Array_Example1{ 151 | :id => 1003, 152 | :str => "pos1", 153 | :level => 85, 154 | :sub_level => 85, 155 | :name => "黑切+蓝盾", 156 | :attr => [[1, 700], [2, 800], [3, 902]], 157 | :desc1 => "有钱就可以买" 158 | } 159 | end 160 | 161 | def get(1004, "pos1", 80, 80) do 162 | %Cfg_Array_Example1{ 163 | :id => 1004, 164 | :str => "pos1", 165 | :level => 80, 166 | :sub_level => 80, 167 | :name => "黑切+蓝盾", 168 | :attr => [[1, 700], [2, 800], [3, 903]], 169 | :desc1 => "有钱就可以买" 170 | } 171 | end 172 | 173 | def get(_, _, _, _) do 174 | :undefined 175 | end 176 | 177 | def get_all() do 178 | [ 179 | {1001, "pos1", 88, 1}, 180 | {1001, "pos1", 88, 2}, 181 | {1001, "pos1", 89, 89}, 182 | {1001, "pos2", 88, 88.9}, 183 | {1001, "pos2", 89, 89}, 184 | {1002, "pos1", 88, 88}, 185 | {1002, "pos1", 89, 89}, 186 | {1002, "pos1", 90, 90}, 187 | {1002, "pos2", 88, 88}, 188 | {1002, "pos2", 89, 89}, 189 | {1002, "pos2", 90, 90}, 190 | {1003, "pos1", 85, 85}, 191 | {1004, "pos1", 80, 80} 192 | ] 193 | end 194 | 195 | def get_list() do 196 | get_all() 197 | end 198 | 199 | def get_list(1001) do 200 | [ 201 | {1001, "pos1", 88, 1}, 202 | {1001, "pos1", 88, 2}, 203 | {1001, "pos1", 89, 89}, 204 | {1001, "pos2", 88, 88.9}, 205 | {1001, "pos2", 89, 89} 206 | ] 207 | end 208 | 209 | def get_list(1002) do 210 | [ 211 | {1002, "pos1", 88, 88}, 212 | {1002, "pos1", 89, 89}, 213 | {1002, "pos1", 90, 90}, 214 | {1002, "pos2", 88, 88}, 215 | {1002, "pos2", 89, 89}, 216 | {1002, "pos2", 90, 90} 217 | ] 218 | end 219 | 220 | def get_list(1003) do 221 | [ 222 | {1003, "pos1", 85, 85} 223 | ] 224 | end 225 | 226 | def get_list(1004) do 227 | [ 228 | {1004, "pos1", 80, 80} 229 | ] 230 | end 231 | 232 | def get_list(_) do 233 | [] 234 | end 235 | 236 | def get_list(1001, "pos1") do 237 | [ 238 | {1001, "pos1", 88, 1}, 239 | {1001, "pos1", 88, 2}, 240 | {1001, "pos1", 89, 89} 241 | ] 242 | end 243 | 244 | def get_list(1001, "pos2") do 245 | [ 246 | {1001, "pos2", 88, 88.9}, 247 | {1001, "pos2", 89, 89} 248 | ] 249 | end 250 | 251 | def get_list(1002, "pos1") do 252 | [ 253 | {1002, "pos1", 88, 88}, 254 | {1002, "pos1", 89, 89}, 255 | {1002, "pos1", 90, 90} 256 | ] 257 | end 258 | 259 | def get_list(1002, "pos2") do 260 | [ 261 | {1002, "pos2", 88, 88}, 262 | {1002, "pos2", 89, 89}, 263 | {1002, "pos2", 90, 90} 264 | ] 265 | end 266 | 267 | def get_list(1003, "pos1") do 268 | [ 269 | {1003, "pos1", 85, 85} 270 | ] 271 | end 272 | 273 | def get_list(1004, "pos1") do 274 | [ 275 | {1004, "pos1", 80, 80} 276 | ] 277 | end 278 | 279 | def get_list(_, _) do 280 | [] 281 | end 282 | 283 | def get_list(1001, "pos1", 88) do 284 | [ 285 | {1001, "pos1", 88, 1}, 286 | {1001, "pos1", 88, 2} 287 | ] 288 | end 289 | 290 | def get_list(1001, "pos1", 89) do 291 | [ 292 | {1001, "pos1", 89, 89} 293 | ] 294 | end 295 | 296 | def get_list(1001, "pos2", 88) do 297 | [ 298 | {1001, "pos2", 88, 88.9} 299 | ] 300 | end 301 | 302 | def get_list(1001, "pos2", 89) do 303 | [ 304 | {1001, "pos2", 89, 89} 305 | ] 306 | end 307 | 308 | def get_list(1002, "pos1", 88) do 309 | [ 310 | {1002, "pos1", 88, 88} 311 | ] 312 | end 313 | 314 | def get_list(1002, "pos1", 89) do 315 | [ 316 | {1002, "pos1", 89, 89} 317 | ] 318 | end 319 | 320 | def get_list(1002, "pos1", 90) do 321 | [ 322 | {1002, "pos1", 90, 90} 323 | ] 324 | end 325 | 326 | def get_list(1002, "pos2", 88) do 327 | [ 328 | {1002, "pos2", 88, 88} 329 | ] 330 | end 331 | 332 | def get_list(1002, "pos2", 89) do 333 | [ 334 | {1002, "pos2", 89, 89} 335 | ] 336 | end 337 | 338 | def get_list(1002, "pos2", 90) do 339 | [ 340 | {1002, "pos2", 90, 90} 341 | ] 342 | end 343 | 344 | def get_list(1003, "pos1", 85) do 345 | [ 346 | {1003, "pos1", 85, 85} 347 | ] 348 | end 349 | 350 | def get_list(1004, "pos1", 80) do 351 | [ 352 | {1004, "pos1", 80, 80} 353 | ] 354 | end 355 | 356 | def get_list(_, _, _) do 357 | [] 358 | end 359 | 360 | end -------------------------------------------------------------------------------- /server/cfg_array_example1.hrl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_array表示例--cfg_array 3 | %% excel sheet name : 示例1-example1 4 | 5 | -record(cfg_array_example1, { 6 | 'id' %% 唯一id 7 | ,'str' %% 佩戴位置 8 | ,'level' %% 等级 9 | ,'sub_level' %% 等级 10 | ,'name' %% 装备名字 11 | ,'attr' %% 装备增加属性 12 | ,'desc1' %% 装备来源描述 13 | }). -------------------------------------------------------------------------------- /server/cfg_array_example1.json: -------------------------------------------------------------------------------- 1 | { 2 | "1001":{ 3 | "pos1":{ 4 | "88":{ 5 | "1":{ 6 | "id":1001, 7 | "str":"pos1", 8 | "level":88, 9 | "sub_level":1, 10 | "name":"黑切+蓝盾", 11 | "desc1":"从小城镇", 12 | "attr":[ 13 | [ 14 | 1, 15 | 700 16 | ], 17 | [ 18 | 2, 19 | 800 20 | ], 21 | [ 22 | 3, 23 | 900 24 | ] 25 | ] 26 | }, 27 | "2":{ 28 | "id":1001, 29 | "str":"pos1", 30 | "level":88, 31 | "sub_level":2, 32 | "name":"黑切+蓝盾", 33 | "desc1":"有钱就可以买", 34 | "attr":[ 35 | [ 36 | 1, 37 | 700 38 | ], 39 | [ 40 | 2, 41 | 800 42 | ], 43 | [ 44 | 3, 45 | 900 46 | ] 47 | ] 48 | } 49 | }, 50 | "89":{ 51 | "89":{ 52 | "id":1001, 53 | "str":"pos1", 54 | "level":89, 55 | "sub_level":89, 56 | "name":"黑切+蓝盾", 57 | "desc1":"有钱就可以买", 58 | "attr":[ 59 | [ 60 | 1, 61 | 700 62 | ], 63 | [ 64 | 2, 65 | 800 66 | ], 67 | [ 68 | 3, 69 | 900 70 | ] 71 | ] 72 | } 73 | } 74 | }, 75 | "pos2":{ 76 | "88":{ 77 | "88.9":{ 78 | "id":1001, 79 | "str":"pos2", 80 | "level":88, 81 | "sub_level":88.9, 82 | "name":"黑切+蓝盾", 83 | "desc1":"有钱就可以买", 84 | "attr":[ 85 | [ 86 | 1, 87 | 700 88 | ], 89 | [ 90 | 2, 91 | 800 92 | ], 93 | [ 94 | 3, 95 | 900 96 | ] 97 | ] 98 | } 99 | }, 100 | "89":{ 101 | "89":{ 102 | "id":1001, 103 | "str":"pos2", 104 | "level":89, 105 | "sub_level":89, 106 | "name":"黑切+蓝盾", 107 | "desc1":"有钱就可以买", 108 | "attr":[ 109 | [ 110 | 1, 111 | 700 112 | ], 113 | [ 114 | 2, 115 | 800 116 | ], 117 | [ 118 | 3, 119 | 900 120 | ] 121 | ] 122 | } 123 | } 124 | } 125 | }, 126 | "1002":{ 127 | "pos1":{ 128 | "88":{ 129 | "88":{ 130 | "id":1002, 131 | "str":"pos1", 132 | "level":88, 133 | "sub_level":88, 134 | "name":"黑切+蓝盾", 135 | "desc1":"有钱就可以买", 136 | "attr":[ 137 | [ 138 | 1, 139 | 700 140 | ], 141 | [ 142 | 2, 143 | 800 144 | ], 145 | [ 146 | 3, 147 | 901 148 | ] 149 | ] 150 | } 151 | }, 152 | "89":{ 153 | "89":{ 154 | "id":1002, 155 | "str":"pos1", 156 | "level":89, 157 | "sub_level":89, 158 | "name":"黑切+蓝盾", 159 | "desc1":"有钱就可以买", 160 | "attr":[ 161 | [ 162 | 1, 163 | 700 164 | ], 165 | [ 166 | 2, 167 | 800 168 | ], 169 | [ 170 | 3, 171 | 900 172 | ] 173 | ] 174 | } 175 | }, 176 | "90":{ 177 | "90":{ 178 | "id":1002, 179 | "str":"pos1", 180 | "level":90, 181 | "sub_level":90, 182 | "name":"黑切+蓝盾", 183 | "desc1":"有钱就可以买", 184 | "attr":[ 185 | [ 186 | 1, 187 | 700 188 | ], 189 | [ 190 | 2, 191 | 800 192 | ], 193 | [ 194 | 3, 195 | 901 196 | ] 197 | ] 198 | } 199 | } 200 | }, 201 | "pos2":{ 202 | "88":{ 203 | "88":{ 204 | "id":1002, 205 | "str":"pos2", 206 | "level":88, 207 | "sub_level":88, 208 | "name":"黑切+蓝盾", 209 | "desc1":"有钱就可以买", 210 | "attr":[ 211 | [ 212 | 1, 213 | 700 214 | ], 215 | [ 216 | 2, 217 | 800 218 | ], 219 | [ 220 | 3, 221 | 901 222 | ] 223 | ] 224 | } 225 | }, 226 | "89":{ 227 | "89":{ 228 | "id":1002, 229 | "str":"pos2", 230 | "level":89, 231 | "sub_level":89, 232 | "name":"黑切+蓝盾", 233 | "desc1":"有钱就可以买", 234 | "attr":[ 235 | [ 236 | 1, 237 | 700 238 | ], 239 | [ 240 | 2, 241 | 800 242 | ], 243 | [ 244 | 3, 245 | 900 246 | ] 247 | ] 248 | } 249 | }, 250 | "90":{ 251 | "90":{ 252 | "id":1002, 253 | "str":"pos2", 254 | "level":90, 255 | "sub_level":90, 256 | "name":"黑切+蓝盾", 257 | "desc1":"有钱就可以买", 258 | "attr":[ 259 | [ 260 | 1, 261 | 700 262 | ], 263 | [ 264 | 2, 265 | 800 266 | ], 267 | [ 268 | 3, 269 | 901 270 | ] 271 | ] 272 | } 273 | } 274 | } 275 | }, 276 | "1003":{ 277 | "pos1":{ 278 | "85":{ 279 | "85":{ 280 | "id":1003, 281 | "str":"pos1", 282 | "level":85, 283 | "sub_level":85, 284 | "name":"黑切+蓝盾", 285 | "desc1":"有钱就可以买", 286 | "attr":[ 287 | [ 288 | 1, 289 | 700 290 | ], 291 | [ 292 | 2, 293 | 800 294 | ], 295 | [ 296 | 3, 297 | 902 298 | ] 299 | ] 300 | } 301 | } 302 | } 303 | }, 304 | "1004":{ 305 | "pos1":{ 306 | "80":{ 307 | "80":{ 308 | "id":1004, 309 | "str":"pos1", 310 | "level":80, 311 | "sub_level":80, 312 | "name":"黑切+蓝盾", 313 | "desc1":"有钱就可以买", 314 | "attr":[ 315 | [ 316 | 1, 317 | 700 318 | ], 319 | [ 320 | 2, 321 | 800 322 | ], 323 | [ 324 | 3, 325 | 903 326 | ] 327 | ] 328 | } 329 | } 330 | } 331 | } 332 | } -------------------------------------------------------------------------------- /server/cfg_array_example1.lua: -------------------------------------------------------------------------------- 1 | -- Automatic generation from -->> 2 | -- excel file name: A_array表示例--cfg_array 3 | -- excel sheet name: 示例1-example1 4 | 5 | local cfg_array_example1 = 6 | --: id ## 唯一id 7 | --: str ## 佩戴位置 8 | --: level ## 等级 9 | --: sub_level ## 等级 10 | --: name ## 装备名字 11 | --: attr ## 装备增加属性 12 | --: desc1 ## 装备来源描述 13 | 14 | { 15 | [1001] = 16 | { 17 | pos1 = 18 | { 19 | [88] = 20 | { 21 | [1] = 22 | { 23 | id = 1001, 24 | str = 'pos1', 25 | level = 88, 26 | sub_level = 1, 27 | name = '黑切+蓝盾', 28 | desc1 = '从小城镇', 29 | attr = 30 | { 31 | [1] = 32 | { 33 | [1] = 1, 34 | [2] = 700 35 | }, 36 | [2] = 37 | { 38 | [1] = 2, 39 | [2] = 800 40 | }, 41 | [3] = 42 | { 43 | [1] = 3, 44 | [2] = 900 45 | } 46 | } 47 | }, 48 | [2] = 49 | { 50 | id = 1001, 51 | str = 'pos1', 52 | level = 88, 53 | sub_level = 2, 54 | name = '黑切+蓝盾', 55 | desc1 = '有钱就可以买', 56 | attr = 57 | { 58 | [1] = 59 | { 60 | [1] = 1, 61 | [2] = 700 62 | }, 63 | [2] = 64 | { 65 | [1] = 2, 66 | [2] = 800 67 | }, 68 | [3] = 69 | { 70 | [1] = 3, 71 | [2] = 900 72 | } 73 | } 74 | } 75 | }, 76 | [89] = 77 | { 78 | [89] = 79 | { 80 | id = 1001, 81 | str = 'pos1', 82 | level = 89, 83 | sub_level = 89, 84 | name = '黑切+蓝盾', 85 | desc1 = '有钱就可以买', 86 | attr = 87 | { 88 | [1] = 89 | { 90 | [1] = 1, 91 | [2] = 700 92 | }, 93 | [2] = 94 | { 95 | [1] = 2, 96 | [2] = 800 97 | }, 98 | [3] = 99 | { 100 | [1] = 3, 101 | [2] = 900 102 | } 103 | } 104 | } 105 | } 106 | }, 107 | pos2 = 108 | { 109 | [88] = 110 | { 111 | [88.9] = 112 | { 113 | id = 1001, 114 | str = 'pos2', 115 | level = 88, 116 | sub_level = 88.9, 117 | name = '黑切+蓝盾', 118 | desc1 = '有钱就可以买', 119 | attr = 120 | { 121 | [1] = 122 | { 123 | [1] = 1, 124 | [2] = 700 125 | }, 126 | [2] = 127 | { 128 | [1] = 2, 129 | [2] = 800 130 | }, 131 | [3] = 132 | { 133 | [1] = 3, 134 | [2] = 900 135 | } 136 | } 137 | } 138 | }, 139 | [89] = 140 | { 141 | [89] = 142 | { 143 | id = 1001, 144 | str = 'pos2', 145 | level = 89, 146 | sub_level = 89, 147 | name = '黑切+蓝盾', 148 | desc1 = '有钱就可以买', 149 | attr = 150 | { 151 | [1] = 152 | { 153 | [1] = 1, 154 | [2] = 700 155 | }, 156 | [2] = 157 | { 158 | [1] = 2, 159 | [2] = 800 160 | }, 161 | [3] = 162 | { 163 | [1] = 3, 164 | [2] = 900 165 | } 166 | } 167 | } 168 | } 169 | } 170 | }, 171 | [1002] = 172 | { 173 | pos1 = 174 | { 175 | [88] = 176 | { 177 | [88] = 178 | { 179 | id = 1002, 180 | str = 'pos1', 181 | level = 88, 182 | sub_level = 88, 183 | name = '黑切+蓝盾', 184 | desc1 = '有钱就可以买', 185 | attr = 186 | { 187 | [1] = 188 | { 189 | [1] = 1, 190 | [2] = 700 191 | }, 192 | [2] = 193 | { 194 | [1] = 2, 195 | [2] = 800 196 | }, 197 | [3] = 198 | { 199 | [1] = 3, 200 | [2] = 901 201 | } 202 | } 203 | } 204 | }, 205 | [89] = 206 | { 207 | [89] = 208 | { 209 | id = 1002, 210 | str = 'pos1', 211 | level = 89, 212 | sub_level = 89, 213 | name = '黑切+蓝盾', 214 | desc1 = '有钱就可以买', 215 | attr = 216 | { 217 | [1] = 218 | { 219 | [1] = 1, 220 | [2] = 700 221 | }, 222 | [2] = 223 | { 224 | [1] = 2, 225 | [2] = 800 226 | }, 227 | [3] = 228 | { 229 | [1] = 3, 230 | [2] = 900 231 | } 232 | } 233 | } 234 | }, 235 | [90] = 236 | { 237 | [90] = 238 | { 239 | id = 1002, 240 | str = 'pos1', 241 | level = 90, 242 | sub_level = 90, 243 | name = '黑切+蓝盾', 244 | desc1 = '有钱就可以买', 245 | attr = 246 | { 247 | [1] = 248 | { 249 | [1] = 1, 250 | [2] = 700 251 | }, 252 | [2] = 253 | { 254 | [1] = 2, 255 | [2] = 800 256 | }, 257 | [3] = 258 | { 259 | [1] = 3, 260 | [2] = 901 261 | } 262 | } 263 | } 264 | } 265 | }, 266 | pos2 = 267 | { 268 | [88] = 269 | { 270 | [88] = 271 | { 272 | id = 1002, 273 | str = 'pos2', 274 | level = 88, 275 | sub_level = 88, 276 | name = '黑切+蓝盾', 277 | desc1 = '有钱就可以买', 278 | attr = 279 | { 280 | [1] = 281 | { 282 | [1] = 1, 283 | [2] = 700 284 | }, 285 | [2] = 286 | { 287 | [1] = 2, 288 | [2] = 800 289 | }, 290 | [3] = 291 | { 292 | [1] = 3, 293 | [2] = 901 294 | } 295 | } 296 | } 297 | }, 298 | [89] = 299 | { 300 | [89] = 301 | { 302 | id = 1002, 303 | str = 'pos2', 304 | level = 89, 305 | sub_level = 89, 306 | name = '黑切+蓝盾', 307 | desc1 = '有钱就可以买', 308 | attr = 309 | { 310 | [1] = 311 | { 312 | [1] = 1, 313 | [2] = 700 314 | }, 315 | [2] = 316 | { 317 | [1] = 2, 318 | [2] = 800 319 | }, 320 | [3] = 321 | { 322 | [1] = 3, 323 | [2] = 900 324 | } 325 | } 326 | } 327 | }, 328 | [90] = 329 | { 330 | [90] = 331 | { 332 | id = 1002, 333 | str = 'pos2', 334 | level = 90, 335 | sub_level = 90, 336 | name = '黑切+蓝盾', 337 | desc1 = '有钱就可以买', 338 | attr = 339 | { 340 | [1] = 341 | { 342 | [1] = 1, 343 | [2] = 700 344 | }, 345 | [2] = 346 | { 347 | [1] = 2, 348 | [2] = 800 349 | }, 350 | [3] = 351 | { 352 | [1] = 3, 353 | [2] = 901 354 | } 355 | } 356 | } 357 | } 358 | } 359 | }, 360 | [1003] = 361 | { 362 | pos1 = 363 | { 364 | [85] = 365 | { 366 | [85] = 367 | { 368 | id = 1003, 369 | str = 'pos1', 370 | level = 85, 371 | sub_level = 85, 372 | name = '黑切+蓝盾', 373 | desc1 = '有钱就可以买', 374 | attr = 375 | { 376 | [1] = 377 | { 378 | [1] = 1, 379 | [2] = 700 380 | }, 381 | [2] = 382 | { 383 | [1] = 2, 384 | [2] = 800 385 | }, 386 | [3] = 387 | { 388 | [1] = 3, 389 | [2] = 902 390 | } 391 | } 392 | } 393 | } 394 | } 395 | }, 396 | [1004] = 397 | { 398 | pos1 = 399 | { 400 | [80] = 401 | { 402 | [80] = 403 | { 404 | id = 1004, 405 | str = 'pos1', 406 | level = 80, 407 | sub_level = 80, 408 | name = '黑切+蓝盾', 409 | desc1 = '有钱就可以买', 410 | attr = 411 | { 412 | [1] = 413 | { 414 | [1] = 1, 415 | [2] = 700 416 | }, 417 | [2] = 418 | { 419 | [1] = 2, 420 | [2] = 800 421 | }, 422 | [3] = 423 | { 424 | [1] = 3, 425 | [2] = 903 426 | } 427 | } 428 | } 429 | } 430 | } 431 | } 432 | } 433 | return cfg_array_example1 -------------------------------------------------------------------------------- /server/cfg_array_example2.erl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_array表示例--cfg_array 3 | %% excel sheet name : 示例2+example2 4 | 5 | -module(cfg_array_example2). 6 | 7 | -include("cfg_array_example2.hrl"). 8 | -compile(export_all). 9 | 10 | get(1) -> 11 | #cfg_array_example2{ 12 | 'id' = 1 13 | ,'name' = "examp1001" 14 | ,'material' = [#{'res' => 1, 'id' => 10001, 'count' => 1}, #{'res' => 1, 'id' => 10001, 'count' => 1}] 15 | ,'attr' = [[1, 700], [2, 800], [3, 900], #{'add' => [4, 100]}] 16 | ,'award1' = {1, 2, 3} 17 | ,'award2' = #{'id' => 1, 'type' => 2, 'num' => 3} 18 | }; 19 | 20 | get(2) -> 21 | #cfg_array_example2{ 22 | 'id' = 2 23 | ,'name' = "examp1002" 24 | ,'material' = #{'res' => 1, 'id' => 10001, 'count' => 1} 25 | ,'attr' = [[1, 700], [2, 800], [3, 901], #{'add' => [5, 100]}] 26 | ,'award1' = {1, 2, 3} 27 | ,'award2' = #{'id' => 1, 'type' => 2, 'num' => 3} 28 | }; 29 | 30 | get(3) -> 31 | #cfg_array_example2{ 32 | 'id' = 3 33 | ,'name' = "examp1003" 34 | ,'material' = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 35 | ,'attr' = [[1, 700], [2, 800], [3, 902], #{'add' => [6, 100]}] 36 | ,'award1' = {1, 2, 3} 37 | ,'award2' = #{'id' => 1, 'type' => 2, 'num' => 3} 38 | }; 39 | 40 | get(4) -> 41 | #cfg_array_example2{ 42 | 'id' = 4 43 | ,'name' = "examp1004" 44 | ,'material' = ["测试数据", "测试数据2", "测试数据3"] 45 | ,'attr' = [[1, 700], [2, 800], [3, 903], #{'add' => [7, 100]}] 46 | ,'award1' = {1, 2, 3} 47 | ,'award2' = #{'id' => 1, 'type' => 2, 'num' => 3} 48 | }; 49 | 50 | get(5) -> 51 | #cfg_array_example2{ 52 | 'id' = 5 53 | ,'name' = "examp1004" 54 | ,'material' = ["test"] 55 | ,'attr' = [[1, 700], [2, 800], [3, 903], #{'add' => [7, 100]}] 56 | ,'award1' = {1, 2, 3} 57 | ,'award2' = #{'id' => 1, 'type' => 2, 'num' => 3} 58 | }; 59 | 60 | get(_) -> 61 | undefined. 62 | 63 | get_all() -> 64 | [ 65 | {1} 66 | ,{2} 67 | ,{3} 68 | ,{4} 69 | ,{5} 70 | ]. 71 | 72 | get_list() -> 73 | get_all(). 74 | 75 | -------------------------------------------------------------------------------- /server/cfg_array_example2.ex: -------------------------------------------------------------------------------- 1 | ## Automatic generation from -->> 2 | ## excel file name: A_array表示例--cfg_array 3 | ## excel sheet name: 示例2+example2 4 | 5 | defmodule Cfg_Array_Example2 do 6 | 7 | defstruct [ 8 | :id, ## 英雄id 9 | :name, ## 英雄名字 10 | :material, ## 合成消耗 11 | :attr, ## 属性 12 | :award1, ## 奖励1 13 | :award2 ## 奖励2 14 | ] 15 | 16 | def get(1) do 17 | %Cfg_Array_Example2{ 18 | :id => 1, 19 | :name => "examp1001", 20 | :material => [%{:res => 1, :id => 10001, :count => 1}, %{:res => 1, :id => 10001, :count => 1}], 21 | :attr => [[1, 700], [2, 800], [3, 900], %{:add => [4, 100]}], 22 | :award1 => {1, 2, 3}, 23 | :award2 => %{:id => 1, :type => 2, :num => 3} 24 | } 25 | end 26 | 27 | def get(2) do 28 | %Cfg_Array_Example2{ 29 | :id => 2, 30 | :name => "examp1002", 31 | :material => %{:res => 1, :id => 10001, :count => 1}, 32 | :attr => [[1, 700], [2, 800], [3, 901], %{:add => [5, 100]}], 33 | :award1 => {1, 2, 3}, 34 | :award2 => %{:id => 1, :type => 2, :num => 3} 35 | } 36 | end 37 | 38 | def get(3) do 39 | %Cfg_Array_Example2{ 40 | :id => 3, 41 | :name => "examp1003", 42 | :material => [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], 43 | :attr => [[1, 700], [2, 800], [3, 902], %{:add => [6, 100]}], 44 | :award1 => {1, 2, 3}, 45 | :award2 => %{:id => 1, :type => 2, :num => 3} 46 | } 47 | end 48 | 49 | def get(4) do 50 | %Cfg_Array_Example2{ 51 | :id => 4, 52 | :name => "examp1004", 53 | :material => ["测试数据", "测试数据2", "测试数据3"], 54 | :attr => [[1, 700], [2, 800], [3, 903], %{:add => [7, 100]}], 55 | :award1 => {1, 2, 3}, 56 | :award2 => %{:id => 1, :type => 2, :num => 3} 57 | } 58 | end 59 | 60 | def get(5) do 61 | %Cfg_Array_Example2{ 62 | :id => 5, 63 | :name => "examp1004", 64 | :material => ["test"], 65 | :attr => [[1, 700], [2, 800], [3, 903], %{:add => [7, 100]}], 66 | :award1 => {1, 2, 3}, 67 | :award2 => %{:id => 1, :type => 2, :num => 3} 68 | } 69 | end 70 | 71 | def get(_) do 72 | :undefined 73 | end 74 | 75 | def get_all() do 76 | [ 77 | {1}, 78 | {2}, 79 | {3}, 80 | {4}, 81 | {5} 82 | ] 83 | end 84 | 85 | def get_list() do 86 | get_all() 87 | end 88 | 89 | end -------------------------------------------------------------------------------- /server/cfg_array_example2.hrl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_array表示例--cfg_array 3 | %% excel sheet name : 示例2+example2 4 | 5 | -record(cfg_array_example2, { 6 | 'id' %% 英雄id 7 | ,'name' %% 英雄名字 8 | ,'material' %% 合成消耗 9 | ,'attr' %% 属性 10 | ,'award1' %% 奖励1 11 | ,'award2' %% 奖励2 12 | }). -------------------------------------------------------------------------------- /server/cfg_array_example2.json: -------------------------------------------------------------------------------- 1 | { 2 | "1":{ 3 | "id":1, 4 | "name":"examp1001", 5 | "material":[ 6 | { 7 | "res":1, 8 | "id":10001, 9 | "count":1 10 | }, 11 | { 12 | "res":1, 13 | "id":10001, 14 | "count":1 15 | } 16 | ], 17 | "attr":[ 18 | [ 19 | 1, 20 | 700 21 | ], 22 | [ 23 | 2, 24 | 800 25 | ], 26 | [ 27 | 3, 28 | 900 29 | ], 30 | { 31 | "add":[ 32 | 4, 33 | 100 34 | ] 35 | } 36 | ], 37 | "award1":[ 38 | 1, 39 | 2, 40 | 3 41 | ], 42 | "award2":{ 43 | "id":1, 44 | "type":2, 45 | "num":3 46 | } 47 | }, 48 | "2":{ 49 | "id":2, 50 | "name":"examp1002", 51 | "material":{ 52 | "res":1, 53 | "id":10001, 54 | "count":1 55 | }, 56 | "attr":[ 57 | [ 58 | 1, 59 | 700 60 | ], 61 | [ 62 | 2, 63 | 800 64 | ], 65 | [ 66 | 3, 67 | 901 68 | ], 69 | { 70 | "add":[ 71 | 5, 72 | 100 73 | ] 74 | } 75 | ], 76 | "award1":[ 77 | 1, 78 | 2, 79 | 3 80 | ], 81 | "award2":{ 82 | "id":1, 83 | "type":2, 84 | "num":3 85 | } 86 | }, 87 | "3":{ 88 | "id":3, 89 | "name":"examp1003", 90 | "material":[ 91 | 1, 92 | 2, 93 | 3, 94 | 4, 95 | 5, 96 | 6, 97 | 7, 98 | 8, 99 | 9, 100 | 9, 101 | 9, 102 | 9, 103 | 9, 104 | 9, 105 | 9, 106 | 9, 107 | 9, 108 | 9 109 | ], 110 | "attr":[ 111 | [ 112 | 1, 113 | 700 114 | ], 115 | [ 116 | 2, 117 | 800 118 | ], 119 | [ 120 | 3, 121 | 902 122 | ], 123 | { 124 | "add":[ 125 | 6, 126 | 100 127 | ] 128 | } 129 | ], 130 | "award1":[ 131 | 1, 132 | 2, 133 | 3 134 | ], 135 | "award2":{ 136 | "id":1, 137 | "type":2, 138 | "num":3 139 | } 140 | }, 141 | "4":{ 142 | "id":4, 143 | "name":"examp1004", 144 | "material":[ 145 | "测试数据", 146 | "测试数据2", 147 | "测试数据3" 148 | ], 149 | "attr":[ 150 | [ 151 | 1, 152 | 700 153 | ], 154 | [ 155 | 2, 156 | 800 157 | ], 158 | [ 159 | 3, 160 | 903 161 | ], 162 | { 163 | "add":[ 164 | 7, 165 | 100 166 | ] 167 | } 168 | ], 169 | "award1":[ 170 | 1, 171 | 2, 172 | 3 173 | ], 174 | "award2":{ 175 | "id":1, 176 | "type":2, 177 | "num":3 178 | } 179 | }, 180 | "5":{ 181 | "id":5, 182 | "name":"examp1004", 183 | "material":[ 184 | "test" 185 | ], 186 | "attr":[ 187 | [ 188 | 1, 189 | 700 190 | ], 191 | [ 192 | 2, 193 | 800 194 | ], 195 | [ 196 | 3, 197 | 903 198 | ], 199 | { 200 | "add":[ 201 | 7, 202 | 100 203 | ] 204 | } 205 | ], 206 | "award1":[ 207 | 1, 208 | 2, 209 | 3 210 | ], 211 | "award2":{ 212 | "id":1, 213 | "type":2, 214 | "num":3 215 | } 216 | } 217 | } -------------------------------------------------------------------------------- /server/cfg_array_example2.lua: -------------------------------------------------------------------------------- 1 | -- Automatic generation from -->> 2 | -- excel file name: A_array表示例--cfg_array 3 | -- excel sheet name: 示例2+example2 4 | 5 | local cfg_array_example2 = 6 | --: id ## 英雄id 7 | --: name ## 英雄名字 8 | --: material ## 合成消耗 9 | --: attr ## 属性 10 | --: award1 ## 奖励1 11 | --: award2 ## 奖励2 12 | 13 | { 14 | [1] = 15 | { 16 | id = 1, 17 | name = 'examp1001', 18 | material = 19 | { 20 | [1] = 21 | { 22 | res = 1, 23 | id = 10001, 24 | count = 1 25 | }, 26 | [2] = 27 | { 28 | res = 1, 29 | id = 10001, 30 | count = 1 31 | } 32 | }, 33 | attr = 34 | { 35 | [1] = 36 | { 37 | [1] = 1, 38 | [2] = 700 39 | }, 40 | [2] = 41 | { 42 | [1] = 2, 43 | [2] = 800 44 | }, 45 | [3] = 46 | { 47 | [1] = 3, 48 | [2] = 900 49 | }, 50 | [4] = 51 | { 52 | add = 53 | { 54 | [1] = 4, 55 | [2] = 100 56 | } 57 | } 58 | }, 59 | award1 = 60 | { 61 | [1] = 1, 62 | [2] = 2, 63 | [3] = 3 64 | }, 65 | award2 = 66 | { 67 | id = 1, 68 | type = 2, 69 | num = 3 70 | } 71 | }, 72 | [2] = 73 | { 74 | id = 2, 75 | name = 'examp1002', 76 | material = 77 | { 78 | res = 1, 79 | id = 10001, 80 | count = 1 81 | }, 82 | attr = 83 | { 84 | [1] = 85 | { 86 | [1] = 1, 87 | [2] = 700 88 | }, 89 | [2] = 90 | { 91 | [1] = 2, 92 | [2] = 800 93 | }, 94 | [3] = 95 | { 96 | [1] = 3, 97 | [2] = 901 98 | }, 99 | [4] = 100 | { 101 | add = 102 | { 103 | [1] = 5, 104 | [2] = 100 105 | } 106 | } 107 | }, 108 | award1 = 109 | { 110 | [1] = 1, 111 | [2] = 2, 112 | [3] = 3 113 | }, 114 | award2 = 115 | { 116 | id = 1, 117 | type = 2, 118 | num = 3 119 | } 120 | }, 121 | [3] = 122 | { 123 | id = 3, 124 | name = 'examp1003', 125 | material = 126 | { 127 | [1] = 1, 128 | [2] = 2, 129 | [3] = 3, 130 | [4] = 4, 131 | [5] = 5, 132 | [6] = 6, 133 | [7] = 7, 134 | [8] = 8, 135 | [9] = 9, 136 | [10] = 9, 137 | [11] = 9, 138 | [12] = 9, 139 | [13] = 9, 140 | [14] = 9, 141 | [15] = 9, 142 | [16] = 9, 143 | [17] = 9, 144 | [18] = 9 145 | }, 146 | attr = 147 | { 148 | [1] = 149 | { 150 | [1] = 1, 151 | [2] = 700 152 | }, 153 | [2] = 154 | { 155 | [1] = 2, 156 | [2] = 800 157 | }, 158 | [3] = 159 | { 160 | [1] = 3, 161 | [2] = 902 162 | }, 163 | [4] = 164 | { 165 | add = 166 | { 167 | [1] = 6, 168 | [2] = 100 169 | } 170 | } 171 | }, 172 | award1 = 173 | { 174 | [1] = 1, 175 | [2] = 2, 176 | [3] = 3 177 | }, 178 | award2 = 179 | { 180 | id = 1, 181 | type = 2, 182 | num = 3 183 | } 184 | }, 185 | [4] = 186 | { 187 | id = 4, 188 | name = 'examp1004', 189 | material = 190 | { 191 | [1] = '测试数据', 192 | [2] = '测试数据2', 193 | [3] = '测试数据3' 194 | }, 195 | attr = 196 | { 197 | [1] = 198 | { 199 | [1] = 1, 200 | [2] = 700 201 | }, 202 | [2] = 203 | { 204 | [1] = 2, 205 | [2] = 800 206 | }, 207 | [3] = 208 | { 209 | [1] = 3, 210 | [2] = 903 211 | }, 212 | [4] = 213 | { 214 | add = 215 | { 216 | [1] = 7, 217 | [2] = 100 218 | } 219 | } 220 | }, 221 | award1 = 222 | { 223 | [1] = 1, 224 | [2] = 2, 225 | [3] = 3 226 | }, 227 | award2 = 228 | { 229 | id = 1, 230 | type = 2, 231 | num = 3 232 | } 233 | }, 234 | [5] = 235 | { 236 | id = 5, 237 | name = 'examp1004', 238 | material = 239 | { 240 | [1] = 'test' 241 | }, 242 | attr = 243 | { 244 | [1] = 245 | { 246 | [1] = 1, 247 | [2] = 700 248 | }, 249 | [2] = 250 | { 251 | [1] = 2, 252 | [2] = 800 253 | }, 254 | [3] = 255 | { 256 | [1] = 3, 257 | [2] = 903 258 | }, 259 | [4] = 260 | { 261 | add = 262 | { 263 | [1] = 7, 264 | [2] = 100 265 | } 266 | } 267 | }, 268 | award1 = 269 | { 270 | [1] = 1, 271 | [2] = 2, 272 | [3] = 3 273 | }, 274 | award2 = 275 | { 276 | id = 1, 277 | type = 2, 278 | num = 3 279 | } 280 | } 281 | } 282 | return cfg_array_example2 -------------------------------------------------------------------------------- /server/cfg_array_example3.erl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_array表示例--cfg_array 3 | %% excel sheet name : +example3 4 | 5 | -module(cfg_array_example3). 6 | 7 | -compile(export_all). 8 | 9 | %% 演示 10 | get('level') -> 11 | "啦啦啦!!!"; 12 | 13 | get(_) -> 14 | undefined. -------------------------------------------------------------------------------- /server/cfg_array_example3.ex: -------------------------------------------------------------------------------- 1 | ## Automatic generation from -->> 2 | ## excel file name: A_array表示例--cfg_array 3 | ## excel sheet name: +example3 4 | 5 | defmodule Cfg_Array_Example3 do 6 | 7 | ## 演示 8 | def get(:level) do 9 | "啦啦啦!!!" 10 | end 11 | 12 | def get(_) do 13 | :undefined 14 | end 15 | 16 | end -------------------------------------------------------------------------------- /server/cfg_array_example3.json: -------------------------------------------------------------------------------- 1 | { 2 | "level":"啦啦啦!!!" 3 | } -------------------------------------------------------------------------------- /server/cfg_array_example3.lua: -------------------------------------------------------------------------------- 1 | -- Automatic generation from -->> 2 | -- excel file name: A_array表示例--cfg_array 3 | -- excel sheet name: +example3 4 | 5 | local cfg_array_example3 = 6 | { 7 | -- 演示 8 | level = '啦啦啦!!!' 9 | } 10 | return cfg_array_example3 -------------------------------------------------------------------------------- /server/cfg_object.erl: -------------------------------------------------------------------------------- 1 | %% Automatic generation from -->> 2 | %% excel file name : A_object表示例--cfg_object 3 | %% excel sheet name : 武器(这个sheet就不会附加到导出名后部分) 4 | 5 | -module(cfg_object). 6 | 7 | -compile(export_all). 8 | 9 | %% 开放等级 10 | get('open_level') -> 11 | 90; 12 | 13 | %% 额外添加属性值1 14 | get('add_value1') -> 15 | 100.1; 16 | 17 | %% 额外添加属性值2 18 | get('add_value2') -> 19 | 100; 20 | 21 | %% 活动id 22 | get('act_id') -> 23 | 1001; 24 | 25 | %% 开始时间 26 | get('open') -> 27 | "18:00:0"; 28 | 29 | %% 错误信息 30 | get(10000) -> 31 | "前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了)"; 32 | 33 | %% 奖励1 34 | get('award1') -> 35 | [[1001, 20], {1002, 20}, [1003, 30]]; 36 | 37 | %% 奖励2 38 | get('award2') -> 39 | {{1001, 10}, [1002, 20]}; 40 | 41 | %% 奖励3(这条转成xml是就会报错) 42 | get('award3') -> 43 | #{1 => #{'res' => 1001, 'id' => 10001, 'count' => 1}, 2 => #{'res' => [1002, 1], 'id' => 10001, 'count' => 1}}; 44 | 45 | %% 奖励4 46 | get('award4') -> 47 | #{'rr' => [1001, 20], 'ff' => [3006, 99], 'aa' => [7003, 1], 'test' => "这就是一个测试"}; 48 | 49 | %% 奖励5 50 | get('award5') -> 51 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]; 52 | 53 | %% 奖励 54 | get('award6') -> 55 | [[1001, 20], [3006, 99], [7003, 1], #{'jsonobject' => [12356, 654321]}]; 56 | 57 | get(_) -> 58 | undefined. -------------------------------------------------------------------------------- /server/cfg_object.ex: -------------------------------------------------------------------------------- 1 | ## Automatic generation from -->> 2 | ## excel file name: A_object表示例--cfg_object 3 | ## excel sheet name: 武器(这个sheet就不会附加到导出名后部分) 4 | 5 | defmodule Cfg_Object do 6 | 7 | ## 开放等级 8 | def get(:open_level) do 9 | 90 10 | end 11 | 12 | ## 额外添加属性值1 13 | def get(:add_value1) do 14 | 100.1 15 | end 16 | 17 | ## 额外添加属性值2 18 | def get(:add_value2) do 19 | 100 20 | end 21 | 22 | ## 活动id 23 | def get(:act_id) do 24 | 1001 25 | end 26 | 27 | ## 开始时间 28 | def get(:open) do 29 | "18:00:0" 30 | end 31 | 32 | ## 错误信息 33 | def get(10000) do 34 | "前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了)" 35 | end 36 | 37 | ## 奖励1 38 | def get(:award1) do 39 | [[1001, 20], {1002, 20}, [1003, 30]] 40 | end 41 | 42 | ## 奖励2 43 | def get(:award2) do 44 | {{1001, 10}, [1002, 20]} 45 | end 46 | 47 | ## 奖励3(这条转成xml是就会报错,因为KEY为数字) 48 | def get(:award3) do 49 | %{1 => %{:res => 1001, :id => 10001, :count => 1}, 2 => %{:res => [1002, 1], :id => 10001, :count => 1}} 50 | end 51 | 52 | ## 奖励4 53 | def get(:award4) do 54 | %{:rr => [1001, 20], :ff => [3006, 99], :aa => [7003, 1], :test => "这就是一个测试"} 55 | end 56 | 57 | ## 奖励5 58 | def get(:award5) do 59 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 60 | end 61 | 62 | ## 奖励 63 | def get(:award6) do 64 | [[1001, 20], [3006, 99], [7003, 1], %{:jsonobject => [12356, 654321]}] 65 | end 66 | 67 | def get(_) do 68 | :undefined 69 | end 70 | 71 | end -------------------------------------------------------------------------------- /server/cfg_object.json: -------------------------------------------------------------------------------- 1 | { 2 | "open_level":90, 3 | "add_value1":100.1, 4 | "add_value2":100, 5 | "act_id":1001, 6 | "open":"18:00:0", 7 | "10000":"前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了)", 8 | "award1":[ 9 | [ 10 | 1001, 11 | 20 12 | ], 13 | [ 14 | 1002, 15 | 20 16 | ], 17 | [ 18 | 1003, 19 | 30 20 | ] 21 | ], 22 | "award2":[ 23 | [ 24 | 1001, 25 | 10 26 | ], 27 | [ 28 | 1002, 29 | 20 30 | ] 31 | ], 32 | "award3":{ 33 | "1":{ 34 | "res":1001, 35 | "id":10001, 36 | "count":1 37 | }, 38 | "2":{ 39 | "id":10001, 40 | "count":1, 41 | "res":[ 42 | 1002, 43 | 1 44 | ] 45 | } 46 | }, 47 | "award4":{ 48 | "test":"这就是一个测试", 49 | "rr":[ 50 | 1001, 51 | 20 52 | ], 53 | "ff":[ 54 | 3006, 55 | 99 56 | ], 57 | "aa":[ 58 | 7003, 59 | 1 60 | ] 61 | }, 62 | "award5":[ 63 | 1, 64 | 2, 65 | 3, 66 | 4, 67 | 5, 68 | 6, 69 | 7, 70 | 8, 71 | 9, 72 | 9, 73 | 9, 74 | 9, 75 | 9, 76 | 9, 77 | 9, 78 | 9, 79 | 9, 80 | 9 81 | ], 82 | "award6":[ 83 | [ 84 | 1001, 85 | 20 86 | ], 87 | [ 88 | 3006, 89 | 99 90 | ], 91 | [ 92 | 7003, 93 | 1 94 | ], 95 | { 96 | "jsonobject":[ 97 | 12356, 98 | 654321 99 | ] 100 | } 101 | ] 102 | } -------------------------------------------------------------------------------- /server/cfg_object.lua: -------------------------------------------------------------------------------- 1 | -- Automatic generation from -->> 2 | -- excel file name: A_object表示例--cfg_object 3 | -- excel sheet name: 武器(这个sheet就不会附加到导出名后部分) 4 | 5 | local cfg_object = 6 | { 7 | -- 开放等级 8 | open_level =90, 9 | 10 | -- 额外添加属性值1 11 | add_value1 =100.1, 12 | 13 | -- 额外添加属性值2 14 | add_value2 =100, 15 | 16 | -- 活动id 17 | act_id =1001, 18 | 19 | -- 开始时间 20 | open ='18:00:0', 21 | 22 | -- 错误信息 23 | [10000] ='前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了)', 24 | 25 | -- 奖励1 26 | award1 = 27 | { 28 | [1] = 29 | { 30 | [1] = 1001, 31 | [2] = 20 32 | }, 33 | [2] = 34 | { 35 | [1] = 1002, 36 | [2] = 20 37 | }, 38 | [3] = 39 | { 40 | [1] = 1003, 41 | [2] = 30 42 | } 43 | }, 44 | 45 | -- 奖励2 46 | award2 = 47 | { 48 | [1] = 49 | { 50 | [1] = 1001, 51 | [2] = 10 52 | }, 53 | [2] = 54 | { 55 | [1] = 1002, 56 | [2] = 20 57 | } 58 | }, 59 | 60 | -- 奖励3(这条转成xml是就会报错) 61 | award3 = 62 | { 63 | [1] = 64 | { 65 | res = 1001, 66 | id = 10001, 67 | count = 1 68 | }, 69 | [2] = 70 | { 71 | id = 10001, 72 | count = 1, 73 | res = 74 | { 75 | [1] = 1002, 76 | [2] = 1 77 | } 78 | } 79 | }, 80 | 81 | -- 奖励4 82 | award4 = 83 | { 84 | test = '这就是一个测试', 85 | rr = 86 | { 87 | [1] = 1001, 88 | [2] = 20 89 | }, 90 | ff = 91 | { 92 | [1] = 3006, 93 | [2] = 99 94 | }, 95 | aa = 96 | { 97 | [1] = 7003, 98 | [2] = 1 99 | } 100 | }, 101 | 102 | -- 奖励5 103 | award5 = 104 | { 105 | [1] = 1, 106 | [2] = 2, 107 | [3] = 3, 108 | [4] = 4, 109 | [5] = 5, 110 | [6] = 6, 111 | [7] = 7, 112 | [8] = 8, 113 | [9] = 9, 114 | [10] = 9, 115 | [11] = 9, 116 | [12] = 9, 117 | [13] = 9, 118 | [14] = 9, 119 | [15] = 9, 120 | [16] = 9, 121 | [17] = 9, 122 | [18] = 9 123 | }, 124 | 125 | -- 奖励 126 | award6 = 127 | { 128 | [1] = 129 | { 130 | [1] = 1001, 131 | [2] = 20 132 | }, 133 | [2] = 134 | { 135 | [1] = 3006, 136 | [2] = 99 137 | }, 138 | [3] = 139 | { 140 | [1] = 7003, 141 | [2] = 1 142 | }, 143 | [4] = 144 | { 145 | jsonobject = 146 | { 147 | [1] = 12356, 148 | [2] = 654321 149 | } 150 | } 151 | } 152 | } 153 | return cfg_object -------------------------------------------------------------------------------- /server/cfg_object1_cfg_object.ex: -------------------------------------------------------------------------------- 1 | ## Automatic generation from -->> 2 | ## excel file name: A_object表示例--cfg_object1 3 | ## excel sheet name: A_object表示例--cfg_object 4 | 5 | defmodule Cfg_Object1_Cfg_Object do 6 | 7 | ## 开放等级 8 | def get(:open_level) do 9 | 90 10 | end 11 | 12 | ## 额外添加属性值1 13 | def get(:add_value1) do 14 | 100.1 15 | end 16 | 17 | ## 额外添加属性值2 18 | def get(:add_value2) do 19 | 100 20 | end 21 | 22 | ## 活动id 23 | def get(:act_id) do 24 | 1001 25 | end 26 | 27 | ## 开始时间 28 | def get(:open) do 29 | "fgfdg" 30 | end 31 | 32 | ## 错误信息 33 | def get(10000) do 34 | "前面字段为errorID,这里是错误描述,是的object配置的server,client字段名还支持数字作为key(但是转出格式为xml和jsonarray时就不支持了)" 35 | end 36 | 37 | ## 奖励1 38 | def get(:award1) do 39 | [[1001, 20], {1002, 20}, [1003, 30]] 40 | end 41 | 42 | ## 奖励2 43 | def get(:award2) do 44 | {{1001, 10}, [1002, 20]} 45 | end 46 | 47 | ## 奖励3(这条转成xml是就会报错,因为KEY为数字) 48 | def get(:award3) do 49 | %{1 => %{:res => 1001, :id => 10001, :count => 1}, 2 => %{:res => [1002, 1], :id => 10001, :count => 1}} 50 | end 51 | 52 | ## 奖励4 53 | def get(:award4) do 54 | %{:rr => [1001, 20], :ff => [3006, 99], :aa => [7003, 1], :test => "这就是一个测试"} 55 | end 56 | 57 | ## 奖励5 58 | def get(:award5) do 59 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 60 | end 61 | 62 | ## 奖励 63 | def get(:award6) do 64 | [[1001, 20], [3006, 99], [7003, 1], %{:jsonobject => [12356, 654321]}] 65 | end 66 | 67 | def get(_) do 68 | :undefined 69 | end 70 | 71 | end -------------------------------------------------------------------------------- /slpp/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | 4 | 5 | -------------------------------------------------------------------------------- /slpp/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, 2011, 2012 SirAnthony 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /slpp/README.markdown: -------------------------------------------------------------------------------- 1 | #### SLPP 2 | SLPP is a simple lua-python data structures parser. 3 | 4 | Lua data check: 5 | 6 | ```lua 7 | data = '{ array = { 65, 23, 5 }, dict = { string = "value", array = { 3, 6, 4}, mixed = { 43, 54.3, false, string = "value", 9 } } }' 8 | > data = assert(loadstring('return ' .. data))() 9 | > for i,j in pairs(data['dict']) do print(i,j) end 10 | mixed table: 0x2014290 11 | string value 12 | array table: 0x2014200 13 | ``` 14 | 15 | Parse lua data: 16 | 17 | ```python 18 | >>> from slpp import slpp as lua 19 | >>> data = lua.decode('{ array = { 65, 23, 5 }, dict = { string = "value", array = { 3, 6, 4}, mixed = { 43, 54.3, false, string = "value", 9 } } }') 20 | >>> print data 21 | {'array': [65, 23, 5], 'dict': {'mixed': {0: 43, 1: 54.33, 2: False, 4: 9, 'string': 'value'}, 'array': [3, 6, 4], 'string': 'value'}} 22 | ``` 23 | 24 | Dump python object: 25 | 26 | ```python 27 | >>> lua.encode(data) 28 | '{array = {65,23,5},dict = {mixed = {43,54.33,false,9,string = "value"},array = {3,6,4},string = "value"}}' 29 | ``` 30 | 31 | Dump test: 32 | 33 | ```lua 34 | > data = assert(loadstring('return ' .. '{array = {65,23,5,},dict = {mixed = {43,54.33,false,9,string = "value",},array = {3,6,4,},string = "value",},}'))() 35 | > print(data['dict']) 36 | table: 0x1b64ea0 37 | > for i,j in pairs(data['dict']) do print(i,j) end 38 | mixed table: 0x880afe0 39 | array table: 0x880af60 40 | string value 41 | ``` 42 | -------------------------------------------------------------------------------- /slpp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlyshare/ConfigConvertTool/3ac2b7fdd8b09cd98e75fac03f589e0cd5881741/slpp/__init__.py -------------------------------------------------------------------------------- /slpp/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from distutils.core import setup 3 | 4 | setup( 5 | name='SLPP', 6 | description='SLPP is a simple lua-python data structures parser', 7 | version='1.0', 8 | author='SirAnthony', 9 | url='https://github.com/SirAnthony/slpp', 10 | license='https://github.com/SirAnthony/slpp/blob/master/LICENSE', 11 | keywords=['lua'], 12 | py_modules=['slpp'], 13 | ) 14 | -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlyshare/ConfigConvertTool/3ac2b7fdd8b09cd98e75fac03f589e0cd5881741/slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229.zip -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | 4 | 5 | -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, 2011, 2012 SirAnthony 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/README.markdown: -------------------------------------------------------------------------------- 1 | #### SLPP 2 | SLPP is a simple lua-python data structures parser. 3 | 4 | Lua data check: 5 | 6 | ```lua 7 | data = '{ array = { 65, 23, 5 }, dict = { string = "value", array = { 3, 6, 4}, mixed = { 43, 54.3, false, string = "value", 9 } } }' 8 | > data = assert(loadstring('return ' .. data))() 9 | > for i,j in pairs(data['dict']) do print(i,j) end 10 | mixed table: 0x2014290 11 | string value 12 | array table: 0x2014200 13 | ``` 14 | 15 | Parse lua data: 16 | 17 | ```python 18 | >>> from slpp import slpp as lua 19 | >>> data = lua.decode('{ array = { 65, 23, 5 }, dict = { string = "value", array = { 3, 6, 4}, mixed = { 43, 54.3, false, string = "value", 9 } } }') 20 | >>> print data 21 | {'array': [65, 23, 5], 'dict': {'mixed': {0: 43, 1: 54.33, 2: False, 4: 9, 'string': 'value'}, 'array': [3, 6, 4], 'string': 'value'}} 22 | ``` 23 | 24 | Dump python object: 25 | 26 | ```python 27 | >>> lua.encode(data) 28 | '{array = {65,23,5},dict = {mixed = {43,54.33,false,9,string = "value"},array = {3,6,4},string = "value"}}' 29 | ``` 30 | 31 | Dump test: 32 | 33 | ```lua 34 | > data = assert(loadstring('return ' .. '{array = {65,23,5,},dict = {mixed = {43,54.33,false,9,string = "value",},array = {3,6,4,},string = "value",},}'))() 35 | > print(data['dict']) 36 | table: 0x1b64ea0 37 | > for i,j in pairs(data['dict']) do print(i,j) end 38 | mixed table: 0x880afe0 39 | array table: 0x880af60 40 | string value 41 | ``` 42 | -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erlyshare/ConfigConvertTool/3ac2b7fdd8b09cd98e75fac03f589e0cd5881741/slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/__init__.py -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from distutils.core import setup 3 | 4 | setup( 5 | name='SLPP', 6 | description='SLPP is a simple lua-python data structures parser', 7 | version='1.0', 8 | author='SirAnthony', 9 | url='https://github.com/SirAnthony/slpp', 10 | license='https://github.com/SirAnthony/slpp/blob/master/LICENSE', 11 | keywords=['lua'], 12 | py_modules=['slpp'], 13 | ) 14 | -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/slpp.py: -------------------------------------------------------------------------------- 1 | import re 2 | import sys 3 | 4 | ERRORS = { 5 | 'unexp_end_string': u'Unexpected end of string while parsing Lua string.', 6 | 'unexp_end_table': u'Unexpected end of table while parsing Lua string.', 7 | 'mfnumber_minus': u'Malformed number (no digits after initial minus).', 8 | 'mfnumber_dec_point': u'Malformed number (no digits after decimal point).', 9 | 'mfnumber_sci': u'Malformed number (bad scientific format).', 10 | } 11 | # Python 3 renamed the unicode type to str, 12 | # the old str type has been replaced by bytes 13 | try: 14 | basestring 15 | except NameError: 16 | basestring = str 17 | 18 | try: 19 | unicode 20 | except NameError: 21 | unicode = str 22 | 23 | class ParseError(Exception): 24 | pass 25 | 26 | 27 | class SLPP(object): 28 | 29 | def __init__(self): 30 | self.text = '' 31 | self.ch = '' 32 | self.at = 0 33 | self.len = 0 34 | self.depth = 0 35 | self.space = re.compile('\s', re.M) 36 | self.alnum = re.compile('\w', re.M) 37 | self.newline = '\n' 38 | self.tab = '\t' 39 | 40 | def decode(self, text): 41 | if not text or not isinstance(text, basestring): 42 | return 43 | #FIXME: only short comments removed 44 | reg = re.compile('--.*$', re.M) 45 | text = reg.sub('', text, 0) 46 | self.text = text 47 | self.at, self.ch, self.depth = 0, '', 0 48 | self.len = len(text) 49 | self.next_chr() 50 | result = self.value() 51 | return result 52 | 53 | def encode(self, obj): 54 | self.depth = 0 55 | return self.__encode(obj) 56 | 57 | def __encode(self, obj): 58 | s = '' 59 | tab = self.tab 60 | newline = self.newline 61 | tp = type(obj) 62 | if isinstance(obj, str): 63 | s += '"%s"' % obj.replace(r'"', r'\"') 64 | if isinstance(obj, unicode): 65 | s += '"%s"' % obj.encode('utf-8').replace(r'"', r'\"') 66 | elif tp in [int, float, long, complex]: 67 | s += str(obj) 68 | elif tp is bool: 69 | s += str(obj).lower() 70 | elif obj is None: 71 | s += 'nil' 72 | elif tp in [list, tuple, dict]: 73 | self.depth += 1 74 | if len(obj) == 0 or ( tp is not dict and len(filter( 75 | lambda x: type(x) in (int, float, long) \ 76 | or (isinstance(x, basestring) and len(x) < 10), obj 77 | )) == len(obj) ): 78 | newline = tab = '' 79 | dp = tab * self.depth 80 | s += "%s{%s" % (tab * (self.depth - 2), newline) 81 | if tp is dict: 82 | contents = [] 83 | for k, v in obj.iteritems(): 84 | if type(k) is int: 85 | contents.append(self.__encode(v)) 86 | else: 87 | contents.append(dp + '%s = %s' % (k, self.__encode(v))) 88 | s += (',%s' % newline).join(contents) 89 | 90 | else: 91 | s += (',%s' % newline).join( 92 | [dp + self.__encode(el) for el in obj]) 93 | self.depth -= 1 94 | s += "%s%s}" % (newline, tab * self.depth) 95 | return s 96 | 97 | def white(self): 98 | while self.ch: 99 | if self.space.match(self.ch): 100 | self.next_chr() 101 | else: 102 | break 103 | 104 | def next_chr(self): 105 | if self.at >= self.len: 106 | self.ch = None 107 | return None 108 | self.ch = self.text[self.at] 109 | self.at += 1 110 | return True 111 | 112 | def value(self): 113 | self.white() 114 | if not self.ch: 115 | return 116 | if self.ch == '{': 117 | return self.object() 118 | if self.ch == "[": 119 | self.next_chr() 120 | if self.ch in ['"', "'", '[']: 121 | return self.string(self.ch) 122 | if self.ch.isdigit() or self.ch == '-': 123 | return self.number() 124 | return self.word() 125 | 126 | def string(self, end=None): 127 | s = '' 128 | start = self.ch 129 | if end == '[': 130 | end = ']' 131 | if start in ['"', "'", '[']: 132 | while self.next_chr(): 133 | if self.ch == end: 134 | self.next_chr() 135 | if start != "[" or self.ch == ']': 136 | return s 137 | if self.ch == '\\' and start == end: 138 | self.next_chr() 139 | if self.ch != end: 140 | s += '\\' 141 | s += self.ch 142 | raise Exception(ERRORS['unexp_end_string']) 143 | 144 | def object(self): 145 | o = {} 146 | k = None 147 | idx = 0 148 | numeric_keys = False 149 | self.depth += 1 150 | self.next_chr() 151 | self.white() 152 | if self.ch and self.ch == '}': 153 | self.depth -= 1 154 | self.next_chr() 155 | return o #Exit here 156 | else: 157 | while self.ch: 158 | self.white() 159 | if self.ch == '{': 160 | o[idx] = self.object() 161 | idx += 1 162 | continue 163 | elif self.ch == '}': 164 | self.depth -= 1 165 | self.next_chr() 166 | if k is not None: 167 | o[idx] = k 168 | if not numeric_keys and len([ key for key in o if isinstance(key, (str, unicode, float, bool, tuple))]) == 0: 169 | ar = [] 170 | for key in o: 171 | ar.insert(key, o[key]) 172 | o = ar 173 | return o #or here 174 | else: 175 | if self.ch == ',': 176 | self.next_chr() 177 | continue 178 | else: 179 | k = self.value() 180 | if self.ch == ']': 181 | numeric_keys = True 182 | self.next_chr() 183 | self.white() 184 | ch = self.ch 185 | if ch in ('=', ','): 186 | self.next_chr() 187 | self.white() 188 | if ch == '=': 189 | o[k] = self.value() 190 | else: 191 | o[idx] = k 192 | idx += 1 193 | k = None 194 | raise Exception(ERRORS['unexp_end_table']) #Bad exit here 195 | 196 | words = {'true': True, 'false': False, 'nil': None} 197 | def word(self): 198 | s = '' 199 | if self.ch != '\n': 200 | s = self.ch 201 | self.next_chr() 202 | while self.ch is not None and self.alnum.match(self.ch) and s not in self.words: 203 | s += self.ch 204 | self.next_chr() 205 | return self.words.get(s, s) 206 | 207 | def number(self): 208 | def next_digit(err): 209 | n = self.ch 210 | self.next_chr() 211 | if not self.ch or not self.ch.isdigit(): 212 | raise ParseError(err) 213 | return n 214 | n = '' 215 | try: 216 | if self.ch == '-': 217 | n += next_digit(ERRORS['mfnumber_minus']) 218 | n += self.digit() 219 | if n == '0' and self.ch in ['x', 'X']: 220 | n += self.ch 221 | self.next_chr() 222 | n += self.hex() 223 | else: 224 | if self.ch and self.ch == '.': 225 | n += next_digit(ERRORS['mfnumber_dec_point']) 226 | n += self.digit() 227 | if self.ch and self.ch in ['e', 'E']: 228 | n += self.ch 229 | self.next_chr() 230 | if not self.ch or self.ch not in ('+', '-'): 231 | raise ParseError(ERRORS['mfnumber_sci']) 232 | n += next_digit(ERRORS['mfnumber_sci']) 233 | n += self.digit() 234 | except ParseError: 235 | t, e = sys.exc_info()[:2] 236 | print(e) 237 | return 0 238 | try: 239 | return int(n, 0) 240 | except: 241 | pass 242 | return float(n) 243 | 244 | def digit(self): 245 | n = '' 246 | while self.ch and self.ch.isdigit(): 247 | n += self.ch 248 | self.next_chr() 249 | return n 250 | 251 | def hex(self): 252 | n = '' 253 | while self.ch and \ 254 | (self.ch in 'ABCDEFabcdef' or self.ch.isdigit()): 255 | n += self.ch 256 | self.next_chr() 257 | return n 258 | 259 | 260 | slpp = SLPP() 261 | 262 | __all__ = ['slpp'] 263 | -------------------------------------------------------------------------------- /slpp/slpp-c4d7f69af338f973c0ef21a9a06a145936367229/tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from slpp import slpp as lua 5 | 6 | """ 7 | Tests for slpp 8 | """ 9 | 10 | 11 | def is_iterator(obj): 12 | """ 13 | >>> assert is_iterator(list()) is True 14 | >>> assert is_iterator(int) is False 15 | """ 16 | if isinstance(obj, (list, tuple)): 17 | return True 18 | try: 19 | iter(obj) 20 | return True 21 | except TypeError: 22 | return False 23 | 24 | 25 | def differ(value, origin): 26 | """ 27 | Same: 28 | >>> differ(1, 1) 29 | >>> differ([2, 3], [2, 3]) 30 | >>> differ({'1': 3, '4': '6'}, {'4': '6', '1': 3}) 31 | >>> differ('4', '4') 32 | 33 | Different: 34 | >>> differ(1, 2) 35 | Traceback (most recent call last): 36 | ... 37 | AssertionError: 1 not match original: 2. 38 | >>> differ([2, 3], [3, 2]) 39 | Traceback (most recent call last): 40 | ... 41 | AssertionError: 2 not match original: 3. 42 | >>> differ({'6': 4, '3': '1'}, {'4': '6', '1': 3}) 43 | Traceback (most recent call last): 44 | ... 45 | AssertionError: {'3': '1', '6': 4} not match original: {'1': 3, '4': '6'}; 46 | Key: 1, item: 3 47 | >>> differ('4', 'no') 48 | Traceback (most recent call last): 49 | ... 50 | AssertionError: 4 not match original: no. 51 | """ 52 | 53 | if type(value) is not type(origin): 54 | raise AssertionError('Types does not match: {0}, {1}'.format(type(value), type(origin))) 55 | 56 | if isinstance(origin, dict): 57 | for key, item in origin.items(): 58 | try: 59 | differ(value[key], item) 60 | except KeyError: 61 | raise AssertionError('''{0} not match original: {1}; 62 | Key: {2}, item: {3}'''.format(value, origin, key, item)) 63 | return 64 | 65 | if isinstance(origin, basestring): 66 | assert value == origin, '{0} not match original: {1}.'.format(value, origin) 67 | return 68 | 69 | if is_iterator(origin): 70 | for i in range(0, len(origin)): 71 | try: 72 | differ(value[i], origin[i]) 73 | except IndexError: 74 | raise AssertionError( 75 | '{0} not match original: {1}. Item {2} not found'.format( 76 | response, origin, origin[i])) 77 | except Exception, e: 78 | raise e 79 | return 80 | 81 | assert value == origin, '{0} not match original: {1}.'.format(value, origin) 82 | 83 | 84 | 85 | 86 | def number_test(): 87 | """ 88 | Integer and float: 89 | >>> assert lua.decode('3') == 3 90 | >>> assert lua.decode('4.1') == 4.1 91 | 92 | Negative float: 93 | >>> assert lua.decode('-0.45') == -0.45 94 | 95 | Scientific: 96 | >>> assert lua.decode('3e-7') == 3e-7 97 | >>> assert lua.decode('-3.23e+17') == -3.23e+17 98 | 99 | Hex: 100 | >>> assert lua.decode('0x3a') == 0x3a 101 | 102 | #4 103 | >>> differ(lua.decode('''{ \ 104 | ID = 0x74fa4cae, \ 105 | Version = 0x07c2, \ 106 | Manufacturer = 0x21544948 \ 107 | }'''), { \ 108 | 'ID': 0x74fa4cae, \ 109 | 'Version': 0x07c2, \ 110 | 'Manufacturer': 0x21544948 \ 111 | }) 112 | """ 113 | pass 114 | 115 | 116 | def test_bool(): 117 | """ 118 | >>> assert lua.decode('false') == False 119 | >>> assert lua.decode('true') == True 120 | 121 | >>> assert lua.encode(False) == 'false' 122 | >>> assert lua.encode(True) == 'true' 123 | """ 124 | pass 125 | 126 | 127 | def test_nil(): 128 | """ 129 | >>> assert lua.decode('nil') == None 130 | >>> assert lua.encode(None) == 'nil' 131 | """ 132 | pass 133 | 134 | 135 | def table_test(): 136 | """ 137 | Bracketed string key: 138 | >>> assert lua.decode('{[10] = 1}') == {10: 1} 139 | 140 | Void table: 141 | >>> assert lua.decode('{nil}') == [] 142 | 143 | Values-only table: 144 | >>> assert lua.decode('{"10"}') == ["10"] 145 | 146 | Last zero 147 | >>> assert lua.decode('{0, 1, 0}') == [0,1,0] 148 | """ 149 | pass 150 | 151 | def string_test(): 152 | r""" 153 | Escape test: 154 | >>> assert lua.decode(r"'test\'s string'") == "test's string" 155 | 156 | Add escaping on encode: 157 | >>> assert lua.encode({'a': 'func("call()");'}) == '{\n\ta = "func(\\"call()\\");"\n}' 158 | """ 159 | pass 160 | 161 | def basic_test(): 162 | """ 163 | No data loss: 164 | 165 | >>> data = '{ array = { 65, 23, 5 }, dict = { string = "value", array = { 3, 6, 4}, mixed = { 43, 54.3, false, string = "value", 9 } } }' 166 | >>> d = lua.decode(data) 167 | >>> differ(d, lua.decode(lua.encode(d))) 168 | """ 169 | pass 170 | 171 | 172 | def unicode_test(): 173 | ur""" 174 | >>> assert lua.encode(u'Привет') == '"\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82"' 175 | >>> assert lua.encode({'s': u'Привет'}) == '{\n\ts = "Привет"\n}' 176 | """ 177 | pass 178 | 179 | 180 | if __name__ == '__main__': 181 | import doctest 182 | doctest.testmod() 183 | -------------------------------------------------------------------------------- /slpp/slpp.py: -------------------------------------------------------------------------------- 1 | import re 2 | import sys 3 | 4 | ERRORS = { 5 | 'unexp_end_string': u'Unexpected end of string while parsing Lua string.', 6 | 'unexp_end_table': u'Unexpected end of table while parsing Lua string.', 7 | 'mfnumber_minus': u'Malformed number (no digits after initial minus).', 8 | 'mfnumber_dec_point': u'Malformed number (no digits after decimal point).', 9 | 'mfnumber_sci': u'Malformed number (bad scientific format).', 10 | } 11 | # Python 3 renamed the unicode type to str, 12 | # the old str type has been replaced by bytes 13 | try: 14 | basestring 15 | except NameError: 16 | basestring = str 17 | 18 | try: 19 | unicode 20 | except NameError: 21 | unicode = str 22 | 23 | class ParseError(Exception): 24 | pass 25 | 26 | 27 | class SLPP(object): 28 | 29 | def __init__(self): 30 | self.text = '' 31 | self.ch = '' 32 | self.at = 0 33 | self.len = 0 34 | self.depth = 0 35 | self.space = re.compile('\s', re.M) 36 | self.alnum = re.compile('\w', re.M) 37 | self.newline = '\n' 38 | self.tab = '\t' 39 | 40 | def decode(self, text): 41 | if not text or not isinstance(text, basestring): 42 | return 43 | #FIXME: only short comments removed 44 | reg = re.compile('--.*$', re.M) 45 | text = reg.sub('', text, 0) 46 | self.text = text 47 | self.at, self.ch, self.depth = 0, '', 0 48 | self.len = len(text) 49 | self.next_chr() 50 | result = self.value() 51 | return result 52 | 53 | def encode(self, obj): 54 | self.depth = 0 55 | return self.__encode(obj) 56 | 57 | def __encode(self, obj): 58 | s = '' 59 | tab = self.tab 60 | newline = self.newline 61 | tp = type(obj) 62 | if isinstance(obj, str): 63 | s += '"%s"' % obj.replace(r'"', r'\"') 64 | if isinstance(obj, unicode): 65 | s += '"%s"' % obj.encode('utf-8').replace(r'"', r'\"') 66 | elif tp in [int, float, long, complex]: 67 | s += str(obj) 68 | elif tp is bool: 69 | s += str(obj).lower() 70 | elif obj is None: 71 | s += 'nil' 72 | elif tp in [list, tuple, dict]: 73 | self.depth += 1 74 | if len(obj) == 0 or ( tp is not dict and len(filter( 75 | lambda x: type(x) in (int, float, long) \ 76 | or (isinstance(x, basestring) and len(x) < 10), obj 77 | )) == len(obj) ): 78 | newline = tab = '' 79 | dp = tab * self.depth 80 | s += "%s{%s" % (tab * (self.depth - 2), newline) 81 | if tp is dict: 82 | contents = [] 83 | for k, v in obj.iteritems(): 84 | if type(k) is int: 85 | contents.append(self.__encode(v)) 86 | else: 87 | contents.append(dp + '%s = %s' % (k, self.__encode(v))) 88 | s += (',%s' % newline).join(contents) 89 | 90 | else: 91 | s += (',%s' % newline).join( 92 | [dp + self.__encode(el) for el in obj]) 93 | self.depth -= 1 94 | s += "%s%s}" % (newline, tab * self.depth) 95 | return s 96 | 97 | def white(self): 98 | while self.ch: 99 | if self.space.match(self.ch): 100 | self.next_chr() 101 | else: 102 | break 103 | 104 | def next_chr(self): 105 | if self.at >= self.len: 106 | self.ch = None 107 | return None 108 | self.ch = self.text[self.at] 109 | self.at += 1 110 | return True 111 | 112 | def value(self): 113 | self.white() 114 | if not self.ch: 115 | return 116 | if self.ch == '{': 117 | return self.object() 118 | if self.ch == "[": 119 | self.next_chr() 120 | if self.ch in ['"', "'", '[']: 121 | return self.string(self.ch) 122 | if self.ch.isdigit() or self.ch == '-': 123 | return self.number() 124 | return self.word() 125 | 126 | def string(self, end=None): 127 | s = '' 128 | start = self.ch 129 | if end == '[': 130 | end = ']' 131 | if start in ['"', "'", '[']: 132 | while self.next_chr(): 133 | if self.ch == end: 134 | self.next_chr() 135 | if start != "[" or self.ch == ']': 136 | return s 137 | if self.ch == '\\' and start == end: 138 | self.next_chr() 139 | if self.ch != end: 140 | s += '\\' 141 | s += self.ch 142 | raise Exception(ERRORS['unexp_end_string']) 143 | 144 | def object(self): 145 | o = {} 146 | k = None 147 | idx = 0 148 | numeric_keys = False 149 | self.depth += 1 150 | self.next_chr() 151 | self.white() 152 | if self.ch and self.ch == '}': 153 | self.depth -= 1 154 | self.next_chr() 155 | return o #Exit here 156 | else: 157 | while self.ch: 158 | self.white() 159 | if self.ch == '{': 160 | o[idx] = self.object() 161 | idx += 1 162 | continue 163 | elif self.ch == '}': 164 | self.depth -= 1 165 | self.next_chr() 166 | if k is not None: 167 | o[idx] = k 168 | if not numeric_keys and len([ key for key in o if isinstance(key, (str, unicode, float, bool, tuple))]) == 0: 169 | ar = [] 170 | for key in o: 171 | ar.insert(key, o[key]) 172 | o = ar 173 | return o #or here 174 | else: 175 | if self.ch == ',': 176 | self.next_chr() 177 | continue 178 | else: 179 | k = self.value() 180 | if self.ch == ']': 181 | numeric_keys = True 182 | self.next_chr() 183 | self.white() 184 | ch = self.ch 185 | if ch in ('=', ','): 186 | self.next_chr() 187 | self.white() 188 | if ch == '=': 189 | o[k] = self.value() 190 | else: 191 | o[idx] = k 192 | idx += 1 193 | k = None 194 | raise Exception(ERRORS['unexp_end_table']) #Bad exit here 195 | 196 | words = {'true': True, 'false': False, 'nil': None} 197 | def word(self): 198 | s = '' 199 | if self.ch != '\n': 200 | s = self.ch 201 | self.next_chr() 202 | while self.ch is not None and self.alnum.match(self.ch) and s not in self.words: 203 | s += self.ch 204 | self.next_chr() 205 | return self.words.get(s, s) 206 | 207 | def number(self): 208 | def next_digit(err): 209 | n = self.ch 210 | self.next_chr() 211 | if not self.ch or not self.ch.isdigit(): 212 | raise ParseError(err) 213 | return n 214 | n = '' 215 | try: 216 | if self.ch == '-': 217 | n += next_digit(ERRORS['mfnumber_minus']) 218 | n += self.digit() 219 | if n == '0' and self.ch in ['x', 'X']: 220 | n += self.ch 221 | self.next_chr() 222 | n += self.hex() 223 | else: 224 | if self.ch and self.ch == '.': 225 | n += next_digit(ERRORS['mfnumber_dec_point']) 226 | n += self.digit() 227 | if self.ch and self.ch in ['e', 'E']: 228 | n += self.ch 229 | self.next_chr() 230 | if not self.ch or self.ch not in ('+', '-'): 231 | raise ParseError(ERRORS['mfnumber_sci']) 232 | n += next_digit(ERRORS['mfnumber_sci']) 233 | n += self.digit() 234 | except ParseError: 235 | t, e = sys.exc_info()[:2] 236 | print(e) 237 | return 0 238 | try: 239 | return int(n, 0) 240 | except: 241 | pass 242 | return float(n) 243 | 244 | def digit(self): 245 | n = '' 246 | while self.ch and self.ch.isdigit(): 247 | n += self.ch 248 | self.next_chr() 249 | return n 250 | 251 | def hex(self): 252 | n = '' 253 | while self.ch and \ 254 | (self.ch in 'ABCDEFabcdef' or self.ch.isdigit()): 255 | n += self.ch 256 | self.next_chr() 257 | return n 258 | 259 | 260 | slpp = SLPP() 261 | 262 | __all__ = ['slpp'] 263 | -------------------------------------------------------------------------------- /slpp/tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from slpp import slpp as lua 5 | 6 | """ 7 | Tests for slpp 8 | """ 9 | 10 | 11 | def is_iterator(obj): 12 | """ 13 | >>> assert is_iterator(list()) is True 14 | >>> assert is_iterator(int) is False 15 | """ 16 | if isinstance(obj, (list, tuple)): 17 | return True 18 | try: 19 | iter(obj) 20 | return True 21 | except TypeError: 22 | return False 23 | 24 | 25 | def differ(value, origin): 26 | """ 27 | Same: 28 | >>> differ(1, 1) 29 | >>> differ([2, 3], [2, 3]) 30 | >>> differ({'1': 3, '4': '6'}, {'4': '6', '1': 3}) 31 | >>> differ('4', '4') 32 | 33 | Different: 34 | >>> differ(1, 2) 35 | Traceback (most recent call last): 36 | ... 37 | AssertionError: 1 not match original: 2. 38 | >>> differ([2, 3], [3, 2]) 39 | Traceback (most recent call last): 40 | ... 41 | AssertionError: 2 not match original: 3. 42 | >>> differ({'6': 4, '3': '1'}, {'4': '6', '1': 3}) 43 | Traceback (most recent call last): 44 | ... 45 | AssertionError: {'3': '1', '6': 4} not match original: {'1': 3, '4': '6'}; 46 | Key: 1, item: 3 47 | >>> differ('4', 'no') 48 | Traceback (most recent call last): 49 | ... 50 | AssertionError: 4 not match original: no. 51 | """ 52 | 53 | if type(value) is not type(origin): 54 | raise AssertionError('Types does not match: {0}, {1}'.format(type(value), type(origin))) 55 | 56 | if isinstance(origin, dict): 57 | for key, item in origin.items(): 58 | try: 59 | differ(value[key], item) 60 | except KeyError: 61 | raise AssertionError('''{0} not match original: {1}; 62 | Key: {2}, item: {3}'''.format(value, origin, key, item)) 63 | return 64 | 65 | if isinstance(origin, basestring): 66 | assert value == origin, '{0} not match original: {1}.'.format(value, origin) 67 | return 68 | 69 | if is_iterator(origin): 70 | for i in range(0, len(origin)): 71 | try: 72 | differ(value[i], origin[i]) 73 | except IndexError: 74 | raise AssertionError( 75 | '{0} not match original: {1}. Item {2} not found'.format( 76 | response, origin, origin[i])) 77 | except Exception, e: 78 | raise e 79 | return 80 | 81 | assert value == origin, '{0} not match original: {1}.'.format(value, origin) 82 | 83 | 84 | 85 | 86 | def number_test(): 87 | """ 88 | Integer and float: 89 | >>> assert lua.decode('3') == 3 90 | >>> assert lua.decode('4.1') == 4.1 91 | 92 | Negative float: 93 | >>> assert lua.decode('-0.45') == -0.45 94 | 95 | Scientific: 96 | >>> assert lua.decode('3e-7') == 3e-7 97 | >>> assert lua.decode('-3.23e+17') == -3.23e+17 98 | 99 | Hex: 100 | >>> assert lua.decode('0x3a') == 0x3a 101 | 102 | #4 103 | >>> differ(lua.decode('''{ \ 104 | ID = 0x74fa4cae, \ 105 | Version = 0x07c2, \ 106 | Manufacturer = 0x21544948 \ 107 | }'''), { \ 108 | 'ID': 0x74fa4cae, \ 109 | 'Version': 0x07c2, \ 110 | 'Manufacturer': 0x21544948 \ 111 | }) 112 | """ 113 | pass 114 | 115 | 116 | def test_bool(): 117 | """ 118 | >>> assert lua.decode('false') == False 119 | >>> assert lua.decode('true') == True 120 | 121 | >>> assert lua.encode(False) == 'false' 122 | >>> assert lua.encode(True) == 'true' 123 | """ 124 | pass 125 | 126 | 127 | def test_nil(): 128 | """ 129 | >>> assert lua.decode('nil') == None 130 | >>> assert lua.encode(None) == 'nil' 131 | """ 132 | pass 133 | 134 | 135 | def table_test(): 136 | """ 137 | Bracketed string key: 138 | >>> assert lua.decode('{[10] = 1}') == {10: 1} 139 | 140 | Void table: 141 | >>> assert lua.decode('{nil}') == [] 142 | 143 | Values-only table: 144 | >>> assert lua.decode('{"10"}') == ["10"] 145 | 146 | Last zero 147 | >>> assert lua.decode('{0, 1, 0}') == [0,1,0] 148 | """ 149 | pass 150 | 151 | def string_test(): 152 | r""" 153 | Escape test: 154 | >>> assert lua.decode(r"'test\'s string'") == "test's string" 155 | 156 | Add escaping on encode: 157 | >>> assert lua.encode({'a': 'func("call()");'}) == '{\n\ta = "func(\\"call()\\");"\n}' 158 | """ 159 | pass 160 | 161 | def basic_test(): 162 | """ 163 | No data loss: 164 | 165 | >>> data = '{ array = { 65, 23, 5 }, dict = { string = "value", array = { 3, 6, 4}, mixed = { 43, 54.3, false, string = "value", 9 } } }' 166 | >>> d = lua.decode(data) 167 | >>> differ(d, lua.decode(lua.encode(d))) 168 | """ 169 | pass 170 | 171 | 172 | def unicode_test(): 173 | ur""" 174 | >>> assert lua.encode(u'Привет') == '"\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82"' 175 | >>> assert lua.encode({'s': u'Привет'}) == '{\n\ts = "Привет"\n}' 176 | """ 177 | pass 178 | 179 | 180 | if __name__ == '__main__': 181 | import doctest 182 | doctest.testmod() 183 | -------------------------------------------------------------------------------- /writer.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | import json 7 | from xml.dom.minidom import Document 8 | 9 | try: 10 | basestring 11 | except NameError: 12 | basestring = str 13 | 14 | try: 15 | long 16 | except NameError: 17 | long = int 18 | 19 | # python3中没有unicode了 20 | try: 21 | unicode 22 | except NameError: 23 | unicode = str 24 | 25 | # 加上不确定的层级缩进,60比较合适 26 | BASE_LENGTH = 60 27 | BASE_INDENT = " " 28 | INDENT_LIST = {} 29 | 30 | class Writer(object): 31 | def __init__(self,doc_name,sheet_name, base_name, keys_list, comment_text): 32 | # 文件名包含中文则需要转unicode 33 | #self.doc_name = unicode(doc_name, "utf-8") 34 | self.doc_name = doc_name 35 | self.sheet_name = sheet_name 36 | self.base_name = base_name 37 | self.keys_list = keys_list 38 | self.comment_text = comment_text 39 | 40 | # 文件后缀 41 | def suffix(self): 42 | pass 43 | # 文件内容 44 | def context(self,ctx): 45 | pass 46 | # 注释开始 47 | def comment_start(self): 48 | pass 49 | # 注释结束 50 | def comment_end(self): 51 | pass 52 | # 文件注释(千万不要加时间,影响svn) 53 | def comment(self): 54 | comment = [] 55 | return "".join( comment ) 56 | 57 | -------------------------------------------------------------------------------- /writer_elixir.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from writer import * 7 | 8 | try: 9 | basestring 10 | except NameError: 11 | basestring = str 12 | 13 | try: 14 | long 15 | except NameError: 16 | long = int 17 | 18 | # python3中没有unicode了 19 | try: 20 | unicode 21 | except NameError: 22 | unicode = str 23 | 24 | # 加上不确定的层级缩进,60比较合适 25 | BASE_LENGTH = 60 26 | BASE_INDENT = " " 27 | INDENT_LIST = {} 28 | 29 | class ElixirWriter(Writer): 30 | # 文件后缀 31 | def suffix(self): 32 | return ".ex" 33 | 34 | def comment(self): 35 | comment = [ 36 | '## Automatic generation from -->>' 37 | '\n## excel file name: ' + self.doc_name + 38 | '\n## excel sheet name: ' + self.sheet_name, 39 | '\ndefmodule ' + self.base_name.title() + ' do\n\n' 40 | ] 41 | 42 | return "\n".join( comment ) 43 | 44 | # 获取缩进字符串 45 | def indent_ctx( self,indent ): 46 | if indent <= 0: return "" 47 | 48 | if indent not in INDENT_LIST: 49 | INDENT_LIST[indent] = "" 50 | else: 51 | ctx = BASE_INDENT*indent 52 | INDENT_LIST[indent] = ctx 53 | 54 | return INDENT_LIST[indent] 55 | 56 | def dict_to_text(self, value, indent) : 57 | dict_text_list = [] 58 | for k in ( value ) : 59 | k_indent,lk = self.to_target_lang( k,indent ) 60 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 61 | 62 | comment = self.comment_text[k] 63 | 64 | val_type = type( lk ) 65 | if str == val_type : 66 | if lk.replace(".", "").isdigit() : 67 | lk.replace("\"", "") 68 | else : 69 | lk = ':' + lk.replace("\"", "") 70 | 71 | key = "".join( [" def get(",lk,") do\n"] ) 72 | 73 | val = "".join( [" ## ", comment, "\n", key, " ", lv, "\n end\n\n"] ) 74 | 75 | dict_text_list.append( val ) 76 | 77 | dict_str = "".join( dict_text_list ) 78 | dict_str = dict_str + " def get(_) do\n :undefined\n end\n\nend" 79 | return False, dict_str 80 | 81 | def list_to_text(self, value, indent): 82 | list_text_list = [] 83 | # 先定义 struct 84 | struct_text_list = [] 85 | struct_len = len(self.comment_text) 86 | tem_count = 0 87 | for k in self.comment_text : 88 | tem_count += 1 89 | comment = self.comment_text[k] 90 | k_indent,lk = self.to_target_lang( k,indent ) 91 | val_type = type( lk ) 92 | if str == val_type : 93 | if lk.replace(".", "").isdigit() : 94 | lk.replace("\"", "") 95 | else : 96 | lk = ':' + lk.replace("\"", "") 97 | 98 | if tem_count != struct_len : 99 | lk = lk + ',' 100 | else : 101 | lk = lk 102 | 103 | if None == comment : 104 | comment = "" 105 | val = "".join( [lk.ljust(20, " "), "\t## ", comment, "\n"] ) 106 | 107 | struct_text_list.append( val ) 108 | 109 | struct_str = " ".join( struct_text_list ) 110 | end_str = " defstruct [\n " + struct_str + " ]\n\n" 111 | 112 | list_text_list.append(end_str) 113 | 114 | all_key_list = [] 115 | # 生成 get() 函数 116 | for i, onedict in enumerate( value ) : 117 | # 生成对应的 key 118 | key_list = [] 119 | for k in ( onedict ) : 120 | if None != self.keys_list.get(k, None) : 121 | is_indent,lv = self.to_target_lang( onedict[k],indent + 1 ) 122 | key_list.append(lv) 123 | all_key_list.append(key_list) 124 | 125 | tem = ", ".join( key_list ) 126 | 127 | key = "".join( [" def get(",tem,") do\n %", self.base_name.title(), "{\n "] ) 128 | 129 | # 生成对应的value 130 | value_list = [] 131 | onedict_len = len(onedict) 132 | tem_count = 0 133 | for k in ( onedict ) : 134 | tem_count += 1 135 | k_indent,lk = self.to_target_lang( k,indent ) 136 | is_indent,lv = self.to_target_lang( onedict[k],indent + 1 ) 137 | 138 | val_type = type( lk ) 139 | if str == val_type : 140 | if lk.replace(".", "").isdigit() : 141 | lk.replace("\"", "") 142 | else : 143 | lk = ':' + lk.replace("\"", "") 144 | 145 | if tem_count != onedict_len : 146 | oneval = "".join( [lk, " => ", lv , ",\n"] ) 147 | value_list.append( oneval ) 148 | else : 149 | oneval = "".join( [lk, " => ", lv , "\n"] ) 150 | value_list.append( oneval ) 151 | 152 | value_list_str = " ".join(value_list) 153 | end_str = "".join( [key, value_list_str, " }\n end\n\n"] ) 154 | 155 | list_text_list.append( end_str ) 156 | 157 | underline_list = [] 158 | for i in self.keys_list : 159 | underline_list.append('_') 160 | 161 | end_str = ", ".join(underline_list) 162 | no_match_str = " def get(" + end_str + ") do\n :undefined\n end\n\n" 163 | 164 | list_text_list.append(no_match_str) 165 | 166 | # 生成 get_all() 函数 167 | get_all_fun = [] 168 | allkey_len = len(all_key_list) 169 | tem_count = 0 170 | for i, ival in enumerate(all_key_list) : 171 | tem_count += 1 172 | if tem_count != allkey_len : 173 | oneval = '{' + ", ".join(ival) + '},\n' 174 | get_all_fun.append(oneval) 175 | else : 176 | oneval = '{' + ", ".join(ival) + '}\n' 177 | get_all_fun.append(oneval) 178 | 179 | value_list_str = " ".join(get_all_fun) 180 | start_str = ' def get_all() do\n [\n ' 181 | end_str = "".join( [start_str, value_list_str, " ]\n end\n\n"] ) 182 | 183 | list_text_list.append( end_str ) 184 | 185 | # 生成 get_list() 函数 186 | get_list_fun = [] 187 | keys_len = len(self.keys_list) 188 | for key in self.keys_list : 189 | keyindex = self.keys_list[key] 190 | if keyindex == 1 : 191 | list_text_list.append( ' def get_list() do\n get_all()\n end\n\n') 192 | elif keyindex <= keys_len : 193 | get_tem_dict = {} 194 | underline_list = [] 195 | for i, ival in enumerate(all_key_list) : 196 | key_tem_list = [] 197 | j = 0 198 | underline_list = [] 199 | while j < keyindex - 1 : 200 | key_tem_list.append(ival[j]) 201 | underline_list.append('_') 202 | j += 1 203 | 204 | keystr = '(' + ", ".join(key_tem_list) + ')' 205 | if None != get_tem_dict.get(keystr, None) : 206 | oldlist = get_tem_dict[keystr] 207 | oldlist.append(ival) 208 | get_tem_dict[keystr] = oldlist 209 | else : 210 | get_tem_dict[keystr] = [ival] 211 | 212 | for onekey in get_tem_dict : 213 | value_tem_list = [] 214 | valuelist = get_tem_dict[onekey] 215 | 216 | value_len = len(valuelist) 217 | tem_count = 0 218 | for l, lval in enumerate(valuelist) : 219 | tem_count += 1 220 | if tem_count != value_len : 221 | oneval = '{' + ", ".join(lval) + '},\n' 222 | value_tem_list.append(oneval) 223 | else : 224 | oneval = '{' + ", ".join(lval) + '}\n' 225 | value_tem_list.append(oneval) 226 | start_str = ' def get_list' + onekey + ' do\n [\n ' 227 | end_str = "".join( [start_str, " ".join(value_tem_list), " ]\n end\n\n"] ) 228 | get_list_fun.append(end_str) 229 | no_match_str = "".join(' def get_list(' + ", ".join(underline_list) + ') do\n []\n end\n\n') 230 | get_list_fun.append(no_match_str) 231 | 232 | 233 | value_list_str = "".join(get_list_fun) + 'end' 234 | list_text_list.append( value_list_str ) 235 | dict_str = "".join( list_text_list ) 236 | 237 | return False, dict_str 238 | 239 | # 转换为文本数据 之前解析出来的excel数据存放方式存在LIST(array格式)和DICT(object格式)两种类型 240 | def to_text(self,value,indent): 241 | val_type = type( value ) 242 | if dict == val_type : 243 | return self.dict_to_text(value, indent) 244 | else : 245 | return self.list_to_text(value, indent) 246 | 247 | # python的dict转换为elixir的map类型 248 | def dict_to_elixir(self,value,indent): 249 | dict_ctx_list = [] 250 | 251 | for k in ( value ) : 252 | k_indent,lk = self.to_target_lang( k,indent ) 253 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 254 | 255 | val_type = type( lk ) 256 | if str == val_type : 257 | if lk.replace(".", "").isdigit() : 258 | lk.replace("\"", "") 259 | else : 260 | lk = ':' + lk.replace("\"", "") 261 | 262 | key = "".join( [lk," => "] ) 263 | val = "".join( [key, lv] ) 264 | dict_ctx_list.append(val) 265 | 266 | dict_str = ", ".join( dict_ctx_list ) 267 | return False,"".join( ["%{",dict_str,"}"] ) 268 | 269 | # python的list转换为elixir的list类型 270 | def list_to_elixir(self,value,indent): 271 | list_ctx_list = [] 272 | for v in value : 273 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 274 | list_ctx_list.append( lv ) 275 | 276 | 277 | list_str = ", ".join( list_ctx_list ) 278 | return False,"".join( ["[",list_str,"]"] ) 279 | 280 | # python的tuple转换为elixir的tuple类型 281 | def tuple_to_elixir(self,value,indent): 282 | tuple_ctx_list = [] 283 | 284 | for v in value : 285 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 286 | tuple_ctx_list.append( lv ) 287 | 288 | # 返回 {a,b,c}这种不换行的格式 289 | list_str = ", ".join( tuple_ctx_list ) 290 | return False,"".join( ["{",list_str,"}"] ) 291 | 292 | 293 | # 变量转换到目标语言字符串 294 | def to_target_lang(self,value,indent): 295 | val_type = type( value ) 296 | if int == val_type : 297 | return False,str( value ) 298 | elif long == val_type : 299 | return False,str( value ) 300 | elif float == val_type : 301 | # 1001.0 -->> 001 去除多余小数点 302 | if int( value ) == value : 303 | return False,str( int(value) ) 304 | return False,str( value ) 305 | elif str == val_type or unicode == val_type: 306 | return False, "".join(["\"",value,"\""]) 307 | elif tuple == val_type : 308 | return self.tuple_to_elixir(value,indent) 309 | elif dict == val_type : 310 | return self.dict_to_elixir(value,indent) 311 | elif list == val_type : 312 | return self.list_to_elixir(value,indent) 313 | else : 314 | raise Exception( "invalid type",val_type ) 315 | 316 | #文件内容 317 | def context(self,ctx): 318 | is_indent,str_ctx = self.to_text( ctx,0 ) 319 | return "".join( [self.comment(),"",str_ctx] ) 320 | -------------------------------------------------------------------------------- /writer_erlang_erl.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from writer import * 7 | 8 | try: 9 | basestring 10 | except NameError: 11 | basestring = str 12 | 13 | try: 14 | long 15 | except NameError: 16 | long = int 17 | 18 | # python3中没有unicode了 19 | try: 20 | unicode 21 | except NameError: 22 | unicode = str 23 | 24 | # 加上不确定的层级缩进,60比较合适 25 | BASE_LENGTH = 60 26 | BASE_INDENT = " " 27 | INDENT_LIST = {} 28 | 29 | class ErlangerlWriter(Writer): 30 | # 文件后缀 31 | def suffix(self): 32 | return ".erl" 33 | 34 | def comment(self): 35 | comment = [ 36 | '%% Automatic generation from -->>' 37 | '\n%% excel file name : ' + self.doc_name + 38 | '\n%% excel sheet name : ' + self.sheet_name, 39 | '\n-module(' + self.base_name + ').', 40 | '\n' 41 | ] 42 | 43 | return "\n".join( comment ) 44 | 45 | # 获取缩进字符串 46 | def indent_ctx( self,indent ): 47 | if indent <= 0: return "" 48 | 49 | if indent not in INDENT_LIST: 50 | INDENT_LIST[indent] = "" 51 | else: 52 | ctx = BASE_INDENT*indent 53 | INDENT_LIST[indent] = ctx 54 | 55 | return INDENT_LIST[indent] 56 | 57 | def dict_to_text(self, value, indent) : 58 | dict_text_list = [] 59 | dict_text_list.append("-compile(export_all).\n\n") 60 | for k in ( value ) : 61 | k_indent,lk = self.to_target_lang( k,indent ) 62 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 63 | 64 | comment = self.comment_text[k] 65 | 66 | val_type = type( lk ) 67 | if str == val_type : 68 | lk = lk.replace("\"", "\'") 69 | 70 | key = "".join( ["get(",lk,") ->\n"] ) 71 | 72 | val = "".join( ["%% ", comment, "\n", key, " ", lv, ";\n\n"] ) 73 | 74 | dict_text_list.append( val ) 75 | 76 | dict_str = "".join( dict_text_list ) 77 | dict_str = dict_str + "get(_) ->\n undefined." 78 | return False, dict_str 79 | 80 | def list_to_text(self, value, indent): 81 | list_text_list = [] 82 | val = "-include(\"" + self.base_name + ".hrl\").\n" + "-compile(export_all).\n\n" 83 | list_text_list.append(val) 84 | all_key_list = [] 85 | # 生成 get() 函数 86 | for i, onedict in enumerate( value ) : 87 | # 生成对应的 key 88 | key_list = [] 89 | for k in ( onedict ) : 90 | if None != self.keys_list.get(k, None) : 91 | is_indent,lv = self.to_target_lang( onedict[k],indent + 1 ) 92 | key_list.append(lv) 93 | all_key_list.append(key_list) 94 | 95 | tem = ", ".join( key_list ) 96 | 97 | key = "".join( ["get(",tem,") ->\n #", self.base_name, "{\n "] ) 98 | 99 | # 生成对应的value 100 | value_list = [] 101 | for k in ( onedict ) : 102 | k_indent,lk = self.to_target_lang( k,indent ) 103 | is_indent,lv = self.to_target_lang( onedict[k],indent + 1 ) 104 | 105 | val_type = type( lk ) 106 | if str == val_type : 107 | lk = lk.replace("\"", "\'") 108 | 109 | oneval = "".join( [lk, " = ", lv , "\n"] ) 110 | 111 | value_list.append( oneval ) 112 | 113 | value_list_str = " ,".join(value_list) 114 | end_str = "".join( [key, value_list_str, " };\n\n"] ) 115 | 116 | list_text_list.append( end_str ) 117 | 118 | underline_list = [] 119 | for i in self.keys_list : 120 | underline_list.append('_') 121 | 122 | end_str = ", ".join(underline_list) 123 | no_match_str = "get(" + end_str + ") ->\n undefined.\n\n" 124 | 125 | list_text_list.append(no_match_str) 126 | 127 | # 生成 get_all() 函数 128 | get_all_fun = [] 129 | for i, ival in enumerate(all_key_list) : 130 | oneval = '{' + ", ".join(ival) + '}\n' 131 | get_all_fun.append(oneval) 132 | value_list_str = " ,".join(get_all_fun) 133 | start_str = 'get_all() ->\n [\n ' 134 | end_str = "".join( [start_str, value_list_str, " ].\n\n"] ) 135 | 136 | list_text_list.append( end_str ) 137 | 138 | # 生成 get_list() 函数 139 | get_list_fun = [] 140 | keys_len = len(self.keys_list) 141 | for key in self.keys_list : 142 | keyindex = self.keys_list[key] 143 | if keyindex == 1 : 144 | list_text_list.append( 'get_list() ->\n get_all().\n\n') 145 | elif keyindex <= keys_len : 146 | get_tem_dict = {} 147 | underline_list = [] 148 | for i, ival in enumerate(all_key_list) : 149 | key_tem_list = [] 150 | j = 0 151 | underline_list = [] 152 | while j < keyindex - 1 : 153 | key_tem_list.append(ival[j]) 154 | underline_list.append('_') 155 | j += 1 156 | 157 | keystr = '(' + ", ".join(key_tem_list) + ')' 158 | if None != get_tem_dict.get(keystr, None) : 159 | oldlist = get_tem_dict[keystr] 160 | oldlist.append(ival) 161 | get_tem_dict[keystr] = oldlist 162 | else : 163 | get_tem_dict[keystr] = [ival] 164 | 165 | for onekey in get_tem_dict : 166 | value_tem_list = [] 167 | valuelist = get_tem_dict[onekey] 168 | for l, lval in enumerate(valuelist) : 169 | oneval = '{' + ", ".join(lval) + '}\n' 170 | value_tem_list.append(oneval) 171 | start = 'get_list' + onekey + ' ->\n [\n ' 172 | val = "".join( [start, " ,".join(value_tem_list), " ];\n\n"] ) 173 | get_list_fun.append(val) 174 | no_match_str = "".join('get_list(' + ", ".join(underline_list) + ') ->\n [].\n\n') 175 | get_list_fun.append(no_match_str) 176 | 177 | 178 | value_list = "".join(get_list_fun) 179 | list_text_list.append( value_list ) 180 | dict_str = "".join( list_text_list ) 181 | 182 | return False, dict_str 183 | 184 | # 转换为文本数据 之前解析出来的excel数据存放方式存在LIST(array格式)和DICT(object格式)两种类型 185 | def to_text(self,value,indent): 186 | val_type = type( value ) 187 | if dict == val_type : 188 | return self.dict_to_text(value, indent) 189 | else : 190 | return self.list_to_text(value, indent) 191 | 192 | # python的dict转换为erlang的map类型 193 | def dict_to_erlang(self,value,indent): 194 | dict_ctx_list = [] 195 | 196 | for k in ( value ) : 197 | k_indent,lk = self.to_target_lang( k,indent ) 198 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 199 | 200 | val_type = type( lk ) 201 | if str == val_type : 202 | lk = lk.replace("\"", "\'") 203 | key = "".join( [lk," => "] ) 204 | val = "".join( [key, lv] ) 205 | dict_ctx_list.append(val) 206 | 207 | dict_str = ", ".join( dict_ctx_list ) 208 | return False,"".join( ["#{",dict_str,"}"] ) 209 | 210 | # python的list转换为erlang的list类型 211 | def list_to_erlang(self,value,indent): 212 | list_ctx_list = [] 213 | for v in value : 214 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 215 | list_ctx_list.append( lv ) 216 | 217 | list_str = ", ".join( list_ctx_list ) 218 | return False,"".join( ["[",list_str,"]"] ) 219 | 220 | # python的tuple转换为erlang的tuple类型 221 | def tuple_to_erlang(self,value,indent): 222 | tuple_ctx_list = [] 223 | 224 | for v in value : 225 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 226 | tuple_ctx_list.append( lv ) 227 | 228 | # 返回 {a,b,c}这种不换行的格式 229 | list_str = ", ".join( tuple_ctx_list ) 230 | return False,"".join( ["{",list_str,"}"] ) 231 | 232 | 233 | # 变量转换到目标语言的字符串 234 | def to_target_lang(self,value,indent): 235 | val_type = type( value ) 236 | if int == val_type : 237 | return False,str( value ) 238 | elif long == val_type : 239 | return False,str( value ) 240 | elif float == val_type : 241 | # 1001.0 -->> 001 去除多余小数点 242 | if int( value ) == value : 243 | return False,str( int(value) ) 244 | return False,str( value ) 245 | elif str == val_type or unicode == val_type: 246 | return False, "".join(["\"",value,"\""]) 247 | elif tuple == val_type : 248 | return self.tuple_to_erlang(value,indent) 249 | elif dict == val_type : 250 | return self.dict_to_erlang(value,indent) 251 | elif list == val_type : 252 | return self.list_to_erlang(value,indent) 253 | else : 254 | raise Exception( "invalid type",val_type ) 255 | 256 | #文件内容 257 | def context(self,ctx): 258 | is_indent,str_ctx = self.to_text( ctx,0 ) 259 | return "".join( [self.comment(),"",str_ctx] ) 260 | -------------------------------------------------------------------------------- /writer_erlang_hrl.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from writer import * 7 | 8 | try: 9 | basestring 10 | except NameError: 11 | basestring = str 12 | 13 | try: 14 | long 15 | except NameError: 16 | long = int 17 | 18 | # python3中没有unicode了 19 | try: 20 | unicode 21 | except NameError: 22 | unicode = str 23 | 24 | # 加上不确定的层级缩进,60比较合适 25 | BASE_LENGTH = 60 26 | BASE_INDENT = " " 27 | INDENT_LIST = {} 28 | 29 | class ErlanghrlWriter(Writer): 30 | # 文件后缀 31 | def suffix(self): 32 | return ".hrl" 33 | 34 | def comment(self): 35 | comment = [ 36 | '%% Automatic generation from -->>' 37 | '\n%% excel file name : ' + self.doc_name + 38 | '\n%% excel sheet name : ' + self.sheet_name, 39 | '\n-record(' + self.base_name + ', {\n ' 40 | ] 41 | 42 | return "\n".join( comment ) 43 | 44 | # 获取缩进字符串 45 | def indent_ctx( self,indent ) : 46 | if indent <= 0: return "" 47 | 48 | if indent not in INDENT_LIST : 49 | INDENT_LIST[indent] = "" 50 | else : 51 | ctx = BASE_INDENT*indent 52 | INDENT_LIST[indent] = ctx 53 | 54 | return INDENT_LIST[indent] 55 | 56 | def list_to_text(self, value, indent): 57 | list_text_list = [] 58 | for k in self.comment_text : 59 | comment = self.comment_text[k] 60 | k_indent,lk = self.to_target_lang( k,indent ) 61 | val_type = type( lk ) 62 | if str == val_type : 63 | lk = lk.replace("\"", "\'") 64 | if None == comment : 65 | comment = "" 66 | val = "".join( [lk.ljust(20, " "), "\t%% ", comment, "\n"] ) 67 | 68 | list_text_list.append( val ) 69 | 70 | list_str = " ,".join( list_text_list ) 71 | list_str = list_str + " })." 72 | return False, list_str 73 | 74 | # 转换为文本数据 之前解析出来的excel数据存放方式存在LIST(array格式)和DICT(object格式)两种类型 75 | def to_text(self,value,indent): 76 | val_type = type( value ) 77 | if list == val_type : 78 | return self.list_to_text(value, indent) 79 | else : 80 | return False, None 81 | 82 | # python的dict转换为erlang的map类型 83 | def dict_to_erlang(self,value,indent): 84 | dict_ctx_list = [] 85 | 86 | for k in ( value ) : 87 | k_indent,lk = self.to_target_lang( k,indent ) 88 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 89 | 90 | val_type = type( lk ) 91 | if str == val_type : 92 | lk = lk.replace("\"", "\'") 93 | key = "".join( [lk," => "] ) 94 | val = "".join( [key, lv] ) 95 | dict_ctx_list.append(val) 96 | 97 | dict_str = ",".join( dict_ctx_list ) 98 | return False,"".join( ["#{",dict_str,"}"] ) 99 | 100 | # python的list转换为erlang的list类型 101 | def list_to_erlang(self,value,indent): 102 | list_ctx_list = [] 103 | for v in value : 104 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 105 | list_ctx_list.append( lv ) 106 | 107 | 108 | list_str = ",".join( list_ctx_list ) 109 | return False,"".join( ["[",list_str,"]"] ) 110 | 111 | # python的tuple转换为erlang的tuple类型 112 | def tuple_to_erlang(self,value,indent): 113 | tuple_ctx_list = [] 114 | 115 | for v in value : 116 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 117 | tuple_ctx_list.append( lv ) 118 | 119 | # 返回 {a,b,c}这种不换行的格式 120 | list_str = ",".join( tuple_ctx_list ) 121 | return False,"".join( ["{",list_str,"}"] ) 122 | 123 | # 变量转换到目标语言的字符串 124 | def to_target_lang(self,value,indent): 125 | val_type = type( value ) 126 | if int == val_type : 127 | return False,str( value ) 128 | elif long == val_type : 129 | return False,str( value ) 130 | elif float == val_type : 131 | # 1001.0 -->> 001 去除多余小数点 132 | if int( value ) == value : 133 | return False,str( int(value) ) 134 | return False,str( value ) 135 | elif str == val_type or unicode == val_type: 136 | return False, "".join(["\"",value,"\""]) 137 | elif tuple == val_type : 138 | return self.tuple_to_erlang(value,indent) 139 | elif dict == val_type : 140 | return self.dict_to_erlang(value,indent) 141 | elif list == val_type : 142 | return self.list_to_erlang(value,indent) 143 | else : 144 | raise Exception( "invalid type",val_type ) 145 | 146 | #文件内容 147 | def context(self,ctx): 148 | is_indent,str_ctx = self.to_text( ctx,0 ) 149 | if None != str_ctx : 150 | return "".join( [self.comment(),"",str_ctx] ) 151 | else : 152 | return None 153 | -------------------------------------------------------------------------------- /writer_json_array.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | import json 7 | from writer import * 8 | 9 | try: 10 | basestring 11 | except NameError: 12 | basestring = str 13 | 14 | try: 15 | long 16 | except NameError: 17 | long = int 18 | 19 | # python3中没有unicode了 20 | try: 21 | unicode 22 | except NameError: 23 | unicode = str 24 | 25 | # 加上不确定的层级缩进,60比较合适 26 | BASE_LENGTH = 60 27 | BASE_INDENT = " " 28 | INDENT_LIST = {} 29 | 30 | class JsonarrayWriter(Writer): 31 | # 文件后缀 32 | def suffix(self): 33 | return ".json" 34 | 35 | # 文件内容(字符串) 36 | def context(self,ctx): 37 | return json.dumps(ctx,ensure_ascii=False,\ 38 | indent=4,sort_keys=True,separators=(',', ':') ) 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /writer_json_object.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from writer import * 7 | 8 | try: 9 | basestring 10 | except NameError: 11 | basestring = str 12 | 13 | try: 14 | long 15 | except NameError: 16 | long = int 17 | 18 | # python3中没有unicode了 19 | try: 20 | unicode 21 | except NameError: 22 | unicode = str 23 | 24 | # 加上不确定的层级缩进,60比较合适 25 | BASE_LENGTH = 60 26 | BASE_INDENT = " " 27 | INDENT_LIST = {} 28 | 29 | class JsonobjectWriter(Writer): 30 | # 文件后缀 31 | def suffix(self): 32 | return ".json" 33 | 34 | def comment(self): 35 | comment = [] 36 | return "\n".join( comment ) 37 | 38 | # 获取缩进字符串 39 | def indent_ctx( self,indent ): 40 | if indent <= 0: return "" 41 | 42 | if indent not in INDENT_LIST: 43 | ctx = BASE_INDENT*indent 44 | INDENT_LIST[indent] = ctx 45 | 46 | return INDENT_LIST[indent] 47 | 48 | def dict_to_text(self, value, indent) : 49 | dict_ctx_list = [] 50 | is_indent,lv = self.to_target_lang( value, indent) 51 | dict_ctx_list.append(lv) 52 | 53 | dict_str = "".join( dict_ctx_list ) 54 | 55 | return False,"".join( [dict_str] ) 56 | 57 | def list_to_dit(self, cur_key_index, total_key_cnt, onedict, storge_dict) : 58 | for k in ( onedict ) : 59 | key_index = self.keys_list.get(k, None) 60 | if None != key_index and key_index == cur_key_index : 61 | lv = onedict[k] 62 | if cur_key_index == total_key_cnt : 63 | storge_dict[lv] = onedict 64 | else : 65 | if None != storge_dict.get(lv, None) : 66 | olddict = storge_dict[lv] 67 | new_storge_dict = olddict 68 | self.list_to_dit(cur_key_index + 1, total_key_cnt, onedict, new_storge_dict) 69 | else : 70 | storge_dict[lv] ={} 71 | new_storge_dict = storge_dict[lv] 72 | self.list_to_dit(cur_key_index + 1, total_key_cnt, onedict, new_storge_dict) 73 | 74 | def list_to_text(self, value, indent): 75 | list_text_list = [] 76 | 77 | ## 处理多个key的情况 78 | key_value_list = {} 79 | key_cnt = len(self.keys_list) 80 | for i, onedict in enumerate( value ) : 81 | self.list_to_dit(1, key_cnt, onedict, key_value_list) 82 | 83 | is_indent,lv = self.to_target_lang( key_value_list, 0 ) 84 | list_str = "".join( lv ) 85 | list_text_list.append(list_str) 86 | return False,"".join( list_text_list ) 87 | 88 | # 转换为文本数据 之前解析出来的excel数据存放方式存在LIST(array格式)和DICT(object格式)两种类型 89 | def to_text(self,value,indent): 90 | val_type = type( value ) 91 | if dict == val_type : 92 | return self.dict_to_text(value, indent) 93 | else : 94 | return self.list_to_text(value, indent) 95 | 96 | # dict转换为json类型 97 | def dict_to_json(self,value,indent): 98 | dict_ctx_list = [] 99 | #if indent % 2 != 0 : 100 | # indent += 1 101 | cur_indent = self.indent_ctx(indent) 102 | next_indent = self.indent_ctx(indent + 1) 103 | 104 | dict_len = len(value) 105 | tem_count = 0 106 | for k in ( value ) : 107 | lvalue = value[k] 108 | lvalue_type = type(lvalue) 109 | if tuple != lvalue_type and dict != lvalue_type and list != lvalue_type : 110 | tem_count += 1 111 | k_indent,lk = self.to_target_lang( k,indent ) 112 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 113 | 114 | if lk.replace(".", "").isdigit() : 115 | key = "".join( ["\"",lk,"\"", ':'] ) 116 | else : 117 | key = lk.replace("\'", "\"") + ':' 118 | 119 | if tem_count != dict_len : 120 | val = "".join( [ next_indent, key + lv + ',\n' ] ) 121 | else : 122 | val = "".join( [ next_indent, key + lv ]) 123 | dict_ctx_list.append( val ) 124 | 125 | for k in ( value ) : 126 | lvalue = value[k] 127 | lvalue_type = type(lvalue) 128 | if tuple == lvalue_type or dict == lvalue_type or list == lvalue_type : 129 | tem_count += 1 130 | k_indent,lk = self.to_target_lang( k,indent ) 131 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 132 | if lk.replace(".", "").isdigit() : 133 | key = "".join( ["\"",lk,"\"", ':'] ) 134 | else : 135 | key = lk.replace("\'", "\"") + ':' 136 | 137 | 138 | if tem_count != dict_len : 139 | val = "".join( [ next_indent, key + lv + ',\n' ] ) 140 | else : 141 | val = "".join( [ next_indent, key + lv ]) 142 | dict_ctx_list.append( val ) 143 | 144 | dict_str = "".join(dict_ctx_list) 145 | return True,"".join(["{\n" , dict_str, "\n",cur_indent,"}"] ) 146 | 147 | # list转换为json类型 148 | def list_to_json(self,value,indent): 149 | list_ctx_list = [] 150 | #if indent % 2 != 0 : 151 | # indent += 1 152 | cur_indent = self.indent_ctx(indent) 153 | next_indent = self.indent_ctx(indent + 1) 154 | 155 | index_cnt = 1 156 | list_len = len(value) 157 | tem_count = 0 158 | for v in value : 159 | tem_count += 1 160 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 161 | if tem_count != list_len : 162 | val = "".join( [ next_indent, lv + ',\n' ] ) 163 | else : 164 | val = "".join( [ next_indent, lv]) 165 | list_ctx_list.append( val ) 166 | index_cnt += 1 167 | 168 | list_str = "".join(list_ctx_list) 169 | return True,"".join(["[\n" , list_str, "\n",cur_indent,"]"] ) 170 | 171 | # 变量转换到目标语言的字符串 172 | def to_target_lang(self,value,indent): 173 | val_type = type( value ) 174 | if int == val_type : 175 | return False,str( value ) 176 | elif long == val_type : 177 | return False,str( value ) 178 | elif float == val_type : 179 | # 1001.0 -->> 001 去除多余小数点 180 | if int( value ) == value : 181 | return False,str( int(value) ) 182 | return False, str( value ) 183 | elif str == val_type or unicode == val_type: 184 | # 字符串要用单引号,因为Lua里单引号级别比双引号高 185 | return False,"".join(["\"",value,"\""]) 186 | elif tuple == val_type : 187 | value1 = list(value) 188 | return self.list_to_json(value1,indent) 189 | elif dict == val_type : 190 | return self.dict_to_json(value,indent) 191 | elif list == val_type : 192 | return self.list_to_json(value,indent) 193 | else : 194 | raise Exception( "invalid type",val_type ) 195 | 196 | #文件内容 197 | def context(self,ctx): 198 | is_indent,str_ctx = self.to_text( ctx, 0 ) 199 | return "".join( [self.comment(), str_ctx] ) 200 | 201 | 202 | -------------------------------------------------------------------------------- /writer_lua.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from writer import * 7 | 8 | try: 9 | basestring 10 | except NameError: 11 | basestring = str 12 | 13 | try: 14 | long 15 | except NameError: 16 | long = int 17 | 18 | # python3中没有unicode了 19 | try: 20 | unicode 21 | except NameError: 22 | unicode = str 23 | 24 | # 加上不确定的层级缩进,60比较合适 25 | BASE_LENGTH = 60 26 | BASE_INDENT = " " 27 | INDENT_LIST = {} 28 | 29 | class LuaWriter(Writer): 30 | # 文件后缀 31 | def suffix(self): 32 | return ".lua" 33 | 34 | def comment(self): 35 | comment = [ 36 | '-- Automatic generation from -->>' 37 | '\n-- excel file name: ' + self.doc_name + 38 | '\n-- excel sheet name: ' + self.sheet_name, 39 | '\nlocal ' + self.base_name + ' =\n' 40 | ] 41 | return "\n".join( comment ) 42 | 43 | # 获取缩进字符串 44 | def indent_ctx( self,indent ): 45 | if indent <= 0: return "" 46 | 47 | if indent not in INDENT_LIST: 48 | ctx = BASE_INDENT*indent 49 | INDENT_LIST[indent] = ctx 50 | 51 | return INDENT_LIST[indent] 52 | 53 | def dict_to_text(self, value, indent) : 54 | dict_ctx_list = [] 55 | 56 | cur_indent = self.indent_ctx(indent) 57 | next_indent = self.indent_ctx(indent + 1) 58 | 59 | tem_count = 0 60 | total_len = len(value) 61 | for k in ( value ) : 62 | tem_count += 1 63 | k_indent,lk = self.to_target_lang( k,indent ) 64 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 65 | 66 | comment = self.comment_text[k] 67 | val = '-- ' + comment + '\n' 68 | dict_ctx_list.append(val) 69 | 70 | val_type = type( lk ) 71 | if str == val_type : 72 | if lk.replace(".", "").isdigit() : 73 | key = "".join( ["[",lk,"]"] ) 74 | else : 75 | key = lk.replace("\'", "") 76 | if tem_count != total_len : 77 | val = "".join( [cur_indent, key," =", lv, ",\n\n", cur_indent] ) 78 | else : 79 | val = "".join( [cur_indent, key," = ",lv] ) 80 | 81 | dict_ctx_list.append( val ) 82 | dict_str = "".join( dict_ctx_list ) 83 | 84 | return False,"".join( ["{\n", cur_indent, dict_str, "\n}"] ) 85 | 86 | def list_to_dit(self, cur_key_index, total_key_cnt, onedict, storge_dict) : 87 | for k in ( onedict ) : 88 | key_index = self.keys_list.get(k, None) 89 | if None != key_index and key_index == cur_key_index : 90 | lv = onedict[k] 91 | if cur_key_index == total_key_cnt : 92 | storge_dict[lv] = onedict 93 | else : 94 | if None != storge_dict.get(lv, None) : 95 | olddict = storge_dict[lv] 96 | new_storge_dict = olddict 97 | self.list_to_dit(cur_key_index + 1, total_key_cnt, onedict, new_storge_dict) 98 | else : 99 | storge_dict[lv] ={} 100 | new_storge_dict = storge_dict[lv] 101 | self.list_to_dit(cur_key_index + 1, total_key_cnt, onedict, new_storge_dict) 102 | 103 | def list_to_text(self, value, indent): 104 | list_text_list = [] 105 | 106 | # 先把各个字段的注释放在前面 107 | comment_text_list = [] 108 | for k in self.comment_text : 109 | comment = self.comment_text[k] 110 | k_indent,lk = self.to_target_lang( k,indent ) 111 | 112 | lk = lk.replace("\'", "") 113 | 114 | if None == comment : 115 | comment = "" 116 | val = "".join( [ '--: ', lk.ljust(20, " "), "\t## ", comment, "\n"] ) 117 | 118 | comment_text_list.append( val ) 119 | 120 | comment_str = "".join( comment_text_list ) 121 | 122 | list_text_list.append(comment_str) 123 | 124 | ## 处理多个key的情况 125 | key_value_list = {} 126 | key_cnt = len(self.keys_list) 127 | for i, onedict in enumerate( value ) : 128 | self.list_to_dit(1, key_cnt, onedict, key_value_list) 129 | 130 | is_indent,lv = self.to_target_lang( key_value_list, 0 ) 131 | list_str = "".join( lv ) 132 | list_text_list.append(list_str) 133 | return False,"".join( list_text_list ) 134 | 135 | # 转换为文本数据 之前解析出来的excel数据存放方式存在LIST(array格式)和DICT(object格式)两种类型 136 | def to_text(self,value,indent): 137 | val_type = type( value ) 138 | if dict == val_type : 139 | return self.dict_to_text(value, indent) 140 | else : 141 | return self.list_to_text(value, indent) 142 | 143 | # dict转换为lua类型 144 | def dict_to_lua(self,value,indent): 145 | dict_ctx_list = [] 146 | if indent % 2 != 0 : 147 | indent += 1 148 | cur_indent = self.indent_ctx(indent) 149 | next_indent = self.indent_ctx(indent + 1) 150 | 151 | dict_len = len(value) 152 | tem_count = 0 153 | for k in ( value ) : 154 | lvalue = value[k] 155 | lvalue_type = type(lvalue) 156 | if tuple != lvalue_type and dict != lvalue_type and list != lvalue_type : 157 | tem_count += 1 158 | k_indent,lk = self.to_target_lang( k,indent ) 159 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 160 | 161 | if lk.replace(".", "").isdigit() : 162 | key = "".join( ["[",lk,"]"] ) 163 | else : 164 | key = lk.replace("\'", "") 165 | 166 | if tem_count != dict_len : 167 | val = "".join( [ next_indent, key + " = " + lv + ',\n' ] ) 168 | else : 169 | val = "".join( [ next_indent, key + " = " + lv ]) 170 | dict_ctx_list.append( val ) 171 | 172 | for k in ( value ) : 173 | lvalue = value[k] 174 | lvalue_type = type(lvalue) 175 | if tuple == lvalue_type or dict == lvalue_type or list == lvalue_type : 176 | tem_count += 1 177 | k_indent,lk = self.to_target_lang( k,indent ) 178 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 179 | 180 | if lk.replace(".", "").isdigit() : 181 | key = "".join( ["[",lk,"]"] ) 182 | else : 183 | key = lk.replace("\'", "") 184 | 185 | if tem_count != dict_len : 186 | val = "".join( [ next_indent, key + " = " + lv + ',\n' ] ) 187 | else : 188 | val = "".join( [ next_indent, key + " = " + lv ]) 189 | dict_ctx_list.append( val ) 190 | 191 | dict_str = "".join(dict_ctx_list) 192 | return True,"".join(['\n', cur_indent,"{\n" , dict_str, "\n",cur_indent,"}"] ) 193 | 194 | # list转换为lua类型 195 | def list_to_lua(self,value,indent): 196 | list_ctx_list = [] 197 | if indent % 2 != 0 : 198 | indent += 1 199 | cur_indent = self.indent_ctx(indent) 200 | next_indent = self.indent_ctx(indent + 1) 201 | 202 | index_cnt = 1 203 | list_len = len(value) 204 | tem_count = 0 205 | for v in value : 206 | tem_count += 1 207 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 208 | if tem_count != list_len : 209 | val = "".join( [ next_indent, "[" + str(index_cnt) + "] = " + lv + ',\n' ] ) 210 | else : 211 | val = "".join( [ next_indent, "[" + str(index_cnt) + "] = " + lv ]) 212 | list_ctx_list.append( val ) 213 | index_cnt += 1 214 | 215 | list_str = "".join(list_ctx_list) 216 | return True,"".join(['\n', cur_indent,"{\n" , list_str, "\n",cur_indent,"}"] ) 217 | 218 | # tuple转换为lua类型 219 | def tuple_to_lua(self,value1,indent): 220 | value = list(value1) 221 | list_ctx_list = [] 222 | if indent % 2 != 0 : 223 | indent += 1 224 | cur_indent = self.indent_ctx(indent) 225 | next_indent = self.indent_ctx(indent + 1) 226 | 227 | index_cnt = 1 228 | list_len = len(value) 229 | tem_count = 0 230 | for v in value : 231 | tem_count += 1 232 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 233 | if tem_count != list_len : 234 | val = "".join( [ next_indent, "[" + str(index_cnt) + "] = " + lv + ',\n' ] ) 235 | else : 236 | val = "".join( [ next_indent, "[" + str(index_cnt) + "] = " + lv ]) 237 | list_ctx_list.append( val ) 238 | index_cnt += 1 239 | 240 | list_str = "".join(list_ctx_list) 241 | return True,"".join(['\n', cur_indent,"{\n" , list_str, "\n",cur_indent,"}"] ) 242 | 243 | 244 | # 变量转换到目标语言的字符串 245 | def to_target_lang(self,value,indent): 246 | val_type = type( value ) 247 | if int == val_type : 248 | return False,str( value ) 249 | elif long == val_type : 250 | return False,str( value ) 251 | elif float == val_type : 252 | # 1001.0 -->> 001 去除多余小数点 253 | if int( value ) == value : 254 | return False,str( int(value) ) 255 | return False,str( value ) 256 | elif str == val_type or unicode == val_type: 257 | # 字符串要用单引号,因为Lua里单引号级别比双引号高 258 | return False,"".join(["'",value,"'"]) 259 | elif tuple == val_type : 260 | return self.tuple_to_lua(value,indent) 261 | elif dict == val_type : 262 | return self.dict_to_lua(value,indent) 263 | elif list == val_type : 264 | return self.list_to_lua(value,indent) 265 | else : 266 | raise Exception( "invalid type",val_type ) 267 | 268 | #文件内容 269 | def context(self,ctx): 270 | is_indent,str_ctx = self.to_text( ctx,1 ) 271 | return "".join( [self.comment(), str_ctx, "\nreturn ", self.base_name] ) 272 | 273 | 274 | -------------------------------------------------------------------------------- /writer_python.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from writer import * 7 | 8 | try: 9 | basestring 10 | except NameError: 11 | basestring = str 12 | 13 | try: 14 | long 15 | except NameError: 16 | long = int 17 | 18 | # python3中没有unicode了 19 | try: 20 | unicode 21 | except NameError: 22 | unicode = str 23 | 24 | # 加上不确定的层级缩进,60比较合适 25 | BASE_LENGTH = 60 26 | BASE_INDENT = " " 27 | INDENT_LIST = {} 28 | 29 | class PythonWriter(Writer): 30 | # 文件后缀 31 | def suffix(self): 32 | return ".py" 33 | 34 | # 文件注释(千万不要加时间,影响svn) 35 | def comment(self): 36 | comment = [ 37 | '## Automatic generation from -->>' 38 | '\n## excel file name: ' + self.doc_name + 39 | '\n## excel sheet name: ' + self.sheet_name, 40 | '\ndefmodule ' + self.base_name.title() + ' do\n\n' 41 | ] 42 | 43 | return "\n".join( comment ) 44 | 45 | # 获取缩进字符串 46 | def indent_ctx( self,indent ): 47 | if indent <= 0: return "" 48 | 49 | if indent not in INDENT_LIST: 50 | INDENT_LIST[indent] = "" 51 | else: 52 | ctx = BASE_INDENT*indent 53 | INDENT_LIST[indent] = ctx 54 | 55 | return INDENT_LIST[indent] 56 | 57 | def dict_to_text(self, value, indent) : 58 | 59 | 60 | dict_text_list = [] 61 | for k in ( value ) : 62 | k_indent,lk = self.to_target_lang( k,indent ) 63 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 64 | 65 | comment = self.comment_text[k] 66 | 67 | val_type = type( lk ) 68 | if str == val_type : 69 | lk = ':' + lk.replace("\"", "") 70 | 71 | key = "".join( [" def get(",lk,") do\n"] ) 72 | 73 | val = "".join( [" ## ", comment, "\n", key, " ", lv, "\n end\n\n"] ) 74 | 75 | dict_text_list.append( val ) 76 | 77 | dict_str = "".join( dict_text_list ) 78 | dict_str = dict_str + " def get(_) do\n :undefined\n end\n\nend" 79 | return False, dict_str 80 | 81 | def list_to_text(self, value, indent): 82 | list_text_list = [] 83 | # 先定义 struct 84 | struct_text_list = [] 85 | struct_len = len(self.comment_text) 86 | tem_count = 0 87 | for k in self.comment_text : 88 | tem_count += 1 89 | comment = self.comment_text[k] 90 | k_indent,lk = self.to_target_lang( k,indent ) 91 | val_type = type( lk ) 92 | if str == val_type : 93 | if tem_count != struct_len : 94 | lk = ':' + lk.replace("\"", "") + ',' 95 | else : 96 | lk = ':' + lk.replace("\"", "") 97 | 98 | if None == comment : 99 | comment = "" 100 | val = "".join( [lk.ljust(20, " "), "\t## ", comment, "\n"] ) 101 | 102 | struct_text_list.append( val ) 103 | 104 | struct_str = " ".join( struct_text_list ) 105 | end_str = " defstruct [\n " + struct_str + " ]\n\n" 106 | 107 | list_text_list.append(end_str) 108 | 109 | all_key_list = [] 110 | # 生成 get() 函数 111 | for i, onedict in enumerate( value ) : 112 | # 生成对应的 key 113 | key_list = [] 114 | for k in ( onedict ) : 115 | if None != self.keys_list.get(k, None) : 116 | is_indent,lv = self.to_target_lang( onedict[k],indent + 1 ) 117 | key_list.append(lv) 118 | all_key_list.append(key_list) 119 | 120 | tem = ", ".join( key_list ) 121 | 122 | key = "".join( [" def get(",tem,") do\n %", self.base_name.title(), "{\n "] ) 123 | 124 | # 生成对应的value 125 | value_list = [] 126 | onedict_len = len(onedict) 127 | tem_count = 0 128 | for k in ( onedict ) : 129 | tem_count += 1 130 | k_indent,lk = self.to_target_lang( k,indent ) 131 | is_indent,lv = self.to_target_lang( onedict[k],indent + 1 ) 132 | 133 | val_type = type( lk ) 134 | if str == val_type : 135 | lk = ':' + lk.replace("\"", "") 136 | 137 | if tem_count != onedict_len : 138 | oneval = "".join( [lk, " => ", lv , ",\n"] ) 139 | value_list.append( oneval ) 140 | else : 141 | oneval = "".join( [lk, " => ", lv , "\n"] ) 142 | value_list.append( oneval ) 143 | 144 | value_list_str = " ".join(value_list) 145 | end_str = "".join( [key, value_list_str, " }\n end\n\n"] ) 146 | 147 | list_text_list.append( end_str ) 148 | 149 | underline_list = [] 150 | for i in self.keys_list : 151 | underline_list.append('_') 152 | 153 | end_str = ", ".join(underline_list) 154 | no_match_str = " def get(" + end_str + ") do\n :undefined\n end\n\n" 155 | 156 | list_text_list.append(no_match_str) 157 | 158 | # 生成 get_all() 函数 159 | get_all_fun = [] 160 | allkey_len = len(all_key_list) 161 | tem_count = 0 162 | for i, ival in enumerate(all_key_list) : 163 | tem_count += 1 164 | if tem_count != allkey_len : 165 | oneval = '{' + ", ".join(ival) + '},\n' 166 | get_all_fun.append(oneval) 167 | else : 168 | oneval = '{' + ", ".join(ival) + '}\n' 169 | get_all_fun.append(oneval) 170 | 171 | value_list_str = " ".join(get_all_fun) 172 | start_str = ' def get_all() do\n [\n ' 173 | end_str = "".join( [start_str, value_list_str, " ]\n end\n\n"] ) 174 | 175 | list_text_list.append( end_str ) 176 | 177 | # 生成 get_list() 函数 178 | get_list_fun = [] 179 | keys_len = len(self.keys_list) 180 | for key in self.keys_list : 181 | keyindex = self.keys_list[key] 182 | if keyindex == 1 : 183 | list_text_list.append( ' def get_list() do\n get_all()\n end\n\n') 184 | elif keyindex <= keys_len : 185 | get_tem_dict = {} 186 | underline_list = [] 187 | for i, ival in enumerate(all_key_list) : 188 | key_tem_list = [] 189 | j = 0 190 | underline_list = [] 191 | while j < keyindex - 1 : 192 | key_tem_list.append(ival[j]) 193 | underline_list.append('_') 194 | j += 1 195 | 196 | keystr = '(' + ", ".join(key_tem_list) + ')' 197 | if None != get_tem_dict.get(keystr, None) : 198 | oldlist = get_tem_dict[keystr] 199 | oldlist.append(ival) 200 | get_tem_dict[keystr] = oldlist 201 | else : 202 | get_tem_dict[keystr] = [ival] 203 | 204 | for onekey in get_tem_dict : 205 | value_tem_list = [] 206 | valuelist = get_tem_dict[onekey] 207 | 208 | value_len = len(valuelist) 209 | tem_count = 0 210 | for l, lval in enumerate(valuelist) : 211 | tem_count += 1 212 | if tem_count != value_len : 213 | oneval = '{' + ", ".join(lval) + '},\n' 214 | value_tem_list.append(oneval) 215 | else : 216 | oneval = '{' + ", ".join(lval) + '}\n' 217 | value_tem_list.append(oneval) 218 | start_str = ' def get_list' + onekey + ' do\n [\n ' 219 | end_str = "".join( [start_str, " ".join(value_tem_list), " ]\n end\n\n"] ) 220 | get_list_fun.append(end_str) 221 | no_match_str = "".join(' def get_list(' + ", ".join(underline_list) + ') do\n []\n end\n\n') 222 | get_list_fun.append(no_match_str) 223 | 224 | 225 | value_list_str = "".join(get_list_fun) + 'end' 226 | list_text_list.append( value_list_str ) 227 | dict_str = "".join( list_text_list ) 228 | 229 | return False, dict_str 230 | 231 | # 转换为erlang 文本数据 之前解析出来的excel数据存放方式存在LIST(array格式)和DICT(object格式)两种类型 232 | def to_text(self,value,indent): 233 | val_type = type( value ) 234 | if dict == val_type : 235 | return self.dict_to_text(value, indent) 236 | else : 237 | return self.list_to_text(value, indent) 238 | 239 | # python的dict转换为elixir的map类型 240 | def dict_to_elixir(self,value,indent): 241 | dict_ctx_list = [] 242 | 243 | for k in ( value ) : 244 | k_indent,lk = self.to_target_lang( k,indent ) 245 | is_indent,lv = self.to_target_lang( value[k],indent + 1 ) 246 | 247 | val_type = type( lk ) 248 | if str == val_type : 249 | lk = lk.replace("\"", "\'") 250 | key = "".join( [lk," => "] ) 251 | val = "".join( [key, lv] ) 252 | dict_ctx_list.append(val) 253 | 254 | dict_str = ", ".join( dict_ctx_list ) 255 | return False,"".join( ["%{",dict_str,"}"] ) 256 | 257 | # python的list转换为elixir的list类型 258 | def list_to_elixir(self,value,indent): 259 | list_ctx_list = [] 260 | for v in value : 261 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 262 | list_ctx_list.append( lv ) 263 | 264 | 265 | list_str = ", ".join( list_ctx_list ) 266 | return False,"".join( ["[",list_str,"]"] ) 267 | 268 | # python的tuple转换为elixir的tuple类型 269 | def tuple_to_elixir(self,value,indent): 270 | tuple_ctx_list = [] 271 | 272 | for v in value : 273 | is_indent,lv = self.to_target_lang( v,indent + 1 ) 274 | tuple_ctx_list.append( lv ) 275 | 276 | # 返回 {a,b,c}这种不换行的格式 277 | list_str = ", ".join( tuple_ctx_list ) 278 | return False,"".join( ["{",list_str,"}"] ) 279 | 280 | 281 | # 变量转换到目标语言字符串 282 | def to_target_lang(self,value,indent): 283 | val_type = type( value ) 284 | if int == val_type : 285 | return False,str( value ) 286 | elif long == val_type : 287 | return False,str( value ) 288 | elif float == val_type : 289 | # 1001.0 -->> 001 去除多余小数点 290 | if int( value ) == value : 291 | return False,str( int(value) ) 292 | return False,str( value ) 293 | elif str == val_type or unicode == val_type: 294 | return False, "".join(["\"",value,"\""]) 295 | elif tuple == val_type : 296 | return self.tuple_to_elixir(value,indent) 297 | elif dict == val_type : 298 | return self.dict_to_elixir(value,indent) 299 | elif list == val_type : 300 | return self.list_to_elixir(value,indent) 301 | else : 302 | raise Exception( "invalid type",val_type ) 303 | 304 | #文件内容 305 | def context(self,ctx): 306 | is_indent,str_ctx = self.to_text( ctx,0 ) 307 | return "".join( [self.comment(),"",str_ctx] ) 308 | -------------------------------------------------------------------------------- /writer_xml.py: -------------------------------------------------------------------------------- 1 | #! python 2 | # -*- coding:utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from xml.dom.minidom import Document 7 | from writer import * 8 | 9 | try: 10 | basestring 11 | except NameError: 12 | basestring = str 13 | 14 | try: 15 | long 16 | except NameError: 17 | long = int 18 | 19 | # python3中没有unicode了 20 | try: 21 | unicode 22 | except NameError: 23 | unicode = str 24 | 25 | # 加上不确定的层级缩进,60比较合适 26 | BASE_LENGTH = 60 27 | BASE_INDENT = " " 28 | INDENT_LIST = {} 29 | 30 | class JsonWriter(Writer): 31 | # 文件后缀 32 | def suffix(self): 33 | return ".json" 34 | 35 | # 文件内容(字符串) 36 | def context(self,ctx): 37 | return json.dumps(ctx,ensure_ascii=False,\ 38 | indent=4,sort_keys=True,separators=(',', ':') ) 39 | 40 | 41 | class XmlWriter(Writer): 42 | # 文件后缀 43 | def suffix(self): 44 | return ".xml" 45 | # 注释开始 46 | def comment_start(self): 47 | return "" 51 | 52 | #创建根元素 53 | def root_element(self): 54 | root = self.doc.createElement( self.base_name ) 55 | return root 56 | 57 | # dict类型转换为xml 58 | def dict_to_xml(self,root,value): 59 | # 需要对key排序,不然每次导出的xml字段是乱的,对版本管理不友好 60 | for k in sorted( value ) : 61 | v = value[k] 62 | sub_root = self.doc.createElement( k ) 63 | 64 | self.to_xml( sub_root,v ) 65 | root.appendChild( sub_root ) 66 | 67 | # list类型转换为xml 68 | def list_to_xml(self,root,value): 69 | for k,v in enumerate( value ) : 70 | # xml中并不支持array,用item来命名,外加一个index属性 71 | sub_root = self.doc.createElement( "item" ) 72 | sub_root.setAttribute( "index",str( k ) ) 73 | 74 | self.to_xml( sub_root,v ) 75 | root.appendChild( sub_root ) 76 | # tuple类型转换为xml 77 | def tuple_to_xml(self,root,value): 78 | valueList = list(value) 79 | for k,v in enumerate( valueList ) : 80 | # xml中并不支持array,用item来命名,外加一个index属性 81 | sub_root = self.doc.createElement( "item" ) 82 | sub_root.setAttribute( "index",str( k ) ) 83 | 84 | self.to_xml( sub_root,v ) 85 | root.appendChild( sub_root ) 86 | 87 | # 转换为xml节点 88 | def to_xml(self,root,value): 89 | sub_node = None 90 | val_type_str = None 91 | val_type = type( value ) 92 | if int == val_type : 93 | # python3中没有Long类型,int64也用int表示 94 | val_type_str = "int64" 95 | sub_node = self.doc.createTextNode( str( value ) ) 96 | elif long == val_type : 97 | val_type_str = "int64" 98 | sub_node = self.doc.createTextNode( str( value ) ) 99 | elif float == val_type : 100 | val_type_str = "number" 101 | # 去除带小数时的小数点,100.0 ==>> 100 102 | if long( value ) == float( value ) : 103 | sub_node = self.doc.createTextNode( str( long( value ) ) ) 104 | else: 105 | sub_node = self.doc.createTextNode( str( value ) ) 106 | elif str == val_type or unicode == val_type : 107 | val_type_str = "string" 108 | sub_node = self.doc.createTextNode( value ) 109 | elif tuple == val_type : 110 | self.tuple_to_xml( root,value ) 111 | elif dict == val_type : 112 | self.dict_to_xml( root,value ) 113 | elif list == val_type : 114 | self.list_to_xml( root,value ) 115 | else : 116 | raise Exception( "invalid type",val_type ) 117 | 118 | # 类型为dict或者list的,没有这个type属性 119 | if val_type_str : root.setAttribute( "type",val_type_str ) 120 | if sub_node : root.appendChild( sub_node ) 121 | 122 | # 文件内容 123 | def context(self,ctx): 124 | #创建DOM文档对象 125 | self.doc = Document() 126 | root = self.root_element() 127 | 128 | self.to_xml( root,ctx ) 129 | self.doc.appendChild( root ) 130 | 131 | return self.comment() + self.doc.toprettyxml( indent=" " ) 132 | 133 | 134 | --------------------------------------------------------------------------------