Compare commits
140 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4e5e82660 | ||
|
|
c5f2d3cf18 | ||
|
|
017049f473 | ||
|
|
75ce8116ca | ||
|
|
73dc7ca2ed | ||
|
|
8c6e111e13 | ||
|
|
305cafbfcf | ||
|
|
8c3d927820 | ||
|
|
b83138c127 | ||
|
|
e7a789e466 | ||
|
|
d5f448c952 | ||
|
|
f43babc491 | ||
|
|
6a78042869 | ||
|
|
4984cf7a4b | ||
|
|
6693a6cd96 | ||
|
|
2909eeb0c3 | ||
|
|
61260f6e48 | ||
|
|
c741d35c67 | ||
|
|
18e06631bf | ||
|
|
efd78f57b9 | ||
|
|
e366377d64 | ||
|
|
4b334a0d40 | ||
|
|
c3471d0077 | ||
|
|
7c7a45d99d | ||
|
|
c57215aeeb | ||
|
|
66e0e04f45 | ||
|
|
9d1d3256c8 | ||
|
|
d61a0d64fc | ||
|
|
796e793902 | ||
|
|
adfc4d98a7 | ||
|
|
cb28bb1b97 | ||
|
|
77ae45ef8b | ||
|
|
d64b44943b | ||
|
|
8fb808d75f | ||
|
|
81e92eec88 | ||
|
|
7d763054b7 | ||
|
|
6b39babf34 | ||
|
|
214c598a85 | ||
|
|
a297104017 | ||
|
|
f6e72fc9ce | ||
|
|
631ca23a97 | ||
|
|
c2d9a0dbac | ||
|
|
cec4eb869d | ||
|
|
7602facb7a | ||
|
|
d5827e233c | ||
|
|
d59a92e0bf | ||
|
|
65d460452b | ||
|
|
867de8f3e4 | ||
|
|
ec756721c2 | ||
|
|
3b554526c6 | ||
|
|
4246d7683a | ||
|
|
b7c922e253 | ||
|
|
beaeb9a65d | ||
|
|
b3d0f40519 | ||
|
|
c64906d09a | ||
|
|
2d993203f8 | ||
|
|
3fdc605d36 | ||
|
|
393c0703a6 | ||
|
|
2c396b775e | ||
|
|
d14c4b544a | ||
|
|
730835a04d | ||
|
|
db315532ed | ||
|
|
cc9128ad73 | ||
|
|
99763ce992 | ||
|
|
c735b7476d | ||
|
|
932274fbbe | ||
|
|
7fed63512d | ||
|
|
14cf94f3bb | ||
|
|
14665f57dd | ||
|
|
414f44b6f5 | ||
|
|
0c1a335aa0 | ||
|
|
ae04d6e1aa | ||
|
|
6fb6c73495 | ||
|
|
5083d561d2 | ||
|
|
2a2bfa69a2 | ||
|
|
56f05aa5fe | ||
|
|
4607721020 | ||
|
|
329baf4b82 | ||
|
|
ed30c2399d | ||
|
|
7663cbbf0c | ||
|
|
c48182b902 | ||
|
|
9297a18b8d | ||
|
|
4fdeccdbc1 | ||
|
|
5c76dbabd6 | ||
|
|
b6176efd07 | ||
|
|
5327916817 | ||
|
|
78e52ac04a | ||
|
|
a9b1729057 | ||
|
|
a226c6e432 | ||
|
|
79af98d75b | ||
|
|
ab26ded71a | ||
|
|
defba4f767 | ||
|
|
585c5c0f9c | ||
|
|
047165b6aa | ||
|
|
3d0e52bdbe | ||
|
|
2e1a512f00 | ||
|
|
09dbdc1cb1 | ||
|
|
a9835c25cb | ||
|
|
dab674be91 | ||
|
|
8e5a6bc284 | ||
|
|
fe53414868 | ||
|
|
6f675b60cb | ||
|
|
85be275590 | ||
|
|
378fe2818e | ||
|
|
20ed88665a | ||
|
|
31759939f2 | ||
|
|
03b63b491e | ||
|
|
409f1f4214 | ||
|
|
caf9db40b1 | ||
|
|
fc7e075a01 | ||
|
|
c956350dc2 | ||
|
|
8273b622e9 | ||
|
|
85b016457b | ||
|
|
15154050f9 | ||
|
|
d6472a2fd5 | ||
|
|
3d452e3092 | ||
|
|
bc2a15915c | ||
|
|
6cdecea47c | ||
|
|
4967a0a68b | ||
|
|
2428b66add | ||
|
|
0a550c1d25 | ||
|
|
43e0566cb6 | ||
|
|
8739e37faa | ||
|
|
fcc11f7dff | ||
|
|
705b5f939c | ||
|
|
af27ef7682 | ||
|
|
863f2780b3 | ||
|
|
790191a681 | ||
|
|
ca0fda0bee | ||
|
|
81e4048754 | ||
|
|
353336796d | ||
|
|
c39ee8fb2f | ||
|
|
fbcc555f4e | ||
|
|
43237b1b1d | ||
|
|
5f8ee5ce63 | ||
|
|
edd82b8a4a | ||
|
|
d710fdb4a9 | ||
|
|
b7124a26ba | ||
|
|
fba27ba1b0 | ||
|
|
1a2a3ac721 |
@@ -1,160 +1,199 @@
|
||||
Estrela Editor License
|
||||
=============================================================================
|
||||
|
||||
Estrela Editor sources are released under the MIT License
|
||||
|
||||
Copyright (c) 2008-2011
|
||||
Luxinia DevTeam:
|
||||
Eike Decker & Christoph Kubisch
|
||||
info at luxinia.de
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
wxLua License
|
||||
=============================================================================
|
||||
http://wxlua.sourceforge.net/
|
||||
|
||||
Pre-Built binaries for wxLua/WxWindows
|
||||
|
||||
Original wxLua Lua sample IDE:
|
||||
Lomtick Software
|
||||
J. Winwood & John Labenski
|
||||
luascript at thersgb.net
|
||||
|
||||
wxLua is based on
|
||||
wxWindows Library Licence, Version 3
|
||||
|
||||
Copyright (c) 1998 Julian Smart, Robert Roebling et al
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this licence document, but changing it is not allowed.
|
||||
|
||||
WXWINDOWS LIBRARY LICENCE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public Licence as published by
|
||||
the Free Software Foundation; either version 2 of the Licence, or (at
|
||||
your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
||||
General Public Licence for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public Licence
|
||||
along with this software, usually in a file named COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA.
|
||||
|
||||
EXCEPTION NOTICE
|
||||
|
||||
1. As a special exception, the copyright holders of this library give
|
||||
permission for additional uses of the text contained in this release of
|
||||
the library as licenced under the wxWindows Library Licence, applying
|
||||
either version 3 of the Licence, or (at your option) any later version of
|
||||
the Licence as published by the copyright holders of version 3 of the
|
||||
Licence document.
|
||||
|
||||
2. The exception is that you may use, copy, link, modify and distribute
|
||||
under the user's own terms, binary object code versions of works based
|
||||
on the Library.
|
||||
|
||||
3. If you copy code from files distributed under the terms of the GNU
|
||||
General Public Licence or the GNU Library General Public Licence into a
|
||||
copy of this library, as this licence permits, the exception does not
|
||||
apply to the code that you add in this way. To avoid misleading anyone as
|
||||
to the status of such modified files, you must delete this exception
|
||||
notice from such code and/or adjust the licensing conditions notice
|
||||
accordingly.
|
||||
|
||||
4. If you write modifications of your own for this library, it is your
|
||||
choice whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, you must delete the exception notice from such
|
||||
code and/or adjust the licensing conditions notice accordingly.
|
||||
|
||||
|
||||
Lua License
|
||||
=============================================================================
|
||||
Copyright: © 1994-2006 Lua.org, PUC-Rio.
|
||||
Homepage: http://www.lua.org
|
||||
License: http://www.lua.org/copyright.html
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
LuaFileSystem
|
||||
=============================================================================
|
||||
LuaFileSystem was designed by Roberto Ierusalimschy, André Carregal and Tomás
|
||||
Guisasola as part of the Kepler Project, which holds its copyright.
|
||||
Homepage: http://www.keplerproject.org/luafilesystem/index.html
|
||||
License: http://www.keplerproject.org/luafilesystem/license.html
|
||||
=============================================================================
|
||||
|
||||
LuaSockets
|
||||
=============================================================================
|
||||
Copyright: © 2004-2006 Diego Nehab. All rights reserved.
|
||||
Homepage: http://www.cs.princeton.edu/~diego/professional/luasocket/
|
||||
License: http://www.lua.org/copyright.html (same as LUA)
|
||||
=============================================================================
|
||||
|
||||
ZMQ
|
||||
=============================================================================
|
||||
Copyright: © 2007-2011 iMatix Corporation and Contributors
|
||||
Homepage: http://www.zeromq.org/
|
||||
License: http://www.zeromq.org/area:licensing
|
||||
|
||||
LuaZMQ
|
||||
Copyright: © 2011 by Robert G. Jakabosky
|
||||
Homepage: https://github.com/Neopallium/lua-zmq
|
||||
=============================================================================
|
||||
|
||||
MojoShader
|
||||
=============================================================================
|
||||
Copyright: © 2008-2010 Ryan C. Gordon
|
||||
Homepage: http://icculus.org/mojoshader/
|
||||
License: http://hg.icculus.org/icculus/mojoshader/raw-file/tip/LICENSE.txt
|
||||
=============================================================================
|
||||
|
||||
|
||||
CLCC
|
||||
=============================================================================
|
||||
Copyright: © 2009 Organic Vectory B.V.
|
||||
Homepage: http://clcc.sourceforge.net/
|
||||
License: boost
|
||||
|
||||
CLCC was modified by Christoph Kubisch to support multiple platforms and
|
||||
output file generation.
|
||||
=============================================================================
|
||||
--[[ ZeroBrane Studio License ]]-------------------------------------------
|
||||
|
||||
ZeroBrane Studio sources are released under the MIT License
|
||||
|
||||
Copyright (c) 2011 Paul Kulchenko (paul@kulchenko.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--[[ Estrela Editor License ]]---------------------------------------------
|
||||
|
||||
Estrela Editor sources are released under the MIT License
|
||||
|
||||
Copyright (c) 2008-2011
|
||||
Luxinia DevTeam:
|
||||
Eike Decker & Christoph Kubisch
|
||||
info at luxinia.de
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--[[ wxLua License License ]]----------------------------------------------
|
||||
|
||||
http://wxlua.sourceforge.net/
|
||||
|
||||
Pre-Built binaries for wxLua/WxWindows
|
||||
|
||||
Original wxLua Lua sample IDE:
|
||||
Lomtick Software
|
||||
J. Winwood & John Labenski
|
||||
luascript at thersgb.net
|
||||
|
||||
wxLua is based on
|
||||
wxWindows Library Licence, Version 3
|
||||
|
||||
Copyright (c) 1998 Julian Smart, Robert Roebling et al
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this licence document, but changing it is not allowed.
|
||||
|
||||
WXWINDOWS LIBRARY LICENCE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public Licence as published by
|
||||
the Free Software Foundation; either version 2 of the Licence, or (at
|
||||
your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
||||
General Public Licence for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public Licence
|
||||
along with this software, usually in a file named COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA.
|
||||
|
||||
EXCEPTION NOTICE
|
||||
|
||||
1. As a special exception, the copyright holders of this library give
|
||||
permission for additional uses of the text contained in this release of
|
||||
the library as licenced under the wxWindows Library Licence, applying
|
||||
either version 3 of the Licence, or (at your option) any later version of
|
||||
the Licence as published by the copyright holders of version 3 of the
|
||||
Licence document.
|
||||
|
||||
2. The exception is that you may use, copy, link, modify and distribute
|
||||
under the user's own terms, binary object code versions of works based
|
||||
on the Library.
|
||||
|
||||
3. If you copy code from files distributed under the terms of the GNU
|
||||
General Public Licence or the GNU Library General Public Licence into a
|
||||
copy of this library, as this licence permits, the exception does not
|
||||
apply to the code that you add in this way. To avoid misleading anyone as
|
||||
to the status of such modified files, you must delete this exception
|
||||
notice from such code and/or adjust the licensing conditions notice
|
||||
accordingly.
|
||||
|
||||
4. If you write modifications of your own for this library, it is your
|
||||
choice whether to permit this exception to apply to your modifications.
|
||||
If you do not wish that, you must delete the exception notice from such
|
||||
code and/or adjust the licensing conditions notice accordingly.
|
||||
|
||||
--[[ Lua License ]]--------------------------------------------------------
|
||||
|
||||
Copyright: © 1994-2006 Lua.org, PUC-Rio.
|
||||
Homepage: http://www.lua.org
|
||||
License: http://www.lua.org/copyright.html
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
--[[ LuaFileSystem License ]]----------------------------------------------
|
||||
|
||||
LuaFileSystem was designed by Roberto Ierusalimschy, André Carregal and Tomás
|
||||
Guisasola as part of the Kepler Project, which holds its copyright.
|
||||
Homepage: http://www.keplerproject.org/luafilesystem/index.html
|
||||
License: http://www.keplerproject.org/luafilesystem/license.html
|
||||
|
||||
--[[ LuaSockets License ]]-------------------------------------------------
|
||||
|
||||
Copyright: © 2004-2006 Diego Nehab. All rights reserved.
|
||||
Homepage: http://www.cs.princeton.edu/~diego/professional/luasocket/
|
||||
License: http://www.lua.org/copyright.html (same as LUA)
|
||||
|
||||
--[[ ZMQ License ]]--------------------------------------------------------
|
||||
|
||||
Copyright: © 2007-2011 iMatix Corporation and Contributors
|
||||
Homepage: http://www.zeromq.org/
|
||||
License: http://www.zeromq.org/area:licensing
|
||||
|
||||
LuaZMQ
|
||||
Copyright: © 2011 by Robert G. Jakabosky
|
||||
Homepage: https://github.com/Neopallium/lua-zmq
|
||||
|
||||
--[[ MojoShader License ]]-------------------------------------------------
|
||||
|
||||
Copyright: © 2008-2010 Ryan C. Gordon
|
||||
Homepage: http://icculus.org/mojoshader/
|
||||
License: http://hg.icculus.org/icculus/mojoshader/raw-file/tip/LICENSE.txt
|
||||
|
||||
--[[ CLCC License ]]-------------------------------------------------------
|
||||
|
||||
Copyright: © 2009 Organic Vectory B.V.
|
||||
Homepage: http://clcc.sourceforge.net/
|
||||
License: boost
|
||||
|
||||
CLCC was modified by Christoph Kubisch to support multiple platforms and
|
||||
output file generation.
|
||||
|
||||
--[[ MobDebug License ]]---------------------------------------------------
|
||||
|
||||
MobDebug sources are released under the MIT License
|
||||
|
||||
Copyright (c) 2011 Paul Kulchenko (paul@kulchenko.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
54
README
Normal file
@@ -0,0 +1,54 @@
|
||||
A simple and extensible Lua IDE and debugger. It supports multiple file
|
||||
formats, "api" for autocompletion and tooltips, and custom command-line
|
||||
tools. Its main focus is extensibility for target applications using Lua.
|
||||
|
||||
--[[ FEATURES ]]-----------------------------------------------------------
|
||||
|
||||
* Written in Lua, so easily customizable
|
||||
* Automatically loads several 'plugin' like classes
|
||||
- applications: overall control of applications settings
|
||||
- specs (spec/): file syntax, lexer, keywords
|
||||
- apis (api/): for code-completion and tool-tips
|
||||
- interpreters (interpreters/): how a project is run
|
||||
- config (cfg/): contains style and basic editor settings
|
||||
- tools (tools/): additional tools, e.g. cg compiler, dx fxc compiler
|
||||
* Auto-completion for functions, keywords...
|
||||
* Function tips
|
||||
* Function list in file (quick jump to)
|
||||
* Function call highlighting
|
||||
* Bracket matching/highlighting
|
||||
* Project file browser
|
||||
* Experimental type/class guessing for auto-completion
|
||||
* Support for different editor styles
|
||||
* Console to directly test code snippets with local and remote execution
|
||||
* Integrated debugger (with support for local and remote debugging)
|
||||
|
||||
--[[ INSTALLATION ]]-------------------------------------------------------
|
||||
|
||||
git clone git://github.com/pkulchenko/ZeroBraneStudio.git zbstudio
|
||||
or
|
||||
git clone git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor estrelaeditor
|
||||
|
||||
--[[ USAGE ]]--------------------------------------------------------------
|
||||
|
||||
Open File(s):
|
||||
<exe> <filename> [<filename>...]
|
||||
any non-option will be treated as filename
|
||||
|
||||
Overriding Config:
|
||||
<exe> [...] -cfg "<luacode overriding config>" [...]
|
||||
e.g.: zbstudio.exe -cfg "singleinstance=false;" somefile.lua
|
||||
|
||||
--[[ AUTHOR ]]-------------------------------------------------------------
|
||||
|
||||
Estrela Editor
|
||||
|
||||
Luxinia DevTeam: Eike Decker & Christoph Kubisch (info at luxinia.de)
|
||||
|
||||
ZeroBrane Studio and MobDebug
|
||||
|
||||
ZeroBrane LLC: Paul Kulchenko (paul@kulchenko.com)
|
||||
|
||||
--[[ LICENSE ]]------------------------------------------------------------
|
||||
|
||||
See LICENSE file
|
||||
@@ -1,205 +1,205 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
local function fn (description)
|
||||
local description2,returns,args = description:match("(.+)%-%s*(%b())%s*(%b())")
|
||||
if not description2 then
|
||||
return {type="function",description=description,
|
||||
returns="(?)"}
|
||||
end
|
||||
return {type="function",description=description2,
|
||||
returns=returns:gsub("^%s+",""):gsub("%s+$",""), args = args}
|
||||
end
|
||||
|
||||
local function val (description)
|
||||
return {type="value",description = description}
|
||||
end
|
||||
-- docs
|
||||
local api = {
|
||||
abs = fn "returns absolute value of scalars and vectors. - (typeN)(typeN)",
|
||||
acos = fn "returns arccosine of scalars and vectors. - (typeN)(typeN)",
|
||||
all = fn "returns true if a boolean scalar or all components of a boolean vector are true. - (bool)(boolN)",
|
||||
any = fn "returns true if a boolean scalar or any component of a boolean vector is true. - (bool)(boolN)",
|
||||
asin = fn "returns arcsine of scalars and vectors. - (typeN)(typeN)",
|
||||
atan = fn "returns arctangent of scalars and vectors. - (typeN)(typeN)",
|
||||
atan2 = fn "returns the arctangent of y/x. atan2 is well defined for every point other than the origin, even if x equals 0 and y does not equal 0. - (typeN)(typeN y, typeN x)",
|
||||
ceil = fn "returns smallest integer not less than a scalar or each vector component. - (typeN)(typeN)",
|
||||
clamp = fn "returns x clamped to the range [a,b]. - (typeN)(typeN x, a, b)",
|
||||
clip = fn "conditionally (<0) kill a pixel before output. - ()(typeN)",
|
||||
cos = fn "returns cosine of scalars and vectors. - (typeN)(typeN)",
|
||||
cosh = fn "returns hyperbolic cosine of scalars and vectors. - (typeN)(typeN)",
|
||||
cross = fn "returns the cross product of two three-component vectors. - (type3)(type3 a, b)",
|
||||
ddx = fn "returns approximate partial derivative with respect to window-space X. - (typeN)(typeN)",
|
||||
ddy = fn "returns approximate partial derivative with respect to window-space Y. - (typeN)(typeN)",
|
||||
degrees = fn "converts values of scalars and vectors from radians to degrees. - (typeN)(typeN)",
|
||||
determinant = fn "returns the scalar determinant of a square matrix. - (float)(floatNxN)",
|
||||
distance = fn "return the Euclidean distance between two points. - (typeN)(typeN a, b)",
|
||||
dot = fn "returns the scalar dot product of two vectors. - (type)(typeN a, b)",
|
||||
exp = fn "returns the base-e exponential of scalars and vectors. - (typeN)(typeN)",
|
||||
exp2 = fn "returns the base-2 exponential of scalars and vectors. - (typeN)(typeN)",
|
||||
faceforward = fn "returns a normal as-is if a vertex's eye-space position vector points in the opposite direction of a geometric normal, otherwise return the negated version of the normal. - (typeN)(typeN Nperturbated, Incident, Ngeometric)",
|
||||
floatToIntBits = fn "returns the 32-bit integer representation of an IEEE 754 floating-point scalar or vector - (intN)(floatN)",
|
||||
floatToRawIntBits = fn "returns the raw 32-bit integer representation of an IEEE 754 floating-point scalar or vector. - (intN)(floatN)",
|
||||
floor = fn "returns largest integer not greater than a scalar or each vector component. - (typeN)(typeN)",
|
||||
fmod = fn "returns the remainder of x/y with the same sign as x. - (typeN)(typeN x, y)",
|
||||
frac = fn "returns the fractional portion of a scalar or each vector component. - (typeN)(typeN)",
|
||||
frexp = fn "splits scalars and vectors into normalized fraction and a power of 2. - (typeN)(typeN x, out typeN e)",
|
||||
fwidth = fn "returns sum of approximate window-space partial derivatives magnitudes. - (typeN)(typeN)",
|
||||
intBitsToFloat = fn "returns the float value corresponding to a given bit represention.of a scalar int value or vector of int values. - (floatN)(intN)",
|
||||
isfinite = fn "test whether or not a scalar or each vector component is a finite value. - (boolN)(typeN)",
|
||||
isinf = fn "test whether or not a scalar or each vector component is infinite. - (boolN)(typeN)",
|
||||
isnan = fn "test whether or not a scalar or each vector component is not-a-number. - (boolN)(typeN)",
|
||||
ldexp = fn "returns x times 2 rained to n. - (typeN)(typeN a, n)",
|
||||
length = fn "return scalar Euclidean length of a vector. - (type)(typeN)",
|
||||
lerp = fn "lerp - returns linear interpolation of two scalars or vectors based on a weight. - (typeN)(typeN a, b, weight)",
|
||||
lit = fn "computes lighting coefficients for ambient(x), diffuse(y), and specular(z) lighting contributions (w=1). - (type4)(type NdotL, NdotH, specshiny)",
|
||||
log = fn "returns the natural logarithm of scalars and vectors. - (typeN)(typeN)",
|
||||
log10 = fn "returns the base-10 logarithm of scalars and vectors. - (typeN)(typeN)",
|
||||
log2 = fn "returns the base-2 logarithm of scalars and vectors. - (typeN)(typeN)",
|
||||
max = fn "returns the maximum of two scalars or each respective component of two vectors. - (typeN)(typeN a, b)",
|
||||
min = fn "returns the minimum of two scalars or each respective component of two vectors. - (typeN)(typeN a, b)",
|
||||
mul = fn "Returns the vector result of multiplying a matrix M by a column vector v; a row vector v by a matrix M; or a matrix A by a second matrix B. - (typeN)(typeNxN/typeN a, typeN/typeNxN b)",
|
||||
normalize = fn "Returns the normalized version of a vector, meaning a vector in the same direction as the original vector but with a Euclidean length of one. - (typeN)(typeN)",
|
||||
pow = fn "returns x to the y-th power of scalars and vectors. - (typeN)(typeN x, y)",
|
||||
radians = fn "converts values of scalars and vectors from degrees to radians. - (typeN)(typeN)",
|
||||
reflect = fn "returns the reflectiton vector given an incidence vector and a normal vector. - (typeN)(typeN incidence, normal)",
|
||||
refract = fn "computes a refraction vector. - (typeN)(typeN incidence, normal, type eta)",
|
||||
round = fn "returns the rounded value of scalars or vectors. - (typeN)(typeN a)",
|
||||
rsqrt = fn "returns reciprocal square root of scalars and vectors. 1/sqrt. - (typeN)(typeN)",
|
||||
saturate = fn "returns x saturated to the range [0,1]. - (typeN)(typeN)",
|
||||
sign = fn "returns sign (1 or -1) of scalar or each vector component. - (typeN)(typeN)",
|
||||
sin = fn "returns sine of scalars and vectors. - (typeN)(typeN)",
|
||||
sincos = fn "returns sine of scalars and vectors. - ()(typeN x, out typeN sin, out typeN cos)",
|
||||
sinh = fn "returns hyperbolic sine of scalars and vectors. - (typeN)(typeN)",
|
||||
sqrt = fn "returns square root of scalars and vectors. - (typeN)(typeN)",
|
||||
step = fn "implement a step function returning either zero or one (a <= b). - (typeN)(typeN a, b)",
|
||||
tan = fn "returns tangent of scalars and vectors. - (typeN)(typeN)",
|
||||
tanh = fn "returns hyperbolic tangent of scalars and vectors. - (typeN)(typeN)",
|
||||
transpose = fn "returns transpose matrix of a matrix. - (typeRxC)(typeCxR)",
|
||||
trunc = fn "returns largest integer not greater than a scalar or each vector component. - (typeN)(typeN)",
|
||||
|
||||
tex1D = fn "performs a texture lookup in a given 1D sampler and, in some cases, a shadow comparison (as .y coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler1D, float/float2 s, |float dx, dy|,[int texeloffset])",
|
||||
tex1Dbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dcmpbias = fn "performs a texture lookup with bias and shadow compare in a given sampler (compare as .y, bias as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dcmplod = fn "performs a texture lookup with a specified level of detail and a shadow compare in a given sampler (compare as .y, lod as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler1D, int4 s, [int texeloffset])",
|
||||
tex1Dlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .y for float3 coord, proj in .y or .z) - (float4)(sampler1D, float2/float3 s, [int texeloff])",
|
||||
tex1Dsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler1D, int lod)",
|
||||
|
||||
tex2D = fn "performs a texture lookup in a given 2D sampler and, in some cases, a shadow comparison (as .z coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler2D, float2/float3 s, |float2 dx, dy|,[int texeloffset])",
|
||||
tex2Dbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dcmpbias = fn "performs a texture lookup with bias and shadow compare in a given sampler (compare as .z, bias as .w). - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dcmplod = fn "performs a texture lookup with a specified level of detail and a shadow compare in a given sampler (compare as .y, lod as .w). - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler2D, int4 s, [int texeloffset])",
|
||||
tex2Dlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .z for float3 coord, proj in .z or .w) - (float4)(sampler2D, float3/float4 s, [int texeloff])",
|
||||
tex2Dsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler2D, int lod)",
|
||||
tex2Dgather = fn "returns 4 texels of a given single channel texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler2D, int lod)",
|
||||
|
||||
tex3D = fn "performs a texture lookup in a given 3D sampler. May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler3D, float3 s, {float3 dx, dy},[int texeloffset])",
|
||||
tex3Dbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler3D, float4 s, [int texeloffset])",
|
||||
tex3Dfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler3D, int4 s, [int texeloffset])",
|
||||
tex3Dlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler3D, float4 s, [int texeloffset])",
|
||||
tex3Dproj = fn "performs a texture lookup with projection in a given sampler. (proj in .w) - (float4)(sampler3D, float4 s, [int texeloff])",
|
||||
tex3Dsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler3D, int lod)",
|
||||
|
||||
texBUF = fn "performs an unfiltered texture lookup in a given texture buffer sampler. (only gp4 profiles) - (float4)(samplerBUF, int s)",
|
||||
texBUFsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(samplerBUF, int lod)",
|
||||
|
||||
texRBUF = fn "performs a multi-sampled texture lookup in a renderbuffer. (only gp4 profiles) - (float4)(samplerRBUF, int2 s, int sample)",
|
||||
texRBUFsize = fn "returns the size of a given renderbuffer. (only gp4 profiles) - (int2)(samplerBUF)",
|
||||
|
||||
texCUBE = fn "performs a texture lookup in a given CUBE sampler and, in some cases, a shadow comparison (float4 coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(samplerCUBE, float3/float4 s, |float3 dx, dy|)",
|
||||
texCUBEbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
texCUBElod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
texCUBEproj = fn "performs a texture lookup with projection in a given sampler. (proj in .w) - (float4)(samplerCUBE, float4 s)",
|
||||
texCUBEsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler1D, int lod)",
|
||||
|
||||
texRECT = fn "performs a texture lookup in a given RECT sampler and, in some cases, a shadow comparison (as .z). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(samplerRECT, float2/float3 s, |float2 dx, dy|, [int texeloff])",
|
||||
texRECTbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(samplerRECT, float4 s, [int texeloffset])",
|
||||
texRECTfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(samplerRECT, int4 s, [int texeloffset])",
|
||||
texRECTlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(samplerRECT, float4 s, [int texeloffset])",
|
||||
texRECTproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .z for float3 coord, proj in .z or .w) - (float4)(samplerRECT, float3/float4 s, [int texeloff])",
|
||||
texRECTsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(samplerRECT, int lod)",
|
||||
|
||||
tex1DARRAY = fn "performs a texture lookup in a given 1D sampler array and, in some cases, a shadow comparison (as .z). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler1DARRAY, float2/float3 s, {float dx, dy},[int texeloffset])",
|
||||
tex1DARRAYbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler1DARRAY, float4 s, [int texeloffset])",
|
||||
tex1DARRAYcmpbias = fn "performs a texture lookup with bias and shadow compare in a given sampler (layer as .y, compare as .z, bias as .w). - (float4)(sampler1DARRAY, float4 s, [int texeloffset])",
|
||||
tex1DARRAYcmplod = fn "performs a texture lookup with a specified level of detail and a shadow compare in a given sampler (compare as .z, lod as .w). - (float4)(sampler1DARRAY, float4 s, [int texeloffset])",
|
||||
tex1DARRAYfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .z). - (float4)(sampler1DARRAY, int3 s, [int texeloffset])",
|
||||
tex1DARRAYlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .z) - (float4)(sampler1DARRAY, float3 s, [int texeloffset])",
|
||||
tex1DARRAYproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .z for float3 coord, proj in .z or .w) - (float4)(sampler1DARRAY, float3/float4 s, [int texeloff])",
|
||||
tex1DARRAYsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler1DARRAY, int lod)",
|
||||
|
||||
tex2DARRAY = fn "performs a texture lookup in a given 2D sampler array and, in some cases, a shadow comparison (as .w coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler2DARRAY, float3/float4 s, {float2 dx, dy},[int texeloffset])",
|
||||
tex2DARRAYbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler2DARRAY, float4 s, [int texeloffset])",
|
||||
tex2DARRAYfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler2DARRAY, int4 s, [int texeloffset])",
|
||||
tex2DARRAYlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler2DARRAY, float4 s, [int texeloffset])",
|
||||
tex2DARRAYproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (proj in .w) - (float4)(sampler2DARRAY, float4 s, [int texeloff])",
|
||||
tex2DARRAYsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler2DARRAY, int lod)",
|
||||
|
||||
texCUBEARRAY = fn "performs a texture lookup in a given CUBE sampler array. May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(samplerCUBEARRAY, float4 s, {float3 dx, dy},[int texeloffset])",
|
||||
texCUBEARRAYsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(samplerCUBEARRAY, int lod)",
|
||||
|
||||
unpack_4ubyte = fn "interprets the single float as 4 normalized unsigned bytes and returns the vector. (only nv/gp4 profiles) - (float4)(float)",
|
||||
pack_4ubyte = fn "packs the floats into a single storing as normalized unsigned bytes.(only nv/gp4 profiles) - (float)(float4)",
|
||||
unpack_4byte = fn "interprets the single float as 4 normalized signed bytes and returns the vector. (only nv/gp4 profiles) - (float4)(float)",
|
||||
pack_4ubyte = fn "packs the floats into a single storing as normalized signed bytes.(only nv/gp4 profiles) - (float)(float4)",
|
||||
unpack_4ushort = fn "interprets the single float as 2 normalized unsigned shorts and returns the vector. (only nv/gp4 profiles) - (float2)(float)",
|
||||
pack_4ushort = fn "packs the floats into a single storing as normalized unsigned shorts.(only nv/gp4 profiles) - (float)(float2)",
|
||||
unpack_2half = fn "interprets the single float as 2 16-bit floats and returns the vector. (only nv/gp4 profiles) - (float2)(float)",
|
||||
pack_2half = fn "packs the floats into a single storing as 16-bit floats.(only nv/gp4 profiles) - (float)(float2)",
|
||||
}
|
||||
|
||||
local keyw =
|
||||
[[int half float float3 float4 float2 float3x3 float3x4 float4x3 float4x4
|
||||
float1x2 float2x1 float2x2 float2x3 float3x2 float1x3 float3x1 float4x1 float1x4
|
||||
float2x4 float4x2 double1x4 double4x4 double4x2 double4x3 double3x4 double2x4 double1x4
|
||||
double half half2 half3 half4 int2 int3 uint uint2 uint3 uint4
|
||||
int4 bool bool2 bool3 bool4 string struct typedef
|
||||
usampler usampler1D usampler2D usampler3D usamplerRECT usamplerCUBE isampler1DARRAY usampler2DARRAY usamplerCUBEARRAY
|
||||
isampler isampler1D isampler2D isampler3D isamplerRECT isamplerCUBE isampler1DARRAY isampler2DARRAY isamplerCUBEARRAY
|
||||
usamplerBUF isamplerBUF samplerBUF
|
||||
sampler sampler1D sampler2D sampler3D samplerRECT samplerCUBE sampler1DARRAY sampler2DARRAY samplerCUBEARRAY
|
||||
texture texture1D texture2D texture3D textureRECT textureCUBE texture1DARRAY texture2DARRAY textureCUBEARRAY
|
||||
|
||||
decl do else extern false for if in inline inout out pass
|
||||
pixelshader return shared static string technique true
|
||||
uniform vector vertexshader void volatile while
|
||||
|
||||
asm compile const auto break case catch char class const_cast continue default delete
|
||||
dynamic_cast enum explicit friend goto long mutable namespace new operator private protected
|
||||
public register reinterpret_case short signed sizeof static_cast switch template this throw
|
||||
try typename union unsigned using virtual
|
||||
|
||||
POSITION PSIZE DIFFUSE SPECULAR TEXCOORD FOG COLOR COLOR0 COLOR1 COLOR2 COLOR3 TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3
|
||||
TEXCOORD4 TEXCOORD5 TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9 TEXCOORD10 TEXCOORD11 TEXCOORD12 TEXCOORD13 TEXCOORD14
|
||||
TEXCOORD15
|
||||
NORMAL WPOS
|
||||
ATTR0 ATTR1 ATTR2 ATTR3 ATTR4 ATTR5 ATTR6 ATTR7 ATTR8 ATTR9 ATTR10 ATTR11 ATTR12 ATTR13 ATTR14 ATTR15
|
||||
TEXUNIT0 TEXUNIT1 TEXUNIT2 TEXUNIT3 TEXUNIT4 TEXUNIT5 TEXUNIT6 TEXUNIT7 TEXUNIT8 TEXUNIT9 TEXUNIT10 TEXUNIT11 TEXUNIT12
|
||||
TEXUNIT13 TEXUNIT14 TEXUNIT15
|
||||
|
||||
PROJ PROJECTION PROJECTIONMATRIX PROJMATRIX
|
||||
PROJMATRIXINV PROJINV PROJECTIONINV PROJINVERSE PROJECTIONINVERSE PROJINVMATRIX PROJECTIONINVMATRIX PROJINVERSEMATRIX PROJECTIONINVERSEMATRIX
|
||||
VIEW VIEWMATRIX VIEWMATRIXINV VIEWINV VIEWINVERSE VIEWINVERSEMATRIX VIEWINVMATRIX
|
||||
VIEWPROJECTION VIEWPROJ VIEWPROJMATRIX VIEWPROJECTIONMATRIX
|
||||
WORLD WORLDMATRIX WORLDVIEW WORLDVIEWMATRIX
|
||||
WORLDVIEWPROJ WORLDVIEWPROJECTION WORLDVIEWPROJMATRIX WORLDVIEWPROJECTIONMATRIX
|
||||
VIEWPORTSIZE VIEWPORTDIMENSION
|
||||
VIEWPORTSIZEINV VIEWPORTSIZEINVERSE VIEWPORTDIMENSIONINV VIEWPORTDIMENSIONINVERSE INVERSEVIEWPORTDIMENSIONS
|
||||
FOGCOLOR FOGDISTANCE CAMERAWORLDPOS CAMERAWORLDDIR
|
||||
|
||||
CENTROID FLAT NOPERSPECTIVE FACE PRIMITIVEID VERTEXID
|
||||
|
||||
]]
|
||||
|
||||
-- keywords - shouldn't be left out
|
||||
for w in keyw:gmatch("([_%w]+)") do
|
||||
api[w] = {type="keyword"}
|
||||
end
|
||||
|
||||
return api
|
||||
|
||||
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
local function fn (description)
|
||||
local description2,returns,args = description:match("(.+)%-%s*(%b())%s*(%b())")
|
||||
if not description2 then
|
||||
return {type="function",description=description,
|
||||
returns="(?)"}
|
||||
end
|
||||
return {type="function",description=description2,
|
||||
returns=returns:gsub("^%s+",""):gsub("%s+$",""), args = args}
|
||||
end
|
||||
|
||||
local function val (description)
|
||||
return {type="value",description = description}
|
||||
end
|
||||
-- docs
|
||||
local api = {
|
||||
abs = fn "returns absolute value of scalars and vectors. - (typeN)(typeN)",
|
||||
acos = fn "returns arccosine of scalars and vectors. - (typeN)(typeN)",
|
||||
all = fn "returns true if a boolean scalar or all components of a boolean vector are true. - (bool)(boolN)",
|
||||
any = fn "returns true if a boolean scalar or any component of a boolean vector is true. - (bool)(boolN)",
|
||||
asin = fn "returns arcsine of scalars and vectors. - (typeN)(typeN)",
|
||||
atan = fn "returns arctangent of scalars and vectors. - (typeN)(typeN)",
|
||||
atan2 = fn "returns the arctangent of y/x. atan2 is well defined for every point other than the origin, even if x equals 0 and y does not equal 0. - (typeN)(typeN y, typeN x)",
|
||||
ceil = fn "returns smallest integer not less than a scalar or each vector component. - (typeN)(typeN)",
|
||||
clamp = fn "returns x clamped to the range [a,b]. - (typeN)(typeN x, a, b)",
|
||||
clip = fn "conditionally (<0) kill a pixel before output. - ()(typeN)",
|
||||
cos = fn "returns cosine of scalars and vectors. - (typeN)(typeN)",
|
||||
cosh = fn "returns hyperbolic cosine of scalars and vectors. - (typeN)(typeN)",
|
||||
cross = fn "returns the cross product of two three-component vectors. - (type3)(type3 a, b)",
|
||||
ddx = fn "returns approximate partial derivative with respect to window-space X. - (typeN)(typeN)",
|
||||
ddy = fn "returns approximate partial derivative with respect to window-space Y. - (typeN)(typeN)",
|
||||
degrees = fn "converts values of scalars and vectors from radians to degrees. - (typeN)(typeN)",
|
||||
determinant = fn "returns the scalar determinant of a square matrix. - (float)(floatNxN)",
|
||||
distance = fn "return the Euclidean distance between two points. - (typeN)(typeN a, b)",
|
||||
dot = fn "returns the scalar dot product of two vectors. - (type)(typeN a, b)",
|
||||
exp = fn "returns the base-e exponential of scalars and vectors. - (typeN)(typeN)",
|
||||
exp2 = fn "returns the base-2 exponential of scalars and vectors. - (typeN)(typeN)",
|
||||
faceforward = fn "returns a normal as-is if a vertex's eye-space position vector points in the opposite direction of a geometric normal, otherwise return the negated version of the normal. - (typeN)(typeN Nperturbated, Incident, Ngeometric)",
|
||||
floatToIntBits = fn "returns the 32-bit integer representation of an IEEE 754 floating-point scalar or vector - (intN)(floatN)",
|
||||
floatToRawIntBits = fn "returns the raw 32-bit integer representation of an IEEE 754 floating-point scalar or vector. - (intN)(floatN)",
|
||||
floor = fn "returns largest integer not greater than a scalar or each vector component. - (typeN)(typeN)",
|
||||
fmod = fn "returns the remainder of x/y with the same sign as x. - (typeN)(typeN x, y)",
|
||||
frac = fn "returns the fractional portion of a scalar or each vector component. - (typeN)(typeN)",
|
||||
frexp = fn "splits scalars and vectors into normalized fraction and a power of 2. - (typeN)(typeN x, out typeN e)",
|
||||
fwidth = fn "returns sum of approximate window-space partial derivatives magnitudes. - (typeN)(typeN)",
|
||||
intBitsToFloat = fn "returns the float value corresponding to a given bit represention.of a scalar int value or vector of int values. - (floatN)(intN)",
|
||||
isfinite = fn "test whether or not a scalar or each vector component is a finite value. - (boolN)(typeN)",
|
||||
isinf = fn "test whether or not a scalar or each vector component is infinite. - (boolN)(typeN)",
|
||||
isnan = fn "test whether or not a scalar or each vector component is not-a-number. - (boolN)(typeN)",
|
||||
ldexp = fn "returns x times 2 rained to n. - (typeN)(typeN a, n)",
|
||||
length = fn "return scalar Euclidean length of a vector. - (type)(typeN)",
|
||||
lerp = fn "lerp - returns linear interpolation of two scalars or vectors based on a weight. - (typeN)(typeN a, b, weight)",
|
||||
lit = fn "computes lighting coefficients for ambient(x), diffuse(y), and specular(z) lighting contributions (w=1). - (type4)(type NdotL, NdotH, specshiny)",
|
||||
log = fn "returns the natural logarithm of scalars and vectors. - (typeN)(typeN)",
|
||||
log10 = fn "returns the base-10 logarithm of scalars and vectors. - (typeN)(typeN)",
|
||||
log2 = fn "returns the base-2 logarithm of scalars and vectors. - (typeN)(typeN)",
|
||||
max = fn "returns the maximum of two scalars or each respective component of two vectors. - (typeN)(typeN a, b)",
|
||||
min = fn "returns the minimum of two scalars or each respective component of two vectors. - (typeN)(typeN a, b)",
|
||||
mul = fn "Returns the vector result of multiplying a matrix M by a column vector v; a row vector v by a matrix M; or a matrix A by a second matrix B. - (typeN)(typeNxN/typeN a, typeN/typeNxN b)",
|
||||
normalize = fn "Returns the normalized version of a vector, meaning a vector in the same direction as the original vector but with a Euclidean length of one. - (typeN)(typeN)",
|
||||
pow = fn "returns x to the y-th power of scalars and vectors. - (typeN)(typeN x, y)",
|
||||
radians = fn "converts values of scalars and vectors from degrees to radians. - (typeN)(typeN)",
|
||||
reflect = fn "returns the reflectiton vector given an incidence vector and a normal vector. - (typeN)(typeN incidence, normal)",
|
||||
refract = fn "computes a refraction vector. - (typeN)(typeN incidence, normal, type eta)",
|
||||
round = fn "returns the rounded value of scalars or vectors. - (typeN)(typeN a)",
|
||||
rsqrt = fn "returns reciprocal square root of scalars and vectors. 1/sqrt. - (typeN)(typeN)",
|
||||
saturate = fn "returns x saturated to the range [0,1]. - (typeN)(typeN)",
|
||||
sign = fn "returns sign (1 or -1) of scalar or each vector component. - (typeN)(typeN)",
|
||||
sin = fn "returns sine of scalars and vectors. - (typeN)(typeN)",
|
||||
sincos = fn "returns sine of scalars and vectors. - ()(typeN x, out typeN sin, out typeN cos)",
|
||||
sinh = fn "returns hyperbolic sine of scalars and vectors. - (typeN)(typeN)",
|
||||
sqrt = fn "returns square root of scalars and vectors. - (typeN)(typeN)",
|
||||
step = fn "implement a step function returning either zero or one (a <= b). - (typeN)(typeN a, b)",
|
||||
tan = fn "returns tangent of scalars and vectors. - (typeN)(typeN)",
|
||||
tanh = fn "returns hyperbolic tangent of scalars and vectors. - (typeN)(typeN)",
|
||||
transpose = fn "returns transpose matrix of a matrix. - (typeRxC)(typeCxR)",
|
||||
trunc = fn "returns largest integer not greater than a scalar or each vector component. - (typeN)(typeN)",
|
||||
|
||||
tex1D = fn "performs a texture lookup in a given 1D sampler and, in some cases, a shadow comparison (as .y coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler1D, float/float2 s, |float dx, dy|,[int texeloffset])",
|
||||
tex1Dbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dcmpbias = fn "performs a texture lookup with bias and shadow compare in a given sampler (compare as .y, bias as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dcmplod = fn "performs a texture lookup with a specified level of detail and a shadow compare in a given sampler (compare as .y, lod as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler1D, int4 s, [int texeloffset])",
|
||||
tex1Dlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
tex1Dproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .y for float3 coord, proj in .y or .z) - (float4)(sampler1D, float2/float3 s, [int texeloff])",
|
||||
tex1Dsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler1D, int lod)",
|
||||
|
||||
tex2D = fn "performs a texture lookup in a given 2D sampler and, in some cases, a shadow comparison (as .z coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler2D, float2/float3 s, |float2 dx, dy|,[int texeloffset])",
|
||||
tex2Dbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dcmpbias = fn "performs a texture lookup with bias and shadow compare in a given sampler (compare as .z, bias as .w). - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dcmplod = fn "performs a texture lookup with a specified level of detail and a shadow compare in a given sampler (compare as .y, lod as .w). - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler2D, int4 s, [int texeloffset])",
|
||||
tex2Dlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler2D, float4 s, [int texeloffset])",
|
||||
tex2Dproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .z for float3 coord, proj in .z or .w) - (float4)(sampler2D, float3/float4 s, [int texeloff])",
|
||||
tex2Dsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler2D, int lod)",
|
||||
tex2Dgather = fn "returns 4 texels of a given single channel texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler2D, int lod)",
|
||||
|
||||
tex3D = fn "performs a texture lookup in a given 3D sampler. May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler3D, float3 s, {float3 dx, dy},[int texeloffset])",
|
||||
tex3Dbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler3D, float4 s, [int texeloffset])",
|
||||
tex3Dfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler3D, int4 s, [int texeloffset])",
|
||||
tex3Dlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler3D, float4 s, [int texeloffset])",
|
||||
tex3Dproj = fn "performs a texture lookup with projection in a given sampler. (proj in .w) - (float4)(sampler3D, float4 s, [int texeloff])",
|
||||
tex3Dsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler3D, int lod)",
|
||||
|
||||
texBUF = fn "performs an unfiltered texture lookup in a given texture buffer sampler. (only gp4 profiles) - (float4)(samplerBUF, int s)",
|
||||
texBUFsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(samplerBUF, int lod)",
|
||||
|
||||
texRBUF = fn "performs a multi-sampled texture lookup in a renderbuffer. (only gp4 profiles) - (float4)(samplerRBUF, int2 s, int sample)",
|
||||
texRBUFsize = fn "returns the size of a given renderbuffer. (only gp4 profiles) - (int2)(samplerBUF)",
|
||||
|
||||
texCUBE = fn "performs a texture lookup in a given CUBE sampler and, in some cases, a shadow comparison (float4 coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(samplerCUBE, float3/float4 s, |float3 dx, dy|)",
|
||||
texCUBEbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
texCUBElod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler1D, float4 s, [int texeloffset])",
|
||||
texCUBEproj = fn "performs a texture lookup with projection in a given sampler. (proj in .w) - (float4)(samplerCUBE, float4 s)",
|
||||
texCUBEsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler1D, int lod)",
|
||||
|
||||
texRECT = fn "performs a texture lookup in a given RECT sampler and, in some cases, a shadow comparison (as .z). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(samplerRECT, float2/float3 s, |float2 dx, dy|, [int texeloff])",
|
||||
texRECTbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(samplerRECT, float4 s, [int texeloffset])",
|
||||
texRECTfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(samplerRECT, int4 s, [int texeloffset])",
|
||||
texRECTlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(samplerRECT, float4 s, [int texeloffset])",
|
||||
texRECTproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .z for float3 coord, proj in .z or .w) - (float4)(samplerRECT, float3/float4 s, [int texeloff])",
|
||||
texRECTsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(samplerRECT, int lod)",
|
||||
|
||||
tex1DARRAY = fn "performs a texture lookup in a given 1D sampler array and, in some cases, a shadow comparison (as .z). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler1DARRAY, float2/float3 s, {float dx, dy},[int texeloffset])",
|
||||
tex1DARRAYbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler1DARRAY, float4 s, [int texeloffset])",
|
||||
tex1DARRAYcmpbias = fn "performs a texture lookup with bias and shadow compare in a given sampler (layer as .y, compare as .z, bias as .w). - (float4)(sampler1DARRAY, float4 s, [int texeloffset])",
|
||||
tex1DARRAYcmplod = fn "performs a texture lookup with a specified level of detail and a shadow compare in a given sampler (compare as .z, lod as .w). - (float4)(sampler1DARRAY, float4 s, [int texeloffset])",
|
||||
tex1DARRAYfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .z). - (float4)(sampler1DARRAY, int3 s, [int texeloffset])",
|
||||
tex1DARRAYlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .z) - (float4)(sampler1DARRAY, float3 s, [int texeloffset])",
|
||||
tex1DARRAYproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (shadow in .z for float3 coord, proj in .z or .w) - (float4)(sampler1DARRAY, float3/float4 s, [int texeloff])",
|
||||
tex1DARRAYsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler1DARRAY, int lod)",
|
||||
|
||||
tex2DARRAY = fn "performs a texture lookup in a given 2D sampler array and, in some cases, a shadow comparison (as .w coord). May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(sampler2DARRAY, float3/float4 s, {float2 dx, dy},[int texeloffset])",
|
||||
tex2DARRAYbias = fn "performs a texture lookup with bias in a given sampler (as .w). - (float4)(sampler2DARRAY, float4 s, [int texeloffset])",
|
||||
tex2DARRAYfetch = fn "performs an unfiltered texture lookup in a given sampler (lod as .w). - (float4)(sampler2DARRAY, int4 s, [int texeloffset])",
|
||||
tex2DARRAYlod = fn "performs a texture lookup with a specified level of detail in a given sampler (lod as .w) - (float4)(sampler2DARRAY, float4 s, [int texeloffset])",
|
||||
tex2DARRAYproj = fn "performs a texture lookup with projection in a given sampler. May perform a shadow comparison if argument for shadow comparison is provided. (proj in .w) - (float4)(sampler2DARRAY, float4 s, [int texeloff])",
|
||||
tex2DARRAYsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(sampler2DARRAY, int lod)",
|
||||
|
||||
texCUBEARRAY = fn "performs a texture lookup in a given CUBE sampler array. May also use pre computed derivatives if those are provided. Texeloffset only in gp4 or higher profiles. - (float4)(samplerCUBEARRAY, float4 s, {float3 dx, dy},[int texeloffset])",
|
||||
texCUBEARRAYsize = fn "returns the size of a given texture image for a given level of detail. (only gp4 profiles) - (int3)(samplerCUBEARRAY, int lod)",
|
||||
|
||||
unpack_4ubyte = fn "interprets the single float as 4 normalized unsigned bytes and returns the vector. (only nv/gp4 profiles) - (float4)(float)",
|
||||
pack_4ubyte = fn "packs the floats into a single storing as normalized unsigned bytes.(only nv/gp4 profiles) - (float)(float4)",
|
||||
unpack_4byte = fn "interprets the single float as 4 normalized signed bytes and returns the vector. (only nv/gp4 profiles) - (float4)(float)",
|
||||
pack_4ubyte = fn "packs the floats into a single storing as normalized signed bytes.(only nv/gp4 profiles) - (float)(float4)",
|
||||
unpack_4ushort = fn "interprets the single float as 2 normalized unsigned shorts and returns the vector. (only nv/gp4 profiles) - (float2)(float)",
|
||||
pack_4ushort = fn "packs the floats into a single storing as normalized unsigned shorts.(only nv/gp4 profiles) - (float)(float2)",
|
||||
unpack_2half = fn "interprets the single float as 2 16-bit floats and returns the vector. (only nv/gp4 profiles) - (float2)(float)",
|
||||
pack_2half = fn "packs the floats into a single storing as 16-bit floats.(only nv/gp4 profiles) - (float)(float2)",
|
||||
}
|
||||
|
||||
local keyw =
|
||||
[[int half float float3 float4 float2 float3x3 float3x4 float4x3 float4x4
|
||||
float1x2 float2x1 float2x2 float2x3 float3x2 float1x3 float3x1 float4x1 float1x4
|
||||
float2x4 float4x2 double1x4 double4x4 double4x2 double4x3 double3x4 double2x4 double1x4
|
||||
double half half2 half3 half4 int2 int3 uint uint2 uint3 uint4
|
||||
int4 bool bool2 bool3 bool4 string struct typedef
|
||||
usampler usampler1D usampler2D usampler3D usamplerRECT usamplerCUBE isampler1DARRAY usampler2DARRAY usamplerCUBEARRAY
|
||||
isampler isampler1D isampler2D isampler3D isamplerRECT isamplerCUBE isampler1DARRAY isampler2DARRAY isamplerCUBEARRAY
|
||||
usamplerBUF isamplerBUF samplerBUF
|
||||
sampler sampler1D sampler2D sampler3D samplerRECT samplerCUBE sampler1DARRAY sampler2DARRAY samplerCUBEARRAY
|
||||
texture texture1D texture2D texture3D textureRECT textureCUBE texture1DARRAY texture2DARRAY textureCUBEARRAY
|
||||
|
||||
decl do else extern false for if in inline inout out pass
|
||||
pixelshader return shared static string technique true
|
||||
uniform vector vertexshader void volatile while
|
||||
|
||||
asm compile const auto break case catch char class const_cast continue default delete
|
||||
dynamic_cast enum explicit friend goto long mutable namespace new operator private protected
|
||||
public register reinterpret_case short signed sizeof static_cast switch template this throw
|
||||
try typename union unsigned using virtual
|
||||
|
||||
POSITION PSIZE DIFFUSE SPECULAR TEXCOORD FOG COLOR COLOR0 COLOR1 COLOR2 COLOR3 TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3
|
||||
TEXCOORD4 TEXCOORD5 TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9 TEXCOORD10 TEXCOORD11 TEXCOORD12 TEXCOORD13 TEXCOORD14
|
||||
TEXCOORD15
|
||||
NORMAL WPOS
|
||||
ATTR0 ATTR1 ATTR2 ATTR3 ATTR4 ATTR5 ATTR6 ATTR7 ATTR8 ATTR9 ATTR10 ATTR11 ATTR12 ATTR13 ATTR14 ATTR15
|
||||
TEXUNIT0 TEXUNIT1 TEXUNIT2 TEXUNIT3 TEXUNIT4 TEXUNIT5 TEXUNIT6 TEXUNIT7 TEXUNIT8 TEXUNIT9 TEXUNIT10 TEXUNIT11 TEXUNIT12
|
||||
TEXUNIT13 TEXUNIT14 TEXUNIT15
|
||||
|
||||
PROJ PROJECTION PROJECTIONMATRIX PROJMATRIX
|
||||
PROJMATRIXINV PROJINV PROJECTIONINV PROJINVERSE PROJECTIONINVERSE PROJINVMATRIX PROJECTIONINVMATRIX PROJINVERSEMATRIX PROJECTIONINVERSEMATRIX
|
||||
VIEW VIEWMATRIX VIEWMATRIXINV VIEWINV VIEWINVERSE VIEWINVERSEMATRIX VIEWINVMATRIX
|
||||
VIEWPROJECTION VIEWPROJ VIEWPROJMATRIX VIEWPROJECTIONMATRIX
|
||||
WORLD WORLDMATRIX WORLDVIEW WORLDVIEWMATRIX
|
||||
WORLDVIEWPROJ WORLDVIEWPROJECTION WORLDVIEWPROJMATRIX WORLDVIEWPROJECTIONMATRIX
|
||||
VIEWPORTSIZE VIEWPORTDIMENSION
|
||||
VIEWPORTSIZEINV VIEWPORTSIZEINVERSE VIEWPORTDIMENSIONINV VIEWPORTDIMENSIONINVERSE INVERSEVIEWPORTDIMENSIONS
|
||||
FOGCOLOR FOGDISTANCE CAMERAWORLDPOS CAMERAWORLDDIR
|
||||
|
||||
CENTROID FLAT NOPERSPECTIVE FACE PRIMITIVEID VERTEXID
|
||||
|
||||
]]
|
||||
|
||||
-- keywords - shouldn't be left out
|
||||
for w in keyw:gmatch("([_%w]+)") do
|
||||
api[w] = {type="keyword"}
|
||||
end
|
||||
|
||||
return api
|
||||
|
||||
|
||||
|
||||
@@ -1,200 +1,200 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
-- function helpers
|
||||
|
||||
local function fn (description)
|
||||
local description2,returns,args = description:match("(.+)%-%s*(%b())%s*(%b())")
|
||||
if not description2 then
|
||||
return {type="function",description=description,
|
||||
returns="(?)"}
|
||||
end
|
||||
returns = returns:gsub("^%s+",""):gsub("%s+$","")
|
||||
local ret = returns:sub(2,-2)
|
||||
local vt = ret:match("^%[?string") and "string"
|
||||
vt = vt or ret:match("^%[?table") and "table"
|
||||
vt = vt or ret:match("^%[?file") and "io"
|
||||
return {type="function",description=description2,
|
||||
returns=returns, args = args, valuetype = vt}
|
||||
end
|
||||
|
||||
local function val (description)
|
||||
return {type="value",description = description}
|
||||
end
|
||||
-- docs
|
||||
|
||||
local api = {
|
||||
table = {
|
||||
description = "Table functions",
|
||||
type = "lib",
|
||||
childs = {
|
||||
concat = fn "concatenates an array of elements - (string)(table,[sep])",
|
||||
insert = fn "inserts an element into an array - ()(table,idx,element)",
|
||||
remove = fn "removes an element from an array - (element)(table,idx)",
|
||||
maxn = fn "Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. - (number)(table)",
|
||||
sort = fn "Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the length of the table. - ()(table,[comp])"
|
||||
}
|
||||
},
|
||||
|
||||
math = {
|
||||
type = "lib",
|
||||
description = "Math functions",
|
||||
childs = {
|
||||
abs = fn "Returns the absolute value of x. - (number)(number)",
|
||||
acos = fn "Returns the arc cosine of x (in radians). - (number)(number)",
|
||||
asin = fn "Returns the arc sine of x (in radians). - (number)(number)",
|
||||
atan = fn "Returns the arc tangent of x (in radians). - (number)(number)",
|
||||
atan2 = fn "Returns the arc tangent of x/y (in radians), but uses the signs of both parameters to find the quadrant of the result. (It also handles correctly the case of y being zero.) - (number)(number,number)",
|
||||
ceil = fn "Returns the smallest integer larger than or equal to x. - (number)(number)",
|
||||
cos = fn "Returns the cosine of x (assumed to be in radians).",
|
||||
cosh = fn "Returns the hyperbolic cosine of x.",
|
||||
deg = fn "Returns the angle x (given in radians) in degrees.",
|
||||
exp = fn "Returns the the value ex.",
|
||||
floor = fn "Returns the largest integer smaller than or equal to x.",
|
||||
fmod = fn "Returns the remainder of the division of x by y.",
|
||||
frexp = fn "Returns m and e such that x = m2e, e is an integer and the absolute value of m is in the range [0.5, 1) (or zero when x is zero).",
|
||||
huge = val "The value HUGE_VAL, a value larger than or equal to any other numerical value.",
|
||||
ldexp = fn "Returns m2e (e should be an integer).",
|
||||
log = fn "Returns the natural logarithm of x.",
|
||||
log10 = fn "Returns the base-10 logarithm of x.",
|
||||
max = fn "Returns the maximum value among its arguments.",
|
||||
min = fn "Returns the minimum value among its arguments.",
|
||||
modf = fn "Returns two numbers, the integral part of x and the fractional part of x.",
|
||||
pi = val "The value PI.",
|
||||
pow = fn "Returns xy. (You can also use the expression x^y to compute this value.)",
|
||||
rad = fn "Returns the angle x (given in degrees) in radians.",
|
||||
random = fn "This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.) When called without arguments, returns a pseudo-random real number in the range [0,1). When called with a number m, math.random returns a pseudo-random integer in the range [1, m]. When called with two numbers m and n, math.random returns a pseudo-random integer in the range [m, n].",
|
||||
randomseed = fn "Sets x as the \"seed\" for the pseudo-random generator: equal seeds produce equal sequences of numbers.",
|
||||
sin = fn"Returns the sine of x (assumed to be in radians).",
|
||||
sinh = fn"Returns the hyperbolic sine of x.",
|
||||
sqrt = fn "Returns the square root of x. (You can also use the expression x^0.5 to compute this value.)",
|
||||
tan = fn "Returns the tangent of x (assumed to be in radians).",
|
||||
tanh = fn "Returns the hyperbolic tangent of x. "
|
||||
}
|
||||
},
|
||||
|
||||
pairs = fn "returns an iterator function for the given table - (function)(table)",
|
||||
ipairs = fn "returns an iterator function for the given table - (function)(table)",
|
||||
xpcall = fn "calls a function in protected mode - (boolean success, [error string / result])(called,errorfunc)",
|
||||
pcall = fn "calls a function in protected mode - (boolean success, [error string / result])(called, args ...)",
|
||||
print = fn "prints out the arguments - ()(...)",
|
||||
assert = fn "error checking, if first arg is false, error message is thrown - (result)(compute,errormsg)",
|
||||
collectgarbage = fn "garbage collector manipulation - (...)(...)",
|
||||
dofile = fn "compile and execute a file - (...)(...)",
|
||||
error = fn "raise an error - (...)(...)",
|
||||
getfenv = fn "get the function environment for a function - (...)(...)",
|
||||
getmetatable = fn "not yet - (...)(...)",
|
||||
load = fn "not yet - (...)(...)",
|
||||
loadfile = fn "not yet - (...)(...)",
|
||||
loadstring = fn "not yet - (...)(...)",
|
||||
next = fn "not yet - (...)(...)",
|
||||
rawequal = fn "not yet - (...)(...)",
|
||||
rawget = fn "not yet - (...)(...)",
|
||||
rawset = fn "not yet - (...)(...)",
|
||||
select = fn "not yet - (...)(...)",
|
||||
setfenv = fn "not yet - (...)(...)",
|
||||
setmetatable = fn "not yet - (...)(...)",
|
||||
tonumber = fn "not yet - (number)(...)",
|
||||
tostring = fn "not yet - (string)(...)",
|
||||
type = fn "not yet - (string)(...)",
|
||||
unpack = fn "not yet - (...)(...)",
|
||||
|
||||
module = fn "Creates a module. - (?)(name,...)",
|
||||
require = fn "Loads the given module. - (?)(name)",
|
||||
|
||||
package = {
|
||||
type = "table",
|
||||
description = "package info",
|
||||
childs = {
|
||||
cpath = val "The path used by require to search for a C loader. ",
|
||||
loaded = val "A table used by require to control which modules are already loaded.",
|
||||
loadlib = fn "Dynamically links the host program with the C library libname. - (?)(libname, funcname)",
|
||||
path = val "The path used by require to search for a Lua loader. ",
|
||||
preload = val "A table to store loaders for specific modules (see require). ",
|
||||
seeall = fn "Sets a metatable for module with its __index field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function module. - (?)(module)"
|
||||
}
|
||||
},
|
||||
|
||||
string = {
|
||||
type = "lib",
|
||||
description = "string lib",
|
||||
childs = {
|
||||
byte = fn "Returns the internal numerical codes of the characters s[i], s[i+1], ···, s[j]. The default value for i is 1; the default value for j is i. - (number)(string [, i [, j]])",
|
||||
char = fn "Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument. - (string)(...)",
|
||||
dump = fn "Returns a string containing a binary representation of the given function, so that a later loadstring on this string returns a copy of the function. function must be a Lua function without upvalues. - (string)(func)",
|
||||
find = fn "Looks for the first match of pattern in the string s. If it finds a match, then find returns the indices of s where this occurrence starts and ends; otherwise, it returns nil. A third, optional numerical argument init specifies where to start the search; its default value is 1 and may be negative. A value of true as a fourth, optional argument plain turns off the pattern matching facilities, so the function does a plain \"find substring\" operation, with no characters in pattern being considered \"magic\". Note that if plain is given, then init must be given as well. - (number,number)(string, pattern [, init [, plain]])",
|
||||
format = fn "Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the printf family of standard C functions. The only differences are that the options/modifiers *, l, L, n, p, and h are not supported and that there is an extra option, q. The q option formats a string in a form suitable to be safely read back by the Lua interpreter: the string is written between double quotes, and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly escaped when written. - (string)(formatstring, ···)",
|
||||
gmatch = fn "Returns an iterator function that, each time it is called, returns the next captures from pattern over string s. - (func)(string, pattern)",
|
||||
gsub = fn "Returns a copy of s in which all occurrences of the pattern have been replaced by a replacement string specified by repl, which may be a string, a table, or a function. gsub also returns, as its second value, the total number of substitutions made. - (string,number)(string, pattern, repl [, n])",
|
||||
len = fn "Receives a string and returns its length. The empty string '' has length 0. Embedded zeros are counted, so 'a\\000bc\\000' has length 5. - (number)(string)",
|
||||
lower = fn "Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale. - (string)(string)",
|
||||
match = fn "Looks for the first match of pattern in the string s. If it finds one, then match returns the captures from the pattern; otherwise it returns nil. If pattern specifies no captures, then the whole match is returned. A third, optional numerical argument init specifies where to start the search; its default value is 1 and may be negative. - (string,...)(string, pattern [, init])",
|
||||
rep = fn "Returns a string that is the concatenation of n copies of the string s. - (string)(string s, n)",
|
||||
reverse = fn "Returns a string that is the string s reversed. - (string)(string)",
|
||||
sub = fn "Returns the substring of s that starts at i and continues until j; i and j may be negative. If j is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s, -i) returns a suffix of s with length i. - (string)(string, i [, j])",
|
||||
upper = fn "Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale. - (string)(string)",
|
||||
}
|
||||
},
|
||||
|
||||
coroutine = {
|
||||
type = "lib",
|
||||
description = "Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends its execution by explicitly calling a yield function.",
|
||||
childs = {
|
||||
create = fn 'Creates a new coroutine, with body f. f must be a Lua function. Returns this new coroutine, an object with type "thread". - (thread)(function)',
|
||||
resume = fn 'Starts or continues the execution of coroutine co. The first time you resume a coroutine, it starts running its body. The values val1, ··· are passed as the arguments to the body function. If the coroutine has yielded, resume restarts it; the values val1, ··· are passed as the results from the yield. - (boolean success, ...)(coroutine,...)',
|
||||
running = fn 'Returns the running coroutine, or nil when called by the main thread. - ([thread])()',
|
||||
status = fn 'Returns the status of coroutine co, as a string: "running", if the coroutine is running (that is, it called status); "suspended", if the coroutine is suspended in a call to yield, or if it has not started running yet; "normal" if the coroutine is active but not running (that is, it has resumed another coroutine); and "dead" if the coroutine has finished its body function, or if it has stopped with an error. - (status)(coroutine)',
|
||||
wrap = fn 'Creates a new coroutine, with body f. f must be a Lua function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to resume. Returns the same values returned by resume, except the first boolean. In case of error, propagates the error. - (function)(function)',
|
||||
yield = fn 'Suspends the execution of the calling coroutine. The coroutine cannot be running a C function, a metamethod, or an iterator. Any arguments to yield are passed as extra results to resume. - (...)(...)'
|
||||
}
|
||||
},
|
||||
|
||||
io = {
|
||||
type = "lib",
|
||||
description = "The I/O library provides two different styles for file manipulation. The first one uses implicit file descriptors; that is, there are operations to set a default input file and a default output file, and all input/output operations are over these default files. The second style uses explicit file descriptors. ",
|
||||
childs = {
|
||||
close = fn'Equivalent to file:close(). Without a file, closes the default output file. - ()([file])',
|
||||
flush = fn'Equivalent to file:flush over the default output file. - ()([file])',
|
||||
input = fn'When called with a file name, it opens the named file (in text mode), and sets its handle as the default input file. When called with a file handle, it simply sets this file handle as the default input file. When called without parameters, it returns the current default input file. - ([in])([file])',
|
||||
lines = fn'Opens the given file name in read mode and returns an iterator function that, each time it is called, returns a new line from the file. - (function)([file])',
|
||||
open = fn'This function opens a file, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message. - (file,[errormsg])(filename,[mode])',
|
||||
output = fn'Similar to io.input, but operates over the default output file. - ([file])([file])',
|
||||
popen = fn'Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w"). - (file)([prog, [mode]])',
|
||||
read = fn'Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below). - (string)(...)',
|
||||
tmpfile = fn'Returns a handle for a temporary file. This file is opened in update mode and it is automatically removed when the program ends. - (file)()',
|
||||
type = fn'Checks whether obj is a valid file handle. Returns the string "file" if obj is an open file handle, "closed file" if obj is a closed file handle, or nil if obj is not a file handle. - (string)(file)',
|
||||
write = fn'Writes the value of each of its arguments to the file. The arguments must be strings or numbers. To write other values, use tostring or string.format before write. - (?)(...)',
|
||||
seek = fn'Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence - (?)([whence] [, offset])',
|
||||
setvbuf = fn'Sets the buffering mode for an output file. - (?)(mode [, size])',
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
os = {
|
||||
type = "lib",
|
||||
description = ' Operating System Facilities',
|
||||
childs = {
|
||||
clock = fn'Returns an approximation of the amount in seconds of CPU time used by the program. - (seconds)()',
|
||||
date = fn'Returns a string or a table containing date and time, formatted according to the given string format. - (string)([format [, time]])',
|
||||
difftime = fn'Returns the number of seconds from time t1 to time t2. In POSIX, Windows, and some other systems, this value is exactly t2-t1. - (time)(t2,t1)',
|
||||
execute = fn'This function is equivalent to the C function system. It passes command to be executed by an operating system shell. It returns a status code, which is system-dependent. If command is absent, then it returns nonzero if a shell is available and zero otherwise. - (return)([cmd])',
|
||||
exit = fn'Calls the C function exit, with an optional code, to terminate the host program. The default value for code is the success code. - ()([code])',
|
||||
getenv = fn'Returns the value of the process environment variable varname, or nil if the variable is not defined. - ([string])(varname)',
|
||||
remove = fn'Deletes the file or directory with the given name. Directories must be empty to be removed. If this function fails, it returns nil, plus a string describing the error. - (success,[error])(filename)',
|
||||
rename = fn'Renames file or directory named oldname to newname. If this function fails, it returns nil, plus a string describing the error. - (success,[error])(oldname, newname)',
|
||||
setlocale = fn'Sets the current locale of the program. locale is a string specifying a locale; category is an optional string describing which category to change: "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category is "all". The function returns the name of the new locale, or nil if the request cannot be honored. - ([string])(locale [, category])',
|
||||
time = fn'Returns the current time when called without arguments, or a time representing the date and time specified by the given table. This table must have fields year, month, and day, and may have fields hour, min, sec, and isdst (for a description of these fields, see the os.date function). - (time)([table])',
|
||||
tmpname = fn'Returns a string with a file name that can be used for a temporary file. The file must be explicitly opened before its use and explicitly removed when no longer needed. - (string)()',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
local function key (str)
|
||||
api[str] = {type="keyword"}
|
||||
return key
|
||||
end
|
||||
-- keywords - shouldn't be left out
|
||||
key "local" "not" "if" "elseif" "else" "end" "do" "while" "repeat" "function" "until" "or"
|
||||
"or" "and" "then" "true" "false" "return" "break" "in"
|
||||
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
-- function helpers
|
||||
|
||||
local function fn (description)
|
||||
local description2,returns,args = description:match("(.+)%-%s*(%b())%s*(%b())")
|
||||
if not description2 then
|
||||
return {type="function",description=description,
|
||||
returns="(?)"}
|
||||
end
|
||||
returns = returns:gsub("^%s+",""):gsub("%s+$","")
|
||||
local ret = returns:sub(2,-2)
|
||||
local vt = ret:match("^%[?string") and "string"
|
||||
vt = vt or ret:match("^%[?table") and "table"
|
||||
vt = vt or ret:match("^%[?file") and "io"
|
||||
return {type="function",description=description2,
|
||||
returns=returns, args = args, valuetype = vt}
|
||||
end
|
||||
|
||||
local function val (description)
|
||||
return {type="value",description = description}
|
||||
end
|
||||
-- docs
|
||||
|
||||
local api = {
|
||||
table = {
|
||||
description = "Table functions",
|
||||
type = "lib",
|
||||
childs = {
|
||||
concat = fn "concatenates an array of elements - (string)(table,[sep])",
|
||||
insert = fn "inserts an element into an array - ()(table,idx,element)",
|
||||
remove = fn "removes an element from an array - (element)(table,idx)",
|
||||
maxn = fn "Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. - (number)(table)",
|
||||
sort = fn "Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the length of the table. - ()(table,[comp])"
|
||||
}
|
||||
},
|
||||
|
||||
math = {
|
||||
type = "lib",
|
||||
description = "Math functions",
|
||||
childs = {
|
||||
abs = fn "Returns the absolute value of x. - (number)(number)",
|
||||
acos = fn "Returns the arc cosine of x (in radians). - (number)(number)",
|
||||
asin = fn "Returns the arc sine of x (in radians). - (number)(number)",
|
||||
atan = fn "Returns the arc tangent of x (in radians). - (number)(number)",
|
||||
atan2 = fn "Returns the arc tangent of x/y (in radians), but uses the signs of both parameters to find the quadrant of the result. (It also handles correctly the case of y being zero.) - (number)(number,number)",
|
||||
ceil = fn "Returns the smallest integer larger than or equal to x. - (number)(number)",
|
||||
cos = fn "Returns the cosine of x (assumed to be in radians).",
|
||||
cosh = fn "Returns the hyperbolic cosine of x.",
|
||||
deg = fn "Returns the angle x (given in radians) in degrees.",
|
||||
exp = fn "Returns the the value ex.",
|
||||
floor = fn "Returns the largest integer smaller than or equal to x.",
|
||||
fmod = fn "Returns the remainder of the division of x by y.",
|
||||
frexp = fn "Returns m and e such that x = m2e, e is an integer and the absolute value of m is in the range [0.5, 1) (or zero when x is zero).",
|
||||
huge = val "The value HUGE_VAL, a value larger than or equal to any other numerical value.",
|
||||
ldexp = fn "Returns m2e (e should be an integer).",
|
||||
log = fn "Returns the natural logarithm of x.",
|
||||
log10 = fn "Returns the base-10 logarithm of x.",
|
||||
max = fn "Returns the maximum value among its arguments.",
|
||||
min = fn "Returns the minimum value among its arguments.",
|
||||
modf = fn "Returns two numbers, the integral part of x and the fractional part of x.",
|
||||
pi = val "The value PI.",
|
||||
pow = fn "Returns xy. (You can also use the expression x^y to compute this value.)",
|
||||
rad = fn "Returns the angle x (given in degrees) in radians.",
|
||||
random = fn "This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.) When called without arguments, returns a pseudo-random real number in the range [0,1). When called with a number m, math.random returns a pseudo-random integer in the range [1, m]. When called with two numbers m and n, math.random returns a pseudo-random integer in the range [m, n].",
|
||||
randomseed = fn "Sets x as the \"seed\" for the pseudo-random generator: equal seeds produce equal sequences of numbers.",
|
||||
sin = fn"Returns the sine of x (assumed to be in radians).",
|
||||
sinh = fn"Returns the hyperbolic sine of x.",
|
||||
sqrt = fn "Returns the square root of x. (You can also use the expression x^0.5 to compute this value.)",
|
||||
tan = fn "Returns the tangent of x (assumed to be in radians).",
|
||||
tanh = fn "Returns the hyperbolic tangent of x. "
|
||||
}
|
||||
},
|
||||
|
||||
pairs = fn "returns an iterator function for the given table - (function)(table)",
|
||||
ipairs = fn "returns an iterator function for the given table - (function)(table)",
|
||||
xpcall = fn "calls a function in protected mode - (boolean success, [error string / result])(called,errorfunc)",
|
||||
pcall = fn "calls a function in protected mode - (boolean success, [error string / result])(called, args ...)",
|
||||
print = fn "prints out the arguments - ()(...)",
|
||||
assert = fn "error checking, if first arg is false, error message is thrown - (result)(compute,errormsg)",
|
||||
collectgarbage = fn "garbage collector manipulation - (...)(...)",
|
||||
dofile = fn "compile and execute a file - (...)(...)",
|
||||
error = fn "raise an error - (...)(...)",
|
||||
getfenv = fn "get the function environment for a function - (...)(...)",
|
||||
getmetatable = fn "not yet - (...)(...)",
|
||||
load = fn "not yet - (...)(...)",
|
||||
loadfile = fn "not yet - (...)(...)",
|
||||
loadstring = fn "not yet - (...)(...)",
|
||||
next = fn "not yet - (...)(...)",
|
||||
rawequal = fn "not yet - (...)(...)",
|
||||
rawget = fn "not yet - (...)(...)",
|
||||
rawset = fn "not yet - (...)(...)",
|
||||
select = fn "not yet - (...)(...)",
|
||||
setfenv = fn "not yet - (...)(...)",
|
||||
setmetatable = fn "not yet - (...)(...)",
|
||||
tonumber = fn "not yet - (number)(...)",
|
||||
tostring = fn "not yet - (string)(...)",
|
||||
type = fn "not yet - (string)(...)",
|
||||
unpack = fn "not yet - (...)(...)",
|
||||
|
||||
module = fn "Creates a module. - (?)(name,...)",
|
||||
require = fn "Loads the given module. - (?)(name)",
|
||||
|
||||
package = {
|
||||
type = "table",
|
||||
description = "package info",
|
||||
childs = {
|
||||
cpath = val "The path used by require to search for a C loader. ",
|
||||
loaded = val "A table used by require to control which modules are already loaded.",
|
||||
loadlib = fn "Dynamically links the host program with the C library libname. - (?)(libname, funcname)",
|
||||
path = val "The path used by require to search for a Lua loader. ",
|
||||
preload = val "A table to store loaders for specific modules (see require). ",
|
||||
seeall = fn "Sets a metatable for module with its __index field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function module. - (?)(module)"
|
||||
}
|
||||
},
|
||||
|
||||
string = {
|
||||
type = "lib",
|
||||
description = "string lib",
|
||||
childs = {
|
||||
byte = fn "Returns the internal numerical codes of the characters s[i], s[i+1], ···, s[j]. The default value for i is 1; the default value for j is i. - (number)(string [, i [, j]])",
|
||||
char = fn "Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument. - (string)(...)",
|
||||
dump = fn "Returns a string containing a binary representation of the given function, so that a later loadstring on this string returns a copy of the function. function must be a Lua function without upvalues. - (string)(func)",
|
||||
find = fn "Looks for the first match of pattern in the string s. If it finds a match, then find returns the indices of s where this occurrence starts and ends; otherwise, it returns nil. A third, optional numerical argument init specifies where to start the search; its default value is 1 and may be negative. A value of true as a fourth, optional argument plain turns off the pattern matching facilities, so the function does a plain \"find substring\" operation, with no characters in pattern being considered \"magic\". Note that if plain is given, then init must be given as well. - (number,number)(string, pattern [, init [, plain]])",
|
||||
format = fn "Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the printf family of standard C functions. The only differences are that the options/modifiers *, l, L, n, p, and h are not supported and that there is an extra option, q. The q option formats a string in a form suitable to be safely read back by the Lua interpreter: the string is written between double quotes, and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly escaped when written. - (string)(formatstring, ···)",
|
||||
gmatch = fn "Returns an iterator function that, each time it is called, returns the next captures from pattern over string s. - (func)(string, pattern)",
|
||||
gsub = fn "Returns a copy of s in which all occurrences of the pattern have been replaced by a replacement string specified by repl, which may be a string, a table, or a function. gsub also returns, as its second value, the total number of substitutions made. - (string,number)(string, pattern, repl [, n])",
|
||||
len = fn "Receives a string and returns its length. The empty string '' has length 0. Embedded zeros are counted, so 'a\\000bc\\000' has length 5. - (number)(string)",
|
||||
lower = fn "Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale. - (string)(string)",
|
||||
match = fn "Looks for the first match of pattern in the string s. If it finds one, then match returns the captures from the pattern; otherwise it returns nil. If pattern specifies no captures, then the whole match is returned. A third, optional numerical argument init specifies where to start the search; its default value is 1 and may be negative. - (string,...)(string, pattern [, init])",
|
||||
rep = fn "Returns a string that is the concatenation of n copies of the string s. - (string)(string s, n)",
|
||||
reverse = fn "Returns a string that is the string s reversed. - (string)(string)",
|
||||
sub = fn "Returns the substring of s that starts at i and continues until j; i and j may be negative. If j is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s, -i) returns a suffix of s with length i. - (string)(string, i [, j])",
|
||||
upper = fn "Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale. - (string)(string)",
|
||||
}
|
||||
},
|
||||
|
||||
coroutine = {
|
||||
type = "lib",
|
||||
description = "Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends its execution by explicitly calling a yield function.",
|
||||
childs = {
|
||||
create = fn 'Creates a new coroutine, with body f. f must be a Lua function. Returns this new coroutine, an object with type "thread". - (thread)(function)',
|
||||
resume = fn 'Starts or continues the execution of coroutine co. The first time you resume a coroutine, it starts running its body. The values val1, ··· are passed as the arguments to the body function. If the coroutine has yielded, resume restarts it; the values val1, ··· are passed as the results from the yield. - (boolean success, ...)(coroutine,...)',
|
||||
running = fn 'Returns the running coroutine, or nil when called by the main thread. - ([thread])()',
|
||||
status = fn 'Returns the status of coroutine co, as a string: "running", if the coroutine is running (that is, it called status); "suspended", if the coroutine is suspended in a call to yield, or if it has not started running yet; "normal" if the coroutine is active but not running (that is, it has resumed another coroutine); and "dead" if the coroutine has finished its body function, or if it has stopped with an error. - (status)(coroutine)',
|
||||
wrap = fn 'Creates a new coroutine, with body f. f must be a Lua function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to resume. Returns the same values returned by resume, except the first boolean. In case of error, propagates the error. - (function)(function)',
|
||||
yield = fn 'Suspends the execution of the calling coroutine. The coroutine cannot be running a C function, a metamethod, or an iterator. Any arguments to yield are passed as extra results to resume. - (...)(...)'
|
||||
}
|
||||
},
|
||||
|
||||
io = {
|
||||
type = "lib",
|
||||
description = "The I/O library provides two different styles for file manipulation. The first one uses implicit file descriptors; that is, there are operations to set a default input file and a default output file, and all input/output operations are over these default files. The second style uses explicit file descriptors. ",
|
||||
childs = {
|
||||
close = fn'Equivalent to file:close(). Without a file, closes the default output file. - ()([file])',
|
||||
flush = fn'Equivalent to file:flush over the default output file. - ()([file])',
|
||||
input = fn'When called with a file name, it opens the named file (in text mode), and sets its handle as the default input file. When called with a file handle, it simply sets this file handle as the default input file. When called without parameters, it returns the current default input file. - ([in])([file])',
|
||||
lines = fn'Opens the given file name in read mode and returns an iterator function that, each time it is called, returns a new line from the file. - (function)([file])',
|
||||
open = fn'This function opens a file, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message. - (file,[errormsg])(filename,[mode])',
|
||||
output = fn'Similar to io.input, but operates over the default output file. - ([file])([file])',
|
||||
popen = fn'Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w"). - (file)([prog, [mode]])',
|
||||
read = fn'Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below). - (string)(...)',
|
||||
tmpfile = fn'Returns a handle for a temporary file. This file is opened in update mode and it is automatically removed when the program ends. - (file)()',
|
||||
type = fn'Checks whether obj is a valid file handle. Returns the string "file" if obj is an open file handle, "closed file" if obj is a closed file handle, or nil if obj is not a file handle. - (string)(file)',
|
||||
write = fn'Writes the value of each of its arguments to the file. The arguments must be strings or numbers. To write other values, use tostring or string.format before write. - (?)(...)',
|
||||
seek = fn'Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence - (?)([whence] [, offset])',
|
||||
setvbuf = fn'Sets the buffering mode for an output file. - (?)(mode [, size])',
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
os = {
|
||||
type = "lib",
|
||||
description = ' Operating System Facilities',
|
||||
childs = {
|
||||
clock = fn'Returns an approximation of the amount in seconds of CPU time used by the program. - (seconds)()',
|
||||
date = fn'Returns a string or a table containing date and time, formatted according to the given string format. - (string)([format [, time]])',
|
||||
difftime = fn'Returns the number of seconds from time t1 to time t2. In POSIX, Windows, and some other systems, this value is exactly t2-t1. - (time)(t2,t1)',
|
||||
execute = fn'This function is equivalent to the C function system. It passes command to be executed by an operating system shell. It returns a status code, which is system-dependent. If command is absent, then it returns nonzero if a shell is available and zero otherwise. - (return)([cmd])',
|
||||
exit = fn'Calls the C function exit, with an optional code, to terminate the host program. The default value for code is the success code. - ()([code])',
|
||||
getenv = fn'Returns the value of the process environment variable varname, or nil if the variable is not defined. - ([string])(varname)',
|
||||
remove = fn'Deletes the file or directory with the given name. Directories must be empty to be removed. If this function fails, it returns nil, plus a string describing the error. - (success,[error])(filename)',
|
||||
rename = fn'Renames file or directory named oldname to newname. If this function fails, it returns nil, plus a string describing the error. - (success,[error])(oldname, newname)',
|
||||
setlocale = fn'Sets the current locale of the program. locale is a string specifying a locale; category is an optional string describing which category to change: "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category is "all". The function returns the name of the new locale, or nil if the request cannot be honored. - ([string])(locale [, category])',
|
||||
time = fn'Returns the current time when called without arguments, or a time representing the date and time specified by the given table. This table must have fields year, month, and day, and may have fields hour, min, sec, and isdst (for a description of these fields, see the os.date function). - (time)([table])',
|
||||
tmpname = fn'Returns a string with a file name that can be used for a temporary file. The file must be explicitly opened before its use and explicitly removed when no longer needed. - (string)()',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
local function key (str)
|
||||
api[str] = {type="keyword"}
|
||||
return key
|
||||
end
|
||||
-- keywords - shouldn't be left out
|
||||
key "local" "not" "if" "elseif" "else" "end" "do" "while" "repeat" "function" "until" "or"
|
||||
"or" "and" "then" "true" "false" "return" "break" "in"
|
||||
|
||||
return api
|
||||
11716
api/lua/luxiniaapi.lua
@@ -1,6 +1,6 @@
|
||||
This directory contains API definitions.
|
||||
|
||||
An API definition is a set of functions that are used
|
||||
for displaying tooltip information on function calls or
|
||||
autocomplete information.
|
||||
|
||||
This directory contains API definitions.
|
||||
|
||||
An API definition is a set of functions that are used
|
||||
for displaying tooltip information on function calls or
|
||||
autocomplete information.
|
||||
|
||||
|
||||
BIN
bin/lua.exe
BIN
bin/lua5.1.dll
BIN
bin/winapi.dll
Normal file
@@ -1,38 +1,38 @@
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, },
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0}, b = true,},
|
||||
keywords2 = {fg = {0, 127, 0}, b = true,},
|
||||
keywords3 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords4 = {fg = {127, 0, 95}, b = true,},
|
||||
keywords5 = {fg = {35, 95, 175}, b = true,},
|
||||
keywords6 = {fg = {0, 127, 127}, b = true,},
|
||||
keywords7 = {fg = {240, 255, 255}, b = true,},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {90, 90, 80},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = {fg = {180, 180, 180,},},
|
||||
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, },
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0}, b = true,},
|
||||
keywords2 = {fg = {0, 127, 0}, b = true,},
|
||||
keywords3 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords4 = {fg = {127, 0, 95}, b = true,},
|
||||
keywords5 = {fg = {35, 95, 175}, b = true,},
|
||||
keywords6 = {fg = {0, 127, 127}, b = true,},
|
||||
keywords7 = {fg = {240, 255, 255}, b = true,},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {90, 90, 80},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = {fg = {180, 180, 180,},},
|
||||
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
local luxpath = os.getenv("LUXINIA")
|
||||
path.luxinia = luxpath and luxpath.."/" or "../../engine/"
|
||||
local luxpath2 = os.getenv("LUXINIA2")
|
||||
path.luxinia2 = luxpath2 and luxpath2.."/" or "../luxinia2/runtime/bin_Windows_x86/"
|
||||
|
||||
editor.fontname = "Courier New"
|
||||
editor.caretline = true
|
||||
editor.showfncall = true
|
||||
|
||||
filehistorylength = 20
|
||||
|
||||
singleinstance = true
|
||||
singleinstanceport = 0xe493
|
||||
acandtip.shorttip = true
|
||||
|
||||
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, },
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0}, b = true,},
|
||||
keywords2 = {fg = {0, 127, 0}, b = true,},
|
||||
keywords3 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords4 = {fg = {127, 0, 95}, b = true,},
|
||||
keywords5 = {fg = {35, 95, 175}, b = true,},
|
||||
keywords6 = {fg = {0, 127, 127}, b = true,},
|
||||
keywords7 = {fg = {240, 255, 255}, b = true,},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {90, 90, 80},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = nil,
|
||||
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
@@ -1,39 +1,38 @@
|
||||
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {200, 230, 120 },bg = {30, 40, 30 }, fill= true,},
|
||||
stringtxt = {fg = {240,128,240},},
|
||||
stringeol = {fg = {240,128,200},bg = {48, 24, 24}, fill = true,},
|
||||
preprocessor = {fg = {220,175,140},},
|
||||
operator = {fg = {210, 230, 240 },},
|
||||
number = {fg = {210, 230, 255, },},
|
||||
|
||||
keywords0 = {fg = {240,240,0}},
|
||||
keywords1 = {fg = {255,64,64},},
|
||||
keywords2 = {fg = {0,240,240},},
|
||||
keywords3 = {fg = {140,140,240},},
|
||||
keywords4 = {fg = {255, 128, 0},},
|
||||
keywords5 = {fg = {200,200,240},},
|
||||
keywords6 = {fg = {64, 250, 64},},
|
||||
keywords7 = {fg = {255, 128, 128},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = {fg = {240,240,240},bg = {24,24,24},},
|
||||
linenumber = {fg = {30, 30, 40},bg = {230, 230, 230},},
|
||||
bracematch = {fg = {255, 127, 0}, b = true},
|
||||
bracemiss = {fg = {255, 0,0}, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {80, 80, 80},bg = {24,24,24},},
|
||||
calltip = {fg = {255,255,255},bg = {10,10,10},},
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = {fg = {240,240,240},bg = {10,10,10},},
|
||||
sel = {fg = {180,220,140},bg = {70,105,100},},
|
||||
caret = {fg = {250,250,250},},
|
||||
caretlinebg = {fg = {180,220,140},bg = {24,44,44},},
|
||||
fold = nil,
|
||||
whitespace = {fg = {54,54,54},},
|
||||
|
||||
fncall = {fg = {140,140,0}, st = wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {200, 230, 120 },bg = {30, 40, 30 }, fill= true,},
|
||||
stringtxt = {fg = {240,128,240},},
|
||||
stringeol = {fg = {240,128,200},bg = {48, 24, 24}, fill = true,},
|
||||
preprocessor = {fg = {220,175,140},},
|
||||
operator = {fg = {210, 230, 240 },},
|
||||
number = {fg = {210, 230, 255, },},
|
||||
|
||||
keywords0 = {fg = {240,240,0}},
|
||||
keywords1 = {fg = {255,64,64},},
|
||||
keywords2 = {fg = {0,240,240},},
|
||||
keywords3 = {fg = {140,140,240},},
|
||||
keywords4 = {fg = {255, 128, 0},},
|
||||
keywords5 = {fg = {200,200,240},},
|
||||
keywords6 = {fg = {64, 250, 64},},
|
||||
keywords7 = {fg = {255, 128, 128},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = {fg = {240,240,240},bg = {24,24,24},},
|
||||
linenumber = {fg = {30, 30, 40},bg = {230, 230, 230},},
|
||||
bracematch = {fg = {255, 127, 0}, b = true},
|
||||
bracemiss = {fg = {255, 0,0}, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {80, 80, 80},bg = {24,24,24},},
|
||||
calltip = {fg = {255,255,255},bg = {10,10,10},},
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = {fg = {240,240,240},bg = {10,10,10},},
|
||||
sel = {fg = {180,220,140},bg = {70,105,100},},
|
||||
caret = {fg = {250,250,250},},
|
||||
caretlinebg = {fg = {180,220,140},bg = {24,44,44},},
|
||||
fold = nil,
|
||||
whitespace = {fg = {54,54,54},},
|
||||
|
||||
fncall = {fg = {140,140,0}, st = wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
|
||||
@@ -1,39 +1,38 @@
|
||||
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {100, 155, 65}, bg = {30, 35, 30 }, fill= true,},
|
||||
stringtxt = {fg = {200, 145, 145},},
|
||||
stringeol = {fg = {200, 145, 145},bg = {48, 24, 24}, fill = true,},
|
||||
preprocessor = {fg = {220, 175, 140},},
|
||||
operator = {fg = {210, 230, 240 },},
|
||||
number = {fg = {210, 230, 255, },},
|
||||
|
||||
keywords0 = {fg = {128,128,255},},
|
||||
keywords1 = {fg = {210,90,90},},
|
||||
keywords2 = {fg = {0,220,220},},
|
||||
keywords3 = {fg = {220,220,0},},
|
||||
keywords4 = {fg = {240, 128,0},},
|
||||
keywords5 = {fg = {200,200,240},},
|
||||
keywords6 = {fg = {64, 240, 64},},
|
||||
keywords7 = {fg = {255, 128, 128},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = {fg = {200,200,200},bg = {18,24,26},},
|
||||
linenumber = {fg = {30, 30, 40},bg = {230, 230, 230},},
|
||||
bracematch = {fg = {255, 127, 0}, b = true},
|
||||
bracemiss = {fg = {255, 0,0}, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {80, 80, 80},bg = {24,24,24},},
|
||||
calltip = {fg = {255,255,255},bg = {10,10,10},},
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = {fg = {240,240,240},bg = {10,10,10},},
|
||||
sel = {fg = {180,220,140},bg = {70,105,100},},
|
||||
caret = {fg = {250,250,250},},
|
||||
caretlinebg = {fg = {180,220,140},bg = {24,44,44},},
|
||||
fold = nil,
|
||||
whitespace = {fg = {54,54,54},},
|
||||
|
||||
fncall = {fg = {75,75,150}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {100, 155, 65}, bg = {30, 35, 30 }, fill= true,},
|
||||
stringtxt = {fg = {200, 145, 145},},
|
||||
stringeol = {fg = {200, 145, 145},bg = {48, 24, 24}, fill = true,},
|
||||
preprocessor = {fg = {220, 175, 140},},
|
||||
operator = {fg = {210, 230, 240 },},
|
||||
number = {fg = {210, 230, 255, },},
|
||||
|
||||
keywords0 = {fg = {128,128,255},},
|
||||
keywords1 = {fg = {210,90,90},},
|
||||
keywords2 = {fg = {0,220,220},},
|
||||
keywords3 = {fg = {220,220,0},},
|
||||
keywords4 = {fg = {240, 128,0},},
|
||||
keywords5 = {fg = {200,200,240},},
|
||||
keywords6 = {fg = {64, 240, 64},},
|
||||
keywords7 = {fg = {255, 128, 128},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = {fg = {200,200,200},bg = {18,24,26},},
|
||||
linenumber = {fg = {30, 30, 40},bg = {230, 230, 230},},
|
||||
bracematch = {fg = {255, 127, 0}, b = true},
|
||||
bracemiss = {fg = {255, 0,0}, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {80, 80, 80},bg = {24,24,24},},
|
||||
calltip = {fg = {255,255,255},bg = {10,10,10},},
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = {fg = {240,240,240},bg = {10,10,10},},
|
||||
sel = {fg = {180,220,140},bg = {70,105,100},},
|
||||
caret = {fg = {250,250,250},},
|
||||
caretlinebg = {fg = {180,220,140},bg = {24,44,44},},
|
||||
fold = nil,
|
||||
whitespace = {fg = {54,54,54},},
|
||||
|
||||
fncall = {fg = {75,75,150}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
|
||||
9
cfg/user.lua_for_custom_settings.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
--[[--
|
||||
|
||||
estrela loads configs in the following order
|
||||
|
||||
1. <application>\config.lua
|
||||
2. cfg\user.lua
|
||||
3. -cfg commandline strings
|
||||
|
||||
--]]--
|
||||
@@ -1,52 +0,0 @@
|
||||
|
||||
local luxpath = os.getenv("LUXINIA")
|
||||
path.luxinia = luxpath and luxpath.."/" or "../luxinia/"
|
||||
|
||||
interpreter = "estrelashell"
|
||||
acandtip.shorttip = true
|
||||
acandtip.nodynwords = true
|
||||
editor.iofilter = "GermanUtf8Ascii"
|
||||
cgprofile = "gp4"
|
||||
cgperfgpu = "G80"
|
||||
|
||||
--[[
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {200, 230, 120 },bg = {30, 40, 30 }, fill= true,},
|
||||
stringtxt = {fg = {240,128,240},},
|
||||
stringeol = {fg = {240,128,200},bg = {48, 24, 24}, fill = true,},
|
||||
preprocessor = {fg = {220,175,140},},
|
||||
operator = {fg = {210, 230, 240 },},
|
||||
number = {fg = {210, 230, 255, },},
|
||||
|
||||
keywords0 = {fg = {240,240,0}},
|
||||
keywords1 = {fg = {255,64,64},},
|
||||
keywords2 = {fg = {0,240,240},},
|
||||
keywords3 = {fg = {140,140,240},},
|
||||
keywords4 = {fg = {255, 128, 0},},
|
||||
keywords5 = {fg = {200,200,240},},
|
||||
keywords6 = {fg = {64, 250, 64},},
|
||||
keywords7 = {fg = {255, 128, 128},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = {fg = {240,240,240},bg = {24,24,24},},
|
||||
linenumber = {fg = {30, 30, 40},bg = {230, 230, 230},},
|
||||
bracematch = {fg = {200, 200, 0}, b = true},
|
||||
bracemiss = {fg = {255, 50, 50 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {80, 80, 80},bg = {24,24,24},},
|
||||
calltip = {fg = {255,255,255},bg = {10,10,10},},
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = {fg = {240,240,240},bg = {10,10,10},},
|
||||
sel = {fg = {180,220,140},bg = {70,105,100},},
|
||||
caret = {fg = {250,250,250},},
|
||||
caretlinebg = {fg = {180,220,140},bg = {24,44,44},},
|
||||
fold = nil,
|
||||
whitespace = {fg = {224,224,224},bg = {24,24,24},},
|
||||
|
||||
}
|
||||
|
||||
]]
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
local luxpath = os.getenv("LUXINIA")
|
||||
path.luxinia = luxpath and luxpath.."/" or "../luxinia/"
|
||||
path.cgbin = "../Cg/bin"
|
||||
|
||||
interpreter = "luxinia"
|
||||
acandtip.shorttip = true
|
||||
acandtip.nodynwords = true
|
||||
editor.iofilter = "GermanUtf8Ascii"
|
||||
|
||||
--[[
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {200, 230, 120 },bg = {30, 40, 30 }, fill= true,},
|
||||
stringtxt = {fg = {240,128,240},},
|
||||
stringeol = {fg = {240,128,200},bg = {48, 24, 24}, fill = true,},
|
||||
preprocessor = {fg = {220,175,140},},
|
||||
operator = {fg = {210, 230, 240 },},
|
||||
number = {fg = {210, 230, 255, },},
|
||||
|
||||
keywords0 = {fg = {240,240,0}},
|
||||
keywords1 = {fg = {255,64,64},},
|
||||
keywords2 = {fg = {0,240,240},},
|
||||
keywords3 = {fg = {140,140,240},},
|
||||
keywords4 = {fg = {255, 128, 0},},
|
||||
keywords5 = {fg = {200,200,240},},
|
||||
keywords6 = {fg = {64, 250, 64},},
|
||||
keywords7 = {fg = {255, 128, 128},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = {fg = {240,240,240},bg = {24,24,24},},
|
||||
linenumber = {fg = {30, 30, 40},bg = {230, 230, 230},},
|
||||
bracematch = {fg = {200, 200, 0}, b = true},
|
||||
bracemiss = {fg = {255, 50, 50 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {80, 80, 80},bg = {24,24,24},},
|
||||
calltip = {fg = {255,255,255},bg = {10,10,10},},
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = {fg = {240,240,240},bg = {10,10,10},},
|
||||
sel = {fg = {180,220,140},bg = {70,105,100},},
|
||||
caret = {fg = {250,250,250},},
|
||||
caretlinebg = {fg = {180,220,140},bg = {24,44,44},},
|
||||
fold = nil,
|
||||
whitespace = {fg = {224,224,224},bg = {24,24,24},},
|
||||
|
||||
}
|
||||
|
||||
]]
|
||||
|
||||
289
doc/defs.lua
@@ -1,289 +0,0 @@
|
||||
-- About
|
||||
-- ----------------------------------------------------
|
||||
-- This file contains lua table definitons used by
|
||||
-- automatic loaded files, not part of the
|
||||
-- editor source.
|
||||
--
|
||||
-- /cfg/config.lua
|
||||
-- /cfg/user.lua
|
||||
-- /spec/*.lua
|
||||
-- /tools/*.lua
|
||||
-- /api/*<apitype>/*.lua
|
||||
|
||||
|
||||
-- style definition
|
||||
-- ----------------------------------------------------
|
||||
-- all entries are optiona
|
||||
stattr = {
|
||||
fg = {r,g,b}, -- foreground color 0-255
|
||||
bg = {r,g,b}, -- background color
|
||||
i = false, -- italic
|
||||
b = false, -- bold
|
||||
u = false, -- underline
|
||||
fill = true, -- fill to lineend
|
||||
}
|
||||
|
||||
style = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = stattr,
|
||||
comment = stattr,
|
||||
stringtxt = stattr,
|
||||
stringeol = stattr,
|
||||
preprocessor = stattr,
|
||||
operator = stattr,
|
||||
number = stattr,
|
||||
|
||||
keywords0 = stattr,
|
||||
keywords1 = stattr,
|
||||
keywords2 = stattr,
|
||||
keywords3 = stattr,
|
||||
keywords4 = stattr,
|
||||
keywords5 = stattr,
|
||||
keywords6 = stattr,
|
||||
keywords7 = stattr,
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = stattr,
|
||||
linenumber = stattr,
|
||||
bracematch = stattr,
|
||||
bracemiss = stattr,
|
||||
escapechar = stattr,
|
||||
indent = stattr,
|
||||
calltip = stattr,
|
||||
|
||||
-- common special (need custom fg & bg )
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = nil,
|
||||
|
||||
-- special, functioncall indicator
|
||||
fncall = {
|
||||
fg = {r,g,b},
|
||||
st = wxstc.wxSTC_INDIC_BOX,
|
||||
},
|
||||
}
|
||||
|
||||
-- config definition
|
||||
-- ----------------------------------------------------
|
||||
-- tables must exist
|
||||
-- content is optional
|
||||
-- config is loaded into existing config table
|
||||
config = {
|
||||
appname = "estrela", -- by default the launcher name
|
||||
|
||||
path = {
|
||||
-- path for tools/interpreters
|
||||
luxinia = "C:/luxbin/",
|
||||
-- path to luxinia exe
|
||||
|
||||
projectdir = "",
|
||||
-- the project directory, used by
|
||||
-- some tools/interpreters
|
||||
},
|
||||
editor = {
|
||||
fontname = "Courier New",
|
||||
-- default font
|
||||
fontsize = 10,
|
||||
-- defailt size
|
||||
caretline = true,
|
||||
-- show active line
|
||||
|
||||
-- input/output filtering of strings
|
||||
-- current filters "GermanUtf8Ascii"
|
||||
iofilter = nil,
|
||||
|
||||
-- use indicator to show function calls
|
||||
-- if spec allows
|
||||
showfncall = true,
|
||||
|
||||
tabwidth = 4,
|
||||
usetabs = true, -- if false then spaces are used
|
||||
whitespace = false,
|
||||
autotabs = true, -- if true test for tabs after file load,
|
||||
-- sets "usetabs" to true for this file
|
||||
},
|
||||
|
||||
outputshell = {
|
||||
-- output and shell settings
|
||||
fontname = "Courier New",
|
||||
-- default font
|
||||
fontsize = 10,
|
||||
-- defult size
|
||||
}
|
||||
|
||||
styles = {},
|
||||
-- styles table as above for editor
|
||||
|
||||
stylesoutshell = {},
|
||||
-- styles for output/shell
|
||||
|
||||
interpreter = "EstrelaEditor",
|
||||
-- the default "project" lua interpreter
|
||||
-- EstrelaEditor, Luxinia, Lua
|
||||
|
||||
autocomplete = true,
|
||||
-- whether autocomplete is on by default
|
||||
|
||||
acandtip = {
|
||||
shorttip = false,
|
||||
-- tooltips are compact during typing
|
||||
nodynwords = false,
|
||||
-- no dynamic words (user entered words)
|
||||
ignorecase = false,
|
||||
-- ignores case when performing comparison with autocomplete list
|
||||
strategy = 0,
|
||||
-- 0: is string comparison
|
||||
-- 1: substring leading characters (camel case or _ separated)
|
||||
-- 2: leading + any correctly ordered fragments (default)
|
||||
}
|
||||
|
||||
savebak = false,
|
||||
-- if bak files are created on save
|
||||
|
||||
filehistorylength = 20,
|
||||
-- historylength for files
|
||||
|
||||
projecthistorylength = 15,
|
||||
-- historylength for project directories
|
||||
|
||||
singleinstance = true,
|
||||
-- if true creates a UDP server to exchange messages
|
||||
-- for loading commandline passed files
|
||||
|
||||
singleinstanceport = 0xe493,
|
||||
-- UDP port for single instance communication
|
||||
}
|
||||
|
||||
-- application engine
|
||||
-- ----------------------------------------------------
|
||||
|
||||
app = {
|
||||
|
||||
postinit = function() end, -- post init, prior starting mainloop
|
||||
loadfilters = {
|
||||
tools = function(file) return true end,
|
||||
specs = function(file) return true end,
|
||||
interpreters = function(file) return true end,
|
||||
}
|
||||
stringtable = { -- optional entries uses defaults otherwise
|
||||
editor = nil,
|
||||
statuswelcome = nil,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-- api definition
|
||||
-- ----------------------------------------------------
|
||||
-- hierarchy encoded into children
|
||||
|
||||
api = {
|
||||
-- global space words, e.g "table"
|
||||
["blah"] = {
|
||||
-- "function", "class", "keyword", "value", "lib"
|
||||
type = "function",
|
||||
description = "this does something",
|
||||
|
||||
-- value and function:
|
||||
valuetype = "api.ClassName",
|
||||
|
||||
-- function:
|
||||
args = "(blah,blubb)",
|
||||
returns = "(foo)",
|
||||
|
||||
-- autogenerated post load:
|
||||
-- concated hierarchy name (e.g. "lib.class")
|
||||
classname = "blah",
|
||||
|
||||
-- children in the class hierarchy
|
||||
childs = {
|
||||
--.. recursive
|
||||
}
|
||||
},
|
||||
["blubb"] = {
|
||||
--...
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- spec definition
|
||||
-- ----------------------------------------------------
|
||||
-- all entries are optional
|
||||
spec = {
|
||||
exts = {"ext","ext2",..},
|
||||
-- compatible extensions
|
||||
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
-- scintilla lexer
|
||||
|
||||
lexerstyleconvert = {
|
||||
-- table mapping each styles to
|
||||
-- appropriate lexer id
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
-- ...
|
||||
}
|
||||
|
||||
linecomment = "//",
|
||||
-- string for linecomments
|
||||
|
||||
sep = "[%.:]",
|
||||
-- class.function separator match string,
|
||||
-- e.g in lua both . and : are allowed
|
||||
-- default is "\1" which should yield no matches
|
||||
-- and therefore disable class.func type autocompletion
|
||||
|
||||
isfncall = function(str) return from,to end
|
||||
-- function that detects positions for a substring that
|
||||
-- stands for a functioncall, ie " call(..)" -> 2,5
|
||||
|
||||
|
||||
apitype = "api",
|
||||
-- which sub directory of "api" is relevant
|
||||
-- api files handle autocomplete and tooltips
|
||||
-- api won't affect syntax coloring
|
||||
|
||||
keywords = {
|
||||
-- up to 8 strings containing space separated keywords
|
||||
-- used by the lexer for coloring (NOT for autocomplete).
|
||||
-- however each lexer supports varying amount
|
||||
-- of keyword types
|
||||
|
||||
"foo bar word",
|
||||
"more words",
|
||||
}
|
||||
}
|
||||
|
||||
-- tool definition
|
||||
-- ----------------------------------------------------
|
||||
-- main entries are optional
|
||||
tool = {
|
||||
fninit = function(frame,menubar) end,
|
||||
-- guarantees that ide is initialized
|
||||
-- can be used for init
|
||||
-- and adding custom menu
|
||||
|
||||
exec = {
|
||||
-- quick exec action, listed under "Tools" menu
|
||||
name = "",
|
||||
description = "",
|
||||
fn = function(wxfilename,projectdir) end,
|
||||
}
|
||||
}
|
||||
|
||||
-- interpreter definition
|
||||
-- ----------------------------------------------------
|
||||
interpreter = {
|
||||
name = "",
|
||||
description = "",
|
||||
api = {"apifile_without_extension"} -- optional to limit loaded apis
|
||||
frun = function(self,wfilename)
|
||||
return "execommand"
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return "projpath_from_filename" -- optional
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="starter" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="..\..\estrela" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="..\..\" />
|
||||
<Option object_output="obj\Debug\" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Option use_console_runner="0" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="..\..\estrela" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="..\..\" />
|
||||
<Option object_output="obj\Release\" />
|
||||
<Option type="0" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-D__MINGW__" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="kernel32" />
|
||||
</Linker>
|
||||
<Unit filename="..\res\estrela.ico" />
|
||||
<Unit filename="..\res\estrela.rc">
|
||||
<Option compilerVar="WINDRES" />
|
||||
</Unit>
|
||||
<Unit filename="..\win32_starter.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="starter" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="..\..\estrela" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="..\..\" />
|
||||
<Option object_output="obj\Debug\" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Option use_console_runner="0" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="..\..\estrela" prefix_auto="1" extension_auto="1" />
|
||||
<Option working_dir="..\..\" />
|
||||
<Option object_output="obj\Release\" />
|
||||
<Option type="0" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-D__MINGW__" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="kernel32" />
|
||||
</Linker>
|
||||
<Unit filename="..\res\estrela.ico" />
|
||||
<Unit filename="..\res\estrela.rc">
|
||||
<Option compilerVar="WINDRES" />
|
||||
</Unit>
|
||||
<Unit filename="..\win32_starter.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
||||
|
||||
61
estrela/config.lua
Normal file
@@ -0,0 +1,61 @@
|
||||
local luxpath = os.getenv("LUXINIA")
|
||||
path.luxinia = luxpath and luxpath.."/" or "../luxinia/engine/"
|
||||
local luxpath2 = os.getenv("LUXINIA2")
|
||||
path.luxinia2 = luxpath2 and luxpath2.."/" or "../luxinia2/runtime/bin_Windows_x86/"
|
||||
|
||||
interpreter = "estrelashell"
|
||||
|
||||
editor.fontname = "Courier New"
|
||||
editor.caretline = true
|
||||
editor.showfncall = true
|
||||
editor.whitespace = true
|
||||
editor.usetabs = false
|
||||
editor.autotabs = true
|
||||
editor.tabwidth = 2
|
||||
|
||||
filehistorylength = 20
|
||||
|
||||
singleinstance = true
|
||||
singleinstanceport = 0xe493
|
||||
acandtip.shorttip = true
|
||||
acandtip.nodynwords = true
|
||||
acandtip.ignorecase = true
|
||||
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, },
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0}, b = true,},
|
||||
keywords2 = {fg = {0, 127, 0}, b = true,},
|
||||
keywords3 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords4 = {fg = {127, 0, 95}, b = true,},
|
||||
keywords5 = {fg = {35, 95, 175}, b = true,},
|
||||
keywords6 = {fg = {0, 127, 127}, b = true,},
|
||||
keywords7 = {fg = {240, 255, 255}, b = true,},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {90, 90, 80},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = nil,
|
||||
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
@@ -1,114 +1,113 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Create the Help menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local helpMenu = wx.wxMenu{
|
||||
{ ID_ABOUT, "&About\tF1", "About Estrela Editor" },
|
||||
}
|
||||
menuBar:Append(helpMenu, "&Help")
|
||||
|
||||
local function DisplayAbout(event)
|
||||
local page = [[
|
||||
<html>
|
||||
<body bgcolor = "#ffffff" text='#ffffff'>
|
||||
<table border='0' width="100%">
|
||||
<tr><td><img src = "estrela/res/estrela.png"></center></td><td>
|
||||
<table cellspacing = 4 cellpadding = 4 width = "400">
|
||||
<tr>
|
||||
<td bgcolor = "#010156">
|
||||
<center>
|
||||
<font size = +2 color = "#FFFFFF"><br><b>]]..
|
||||
wxlua.wxLUA_VERSION_STRING..[[</b></font>
|
||||
<font size = +1 color = "#FFFFFF">built with</font>
|
||||
<font size = +2 color = "#FFFFFF"><b>]]..
|
||||
wx.wxVERSION_STRING..[[</b></font>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor = "#4747A1">
|
||||
<b>Estrela Editor</b><br>
|
||||
<b><font color='#ffffff'>Copyright © 2008-2011 Luxinia DevTeam</font></b>
|
||||
<p>
|
||||
<font size=-1>
|
||||
<table cellpadding = 0 cellspacing = 0 width = "100%">
|
||||
<tr>
|
||||
<td width = "65%">
|
||||
Christoph Kubisch<br>
|
||||
Eike Decker<p>
|
||||
</td>
|
||||
<td valign = top>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<font size = 1>
|
||||
Licenced under The MIT License.
|
||||
</font>
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor = "#4747A1">
|
||||
<b>based on wxLua editor sample</b><br>
|
||||
<b>Copyright © 2002-2005 Lomtick Software</b>
|
||||
<p>
|
||||
<font size=-1>
|
||||
<table cellpadding = 0 cellspacing = 0 width = "100%">
|
||||
<tr>
|
||||
<td width = "65%">
|
||||
J. Winwood (luascript@thersgb.net)<br>
|
||||
John Labenski<p>
|
||||
</td>
|
||||
<td valign = top>
|
||||
<img src = "estrela/res/wxlualogo2.png">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<font size = 1>
|
||||
wxLua binding licenced under wxWindows Library Licence, Version 3.
|
||||
</font>
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>
|
||||
]]
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, "About Estrela Editor")
|
||||
|
||||
local html = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(500, 270),
|
||||
wx.wxHW_SCROLLBAR_NEVER)
|
||||
local line = wx.wxStaticLine(dlg, wx.wxID_ANY)
|
||||
local button = wx.wxButton(dlg, wx.wxID_OK, "OK")
|
||||
|
||||
button:SetDefault()
|
||||
|
||||
html:SetBorders(0)
|
||||
html:SetPage(page)
|
||||
html:SetSize(html:GetInternalRepresentation():GetWidth(),
|
||||
html:GetInternalRepresentation():GetHeight())
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(html, 1, wx.wxALL, 10)
|
||||
topsizer:Add(line, 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(button, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
|
||||
dlg:SetAutoLayout(true)
|
||||
dlg:SetSizer(topsizer)
|
||||
topsizer:Fit(dlg)
|
||||
|
||||
dlg:ShowModal()
|
||||
dlg:Destroy()
|
||||
end
|
||||
|
||||
frame:Connect(ID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, DisplayAbout)
|
||||
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Create the Help menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local helpMenu = wx.wxMenu{
|
||||
{ ID_ABOUT, "&About\tF1", "About Estrela Editor" },
|
||||
}
|
||||
menuBar:Append(helpMenu, "&Help")
|
||||
|
||||
local function DisplayAbout(event)
|
||||
local page = [[
|
||||
<html>
|
||||
<body bgcolor = "#ffffff" text='#ffffff'>
|
||||
<table border='0' width="100%">
|
||||
<tr><td><img src = "estrela/res/estrela.png"></center></td><td>
|
||||
<table cellspacing = 4 cellpadding = 4 width = "400">
|
||||
<tr>
|
||||
<td bgcolor = "#010156">
|
||||
<center>
|
||||
<font size = +2 color = "#FFFFFF"><br><b>]]..
|
||||
wxlua.wxLUA_VERSION_STRING..[[</b></font>
|
||||
<font size = +1 color = "#FFFFFF">built with</font>
|
||||
<font size = +2 color = "#FFFFFF"><b>]]..
|
||||
wx.wxVERSION_STRING..[[</b></font>
|
||||
</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor = "#4747A1">
|
||||
<b>Estrela Editor</b><br>
|
||||
<b><font color='#ffffff'>Copyright © 2008-2011 Luxinia DevTeam</font></b>
|
||||
<p>
|
||||
<font size=-1>
|
||||
<table cellpadding = 0 cellspacing = 0 width = "100%">
|
||||
<tr>
|
||||
<td width = "65%">
|
||||
Christoph Kubisch<br>
|
||||
Eike Decker<p>
|
||||
</td>
|
||||
<td valign = top>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<font size = 1>
|
||||
Licensed under The MIT License.
|
||||
</font>
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor = "#4747A1">
|
||||
<b>based on wxLua editor sample</b><br>
|
||||
<b>Copyright © 2002-2005 Lomtick Software</b>
|
||||
<p>
|
||||
<font size=-1>
|
||||
<table cellpadding = 0 cellspacing = 0 width = "100%">
|
||||
<tr>
|
||||
<td width = "65%">
|
||||
J. Winwood (luascript@thersgb.net)<br>
|
||||
John Labenski<p>
|
||||
</td>
|
||||
<td valign = top>
|
||||
<img src = "estrela/res/wxlualogo2.png">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<font size = 1>
|
||||
wxLua binding licensed under wxWindows Library License, Version 3.
|
||||
</font>
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>
|
||||
]]
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, "About Estrela Editor")
|
||||
|
||||
local html = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(500, 270),
|
||||
wx.wxHW_SCROLLBAR_NEVER)
|
||||
local line = wx.wxStaticLine(dlg, wx.wxID_ANY)
|
||||
local button = wx.wxButton(dlg, wx.wxID_OK, "OK")
|
||||
|
||||
button:SetDefault()
|
||||
|
||||
html:SetBorders(0)
|
||||
html:SetPage(page)
|
||||
html:SetSize(html:GetInternalRepresentation():GetWidth(),
|
||||
html:GetInternalRepresentation():GetHeight())
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(html, 1, wx.wxALL, 10)
|
||||
topsizer:Add(line, 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(button, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
|
||||
dlg:SetAutoLayout(true)
|
||||
dlg:SetSizer(topsizer)
|
||||
topsizer:Fit(dlg)
|
||||
|
||||
dlg:ShowModal()
|
||||
dlg:Destroy()
|
||||
end
|
||||
|
||||
frame:Connect(ID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, DisplayAbout)
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
Estrela Editor
|
||||
-----------------
|
||||
Estrela Editor is a wxLua based IDE. It supports multiple
|
||||
fileformats, "api" for autocompletion and tooltips, and custom
|
||||
commandline tools. Focus is extensibility for target applications
|
||||
using Lua. Its main purpose is as IDE for the 3D engine "Luxinia".
|
||||
|
||||
|
||||
|
||||
Commandline:
|
||||
------------
|
||||
|
||||
Open File(s):
|
||||
<exe> <filename> [<filename>...]
|
||||
any non-option will be treated as filename
|
||||
|
||||
Overriding Config:
|
||||
<exe> [...] -cfg "<luacode overriding config>" [...]
|
||||
e.g.: estrela.exe -cfg "singleinstance=false;" somefile.lua
|
||||
|
||||
Estrela Editor
|
||||
-----------------
|
||||
Estrela Editor is a wxLua based IDE. It supports multiple
|
||||
fileformats, "api" for autocompletion and tooltips, and custom
|
||||
commandline tools. Focus is extensibility for target applications
|
||||
using Lua. Its main purpose is as IDE for the 3D engine "Luxinia".
|
||||
|
||||
|
||||
|
||||
Commandline:
|
||||
------------
|
||||
|
||||
Open File(s):
|
||||
<exe> <filename> [<filename>...]
|
||||
any non-option will be treated as filename
|
||||
|
||||
Overriding Config:
|
||||
<exe> [...] -cfg "<luacode overriding config>" [...]
|
||||
e.g.: estrela.exe -cfg "singleinstance=false;" somefile.lua
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
icon ICON "../res/estrela.ico"
|
||||
icon ICON "../res/estrela.ico"
|
||||
|
||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@@ -1,132 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="204.22055"
|
||||
height="96.006279"
|
||||
id="svg3513"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46+devel"
|
||||
version="1.0"
|
||||
inkscape:export-filename="D:\dev\c\tools\wxide\res\wxlualogo2.png"
|
||||
inkscape:export-xdpi="59.996075"
|
||||
inkscape:export-ydpi="59.996075"
|
||||
sodipodi:docname="wxlogo.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3515">
|
||||
<linearGradient
|
||||
id="linearGradient3538">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3540" />
|
||||
<stop
|
||||
style="stop-color:#e3e3eb;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3542" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3521" />
|
||||
<inkscape:perspective
|
||||
id="perspective3530"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3538"
|
||||
id="linearGradient3544"
|
||||
x1="88.214287"
|
||||
y1="0.2142856"
|
||||
x2="88.214287"
|
||||
y2="81.130592"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter4057"
|
||||
x="-0.044305418"
|
||||
width="1.0886108"
|
||||
y="-0.10071105"
|
||||
height="1.2014221">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="2.2929748"
|
||||
id="feGaussianBlur4059" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="98.55416"
|
||||
inkscape:cy="58.784487"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="719"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="-4" />
|
||||
<metadata
|
||||
id="metadata3518">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-102.354,-435.00191)">
|
||||
<rect
|
||||
ry="12.142858"
|
||||
y="-1.9285716"
|
||||
x="-5"
|
||||
height="85"
|
||||
width="193.21428"
|
||||
id="rect3546"
|
||||
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter4057)"
|
||||
transform="translate(112.85714,442.43362)" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient3544);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="rect3536"
|
||||
width="193.21428"
|
||||
height="85"
|
||||
x="-5"
|
||||
y="-1.9285716"
|
||||
transform="translate(112.85714,442.43362)"
|
||||
ry="12.142858" />
|
||||
<image
|
||||
y="442.43362"
|
||||
x="112.85714"
|
||||
id="image3532"
|
||||
height="77"
|
||||
width="180"
|
||||
sodipodi:absref="D:\dev\c\tools\wxide\res\wxlualogo.png"
|
||||
xlink:href="wxlualogo.png" />
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="204.22055"
|
||||
height="96.006279"
|
||||
id="svg3513"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46+devel"
|
||||
version="1.0"
|
||||
inkscape:export-filename="D:\dev\c\tools\wxide\res\wxlualogo2.png"
|
||||
inkscape:export-xdpi="59.996075"
|
||||
inkscape:export-ydpi="59.996075"
|
||||
sodipodi:docname="wxlogo.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3515">
|
||||
<linearGradient
|
||||
id="linearGradient3538">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3540" />
|
||||
<stop
|
||||
style="stop-color:#e3e3eb;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3542" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3521" />
|
||||
<inkscape:perspective
|
||||
id="perspective3530"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3538"
|
||||
id="linearGradient3544"
|
||||
x1="88.214287"
|
||||
y1="0.2142856"
|
||||
x2="88.214287"
|
||||
y2="81.130592"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter4057"
|
||||
x="-0.044305418"
|
||||
width="1.0886108"
|
||||
y="-0.10071105"
|
||||
height="1.2014221">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="2.2929748"
|
||||
id="feGaussianBlur4059" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="98.55416"
|
||||
inkscape:cy="58.784487"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1024"
|
||||
inkscape:window-height="719"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="-4" />
|
||||
<metadata
|
||||
id="metadata3518">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-102.354,-435.00191)">
|
||||
<rect
|
||||
ry="12.142858"
|
||||
y="-1.9285716"
|
||||
x="-5"
|
||||
height="85"
|
||||
width="193.21428"
|
||||
id="rect3546"
|
||||
style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter4057)"
|
||||
transform="translate(112.85714,442.43362)" />
|
||||
<rect
|
||||
style="opacity:1;fill:url(#linearGradient3544);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="rect3536"
|
||||
width="193.21428"
|
||||
height="85"
|
||||
x="-5"
|
||||
y="-1.9285716"
|
||||
transform="translate(112.85714,442.43362)"
|
||||
ry="12.142858" />
|
||||
<image
|
||||
y="442.43362"
|
||||
x="112.85714"
|
||||
id="image3532"
|
||||
height="77"
|
||||
width="180"
|
||||
sodipodi:absref="D:\dev\c\tools\wxide\res\wxlualogo.png"
|
||||
xlink:href="wxlualogo.png" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 3.9 KiB |
@@ -1,236 +1,236 @@
|
||||
// this is an extremly ugly quick and dirty hack...
|
||||
// maybe it could be refactored to do some error catching and
|
||||
// other things, but right now it does what it should...
|
||||
// (providing a single exe file in our main directory without
|
||||
// polluting it with all these dlls located in the /bin folder)
|
||||
|
||||
#ifdef __MINGW__ /* not sure if this is the *official* define */
|
||||
#define _WIN32_WINNT 0x0502
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* some typedef functions - these are not matching exactly the
|
||||
original definitions, but their signature is supposed to be
|
||||
compatible
|
||||
Currently 10 different functions are needed - each with different signatures... */
|
||||
typedef void *voidfunc ();
|
||||
typedef int *varfunc (void *L,...); // quick and dirty using the varargs
|
||||
typedef void varfuncvoid (void *L,...);
|
||||
|
||||
// from lua.h
|
||||
#define LUA_GLOBALSINDEX (-10002)
|
||||
|
||||
|
||||
static voidfunc *luaL_newstate;
|
||||
static varfunc *luaL_loadbuffer;
|
||||
static varfunc *luaL_openlibs;
|
||||
static varfunc *lua_pcall;
|
||||
static varfunc *lua_pushcclosure;
|
||||
static varfunc *lua_setfield;
|
||||
static varfunc *lua_tolstring;
|
||||
static varfuncvoid *lua_createtable;
|
||||
static varfuncvoid *lua_pushstring;
|
||||
static varfuncvoid *lua_rawseti;
|
||||
|
||||
static int luafunc_mbox (void *L)
|
||||
{
|
||||
const char *title = (const char*)lua_tolstring(L,1,NULL);
|
||||
const char *msg = (const char*)lua_tolstring(L,2,NULL);
|
||||
MessageBox(NULL,msg,title,MB_OK|MB_ICONERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *luacode =
|
||||
"local msg = _ERRMSG; _ERRMSG = nil "
|
||||
"local arg = _ARG or {}; _ARG = nil "
|
||||
"xpcall("
|
||||
"function() "
|
||||
"(loadfile 'src/main.lua')(unpack(arg)) end,"
|
||||
"function(err) msg('Uncaught lua script exception',debug.traceback(err)) end)"
|
||||
;
|
||||
|
||||
#if defined(_WIN32) && defined (_MSC_VER)
|
||||
|
||||
PCHAR* CommandLineToArgvA(PCHAR CmdLine,int* _argc)
|
||||
{
|
||||
PCHAR* argv;
|
||||
PCHAR _argv;
|
||||
size_t len;
|
||||
ULONG argc;
|
||||
CHAR a;
|
||||
size_t i, j;
|
||||
|
||||
BOOLEAN in_QM;
|
||||
BOOLEAN in_TEXT;
|
||||
BOOLEAN in_SPACE;
|
||||
|
||||
len = strlen(CmdLine);
|
||||
i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID);
|
||||
|
||||
argv = (PCHAR*)GlobalAlloc(GMEM_FIXED,
|
||||
i + (len+2)*sizeof(CHAR));
|
||||
|
||||
_argv = (PCHAR)(((PUCHAR)argv)+i);
|
||||
|
||||
argc = 0;
|
||||
argv[argc] = _argv;
|
||||
in_QM = 0;
|
||||
in_TEXT = 0;
|
||||
in_SPACE = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
while( a = CmdLine[i] ) {
|
||||
if(in_QM) {
|
||||
if(a == '\"') {
|
||||
in_QM = 0;
|
||||
} else {
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
switch(a) {
|
||||
case '\"':
|
||||
in_QM = 1;
|
||||
in_TEXT = 1;
|
||||
if(in_SPACE) {
|
||||
argv[argc] = _argv+j;
|
||||
argc++;
|
||||
}
|
||||
in_SPACE = 0;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
if(in_TEXT) {
|
||||
_argv[j] = '\0';
|
||||
j++;
|
||||
}
|
||||
in_TEXT = 0;
|
||||
in_SPACE = 1;
|
||||
break;
|
||||
default:
|
||||
in_TEXT = 1;
|
||||
if(in_SPACE) {
|
||||
argv[argc] = _argv+j;
|
||||
argc++;
|
||||
}
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
in_SPACE = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_argv[j] = '\0';
|
||||
argv[argc] = NULL;
|
||||
|
||||
(*_argc) = argc;
|
||||
return argv;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
int argc;
|
||||
char ** argv = CommandLineToArgvA(GetCommandLineA(),&argc);
|
||||
|
||||
#else
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#endif
|
||||
HINSTANCE hinstLib;
|
||||
|
||||
|
||||
char buffer[MAX_PATH],*file;
|
||||
|
||||
if (!GetFullPathName(argv[0],MAX_PATH,buffer,&file)) {
|
||||
MessageBox(NULL,
|
||||
TEXT("Couldn't find the correct working directory"),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
return 0;
|
||||
}
|
||||
if (file!=NULL)
|
||||
*file = 0; // finish the string, I don't need the appname
|
||||
//int i;
|
||||
//for (i=0;i<argc; i++)
|
||||
// printf("%d %s\n",i,argv[i]);
|
||||
|
||||
SetCurrentDirectory(buffer);
|
||||
|
||||
|
||||
SetDllDirectory(".\\bin\\");
|
||||
hinstLib = LoadLibrary("lua5.1.dll");
|
||||
if (hinstLib != NULL)
|
||||
{
|
||||
luaL_newstate = (voidfunc*) GetProcAddress(hinstLib, "luaL_newstate");
|
||||
luaL_loadbuffer = (varfunc*) GetProcAddress(hinstLib, "luaL_loadbuffer");
|
||||
luaL_openlibs = (varfunc*) GetProcAddress(hinstLib, "luaL_openlibs");
|
||||
lua_pcall = (varfunc*)GetProcAddress(hinstLib, "lua_pcall");
|
||||
lua_tolstring = (varfunc*)GetProcAddress(hinstLib, "lua_tolstring");
|
||||
lua_setfield = (varfunc*)GetProcAddress(hinstLib, "lua_setfield");
|
||||
lua_pushcclosure = (varfunc*)GetProcAddress(hinstLib, "lua_pushcclosure");
|
||||
lua_createtable = (varfuncvoid*)GetProcAddress(hinstLib, "lua_createtable");
|
||||
lua_pushstring = (varfuncvoid*)GetProcAddress(hinstLib, "lua_pushstring");
|
||||
lua_rawseti = (varfuncvoid*)GetProcAddress(hinstLib, "lua_rawseti");
|
||||
// If the function address is valid, call the function.
|
||||
|
||||
if (luaL_newstate && luaL_loadbuffer && luaL_openlibs && lua_pcall &&
|
||||
lua_pushcclosure && lua_setfield && lua_tolstring &&
|
||||
lua_createtable && lua_pushstring && lua_rawseti)
|
||||
{
|
||||
// OK, I don't do any error checking here, which COULD
|
||||
// lead to bugs that are hard to find, but considered the simplicity
|
||||
// of the whole process, it SHOULD be pretty unlikely to fail here
|
||||
// but don't come back on me if it does...
|
||||
void *L = luaL_newstate();
|
||||
int i;
|
||||
|
||||
if (L!=NULL) {
|
||||
lua_createtable(L,argc,0);
|
||||
for (i=0;i<argc;i++) {
|
||||
lua_pushstring(L,argv[i]);
|
||||
lua_rawseti(L,-2,i+1);
|
||||
}
|
||||
lua_setfield(L,LUA_GLOBALSINDEX,"_ARG");
|
||||
luaL_openlibs(L);
|
||||
lua_pushcclosure(L,luafunc_mbox,0);
|
||||
lua_setfield(L,LUA_GLOBALSINDEX,"_ERRMSG");
|
||||
if (luaL_loadbuffer(L,luacode,strlen(luacode),"Initializer") == 0)
|
||||
lua_pcall(L,0,0,0);
|
||||
else
|
||||
MessageBox(NULL,
|
||||
TEXT("An unexpected error occured while loading the lua chunk."),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
} else
|
||||
MessageBox(NULL,
|
||||
TEXT("Couldn't initialize a luastate"),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
} else {
|
||||
MessageBox(NULL,
|
||||
TEXT("Could not load all functions that are supposed to be located in the lua5.1.dll\n"
|
||||
"This is not supposed to be happening..."),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
}
|
||||
|
||||
// Free the DLL module.
|
||||
FreeLibrary(hinstLib);
|
||||
} else {
|
||||
MessageBox(NULL,
|
||||
TEXT("The lua5.1.dll could not be found or loaded, please check the working directory of the application.\n"),
|
||||
TEXT("Failed to initialize estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
// this is an extremly ugly quick and dirty hack...
|
||||
// maybe it could be refactored to do some error catching and
|
||||
// other things, but right now it does what it should...
|
||||
// (providing a single exe file in our main directory without
|
||||
// polluting it with all these dlls located in the /bin folder)
|
||||
|
||||
#ifdef __MINGW__ /* not sure if this is the *official* define */
|
||||
#define _WIN32_WINNT 0x0502
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* some typedef functions - these are not matching exactly the
|
||||
original definitions, but their signature is supposed to be
|
||||
compatible
|
||||
Currently 10 different functions are needed - each with different signatures... */
|
||||
typedef void *voidfunc ();
|
||||
typedef int *varfunc (void *L,...); // quick and dirty using the varargs
|
||||
typedef void varfuncvoid (void *L,...);
|
||||
|
||||
// from lua.h
|
||||
#define LUA_GLOBALSINDEX (-10002)
|
||||
|
||||
|
||||
static voidfunc *luaL_newstate;
|
||||
static varfunc *luaL_loadbuffer;
|
||||
static varfunc *luaL_openlibs;
|
||||
static varfunc *lua_pcall;
|
||||
static varfunc *lua_pushcclosure;
|
||||
static varfunc *lua_setfield;
|
||||
static varfunc *lua_tolstring;
|
||||
static varfuncvoid *lua_createtable;
|
||||
static varfuncvoid *lua_pushstring;
|
||||
static varfuncvoid *lua_rawseti;
|
||||
|
||||
static int luafunc_mbox (void *L)
|
||||
{
|
||||
const char *title = (const char*)lua_tolstring(L,1,NULL);
|
||||
const char *msg = (const char*)lua_tolstring(L,2,NULL);
|
||||
MessageBox(NULL,msg,title,MB_OK|MB_ICONERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *luacode =
|
||||
"local msg = _ERRMSG; _ERRMSG = nil "
|
||||
"local arg = _ARG or {}; _ARG = nil "
|
||||
"xpcall("
|
||||
"function() "
|
||||
"(loadfile 'src/main.lua')(unpack(arg)) end,"
|
||||
"function(err) msg('Uncaught lua script exception',debug.traceback(err)) end)"
|
||||
;
|
||||
|
||||
#if defined(_WIN32) && defined (_MSC_VER)
|
||||
|
||||
PCHAR* CommandLineToArgvA(PCHAR CmdLine,int* _argc)
|
||||
{
|
||||
PCHAR* argv;
|
||||
PCHAR _argv;
|
||||
size_t len;
|
||||
ULONG argc;
|
||||
CHAR a;
|
||||
size_t i, j;
|
||||
|
||||
BOOLEAN in_QM;
|
||||
BOOLEAN in_TEXT;
|
||||
BOOLEAN in_SPACE;
|
||||
|
||||
len = strlen(CmdLine);
|
||||
i = ((len+2)/2)*sizeof(PVOID) + sizeof(PVOID);
|
||||
|
||||
argv = (PCHAR*)GlobalAlloc(GMEM_FIXED,
|
||||
i + (len+2)*sizeof(CHAR));
|
||||
|
||||
_argv = (PCHAR)(((PUCHAR)argv)+i);
|
||||
|
||||
argc = 0;
|
||||
argv[argc] = _argv;
|
||||
in_QM = 0;
|
||||
in_TEXT = 0;
|
||||
in_SPACE = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
|
||||
while( a = CmdLine[i] ) {
|
||||
if(in_QM) {
|
||||
if(a == '\"') {
|
||||
in_QM = 0;
|
||||
} else {
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
}
|
||||
} else {
|
||||
switch(a) {
|
||||
case '\"':
|
||||
in_QM = 1;
|
||||
in_TEXT = 1;
|
||||
if(in_SPACE) {
|
||||
argv[argc] = _argv+j;
|
||||
argc++;
|
||||
}
|
||||
in_SPACE = 0;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r':
|
||||
if(in_TEXT) {
|
||||
_argv[j] = '\0';
|
||||
j++;
|
||||
}
|
||||
in_TEXT = 0;
|
||||
in_SPACE = 1;
|
||||
break;
|
||||
default:
|
||||
in_TEXT = 1;
|
||||
if(in_SPACE) {
|
||||
argv[argc] = _argv+j;
|
||||
argc++;
|
||||
}
|
||||
_argv[j] = a;
|
||||
j++;
|
||||
in_SPACE = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
_argv[j] = '\0';
|
||||
argv[argc] = NULL;
|
||||
|
||||
(*_argc) = argc;
|
||||
return argv;
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
int argc;
|
||||
char ** argv = CommandLineToArgvA(GetCommandLineA(),&argc);
|
||||
|
||||
#else
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
#endif
|
||||
HINSTANCE hinstLib;
|
||||
|
||||
|
||||
char buffer[MAX_PATH],*file;
|
||||
|
||||
if (!GetFullPathName(argv[0],MAX_PATH,buffer,&file)) {
|
||||
MessageBox(NULL,
|
||||
TEXT("Couldn't find the correct working directory"),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
return 0;
|
||||
}
|
||||
if (file!=NULL)
|
||||
*file = 0; // finish the string, I don't need the appname
|
||||
//int i;
|
||||
//for (i=0;i<argc; i++)
|
||||
// printf("%d %s\n",i,argv[i]);
|
||||
|
||||
SetCurrentDirectory(buffer);
|
||||
|
||||
|
||||
SetDllDirectory(".\\bin\\");
|
||||
hinstLib = LoadLibrary("lua5.1.dll");
|
||||
if (hinstLib != NULL)
|
||||
{
|
||||
luaL_newstate = (voidfunc*) GetProcAddress(hinstLib, "luaL_newstate");
|
||||
luaL_loadbuffer = (varfunc*) GetProcAddress(hinstLib, "luaL_loadbuffer");
|
||||
luaL_openlibs = (varfunc*) GetProcAddress(hinstLib, "luaL_openlibs");
|
||||
lua_pcall = (varfunc*)GetProcAddress(hinstLib, "lua_pcall");
|
||||
lua_tolstring = (varfunc*)GetProcAddress(hinstLib, "lua_tolstring");
|
||||
lua_setfield = (varfunc*)GetProcAddress(hinstLib, "lua_setfield");
|
||||
lua_pushcclosure = (varfunc*)GetProcAddress(hinstLib, "lua_pushcclosure");
|
||||
lua_createtable = (varfuncvoid*)GetProcAddress(hinstLib, "lua_createtable");
|
||||
lua_pushstring = (varfuncvoid*)GetProcAddress(hinstLib, "lua_pushstring");
|
||||
lua_rawseti = (varfuncvoid*)GetProcAddress(hinstLib, "lua_rawseti");
|
||||
// If the function address is valid, call the function.
|
||||
|
||||
if (luaL_newstate && luaL_loadbuffer && luaL_openlibs && lua_pcall &&
|
||||
lua_pushcclosure && lua_setfield && lua_tolstring &&
|
||||
lua_createtable && lua_pushstring && lua_rawseti)
|
||||
{
|
||||
// OK, I don't do any error checking here, which COULD
|
||||
// lead to bugs that are hard to find, but considered the simplicity
|
||||
// of the whole process, it SHOULD be pretty unlikely to fail here
|
||||
// but don't come back on me if it does...
|
||||
void *L = luaL_newstate();
|
||||
int i;
|
||||
|
||||
if (L!=NULL) {
|
||||
lua_createtable(L,argc,0);
|
||||
for (i=0;i<argc;i++) {
|
||||
lua_pushstring(L,argv[i]);
|
||||
lua_rawseti(L,-2,i+1);
|
||||
}
|
||||
lua_setfield(L,LUA_GLOBALSINDEX,"_ARG");
|
||||
luaL_openlibs(L);
|
||||
lua_pushcclosure(L,luafunc_mbox,0);
|
||||
lua_setfield(L,LUA_GLOBALSINDEX,"_ERRMSG");
|
||||
if (luaL_loadbuffer(L,luacode,strlen(luacode),"Initializer") == 0)
|
||||
lua_pcall(L,0,0,0);
|
||||
else
|
||||
MessageBox(NULL,
|
||||
TEXT("An unexpected error occured while loading the lua chunk."),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
} else
|
||||
MessageBox(NULL,
|
||||
TEXT("Couldn't initialize a luastate"),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
} else {
|
||||
MessageBox(NULL,
|
||||
TEXT("Could not load all functions that are supposed to be located in the lua5.1.dll\n"
|
||||
"This is not supposed to be happening..."),
|
||||
TEXT("Failed to start estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
}
|
||||
|
||||
// Free the DLL module.
|
||||
FreeLibrary(hinstLib);
|
||||
} else {
|
||||
MessageBox(NULL,
|
||||
TEXT("The lua5.1.dll could not be found or loaded, please check the working directory of the application.\n"),
|
||||
TEXT("Failed to initialize estrela"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor
|
||||
@@ -1,12 +1,12 @@
|
||||
return {
|
||||
name = "Estrela Editor",
|
||||
description = "Estrela Editor as run target (IDE development)",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename)
|
||||
local cmd = ide.editorFilename and '"'..ide.editorFilename..'" '..(wfilename and wfilename:GetFullPath() or "")..' -cfg "singleinstance=false;"' or nil
|
||||
CommandLineRun(cmd,nil,false,true)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
}
|
||||
return {
|
||||
name = "Estrela Editor",
|
||||
description = "Estrela Editor as run target (IDE development)",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename)
|
||||
local cmd = ide.editorFilename and '"'..ide.editorFilename..'" '..(wfilename and wfilename:GetFullPath() or "")..' -cfg "singleinstance=false;"' or nil
|
||||
CommandLineRun(cmd,nil,false,true)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
return {
|
||||
name = "Estrela Shell",
|
||||
description = "Estrela Lua Shell",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename)
|
||||
-- set shellbox for focus
|
||||
local bottomnotebook = ide.frame.vsplitter.splitter.bottomnotebook
|
||||
bottomnotebook:SetSelection(1)
|
||||
if ide.frame.menuBar:IsChecked(ID_CLEAROUTPUT) then
|
||||
local shellLog = bottomnotebook.shellbox.output
|
||||
shellLog:SetReadOnly(false)
|
||||
shellLog:ClearAll()
|
||||
shellLog:SetReadOnly(true)
|
||||
end
|
||||
|
||||
ShellExecuteCode(nil,wfilename)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
}
|
||||
return {
|
||||
name = "Estrela Shell",
|
||||
description = "Estrela Lua Shell",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename)
|
||||
-- set shellbox for focus
|
||||
local bottomnotebook = ide.frame.bottomnotebook
|
||||
bottomnotebook:SetSelection(1)
|
||||
|
||||
ShellExecuteCode(wfilename)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
return {
|
||||
name = "Lua",
|
||||
description = "Commandline Lua interpreter",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename,script)
|
||||
local mainpath = ide.editorFilename:gsub("[^/\\]+$","")
|
||||
local filepath = wfilename:GetFullPath()
|
||||
if not script then script = ([[dofile '%s']]):format(filepath:gsub("\\","/")) end
|
||||
local code = ([[xpcall(function() %s end,function(err) print(debug.traceback(err)) end)]]):format(script)
|
||||
local cmd = '"'..mainpath..'/bin/lua.exe" -e "'..code..'"'
|
||||
CommandLineRun(cmd,self:fworkdir(wfilename),true,false)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return ide.config.path.projectdir
|
||||
end,
|
||||
fworkdir = function (self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
}
|
||||
return {
|
||||
name = "Lua",
|
||||
description = "Commandline Lua interpreter",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename)
|
||||
local mainpath = ide.editorFilename:gsub("[^/\\]+$","")
|
||||
local filepath = wfilename:GetFullPath()
|
||||
local code = ([[
|
||||
xpcall(function() dofile '%s' end,
|
||||
function(err) print(debug.traceback(err)) end)
|
||||
]]):format(filepath:gsub("\\","/"))
|
||||
local cmd = '"'..mainpath..'/bin/lua.exe" -e "'..code..'"'
|
||||
CommandLineRun(cmd,self:fworkdir(wfilename),true,false)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
fworkdir = function (self,wfilename)
|
||||
return ide.config.path.projectdir and ide.config.path.projectdir:len()>0 and
|
||||
ide.config.path.projectdir
|
||||
end,
|
||||
}
|
||||
|
||||
33
interpreters/luadeb.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
return {
|
||||
name = "Lua Debug",
|
||||
description = "Commandline Lua interpreter",
|
||||
api = {"wxwidgets","baselib"},
|
||||
frun = function(self,wfilename,rundebug)
|
||||
local mainpath = string.gsub(ide.editorFilename:gsub("[^/\\]+$",""),"\\","/")
|
||||
local filepath = string.gsub(wfilename:GetFullPath(), "\\","/")
|
||||
local script
|
||||
if rundebug then
|
||||
DebuggerAttachDefault()
|
||||
script = (""..
|
||||
"package.path=package.path..';"..mainpath.."lualibs/?/?.lua';"..
|
||||
"package.cpath=package.cpath..';"..mainpath.."bin/clibs/?.dll';"..
|
||||
"require 'mobdebug'; io.stdout:setvbuf('no'); mobdebug.loop('" .. wx.wxGetHostName().."',"..ide.debugger.portnumber..")")
|
||||
else
|
||||
script = ([[dofile '%s']]):format(filepath)
|
||||
end
|
||||
local code = ([[xpcall(function() %s end,function(err) print(debug.traceback(err)) end)]]):format(script)
|
||||
local cmd = '"'..mainpath..'bin/lua.exe" -e "'..code..'"'
|
||||
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
fworkdir = function (self,wfilename)
|
||||
return ide.config.path.projectdir
|
||||
or wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
hasdebugger = true,
|
||||
fattachdebug = function(self)
|
||||
DebuggerAttachDefault()
|
||||
end,
|
||||
}
|
||||
@@ -1,27 +1,32 @@
|
||||
return {
|
||||
name = "Luxinia",
|
||||
description = "Luxinia project",
|
||||
api = {"luxiniaapi","baselib"},
|
||||
fcmdline = function(self,wfilename)
|
||||
local projdir = ide.config.path.projectdir
|
||||
local endstr = projdir and projdir:len()>0
|
||||
and " -p "..projdir or ""
|
||||
|
||||
local fname = wfilename:GetFullName()
|
||||
endstr = endstr..(fname and (" -t "..fname) or "")
|
||||
|
||||
local cmd = ide.config.path.luxinia..'luxinia.exe --nologo'..endstr
|
||||
CommandLineRun(cmd,ide.config.path.luxinia,true,true)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
local path = GetPathWithSep(wfilename)
|
||||
fname = wx.wxFileName(path)
|
||||
|
||||
while ((not wx.wxFileExists(path.."main.lua")) and (fname:GetDirCount() > 0)) do
|
||||
fname:RemoveDir(fname:GetDirCount()-1)
|
||||
path = GetPathWithSep(fname)
|
||||
end
|
||||
|
||||
return path:sub(0,-2)
|
||||
end,
|
||||
}
|
||||
if (not(ide.config.path.luxinia and
|
||||
wx.wxFileExists(ide.config.path.luxinia..'luxinia.exe'))) then
|
||||
return
|
||||
end
|
||||
|
||||
return {
|
||||
name = "Luxinia",
|
||||
description = "Luxinia project",
|
||||
api = {"luxiniaapi","baselib"},
|
||||
fcmdline = function(self,wfilename)
|
||||
local projdir = ide.config.path.projectdir
|
||||
local endstr = (projdir and projdir:len()>0
|
||||
and " -p "..projdir or "")
|
||||
|
||||
local fname = wfilename:GetFullName()
|
||||
endstr = endstr..(fname and (" -t "..fname) or "")
|
||||
|
||||
local cmd = 'luxinia.exe --nologo'..endstr
|
||||
CommandLineRun(cmd,ide.config.path.luxinia,true,true)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
local path = GetPathWithSep(wfilename)
|
||||
fname = wx.wxFileName(path)
|
||||
|
||||
while ((not wx.wxFileExists(path.."main.lua")) and (fname:GetDirCount() > 0)) do
|
||||
fname:RemoveDir(fname:GetDirCount()-1)
|
||||
path = GetPathWithSep(fname)
|
||||
end
|
||||
|
||||
return path:sub(0,-2)
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -1,60 +1,97 @@
|
||||
if (not(ide.config.path.luxinia2 and
|
||||
wx.wxFileExists(ide.config.path.luxinia2..'luajit.exe'))) then
|
||||
return
|
||||
end
|
||||
|
||||
return {
|
||||
name = "Luxinia2",
|
||||
description = "Luxinia2",
|
||||
api = {"baselib","cg30","cggl30","glfw3","glewgl","assimp20","luxmath","luxgfx","luxscene","luajit2",},
|
||||
|
||||
finitclient = function(self)
|
||||
if (not CommandLineRunning(self:fuid(wfilename))) then return end
|
||||
local init = dofile(ide.config.path.luxinia2.."/../comserver/client.lua")
|
||||
local fenv = {}
|
||||
setmetatable(fenv,{__index = _G})
|
||||
fenv.print = function(...) DisplayOutput(...); DisplayOutput("\n"); end
|
||||
|
||||
setfenv(init,fenv)
|
||||
local client = init()
|
||||
|
||||
self.fclient = client
|
||||
return client
|
||||
end,
|
||||
|
||||
frun = function(self,wfilename)
|
||||
local luxdir = ide.config.path.luxinia2
|
||||
local projdir = ide.config.path.projectdir
|
||||
assert(projdir and projdir:len()>0,"no project directory")
|
||||
local args = " -e "..projdir.."/main.lua"
|
||||
|
||||
if (CommandLineRunning(self:fuid(wfilename))) then
|
||||
if (not self.fclient) then
|
||||
self:finitclient()
|
||||
end
|
||||
-- try to communicate with server
|
||||
self.fclient("dofile([["..wfilename:GetFullPath().."]])")
|
||||
return
|
||||
end
|
||||
|
||||
self.fclient = nil
|
||||
local fname = wfilename:GetFullName()
|
||||
args = args..(fname and (" -f "..fname) or "")
|
||||
local jitargs = ide.config.luxinia2jitargs
|
||||
jitargs = jitargs or ""
|
||||
local cmd = luxdir..'/luajit.exe '..jitargs..' ../main.lua -s'..args
|
||||
|
||||
if(CommandLineRun(cmd,ide.config.path.luxinia2,true,true,nil,self:fuid(wfilename),
|
||||
function() ShellSupportRemote(nil) end)) then return end
|
||||
|
||||
local client = self:finitclient()
|
||||
ShellSupportRemote(client,self:fuid(wfilename))
|
||||
end,
|
||||
fuid = function(self,wfilename) return "luxinia2 "..(ide.config.path.projectdir or "") end,
|
||||
fprojdir = function(self,wfilename)
|
||||
local path = GetPathWithSep(wfilename)
|
||||
filepath = wx.wxFileName(path)
|
||||
|
||||
while ((not wx.wxFileExists(path.."main.lua")) and (filepath:GetDirCount() > 0)) do
|
||||
filepath:RemoveDir(filepath:GetDirCount()-1)
|
||||
path = GetPathWithSep(filepath)
|
||||
end
|
||||
|
||||
return path:sub(0,-2)
|
||||
end,
|
||||
}
|
||||
name = "Luxinia2",
|
||||
description = "Luxinia2",
|
||||
api = {"baselib","cg30","cggl30","glfw3","glewgl","assimp20","luxmath","luxgfx","luxscene","luajit2",},
|
||||
|
||||
finitclient = function(self)
|
||||
if (not CommandLineRunning(self:fuid(wfilename))) then return end
|
||||
local init = dofile(ide.config.path.luxinia2.."/../comserver/client.lua")
|
||||
local fenv = {}
|
||||
setmetatable(fenv,{__index = _G})
|
||||
fenv.print = function(...) DisplayOutput(...); DisplayOutput("\n"); end
|
||||
|
||||
setfenv(init,fenv)
|
||||
local client = init()
|
||||
|
||||
self.fclient = client
|
||||
return client
|
||||
end,
|
||||
|
||||
frun = function(self,wfilename,rundebug)
|
||||
local luxdir = ide.config.path.luxinia2
|
||||
local projdir = ide.config.path.projectdir
|
||||
assert(projdir and projdir:len()>0,"no project directory")
|
||||
local basedir = luxdir
|
||||
local startfile = projdir.."/main.lua"
|
||||
local startargs = " -e "..startfile
|
||||
|
||||
if (CommandLineRunning(self:fuid(wfilename))) then
|
||||
if (not self.fclient) then
|
||||
self:finitclient()
|
||||
end
|
||||
-- try to communicate with server
|
||||
self.fclient("dofile([["..wfilename:GetFullPath().."]])")
|
||||
return
|
||||
end
|
||||
|
||||
self.fclient = nil
|
||||
local fname = wfilename:GetFullName()
|
||||
local args = (fname and (" -f "..fname) or "")
|
||||
|
||||
if rundebug then
|
||||
DebuggerAttachDefault({
|
||||
basedir=basedir,
|
||||
startfile=startfile,
|
||||
run=true, noshell=true,}
|
||||
)
|
||||
local editorDir = string.gsub(ide.editorFilename:gsub("[^/\\]+$",""),"\\","/")
|
||||
script = ""..
|
||||
"package.path=package.path..';"..editorDir.."lualibs/?/?.lua';"..
|
||||
"require 'mobdebug'; io.stdout:setvbuf('no'); mobdebug.start('" .. wx.wxGetHostName().."',"..ide.debugger.portnumber..")"
|
||||
|
||||
args = args..' -es "'..script..'"'..startargs
|
||||
else
|
||||
args = " -s "..args..startargs
|
||||
end
|
||||
|
||||
local jitargs = ide.config.luxinia2jitargs
|
||||
jitargs = jitargs or ""
|
||||
local cmd = 'luajit.exe '..jitargs..' ../main.lua '..args
|
||||
|
||||
|
||||
local pid = CommandLineRun(cmd,ide.config.path.luxinia2,true,true,nil,self:fuid(wfilename),
|
||||
function()
|
||||
ShellSupportRemote(nil)
|
||||
if (rundebug) then
|
||||
DebuggerStop()
|
||||
end
|
||||
end)
|
||||
|
||||
if(not pid) then return end
|
||||
|
||||
if not rundebug then
|
||||
local client = self:finitclient()
|
||||
ShellSupportRemote(client,self:fuid(wfilename))
|
||||
end
|
||||
|
||||
return pid
|
||||
end,
|
||||
fuid = function(self,wfilename) return "luxinia2 "..(ide.config.path.projectdir or "") end,
|
||||
fprojdir = function(self,wfilename)
|
||||
local path = GetPathWithSep(wfilename)
|
||||
filepath = wx.wxFileName(path)
|
||||
|
||||
while ((not wx.wxFileExists(path.."main.lua")) and (filepath:GetDirCount() > 0)) do
|
||||
filepath:RemoveDir(filepath:GetDirCount()-1)
|
||||
path = GetPathWithSep(filepath)
|
||||
end
|
||||
|
||||
return path:sub(0,-2)
|
||||
end,
|
||||
hasdebugger = true,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- MobDebug 0.40
|
||||
-- MobDebug 0.43
|
||||
-- Copyright Paul Kulchenko 2011
|
||||
-- Based on RemDebug 1.0 (http://www.keplerproject.org/remdebug)
|
||||
--
|
||||
@@ -10,11 +10,12 @@ module("mobdebug", package.seeall)
|
||||
|
||||
_COPYRIGHT = "Paul Kulchenko"
|
||||
_DESCRIPTION = "Mobile Remote Debugger for the Lua programming language"
|
||||
_VERSION = "0.40"
|
||||
_VERSION = "0.43"
|
||||
|
||||
-- this is a socket class that implements maConnect interface
|
||||
local function socketMobileLua()
|
||||
local self = {}
|
||||
self.select = function() return {} end
|
||||
self.connect = coroutine.wrap(function(host, port)
|
||||
while true do
|
||||
local connection = maConnect("socket://" .. host .. ":" .. port)
|
||||
@@ -139,7 +140,11 @@ local coro_debugger
|
||||
local events = { BREAK = 1, WATCH = 2 }
|
||||
local breakpoints = {}
|
||||
local watches = {}
|
||||
local abort = false
|
||||
local lastsource
|
||||
local lastfile
|
||||
local watchescnt = 0
|
||||
local abort -- default value is nil; this is used in start/loop distinction
|
||||
local check_break = false
|
||||
local step_into = false
|
||||
local step_over = false
|
||||
local step_level = 0
|
||||
@@ -147,12 +152,12 @@ local stack_level = 0
|
||||
local server
|
||||
local debugee = function ()
|
||||
local a = 1
|
||||
print("Dummy script for debugging 1")
|
||||
print("Dummy script for debugging 2")
|
||||
a = a + 1
|
||||
return "ok"
|
||||
end
|
||||
|
||||
local function set_breakpoint(file, line)
|
||||
if file == '-' and lastfile then file = lastfile end
|
||||
if not breakpoints[file] then
|
||||
breakpoints[file] = {}
|
||||
end
|
||||
@@ -160,6 +165,7 @@ local function set_breakpoint(file, line)
|
||||
end
|
||||
|
||||
local function remove_breakpoint(file, line)
|
||||
if file == '-' and lastfile then file = lastfile end
|
||||
if breakpoints[file] then
|
||||
breakpoints[file][line] = nil
|
||||
end
|
||||
@@ -224,29 +230,40 @@ local function debug_hook(event, line)
|
||||
local caller = debug.getinfo(2, "S")
|
||||
|
||||
-- grab the filename and fix it if needed
|
||||
local file = caller.source
|
||||
if string.find(file, "@") == 1 then
|
||||
file = string.sub(file, 2)
|
||||
end
|
||||
-- remove references to the current folder (./ or .\)
|
||||
if string.find(file, "./") == 1 or string.find(file, ".\\") == 1 then
|
||||
file = string.sub(file, 3)
|
||||
end
|
||||
-- fix filenames for loaded strings that may contain scripts with newlines
|
||||
if string.find(file, "\n") then
|
||||
file = string.sub(string.gsub(file, "\n", ' '), 1, 32) -- limit to 32 chars
|
||||
local file = lastfile
|
||||
if (lastsource ~= caller.source) then
|
||||
lastsource = caller.source
|
||||
file = lastsource
|
||||
if string.find(file, "@") == 1 then file = string.sub(file, 2) end
|
||||
-- remove references to the current folder (./ or .\)
|
||||
if string.find(file, "%.[/\\]") == 1 then file = string.sub(file, 3) end
|
||||
-- fix filenames for loaded strings that may contain scripts with newlines
|
||||
if string.find(file, "\n") then
|
||||
file = string.sub(string.gsub(file, "\n", ' '), 1, 32) -- limit to 32 chars
|
||||
end
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
lastfile = file
|
||||
end
|
||||
|
||||
local vars = capture_vars()
|
||||
for index, value in pairs(watches) do
|
||||
setfenv(value, vars)
|
||||
local status, res = pcall(value)
|
||||
if status and res then
|
||||
coroutine.resume(coro_debugger, events.WATCH, vars, file, line, index)
|
||||
restore_vars(vars)
|
||||
local vars
|
||||
if (watchescnt > 0) then
|
||||
vars = capture_vars()
|
||||
for index, value in pairs(watches) do
|
||||
setfenv(value, vars)
|
||||
local status, res = pcall(value)
|
||||
if status and res then
|
||||
coroutine.resume(coro_debugger, events.WATCH, vars, file, line, index)
|
||||
restore_vars(vars)
|
||||
end
|
||||
end
|
||||
end
|
||||
if step_into or (step_over and stack_level <= step_level) or has_breakpoint(file, line) then
|
||||
|
||||
if step_into
|
||||
or (step_over and stack_level <= step_level)
|
||||
or has_breakpoint(file, line)
|
||||
or (check_break and (socket.select({server}, {}, 0))[server]) then
|
||||
vars = vars or capture_vars()
|
||||
check_break = true -- this is only needed to avoid breaking too early when debugging is starting
|
||||
step_into = false
|
||||
step_over = false
|
||||
coroutine.resume(coro_debugger, events.BREAK, vars, file, line)
|
||||
@@ -254,26 +271,49 @@ local function debug_hook(event, line)
|
||||
end
|
||||
end
|
||||
|
||||
local function debugger_loop()
|
||||
local function debugger_loop(sfile, sline)
|
||||
local command
|
||||
local eval_env = {}
|
||||
local function emptyWatch () return false end
|
||||
|
||||
while true do
|
||||
local line = server:receive()
|
||||
local line, err
|
||||
if server.settimeout then server:settimeout(0.010) end
|
||||
while true do
|
||||
line, err = server:receive()
|
||||
if not line and err == "timeout" then
|
||||
-- yield for wx GUI applications if possible to avoid "busyness"
|
||||
if wx and wx.wxGetApp then
|
||||
local app = wx.wxGetApp()
|
||||
local win = app:GetTopWindow()
|
||||
if win then
|
||||
-- process messages in a regular way
|
||||
-- and exit as soon as the event loop is idle
|
||||
win:Connect(wx.wxEVT_IDLE, function(event)
|
||||
app:ExitMainLoop()
|
||||
win:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_IDLE)
|
||||
end)
|
||||
app:MainLoop()
|
||||
end
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
if server.settimeout then server:settimeout() end -- back to blocking
|
||||
command = string.sub(line, string.find(line, "^[A-Z]+"))
|
||||
if command == "SETB" then
|
||||
local _, _, _, filename, line = string.find(line, "^([A-Z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if filename and line then
|
||||
set_breakpoint(filename, tonumber(line))
|
||||
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if file and line then
|
||||
set_breakpoint(file, tonumber(line))
|
||||
server:send("200 OK\n")
|
||||
else
|
||||
server:send("400 Bad Request\n")
|
||||
end
|
||||
elseif command == "DELB" then
|
||||
local _, _, _, filename, line = string.find(line, "^([A-Z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if filename and line then
|
||||
remove_breakpoint(filename, tonumber(line))
|
||||
_, _, _, file, line = string.find(line, "^([A-Z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if file and line then
|
||||
remove_breakpoint(file, tonumber(line))
|
||||
server:send("200 OK\n")
|
||||
else
|
||||
server:send("400 Bad Request\n")
|
||||
@@ -301,32 +341,43 @@ local function debugger_loop()
|
||||
elseif command == "LOAD" then
|
||||
local _, _, size, name = string.find(line, "^[A-Z]+%s+(%d+)%s+([%w%p%s]*[%w%p]+)%s*$")
|
||||
size = tonumber(size)
|
||||
if size == 0 then -- RELOAD the current script being debugged
|
||||
server:send("200 OK 0\n")
|
||||
abort = true
|
||||
coroutine.yield() -- this should not return as the hook will abort
|
||||
end
|
||||
|
||||
local chunk = server:receive(size)
|
||||
if chunk then -- LOAD a new script for debugging
|
||||
local func, res = loadstring(chunk, name)
|
||||
if func then
|
||||
server:send("200 OK 0\n")
|
||||
debugee = func
|
||||
abort = true
|
||||
coroutine.yield() -- this should not return as the hook will abort
|
||||
if abort == nil then -- no LOAD/RELOAD allowed inside start()
|
||||
if size > 0 then local _ = server:receive(size) end
|
||||
if sfile and sline then
|
||||
server:send("201 Started " .. sfile .. " " .. sline .. "\n")
|
||||
else
|
||||
server:send("401 Error in Expression " .. string.len(res) .. "\n")
|
||||
server:send(res)
|
||||
server:send("200 OK 0\n")
|
||||
end
|
||||
else
|
||||
server:send("400 Bad Request\n")
|
||||
if size == 0 then -- RELOAD the current script being debugged
|
||||
server:send("200 OK 0\n")
|
||||
abort = true
|
||||
coroutine.yield() -- this should not return as the hook will abort
|
||||
end
|
||||
|
||||
local chunk = server:receive(size)
|
||||
if chunk then -- LOAD a new script for debugging
|
||||
local func, res = loadstring(chunk, name)
|
||||
if func then
|
||||
server:send("200 OK 0\n")
|
||||
debugee = func
|
||||
abort = true
|
||||
coroutine.yield() -- this should not return as the hook will abort
|
||||
else
|
||||
server:send("401 Error in Expression " .. string.len(res) .. "\n")
|
||||
server:send(res)
|
||||
end
|
||||
else
|
||||
server:send("400 Bad Request\n")
|
||||
end
|
||||
end
|
||||
elseif command == "SETW" then
|
||||
local _, _, exp = string.find(line, "^[A-Z]+%s+(.+)%s*$")
|
||||
if exp then
|
||||
local func = loadstring("return(" .. exp .. ")")
|
||||
if func then
|
||||
watchescnt = watchescnt + 1
|
||||
local newidx = #watches + 1
|
||||
watches[newidx] = func
|
||||
server:send("200 OK " .. newidx .. "\n")
|
||||
@@ -340,13 +391,15 @@ local function debugger_loop()
|
||||
local _, _, index = string.find(line, "^[A-Z]+%s+(%d+)%s*$")
|
||||
index = tonumber(index)
|
||||
if index > 0 and index <= #watches then
|
||||
watchescnt = watchescnt - (watches[index] ~= emptyWatch and 1 or 0)
|
||||
watches[index] = emptyWatch
|
||||
server:send("200 OK\n")
|
||||
server:send("200 OK\n")
|
||||
else
|
||||
server:send("400 Bad Request\n")
|
||||
end
|
||||
elseif command == "RUN" then
|
||||
server:send("200 OK\n")
|
||||
|
||||
local ev, vars, file, line, idx_watch = coroutine.yield()
|
||||
eval_env = vars
|
||||
if ev == events.BREAK then
|
||||
@@ -360,6 +413,7 @@ local function debugger_loop()
|
||||
elseif command == "STEP" then
|
||||
server:send("200 OK\n")
|
||||
step_into = true
|
||||
|
||||
local ev, vars, file, line, idx_watch = coroutine.yield()
|
||||
eval_env = vars
|
||||
if ev == events.BREAK then
|
||||
@@ -406,10 +460,14 @@ end
|
||||
function start(controller_host, controller_port)
|
||||
server = socket.connect(controller_host, controller_port)
|
||||
if server then
|
||||
print("Connected to " .. controller_host .. ":" .. controller_port)
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
local file = info.source
|
||||
if string.find(file, "@") == 1 then file = string.sub(file, 2) end
|
||||
if string.find(file, "%.[/\\]") == 1 then file = string.sub(file, 3) end
|
||||
|
||||
debug.sethook(debug_hook, "lcr")
|
||||
coro_debugger = coroutine.create(debugger_loop)
|
||||
return coroutine.resume(coro_debugger)
|
||||
return coroutine.resume(coro_debugger, file, info.currentline)
|
||||
else
|
||||
print("Could not connect to " .. controller_host .. ":" .. controller_port)
|
||||
end
|
||||
@@ -418,8 +476,6 @@ end
|
||||
function loop(controller_host, controller_port)
|
||||
server = socket.connect(controller_host, controller_port)
|
||||
if server then
|
||||
print("Connected to " .. controller_host .. ":" .. controller_port)
|
||||
|
||||
local function report(trace, err)
|
||||
local msg = err .. "\n" .. trace
|
||||
server:send("401 Error in Execution " .. string.len(msg) .. "\n")
|
||||
@@ -494,13 +550,14 @@ function handle(params, client)
|
||||
return nil, nil, "Unknown error" -- use return here for those cases where os.exit() is not wanted
|
||||
end
|
||||
elseif command == "setb" then
|
||||
_, _, _, filename, line = string.find(params, "^([a-z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if filename and line then
|
||||
filename = string.gsub(filename, basedir, '') -- remove basedir
|
||||
if not breakpoints[filename] then breakpoints[filename] = {} end
|
||||
client:send("SETB " .. filename .. " " .. line .. "\n")
|
||||
_, _, _, file, line = string.find(params, "^([a-z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if file and line then
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = string.gsub(file, basedir, '') -- remove basedir
|
||||
if not breakpoints[file] then breakpoints[file] = {} end
|
||||
client:send("SETB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
breakpoints[filename][line] = true
|
||||
breakpoints[file][line] = true
|
||||
else
|
||||
print("Error: breakpoint not inserted")
|
||||
end
|
||||
@@ -523,13 +580,14 @@ function handle(params, client)
|
||||
print("Invalid command")
|
||||
end
|
||||
elseif command == "delb" then
|
||||
_, _, _, filename, line = string.find(params, "^([a-z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if filename and line then
|
||||
filename = string.gsub(filename, basedir, '') -- remove basedir
|
||||
if not breakpoints[filename] then breakpoints[filename] = {} end
|
||||
client:send("DELB " .. filename .. " " .. line .. "\n")
|
||||
_, _, _, file, line = string.find(params, "^([a-z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
if file and line then
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = string.gsub(file, basedir, '') -- remove basedir
|
||||
if not breakpoints[file] then breakpoints[file] = {} end
|
||||
client:send("DELB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
breakpoints[filename][line] = nil
|
||||
breakpoints[file][line] = nil
|
||||
else
|
||||
print("Error: breakpoint not removed")
|
||||
end
|
||||
@@ -537,13 +595,13 @@ function handle(params, client)
|
||||
print("Invalid command")
|
||||
end
|
||||
elseif command == "delallb" then
|
||||
for filename, breaks in pairs(breakpoints) do
|
||||
for file, breaks in pairs(breakpoints) do
|
||||
for line, _ in pairs(breaks) do
|
||||
client:send("DELB " .. filename .. " " .. line .. "\n")
|
||||
client:send("DELB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
breakpoints[filename][line] = nil
|
||||
breakpoints[file][line] = nil
|
||||
else
|
||||
print("Error: breakpoint at file " .. filename .. " line " .. line .. " not removed")
|
||||
print("Error: breakpoint at file " .. file .. " line " .. line .. " not removed")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -573,8 +631,10 @@ function handle(params, client)
|
||||
local _, _, exp = string.find(params, "^[a-z]+%s+(.+)$")
|
||||
if exp or (command == "reload") then
|
||||
if command == "eval" then
|
||||
client:send("EXEC return (" .. exp .. ")\n")
|
||||
exp = string.gsub(exp, "\n", " ") -- convert new lines
|
||||
client:send("EXEC return " .. exp .. "\n")
|
||||
elseif command == "exec" then
|
||||
exp = string.gsub(exp, "\n", " ") -- convert new lines
|
||||
client:send("EXEC " .. exp .. "\n")
|
||||
elseif command == "reload" then
|
||||
client:send("LOAD 0 -\n")
|
||||
@@ -584,12 +644,13 @@ function handle(params, client)
|
||||
local lines = file:read("*all")
|
||||
file:close()
|
||||
|
||||
local filename = string.gsub(exp, basedir, '') -- remove basedir
|
||||
client:send("LOAD " .. string.len(lines) .. " " .. filename .. "\n")
|
||||
local file = string.gsub(exp, "\\", "/") -- convert slash
|
||||
file = string.gsub(file, basedir, '') -- remove basedir
|
||||
client:send("LOAD " .. string.len(lines) .. " " .. file .. "\n")
|
||||
client:send(lines)
|
||||
end
|
||||
local line = client:receive()
|
||||
local _, _, status, len = string.find(line, "^(%d+)[%s%w]+%s+(%d+)%s*$")
|
||||
local params = client:receive()
|
||||
local _, _, status, len = string.find(params, "^(%d+)[%w%p%s]+%s+(%d+)%s*$")
|
||||
if status == "200" then
|
||||
len = tonumber(len)
|
||||
if len > 0 then
|
||||
@@ -597,6 +658,8 @@ function handle(params, client)
|
||||
print(res)
|
||||
return res
|
||||
end
|
||||
elseif status == "201" then
|
||||
_, _, file, line = string.find(params, "^201 Started%s+([%w%p%s]+)%s+(%d+)%s*$")
|
||||
elseif status == "401" then
|
||||
len = tonumber(len)
|
||||
local res = client:receive(len)
|
||||
@@ -624,6 +687,7 @@ function handle(params, client)
|
||||
elseif command == "basedir" then
|
||||
local _, _, dir = string.find(params, "^[a-z]+%s+(.+)$")
|
||||
if dir then
|
||||
dir = string.gsub(dir, "\\", "/") -- convert slash
|
||||
if not string.find(dir, "/$") then dir = dir .. "/" end
|
||||
basedir = dir
|
||||
print("New base directory is " .. basedir)
|
||||
|
||||
@@ -1,291 +1,291 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- LTN12 - Filters, sources, sinks and pumps.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: ltn12.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module
|
||||
-----------------------------------------------------------------------------
|
||||
local string = require("string")
|
||||
local table = require("table")
|
||||
local base = _G
|
||||
module("ltn12")
|
||||
|
||||
filter = {}
|
||||
source = {}
|
||||
sink = {}
|
||||
pump = {}
|
||||
|
||||
-- 2048 seems to be better in windows...
|
||||
BLOCKSIZE = 2048
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Filter stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- returns a high level filter that cycles a low-level filter
|
||||
function filter.cycle(low, ctx, extra)
|
||||
base.assert(low)
|
||||
return function(chunk)
|
||||
local ret
|
||||
ret, ctx = low(ctx, chunk, extra)
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
-- chains a bunch of filters together
|
||||
-- (thanks to Wim Couwenberg)
|
||||
function filter.chain(...)
|
||||
local n = table.getn(arg)
|
||||
local top, index = 1, 1
|
||||
local retry = ""
|
||||
return function(chunk)
|
||||
retry = chunk and retry
|
||||
while true do
|
||||
if index == top then
|
||||
chunk = arg[index](chunk)
|
||||
if chunk == "" or top == n then return chunk
|
||||
elseif chunk then index = index + 1
|
||||
else
|
||||
top = top+1
|
||||
index = top
|
||||
end
|
||||
else
|
||||
chunk = arg[index](chunk or "")
|
||||
if chunk == "" then
|
||||
index = index - 1
|
||||
chunk = retry
|
||||
elseif chunk then
|
||||
if index == n then return chunk
|
||||
else index = index + 1 end
|
||||
else base.error("filter returned inappropriate nil") end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Source stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- create an empty source
|
||||
local function empty()
|
||||
return nil
|
||||
end
|
||||
|
||||
function source.empty()
|
||||
return empty
|
||||
end
|
||||
|
||||
-- returns a source that just outputs an error
|
||||
function source.error(err)
|
||||
return function()
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a file source
|
||||
function source.file(handle, io_err)
|
||||
if handle then
|
||||
return function()
|
||||
local chunk = handle:read(BLOCKSIZE)
|
||||
if not chunk then handle:close() end
|
||||
return chunk
|
||||
end
|
||||
else return source.error(io_err or "unable to open file") end
|
||||
end
|
||||
|
||||
-- turns a fancy source into a simple source
|
||||
function source.simplify(src)
|
||||
base.assert(src)
|
||||
return function()
|
||||
local chunk, err_or_new = src()
|
||||
src = err_or_new or src
|
||||
if not chunk then return nil, err_or_new
|
||||
else return chunk end
|
||||
end
|
||||
end
|
||||
|
||||
-- creates string source
|
||||
function source.string(s)
|
||||
if s then
|
||||
local i = 1
|
||||
return function()
|
||||
local chunk = string.sub(s, i, i+BLOCKSIZE-1)
|
||||
i = i + BLOCKSIZE
|
||||
if chunk ~= "" then return chunk
|
||||
else return nil end
|
||||
end
|
||||
else return source.empty() end
|
||||
end
|
||||
|
||||
-- creates rewindable source
|
||||
function source.rewind(src)
|
||||
base.assert(src)
|
||||
local t = {}
|
||||
return function(chunk)
|
||||
if not chunk then
|
||||
chunk = table.remove(t)
|
||||
if not chunk then return src()
|
||||
else return chunk end
|
||||
else
|
||||
table.insert(t, chunk)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function source.chain(src, f)
|
||||
base.assert(src and f)
|
||||
local last_in, last_out = "", ""
|
||||
local state = "feeding"
|
||||
local err
|
||||
return function()
|
||||
if not last_out then
|
||||
base.error('source is empty!', 2)
|
||||
end
|
||||
while true do
|
||||
if state == "feeding" then
|
||||
last_in, err = src()
|
||||
if err then return nil, err end
|
||||
last_out = f(last_in)
|
||||
if not last_out then
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
else
|
||||
return nil
|
||||
end
|
||||
elseif last_out ~= "" then
|
||||
state = "eating"
|
||||
if last_in then last_in = "" end
|
||||
return last_out
|
||||
end
|
||||
else
|
||||
last_out = f(last_in)
|
||||
if last_out == "" then
|
||||
if last_in == "" then
|
||||
state = "feeding"
|
||||
else
|
||||
base.error('filter returned ""')
|
||||
end
|
||||
elseif not last_out then
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return last_out
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a source that produces contents of several sources, one after the
|
||||
-- other, as if they were concatenated
|
||||
-- (thanks to Wim Couwenberg)
|
||||
function source.cat(...)
|
||||
local src = table.remove(arg, 1)
|
||||
return function()
|
||||
while src do
|
||||
local chunk, err = src()
|
||||
if chunk then return chunk end
|
||||
if err then return nil, err end
|
||||
src = table.remove(arg, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Sink stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- creates a sink that stores into a table
|
||||
function sink.table(t)
|
||||
t = t or {}
|
||||
local f = function(chunk, err)
|
||||
if chunk then table.insert(t, chunk) end
|
||||
return 1
|
||||
end
|
||||
return f, t
|
||||
end
|
||||
|
||||
-- turns a fancy sink into a simple sink
|
||||
function sink.simplify(snk)
|
||||
base.assert(snk)
|
||||
return function(chunk, err)
|
||||
local ret, err_or_new = snk(chunk, err)
|
||||
if not ret then return nil, err_or_new end
|
||||
snk = err_or_new or snk
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a file sink
|
||||
function sink.file(handle, io_err)
|
||||
if handle then
|
||||
return function(chunk, err)
|
||||
if not chunk then
|
||||
handle:close()
|
||||
return 1
|
||||
else return handle:write(chunk) end
|
||||
end
|
||||
else return sink.error(io_err or "unable to open file") end
|
||||
end
|
||||
|
||||
-- creates a sink that discards data
|
||||
local function null()
|
||||
return 1
|
||||
end
|
||||
|
||||
function sink.null()
|
||||
return null
|
||||
end
|
||||
|
||||
-- creates a sink that just returns an error
|
||||
function sink.error(err)
|
||||
return function()
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
-- chains a sink with a filter
|
||||
function sink.chain(f, snk)
|
||||
base.assert(f and snk)
|
||||
return function(chunk, err)
|
||||
if chunk ~= "" then
|
||||
local filtered = f(chunk)
|
||||
local done = chunk and ""
|
||||
while true do
|
||||
local ret, snkerr = snk(filtered, err)
|
||||
if not ret then return nil, snkerr end
|
||||
if filtered == done then return 1 end
|
||||
filtered = f(done)
|
||||
end
|
||||
else return 1 end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Pump stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- pumps one chunk from the source to the sink
|
||||
function pump.step(src, snk)
|
||||
local chunk, src_err = src()
|
||||
local ret, snk_err = snk(chunk, src_err)
|
||||
if chunk and ret then return 1
|
||||
else return nil, src_err or snk_err end
|
||||
end
|
||||
|
||||
-- pumps all data from a source to a sink, using a step function
|
||||
function pump.all(src, snk, step)
|
||||
base.assert(src and snk)
|
||||
step = step or pump.step
|
||||
while true do
|
||||
local ret, err = step(src, snk)
|
||||
if not ret then
|
||||
if err then return nil, err
|
||||
else return 1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- LTN12 - Filters, sources, sinks and pumps.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: ltn12.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module
|
||||
-----------------------------------------------------------------------------
|
||||
local string = require("string")
|
||||
local table = require("table")
|
||||
local base = _G
|
||||
module("ltn12")
|
||||
|
||||
filter = {}
|
||||
source = {}
|
||||
sink = {}
|
||||
pump = {}
|
||||
|
||||
-- 2048 seems to be better in windows...
|
||||
BLOCKSIZE = 2048
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Filter stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- returns a high level filter that cycles a low-level filter
|
||||
function filter.cycle(low, ctx, extra)
|
||||
base.assert(low)
|
||||
return function(chunk)
|
||||
local ret
|
||||
ret, ctx = low(ctx, chunk, extra)
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
-- chains a bunch of filters together
|
||||
-- (thanks to Wim Couwenberg)
|
||||
function filter.chain(...)
|
||||
local n = table.getn(arg)
|
||||
local top, index = 1, 1
|
||||
local retry = ""
|
||||
return function(chunk)
|
||||
retry = chunk and retry
|
||||
while true do
|
||||
if index == top then
|
||||
chunk = arg[index](chunk)
|
||||
if chunk == "" or top == n then return chunk
|
||||
elseif chunk then index = index + 1
|
||||
else
|
||||
top = top+1
|
||||
index = top
|
||||
end
|
||||
else
|
||||
chunk = arg[index](chunk or "")
|
||||
if chunk == "" then
|
||||
index = index - 1
|
||||
chunk = retry
|
||||
elseif chunk then
|
||||
if index == n then return chunk
|
||||
else index = index + 1 end
|
||||
else base.error("filter returned inappropriate nil") end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Source stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- create an empty source
|
||||
local function empty()
|
||||
return nil
|
||||
end
|
||||
|
||||
function source.empty()
|
||||
return empty
|
||||
end
|
||||
|
||||
-- returns a source that just outputs an error
|
||||
function source.error(err)
|
||||
return function()
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a file source
|
||||
function source.file(handle, io_err)
|
||||
if handle then
|
||||
return function()
|
||||
local chunk = handle:read(BLOCKSIZE)
|
||||
if not chunk then handle:close() end
|
||||
return chunk
|
||||
end
|
||||
else return source.error(io_err or "unable to open file") end
|
||||
end
|
||||
|
||||
-- turns a fancy source into a simple source
|
||||
function source.simplify(src)
|
||||
base.assert(src)
|
||||
return function()
|
||||
local chunk, err_or_new = src()
|
||||
src = err_or_new or src
|
||||
if not chunk then return nil, err_or_new
|
||||
else return chunk end
|
||||
end
|
||||
end
|
||||
|
||||
-- creates string source
|
||||
function source.string(s)
|
||||
if s then
|
||||
local i = 1
|
||||
return function()
|
||||
local chunk = string.sub(s, i, i+BLOCKSIZE-1)
|
||||
i = i + BLOCKSIZE
|
||||
if chunk ~= "" then return chunk
|
||||
else return nil end
|
||||
end
|
||||
else return source.empty() end
|
||||
end
|
||||
|
||||
-- creates rewindable source
|
||||
function source.rewind(src)
|
||||
base.assert(src)
|
||||
local t = {}
|
||||
return function(chunk)
|
||||
if not chunk then
|
||||
chunk = table.remove(t)
|
||||
if not chunk then return src()
|
||||
else return chunk end
|
||||
else
|
||||
table.insert(t, chunk)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function source.chain(src, f)
|
||||
base.assert(src and f)
|
||||
local last_in, last_out = "", ""
|
||||
local state = "feeding"
|
||||
local err
|
||||
return function()
|
||||
if not last_out then
|
||||
base.error('source is empty!', 2)
|
||||
end
|
||||
while true do
|
||||
if state == "feeding" then
|
||||
last_in, err = src()
|
||||
if err then return nil, err end
|
||||
last_out = f(last_in)
|
||||
if not last_out then
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
else
|
||||
return nil
|
||||
end
|
||||
elseif last_out ~= "" then
|
||||
state = "eating"
|
||||
if last_in then last_in = "" end
|
||||
return last_out
|
||||
end
|
||||
else
|
||||
last_out = f(last_in)
|
||||
if last_out == "" then
|
||||
if last_in == "" then
|
||||
state = "feeding"
|
||||
else
|
||||
base.error('filter returned ""')
|
||||
end
|
||||
elseif not last_out then
|
||||
if last_in then
|
||||
base.error('filter returned inappropriate nil')
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return last_out
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a source that produces contents of several sources, one after the
|
||||
-- other, as if they were concatenated
|
||||
-- (thanks to Wim Couwenberg)
|
||||
function source.cat(...)
|
||||
local src = table.remove(arg, 1)
|
||||
return function()
|
||||
while src do
|
||||
local chunk, err = src()
|
||||
if chunk then return chunk end
|
||||
if err then return nil, err end
|
||||
src = table.remove(arg, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Sink stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- creates a sink that stores into a table
|
||||
function sink.table(t)
|
||||
t = t or {}
|
||||
local f = function(chunk, err)
|
||||
if chunk then table.insert(t, chunk) end
|
||||
return 1
|
||||
end
|
||||
return f, t
|
||||
end
|
||||
|
||||
-- turns a fancy sink into a simple sink
|
||||
function sink.simplify(snk)
|
||||
base.assert(snk)
|
||||
return function(chunk, err)
|
||||
local ret, err_or_new = snk(chunk, err)
|
||||
if not ret then return nil, err_or_new end
|
||||
snk = err_or_new or snk
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a file sink
|
||||
function sink.file(handle, io_err)
|
||||
if handle then
|
||||
return function(chunk, err)
|
||||
if not chunk then
|
||||
handle:close()
|
||||
return 1
|
||||
else return handle:write(chunk) end
|
||||
end
|
||||
else return sink.error(io_err or "unable to open file") end
|
||||
end
|
||||
|
||||
-- creates a sink that discards data
|
||||
local function null()
|
||||
return 1
|
||||
end
|
||||
|
||||
function sink.null()
|
||||
return null
|
||||
end
|
||||
|
||||
-- creates a sink that just returns an error
|
||||
function sink.error(err)
|
||||
return function()
|
||||
return nil, err
|
||||
end
|
||||
end
|
||||
|
||||
-- chains a sink with a filter
|
||||
function sink.chain(f, snk)
|
||||
base.assert(f and snk)
|
||||
return function(chunk, err)
|
||||
if chunk ~= "" then
|
||||
local filtered = f(chunk)
|
||||
local done = chunk and ""
|
||||
while true do
|
||||
local ret, snkerr = snk(filtered, err)
|
||||
if not ret then return nil, snkerr end
|
||||
if filtered == done then return 1 end
|
||||
filtered = f(done)
|
||||
end
|
||||
else return 1 end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Pump stuff
|
||||
-----------------------------------------------------------------------------
|
||||
-- pumps one chunk from the source to the sink
|
||||
function pump.step(src, snk)
|
||||
local chunk, src_err = src()
|
||||
local ret, snk_err = snk(chunk, src_err)
|
||||
if chunk and ret then return 1
|
||||
else return nil, src_err or snk_err end
|
||||
end
|
||||
|
||||
-- pumps all data from a source to a sink, using a step function
|
||||
function pump.all(src, snk, step)
|
||||
base.assert(src and snk)
|
||||
step = step or pump.step
|
||||
while true do
|
||||
local ret, err = step(src, snk)
|
||||
if not ret then
|
||||
if err then return nil, err
|
||||
else return 1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- MIME support for the Lua language.
|
||||
-- Author: Diego Nehab
|
||||
-- Conforming to RFCs 2045-2049
|
||||
-- RCS ID: $Id: mime.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime.core")
|
||||
local io = require("io")
|
||||
local string = require("string")
|
||||
module("mime")
|
||||
|
||||
-- encode, decode and wrap algorithm tables
|
||||
encodet = {}
|
||||
decodet = {}
|
||||
wrapt = {}
|
||||
|
||||
-- creates a function that chooses a filter by name from a given table
|
||||
local function choose(table)
|
||||
return function(name, opt1, opt2)
|
||||
if base.type(name) ~= "string" then
|
||||
name, opt1, opt2 = "default", name, opt1
|
||||
end
|
||||
local f = table[name or "nil"]
|
||||
if not f then error("unknown key (" .. base.tostring(name) .. ")", 3)
|
||||
else return f(opt1, opt2) end
|
||||
end
|
||||
end
|
||||
|
||||
-- define the encoding filters
|
||||
encodet['base64'] = function()
|
||||
return ltn12.filter.cycle(b64, "")
|
||||
end
|
||||
|
||||
encodet['quoted-printable'] = function(mode)
|
||||
return ltn12.filter.cycle(qp, "",
|
||||
(mode == "binary") and "=0D=0A" or "\r\n")
|
||||
end
|
||||
|
||||
-- define the decoding filters
|
||||
decodet['base64'] = function()
|
||||
return ltn12.filter.cycle(unb64, "")
|
||||
end
|
||||
|
||||
decodet['quoted-printable'] = function()
|
||||
return ltn12.filter.cycle(unqp, "")
|
||||
end
|
||||
|
||||
local function format(chunk)
|
||||
if chunk then
|
||||
if chunk == "" then return "''"
|
||||
else return string.len(chunk) end
|
||||
else return "nil" end
|
||||
end
|
||||
|
||||
-- define the line-wrap filters
|
||||
wrapt['text'] = function(length)
|
||||
length = length or 76
|
||||
return ltn12.filter.cycle(wrp, length, length)
|
||||
end
|
||||
wrapt['base64'] = wrapt['text']
|
||||
wrapt['default'] = wrapt['text']
|
||||
|
||||
wrapt['quoted-printable'] = function()
|
||||
return ltn12.filter.cycle(qpwrp, 76, 76)
|
||||
end
|
||||
|
||||
-- function that choose the encoding, decoding or wrap algorithm
|
||||
encode = choose(encodet)
|
||||
decode = choose(decodet)
|
||||
wrap = choose(wrapt)
|
||||
|
||||
-- define the end-of-line normalization filter
|
||||
function normalize(marker)
|
||||
return ltn12.filter.cycle(eol, 0, marker)
|
||||
end
|
||||
|
||||
-- high level stuffing filter
|
||||
function stuff()
|
||||
return ltn12.filter.cycle(dot, 2)
|
||||
end
|
||||
-----------------------------------------------------------------------------
|
||||
-- MIME support for the Lua language.
|
||||
-- Author: Diego Nehab
|
||||
-- Conforming to RFCs 2045-2049
|
||||
-- RCS ID: $Id: mime.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime.core")
|
||||
local io = require("io")
|
||||
local string = require("string")
|
||||
module("mime")
|
||||
|
||||
-- encode, decode and wrap algorithm tables
|
||||
encodet = {}
|
||||
decodet = {}
|
||||
wrapt = {}
|
||||
|
||||
-- creates a function that chooses a filter by name from a given table
|
||||
local function choose(table)
|
||||
return function(name, opt1, opt2)
|
||||
if base.type(name) ~= "string" then
|
||||
name, opt1, opt2 = "default", name, opt1
|
||||
end
|
||||
local f = table[name or "nil"]
|
||||
if not f then error("unknown key (" .. base.tostring(name) .. ")", 3)
|
||||
else return f(opt1, opt2) end
|
||||
end
|
||||
end
|
||||
|
||||
-- define the encoding filters
|
||||
encodet['base64'] = function()
|
||||
return ltn12.filter.cycle(b64, "")
|
||||
end
|
||||
|
||||
encodet['quoted-printable'] = function(mode)
|
||||
return ltn12.filter.cycle(qp, "",
|
||||
(mode == "binary") and "=0D=0A" or "\r\n")
|
||||
end
|
||||
|
||||
-- define the decoding filters
|
||||
decodet['base64'] = function()
|
||||
return ltn12.filter.cycle(unb64, "")
|
||||
end
|
||||
|
||||
decodet['quoted-printable'] = function()
|
||||
return ltn12.filter.cycle(unqp, "")
|
||||
end
|
||||
|
||||
local function format(chunk)
|
||||
if chunk then
|
||||
if chunk == "" then return "''"
|
||||
else return string.len(chunk) end
|
||||
else return "nil" end
|
||||
end
|
||||
|
||||
-- define the line-wrap filters
|
||||
wrapt['text'] = function(length)
|
||||
length = length or 76
|
||||
return ltn12.filter.cycle(wrp, length, length)
|
||||
end
|
||||
wrapt['base64'] = wrapt['text']
|
||||
wrapt['default'] = wrapt['text']
|
||||
|
||||
wrapt['quoted-printable'] = function()
|
||||
return ltn12.filter.cycle(qpwrp, 76, 76)
|
||||
end
|
||||
|
||||
-- function that choose the encoding, decoding or wrap algorithm
|
||||
encode = choose(encodet)
|
||||
decode = choose(decodet)
|
||||
wrap = choose(wrapt)
|
||||
|
||||
-- define the end-of-line normalization filter
|
||||
function normalize(marker)
|
||||
return ltn12.filter.cycle(eol, 0, marker)
|
||||
end
|
||||
|
||||
-- high level stuffing filter
|
||||
function stuff()
|
||||
return ltn12.filter.cycle(dot, 2)
|
||||
end
|
||||
|
||||
@@ -1,133 +1,133 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- LuaSocket helper module
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: socket.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local string = require("string")
|
||||
local math = require("math")
|
||||
local socket = require("socket.core")
|
||||
module("socket")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Exported auxiliar functions
|
||||
-----------------------------------------------------------------------------
|
||||
function connect(address, port, laddress, lport)
|
||||
local sock, err = socket.tcp()
|
||||
if not sock then return nil, err end
|
||||
if laddress then
|
||||
local res, err = sock:bind(laddress, lport, -1)
|
||||
if not res then return nil, err end
|
||||
end
|
||||
local res, err = sock:connect(address, port)
|
||||
if not res then return nil, err end
|
||||
return sock
|
||||
end
|
||||
|
||||
function bind(host, port, backlog)
|
||||
local sock, err = socket.tcp()
|
||||
if not sock then return nil, err end
|
||||
sock:setoption("reuseaddr", true)
|
||||
local res, err = sock:bind(host, port)
|
||||
if not res then return nil, err end
|
||||
res, err = sock:listen(backlog)
|
||||
if not res then return nil, err end
|
||||
return sock
|
||||
end
|
||||
|
||||
try = newtry()
|
||||
|
||||
function choose(table)
|
||||
return function(name, opt1, opt2)
|
||||
if base.type(name) ~= "string" then
|
||||
name, opt1, opt2 = "default", name, opt1
|
||||
end
|
||||
local f = table[name or "nil"]
|
||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
||||
else return f(opt1, opt2) end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Socket sources and sinks, conforming to LTN12
|
||||
-----------------------------------------------------------------------------
|
||||
-- create namespaces inside LuaSocket namespace
|
||||
sourcet = {}
|
||||
sinkt = {}
|
||||
|
||||
BLOCKSIZE = 2048
|
||||
|
||||
sinkt["close-when-done"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if not chunk then
|
||||
sock:close()
|
||||
return 1
|
||||
else return sock:send(chunk) end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
sinkt["keep-open"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if chunk then return sock:send(chunk)
|
||||
else return 1 end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
sinkt["default"] = sinkt["keep-open"]
|
||||
|
||||
sink = choose(sinkt)
|
||||
|
||||
sourcet["by-length"] = function(sock, length)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function()
|
||||
if length <= 0 then return nil end
|
||||
local size = math.min(socket.BLOCKSIZE, length)
|
||||
local chunk, err = sock:receive(size)
|
||||
if err then return nil, err end
|
||||
length = length - string.len(chunk)
|
||||
return chunk
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
sourcet["until-closed"] = function(sock)
|
||||
local done
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function()
|
||||
if done then return nil end
|
||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
||||
if not err then return chunk
|
||||
elseif err == "closed" then
|
||||
sock:close()
|
||||
done = 1
|
||||
return partial
|
||||
else return nil, err end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
sourcet["default"] = sourcet["until-closed"]
|
||||
|
||||
source = choose(sourcet)
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- LuaSocket helper module
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: socket.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local string = require("string")
|
||||
local math = require("math")
|
||||
local socket = require("socket.core")
|
||||
module("socket")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Exported auxiliar functions
|
||||
-----------------------------------------------------------------------------
|
||||
function connect(address, port, laddress, lport)
|
||||
local sock, err = socket.tcp()
|
||||
if not sock then return nil, err end
|
||||
if laddress then
|
||||
local res, err = sock:bind(laddress, lport, -1)
|
||||
if not res then return nil, err end
|
||||
end
|
||||
local res, err = sock:connect(address, port)
|
||||
if not res then return nil, err end
|
||||
return sock
|
||||
end
|
||||
|
||||
function bind(host, port, backlog)
|
||||
local sock, err = socket.tcp()
|
||||
if not sock then return nil, err end
|
||||
sock:setoption("reuseaddr", true)
|
||||
local res, err = sock:bind(host, port)
|
||||
if not res then return nil, err end
|
||||
res, err = sock:listen(backlog)
|
||||
if not res then return nil, err end
|
||||
return sock
|
||||
end
|
||||
|
||||
try = newtry()
|
||||
|
||||
function choose(table)
|
||||
return function(name, opt1, opt2)
|
||||
if base.type(name) ~= "string" then
|
||||
name, opt1, opt2 = "default", name, opt1
|
||||
end
|
||||
local f = table[name or "nil"]
|
||||
if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
|
||||
else return f(opt1, opt2) end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Socket sources and sinks, conforming to LTN12
|
||||
-----------------------------------------------------------------------------
|
||||
-- create namespaces inside LuaSocket namespace
|
||||
sourcet = {}
|
||||
sinkt = {}
|
||||
|
||||
BLOCKSIZE = 2048
|
||||
|
||||
sinkt["close-when-done"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if not chunk then
|
||||
sock:close()
|
||||
return 1
|
||||
else return sock:send(chunk) end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
sinkt["keep-open"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if chunk then return sock:send(chunk)
|
||||
else return 1 end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
sinkt["default"] = sinkt["keep-open"]
|
||||
|
||||
sink = choose(sinkt)
|
||||
|
||||
sourcet["by-length"] = function(sock, length)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function()
|
||||
if length <= 0 then return nil end
|
||||
local size = math.min(socket.BLOCKSIZE, length)
|
||||
local chunk, err = sock:receive(size)
|
||||
if err then return nil, err end
|
||||
length = length - string.len(chunk)
|
||||
return chunk
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
sourcet["until-closed"] = function(sock)
|
||||
local done
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function()
|
||||
if done then return nil end
|
||||
local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
|
||||
if not err then return chunk
|
||||
elseif err == "closed" then
|
||||
sock:close()
|
||||
done = 1
|
||||
return partial
|
||||
else return nil, err end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
sourcet["default"] = sourcet["until-closed"]
|
||||
|
||||
source = choose(sourcet)
|
||||
|
||||
|
||||
@@ -1,280 +1,280 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- FTP support for the Lua language
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: ftp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
local string = require("string")
|
||||
local math = require("math")
|
||||
local socket = require("socket")
|
||||
local url = require("socket.url")
|
||||
local tp = require("socket.tp")
|
||||
local ltn12 = require("ltn12")
|
||||
module("socket.ftp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- timeout in seconds before the program gives up on a connection
|
||||
TIMEOUT = 60
|
||||
-- default port for ftp service
|
||||
PORT = 21
|
||||
-- this is the default anonymous password. used when no password is
|
||||
-- provided in url. should be changed to your e-mail.
|
||||
USER = "ftp"
|
||||
PASSWORD = "anonymous@anonymous.org"
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Low level FTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function open(server, port, create)
|
||||
local tp = socket.try(tp.connect(server, port or PORT, create, TIMEOUT))
|
||||
local f = base.setmetatable({ tp = tp }, metat)
|
||||
-- make sure everything gets closed in an exception
|
||||
f.try = socket.newtry(function() f:close() end)
|
||||
return f
|
||||
end
|
||||
|
||||
function metat.__index:portconnect()
|
||||
self.try(self.server:settimeout(TIMEOUT))
|
||||
self.data = self.try(self.server:accept())
|
||||
self.try(self.data:settimeout(TIMEOUT))
|
||||
end
|
||||
|
||||
function metat.__index:pasvconnect()
|
||||
self.data = self.try(socket.tcp())
|
||||
self.try(self.data:settimeout(TIMEOUT))
|
||||
self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
|
||||
end
|
||||
|
||||
function metat.__index:login(user, password)
|
||||
self.try(self.tp:command("user", user or USER))
|
||||
local code, reply = self.try(self.tp:check{"2..", 331})
|
||||
if code == 331 then
|
||||
self.try(self.tp:command("pass", password or PASSWORD))
|
||||
self.try(self.tp:check("2.."))
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:pasv()
|
||||
self.try(self.tp:command("pasv"))
|
||||
local code, reply = self.try(self.tp:check("2.."))
|
||||
local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
|
||||
local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
|
||||
self.try(a and b and c and d and p1 and p2, reply)
|
||||
self.pasvt = {
|
||||
ip = string.format("%d.%d.%d.%d", a, b, c, d),
|
||||
port = p1*256 + p2
|
||||
}
|
||||
if self.server then
|
||||
self.server:close()
|
||||
self.server = nil
|
||||
end
|
||||
return self.pasvt.ip, self.pasvt.port
|
||||
end
|
||||
|
||||
function metat.__index:port(ip, port)
|
||||
self.pasvt = nil
|
||||
if not ip then
|
||||
ip, port = self.try(self.tp:getcontrol():getsockname())
|
||||
self.server = self.try(socket.bind(ip, 0))
|
||||
ip, port = self.try(self.server:getsockname())
|
||||
self.try(server:settimeout(TIMEOUT))
|
||||
end
|
||||
local pl = math.mod(port, 256)
|
||||
local ph = (port - pl)/256
|
||||
local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",")
|
||||
self.try(self.tp:command("port", arg))
|
||||
self.try(self.tp:check("2.."))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:send(sendt)
|
||||
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||
-- if there is a pasvt table, we already sent a PASV command
|
||||
-- we just get the data connection into self.data
|
||||
if self.pasvt then self:pasvconnect() end
|
||||
-- get the transfer argument and command
|
||||
local argument = sendt.argument or
|
||||
url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
|
||||
if argument == "" then argument = nil end
|
||||
local command = sendt.command or "stor"
|
||||
-- send the transfer command and check the reply
|
||||
self.try(self.tp:command(command, argument))
|
||||
local code, reply = self.try(self.tp:check{"2..", "1.."})
|
||||
-- if there is not a a pasvt table, then there is a server
|
||||
-- and we already sent a PORT command
|
||||
if not self.pasvt then self:portconnect() end
|
||||
-- get the sink, source and step for the transfer
|
||||
local step = sendt.step or ltn12.pump.step
|
||||
local checkstep = function(src, snk)
|
||||
-- check status in control connection while downloading
|
||||
local readyt = socket.select(readt, nil, 0)
|
||||
if readyt[tp] then self.try(self.tp:check("2..")) end
|
||||
return step(src, snk)
|
||||
end
|
||||
local sink = socket.sink("close-when-done", self.data)
|
||||
-- transfer all data and check error
|
||||
self.try(ltn12.pump.all(sendt.source, sink, checkstep))
|
||||
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||
-- done with data connection
|
||||
self.data:close()
|
||||
-- find out how many bytes were sent
|
||||
local sent = socket.skip(1, self.data:getstats())
|
||||
self.data = nil
|
||||
return sent
|
||||
end
|
||||
|
||||
function metat.__index:receive(recvt)
|
||||
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||
if self.pasvt then self:pasvconnect() end
|
||||
local argument = recvt.argument or
|
||||
url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
|
||||
if argument == "" then argument = nil end
|
||||
local command = recvt.command or "retr"
|
||||
self.try(self.tp:command(command, argument))
|
||||
local code = self.try(self.tp:check{"1..", "2.."})
|
||||
if not self.pasvt then self:portconnect() end
|
||||
local source = socket.source("until-closed", self.data)
|
||||
local step = recvt.step or ltn12.pump.step
|
||||
self.try(ltn12.pump.all(source, recvt.sink, step))
|
||||
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||
self.data:close()
|
||||
self.data = nil
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:cwd(dir)
|
||||
self.try(self.tp:command("cwd", dir))
|
||||
self.try(self.tp:check(250))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:type(type)
|
||||
self.try(self.tp:command("type", type))
|
||||
self.try(self.tp:check(200))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:greet()
|
||||
local code = self.try(self.tp:check{"1..", "2.."})
|
||||
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:quit()
|
||||
self.try(self.tp:command("quit"))
|
||||
self.try(self.tp:check("2.."))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:close()
|
||||
if self.data then self.data:close() end
|
||||
if self.server then self.server:close() end
|
||||
return self.tp:close()
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- High level FTP API
|
||||
-----------------------------------------------------------------------------
|
||||
function override(t)
|
||||
if t.url then
|
||||
u = url.parse(t.url)
|
||||
for i,v in base.pairs(t) do
|
||||
u[i] = v
|
||||
end
|
||||
return u
|
||||
else return t end
|
||||
end
|
||||
|
||||
local function tput(putt)
|
||||
putt = override(putt)
|
||||
socket.try(putt.host, "missing hostname")
|
||||
local f = open(putt.host, putt.port, putt.create)
|
||||
f:greet()
|
||||
f:login(putt.user, putt.password)
|
||||
if putt.type then f:type(putt.type) end
|
||||
f:pasv()
|
||||
local sent = f:send(putt)
|
||||
f:quit()
|
||||
f:close()
|
||||
return sent
|
||||
end
|
||||
|
||||
local default = {
|
||||
path = "/",
|
||||
scheme = "ftp"
|
||||
}
|
||||
|
||||
local function parse(u)
|
||||
local t = socket.try(url.parse(u, default))
|
||||
socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
|
||||
socket.try(t.host, "missing hostname")
|
||||
local pat = "^type=(.)$"
|
||||
if t.params then
|
||||
t.type = socket.skip(2, string.find(t.params, pat))
|
||||
socket.try(t.type == "a" or t.type == "i",
|
||||
"invalid type '" .. t.type .. "'")
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function sput(u, body)
|
||||
local putt = parse(u)
|
||||
putt.source = ltn12.source.string(body)
|
||||
return tput(putt)
|
||||
end
|
||||
|
||||
put = socket.protect(function(putt, body)
|
||||
if base.type(putt) == "string" then return sput(putt, body)
|
||||
else return tput(putt) end
|
||||
end)
|
||||
|
||||
local function tget(gett)
|
||||
gett = override(gett)
|
||||
socket.try(gett.host, "missing hostname")
|
||||
local f = open(gett.host, gett.port, gett.create)
|
||||
f:greet()
|
||||
f:login(gett.user, gett.password)
|
||||
if gett.type then f:type(gett.type) end
|
||||
f:pasv()
|
||||
f:receive(gett)
|
||||
f:quit()
|
||||
return f:close()
|
||||
end
|
||||
|
||||
local function sget(u)
|
||||
local gett = parse(u)
|
||||
local t = {}
|
||||
gett.sink = ltn12.sink.table(t)
|
||||
tget(gett)
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
command = socket.protect(function(cmdt)
|
||||
cmdt = override(cmdt)
|
||||
socket.try(cmdt.host, "missing hostname")
|
||||
socket.try(cmdt.command, "missing command")
|
||||
local f = open(cmdt.host, cmdt.port, cmdt.create)
|
||||
f:greet()
|
||||
f:login(cmdt.user, cmdt.password)
|
||||
f.try(f.tp:command(cmdt.command, cmdt.argument))
|
||||
if cmdt.check then f.try(f.tp:check(cmdt.check)) end
|
||||
f:quit()
|
||||
return f:close()
|
||||
end)
|
||||
|
||||
get = socket.protect(function(gett)
|
||||
if base.type(gett) == "string" then return sget(gett)
|
||||
else return tget(gett) end
|
||||
end)
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- FTP support for the Lua language
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: ftp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
local string = require("string")
|
||||
local math = require("math")
|
||||
local socket = require("socket")
|
||||
local url = require("socket.url")
|
||||
local tp = require("socket.tp")
|
||||
local ltn12 = require("ltn12")
|
||||
module("socket.ftp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- timeout in seconds before the program gives up on a connection
|
||||
TIMEOUT = 60
|
||||
-- default port for ftp service
|
||||
PORT = 21
|
||||
-- this is the default anonymous password. used when no password is
|
||||
-- provided in url. should be changed to your e-mail.
|
||||
USER = "ftp"
|
||||
PASSWORD = "anonymous@anonymous.org"
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Low level FTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function open(server, port, create)
|
||||
local tp = socket.try(tp.connect(server, port or PORT, create, TIMEOUT))
|
||||
local f = base.setmetatable({ tp = tp }, metat)
|
||||
-- make sure everything gets closed in an exception
|
||||
f.try = socket.newtry(function() f:close() end)
|
||||
return f
|
||||
end
|
||||
|
||||
function metat.__index:portconnect()
|
||||
self.try(self.server:settimeout(TIMEOUT))
|
||||
self.data = self.try(self.server:accept())
|
||||
self.try(self.data:settimeout(TIMEOUT))
|
||||
end
|
||||
|
||||
function metat.__index:pasvconnect()
|
||||
self.data = self.try(socket.tcp())
|
||||
self.try(self.data:settimeout(TIMEOUT))
|
||||
self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
|
||||
end
|
||||
|
||||
function metat.__index:login(user, password)
|
||||
self.try(self.tp:command("user", user or USER))
|
||||
local code, reply = self.try(self.tp:check{"2..", 331})
|
||||
if code == 331 then
|
||||
self.try(self.tp:command("pass", password or PASSWORD))
|
||||
self.try(self.tp:check("2.."))
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:pasv()
|
||||
self.try(self.tp:command("pasv"))
|
||||
local code, reply = self.try(self.tp:check("2.."))
|
||||
local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
|
||||
local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
|
||||
self.try(a and b and c and d and p1 and p2, reply)
|
||||
self.pasvt = {
|
||||
ip = string.format("%d.%d.%d.%d", a, b, c, d),
|
||||
port = p1*256 + p2
|
||||
}
|
||||
if self.server then
|
||||
self.server:close()
|
||||
self.server = nil
|
||||
end
|
||||
return self.pasvt.ip, self.pasvt.port
|
||||
end
|
||||
|
||||
function metat.__index:port(ip, port)
|
||||
self.pasvt = nil
|
||||
if not ip then
|
||||
ip, port = self.try(self.tp:getcontrol():getsockname())
|
||||
self.server = self.try(socket.bind(ip, 0))
|
||||
ip, port = self.try(self.server:getsockname())
|
||||
self.try(server:settimeout(TIMEOUT))
|
||||
end
|
||||
local pl = math.mod(port, 256)
|
||||
local ph = (port - pl)/256
|
||||
local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",")
|
||||
self.try(self.tp:command("port", arg))
|
||||
self.try(self.tp:check("2.."))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:send(sendt)
|
||||
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||
-- if there is a pasvt table, we already sent a PASV command
|
||||
-- we just get the data connection into self.data
|
||||
if self.pasvt then self:pasvconnect() end
|
||||
-- get the transfer argument and command
|
||||
local argument = sendt.argument or
|
||||
url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
|
||||
if argument == "" then argument = nil end
|
||||
local command = sendt.command or "stor"
|
||||
-- send the transfer command and check the reply
|
||||
self.try(self.tp:command(command, argument))
|
||||
local code, reply = self.try(self.tp:check{"2..", "1.."})
|
||||
-- if there is not a a pasvt table, then there is a server
|
||||
-- and we already sent a PORT command
|
||||
if not self.pasvt then self:portconnect() end
|
||||
-- get the sink, source and step for the transfer
|
||||
local step = sendt.step or ltn12.pump.step
|
||||
local checkstep = function(src, snk)
|
||||
-- check status in control connection while downloading
|
||||
local readyt = socket.select(readt, nil, 0)
|
||||
if readyt[tp] then self.try(self.tp:check("2..")) end
|
||||
return step(src, snk)
|
||||
end
|
||||
local sink = socket.sink("close-when-done", self.data)
|
||||
-- transfer all data and check error
|
||||
self.try(ltn12.pump.all(sendt.source, sink, checkstep))
|
||||
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||
-- done with data connection
|
||||
self.data:close()
|
||||
-- find out how many bytes were sent
|
||||
local sent = socket.skip(1, self.data:getstats())
|
||||
self.data = nil
|
||||
return sent
|
||||
end
|
||||
|
||||
function metat.__index:receive(recvt)
|
||||
self.try(self.pasvt or self.server, "need port or pasv first")
|
||||
if self.pasvt then self:pasvconnect() end
|
||||
local argument = recvt.argument or
|
||||
url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
|
||||
if argument == "" then argument = nil end
|
||||
local command = recvt.command or "retr"
|
||||
self.try(self.tp:command(command, argument))
|
||||
local code = self.try(self.tp:check{"1..", "2.."})
|
||||
if not self.pasvt then self:portconnect() end
|
||||
local source = socket.source("until-closed", self.data)
|
||||
local step = recvt.step or ltn12.pump.step
|
||||
self.try(ltn12.pump.all(source, recvt.sink, step))
|
||||
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||
self.data:close()
|
||||
self.data = nil
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:cwd(dir)
|
||||
self.try(self.tp:command("cwd", dir))
|
||||
self.try(self.tp:check(250))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:type(type)
|
||||
self.try(self.tp:command("type", type))
|
||||
self.try(self.tp:check(200))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:greet()
|
||||
local code = self.try(self.tp:check{"1..", "2.."})
|
||||
if string.find(code, "1..") then self.try(self.tp:check("2..")) end
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:quit()
|
||||
self.try(self.tp:command("quit"))
|
||||
self.try(self.tp:check("2.."))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:close()
|
||||
if self.data then self.data:close() end
|
||||
if self.server then self.server:close() end
|
||||
return self.tp:close()
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- High level FTP API
|
||||
-----------------------------------------------------------------------------
|
||||
function override(t)
|
||||
if t.url then
|
||||
u = url.parse(t.url)
|
||||
for i,v in base.pairs(t) do
|
||||
u[i] = v
|
||||
end
|
||||
return u
|
||||
else return t end
|
||||
end
|
||||
|
||||
local function tput(putt)
|
||||
putt = override(putt)
|
||||
socket.try(putt.host, "missing hostname")
|
||||
local f = open(putt.host, putt.port, putt.create)
|
||||
f:greet()
|
||||
f:login(putt.user, putt.password)
|
||||
if putt.type then f:type(putt.type) end
|
||||
f:pasv()
|
||||
local sent = f:send(putt)
|
||||
f:quit()
|
||||
f:close()
|
||||
return sent
|
||||
end
|
||||
|
||||
local default = {
|
||||
path = "/",
|
||||
scheme = "ftp"
|
||||
}
|
||||
|
||||
local function parse(u)
|
||||
local t = socket.try(url.parse(u, default))
|
||||
socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
|
||||
socket.try(t.host, "missing hostname")
|
||||
local pat = "^type=(.)$"
|
||||
if t.params then
|
||||
t.type = socket.skip(2, string.find(t.params, pat))
|
||||
socket.try(t.type == "a" or t.type == "i",
|
||||
"invalid type '" .. t.type .. "'")
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function sput(u, body)
|
||||
local putt = parse(u)
|
||||
putt.source = ltn12.source.string(body)
|
||||
return tput(putt)
|
||||
end
|
||||
|
||||
put = socket.protect(function(putt, body)
|
||||
if base.type(putt) == "string" then return sput(putt, body)
|
||||
else return tput(putt) end
|
||||
end)
|
||||
|
||||
local function tget(gett)
|
||||
gett = override(gett)
|
||||
socket.try(gett.host, "missing hostname")
|
||||
local f = open(gett.host, gett.port, gett.create)
|
||||
f:greet()
|
||||
f:login(gett.user, gett.password)
|
||||
if gett.type then f:type(gett.type) end
|
||||
f:pasv()
|
||||
f:receive(gett)
|
||||
f:quit()
|
||||
return f:close()
|
||||
end
|
||||
|
||||
local function sget(u)
|
||||
local gett = parse(u)
|
||||
local t = {}
|
||||
gett.sink = ltn12.sink.table(t)
|
||||
tget(gett)
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
command = socket.protect(function(cmdt)
|
||||
cmdt = override(cmdt)
|
||||
socket.try(cmdt.host, "missing hostname")
|
||||
socket.try(cmdt.command, "missing command")
|
||||
local f = open(cmdt.host, cmdt.port, cmdt.create)
|
||||
f:greet()
|
||||
f:login(cmdt.user, cmdt.password)
|
||||
f.try(f.tp:command(cmdt.command, cmdt.argument))
|
||||
if cmdt.check then f.try(f.tp:check(cmdt.check)) end
|
||||
f:quit()
|
||||
return f:close()
|
||||
end)
|
||||
|
||||
get = socket.protect(function(gett)
|
||||
if base.type(gett) == "string" then return sget(gett)
|
||||
else return tget(gett) end
|
||||
end)
|
||||
|
||||
|
||||
@@ -1,326 +1,326 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- HTTP/1.1 client support for the Lua language.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: http.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-------------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
local url = require("socket.url")
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
local string = require("string")
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
module("socket.http")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- connection timeout in seconds
|
||||
TIMEOUT = 60
|
||||
-- default port for document retrieval
|
||||
PORT = 80
|
||||
-- user agent field sent in request
|
||||
USERAGENT = socket._VERSION
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Reads MIME headers from a connection, unfolding where needed
|
||||
-----------------------------------------------------------------------------
|
||||
local function receiveheaders(sock, headers)
|
||||
local line, name, value, err
|
||||
headers = headers or {}
|
||||
-- get first line
|
||||
line, err = sock:receive()
|
||||
if err then return nil, err end
|
||||
-- headers go until a blank line is found
|
||||
while line ~= "" do
|
||||
-- get field-name and value
|
||||
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
|
||||
if not (name and value) then return nil, "malformed reponse headers" end
|
||||
name = string.lower(name)
|
||||
-- get next line (value might be folded)
|
||||
line, err = sock:receive()
|
||||
if err then return nil, err end
|
||||
-- unfold any folded values
|
||||
while string.find(line, "^%s") do
|
||||
value = value .. line
|
||||
line = sock:receive()
|
||||
if err then return nil, err end
|
||||
end
|
||||
-- save pair in table
|
||||
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
||||
else headers[name] = value end
|
||||
end
|
||||
return headers
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Extra sources and sinks
|
||||
-----------------------------------------------------------------------------
|
||||
socket.sourcet["http-chunked"] = function(sock, headers)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function()
|
||||
-- get chunk size, skip extention
|
||||
local line, err = sock:receive()
|
||||
if err then return nil, err end
|
||||
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
||||
if not size then return nil, "invalid chunk size" end
|
||||
-- was it the last chunk?
|
||||
if size > 0 then
|
||||
-- if not, get chunk and skip terminating CRLF
|
||||
local chunk, err, part = sock:receive(size)
|
||||
if chunk then sock:receive() end
|
||||
return chunk, err
|
||||
else
|
||||
-- if it was, read trailers into headers table
|
||||
headers, err = receiveheaders(sock, headers)
|
||||
if not headers then return nil, err end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
socket.sinkt["http-chunked"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if not chunk then return sock:send("0\r\n\r\n") end
|
||||
local size = string.format("%X\r\n", string.len(chunk))
|
||||
return sock:send(size .. chunk .. "\r\n")
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Low level HTTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function open(host, port, create)
|
||||
-- create socket with user connect function, or with default
|
||||
local c = socket.try(create or socket.tcp)()
|
||||
local h = base.setmetatable({ c = c }, metat)
|
||||
-- create finalized try
|
||||
h.try = socket.newtry(function() h:close() end)
|
||||
-- set timeout before connecting
|
||||
h.try(c:settimeout(TIMEOUT))
|
||||
h.try(c:connect(host, port or PORT))
|
||||
-- here everything worked
|
||||
return h
|
||||
end
|
||||
|
||||
function metat.__index:sendrequestline(method, uri)
|
||||
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
|
||||
return self.try(self.c:send(reqline))
|
||||
end
|
||||
|
||||
function metat.__index:sendheaders(headers)
|
||||
local h = "\r\n"
|
||||
for i, v in base.pairs(headers) do
|
||||
h = i .. ": " .. v .. "\r\n" .. h
|
||||
end
|
||||
self.try(self.c:send(h))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:sendbody(headers, source, step)
|
||||
source = source or ltn12.source.empty()
|
||||
step = step or ltn12.pump.step
|
||||
-- if we don't know the size in advance, send chunked and hope for the best
|
||||
local mode = "http-chunked"
|
||||
if headers["content-length"] then mode = "keep-open" end
|
||||
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
||||
end
|
||||
|
||||
function metat.__index:receivestatusline()
|
||||
local status = self.try(self.c:receive())
|
||||
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
|
||||
return self.try(base.tonumber(code), status)
|
||||
end
|
||||
|
||||
function metat.__index:receiveheaders()
|
||||
return self.try(receiveheaders(self.c))
|
||||
end
|
||||
|
||||
function metat.__index:receivebody(headers, sink, step)
|
||||
sink = sink or ltn12.sink.null()
|
||||
step = step or ltn12.pump.step
|
||||
local length = base.tonumber(headers["content-length"])
|
||||
local t = headers["transfer-encoding"] -- shortcut
|
||||
local mode = "default" -- connection close
|
||||
if t and t ~= "identity" then mode = "http-chunked"
|
||||
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
||||
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
||||
sink, step))
|
||||
end
|
||||
|
||||
function metat.__index:close()
|
||||
return self.c:close()
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- High level HTTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local function adjusturi(reqt)
|
||||
local u = reqt
|
||||
-- if there is a proxy, we need the full url. otherwise, just a part.
|
||||
if not reqt.proxy and not PROXY then
|
||||
u = {
|
||||
path = socket.try(reqt.path, "invalid path 'nil'"),
|
||||
params = reqt.params,
|
||||
query = reqt.query,
|
||||
fragment = reqt.fragment
|
||||
}
|
||||
end
|
||||
return url.build(u)
|
||||
end
|
||||
|
||||
local function adjustproxy(reqt)
|
||||
local proxy = reqt.proxy or PROXY
|
||||
if proxy then
|
||||
proxy = url.parse(proxy)
|
||||
return proxy.host, proxy.port or 3128
|
||||
else
|
||||
return reqt.host, reqt.port
|
||||
end
|
||||
end
|
||||
|
||||
local function adjustheaders(headers, host)
|
||||
-- default headers
|
||||
local lower = {
|
||||
["user-agent"] = USERAGENT,
|
||||
["host"] = host,
|
||||
["connection"] = "close, TE",
|
||||
["te"] = "trailers"
|
||||
}
|
||||
-- override with user headers
|
||||
for i,v in base.pairs(headers or lower) do
|
||||
lower[string.lower(i)] = v
|
||||
end
|
||||
return lower
|
||||
end
|
||||
|
||||
-- default url parts
|
||||
local default = {
|
||||
host = "",
|
||||
port = PORT,
|
||||
path ="/",
|
||||
scheme = "http"
|
||||
}
|
||||
|
||||
local function adjustrequest(reqt)
|
||||
-- parse url if provided
|
||||
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
|
||||
local t = url.parse(reqt.url, default)
|
||||
-- explicit components override url
|
||||
for i,v in base.pairs(reqt) do nreqt[i] = v end
|
||||
socket.try(nreqt.host, "invalid host '" .. base.tostring(nreqt.host) .. "'")
|
||||
-- compute uri if user hasn't overriden
|
||||
nreqt.uri = reqt.uri or adjusturi(nreqt)
|
||||
-- ajust host and port if there is a proxy
|
||||
nreqt.host, nreqt.port = adjustproxy(nreqt)
|
||||
-- adjust headers in request
|
||||
nreqt.headers = adjustheaders(nreqt.headers, nreqt.host)
|
||||
return nreqt
|
||||
end
|
||||
|
||||
local function shouldredirect(reqt, code, headers)
|
||||
return headers.location and
|
||||
string.gsub(headers.location, "%s", "") ~= "" and
|
||||
(reqt.redirect ~= false) and
|
||||
(code == 301 or code == 302) and
|
||||
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
|
||||
and (not reqt.nredirects or reqt.nredirects < 5)
|
||||
end
|
||||
|
||||
local function shouldauthorize(reqt, code)
|
||||
-- if there has been an authorization attempt, it must have failed
|
||||
if reqt.headers and reqt.headers["authorization"] then return nil end
|
||||
-- if last attempt didn't fail due to lack of authentication,
|
||||
-- or we don't have authorization information, we can't retry
|
||||
return code == 401 and reqt.user and reqt.password
|
||||
end
|
||||
|
||||
local function shouldreceivebody(reqt, code)
|
||||
if reqt.method == "HEAD" then return nil end
|
||||
if code == 204 or code == 304 then return nil end
|
||||
if code >= 100 and code < 200 then return nil end
|
||||
return 1
|
||||
end
|
||||
|
||||
-- forward declarations
|
||||
local trequest, tauthorize, tredirect
|
||||
|
||||
function tauthorize(reqt)
|
||||
local auth = "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
|
||||
reqt.headers["authorization"] = auth
|
||||
return trequest(reqt)
|
||||
end
|
||||
|
||||
function tredirect(reqt, location)
|
||||
local result, code, headers, status = trequest {
|
||||
-- the RFC says the redirect URL has to be absolute, but some
|
||||
-- servers do not respect that
|
||||
url = url.absolute(reqt, location),
|
||||
source = reqt.source,
|
||||
sink = reqt.sink,
|
||||
headers = reqt.headers,
|
||||
proxy = reqt.proxy,
|
||||
nredirects = (reqt.nredirects or 0) + 1,
|
||||
connect = reqt.connect
|
||||
}
|
||||
-- pass location header back as a hint we redirected
|
||||
headers.location = headers.location or location
|
||||
return result, code, headers, status
|
||||
end
|
||||
|
||||
function trequest(reqt)
|
||||
reqt = adjustrequest(reqt)
|
||||
local h = open(reqt.host, reqt.port, reqt.create)
|
||||
h:sendrequestline(reqt.method, reqt.uri)
|
||||
h:sendheaders(reqt.headers)
|
||||
if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end
|
||||
local code, headers, status
|
||||
code, status = h:receivestatusline()
|
||||
headers = h:receiveheaders()
|
||||
if shouldredirect(reqt, code, headers) then
|
||||
h:close()
|
||||
return tredirect(reqt, headers.location)
|
||||
elseif shouldauthorize(reqt, code) then
|
||||
h:close()
|
||||
return tauthorize(reqt)
|
||||
elseif shouldreceivebody(reqt, code) then
|
||||
h:receivebody(headers, reqt.sink, reqt.step)
|
||||
end
|
||||
h:close()
|
||||
return 1, code, headers, status
|
||||
end
|
||||
|
||||
local function srequest(u, body)
|
||||
local t = {}
|
||||
local reqt = {
|
||||
url = u,
|
||||
sink = ltn12.sink.table(t)
|
||||
}
|
||||
if body then
|
||||
reqt.source = ltn12.source.string(body)
|
||||
reqt.headers = { ["content-length"] = string.len(body) }
|
||||
reqt.method = "POST"
|
||||
end
|
||||
local code, headers, status = socket.skip(1, trequest(reqt))
|
||||
return table.concat(t), code, headers, status
|
||||
end
|
||||
|
||||
request = socket.protect(function(reqt, body)
|
||||
if base.type(reqt) == "string" then return srequest(reqt, body)
|
||||
else return trequest(reqt) end
|
||||
end)
|
||||
-----------------------------------------------------------------------------
|
||||
-- HTTP/1.1 client support for the Lua language.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: http.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-------------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
local url = require("socket.url")
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
local string = require("string")
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
module("socket.http")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- connection timeout in seconds
|
||||
TIMEOUT = 60
|
||||
-- default port for document retrieval
|
||||
PORT = 80
|
||||
-- user agent field sent in request
|
||||
USERAGENT = socket._VERSION
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Reads MIME headers from a connection, unfolding where needed
|
||||
-----------------------------------------------------------------------------
|
||||
local function receiveheaders(sock, headers)
|
||||
local line, name, value, err
|
||||
headers = headers or {}
|
||||
-- get first line
|
||||
line, err = sock:receive()
|
||||
if err then return nil, err end
|
||||
-- headers go until a blank line is found
|
||||
while line ~= "" do
|
||||
-- get field-name and value
|
||||
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
|
||||
if not (name and value) then return nil, "malformed reponse headers" end
|
||||
name = string.lower(name)
|
||||
-- get next line (value might be folded)
|
||||
line, err = sock:receive()
|
||||
if err then return nil, err end
|
||||
-- unfold any folded values
|
||||
while string.find(line, "^%s") do
|
||||
value = value .. line
|
||||
line = sock:receive()
|
||||
if err then return nil, err end
|
||||
end
|
||||
-- save pair in table
|
||||
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
||||
else headers[name] = value end
|
||||
end
|
||||
return headers
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Extra sources and sinks
|
||||
-----------------------------------------------------------------------------
|
||||
socket.sourcet["http-chunked"] = function(sock, headers)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function()
|
||||
-- get chunk size, skip extention
|
||||
local line, err = sock:receive()
|
||||
if err then return nil, err end
|
||||
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
||||
if not size then return nil, "invalid chunk size" end
|
||||
-- was it the last chunk?
|
||||
if size > 0 then
|
||||
-- if not, get chunk and skip terminating CRLF
|
||||
local chunk, err, part = sock:receive(size)
|
||||
if chunk then sock:receive() end
|
||||
return chunk, err
|
||||
else
|
||||
-- if it was, read trailers into headers table
|
||||
headers, err = receiveheaders(sock, headers)
|
||||
if not headers then return nil, err end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
socket.sinkt["http-chunked"] = function(sock)
|
||||
return base.setmetatable({
|
||||
getfd = function() return sock:getfd() end,
|
||||
dirty = function() return sock:dirty() end
|
||||
}, {
|
||||
__call = function(self, chunk, err)
|
||||
if not chunk then return sock:send("0\r\n\r\n") end
|
||||
local size = string.format("%X\r\n", string.len(chunk))
|
||||
return sock:send(size .. chunk .. "\r\n")
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Low level HTTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function open(host, port, create)
|
||||
-- create socket with user connect function, or with default
|
||||
local c = socket.try(create or socket.tcp)()
|
||||
local h = base.setmetatable({ c = c }, metat)
|
||||
-- create finalized try
|
||||
h.try = socket.newtry(function() h:close() end)
|
||||
-- set timeout before connecting
|
||||
h.try(c:settimeout(TIMEOUT))
|
||||
h.try(c:connect(host, port or PORT))
|
||||
-- here everything worked
|
||||
return h
|
||||
end
|
||||
|
||||
function metat.__index:sendrequestline(method, uri)
|
||||
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
|
||||
return self.try(self.c:send(reqline))
|
||||
end
|
||||
|
||||
function metat.__index:sendheaders(headers)
|
||||
local h = "\r\n"
|
||||
for i, v in base.pairs(headers) do
|
||||
h = i .. ": " .. v .. "\r\n" .. h
|
||||
end
|
||||
self.try(self.c:send(h))
|
||||
return 1
|
||||
end
|
||||
|
||||
function metat.__index:sendbody(headers, source, step)
|
||||
source = source or ltn12.source.empty()
|
||||
step = step or ltn12.pump.step
|
||||
-- if we don't know the size in advance, send chunked and hope for the best
|
||||
local mode = "http-chunked"
|
||||
if headers["content-length"] then mode = "keep-open" end
|
||||
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
||||
end
|
||||
|
||||
function metat.__index:receivestatusline()
|
||||
local status = self.try(self.c:receive())
|
||||
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
|
||||
return self.try(base.tonumber(code), status)
|
||||
end
|
||||
|
||||
function metat.__index:receiveheaders()
|
||||
return self.try(receiveheaders(self.c))
|
||||
end
|
||||
|
||||
function metat.__index:receivebody(headers, sink, step)
|
||||
sink = sink or ltn12.sink.null()
|
||||
step = step or ltn12.pump.step
|
||||
local length = base.tonumber(headers["content-length"])
|
||||
local t = headers["transfer-encoding"] -- shortcut
|
||||
local mode = "default" -- connection close
|
||||
if t and t ~= "identity" then mode = "http-chunked"
|
||||
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
||||
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
||||
sink, step))
|
||||
end
|
||||
|
||||
function metat.__index:close()
|
||||
return self.c:close()
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- High level HTTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local function adjusturi(reqt)
|
||||
local u = reqt
|
||||
-- if there is a proxy, we need the full url. otherwise, just a part.
|
||||
if not reqt.proxy and not PROXY then
|
||||
u = {
|
||||
path = socket.try(reqt.path, "invalid path 'nil'"),
|
||||
params = reqt.params,
|
||||
query = reqt.query,
|
||||
fragment = reqt.fragment
|
||||
}
|
||||
end
|
||||
return url.build(u)
|
||||
end
|
||||
|
||||
local function adjustproxy(reqt)
|
||||
local proxy = reqt.proxy or PROXY
|
||||
if proxy then
|
||||
proxy = url.parse(proxy)
|
||||
return proxy.host, proxy.port or 3128
|
||||
else
|
||||
return reqt.host, reqt.port
|
||||
end
|
||||
end
|
||||
|
||||
local function adjustheaders(headers, host)
|
||||
-- default headers
|
||||
local lower = {
|
||||
["user-agent"] = USERAGENT,
|
||||
["host"] = host,
|
||||
["connection"] = "close, TE",
|
||||
["te"] = "trailers"
|
||||
}
|
||||
-- override with user headers
|
||||
for i,v in base.pairs(headers or lower) do
|
||||
lower[string.lower(i)] = v
|
||||
end
|
||||
return lower
|
||||
end
|
||||
|
||||
-- default url parts
|
||||
local default = {
|
||||
host = "",
|
||||
port = PORT,
|
||||
path ="/",
|
||||
scheme = "http"
|
||||
}
|
||||
|
||||
local function adjustrequest(reqt)
|
||||
-- parse url if provided
|
||||
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
|
||||
local t = url.parse(reqt.url, default)
|
||||
-- explicit components override url
|
||||
for i,v in base.pairs(reqt) do nreqt[i] = v end
|
||||
socket.try(nreqt.host, "invalid host '" .. base.tostring(nreqt.host) .. "'")
|
||||
-- compute uri if user hasn't overriden
|
||||
nreqt.uri = reqt.uri or adjusturi(nreqt)
|
||||
-- ajust host and port if there is a proxy
|
||||
nreqt.host, nreqt.port = adjustproxy(nreqt)
|
||||
-- adjust headers in request
|
||||
nreqt.headers = adjustheaders(nreqt.headers, nreqt.host)
|
||||
return nreqt
|
||||
end
|
||||
|
||||
local function shouldredirect(reqt, code, headers)
|
||||
return headers.location and
|
||||
string.gsub(headers.location, "%s", "") ~= "" and
|
||||
(reqt.redirect ~= false) and
|
||||
(code == 301 or code == 302) and
|
||||
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
|
||||
and (not reqt.nredirects or reqt.nredirects < 5)
|
||||
end
|
||||
|
||||
local function shouldauthorize(reqt, code)
|
||||
-- if there has been an authorization attempt, it must have failed
|
||||
if reqt.headers and reqt.headers["authorization"] then return nil end
|
||||
-- if last attempt didn't fail due to lack of authentication,
|
||||
-- or we don't have authorization information, we can't retry
|
||||
return code == 401 and reqt.user and reqt.password
|
||||
end
|
||||
|
||||
local function shouldreceivebody(reqt, code)
|
||||
if reqt.method == "HEAD" then return nil end
|
||||
if code == 204 or code == 304 then return nil end
|
||||
if code >= 100 and code < 200 then return nil end
|
||||
return 1
|
||||
end
|
||||
|
||||
-- forward declarations
|
||||
local trequest, tauthorize, tredirect
|
||||
|
||||
function tauthorize(reqt)
|
||||
local auth = "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
|
||||
reqt.headers["authorization"] = auth
|
||||
return trequest(reqt)
|
||||
end
|
||||
|
||||
function tredirect(reqt, location)
|
||||
local result, code, headers, status = trequest {
|
||||
-- the RFC says the redirect URL has to be absolute, but some
|
||||
-- servers do not respect that
|
||||
url = url.absolute(reqt, location),
|
||||
source = reqt.source,
|
||||
sink = reqt.sink,
|
||||
headers = reqt.headers,
|
||||
proxy = reqt.proxy,
|
||||
nredirects = (reqt.nredirects or 0) + 1,
|
||||
connect = reqt.connect
|
||||
}
|
||||
-- pass location header back as a hint we redirected
|
||||
headers.location = headers.location or location
|
||||
return result, code, headers, status
|
||||
end
|
||||
|
||||
function trequest(reqt)
|
||||
reqt = adjustrequest(reqt)
|
||||
local h = open(reqt.host, reqt.port, reqt.create)
|
||||
h:sendrequestline(reqt.method, reqt.uri)
|
||||
h:sendheaders(reqt.headers)
|
||||
if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end
|
||||
local code, headers, status
|
||||
code, status = h:receivestatusline()
|
||||
headers = h:receiveheaders()
|
||||
if shouldredirect(reqt, code, headers) then
|
||||
h:close()
|
||||
return tredirect(reqt, headers.location)
|
||||
elseif shouldauthorize(reqt, code) then
|
||||
h:close()
|
||||
return tauthorize(reqt)
|
||||
elseif shouldreceivebody(reqt, code) then
|
||||
h:receivebody(headers, reqt.sink, reqt.step)
|
||||
end
|
||||
h:close()
|
||||
return 1, code, headers, status
|
||||
end
|
||||
|
||||
local function srequest(u, body)
|
||||
local t = {}
|
||||
local reqt = {
|
||||
url = u,
|
||||
sink = ltn12.sink.table(t)
|
||||
}
|
||||
if body then
|
||||
reqt.source = ltn12.source.string(body)
|
||||
reqt.headers = { ["content-length"] = string.len(body) }
|
||||
reqt.method = "POST"
|
||||
end
|
||||
local code, headers, status = socket.skip(1, trequest(reqt))
|
||||
return table.concat(t), code, headers, status
|
||||
end
|
||||
|
||||
request = socket.protect(function(reqt, body)
|
||||
if base.type(reqt) == "string" then return srequest(reqt, body)
|
||||
else return trequest(reqt) end
|
||||
end)
|
||||
|
||||
@@ -1,245 +1,245 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- SMTP client support for the Lua language.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: smtp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local coroutine = require("coroutine")
|
||||
local string = require("string")
|
||||
local math = require("math")
|
||||
local os = require("os")
|
||||
local socket = require("socket")
|
||||
local tp = require("socket.tp")
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
module("socket.smtp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- timeout for connection
|
||||
TIMEOUT = 60
|
||||
-- default server used to send e-mails
|
||||
SERVER = "localhost"
|
||||
-- default port
|
||||
PORT = 25
|
||||
-- domain used in HELO command and default sendmail
|
||||
-- If we are under a CGI, try to get from environment
|
||||
DOMAIN = os.getenv("SERVER_NAME") or "localhost"
|
||||
-- default time zone (means we don't know)
|
||||
ZONE = "-0000"
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Low level SMTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function metat.__index:greet(domain)
|
||||
self.try(self.tp:check("2.."))
|
||||
self.try(self.tp:command("EHLO", domain or DOMAIN))
|
||||
return socket.skip(1, self.try(self.tp:check("2..")))
|
||||
end
|
||||
|
||||
function metat.__index:mail(from)
|
||||
self.try(self.tp:command("MAIL", "FROM:" .. from))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:rcpt(to)
|
||||
self.try(self.tp:command("RCPT", "TO:" .. to))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:data(src, step)
|
||||
self.try(self.tp:command("DATA"))
|
||||
self.try(self.tp:check("3.."))
|
||||
self.try(self.tp:source(src, step))
|
||||
self.try(self.tp:send("\r\n.\r\n"))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:quit()
|
||||
self.try(self.tp:command("QUIT"))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:close()
|
||||
return self.tp:close()
|
||||
end
|
||||
|
||||
function metat.__index:login(user, password)
|
||||
self.try(self.tp:command("AUTH", "LOGIN"))
|
||||
self.try(self.tp:check("3.."))
|
||||
self.try(self.tp:command(mime.b64(user)))
|
||||
self.try(self.tp:check("3.."))
|
||||
self.try(self.tp:command(mime.b64(password)))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:plain(user, password)
|
||||
local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password)
|
||||
self.try(self.tp:command("AUTH", auth))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:auth(user, password, ext)
|
||||
if not user or not password then return 1 end
|
||||
if string.find(ext, "AUTH[^\n]+LOGIN") then
|
||||
return self:login(user, password)
|
||||
elseif string.find(ext, "AUTH[^\n]+PLAIN") then
|
||||
return self:plain(user, password)
|
||||
else
|
||||
self.try(nil, "authentication not supported")
|
||||
end
|
||||
end
|
||||
|
||||
-- send message or throw an exception
|
||||
function metat.__index:send(mailt)
|
||||
self:mail(mailt.from)
|
||||
if base.type(mailt.rcpt) == "table" then
|
||||
for i,v in base.ipairs(mailt.rcpt) do
|
||||
self:rcpt(v)
|
||||
end
|
||||
else
|
||||
self:rcpt(mailt.rcpt)
|
||||
end
|
||||
self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
|
||||
end
|
||||
|
||||
function open(server, port, create)
|
||||
local tp = socket.try(tp.connect(server or SERVER, port or PORT,
|
||||
create, TIMEOUT))
|
||||
local s = base.setmetatable({tp = tp}, metat)
|
||||
-- make sure tp is closed if we get an exception
|
||||
s.try = socket.newtry(function()
|
||||
s:close()
|
||||
end)
|
||||
return s
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Multipart message source
|
||||
-----------------------------------------------------------------------------
|
||||
-- returns a hopefully unique mime boundary
|
||||
local seqno = 0
|
||||
local function newboundary()
|
||||
seqno = seqno + 1
|
||||
return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'),
|
||||
math.random(0, 99999), seqno)
|
||||
end
|
||||
|
||||
-- send_message forward declaration
|
||||
local send_message
|
||||
|
||||
-- yield the headers all at once, it's faster
|
||||
local function send_headers(headers)
|
||||
local h = "\r\n"
|
||||
for i,v in base.pairs(headers) do
|
||||
h = i .. ': ' .. v .. "\r\n" .. h
|
||||
end
|
||||
coroutine.yield(h)
|
||||
end
|
||||
|
||||
-- yield multipart message body from a multipart message table
|
||||
local function send_multipart(mesgt)
|
||||
-- make sure we have our boundary and send headers
|
||||
local bd = newboundary()
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or 'multipart/mixed'
|
||||
headers['content-type'] = headers['content-type'] ..
|
||||
'; boundary="' .. bd .. '"'
|
||||
send_headers(headers)
|
||||
-- send preamble
|
||||
if mesgt.body.preamble then
|
||||
coroutine.yield(mesgt.body.preamble)
|
||||
coroutine.yield("\r\n")
|
||||
end
|
||||
-- send each part separated by a boundary
|
||||
for i, m in base.ipairs(mesgt.body) do
|
||||
coroutine.yield("\r\n--" .. bd .. "\r\n")
|
||||
send_message(m)
|
||||
end
|
||||
-- send last boundary
|
||||
coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
|
||||
-- send epilogue
|
||||
if mesgt.body.epilogue then
|
||||
coroutine.yield(mesgt.body.epilogue)
|
||||
coroutine.yield("\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
-- yield message body from a source
|
||||
local function send_source(mesgt)
|
||||
-- make sure we have a content-type
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or
|
||||
'text/plain; charset="iso-8859-1"'
|
||||
send_headers(headers)
|
||||
-- send body from source
|
||||
while true do
|
||||
local chunk, err = mesgt.body()
|
||||
if err then coroutine.yield(nil, err)
|
||||
elseif chunk then coroutine.yield(chunk)
|
||||
else break end
|
||||
end
|
||||
end
|
||||
|
||||
-- yield message body from a string
|
||||
local function send_string(mesgt)
|
||||
-- make sure we have a content-type
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or
|
||||
'text/plain; charset="iso-8859-1"'
|
||||
send_headers(headers)
|
||||
-- send body from string
|
||||
coroutine.yield(mesgt.body)
|
||||
end
|
||||
|
||||
-- message source
|
||||
function send_message(mesgt)
|
||||
if base.type(mesgt.body) == "table" then send_multipart(mesgt)
|
||||
elseif base.type(mesgt.body) == "function" then send_source(mesgt)
|
||||
else send_string(mesgt) end
|
||||
end
|
||||
|
||||
-- set defaul headers
|
||||
local function adjust_headers(mesgt)
|
||||
local lower = {}
|
||||
for i,v in base.pairs(mesgt.headers or lower) do
|
||||
lower[string.lower(i)] = v
|
||||
end
|
||||
lower["date"] = lower["date"] or
|
||||
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
|
||||
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
|
||||
-- this can't be overriden
|
||||
lower["mime-version"] = "1.0"
|
||||
mesgt.headers = lower
|
||||
end
|
||||
|
||||
function message(mesgt)
|
||||
adjust_headers(mesgt)
|
||||
-- create and return message source
|
||||
local co = coroutine.create(function() send_message(mesgt) end)
|
||||
return function()
|
||||
local ret, a, b = coroutine.resume(co)
|
||||
if ret then return a, b
|
||||
else return nil, a end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- High level SMTP API
|
||||
-----------------------------------------------------------------------------
|
||||
send = socket.protect(function(mailt)
|
||||
local s = open(mailt.server, mailt.port, mailt.create)
|
||||
local ext = s:greet(mailt.domain)
|
||||
s:auth(mailt.user, mailt.password, ext)
|
||||
s:send(mailt)
|
||||
s:quit()
|
||||
return s:close()
|
||||
end)
|
||||
-----------------------------------------------------------------------------
|
||||
-- SMTP client support for the Lua language.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: smtp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local coroutine = require("coroutine")
|
||||
local string = require("string")
|
||||
local math = require("math")
|
||||
local os = require("os")
|
||||
local socket = require("socket")
|
||||
local tp = require("socket.tp")
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
module("socket.smtp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
-- timeout for connection
|
||||
TIMEOUT = 60
|
||||
-- default server used to send e-mails
|
||||
SERVER = "localhost"
|
||||
-- default port
|
||||
PORT = 25
|
||||
-- domain used in HELO command and default sendmail
|
||||
-- If we are under a CGI, try to get from environment
|
||||
DOMAIN = os.getenv("SERVER_NAME") or "localhost"
|
||||
-- default time zone (means we don't know)
|
||||
ZONE = "-0000"
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Low level SMTP API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function metat.__index:greet(domain)
|
||||
self.try(self.tp:check("2.."))
|
||||
self.try(self.tp:command("EHLO", domain or DOMAIN))
|
||||
return socket.skip(1, self.try(self.tp:check("2..")))
|
||||
end
|
||||
|
||||
function metat.__index:mail(from)
|
||||
self.try(self.tp:command("MAIL", "FROM:" .. from))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:rcpt(to)
|
||||
self.try(self.tp:command("RCPT", "TO:" .. to))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:data(src, step)
|
||||
self.try(self.tp:command("DATA"))
|
||||
self.try(self.tp:check("3.."))
|
||||
self.try(self.tp:source(src, step))
|
||||
self.try(self.tp:send("\r\n.\r\n"))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:quit()
|
||||
self.try(self.tp:command("QUIT"))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:close()
|
||||
return self.tp:close()
|
||||
end
|
||||
|
||||
function metat.__index:login(user, password)
|
||||
self.try(self.tp:command("AUTH", "LOGIN"))
|
||||
self.try(self.tp:check("3.."))
|
||||
self.try(self.tp:command(mime.b64(user)))
|
||||
self.try(self.tp:check("3.."))
|
||||
self.try(self.tp:command(mime.b64(password)))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:plain(user, password)
|
||||
local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password)
|
||||
self.try(self.tp:command("AUTH", auth))
|
||||
return self.try(self.tp:check("2.."))
|
||||
end
|
||||
|
||||
function metat.__index:auth(user, password, ext)
|
||||
if not user or not password then return 1 end
|
||||
if string.find(ext, "AUTH[^\n]+LOGIN") then
|
||||
return self:login(user, password)
|
||||
elseif string.find(ext, "AUTH[^\n]+PLAIN") then
|
||||
return self:plain(user, password)
|
||||
else
|
||||
self.try(nil, "authentication not supported")
|
||||
end
|
||||
end
|
||||
|
||||
-- send message or throw an exception
|
||||
function metat.__index:send(mailt)
|
||||
self:mail(mailt.from)
|
||||
if base.type(mailt.rcpt) == "table" then
|
||||
for i,v in base.ipairs(mailt.rcpt) do
|
||||
self:rcpt(v)
|
||||
end
|
||||
else
|
||||
self:rcpt(mailt.rcpt)
|
||||
end
|
||||
self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
|
||||
end
|
||||
|
||||
function open(server, port, create)
|
||||
local tp = socket.try(tp.connect(server or SERVER, port or PORT,
|
||||
create, TIMEOUT))
|
||||
local s = base.setmetatable({tp = tp}, metat)
|
||||
-- make sure tp is closed if we get an exception
|
||||
s.try = socket.newtry(function()
|
||||
s:close()
|
||||
end)
|
||||
return s
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- Multipart message source
|
||||
-----------------------------------------------------------------------------
|
||||
-- returns a hopefully unique mime boundary
|
||||
local seqno = 0
|
||||
local function newboundary()
|
||||
seqno = seqno + 1
|
||||
return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'),
|
||||
math.random(0, 99999), seqno)
|
||||
end
|
||||
|
||||
-- send_message forward declaration
|
||||
local send_message
|
||||
|
||||
-- yield the headers all at once, it's faster
|
||||
local function send_headers(headers)
|
||||
local h = "\r\n"
|
||||
for i,v in base.pairs(headers) do
|
||||
h = i .. ': ' .. v .. "\r\n" .. h
|
||||
end
|
||||
coroutine.yield(h)
|
||||
end
|
||||
|
||||
-- yield multipart message body from a multipart message table
|
||||
local function send_multipart(mesgt)
|
||||
-- make sure we have our boundary and send headers
|
||||
local bd = newboundary()
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or 'multipart/mixed'
|
||||
headers['content-type'] = headers['content-type'] ..
|
||||
'; boundary="' .. bd .. '"'
|
||||
send_headers(headers)
|
||||
-- send preamble
|
||||
if mesgt.body.preamble then
|
||||
coroutine.yield(mesgt.body.preamble)
|
||||
coroutine.yield("\r\n")
|
||||
end
|
||||
-- send each part separated by a boundary
|
||||
for i, m in base.ipairs(mesgt.body) do
|
||||
coroutine.yield("\r\n--" .. bd .. "\r\n")
|
||||
send_message(m)
|
||||
end
|
||||
-- send last boundary
|
||||
coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
|
||||
-- send epilogue
|
||||
if mesgt.body.epilogue then
|
||||
coroutine.yield(mesgt.body.epilogue)
|
||||
coroutine.yield("\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
-- yield message body from a source
|
||||
local function send_source(mesgt)
|
||||
-- make sure we have a content-type
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or
|
||||
'text/plain; charset="iso-8859-1"'
|
||||
send_headers(headers)
|
||||
-- send body from source
|
||||
while true do
|
||||
local chunk, err = mesgt.body()
|
||||
if err then coroutine.yield(nil, err)
|
||||
elseif chunk then coroutine.yield(chunk)
|
||||
else break end
|
||||
end
|
||||
end
|
||||
|
||||
-- yield message body from a string
|
||||
local function send_string(mesgt)
|
||||
-- make sure we have a content-type
|
||||
local headers = mesgt.headers or {}
|
||||
headers['content-type'] = headers['content-type'] or
|
||||
'text/plain; charset="iso-8859-1"'
|
||||
send_headers(headers)
|
||||
-- send body from string
|
||||
coroutine.yield(mesgt.body)
|
||||
end
|
||||
|
||||
-- message source
|
||||
function send_message(mesgt)
|
||||
if base.type(mesgt.body) == "table" then send_multipart(mesgt)
|
||||
elseif base.type(mesgt.body) == "function" then send_source(mesgt)
|
||||
else send_string(mesgt) end
|
||||
end
|
||||
|
||||
-- set defaul headers
|
||||
local function adjust_headers(mesgt)
|
||||
local lower = {}
|
||||
for i,v in base.pairs(mesgt.headers or lower) do
|
||||
lower[string.lower(i)] = v
|
||||
end
|
||||
lower["date"] = lower["date"] or
|
||||
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
|
||||
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
|
||||
-- this can't be overriden
|
||||
lower["mime-version"] = "1.0"
|
||||
mesgt.headers = lower
|
||||
end
|
||||
|
||||
function message(mesgt)
|
||||
adjust_headers(mesgt)
|
||||
-- create and return message source
|
||||
local co = coroutine.create(function() send_message(mesgt) end)
|
||||
return function()
|
||||
local ret, a, b = coroutine.resume(co)
|
||||
if ret then return a, b
|
||||
else return nil, a end
|
||||
end
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
-- High level SMTP API
|
||||
-----------------------------------------------------------------------------
|
||||
send = socket.protect(function(mailt)
|
||||
local s = open(mailt.server, mailt.port, mailt.create)
|
||||
local ext = s:greet(mailt.domain)
|
||||
s:auth(mailt.user, mailt.password, ext)
|
||||
s:send(mailt)
|
||||
s:quit()
|
||||
return s:close()
|
||||
end)
|
||||
|
||||
@@ -1,123 +1,123 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Unified SMTP/FTP subsystem
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: tp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local string = require("string")
|
||||
local socket = require("socket")
|
||||
local ltn12 = require("ltn12")
|
||||
module("socket.tp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
TIMEOUT = 60
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Implementation
|
||||
-----------------------------------------------------------------------------
|
||||
-- gets server reply (works for SMTP and FTP)
|
||||
local function get_reply(c)
|
||||
local code, current, sep
|
||||
local line, err = c:receive()
|
||||
local reply = line
|
||||
if err then return nil, err end
|
||||
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||
if not code then return nil, "invalid server reply" end
|
||||
if sep == "-" then -- reply is multiline
|
||||
repeat
|
||||
line, err = c:receive()
|
||||
if err then return nil, err end
|
||||
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||
reply = reply .. "\n" .. line
|
||||
-- reply ends with same code
|
||||
until code == current and sep == " "
|
||||
end
|
||||
return code, reply
|
||||
end
|
||||
|
||||
-- metatable for sock object
|
||||
local metat = { __index = {} }
|
||||
|
||||
function metat.__index:check(ok)
|
||||
local code, reply = get_reply(self.c)
|
||||
if not code then return nil, reply end
|
||||
if base.type(ok) ~= "function" then
|
||||
if base.type(ok) == "table" then
|
||||
for i, v in base.ipairs(ok) do
|
||||
if string.find(code, v) then
|
||||
return base.tonumber(code), reply
|
||||
end
|
||||
end
|
||||
return nil, reply
|
||||
else
|
||||
if string.find(code, ok) then return base.tonumber(code), reply
|
||||
else return nil, reply end
|
||||
end
|
||||
else return ok(base.tonumber(code), reply) end
|
||||
end
|
||||
|
||||
function metat.__index:command(cmd, arg)
|
||||
if arg then
|
||||
return self.c:send(cmd .. " " .. arg.. "\r\n")
|
||||
else
|
||||
return self.c:send(cmd .. "\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
function metat.__index:sink(snk, pat)
|
||||
local chunk, err = c:receive(pat)
|
||||
return snk(chunk, err)
|
||||
end
|
||||
|
||||
function metat.__index:send(data)
|
||||
return self.c:send(data)
|
||||
end
|
||||
|
||||
function metat.__index:receive(pat)
|
||||
return self.c:receive(pat)
|
||||
end
|
||||
|
||||
function metat.__index:getfd()
|
||||
return self.c:getfd()
|
||||
end
|
||||
|
||||
function metat.__index:dirty()
|
||||
return self.c:dirty()
|
||||
end
|
||||
|
||||
function metat.__index:getcontrol()
|
||||
return self.c
|
||||
end
|
||||
|
||||
function metat.__index:source(source, step)
|
||||
local sink = socket.sink("keep-open", self.c)
|
||||
local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
||||
return ret, err
|
||||
end
|
||||
|
||||
-- closes the underlying c
|
||||
function metat.__index:close()
|
||||
self.c:close()
|
||||
return 1
|
||||
end
|
||||
|
||||
-- connect with server and return c object
|
||||
function connect(host, port, create, timeout)
|
||||
local c, e = (create or socket.tcp())
|
||||
if not c then return nil, e end
|
||||
c:settimeout(timeout or TIMEOUT)
|
||||
local r, e = c:connect(host, port)
|
||||
if not r then
|
||||
c:close()
|
||||
return nil, e
|
||||
end
|
||||
return base.setmetatable({c = c}, metat)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Unified SMTP/FTP subsystem
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: tp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module and import dependencies
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local string = require("string")
|
||||
local socket = require("socket")
|
||||
local ltn12 = require("ltn12")
|
||||
module("socket.tp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
TIMEOUT = 60
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Implementation
|
||||
-----------------------------------------------------------------------------
|
||||
-- gets server reply (works for SMTP and FTP)
|
||||
local function get_reply(c)
|
||||
local code, current, sep
|
||||
local line, err = c:receive()
|
||||
local reply = line
|
||||
if err then return nil, err end
|
||||
code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||
if not code then return nil, "invalid server reply" end
|
||||
if sep == "-" then -- reply is multiline
|
||||
repeat
|
||||
line, err = c:receive()
|
||||
if err then return nil, err end
|
||||
current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||
reply = reply .. "\n" .. line
|
||||
-- reply ends with same code
|
||||
until code == current and sep == " "
|
||||
end
|
||||
return code, reply
|
||||
end
|
||||
|
||||
-- metatable for sock object
|
||||
local metat = { __index = {} }
|
||||
|
||||
function metat.__index:check(ok)
|
||||
local code, reply = get_reply(self.c)
|
||||
if not code then return nil, reply end
|
||||
if base.type(ok) ~= "function" then
|
||||
if base.type(ok) == "table" then
|
||||
for i, v in base.ipairs(ok) do
|
||||
if string.find(code, v) then
|
||||
return base.tonumber(code), reply
|
||||
end
|
||||
end
|
||||
return nil, reply
|
||||
else
|
||||
if string.find(code, ok) then return base.tonumber(code), reply
|
||||
else return nil, reply end
|
||||
end
|
||||
else return ok(base.tonumber(code), reply) end
|
||||
end
|
||||
|
||||
function metat.__index:command(cmd, arg)
|
||||
if arg then
|
||||
return self.c:send(cmd .. " " .. arg.. "\r\n")
|
||||
else
|
||||
return self.c:send(cmd .. "\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
function metat.__index:sink(snk, pat)
|
||||
local chunk, err = c:receive(pat)
|
||||
return snk(chunk, err)
|
||||
end
|
||||
|
||||
function metat.__index:send(data)
|
||||
return self.c:send(data)
|
||||
end
|
||||
|
||||
function metat.__index:receive(pat)
|
||||
return self.c:receive(pat)
|
||||
end
|
||||
|
||||
function metat.__index:getfd()
|
||||
return self.c:getfd()
|
||||
end
|
||||
|
||||
function metat.__index:dirty()
|
||||
return self.c:dirty()
|
||||
end
|
||||
|
||||
function metat.__index:getcontrol()
|
||||
return self.c
|
||||
end
|
||||
|
||||
function metat.__index:source(source, step)
|
||||
local sink = socket.sink("keep-open", self.c)
|
||||
local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
|
||||
return ret, err
|
||||
end
|
||||
|
||||
-- closes the underlying c
|
||||
function metat.__index:close()
|
||||
self.c:close()
|
||||
return 1
|
||||
end
|
||||
|
||||
-- connect with server and return c object
|
||||
function connect(host, port, create, timeout)
|
||||
local c, e = (create or socket.tcp())
|
||||
if not c then return nil, e end
|
||||
c:settimeout(timeout or TIMEOUT)
|
||||
local r, e = c:connect(host, port)
|
||||
if not r then
|
||||
c:close()
|
||||
return nil, e
|
||||
end
|
||||
return base.setmetatable({c = c}, metat)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,297 +1,297 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- URI parsing, composition and relative URL resolution
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: url.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module
|
||||
-----------------------------------------------------------------------------
|
||||
local string = require("string")
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
module("socket.url")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Module version
|
||||
-----------------------------------------------------------------------------
|
||||
_VERSION = "URL 1.0"
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
function escape(s)
|
||||
return string.gsub(s, "([^A-Za-z0-9_])", function(c)
|
||||
return string.format("%%%02x", string.byte(c))
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Protects a path segment, to prevent it from interfering with the
|
||||
-- url parsing.
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
local function make_set(t)
|
||||
local s = {}
|
||||
for i,v in base.ipairs(t) do
|
||||
s[t[i]] = 1
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
-- these are allowed withing a path segment, along with alphanum
|
||||
-- other characters must be escaped
|
||||
local segment_set = make_set {
|
||||
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||
")", ":", "@", "&", "=", "+", "$", ",",
|
||||
}
|
||||
|
||||
local function protect_segment(s)
|
||||
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
|
||||
if segment_set[c] then return c
|
||||
else return string.format("%%%02x", string.byte(c)) end
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
function unescape(s)
|
||||
return string.gsub(s, "%%(%x%x)", function(hex)
|
||||
return string.char(base.tonumber(hex, 16))
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a path from a base path and a relative path
|
||||
-- Input
|
||||
-- base_path
|
||||
-- relative_path
|
||||
-- Returns
|
||||
-- corresponding absolute path
|
||||
-----------------------------------------------------------------------------
|
||||
local function absolute_path(base_path, relative_path)
|
||||
if string.sub(relative_path, 1, 1) == "/" then return relative_path end
|
||||
local path = string.gsub(base_path, "[^/]*$", "")
|
||||
path = path .. relative_path
|
||||
path = string.gsub(path, "([^/]*%./)", function (s)
|
||||
if s ~= "./" then return s else return "" end
|
||||
end)
|
||||
path = string.gsub(path, "/%.$", "/")
|
||||
local reduced
|
||||
while reduced ~= path do
|
||||
reduced = path
|
||||
path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
|
||||
if s ~= "../../" then return "" else return s end
|
||||
end)
|
||||
end
|
||||
path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
|
||||
if s ~= "../.." then return "" else return s end
|
||||
end)
|
||||
return path
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Parses a url and returns a table with all its parts according to RFC 2396
|
||||
-- The following grammar describes the names given to the URL parts
|
||||
-- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
|
||||
-- <authority> ::= <userinfo>@<host>:<port>
|
||||
-- <userinfo> ::= <user>[:<password>]
|
||||
-- <path> :: = {<segment>/}<segment>
|
||||
-- Input
|
||||
-- url: uniform resource locator of request
|
||||
-- default: table with default values for each field
|
||||
-- Returns
|
||||
-- table with the following fields, where RFC naming conventions have
|
||||
-- been preserved:
|
||||
-- scheme, authority, userinfo, user, password, host, port,
|
||||
-- path, params, query, fragment
|
||||
-- Obs:
|
||||
-- the leading '/' in {/<path>} is considered part of <path>
|
||||
-----------------------------------------------------------------------------
|
||||
function parse(url, default)
|
||||
-- initialize default parameters
|
||||
local parsed = {}
|
||||
for i,v in base.pairs(default or parsed) do parsed[i] = v end
|
||||
-- empty url is parsed to nil
|
||||
if not url or url == "" then return nil, "invalid url" end
|
||||
-- remove whitespace
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
-- get fragment
|
||||
url = string.gsub(url, "#(.*)$", function(f)
|
||||
parsed.fragment = f
|
||||
return ""
|
||||
end)
|
||||
-- get scheme
|
||||
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
|
||||
function(s) parsed.scheme = s; return "" end)
|
||||
-- get authority
|
||||
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||
parsed.authority = n
|
||||
return ""
|
||||
end)
|
||||
-- get query stringing
|
||||
url = string.gsub(url, "%?(.*)", function(q)
|
||||
parsed.query = q
|
||||
return ""
|
||||
end)
|
||||
-- get params
|
||||
url = string.gsub(url, "%;(.*)", function(p)
|
||||
parsed.params = p
|
||||
return ""
|
||||
end)
|
||||
-- path is whatever was left
|
||||
if url ~= "" then parsed.path = url end
|
||||
local authority = parsed.authority
|
||||
if not authority then return parsed end
|
||||
authority = string.gsub(authority,"^([^@]*)@",
|
||||
function(u) parsed.userinfo = u; return "" end)
|
||||
authority = string.gsub(authority, ":([^:]*)$",
|
||||
function(p) parsed.port = p; return "" end)
|
||||
if authority ~= "" then parsed.host = authority end
|
||||
local userinfo = parsed.userinfo
|
||||
if not userinfo then return parsed end
|
||||
userinfo = string.gsub(userinfo, ":([^:]*)$",
|
||||
function(p) parsed.password = p; return "" end)
|
||||
parsed.user = userinfo
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Rebuilds a parsed URL from its components.
|
||||
-- Components are protected if any reserved or unallowed characters are found
|
||||
-- Input
|
||||
-- parsed: parsed URL, as returned by parse
|
||||
-- Returns
|
||||
-- a stringing with the corresponding URL
|
||||
-----------------------------------------------------------------------------
|
||||
function build(parsed)
|
||||
local ppath = parse_path(parsed.path or "")
|
||||
local url = build_path(ppath)
|
||||
if parsed.params then url = url .. ";" .. parsed.params end
|
||||
if parsed.query then url = url .. "?" .. parsed.query end
|
||||
local authority = parsed.authority
|
||||
if parsed.host then
|
||||
authority = parsed.host
|
||||
if parsed.port then authority = authority .. ":" .. parsed.port end
|
||||
local userinfo = parsed.userinfo
|
||||
if parsed.user then
|
||||
userinfo = parsed.user
|
||||
if parsed.password then
|
||||
userinfo = userinfo .. ":" .. parsed.password
|
||||
end
|
||||
end
|
||||
if userinfo then authority = userinfo .. "@" .. authority end
|
||||
end
|
||||
if authority then url = "//" .. authority .. url end
|
||||
if parsed.scheme then url = parsed.scheme .. ":" .. url end
|
||||
if parsed.fragment then url = url .. "#" .. parsed.fragment end
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
return url
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a absolute URL from a base and a relative URL according to RFC 2396
|
||||
-- Input
|
||||
-- base_url
|
||||
-- relative_url
|
||||
-- Returns
|
||||
-- corresponding absolute url
|
||||
-----------------------------------------------------------------------------
|
||||
function absolute(base_url, relative_url)
|
||||
if base.type(base_url) == "table" then
|
||||
base_parsed = base_url
|
||||
base_url = build(base_parsed)
|
||||
else
|
||||
base_parsed = parse(base_url)
|
||||
end
|
||||
local relative_parsed = parse(relative_url)
|
||||
if not base_parsed then return relative_url
|
||||
elseif not relative_parsed then return base_url
|
||||
elseif relative_parsed.scheme then return relative_url
|
||||
else
|
||||
relative_parsed.scheme = base_parsed.scheme
|
||||
if not relative_parsed.authority then
|
||||
relative_parsed.authority = base_parsed.authority
|
||||
if not relative_parsed.path then
|
||||
relative_parsed.path = base_parsed.path
|
||||
if not relative_parsed.params then
|
||||
relative_parsed.params = base_parsed.params
|
||||
if not relative_parsed.query then
|
||||
relative_parsed.query = base_parsed.query
|
||||
end
|
||||
end
|
||||
else
|
||||
relative_parsed.path = absolute_path(base_parsed.path or "",
|
||||
relative_parsed.path)
|
||||
end
|
||||
end
|
||||
return build(relative_parsed)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Breaks a path into its segments, unescaping the segments
|
||||
-- Input
|
||||
-- path
|
||||
-- Returns
|
||||
-- segment: a table with one entry per segment
|
||||
-----------------------------------------------------------------------------
|
||||
function parse_path(path)
|
||||
local parsed = {}
|
||||
path = path or ""
|
||||
--path = string.gsub(path, "%s", "")
|
||||
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
|
||||
for i = 1, table.getn(parsed) do
|
||||
parsed[i] = unescape(parsed[i])
|
||||
end
|
||||
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
|
||||
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a path component from its segments, escaping protected characters.
|
||||
-- Input
|
||||
-- parsed: path segments
|
||||
-- unsafe: if true, segments are not protected before path is built
|
||||
-- Returns
|
||||
-- path: corresponding path stringing
|
||||
-----------------------------------------------------------------------------
|
||||
function build_path(parsed, unsafe)
|
||||
local path = ""
|
||||
local n = table.getn(parsed)
|
||||
if unsafe then
|
||||
for i = 1, n-1 do
|
||||
path = path .. parsed[i]
|
||||
path = path .. "/"
|
||||
end
|
||||
if n > 0 then
|
||||
path = path .. parsed[n]
|
||||
if parsed.is_directory then path = path .. "/" end
|
||||
end
|
||||
else
|
||||
for i = 1, n-1 do
|
||||
path = path .. protect_segment(parsed[i])
|
||||
path = path .. "/"
|
||||
end
|
||||
if n > 0 then
|
||||
path = path .. protect_segment(parsed[n])
|
||||
if parsed.is_directory then path = path .. "/" end
|
||||
end
|
||||
end
|
||||
if parsed.is_absolute then path = "/" .. path end
|
||||
return path
|
||||
end
|
||||
-----------------------------------------------------------------------------
|
||||
-- URI parsing, composition and relative URL resolution
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: url.lua 1418 2006-04-25 09:38:15Z 3rdparty $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module
|
||||
-----------------------------------------------------------------------------
|
||||
local string = require("string")
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
module("socket.url")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Module version
|
||||
-----------------------------------------------------------------------------
|
||||
_VERSION = "URL 1.0"
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
function escape(s)
|
||||
return string.gsub(s, "([^A-Za-z0-9_])", function(c)
|
||||
return string.format("%%%02x", string.byte(c))
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Protects a path segment, to prevent it from interfering with the
|
||||
-- url parsing.
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
local function make_set(t)
|
||||
local s = {}
|
||||
for i,v in base.ipairs(t) do
|
||||
s[t[i]] = 1
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
-- these are allowed withing a path segment, along with alphanum
|
||||
-- other characters must be escaped
|
||||
local segment_set = make_set {
|
||||
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||
")", ":", "@", "&", "=", "+", "$", ",",
|
||||
}
|
||||
|
||||
local function protect_segment(s)
|
||||
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
|
||||
if segment_set[c] then return c
|
||||
else return string.format("%%%02x", string.byte(c)) end
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
function unescape(s)
|
||||
return string.gsub(s, "%%(%x%x)", function(hex)
|
||||
return string.char(base.tonumber(hex, 16))
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a path from a base path and a relative path
|
||||
-- Input
|
||||
-- base_path
|
||||
-- relative_path
|
||||
-- Returns
|
||||
-- corresponding absolute path
|
||||
-----------------------------------------------------------------------------
|
||||
local function absolute_path(base_path, relative_path)
|
||||
if string.sub(relative_path, 1, 1) == "/" then return relative_path end
|
||||
local path = string.gsub(base_path, "[^/]*$", "")
|
||||
path = path .. relative_path
|
||||
path = string.gsub(path, "([^/]*%./)", function (s)
|
||||
if s ~= "./" then return s else return "" end
|
||||
end)
|
||||
path = string.gsub(path, "/%.$", "/")
|
||||
local reduced
|
||||
while reduced ~= path do
|
||||
reduced = path
|
||||
path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
|
||||
if s ~= "../../" then return "" else return s end
|
||||
end)
|
||||
end
|
||||
path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
|
||||
if s ~= "../.." then return "" else return s end
|
||||
end)
|
||||
return path
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Parses a url and returns a table with all its parts according to RFC 2396
|
||||
-- The following grammar describes the names given to the URL parts
|
||||
-- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
|
||||
-- <authority> ::= <userinfo>@<host>:<port>
|
||||
-- <userinfo> ::= <user>[:<password>]
|
||||
-- <path> :: = {<segment>/}<segment>
|
||||
-- Input
|
||||
-- url: uniform resource locator of request
|
||||
-- default: table with default values for each field
|
||||
-- Returns
|
||||
-- table with the following fields, where RFC naming conventions have
|
||||
-- been preserved:
|
||||
-- scheme, authority, userinfo, user, password, host, port,
|
||||
-- path, params, query, fragment
|
||||
-- Obs:
|
||||
-- the leading '/' in {/<path>} is considered part of <path>
|
||||
-----------------------------------------------------------------------------
|
||||
function parse(url, default)
|
||||
-- initialize default parameters
|
||||
local parsed = {}
|
||||
for i,v in base.pairs(default or parsed) do parsed[i] = v end
|
||||
-- empty url is parsed to nil
|
||||
if not url or url == "" then return nil, "invalid url" end
|
||||
-- remove whitespace
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
-- get fragment
|
||||
url = string.gsub(url, "#(.*)$", function(f)
|
||||
parsed.fragment = f
|
||||
return ""
|
||||
end)
|
||||
-- get scheme
|
||||
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
|
||||
function(s) parsed.scheme = s; return "" end)
|
||||
-- get authority
|
||||
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||
parsed.authority = n
|
||||
return ""
|
||||
end)
|
||||
-- get query stringing
|
||||
url = string.gsub(url, "%?(.*)", function(q)
|
||||
parsed.query = q
|
||||
return ""
|
||||
end)
|
||||
-- get params
|
||||
url = string.gsub(url, "%;(.*)", function(p)
|
||||
parsed.params = p
|
||||
return ""
|
||||
end)
|
||||
-- path is whatever was left
|
||||
if url ~= "" then parsed.path = url end
|
||||
local authority = parsed.authority
|
||||
if not authority then return parsed end
|
||||
authority = string.gsub(authority,"^([^@]*)@",
|
||||
function(u) parsed.userinfo = u; return "" end)
|
||||
authority = string.gsub(authority, ":([^:]*)$",
|
||||
function(p) parsed.port = p; return "" end)
|
||||
if authority ~= "" then parsed.host = authority end
|
||||
local userinfo = parsed.userinfo
|
||||
if not userinfo then return parsed end
|
||||
userinfo = string.gsub(userinfo, ":([^:]*)$",
|
||||
function(p) parsed.password = p; return "" end)
|
||||
parsed.user = userinfo
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Rebuilds a parsed URL from its components.
|
||||
-- Components are protected if any reserved or unallowed characters are found
|
||||
-- Input
|
||||
-- parsed: parsed URL, as returned by parse
|
||||
-- Returns
|
||||
-- a stringing with the corresponding URL
|
||||
-----------------------------------------------------------------------------
|
||||
function build(parsed)
|
||||
local ppath = parse_path(parsed.path or "")
|
||||
local url = build_path(ppath)
|
||||
if parsed.params then url = url .. ";" .. parsed.params end
|
||||
if parsed.query then url = url .. "?" .. parsed.query end
|
||||
local authority = parsed.authority
|
||||
if parsed.host then
|
||||
authority = parsed.host
|
||||
if parsed.port then authority = authority .. ":" .. parsed.port end
|
||||
local userinfo = parsed.userinfo
|
||||
if parsed.user then
|
||||
userinfo = parsed.user
|
||||
if parsed.password then
|
||||
userinfo = userinfo .. ":" .. parsed.password
|
||||
end
|
||||
end
|
||||
if userinfo then authority = userinfo .. "@" .. authority end
|
||||
end
|
||||
if authority then url = "//" .. authority .. url end
|
||||
if parsed.scheme then url = parsed.scheme .. ":" .. url end
|
||||
if parsed.fragment then url = url .. "#" .. parsed.fragment end
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
return url
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a absolute URL from a base and a relative URL according to RFC 2396
|
||||
-- Input
|
||||
-- base_url
|
||||
-- relative_url
|
||||
-- Returns
|
||||
-- corresponding absolute url
|
||||
-----------------------------------------------------------------------------
|
||||
function absolute(base_url, relative_url)
|
||||
if base.type(base_url) == "table" then
|
||||
base_parsed = base_url
|
||||
base_url = build(base_parsed)
|
||||
else
|
||||
base_parsed = parse(base_url)
|
||||
end
|
||||
local relative_parsed = parse(relative_url)
|
||||
if not base_parsed then return relative_url
|
||||
elseif not relative_parsed then return base_url
|
||||
elseif relative_parsed.scheme then return relative_url
|
||||
else
|
||||
relative_parsed.scheme = base_parsed.scheme
|
||||
if not relative_parsed.authority then
|
||||
relative_parsed.authority = base_parsed.authority
|
||||
if not relative_parsed.path then
|
||||
relative_parsed.path = base_parsed.path
|
||||
if not relative_parsed.params then
|
||||
relative_parsed.params = base_parsed.params
|
||||
if not relative_parsed.query then
|
||||
relative_parsed.query = base_parsed.query
|
||||
end
|
||||
end
|
||||
else
|
||||
relative_parsed.path = absolute_path(base_parsed.path or "",
|
||||
relative_parsed.path)
|
||||
end
|
||||
end
|
||||
return build(relative_parsed)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Breaks a path into its segments, unescaping the segments
|
||||
-- Input
|
||||
-- path
|
||||
-- Returns
|
||||
-- segment: a table with one entry per segment
|
||||
-----------------------------------------------------------------------------
|
||||
function parse_path(path)
|
||||
local parsed = {}
|
||||
path = path or ""
|
||||
--path = string.gsub(path, "%s", "")
|
||||
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
|
||||
for i = 1, table.getn(parsed) do
|
||||
parsed[i] = unescape(parsed[i])
|
||||
end
|
||||
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
|
||||
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a path component from its segments, escaping protected characters.
|
||||
-- Input
|
||||
-- parsed: path segments
|
||||
-- unsafe: if true, segments are not protected before path is built
|
||||
-- Returns
|
||||
-- path: corresponding path stringing
|
||||
-----------------------------------------------------------------------------
|
||||
function build_path(parsed, unsafe)
|
||||
local path = ""
|
||||
local n = table.getn(parsed)
|
||||
if unsafe then
|
||||
for i = 1, n-1 do
|
||||
path = path .. parsed[i]
|
||||
path = path .. "/"
|
||||
end
|
||||
if n > 0 then
|
||||
path = path .. parsed[n]
|
||||
if parsed.is_directory then path = path .. "/" end
|
||||
end
|
||||
else
|
||||
for i = 1, n-1 do
|
||||
path = path .. protect_segment(parsed[i])
|
||||
path = path .. "/"
|
||||
end
|
||||
if n > 0 then
|
||||
path = path .. protect_segment(parsed[n])
|
||||
if parsed.is_directory then path = path .. "/" end
|
||||
end
|
||||
end
|
||||
if parsed.is_absolute then path = "/" .. path end
|
||||
return path
|
||||
end
|
||||
|
||||
211
spec/cg.lua
@@ -1,106 +1,105 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"cg","cgh","fx","fxh","cgfx","cgfxh",},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "cg",
|
||||
sep = "%.",
|
||||
linecomment = "//",
|
||||
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
|
||||
end
|
||||
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[int half float float3 float4 float2 float3x3 float3x4 float4x3 float4x4
|
||||
float1x2 float2x1 float2x2 float2x3 float3x2 float1x3 float3x1 float4x1 float1x4
|
||||
float2x4 float4x2 double1x4 double4x4 double4x2 double4x3 double3x4 double2x4 double1x4
|
||||
double half half2 half3 half4 int2 int3 uint uint2 uint3 uint4
|
||||
int4 bool bool2 bool3 bool4 string struct typedef
|
||||
usampler usampler1D usampler2D usampler3D usamplerRECT usamplerCUBE isampler1DARRAY usampler2DARRAY usamplerCUBEARRAY isampler
|
||||
isampler1D isampler2D isampler3D isamplerRECT isamplerCUBE isampler1DARRAY isampler2DARRAY isamplerCUBEARRAY sampler sampler1D
|
||||
sampler2D sampler3D samplerRECT samplerCUBE sampler1DARRAY sampler2DARRAY samplerCUBEARRAY texture texture1D texture2D
|
||||
texture3D textureRECT textureCUBE texture1DARRAY texture2DARRAY textureCUBEARRAY decl do double else
|
||||
usamplerBUF isamplerBUF samplerBUF samplerRBUF sampler2DMS sampler2DMSARRAY usamplerRBUF usampler2DMS usampler2DMSARRAY
|
||||
isamplerRBUF isampler2DMS isampler2DMSARRAY
|
||||
extern false for if in inline inout out pass pixelshader
|
||||
return shared static string technique true uniform vector vertexshader void
|
||||
volatile while asm compile const auto break case catch
|
||||
char class const_cast continue default delete dynamic_cast enum explicit friend
|
||||
goto long mutable namespace new operator private protected public register
|
||||
reinterpret_case short signed sizeof static_cast switch template this throw try
|
||||
typename union unsigned using virtual ]],
|
||||
|
||||
[[abs acos all any asin atan atan2 ceil clamp clip
|
||||
cos cosh cross ddx ddy degrees determinant distance dot exp
|
||||
exp2 faceforward floatToIntBits floatToRawIntBits floor fmod frac frexp fwidth intBitsToFloat
|
||||
isfinite isinf isnan ldexp length lerp lit log log10 log2
|
||||
max min mul normalize pow radians reflect refract round rsqrt
|
||||
saturate sign sin sincos sinh sqrt step tan tanh tex1D
|
||||
tex1DARRAY tex1DARRAYbias tex1DARRAYcmpbias tex1DARRAYcmplod tex1DARRAYfetch tex1DARRAYlod tex1DARRAYproj tex1DARRAYsize tex1Dbias tex1Dcmpbias
|
||||
tex1Dcmplod tex1Dfetch tex1Dlod tex1Dproj tex1Dsize tex2D tex2DARRAY tex2DARRAYbias tex2DARRAYfetch tex2DARRAYlod
|
||||
tex2DARRAYproj tex2DARRAYsize tex2Dbias tex2Dcmpbias tex2Dcmplod tex2Dfetch tex2Dlod tex2Dproj tex2Dsize tex3D
|
||||
tex3Dbias tex3Dfetch tex3Dlod tex3Dproj tex3Dsize texBUF texBUFsize texCUBE texCUBEARRAY texCUBEARRAYsize
|
||||
texCUBEbias texCUBElod texCUBEproj texCUBEsize texRECT texRECTbias texRECTfetch texRECTlod texRECTproj texRECTsize
|
||||
texBUF texBUFsize texRBUF texRBUFsize tex2DMS tex2DMSARRAY tex2DMSsize tex2DMSARRAYsize
|
||||
unpack_4ubyte pack_4ubyte unpack_4byte pack_4byte unpack_2ushort pack_2ushort
|
||||
unpack_2half pack_2half
|
||||
|
||||
transpose trunc POSITION PSIZE DIFFUSE SPECULAR TEXCOORD FOG FOGP COLOR WPOS
|
||||
COLOR0 COLOR1 COLOR2 COLOR3 TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3 TEXCOORD4 TEXCOORD5
|
||||
TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9 TEXCOORD10 TEXCOORD11 TEXCOORD12 TEXCOORD13 TEXCOORD14 TEXCOORD15
|
||||
NORMAL FACE PRIMITIVEID DEPTH ATTR0 ATTR1 ATTR2 ATTR3 ATTR4 ATTR5
|
||||
ATTR6 ATTR7 ATTR8 ATTR9 ATTR10 ATTR11 ATTR12 ATTR13 ATTR14 ATTR15
|
||||
TEXUNIT0 TEXUNIT1 TEXUNIT2 TEXUNIT3 TEXUNIT4 TEXUNIT5 TEXUNIT6 TEXUNIT7 TEXUNIT8 TEXUNIT9
|
||||
TEXUNIT10 TEXUNIT11 TEXUNIT12 TEXUNIT13 TEXUNIT14 TEXUNIT15 LAYER INSTANCEID
|
||||
|
||||
PROJ PROJECTION PROJECTIONMATRIX PROJMATRIX
|
||||
PROJMATRIXINV PROJINV PROJECTIONINV PROJINVERSE PROJECTIONINVERSE PROJINVMATRIX PROJECTIONINVMATRIX PROJINVERSEMATRIX PROJECTIONINVERSEMATRIX
|
||||
VIEW VIEWMATRIX VIEWMATRIXINV VIEWINV VIEWINVERSE VIEWINVERSEMATRIX VIEWINVMATRIX
|
||||
VIEWPROJECTION VIEWPROJ VIEWPROJMATRIX VIEWPROJECTIONMATRIX
|
||||
WORLD WORLDMATRIX WORLDVIEW WORLDVIEWMATRIX
|
||||
WORLDVIEWPROJ WORLDVIEWPROJECTION WORLDVIEWPROJMATRIX WORLDVIEWPROJECTIONMATRIX
|
||||
VIEWPORTSIZE VIEWPORTDIMENSION
|
||||
VIEWPORTSIZEINV VIEWPORTSIZEINVERSE VIEWPORTDIMENSIONINV VIEWPORTDIMENSIONINVERSE INVERSEVIEWPORTDIMENSIONS
|
||||
FOGCOLOR FOGDISTANCE CAMERAWORLDPOS CAMERAWORLDDIR
|
||||
|
||||
CENTROID FLAT NOPERSPECTIVE FACE PRIMITIVEID VERTEXID
|
||||
]],
|
||||
|
||||
},
|
||||
}
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"cg","cgh","fx","fxh","cgfx","cgfxh",},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "cg",
|
||||
sep = "%.",
|
||||
linecomment = "//",
|
||||
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
|
||||
end
|
||||
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[int half float float3 float4 float2 float3x3 float3x4 float4x3 float4x4
|
||||
float1x2 float2x1 float2x2 float2x3 float3x2 float1x3 float3x1 float4x1 float1x4
|
||||
float2x4 float4x2 double1x4 double4x4 double4x2 double4x3 double3x4 double2x4 double1x4
|
||||
double half half2 half3 half4 int2 int3 uint uint2 uint3 uint4
|
||||
int4 bool bool2 bool3 bool4 string struct typedef
|
||||
usampler usampler1D usampler2D usampler3D usamplerRECT usamplerCUBE isampler1DARRAY usampler2DARRAY usamplerCUBEARRAY isampler
|
||||
isampler1D isampler2D isampler3D isamplerRECT isamplerCUBE isampler1DARRAY isampler2DARRAY isamplerCUBEARRAY sampler sampler1D
|
||||
sampler2D sampler3D samplerRECT samplerCUBE sampler1DARRAY sampler2DARRAY samplerCUBEARRAY texture texture1D texture2D
|
||||
texture3D textureRECT textureCUBE texture1DARRAY texture2DARRAY textureCUBEARRAY decl do double else
|
||||
usamplerBUF isamplerBUF samplerBUF samplerRBUF sampler2DMS sampler2DMSARRAY usamplerRBUF usampler2DMS usampler2DMSARRAY
|
||||
isamplerRBUF isampler2DMS isampler2DMSARRAY
|
||||
extern false for if in inline inout out pass pixelshader
|
||||
return shared static string technique true uniform vector vertexshader void
|
||||
volatile while asm compile const auto break case catch
|
||||
char class const_cast continue default delete dynamic_cast enum explicit friend
|
||||
goto long mutable namespace new operator private protected public register
|
||||
reinterpret_case short signed sizeof static_cast switch template this throw try
|
||||
typename union unsigned using virtual ]],
|
||||
|
||||
[[abs acos all any asin atan atan2 ceil clamp clip
|
||||
cos cosh cross ddx ddy degrees determinant distance dot exp
|
||||
exp2 faceforward floatToIntBits floatToRawIntBits floor fmod frac frexp fwidth intBitsToFloat
|
||||
isfinite isinf isnan ldexp length lerp lit log log10 log2
|
||||
max min mul normalize pow radians reflect refract round rsqrt
|
||||
saturate sign sin sincos sinh sqrt step tan tanh tex1D
|
||||
tex1DARRAY tex1DARRAYbias tex1DARRAYcmpbias tex1DARRAYcmplod tex1DARRAYfetch tex1DARRAYlod tex1DARRAYproj tex1DARRAYsize tex1Dbias tex1Dcmpbias
|
||||
tex1Dcmplod tex1Dfetch tex1Dlod tex1Dproj tex1Dsize tex2D tex2DARRAY tex2DARRAYbias tex2DARRAYfetch tex2DARRAYlod
|
||||
tex2DARRAYproj tex2DARRAYsize tex2Dbias tex2Dcmpbias tex2Dcmplod tex2Dfetch tex2Dlod tex2Dproj tex2Dsize tex3D
|
||||
tex3Dbias tex3Dfetch tex3Dlod tex3Dproj tex3Dsize texBUF texBUFsize texCUBE texCUBEARRAY texCUBEARRAYsize
|
||||
texCUBEbias texCUBElod texCUBEproj texCUBEsize texRECT texRECTbias texRECTfetch texRECTlod texRECTproj texRECTsize
|
||||
texBUF texBUFsize texRBUF texRBUFsize tex2DMS tex2DMSARRAY tex2DMSsize tex2DMSARRAYsize
|
||||
unpack_4ubyte pack_4ubyte unpack_4byte pack_4byte unpack_2ushort pack_2ushort
|
||||
unpack_2half pack_2half
|
||||
|
||||
transpose trunc POSITION PSIZE DIFFUSE SPECULAR TEXCOORD FOG FOGP COLOR WPOS
|
||||
COLOR0 COLOR1 COLOR2 COLOR3 TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3 TEXCOORD4 TEXCOORD5
|
||||
TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9 TEXCOORD10 TEXCOORD11 TEXCOORD12 TEXCOORD13 TEXCOORD14 TEXCOORD15
|
||||
NORMAL FACE PRIMITIVEID DEPTH ATTR0 ATTR1 ATTR2 ATTR3 ATTR4 ATTR5
|
||||
ATTR6 ATTR7 ATTR8 ATTR9 ATTR10 ATTR11 ATTR12 ATTR13 ATTR14 ATTR15
|
||||
TEXUNIT0 TEXUNIT1 TEXUNIT2 TEXUNIT3 TEXUNIT4 TEXUNIT5 TEXUNIT6 TEXUNIT7 TEXUNIT8 TEXUNIT9
|
||||
TEXUNIT10 TEXUNIT11 TEXUNIT12 TEXUNIT13 TEXUNIT14 TEXUNIT15 LAYER INSTANCEID
|
||||
|
||||
PROJ PROJECTION PROJECTIONMATRIX PROJMATRIX
|
||||
PROJMATRIXINV PROJINV PROJECTIONINV PROJINVERSE PROJECTIONINVERSE PROJINVMATRIX PROJECTIONINVMATRIX PROJINVERSEMATRIX PROJECTIONINVERSEMATRIX
|
||||
VIEW VIEWMATRIX VIEWMATRIXINV VIEWINV VIEWINVERSE VIEWINVERSEMATRIX VIEWINVMATRIX
|
||||
VIEWPROJECTION VIEWPROJ VIEWPROJMATRIX VIEWPROJECTIONMATRIX
|
||||
WORLD WORLDMATRIX WORLDVIEW WORLDVIEWMATRIX
|
||||
WORLDVIEWPROJ WORLDVIEWPROJECTION WORLDVIEWPROJMATRIX WORLDVIEWPROJECTIONMATRIX
|
||||
VIEWPORTSIZE VIEWPORTDIMENSION
|
||||
VIEWPORTSIZEINV VIEWPORTSIZEINVERSE VIEWPORTDIMENSIONINV VIEWPORTDIMENSIONINVERSE INVERSEVIEWPORTDIMENSIONS
|
||||
FOGCOLOR FOGDISTANCE CAMERAWORLDPOS CAMERAWORLDDIR
|
||||
|
||||
CENTROID FLAT NOPERSPECTIVE FACE PRIMITIVEID VERTEXID
|
||||
]],
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
335
spec/glsl.lua
@@ -2,173 +2,172 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"glsl","vert","frag","geom","cont","eval", "glslv", "glslf"},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "glsl",
|
||||
sep = "%.",
|
||||
linecomment = "//",
|
||||
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
|
||||
end
|
||||
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[int uint half float bool double
|
||||
vec2 vec3 vec4 dvec2 dvec3 dvec4
|
||||
ivec2 ivec3 ivec4 uvec2 uvec3 uvec4 bvec2 bvec3 bvec4
|
||||
mat2 mat3 mat4 mat2x2 mat3x3 mat4x4 mat2x3 mat3x2 mat4x2 mat2x4 mat4x3 mat3x4
|
||||
dmat2 dmat3 dmat4 dmat2x2 dmat3x3 dmat4x4 dmat2x3 dmat3x2 dmat4x2 dmat2x4 dmat4x3 dmat3x4
|
||||
struct typedef void
|
||||
usampler1D usampler2D usampler3D usampler2DRect usamplerCube isampler1DArray usampler2DARRAY usamplerCubeArray usampler2DMS usampler2DMSArray
|
||||
isampler1D isampler2D isampler3D isampler2DRect isamplerCube isampler1DArray isampler2DARRAY isamplerCubeArray isampler2DMS isampler2DMSArray
|
||||
sampler1D sampler2D sampler3D sampler2DRect samplerCube sampler1DArray sampler2DArray samplerCubeArray sampler2DMS sampler2DMSArray
|
||||
sampler1DShadow sampler2DShadow sampler2DRectShadow sampler1DArrayShadow sampler2DArrayShadow samplerCubeArrayShadow
|
||||
usamplerBuffer isamplerBuffer samplerBuffer samplerRenderbuffer isamplerRenderbuffer usamplerRenderbuffer
|
||||
in out inout uniform const centroid sample attribute varying patch index true false
|
||||
return switch case for do while if else break continue main inline
|
||||
layout location vertices line_strip triangle_strip max_vertices stream
|
||||
triangles quads equal_spacing isolines fractional_even_spacing lines points
|
||||
fractional_odd_spacing cw ccw point_mode lines_adjacency triangles_adjacency
|
||||
invocations
|
||||
origin_upper_left pixel_center_integer
|
||||
smooth flat noperspective highp mediump lowp shared packed std140 row_major column_major
|
||||
gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_Color gl_SecondaryColor
|
||||
subroutine gl_Position gl_FragCoord
|
||||
gl_VertexID gl_InstanceID gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1
|
||||
gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6
|
||||
gl_MultiTexCoord7 gl_FogCoord gl_PointSize gl_ClipDistance
|
||||
gl_TexCoord gl_FogFragCoord gl_ClipVertex gl_in
|
||||
gl_PatchVerticesIn
|
||||
gl_PrimitiveID gl_InvocationID gl_TessLevelOuter gl_TessLevelInner gl_TessCoord
|
||||
gl_InvocationID gl_PrimitiveIDIn gl_Layer gl_ViewportIndex gl_FrontFacing
|
||||
gl_PointCoord gl_SampleID gl_SamplePosition gl_FragColor
|
||||
gl_FragData gl_FragDepth gl_SampleMask
|
||||
|
||||
coherent volatile restrict
|
||||
image1D image2D image3D image2DRect imageCube imageBuffer image1DArray image2DArray imageCubeArray image2DMS image2DMSArray
|
||||
uimage1D uimage2D uimage3D uimage2DRect uimageCube uimageBuffer uimage1DArray uimage2DArray uimageCubeArray uimage2DMS uimage2DMSArray
|
||||
iimage1D iimage2D iimage3D iimage2DRect iimageCube iimageBuffer iimage1DArray iimage2DArray iimageCubeArray iimage2DMS iimage2DMSArray
|
||||
size1x8 size1x16 size1x32 size2x32 size4x32
|
||||
]],
|
||||
exts = {"glsl","vert","frag","geom","cont","eval", "glslv", "glslf"},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "glsl",
|
||||
sep = "%.",
|
||||
linecomment = "//",
|
||||
|
||||
[[discard
|
||||
radians degrees sin cos tan asin acos atan sinh cosh tanh asinh acosh atanh
|
||||
pow exp log exp2 log2 sqrt inversesqrt abs sign floor trunc round
|
||||
roundEven ceil fract mod modf min max mix step isnan isinf clamp smoothstep
|
||||
floatBitsToInt intBitsToFloat uintBitsToFloat fma frexp ldexp
|
||||
packUnorm2x16 packUnorm4x8 packSnorm4x8
|
||||
unpackUnorm2x16 unpackUnorm4x8 unpackSnorm4x8
|
||||
packDouble2x32 unpackDouble2x32
|
||||
length distance dot cross normalize ftransform faceforward
|
||||
reflect refract
|
||||
matrixCompMult outerProduct transpose determinant inverse
|
||||
lessThan lessThanEqual greaterThan greaterThanEqual equal
|
||||
notEqual any all not
|
||||
uaddCarry usubBorrow umulExtended imulExtended
|
||||
bitfeldExtract bitfieldInsert bitfeldReverse bitCount
|
||||
findLSB findMSB
|
||||
dFdx dFdy fwidth
|
||||
interpolateAtCentroid interpolateAtSample interpolateAtOffset
|
||||
noise1 noise2 noise3 noise4
|
||||
EmitStreamVertex EndStreamPrimitive EmitVertex EndPrimitive
|
||||
barrier
|
||||
textureSize textureQueryLod texture textureOffset textureProj
|
||||
textureLod textureProjOffset textureLodOffset
|
||||
texelFetchOffset texelFetch textureProjLod textureProjLodOffset
|
||||
textureGrad textureGradOffset textureProjGrad textureProjGradOffset
|
||||
textureGather textureGatherOffset
|
||||
texture2D texture1D texture3D textureCube texture2DRect
|
||||
texture1DProj texture1DLod texture1DProjLod
|
||||
texture2DProj texture2DLod texture2DProjLod
|
||||
texture3DProj texture3DLod texture3DProjLod
|
||||
textureCubeLod
|
||||
shadow1D shadow2D
|
||||
shadow1DProj shadow1DLod shadow1DProjLod
|
||||
shadow2DProj shadow2DLod shadow2DProjLod
|
||||
texelFetch1D texelFetch2D texelFetch3D texelFetch2DRect texelFetch1DArray texelFetch2DArray texelFetchBuffer
|
||||
textureSizeBuffer textureSize1D textureSize2D textureSize3D textureSizeCube textureSize2DRect
|
||||
textureSize1DArray textureSize2DArray
|
||||
texture1DArray texture1DArrayLod
|
||||
texture2DArray texture2DArrayLod
|
||||
shadow1DArray shadow1DArrayLod shadow2DArray shadowCube
|
||||
texture1DGrad texture1DProjGrad texture1DProjGrad texture1DArrayGrad
|
||||
texture2DGrad texture2DProjGrad texture2DProjGrad texture2DArrayGrad
|
||||
texture3DGrad texture3DProjGrad textureCubeGrad
|
||||
shadow1DGrad shadow1DProjGrad shadow1DArrayGrad shadow2DGrad shadow2DProjGrad shadow2DArrayGrad
|
||||
texture2DRectGrad texture2DRectProjGrad texture2DRectProjGrad shadow2DRectGrad shadow2DRectProjGrad
|
||||
shadowCubeGrad
|
||||
texture1DOffset texture1DProjOffset texture1DLodOffset texture1DProjLodOffset
|
||||
texture2DOffset texture2DProjOffset texture2DLodOffset texture2DProjLodOffset
|
||||
texture3DOffset texture3DProjOffset texture3DLodOffset texture3DProjLodOffset
|
||||
|
||||
imageLoad imageStore
|
||||
imageAtomicAdd imageAtomicMin imageAtomicMax
|
||||
imageAtomicIncWrap imageAtomicDecWrap imageAtomicAnd
|
||||
imageAtomicOr imageAtomixXor imageAtomicExchange
|
||||
imageCompSwap memoryBarrier
|
||||
|
||||
x y z w
|
||||
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy
|
||||
xxzz xxzw xxwx xxwy xxwz xxww xyxx xyxy xyxz xyxw
|
||||
xyyx xyyy xyyz xyyw xyzx xyzy xyzz xyzw xywx xywy
|
||||
xywz xyww xzxx xzxy xzxz xzxw xzyx xzyy xzyz xzyw
|
||||
xzzx xzzy xzzz xzzw xzwx xzwy xzwz xzww xwxx xwxy
|
||||
xwxz xwxw xwyx xwyy xwyz xwyw xwzx xwzy xwzz xwzw
|
||||
xwwx xwwy xwwz xwww yxxx yxxy yxxz yxxw yxyx yxyy
|
||||
yxyz yxyw yxzx yxzy yxzz yxzw yxwx yxwy yxwz yxww
|
||||
yyxx yyxy yyxz yyxw yyyx yyyy yyyz yyyw yyzx yyzy
|
||||
yyzz yyzw yywx yywy yywz yyww yzxx yzxy yzxz yzxw
|
||||
yzyx yzyy yzyz yzyw yzzx yzzy yzzz yzzw yzwx yzwy
|
||||
yzwz yzww ywxx ywxy ywxz ywxw ywyx ywyy ywyz ywyw
|
||||
ywzx ywzy ywzz ywzw ywwx ywwy ywwz ywww zxxx zxxy
|
||||
zxxz zxxw zxyx zxyy zxyz zxyw zxzx zxzy zxzz zxzw
|
||||
zxwx zxwy zxwz zxww zyxx zyxy zyxz zyxw zyyx zyyy
|
||||
zyyz zyyw zyzx zyzy zyzz zyzw zywx zywy zywz zyww
|
||||
zzxx zzxy zzxz zzxw zzyx zzyy zzyz zzyw zzzx zzzy
|
||||
zzzz zzzw zzwx zzwy zzwz zzww zwxx zwxy zwxz zwxw
|
||||
zwyx zwyy zwyz zwyw zwzx zwzy zwzz zwzw zwwx zwwy
|
||||
zwwz zwww wxxx wxxy wxxz wxxw wxyx wxyy wxyz wxyw
|
||||
wxzx wxzy wxzz wxzw wxwx wxwy wxwz wxww wyxx wyxy
|
||||
wyxz wyxw wyyx wyyy wyyz wyyw wyzx wyzy wyzz wyzw
|
||||
wywx wywy wywz wyww wzxx wzxy wzxz wzxw wzyx wzyy
|
||||
wzyz wzyw wzzx wzzy wzzz wzzw wzwx wzwy wzwz wzww
|
||||
wwxx wwxy wwxz wwxw wwyx wwyy wwyz wwyw wwzx wwzy
|
||||
wwzz wwzw wwwx wwwy wwwz wwww xy xz yz xyz
|
||||
xw yw xyw zw xzw yzw xyzw ]],
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
|
||||
end
|
||||
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
},
|
||||
}
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[int uint half float bool double
|
||||
vec2 vec3 vec4 dvec2 dvec3 dvec4
|
||||
ivec2 ivec3 ivec4 uvec2 uvec3 uvec4 bvec2 bvec3 bvec4
|
||||
mat2 mat3 mat4 mat2x2 mat3x3 mat4x4 mat2x3 mat3x2 mat4x2 mat2x4 mat4x3 mat3x4
|
||||
dmat2 dmat3 dmat4 dmat2x2 dmat3x3 dmat4x4 dmat2x3 dmat3x2 dmat4x2 dmat2x4 dmat4x3 dmat3x4
|
||||
struct typedef void
|
||||
usampler1D usampler2D usampler3D usampler2DRect usamplerCube isampler1DArray usampler2DARRAY usamplerCubeArray usampler2DMS usampler2DMSArray
|
||||
isampler1D isampler2D isampler3D isampler2DRect isamplerCube isampler1DArray isampler2DARRAY isamplerCubeArray isampler2DMS isampler2DMSArray
|
||||
sampler1D sampler2D sampler3D sampler2DRect samplerCube sampler1DArray sampler2DArray samplerCubeArray sampler2DMS sampler2DMSArray
|
||||
sampler1DShadow sampler2DShadow sampler2DRectShadow sampler1DArrayShadow sampler2DArrayShadow samplerCubeArrayShadow
|
||||
usamplerBuffer isamplerBuffer samplerBuffer samplerRenderbuffer isamplerRenderbuffer usamplerRenderbuffer
|
||||
in out inout uniform const centroid sample attribute varying patch index true false
|
||||
return switch case for do while if else break continue main inline
|
||||
layout location vertices line_strip triangle_strip max_vertices stream
|
||||
triangles quads equal_spacing isolines fractional_even_spacing lines points
|
||||
fractional_odd_spacing cw ccw point_mode lines_adjacency triangles_adjacency
|
||||
invocations
|
||||
origin_upper_left pixel_center_integer
|
||||
smooth flat noperspective highp mediump lowp shared packed std140 row_major column_major
|
||||
gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_Color gl_SecondaryColor
|
||||
subroutine gl_Position gl_FragCoord
|
||||
gl_VertexID gl_InstanceID gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1
|
||||
gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6
|
||||
gl_MultiTexCoord7 gl_FogCoord gl_PointSize gl_ClipDistance
|
||||
gl_TexCoord gl_FogFragCoord gl_ClipVertex gl_in
|
||||
gl_PatchVerticesIn
|
||||
gl_PrimitiveID gl_InvocationID gl_TessLevelOuter gl_TessLevelInner gl_TessCoord
|
||||
gl_InvocationID gl_PrimitiveIDIn gl_Layer gl_ViewportIndex gl_FrontFacing
|
||||
gl_PointCoord gl_SampleID gl_SamplePosition gl_FragColor
|
||||
gl_FragData gl_FragDepth gl_SampleMask
|
||||
|
||||
coherent volatile restrict
|
||||
image1D image2D image3D image2DRect imageCube imageBuffer image1DArray image2DArray imageCubeArray image2DMS image2DMSArray
|
||||
uimage1D uimage2D uimage3D uimage2DRect uimageCube uimageBuffer uimage1DArray uimage2DArray uimageCubeArray uimage2DMS uimage2DMSArray
|
||||
iimage1D iimage2D iimage3D iimage2DRect iimageCube iimageBuffer iimage1DArray iimage2DArray iimageCubeArray iimage2DMS iimage2DMSArray
|
||||
size1x8 size1x16 size1x32 size2x32 size4x32
|
||||
]],
|
||||
|
||||
[[discard
|
||||
radians degrees sin cos tan asin acos atan sinh cosh tanh asinh acosh atanh
|
||||
pow exp log exp2 log2 sqrt inversesqrt abs sign floor trunc round
|
||||
roundEven ceil fract mod modf min max mix step isnan isinf clamp smoothstep
|
||||
floatBitsToInt intBitsToFloat uintBitsToFloat fma frexp ldexp
|
||||
packUnorm2x16 packUnorm4x8 packSnorm4x8
|
||||
unpackUnorm2x16 unpackUnorm4x8 unpackSnorm4x8
|
||||
packDouble2x32 unpackDouble2x32
|
||||
length distance dot cross normalize ftransform faceforward
|
||||
reflect refract
|
||||
matrixCompMult outerProduct transpose determinant inverse
|
||||
lessThan lessThanEqual greaterThan greaterThanEqual equal
|
||||
notEqual any all not
|
||||
uaddCarry usubBorrow umulExtended imulExtended
|
||||
bitfeldExtract bitfieldInsert bitfeldReverse bitCount
|
||||
findLSB findMSB
|
||||
dFdx dFdy fwidth
|
||||
interpolateAtCentroid interpolateAtSample interpolateAtOffset
|
||||
noise1 noise2 noise3 noise4
|
||||
EmitStreamVertex EndStreamPrimitive EmitVertex EndPrimitive
|
||||
barrier
|
||||
textureSize textureQueryLod texture textureOffset textureProj
|
||||
textureLod textureProjOffset textureLodOffset
|
||||
texelFetchOffset texelFetch textureProjLod textureProjLodOffset
|
||||
textureGrad textureGradOffset textureProjGrad textureProjGradOffset
|
||||
textureGather textureGatherOffset
|
||||
texture2D texture1D texture3D textureCube texture2DRect
|
||||
texture1DProj texture1DLod texture1DProjLod
|
||||
texture2DProj texture2DLod texture2DProjLod
|
||||
texture3DProj texture3DLod texture3DProjLod
|
||||
textureCubeLod
|
||||
shadow1D shadow2D
|
||||
shadow1DProj shadow1DLod shadow1DProjLod
|
||||
shadow2DProj shadow2DLod shadow2DProjLod
|
||||
texelFetch1D texelFetch2D texelFetch3D texelFetch2DRect texelFetch1DArray texelFetch2DArray texelFetchBuffer
|
||||
textureSizeBuffer textureSize1D textureSize2D textureSize3D textureSizeCube textureSize2DRect
|
||||
textureSize1DArray textureSize2DArray
|
||||
texture1DArray texture1DArrayLod
|
||||
texture2DArray texture2DArrayLod
|
||||
shadow1DArray shadow1DArrayLod shadow2DArray shadowCube
|
||||
texture1DGrad texture1DProjGrad texture1DProjGrad texture1DArrayGrad
|
||||
texture2DGrad texture2DProjGrad texture2DProjGrad texture2DArrayGrad
|
||||
texture3DGrad texture3DProjGrad textureCubeGrad
|
||||
shadow1DGrad shadow1DProjGrad shadow1DArrayGrad shadow2DGrad shadow2DProjGrad shadow2DArrayGrad
|
||||
texture2DRectGrad texture2DRectProjGrad texture2DRectProjGrad shadow2DRectGrad shadow2DRectProjGrad
|
||||
shadowCubeGrad
|
||||
texture1DOffset texture1DProjOffset texture1DLodOffset texture1DProjLodOffset
|
||||
texture2DOffset texture2DProjOffset texture2DLodOffset texture2DProjLodOffset
|
||||
texture3DOffset texture3DProjOffset texture3DLodOffset texture3DProjLodOffset
|
||||
|
||||
imageLoad imageStore
|
||||
imageAtomicAdd imageAtomicMin imageAtomicMax
|
||||
imageAtomicIncWrap imageAtomicDecWrap imageAtomicAnd
|
||||
imageAtomicOr imageAtomixXor imageAtomicExchange
|
||||
imageCompSwap memoryBarrier
|
||||
|
||||
x y z w
|
||||
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy
|
||||
xxzz xxzw xxwx xxwy xxwz xxww xyxx xyxy xyxz xyxw
|
||||
xyyx xyyy xyyz xyyw xyzx xyzy xyzz xyzw xywx xywy
|
||||
xywz xyww xzxx xzxy xzxz xzxw xzyx xzyy xzyz xzyw
|
||||
xzzx xzzy xzzz xzzw xzwx xzwy xzwz xzww xwxx xwxy
|
||||
xwxz xwxw xwyx xwyy xwyz xwyw xwzx xwzy xwzz xwzw
|
||||
xwwx xwwy xwwz xwww yxxx yxxy yxxz yxxw yxyx yxyy
|
||||
yxyz yxyw yxzx yxzy yxzz yxzw yxwx yxwy yxwz yxww
|
||||
yyxx yyxy yyxz yyxw yyyx yyyy yyyz yyyw yyzx yyzy
|
||||
yyzz yyzw yywx yywy yywz yyww yzxx yzxy yzxz yzxw
|
||||
yzyx yzyy yzyz yzyw yzzx yzzy yzzz yzzw yzwx yzwy
|
||||
yzwz yzww ywxx ywxy ywxz ywxw ywyx ywyy ywyz ywyw
|
||||
ywzx ywzy ywzz ywzw ywwx ywwy ywwz ywww zxxx zxxy
|
||||
zxxz zxxw zxyx zxyy zxyz zxyw zxzx zxzy zxzz zxzw
|
||||
zxwx zxwy zxwz zxww zyxx zyxy zyxz zyxw zyyx zyyy
|
||||
zyyz zyyw zyzx zyzy zyzz zyzw zywx zywy zywz zyww
|
||||
zzxx zzxy zzxz zzxw zzyx zzyy zzyz zzyw zzzx zzzy
|
||||
zzzz zzzw zzwx zzwy zzwz zzww zwxx zwxy zwxz zwxw
|
||||
zwyx zwyy zwyz zwyw zwzx zwzy zwzz zwzw zwwx zwwy
|
||||
zwwz zwww wxxx wxxy wxxz wxxw wxyx wxyy wxyz wxyw
|
||||
wxzx wxzy wxzz wxzw wxwx wxwy wxwz wxww wyxx wyxy
|
||||
wyxz wyxw wyyx wyyy wyyz wyyw wyzx wyzy wyzz wyzw
|
||||
wywx wywy wywz wyww wzxx wzxy wzxz wzxw wzyx wzyy
|
||||
wzyz wzyw wzzx wzzy wzzz wzzw wzwx wzwy wzwz wzww
|
||||
wwxx wwxy wwxz wwxw wwyx wwyy wwyz wwyw wwzx wwzy
|
||||
wwzz wwzw wwwx wwwy wwwz wwww xy xz yz xyz
|
||||
xw yw xyw zw xzw yzw xyzw ]],
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
245
spec/html.lua
@@ -2,133 +2,124 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"htm","html"},
|
||||
lexer = wxstc.wxSTC_LEX_HTML,
|
||||
apitype = "html",
|
||||
|
||||
stylingbits = 7,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {
|
||||
wxstc.wxSTC_H_DEFAULT,
|
||||
wxstc.wxSTC_HJ_DEFAULT,
|
||||
},
|
||||
comment = {wxstc.wxSTC_H_COMMENT,
|
||||
wxstc.wxSTC_HPHP_COMMENT,
|
||||
wxstc.wxSTC_HPHP_COMMENTLINE,
|
||||
wxstc.wxSTC_HJA_COMMENTLINE,
|
||||
wxstc.wxSTC_HJA_COMMENTDOC,
|
||||
wxstc.wxSTC_HJ_COMMENT,
|
||||
wxstc.wxSTC_HJ_COMMENTLINE,
|
||||
wxstc.wxSTC_HJ_COMMENTDOC,},
|
||||
stringeol = {wxstc.wxSTC_HJ_STRINGEOL,},
|
||||
number = {wxstc.wxSTC_H_NUMBER,
|
||||
wxstc.wxSTC_HJ_NUMBER,
|
||||
wxstc.wxSTC_HJA_NUMBER,
|
||||
wxstc.wxSTC_HPHP_NUMBER,},
|
||||
stringtxt = {
|
||||
wxstc.wxSTC_H_DOUBLESTRING,
|
||||
wxstc.wxSTC_H_SINGLESTRING,
|
||||
wxstc.wxSTC_HJ_DOUBLESTRING,
|
||||
wxstc.wxSTC_HJ_SINGLESTRING,
|
||||
wxstc.wxSTC_HJA_DOUBLESTRING,
|
||||
wxstc.wxSTC_HJA_SINGLESTRING,
|
||||
wxstc.wxSTC_HPHP_HSTRING,
|
||||
wxstc.wxSTC_HPHP_SIMPLESTRING,
|
||||
},
|
||||
lexerdef= {
|
||||
|
||||
wxstc.wxSTC_H_OTHER,
|
||||
wxstc.wxSTC_H_ENTITY,
|
||||
wxstc.wxSTC_H_VALUE,
|
||||
|
||||
|
||||
wxstc.wxSTC_HJA_START,
|
||||
wxstc.wxSTC_HJA_DEFAULT,
|
||||
wxstc.wxSTC_HJA_COMMENT,
|
||||
|
||||
wxstc.wxSTC_HJA_SYMBOLS,
|
||||
wxstc.wxSTC_HJA_STRINGEOL,
|
||||
wxstc.wxSTC_HJA_REGEX,
|
||||
exts = {"htm","html"},
|
||||
lexer = wxstc.wxSTC_LEX_HTML,
|
||||
apitype = "html",
|
||||
|
||||
wxstc.wxSTC_HPHP_DEFAULT,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
keywords0 = {
|
||||
wxstc.wxSTC_H_TAG,
|
||||
wxstc.wxSTC_H_ATTRIBUTE,
|
||||
|
||||
wxstc.wxSTC_HPHP_OPERATOR,
|
||||
|
||||
|
||||
wxstc.wxSTC_HJA_KEYWORD,
|
||||
},
|
||||
keywords1 = {wxstc.wxSTC_H_TAGUNKNOWN,
|
||||
wxstc.wxSTC_H_ATTRIBUTEUNKNOWN,
|
||||
wxstc.wxSTC_HJ_WORD,
|
||||
wxstc.wxSTC_HPHP_WORD,
|
||||
wxstc.wxSTC_HJA_WORD,
|
||||
wxstc.wxSTC_HPHP_VARIABLE,
|
||||
wxstc.wxSTC_HPHP_HSTRING_VARIABLE,},
|
||||
keywords2 = {wxstc.wxSTC_H_SCRIPT,
|
||||
wxstc.wxSTC_HJ_KEYWORD,
|
||||
wxstc.wxSTC_HJ_REGEX,},
|
||||
keywords3 = {wxstc.wxSTC_HJ_SYMBOLS,},
|
||||
keywords4 = {
|
||||
wxstc.wxSTC_HJ_START,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
-- HTML tags and attributes
|
||||
[[ a abbr acronym address applet area b base basefont bdo big blockquote
|
||||
body br button caption center cite code col colgroup dd del dfn dir div
|
||||
dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html
|
||||
i iframe img input ins isindex kbd label legend li link map menu meta
|
||||
noframes noscript object ol optgroup option p param pre q s samp script
|
||||
select small span strike strong style sub sup table tbody td textarea
|
||||
tfoot th thead title tr tt u ul var
|
||||
|
||||
class id style title dir lang onclick ondblclick onmousedown onmouseup
|
||||
onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup
|
||||
accesskey charset coords href hreflang name onblur onfocus rel rev
|
||||
shape tabindex target type
|
||||
align alt archive code codebase width height hspace name object vspace
|
||||
nohref color face size cite alink background bgcolor link onload
|
||||
onunload text vlink clear disabled type value char charoff span
|
||||
datetime compact color action accept accept-charset enctype method
|
||||
onreset onsubmit frameborder longdesc marginwidth marginheight
|
||||
noresize scrolling src cols rows profile noshade version
|
||||
border ismap usemap checked maxlength readonly onchange onselect
|
||||
prompt for http-equiv content scheme classid codetype data declare
|
||||
standby start disabled label selected defer event language for
|
||||
multiple media cellpadding cellspacing rules summary
|
||||
axis headers scope image hidden radio]],
|
||||
-- javascript keywords
|
||||
[[break else end false for function if
|
||||
in var null return true while undefined this]],
|
||||
-- VBScript keywords
|
||||
"",
|
||||
-- Python keywords
|
||||
"",
|
||||
-- PHP keywords (used for Lua however)
|
||||
[[and break do else elseif end false for function if
|
||||
in local nil not or repeat return then true until while]],
|
||||
-- XML
|
||||
"",
|
||||
-- SGML
|
||||
"",
|
||||
-- SGML block
|
||||
""
|
||||
},
|
||||
stylingbits = 7,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {
|
||||
wxstc.wxSTC_H_DEFAULT,
|
||||
wxstc.wxSTC_HJ_DEFAULT,
|
||||
},
|
||||
comment = {wxstc.wxSTC_H_COMMENT,
|
||||
wxstc.wxSTC_HPHP_COMMENT,
|
||||
wxstc.wxSTC_HPHP_COMMENTLINE,
|
||||
wxstc.wxSTC_HJA_COMMENTLINE,
|
||||
wxstc.wxSTC_HJA_COMMENTDOC,
|
||||
wxstc.wxSTC_HJ_COMMENT,
|
||||
wxstc.wxSTC_HJ_COMMENTLINE,
|
||||
wxstc.wxSTC_HJ_COMMENTDOC,},
|
||||
stringeol = {wxstc.wxSTC_HJ_STRINGEOL,},
|
||||
number = {wxstc.wxSTC_H_NUMBER,
|
||||
wxstc.wxSTC_HJ_NUMBER,
|
||||
wxstc.wxSTC_HJA_NUMBER,
|
||||
wxstc.wxSTC_HPHP_NUMBER,},
|
||||
stringtxt = {
|
||||
wxstc.wxSTC_H_DOUBLESTRING,
|
||||
wxstc.wxSTC_H_SINGLESTRING,
|
||||
wxstc.wxSTC_HJ_DOUBLESTRING,
|
||||
wxstc.wxSTC_HJ_SINGLESTRING,
|
||||
wxstc.wxSTC_HJA_DOUBLESTRING,
|
||||
wxstc.wxSTC_HJA_SINGLESTRING,
|
||||
wxstc.wxSTC_HPHP_HSTRING,
|
||||
wxstc.wxSTC_HPHP_SIMPLESTRING,
|
||||
},
|
||||
lexerdef= {
|
||||
|
||||
}
|
||||
wxstc.wxSTC_H_OTHER,
|
||||
wxstc.wxSTC_H_ENTITY,
|
||||
wxstc.wxSTC_H_VALUE,
|
||||
|
||||
wxstc.wxSTC_HJA_START,
|
||||
wxstc.wxSTC_HJA_DEFAULT,
|
||||
wxstc.wxSTC_HJA_COMMENT,
|
||||
|
||||
wxstc.wxSTC_HJA_SYMBOLS,
|
||||
wxstc.wxSTC_HJA_STRINGEOL,
|
||||
wxstc.wxSTC_HJA_REGEX,
|
||||
|
||||
wxstc.wxSTC_HPHP_DEFAULT,
|
||||
|
||||
},
|
||||
keywords0 = {
|
||||
wxstc.wxSTC_H_TAG,
|
||||
wxstc.wxSTC_H_ATTRIBUTE,
|
||||
|
||||
wxstc.wxSTC_HPHP_OPERATOR,
|
||||
|
||||
wxstc.wxSTC_HJA_KEYWORD,
|
||||
},
|
||||
keywords1 = {wxstc.wxSTC_H_TAGUNKNOWN,
|
||||
wxstc.wxSTC_H_ATTRIBUTEUNKNOWN,
|
||||
wxstc.wxSTC_HJ_WORD,
|
||||
wxstc.wxSTC_HPHP_WORD,
|
||||
wxstc.wxSTC_HJA_WORD,
|
||||
wxstc.wxSTC_HPHP_VARIABLE,
|
||||
wxstc.wxSTC_HPHP_HSTRING_VARIABLE,},
|
||||
keywords2 = {wxstc.wxSTC_H_SCRIPT,
|
||||
wxstc.wxSTC_HJ_KEYWORD,
|
||||
wxstc.wxSTC_HJ_REGEX,},
|
||||
keywords3 = {wxstc.wxSTC_HJ_SYMBOLS,},
|
||||
keywords4 = {
|
||||
wxstc.wxSTC_HJ_START,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
-- HTML tags and attributes
|
||||
[[ a abbr acronym address applet area b base basefont bdo big blockquote
|
||||
body br button caption center cite code col colgroup dd del dfn dir div
|
||||
dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html
|
||||
i iframe img input ins isindex kbd label legend li link map menu meta
|
||||
noframes noscript object ol optgroup option p param pre q s samp script
|
||||
select small span strike strong style sub sup table tbody td textarea
|
||||
tfoot th thead title tr tt u ul var
|
||||
|
||||
class id style title dir lang onclick ondblclick onmousedown onmouseup
|
||||
onmouseover onmousemove onmouseout onkeypress onkeydown onkeyup
|
||||
accesskey charset coords href hreflang name onblur onfocus rel rev
|
||||
shape tabindex target type
|
||||
align alt archive code codebase width height hspace name object vspace
|
||||
nohref color face size cite alink background bgcolor link onload
|
||||
onunload text vlink clear disabled type value char charoff span
|
||||
datetime compact color action accept accept-charset enctype method
|
||||
onreset onsubmit frameborder longdesc marginwidth marginheight
|
||||
noresize scrolling src cols rows profile noshade version
|
||||
border ismap usemap checked maxlength readonly onchange onselect
|
||||
prompt for http-equiv content scheme classid codetype data declare
|
||||
standby start disabled label selected defer event language for
|
||||
multiple media cellpadding cellspacing rules summary
|
||||
axis headers scope image hidden radio]],
|
||||
-- javascript keywords
|
||||
[[break else end false for function if
|
||||
in var null return true while undefined this]],
|
||||
-- VBScript keywords
|
||||
"",
|
||||
-- Python keywords
|
||||
"",
|
||||
-- PHP keywords (used for Lua however)
|
||||
[[and break do else elseif end false for function if
|
||||
in local nil not or repeat return then true until while]],
|
||||
-- XML
|
||||
"",
|
||||
-- SGML
|
||||
"",
|
||||
-- SGML block
|
||||
""
|
||||
},
|
||||
}
|
||||
|
||||
358
spec/lua.lua
@@ -1,175 +1,183 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"lua"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "lua",
|
||||
linecomment = "--",
|
||||
sep = "%.:",
|
||||
isfncall = function(str)
|
||||
return string.find(str,"([A-Za-z0-9_]+)%s*%(")
|
||||
end,
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"function%s+([A-Za-z0-9_]+%s*[%.%:]*%s*[A-Za-z0-9_]*%s*%(.*%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"function%s+([A-Za-z0-9_]+%s*[%.%:]*%s*[A-Za-z0-9_]*)%s*")
|
||||
end
|
||||
if (s) then
|
||||
l = string.find(string.sub(str,1,s-1),"local%s+$")
|
||||
end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
typeassigns = function(editor)
|
||||
local line = editor:GetCurrentLine()
|
||||
line = line-1
|
||||
|
||||
local scopestart = {"if","do","while","function", "local%s+function", "for", "else", "elseif"}
|
||||
local scopeend = {"end"}
|
||||
local iscomment = editor.spec.iscomment
|
||||
|
||||
local assigns = {}
|
||||
|
||||
-- iterate up until a line starts with scopestart
|
||||
-- always ignore lines whose first symbol is styled as comment
|
||||
local endline = line
|
||||
while (line >= 0) do
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local s = bit.band(editor:GetStyleAt(ls),31)
|
||||
|
||||
if (not iscomment[s]) then
|
||||
local tx = editor:GetLine(line)
|
||||
local leftscope
|
||||
|
||||
for i,v in ipairs(scopestart) do
|
||||
if (tx:match("^"..v)) then
|
||||
leftscope = true
|
||||
end
|
||||
end
|
||||
if (leftscope) then
|
||||
break
|
||||
end
|
||||
end
|
||||
line = line -1
|
||||
end
|
||||
|
||||
local added
|
||||
while (line <= endline) do
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local s = bit.band(editor:GetStyleAt(ls),31)
|
||||
|
||||
if (not iscomment[s]) then
|
||||
local tx = editor:GetLine(line) --= string
|
||||
|
||||
-- check for assignments
|
||||
local varname = "([%w_%.]+)"
|
||||
local identifier = "([%w_%.:]+)"
|
||||
|
||||
-- special hint
|
||||
local typ,var = tx:match("%s*%-%-=%s*"..varname.."%s+"..identifier)
|
||||
if (var and typ) then
|
||||
assigns[var] = typ
|
||||
added = true
|
||||
else
|
||||
-- real assignments
|
||||
local var,typ,rest = tx:match("%s*"..identifier.."%s*=%s*"..identifier.."(.*)")
|
||||
local comment = rest and rest:match(".*%-%-=%s*"..varname.."%s*$")
|
||||
local comma = rest and rest:match(".-%s*([,]*)%s*$")
|
||||
if (var and comment) then
|
||||
assigns[var] = comment
|
||||
added = true
|
||||
elseif (var and typ and comma=="") then
|
||||
class,func = typ:match(varname.."[%.:]"..varname)
|
||||
if (func) then
|
||||
local funcnames = {"new","load","create"}
|
||||
for i,v in ipairs(funcnames) do
|
||||
if (func:match("^"..v)) then
|
||||
assigns[var] = class
|
||||
added = true
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif (assigns[typ]) then
|
||||
assigns[var] = assigns[typ]
|
||||
added = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
line = line+1
|
||||
end
|
||||
|
||||
if (added) then
|
||||
DisplayOutput("\nTYPES\n")
|
||||
for i,v in pairs(assigns) do
|
||||
DisplayOutput(i,v,"\n")
|
||||
end
|
||||
end
|
||||
|
||||
return assigns
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_LUA_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_LUA_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_LUA_COMMENT,
|
||||
wxstc.wxSTC_LUA_COMMENTLINE,
|
||||
wxstc.wxSTC_LUA_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_LUA_STRING,
|
||||
wxstc.wxSTC_LUA_CHARACTER,
|
||||
wxstc.wxSTC_LUA_LITERALSTRING,},
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_LUA_OPERATOR,},
|
||||
number = {wxstc.wxSTC_LUA_NUMBER,},
|
||||
|
||||
|
||||
keywords0 = {wxstc.wxSTC_LUA_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_LUA_WORD2,},
|
||||
keywords2 = {wxstc.wxSTC_LUA_WORD3,},
|
||||
keywords3 = {wxstc.wxSTC_LUA_WORD4,},
|
||||
keywords4 = {wxstc.wxSTC_LUA_WORD5,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[and break do else elseif end false for function if ipairs pairs
|
||||
in local nil not or repeat return then true until while]],
|
||||
|
||||
[[_VERSION assert collectgarbage dofile error gcinfo loadfile loadstring
|
||||
print rawget rawset require tonumber tostring type unpack]],
|
||||
|
||||
[[_G getfenv getmetatable loadlib next pcall
|
||||
rawequal setfenv setmetatable xpcall
|
||||
string table math coroutine io os debug
|
||||
load module select]],
|
||||
|
||||
[[string.byte string.char string.dump string.find string.len
|
||||
string.lower string.rep string.sub string.upper string.format string.gfind string.gsub
|
||||
table.concat table.foreach table.foreachi table.getn table.sort table.insert table.remove table.setn
|
||||
math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.deg math.exp
|
||||
math.floor math.frexp math.ldexp math.log math.log10 math.max math.min math.mod
|
||||
math.pi math.pow math.rad math.random math.randomseed math.sin math.sqrt math.tan
|
||||
string.gmatch string.match string.reverse table.maxn
|
||||
math.cosh math.fmod math.modf math.sinh math.tanh math.huge]],
|
||||
|
||||
[[coroutine.create coroutine.resume coroutine.status
|
||||
coroutine.wrap coroutine.yield
|
||||
io.close io.flush io.input io.lines io.open io.output io.read io.tmpfile io.type io.write
|
||||
io.stdin io.stdout io.stderr
|
||||
os.clock os.date os.difftime os.execute os.exit os.getenv os.remove os.rename
|
||||
os.setlocale os.time os.tmpname
|
||||
coroutine.running package.cpath package.loaded package.loadlib package.path
|
||||
package.preload package.seeall io.popen
|
||||
debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal
|
||||
debug.getmetatable debug.getregistry debug.getupvalue debug.setfenv
|
||||
debug.sethook debug.setlocal debug.setmetatable debug.setupvalue debug.traceback]],
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"lua"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "lua",
|
||||
linecomment = "--",
|
||||
sep = "%.:",
|
||||
isfncall = function(str)
|
||||
return string.find(str,"([A-Za-z0-9_]+)%s*%(")
|
||||
end,
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap,par = string.find(str,"function%s+([A-Za-z0-9_]+%s-[%.%:]?%s-[A-Za-z0-9_]*)%s*(%(.-%))")
|
||||
-- try to match without brackets now, but only at the beginning of the line
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*function%s+([A-Za-z0-9_]+%s-[%.%:]?%s-[A-Za-z0-9_]*)%s*")
|
||||
end
|
||||
-- try to match "foo = function()"
|
||||
if (not s) then
|
||||
s,e,cap,cap1,cap2,par = string.find(str,"(([A-Za-z0-9_]+%s-[%.%:]?%s-)([A-Za-z0-9_]*))%s*=%s*function%s*(%(.-%))")
|
||||
-- check if we captured 'local foo =' instead of 'foo.bar ='
|
||||
if cap1 and cap2 and string.len(cap2) > 0 and not string.find(cap1,'[%.%:]') then
|
||||
cap = cap2
|
||||
s = s + string.len(cap1)
|
||||
end
|
||||
end
|
||||
if (s) then
|
||||
l = string.find(string.sub(str,1,s-1),"local%s+$")
|
||||
cap = cap .. " " .. (par or "(?)")
|
||||
end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
typeassigns = function(editor)
|
||||
local line = editor:GetCurrentLine()
|
||||
line = line-1
|
||||
|
||||
local scopestart = {"if","do","while","function", "local%s+function", "for", "else", "elseif"}
|
||||
local scopeend = {"end"}
|
||||
local iscomment = editor.spec.iscomment
|
||||
|
||||
local assigns = {}
|
||||
|
||||
-- iterate up until a line starts with scopestart
|
||||
-- always ignore lines whose first symbol is styled as comment
|
||||
local endline = line
|
||||
while (line >= 0) do
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local s = bit.band(editor:GetStyleAt(ls),31)
|
||||
|
||||
if (not iscomment[s]) then
|
||||
local tx = editor:GetLine(line)
|
||||
local leftscope
|
||||
|
||||
for i,v in ipairs(scopestart) do
|
||||
if (tx:match("^"..v)) then
|
||||
leftscope = true
|
||||
end
|
||||
end
|
||||
if (leftscope) then
|
||||
break
|
||||
end
|
||||
end
|
||||
line = line -1
|
||||
end
|
||||
|
||||
local added
|
||||
while (line <= endline) do
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local s = bit.band(editor:GetStyleAt(ls),31)
|
||||
|
||||
if (not iscomment[s]) then
|
||||
local tx = editor:GetLine(line) --= string
|
||||
|
||||
-- check for assignments
|
||||
local varname = "([%w_%.]+)"
|
||||
local identifier = "([%w_%.:]+)"
|
||||
|
||||
-- special hint
|
||||
local typ,var = tx:match("%s*%-%-=%s*"..varname.."%s+"..identifier)
|
||||
if (var and typ) then
|
||||
assigns[var] = typ
|
||||
added = true
|
||||
else
|
||||
-- real assignments
|
||||
local var,typ,rest = tx:match("%s*"..identifier.."%s*=%s*"..identifier.."(.*)")
|
||||
local comment = rest and rest:match(".*%-%-=%s*"..varname.."%s*$")
|
||||
local comma = rest and rest:match(".-%s*([,]*)%s*$")
|
||||
if (var and comment) then
|
||||
assigns[var] = comment
|
||||
added = true
|
||||
elseif (var and typ and comma=="") then
|
||||
class,func = typ:match(varname.."[%.:]"..varname)
|
||||
if (func) then
|
||||
local funcnames = {"new","load","create"}
|
||||
for i,v in ipairs(funcnames) do
|
||||
if (func:match("^"..v)) then
|
||||
assigns[var] = class
|
||||
added = true
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif (assigns[typ]) then
|
||||
assigns[var] = assigns[typ]
|
||||
added = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
line = line+1
|
||||
end
|
||||
|
||||
if (added) then
|
||||
DisplayOutput("\nTYPES\n")
|
||||
for i,v in pairs(assigns) do
|
||||
DisplayOutput(i,v,"\n")
|
||||
end
|
||||
end
|
||||
|
||||
return assigns
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_LUA_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_LUA_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_LUA_COMMENT,
|
||||
wxstc.wxSTC_LUA_COMMENTLINE,
|
||||
wxstc.wxSTC_LUA_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_LUA_STRING,
|
||||
wxstc.wxSTC_LUA_CHARACTER,
|
||||
wxstc.wxSTC_LUA_LITERALSTRING,},
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_LUA_OPERATOR,},
|
||||
number = {wxstc.wxSTC_LUA_NUMBER,},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_LUA_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_LUA_WORD2,},
|
||||
keywords2 = {wxstc.wxSTC_LUA_WORD3,},
|
||||
keywords3 = {wxstc.wxSTC_LUA_WORD4,},
|
||||
keywords4 = {wxstc.wxSTC_LUA_WORD5,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[and break do else elseif end false for function if ipairs pairs
|
||||
in local nil not or repeat return then true until while]],
|
||||
|
||||
[[_VERSION assert collectgarbage dofile error gcinfo loadfile loadstring
|
||||
print rawget rawset require tonumber tostring type unpack]],
|
||||
|
||||
[[_G getfenv getmetatable loadlib next pcall
|
||||
rawequal setfenv setmetatable xpcall
|
||||
string table math coroutine io os debug
|
||||
load module select]],
|
||||
|
||||
[[string.byte string.char string.dump string.find string.len
|
||||
string.lower string.rep string.sub string.upper string.format string.gfind string.gsub
|
||||
table.concat table.foreach table.foreachi table.getn table.sort table.insert table.remove table.setn
|
||||
math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.deg math.exp
|
||||
math.floor math.frexp math.ldexp math.log math.log10 math.max math.min math.mod
|
||||
math.pi math.pow math.rad math.random math.randomseed math.sin math.sqrt math.tan
|
||||
string.gmatch string.match string.reverse table.maxn
|
||||
math.cosh math.fmod math.modf math.sinh math.tanh math.huge]],
|
||||
|
||||
[[coroutine.create coroutine.resume coroutine.status
|
||||
coroutine.wrap coroutine.yield
|
||||
io.close io.flush io.input io.lines io.open io.output io.read io.tmpfile io.type io.write
|
||||
io.stdin io.stdout io.stderr
|
||||
os.clock os.date os.difftime os.execute os.exit os.getenv os.remove os.rename
|
||||
os.setlocale os.time os.tmpname
|
||||
coroutine.running package.cpath package.loaded package.loadlib package.path
|
||||
package.preload package.seeall io.popen
|
||||
debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal
|
||||
debug.getmetatable debug.getregistry debug.getupvalue debug.setfenv
|
||||
debug.sethook debug.setlocal debug.setmetatable debug.setupvalue debug.traceback]],
|
||||
},
|
||||
}
|
||||
|
||||
117
spec/luxres.lua
@@ -2,68 +2,67 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"prt","shd","mtl"},
|
||||
lexer = wxstc.wxSTC_LEX_POV,
|
||||
apitype = "luxres",
|
||||
linecomment = "//",
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_POV_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_POV_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_POV_COMMENT,
|
||||
wxstc.wxSTC_POV_COMMENTLINE,},
|
||||
stringtxt = {wxstc.wxSTC_POV_STRING,},
|
||||
stringeol = {wxstc.wxSTC_POV_STRINGEOL,},
|
||||
--preprocessor= {wxstc.wxSTC_POV_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_POV_OPERATOR,},
|
||||
number = {wxstc.wxSTC_POV_NUMBER,},
|
||||
|
||||
|
||||
keywords0 = {wxstc.wxSTC_POV_WORD2,},
|
||||
keywords1 = {wxstc.wxSTC_POV_WORD3,},
|
||||
keywords2 = {wxstc.wxSTC_POV_WORD4,},
|
||||
keywords3 = {wxstc.wxSTC_POV_WORD5,},
|
||||
keywords4 = {wxstc.wxSTC_POV_WORD6,},
|
||||
keywords5 = {wxstc.wxSTC_POV_WORD7,},
|
||||
keywords6 = {wxstc.wxSTC_POV_WORD8,},
|
||||
},
|
||||
exts = {"prt","shd","mtl"},
|
||||
lexer = wxstc.wxSTC_LEX_POV,
|
||||
apitype = "luxres",
|
||||
linecomment = "//",
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_POV_IDENTIFIER,},
|
||||
|
||||
keywords = {
|
||||
-- word0 doesnt exist in lexer
|
||||
"",
|
||||
[[RenderFlag Color Texture Forces SubSystem Emitter Particle Technique GpuProgram Shader
|
||||
NewPass DrawPass ]],
|
||||
lexerdef = {wxstc.wxSTC_POV_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_POV_COMMENT,
|
||||
wxstc.wxSTC_POV_COMMENTLINE,},
|
||||
stringtxt = {wxstc.wxSTC_POV_STRING,},
|
||||
stringeol = {wxstc.wxSTC_POV_STRINGEOL,},
|
||||
--preprocessor= {wxstc.wxSTC_POV_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_POV_OPERATOR,},
|
||||
number = {wxstc.wxSTC_POV_NUMBER,},
|
||||
|
||||
[[control floatmod texcontrol shdcontrol texconst texcenter texscale texrotate texmove texgenplane texclamp
|
||||
frames delay loop param alpha rfalpha layer alphaTEX alphafunc texmatrixcolum
|
||||
blendmode texcoord count type size width height axis model rate
|
||||
alphaTEX alphamode stateflag velocity endtime maxoffsetdist velocityvar flipdirection spread restarttime
|
||||
restarts life size sizeage3 sizevar lifevar rotate rotatevar rotateoffset rotateage3
|
||||
RGBAvar pointparams speedage3 numcolor numtex originoffset gravity wind trail normal
|
||||
translated instancemesh rotateagetex speedagetex sizeagetex RGBAagetex RGBAvar TEXPROJ TEXCUBE TEXALPHA
|
||||
TEX TEXDOTZ VTEXPROJ VTEXCUBE VTEXALPHA VTEX VTEXDOTZ SHD RGBA BASE
|
||||
SKIN FOGGED TEXCOMBINE1D MATERIAL TEXCOMBINE2D_16 TEXCOMBINE2D_32 ]],
|
||||
keywords0 = {wxstc.wxSTC_POV_WORD2,},
|
||||
keywords1 = {wxstc.wxSTC_POV_WORD3,},
|
||||
keywords2 = {wxstc.wxSTC_POV_WORD4,},
|
||||
keywords3 = {wxstc.wxSTC_POV_WORD5,},
|
||||
keywords4 = {wxstc.wxSTC_POV_WORD6,},
|
||||
keywords5 = {wxstc.wxSTC_POV_WORD7,},
|
||||
keywords6 = {wxstc.wxSTC_POV_WORD8,},
|
||||
},
|
||||
|
||||
[[VID_REPLACE VID_DECAL VID_DECAL_PREV VID_DECAL_VERTEX VID_DECAL_CONST VID_MODULATE VID_ADD VID_AMODADD VID_AMODADD_PREV VID_AMODADD_VERTEX
|
||||
VID_AMODADD_CONST VID_AMODADD_CONSTMOD VID_NORMALMAPTAN VID_DECAL_CONSTMOD VID_LIGHTPOS VID_LIGHTCOLOR VID_LIGHTDIR VID_CAMPOS VID_CAMDIR VID_ARRAY
|
||||
VID_LIGHTAMBIENT VID_VALUE VID_LIGHTRANGE VID_RANDOM VID_TIME VID_TEXCONST VID_TEXSIZE VID_TEXSIZEINV VID_TEXLMSCALE VID_TEXMAT0
|
||||
VID_TEXMAT1 VID_TEXMAT2 VID_TEXMAT3 VID_TEXGEN0 VID_TEXGEN1 VID_TEXGEN2 VID_TEXGEN3 RENDER_BLEND RENDER_NOVERTEXCOLOR RENDER_ALPHATEST
|
||||
RENDER_STENCILTEST RENDER_NODEPTHTEST RENDER_NOCULL RENDER_FRONTCULL RENDER_NOCOLORMASK RENDER_NODEPTHMASK RENDER_STENCILMASK RENDER_LIT ADD SIN
|
||||
COS ZIGZAG USER_TEX LIGHTMAP ATTENUATE3D NORMALIZE SKYBOX SPECULAR DIFFUSE DUMMY
|
||||
VID_DEFAULT VID_LOWDETAIL VID_ARB_V VID_ARB_V_TEX4 VID_ARB_V_TEX8 VID_ARB_TEXCOMB VID_ARB_TEXCOMB_TEX4 VID_ARB_VF VID_ARB_VF_TEX4 VID_ARB_VF_TEX8
|
||||
VID_CG_SM3_TEX8 VID_CG_SM3 VID_CG_SM4 VID_CG_SM4_GS GL_NEVER GL_ALWAYS GL_LESS GL_GREATER GL_LEQUAL GL_GEQUAL
|
||||
GL_EQUAL GL_NOTEQUAL VID_POINT VID_CIRCLE VID_SPHERE VID_RECTANGLE VID_MODEL VID_QUAD VID_TRIANGLE VID_HSPHERE
|
||||
VID_DIR VID_ODIR CAP_MODADD CAP_COMBINE4 CAP_TEX3D CAP_TEXFLOAT ]],
|
||||
keywords = {
|
||||
-- word0 doesnt exist in lexer
|
||||
"",
|
||||
[[RenderFlag Color Texture Forces SubSystem Emitter Particle Technique GpuProgram Shader
|
||||
NewPass DrawPass ]],
|
||||
|
||||
[[reflectmap blendinvertalpha spheremap screenmap interpolate skyreflectmap nocolorarray lit unlit sunlit
|
||||
nocull nodepthmask alphamask eyelinmap normalmap sunreflectmap sunnormalmap vertexcolored tangents normals
|
||||
colorpass nodepthtest sort novistest depthmask nodraw depthcompare depthvalue nomipmap fog
|
||||
rotatevelocity dieonfrontplane camrotfix noagedeath pointsmooth noage eventimed sequence combinedraw skymatrix
|
||||
lightmapscale rgbscale2 rgbscale4 alphascale2 alphascale4 lightreflectmap0 lightreflectmap1 lightreflectmap2 lightreflectmap3 lightnormalmap0
|
||||
lightnormalmap1 lightnormalmap2 lightnormalmap3 lowCgProfile VPROG VCG FCG GCG FPROG FFIXED
|
||||
VFIXED GFIXED ]],
|
||||
[[control floatmod texcontrol shdcontrol texconst texcenter texscale texrotate texmove texgenplane texclamp
|
||||
frames delay loop param alpha rfalpha layer alphaTEX alphafunc texmatrixcolum
|
||||
blendmode texcoord count type size width height axis model rate
|
||||
alphaTEX alphamode stateflag velocity endtime maxoffsetdist velocityvar flipdirection spread restarttime
|
||||
restarts life size sizeage3 sizevar lifevar rotate rotatevar rotateoffset rotateage3
|
||||
RGBAvar pointparams speedage3 numcolor numtex originoffset gravity wind trail normal
|
||||
translated instancemesh rotateagetex speedagetex sizeagetex RGBAagetex RGBAvar TEXPROJ TEXCUBE TEXALPHA
|
||||
TEX TEXDOTZ VTEXPROJ VTEXCUBE VTEXALPHA VTEX VTEXDOTZ SHD RGBA BASE
|
||||
SKIN FOGGED TEXCOMBINE1D MATERIAL TEXCOMBINE2D_16 TEXCOMBINE2D_32 ]],
|
||||
|
||||
[[luxinia_ParticleSys_v120 luxinia_Shader_v310 luxinia_Material_v110 IF ELSEIF ELSE ]],
|
||||
[[VID_REPLACE VID_DECAL VID_DECAL_PREV VID_DECAL_VERTEX VID_DECAL_CONST VID_MODULATE VID_ADD VID_AMODADD VID_AMODADD_PREV VID_AMODADD_VERTEX
|
||||
VID_AMODADD_CONST VID_AMODADD_CONSTMOD VID_NORMALMAPTAN VID_DECAL_CONSTMOD VID_LIGHTPOS VID_LIGHTCOLOR VID_LIGHTDIR VID_CAMPOS VID_CAMDIR VID_ARRAY
|
||||
VID_LIGHTAMBIENT VID_VALUE VID_LIGHTRANGE VID_RANDOM VID_TIME VID_TEXCONST VID_TEXSIZE VID_TEXSIZEINV VID_TEXLMSCALE VID_TEXMAT0
|
||||
VID_TEXMAT1 VID_TEXMAT2 VID_TEXMAT3 VID_TEXGEN0 VID_TEXGEN1 VID_TEXGEN2 VID_TEXGEN3 RENDER_BLEND RENDER_NOVERTEXCOLOR RENDER_ALPHATEST
|
||||
RENDER_STENCILTEST RENDER_NODEPTHTEST RENDER_NOCULL RENDER_FRONTCULL RENDER_NOCOLORMASK RENDER_NODEPTHMASK RENDER_STENCILMASK RENDER_LIT ADD SIN
|
||||
COS ZIGZAG USER_TEX LIGHTMAP ATTENUATE3D NORMALIZE SKYBOX SPECULAR DIFFUSE DUMMY
|
||||
VID_DEFAULT VID_LOWDETAIL VID_ARB_V VID_ARB_V_TEX4 VID_ARB_V_TEX8 VID_ARB_TEXCOMB VID_ARB_TEXCOMB_TEX4 VID_ARB_VF VID_ARB_VF_TEX4 VID_ARB_VF_TEX8
|
||||
VID_CG_SM3_TEX8 VID_CG_SM3 VID_CG_SM4 VID_CG_SM4_GS GL_NEVER GL_ALWAYS GL_LESS GL_GREATER GL_LEQUAL GL_GEQUAL
|
||||
GL_EQUAL GL_NOTEQUAL VID_POINT VID_CIRCLE VID_SPHERE VID_RECTANGLE VID_MODEL VID_QUAD VID_TRIANGLE VID_HSPHERE
|
||||
VID_DIR VID_ODIR CAP_MODADD CAP_COMBINE4 CAP_TEX3D CAP_TEXFLOAT ]],
|
||||
|
||||
},
|
||||
}
|
||||
[[reflectmap blendinvertalpha spheremap screenmap interpolate skyreflectmap nocolorarray lit unlit sunlit
|
||||
nocull nodepthmask alphamask eyelinmap normalmap sunreflectmap sunnormalmap vertexcolored tangents normals
|
||||
colorpass nodepthtest sort novistest depthmask nodraw depthcompare depthvalue nomipmap fog
|
||||
rotatevelocity dieonfrontplane camrotfix noagedeath pointsmooth noage eventimed sequence combinedraw skymatrix
|
||||
lightmapscale rgbscale2 rgbscale4 alphascale2 alphascale4 lightreflectmap0 lightreflectmap1 lightreflectmap2 lightreflectmap3 lightnormalmap0
|
||||
lightnormalmap1 lightnormalmap2 lightnormalmap3 lowCgProfile VPROG VCG FCG GCG FPROG FFIXED
|
||||
VFIXED GFIXED ]],
|
||||
|
||||
[[luxinia_ParticleSys_v120 luxinia_Shader_v310 luxinia_Material_v110 IF ELSEIF ELSE ]],
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,115 +1,114 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
-- unfortunately no good lexer
|
||||
-- ASM comments start with ;
|
||||
-- and TCL doesnt allow coloring
|
||||
-- behind keywords
|
||||
|
||||
exts = {"glp","vp","fp"},
|
||||
lexer = wxstc.wxSTC_LEX_TCL,
|
||||
--apitype = "cg",
|
||||
linecomment = "#",
|
||||
lexerstyleconvert = {
|
||||
text = {4,5,7,8,9,10,11,
|
||||
},
|
||||
|
||||
lexerdef = {0,},
|
||||
comment = {1,2,20,21,
|
||||
},
|
||||
--stringtxt = {wxstc.wxSTC_SQL_STRING,
|
||||
-- wxstc.wxSTC_SQL_CHARACTER,
|
||||
-- },
|
||||
--stringeol = {wxstc.wxSTC_SQL_STRINGEOL,},
|
||||
--preprocessor= {,},
|
||||
operator = {6,},
|
||||
number = {3,
|
||||
},
|
||||
|
||||
|
||||
keywords0 = {12,},
|
||||
keywords1 = {13,},
|
||||
keywords2 = {14,},
|
||||
keywords3 = {15,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[EMIT ENDPRIM
|
||||
ABS ADD AND BRK CAL CEIL CMP CONT COS DIV DP2 DP2A DP3 DP4 DPH DST ELSE
|
||||
ENDIF ENDREP EX2 FLR FRC I2F IF KIL LG2 LIT LRP MAD MAX MIN MOD MOV MUL
|
||||
NOT NRM OR PK2H PK2US PK4B PK4UB POW RCC RCP REP RET RFL ROUND RSQ SAD
|
||||
SCS SEQ SFL SGE SGT SHL SHR SIN SLE SLT SNE SSG STR SUB SWZ TEX TRUNC LOOP
|
||||
TXB TXD TXF TXL TXP TXQ UP2H UP2US UP4B UP4UB X2D XOR XPD REP.S REP.F REP.U
|
||||
ENDLOOP SUBROUTINENUM CALI
|
||||
|
||||
ABS_SAT ADD_SAT CEIL_SAT CMP_SAT COS_SAT DIV_SAT DP2_SAT DP2A_SAT DP3_SAT
|
||||
DP4_SAT DPH_SAT DST_SAT EX2_SAT FLR_SAT FRC_SAT LG2_SAT LIT_SAT LRP_SAT
|
||||
MAD_SAT MAX_SAT MIN_SAT MOV_SAT MUL_SAT NRM_SAT POW_SAT RCC_SAT RCP_SAT
|
||||
RFL_SAT ROUND_SAT RSQ_SAT SCS_SAT SEQ_SAT SFL_SAT SGE_SAT SGT_SAT SIN_SAT
|
||||
SLE_SAT SLT_SAT SNE_SAT SSG_SAT STR_SAT SUB_SAT SWZ_SAT TEX_SAT TRUNC_SAT
|
||||
TXB_SAT TXD_SAT TXF_SAT TXL_SAT TXP_SAT UP2H_SAT UP2US_SAT UP4B_SAT UP4UB_SAT
|
||||
X2D_SAT XPD_SAT
|
||||
|
||||
]],
|
||||
[[
|
||||
|
||||
ATTRIB PARAM TEMP ADDRESS OUTPUT ALIAS OPTION TEXTURE
|
||||
PRIMITIVE_IN PRIMITIVE_OUT VERTICES_OUT POINTS LINES LINES_ADJACENCY
|
||||
TRIANGLES TRIANGLES_ADJACENCY
|
||||
LINE_STRIP TRIANGLE_STRIP
|
||||
EQ GE GT LE LT NE TR FL EQ0 GE0 GT0 LE0 LT0 NE0 TR0 FL0 EQ1 GE1 GT1 LE1 LT1
|
||||
NE1 TR1 FL1 NAN NAN0 NAN1 LEG LEG0 LEG1 CF CF0 CF1 NCF NCF0 NCF1 OF OF0 OF1
|
||||
NOF NOF0 NOF1 AB AB0 AB1 BLE BLE0 BLE1 SF SF0 SF1 NSF NSF0 NSF1
|
||||
END SUBROUTINETYPE SUBROUTINE
|
||||
|
||||
]],
|
||||
[[
|
||||
|
||||
vertex position weight normal color primary secondary fogcoord texcoord
|
||||
matrixindex attrib
|
||||
program env local fragment
|
||||
state material ambient diffuse specular emission shininess front back
|
||||
light attenuation spot direction half
|
||||
lightmodel scene lightprod
|
||||
texgen eye object s t r q
|
||||
fog params
|
||||
clip plane
|
||||
point size attenuation
|
||||
matrix modelview projection mvp texture palette row transpose inverse invtrans
|
||||
result pointsize 1D 2D 3D CUBE RECT
|
||||
|
||||
]],
|
||||
[[
|
||||
|
||||
x y z w xxxx xxxy xxxz xxxw
|
||||
xxyx xxyy xxyz xxyw xxzx xxzy xxzz xxzw xxwx xxwy
|
||||
xxwz xxww xyxx xyxy xyxz xyxw xyyx xyyy xyyz xyyw
|
||||
xyzx xyzy xyzz xyzw xywx xywy xywz xyww xzxx xzxy
|
||||
xzxz xzxw xzyx xzyy xzyz xzyw xzzx xzzy xzzz xzzw
|
||||
xzwx xzwy xzwz xzww xwxx xwxy xwxz xwxw xwyx xwyy
|
||||
xwyz xwyw xwzx xwzy xwzz xwzw xwwx xwwy xwwz xwww
|
||||
yxxx yxxy yxxz yxxw yxyx yxyy yxyz yxyw yxzx yxzy
|
||||
yxzz yxzw yxwx yxwy yxwz yxww yyxx yyxy yyxz yyxw
|
||||
yyyx yyyy yyyz yyyw yyzx yyzy yyzz yyzw yywx yywy
|
||||
yywz yyww yzxx yzxy yzxz yzxw yzyx yzyy yzyz yzyw
|
||||
yzzx yzzy yzzz yzzw yzwx yzwy yzwz yzww ywxx ywxy
|
||||
ywxz ywxw ywyx ywyy ywyz ywyw ywzx ywzy ywzz ywzw
|
||||
ywwx ywwy ywwz ywww zxxx zxxy zxxz zxxw zxyx zxyy
|
||||
zxyz zxyw zxzx zxzy zxzz zxzw zxwx zxwy zxwz zxww
|
||||
zyxx zyxy zyxz zyxw zyyx zyyy zyyz zyyw zyzx zyzy
|
||||
zyzz zyzw zywx zywy zywz zyww zzxx zzxy zzxz zzxw
|
||||
zzyx zzyy zzyz zzyw zzzx zzzy zzzz zzzw zzwx zzwy
|
||||
zzwz zzww zwxx zwxy zwxz zwxw zwyx zwyy zwyz zwyw
|
||||
zwzx zwzy zwzz zwzw zwwx zwwy zwwz zwww wxxx wxxy
|
||||
wxxz wxxw wxyx wxyy wxyz wxyw wxzx wxzy wxzz wxzw
|
||||
wxwx wxwy wxwz wxww wyxx wyxy wyxz wyxw wyyx wyyy
|
||||
wyyz wyyw wyzx wyzy wyzz wyzw wywx wywy wywz wyww
|
||||
wzxx wzxy wzxz wzxw wzyx wzyy wzyz wzyw wzzx wzzy
|
||||
wzzz wzzw wzwx wzwy wzwz wzww wwxx wwxy wwxz wwxw
|
||||
wwyx wwyy wwyz wwyw wwzx wwzy wwzz wwzw wwwx wwwy
|
||||
wwwz wwww xy xz yz xyz xw yw xyw zw
|
||||
xzw yzw xyzw ]],
|
||||
|
||||
},
|
||||
}
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
-- unfortunately no good lexer
|
||||
-- ASM comments start with ;
|
||||
-- and TCL doesnt allow coloring
|
||||
-- behind keywords
|
||||
|
||||
exts = {"glp","vp","fp"},
|
||||
lexer = wxstc.wxSTC_LEX_TCL,
|
||||
--apitype = "cg",
|
||||
linecomment = "#",
|
||||
lexerstyleconvert = {
|
||||
text = {4,5,7,8,9,10,11,
|
||||
},
|
||||
|
||||
lexerdef = {0,},
|
||||
comment = {1,2,20,21,
|
||||
},
|
||||
--stringtxt = {wxstc.wxSTC_SQL_STRING,
|
||||
-- wxstc.wxSTC_SQL_CHARACTER,
|
||||
-- },
|
||||
--stringeol = {wxstc.wxSTC_SQL_STRINGEOL,},
|
||||
--preprocessor= {,},
|
||||
operator = {6,},
|
||||
number = {3,
|
||||
},
|
||||
|
||||
keywords0 = {12,},
|
||||
keywords1 = {13,},
|
||||
keywords2 = {14,},
|
||||
keywords3 = {15,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[EMIT ENDPRIM
|
||||
ABS ADD AND BRK CAL CEIL CMP CONT COS DIV DP2 DP2A DP3 DP4 DPH DST ELSE
|
||||
ENDIF ENDREP EX2 FLR FRC I2F IF KIL LG2 LIT LRP MAD MAX MIN MOD MOV MUL
|
||||
NOT NRM OR PK2H PK2US PK4B PK4UB POW RCC RCP REP RET RFL ROUND RSQ SAD
|
||||
SCS SEQ SFL SGE SGT SHL SHR SIN SLE SLT SNE SSG STR SUB SWZ TEX TRUNC LOOP
|
||||
TXB TXD TXF TXL TXP TXQ UP2H UP2US UP4B UP4UB X2D XOR XPD REP.S REP.F REP.U
|
||||
ENDLOOP SUBROUTINENUM CALI
|
||||
|
||||
ABS_SAT ADD_SAT CEIL_SAT CMP_SAT COS_SAT DIV_SAT DP2_SAT DP2A_SAT DP3_SAT
|
||||
DP4_SAT DPH_SAT DST_SAT EX2_SAT FLR_SAT FRC_SAT LG2_SAT LIT_SAT LRP_SAT
|
||||
MAD_SAT MAX_SAT MIN_SAT MOV_SAT MUL_SAT NRM_SAT POW_SAT RCC_SAT RCP_SAT
|
||||
RFL_SAT ROUND_SAT RSQ_SAT SCS_SAT SEQ_SAT SFL_SAT SGE_SAT SGT_SAT SIN_SAT
|
||||
SLE_SAT SLT_SAT SNE_SAT SSG_SAT STR_SAT SUB_SAT SWZ_SAT TEX_SAT TRUNC_SAT
|
||||
TXB_SAT TXD_SAT TXF_SAT TXL_SAT TXP_SAT UP2H_SAT UP2US_SAT UP4B_SAT UP4UB_SAT
|
||||
X2D_SAT XPD_SAT
|
||||
|
||||
]],
|
||||
[[
|
||||
|
||||
ATTRIB PARAM TEMP ADDRESS OUTPUT ALIAS OPTION TEXTURE
|
||||
PRIMITIVE_IN PRIMITIVE_OUT VERTICES_OUT POINTS LINES LINES_ADJACENCY
|
||||
TRIANGLES TRIANGLES_ADJACENCY
|
||||
LINE_STRIP TRIANGLE_STRIP
|
||||
EQ GE GT LE LT NE TR FL EQ0 GE0 GT0 LE0 LT0 NE0 TR0 FL0 EQ1 GE1 GT1 LE1 LT1
|
||||
NE1 TR1 FL1 NAN NAN0 NAN1 LEG LEG0 LEG1 CF CF0 CF1 NCF NCF0 NCF1 OF OF0 OF1
|
||||
NOF NOF0 NOF1 AB AB0 AB1 BLE BLE0 BLE1 SF SF0 SF1 NSF NSF0 NSF1
|
||||
END SUBROUTINETYPE SUBROUTINE
|
||||
|
||||
]],
|
||||
[[
|
||||
|
||||
vertex position weight normal color primary secondary fogcoord texcoord
|
||||
matrixindex attrib
|
||||
program env local fragment
|
||||
state material ambient diffuse specular emission shininess front back
|
||||
light attenuation spot direction half
|
||||
lightmodel scene lightprod
|
||||
texgen eye object s t r q
|
||||
fog params
|
||||
clip plane
|
||||
point size attenuation
|
||||
matrix modelview projection mvp texture palette row transpose inverse invtrans
|
||||
result pointsize 1D 2D 3D CUBE RECT
|
||||
|
||||
]],
|
||||
[[
|
||||
|
||||
x y z w xxxx xxxy xxxz xxxw
|
||||
xxyx xxyy xxyz xxyw xxzx xxzy xxzz xxzw xxwx xxwy
|
||||
xxwz xxww xyxx xyxy xyxz xyxw xyyx xyyy xyyz xyyw
|
||||
xyzx xyzy xyzz xyzw xywx xywy xywz xyww xzxx xzxy
|
||||
xzxz xzxw xzyx xzyy xzyz xzyw xzzx xzzy xzzz xzzw
|
||||
xzwx xzwy xzwz xzww xwxx xwxy xwxz xwxw xwyx xwyy
|
||||
xwyz xwyw xwzx xwzy xwzz xwzw xwwx xwwy xwwz xwww
|
||||
yxxx yxxy yxxz yxxw yxyx yxyy yxyz yxyw yxzx yxzy
|
||||
yxzz yxzw yxwx yxwy yxwz yxww yyxx yyxy yyxz yyxw
|
||||
yyyx yyyy yyyz yyyw yyzx yyzy yyzz yyzw yywx yywy
|
||||
yywz yyww yzxx yzxy yzxz yzxw yzyx yzyy yzyz yzyw
|
||||
yzzx yzzy yzzz yzzw yzwx yzwy yzwz yzww ywxx ywxy
|
||||
ywxz ywxw ywyx ywyy ywyz ywyw ywzx ywzy ywzz ywzw
|
||||
ywwx ywwy ywwz ywww zxxx zxxy zxxz zxxw zxyx zxyy
|
||||
zxyz zxyw zxzx zxzy zxzz zxzw zxwx zxwy zxwz zxww
|
||||
zyxx zyxy zyxz zyxw zyyx zyyy zyyz zyyw zyzx zyzy
|
||||
zyzz zyzw zywx zywy zywz zyww zzxx zzxy zzxz zzxw
|
||||
zzyx zzyy zzyz zzyw zzzx zzzy zzzz zzzw zzwx zzwy
|
||||
zzwz zzww zwxx zwxy zwxz zwxw zwyx zwyy zwyz zwyw
|
||||
zwzx zwzy zwzz zwzw zwwx zwwy zwwz zwww wxxx wxxy
|
||||
wxxz wxxw wxyx wxyy wxyz wxyw wxzx wxzy wxzz wxzw
|
||||
wxwx wxwy wxwz wxww wyxx wyxy wyxz wyxw wyyx wyyy
|
||||
wyyz wyyw wyzx wyzy wyzz wyzw wywx wywy wywz wyww
|
||||
wzxx wzxy wzxz wzxw wzyx wzyy wzyz wzyw wzzx wzzy
|
||||
wzzz wzzw wzwx wzwy wzwz wzww wwxx wwxy wwxz wwxw
|
||||
wwyx wwyy wwyz wwyw wwzx wwzy wwzz wwzw wwwx wwwy
|
||||
wwwz wwww xy xz yz xyz xw yw xyw zw
|
||||
xzw yzw xyzw ]],
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
355
spec/opencl.lua
@@ -4,195 +4,192 @@
|
||||
local convtypes = [[bool char uchar short ushort int uint long ulong float double]]
|
||||
local convout = {}
|
||||
for i in convtypes:gmatch("([%w_]+)") do
|
||||
local suffix = {"","_rte","_rtz","_rtp","_rtn"}
|
||||
for k,t in ipairs(suffix) do
|
||||
table.insert(convout,"convert_"..i..t)
|
||||
table.insert(convout,"convert_"..i.."_sat"..t)
|
||||
local vectors = {2,4,8,16}
|
||||
for n,v in ipairs(vectors) do
|
||||
table.insert(convout,"convert_"..i..v..t)
|
||||
table.insert(convout,"convert_"..i..v.."_sat"..t)
|
||||
end
|
||||
end
|
||||
local suffix = {"","_rte","_rtz","_rtp","_rtn"}
|
||||
for k,t in ipairs(suffix) do
|
||||
table.insert(convout,"convert_"..i..t)
|
||||
table.insert(convout,"convert_"..i.."_sat"..t)
|
||||
local vectors = {2,4,8,16}
|
||||
for n,v in ipairs(vectors) do
|
||||
table.insert(convout,"convert_"..i..v..t)
|
||||
table.insert(convout,"convert_"..i..v.."_sat"..t)
|
||||
end
|
||||
end
|
||||
end
|
||||
convout = table.concat(convout, " ")
|
||||
|
||||
local astypes = [[int uint uchar ushort float double size_t ptrdiff_t intptr_t uintptr_t
|
||||
long ulong char short unsigned
|
||||
float2 float4 float8 float16
|
||||
double2 double4 double8 double16
|
||||
char2 char4 char8 char16
|
||||
uchar2 uchar4 uchar8 uchar16
|
||||
short2 short4 short8 short16
|
||||
ushort2 ushort4 ushort8 ushort16
|
||||
int2 int4 int8 int16
|
||||
uint2 uint4 uint8 uint16
|
||||
long2 long4 long8 long16
|
||||
ulong2 ulong4 ulong8 ulong16]]
|
||||
long ulong char short unsigned
|
||||
float2 float4 float8 float16
|
||||
double2 double4 double8 double16
|
||||
char2 char4 char8 char16
|
||||
uchar2 uchar4 uchar8 uchar16
|
||||
short2 short4 short8 short16
|
||||
ushort2 ushort4 ushort8 ushort16
|
||||
int2 int4 int8 int16
|
||||
uint2 uint4 uint8 uint16
|
||||
long2 long4 long8 long16
|
||||
ulong2 ulong4 ulong8 ulong16]]
|
||||
|
||||
local astypeout = {}
|
||||
for i in astypes:gmatch("([%w_]+)") do
|
||||
table.insert(astypeout, "as_"..i)
|
||||
table.insert(astypeout, "as_"..i)
|
||||
end
|
||||
astypeout = table.concat(astypeout, " ")
|
||||
|
||||
return {
|
||||
exts = {"cl","ocl","clh",},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "opencl",
|
||||
sep = "%.",
|
||||
linecomment = "//",
|
||||
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
|
||||
end
|
||||
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[int uint uchar ushort float double size_t ptrdiff_t intptr_t uintptr_t
|
||||
long ulong char short unsigned
|
||||
|
||||
float2 float4 float8 float16
|
||||
double2 double4 double8 double16
|
||||
char2 char4 char8 char16
|
||||
uchar2 uchar4 uchar8 uchar16
|
||||
short2 short4 short8 short16
|
||||
ushort2 ushort4 ushort8 ushort16
|
||||
int2 int4 int8 int16
|
||||
uint2 uint4 uint8 uint16
|
||||
long2 long4 long8 long16
|
||||
ulong2 ulong4 ulong8 ulong16
|
||||
|
||||
half2 half4 half8 half16
|
||||
void half bool
|
||||
image2d_t image3d_t sampler_t event_t cl_image_format
|
||||
|
||||
struct typedef void const inline
|
||||
return switch case for do while if else break continue volatile
|
||||
CLK_A CLK_R CLK_RG CLK_RGB CLK_RGBA CLK_ARGB CLK_BGRA CLK_INTENSITY CLK_LUMINANCE
|
||||
|
||||
MAXFLOAT HUGE_VALF INFINITY NAN
|
||||
CLK_LOCAL_MEM_FENCE CLK_GLOBAL_MEM_FENCE
|
||||
CLK_SNORM_INT8
|
||||
CLK_SNORM_INT16
|
||||
CLK_UNORM_INT8
|
||||
CLK_UNORM_INT16
|
||||
CLK_UNORM_SHORT_565
|
||||
CLK_UNORM_SHORT_555
|
||||
CLK_UNORM_SHORT_101010
|
||||
CLK_SIGNED_INT8
|
||||
CLK_SIGNED_INT16
|
||||
CLK_SIGNED_INT32
|
||||
CLK_UNSIGNED_INT8
|
||||
CLK_UNSIGNED_INT16
|
||||
CLK_UNSIGNED_INT32
|
||||
CLK_HALF_FLOAT
|
||||
CLK_FLOAT
|
||||
__FILE__ __LINE__ __OPENCL_VERSION__ __ENDIAN_LITTLE__
|
||||
__ROUNDING_MODE__ __IMAGE_SUPPORT__ __FAST_RELAXED_MATH__
|
||||
]],
|
||||
exts = {"cl","ocl","clh",},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "opencl",
|
||||
sep = "%.",
|
||||
linecomment = "//",
|
||||
|
||||
[[__kernel kernel __attribute__ __read_only __write_only read_only write_only
|
||||
__constant constant __local local __global global __private private
|
||||
vec_type_hint work_group_size_hint reqd_work_group_size
|
||||
aligned packed endian host device
|
||||
|
||||
async_work_group_copy wait_group_events prefetch
|
||||
clamp min max degrees radians sign smoothstep step mix
|
||||
mem_fence read_mem_fence write_mem_fence
|
||||
cross prod distance dot length normalize fast_distance fast_length fast_normalize
|
||||
get_image_width get_image_height get_image_depth
|
||||
get_image_channel_data_type get_image_channel_order
|
||||
get_image_dim
|
||||
abs abs_diff add_sat clz hadd mad24 mad_hi mad_sat
|
||||
mul24 mul_hi rhadd rotate sub_sat upsample
|
||||
read_imagei write_imagei read_imageui write_imageui
|
||||
read_imagef write_imagef
|
||||
|
||||
isequal isnotequal isgreater isgreaterequal isless islessequal islessgreater
|
||||
isfinite isinf isnan isnormal isordered isunordered signbit any all bitselect select
|
||||
|
||||
acos acosh acospi asin asinh asinpi atan atan2 atanh atanpi atan2pi
|
||||
cbrt ceil copysign cos half_cos native_cos cosh cospi half_divide native_divide
|
||||
erf erfc exp half_exp native_exp exp2 half_exp2 native_exp2 exp10 half_exp10 native_exp10
|
||||
expm1 fabs fdim floor fma fmax fmin fmod fract frexp hypot ilogb
|
||||
ldexp lgamma lgamma_r log half_log native_log log2 half_log2 native_log2
|
||||
log10 half_log10 native_log10 log1p logb mad modf nan nextafter
|
||||
pow pown powr half_powr native_powr half_recip native_recip
|
||||
remainder remquo rint round rootn rsqrt half_rsqrt native_rsqrt
|
||||
sin half_sin native_sin sincos sinh sinpi sqrt half_sqrt native_sqrt
|
||||
tan half_tan native_tan tanh tanpi tgamma trunc
|
||||
|
||||
barrier
|
||||
vload2 vload4 vload8 vload16
|
||||
vload_half vload_half2 vload_half4 vload_half8 vload_half16 vloada_half4 vloada_half8 vloada_half16
|
||||
vstore2 vstore4 vstore8 vstore16
|
||||
vstore_half vstore_half2 vstore_half4 vstore_half8 vstore_half16 vstorea_half4 vstorea_half8 vstorea_half16
|
||||
get_global_id get_global_size get_group_id get_local_id get_local_size get_num_groups get_work_dim
|
||||
|
||||
|
||||
|
||||
x y z w
|
||||
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy
|
||||
xxzz xxzw xxwx xxwy xxwz xxww xyxx xyxy xyxz xyxw
|
||||
xyyx xyyy xyyz xyyw xyzx xyzy xyzz xyzw xywx xywy
|
||||
xywz xyww xzxx xzxy xzxz xzxw xzyx xzyy xzyz xzyw
|
||||
xzzx xzzy xzzz xzzw xzwx xzwy xzwz xzww xwxx xwxy
|
||||
xwxz xwxw xwyx xwyy xwyz xwyw xwzx xwzy xwzz xwzw
|
||||
xwwx xwwy xwwz xwww yxxx yxxy yxxz yxxw yxyx yxyy
|
||||
yxyz yxyw yxzx yxzy yxzz yxzw yxwx yxwy yxwz yxww
|
||||
yyxx yyxy yyxz yyxw yyyx yyyy yyyz yyyw yyzx yyzy
|
||||
yyzz yyzw yywx yywy yywz yyww yzxx yzxy yzxz yzxw
|
||||
yzyx yzyy yzyz yzyw yzzx yzzy yzzz yzzw yzwx yzwy
|
||||
yzwz yzww ywxx ywxy ywxz ywxw ywyx ywyy ywyz ywyw
|
||||
ywzx ywzy ywzz ywzw ywwx ywwy ywwz ywww zxxx zxxy
|
||||
zxxz zxxw zxyx zxyy zxyz zxyw zxzx zxzy zxzz zxzw
|
||||
zxwx zxwy zxwz zxww zyxx zyxy zyxz zyxw zyyx zyyy
|
||||
zyyz zyyw zyzx zyzy zyzz zyzw zywx zywy zywz zyww
|
||||
zzxx zzxy zzxz zzxw zzyx zzyy zzyz zzyw zzzx zzzy
|
||||
zzzz zzzw zzwx zzwy zzwz zzww zwxx zwxy zwxz zwxw
|
||||
zwyx zwyy zwyz zwyw zwzx zwzy zwzz zwzw zwwx zwwy
|
||||
zwwz zwww wxxx wxxy wxxz wxxw wxyx wxyy wxyz wxyw
|
||||
wxzx wxzy wxzz wxzw wxwx wxwy wxwz wxww wyxx wyxy
|
||||
wyxz wyxw wyyx wyyy wyyz wyyw wyzx wyzy wyzz wyzw
|
||||
wywx wywy wywz wyww wzxx wzxy wzxz wzxw wzyx wzyy
|
||||
wzyz wzyw wzzx wzzy wzzz wzzw wzwx wzwy wzwz wzww
|
||||
wwxx wwxy wwxz wwxw wwyx wwyy wwyz wwyw wwzx wwzy
|
||||
wwzz wwzw wwwx wwwy wwwz wwww xy xz yz xyz
|
||||
xw yw xyw zw xzw yzw xyzw ]]..convout.." "..astypeout,
|
||||
isfndef = function(str)
|
||||
local l
|
||||
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
|
||||
if (not s) then
|
||||
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
|
||||
end
|
||||
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
|
||||
return s,e,cap,l
|
||||
end,
|
||||
|
||||
},
|
||||
}
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[int uint uchar ushort float double size_t ptrdiff_t intptr_t uintptr_t
|
||||
long ulong char short unsigned
|
||||
|
||||
float2 float4 float8 float16
|
||||
double2 double4 double8 double16
|
||||
char2 char4 char8 char16
|
||||
uchar2 uchar4 uchar8 uchar16
|
||||
short2 short4 short8 short16
|
||||
ushort2 ushort4 ushort8 ushort16
|
||||
int2 int4 int8 int16
|
||||
uint2 uint4 uint8 uint16
|
||||
long2 long4 long8 long16
|
||||
ulong2 ulong4 ulong8 ulong16
|
||||
|
||||
half2 half4 half8 half16
|
||||
void half bool
|
||||
image2d_t image3d_t sampler_t event_t cl_image_format
|
||||
|
||||
struct typedef void const inline
|
||||
return switch case for do while if else break continue volatile
|
||||
CLK_A CLK_R CLK_RG CLK_RGB CLK_RGBA CLK_ARGB CLK_BGRA CLK_INTENSITY CLK_LUMINANCE
|
||||
|
||||
MAXFLOAT HUGE_VALF INFINITY NAN
|
||||
CLK_LOCAL_MEM_FENCE CLK_GLOBAL_MEM_FENCE
|
||||
CLK_SNORM_INT8
|
||||
CLK_SNORM_INT16
|
||||
CLK_UNORM_INT8
|
||||
CLK_UNORM_INT16
|
||||
CLK_UNORM_SHORT_565
|
||||
CLK_UNORM_SHORT_555
|
||||
CLK_UNORM_SHORT_101010
|
||||
CLK_SIGNED_INT8
|
||||
CLK_SIGNED_INT16
|
||||
CLK_SIGNED_INT32
|
||||
CLK_UNSIGNED_INT8
|
||||
CLK_UNSIGNED_INT16
|
||||
CLK_UNSIGNED_INT32
|
||||
CLK_HALF_FLOAT
|
||||
CLK_FLOAT
|
||||
__FILE__ __LINE__ __OPENCL_VERSION__ __ENDIAN_LITTLE__
|
||||
__ROUNDING_MODE__ __IMAGE_SUPPORT__ __FAST_RELAXED_MATH__
|
||||
]],
|
||||
|
||||
[[__kernel kernel __attribute__ __read_only __write_only read_only write_only
|
||||
__constant constant __local local __global global __private private
|
||||
vec_type_hint work_group_size_hint reqd_work_group_size
|
||||
aligned packed endian host device
|
||||
|
||||
async_work_group_copy wait_group_events prefetch
|
||||
clamp min max degrees radians sign smoothstep step mix
|
||||
mem_fence read_mem_fence write_mem_fence
|
||||
cross prod distance dot length normalize fast_distance fast_length fast_normalize
|
||||
get_image_width get_image_height get_image_depth
|
||||
get_image_channel_data_type get_image_channel_order
|
||||
get_image_dim
|
||||
abs abs_diff add_sat clz hadd mad24 mad_hi mad_sat
|
||||
mul24 mul_hi rhadd rotate sub_sat upsample
|
||||
read_imagei write_imagei read_imageui write_imageui
|
||||
read_imagef write_imagef
|
||||
|
||||
isequal isnotequal isgreater isgreaterequal isless islessequal islessgreater
|
||||
isfinite isinf isnan isnormal isordered isunordered signbit any all bitselect select
|
||||
|
||||
acos acosh acospi asin asinh asinpi atan atan2 atanh atanpi atan2pi
|
||||
cbrt ceil copysign cos half_cos native_cos cosh cospi half_divide native_divide
|
||||
erf erfc exp half_exp native_exp exp2 half_exp2 native_exp2 exp10 half_exp10 native_exp10
|
||||
expm1 fabs fdim floor fma fmax fmin fmod fract frexp hypot ilogb
|
||||
ldexp lgamma lgamma_r log half_log native_log log2 half_log2 native_log2
|
||||
log10 half_log10 native_log10 log1p logb mad modf nan nextafter
|
||||
pow pown powr half_powr native_powr half_recip native_recip
|
||||
remainder remquo rint round rootn rsqrt half_rsqrt native_rsqrt
|
||||
sin half_sin native_sin sincos sinh sinpi sqrt half_sqrt native_sqrt
|
||||
tan half_tan native_tan tanh tanpi tgamma trunc
|
||||
|
||||
barrier
|
||||
vload2 vload4 vload8 vload16
|
||||
vload_half vload_half2 vload_half4 vload_half8 vload_half16 vloada_half4 vloada_half8 vloada_half16
|
||||
vstore2 vstore4 vstore8 vstore16
|
||||
vstore_half vstore_half2 vstore_half4 vstore_half8 vstore_half16 vstorea_half4 vstorea_half8 vstorea_half16
|
||||
get_global_id get_global_size get_group_id get_local_id get_local_size get_num_groups get_work_dim
|
||||
|
||||
x y z w
|
||||
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy
|
||||
xxzz xxzw xxwx xxwy xxwz xxww xyxx xyxy xyxz xyxw
|
||||
xyyx xyyy xyyz xyyw xyzx xyzy xyzz xyzw xywx xywy
|
||||
xywz xyww xzxx xzxy xzxz xzxw xzyx xzyy xzyz xzyw
|
||||
xzzx xzzy xzzz xzzw xzwx xzwy xzwz xzww xwxx xwxy
|
||||
xwxz xwxw xwyx xwyy xwyz xwyw xwzx xwzy xwzz xwzw
|
||||
xwwx xwwy xwwz xwww yxxx yxxy yxxz yxxw yxyx yxyy
|
||||
yxyz yxyw yxzx yxzy yxzz yxzw yxwx yxwy yxwz yxww
|
||||
yyxx yyxy yyxz yyxw yyyx yyyy yyyz yyyw yyzx yyzy
|
||||
yyzz yyzw yywx yywy yywz yyww yzxx yzxy yzxz yzxw
|
||||
yzyx yzyy yzyz yzyw yzzx yzzy yzzz yzzw yzwx yzwy
|
||||
yzwz yzww ywxx ywxy ywxz ywxw ywyx ywyy ywyz ywyw
|
||||
ywzx ywzy ywzz ywzw ywwx ywwy ywwz ywww zxxx zxxy
|
||||
zxxz zxxw zxyx zxyy zxyz zxyw zxzx zxzy zxzz zxzw
|
||||
zxwx zxwy zxwz zxww zyxx zyxy zyxz zyxw zyyx zyyy
|
||||
zyyz zyyw zyzx zyzy zyzz zyzw zywx zywy zywz zyww
|
||||
zzxx zzxy zzxz zzxw zzyx zzyy zzyz zzyw zzzx zzzy
|
||||
zzzz zzzw zzwx zzwy zzwz zzww zwxx zwxy zwxz zwxw
|
||||
zwyx zwyy zwyz zwyw zwzx zwzy zwzz zwzw zwwx zwwy
|
||||
zwwz zwww wxxx wxxy wxxz wxxw wxyx wxyy wxyz wxyw
|
||||
wxzx wxzy wxzz wxzw wxwx wxwy wxwz wxww wyxx wyxy
|
||||
wyxz wyxw wyyx wyyy wyyz wyyw wyzx wyzy wyzz wyzw
|
||||
wywx wywy wywz wyww wzxx wzxy wzxz wzxw wzyx wzyy
|
||||
wzyz wzyw wzzx wzzy wzzz wzzw wzwx wzwy wzwz wzww
|
||||
wwxx wwxy wwxz wwxw wwyx wwyy wwyz wwyw wwzx wwzy
|
||||
wwzz wwzw wwwx wwwy wwwz wwww xy xz yz xyz
|
||||
xw yw xyw zw xzw yzw xyzw ]]..convout.." "..astypeout,
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
155
spec/sql.lua
@@ -2,87 +2,86 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"sql"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "sql",
|
||||
linecomment = "--",
|
||||
isfncall = function(str)
|
||||
return string.find(str,"([A-Za-z0-9_]+)%s*%(")
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_LUA_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_LUA_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_LUA_COMMENT,
|
||||
wxstc.wxSTC_LUA_COMMENTLINE,
|
||||
wxstc.wxSTC_LUA_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_LUA_STRING,
|
||||
wxstc.wxSTC_LUA_CHARACTER,
|
||||
wxstc.wxSTC_LUA_LITERALSTRING,},
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_LUA_OPERATOR,},
|
||||
number = {wxstc.wxSTC_LUA_NUMBER,},
|
||||
|
||||
|
||||
keywords0 = {wxstc.wxSTC_LUA_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_LUA_WORD2,},
|
||||
keywords2 = {wxstc.wxSTC_LUA_WORD3,},
|
||||
keywords3 = {wxstc.wxSTC_LUA_WORD4,},
|
||||
keywords4 = {wxstc.wxSTC_LUA_WORD5,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[ SELECT FROM CREATE TABLE WHERE ORDER BY CASE
|
||||
WHEN CHECK CONSTRAINT PRIMARY AUTOINCREMENT
|
||||
INSERT INTO DELETE DROP DISTINCT GROUP IS DEFAULT
|
||||
BEGIN TRANSACTION COMMIT KEY REFERENCES UNIQUE INDEX ON SET RESTRICT
|
||||
CASCADE ]],
|
||||
-- javascript keywords
|
||||
[[ NULL]],
|
||||
[[ TEXT BOOLEAN INTEGER]]
|
||||
},
|
||||
exts = {"sql"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "sql",
|
||||
linecomment = "--",
|
||||
isfncall = function(str)
|
||||
return string.find(str,"([A-Za-z0-9_]+)%s*%(")
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_LUA_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_LUA_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_LUA_COMMENT,
|
||||
wxstc.wxSTC_LUA_COMMENTLINE,
|
||||
wxstc.wxSTC_LUA_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_LUA_STRING,
|
||||
wxstc.wxSTC_LUA_CHARACTER,
|
||||
wxstc.wxSTC_LUA_LITERALSTRING,},
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_LUA_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_LUA_OPERATOR,},
|
||||
number = {wxstc.wxSTC_LUA_NUMBER,},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_LUA_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_LUA_WORD2,},
|
||||
keywords2 = {wxstc.wxSTC_LUA_WORD3,},
|
||||
keywords3 = {wxstc.wxSTC_LUA_WORD4,},
|
||||
keywords4 = {wxstc.wxSTC_LUA_WORD5,},
|
||||
keywords5 = {wxstc.wxSTC_LUA_WORD6,},
|
||||
keywords6 = {wxstc.wxSTC_LUA_WORD7,},
|
||||
keywords7 = {wxstc.wxSTC_LUA_WORD8,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[ SELECT FROM CREATE TABLE WHERE ORDER BY CASE
|
||||
WHEN CHECK CONSTRAINT PRIMARY AUTOINCREMENT
|
||||
INSERT INTO DELETE DROP DISTINCT GROUP IS DEFAULT
|
||||
BEGIN TRANSACTION COMMIT KEY REFERENCES UNIQUE INDEX ON SET RESTRICT
|
||||
CASCADE ]],
|
||||
-- javascript keywords
|
||||
[[ NULL]],
|
||||
[[ TEXT BOOLEAN INTEGER]]
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
--[==[return {
|
||||
exts = {"sql"},
|
||||
lexer = wxstc.wxSTC_LEX_SQL,
|
||||
apitype = "sql",
|
||||
linecomment = "--",
|
||||
stylingbits = 5,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wx.wxSTC_SQL_DEFAULT},
|
||||
comment = {wx.wxSTC_SQL_COMMENT,wx.wxSTC_SQL_COMMENTLINE},
|
||||
stringeol = {},
|
||||
number = {wx.wxSTC_SQL_NUMBER},
|
||||
stringtxt = {},
|
||||
lexerdef= {},
|
||||
keywords0 = {wx.wxSTC_SQL_IDENTIFIER, wx.wxSTC_SQL_QUOTEDIDENTIFIER},
|
||||
keywords1 = {wx.wxSTC_SQL_STRING},
|
||||
keywords2 = {wx.wxSTC_SQL_COMMENTDOC,wx.wxSTC_SQL_COMMENTDOCKEYWORD},
|
||||
keywords3 = {wx.wxSTC_SQL_COMMENTDOCKEYWORDERROR,wx.wxSTC_SQL_COMMENTLINEDOC},
|
||||
keywords4 = {wx.wxSTC_SQL_WORD,wx.wxSTC_SQL_WORD2,},
|
||||
keywords5 = {wx.wxSTC_SQL_USER1,wx.wxSTC_SQL_USER2,wx.wxSTC_SQL_USER3,wx.wxSTC_SQL_USER4},
|
||||
keywords6 = {},
|
||||
keywords7 = {},
|
||||
preprocessor= {},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
-- HTML tags and attributes
|
||||
[[ SELECT FROM CREATE TABLE WHERE ORDER BY CASE
|
||||
WHEN CHECK CONSTRAINT PRIMARY INTEGER AUTOINCREMENT
|
||||
INSERT INTO DELETE DROP DISTINCT GROUP IS DEFAULT]],
|
||||
-- javascript keywords
|
||||
[[ NULL]]
|
||||
},
|
||||
--[==[
|
||||
return {
|
||||
exts = {"sql"},
|
||||
lexer = wxstc.wxSTC_LEX_SQL,
|
||||
apitype = "sql",
|
||||
linecomment = "--",
|
||||
stylingbits = 5,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wx.wxSTC_SQL_DEFAULT},
|
||||
comment = {wx.wxSTC_SQL_COMMENT,wx.wxSTC_SQL_COMMENTLINE},
|
||||
stringeol = {},
|
||||
number = {wx.wxSTC_SQL_NUMBER},
|
||||
stringtxt = {},
|
||||
lexerdef= {},
|
||||
keywords0 = {wx.wxSTC_SQL_IDENTIFIER, wx.wxSTC_SQL_QUOTEDIDENTIFIER},
|
||||
keywords1 = {wx.wxSTC_SQL_STRING},
|
||||
keywords2 = {wx.wxSTC_SQL_COMMENTDOC,wx.wxSTC_SQL_COMMENTDOCKEYWORD},
|
||||
keywords3 = {wx.wxSTC_SQL_COMMENTDOCKEYWORDERROR,wx.wxSTC_SQL_COMMENTLINEDOC},
|
||||
keywords4 = {wx.wxSTC_SQL_WORD,wx.wxSTC_SQL_WORD2,},
|
||||
keywords5 = {wx.wxSTC_SQL_USER1,wx.wxSTC_SQL_USER2,wx.wxSTC_SQL_USER3,wx.wxSTC_SQL_USER4},
|
||||
keywords6 = {},
|
||||
keywords7 = {},
|
||||
preprocessor= {},
|
||||
},
|
||||
|
||||
}]==]
|
||||
keywords = {
|
||||
-- HTML tags and attributes
|
||||
[[ SELECT FROM CREATE TABLE WHERE ORDER BY CASE
|
||||
WHEN CHECK CONSTRAINT PRIMARY INTEGER AUTOINCREMENT
|
||||
INSERT INTO DELETE DROP DISTINCT GROUP IS DEFAULT]],
|
||||
-- javascript keywords
|
||||
[[ NULL]]
|
||||
},
|
||||
|
||||
}
|
||||
]==]
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"txt"},
|
||||
--lexer = wxstc.wxSTC_LEX_POV,
|
||||
--apitype = "luxres",
|
||||
linecomment = ">",
|
||||
}
|
||||
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exts = {"txt"},
|
||||
--lexer = wxstc.wxSTC_LEX_POV,
|
||||
--apitype = "luxres",
|
||||
linecomment = ">",
|
||||
}
|
||||
|
||||
310
src/defs.lua
Normal file
@@ -0,0 +1,310 @@
|
||||
-- About
|
||||
-- ----------------------------------------------------
|
||||
-- This file contains lua table definitons used by
|
||||
-- automatic loaded files, not part of the
|
||||
-- editor source.
|
||||
--
|
||||
-- /<app>/config.lua
|
||||
-- /cfg/user.lua
|
||||
-- /interpreters/*.lua
|
||||
-- /specs/*.lua
|
||||
-- /tools/*.lua
|
||||
-- /api/<apitype>/*.lua
|
||||
|
||||
-- style definition
|
||||
-- ----------------------------------------------------
|
||||
-- all entries are optiona
|
||||
stattr = {
|
||||
fg = {r,g,b}, -- foreground color 0-255
|
||||
bg = {r,g,b}, -- background color
|
||||
i = false, -- italic
|
||||
b = false, -- bold
|
||||
u = false, -- underline
|
||||
fill = true, -- fill to lineend
|
||||
}
|
||||
|
||||
style = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = stattr,
|
||||
comment = stattr,
|
||||
stringtxt = stattr,
|
||||
stringeol = stattr,
|
||||
preprocessor = stattr,
|
||||
operator = stattr,
|
||||
number = stattr,
|
||||
|
||||
keywords0 = stattr,
|
||||
keywords1 = stattr,
|
||||
keywords2 = stattr,
|
||||
keywords3 = stattr,
|
||||
keywords4 = stattr,
|
||||
keywords5 = stattr,
|
||||
keywords6 = stattr,
|
||||
keywords7 = stattr,
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = stattr,
|
||||
linenumber = stattr,
|
||||
bracematch = stattr,
|
||||
bracemiss = stattr,
|
||||
escapechar = stattr,
|
||||
indent = stattr,
|
||||
calltip = stattr,
|
||||
|
||||
-- common special (need custom fg & bg )
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = nil,
|
||||
|
||||
-- special, functioncall indicator
|
||||
fncall = {
|
||||
fg = {r,g,b},
|
||||
st = wxstc.wxSTC_INDIC_BOX,
|
||||
},
|
||||
}
|
||||
|
||||
-- config definition
|
||||
-- ----------------------------------------------------
|
||||
-- tables must exist
|
||||
-- content is optional
|
||||
-- config is loaded into existing config table
|
||||
config = {
|
||||
appname = "estrela", -- by default the launcher name
|
||||
|
||||
path = {
|
||||
-- path for tools/interpreters
|
||||
luxinia = "C:/luxbin/",
|
||||
-- path to luxinia exe
|
||||
|
||||
projectdir = "",
|
||||
-- the project directory, used by
|
||||
-- some tools/interpreters
|
||||
},
|
||||
editor = {
|
||||
fontname = "Courier New",
|
||||
-- default font
|
||||
fontsize = 10,
|
||||
-- defailt size
|
||||
caretline = true,
|
||||
-- show active line
|
||||
|
||||
-- input/output filtering of strings
|
||||
-- current filters "GermanUtf8Ascii"
|
||||
iofilter = nil,
|
||||
|
||||
-- use indicator to show function calls
|
||||
-- if spec allows
|
||||
showfncall = true,
|
||||
|
||||
tabwidth = 4,
|
||||
usetabs = true, -- if false then spaces are used
|
||||
usewrap = true, -- if true then the text is wrapped in the editor
|
||||
whitespace = false,
|
||||
autotabs = true, -- if true test for tabs after file load,
|
||||
-- sets "usetabs" to true for this file
|
||||
},
|
||||
|
||||
debugger = {
|
||||
verbose = false,
|
||||
}
|
||||
|
||||
outputshell = {
|
||||
-- output and shell settings
|
||||
fontname = "Courier New",
|
||||
-- default font
|
||||
fontsize = 10,
|
||||
-- defult size
|
||||
}
|
||||
|
||||
styles = {},
|
||||
-- styles table as above for editor
|
||||
|
||||
stylesoutshell = {},
|
||||
-- styles for output/shell
|
||||
|
||||
interpreter = "EstrelaEditor",
|
||||
-- the default "project" lua interpreter
|
||||
|
||||
autocomplete = true,
|
||||
-- whether autocomplete is on by default
|
||||
|
||||
acandtip = {
|
||||
shorttip = false,
|
||||
-- tooltips are compact during typing
|
||||
nodynwords = false,
|
||||
-- no dynamic words (user entered words)
|
||||
ignorecase = false,
|
||||
-- ignores case when performing comparison with autocomplete list
|
||||
strategy = 0,
|
||||
-- 0: is string comparison
|
||||
-- 1: substring leading characters (camel case or _ separated)
|
||||
-- 2: leading + any correctly ordered fragments (default)
|
||||
}
|
||||
|
||||
savebak = false,
|
||||
-- if bak files are created on save
|
||||
|
||||
filehistorylength = 20,
|
||||
-- historylength for files
|
||||
|
||||
projecthistorylength = 15,
|
||||
-- historylength for project directories
|
||||
|
||||
singleinstance = true,
|
||||
-- if true creates a UDP server to exchange messages
|
||||
-- for loading commandline passed files
|
||||
|
||||
singleinstanceport = 0xe493,
|
||||
-- UDP port for single instance communication
|
||||
}
|
||||
|
||||
-- application engine
|
||||
-- ----------------------------------------------------
|
||||
|
||||
app = {
|
||||
preinit = function() end, -- post spec/tool loading, but prior subsystems/ui generation
|
||||
postinit = function() end, -- post init, prior starting mainloop
|
||||
loadfilters = {
|
||||
tools = function(file) return true end,
|
||||
specs = function(file) return true end,
|
||||
interpreters = function(file) return true end,
|
||||
}
|
||||
stringtable = { -- optional entries uses defaults otherwise
|
||||
editor = nil, statuswelcome = nil,
|
||||
-- ...
|
||||
}
|
||||
}
|
||||
|
||||
-- api definition
|
||||
-- ----------------------------------------------------
|
||||
-- hierarchy encoded into children
|
||||
|
||||
api = {
|
||||
-- global space words, e.g "table"
|
||||
["blah"] = {
|
||||
-- "function", "class", "keyword", "value", "lib"
|
||||
type = "function",
|
||||
description = "this does something",
|
||||
|
||||
-- value and function:
|
||||
valuetype = "api.ClassName",
|
||||
|
||||
-- function:
|
||||
args = "(blah,blubb)",
|
||||
returns = "(foo)",
|
||||
|
||||
-- autogenerated post load:
|
||||
-- concated hierarchy name (e.g. "lib.class")
|
||||
classname = "blah",
|
||||
|
||||
-- children in the class hierarchy
|
||||
childs = {
|
||||
--.. recursive
|
||||
}
|
||||
},
|
||||
["blubb"] = {
|
||||
--...
|
||||
},
|
||||
}
|
||||
|
||||
-- spec definition
|
||||
-- ----------------------------------------------------
|
||||
-- all entries are optional
|
||||
spec = {
|
||||
exts = {"ext","ext2",..},
|
||||
-- compatible extensions
|
||||
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
-- scintilla lexer
|
||||
|
||||
lexerstyleconvert = {
|
||||
-- table mapping each styles to
|
||||
-- appropriate lexer id
|
||||
stringeol = {wxstc.wxSTC_LUA_STRINGEOL,},
|
||||
-- ...
|
||||
}
|
||||
|
||||
linecomment = "//",
|
||||
-- string for linecomments
|
||||
|
||||
sep = "[%.:]",
|
||||
-- class.function separator match string,
|
||||
-- e.g in lua both . and : are allowed
|
||||
-- default is "\1" which should yield no matches
|
||||
-- and therefore disable class.func type autocompletion
|
||||
|
||||
isfncall = function(str) return from,to end
|
||||
-- function that detects positions for a substring that
|
||||
-- stands for a functioncall, ie " call(..)" -> 2,5
|
||||
|
||||
apitype = "api",
|
||||
-- which sub directory of "api" is relevant
|
||||
-- api files handle autocomplete and tooltips
|
||||
-- api won't affect syntax coloring
|
||||
|
||||
keywords = {
|
||||
-- up to 8 strings containing space separated keywords
|
||||
-- used by the lexer for coloring (NOT for autocomplete).
|
||||
-- however each lexer supports varying amount
|
||||
-- of keyword types
|
||||
|
||||
"foo bar word",
|
||||
"more words",
|
||||
}
|
||||
}
|
||||
|
||||
-- tool definition
|
||||
-- ----------------------------------------------------
|
||||
-- main entries are optional
|
||||
tool = {
|
||||
fninit = function(frame,menubar) end,
|
||||
-- guarantees that ide is initialized
|
||||
-- can be used for init
|
||||
-- and adding custom menu
|
||||
|
||||
exec = {
|
||||
-- quick exec action, listed under "Tools" menu
|
||||
name = "",
|
||||
description = "",
|
||||
fn = function(wxfilename,projectdir) end,
|
||||
}
|
||||
}
|
||||
|
||||
-- debuginterface definition
|
||||
-- ----------------------------------------------------
|
||||
debuginterface = {
|
||||
update = function(self) end, -- run in idle when active
|
||||
close = function(self) end, -- run when closed
|
||||
|
||||
-- following are "debugging" actions and must return
|
||||
-- error, running, [filePath, fileLine]
|
||||
run = function(self) end,
|
||||
step = function(self) end,
|
||||
over = function(self) end,
|
||||
out = function(self) end,
|
||||
terminate = function(self) end,
|
||||
breaknow = function(self) end,
|
||||
breakpoint = function(self,file,line,state) end, -- set breakpoint state
|
||||
|
||||
-- returns result table if successful
|
||||
evaluate = function(self, expressions, fnSetValues) end, -- for watches tables expected
|
||||
|
||||
-- NYI getstack = function(self, fnSetValues ) end, -- get stack information
|
||||
}
|
||||
|
||||
-- interpreter definition-- ----------------------------------------------------
|
||||
interpreter = {
|
||||
name = "",
|
||||
description = "",
|
||||
api = {"apifile_without_extension"} -- optional to limit loaded lua apis
|
||||
frun = function(self,wfilename,withdebugger)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return "projpath_from_filename" -- optional
|
||||
end,
|
||||
fattachdebug = function(self) end, -- optional
|
||||
hasdebugger = false, -- if debugging is available
|
||||
}
|
||||
@@ -1,470 +1,492 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local splitter = ide.frame.vsplitter.splitter
|
||||
local notebook = splitter.notebook
|
||||
local openDocuments = ide.openDocuments
|
||||
|
||||
function NewFile(event)
|
||||
local editor = CreateEditor("untitled.lua")
|
||||
SetupKeywords(editor, "lua")
|
||||
end
|
||||
|
||||
-- Find an editor page that hasn't been used at all, eg. an untouched NewFile()
|
||||
local function findDocumentToReuse()
|
||||
local editor = nil
|
||||
for id, document in pairs(openDocuments) do
|
||||
if (document.editor:GetLength() == 0) and
|
||||
(not document.isModified) and (not document.filePath) and
|
||||
not (document.editor:GetReadOnly() == true) then
|
||||
editor = document.editor
|
||||
break
|
||||
end
|
||||
end
|
||||
return editor
|
||||
end
|
||||
|
||||
function LoadFile(filePath, editor, file_must_exist)
|
||||
filePath = filePath:gsub("\\","/")
|
||||
|
||||
-- prevent files from being reopened again
|
||||
if (not editor) then
|
||||
for id, doc in pairs(openDocuments) do
|
||||
if doc.filePath == filePath then
|
||||
notebook:SetSelection(doc.index)
|
||||
return doc.editor
|
||||
end
|
||||
end
|
||||
end
|
||||
-- if not opened yet, try open now
|
||||
local file_text = ""
|
||||
local handle = io.open(filePath, "rb")
|
||||
if handle then
|
||||
file_text = handle:read("*a")
|
||||
if GetConfigIOFilter("input") then
|
||||
file_text = GetConfigIOFilter("input")(filePath,file_text)
|
||||
end
|
||||
handle:close()
|
||||
elseif file_must_exist then
|
||||
return nil
|
||||
end
|
||||
|
||||
if not editor then
|
||||
editor = findDocumentToReuse()
|
||||
end
|
||||
if not editor then
|
||||
editor = CreateEditor(wx.wxFileName(filePath):GetFullName() or "untitled.lua")
|
||||
end
|
||||
|
||||
editor:Clear()
|
||||
editor:ClearAll()
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
editor:MarkerDeleteAll(BREAKPOINT_MARKER)
|
||||
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
|
||||
editor:AppendText(file_text)
|
||||
if (ide.config.editor.autotabs) then
|
||||
local found = string.find(file_text,"\t") ~= nil
|
||||
editor:SetUseTabs(found)
|
||||
end
|
||||
|
||||
editor:EmptyUndoBuffer()
|
||||
local id = editor:GetId()
|
||||
openDocuments[id].filePath = filePath
|
||||
openDocuments[id].fileName = wx.wxFileName(filePath):GetFullName()
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
editor:Colourise(0, -1)
|
||||
|
||||
AddDynamicWords(editor)
|
||||
IndicateFunctions(editor)
|
||||
|
||||
SettingsAppendFileToHistory(filePath)
|
||||
|
||||
return editor
|
||||
end
|
||||
|
||||
local function getExtsString()
|
||||
local knownexts = ""
|
||||
for i,spec in pairs(ide.specs) do
|
||||
if (spec.exts) then
|
||||
for n,ext in ipairs(spec.exts) do
|
||||
knownexts = knownexts.."*."..ext..";"
|
||||
end
|
||||
end
|
||||
end
|
||||
knownexts = knownexts:len() > 0 and knownexts:sub(1,-2) or nil
|
||||
|
||||
local exts = knownexts and "Known Files ("..knownexts..")|"..knownexts.."|" or ""
|
||||
exts = exts.."All files (*)|*"
|
||||
|
||||
return exts
|
||||
end
|
||||
|
||||
function OpenFile(event)
|
||||
|
||||
local exts = getExtsString()
|
||||
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, "Open file",
|
||||
"",
|
||||
"",
|
||||
exts,
|
||||
wx.wxOPEN + wx.wxFILE_MUST_EXIST)
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
if not LoadFile(fileDialog:GetPath(), nil, true) then
|
||||
wx.wxMessageBox("Unable to load file '"..fileDialog:GetPath().."'.",
|
||||
"wxLua Error",
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
end
|
||||
end
|
||||
fileDialog:Destroy()
|
||||
end
|
||||
|
||||
-- save the file to filePath or if filePath is nil then call SaveFileAs
|
||||
function SaveFile(editor, filePath)
|
||||
if not filePath then
|
||||
return SaveFileAs(editor)
|
||||
else
|
||||
filePath = filePath:gsub("\\","/")
|
||||
|
||||
if (ide.config.savebak) then
|
||||
local backPath = filePath..".bak"
|
||||
os.remove(backPath)
|
||||
os.rename(filePath, backPath)
|
||||
end
|
||||
|
||||
local handle = io.open(filePath, "wb")
|
||||
if handle then
|
||||
local st = editor:GetText()
|
||||
|
||||
if GetConfigIOFilter("output") then
|
||||
st = GetConfigIOFilter("output")(filePath,st)
|
||||
end
|
||||
handle:write(st)
|
||||
handle:close()
|
||||
--editor:EmptyUndoBuffer()
|
||||
editor:SetSavePoint()
|
||||
local id = editor:GetId()
|
||||
openDocuments[id].filePath = filePath
|
||||
openDocuments[id].fileName = wx.wxFileName(filePath):GetFullName()
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
return true
|
||||
else
|
||||
wx.wxMessageBox("Unable to save file '"..filePath.."'.",
|
||||
"wxLua Error Saving",
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SaveFileAs(editor)
|
||||
local id = editor:GetId()
|
||||
local saved = false
|
||||
local filePath = openDocuments[id].filePath
|
||||
if (not filePath) then
|
||||
filePath = GetFileTreeDir()
|
||||
filePath = (filePath or "").."untitled"
|
||||
end
|
||||
|
||||
local fn = wx.wxFileName(filePath)
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
local exts = getExtsString()
|
||||
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, "Save file as",
|
||||
fn:GetPath(wx.wxPATH_GET_VOLUME),
|
||||
fn:GetFullName(),
|
||||
exts,
|
||||
wx.wxSAVE)
|
||||
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
local filePath = fileDialog:GetPath()
|
||||
|
||||
if SaveFile(editor, filePath) then
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
IndicateFunctions(editor)
|
||||
saved = true
|
||||
end
|
||||
end
|
||||
|
||||
fileDialog:Destroy()
|
||||
return saved
|
||||
end
|
||||
|
||||
function SaveAll()
|
||||
for id, document in pairs(openDocuments) do
|
||||
local editor = document.editor
|
||||
local filePath = document.filePath
|
||||
|
||||
if document.isModified then
|
||||
SaveFile(editor, filePath) -- will call SaveFileAs if necessary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function RemovePage(index)
|
||||
local prevIndex = nil
|
||||
local nextIndex = nil
|
||||
--local newOpenDocuments = {}
|
||||
|
||||
local delid = nil
|
||||
for id, document in pairs(openDocuments) do
|
||||
if document.index < index then
|
||||
--newOpenDocuments[id] = document
|
||||
prevIndex = document.index
|
||||
elseif document.index == index then
|
||||
delid = id
|
||||
document.editor:Destroy()
|
||||
elseif document.index > index then
|
||||
document.index = document.index - 1
|
||||
if nextIndex == nil then
|
||||
nextIndex = document.index
|
||||
end
|
||||
--newOpenDocuments[id] = document
|
||||
end
|
||||
end
|
||||
|
||||
if (delid) then
|
||||
openDocuments[delid] = nil
|
||||
end
|
||||
|
||||
notebook:RemovePage(index)
|
||||
|
||||
if nextIndex then
|
||||
notebook:SetSelection(nextIndex)
|
||||
elseif prevIndex then
|
||||
notebook:SetSelection(prevIndex)
|
||||
end
|
||||
|
||||
SetEditorSelection(nil) -- will use notebook GetSelection to update
|
||||
end
|
||||
|
||||
-- Show a dialog to save a file before closing editor.
|
||||
-- returns wxID_YES, wxID_NO, or wxID_CANCEL if allow_cancel
|
||||
function SaveModifiedDialog(editor, allow_cancel)
|
||||
local result = wx.wxID_NO
|
||||
local id = editor:GetId()
|
||||
local document = openDocuments[id]
|
||||
local filePath = document.filePath
|
||||
local fileName = document.fileName
|
||||
if document.isModified then
|
||||
local message
|
||||
if fileName then
|
||||
message = "Save changes to '"..fileName.."' before exiting?"
|
||||
else
|
||||
message = "Save changes to 'untitled' before exiting?"
|
||||
end
|
||||
local dlg_styles = wx.wxYES_NO + wx.wxCENTRE + wx.wxICON_QUESTION
|
||||
if allow_cancel then dlg_styles = dlg_styles + wx.wxCANCEL end
|
||||
local dialog = wx.wxMessageDialog(ide.frame, message,
|
||||
"Save Changes?",
|
||||
dlg_styles)
|
||||
result = dialog:ShowModal()
|
||||
dialog:Destroy()
|
||||
if result == wx.wxID_YES then
|
||||
SaveFile(editor, filePath)
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function SaveOnExit(allow_cancel)
|
||||
for id, document in pairs(openDocuments) do
|
||||
if (SaveModifiedDialog(document.editor, allow_cancel) == wx.wxID_CANCEL) then
|
||||
return false
|
||||
end
|
||||
|
||||
document.isModified = false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function FoldSome()
|
||||
local editor = GetEditor()
|
||||
editor:Colourise(0, -1) -- update doc's folding info
|
||||
local visible, baseFound, expanded, folded
|
||||
for ln = 2, editor.LineCount - 1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if not baseFound and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
baseFound = true
|
||||
visible = editor:GetLineVisible(ln)
|
||||
end
|
||||
if foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
expanded = true
|
||||
else
|
||||
folded = true
|
||||
end
|
||||
end
|
||||
if expanded and folded and baseFound then break end
|
||||
end
|
||||
local show = not visible or (not baseFound and expanded) or (expanded and folded)
|
||||
local hide = visible and folded
|
||||
|
||||
if show then
|
||||
editor:ShowLines(1, editor.LineCount-1)
|
||||
end
|
||||
|
||||
for ln = 1, editor.LineCount - 1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if show then
|
||||
if foldHdr then
|
||||
if not editor:GetFoldExpanded(ln) then editor:ToggleFold(ln) end
|
||||
end
|
||||
elseif hide and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
if not foldHdr then
|
||||
editor:HideLines(ln, ln)
|
||||
end
|
||||
elseif foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln)
|
||||
end
|
||||
end
|
||||
end
|
||||
editor:EnsureCaretVisible()
|
||||
end
|
||||
|
||||
function EnsureRangeVisible(posStart, posEnd)
|
||||
local editor = GetEditor()
|
||||
if posStart > posEnd then
|
||||
posStart, posEnd = posEnd, posStart
|
||||
end
|
||||
|
||||
local lineStart = editor:LineFromPosition(posStart)
|
||||
local lineEnd = editor:LineFromPosition(posEnd)
|
||||
for line = lineStart, lineEnd do
|
||||
editor:EnsureVisibleEnforcePolicy(line)
|
||||
end
|
||||
end
|
||||
|
||||
function SetAllEditorsReadOnly(enable)
|
||||
for id, document in pairs(openDocuments) do
|
||||
local editor = document.editor
|
||||
editor:SetReadOnly(enable)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------
|
||||
-- Debug related
|
||||
|
||||
function ClearAllCurrentLineMarkers()
|
||||
for id, document in pairs(openDocuments) do
|
||||
local editor = document.editor
|
||||
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
|
||||
end
|
||||
end
|
||||
|
||||
function CompileProgram(editor)
|
||||
local editorText = editor:GetText()
|
||||
local id = editor:GetId()
|
||||
local filePath = MakeDebugFileName(editor, openDocuments[id].filePath)
|
||||
local ret, errMsg, line_num = wxlua.CompileLuaScript(editorText, filePath)
|
||||
if ide.frame.menuBar:IsChecked(ID_CLEAROUTPUT) then
|
||||
ClearOutput()
|
||||
end
|
||||
|
||||
if line_num > -1 then
|
||||
DisplayOutput("Compilation error on line number :"..tostring(line_num).."\n"..errMsg.."\n")
|
||||
editor:GotoLine(line_num-1)
|
||||
else
|
||||
DisplayOutput("Compilation successful.\n")
|
||||
end
|
||||
|
||||
return line_num == -1 -- return true if it compiled ok
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Save & Close
|
||||
|
||||
function SaveIfModified(editor)
|
||||
local id = editor:GetId()
|
||||
if openDocuments[id].isModified then
|
||||
local saved = false
|
||||
if not openDocuments[id].filePath then
|
||||
local ret = wx.wxMessageBox("You must save the program before running it.\nPress cancel to abort running.",
|
||||
"Save file?", wx.wxOK + wx.wxCANCEL + wx.wxCENTRE, ide.frame)
|
||||
if ret == wx.wxOK then
|
||||
saved = SaveFileAs(editor)
|
||||
end
|
||||
else
|
||||
saved = SaveFile(editor, openDocuments[id].filePath)
|
||||
end
|
||||
|
||||
if saved then
|
||||
openDocuments[id].isModified = false
|
||||
else
|
||||
return false -- not saved
|
||||
end
|
||||
end
|
||||
|
||||
return true -- saved
|
||||
end
|
||||
|
||||
function GetOpenFiles()
|
||||
local opendocs = {}
|
||||
for id, document in pairs(ide.openDocuments) do
|
||||
if (document.filePath) then
|
||||
local wxfname = wx.wxFileName(document.filePath)
|
||||
wxfname:Normalize()
|
||||
|
||||
table.insert(opendocs,{fname=wxfname:GetFullPath(),id=document.index,
|
||||
cursorpos = document.editor:GetCurrentPos()})
|
||||
end
|
||||
end
|
||||
|
||||
-- to keep tab order
|
||||
table.sort(opendocs,function(a,b) return (a.id < b.id) end)
|
||||
|
||||
local openfiles = {}
|
||||
for i,doc in ipairs(opendocs) do
|
||||
table.insert(openfiles,{filename = doc.fname, cursorpos = doc.cursorpos} )
|
||||
end
|
||||
|
||||
local id = GetEditor()
|
||||
id = id and id:GetId()
|
||||
|
||||
return openfiles, id and openDocuments[id].index or 0
|
||||
end
|
||||
|
||||
function SetOpenFiles(nametab,index)
|
||||
for i,doc in ipairs(nametab) do
|
||||
local editor = LoadFile(doc.filename,nil,true)
|
||||
if editor then
|
||||
editor:SetCurrentPos(doc.cursorpos or 0)
|
||||
editor:SetSelectionStart(doc.cursorpos or 0)
|
||||
editor:SetSelectionEnd(doc.cursorpos or 0)
|
||||
editor:EnsureCaretVisible()
|
||||
end
|
||||
end
|
||||
notebook:SetSelection(index or 0)
|
||||
end
|
||||
|
||||
function CloseWindow(event)
|
||||
exitingProgram = true -- don't handle focus events
|
||||
|
||||
if not SaveOnExit(event:CanVeto()) then
|
||||
event:Veto()
|
||||
exitingProgram = false
|
||||
return
|
||||
end
|
||||
|
||||
SettingsSaveProjectSession(GetProjects())
|
||||
SettingsSaveFileSession(GetOpenFiles())
|
||||
SettingsSaveView()
|
||||
SettingsSaveFramePosition(ide.frame, "MainFrame")
|
||||
SettingsSaveEditorSettings()
|
||||
CloseWatchWindow()
|
||||
ide.settings:delete() -- always delete the config
|
||||
event:Skip()
|
||||
end
|
||||
frame:Connect(wx.wxEVT_CLOSE_WINDOW, CloseWindow)
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local notebook = frame.notebook
|
||||
local openDocuments = ide.openDocuments
|
||||
|
||||
function NewFile(event)
|
||||
local editor = CreateEditor("untitled.lua")
|
||||
SetupKeywords(editor, "lua")
|
||||
end
|
||||
|
||||
-- Find an editor page that hasn't been used at all, eg. an untouched NewFile()
|
||||
local function findDocumentToReuse()
|
||||
local editor = nil
|
||||
for id, document in pairs(openDocuments) do
|
||||
if (document.editor:GetLength() == 0) and
|
||||
(not document.isModified) and (not document.filePath) and
|
||||
not (document.editor:GetReadOnly() == true) then
|
||||
editor = document.editor
|
||||
break
|
||||
end
|
||||
end
|
||||
return editor
|
||||
end
|
||||
|
||||
function LoadFile(filePath, editor, file_must_exist)
|
||||
filePath = wx.wxFileName(filePath):GetFullPath()
|
||||
local cmpName = string.lower(string.gsub(filePath, "\\", "/"))
|
||||
|
||||
-- prevent files from being reopened again
|
||||
if (not editor) then
|
||||
for id, doc in pairs(openDocuments) do
|
||||
local docName = doc.filePath and string.lower(string.gsub(doc.filePath, "\\", "/"))
|
||||
if cmpName == docName then
|
||||
notebook:SetSelection(doc.index)
|
||||
return doc.editor
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if not opened yet, try open now
|
||||
local file_text = ""
|
||||
local handle = io.open(filePath, "rb")
|
||||
if handle then
|
||||
file_text = handle:read("*a")
|
||||
if GetConfigIOFilter("input") then
|
||||
file_text = GetConfigIOFilter("input")(filePath,file_text)
|
||||
end
|
||||
handle:close()
|
||||
elseif file_must_exist then
|
||||
return nil
|
||||
end
|
||||
|
||||
if not editor then
|
||||
editor = findDocumentToReuse()
|
||||
end
|
||||
if not editor then
|
||||
editor = CreateEditor(wx.wxFileName(filePath):GetFullName() or "untitled.lua")
|
||||
end
|
||||
|
||||
editor:Clear()
|
||||
editor:ClearAll()
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
editor:MarkerDeleteAll(BREAKPOINT_MARKER)
|
||||
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
|
||||
editor:AppendText(file_text)
|
||||
if (ide.config.editor.autotabs) then
|
||||
local found = string.find(file_text,"\t") ~= nil
|
||||
editor:SetUseTabs(found)
|
||||
end
|
||||
|
||||
editor:EmptyUndoBuffer()
|
||||
local id = editor:GetId()
|
||||
openDocuments[id].filePath = filePath
|
||||
openDocuments[id].fileName = wx.wxFileName(filePath):GetFullName()
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
editor:Colourise(0, -1)
|
||||
|
||||
IndicateFunctions(editor)
|
||||
|
||||
SettingsAppendFileToHistory(filePath)
|
||||
|
||||
SetEditorSelection(nil)
|
||||
|
||||
return editor
|
||||
end
|
||||
|
||||
local function getExtsString()
|
||||
local knownexts = ""
|
||||
for i,spec in pairs(ide.specs) do
|
||||
if (spec.exts) then
|
||||
for n,ext in ipairs(spec.exts) do
|
||||
knownexts = knownexts.."*."..ext..";"
|
||||
end
|
||||
end
|
||||
end
|
||||
knownexts = knownexts:len() > 0 and knownexts:sub(1,-2) or nil
|
||||
|
||||
local exts = knownexts and "Known Files ("..knownexts..")|"..knownexts.."|" or ""
|
||||
exts = exts.."All files (*)|*"
|
||||
|
||||
return exts
|
||||
end
|
||||
|
||||
function OpenFile(event)
|
||||
|
||||
local exts = getExtsString()
|
||||
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, "Open file",
|
||||
"",
|
||||
"",
|
||||
exts,
|
||||
wx.wxOPEN + wx.wxFILE_MUST_EXIST)
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
if not LoadFile(fileDialog:GetPath(), nil, true) then
|
||||
wx.wxMessageBox("Unable to load file '"..fileDialog:GetPath().."'.",
|
||||
"wxLua Error",
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
end
|
||||
end
|
||||
fileDialog:Destroy()
|
||||
end
|
||||
|
||||
-- save the file to filePath or if filePath is nil then call SaveFileAs
|
||||
function SaveFile(editor, filePath)
|
||||
if not filePath then
|
||||
return SaveFileAs(editor)
|
||||
else
|
||||
filePath = filePath:gsub("\\","/")
|
||||
|
||||
if (ide.config.savebak) then
|
||||
local backPath = filePath..".bak"
|
||||
os.remove(backPath)
|
||||
os.rename(filePath, backPath)
|
||||
end
|
||||
|
||||
local handle = io.open(filePath, "wb")
|
||||
if handle then
|
||||
local st = editor:GetText()
|
||||
|
||||
if GetConfigIOFilter("output") then
|
||||
st = GetConfigIOFilter("output")(filePath,st)
|
||||
end
|
||||
handle:write(st)
|
||||
handle:close()
|
||||
--editor:EmptyUndoBuffer()
|
||||
editor:SetSavePoint()
|
||||
local id = editor:GetId()
|
||||
openDocuments[id].filePath = filePath
|
||||
openDocuments[id].fileName = wx.wxFileName(filePath):GetFullName()
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
return true
|
||||
else
|
||||
wx.wxMessageBox("Unable to save file '"..filePath.."'.",
|
||||
"wxLua Error Saving",
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function SaveFileAs(editor)
|
||||
local id = editor:GetId()
|
||||
local saved = false
|
||||
local filePath = openDocuments[id].filePath
|
||||
if (not filePath) then
|
||||
filePath = FileTreeGetDir()
|
||||
filePath = (filePath or "").."untitled"
|
||||
end
|
||||
|
||||
local fn = wx.wxFileName(filePath)
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
local exts = getExtsString()
|
||||
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, "Save file as",
|
||||
fn:GetPath(wx.wxPATH_GET_VOLUME),
|
||||
fn:GetFullName(),
|
||||
exts,
|
||||
wx.wxSAVE)
|
||||
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
local filePath = fileDialog:GetPath()
|
||||
|
||||
if SaveFile(editor, filePath) then
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
IndicateFunctions(editor)
|
||||
saved = true
|
||||
end
|
||||
end
|
||||
|
||||
fileDialog:Destroy()
|
||||
return saved
|
||||
end
|
||||
|
||||
function SaveAll()
|
||||
for id, document in pairs(openDocuments) do
|
||||
local editor = document.editor
|
||||
local filePath = document.filePath
|
||||
|
||||
if document.isModified then
|
||||
SaveFile(editor, filePath) -- will call SaveFileAs if necessary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function removePage(index)
|
||||
local prevIndex = nil
|
||||
local nextIndex = nil
|
||||
|
||||
-- try to preserve old selection
|
||||
local selectIndex = notebook:GetSelection()
|
||||
selectIndex = selectIndex ~= index and selectIndex
|
||||
|
||||
local delid = nil
|
||||
for id, document in pairs(openDocuments) do
|
||||
local wasselected = document.index == selectIndex
|
||||
if document.index < index then
|
||||
prevIndex = document.index
|
||||
elseif document.index == index then
|
||||
delid = id
|
||||
document.editor:Destroy()
|
||||
elseif document.index > index then
|
||||
document.index = document.index - 1
|
||||
if nextIndex == nil then
|
||||
nextIndex = document.index
|
||||
end
|
||||
end
|
||||
if (wasselected) then
|
||||
selectIndex = document.index
|
||||
end
|
||||
end
|
||||
|
||||
if (delid) then
|
||||
openDocuments[delid] = nil
|
||||
end
|
||||
|
||||
notebook:RemovePage(index)
|
||||
|
||||
if selectIndex then
|
||||
notebook:SetSelection(selectIndex)
|
||||
elseif nextIndex then
|
||||
notebook:SetSelection(nextIndex)
|
||||
elseif prevIndex then
|
||||
notebook:SetSelection(prevIndex)
|
||||
end
|
||||
|
||||
SetEditorSelection(nil) -- will use notebook GetSelection to update
|
||||
end
|
||||
|
||||
function ClosePage(selection)
|
||||
local editor = GetEditor(selection)
|
||||
local id = editor:GetId()
|
||||
if SaveModifiedDialog(editor, true) ~= wx.wxID_CANCEL then
|
||||
DynamicWordsRemoveAll(editor)
|
||||
removePage(ide.openDocuments[id].index)
|
||||
end
|
||||
end
|
||||
|
||||
-- Show a dialog to save a file before closing editor.
|
||||
-- returns wxID_YES, wxID_NO, or wxID_CANCEL if allow_cancel
|
||||
function SaveModifiedDialog(editor, allow_cancel)
|
||||
local result = wx.wxID_NO
|
||||
local id = editor:GetId()
|
||||
local document = openDocuments[id]
|
||||
local filePath = document.filePath
|
||||
local fileName = document.fileName
|
||||
if document.isModified then
|
||||
local message
|
||||
if fileName then
|
||||
message = "Save changes to '"..fileName.."' before exiting?"
|
||||
else
|
||||
message = "Save changes to 'untitled' before exiting?"
|
||||
end
|
||||
local dlg_styles = wx.wxYES_NO + wx.wxCENTRE + wx.wxICON_QUESTION
|
||||
if allow_cancel then dlg_styles = dlg_styles + wx.wxCANCEL end
|
||||
local dialog = wx.wxMessageDialog(ide.frame, message,
|
||||
"Save Changes?",
|
||||
dlg_styles)
|
||||
result = dialog:ShowModal()
|
||||
dialog:Destroy()
|
||||
if result == wx.wxID_YES then
|
||||
if not SaveFile(editor, filePath) then
|
||||
return wx.wxID_CANCEL -- cancel if canceled save dialog
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function SaveOnExit(allow_cancel)
|
||||
for id, document in pairs(openDocuments) do
|
||||
if (SaveModifiedDialog(document.editor, allow_cancel) == wx.wxID_CANCEL) then
|
||||
return false
|
||||
end
|
||||
|
||||
document.isModified = false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function FoldSome()
|
||||
local editor = GetEditor()
|
||||
editor:Colourise(0, -1) -- update doc's folding info
|
||||
local visible, baseFound, expanded, folded
|
||||
for ln = 2, editor.LineCount - 1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if not baseFound and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
baseFound = true
|
||||
visible = editor:GetLineVisible(ln)
|
||||
end
|
||||
if foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
expanded = true
|
||||
else
|
||||
folded = true
|
||||
end
|
||||
end
|
||||
if expanded and folded and baseFound then break end
|
||||
end
|
||||
local show = not visible or (not baseFound and expanded) or (expanded and folded)
|
||||
local hide = visible and folded
|
||||
|
||||
if show then
|
||||
editor:ShowLines(1, editor.LineCount-1)
|
||||
end
|
||||
|
||||
for ln = 1, editor.LineCount - 1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if show then
|
||||
if foldHdr then
|
||||
if not editor:GetFoldExpanded(ln) then editor:ToggleFold(ln) end
|
||||
end
|
||||
elseif hide and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
if not foldHdr then
|
||||
editor:HideLines(ln, ln)
|
||||
end
|
||||
elseif foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln)
|
||||
end
|
||||
end
|
||||
end
|
||||
editor:EnsureCaretVisible()
|
||||
end
|
||||
|
||||
function EnsureRangeVisible(posStart, posEnd)
|
||||
local editor = GetEditor()
|
||||
if posStart > posEnd then
|
||||
posStart, posEnd = posEnd, posStart
|
||||
end
|
||||
|
||||
local lineStart = editor:LineFromPosition(posStart)
|
||||
local lineEnd = editor:LineFromPosition(posEnd)
|
||||
for line = lineStart, lineEnd do
|
||||
editor:EnsureVisibleEnforcePolicy(line)
|
||||
end
|
||||
end
|
||||
|
||||
function SetAllEditorsReadOnly(enable)
|
||||
for id, document in pairs(openDocuments) do
|
||||
local editor = document.editor
|
||||
editor:SetReadOnly(enable)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------
|
||||
-- Debug related
|
||||
|
||||
function ClearAllCurrentLineMarkers()
|
||||
for id, document in pairs(openDocuments) do
|
||||
local editor = document.editor
|
||||
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
|
||||
end
|
||||
end
|
||||
|
||||
function CompileProgram(editor)
|
||||
local editorText = editor:GetText()
|
||||
local id = editor:GetId()
|
||||
local filePath = DebuggerMakeFileName(editor, openDocuments[id].filePath)
|
||||
local ret, errMsg, line_num = wxlua.CompileLuaScript(editorText, filePath)
|
||||
if ide.frame.menuBar:IsChecked(ID_CLEAROUTPUT) then
|
||||
ClearOutput()
|
||||
end
|
||||
|
||||
if line_num > -1 then
|
||||
DisplayOutput("Compilation error on line number :"..tostring(line_num).."\n"..errMsg.."\n")
|
||||
editor:GotoLine(line_num-1)
|
||||
else
|
||||
DisplayOutput("Compilation successful.\n")
|
||||
end
|
||||
|
||||
return line_num == -1 -- return true if it compiled ok
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Save & Close
|
||||
|
||||
function SaveIfModified(editor)
|
||||
local id = editor:GetId()
|
||||
if openDocuments[id].isModified then
|
||||
local saved = false
|
||||
if not openDocuments[id].filePath then
|
||||
local ret = wx.wxMessageBox("You must save the program before running it.\nPress cancel to abort running.",
|
||||
"Save file?", wx.wxOK + wx.wxCANCEL + wx.wxCENTRE, ide.frame)
|
||||
if ret == wx.wxOK then
|
||||
saved = SaveFileAs(editor)
|
||||
end
|
||||
else
|
||||
saved = SaveFile(editor, openDocuments[id].filePath)
|
||||
end
|
||||
|
||||
if saved then
|
||||
openDocuments[id].isModified = false
|
||||
else
|
||||
return false -- not saved
|
||||
end
|
||||
end
|
||||
|
||||
return true -- saved
|
||||
end
|
||||
|
||||
function GetOpenFiles()
|
||||
local opendocs = {}
|
||||
for id, document in pairs(ide.openDocuments) do
|
||||
if (document.filePath) then
|
||||
local wxfname = wx.wxFileName(document.filePath)
|
||||
wxfname:Normalize()
|
||||
|
||||
table.insert(opendocs,{fname=wxfname:GetFullPath(),id=document.index,
|
||||
cursorpos = document.editor:GetCurrentPos()})
|
||||
end
|
||||
end
|
||||
|
||||
-- to keep tab order
|
||||
table.sort(opendocs,function(a,b) return (a.id < b.id) end)
|
||||
|
||||
local openfiles = {}
|
||||
for i,doc in ipairs(opendocs) do
|
||||
table.insert(openfiles,{filename = doc.fname, cursorpos = doc.cursorpos} )
|
||||
end
|
||||
|
||||
local id = GetEditor()
|
||||
id = id and id:GetId()
|
||||
|
||||
return openfiles, id and openDocuments[id].index or 0
|
||||
end
|
||||
|
||||
function SetOpenFiles(nametab,index)
|
||||
for i,doc in ipairs(nametab) do
|
||||
local editor = LoadFile(doc.filename,nil,true)
|
||||
if editor then
|
||||
editor:SetCurrentPos(doc.cursorpos or 0)
|
||||
editor:SetSelectionStart(doc.cursorpos or 0)
|
||||
editor:SetSelectionEnd(doc.cursorpos or 0)
|
||||
editor:EnsureCaretVisible()
|
||||
end
|
||||
end
|
||||
notebook:SetSelection(index or 0)
|
||||
end
|
||||
|
||||
function CloseWindow(event)
|
||||
exitingProgram = true -- don't handle focus events
|
||||
|
||||
if not SaveOnExit(event:CanVeto()) then
|
||||
event:Veto()
|
||||
exitingProgram = false
|
||||
return
|
||||
end
|
||||
|
||||
SettingsSaveProjectSession(FileTreeGetProjects())
|
||||
SettingsSaveFileSession(GetOpenFiles())
|
||||
SettingsSaveView()
|
||||
SettingsSaveFramePosition(ide.frame, "MainFrame")
|
||||
SettingsSaveEditorSettings()
|
||||
DebuggerCloseWatchWindow()
|
||||
DebuggerKillClient()
|
||||
ide.settings:delete() -- always delete the config
|
||||
event:Skip()
|
||||
end
|
||||
frame:Connect(wx.wxEVT_CLOSE_WINDOW, CloseWindow)
|
||||
|
||||
@@ -1,309 +1,460 @@
|
||||
-- Integration with MobDebug
|
||||
-- Copyright Paul Kulchenko 2011
|
||||
|
||||
local copas = require "copas"
|
||||
local socket = require "socket"
|
||||
local mobdebug = require "mobdebug"
|
||||
|
||||
local debugger = {}
|
||||
debugger.server = nil -- DebuggerServer object when debugging, else nil
|
||||
debugger.running = false -- true when the debuggee is running
|
||||
debugger.portnumber = 8171 -- the port # to use for debugging
|
||||
debugger.watchWindow = nil -- the watchWindow, nil when not created
|
||||
debugger.watchListCtrl = nil -- the child listctrl in the watchWindow
|
||||
|
||||
ide.debugger = debugger
|
||||
|
||||
local notebook = ide.frame.vsplitter.splitter.notebook
|
||||
|
||||
debugger.shell = function(expression)
|
||||
if debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
local value, _, err = debugger.handle('eval ' .. expression)
|
||||
if err ~= nil then value, _, err = debugger.handle('exec ' .. expression) end
|
||||
if err then DisplayShellErr(err)
|
||||
else DisplayShell(value)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.listen = function()
|
||||
local server = socket.bind("*", debugger.portnumber)
|
||||
DisplayOutput("Started debugger server; clients can connect to "..wx.wxGetHostName()..":"..debugger.portnumber..".\n")
|
||||
copas.autoclose = false
|
||||
copas.addserver(server, function (skt)
|
||||
debugger.server = copas.wrap(skt)
|
||||
SetAllEditorsReadOnly(true)
|
||||
local editor = GetEditor()
|
||||
local filePath = ide.openDocuments[editor:GetId()].filePath;
|
||||
debugger.basedir = string.gsub(wx.wxFileName(filePath):GetPath(wx.wxPATH_GET_VOLUME), "\\", "/")
|
||||
|
||||
-- load the remote file into the debugger
|
||||
-- set basedir first, before loading to make sure that the path is correct
|
||||
debugger.handle("basedir " .. debugger.basedir)
|
||||
debugger.handle("load " .. filePath)
|
||||
|
||||
-- remove all breakpoints that may still be present from the last session
|
||||
-- this only matters for those remote clients that reload scripts
|
||||
-- without resetting their breakpoints
|
||||
debugger.handle("delallb")
|
||||
|
||||
-- go over all windows and find all breakpoints
|
||||
for id, document in pairs(ide.openDocuments) do
|
||||
local editor = document.editor
|
||||
local filePath = string.gsub(document.filePath, "\\", "/")
|
||||
line = editor:MarkerNext(0, BREAKPOINT_MARKER_VALUE)
|
||||
while line ~= -1 do
|
||||
debugger.handle("setb " .. filePath .. " " .. (line+1))
|
||||
line = editor:MarkerNext(line + 1, BREAKPOINT_MARKER_VALUE)
|
||||
end
|
||||
end
|
||||
|
||||
local line = 1
|
||||
editor:MarkerAdd(line-1, CURRENT_LINE_MARKER)
|
||||
editor:EnsureVisibleEnforcePolicy(line-1)
|
||||
|
||||
ShellSupportRemote(debugger.shell, 0)
|
||||
|
||||
DisplayOutput("Started remote debugging session (base directory: " .. debugger.basedir .. "/).\n")
|
||||
end)
|
||||
end
|
||||
|
||||
debugger.handle = function(line)
|
||||
local _G = _G
|
||||
local os = os
|
||||
os.exit = function () end
|
||||
_G.print = function () end
|
||||
|
||||
debugger.running = true
|
||||
local file, line, err = mobdebug.handle(line, debugger.server)
|
||||
debugger.running = false
|
||||
|
||||
return file, line, err
|
||||
end
|
||||
|
||||
debugger.run = function(command)
|
||||
if debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
while true do
|
||||
local file, line, err = debugger.handle(command)
|
||||
if line == nil then
|
||||
debugger.server = nil
|
||||
SetAllEditorsReadOnly(false)
|
||||
ShellSupportRemote(nil, 0)
|
||||
if err then DisplayOutput(err .. "\n") end
|
||||
DisplayOutput("Completed debugging session.\n")
|
||||
return
|
||||
else
|
||||
if debugger.basedir and not wx.wxIsAbsolutePath(file) then
|
||||
file = debugger.basedir .. "/" .. file
|
||||
end
|
||||
if ActivateDocument(file, line) then
|
||||
debugger.updateWatches()
|
||||
return
|
||||
else
|
||||
command = "out" -- redo now trying to get out of this file
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.updateBreakpoint = function(command)
|
||||
if debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
debugger.handle(command)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.updateWatches = function()
|
||||
local watchListCtrl = debugger.watchListCtrl
|
||||
if watchListCtrl and debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
for idx = 0, watchListCtrl:GetItemCount() - 1 do
|
||||
local expression = watchListCtrl:GetItemText(idx)
|
||||
local value = debugger.handle('eval ' .. expression)
|
||||
watchListCtrl:SetItem(idx, 1, value)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.update = function() copas.step(0) end
|
||||
|
||||
debugger.listen()
|
||||
|
||||
function CloseWatchWindow()
|
||||
if (debugger.watchWindow) then
|
||||
SettingsSaveFramePosition(debugger.watchWindow, "WatchWindow")
|
||||
debugger.watchListCtrl = nil
|
||||
debugger.watchWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function CreateWatchWindow()
|
||||
local width = 200
|
||||
local watchWindow = wx.wxFrame(ide.frame, wx.wxID_ANY,
|
||||
"Watch Window",
|
||||
wx.wxDefaultPosition, wx.wxSize(width, 160),
|
||||
wx.wxDEFAULT_FRAME_STYLE + wx.wxFRAME_FLOAT_ON_PARENT)
|
||||
|
||||
debugger.watchWindow = watchWindow
|
||||
|
||||
local watchMenu = wx.wxMenu{
|
||||
{ ID_ADDWATCH, "&Add Watch" },
|
||||
{ ID_EDITWATCH, "&Edit Watch\tF2" },
|
||||
{ ID_REMOVEWATCH, "&Remove Watch" },
|
||||
{ ID_EVALUATEWATCH, "Evaluate &Watches" }}
|
||||
|
||||
local watchMenuBar = wx.wxMenuBar()
|
||||
watchMenuBar:Append(watchMenu, "&Watches")
|
||||
watchWindow:SetMenuBar(watchMenuBar)
|
||||
|
||||
local watchListCtrl = wx.wxListCtrl(watchWindow, ID_WATCH_LISTCTRL,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxLC_REPORT + wx.wxLC_EDIT_LABELS)
|
||||
|
||||
debugger.watchListCtrl = watchListCtrl
|
||||
|
||||
local info = wx.wxListItem()
|
||||
info:SetMask(wx.wxLIST_MASK_TEXT + wx.wxLIST_MASK_WIDTH)
|
||||
info:SetText("Expression")
|
||||
info:SetWidth(width * 0.45)
|
||||
watchListCtrl:InsertColumn(0, info)
|
||||
|
||||
info:SetText("Value")
|
||||
info:SetWidth(width * 0.45)
|
||||
watchListCtrl:InsertColumn(1, info)
|
||||
|
||||
watchWindow:CentreOnParent()
|
||||
SettingsRestoreFramePosition(watchWindow, "WatchWindow")
|
||||
watchWindow:Show(true)
|
||||
|
||||
local function FindSelectedWatchItem()
|
||||
local count = watchListCtrl:GetSelectedItemCount()
|
||||
if count > 0 then
|
||||
for idx = 0, watchListCtrl:GetItemCount() - 1 do
|
||||
if watchListCtrl:GetItemState(idx, wx.wxLIST_STATE_FOCUSED) ~= 0 then
|
||||
return idx
|
||||
end
|
||||
end
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
watchWindow:Connect( wx.wxEVT_CLOSE_WINDOW,
|
||||
function (event)
|
||||
CloseWatchWindow()
|
||||
watchWindow = nil
|
||||
watchListCtrl = nil
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_ADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local row = watchListCtrl:InsertItem(watchListCtrl:GetItemCount(), "Expr")
|
||||
watchListCtrl:SetItem(row, 0, "Expr")
|
||||
watchListCtrl:SetItem(row, 1, "Value")
|
||||
watchListCtrl:EditLabel(row)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_EDITWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local row = FindSelectedWatchItem()
|
||||
if row >= 0 then
|
||||
watchListCtrl:EditLabel(row)
|
||||
end
|
||||
end)
|
||||
watchWindow:Connect(ID_EDITWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchListCtrl:GetSelectedItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_REMOVEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local row = FindSelectedWatchItem()
|
||||
if row >= 0 then
|
||||
watchListCtrl:DeleteItem(row)
|
||||
end
|
||||
end)
|
||||
watchWindow:Connect(ID_REMOVEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchListCtrl:GetSelectedItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_EVALUATEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
debugger.updateWatches()
|
||||
end)
|
||||
watchWindow:Connect(ID_EVALUATEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchListCtrl:GetItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchListCtrl:Connect(wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT,
|
||||
function (event)
|
||||
watchListCtrl:SetItem(event:GetIndex(), 0, event:GetText())
|
||||
debugger.updateWatches()
|
||||
event:Skip()
|
||||
end)
|
||||
end
|
||||
|
||||
function MakeDebugFileName(editor, filePath)
|
||||
if not filePath then
|
||||
filePath = "file"..tostring(editor)
|
||||
end
|
||||
return filePath
|
||||
end
|
||||
|
||||
function ToggleDebugMarker(editor, line)
|
||||
local markers = editor:MarkerGet(line)
|
||||
if markers >= CURRENT_LINE_MARKER_VALUE then
|
||||
markers = markers - CURRENT_LINE_MARKER_VALUE
|
||||
end
|
||||
local id = editor:GetId()
|
||||
local filePath = MakeDebugFileName(editor, ide.openDocuments[id].filePath)
|
||||
if markers >= BREAKPOINT_MARKER_VALUE then
|
||||
editor:MarkerDelete(line, BREAKPOINT_MARKER)
|
||||
if debugger.server then
|
||||
debugger.updateBreakpoint("delb " .. filePath .. " " .. (line+1))
|
||||
end
|
||||
else
|
||||
editor:MarkerAdd(line, BREAKPOINT_MARKER)
|
||||
if debugger.server then
|
||||
debugger.updateBreakpoint("setb " .. filePath .. " " .. (line+1))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ActivateDocument(fileName, line)
|
||||
if not wx.wxIsAbsolutePath(fileName) then
|
||||
fileName = wx.wxGetCwd().."/"..fileName
|
||||
end
|
||||
|
||||
if wx.__WXMSW__ then
|
||||
fileName = wx.wxUnix2DosFilename(fileName)
|
||||
end
|
||||
|
||||
local fileFound = false
|
||||
for id, document in pairs(ide.openDocuments) do
|
||||
local editor = document.editor
|
||||
-- for running in cygwin, use same type of separators
|
||||
filePath = string.gsub(document.filePath, "\\", "/")
|
||||
local fileName = string.gsub(fileName, "\\", "/")
|
||||
if string.upper(filePath) == string.upper(fileName) then
|
||||
local selection = document.index
|
||||
notebook:SetSelection(selection)
|
||||
SetEditorSelection(selection)
|
||||
editor:MarkerAdd(line-1, CURRENT_LINE_MARKER)
|
||||
editor:EnsureVisibleEnforcePolicy(line-1)
|
||||
fileFound = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return fileFound
|
||||
end
|
||||
-- Integration with MobDebug
|
||||
-- Copyright Paul Kulchenko 2011
|
||||
-- Original authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
|
||||
local copas = require "copas"
|
||||
local socket = require "socket"
|
||||
local mobdebug = require "mobdebug"
|
||||
|
||||
local ide = ide
|
||||
local debugger = ide.debugger
|
||||
debugger.server = nil -- DebuggerServer object when debugging, else nil
|
||||
debugger.running = false -- true when the debuggee is running
|
||||
debugger.listening = false -- true when the debugger is listening for a client
|
||||
debugger.portnumber = 8171 -- the port # to use for debugging
|
||||
debugger.watchWindow = nil -- the watchWindow, nil when not created
|
||||
debugger.watchListCtrl = nil -- the child listctrl in the watchWindow
|
||||
|
||||
local notebook = ide.frame.notebook
|
||||
|
||||
local function updateWatchesSync()
|
||||
local watchListCtrl = debugger.watchListCtrl
|
||||
if watchListCtrl and debugger.server and not debugger.running then
|
||||
for idx = 0, watchListCtrl:GetItemCount() - 1 do
|
||||
local expression = watchListCtrl:GetItemText(idx)
|
||||
local value, _, error = debugger.evaluate(expression)
|
||||
watchListCtrl:SetItem(idx, 1, value or ('error: ' .. error))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateWatches()
|
||||
if debugger.watchListCtrl and debugger.server and not debugger.running then
|
||||
copas.addthread(updateWatchesSync)
|
||||
end
|
||||
end
|
||||
|
||||
local function activateDocument(fileName, line)
|
||||
if (not fileName and line) then return end
|
||||
|
||||
if not wx.wxIsAbsolutePath(fileName) then
|
||||
fileName = wx.wxGetCwd().."/"..fileName
|
||||
end
|
||||
|
||||
if wx.__WXMSW__ then
|
||||
fileName = wx.wxUnix2DosFilename(fileName)
|
||||
end
|
||||
|
||||
local fileFound = false
|
||||
for id, document in pairs(ide.openDocuments) do
|
||||
local editor = document.editor
|
||||
-- for running in cygwin, use same type of separators
|
||||
filePath = string.gsub(document.filePath, "\\", "/")
|
||||
local fileName = string.gsub(fileName, "\\", "/")
|
||||
if string.upper(filePath) == string.upper(fileName) then
|
||||
local selection = document.index
|
||||
notebook:SetSelection(selection)
|
||||
SetEditorSelection(selection)
|
||||
ClearAllCurrentLineMarkers()
|
||||
editor:MarkerAdd(line-1, CURRENT_LINE_MARKER)
|
||||
editor:EnsureVisibleEnforcePolicy(line-1)
|
||||
fileFound = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return fileFound
|
||||
end
|
||||
|
||||
debugger.shell = function(expression)
|
||||
if debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
local addedret = false
|
||||
local value, _, err = debugger.handle('exec ' .. expression)
|
||||
if err and (err:find("'=' expected near '<eof>'") or
|
||||
err:find("unexpected symbol near '")) then
|
||||
value, _, err = debugger.handle('eval ' .. expression:gsub("^%s*=%s*",""))
|
||||
addedret = true
|
||||
end
|
||||
|
||||
if err then
|
||||
if addedret then err = err:gsub('^%[string "return ', '[string "') end
|
||||
DisplayShellErr(err)
|
||||
elseif addedret or (value ~= nil and value ~= 'nil') then
|
||||
DisplayShell(value)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.listen = function()
|
||||
local server = socket.bind("*", debugger.portnumber)
|
||||
DisplayOutput("Started debugger server; clients can connect to "..wx.wxGetHostName()..":"..debugger.portnumber..".\n")
|
||||
copas.autoclose = false
|
||||
copas.addserver(server, function (skt)
|
||||
SetAllEditorsReadOnly(true)
|
||||
local options = debugger.options or {}
|
||||
local wxfilepath = GetEditorFileAndCurInfo()
|
||||
local startfile = options.startfile or wxfilepath:GetFullPath()
|
||||
local basedir = options.basedir or wxfilepath:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
debugger.basedir = basedir
|
||||
debugger.server = copas.wrap(skt)
|
||||
debugger.socket = skt
|
||||
debugger.loop = false
|
||||
|
||||
-- load the remote file into the debugger
|
||||
-- set basedir first, before loading to make sure that the path is correct
|
||||
debugger.handle("basedir " .. debugger.basedir)
|
||||
|
||||
-- remove all breakpoints that may still be present from the last session
|
||||
-- this only matters for those remote clients that reload scripts
|
||||
-- without resetting their breakpoints
|
||||
debugger.handle("delallb")
|
||||
|
||||
-- go over all windows and find all breakpoints
|
||||
for id, document in pairs(ide.openDocuments) do
|
||||
local editor = document.editor
|
||||
local filePath = document.filePath
|
||||
line = editor:MarkerNext(0, BREAKPOINT_MARKER_VALUE)
|
||||
while line ~= -1 do
|
||||
debugger.handle("setb " .. filePath .. " " .. (line+1))
|
||||
line = editor:MarkerNext(line + 1, BREAKPOINT_MARKER_VALUE)
|
||||
end
|
||||
end
|
||||
|
||||
if (options.run) then
|
||||
activateDocument(debugger.handle("run"))
|
||||
else
|
||||
local file, line = debugger.handle("load " .. startfile)
|
||||
-- "load" can work in two ways: (1) it can load the requested file
|
||||
-- OR (2) it can "refuse" to load it if the client was started
|
||||
-- with start() method, which can't load new files
|
||||
-- if file and line are set, this indicates option #2
|
||||
if file and line then
|
||||
-- if the file name is absolute, try to load it
|
||||
local activated
|
||||
if wx.wxIsAbsolutePath(file) then
|
||||
activated = activateDocument(file, line)
|
||||
else
|
||||
-- try to find a proper file based on file name
|
||||
-- first check using basedir that was set based on current file path
|
||||
-- if not found, check using project directory and reset basedir
|
||||
if not activated then
|
||||
local fullPath = debugger.basedir..string_Pathsep..file
|
||||
activated = activateDocument(fullPath, line)
|
||||
end
|
||||
|
||||
local projectDir = FileTreeGetDir()
|
||||
if not activated and projectDir then
|
||||
debugger.basedir = projectDir:gsub(string_Pathsep .. "$", "")
|
||||
debugger.handle("basedir " .. debugger.basedir)
|
||||
fullPath = projectDir .. file
|
||||
activated = activateDocument(fullPath, line)
|
||||
end
|
||||
end
|
||||
|
||||
if not activated then
|
||||
DisplayOutput("Can't find file '" .. file .. "' to activate for debugging; try opening the file before debugging.\n")
|
||||
return debugger.terminate()
|
||||
end
|
||||
else
|
||||
activateDocument(startfile, 1)
|
||||
end
|
||||
end
|
||||
|
||||
if (not options.noshell) then
|
||||
ShellSupportRemote(debugger.shell, debugger.pid)
|
||||
end
|
||||
|
||||
DisplayOutput("Started remote debugging session (base directory: '" .. debugger.basedir .. "').\n")
|
||||
|
||||
end)
|
||||
debugger.listening = true
|
||||
end
|
||||
|
||||
debugger.handle = function(command, server)
|
||||
local _G = _G
|
||||
local os = os
|
||||
os.exit = function () end
|
||||
_G.print = function (...)
|
||||
if (ide.config.debugger.verbose) then
|
||||
DisplayOutput(...)
|
||||
DisplayOutput("\n")
|
||||
end
|
||||
end
|
||||
|
||||
debugger.running = true
|
||||
local file, line, err = mobdebug.handle(command, server and server or debugger.server)
|
||||
debugger.running = false
|
||||
|
||||
return file, line, err
|
||||
end
|
||||
|
||||
debugger.exec = function(command)
|
||||
if debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
while true do
|
||||
local file, line, err = debugger.handle(command)
|
||||
if line == nil then
|
||||
if err then DisplayOutput(err .. "\n") end
|
||||
DebuggerStop()
|
||||
return
|
||||
else
|
||||
if debugger.basedir and not wx.wxIsAbsolutePath(file) then
|
||||
file = debugger.basedir .. "/" .. file
|
||||
end
|
||||
if activateDocument(file, line) then
|
||||
if debugger.loop then
|
||||
updateWatchesSync()
|
||||
else
|
||||
updateWatches()
|
||||
return
|
||||
end
|
||||
else
|
||||
command = "out" -- redo now trying to get out of this file
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.updateBreakpoint = function(command)
|
||||
if debugger.server and not debugger.running then
|
||||
copas.addthread(function ()
|
||||
debugger.handle(command)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
debugger.update = function() copas.step(0) end
|
||||
debugger.terminate = function()
|
||||
if debugger.server then
|
||||
if debugger.pid then -- if there is PID, try local kill
|
||||
DebuggerKillClient()
|
||||
else -- otherwise, trace graceful exit for the remote process
|
||||
debugger.exec("exit")
|
||||
copas.step(1) -- process 'exit' right away; doesn't guarantee the response
|
||||
end
|
||||
DebuggerStop()
|
||||
end
|
||||
end
|
||||
debugger.step = function() debugger.exec("step") end
|
||||
debugger.trace = function()
|
||||
debugger.loop = true
|
||||
debugger.exec("step")
|
||||
end
|
||||
debugger.over = function() debugger.exec("over") end
|
||||
debugger.out = function() debugger.exec("out") end
|
||||
debugger.run = function() debugger.exec("run") end
|
||||
debugger.evaluate = function(expression) return debugger.handle('eval ' .. expression) end
|
||||
debugger.breaknow = function()
|
||||
-- stop if we're running a "trace" command
|
||||
debugger.loop = false
|
||||
|
||||
-- force a step command; don't use copas interface as it checks
|
||||
-- for the other side "reading" and the other side is not reading anything.
|
||||
-- use the "original" socket to write a "step" command.
|
||||
-- this will only break on the next Lua command.
|
||||
if debugger.socket then
|
||||
local running = debugger.running
|
||||
-- this needs to be short as it will block the UI
|
||||
debugger.socket:settimeout(0.25)
|
||||
local file, line, err = debugger.handle("step", debugger.socket)
|
||||
debugger.socket:settimeout(0)
|
||||
-- restore running status
|
||||
debugger.running = running
|
||||
-- don't need to do anything else as the earlier call (run, step, etc.)
|
||||
-- will get the results (file, line) back and will update the UI
|
||||
end
|
||||
end
|
||||
debugger.breakpoint = function(file, line, state)
|
||||
debugger.updateBreakpoint((state and "setb " or "delb ") .. file .. " " .. line)
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- public api
|
||||
|
||||
function DebuggerAttachDefault(options)
|
||||
debugger.options = options
|
||||
if (debugger.listening) then return end
|
||||
debugger.listen()
|
||||
end
|
||||
|
||||
function DebuggerKillClient()
|
||||
if (debugger.pid) then
|
||||
-- using SIGTERM for some reason kills not only the debugee process,
|
||||
-- but also some system processes, which leads to a blue screen crash
|
||||
-- (at least on Windows Vista SP2)
|
||||
local ret = wx.wxProcess.Kill(debugger.pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
|
||||
if ret == wx.wxKILL_OK then
|
||||
DisplayOutput("Stopped debuggee process (pid: "..debugger.pid..").\n")
|
||||
elseif ret ~= wx.wxKILL_NO_PROCESS then
|
||||
DisplayOutput("Unable to kill debuggee process (pid: "..debugger.pid.."), code "..tostring(ret)..".\n")
|
||||
end
|
||||
debugger.pid = nil
|
||||
end
|
||||
end
|
||||
|
||||
function DebuggerStop()
|
||||
if (debugger.server) then
|
||||
debugger.server = nil
|
||||
debugger.pid = nil
|
||||
SetAllEditorsReadOnly(false)
|
||||
ShellSupportRemote(nil, 0)
|
||||
ClearAllCurrentLineMarkers()
|
||||
DisplayOutput("Completed debugging session.\n")
|
||||
end
|
||||
end
|
||||
|
||||
function DebuggerCreateStackWindow()
|
||||
DisplayOutput("Not Yet Implemented\n")
|
||||
end
|
||||
|
||||
function DebuggerCloseStackWindow()
|
||||
|
||||
end
|
||||
|
||||
function DebuggerCloseWatchWindow()
|
||||
if (debugger.watchWindow) then
|
||||
SettingsSaveFramePosition(debugger.watchWindow, "WatchWindow")
|
||||
debugger.watchListCtrl = nil
|
||||
debugger.watchWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function DebuggerCreateWatchWindow()
|
||||
local width = 200
|
||||
local watchWindow = wx.wxFrame(ide.frame, wx.wxID_ANY,
|
||||
"Watch Window",
|
||||
wx.wxDefaultPosition, wx.wxSize(width, 160),
|
||||
wx.wxDEFAULT_FRAME_STYLE + wx.wxFRAME_FLOAT_ON_PARENT)
|
||||
|
||||
debugger.watchWindow = watchWindow
|
||||
|
||||
local watchMenu = wx.wxMenu{
|
||||
{ ID_ADDWATCH, "&Add Watch" },
|
||||
{ ID_EDITWATCH, "&Edit Watch\tF2" },
|
||||
{ ID_REMOVEWATCH, "&Remove Watch" },
|
||||
{ ID_EVALUATEWATCH, "Evaluate &Watches" }}
|
||||
|
||||
local watchMenuBar = wx.wxMenuBar()
|
||||
watchMenuBar:Append(watchMenu, "&Watches")
|
||||
watchWindow:SetMenuBar(watchMenuBar)
|
||||
|
||||
local watchListCtrl = wx.wxListCtrl(watchWindow, ID_WATCH_LISTCTRL,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxLC_REPORT + wx.wxLC_EDIT_LABELS)
|
||||
|
||||
debugger.watchListCtrl = watchListCtrl
|
||||
|
||||
local info = wx.wxListItem()
|
||||
info:SetMask(wx.wxLIST_MASK_TEXT + wx.wxLIST_MASK_WIDTH)
|
||||
info:SetText("Expression")
|
||||
info:SetWidth(width * 0.45)
|
||||
watchListCtrl:InsertColumn(0, info)
|
||||
|
||||
info:SetText("Value")
|
||||
info:SetWidth(width * 0.45)
|
||||
watchListCtrl:InsertColumn(1, info)
|
||||
|
||||
watchWindow:CentreOnParent()
|
||||
SettingsRestoreFramePosition(watchWindow, "WatchWindow")
|
||||
watchWindow:Show(true)
|
||||
|
||||
local function findSelectedWatchItem()
|
||||
local count = watchListCtrl:GetSelectedItemCount()
|
||||
if count > 0 then
|
||||
for idx = 0, watchListCtrl:GetItemCount() - 1 do
|
||||
if watchListCtrl:GetItemState(idx, wx.wxLIST_STATE_FOCUSED) ~= 0 then
|
||||
return idx
|
||||
end
|
||||
end
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
watchWindow:Connect( wx.wxEVT_CLOSE_WINDOW,
|
||||
function (event)
|
||||
DebuggerCloseWatchWindow()
|
||||
watchWindow = nil
|
||||
watchListCtrl = nil
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_ADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local row = watchListCtrl:InsertItem(watchListCtrl:GetItemCount(), "Expr")
|
||||
watchListCtrl:SetItem(row, 0, "Expr")
|
||||
watchListCtrl:SetItem(row, 1, "Value")
|
||||
watchListCtrl:EditLabel(row)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_EDITWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local row = findSelectedWatchItem()
|
||||
if row >= 0 then
|
||||
watchListCtrl:EditLabel(row)
|
||||
end
|
||||
end)
|
||||
watchWindow:Connect(ID_EDITWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchListCtrl:GetSelectedItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_REMOVEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local row = findSelectedWatchItem()
|
||||
if row >= 0 then
|
||||
watchListCtrl:DeleteItem(row)
|
||||
end
|
||||
end)
|
||||
watchWindow:Connect(ID_REMOVEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchListCtrl:GetSelectedItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_EVALUATEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
updateWatches()
|
||||
end)
|
||||
watchWindow:Connect(ID_EVALUATEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchListCtrl:GetItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchListCtrl:Connect(wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT,
|
||||
function (event)
|
||||
watchListCtrl:SetItem(event:GetIndex(), 0, event:GetText())
|
||||
updateWatches()
|
||||
event:Skip()
|
||||
end)
|
||||
end
|
||||
|
||||
function DebuggerMakeFileName(editor, filePath)
|
||||
if not filePath then
|
||||
filePath = "file"..tostring(editor)
|
||||
end
|
||||
return filePath
|
||||
end
|
||||
|
||||
function DebuggerToggleBreakpoint(editor, line)
|
||||
local markers = editor:MarkerGet(line)
|
||||
if markers >= CURRENT_LINE_MARKER_VALUE then
|
||||
markers = markers - CURRENT_LINE_MARKER_VALUE
|
||||
end
|
||||
local id = editor:GetId()
|
||||
local filePath = DebuggerMakeFileName(editor, ide.openDocuments[id].filePath)
|
||||
if markers >= BREAKPOINT_MARKER_VALUE then
|
||||
editor:MarkerDelete(line, BREAKPOINT_MARKER)
|
||||
if debugger.server then
|
||||
debugger.breakpoint(filePath, line+1, false)
|
||||
end
|
||||
else
|
||||
editor:MarkerAdd(line, BREAKPOINT_MARKER)
|
||||
if debugger.server then
|
||||
debugger.breakpoint(filePath, line+1, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,254 +1,345 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
--
|
||||
-- filetree, treectrl for drive & project
|
||||
--
|
||||
|
||||
ide.filetree = {
|
||||
dirdriveText = "",
|
||||
dirdriveTextArray = {},
|
||||
|
||||
projdirText = "",
|
||||
projdirTextArray = {},
|
||||
|
||||
showroot = true,
|
||||
|
||||
dirdata = {
|
||||
root_id = nil,
|
||||
rootdir = "",
|
||||
},
|
||||
|
||||
projdata = {
|
||||
root_id = nil,
|
||||
rootdir = "",
|
||||
},
|
||||
imglist,
|
||||
|
||||
newfiledir,
|
||||
}
|
||||
local filetree = ide.filetree
|
||||
local frame = ide.frame
|
||||
local sidenotebook = ide.frame.vsplitter.sidenotebook
|
||||
|
||||
|
||||
-- generic tree
|
||||
-- ------------
|
||||
|
||||
do
|
||||
filetree.imglist = wx.wxImageList(16,16)
|
||||
-- 0 = directory
|
||||
filetree.imglist:Add(wx.wxArtProvider.GetIcon(wx.wxART_FOLDER,wx.wxART_TOOLBAR, wx.wxSize(16, 16)))
|
||||
-- 1 = file known spec
|
||||
filetree.imglist:Add(wx.wxArtProvider.GetIcon(wx.wxART_HELP_PAGE ,wx.wxART_TOOLBAR, wx.wxSize(16, 16)))
|
||||
-- 2 = file rest
|
||||
filetree.imglist:Add(wx.wxArtProvider.GetIcon(wx.wxART_NORMAL_FILE,wx.wxART_TOOLBAR, wx.wxSize(16, 16)))
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function treeAddDir(tree,parent_id,rootdir)
|
||||
tree:DeleteChildren(parent_id)
|
||||
local search = rootdir..string_Pathsep.."*.*"
|
||||
local dirs = FileSysGet(search,wx.wxDIR)
|
||||
-- append directories
|
||||
for i,dir in ipairs(dirs) do
|
||||
local dir_id = tree:AppendItem(parent_id, dir:match("(%"..string_Pathsep..stringset_File.."+)$"),0)
|
||||
|
||||
tree:SetItemHasChildren(dir_id,FileSysHasContent(dir))
|
||||
end
|
||||
-- then append files
|
||||
local files = FileSysGet(search,wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
local fname = file:match("%"..string_Pathsep.."("..stringset_File.."+)$")
|
||||
local known = GetSpec(GetFileExt(fname))
|
||||
tree:AppendItem(parent_id, fname,known and 1 or 2)
|
||||
end
|
||||
end
|
||||
|
||||
local function treeGetItemFullName(tree,treedata,item_id,isfile)
|
||||
local str = isfile and string_Pathsep or ""
|
||||
str = str..tree:GetItemText(item_id)
|
||||
local cur = str
|
||||
|
||||
local stop = 4
|
||||
while (#cur > 0) do
|
||||
item_id = tree:GetItemParent(item_id)
|
||||
cur = tree:GetItemText(item_id)
|
||||
str = cur..str
|
||||
end
|
||||
return ((not filetree.showroot) and filetree.projdata.rootdir or "").. str
|
||||
end
|
||||
|
||||
local function treeSetRoot(tree,treedata,rootdir)
|
||||
tree:DeleteAllItems()
|
||||
|
||||
if (not wx.wxDirExists(rootdir)) then
|
||||
treedata.root_id = nil
|
||||
tree:AddRoot("Invalid")
|
||||
return
|
||||
end
|
||||
|
||||
local root_id = tree:AddRoot(rootdir,0)
|
||||
treedata.root_id = root_id
|
||||
treedata.rootdir = rootdir
|
||||
|
||||
treeAddDir(tree,root_id,rootdir)
|
||||
|
||||
filetree.newfiledir = rootdir..string_Pathsep
|
||||
|
||||
tree:Expand(root_id)
|
||||
end
|
||||
|
||||
local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
tree:SetImageList(filetree.imglist)
|
||||
|
||||
-- connect to some events from the wxTreeCtrl
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
local dir = treeGetItemFullName(tree,treedata,item_id)
|
||||
DisplayOutput(dir.."\n")
|
||||
treeAddDir(tree,item_id,dir)
|
||||
|
||||
return true
|
||||
end )
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
tree:DeleteChildren(item_id)
|
||||
|
||||
-- directories must stay expandable if they have content
|
||||
local dir = treeGetItemFullName(tree,treedata,item_id)
|
||||
tree:SetItemHasChildren(item_id,FileSysHasContent(dir))
|
||||
|
||||
return true
|
||||
end )
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
|
||||
if (tree:GetItemImage(item_id) == 0) then return end
|
||||
-- openfile
|
||||
local name = treeGetItemFullName(tree,treedata,item_id,true)
|
||||
LoadFile(name,nil,true)
|
||||
|
||||
end )
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
|
||||
-- set "newfile-path"
|
||||
local isfile = tree:GetItemImage(item_id) ~= 0
|
||||
filetree.newfiledir = treeGetItemFullName(tree,treedata,item_id,isfile)
|
||||
|
||||
if (isfile) then
|
||||
-- remove file
|
||||
filetree.newfiledir = wx.wxFileName(filetree.newfiledir):GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end
|
||||
|
||||
filetree.newfiledir = filetree.newfiledir..string_Pathsep
|
||||
end )
|
||||
end
|
||||
|
||||
-- project
|
||||
-- panel
|
||||
-- ( combobox, button)
|
||||
-- ( treectrl)
|
||||
|
||||
local projpanel = wx.wxPanel(sidenotebook,wx.wxID_ANY)
|
||||
local projcombobox = wx.wxComboBox(projpanel, ID "filetree.proj.drivecb",
|
||||
filetree.projdirText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
filetree.projdirTextArray, wx.wxTE_PROCESS_ENTER)
|
||||
|
||||
|
||||
local projbutton = wx.wxButton(projpanel, ID "debug.projectdir.choose", "...",wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
|
||||
|
||||
|
||||
local projtree = wx.wxTreeCtrl(projpanel, ID "filetree.projtree",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
filetree.showroot
|
||||
and (wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE)
|
||||
or (wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT))
|
||||
|
||||
local projTopSizer = wx.wxBoxSizer( wx.wxHORIZONTAL );
|
||||
projTopSizer:Add(projcombobox, 1, wx.wxALL + wx.wxALIGN_LEFT + wx.wxGROW, 0)
|
||||
projTopSizer:Add(projbutton, 0, wx.wxALL + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE, 0)
|
||||
|
||||
local projSizer = wx.wxBoxSizer( wx.wxVERTICAL );
|
||||
projSizer:Add(projTopSizer, 0, wx.wxALL + wx.wxALIGN_CENTER_HORIZONTAL + wx.wxGROW, 0)
|
||||
projSizer:Add(projtree, 1, wx.wxALL + wx.wxALIGN_LEFT + wx.wxGROW, 0)
|
||||
|
||||
projpanel:SetSizer(projSizer)
|
||||
|
||||
-- proj connectors
|
||||
-- ---------------
|
||||
|
||||
local function projcomboboxUpdate(event)
|
||||
local cur = projcombobox:GetValue()
|
||||
local fn = wx.wxFileName(cur)
|
||||
fn:Normalize()
|
||||
|
||||
filetree:UpdateProjectDir(fn:GetFullPath(), event:GetEventType() == wx.wxEVT_COMMAND_COMBOBOX_SELECTED)
|
||||
end
|
||||
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_COMBOBOX_SELECTED, projcomboboxUpdate)
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_TEXT_ENTER, projcomboboxUpdate)
|
||||
|
||||
|
||||
treeSetConnectorsAndIcons(projtree,filetree.projdata)
|
||||
|
||||
-- proj functions
|
||||
-- ---------------
|
||||
|
||||
|
||||
|
||||
function filetree:UpdateProjectDir(newdir, cboxsel)
|
||||
if (newdir and newdir:sub(-3,-2) == string_Pathsep) then
|
||||
newdir = newdir:sub(0,-2)
|
||||
end
|
||||
|
||||
if ((not newdir) or filetree.projdirText == newdir or not wx.wxDirExists(newdir)) then return end
|
||||
filetree.projdirText = newdir
|
||||
|
||||
--if (not cboxsel) then
|
||||
PrependStringToArray(filetree.projdirTextArray,newdir,ide.config.projecthistorylength)
|
||||
projcombobox:Clear()
|
||||
projcombobox:Append(filetree.projdirTextArray)
|
||||
if (not cboxsel) then
|
||||
projcombobox:SetValue(newdir)
|
||||
--projcombobox:SetValue(newdir)
|
||||
else
|
||||
projcombobox:Select(0)
|
||||
end
|
||||
--end
|
||||
UpdateProjectDir(newdir,true)
|
||||
treeSetRoot(projtree,filetree.projdata,newdir)
|
||||
end
|
||||
|
||||
|
||||
projpanel.projbutton = projbutton
|
||||
projpanel.projcombobox = projcombobox
|
||||
projpanel.projtree = projtree
|
||||
sidenotebook.projpanel = projpanel
|
||||
|
||||
sidenotebook:AddPage(projpanel, "Project",true)
|
||||
|
||||
function GetFileTreeDir()
|
||||
-- atm only projtree
|
||||
--print(ide.frame.vsplitter:IsSplit(),filetree.newfiledir)
|
||||
return ide.frame.vsplitter:IsSplit() and filetree.newfiledir
|
||||
end
|
||||
|
||||
function SetProjects(tab)
|
||||
filetree.projdirTextArray = tab
|
||||
if (tab and tab[1]) then
|
||||
filetree:UpdateProjectDir(tab[1])
|
||||
end
|
||||
end
|
||||
|
||||
function GetProjects()
|
||||
return filetree.projdirTextArray
|
||||
end
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
--
|
||||
-- filetree, treectrl for drive & project
|
||||
--
|
||||
|
||||
ide.filetree = {
|
||||
dirdriveText = "",
|
||||
dirdriveTextArray = {},
|
||||
|
||||
projdirText = "",
|
||||
projdirTextArray = {},
|
||||
|
||||
showroot = true,
|
||||
|
||||
dirdata = {
|
||||
root_id = nil,
|
||||
rootdir = "",
|
||||
},
|
||||
|
||||
projdata = {
|
||||
root_id = nil,
|
||||
rootdir = "",
|
||||
},
|
||||
imglist,
|
||||
|
||||
newfiledir,
|
||||
}
|
||||
local filetree = ide.filetree
|
||||
local frame = ide.frame
|
||||
|
||||
-- generic tree
|
||||
-- ------------
|
||||
|
||||
do
|
||||
local size = wx.wxSize(16, 16)
|
||||
filetree.imglist = wx.wxImageList(16,16)
|
||||
-- 0 = directory
|
||||
filetree.imglist:Add(wx.wxArtProvider.GetBitmap(wx.wxART_FOLDER, wx.wxART_OTHER, size))
|
||||
-- 1 = file known spec
|
||||
filetree.imglist:Add(wx.wxArtProvider.GetBitmap(wx.wxART_HELP_PAGE, wx.wxART_OTHER, size))
|
||||
-- 2 = file rest
|
||||
filetree.imglist:Add(wx.wxArtProvider.GetBitmap(wx.wxART_NORMAL_FILE, wx.wxART_OTHER, size))
|
||||
end
|
||||
|
||||
local function treeAddDir(tree,parent_id,rootdir)
|
||||
local item, cookie = tree:GetFirstChild(parent_id)
|
||||
local items = {}
|
||||
while true do
|
||||
if not item:IsOk() then break end
|
||||
items[tree:GetItemText(item) .. tree:GetItemImage(item)] = item
|
||||
item, cookie = tree:GetNextChild(item, cookie)
|
||||
end
|
||||
|
||||
local curr
|
||||
local search = rootdir..string_Pathsep.."*.*"
|
||||
local dirs = FileSysGet(search,wx.wxDIR)
|
||||
|
||||
-- append directories
|
||||
for i,dir in ipairs(dirs) do
|
||||
local name = dir:match("%"..string_Pathsep.."("..stringset_File.."+)$")
|
||||
local icon = 0
|
||||
local item = items[name .. icon]
|
||||
if item then -- existing item
|
||||
-- keep deleting items until we find item
|
||||
while true do
|
||||
local next = curr and tree:GetNextSibling(curr)
|
||||
or tree:GetFirstChild(parent_id)
|
||||
if not next:IsOk() or name == tree:GetItemText(next) then
|
||||
curr = next
|
||||
break
|
||||
end
|
||||
tree:Delete(next)
|
||||
end
|
||||
else -- new item
|
||||
local dir_id = curr and tree:InsertItem(parent_id, curr, name, icon)
|
||||
or tree:PrependItem(parent_id, name, icon)
|
||||
tree:SetItemHasChildren(dir_id,FileSysHasContent(dir))
|
||||
curr = dir_id
|
||||
end
|
||||
end
|
||||
|
||||
-- then append files
|
||||
local files = FileSysGet(search,wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
local name = file:match("%"..string_Pathsep.."("..stringset_File.."+)$")
|
||||
local known = GetSpec(GetFileExt(fname))
|
||||
local icon = known and 1 or 2
|
||||
local item = items[name .. icon]
|
||||
if item then -- existing item
|
||||
-- keep deleting items until we find item
|
||||
while true do
|
||||
local next = curr and tree:GetNextSibling(curr)
|
||||
or tree:GetFirstChild(parent_id)
|
||||
if not next:IsOk() or name == tree:GetItemText(next) then
|
||||
curr = next
|
||||
break
|
||||
end
|
||||
tree:Delete(next)
|
||||
end
|
||||
else -- new item
|
||||
curr = curr and tree:InsertItem(parent_id, curr, name, icon)
|
||||
or tree:PrependItem(parent_id, name, icon)
|
||||
end
|
||||
end
|
||||
|
||||
-- delete any leftovers (something that exists in the tree, but not on disk)
|
||||
while true do
|
||||
local next = curr and tree:GetNextSibling(curr)
|
||||
or tree:GetFirstChild(parent_id)
|
||||
if not next:IsOk() then break end
|
||||
tree:Delete(next)
|
||||
end
|
||||
|
||||
tree:SetItemHasChildren(parent_id,
|
||||
tree:GetChildrenCount(parent_id, false) > 0)
|
||||
end
|
||||
|
||||
local function treeGetItemFullName(tree,treedata,item_id)
|
||||
local str = tree:GetItemText(item_id)
|
||||
local cur = str
|
||||
|
||||
while (#cur > 0) do
|
||||
item_id = tree:GetItemParent(item_id)
|
||||
cur = tree:GetItemText(item_id)
|
||||
if cur and string.len(cur) > 0 then str = cur..string_Pathsep..str end
|
||||
end
|
||||
return ((not filetree.showroot) and filetree.projdata.rootdir or "")..str
|
||||
end
|
||||
|
||||
local function treeSetRoot(tree,treedata,rootdir)
|
||||
tree:DeleteAllItems()
|
||||
|
||||
if (not wx.wxDirExists(rootdir)) then
|
||||
treedata.root_id = nil
|
||||
tree:AddRoot("Invalid")
|
||||
return
|
||||
end
|
||||
|
||||
local root_id = tree:AddRoot(rootdir,0)
|
||||
treedata.root_id = root_id
|
||||
treedata.rootdir = rootdir
|
||||
|
||||
treeAddDir(tree,root_id,rootdir)
|
||||
filetree.newfiledir = rootdir
|
||||
|
||||
tree:Expand(root_id)
|
||||
end
|
||||
|
||||
local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
tree:SetImageList(filetree.imglist)
|
||||
|
||||
-- connect to some events from the wxTreeCtrl
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
local dir = treeGetItemFullName(tree,treedata,item_id)
|
||||
treeAddDir(tree,item_id,dir)
|
||||
return true
|
||||
end )
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED,
|
||||
function( event )
|
||||
-- don't need to do anything here
|
||||
return true
|
||||
end )
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
|
||||
local name = treeGetItemFullName(tree,treedata,item_id)
|
||||
-- refresh the folder
|
||||
if (tree:GetItemImage(item_id) == 0) then
|
||||
if wx.wxFileName(name):DirExists() then
|
||||
treeAddDir(tree,item_id,name) -- refresh the content
|
||||
else -- stale filetree information; rescan
|
||||
treeAddDir(tree,tree:GetItemParent(item_id),name)
|
||||
end
|
||||
else -- open file
|
||||
if wx.wxFileName(name):FileExists() then
|
||||
LoadFile(name,nil,true)
|
||||
FileTreeMarkSelected(name)
|
||||
else -- stale filetree information; rescan
|
||||
treeAddDir(tree,tree:GetItemParent(item_id),name)
|
||||
end
|
||||
end
|
||||
end )
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
|
||||
-- set "newfile-path"
|
||||
local isfile = tree:GetItemImage(item_id) ~= 0
|
||||
filetree.newfiledir = treeGetItemFullName(tree,treedata,item_id)
|
||||
|
||||
if (isfile) then
|
||||
-- remove file
|
||||
filetree.newfiledir = wx.wxFileName(filetree.newfiledir):GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end
|
||||
|
||||
filetree.newfiledir = filetree.newfiledir..string_Pathsep
|
||||
end )
|
||||
end
|
||||
|
||||
-- project
|
||||
-- panel
|
||||
-- (combobox, button)
|
||||
-- (treectrl)
|
||||
local projpanel = ide.frame.projpanel
|
||||
local projcombobox = wx.wxComboBox(projpanel, ID "filetree.proj.drivecb",
|
||||
filetree.projdirText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
filetree.projdirTextArray, wx.wxTE_PROCESS_ENTER)
|
||||
|
||||
local projbutton = wx.wxButton(projpanel, ID "debug.projectdir.choose", "...",wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
|
||||
local projtree = wx.wxTreeCtrl(projpanel, ID "filetree.projtree",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
filetree.showroot
|
||||
and (wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE)
|
||||
or (wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT))
|
||||
|
||||
-- use the same font in the combobox as is used in the filetree
|
||||
projcombobox:SetFont(projtree:GetFont())
|
||||
|
||||
local projTopSizer = wx.wxBoxSizer( wx.wxHORIZONTAL );
|
||||
projTopSizer:Add(projcombobox, 1, wx.wxALL + wx.wxALIGN_LEFT + wx.wxGROW, 0)
|
||||
projTopSizer:Add(projbutton, 0, wx.wxALL + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE + wx.wxALIGN_CENTER_VERTICAL, 0)
|
||||
|
||||
local projSizer = wx.wxBoxSizer( wx.wxVERTICAL );
|
||||
projSizer:Add(projTopSizer, 0, wx.wxALL + wx.wxALIGN_CENTER_HORIZONTAL + wx.wxGROW, 0)
|
||||
projSizer:Add(projtree, 1, wx.wxALL + wx.wxALIGN_LEFT + wx.wxGROW, 0)
|
||||
|
||||
projpanel:SetSizer(projSizer)
|
||||
|
||||
-- proj connectors
|
||||
-- ---------------
|
||||
|
||||
local function projcomboboxUpdate(event)
|
||||
local cur = projcombobox:GetValue()
|
||||
local fn = wx.wxFileName(cur)
|
||||
fn:Normalize()
|
||||
|
||||
filetree:updateProjectDir(fn:GetFullPath(), event:GetEventType() == wx.wxEVT_COMMAND_COMBOBOX_SELECTED)
|
||||
end
|
||||
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_COMBOBOX_SELECTED, projcomboboxUpdate)
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_TEXT_ENTER, projcomboboxUpdate)
|
||||
|
||||
treeSetConnectorsAndIcons(projtree,filetree.projdata)
|
||||
|
||||
-- proj functions
|
||||
-- ---------------
|
||||
|
||||
function filetree:updateProjectDir(newdir, cboxsel)
|
||||
if (newdir and newdir:sub(-3,-2) == string_Pathsep) then
|
||||
newdir = newdir:sub(0,-2)
|
||||
end
|
||||
|
||||
if ((not newdir) or filetree.projdirText == newdir or not wx.wxDirExists(newdir)) then return end
|
||||
filetree.projdirText = newdir
|
||||
|
||||
PrependStringToArray(filetree.projdirTextArray,newdir,ide.config.projecthistorylength)
|
||||
projcombobox:Clear()
|
||||
projcombobox:Append(filetree.projdirTextArray)
|
||||
if (not cboxsel) then
|
||||
projcombobox:SetValue(newdir)
|
||||
else
|
||||
projcombobox:Select(0)
|
||||
end
|
||||
|
||||
ProjectUpdateProjectDir(newdir,true)
|
||||
treeSetRoot(projtree,filetree.projdata,newdir)
|
||||
|
||||
-- sync with the current editor window and activate selected file
|
||||
local editor = GetEditor()
|
||||
if (editor) then
|
||||
local id = GetEditor():GetId()
|
||||
if ide.openDocuments[id] then
|
||||
FileTreeMarkSelected(ide.openDocuments[id].filePath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
projpanel.projbutton = projbutton
|
||||
projpanel.projcombobox = projcombobox
|
||||
projpanel.projtree = projtree
|
||||
|
||||
function FileTreeGetDir()
|
||||
-- atm only projtree
|
||||
return projpanel:IsShown() and (filetree.newfiledir .. string_Pathsep)
|
||||
end
|
||||
|
||||
function FileTreeSetProjects(tab)
|
||||
filetree.projdirTextArray = tab
|
||||
if (tab and tab[1]) then
|
||||
filetree:updateProjectDir(tab[1])
|
||||
end
|
||||
end
|
||||
|
||||
function FileTreeGetProjects()
|
||||
return filetree.projdirTextArray
|
||||
end
|
||||
|
||||
local function findItem(tree, match)
|
||||
local node = projtree:GetRootItem()
|
||||
local label = tree:GetItemText(node)
|
||||
|
||||
local s, e = string.find(match, label .. string_Pathsep)
|
||||
if not s or s ~= 1 then return end
|
||||
|
||||
for token in string.gmatch(string.sub(match,e+1), "[^%"..string_Pathsep.."]+") do
|
||||
local dir = treeGetItemFullName(tree,filetree.projdata,node)
|
||||
treeAddDir(tree,node,dir)
|
||||
|
||||
local item, cookie = tree:GetFirstChild(node)
|
||||
while true do
|
||||
if not item:IsOk() then return end -- not found
|
||||
if tree:GetItemText(item) == token then
|
||||
node = item
|
||||
break
|
||||
end
|
||||
item, cookie = tree:GetNextChild(item, cookie)
|
||||
end
|
||||
end
|
||||
|
||||
-- this loop exits only when a match is found
|
||||
return node
|
||||
end
|
||||
|
||||
local curr_id
|
||||
function FileTreeMarkSelected(file)
|
||||
if not file then return end
|
||||
local item_id = findItem(projtree, file)
|
||||
if curr_id ~= item_id then
|
||||
if curr_id and projtree:IsBold(curr_id) then
|
||||
projtree:SetItemBold(curr_id, false)
|
||||
end
|
||||
if item_id then
|
||||
projtree:EnsureVisible(item_id)
|
||||
projtree:SetItemBold(item_id, true)
|
||||
curr_id = item_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,213 +1,215 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
-- Lomtik Software (J. Winwood & John Labenski)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
-- Global variables
|
||||
-- Markers for editor marker margin
|
||||
BREAKPOINT_MARKER = 1
|
||||
BREAKPOINT_MARKER_VALUE = 2 -- = 2^BREAKPOINT_MARKER
|
||||
CURRENT_LINE_MARKER = 2
|
||||
CURRENT_LINE_MARKER_VALUE = 4 -- = 2^CURRENT_LINE_MARKER
|
||||
|
||||
-- Globals
|
||||
local font = nil -- fonts to use for the editor
|
||||
local fontItalic = nil
|
||||
local ofont = nil -- fonts to use for the outputshell
|
||||
local ofontItalic = nil
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Pick some reasonable fixed width fonts to use for the editor
|
||||
if wx.__WXMSW__ then
|
||||
font = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "Courier New")
|
||||
fontItalic = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "Courier New")
|
||||
else
|
||||
font = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "")
|
||||
fontItalic = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "")
|
||||
end
|
||||
|
||||
if wx.__WXMSW__ then
|
||||
ofont = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "Courier New")
|
||||
ofontItalic = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "Courier New")
|
||||
else
|
||||
ofont = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "")
|
||||
ofontItalic = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "")
|
||||
end
|
||||
|
||||
ide.font = font
|
||||
ide.fontItalic = fontItalic
|
||||
ide.ofont = ofont
|
||||
ide.ofontItalic = ofontItalic
|
||||
|
||||
-- wxWindow variables
|
||||
local frame = nil -- wxFrame the main top level window
|
||||
local toolBar = nil
|
||||
local funclist = nil
|
||||
local statusBar = nil
|
||||
local menuBar = nil
|
||||
|
||||
local vsplitter = nil
|
||||
local sidenotebook = nil
|
||||
|
||||
local splitter = nil -- wxSplitterWindow for the notebook and errorlog
|
||||
local notebook = nil -- wxNotebook of editors
|
||||
local bottomnotebook = nil -- notebook for the GUIs in the bottom line
|
||||
local errorlog = nil -- wxStyledTextCtrl log window for messages
|
||||
local shellbox = nil -- 2 wxStyledTextCtrl for lua shell
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Create the wxFrame
|
||||
-- ----------------------------------------------------------------------------
|
||||
frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, GetIDEString("editor"))
|
||||
|
||||
menuBar = wx.wxMenuBar()
|
||||
statusBar = frame:CreateStatusBar( 5 )
|
||||
local status_txt_width = statusBar:GetTextExtent("OVRW")
|
||||
statusBar:SetStatusWidths({-1, status_txt_width*6, status_txt_width, status_txt_width, status_txt_width*5})
|
||||
statusBar:SetStatusText(GetIDEString("statuswelcome"))
|
||||
|
||||
frame:DragAcceptFiles(true)
|
||||
frame:Connect(wx.wxEVT_DROP_FILES,function(evt)
|
||||
local files = evt:GetFiles()
|
||||
if not files or #files == 0 then return end
|
||||
for i,f in ipairs(files) do
|
||||
LoadFile(f,nil,true)
|
||||
end
|
||||
end)
|
||||
|
||||
toolBar = frame:CreateToolBar(wx.wxNO_BORDER + wx.wxTB_FLAT + wx.wxTB_DOCKABLE)
|
||||
funclist = wx.wxChoice.new(toolBar,ID "toolBar.funclist",wx.wxDefaultPosition, wx.wxSize.new(300,16))
|
||||
|
||||
-- note: Ususally the bmp size isn't necessary, but the HELP icon is not the right size in MSW
|
||||
local toolBmpSize = toolBar:GetToolBitmapSize()
|
||||
toolBar:AddTool(ID_NEW, "New", wx.wxArtProvider.GetBitmap(wx.wxART_NORMAL_FILE, wx.wxART_MENU, toolBmpSize), "Create an empty document")
|
||||
toolBar:AddTool(ID_OPEN, "Open", wx.wxArtProvider.GetBitmap(wx.wxART_FILE_OPEN, wx.wxART_MENU, toolBmpSize), "Open an existing document")
|
||||
toolBar:AddTool(ID_SAVE, "Save", wx.wxArtProvider.GetBitmap(wx.wxART_FILE_SAVE, wx.wxART_MENU, toolBmpSize), "Save the current document")
|
||||
toolBar:AddTool(ID_SAVEALL, "Save All", wx.wxArtProvider.GetBitmap(wx.wxART_NEW_DIR, wx.wxART_MENU, toolBmpSize), "Save all documents")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_CUT, "Cut", wx.wxArtProvider.GetBitmap(wx.wxART_CUT, wx.wxART_MENU, toolBmpSize), "Cut the selection")
|
||||
toolBar:AddTool(ID_COPY, "Copy", wx.wxArtProvider.GetBitmap(wx.wxART_COPY, wx.wxART_MENU, toolBmpSize), "Copy the selection")
|
||||
toolBar:AddTool(ID_PASTE, "Paste", wx.wxArtProvider.GetBitmap(wx.wxART_PASTE, wx.wxART_MENU, toolBmpSize), "Paste text from the clipboard")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_UNDO, "Undo", wx.wxArtProvider.GetBitmap(wx.wxART_UNDO, wx.wxART_MENU, toolBmpSize), "Undo last edit")
|
||||
toolBar:AddTool(ID_REDO, "Redo", wx.wxArtProvider.GetBitmap(wx.wxART_REDO, wx.wxART_MENU, toolBmpSize), "Redo last undo")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_FIND, "Find", wx.wxArtProvider.GetBitmap(wx.wxART_FIND, wx.wxART_MENU, toolBmpSize), "Find text")
|
||||
toolBar:AddTool(ID_REPLACE, "Replace", wx.wxArtProvider.GetBitmap(wx.wxART_FIND_AND_REPLACE, wx.wxART_MENU, toolBmpSize), "Find and replace text")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID "debug.projectdir.fromfile", "Update", wx.wxArtProvider.GetBitmap(wx.wxART_GO_DIR_UP , wx.wxART_MENU, toolBmpSize), "Sets projectdir from file")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddControl(funclist)
|
||||
toolBar:Realize()
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Add the child windows to the frame
|
||||
|
||||
-- vertical splitter (splitter / sidenotebook)
|
||||
vsplitter = wx.wxSplitterWindow(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxSP_3DSASH)
|
||||
|
||||
|
||||
-- horizontal splitter (notebook,bottomnotebook)
|
||||
splitter = wx.wxSplitterWindow(vsplitter, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxSP_3DSASH)
|
||||
local ph
|
||||
splitter:Connect(wx.wxEVT_SIZE, function (evt)
|
||||
local h = evt:GetSize():GetHeight()
|
||||
ph = ph or h
|
||||
local h2 = ph
|
||||
ph = h
|
||||
local dh = splitter:GetSashPosition()
|
||||
splitter:SetSashPosition(dh-h2+h)
|
||||
splitter:UpdateSize()
|
||||
evt:Skip()
|
||||
end)
|
||||
|
||||
-- notebook for editors
|
||||
notebook = wx.wxNotebook(splitter, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxCLIP_CHILDREN)
|
||||
|
||||
local current -- the currently active editor, needed by the focus selection
|
||||
notebook:Connect(wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
|
||||
function (event)
|
||||
current = event:GetSelection() -- update the active editor reference
|
||||
SetEditorSelection(event:GetSelection())
|
||||
event:Skip() -- skip to let page change
|
||||
end)
|
||||
|
||||
notebook:Connect(wx.wxEVT_SET_FOCUS, -- Notepad tabs shouldn't be selectable,
|
||||
function (event) -- select the editor then instead
|
||||
SetEditorSelection(current) -- select the currently active one.
|
||||
end)
|
||||
|
||||
-- bottomnotebook (errorlog,shellbox)
|
||||
bottomnotebook = wx.wxNotebook(splitter, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxCLIP_CHILDREN)
|
||||
errorlog = wxstc.wxStyledTextCtrl(bottomnotebook, wx.wxID_ANY,wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxBORDER_STATIC)
|
||||
bottomnotebook:AddPage(errorlog, "Output", true)
|
||||
|
||||
shellbox = wx.wxPanel(bottomnotebook,wx.wxID_ANY)
|
||||
shellbox.output = wxstc.wxStyledTextCtrl(shellbox, ID "shellbox.output")
|
||||
shellbox.input = wxstc.wxStyledTextCtrl(shellbox, ID "shellbox.input")
|
||||
shellbox.run = wx.wxButton(shellbox, ID "shellbox.run", "Run")
|
||||
shellbox.remote = wx.wxCheckBox(shellbox, ID "shellbox.remote", "Remote")
|
||||
shellbox.remote:Disable()
|
||||
|
||||
local hsizer = wx.wxFlexGridSizer(0, 1, 0, 0)
|
||||
hsizer:AddGrowableCol(0)
|
||||
hsizer:AddGrowableRow(0)
|
||||
hsizer:Add(shellbox.run, 0, wx.wxGROW+wx.wxALIGN_CENTER_VERTICAL, 0 )
|
||||
hsizer:Add(shellbox.remote, 0, wx.wxGROW+wx.wxALIGN_CENTER_VERTICAL, 0 )
|
||||
|
||||
local vsizer = wx.wxFlexGridSizer(1, 0, 0, 0)
|
||||
vsizer:AddGrowableCol(0)
|
||||
vsizer:AddGrowableRow(0)
|
||||
vsizer:Add(shellbox.input, 0, wx.wxGROW+wx.wxALIGN_CENTER_HORIZONTAL, 0 )
|
||||
vsizer:Add(hsizer, 0, wx.wxGROW+wx.wxALIGN_CENTER_HORIZONTAL, 0 )
|
||||
|
||||
local gridsizer = wx.wxFlexGridSizer(0, 1, 0, 0)
|
||||
gridsizer:AddGrowableCol(0)
|
||||
gridsizer:AddGrowableRow(0)
|
||||
gridsizer:Add(shellbox.output, 0, wx.wxGROW+wx.wxALIGN_CENTER_HORIZONTAL, 0 )
|
||||
gridsizer:Add(vsizer, 0, wx.wxGROW+wx.wxALIGN_CENTER_HORIZONTAL, 0 )
|
||||
shellbox:SetSizer(gridsizer)
|
||||
|
||||
bottomnotebook:AddPage(shellbox, "Lua shell",false)
|
||||
|
||||
|
||||
-- sidenotebook
|
||||
sidenotebook = wx.wxNotebook(vsplitter, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxCLIP_CHILDREN)
|
||||
|
||||
|
||||
-- init splitters
|
||||
splitter:Initialize(notebook)
|
||||
vsplitter:Initialize(splitter)
|
||||
|
||||
|
||||
-------
|
||||
-- hierarchy
|
||||
bottomnotebook.shellbox = shellbox
|
||||
bottomnotebook.errorlog = errorlog
|
||||
|
||||
splitter.bottomnotebook = bottomnotebook
|
||||
splitter.notebook = notebook
|
||||
|
||||
vsplitter.splitter = splitter
|
||||
vsplitter.sidenotebook = sidenotebook
|
||||
|
||||
toolBar.funclist = funclist
|
||||
|
||||
frame.vsplitter = vsplitter
|
||||
frame.toolBar = toolBar
|
||||
frame.statusBar = statusBar
|
||||
frame.menuBar = menuBar
|
||||
|
||||
ide.frame = frame
|
||||
|
||||
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
-- Lomtik Software (J. Winwood & John Labenski)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
-- Global variables
|
||||
-- Markers for editor marker margin
|
||||
BREAKPOINT_MARKER = 1
|
||||
BREAKPOINT_MARKER_VALUE = 2 -- = 2^BREAKPOINT_MARKER
|
||||
CURRENT_LINE_MARKER = 2
|
||||
CURRENT_LINE_MARKER_VALUE = 4 -- = 2^CURRENT_LINE_MARKER
|
||||
|
||||
-- Globals
|
||||
local font = nil -- fonts to use for the editor
|
||||
local fontItalic = nil
|
||||
local ofont = nil -- fonts to use for the outputshell
|
||||
local ofontItalic = nil
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Pick some reasonable fixed width fonts to use for the editor
|
||||
if wx.__WXMSW__ then
|
||||
font = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "Courier New")
|
||||
fontItalic = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "Courier New")
|
||||
else
|
||||
font = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "")
|
||||
fontItalic = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "")
|
||||
end
|
||||
|
||||
if wx.__WXMSW__ then
|
||||
ofont = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "Courier New")
|
||||
ofontItalic = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "Courier New")
|
||||
else
|
||||
ofont = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_NORMAL, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "")
|
||||
ofontItalic = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC, wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "")
|
||||
end
|
||||
|
||||
ide.font = font
|
||||
ide.fontItalic = fontItalic
|
||||
ide.ofont = ofont
|
||||
ide.ofontItalic = ofontItalic
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Create the wxFrame
|
||||
-- ----------------------------------------------------------------------------
|
||||
local function createFrame()
|
||||
frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, GetIDEString("editor"),
|
||||
wx.wxDefaultPosition, wx.wxSize(1000, 700))
|
||||
frame:DragAcceptFiles(true)
|
||||
frame:Connect(wx.wxEVT_DROP_FILES,function(evt)
|
||||
local files = evt:GetFiles()
|
||||
if not files or #files == 0 then return end
|
||||
for i,f in ipairs(files) do
|
||||
LoadFile(f,nil,true)
|
||||
end
|
||||
end)
|
||||
|
||||
local menuBar = wx.wxMenuBar()
|
||||
frame:SetMenuBar(menuBar)
|
||||
frame.menuBar = menuBar
|
||||
|
||||
local statusBar = frame:CreateStatusBar( 5 )
|
||||
frame.statusBar = statusBar
|
||||
local status_txt_width = statusBar:GetTextExtent("OVRW")
|
||||
statusBar:SetStatusWidths({-1, status_txt_width*6, status_txt_width, status_txt_width, status_txt_width*5})
|
||||
statusBar:SetStatusText(GetIDEString("statuswelcome"))
|
||||
|
||||
local mgr = wxaui.wxAuiManager()
|
||||
frame.uimgr = mgr
|
||||
mgr:SetManagedWindow(frame)
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
local function createToolBar(frame)
|
||||
local toolBar = wx.wxToolBar(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxTB_FLAT + wx.wxTB_NODIVIDER)
|
||||
local funclist = wx.wxChoice.new(toolBar,ID "toolBar.funclist",wx.wxDefaultPosition, wx.wxSize.new(240,16))
|
||||
|
||||
-- note: Ususally the bmp size isn't necessary, but the HELP icon is not the right size in MSW
|
||||
local toolBmpSize = toolBar:GetToolBitmapSize()
|
||||
toolBar:AddTool(ID_NEW, "New", wx.wxArtProvider.GetBitmap(wx.wxART_NORMAL_FILE, wx.wxART_TOOLBAR, toolBmpSize), "Create an empty document")
|
||||
toolBar:AddTool(ID_OPEN, "Open", wx.wxArtProvider.GetBitmap(wx.wxART_FILE_OPEN, wx.wxART_TOOLBAR, toolBmpSize), "Open an existing document")
|
||||
toolBar:AddTool(ID_SAVE, "Save", wx.wxArtProvider.GetBitmap(wx.wxART_FILE_SAVE, wx.wxART_TOOLBAR, toolBmpSize), "Save the current document")
|
||||
toolBar:AddTool(ID_SAVEALL, "Save All", wx.wxArtProvider.GetBitmap(wx.wxART_NEW_DIR, wx.wxART_TOOLBAR, toolBmpSize), "Save all documents")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_CUT, "Cut", wx.wxArtProvider.GetBitmap(wx.wxART_CUT, wx.wxART_TOOLBAR, toolBmpSize), "Cut the selection")
|
||||
toolBar:AddTool(ID_COPY, "Copy", wx.wxArtProvider.GetBitmap(wx.wxART_COPY, wx.wxART_TOOLBAR, toolBmpSize), "Copy the selection")
|
||||
toolBar:AddTool(ID_PASTE, "Paste", wx.wxArtProvider.GetBitmap(wx.wxART_PASTE, wx.wxART_TOOLBAR, toolBmpSize), "Paste text from the clipboard")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_UNDO, "Undo", wx.wxArtProvider.GetBitmap(wx.wxART_UNDO, wx.wxART_TOOLBAR, toolBmpSize), "Undo last edit")
|
||||
toolBar:AddTool(ID_REDO, "Redo", wx.wxArtProvider.GetBitmap(wx.wxART_REDO, wx.wxART_TOOLBAR, toolBmpSize), "Redo last undo")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_FIND, "Find", wx.wxArtProvider.GetBitmap(wx.wxART_FIND, wx.wxART_TOOLBAR, toolBmpSize), "Find text")
|
||||
toolBar:AddTool(ID_REPLACE, "Replace", wx.wxArtProvider.GetBitmap(wx.wxART_FIND_AND_REPLACE, wx.wxART_TOOLBAR, toolBmpSize), "Find and replace text")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID "debug.projectdir.fromfile", "Update", wx.wxArtProvider.GetBitmap(wx.wxART_GO_DIR_UP , wx.wxART_TOOLBAR, toolBmpSize), "Sets projectdir from file")
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddControl(funclist)
|
||||
toolBar:Realize()
|
||||
|
||||
toolBar.funclist = funclist
|
||||
frame.toolBar = toolBar
|
||||
return toolBar
|
||||
end
|
||||
|
||||
|
||||
local function createNotebook(frame)
|
||||
-- notebook for editors
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
+ wx.wxNO_BORDER)
|
||||
|
||||
local current -- the currently active editor, needed by the focus selection
|
||||
local function onPageChange(event)
|
||||
current = event:GetSelection() -- update the active editor reference
|
||||
SetEditorSelection(current)
|
||||
event:Skip() -- skip to let page change
|
||||
end
|
||||
|
||||
notebook:Connect(wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, onPageChange)
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, onPageChange)
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE,
|
||||
function (event)
|
||||
ClosePage(event:GetSelection())
|
||||
event:Veto() -- don't propagate the event as the page is already closed
|
||||
end)
|
||||
|
||||
notebook:Connect(wx.wxEVT_SET_FOCUS, -- Notepad tabs shouldn't be selectable,
|
||||
function (event)
|
||||
SetEditorSelection(current) -- select the currently active editor
|
||||
end)
|
||||
|
||||
frame.notebook = notebook
|
||||
return notebook
|
||||
end
|
||||
|
||||
local function createBottomNotebook(frame)
|
||||
-- bottomnotebook (errorlog,shellbox)
|
||||
local bottomnotebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
|
||||
|
||||
local errorlog = wxstc.wxStyledTextCtrl(bottomnotebook, ID "output",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxBORDER_STATIC)
|
||||
|
||||
local shellbox = wxstc.wxStyledTextCtrl(bottomnotebook, ID "shell",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxBORDER_STATIC)
|
||||
|
||||
bottomnotebook:AddPage(errorlog, "Output", true)
|
||||
bottomnotebook:AddPage(shellbox, "Local console", false)
|
||||
bottomnotebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE,
|
||||
function (event)
|
||||
event:Veto() -- don't allow closing pages in this notebook
|
||||
end)
|
||||
|
||||
frame.bottomnotebook = bottomnotebook
|
||||
bottomnotebook.errorlog = errorlog
|
||||
bottomnotebook.shellbox = shellbox
|
||||
|
||||
return bottomnotebook
|
||||
end
|
||||
|
||||
local function createProjpanel(frame)
|
||||
local projpanel = wx.wxPanel(frame,wx.wxID_ANY)
|
||||
frame.projpanel = projpanel
|
||||
return projpanel
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Add the child windows to the frame
|
||||
|
||||
local frame = createFrame()
|
||||
ide.frame = frame
|
||||
createToolBar(frame)
|
||||
createNotebook(frame)
|
||||
createProjpanel(frame)
|
||||
createBottomNotebook(frame)
|
||||
|
||||
do
|
||||
local frame = ide.frame
|
||||
local mgr = frame.uimgr
|
||||
|
||||
mgr:AddPane(frame.toolBar, wxaui.wxAuiPaneInfo():
|
||||
Name("toolBar"):Caption("Main Toolbar"):
|
||||
MinSize(300,16):
|
||||
ToolbarPane():Top():CloseButton(false):
|
||||
LeftDockable(false):RightDockable(false):Hide())
|
||||
|
||||
mgr:AddPane(frame.notebook, wxaui.wxAuiPaneInfo():
|
||||
Name("notebook"):
|
||||
CenterPane():PaneBorder(false):Hide())
|
||||
|
||||
mgr:AddPane(frame.projpanel, wxaui.wxAuiPaneInfo():
|
||||
Name("projpanel"):Caption("Project"):
|
||||
MinSize(200,200):FloatingSize(200,400):
|
||||
Left():Layer(1):Position(1):
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true):Hide())
|
||||
|
||||
mgr:AddPane(frame.bottomnotebook, wxaui.wxAuiPaneInfo():
|
||||
Name("bottomnotebook"):
|
||||
MinSize(200,200):FloatingSize(400,250):
|
||||
Bottom():Layer(1):Position(1):
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true):Hide())
|
||||
|
||||
mgr:GetPane("toolBar"):Show(true)
|
||||
mgr:GetPane("bottomnotebook"):Show(true)
|
||||
mgr:GetPane("projpanel"):Show(true)
|
||||
mgr:GetPane("notebook"):Show(true)
|
||||
|
||||
local pp = mgr:SavePerspective()
|
||||
mgr.defaultPerspective = pp
|
||||
|
||||
mgr:Update()
|
||||
end
|
||||
|
||||
@@ -1,77 +1,78 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
-- Generate a unique new wxWindowID
|
||||
local ID_IDCOUNTER = wx.wxID_HIGHEST + 1
|
||||
function NewID()
|
||||
ID_IDCOUNTER = ID_IDCOUNTER + 1
|
||||
return ID_IDCOUNTER
|
||||
end
|
||||
|
||||
-- File menu
|
||||
ID_NEW = wx.wxID_NEW
|
||||
ID_OPEN = wx.wxID_OPEN
|
||||
ID_CLOSE = NewID()
|
||||
ID_SAVE = wx.wxID_SAVE
|
||||
ID_SAVEAS = wx.wxID_SAVEAS
|
||||
ID_SAVEALL = NewID()
|
||||
ID_EXIT = wx.wxID_EXIT
|
||||
-- Edit menu
|
||||
ID_CUT = wx.wxID_CUT
|
||||
ID_COPY = wx.wxID_COPY
|
||||
ID_PASTE = wx.wxID_PASTE
|
||||
ID_SELECTALL = wx.wxID_SELECTALL
|
||||
ID_UNDO = wx.wxID_UNDO
|
||||
ID_REDO = wx.wxID_REDO
|
||||
ID_AUTOCOMPLETE = NewID()
|
||||
ID_AUTOCOMPLETE_ENABLE = NewID()
|
||||
ID_COMMENT = NewID()
|
||||
ID_FOLD = NewID()
|
||||
-- Find menu
|
||||
ID_FIND = wx.wxID_FIND
|
||||
ID_FINDNEXT = NewID()
|
||||
ID_FINDPREV = NewID()
|
||||
ID_REPLACE = NewID()
|
||||
ID_FIND_IN_FILES = NewID()
|
||||
ID_REPLACE_IN_FILES = NewID()
|
||||
ID_GOTOLINE = NewID()
|
||||
ID_SORT = NewID()
|
||||
-- Debug menu
|
||||
ID_TOGGLEBREAKPOINT = NewID()
|
||||
ID_COMPILE = NewID()
|
||||
ID_RUN = NewID()
|
||||
ID_ATTACH_DEBUG = NewID()
|
||||
ID_START_DEBUG = NewID()
|
||||
--ID_USECONSOLE = NewID()
|
||||
|
||||
ID_STOP_DEBUG = NewID()
|
||||
ID_STEP = NewID()
|
||||
ID_STEP_OVER = NewID()
|
||||
ID_STEP_OUT = NewID()
|
||||
ID_CONTINUE = NewID()
|
||||
ID_BREAK = NewID()
|
||||
--ID_VIEWCALLSTACK = NewID()
|
||||
--ID_VIEWWATCHWINDOW = NewID()
|
||||
ID_CLEAROUTPUT = NewID()
|
||||
ID_DEBUGGER_PORT = NewID()
|
||||
-- Help menu
|
||||
ID_ABOUT = wx.wxID_ABOUT
|
||||
-- Watch window menu items
|
||||
ID_WATCH_LISTCTRL = NewID()
|
||||
ID_ADDWATCH = NewID()
|
||||
ID_EDITWATCH = NewID()
|
||||
ID_REMOVEWATCH = NewID()
|
||||
ID_EVALUATEWATCH = NewID()
|
||||
|
||||
ID_WORKDIR_CHOSE = NewID()
|
||||
|
||||
local ids = {}
|
||||
function ID (name)
|
||||
ids[name] = ids[name] or NewID()
|
||||
return ids[name]
|
||||
end
|
||||
|
||||
function IDget (name)
|
||||
return ids[name]
|
||||
end
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
-- Generate a unique new wxWindowID
|
||||
local ID_IDCOUNTER = wx.wxID_HIGHEST + 1
|
||||
function NewID()
|
||||
ID_IDCOUNTER = ID_IDCOUNTER + 1
|
||||
return ID_IDCOUNTER
|
||||
end
|
||||
|
||||
-- File menu
|
||||
ID_NEW = wx.wxID_NEW
|
||||
ID_OPEN = wx.wxID_OPEN
|
||||
ID_CLOSE = NewID()
|
||||
ID_SAVE = wx.wxID_SAVE
|
||||
ID_SAVEAS = wx.wxID_SAVEAS
|
||||
ID_SAVEALL = NewID()
|
||||
ID_EXIT = wx.wxID_EXIT
|
||||
-- Edit menu
|
||||
ID_CUT = wx.wxID_CUT
|
||||
ID_COPY = wx.wxID_COPY
|
||||
ID_PASTE = wx.wxID_PASTE
|
||||
ID_SELECTALL = wx.wxID_SELECTALL
|
||||
ID_UNDO = wx.wxID_UNDO
|
||||
ID_REDO = wx.wxID_REDO
|
||||
ID_AUTOCOMPLETE = NewID()
|
||||
ID_AUTOCOMPLETE_ENABLE = NewID()
|
||||
ID_COMMENT = NewID()
|
||||
ID_FOLD = NewID()
|
||||
-- Find menu
|
||||
ID_FIND = wx.wxID_FIND
|
||||
ID_FINDNEXT = NewID()
|
||||
ID_FINDPREV = NewID()
|
||||
ID_REPLACE = NewID()
|
||||
ID_FIND_IN_FILES = NewID()
|
||||
ID_REPLACE_IN_FILES = NewID()
|
||||
ID_GOTOLINE = NewID()
|
||||
ID_SORT = NewID()
|
||||
-- Debug menu
|
||||
ID_TOGGLEBREAKPOINT = NewID()
|
||||
ID_COMPILE = NewID()
|
||||
ID_RUN = NewID()
|
||||
ID_ATTACH_DEBUG = NewID()
|
||||
ID_START_DEBUG = NewID()
|
||||
--ID_USECONSOLE = NewID()
|
||||
|
||||
ID_STOP_DEBUG = NewID()
|
||||
ID_STEP = NewID()
|
||||
ID_STEP_OVER = NewID()
|
||||
ID_STEP_OUT = NewID()
|
||||
ID_CONTINUE = NewID()
|
||||
ID_BREAK = NewID()
|
||||
ID_TRACE = NewID()
|
||||
--ID_VIEWCALLSTACK = NewID()
|
||||
--ID_VIEWWATCHWINDOW = NewID()
|
||||
ID_CLEAROUTPUT = NewID()
|
||||
ID_DEBUGGER_PORT = NewID()
|
||||
-- Help menu
|
||||
ID_ABOUT = wx.wxID_ABOUT
|
||||
-- Watch window menu items
|
||||
ID_WATCH_LISTCTRL = NewID()
|
||||
ID_ADDWATCH = NewID()
|
||||
ID_EDITWATCH = NewID()
|
||||
ID_REMOVEWATCH = NewID()
|
||||
ID_EVALUATEWATCH = NewID()
|
||||
|
||||
ID_WORKDIR_CHOSE = NewID()
|
||||
|
||||
local ids = {}
|
||||
function ID (name)
|
||||
ids[name] = ids[name] or NewID()
|
||||
return ids[name]
|
||||
end
|
||||
|
||||
function IDget (name)
|
||||
return ids[name]
|
||||
end
|
||||
|
||||
@@ -1,61 +1,59 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
ide.iofilters["GermanUtf8Ascii"] = {
|
||||
|
||||
-- this function converts some utf8 character output. It's a hack.
|
||||
-- Since luxinia is not utf8 prepared, this is still necessary.
|
||||
-- if you wish to turn this off, edit user.lua and set this filefunction to nil
|
||||
output = function (fpath, content)
|
||||
local utf8escape = ("string").char(195)
|
||||
-- only simple cases are handled (umlauts)
|
||||
local chr = ("string").char
|
||||
local charconv = {
|
||||
[chr(164)] = chr(228), -- ä
|
||||
[chr(182)] = chr(246), -- ö
|
||||
[chr(188)] = chr(252), -- ü
|
||||
[chr(132)] = chr(196), -- Ä
|
||||
[chr(150)] = chr(214), -- Ö
|
||||
[chr(156)] = chr(220), -- Ü
|
||||
[chr(159)] = chr(223), -- ß
|
||||
}
|
||||
return content : gsub (utf8escape.."(.)",charconv)
|
||||
end,
|
||||
|
||||
|
||||
-- this function is another hack to read an ANSI encoded
|
||||
-- file and converts the umlauts to utf8 chars
|
||||
input = function (fpath, content)
|
||||
local utf8escape = ("string").char(195)
|
||||
local chr = ("string").char
|
||||
local charconv = {
|
||||
[chr(228)] = utf8escape..chr(164), -- ä
|
||||
[chr(246)] = utf8escape..chr(182), -- ö
|
||||
[chr(252)] = utf8escape..chr(188), -- ü
|
||||
[chr(196)] = utf8escape..chr(132), -- Ä
|
||||
[chr(214)] = utf8escape..chr(150), -- Ö
|
||||
[chr(220)] = utf8escape..chr(156), -- Ü
|
||||
[chr(223)] = utf8escape..chr(159), -- ß
|
||||
}
|
||||
local lst = "["
|
||||
for k in pairs(charconv) do lst = lst .. k end
|
||||
lst = "]"
|
||||
|
||||
return content:gsub(lst,charconv)
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
--üäß
|
||||
|
||||
for i,filter in pairs(ide.iofilters) do
|
||||
assert(filter.output("",filter.input("","äöüÄÖÜß")),"„â€ÂäöüÄÖÜß","UTF8-ANSI conversion failed: "..(i))
|
||||
end
|
||||
|
||||
-- which: "input" or "output"
|
||||
function GetConfigIOFilter(which)
|
||||
local filtername = ide.config.editor.iofilter
|
||||
return (filtername and ide.iofilters[filtername] and ide.iofilters[filtername][which])
|
||||
end
|
||||
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
ide.iofilters["GermanUtf8Ascii"] = {
|
||||
|
||||
-- this function converts some utf8 character output. It's a hack.
|
||||
-- Since luxinia is not utf8 prepared, this is still necessary.
|
||||
-- if you wish to turn this off, edit user.lua and set this filefunction to nil
|
||||
output = function (fpath, content)
|
||||
local utf8escape = ("string").char(195)
|
||||
-- only simple cases are handled (umlauts)
|
||||
local chr = ("string").char
|
||||
local charconv = {
|
||||
[chr(164)] = chr(228), -- ä
|
||||
[chr(182)] = chr(246), -- ö
|
||||
[chr(188)] = chr(252), -- ü
|
||||
[chr(132)] = chr(196), -- Ä
|
||||
[chr(150)] = chr(214), -- Ö
|
||||
[chr(156)] = chr(220), -- Ü
|
||||
[chr(159)] = chr(223), -- ß
|
||||
}
|
||||
return content : gsub (utf8escape.."(.)",charconv)
|
||||
end,
|
||||
|
||||
-- this function is another hack to read an ANSI encoded
|
||||
-- file and converts the umlauts to utf8 chars
|
||||
input = function (fpath, content)
|
||||
local utf8escape = ("string").char(195)
|
||||
local chr = ("string").char
|
||||
local charconv = {
|
||||
[chr(228)] = utf8escape..chr(164), -- ä
|
||||
[chr(246)] = utf8escape..chr(182), -- ö
|
||||
[chr(252)] = utf8escape..chr(188), -- ü
|
||||
[chr(196)] = utf8escape..chr(132), -- Ä
|
||||
[chr(214)] = utf8escape..chr(150), -- Ö
|
||||
[chr(220)] = utf8escape..chr(156), -- Ü
|
||||
[chr(223)] = utf8escape..chr(159), -- ß
|
||||
}
|
||||
local lst = "["
|
||||
for k in pairs(charconv) do lst = lst .. k end
|
||||
lst = "]"
|
||||
|
||||
return content:gsub(lst,charconv)
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
--üäß
|
||||
|
||||
for i,filter in pairs(ide.iofilters) do
|
||||
assert(filter.output("",filter.input("","äöüÄÖÜß")),"„â€ÂäöüÄÖÜß","UTF8-ANSI conversion failed: "..(i))
|
||||
end
|
||||
|
||||
-- which: "input" or "output"
|
||||
function GetConfigIOFilter(which)
|
||||
local filtername = ide.config.editor.iofilter
|
||||
return (filtername and ide.iofilters[filtername] and ide.iofilters[filtername][which])
|
||||
end
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
dofile "src/editor/menu_file.lua"
|
||||
dofile "src/editor/menu_edit.lua"
|
||||
dofile "src/editor/menu_search.lua"
|
||||
dofile "src/editor/menu_view.lua"
|
||||
dofile "src/editor/menu_project.lua"
|
||||
dofile "src/editor/menu_tools.lua"
|
||||
|
||||
ide.frame:SetMenuBar(ide.frame.menuBar )
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
dofile "src/editor/menu_file.lua"
|
||||
dofile "src/editor/menu_edit.lua"
|
||||
dofile "src/editor/menu_search.lua"
|
||||
dofile "src/editor/menu_view.lua"
|
||||
dofile "src/editor/menu_project.lua"
|
||||
dofile "src/editor/menu_tools.lua"
|
||||
|
||||
ide.frame:SetMenuBar(ide.frame.menuBar )
|
||||
|
||||
@@ -1,199 +1,177 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Create the Edit menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
|
||||
|
||||
local editMenu = wx.wxMenu{
|
||||
{ ID_CUT, "Cu&t\tCtrl-X", "Cut selected text to clipboard" },
|
||||
{ ID_COPY, "&Copy\tCtrl-C", "Copy selected text to the clipboard" },
|
||||
{ ID_PASTE, "&Paste\tCtrl-V", "Insert clipboard text at cursor" },
|
||||
{ ID_SELECTALL, "Select A&ll\tCtrl-A", "Select all text in the editor" },
|
||||
{ },
|
||||
{ ID_UNDO, "&Undo\tCtrl-Z", "Undo the last action" },
|
||||
{ ID_REDO, "&Redo\tCtrl-Y", "Redo the last action undone" },
|
||||
{ },
|
||||
{ ID "edit.showtooltip", "Show &Tooltip\tCtrl+T", "Show tooltip for current position. Place cursor after opening bracket of function."},
|
||||
{ ID_AUTOCOMPLETE, "Complete &Identifier\tCtrl+K", "Complete the current identifier" },
|
||||
{ ID_AUTOCOMPLETE_ENABLE, "Auto complete Identifiers", "Auto complete while typing", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID_COMMENT, "C&omment/Uncomment\tCtrl-Q", "Comment or uncomment current or selected lines"},
|
||||
{ },
|
||||
{ ID_FOLD, "&Fold/Unfold all\tF12", "Fold or unfold all code folds"} }
|
||||
menuBar:Append(editMenu, "&Edit")
|
||||
|
||||
editMenu:Check(ID_AUTOCOMPLETE_ENABLE, ide.config.autocomplete)
|
||||
|
||||
function OnUpdateUIEditMenu(event) -- enable if there is a valid focused editor
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor ~= nil)
|
||||
end
|
||||
|
||||
local shellboxeditor = ide.frame.vsplitter.splitter.bottomnotebook.shellbox.input
|
||||
function OnEditMenu(event)
|
||||
|
||||
local menu_id = event:GetId()
|
||||
local editor = GetEditor()
|
||||
if shellboxeditor:FindFocus():GetId() == shellboxeditor:GetId() then
|
||||
editor = shellboxeditor
|
||||
end
|
||||
if editor == nil then return end
|
||||
|
||||
if menu_id == ID_CUT then editor:Cut()
|
||||
elseif menu_id == ID_COPY then editor:Copy()
|
||||
elseif menu_id == ID_PASTE then editor:Paste()
|
||||
elseif menu_id == ID_SELECTALL then editor:SelectAll()
|
||||
elseif menu_id == ID_UNDO then editor:Undo()
|
||||
elseif menu_id == ID_REDO then editor:Redo()
|
||||
end
|
||||
end
|
||||
|
||||
frame:Connect(ID_CUT, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_CUT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_COPY, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_COPY, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_PASTE, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_PASTE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
-- buggy GTK clipboard runs eventloop and can generate asserts
|
||||
event:Enable(editor and (wx.__WXGTK__ or editor:CanPaste()))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SELECTALL, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_SELECTALL, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_UNDO, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_UNDO, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor and editor:CanUndo())
|
||||
end)
|
||||
|
||||
frame:Connect(ID_REDO, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_REDO, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor and editor:CanRedo())
|
||||
end)
|
||||
|
||||
frame:Connect(ID "edit.showtooltip", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local pos = editor:GetCurrentPos()
|
||||
local line = editor:GetCurrentLine()
|
||||
local linetx = editor:GetLine(line)
|
||||
local linestart = editor:PositionFromLine(line)
|
||||
local localpos = pos-linestart
|
||||
|
||||
linetxtopos = linetx:sub(1,localpos)
|
||||
linetxtopos = linetxtopos..")"
|
||||
linetxtopos = linetxtopos:match("([a-zA-Z_0-9%.%:]+)%b()$")
|
||||
|
||||
local tip = linetxtopos and GetTipInfo(editor,linetxtopos.."(",false)
|
||||
if tip then
|
||||
if(editor:CallTipActive()) then
|
||||
editor:CallTipCancel()
|
||||
end
|
||||
editor:CallTipShow(pos,tip)
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_AUTOCOMPLETE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if (editor == nil or not editor.spec) then return end
|
||||
|
||||
-- retrieve the current line and get a string to the current cursor position in the line
|
||||
local pos = editor:GetCurrentPos()
|
||||
local line = editor:GetCurrentLine()
|
||||
local linetx = editor:GetLine(line)
|
||||
local linestart = editor:PositionFromLine(line)
|
||||
local localpos = pos-linestart
|
||||
|
||||
|
||||
local lt = linetx:sub(1,localpos)
|
||||
lt = lt:gsub("%s*("..editor.spec.sep..")%s*",function(a) return a end)
|
||||
lt = lt:gsub("%s*%b[]%s*","")
|
||||
lt = lt:gsub("%s*%b()%s*","")
|
||||
lt = lt:gsub("%s*%b{}%s*","")
|
||||
lt = lt:match("[^%[%(%s]*$")
|
||||
lt = lt:gsub("%s","")
|
||||
|
||||
|
||||
--[[
|
||||
local acstart = 1
|
||||
local state = ""
|
||||
for i=localpos,1,-1 do -- find out what should be completed
|
||||
local c = linetx:sub(i,i)
|
||||
if c : match "[%s]" and state~="begin" then
|
||||
state = "space"
|
||||
elseif c : match "[_0-9a-zA-Z]" then
|
||||
if state == "space" then
|
||||
acstart = i+1
|
||||
break
|
||||
end
|
||||
state = "word"
|
||||
elseif c : match(editor.spec.sep) then
|
||||
state = "begin"
|
||||
elseif c : match "[^%s]" then -- unknown char
|
||||
acstart = i + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
local lt = linetx:sub(acstart,localpos) : gsub("%s","")
|
||||
]]
|
||||
|
||||
-- know now which string is to be completed
|
||||
|
||||
local userList = CreateAutoCompList(editor,lt)
|
||||
if userList and string.len(userList) > 0 then
|
||||
editor:UserListShow(1, userList)
|
||||
--ShowList(userList)
|
||||
elseif (editor:AutoCompActive()) then
|
||||
editor:AutoCompCancel()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_AUTOCOMPLETE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_AUTOCOMPLETE_ENABLE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ide.config.autocomplete = event:IsChecked()
|
||||
end)
|
||||
|
||||
frame:Connect(ID_COMMENT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local buf = {}
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd() then
|
||||
local lineNumber = editor:GetCurrentLine()
|
||||
editor:SetSelection(editor:PositionFromLine(lineNumber), editor:GetLineEndPosition(lineNumber))
|
||||
end
|
||||
local lc = editor.spec.linecomment
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
if string.sub(line,1,2) == lc then
|
||||
line = string.sub(line,3)
|
||||
else
|
||||
line = lc..line
|
||||
end
|
||||
table.insert(buf, line)
|
||||
end
|
||||
editor:ReplaceSelection(table.concat(buf,"\n"))
|
||||
end)
|
||||
frame:Connect(ID_COMMENT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
|
||||
frame:Connect(ID_FOLD, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
FoldSome()
|
||||
end)
|
||||
frame:Connect(ID_FOLD, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Create the Edit menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local editMenu = wx.wxMenu{
|
||||
{ ID_CUT, "Cu&t\tCtrl-X", "Cut selected text to clipboard" },
|
||||
{ ID_COPY, "&Copy\tCtrl-C", "Copy selected text to the clipboard" },
|
||||
{ ID_PASTE, "&Paste\tCtrl-V", "Insert clipboard text at cursor" },
|
||||
{ ID_SELECTALL, "Select A&ll\tCtrl-A", "Select all text in the editor" },
|
||||
{ },
|
||||
{ ID_UNDO, "&Undo\tCtrl-Z", "Undo the last action" },
|
||||
{ ID_REDO, "&Redo\tCtrl-Y", "Redo the last action undone" },
|
||||
{ },
|
||||
{ ID "edit.showtooltip", "Show &Tooltip\tCtrl+T", "Show tooltip for current position. Place cursor after opening bracket of function."},
|
||||
{ ID_AUTOCOMPLETE, "Complete &Identifier\tCtrl+K", "Complete the current identifier" },
|
||||
{ ID_AUTOCOMPLETE_ENABLE, "Auto complete Identifiers", "Auto complete while typing", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID_COMMENT, "C&omment/Uncomment\tCtrl-Q", "Comment or uncomment current or selected lines"},
|
||||
{ },
|
||||
{ ID_FOLD, "&Fold/Unfold all\tF12", "Fold or unfold all code folds"},
|
||||
{ ID "edit.cleardynamics", "Clear &Dynamic Words", "Resets the dynamic word list for autcompletion."},
|
||||
}
|
||||
menuBar:Append(editMenu, "&Edit")
|
||||
|
||||
editMenu:Check(ID_AUTOCOMPLETE_ENABLE, ide.config.autocomplete)
|
||||
|
||||
function OnUpdateUIEditMenu(event) -- enable if there is a valid focused editor
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor ~= nil)
|
||||
end
|
||||
|
||||
local shellboxeditor = ide.frame.bottomnotebook.shellbox
|
||||
|
||||
function OnEditMenu(event)
|
||||
local menu_id = event:GetId()
|
||||
local editor = GetEditor()
|
||||
if shellboxeditor:FindFocus():GetId() == shellboxeditor:GetId() then
|
||||
editor = shellboxeditor
|
||||
end
|
||||
if editor == nil then return end
|
||||
|
||||
if menu_id == ID_CUT then editor:Cut()
|
||||
elseif menu_id == ID_COPY then editor:Copy()
|
||||
elseif menu_id == ID_PASTE then editor:Paste()
|
||||
elseif menu_id == ID_SELECTALL then editor:SelectAll()
|
||||
elseif menu_id == ID_UNDO then editor:Undo()
|
||||
elseif menu_id == ID_REDO then editor:Redo()
|
||||
end
|
||||
end
|
||||
|
||||
frame:Connect(ID_CUT, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_CUT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_COPY, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_COPY, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_PASTE, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_PASTE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
-- buggy GTK clipboard runs eventloop and can generate asserts
|
||||
event:Enable(editor and (wx.__WXGTK__ or editor:CanPaste()))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SELECTALL, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_SELECTALL, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_UNDO, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_UNDO, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor and editor:CanUndo())
|
||||
end)
|
||||
|
||||
frame:Connect(ID_REDO, wx.wxEVT_COMMAND_MENU_SELECTED, OnEditMenu)
|
||||
frame:Connect(ID_REDO, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor and editor:CanRedo())
|
||||
end)
|
||||
|
||||
frame:Connect(ID "edit.cleardynamics", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
DynamicWordsReset()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "edit.showtooltip", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local pos = editor:GetCurrentPos()
|
||||
local line = editor:GetCurrentLine()
|
||||
local linetx = editor:GetLine(line)
|
||||
local linestart = editor:PositionFromLine(line)
|
||||
local localpos = pos-linestart
|
||||
|
||||
linetxtopos = linetx:sub(1,localpos)
|
||||
linetxtopos = linetxtopos..")"
|
||||
linetxtopos = linetxtopos:match("([a-zA-Z_0-9%.%:]+)%b()$")
|
||||
|
||||
local tip = linetxtopos and GetTipInfo(editor,linetxtopos.."(",false)
|
||||
if tip then
|
||||
if(editor:CallTipActive()) then
|
||||
editor:CallTipCancel()
|
||||
end
|
||||
editor:CallTipShow(pos,tip)
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_AUTOCOMPLETE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if (editor == nil or not editor.spec) then return end
|
||||
|
||||
-- retrieve the current line and get a string to the current cursor position in the line
|
||||
local pos = editor:GetCurrentPos()
|
||||
local line = editor:GetCurrentLine()
|
||||
local linetx = editor:GetLine(line)
|
||||
local linestart = editor:PositionFromLine(line)
|
||||
local localpos = pos-linestart
|
||||
|
||||
local lt = linetx:sub(1,localpos)
|
||||
lt = lt:gsub("%s*("..editor.spec.sep..")%s*",function(a) return a end)
|
||||
lt = lt:gsub("%s*%b[]%s*","")
|
||||
lt = lt:gsub("%s*%b()%s*","")
|
||||
lt = lt:gsub("%s*%b{}%s*","")
|
||||
lt = lt:match("[^%[%(%s]*$")
|
||||
lt = lt:gsub("%s","")
|
||||
|
||||
-- know now which string is to be completed
|
||||
|
||||
local userList = CreateAutoCompList(editor,lt)
|
||||
if userList and string.len(userList) > 0 then
|
||||
editor:UserListShow(1, userList)
|
||||
--ShowList(userList)
|
||||
elseif (editor:AutoCompActive()) then
|
||||
editor:AutoCompCancel()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_AUTOCOMPLETE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_AUTOCOMPLETE_ENABLE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ide.config.autocomplete = event:IsChecked()
|
||||
end)
|
||||
|
||||
frame:Connect(ID_COMMENT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local buf = {}
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd() then
|
||||
local lineNumber = editor:GetCurrentLine()
|
||||
editor:SetSelection(editor:PositionFromLine(lineNumber), editor:GetLineEndPosition(lineNumber))
|
||||
end
|
||||
local lc = editor.spec.linecomment
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
if string.sub(line,1,2) == lc then
|
||||
line = string.sub(line,3)
|
||||
else
|
||||
line = lc..line
|
||||
end
|
||||
table.insert(buf, line)
|
||||
end
|
||||
editor:ReplaceSelection(table.concat(buf,"\n"))
|
||||
end)
|
||||
frame:Connect(ID_COMMENT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_FOLD, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
FoldSome()
|
||||
end)
|
||||
frame:Connect(ID_FOLD, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
@@ -1,125 +1,113 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- Create the File menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local openDocuments = ide.openDocuments
|
||||
local debugger = ide.debugger
|
||||
|
||||
local fileMenu = wx.wxMenu({
|
||||
{ ID_NEW, "&New\tCtrl-N", "Create an empty document" },
|
||||
{ ID_OPEN, "&Open...\tCtrl-O", "Open an existing document" },
|
||||
{ ID_CLOSE, "&Close page\tCtrl+W", "Close the current editor window" },
|
||||
{ },
|
||||
{ ID_SAVE, "&Save\tCtrl-S", "Save the current document" },
|
||||
{ ID_SAVEAS, "Save &As...\tAlt-Shift-S", "Save the current document to a file with a new name" },
|
||||
{ ID_SAVEALL, "Save A&ll...\tCtrl-Shift-S", "Save all open documents" },
|
||||
{ },
|
||||
--{ ID "file.recentfiles", "Recent files",},
|
||||
{ },
|
||||
{ ID_EXIT, "E&xit\tAlt-X", "Exit Program" }})
|
||||
menuBar:Append(fileMenu, "&File")
|
||||
|
||||
local filehistorymenu = wx.wxMenu({})
|
||||
local filehistory = wx.wxMenuItem(fileMenu,ID"file.recentfiles","Recent files", "File history", wx.wxITEM_NORMAL,filehistorymenu)
|
||||
fileMenu:Insert(8,filehistory)
|
||||
function UpdateFileHistoryUI(list)
|
||||
-- remove all at first
|
||||
for i=1,filehistorymenu:GetMenuItemCount() do
|
||||
filehistorymenu:Delete( ID("file.recentfiles."..i))
|
||||
end
|
||||
for i=1,#list do
|
||||
local file = list[i].filename
|
||||
local item = wx.wxMenuItem(filehistorymenu, ID("file.recentfiles."..i),file,"")
|
||||
filehistorymenu:Append(item)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,ide.config.filehistorylength do
|
||||
frame:Connect(ID("file.recentfiles."..i), wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local item = filehistorymenu:FindItemByPosition(i-1)
|
||||
local filename = item:GetLabel()
|
||||
LoadFile(filename)
|
||||
--DisplayOutput("selected "..tostring(filename).."\n")
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, NewFile)
|
||||
frame:Connect(ID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, OpenFile)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local id = editor:GetId()
|
||||
local filePath = openDocuments[id].filePath
|
||||
if (filePath) then
|
||||
SaveFile(editor, filePath)
|
||||
else
|
||||
SaveFileAs(editor)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if editor then
|
||||
local id = editor:GetId()
|
||||
if openDocuments[id] then
|
||||
event:Enable(openDocuments[id].isModified or not openDocuments[id].filePath)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
SaveFileAs(editor)
|
||||
end)
|
||||
frame:Connect(ID_SAVEAS, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor ~= nil)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEALL, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
SaveAll()
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEALL, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local atLeastOneModifiedDocument = false
|
||||
for id, document in pairs(openDocuments) do
|
||||
if document.isModified then
|
||||
atLeastOneModifiedDocument = true
|
||||
break
|
||||
end
|
||||
end
|
||||
event:Enable(atLeastOneModifiedDocument)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_CLOSE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local id = editor:GetId()
|
||||
if SaveModifiedDialog(editor, true) ~= wx.wxID_CANCEL then
|
||||
RemovePage(openDocuments[id].index)
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_CLOSE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((GetEditor() ~= nil) and (debugger.server == nil))
|
||||
end)
|
||||
|
||||
|
||||
frame:Connect( ID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if not SaveOnExit(true) then return end
|
||||
frame:Close() -- will handle wxEVT_CLOSE_WINDOW
|
||||
CloseWatchWindow()
|
||||
end)
|
||||
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- Create the File menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local openDocuments = ide.openDocuments
|
||||
local debugger = ide.debugger
|
||||
|
||||
local fileMenu = wx.wxMenu({
|
||||
{ ID_NEW, "&New\tCtrl-N", "Create an empty document" },
|
||||
{ ID_OPEN, "&Open...\tCtrl-O", "Open an existing document" },
|
||||
{ ID_CLOSE, "&Close page\tCtrl+W", "Close the current editor window" },
|
||||
{ },
|
||||
{ ID_SAVE, "&Save\tCtrl-S", "Save the current document" },
|
||||
{ ID_SAVEAS, "Save &As...\tAlt-Shift-S", "Save the current document to a file with a new name" },
|
||||
{ ID_SAVEALL, "Save A&ll...\tCtrl-Shift-S", "Save all open documents" },
|
||||
{ },
|
||||
--{ ID "file.recentfiles", "Recent files",},
|
||||
{ },
|
||||
{ ID_EXIT, "E&xit\tAlt-X", "Exit Program" }})
|
||||
menuBar:Append(fileMenu, "&File")
|
||||
|
||||
local filehistorymenu = wx.wxMenu({})
|
||||
local filehistory = wx.wxMenuItem(fileMenu,ID"file.recentfiles","Recent files", "File history", wx.wxITEM_NORMAL,filehistorymenu)
|
||||
fileMenu:Insert(8,filehistory)
|
||||
function UpdateFileHistoryUI(list)
|
||||
-- remove all at first
|
||||
for i=1,filehistorymenu:GetMenuItemCount() do
|
||||
filehistorymenu:Delete( ID("file.recentfiles."..i))
|
||||
end
|
||||
for i=1,#list do
|
||||
local file = list[i].filename
|
||||
local item = wx.wxMenuItem(filehistorymenu, ID("file.recentfiles."..i),file,"")
|
||||
filehistorymenu:Append(item)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,ide.config.filehistorylength do
|
||||
frame:Connect(ID("file.recentfiles."..i), wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local item = filehistorymenu:FindItemByPosition(i-1)
|
||||
local filename = item:GetLabel()
|
||||
LoadFile(filename)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, NewFile)
|
||||
frame:Connect(ID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, OpenFile)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local id = editor:GetId()
|
||||
local filePath = openDocuments[id].filePath
|
||||
if (filePath) then
|
||||
SaveFile(editor, filePath)
|
||||
else
|
||||
SaveFileAs(editor)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if editor then
|
||||
local id = editor:GetId()
|
||||
if openDocuments[id] then
|
||||
event:Enable(openDocuments[id].isModified or not openDocuments[id].filePath)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
SaveFileAs(editor)
|
||||
end)
|
||||
frame:Connect(ID_SAVEAS, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor ~= nil)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEALL, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
SaveAll()
|
||||
end)
|
||||
frame:Connect(ID_SAVEALL, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local atLeastOneModifiedDocument = false
|
||||
for id, document in pairs(openDocuments) do
|
||||
if document.isModified then
|
||||
atLeastOneModifiedDocument = true
|
||||
break
|
||||
end
|
||||
end
|
||||
event:Enable(atLeastOneModifiedDocument)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_CLOSE, wx.wxEVT_COMMAND_MENU_SELECTED, ClosePage)
|
||||
frame:Connect(ID_CLOSE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((GetEditor() ~= nil) and (debugger.server == nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if not SaveOnExit(true) then return end
|
||||
frame:Close() -- will handle wxEVT_CLOSE_WINDOW
|
||||
DebuggerCloseWatchWindow()
|
||||
end)
|
||||
|
||||
@@ -1,331 +1,347 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
-- Create the Debug menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local vsplitter= frame.vsplitter
|
||||
local sidenotebook = vsplitter.sidenotebook
|
||||
local splitter = vsplitter.splitter
|
||||
local errorlog = splitter.bottomnotebook.errorlog
|
||||
local notebook = splitter.notebook
|
||||
|
||||
local openDocuments = ide.openDocuments
|
||||
local debugger = ide.debugger
|
||||
local filetree = ide.filetree
|
||||
|
||||
--------------
|
||||
-- Interpreters
|
||||
local interpreters = {}
|
||||
local lastinterpreter
|
||||
for i,v in pairs(ide.interpreters) do
|
||||
interpreters[ID ("debug.interpreter."..i)] = v
|
||||
v.fname = i
|
||||
lastinterpreter = v.name
|
||||
end
|
||||
assert(lastinterpreter,"no interpreters defined")
|
||||
|
||||
local debugMenu = wx.wxMenu{
|
||||
{ ID_RUN, "&Run\tShift-F5", "Execute the current project/file" },
|
||||
{ ID_COMPILE, "&Compile\tF7", "Test compile the Lua file" },
|
||||
--{ ID_ATTACH_DEBUG, "&Attach\tShift-F6", "Allow a client to start a debugging session" },
|
||||
{ ID_START_DEBUG, "&Start Debugging\tF5", "Start a debugging session" },
|
||||
--{ ID_USECONSOLE, "Console", "Use console when running", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID_STOP_DEBUG, "S&top Debugging\tShift-F12", "Stop and end the debugging session" },
|
||||
{ ID_STEP, "St&ep\tF11", "Step into the next line" },
|
||||
{ ID_STEP_OVER, "Step &Over\tF10", "Step over the next line" },
|
||||
{ ID_STEP_OUT, "Step O&ut\tShift-F10", "Step out of the current function" },
|
||||
{ ID_CONTINUE, "Co&ntinue\tF6", "Run the program at full speed" },
|
||||
{ ID_BREAK, "&Break", "Stop execution of the program at the next executed line of code" },
|
||||
{ },
|
||||
{ ID_TOGGLEBREAKPOINT, "Toggle &Breakpoint\tF9", "Toggle Breakpoint" },
|
||||
--{ ID "view.debug.callstack", "V&iew Call Stack", "View the LUA call stack" },
|
||||
{ ID "view.debug.watches", "View &Watch Window", "View the Watch window" },
|
||||
{ },
|
||||
{ ID_CLEAROUTPUT, "C&lear Output Window", "Clear the output window before compiling or debugging", wx.wxITEM_CHECK },
|
||||
--{ }, { ID_DEBUGGER_PORT, "Set debugger socket port...", "Chose what port to use for debugger sockets." },
|
||||
}
|
||||
|
||||
local targetargs = {}
|
||||
for id,inter in pairs(interpreters) do
|
||||
table.insert(targetargs,{id,inter.name,inter.description,wx.wxITEM_CHECK})
|
||||
end
|
||||
local target = wx.wxMenu{
|
||||
unpack(targetargs)
|
||||
}
|
||||
|
||||
local targetworkdir = wx.wxMenu{
|
||||
{ID "debug.projectdir.choose","Choose ..."},
|
||||
{ID "debug.projectdir.fromfile","From current filepath"},
|
||||
{},
|
||||
{ID "debug.projectdir.currentdir",""}
|
||||
}
|
||||
|
||||
debugMenu:Append(0,"Lua &interpreter",target,"Set the interpreter to be used")
|
||||
debugMenu:Append(0,"Project directory",targetworkdir,"Set the project directory to be used")
|
||||
menuBar:Append(debugMenu, "&Project")
|
||||
--menuBar:Check(ID_USECONSOLE, true)
|
||||
|
||||
function UpdateProjectDir(projdir,skiptree)
|
||||
ide.config.path.projectdir = projdir
|
||||
menuBar:SetLabel(ID "debug.projectdir.currentdir",projdir)
|
||||
frame:SetStatusText(projdir)
|
||||
if (not skiptree) then
|
||||
ide.filetree:UpdateProjectDir(projdir)
|
||||
end
|
||||
end
|
||||
UpdateProjectDir(ide.config.path.projectdir)
|
||||
|
||||
-- interpreter setup
|
||||
local curinterpreterid = IDget("debug.interpreter."..ide.config.interpreter) or
|
||||
ID ("debug.interpreter."..lastinterpreter)
|
||||
ide.config.interpreterClass = interpreters[curinterpreterid]
|
||||
|
||||
menuBar:Check(curinterpreterid, true)
|
||||
|
||||
local function selectInterpreter (id)
|
||||
for i,inter in pairs(interpreters) do
|
||||
menuBar:Check(i, false)
|
||||
end
|
||||
menuBar:Check(id, true)
|
||||
curinterpreterid = id
|
||||
ide.config.interpreter = interpreters[id].fname
|
||||
ide.config.interpreterClass = interpreters[id]
|
||||
ReloadLuaAPI()
|
||||
end
|
||||
|
||||
local function evSelectInterpreter (event)
|
||||
local chose = event:GetId()
|
||||
selectInterpreter(chose)
|
||||
end
|
||||
|
||||
for id,inter in pairs(interpreters) do
|
||||
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectInterpreter)
|
||||
end
|
||||
|
||||
function SetInterpreter(name)
|
||||
local id = IDget("debug.interpreter."..name)
|
||||
if (not interpreters[id]) then return end
|
||||
selectInterpreter(id)
|
||||
end
|
||||
|
||||
local function projChoose(event)
|
||||
local editor = GetEditor()
|
||||
local id = editor:GetId()
|
||||
local saved = false
|
||||
local fn = wx.wxFileName(openDocuments[id].filePath or "")
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
local projectdir = ide.config.path.projectdir
|
||||
|
||||
--filePicker:Show(true)
|
||||
--local diag = wx.wxDialog()
|
||||
--diag:ShowModal(true)
|
||||
local filePicker = wx.wxDirDialog(frame, "Chose a project directory",
|
||||
projectdir~="" and projectdir or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
|
||||
local res = filePicker:ShowModal(true)
|
||||
--for i,v in pairs(wx) do if v == res then print(i) end end
|
||||
--print(res)
|
||||
if res == wx.wxID_OK then
|
||||
UpdateProjectDir(filePicker:GetPath())
|
||||
end
|
||||
--filePicker:Destroy()
|
||||
return true
|
||||
end
|
||||
|
||||
frame:Connect(ID "debug.projectdir.choose", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
projChoose)
|
||||
frame:Connect(ID "debug.projectdir.choose", wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
projChoose)
|
||||
|
||||
local function projFromFile(event)
|
||||
local editor = GetEditor()
|
||||
if not editor then return end
|
||||
local id = editor:GetId()
|
||||
local filepath = openDocuments[id].filePath
|
||||
if not filepath then return end
|
||||
local fn = wx.wxFileName(filepath)
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
UpdateProjectDir(interpreters[curinterpreterid]:fprojdir(fn))
|
||||
end
|
||||
frame:Connect(ID "debug.projectdir.fromfile", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
projFromFile)
|
||||
|
||||
function RunInterpreter(wfilename, script)
|
||||
-- SaveAll()
|
||||
|
||||
local editor = GetEditor()
|
||||
|
||||
-- test compile it before we run it, if successful then ask to save
|
||||
-- only compile if lua api
|
||||
if (editor.spec.apitype and
|
||||
editor.spec.apitype == "lua" and
|
||||
not CompileProgram(editor)) then
|
||||
return
|
||||
end
|
||||
if not SaveIfModified(editor) then
|
||||
return
|
||||
end
|
||||
|
||||
local interpreter = interpreters[curinterpreterid]
|
||||
interpreter:frun(wfilename, script)
|
||||
end
|
||||
|
||||
frame:Connect(ID_TOGGLEBREAKPOINT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local line = editor:LineFromPosition(editor:GetCurrentPos())
|
||||
ToggleDebugMarker(editor, line)
|
||||
end)
|
||||
frame:Connect(ID_TOGGLEBREAKPOINT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
|
||||
frame:Connect(ID_COMPILE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
CompileProgram(editor)
|
||||
end)
|
||||
frame:Connect(ID_COMPILE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
|
||||
frame:Connect(ID_RUN, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
RunInterpreter(wx.wxFileName(openDocuments[GetEditor():GetId()].filePath));
|
||||
end)
|
||||
frame:Connect(ID_RUN, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server == nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_ATTACH_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
debugger.connect()
|
||||
end)
|
||||
frame:Connect(ID_ATTACH_DEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server == nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_START_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editorDir = string.gsub(ide.editorFilename:gsub("[^/\\]+$",""),"\\","/")
|
||||
RunInterpreter(wx.wxFileName(openDocuments[GetEditor():GetId()].filePath),
|
||||
"package.path=package.path..';"..editorDir.."lualibs/?/?.lua';"..
|
||||
"package.cpath=package.cpath..';"..editorDir.."bin/clibs/?.dll';"..
|
||||
"require 'mobdebug'; io.stdout:setvbuf('no'); mobdebug.loop('" .. wx.wxGetHostName().."',"..debugger.portnumber..")");
|
||||
end)
|
||||
frame:Connect(ID_START_DEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server == nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STOP_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
|
||||
debugger.run("exit")
|
||||
end)
|
||||
frame:Connect(ID_STOP_DEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STEP, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
|
||||
debugger.run("step")
|
||||
end)
|
||||
frame:Connect(ID_STEP, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STEP_OVER, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
|
||||
debugger.run("over")
|
||||
end)
|
||||
frame:Connect(ID_STEP_OVER, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STEP_OUT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
|
||||
debugger.run("out")
|
||||
end)
|
||||
frame:Connect(ID_STEP_OUT, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_CONTINUE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
|
||||
debugger.run("run")
|
||||
end)
|
||||
frame:Connect(ID_CONTINUE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_BREAK, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if debugger.server then
|
||||
debugger.server:Break()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_BREAK, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((debugger.server ~= nil) and debugger.running)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_DEBUGGER_PORT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
end)
|
||||
frame:Connect(ID_DEBUGGER_PORT, wx.wxEVT_UPDATE_UI,
|
||||
function(event)
|
||||
event:Enable(debugger.server == nil)
|
||||
end)
|
||||
|
||||
frame:Connect(wx.wxEVT_IDLE,
|
||||
function(event)
|
||||
debugger.update()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.debug.callstack", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if debugger.server then
|
||||
debugger.server:DisplayStackDialog(frame)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID "view.debug.callstack", wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running))
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.debug.watches", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if not debugger.watchWindow then
|
||||
CreateWatchWindow()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID "view.debug.watches", wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running))
|
||||
end)
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
-- Create the Debug menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local openDocuments = ide.openDocuments
|
||||
local debugger = ide.debugger
|
||||
local filetree = ide.filetree
|
||||
|
||||
------------------------
|
||||
-- Interpreters and Menu
|
||||
local targetMenu
|
||||
local interpreters = {}
|
||||
local lastinterpreter
|
||||
do
|
||||
local interpreternames = {}
|
||||
local lkinterpreters = {}
|
||||
for i,v in pairs(ide.interpreters) do
|
||||
interpreters[ID ("debug.interpreter."..i)] = v
|
||||
v.fname = i
|
||||
lastinterpreter = i
|
||||
table.insert(interpreternames,v.name)
|
||||
lkinterpreters[v.name] = i
|
||||
end
|
||||
assert(lastinterpreter,"no interpreters defined")
|
||||
table.sort(interpreternames)
|
||||
|
||||
local targetargs = {}
|
||||
for i,v in ipairs(interpreternames) do
|
||||
local id = ID ("debug.interpreter."..lkinterpreters[v])
|
||||
local inter = interpreters[id]
|
||||
table.insert(targetargs,{id,inter.name,inter.description,wx.wxITEM_CHECK})
|
||||
end
|
||||
targetMenu = wx.wxMenu(targetargs)
|
||||
end
|
||||
|
||||
|
||||
local debugTab = {
|
||||
{ ID_RUN, "&Run\tF6", "Execute the current project/file" },
|
||||
{ ID_COMPILE, "&Compile\tF7", "Test compile the Lua file" },
|
||||
{ ID_START_DEBUG, "Start &Debugging\tF5", "Start a debugging session" },
|
||||
{ ID_ATTACH_DEBUG, "&Start Debugger Server\tShift-F6", "Allow a client to start a debugging session" },
|
||||
{ },
|
||||
{ ID_STOP_DEBUG, "S&top Debugging\tShift-F12", "Stop and end the debugging session" },
|
||||
{ ID_STEP, "St&ep\tF11", "Step into the next line" },
|
||||
{ ID_STEP_OVER, "Step &Over\tF10", "Step over the next line" },
|
||||
{ ID_STEP_OUT, "Step O&ut\tShift-F10", "Step out of the current function" },
|
||||
{ ID_TRACE, "Tr&ace", "Trace execution showing each executed line" },
|
||||
{ ID_BREAK, "&Break", "Stop execution of the program at the next executed line of code" },
|
||||
{ },
|
||||
{ ID_TOGGLEBREAKPOINT, "Toggle &Breakpoint\tF9", "Toggle Breakpoint" },
|
||||
--{ ID "view.debug.callstack", "V&iew Call Stack", "View the LUA call stack" },
|
||||
{ },
|
||||
{ ID_CLEAROUTPUT, "C&lear Output Window", "Clear the output window before compiling or debugging", wx.wxITEM_CHECK },
|
||||
}
|
||||
|
||||
local debugMenu = wx.wxMenu(debugTab)
|
||||
local debugMenuRun = {start="Start &Debugging\tF5", continue="Co&ntinue\tF5"}
|
||||
|
||||
local targetDirMenu = wx.wxMenu{
|
||||
{ID "debug.projectdir.choose","Choose ..."},
|
||||
{ID "debug.projectdir.fromfile","From current filepath"},
|
||||
{},
|
||||
{ID "debug.projectdir.currentdir",""}
|
||||
}
|
||||
|
||||
debugMenu:Append(0,"Lua &interpreter",targetMenu,"Set the interpreter to be used")
|
||||
debugMenu:Append(0,"Project directory",targetDirMenu,"Set the project directory to be used")
|
||||
menuBar:Append(debugMenu, "&Project")
|
||||
|
||||
-----------------------------
|
||||
-- Project directory handling
|
||||
|
||||
function ProjectUpdateProjectDir(projdir,skiptree)
|
||||
ide.config.path.projectdir = projdir
|
||||
menuBar:SetLabel(ID "debug.projectdir.currentdir",projdir)
|
||||
frame:SetStatusText(projdir)
|
||||
if (not skiptree) then
|
||||
ide.filetree:updateProjectDir(projdir)
|
||||
end
|
||||
end
|
||||
ProjectUpdateProjectDir(ide.config.path.projectdir)
|
||||
|
||||
local function projChoose(event)
|
||||
local editor = GetEditor()
|
||||
local saved = false
|
||||
local fn = wx.wxFileName(
|
||||
editor and openDocuments[editor:GetId()].filePath or "")
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
local projectdir = ide.config.path.projectdir
|
||||
|
||||
local filePicker = wx.wxDirDialog(frame, "Chose a project directory",
|
||||
projectdir~="" and projectdir or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
|
||||
local res = filePicker:ShowModal(true)
|
||||
if res == wx.wxID_OK then
|
||||
ProjectUpdateProjectDir(filePicker:GetPath())
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
frame:Connect(ID "debug.projectdir.choose", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
projChoose)
|
||||
frame:Connect(ID "debug.projectdir.choose", wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
projChoose)
|
||||
|
||||
local function projFromFile(event)
|
||||
local editor = GetEditor()
|
||||
if not editor then return end
|
||||
local id = editor:GetId()
|
||||
local filepath = openDocuments[id].filePath
|
||||
if not filepath then return end
|
||||
local fn = wx.wxFileName(filepath)
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
if ide.interpreter then ProjectUpdateProjectDir(ide.interpreter:fprojdir(fn)) end
|
||||
end
|
||||
frame:Connect(ID "debug.projectdir.fromfile", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
projFromFile)
|
||||
|
||||
------------------------------------
|
||||
-- Interpreter Selection and Running
|
||||
|
||||
local function selectInterpreter(id)
|
||||
for i,inter in pairs(interpreters) do
|
||||
menuBar:Check(i, false)
|
||||
end
|
||||
menuBar:Check(id, true)
|
||||
ide.interpreter = interpreters[id]
|
||||
ReloadLuaAPI()
|
||||
end
|
||||
|
||||
function ProjectSetInterpreter(name)
|
||||
local id = IDget("debug.interpreter."..name)
|
||||
if (not interpreters[id]) then return end
|
||||
selectInterpreter(id)
|
||||
end
|
||||
|
||||
local function evSelectInterpreter (event)
|
||||
local chose = event:GetId()
|
||||
selectInterpreter(chose)
|
||||
end
|
||||
|
||||
for id,inter in pairs(interpreters) do
|
||||
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectInterpreter)
|
||||
end
|
||||
|
||||
do
|
||||
local defaultid = (
|
||||
IDget("debug.interpreter."..ide.config.interpreter) or
|
||||
ID ("debug.interpreter."..lastinterpreter)
|
||||
)
|
||||
ide.interpreter = interpreters[defaultid]
|
||||
menuBar:Check(defaultid, true)
|
||||
end
|
||||
|
||||
local function getNameToRun()
|
||||
local editor = GetEditor()
|
||||
|
||||
-- test compile it before we run it, if successful then ask to save
|
||||
-- only compile if lua api
|
||||
if (editor.spec.apitype and
|
||||
editor.spec.apitype == "lua" and
|
||||
not CompileProgram(editor)) then
|
||||
return
|
||||
end
|
||||
|
||||
local id = editor:GetId()
|
||||
if not openDocuments[id].filePath then SetDocumentModified(id, true) end
|
||||
if not SaveIfModified(editor) then return end
|
||||
|
||||
return wx.wxFileName(openDocuments[id].filePath)
|
||||
end
|
||||
|
||||
local function runInterpreter(wfilename, withdebugger)
|
||||
ClearAllCurrentLineMarkers()
|
||||
if not wfilename then return end
|
||||
local pid = ide.interpreter:frun(wfilename, withdebugger)
|
||||
if withdebugger then debugger.pid = pid end
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- Actions
|
||||
|
||||
frame:Connect(ID_TOGGLEBREAKPOINT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local line = editor:LineFromPosition(editor:GetCurrentPos())
|
||||
DebuggerToggleBreakpoint(editor, line)
|
||||
end)
|
||||
frame:Connect(ID_TOGGLEBREAKPOINT, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((ide.interpreter) and (ide.interpreter.hasdebugger) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_COMPILE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
CompileProgram(editor)
|
||||
end)
|
||||
frame:Connect(ID_COMPILE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server == nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_RUN, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
runInterpreter(getNameToRun())
|
||||
end)
|
||||
frame:Connect(ID_RUN, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server == nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_ATTACH_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
if (ide.interpreter.fattachdebug) then ide.interpreter:fattachdebug() end
|
||||
end)
|
||||
frame:Connect(ID_ATTACH_DEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((ide.interpreter) and (ide.interpreter.fattachdebug) and
|
||||
(not debugger.listening) and (debugger.server == nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
local lastcontinue
|
||||
frame:Connect(ID_START_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if (debugger.server ~= nil) then
|
||||
if (not debugger.running) then
|
||||
ClearAllCurrentLineMarkers()
|
||||
debugger.run()
|
||||
end
|
||||
else
|
||||
runInterpreter(getNameToRun(), true)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_START_DEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((ide.interpreter) and (ide.interpreter.hasdebugger) and
|
||||
((debugger.server == nil) or (debugger.server ~= nil and not debugger.running)) and (editor ~= nil))
|
||||
local curcontinue = (debugger.server ~= nil)
|
||||
if curcontinue == lastcontinue then return end
|
||||
lastcontinue = curcontinue
|
||||
if curcontinue then
|
||||
debugMenu:SetLabel(ID_START_DEBUG, debugMenuRun.continue)
|
||||
else
|
||||
debugMenu:SetLabel(ID_START_DEBUG, debugMenuRun.start)
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STOP_DEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
debugger.terminate()
|
||||
end)
|
||||
frame:Connect(ID_STOP_DEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STEP, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
debugger.step()
|
||||
end)
|
||||
frame:Connect(ID_STEP, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STEP_OVER, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
debugger.over()
|
||||
end)
|
||||
frame:Connect(ID_STEP_OVER, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_STEP_OUT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
debugger.out()
|
||||
end)
|
||||
frame:Connect(ID_STEP_OUT, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_TRACE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClearAllCurrentLineMarkers()
|
||||
debugger.trace()
|
||||
end)
|
||||
frame:Connect(ID_TRACE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_BREAK, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if debugger.server then
|
||||
debugger.breaknow()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_BREAK, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (debugger.running) and (editor ~= nil))
|
||||
end)
|
||||
|
||||
--[[
|
||||
frame:Connect(ID "view.debug.callstack", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if debugger.server then
|
||||
DebuggerCreateStackWindow()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID "view.debug.callstack", wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable((debugger.server ~= nil) and (not debugger.running))
|
||||
end)
|
||||
]]
|
||||
|
||||
frame:Connect(wx.wxEVT_IDLE,
|
||||
function(event)
|
||||
if (debugger.update) then
|
||||
debugger.update()
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -1,92 +1,90 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- Create the Search menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local findReplace = ide.findReplace
|
||||
|
||||
local findMenu = wx.wxMenu{
|
||||
{ ID_FIND, "&Find\tCtrl-F", "Find the specified text" },
|
||||
{ ID_FINDNEXT, "Find &Next\tF3", "Find the next occurrence of the specified text" },
|
||||
{ ID_FINDPREV, "Find &Previous\tShift-F3", "Repeat the search backwards in the file" },
|
||||
{ ID_REPLACE, "&Replace\tCtrl-H", "Replaces the specified text with different text" },
|
||||
{ },
|
||||
{ ID_FIND_IN_FILES, "Find &In Files\tCtrl-Shift-F", " Find specified text in files"},
|
||||
{ ID_REPLACE_IN_FILES, "Re&place In Files\tCtrl-Shift-H", " Replace specified text in files"},
|
||||
{ },
|
||||
{ ID_GOTOLINE, "&Goto line\tCtrl-G", "Go to a selected line" },
|
||||
{ },
|
||||
{ ID_SORT, "&Sort", "Sort selected lines"}}
|
||||
menuBar:Append(findMenu, "&Search")
|
||||
|
||||
|
||||
|
||||
frame:Connect(ID_FIND, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false)
|
||||
end)
|
||||
frame:Connect(ID_FIND, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_FIND_IN_FILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false,true)
|
||||
end)
|
||||
frame:Connect(ID_FIND_IN_FILES, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_REPLACE_IN_FILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true,true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACE_IN_FILES, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_COMMAND_MENU_SELECTED, function (event) findReplace:GetSelectedString() findReplace:FindString() end)
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_UPDATE_UI, function (event) findReplace:HasText() end)
|
||||
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_COMMAND_MENU_SELECTED, function (event) findReplace:GetSelectedString() findReplace:FindString(true) end)
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_UPDATE_UI, function (event) findReplace:HasText() end)
|
||||
|
||||
-------------------- Find replace end
|
||||
|
||||
frame:Connect(ID_GOTOLINE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local linecur = editor:LineFromPosition(editor:GetCurrentPos())
|
||||
local linemax = editor:LineFromPosition(editor:GetLength()) + 1
|
||||
local linenum = wx.wxGetNumberFromUser( "Enter line number",
|
||||
"1 .. "..tostring(linemax),
|
||||
"Goto Line",
|
||||
linecur, 1, linemax,
|
||||
frame)
|
||||
if linenum > 0 then
|
||||
editor:GotoLine(linenum-1)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_GOTOLINE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_SORT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local buf = {}
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
table.insert(buf, line)
|
||||
end
|
||||
if #buf > 0 then
|
||||
table.sort(buf)
|
||||
editor:ReplaceSelection(table.concat(buf,"\n"))
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_SORT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- Create the Search menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local findReplace = ide.findReplace
|
||||
|
||||
local findMenu = wx.wxMenu{
|
||||
{ ID_FIND, "&Find\tCtrl-F", "Find the specified text" },
|
||||
{ ID_FINDNEXT, "Find &Next\tF3", "Find the next occurrence of the specified text" },
|
||||
{ ID_FINDPREV, "Find &Previous\tShift-F3", "Repeat the search backwards in the file" },
|
||||
{ ID_REPLACE, "&Replace\tCtrl-H", "Replaces the specified text with different text" },
|
||||
{ },
|
||||
{ ID_FIND_IN_FILES, "Find &In Files\tCtrl-Shift-F", " Find specified text in files"},
|
||||
{ ID_REPLACE_IN_FILES, "Re&place In Files\tCtrl-Shift-H", " Replace specified text in files"},
|
||||
{ },
|
||||
{ ID_GOTOLINE, "&Goto line\tCtrl-G", "Go to a selected line" },
|
||||
{ },
|
||||
{ ID_SORT, "&Sort", "Sort selected lines"}}
|
||||
menuBar:Append(findMenu, "&Search")
|
||||
|
||||
frame:Connect(ID_FIND, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false)
|
||||
end)
|
||||
frame:Connect(ID_FIND, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_FIND_IN_FILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false,true)
|
||||
end)
|
||||
frame:Connect(ID_FIND_IN_FILES, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_REPLACE_IN_FILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true,true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACE_IN_FILES, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_COMMAND_MENU_SELECTED, function (event) findReplace:GetSelectedString() findReplace:FindString() end)
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_UPDATE_UI, function (event) findReplace:HasText() end)
|
||||
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_COMMAND_MENU_SELECTED, function (event) findReplace:GetSelectedString() findReplace:FindString(true) end)
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_UPDATE_UI, function (event) findReplace:HasText() end)
|
||||
|
||||
-------------------- Find replace end
|
||||
|
||||
frame:Connect(ID_GOTOLINE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local linecur = editor:LineFromPosition(editor:GetCurrentPos())
|
||||
local linemax = editor:LineFromPosition(editor:GetLength()) + 1
|
||||
local linenum = wx.wxGetNumberFromUser( "Enter line number",
|
||||
"1 .. "..tostring(linemax),
|
||||
"Goto Line",
|
||||
linecur, 1, linemax,
|
||||
frame)
|
||||
if linenum > 0 then
|
||||
editor:GotoLine(linenum-1)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_GOTOLINE, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_SORT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local buf = {}
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
table.insert(buf, line)
|
||||
end
|
||||
if #buf > 0 then
|
||||
table.sort(buf)
|
||||
editor:ReplaceSelection(table.concat(buf,"\n"))
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_SORT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
@@ -1,94 +1,91 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local openDocuments = ide.openDocuments
|
||||
|
||||
--[=[
|
||||
-- tool definition
|
||||
-- main entries are optional
|
||||
tool = {
|
||||
fnmenu = function(frame,menubar),
|
||||
-- can be used for init
|
||||
-- and custom menu
|
||||
exec = {
|
||||
-- quick exec action
|
||||
name = "",
|
||||
description = "",
|
||||
fn = function(wxfilename,projectdir),
|
||||
}
|
||||
}
|
||||
|
||||
]=]
|
||||
|
||||
|
||||
local toolArgs = {{},}
|
||||
|
||||
|
||||
-- fill in tools that have a automatic execution
|
||||
-- function
|
||||
do
|
||||
local cnt = 1
|
||||
local maxcnt = 10
|
||||
|
||||
local tools = {}
|
||||
for name,tool in pairs(ide.tools) do
|
||||
if (tool.exec and tool.exec.name) then
|
||||
tool.fname = name
|
||||
table.insert(tools,tool)
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(tools,function(a,b) return a.exec.name < b.exec.name end)
|
||||
|
||||
-- todo config specifc ignore/priority list
|
||||
for i,tool in ipairs(tools) do
|
||||
local exec = tool.exec
|
||||
if (exec and cnt < maxcnt and exec.name and exec.fn and exec.description) then
|
||||
local id = ID("tools.exec."..tool.fname)
|
||||
table.insert(toolArgs,{id , exec.name.."\tCtrl-"..cnt, exec.description})
|
||||
-- flag it
|
||||
tool._execid = id
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Build Menu
|
||||
local toolMenu = wx.wxMenu{
|
||||
unpack(toolArgs)
|
||||
}
|
||||
menuBar:Append(toolMenu, "&Tools")
|
||||
|
||||
|
||||
-- connect auto execs
|
||||
do
|
||||
for name,tool in pairs(ide.tools) do
|
||||
if (tool._execid) then
|
||||
frame:Connect(tool._execid, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if (not editor) then return end
|
||||
|
||||
local id = editor:GetId()
|
||||
local saved = false
|
||||
local fn = wx.wxFileName(openDocuments[id].filePath or "")
|
||||
fn:Normalize()
|
||||
|
||||
tool.exec.fn(fn,ide.config.path.projectdir)
|
||||
|
||||
return true
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Generate Custom Menus/Init
|
||||
for name,tool in pairs(ide.tools) do
|
||||
if (tool.fninit) then
|
||||
tool.fninit(frame,menuBar)
|
||||
end
|
||||
end
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local openDocuments = ide.openDocuments
|
||||
|
||||
--[=[
|
||||
-- tool definition
|
||||
-- main entries are optional
|
||||
tool = {
|
||||
fnmenu = function(frame,menubar),
|
||||
-- can be used for init
|
||||
-- and custom menu
|
||||
exec = {
|
||||
-- quick exec action
|
||||
name = "",
|
||||
description = "",
|
||||
fn = function(wxfilename,projectdir),
|
||||
}
|
||||
}
|
||||
|
||||
]=]
|
||||
|
||||
local toolArgs = {{},}
|
||||
local cnt = 1
|
||||
|
||||
-- fill in tools that have a automatic execution
|
||||
-- function
|
||||
do
|
||||
local maxcnt = 10
|
||||
|
||||
local tools = {}
|
||||
for name,tool in pairs(ide.tools) do
|
||||
if (tool.exec and tool.exec.name) then
|
||||
tool.fname = name
|
||||
table.insert(tools,tool)
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(tools,function(a,b) return a.exec.name < b.exec.name end)
|
||||
|
||||
-- todo config specifc ignore/priority list
|
||||
for i,tool in ipairs(tools) do
|
||||
local exec = tool.exec
|
||||
if (exec and cnt < maxcnt and exec.name and exec.fn and exec.description) then
|
||||
local id = ID("tools.exec."..tool.fname)
|
||||
table.insert(toolArgs,{id , exec.name.."\tCtrl-"..cnt, exec.description})
|
||||
-- flag it
|
||||
tool._execid = id
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (cnt > 1) then
|
||||
|
||||
-- Build Menu
|
||||
local toolMenu = wx.wxMenu{
|
||||
unpack(toolArgs)
|
||||
}
|
||||
menuBar:Append(toolMenu, "&Tools")
|
||||
|
||||
-- connect auto execs
|
||||
for name,tool in pairs(ide.tools) do
|
||||
if (tool._execid) then
|
||||
frame:Connect(tool._execid, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if (not editor) then return end
|
||||
|
||||
local id = editor:GetId()
|
||||
local saved = false
|
||||
local fn = wx.wxFileName(openDocuments[id].filePath or "")
|
||||
fn:Normalize()
|
||||
|
||||
tool.exec.fn(fn,ide.config.path.projectdir)
|
||||
|
||||
return true
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Generate Custom Menus/Init
|
||||
for name,tool in pairs(ide.tools) do
|
||||
if (tool.fninit) then
|
||||
tool.fninit(frame,menuBar)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,54 +1,53 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local vsplitter= frame.vsplitter
|
||||
local sidenotebook = vsplitter.sidenotebook
|
||||
local splitter = vsplitter.splitter
|
||||
local errorlog = splitter.bottomnotebook.errorlog
|
||||
local notebook = splitter.notebook
|
||||
|
||||
local debugger = ide.debugger
|
||||
|
||||
local viewMenu = wx.wxMenu{
|
||||
{ ID "view.preferences", "&Preferences...", "Brings up dialog for settings (TODO)" },
|
||||
{ },
|
||||
{ ID "view.filetree.show", "View &FileTree Window", "View or Hide the filetree window",wx.wxITEM_CHECK },
|
||||
{ ID "view.output.show", "View &Output/Shell Window", "View or Hide the output/shell window",wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "view.style.loadconfig", "&Load Config Style...", "Load and apply style from config file (must contain .styles)"},
|
||||
}
|
||||
menuBar:Append(viewMenu, "&View")
|
||||
|
||||
menuBar:Check(ID "view.filetree.show", true)
|
||||
menuBar:Check(ID "view.output.show", true)
|
||||
|
||||
frame:Connect(ID "view.preferences", wx.wxEVT_COMMAND_MENU_SELECTED,preferencesDialog.show)
|
||||
|
||||
frame:Connect(ID "view.style.loadconfig", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
LoadConfigStyle()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.output.show", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local w, h = frame:GetClientSizeWH()
|
||||
if splitter:IsSplit() then
|
||||
ide.config.view.splitterheight = h - splitter:GetSashPosition()
|
||||
splitter:Unsplit()
|
||||
else
|
||||
splitter:SplitHorizontally(notebook, splitter.bottomnotebook, h - ide.config.view.splitterheight)
|
||||
end
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.filetree.show", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if vsplitter:IsSplit() then
|
||||
ide.config.view.vsplitterpos = vsplitter:GetSashPosition()
|
||||
vsplitter:Unsplit(sidenotebook)
|
||||
else
|
||||
vsplitter:SplitVertically(sidenotebook,splitter,ide.config.view.vsplitterpos)
|
||||
end
|
||||
end)
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local uimgr = frame.uimgr
|
||||
|
||||
local debugger = ide.debugger
|
||||
|
||||
local viewMenu = wx.wxMenu{
|
||||
-- NYI { ID "view.preferences", "&Preferences...", "Brings up dialog for settings (TODO)" },
|
||||
-- NYI { },
|
||||
{ ID "view.filetree.show", "Project/&FileTree Window", "View the project/filetree window" },
|
||||
{ ID "view.output.show", "&Output/Shell Window", "View the output/shell window" },
|
||||
{ ID "view.debug.watches", "&Watch Window", "View the Watch window" },
|
||||
{ },
|
||||
{ ID "view.defaultlayout", "&Default Layout", "Reset to default ui layout"},
|
||||
{ ID "view.style.loadconfig", "&Load Config Style...", "Load and apply style from config file (must contain .styles)"},
|
||||
}
|
||||
menuBar:Append(viewMenu, "&View")
|
||||
|
||||
--frame:Connect(ID "view.preferences", wx.wxEVT_COMMAND_MENU_SELECTED,preferencesDialog.show)
|
||||
|
||||
frame:Connect(ID "view.style.loadconfig", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
LoadConfigStyle()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.defaultlayout", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
uimgr:LoadPerspective(uimgr.defaultPerspective)
|
||||
uimgr:Update()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.output.show", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
uimgr:GetPane("bottomnotebook"):Show(true)
|
||||
uimgr:Update()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.filetree.show", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
uimgr:GetPane("projpanel"):Show(true)
|
||||
uimgr:Update()
|
||||
end)
|
||||
|
||||
frame:Connect(ID "view.debug.watches", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
if not debugger.watchWindow then
|
||||
DebuggerCreateWatchWindow()
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -1,222 +1,244 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local splitter = frame.vsplitter.splitter
|
||||
local notebook = splitter.notebook
|
||||
local bottomnotebook = splitter.bottomnotebook
|
||||
local errorlog = bottomnotebook.errorlog
|
||||
|
||||
-------
|
||||
-- setup errorlog
|
||||
errorlog:Show(true)
|
||||
errorlog:SetFont(ide.ofont)
|
||||
errorlog:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.ofont)
|
||||
errorlog:StyleClearAll()
|
||||
errorlog:SetMarginWidth(1, 16) -- marker margin
|
||||
errorlog:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL);
|
||||
errorlog:MarkerDefine(CURRENT_LINE_MARKER, wxstc.wxSTC_MARK_ARROWS, wx.wxBLACK, wx.wxWHITE)
|
||||
errorlog:SetReadOnly(true)
|
||||
StylesApplyToEditor(ide.config.stylesoutshell,errorlog,ide.ofont,ide.ofontItalic)
|
||||
|
||||
|
||||
function ClearOutput(event)
|
||||
errorlog:SetReadOnly(false)
|
||||
errorlog:ClearAll()
|
||||
errorlog:SetReadOnly(true)
|
||||
end
|
||||
|
||||
function DisplayOutputNoMarker(...)
|
||||
local message = ""
|
||||
local cnt = select('#',...)
|
||||
for i=1,cnt do
|
||||
local v = select(i,...)
|
||||
message = message..tostring(v)..(i<cnt and "\t" or "")
|
||||
end
|
||||
|
||||
errorlog:SetReadOnly(false)
|
||||
errorlog:AppendText(message)
|
||||
errorlog:SetReadOnly(true)
|
||||
errorlog:GotoPos(errorlog:GetLength())
|
||||
end
|
||||
function DisplayOutput(...)
|
||||
errorlog:MarkerAdd(errorlog:GetLineCount()-1, CURRENT_LINE_MARKER)
|
||||
DisplayOutputNoMarker(...)
|
||||
end
|
||||
|
||||
local streamins = {}
|
||||
local streamerrs = {}
|
||||
local customprocs = {}
|
||||
|
||||
function CommandLineRunning(uid)
|
||||
for pid,custom in pairs(customprocs) do
|
||||
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(tostring(pid))) )then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function CommandLineToShell(uid,state)
|
||||
for pid,custom in pairs(customprocs) do
|
||||
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(tostring(pid))) )then
|
||||
if (streamins[pid]) then streamins[pid].toshell = state end
|
||||
if (streamerrs[pid]) then streamerrs[pid].toshell = state end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
if (not cmd) then return true end
|
||||
|
||||
local exename = string.gsub(cmd, "\\", "/")
|
||||
exename = string.match(exename,'%/*([^%/]+%.%w+)') or exename
|
||||
exename = string.match(exename,'%/*([^%/]+%.%w+)[%s%"]') or exename
|
||||
|
||||
uid = uid or exename
|
||||
|
||||
if (CommandLineRunning(uid)) then
|
||||
DisplayOutput("Conflicting Process still running: "..cmd.."\n")
|
||||
return true
|
||||
end
|
||||
|
||||
DisplayOutput("Running program: "..cmd.."\n")
|
||||
|
||||
|
||||
local pid = -1
|
||||
local proc = nil
|
||||
local customproc
|
||||
|
||||
if (tooutput) then
|
||||
customproc = wx.wxProcess(errorlog)
|
||||
customproc:Redirect()
|
||||
|
||||
proc = customproc
|
||||
end
|
||||
|
||||
-- manipulate working directory
|
||||
local oldcwd
|
||||
if (wdir) then
|
||||
oldcwd = wx.wxFileName.GetCwd()
|
||||
oldcwd = wx.wxFileName.SetCwd(wdir) and oldcwd
|
||||
end
|
||||
|
||||
-- launch process
|
||||
local pid = proc and wx.wxExecute(cmd, wx.wxEXEC_ASYNC + (nohide and wx.wxEXEC_NOHIDE or 0),proc) or
|
||||
wx.wxExecute(cmd, wx.wxEXEC_ASYNC + (nohide and wx.wxEXEC_NOHIDE or 0))
|
||||
|
||||
if (oldcwd) then
|
||||
wx.wxFileName.SetCwd(oldcwd)
|
||||
end
|
||||
|
||||
-- check process
|
||||
if not pid or pid == -1 then
|
||||
DisplayOutputNoMarker("Unknown ERROR Running program!\n")
|
||||
customproc = nil
|
||||
return true
|
||||
else
|
||||
DisplayOutputNoMarker("Process: "..uid.." pid:"..tostring(pid).."\n")
|
||||
customprocs[pid] = {proc=customproc, uid=uid, endcallback=endcallback}
|
||||
end
|
||||
|
||||
local streamin = proc and proc:GetInputStream()
|
||||
local streamerr = proc and proc:GetErrorStream()
|
||||
if (streamin) then
|
||||
streamins[pid] = {stream=streamin, callback=stringcallback}
|
||||
end
|
||||
if (streamerr) then
|
||||
streamerrs[pid] = {stream=streamerr, callback=stringcallback}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function getStreams()
|
||||
local function displayStream(tab)
|
||||
for i,v in pairs(tab) do
|
||||
while(v.stream:CanRead()) do
|
||||
local str = v.stream:Read(4096)
|
||||
local pfn
|
||||
if (v.callback) then
|
||||
str,pfn = v.callback(str)
|
||||
end
|
||||
if (v.toshell) then
|
||||
DisplayShell(str)
|
||||
else
|
||||
DisplayOutputNoMarker(str)
|
||||
end
|
||||
pfn = pfn and pfn()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
displayStream(streamins)
|
||||
displayStream(streamerrs)
|
||||
end
|
||||
|
||||
errorlog:Connect(wx.wxEVT_END_PROCESS, function(event)
|
||||
local pid = event:GetPid()
|
||||
if (pid ~= -1) then
|
||||
getStreams()
|
||||
streamins[pid] = nil
|
||||
streamerrs[pid] = nil
|
||||
if (customprocs[pid].endcallback) then
|
||||
customprocs[pid].endcallback()
|
||||
end
|
||||
customprocs[pid] = nil
|
||||
DisplayOutput("Program finished ("..pid..").\n")
|
||||
end
|
||||
end)
|
||||
|
||||
errorlog:Connect(wx.wxEVT_IDLE, function(event)
|
||||
if (#streamins or #streamerrs) then
|
||||
getStreams()
|
||||
end
|
||||
end)
|
||||
|
||||
local jumptopatterns = {
|
||||
-- <filename>(line,linepos):
|
||||
"%s*([%w:/%\\_%-%.]+)%((%d+),(%d+)%)%s*:",
|
||||
-- <filename>(line):
|
||||
"%s*([%w:/%\\_%-%.]+)%((%d+).*%)%s*:",
|
||||
-- <filename>:line:
|
||||
"%s*([%w:/%\\_%-%.]+):(%d+)%s*:",
|
||||
--[string "<filename>"]:line:
|
||||
'.*%[string "([%w:/%\\_%-%.]+)"%]:(%d+)%s*:',
|
||||
}
|
||||
|
||||
errorlog:Connect(wxstc.wxEVT_STC_DOUBLECLICK,
|
||||
function(event)
|
||||
local line = errorlog:GetCurrentLine()
|
||||
local linetx = errorlog:GetLine(line)
|
||||
-- try to detect a filename + line
|
||||
-- in linetx
|
||||
|
||||
local fname
|
||||
local jumpline
|
||||
local jumplinepos
|
||||
|
||||
for i,pattern in ipairs(jumptopatterns) do
|
||||
fname,jumpline,jumplinepos = linetx:match(pattern)
|
||||
if (fname and jumpline) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if (fname and jumpline) then
|
||||
LoadFile(fname,nil,true)
|
||||
local editor = GetEditor()
|
||||
if (editor) then
|
||||
jumpline = tonumber(jumpline)
|
||||
jumplinepos = tonumber(jumplinepos)
|
||||
|
||||
--editor:ScrollToLine(jumpline)
|
||||
editor:GotoPos(editor:PositionFromLine(math.max(0,jumpline-1)) + (jumplinepos and (math.max(0,jumplinepos-1)) or 0))
|
||||
editor:SetFocus()
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local notebook = frame.notebook
|
||||
local bottomnotebook = frame.bottomnotebook
|
||||
local errorlog = bottomnotebook.errorlog
|
||||
|
||||
-------
|
||||
-- setup errorlog
|
||||
errorlog:Show(true)
|
||||
errorlog:SetFont(ide.ofont)
|
||||
errorlog:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.ofont)
|
||||
errorlog:StyleClearAll()
|
||||
errorlog:SetMarginWidth(1, 16) -- marker margin
|
||||
errorlog:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL);
|
||||
errorlog:MarkerDefine(CURRENT_LINE_MARKER, wxstc.wxSTC_MARK_ARROWS, wx.wxBLACK, wx.wxWHITE)
|
||||
errorlog:SetReadOnly(true)
|
||||
StylesApplyToEditor(ide.config.stylesoutshell,errorlog,ide.ofont,ide.ofontItalic)
|
||||
|
||||
function ClearOutput(event)
|
||||
errorlog:SetReadOnly(false)
|
||||
errorlog:ClearAll()
|
||||
errorlog:SetReadOnly(true)
|
||||
end
|
||||
|
||||
function DisplayOutputNoMarker(...)
|
||||
local message = ""
|
||||
local cnt = select('#',...)
|
||||
for i=1,cnt do
|
||||
local v = select(i,...)
|
||||
message = message..tostring(v)..(i<cnt and "\t" or "")
|
||||
end
|
||||
|
||||
errorlog:SetReadOnly(false)
|
||||
errorlog:AppendText(message)
|
||||
errorlog:SetReadOnly(true)
|
||||
errorlog:GotoPos(errorlog:GetLength())
|
||||
end
|
||||
function DisplayOutput(...)
|
||||
errorlog:MarkerAdd(errorlog:GetLineCount()-1, CURRENT_LINE_MARKER)
|
||||
DisplayOutputNoMarker(...)
|
||||
end
|
||||
|
||||
local streamins = {}
|
||||
local streamerrs = {}
|
||||
local customprocs = {}
|
||||
|
||||
function CommandLineRunning(uid)
|
||||
for pid,custom in pairs(customprocs) do
|
||||
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(tostring(pid))) )then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function CommandLineToShell(uid,state)
|
||||
for pid,custom in pairs(customprocs) do
|
||||
if ((pid == uid or custom.uid == uid) and custom.proc and custom.proc.Exists(tonumber(tostring(pid))) )then
|
||||
if (streamins[pid]) then streamins[pid].toshell = state end
|
||||
if (streamerrs[pid]) then streamerrs[pid].toshell = state end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- logic to "unhide" wxwidget window using winapi
|
||||
pcall(function () return require 'winapi' end)
|
||||
local pid = nil
|
||||
local function unHideWxWindow(pidAssign)
|
||||
if pidAssign ~= nil then
|
||||
pid = pidAssign > 0 and pidAssign or nil
|
||||
end
|
||||
if pid and winapi then
|
||||
local win = winapi.find_window_ex(function(w)
|
||||
return w:get_process():get_pid() == pid
|
||||
and w:get_class_name() == 'wxWindowClassNR'
|
||||
end)
|
||||
if win and not win:is_visible() then
|
||||
win:show()
|
||||
pid = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
if (not cmd) then return end
|
||||
|
||||
local exename = string.gsub(cmd, "\\", "/")
|
||||
exename = string.match(exename,'%/*([^%/]+%.%w+)') or exename
|
||||
exename = string.match(exename,'%/*([^%/]+%.%w+)[%s%"]') or exename
|
||||
|
||||
uid = uid or exename
|
||||
|
||||
if (CommandLineRunning(uid)) then
|
||||
DisplayOutput("Conflicting Process still running: "..cmd.."\n")
|
||||
return
|
||||
end
|
||||
|
||||
DisplayOutput("Running program: "..cmd.."\n")
|
||||
|
||||
local pid = -1
|
||||
local proc = nil
|
||||
local customproc
|
||||
|
||||
if (tooutput) then
|
||||
customproc = wx.wxProcess(errorlog)
|
||||
customproc:Redirect()
|
||||
|
||||
proc = customproc
|
||||
end
|
||||
|
||||
-- manipulate working directory
|
||||
local oldcwd
|
||||
if (wdir) then
|
||||
oldcwd = wx.wxFileName.GetCwd()
|
||||
oldcwd = wx.wxFileName.SetCwd(wdir) and oldcwd
|
||||
end
|
||||
|
||||
-- launch process
|
||||
local pid = (proc and wx.wxExecute(cmd, wx.wxEXEC_ASYNC + (nohide and wx.wxEXEC_NOHIDE or 0),proc) or
|
||||
wx.wxExecute(cmd, wx.wxEXEC_ASYNC + (nohide and wx.wxEXEC_NOHIDE or 0)))
|
||||
|
||||
if (oldcwd) then
|
||||
wx.wxFileName.SetCwd(oldcwd)
|
||||
end
|
||||
|
||||
-- check process
|
||||
if not pid or pid == -1 then
|
||||
DisplayOutputNoMarker("Unknown ERROR Running program!\n")
|
||||
customproc = nil
|
||||
return
|
||||
else
|
||||
DisplayOutput(
|
||||
"Process: "..uid..", pid:"..tostring(pid)..
|
||||
", started in '"..(wdir and wdir or wx.wxFileName.GetCwd()).."'\n")
|
||||
customprocs[pid] = {proc=customproc, uid=uid, endcallback=endcallback}
|
||||
end
|
||||
|
||||
local streamin = proc and proc:GetInputStream()
|
||||
local streamerr = proc and proc:GetErrorStream()
|
||||
if (streamin) then
|
||||
streamins[pid] = {stream=streamin, callback=stringcallback}
|
||||
end
|
||||
if (streamerr) then
|
||||
streamerrs[pid] = {stream=streamerr, callback=stringcallback}
|
||||
end
|
||||
|
||||
unHideWxWindow(pid)
|
||||
|
||||
return pid
|
||||
end
|
||||
|
||||
local function getStreams()
|
||||
local function displayStream(tab)
|
||||
for i,v in pairs(tab) do
|
||||
while(v.stream:CanRead()) do
|
||||
local str = v.stream:Read(4096)
|
||||
local pfn
|
||||
if (v.callback) then
|
||||
str,pfn = v.callback(str)
|
||||
end
|
||||
if (v.toshell) then
|
||||
DisplayShell(str)
|
||||
else
|
||||
DisplayOutputNoMarker(str)
|
||||
end
|
||||
pfn = pfn and pfn()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
displayStream(streamins)
|
||||
displayStream(streamerrs)
|
||||
end
|
||||
|
||||
errorlog:Connect(wx.wxEVT_END_PROCESS, function(event)
|
||||
local pid = event:GetPid()
|
||||
if (pid ~= -1) then
|
||||
getStreams()
|
||||
streamins[pid] = nil
|
||||
streamerrs[pid] = nil
|
||||
if (customprocs[pid].endcallback) then
|
||||
customprocs[pid].endcallback()
|
||||
end
|
||||
customprocs[pid] = nil
|
||||
unHideWxWindow(0)
|
||||
DisplayOutput("Program finished (pid: "..pid..").\n")
|
||||
end
|
||||
end)
|
||||
|
||||
errorlog:Connect(wx.wxEVT_IDLE, function(event)
|
||||
if (#streamins or #streamerrs) then
|
||||
getStreams()
|
||||
end
|
||||
unHideWxWindow()
|
||||
end)
|
||||
|
||||
local jumptopatterns = {
|
||||
-- <filename>(line,linepos):
|
||||
"%s*([%w:/%\\_%-%.]+)%((%d+),(%d+)%)%s*:",
|
||||
-- <filename>(line):
|
||||
"%s*([%w:/%\\_%-%.]+)%((%d+).*%)%s*:",
|
||||
-- <filename>:line:
|
||||
"%s*([%w:/%\\_%-%.]+):(%d+)%s*:",
|
||||
--[string "<filename>"]:line:
|
||||
'.*%[string "([%w:/%\\_%-%.]+)"%]:(%d+)%s*:',
|
||||
}
|
||||
|
||||
errorlog:Connect(wxstc.wxEVT_STC_DOUBLECLICK,
|
||||
function(event)
|
||||
local line = errorlog:GetCurrentLine()
|
||||
local linetx = errorlog:GetLine(line)
|
||||
-- try to detect a filename + line
|
||||
-- in linetx
|
||||
|
||||
local fname
|
||||
local jumpline
|
||||
local jumplinepos
|
||||
|
||||
for i,pattern in ipairs(jumptopatterns) do
|
||||
fname,jumpline,jumplinepos = linetx:match(pattern)
|
||||
if (fname and jumpline) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (fname and jumpline) then
|
||||
LoadFile(fname,nil,true)
|
||||
local editor = GetEditor()
|
||||
if (editor) then
|
||||
jumpline = tonumber(jumpline)
|
||||
jumplinepos = tonumber(jumplinepos)
|
||||
|
||||
--editor:ScrollToLine(jumpline)
|
||||
editor:GotoPos(editor:PositionFromLine(math.max(0,jumpline-1)) + (jumplinepos and (math.max(0,jumplinepos-1)) or 0))
|
||||
editor:SetFocus()
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
@@ -4,302 +4,300 @@ local ide = ide
|
||||
-- the preferences dialog
|
||||
|
||||
preferencesDialog = {
|
||||
category = {};
|
||||
uifactory = {};
|
||||
category = {};
|
||||
uifactory = {};
|
||||
}
|
||||
local cats = preferencesDialog.category
|
||||
|
||||
local function checkstring (v,m)
|
||||
if type(v)~="string" then
|
||||
error(m.." ("..type(v)..")")
|
||||
end
|
||||
if type(v)~="string" then
|
||||
error(m.." ("..type(v)..")")
|
||||
end
|
||||
end
|
||||
|
||||
function preferencesDialog.addCategory(category)
|
||||
checkstring(category.title,"Invalid category title")
|
||||
checkstring(category.category,"No category")
|
||||
assert(not cats[category.category],"Category already declared")
|
||||
cats[category.category] = category
|
||||
cats[#cats+1] = category
|
||||
category.order = category.order or #cats
|
||||
category.entry = {}
|
||||
checkstring(category.title,"Invalid category title")
|
||||
checkstring(category.category,"No category")
|
||||
assert(not cats[category.category],"Category already declared")
|
||||
cats[category.category] = category
|
||||
cats[#cats+1] = category
|
||||
category.order = category.order or #cats
|
||||
category.entry = {}
|
||||
end
|
||||
|
||||
function preferencesDialog.addPage(page)
|
||||
assert(page.category and cats[page.category],"Invalid category given")
|
||||
checkstring(page.title,"Invalid title")
|
||||
local c = cats[page.category]
|
||||
c.entry[#c.entry+1] = page
|
||||
page.order = page.order or #c.entry
|
||||
assert(page.category and cats[page.category],"Invalid category given")
|
||||
checkstring(page.title,"Invalid title")
|
||||
local c = cats[page.category]
|
||||
c.entry[#c.entry+1] = page
|
||||
page.order = page.order or #c.entry
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.space(page,layout,element)
|
||||
layout.currentx = layout.currentx + element.space
|
||||
return layout
|
||||
layout.currentx = layout.currentx + element.space
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.group(page,layout,element)
|
||||
local margin = element.margin or 6
|
||||
local nl = {
|
||||
currentx = margin;
|
||||
currenty = margin+ (element.title and 12 or 8);
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
minwidth = element.minwidth or 0;
|
||||
minheight = element.minheight or 0;
|
||||
margin = margin;
|
||||
layout = layout;
|
||||
parent = wx.wxStaticBox(layout.parent,wx.wxID_ANY,element.title or "",
|
||||
wx.wxPoint(layout.currentx,layout.currenty),
|
||||
wx.wxDefaultSize, element.borderstyle and wx["wxBORDER_"..element.borderstyle:upper()] or 0);
|
||||
}
|
||||
return nl
|
||||
local margin = element.margin or 6
|
||||
local nl = {
|
||||
currentx = margin;
|
||||
currenty = margin+ (element.title and 12 or 8);
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
minwidth = element.minwidth or 0;
|
||||
minheight = element.minheight or 0;
|
||||
margin = margin;
|
||||
layout = layout;
|
||||
parent = wx.wxStaticBox(layout.parent,wx.wxID_ANY,element.title or "",
|
||||
wx.wxPoint(layout.currentx,layout.currenty),
|
||||
wx.wxDefaultSize, element.borderstyle and wx["wxBORDER_"..element.borderstyle:upper()] or 0);
|
||||
}
|
||||
return nl
|
||||
end
|
||||
function preferencesDialog.uifactory.finishgroup(page,layout,element)
|
||||
local l = layout.layout
|
||||
layout.maxsizex = math.max(layout.minwidth,layout.maxsizex + layout.margin)
|
||||
layout.maxsizey = math.max(layout.minheight,layout.maxsizey + layout.margin)
|
||||
l.maxsizey = math.max(l.maxsizey,layout.maxsizey+l.currenty)
|
||||
l.currentx = l.currentx + layout.maxsizex
|
||||
l.maxsizex = math.max(l.maxsizex,l.currentx)
|
||||
layout.parent:SetSize(wx.wxSize(layout.maxsizex,layout.maxsizey))
|
||||
return l
|
||||
local l = layout.layout
|
||||
layout.maxsizex = math.max(layout.minwidth,layout.maxsizex + layout.margin)
|
||||
layout.maxsizey = math.max(layout.minheight,layout.maxsizey + layout.margin)
|
||||
l.maxsizey = math.max(l.maxsizey,layout.maxsizey+l.currenty)
|
||||
l.currentx = l.currentx + layout.maxsizex
|
||||
l.maxsizex = math.max(l.maxsizex,l.currentx)
|
||||
layout.parent:SetSize(wx.wxSize(layout.maxsizex,layout.maxsizey))
|
||||
return l
|
||||
end
|
||||
|
||||
local function pos(layout) return layout.currentx,layout.currenty end
|
||||
local function fitin(el,layout)
|
||||
local x,y = pos(layout)
|
||||
local sz = el:GetBestFittingSize()
|
||||
el:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = x+sz:GetWidth()
|
||||
return layout
|
||||
local x,y = pos(layout)
|
||||
local sz = el:GetBestFittingSize()
|
||||
el:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = x+sz:GetWidth()
|
||||
return layout
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.combobox(page,layout,element,value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxComboBox(layout.parent,id,"",wx.wxPoint(x,y-4),wx.wxDefaultSize,
|
||||
wx.wxArrayString(),wx.wxCB_READONLY)
|
||||
|
||||
if value then
|
||||
for i=1,#value do
|
||||
cbox:Append(value[i])
|
||||
end
|
||||
end
|
||||
|
||||
return fitin(cbox,layout)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxComboBox(layout.parent,id,"",wx.wxPoint(x,y-4),wx.wxDefaultSize,
|
||||
wx.wxArrayString(),wx.wxCB_READONLY)
|
||||
|
||||
if value then
|
||||
for i=1,#value do
|
||||
cbox:Append(value[i])
|
||||
end
|
||||
end
|
||||
|
||||
return fitin(cbox,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.dirpicker(page,layout,element,value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local picker = wx.wxDirPickerCtrl(layout.parent,id,value or "",element.title or "",wx.wxPoint(x,y-4))
|
||||
return fitin(picker,layout)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local picker = wx.wxDirPickerCtrl(layout.parent,id,value or "",element.title or "",wx.wxPoint(x,y-4))
|
||||
return fitin(picker,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.edit (page,layout,element,value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local edit = wx.wxTextCtrl(layout.parent,id,value or (""..x..","..y), wx.wxPoint(x,y-4))
|
||||
return fitin(edit,layout)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local edit = wx.wxTextCtrl(layout.parent,id,value or (""..x..","..y), wx.wxPoint(x,y-4))
|
||||
return fitin(edit,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.linebreak(page,layout,element)
|
||||
layout.currentx = layout.margin or 0
|
||||
layout.currenty = layout.maxsizey + (element.space or 0)
|
||||
return layout
|
||||
layout.currentx = layout.margin or 0
|
||||
layout.currenty = layout.maxsizey + (element.space or 0)
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.checkbox (page,layout,element, value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxCheckBox(layout.parent,id,element.title,wx.wxPoint(x,y))
|
||||
if value then cbox:SetValue(value) end
|
||||
return fitin(cbox,layout)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxCheckBox(layout.parent,id,element.title,wx.wxPoint(x,y))
|
||||
if value then cbox:SetValue(value) end
|
||||
return fitin(cbox,layout)
|
||||
end
|
||||
function preferencesDialog.uifactory.static(page,layout,element)
|
||||
local x,y = pos(layout)
|
||||
local static = wx.wxStaticText(layout.parent,wx.wxID_ANY,element.title,wx.wxPoint(x,y))
|
||||
return fitin(static,layout)
|
||||
local x,y = pos(layout)
|
||||
local static = wx.wxStaticText(layout.parent,wx.wxID_ANY,element.title,wx.wxPoint(x,y))
|
||||
return fitin(static,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.space(page,layout,element)
|
||||
layout.currentx = layout.currentx + element.space
|
||||
return layout
|
||||
layout.currentx = layout.currentx + element.space
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.group(page,layout,element)
|
||||
local margin = element.margin or 6
|
||||
local nl = {
|
||||
currentx = margin;
|
||||
currenty = margin+ (element.title and 12 or 8);
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
minwidth = element.minwidth or 0;
|
||||
minheight = element.minheight or 0;
|
||||
margin = margin;
|
||||
layout = layout;
|
||||
parent = wx.wxStaticBox(layout.parent,wx.wxID_ANY,element.title or "",
|
||||
wx.wxPoint(layout.currentx,layout.currenty),
|
||||
wx.wxDefaultSize, element.borderstyle and wx["wxBORDER_"..element.borderstyle:upper()] or 0);
|
||||
}
|
||||
return nl
|
||||
local margin = element.margin or 6
|
||||
local nl = {
|
||||
currentx = margin;
|
||||
currenty = margin+ (element.title and 12 or 8);
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
minwidth = element.minwidth or 0;
|
||||
minheight = element.minheight or 0;
|
||||
margin = margin;
|
||||
layout = layout;
|
||||
parent = wx.wxStaticBox(layout.parent,wx.wxID_ANY,element.title or "",
|
||||
wx.wxPoint(layout.currentx,layout.currenty),
|
||||
wx.wxDefaultSize, element.borderstyle and wx["wxBORDER_"..element.borderstyle:upper()] or 0);
|
||||
}
|
||||
return nl
|
||||
end
|
||||
function preferencesDialog.uifactory.finishgroup(page,layout,element)
|
||||
local l = layout.layout
|
||||
layout.maxsizex = math.max(layout.minwidth,layout.maxsizex + layout.margin)
|
||||
layout.maxsizey = math.max(layout.minheight,layout.maxsizey + layout.margin)
|
||||
l.maxsizey = math.max(l.maxsizey,layout.maxsizey+l.currenty)
|
||||
l.currentx = l.currentx + layout.maxsizex
|
||||
l.maxsizex = math.max(l.maxsizex,l.currentx)
|
||||
layout.parent:SetSize(wx.wxSize(layout.maxsizex,layout.maxsizey))
|
||||
return l
|
||||
local l = layout.layout
|
||||
layout.maxsizex = math.max(layout.minwidth,layout.maxsizex + layout.margin)
|
||||
layout.maxsizey = math.max(layout.minheight,layout.maxsizey + layout.margin)
|
||||
l.maxsizey = math.max(l.maxsizey,layout.maxsizey+l.currenty)
|
||||
l.currentx = l.currentx + layout.maxsizex
|
||||
l.maxsizex = math.max(l.maxsizex,l.currentx)
|
||||
layout.parent:SetSize(wx.wxSize(layout.maxsizex,layout.maxsizey))
|
||||
return l
|
||||
end
|
||||
function preferencesDialog.uifactory.linebreak(page,layout,element)
|
||||
layout.currentx = layout.margin or 0
|
||||
layout.currenty = layout.maxsizey + (element.space or 0)
|
||||
return layout
|
||||
layout.currentx = layout.margin or 0
|
||||
layout.currenty = layout.maxsizey + (element.space or 0)
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.checkbox (page,layout,element, value)
|
||||
local x,y = layout.currentx,layout.currenty
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxCheckBox(layout.parent,id,element.title,wx.wxPoint(x,y))
|
||||
local sz = cbox:GetBestFittingSize()
|
||||
cbox:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = layout.maxsizex
|
||||
if value then cbox:SetValue(value) end
|
||||
return layout
|
||||
local x,y = layout.currentx,layout.currenty
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxCheckBox(layout.parent,id,element.title,wx.wxPoint(x,y))
|
||||
local sz = cbox:GetBestFittingSize()
|
||||
cbox:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = layout.maxsizex
|
||||
if value then cbox:SetValue(value) end
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.static(page,layout,element)
|
||||
local x,y = layout.currentx,layout.currenty
|
||||
local static = wx.wxStaticText(layout.parent,wx.wxID_ANY,element.title,wx.wxPoint(x,y))
|
||||
local sz = static:GetBestFittingSize()
|
||||
static:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = layout.maxsizex
|
||||
|
||||
return layout
|
||||
local x,y = layout.currentx,layout.currenty
|
||||
local static = wx.wxStaticText(layout.parent,wx.wxID_ANY,element.title,wx.wxPoint(x,y))
|
||||
local sz = static:GetBestFittingSize()
|
||||
static:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = layout.maxsizex
|
||||
|
||||
return layout
|
||||
end
|
||||
|
||||
|
||||
local function showpage(panel,page)
|
||||
--TODO: layout the page, load values, etc
|
||||
local data = page.onload()
|
||||
local layout = page.layout
|
||||
local layoutdata = {
|
||||
currentx = 0;
|
||||
currenty = 0;
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
parent = panel;
|
||||
}
|
||||
for i,el in ipairs(layout) do
|
||||
assert(preferencesDialog.uifactory[el.type],"Unknown ui type type")
|
||||
layoutdata = assert(
|
||||
preferencesDialog.uifactory[el.type](page,layoutdata,el,data[el.name])
|
||||
)
|
||||
end
|
||||
panel:SetSize(layoutdata.maxsizex,layoutdata.maxsizey)
|
||||
--print(layoutdata.maxsizex,layoutdata.maxsizey)
|
||||
--TODO: layout the page, load values, etc
|
||||
local data = page.onload()
|
||||
local layout = page.layout
|
||||
local layoutdata = {
|
||||
currentx = 0;
|
||||
currenty = 0;
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
parent = panel;
|
||||
}
|
||||
for i,el in ipairs(layout) do
|
||||
assert(preferencesDialog.uifactory[el.type],"Unknown ui type type")
|
||||
layoutdata = assert(
|
||||
preferencesDialog.uifactory[el.type](page,layoutdata,el,data[el.name])
|
||||
)
|
||||
end
|
||||
panel:SetSize(layoutdata.maxsizex,layoutdata.maxsizey)
|
||||
--print(layoutdata.maxsizex,layoutdata.maxsizey)
|
||||
end
|
||||
|
||||
function preferencesDialog.show(event)
|
||||
local dialog = wx.wxDialog(ide.frame, ID "view.preferences.dialog","Preferences")
|
||||
|
||||
local id_btn_ok = ID "view.preferences.dialog.button.ok"
|
||||
local id_btn_cancel = ID "view.preferences.dialog.button.cancel"
|
||||
local id_btn_apply = ID "view.preferences.dialog.button.apply"
|
||||
|
||||
local panel_buttons = wx.wxPanel(dialog,ID "view.preferences.dialog.buttonpanel")
|
||||
local btn_ok = wx.wxButton(panel_buttons,id_btn_ok, "OK")
|
||||
local btn_cancel = wx.wxButton(panel_buttons,id_btn_cancel, "Cancel")
|
||||
local btn_apply = wx.wxButton(panel_buttons,id_btn_apply, "Apply")
|
||||
|
||||
|
||||
dialog:Connect(id_btn_cancel, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function (event)
|
||||
dialog:EndModal(0)
|
||||
end)
|
||||
dialog:Connect(id_btn_ok, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function (event)
|
||||
dialog:EndModal(0)
|
||||
end)
|
||||
|
||||
local panel = wx.wxPanel(dialog,ID "view.preferences.dialog.panel",
|
||||
wx.wxDefaultPosition, wx.wxSize(600,400))
|
||||
|
||||
local projtree = wx.wxTreeCtrl(panel, ID "view.preferences.dialog.panel.tree",
|
||||
wx.wxDefaultPosition, wx.wxSize(180,400),
|
||||
wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT)
|
||||
local preferencesPage = wx.wxPanel(panel,ID "view.preferences.dialog.page",
|
||||
wx.wxDefaultPosition, wx.wxSize(500,400))
|
||||
local panelsizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
|
||||
panelsizer:Add(projtree,0,wx.wxALL + wx.wxALIGN_LEFT + wx.wxTOP + wx.wxBOTTOM,0)
|
||||
panelsizer:AddSpacer(5)
|
||||
panelsizer:Add(preferencesPage)
|
||||
panel:SetSizer(panelsizer)
|
||||
|
||||
local treecats = {}
|
||||
local catdata = {}
|
||||
table.sort(cats,function(a,b) return a.order < b.order end)
|
||||
local rootit = projtree:AddRoot("")
|
||||
|
||||
catdata[rootit:GetValue()] = {category = "root", children = treecats}
|
||||
for i=1,#cats do
|
||||
local it = projtree:AppendItem(rootit,cats[i].title)
|
||||
treecats[i] = it
|
||||
local c = cats[i]
|
||||
local children = {}
|
||||
catdata[it:GetValue()] = {category = c,children = children}
|
||||
for i=1,#c.entry do
|
||||
local e = c.entry[i]
|
||||
local it = projtree:AppendItem(it,e.title)
|
||||
catdata[it:GetValue()] = {page = e}
|
||||
children[i] = it
|
||||
end
|
||||
projtree:Expand(it)
|
||||
end
|
||||
|
||||
projtree:Expand(rootit)
|
||||
|
||||
local preferencesContent
|
||||
projtree:Connect( wx.wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
function( event )
|
||||
local item_id = event:GetItem():GetValue()
|
||||
local data = catdata[item_id]
|
||||
if data.category then
|
||||
if data.children[1] then
|
||||
projtree:SelectItem(data.children[1])
|
||||
end
|
||||
else
|
||||
if preferencesContent then
|
||||
preferencesPage:RemoveChild(preferencesContent)
|
||||
end
|
||||
preferencesContent = wx.wxPanel(preferencesPage,wx.wxID_ANY)
|
||||
|
||||
showpage(preferencesContent,data.page)
|
||||
end
|
||||
end )
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(panel,0,wx.wxALL + wx.wxALIGN_CENTER,10)
|
||||
topsizer:Add(wx.wxStaticLine(dialog, wx.wxID_ANY), 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(panel_buttons, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
|
||||
local buttonpanelsizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
|
||||
buttonpanelsizer:Add(btn_cancel,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
buttonpanelsizer:AddSpacer(5)
|
||||
buttonpanelsizer:Add(btn_apply,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
buttonpanelsizer:AddSpacer(5)
|
||||
buttonpanelsizer:Add(btn_ok,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
panel_buttons:SetSizer(buttonpanelsizer)
|
||||
buttonpanelsizer:Fit(panel_buttons)
|
||||
local dialog = wx.wxDialog(ide.frame, ID "view.preferences.dialog","Preferences")
|
||||
|
||||
dialog:SetAutoLayout(true)
|
||||
dialog:SetSizer(topsizer)
|
||||
topsizer:Fit(dialog)
|
||||
dialog:Center()
|
||||
dialog:ShowModal()
|
||||
local id_btn_ok = ID "view.preferences.dialog.button.ok"
|
||||
local id_btn_cancel = ID "view.preferences.dialog.button.cancel"
|
||||
local id_btn_apply = ID "view.preferences.dialog.button.apply"
|
||||
|
||||
local panel_buttons = wx.wxPanel(dialog,ID "view.preferences.dialog.buttonpanel")
|
||||
local btn_ok = wx.wxButton(panel_buttons,id_btn_ok, "OK")
|
||||
local btn_cancel = wx.wxButton(panel_buttons,id_btn_cancel, "Cancel")
|
||||
local btn_apply = wx.wxButton(panel_buttons,id_btn_apply, "Apply")
|
||||
|
||||
dialog:Connect(id_btn_cancel, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function (event)
|
||||
dialog:EndModal(0)
|
||||
end)
|
||||
dialog:Connect(id_btn_ok, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function (event)
|
||||
dialog:EndModal(0)
|
||||
end)
|
||||
|
||||
local panel = wx.wxPanel(dialog,ID "view.preferences.dialog.panel",
|
||||
wx.wxDefaultPosition, wx.wxSize(600,400))
|
||||
|
||||
local projtree = wx.wxTreeCtrl(panel, ID "view.preferences.dialog.panel.tree",
|
||||
wx.wxDefaultPosition, wx.wxSize(180,400),
|
||||
wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT)
|
||||
local preferencesPage = wx.wxPanel(panel,ID "view.preferences.dialog.page",
|
||||
wx.wxDefaultPosition, wx.wxSize(500,400))
|
||||
local panelsizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
|
||||
panelsizer:Add(projtree,0,wx.wxALL + wx.wxALIGN_LEFT + wx.wxTOP + wx.wxBOTTOM,0)
|
||||
panelsizer:AddSpacer(5)
|
||||
panelsizer:Add(preferencesPage)
|
||||
panel:SetSizer(panelsizer)
|
||||
|
||||
local treecats = {}
|
||||
local catdata = {}
|
||||
table.sort(cats,function(a,b) return a.order < b.order end)
|
||||
local rootit = projtree:AddRoot("")
|
||||
|
||||
catdata[rootit:GetValue()] = {category = "root", children = treecats}
|
||||
for i=1,#cats do
|
||||
local it = projtree:AppendItem(rootit,cats[i].title)
|
||||
treecats[i] = it
|
||||
local c = cats[i]
|
||||
local children = {}
|
||||
catdata[it:GetValue()] = {category = c,children = children}
|
||||
for i=1,#c.entry do
|
||||
local e = c.entry[i]
|
||||
local it = projtree:AppendItem(it,e.title)
|
||||
catdata[it:GetValue()] = {page = e}
|
||||
children[i] = it
|
||||
end
|
||||
projtree:Expand(it)
|
||||
end
|
||||
|
||||
projtree:Expand(rootit)
|
||||
|
||||
local preferencesContent
|
||||
projtree:Connect( wx.wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
function( event )
|
||||
local item_id = event:GetItem():GetValue()
|
||||
local data = catdata[item_id]
|
||||
if data.category then
|
||||
if data.children[1] then
|
||||
projtree:SelectItem(data.children[1])
|
||||
end
|
||||
else
|
||||
if preferencesContent then
|
||||
preferencesPage:RemoveChild(preferencesContent)
|
||||
end
|
||||
preferencesContent = wx.wxPanel(preferencesPage,wx.wxID_ANY)
|
||||
|
||||
showpage(preferencesContent,data.page)
|
||||
end
|
||||
end )
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(panel,0,wx.wxALL + wx.wxALIGN_CENTER,10)
|
||||
topsizer:Add(wx.wxStaticLine(dialog, wx.wxID_ANY), 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(panel_buttons, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
|
||||
local buttonpanelsizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
|
||||
buttonpanelsizer:Add(btn_cancel,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
buttonpanelsizer:AddSpacer(5)
|
||||
buttonpanelsizer:Add(btn_apply,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
buttonpanelsizer:AddSpacer(5)
|
||||
buttonpanelsizer:Add(btn_ok,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
panel_buttons:SetSizer(buttonpanelsizer)
|
||||
buttonpanelsizer:Fit(panel_buttons)
|
||||
|
||||
dialog:SetAutoLayout(true)
|
||||
dialog:SetSizer(topsizer)
|
||||
topsizer:Fit(dialog)
|
||||
dialog:Center()
|
||||
dialog:ShowModal()
|
||||
end
|
||||
|
||||
@@ -1,318 +1,436 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Initialize the wxConfig for loading/saving the preferences
|
||||
|
||||
local settings = wx.wxFileConfig(GetIDEString("settingsapp"),GetIDEString("settingsvendor"))
|
||||
ide.settings = settings
|
||||
|
||||
if settings then
|
||||
-- we dont like defaults ?
|
||||
--settings:SetRecordDefaults()
|
||||
end
|
||||
|
||||
|
||||
local function settingsReadSafe(settings,what,default)
|
||||
local cr,out = settings:Read(what,default)
|
||||
|
||||
if (cr) then
|
||||
return out
|
||||
else
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- wxConfig load/save preferences functions
|
||||
|
||||
function SettingsRestoreFramePosition(window, windowName)
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath("/"..windowName)
|
||||
|
||||
local s = -1
|
||||
s = tonumber(select(2,settings:Read("s", -1)))
|
||||
local x = tonumber(select(2,settings:Read("x", 0)))
|
||||
local y = tonumber(select(2,settings:Read("y", 0)))
|
||||
local w = tonumber(select(2,settings:Read("w", 600)))
|
||||
local h = tonumber(select(2,settings:Read("h", 400)))
|
||||
|
||||
if (s ~= 1) and (s ~= 2) then
|
||||
local clientX, clientY, clientWidth, clientHeight
|
||||
clientX, clientY, clientWidth, clientHeight = wx.wxClientDisplayRect()
|
||||
|
||||
if x < clientX then x = clientX end
|
||||
if y < clientY then y = clientY end
|
||||
|
||||
if w > clientWidth then w = clientWidth end
|
||||
if h > clientHeight then h = clientHeight end
|
||||
|
||||
window:SetSize(x, y, w, h)
|
||||
elseif s == 1 then
|
||||
window:Maximize(true)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsSaveFramePosition(window, windowName)
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath("/"..windowName)
|
||||
|
||||
local s = 0
|
||||
local w, h = window:GetSizeWH()
|
||||
local x, y = window:GetPositionXY()
|
||||
|
||||
if window:IsMaximized() then
|
||||
s = 1
|
||||
elseif window:IsIconized() then
|
||||
s = 2
|
||||
end
|
||||
|
||||
settings:Write("s", s==2 and 0 or s) -- iconized maybe - but that shouldnt be saved
|
||||
|
||||
if s == 0 then
|
||||
settings:Write("x", x)
|
||||
settings:Write("y", y)
|
||||
settings:Write("w", w)
|
||||
settings:Write("h", h)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
---
|
||||
-- (table) SettingsRestoreFileHistory (function)
|
||||
-- restores a list of recently loaded documents from the settings table
|
||||
-- a table is returned which contains tables each with a filename key, pointing to
|
||||
-- the filename
|
||||
function SettingsRestoreFileHistory(fntab)
|
||||
local path = settings:GetPath()
|
||||
local listname = "/filehistory"
|
||||
settings:SetPath(listname)
|
||||
|
||||
local outtab = {}
|
||||
local inlist = {}
|
||||
for id=1,ide.config.filehistorylength do
|
||||
local couldread, name = settings:Read(tostring(id), "")
|
||||
if not couldread or name == "" then break end
|
||||
if not inlist[name] then
|
||||
inlist[name] = true
|
||||
table.insert(outtab,{filename = name})
|
||||
end
|
||||
end
|
||||
|
||||
if fntab then fntab(outtab) end
|
||||
|
||||
settings:SetPath(path)
|
||||
|
||||
return outtab
|
||||
end
|
||||
|
||||
function SettingsAppendFileToHistory (filename)
|
||||
local listname = "/filehistory"
|
||||
local oldlist = SettingsRestoreFileHistory(nil,listname)
|
||||
|
||||
-- if the file has been in the history before, remove it
|
||||
for i=#oldlist,1,-1 do
|
||||
if oldlist[i] == filename then table.remove(oldlist,i) end
|
||||
end
|
||||
|
||||
table.insert(oldlist,1,{filename=filename})
|
||||
|
||||
-- remove all entries that are no longer needed
|
||||
while #oldlist>ide.config.filehistorylength do table.remove(oldlist) end
|
||||
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,doc in ipairs(oldlist) do
|
||||
settings:Write(tostring(i), doc.filename)
|
||||
end
|
||||
|
||||
UpdateFileHistoryUI(oldlist)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsRestoreFileSession (function)
|
||||
-- restores a list of opened files from the file settings
|
||||
-- calls the given function with the restored table, a list
|
||||
-- of tables containing tables like
|
||||
-- {filename = "filename", cursorpos = <cursor position>}
|
||||
function SettingsRestoreFileSession(fntab)
|
||||
local listname = "/session"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
local outtab = {}
|
||||
local couldread = true
|
||||
local id = 1
|
||||
local name
|
||||
while(couldread) do
|
||||
couldread, name = settings:Read(tostring(id), "")
|
||||
local fname,cursorpos = name:match("^(.+);(.-)$")
|
||||
name = fname or name
|
||||
cursorpos = tonumber(cursorpos or 0)
|
||||
couldread = couldread and name ~= ""
|
||||
if (couldread) then
|
||||
table.insert(outtab,{filename = name, cursorpos = cursorpos})
|
||||
id = id + 1
|
||||
end
|
||||
end
|
||||
|
||||
local index = settingsReadSafe(settings,"index",1)
|
||||
|
||||
if fntab then fntab(outtab,index) end
|
||||
|
||||
settings:SetPath(path)
|
||||
|
||||
return outtab
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsSaveFileList (table opendocs)
|
||||
-- saves the list of currently opened documents (passed in the opendocs table)
|
||||
-- in the settings.
|
||||
function SettingsSaveFileSession(opendocs,index)
|
||||
local listname = "/session"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,doc in ipairs(opendocs) do
|
||||
settings:Write(tostring(i), doc.filename..";"..doc.cursorpos)
|
||||
end
|
||||
settings:Write("index",index)
|
||||
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsRestoreProjectSession (function)
|
||||
|
||||
function SettingsRestoreProjectSession(fntab)
|
||||
local listname = "/projectsession"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
local outtab = {}
|
||||
local couldread = true
|
||||
local id = 1
|
||||
local name
|
||||
while(couldread) do
|
||||
couldread, name = settings:Read(tostring(id), "")
|
||||
couldread = couldread and name ~= ""
|
||||
if (couldread) then
|
||||
if (wx.wxDirExists(name)) then
|
||||
table.insert(outtab,name)
|
||||
end
|
||||
id = id + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if fntab then fntab(outtab) end
|
||||
|
||||
settings:SetPath(path)
|
||||
|
||||
return outtab
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsSaveProjectSession (table projdirs)
|
||||
-- saves the list of currently active projects
|
||||
-- in the settings.
|
||||
function SettingsSaveProjectSession(projdirs)
|
||||
local listname = "/projectsession"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,dir in ipairs(projdirs) do
|
||||
settings:Write(tostring(i), dir)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
-----------------------------------
|
||||
|
||||
function SettingsRestoreView()
|
||||
local listname = "/view"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
|
||||
local frame = ide.frame
|
||||
local vsplitter = frame.vsplitter
|
||||
local sidenotebook = vsplitter.sidenotebook
|
||||
local splitter = vsplitter.splitter
|
||||
|
||||
local treevis = tonumber(settingsReadSafe(settings,"filetreevis",1))
|
||||
local outvis = tonumber(settingsReadSafe(settings,"outputvis",1))
|
||||
|
||||
ide.config.view.vsplitterpos = tonumber(settingsReadSafe(settings,"filetreewidth",ide.config.view.vsplitterpos))
|
||||
ide.config.view.splitterheight = tonumber(settingsReadSafe(settings,"outputheight",ide.config.view.splitterheight))
|
||||
|
||||
|
||||
local w, h = frame:GetClientSizeWH()
|
||||
|
||||
if (treevis > 0) then
|
||||
vsplitter:SplitVertically(sidenotebook,splitter,ide.config.view.vsplitterpos)
|
||||
else
|
||||
vsplitter:Initialize(splitter)
|
||||
end
|
||||
|
||||
if (outvis > 0) then
|
||||
splitter:SplitHorizontally(splitter.notebook, splitter.bottomnotebook, h-ide.config.view.splitterheight)
|
||||
else
|
||||
splitter:Initialize(splitter.notebook)
|
||||
end
|
||||
|
||||
frame.menuBar:Check(ID "view.filetree.show", treevis > 0)
|
||||
frame.menuBar:Check(ID "view.output.show", outvis > 0)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsSaveView()
|
||||
local listname = "/view"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
local frame = ide.frame
|
||||
local vsplitter = frame.vsplitter
|
||||
local splitter = vsplitter.splitter
|
||||
|
||||
local w, h = frame:GetClientSizeWH()
|
||||
|
||||
settings:Write("filetreevis", vsplitter:IsSplit())
|
||||
settings:Write("filetreewidth", vsplitter:IsSplit() and vsplitter:GetSashPosition() or ide.config.view.vsplitterpos)
|
||||
settings:Write("outputvis", splitter:IsSplit())
|
||||
settings:Write("outputheight", splitter:IsSplit() and (h-splitter:GetSashPosition()) or ide.config.view.splitterheight)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsRestoreEditorSettings()
|
||||
local listname = "/editor"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
|
||||
ide.config.interpreter = settingsReadSafe(settings,"interpreter",ide.config.interpreter)
|
||||
SetInterpreter(ide.config.interpreter)
|
||||
end
|
||||
function SettingsSaveEditorSettings()
|
||||
local listname = "/editor"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
settings:Write("interpreter", ide.config.interpreter)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Initialize the wxConfig for loading/saving the preferences
|
||||
|
||||
local settings = wx.wxFileConfig(GetIDEString("settingsapp"),GetIDEString("settingsvendor"))
|
||||
ide.settings = settings
|
||||
|
||||
local function settingsReadSafe(settings,what,default)
|
||||
local cr,out = settings:Read(what,default)
|
||||
|
||||
if (cr) then
|
||||
return out
|
||||
else
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- wxConfig load/save preferences functions
|
||||
|
||||
function SettingsRestoreFramePosition(window, windowName)
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath("/"..windowName)
|
||||
|
||||
local s = -1
|
||||
s = tonumber(select(2,settings:Read("s", -1)))
|
||||
local x = tonumber(select(2,settings:Read("x", 0)))
|
||||
local y = tonumber(select(2,settings:Read("y", 0)))
|
||||
local w = tonumber(select(2,settings:Read("w", 1000)))
|
||||
local h = tonumber(select(2,settings:Read("h", 700)))
|
||||
|
||||
if (s ~= -1) and (s ~= 1) and (s ~= 2) then
|
||||
local clientX, clientY, clientWidth, clientHeight
|
||||
clientX, clientY, clientWidth, clientHeight = wx.wxClientDisplayRect()
|
||||
|
||||
if x < clientX then x = clientX end
|
||||
if y < clientY then y = clientY end
|
||||
|
||||
if w > clientWidth then w = clientWidth end
|
||||
if h > clientHeight then h = clientHeight end
|
||||
|
||||
window:SetSize(x, y, w, h)
|
||||
elseif s == 1 then
|
||||
window:Maximize(true)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsSaveFramePosition(window, windowName)
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath("/"..windowName)
|
||||
|
||||
local s = 0
|
||||
local w, h = window:GetSizeWH()
|
||||
local x, y = window:GetPositionXY()
|
||||
|
||||
if window:IsMaximized() then
|
||||
s = 1
|
||||
elseif window:IsIconized() then
|
||||
s = 2
|
||||
end
|
||||
|
||||
settings:Write("s", s==2 and 0 or s) -- iconized maybe - but that shouldnt be saved
|
||||
|
||||
if s == 0 then
|
||||
settings:Write("x", x)
|
||||
settings:Write("y", y)
|
||||
settings:Write("w", w)
|
||||
settings:Write("h", h)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
---
|
||||
-- (table) SettingsRestoreFileHistory (function)
|
||||
-- restores a list of recently loaded documents from the settings table
|
||||
-- a table is returned which contains tables each with a filename key, pointing to
|
||||
-- the filename
|
||||
function SettingsRestoreFileHistory(fntab)
|
||||
local path = settings:GetPath()
|
||||
local listname = "/filehistory"
|
||||
settings:SetPath(listname)
|
||||
|
||||
local outtab = {}
|
||||
local inlist = {}
|
||||
for id=1,ide.config.filehistorylength do
|
||||
local couldread, name = settings:Read(tostring(id), "")
|
||||
if not couldread or name == "" then break end
|
||||
if not inlist[name] then
|
||||
inlist[name] = true
|
||||
table.insert(outtab,{filename = name})
|
||||
end
|
||||
end
|
||||
|
||||
if fntab then fntab(outtab) end
|
||||
|
||||
settings:SetPath(path)
|
||||
|
||||
return outtab
|
||||
end
|
||||
|
||||
function SettingsAppendFileToHistory (filename)
|
||||
local listname = "/filehistory"
|
||||
local oldlist = SettingsRestoreFileHistory(nil,listname)
|
||||
|
||||
-- if the file has been in the history before, remove it
|
||||
for i=#oldlist,1,-1 do
|
||||
if oldlist[i] == filename then table.remove(oldlist,i) end
|
||||
end
|
||||
|
||||
table.insert(oldlist,1,{filename=filename})
|
||||
|
||||
-- remove all entries that are no longer needed
|
||||
while #oldlist>ide.config.filehistorylength do table.remove(oldlist) end
|
||||
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,doc in ipairs(oldlist) do
|
||||
settings:Write(tostring(i), doc.filename)
|
||||
end
|
||||
|
||||
UpdateFileHistoryUI(oldlist)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsRestoreFileSession (function)
|
||||
-- restores a list of opened files from the file settings
|
||||
-- calls the given function with the restored table, a list
|
||||
-- of tables containing tables like
|
||||
-- {filename = "filename", cursorpos = <cursor position>}
|
||||
function SettingsRestoreFileSession(fntab)
|
||||
local listname = "/session"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
local outtab = {}
|
||||
local couldread = true
|
||||
local id = 1
|
||||
local name
|
||||
while(couldread) do
|
||||
couldread, name = settings:Read(tostring(id), "")
|
||||
local fname,cursorpos = name:match("^(.+);(.-)$")
|
||||
name = fname or name
|
||||
cursorpos = tonumber(cursorpos or 0)
|
||||
couldread = couldread and name ~= ""
|
||||
if (couldread) then
|
||||
table.insert(outtab,{filename = name, cursorpos = cursorpos})
|
||||
id = id + 1
|
||||
end
|
||||
end
|
||||
|
||||
local index = settingsReadSafe(settings,"index",1)
|
||||
|
||||
if fntab then fntab(outtab,index) end
|
||||
|
||||
settings:SetPath(path)
|
||||
|
||||
return outtab
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsSaveFileList (table opendocs)
|
||||
-- saves the list of currently opened documents (passed in the opendocs table)
|
||||
-- in the settings.
|
||||
function SettingsSaveFileSession(opendocs,index)
|
||||
local listname = "/session"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,doc in ipairs(opendocs) do
|
||||
settings:Write(tostring(i), doc.filename..";"..doc.cursorpos)
|
||||
end
|
||||
settings:Write("index",index)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsRestoreProjectSession (function)
|
||||
|
||||
function SettingsRestoreProjectSession(fntab)
|
||||
local listname = "/projectsession"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
local outtab = {}
|
||||
local couldread = true
|
||||
local id = 1
|
||||
local name
|
||||
while(couldread) do
|
||||
couldread, name = settings:Read(tostring(id), "")
|
||||
couldread = couldread and name ~= ""
|
||||
if (couldread) then
|
||||
if (wx.wxDirExists(name)) then
|
||||
table.insert(outtab,name)
|
||||
end
|
||||
id = id + 1
|
||||
end
|
||||
end
|
||||
|
||||
if fntab then fntab(outtab) end
|
||||
|
||||
settings:SetPath(path)
|
||||
|
||||
return outtab
|
||||
end
|
||||
|
||||
---
|
||||
-- () SettingsSaveProjectSession (table projdirs)
|
||||
-- saves the list of currently active projects
|
||||
-- in the settings.
|
||||
function SettingsSaveProjectSession(projdirs)
|
||||
local listname = "/projectsession"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,dir in ipairs(projdirs) do
|
||||
settings:Write(tostring(i), dir)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
-----------------------------------
|
||||
|
||||
|
||||
local function saveNotebook(nb)
|
||||
local cnt = nb:GetPageCount()
|
||||
|
||||
local function addTo(tab,key,value)
|
||||
local out = tab[key] or {}
|
||||
table.insert(out,value)
|
||||
tab[key] = out
|
||||
end
|
||||
|
||||
local pagesX = {}
|
||||
local pagesY = {}
|
||||
|
||||
local str = "nblayout|"
|
||||
|
||||
for i=1,cnt do
|
||||
local id = nb:GetPageText(i-1)
|
||||
|
||||
local pg = nb:GetPage(i-1)
|
||||
local x,y = pg:GetPosition():GetXY()
|
||||
addTo(pagesX,x,id)
|
||||
addTo(pagesY,y,id)
|
||||
end
|
||||
|
||||
local function sortedPages(tab)
|
||||
local t = {}
|
||||
for i,v in pairs(tab) do
|
||||
table.insert(t,i)
|
||||
end
|
||||
table.sort(t)
|
||||
return t
|
||||
end
|
||||
|
||||
sortedX = sortedPages(pagesX)
|
||||
sortedY = sortedPages(pagesY)
|
||||
|
||||
-- for now only support "1D" splits and prefer
|
||||
-- dimension which has more, anything else
|
||||
-- requires a more complex algorithm, yet to do
|
||||
|
||||
local pagesUse
|
||||
local sortedUse
|
||||
local split
|
||||
|
||||
if ( #sortedX >= #sortedY) then
|
||||
pagesUse = pagesX
|
||||
sortedUse = sortedX
|
||||
split = "<X>"
|
||||
else
|
||||
pagesUse = pagesY
|
||||
sortedUse = sortedY
|
||||
split = "<Y>"
|
||||
end
|
||||
|
||||
for i,v in ipairs(sortedUse) do
|
||||
local pages = pagesUse[v]
|
||||
for n,id in ipairs(pages) do
|
||||
str = str..id.."|"
|
||||
end
|
||||
str = str..split.."|"
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
local function loadNotebook(nb,str,fnIdConvert)
|
||||
str = str:match("nblayout|(.+)")
|
||||
if (not str) then return end
|
||||
local cnt = nb:GetPageCount()
|
||||
local sel = nb:GetSelection()
|
||||
|
||||
|
||||
-- store old pages
|
||||
local currentpages = {}
|
||||
for i=1,cnt do
|
||||
local id = nb:GetPageText(i-1)
|
||||
local newid = fnIdConvert and fnIdConvert(id) or id
|
||||
currentpages[newid] = {page = nb:GetPage(i-1), text = id, index = i-1}
|
||||
end
|
||||
|
||||
-- remove them
|
||||
for i=cnt,1,-1 do
|
||||
nb:RemovePage(i-1)
|
||||
end
|
||||
|
||||
-- readd them and perform splits
|
||||
local direction
|
||||
local splits = {
|
||||
X = wx.wxRIGHT,
|
||||
Y = wx.wxBOTTOM,
|
||||
}
|
||||
local t = 0
|
||||
local newsel
|
||||
local function finishPage(page)
|
||||
if (page.index == sel) then
|
||||
newsel = t
|
||||
end
|
||||
t = t + 1
|
||||
end
|
||||
|
||||
for cmd in str:gmatch("([^|]+)") do
|
||||
local instr = cmd:match("<(%w)>")
|
||||
if (not instr) then
|
||||
local id = fnIdConvert and fnIdConvert(cmd) or cmd
|
||||
local page = currentpages[id]
|
||||
if (page) then
|
||||
nb:AddPage(page.page, page.text)
|
||||
currentpages[id] = nil
|
||||
if (direction) then
|
||||
nb:Split(t, direction)
|
||||
end
|
||||
finishPage(page)
|
||||
end
|
||||
end
|
||||
direction = instr and splits[instr]
|
||||
end
|
||||
|
||||
-- add anything we forgot
|
||||
for i,page in pairs(currentpages) do
|
||||
nb:AddPage(page.page, page.text)
|
||||
finishPage(page)
|
||||
end
|
||||
|
||||
if (newsel) then
|
||||
nb:SetSelection(newsel)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function SettingsRestoreView()
|
||||
local listname = "/view"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
|
||||
local frame = ide.frame
|
||||
local uimgr = frame.uimgr
|
||||
|
||||
local layoutcur = uimgr:SavePerspective()
|
||||
local layout = settingsReadSafe(settings,"uimgrlayout",layoutcur)
|
||||
if (layout ~= layoutcur) then
|
||||
uimgr:LoadPerspective(layout)
|
||||
uimgr:Update()
|
||||
end
|
||||
|
||||
local layoutcur = saveNotebook(frame.notebook)
|
||||
local layout = settingsReadSafe(settings,"nblayout",layoutcur)
|
||||
if (layout ~= layoutcur) then
|
||||
loadNotebook(ide.frame.notebook,layout)
|
||||
local openDocuments = ide.openDocuments
|
||||
local nb = frame.notebook
|
||||
local cnt = nb:GetPageCount()
|
||||
for i=0,cnt-1 do
|
||||
openDocuments[nb:GetPage(i):GetId()].index = i
|
||||
end
|
||||
end
|
||||
|
||||
local layoutcur = saveNotebook(frame.bottomnotebook)
|
||||
local layout = settingsReadSafe(settings,"nbbtmlayout",layoutcur)
|
||||
if (layout ~= layoutcur) then
|
||||
loadNotebook(ide.frame.bottomnotebook,layout,
|
||||
function(name) return name:match("console") or name end)
|
||||
end
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsSaveView()
|
||||
local listname = "/view"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
local frame = ide.frame
|
||||
local uimgr = frame.uimgr
|
||||
|
||||
settings:Write("uimgrlayout",uimgr:SavePerspective())
|
||||
settings:Write("nblayout", saveNotebook(frame.notebook))
|
||||
settings:Write("nbbtmlayout",saveNotebook(frame.bottomnotebook))
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsRestoreEditorSettings()
|
||||
local listname = "/editor"
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(listname)
|
||||
|
||||
ide.config.interpreter = settingsReadSafe(settings,"interpreter",ide.config.interpreter)
|
||||
ProjectSetInterpreter(ide.config.interpreter)
|
||||
end
|
||||
function SettingsSaveEditorSettings()
|
||||
local listname = "/editor"
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
settings:Write("interpreter", ide.interpreter and ide.interpreter.fname or "_undefined_")
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
@@ -1,195 +1,372 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
--
|
||||
-- shellbox - a lua testbed environment within estrela
|
||||
--
|
||||
|
||||
local shellbox = ide.frame.vsplitter.splitter.bottomnotebook.shellbox
|
||||
local out = shellbox.output
|
||||
local code = shellbox.input
|
||||
local remote = shellbox.remote
|
||||
|
||||
local remotesend
|
||||
local remoteuid
|
||||
|
||||
local frame = ide.frame
|
||||
out:SetFont(ide.ofont)
|
||||
out:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.ofont)
|
||||
out:StyleClearAll()
|
||||
out:SetBufferedDraw(true)
|
||||
out:WrapCount(80)
|
||||
out:MarkerDefine(BREAKPOINT_MARKER, wxstc.wxSTC_MARK_BACKGROUND, wx.wxBLACK, wx.wxColour(255, 220, 220))
|
||||
out:SetReadOnly(true)
|
||||
StylesApplyToEditor(ide.config.stylesoutshell,out,ide.ofont,ide.ofontItalic)
|
||||
|
||||
local function shellPrint(...)
|
||||
out:SetReadOnly(false)
|
||||
local cnt = select('#',...)
|
||||
for i=1,cnt do
|
||||
local x = select(i,...)
|
||||
out:InsertText(out:GetLength(),tostring(x)..(i < cnt and "\t" or ""))
|
||||
end
|
||||
out:InsertText(out:GetLength(),"\n")
|
||||
out:GotoPos(out:GetLength())
|
||||
out:SetReadOnly(true)
|
||||
end
|
||||
|
||||
DisplayShell = shellPrint
|
||||
DisplayShellErr = function (...)
|
||||
out:MarkerAdd(out:GetLineCount()-1, BREAKPOINT_MARKER)
|
||||
DisplayShell("! " .. ...)
|
||||
end
|
||||
|
||||
local function createenv ()
|
||||
local env = {}
|
||||
setmetatable(env,{__index = _G})
|
||||
|
||||
local function luafilename(level)
|
||||
level = level and level + 1 or 2
|
||||
local src
|
||||
while (true) do
|
||||
src = debug.getinfo(level)
|
||||
if (src == nil) then return nil,level end
|
||||
if (string.byte(src.source) == string.byte("@")) then
|
||||
return string.sub(src.source,2),level
|
||||
end
|
||||
level = level + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function luafilepath(level)
|
||||
local src,level = luafilename(level)
|
||||
if (src == nil) then return src,level end
|
||||
src = string.gsub(src,"[\\/][^\\//]*$","")
|
||||
return src,level
|
||||
end
|
||||
|
||||
local function relativeFilename(file)
|
||||
assert(type(file)=='string',"String as filename expected")
|
||||
local name = file
|
||||
local level = 3
|
||||
while (name) do
|
||||
if (wx.wxFileName(name):FileExists()) then return name end
|
||||
name,level = luafilepath(level)
|
||||
if (name == nil) then break end
|
||||
name = name .. "/" .. file
|
||||
end
|
||||
|
||||
return file
|
||||
end
|
||||
|
||||
local function relativeFilepath(file)
|
||||
local name,level = luafilepath(3)
|
||||
return (file and name) and name.."/"..file or file or name
|
||||
end
|
||||
|
||||
|
||||
local _loadfile = loadfile
|
||||
local function loadfile(file)
|
||||
assert(type(file)=='string',"String as filename expected")
|
||||
local name = relativeFilename(file)
|
||||
|
||||
return _loadfile(name)
|
||||
end
|
||||
|
||||
local function dofile(file, ...)
|
||||
assert(type(file) == 'string',"String as filename expected")
|
||||
local fn,err = loadfile(file)
|
||||
local args = {...}
|
||||
if not fn then
|
||||
shellPrint("Error: "..err)
|
||||
else
|
||||
setfenv(fn,env)
|
||||
xpcall(function() return fn(unpack(args)) end,function(err)
|
||||
shellPrint(debug.traceback(err))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
env.print = shellPrint
|
||||
env.dofile = dofile
|
||||
env.loadfile = loadfile
|
||||
env.RELFILE = relativeFilename
|
||||
env.RELPATH = relativeFilepath
|
||||
|
||||
return env
|
||||
end
|
||||
|
||||
local env = createenv()
|
||||
|
||||
code:SetBufferedDraw(true)
|
||||
code:SetFont(ide.ofont)
|
||||
code:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.ofont)
|
||||
code:StyleClearAll()
|
||||
code:SetTabWidth(4)
|
||||
code:SetIndent(ide.config.editor.tabwidth or 4)
|
||||
code:SetUseTabs(ide.config.editor.usetabs and true or false)
|
||||
code:SetViewWhiteSpace(ide.config.editor.whitespace and true or false)
|
||||
code:SetIndentationGuides(true)
|
||||
--StylesApplyToEditor(ide.config.stylesoutshell,code,ide.ofont,ide.ofontItalic)
|
||||
SetupKeywords(code,"lua",nil,ide.config.stylesoutshell,ide.ofont,ide.ofontItalic)
|
||||
|
||||
local accel = wx.wxAcceleratorTable{
|
||||
{wx.wxACCEL_CTRL,13,ID "shellbox.execute"},
|
||||
{wx.wxACCEL_CTRL+wx.wxACCEL_ALT,string.byte "\b",ID "shellbox.eraseall"}
|
||||
}
|
||||
code:SetAcceleratorTable(accel)
|
||||
|
||||
function ShellExecuteCode(ev,wfilename)
|
||||
local fn,err
|
||||
local tx
|
||||
local marker = "> " -- local execution
|
||||
if (wfilename) then
|
||||
fn,err = loadfile(wfilename:GetFullPath())
|
||||
elseif(remotesend and remote:IsChecked()) then
|
||||
marker = ">> " -- remote execution
|
||||
tx = code:GetText()
|
||||
remotesend(tx)
|
||||
else
|
||||
tx = code:GetText()
|
||||
-- return (...) works for everything except assignments
|
||||
fn,err = loadstring("return (" .. tx .. ")")
|
||||
if err then -- now try assignments
|
||||
fn,err = loadstring(tx)
|
||||
end
|
||||
end
|
||||
|
||||
if (tx ~= nil) then
|
||||
DisplayShell(marker .. tx)
|
||||
end
|
||||
|
||||
if fn==nil and err then
|
||||
DisplayShellErr(err)
|
||||
elseif fn then
|
||||
setfenv(fn,env)
|
||||
local ok, res = pcall(fn)
|
||||
if ok then DisplayShell(res)
|
||||
else DisplayShellErr(res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ShellSupportRemote(client,uid)
|
||||
remote:Enable(client and true or false)
|
||||
remotesend = client
|
||||
remoteuid = client and uid
|
||||
if (not client) then
|
||||
remote:SetValue(false)
|
||||
end
|
||||
end
|
||||
|
||||
shellbox:Connect(wxstc.wxEVT_STC_CHARADDED,
|
||||
function (event)
|
||||
frame:SetStatusText("Execute your code pressing CTRL+ENTER")
|
||||
end)
|
||||
frame:Connect(ID "shellbox.eraseall", wx.wxEVT_COMMAND_MENU_SELECTED, function()
|
||||
code:SetText ""
|
||||
end)
|
||||
frame:Connect(ID "shellbox.execute", wx.wxEVT_COMMAND_MENU_SELECTED, ShellExecuteCode)
|
||||
shellbox:Connect(ID "shellbox.run",wx.wxEVT_COMMAND_BUTTON_CLICKED, ShellExecuteCode)
|
||||
shellbox:Connect(ID "shellbox.remote",wx.wxEVT_COMMAND_CHECKBOX_CLICKED, function(event)
|
||||
if (remotesend) then
|
||||
CommandLineToShell(remoteuid,event:IsChecked())
|
||||
end
|
||||
end)
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
--
|
||||
-- shellbox - a lua testbed environment within the IDE
|
||||
--
|
||||
|
||||
local bottomnotebook = ide.frame.bottomnotebook
|
||||
local out = bottomnotebook.shellbox
|
||||
|
||||
local remotesend
|
||||
|
||||
local OUTPUT_MARKER = 3
|
||||
local OUTPUT_MARKER_VALUE = 8 -- = 2^OUTPUT_MARKER
|
||||
|
||||
local frame = ide.frame
|
||||
out:SetFont(ide.ofont)
|
||||
out:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.ofont)
|
||||
out:StyleClearAll()
|
||||
out:SetBufferedDraw(true)
|
||||
|
||||
out:SetTabWidth(ide.config.editor.tabwidth or 2)
|
||||
out:SetIndent(ide.config.editor.tabwidth or 2)
|
||||
out:SetUseTabs(ide.config.editor.usetabs and true or false)
|
||||
out:SetViewWhiteSpace(ide.config.editor.whitespace and true or false)
|
||||
out:SetIndentationGuides(true)
|
||||
|
||||
out:SetWrapMode(wxstc.wxSTC_WRAP_WORD)
|
||||
out:SetWrapStartIndent(2)
|
||||
out:SetWrapVisualFlagsLocation(wxstc.wxSTC_WRAPVISUALFLAGLOC_END_BY_TEXT)
|
||||
out:SetWrapVisualFlags(wxstc.wxSTC_WRAPVISUALFLAG_START)
|
||||
out:WrapCount(80)
|
||||
|
||||
out:MarkerDefine(CURRENT_LINE_MARKER, wxstc.wxSTC_MARK_CHARACTER+string.byte('>'), wx.wxBLACK, wx.wxColour(240, 240, 240))
|
||||
out:MarkerDefine(BREAKPOINT_MARKER, wxstc.wxSTC_MARK_BACKGROUND, wx.wxBLACK, wx.wxColour(255, 220, 220))
|
||||
out:MarkerDefine(OUTPUT_MARKER, wxstc.wxSTC_MARK_BACKGROUND, wx.wxBLACK, wx.wxColour(240, 240, 240))
|
||||
out:SetReadOnly(false)
|
||||
|
||||
SetupKeywords(out,"lua",nil,ide.config.stylesoutshell,ide.ofont,ide.ofontItalic)
|
||||
|
||||
local function getPromptLine()
|
||||
local totalLines = out:GetLineCount()
|
||||
return out:MarkerPrevious(totalLines+1, CURRENT_LINE_MARKER_VALUE)
|
||||
end
|
||||
|
||||
local function getPromptText()
|
||||
local prompt = getPromptLine()
|
||||
return out:GetTextRange(out:PositionFromLine(prompt), out:GetLength())
|
||||
end
|
||||
|
||||
local function setPromptText(text)
|
||||
local length = out:GetLength()
|
||||
out:SetTargetStart(length - string.len(getPromptText()))
|
||||
out:SetTargetEnd(length)
|
||||
out:ReplaceTarget(text)
|
||||
out:GotoPos(out:GetLength())
|
||||
end
|
||||
|
||||
local function positionInLine(line)
|
||||
return out:GetCurrentPos() - out:PositionFromLine(line)
|
||||
end
|
||||
|
||||
local function caretOnPromptLine(disallowLeftmost)
|
||||
local promptLine = getPromptLine()
|
||||
local boundary = disallowLeftmost and 0 or -1
|
||||
return (out:GetCurrentLine() > promptLine
|
||||
or out:GetCurrentLine() == promptLine and positionInLine(promptLine) > boundary)
|
||||
end
|
||||
|
||||
local function chomp(line)
|
||||
return line:gsub("%s+$", "")
|
||||
end
|
||||
|
||||
local function getInput(line)
|
||||
local nextMarker = line
|
||||
|
||||
repeat
|
||||
nextMarker = nextMarker+1
|
||||
until out:MarkerGet(nextMarker) > 0 -- check until we find at least some marker
|
||||
return chomp(out:GetTextRange(out:PositionFromLine(line),
|
||||
out:PositionFromLine(nextMarker)))
|
||||
end
|
||||
|
||||
local currentHistory
|
||||
local function getNextHistoryLine(forward, promptText)
|
||||
local count = out:GetLineCount()
|
||||
if currentHistory == nil then currentHistory = count end
|
||||
|
||||
if forward then
|
||||
currentHistory = out:MarkerNext(currentHistory+1, CURRENT_LINE_MARKER_VALUE)
|
||||
if currentHistory == -1 then
|
||||
currentHistory = count
|
||||
return ""
|
||||
end
|
||||
else
|
||||
currentHistory = out:MarkerPrevious(currentHistory-1, CURRENT_LINE_MARKER_VALUE)
|
||||
if currentHistory == -1 then
|
||||
currentHistory = -1
|
||||
return ""
|
||||
end
|
||||
end
|
||||
-- need to skip the current prompt line
|
||||
-- or skip repeated commands
|
||||
if currentHistory == getPromptLine()
|
||||
or getInput(currentHistory) == promptText then
|
||||
return getNextHistoryLine(forward, promptText)
|
||||
end
|
||||
return getInput(currentHistory)
|
||||
end
|
||||
|
||||
local function shellPrint(marker, ...)
|
||||
local cnt = select('#',...)
|
||||
local isPrompt = marker and (getPromptLine() > -1)
|
||||
|
||||
local text = ''
|
||||
for i=1,cnt do
|
||||
local x = select(i,...)
|
||||
text = text .. tostring(x)..(i < cnt and "\t" or "")
|
||||
end
|
||||
-- add "\n" if it is missing
|
||||
if text then text = text:gsub("\n$", "") .. "\n" end
|
||||
|
||||
local lines = out:GetLineCount()
|
||||
local promptLine = isPrompt and getPromptLine() or nil
|
||||
local insertLineAt = isPrompt and getPromptLine() or out:GetLineCount()-1
|
||||
local insertAt = isPrompt and out:PositionFromLine(getPromptLine()) or out:GetLength()
|
||||
out:InsertText(insertAt, text)
|
||||
local linesAdded = out:GetLineCount() - lines
|
||||
|
||||
if marker then
|
||||
if promptLine then out:MarkerDelete(promptLine, CURRENT_LINE_MARKER) end
|
||||
for line = insertLineAt, insertLineAt + linesAdded - 1 do
|
||||
out:MarkerAdd(line, marker)
|
||||
end
|
||||
if promptLine then out:MarkerAdd(promptLine+linesAdded, CURRENT_LINE_MARKER) end
|
||||
end
|
||||
|
||||
out:EmptyUndoBuffer() -- don't allow the user to undo shell text
|
||||
out:GotoPos(out:GetLength())
|
||||
end
|
||||
|
||||
DisplayShell = function (...)
|
||||
shellPrint(OUTPUT_MARKER, ...)
|
||||
end
|
||||
DisplayShellErr = function (...)
|
||||
shellPrint(BREAKPOINT_MARKER, ...)
|
||||
end
|
||||
DisplayShellDirect = function (...)
|
||||
shellPrint(nil, ...)
|
||||
end
|
||||
DisplayShellPrompt = function (...)
|
||||
-- don't print anything; just mark the line with a prompt mark
|
||||
out:MarkerAdd(out:GetLineCount()-1, CURRENT_LINE_MARKER)
|
||||
end
|
||||
|
||||
local function filterTraceError(err, addedret)
|
||||
local err = err:match("(.-:%d+:.-)\n[^\n]*\n[^\n]*\n[^\n]*src/editor/shellbox.lua:.*in function 'executeShellCode'")
|
||||
err = err:gsub("stack traceback:.-\n[^\n]+\n?","")
|
||||
if addedret then err = err:gsub('^%[string "return ', '[string "') end
|
||||
err = err:match("(.*)\n[^\n]*%(tail call%): %?$") or err
|
||||
return err
|
||||
end
|
||||
|
||||
local function createenv ()
|
||||
local env = {}
|
||||
setmetatable(env,{__index = _G})
|
||||
|
||||
local function luafilename(level)
|
||||
level = level and level + 1 or 2
|
||||
local src
|
||||
while (true) do
|
||||
src = debug.getinfo(level)
|
||||
if (src == nil) then return nil,level end
|
||||
if (string.byte(src.source) == string.byte("@")) then
|
||||
return string.sub(src.source,2),level
|
||||
end
|
||||
level = level + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function luafilepath(level)
|
||||
local src,level = luafilename(level)
|
||||
if (src == nil) then return src,level end
|
||||
src = string.gsub(src,"[\\/][^\\//]*$","")
|
||||
return src,level
|
||||
end
|
||||
|
||||
local function relativeFilename(file)
|
||||
assert(type(file)=='string',"String as filename expected")
|
||||
local name = file
|
||||
local level = 3
|
||||
while (name) do
|
||||
if (wx.wxFileName(name):FileExists()) then return name end
|
||||
name,level = luafilepath(level)
|
||||
if (name == nil) then break end
|
||||
name = name .. "/" .. file
|
||||
end
|
||||
|
||||
return file
|
||||
end
|
||||
|
||||
local function relativeFilepath(file)
|
||||
local name,level = luafilepath(3)
|
||||
return (file and name) and name.."/"..file or file or name
|
||||
end
|
||||
|
||||
local _loadfile = loadfile
|
||||
local function loadfile(file)
|
||||
assert(type(file)=='string',"String as filename expected")
|
||||
local name = relativeFilename(file)
|
||||
|
||||
return _loadfile(name)
|
||||
end
|
||||
|
||||
local function dofile(file, ...)
|
||||
assert(type(file) == 'string',"String as filename expected")
|
||||
local fn,err = loadfile(file)
|
||||
local args = {...}
|
||||
if not fn then
|
||||
DisplayShellErr(err)
|
||||
else
|
||||
setfenv(fn,env)
|
||||
return fn(unpack(args))
|
||||
end
|
||||
end
|
||||
|
||||
env.print = DisplayShell
|
||||
env.dofile = dofile
|
||||
env.loadfile = loadfile
|
||||
env.RELFILE = relativeFilename
|
||||
env.RELPATH = relativeFilepath
|
||||
|
||||
return env
|
||||
end
|
||||
|
||||
local env = createenv()
|
||||
|
||||
local function executeShellCode(tx)
|
||||
if tx == nil or tx == '' then return end
|
||||
|
||||
DisplayShellDirect('\n')
|
||||
DisplayShellPrompt('')
|
||||
|
||||
local addedret = false
|
||||
local fn,err
|
||||
if remotesend then
|
||||
remotesend(tx)
|
||||
else
|
||||
fn,err = loadstring(tx)
|
||||
-- for statement queries create the return
|
||||
if err and (err:find("'=' expected near '<eof>'") or
|
||||
err:find("unexpected symbol near '")) then
|
||||
local errmore
|
||||
fn,errmore = loadstring("return "..tx:gsub("^%s*=%s*",""))
|
||||
addedret = not errmore
|
||||
end
|
||||
end
|
||||
|
||||
if fn == nil and err then
|
||||
DisplayShellErr(err)
|
||||
elseif fn then
|
||||
setfenv(fn,env)
|
||||
local ok, res = xpcall(fn,
|
||||
function(err)
|
||||
DisplayShellErr(filterTraceError(debug.traceback(err), addedret))
|
||||
end)
|
||||
|
||||
if ok and (addedret or res ~= nil) then DisplayShell(res) end
|
||||
end
|
||||
end
|
||||
|
||||
function ShellSupportRemote(client,uid)
|
||||
remotesend = client
|
||||
|
||||
-- change the name of the tab: console is the second page in the notebook
|
||||
bottomnotebook:SetPageText(1,
|
||||
client and "Remote console" or "Local console")
|
||||
end
|
||||
|
||||
function ShellExecuteCode(wfilename)
|
||||
if (not wfilename) then return end
|
||||
local cmd = 'dofile([['..wfilename:GetFullPath()..']])'
|
||||
DisplayShellDirect(cmd)
|
||||
executeShellCode(cmd)
|
||||
end
|
||||
|
||||
local function displayShellIntro()
|
||||
DisplayShellDirect([[Welcome to the interactive Lua interpreter.
|
||||
Enter Lua code and press Enter to run it. Use Shift-Enter for multiline code.
|
||||
Use 'clear' to clear the shell output and the history. Prepend '=' to show values.]])
|
||||
DisplayShellPrompt('')
|
||||
end
|
||||
|
||||
out:Connect(wx.wxEVT_KEY_DOWN,
|
||||
function (event)
|
||||
-- this loop is only needed to allow to get to the end of function easily
|
||||
-- "return" aborts the processing and ignores the key
|
||||
-- "break" aborts the processing and processes the key normally
|
||||
while true do
|
||||
local key = event:GetKeyCode()
|
||||
if key == wx.WXK_UP or key == wx.WXK_NUMPAD_UP then
|
||||
-- if we are below the prompt line, then allow to go up
|
||||
-- through multiline entry
|
||||
if out:GetCurrentLine() > getPromptLine() then break end
|
||||
|
||||
-- if we are not on the caret line, then don't move
|
||||
if not caretOnPromptLine() then return end
|
||||
|
||||
local promptText = getPromptText()
|
||||
setPromptText(getNextHistoryLine(false, promptText))
|
||||
return
|
||||
elseif key == wx.WXK_DOWN or key == wx.WXK_NUMPAD_DOWN then
|
||||
-- if we are above the last line, then allow to go down
|
||||
-- through multiline entry
|
||||
local totalLines = out:GetLineCount()-1
|
||||
if out:GetCurrentLine() < totalLines then break end
|
||||
|
||||
if not caretOnPromptLine() then break end
|
||||
local promptText = getPromptText()
|
||||
setPromptText(getNextHistoryLine(true, promptText))
|
||||
return
|
||||
elseif key == wx.WXK_LEFT or key == wx.WXK_NUMPAD_LEFT then
|
||||
if not caretOnPromptLine(true) then return end
|
||||
elseif key == wx.WXK_BACK then
|
||||
if not caretOnPromptLine(true) then return end
|
||||
elseif key == wx.WXK_DELETE or key == wx.WXK_NUMPAD_DELETE then
|
||||
if not caretOnPromptLine()
|
||||
or out:LineFromPosition(out:GetSelectionStart()) < getPromptLine() then
|
||||
return
|
||||
end
|
||||
elseif key == wx.WXK_PAGEUP or key == wx.WXK_NUMPAD_PAGEUP
|
||||
or key == wx.WXK_PAGEDOWN or key == wx.WXK_NUMPAD_PAGEDOWN
|
||||
or key == wx.WXK_END or key == wx.WXK_NUMPAD_END
|
||||
or key == wx.WXK_HOME or key == wx.WXK_NUMPAD_HOME
|
||||
or key == wx.WXK_RIGHT or key == wx.WXK_NUMPAD_RIGHT
|
||||
or key == wx.WXK_SHIFT or key == wx.WXK_CONTROL
|
||||
or key == wx.WXK_ALT then
|
||||
break
|
||||
elseif key == wx.WXK_RETURN or key == WXK_NUMPAD_ENTER then
|
||||
if not caretOnPromptLine()
|
||||
or out:LineFromPosition(out:GetSelectionStart()) < getPromptLine() then
|
||||
return
|
||||
end
|
||||
|
||||
-- allow multiline entry for shift+enter
|
||||
if caretOnPromptLine(true) and event:ShiftDown() then break end
|
||||
|
||||
local promptText = getPromptText()
|
||||
if promptText == 'clear' then
|
||||
out:ClearAll()
|
||||
displayShellIntro()
|
||||
else
|
||||
executeShellCode(promptText)
|
||||
end
|
||||
currentHistory = getPromptLine() -- reset history
|
||||
return -- don't need to do anything else with return
|
||||
else
|
||||
-- move cursor to end if not already there
|
||||
if not caretOnPromptLine() then
|
||||
out:GotoPos(out:GetLength())
|
||||
-- check if the selection starts before the prompt line and reset it
|
||||
elseif out:LineFromPosition(out:GetSelectionStart()) < getPromptLine() then
|
||||
out:GotoPos(out:GetLength())
|
||||
out:SetSelection(out:GetSelectionEnd()+1,out:GetSelectionEnd())
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
displayShellIntro()
|
||||
|
||||
@@ -1,101 +1,100 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
--[[ single instance
|
||||
open an UDP port - if it fails it is either because
|
||||
- Estrela is running already
|
||||
- an application is already blocking that port
|
||||
if it fails it tries to contact the running application
|
||||
- if it confirms being the estrela IDE we let that instance open it, finish our application
|
||||
- otherwise we throw an error message on the user and start like normal
|
||||
|
||||
probably a pitfal: an estreala instance is running but is not visible (because it was finished
|
||||
though the UDP thing still runs)
|
||||
]]
|
||||
|
||||
if not ide.config.singleinstance then return end
|
||||
|
||||
require "socket"
|
||||
|
||||
local port = ide.config.singleinstanceport
|
||||
|
||||
local svr = socket.udp()
|
||||
|
||||
local success, errmsg = svr:setsockname("127.0.0.1",port) -- bind on local host
|
||||
|
||||
local protocoll = {client = {}, server = {}}
|
||||
|
||||
protocoll.client.greeting = "Is this you, Estrela? It's me, a new instance."
|
||||
protocoll.server.greeting = "Yes it is me, how may I serve you?"
|
||||
protocoll.client.requestloading = "Could you please load this file for me: %s"
|
||||
protocoll.server.answerok = "Sure. You may now leave."
|
||||
|
||||
if success then -- ok, server was started, we are solo
|
||||
--TODO: if multiple files are to be opened, each file is handled one by one - we could create a single string instead...
|
||||
ide.idletimer = wx.wxTimer(wx.wxGetApp())
|
||||
ide.idletimer:Start(200,false)
|
||||
svr:settimeout(0) -- don't block
|
||||
wx.wxGetApp():Connect(wx.wxEVT_TIMER,function (evt)
|
||||
if ide.exitingProgram then -- if exiting, terminate the timer loop
|
||||
wx.wxGetApp():Disconnect(wx.wxEVT_TIMER)
|
||||
return
|
||||
end
|
||||
|
||||
local msg, err, port = svr:receivefrom() -- receive a msg
|
||||
if msg then
|
||||
local ip = err -- the errmsg is actually the IP
|
||||
-- DisplayOutput("client sent request: "..tostring(ip)..","..tostring(port).."\n")
|
||||
-- DisplayOutput("UDP.SingleInstanceServer: "..msg.."\n")
|
||||
if msg == protocoll.client.greeting then -- just send back hi
|
||||
svr:sendto(protocoll.server.greeting,ip,port)
|
||||
elseif msg:match(protocoll.client.requestloading:gsub("%%s",".+$")) then -- ok we need to open something
|
||||
local filename = msg:match(protocoll.client.requestloading:gsub("%%s","(.+)$"))
|
||||
-- DisplayOutput("UDP.SingleInstanceServer: open file "..filename.."\n")
|
||||
|
||||
LoadFile(filename, nil, true)
|
||||
svr:sendto(protocoll.server.answerok,ip,port)
|
||||
|
||||
|
||||
ide.frame:RequestUserAttention() -- let's let the user know we want his attention
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
--DisplayOutput("check "..os.clock().."\n")
|
||||
end)
|
||||
else -- something different is running on our port
|
||||
local cln = socket.udp()
|
||||
cln:setpeername("127.0.0.1",port)
|
||||
cln:settimeout(5) -- two seconds of waiting should be enough, if no response, we asume we are running
|
||||
|
||||
cln:send(protocoll.client.greeting)
|
||||
|
||||
local msg,err = cln:receive()
|
||||
local arg = ide.arg
|
||||
if msg and msg == protocoll.server.greeting then
|
||||
local failed = false
|
||||
for index = 2, #arg do
|
||||
local fileName = arg[index]
|
||||
if fileName ~= "--" then
|
||||
cln:send(protocoll.client.requestloading:format(fileName))
|
||||
|
||||
local msg,err = cln:receive()
|
||||
if msg~=protocoll.server.answerok then
|
||||
failed = true
|
||||
print(err,msg)
|
||||
else
|
||||
end
|
||||
end
|
||||
end
|
||||
if failed then
|
||||
print("The server instance failed to open the files, this instance will continue running.")
|
||||
else -- done
|
||||
os.exit(0)
|
||||
end
|
||||
--DisplayOutput("OK\n")
|
||||
else
|
||||
print("The Single instance communication has failed, it is not certain if this is the only running instance")
|
||||
end
|
||||
end
|
||||
|
||||
--print("UDP Server: "..success.." - "..tostring(errmsg).."\n")
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
--[[ single instance
|
||||
open an UDP port - if it fails it is either because
|
||||
- IDE is running already
|
||||
- an application is already blocking that port
|
||||
if it fails it tries to contact the running application
|
||||
- if it confirms being the IDE we let that instance open it, finish our application
|
||||
- otherwise we throw an error message on the user and start like normal
|
||||
|
||||
probably a pitfal: an estreala instance is running but is not visible (because it was finished
|
||||
though the UDP thing still runs)
|
||||
]]
|
||||
|
||||
if not ide.config.singleinstance then return end
|
||||
|
||||
require "socket"
|
||||
|
||||
local port = ide.config.singleinstanceport
|
||||
|
||||
local svr = socket.udp()
|
||||
|
||||
local success, errmsg = svr:setsockname("127.0.0.1",port) -- bind on local host
|
||||
|
||||
local protocoll = {client = {}, server = {}}
|
||||
|
||||
protocoll.client.greeting = "Is this you, my IDE? It's me, a new instance."
|
||||
protocoll.server.greeting = "Yes it is me, how may I serve you?"
|
||||
protocoll.client.requestloading = "Could you please load this file for me: %s"
|
||||
protocoll.server.answerok = "Sure. You may now leave."
|
||||
|
||||
if success then -- ok, server was started, we are solo
|
||||
--TODO: if multiple files are to be opened, each file is handled one by one - we could create a single string instead...
|
||||
ide.idletimer = wx.wxTimer(wx.wxGetApp())
|
||||
ide.idletimer:Start(200,false)
|
||||
svr:settimeout(0) -- don't block
|
||||
wx.wxGetApp():Connect(wx.wxEVT_TIMER,function (evt)
|
||||
if ide.exitingProgram then -- if exiting, terminate the timer loop
|
||||
wx.wxGetApp():Disconnect(wx.wxEVT_TIMER)
|
||||
return
|
||||
end
|
||||
|
||||
local msg, err, port = svr:receivefrom() -- receive a msg
|
||||
if msg then
|
||||
local ip = err -- the errmsg is actually the IP
|
||||
-- DisplayOutput("client sent request: "..tostring(ip)..","..tostring(port).."\n")
|
||||
-- DisplayOutput("UDP.SingleInstanceServer: "..msg.."\n")
|
||||
if msg == protocoll.client.greeting then -- just send back hi
|
||||
svr:sendto(protocoll.server.greeting,ip,port)
|
||||
elseif msg:match(protocoll.client.requestloading:gsub("%%s",".+$")) then -- ok we need to open something
|
||||
local filename = msg:match(protocoll.client.requestloading:gsub("%%s","(.+)$"))
|
||||
-- DisplayOutput("UDP.SingleInstanceServer: open file "..filename.."\n")
|
||||
|
||||
LoadFile(filename, nil, true)
|
||||
svr:sendto(protocoll.server.answerok,ip,port)
|
||||
|
||||
ide.frame:RequestUserAttention() -- let's let the user know we want his attention
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
--DisplayOutput("check "..os.clock().."\n")
|
||||
end)
|
||||
else -- something different is running on our port
|
||||
local cln = socket.udp()
|
||||
cln:setpeername("127.0.0.1",port)
|
||||
cln:settimeout(5) -- two seconds of waiting should be enough, if no response, we asume we are running
|
||||
|
||||
cln:send(protocoll.client.greeting)
|
||||
|
||||
local msg,err = cln:receive()
|
||||
local arg = ide.arg
|
||||
if msg and msg == protocoll.server.greeting then
|
||||
local failed = false
|
||||
for index = 2, #arg do
|
||||
local fileName = arg[index]
|
||||
if fileName ~= "--" then
|
||||
cln:send(protocoll.client.requestloading:format(fileName))
|
||||
|
||||
local msg,err = cln:receive()
|
||||
if msg~=protocoll.server.answerok then
|
||||
failed = true
|
||||
print(err,msg)
|
||||
else
|
||||
end
|
||||
end
|
||||
end
|
||||
if failed then
|
||||
print("The server instance failed to open the files, this instance will continue running.")
|
||||
else -- done
|
||||
os.exit(0)
|
||||
end
|
||||
--DisplayOutput("OK\n")
|
||||
else
|
||||
print("The Single instance communication has failed, it is not certain if this is the only running instance")
|
||||
end
|
||||
end
|
||||
|
||||
--print("UDP Server: "..success.." - "..tostring(errmsg).."\n")
|
||||
|
||||
@@ -1,301 +1,294 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
----------
|
||||
-- Style
|
||||
--
|
||||
-- common style attributes
|
||||
-- ---------------------------
|
||||
-- fg foreground - {r,g,b} 0-255
|
||||
-- bg background - {r,g,b} 0-255
|
||||
-- u underline - boolean
|
||||
-- b bold - boolean
|
||||
-- i italic - boolean
|
||||
-- fill fill to end - boolean
|
||||
|
||||
function StylesGetDefault()
|
||||
return {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, b = true},
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0},},
|
||||
keywords2 = {fg = {0, 127, 0},},
|
||||
keywords3 = {fg = {0, 0, 127},},
|
||||
keywords4 = {fg = {127, 0, 95},},
|
||||
keywords5 = {fg = {35, 95, 175},},
|
||||
keywords6 = {fg = {0, 127, 127},},
|
||||
keywords7 = {fg = {240, 255, 255},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {192, 192, 192},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
escapechar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg )
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = {fg = {180, 180, 180},},
|
||||
|
||||
-- indicators
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
end
|
||||
|
||||
-- used to fill unset bg colors
|
||||
local defaultfg = nil
|
||||
local defaultbg = nil
|
||||
|
||||
local function applymarker(editor,marker,clrfg,clrbg)
|
||||
if (clrfg) then
|
||||
editor:MarkerSetForeground(marker,clrfg)
|
||||
end
|
||||
if (clrbg) then
|
||||
editor:MarkerSetBackground(marker,clrbg)
|
||||
end
|
||||
end
|
||||
local specialmapping = {
|
||||
sel = function(editor,style)
|
||||
if (style.fg) then
|
||||
editor:SetSelForeground(1,wx.wxColour(unpack(style.fg)))
|
||||
else
|
||||
editor:SetSelForeground(0)
|
||||
end
|
||||
if (style.bg) then
|
||||
editor:SetSelBackground(1,wx.wxColour(unpack(style.bg)))
|
||||
else
|
||||
editor:SetSelBackground(0)
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
caret = function(editor,style)
|
||||
if (style.fg) then
|
||||
editor:SetCaretForeground(wx.wxColour(unpack(style.fg)))
|
||||
end
|
||||
--if (style.bg) then
|
||||
-- editor:SetCaretBackground(wx.wxColour(unpack(style.bg)))
|
||||
--end
|
||||
end,
|
||||
|
||||
caretlinebg = function(editor,style)
|
||||
if (style.bg) then
|
||||
editor:SetCaretLineBackground(wx.wxColour(unpack(style.bg)))
|
||||
end
|
||||
end,
|
||||
|
||||
whitespace = function(editor,style)
|
||||
if (style.fg) then
|
||||
editor:SetWhitespaceForeground(1,wx.wxColour(unpack(style.fg)))
|
||||
else
|
||||
--editor:SetWhitespaceForeground(0)
|
||||
end
|
||||
if (style.bg) then
|
||||
editor:SetWhitespaceBackground(1,wx.wxColour(unpack(style.bg)))
|
||||
else
|
||||
--editor:SetWhitespaceBackground(0)
|
||||
end
|
||||
end,
|
||||
|
||||
calltipbg = function(editor,style)
|
||||
if (style.bg) then
|
||||
editor:CallTipSetBackground(wx.wxColour(unpack(style.bg)))
|
||||
end
|
||||
end,
|
||||
|
||||
|
||||
fold = function(editor,style)
|
||||
local clrfg = style.fg and wx.wxColour(unpack(style.fg))
|
||||
local clrbg = style.bg and wx.wxColour(unpack(style.bg))
|
||||
|
||||
|
||||
if (clrfg or clrbg) then
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPEN, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDER, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERSUB, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERTAIL, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEREND, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPENMID, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, clrfg,clrbg)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
local defaultmapping = {
|
||||
text = wxstc.wxSTC_STYLE_DEFAULT,
|
||||
linenumber = wxstc.wxSTC_STYLE_LINENUMBER,
|
||||
bracematch = wxstc.wxSTC_STYLE_BRACELIGHT,
|
||||
bracemiss = wxstc.wxSTC_STYLE_BRACEBAD,
|
||||
escapechar = wxstc.wxSTC_STYLE_CONTROLCHAR,
|
||||
indent = wxstc.wxSTC_STYLE_INDENTGUIDE,
|
||||
calltip = wxstc.wxSTC_STYLE_CALLTIP,
|
||||
}
|
||||
|
||||
|
||||
function StylesApplyToEditor(styles,editor,font,fontitalic,lexerconvert)
|
||||
local function applystyle(style,id)
|
||||
editor:StyleSetFont(id, style.i and fontitalic or font)
|
||||
editor:StyleSetBold(id, style.b or false)
|
||||
editor:StyleSetUnderline(id, style.u or false)
|
||||
editor:StyleSetEOLFilled(id, style.fill or false)
|
||||
|
||||
if (style.fg or defaultfg) then
|
||||
editor:StyleSetForeground(id, style.fg and wx.wxColour(unpack(style.fg)) or defaultfg)
|
||||
end
|
||||
if (style.bg or defaultbg) then
|
||||
editor:StyleSetBackground(id, style.bg and wx.wxColour(unpack(style.bg)) or defaultbg)
|
||||
end
|
||||
end
|
||||
editor:StyleResetDefault()
|
||||
editor:SetFont(font)
|
||||
if (styles.text) then
|
||||
applystyle(styles.text,defaultmapping["text"])
|
||||
else
|
||||
applystyle({},defaultmapping["text"])
|
||||
end
|
||||
editor:StyleClearAll()
|
||||
|
||||
defaultfg = styles.text and styles.text.fg and wx.wxColour(unpack(styles.text.fg)) or nil
|
||||
defaultbg = styles.text and styles.text.bg and wx.wxColour(unpack(styles.text.bg)) or nil
|
||||
|
||||
for name,style in pairs(styles) do
|
||||
if (specialmapping[name]) then
|
||||
specialmapping[name](editor,style)
|
||||
elseif (defaultmapping[name]) then
|
||||
applystyle(style,defaultmapping[name])
|
||||
end
|
||||
if (lexerconvert and lexerconvert[name]) then
|
||||
local targets = lexerconvert[name]
|
||||
|
||||
for n,outid in pairs(targets) do
|
||||
applystyle(style,outid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
editor:IndicatorSetStyle(0,styles.fncall and styles.fncall.st or wxstc.wxSTC_INDIC_BOX)
|
||||
editor:IndicatorSetForeground(0,wx.wxColour(unpack(styles.fncall and styles.fncall.fg or {128,128,128})))
|
||||
end
|
||||
|
||||
editor:Colourise(0, -1)
|
||||
end
|
||||
|
||||
|
||||
function ReApplySpecAndStyles()
|
||||
local openDocuments = ide.openDocuments
|
||||
for i,doc in pairs(openDocuments) do
|
||||
if (doc.editor.spec) then
|
||||
SetupKeywords(doc.editor,nil,doc.editor.spec)
|
||||
end
|
||||
end
|
||||
|
||||
local errorlog = ide.frame.vsplitter.splitter.bottomnotebook.errorlog
|
||||
local shellbox = ide.frame.vsplitter.splitter.bottomnotebook.shellbox
|
||||
|
||||
SetupKeywords(shellbox.input,"lua",nil,ide.config.stylesoutshell,ide.ofont,ide.ofontItalic)
|
||||
|
||||
StylesApplyToEditor(ide.config.stylesoutshell,errorlog,ide.ofont,ide.ofontItalic)
|
||||
StylesApplyToEditor(ide.config.stylesoutshell,shellbox.output,ide.ofont,ide.ofontItalic)
|
||||
end
|
||||
|
||||
function LoadConfigStyle()
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, "Open Config File",
|
||||
"/cfg",
|
||||
"",
|
||||
"Lua file (*.lua)|*.lua|All files (*)|*",
|
||||
wx.wxOPEN + wx.wxFILE_MUST_EXIST)
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
local cfg = {path = {}, editor = {}, view ={}, acandtip = {}, outputshell = {},}
|
||||
local cfgfn,err = loadfile(fileDialog:GetPath())
|
||||
if cfgfn then
|
||||
setfenv(cfgfn,cfg)
|
||||
cfgfn = xpcall(cfgfn,function(err)DisplayOutput("Error while executing configuration file: \n",debug.traceback(err))end)
|
||||
end
|
||||
|
||||
if not (cfgfn and (cfg.styles or cfg.stylesoutshell)) then
|
||||
wx.wxMessageBox("Unable to load config style '"..fileDialog:GetPath().."'.",
|
||||
"wxLua Error",
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
else
|
||||
if (cfg.styles) then
|
||||
ide.config.styles = StylesGetDefault()
|
||||
-- copy
|
||||
for i,s in pairs(cfg.styles) do
|
||||
ide.config.styles[i] = s
|
||||
end
|
||||
end
|
||||
if (cfg.stylesoutshell) then
|
||||
ide.config.stylesoutshell = StylesGetDefault()
|
||||
-- copy
|
||||
for i,s in pairs(cfg.stylesoutshell) do
|
||||
ide.config.stylesoutshell[i] = s
|
||||
end
|
||||
end
|
||||
ReApplySpecAndStyles()
|
||||
end
|
||||
end
|
||||
fileDialog:Destroy()
|
||||
|
||||
end
|
||||
|
||||
-- used lexers ?
|
||||
--[=[
|
||||
#define wxSTC_POV_DEFAULT 0
|
||||
#define wxSTC_POV_COMMENT 1
|
||||
#define wxSTC_POV_COMMENTLINE 2
|
||||
#define wxSTC_POV_NUMBER 3
|
||||
#define wxSTC_POV_OPERATOR 4
|
||||
#define wxSTC_POV_IDENTIFIER 5
|
||||
#define wxSTC_POV_STRING 6
|
||||
#define wxSTC_POV_STRINGEOL 7
|
||||
|
||||
%define wxSTC_C_DEFAULT
|
||||
%define wxSTC_C_COMMENT
|
||||
%define wxSTC_C_COMMENTLINE
|
||||
%define wxSTC_C_COMMENTDOC
|
||||
%define wxSTC_C_NUMBER
|
||||
%define wxSTC_C_WORD
|
||||
%define wxSTC_C_STRING
|
||||
%define wxSTC_C_CHARACTER
|
||||
%define wxSTC_C_UUID
|
||||
%define wxSTC_C_PREPROCESSOR
|
||||
%define wxSTC_C_OPERATOR
|
||||
%define wxSTC_C_IDENTIFIER
|
||||
%define wxSTC_C_STRINGEOL
|
||||
%define wxSTC_C_VERBATIM
|
||||
%define wxSTC_C_REGEX
|
||||
%define wxSTC_C_COMMENTLINEDOC
|
||||
%define wxSTC_C_WORD2
|
||||
%define wxSTC_C_COMMENTDOCKEYWORD
|
||||
%define wxSTC_C_COMMENTDOCKEYWORDERROR
|
||||
%define wxSTC_C_GLOBALCLASS
|
||||
|
||||
#define wxSTC_LUA_DEFAULT 0
|
||||
#define wxSTC_LUA_COMMENT 1
|
||||
#define wxSTC_LUA_COMMENTLINE 2
|
||||
#define wxSTC_LUA_COMMENTDOC 3
|
||||
#define wxSTC_LUA_NUMBER 4
|
||||
#define wxSTC_LUA_WORD 5
|
||||
#define wxSTC_LUA_STRING 6
|
||||
#define wxSTC_LUA_CHARACTER 7
|
||||
#define wxSTC_LUA_LITERALSTRING 8
|
||||
#define wxSTC_LUA_PREPROCESSOR 9
|
||||
#define wxSTC_LUA_OPERATOR 10
|
||||
#define wxSTC_LUA_IDENTIFIER 11
|
||||
#define wxSTC_LUA_STRINGEOL 12
|
||||
]=]
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
----------
|
||||
-- Style
|
||||
--
|
||||
-- common style attributes
|
||||
-- ---------------------------
|
||||
-- fg foreground - {r,g,b} 0-255
|
||||
-- bg background - {r,g,b} 0-255
|
||||
-- u underline - boolean
|
||||
-- b bold - boolean
|
||||
-- i italic - boolean
|
||||
-- fill fill to end - boolean
|
||||
|
||||
function StylesGetDefault()
|
||||
return {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, b = true},
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0},},
|
||||
keywords2 = {fg = {0, 127, 0},},
|
||||
keywords3 = {fg = {0, 0, 127},},
|
||||
keywords4 = {fg = {127, 0, 95},},
|
||||
keywords5 = {fg = {35, 95, 175},},
|
||||
keywords6 = {fg = {0, 127, 127},},
|
||||
keywords7 = {fg = {240, 255, 255},},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {192, 192, 192},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
escapechar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg )
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = {fg = {180, 180, 180},},
|
||||
|
||||
-- indicators
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
end
|
||||
|
||||
-- used to fill unset bg colors
|
||||
local defaultfg = nil
|
||||
local defaultbg = nil
|
||||
|
||||
local function applymarker(editor,marker,clrfg,clrbg)
|
||||
if (clrfg) then
|
||||
editor:MarkerSetForeground(marker,clrfg)
|
||||
end
|
||||
if (clrbg) then
|
||||
editor:MarkerSetBackground(marker,clrbg)
|
||||
end
|
||||
end
|
||||
local specialmapping = {
|
||||
sel = function(editor,style)
|
||||
if (style.fg) then
|
||||
editor:SetSelForeground(1,wx.wxColour(unpack(style.fg)))
|
||||
else
|
||||
editor:SetSelForeground(0)
|
||||
end
|
||||
if (style.bg) then
|
||||
editor:SetSelBackground(1,wx.wxColour(unpack(style.bg)))
|
||||
else
|
||||
editor:SetSelBackground(0)
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
caret = function(editor,style)
|
||||
if (style.fg) then
|
||||
editor:SetCaretForeground(wx.wxColour(unpack(style.fg)))
|
||||
end
|
||||
--if (style.bg) then
|
||||
-- editor:SetCaretBackground(wx.wxColour(unpack(style.bg)))
|
||||
--end
|
||||
end,
|
||||
|
||||
caretlinebg = function(editor,style)
|
||||
if (style.bg) then
|
||||
editor:SetCaretLineBackground(wx.wxColour(unpack(style.bg)))
|
||||
end
|
||||
end,
|
||||
|
||||
whitespace = function(editor,style)
|
||||
if (style.fg) then
|
||||
editor:SetWhitespaceForeground(1,wx.wxColour(unpack(style.fg)))
|
||||
else
|
||||
--editor:SetWhitespaceForeground(0)
|
||||
end
|
||||
if (style.bg) then
|
||||
editor:SetWhitespaceBackground(1,wx.wxColour(unpack(style.bg)))
|
||||
else
|
||||
--editor:SetWhitespaceBackground(0)
|
||||
end
|
||||
end,
|
||||
|
||||
calltipbg = function(editor,style)
|
||||
if (style.bg) then
|
||||
editor:CallTipSetBackground(wx.wxColour(unpack(style.bg)))
|
||||
end
|
||||
end,
|
||||
|
||||
fold = function(editor,style)
|
||||
local clrfg = style.fg and wx.wxColour(unpack(style.fg))
|
||||
local clrbg = style.bg and wx.wxColour(unpack(style.bg))
|
||||
|
||||
if (clrfg or clrbg) then
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPEN, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDER, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERSUB, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERTAIL, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEREND, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPENMID, clrfg,clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, clrfg,clrbg)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local defaultmapping = {
|
||||
text = wxstc.wxSTC_STYLE_DEFAULT,
|
||||
linenumber = wxstc.wxSTC_STYLE_LINENUMBER,
|
||||
bracematch = wxstc.wxSTC_STYLE_BRACELIGHT,
|
||||
bracemiss = wxstc.wxSTC_STYLE_BRACEBAD,
|
||||
escapechar = wxstc.wxSTC_STYLE_CONTROLCHAR,
|
||||
indent = wxstc.wxSTC_STYLE_INDENTGUIDE,
|
||||
calltip = wxstc.wxSTC_STYLE_CALLTIP,
|
||||
}
|
||||
|
||||
function StylesApplyToEditor(styles,editor,font,fontitalic,lexerconvert)
|
||||
local function applystyle(style,id)
|
||||
editor:StyleSetFont(id, style.i and fontitalic or font)
|
||||
editor:StyleSetBold(id, style.b or false)
|
||||
editor:StyleSetUnderline(id, style.u or false)
|
||||
editor:StyleSetEOLFilled(id, style.fill or false)
|
||||
|
||||
if (style.fg or defaultfg) then
|
||||
editor:StyleSetForeground(id, style.fg and wx.wxColour(unpack(style.fg)) or defaultfg)
|
||||
end
|
||||
if (style.bg or defaultbg) then
|
||||
editor:StyleSetBackground(id, style.bg and wx.wxColour(unpack(style.bg)) or defaultbg)
|
||||
end
|
||||
end
|
||||
editor:StyleResetDefault()
|
||||
editor:SetFont(font)
|
||||
if (styles.text) then
|
||||
applystyle(styles.text,defaultmapping["text"])
|
||||
else
|
||||
applystyle({},defaultmapping["text"])
|
||||
end
|
||||
editor:StyleClearAll()
|
||||
|
||||
defaultfg = styles.text and styles.text.fg and wx.wxColour(unpack(styles.text.fg)) or nil
|
||||
defaultbg = styles.text and styles.text.bg and wx.wxColour(unpack(styles.text.bg)) or nil
|
||||
|
||||
for name,style in pairs(styles) do
|
||||
if (specialmapping[name]) then
|
||||
specialmapping[name](editor,style)
|
||||
elseif (defaultmapping[name]) then
|
||||
applystyle(style,defaultmapping[name])
|
||||
end
|
||||
if (lexerconvert and lexerconvert[name]) then
|
||||
local targets = lexerconvert[name]
|
||||
|
||||
for n,outid in pairs(targets) do
|
||||
applystyle(style,outid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
editor:IndicatorSetStyle(0,styles.fncall and styles.fncall.st or wxstc.wxSTC_INDIC_BOX)
|
||||
editor:IndicatorSetForeground(0,wx.wxColour(unpack(styles.fncall and styles.fncall.fg or {128,128,128})))
|
||||
end
|
||||
|
||||
editor:Colourise(0, -1)
|
||||
end
|
||||
|
||||
function ReApplySpecAndStyles()
|
||||
local openDocuments = ide.openDocuments
|
||||
for i,doc in pairs(openDocuments) do
|
||||
if (doc.editor.spec) then
|
||||
SetupKeywords(doc.editor,nil,doc.editor.spec)
|
||||
end
|
||||
end
|
||||
|
||||
local errorlog = ide.frame.bottomnotebook.errorlog
|
||||
local shellbox = ide.frame.bottomnotebook.shellbox
|
||||
|
||||
SetupKeywords(shellbox,"lua",nil,ide.config.stylesoutshell,ide.ofont,ide.ofontItalic)
|
||||
|
||||
StylesApplyToEditor(ide.config.stylesoutshell,errorlog,ide.ofont,ide.ofontItalic)
|
||||
end
|
||||
|
||||
function LoadConfigStyle()
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, "Open Config File",
|
||||
"/cfg",
|
||||
"",
|
||||
"Lua file (*.lua)|*.lua|All files (*)|*",
|
||||
wx.wxOPEN + wx.wxFILE_MUST_EXIST)
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
local cfg = {wxstc = wxstc, path = {}, editor = {}, view ={}, acandtip = {}, outputshell = {}, debugger={},}
|
||||
local cfgfn,err = loadfile(fileDialog:GetPath())
|
||||
if cfgfn then
|
||||
setfenv(cfgfn,cfg)
|
||||
cfgfn = xpcall(cfgfn,function(err)DisplayOutput("Error while executing configuration file: \n",debug.traceback(err))end)
|
||||
end
|
||||
|
||||
if not (cfgfn and (cfg.styles or cfg.stylesoutshell)) then
|
||||
wx.wxMessageBox("Unable to load config style '"..fileDialog:GetPath().."'.",
|
||||
"wxLua Error",
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
else
|
||||
if (cfg.styles) then
|
||||
ide.config.styles = StylesGetDefault()
|
||||
-- copy
|
||||
for i,s in pairs(cfg.styles) do
|
||||
ide.config.styles[i] = s
|
||||
end
|
||||
end
|
||||
if (cfg.stylesoutshell) then
|
||||
ide.config.stylesoutshell = StylesGetDefault()
|
||||
-- copy
|
||||
for i,s in pairs(cfg.stylesoutshell) do
|
||||
ide.config.stylesoutshell[i] = s
|
||||
end
|
||||
end
|
||||
ReApplySpecAndStyles()
|
||||
end
|
||||
end
|
||||
fileDialog:Destroy()
|
||||
|
||||
end
|
||||
|
||||
-- used lexers ?
|
||||
--[=[
|
||||
#define wxSTC_POV_DEFAULT 0
|
||||
#define wxSTC_POV_COMMENT 1
|
||||
#define wxSTC_POV_COMMENTLINE 2
|
||||
#define wxSTC_POV_NUMBER 3
|
||||
#define wxSTC_POV_OPERATOR 4
|
||||
#define wxSTC_POV_IDENTIFIER 5
|
||||
#define wxSTC_POV_STRING 6
|
||||
#define wxSTC_POV_STRINGEOL 7
|
||||
|
||||
%define wxSTC_C_DEFAULT
|
||||
%define wxSTC_C_COMMENT
|
||||
%define wxSTC_C_COMMENTLINE
|
||||
%define wxSTC_C_COMMENTDOC
|
||||
%define wxSTC_C_NUMBER
|
||||
%define wxSTC_C_WORD
|
||||
%define wxSTC_C_STRING
|
||||
%define wxSTC_C_CHARACTER
|
||||
%define wxSTC_C_UUID
|
||||
%define wxSTC_C_PREPROCESSOR
|
||||
%define wxSTC_C_OPERATOR
|
||||
%define wxSTC_C_IDENTIFIER
|
||||
%define wxSTC_C_STRINGEOL
|
||||
%define wxSTC_C_VERBATIM
|
||||
%define wxSTC_C_REGEX
|
||||
%define wxSTC_C_COMMENTLINEDOC
|
||||
%define wxSTC_C_WORD2
|
||||
%define wxSTC_C_COMMENTDOCKEYWORD
|
||||
%define wxSTC_C_COMMENTDOCKEYWORDERROR
|
||||
%define wxSTC_C_GLOBALCLASS
|
||||
|
||||
#define wxSTC_LUA_DEFAULT 0
|
||||
#define wxSTC_LUA_COMMENT 1
|
||||
#define wxSTC_LUA_COMMENTLINE 2
|
||||
#define wxSTC_LUA_COMMENTDOC 3
|
||||
#define wxSTC_LUA_NUMBER 4
|
||||
#define wxSTC_LUA_WORD 5
|
||||
#define wxSTC_LUA_STRING 6
|
||||
#define wxSTC_LUA_CHARACTER 7
|
||||
#define wxSTC_LUA_LITERALSTRING 8
|
||||
#define wxSTC_LUA_PREPROCESSOR 9
|
||||
#define wxSTC_LUA_OPERATOR 10
|
||||
#define wxSTC_LUA_IDENTIFIER 11
|
||||
#define wxSTC_LUA_STRINGEOL 12
|
||||
]=]
|
||||
|
||||
621
src/main.lua
@@ -1,311 +1,310 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
package.cpath = package.cpath..';bin/?.dll;bin/clibs/?.dll;bin/clibs/?/?.dll;bin/clibs/?/?/?.dll'
|
||||
package.cpath = package.cpath..';bin/?.so;bin/clibs/?.so;bin/clibs/?/?.so;bin/clibs/?/?/?.so'
|
||||
package.path = package.path..'lualibs/?.lua;lualibs/?/?.lua;lualibs/?/init.lua;lualibs/?/?/?.lua;lualibs/?/?/init.lua'
|
||||
|
||||
require("wx")
|
||||
require("bit")
|
||||
|
||||
dofile "src/misc/util.lua"
|
||||
|
||||
-----------
|
||||
-- IDE
|
||||
--
|
||||
-- Setup important defaults
|
||||
dofile "src/editor/ids.lua"
|
||||
dofile "src/editor/style.lua"
|
||||
|
||||
ide = {
|
||||
config = {
|
||||
path = {
|
||||
projectdir = "",
|
||||
app = nil,
|
||||
},
|
||||
editor = {
|
||||
usetabs = true,
|
||||
autotabs = true,
|
||||
},
|
||||
outputshell = {},
|
||||
|
||||
styles = StylesGetDefault(),
|
||||
stylesoutshell = StylesGetDefault(),
|
||||
interpreter = "EstrelaShell",
|
||||
|
||||
autocomplete = true,
|
||||
acandtip = {
|
||||
shorttip = false,
|
||||
ignorecase = false,
|
||||
strategy = 2,
|
||||
},
|
||||
|
||||
filehistorylength = 20,
|
||||
projecthistorylength = 15,
|
||||
savebak = false,
|
||||
singleinstance = true,
|
||||
singleinstanceport = 0xe493,
|
||||
|
||||
view = {
|
||||
vsplitterpos = 150,
|
||||
splitterheight = 200,
|
||||
},
|
||||
|
||||
setup = "",
|
||||
},
|
||||
specs = {
|
||||
none = {
|
||||
linecomment = ">",
|
||||
sep = "\1",
|
||||
}
|
||||
},
|
||||
tools = {
|
||||
},
|
||||
iofilters = {
|
||||
},
|
||||
interpreters = {
|
||||
},
|
||||
|
||||
app = nil, -- application engine
|
||||
interpreter = nil, -- current Lua interpreter
|
||||
frame = nil, -- gui related
|
||||
debugger = nil, -- debugger
|
||||
filetree = nil, -- filetree
|
||||
findReplace = nil, -- find & replace handling
|
||||
settings = nil, -- user settings (window pos, last files..)
|
||||
|
||||
-- misc
|
||||
exitingProgram = false, -- are we currently exiting, ID_EXIT
|
||||
editorFilename = nil, -- the name of the wxLua program to be used when starting debugger
|
||||
editorApp = wx.wxGetApp(),
|
||||
openDocuments = {},-- open notebook editor documents[winId] = {
|
||||
-- editor = wxStyledTextCtrl,
|
||||
-- index = wxNotebook page index,
|
||||
-- filePath = full filepath, nil if not saved,
|
||||
-- fileName = just the filename,
|
||||
-- modTime = wxDateTime of disk file or nil,
|
||||
-- isModified = bool is the document modified? }
|
||||
ignoredFilesList = {},
|
||||
font = nil,
|
||||
fontItalic = nil,
|
||||
ofont = nil,
|
||||
ofontItalic = nil,
|
||||
}
|
||||
|
||||
-- load config
|
||||
local function addConfig(filename,showerror,isstring)
|
||||
local cfgfn,err = isstring and loadstring(filename) or loadfile(filename)
|
||||
if not cfgfn then
|
||||
if (showerror) then
|
||||
print(("Error while loading configuration file: %s\n%s"):format(filename,err))
|
||||
end
|
||||
else
|
||||
ide.config.os = os
|
||||
ide.config.wxstc = wxstc
|
||||
setfenv(cfgfn,ide.config)
|
||||
xpcall(function()cfgfn(assert(_G))end,
|
||||
function(err)
|
||||
print("Error while executing configuration file: \n",
|
||||
debug.traceback(err))end)
|
||||
end
|
||||
end
|
||||
local function loadCFG()
|
||||
addConfig("cfg/config.lua",true)
|
||||
addConfig("cfg/user.lua",false)
|
||||
end
|
||||
loadCFG()
|
||||
|
||||
---------------
|
||||
-- process args
|
||||
local filenames = {}
|
||||
|
||||
do
|
||||
local arg = {...}
|
||||
ide.arg = arg
|
||||
-- first argument must be the application name
|
||||
assert(type(arg[1]) == "string","first argument must be application name")
|
||||
ide.editorFilename = arg[1]
|
||||
ide.config.path.app = arg[1]:match("([%w_-]+)%.?[^%.]*$")
|
||||
assert(ide.config.path.app, "no application path defined")
|
||||
for index = 2, #arg do
|
||||
if (arg[index] == "-cfg" and index+1 <= #arg) then
|
||||
local str = arg[index+1]
|
||||
if #str < 4 then
|
||||
print("Comandline: -cfg arg data not passed as string")
|
||||
else
|
||||
addConfig(str,true,true)
|
||||
end
|
||||
index = index+1
|
||||
else
|
||||
table.insert(filenames,arg[index])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- process application
|
||||
|
||||
ide.app = dofile(ide.config.path.app.."/app.lua")
|
||||
local app = ide.app
|
||||
assert(app)
|
||||
|
||||
do
|
||||
local app = ide.app
|
||||
function GetIDEString(keyword, default)
|
||||
return app.stringtable[keyword] or default or keyword
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- process plugins
|
||||
|
||||
local function addToTab(tab,file)
|
||||
local cfgfn,err = loadfile(file)
|
||||
if not cfgfn then
|
||||
print(("Error while loading configuration file (%s): \n%s"):format(file,err))
|
||||
else
|
||||
local name = file:match("([a-zA-Z_0-9]+)%.lua$")
|
||||
|
||||
local success,result
|
||||
success, result = xpcall(
|
||||
function()return cfgfn(_G)end,
|
||||
function(err)
|
||||
print(("Error while executing configuration file (%s): \n%s"):
|
||||
format(file,debug.traceback(err)))
|
||||
end)
|
||||
if (name and success) then
|
||||
if (tab[name]) then
|
||||
local out = tab[name]
|
||||
for i,v in pairs(result) do
|
||||
out[i] = v
|
||||
end
|
||||
else
|
||||
tab[name] = result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- load interpreters
|
||||
local function loadInterpreters()
|
||||
|
||||
local files = FileSysGet(".\\interpreters\\*.*",wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
if file:match "%.lua$" and app.loadfilters.interpreters(file) then
|
||||
addToTab(ide.interpreters,file)
|
||||
end
|
||||
end
|
||||
end
|
||||
loadInterpreters()
|
||||
|
||||
|
||||
-- load specs
|
||||
local function loadSpecs()
|
||||
|
||||
local files = FileSysGet(".\\spec\\*.*",wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
if file:match "%.lua$" and app.loadfilters.specs(file) then
|
||||
addToTab(ide.specs,file)
|
||||
end
|
||||
end
|
||||
|
||||
for n,spec in pairs(ide.specs) do
|
||||
spec.sep = spec.sep or ""
|
||||
spec.iscomment = {}
|
||||
spec.iskeyword0 = {}
|
||||
if (spec.lexerstyleconvert) then
|
||||
if (spec.lexerstyleconvert.comment) then
|
||||
for i,s in pairs(spec.lexerstyleconvert.comment) do
|
||||
spec.iscomment[s] = true
|
||||
end
|
||||
end
|
||||
if (spec.lexerstyleconvert.keywords0) then
|
||||
for i,s in pairs(spec.lexerstyleconvert.keywords0) do
|
||||
spec.iskeyword0[s] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
loadSpecs()
|
||||
|
||||
-- load tools
|
||||
local function loadTools()
|
||||
|
||||
local files = FileSysGet(".\\tools\\*.*",wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
if file:match "%.lua$" and app.loadfilters.tools(file) then
|
||||
addToTab(ide.tools,file)
|
||||
end
|
||||
end
|
||||
end
|
||||
loadTools()
|
||||
|
||||
|
||||
---------------
|
||||
-- Load App
|
||||
|
||||
dofile "src/editor/settings.lua"
|
||||
dofile "src/editor/singleinstance.lua"
|
||||
dofile "src/editor/iofilters.lua"
|
||||
|
||||
dofile "src/editor/gui.lua"
|
||||
dofile "src/editor/output.lua"
|
||||
dofile "src/editor/debugger.lua"
|
||||
dofile "src/editor/filetree.lua"
|
||||
dofile "src/editor/preferences.lua"
|
||||
|
||||
dofile "src/editor/editor.lua"
|
||||
dofile "src/editor/autocomplete.lua"
|
||||
dofile "src/editor/findreplace.lua"
|
||||
dofile "src/editor/commands.lua"
|
||||
|
||||
dofile "src/editor/shellbox.lua"
|
||||
|
||||
dofile "src/editor/menu.lua"
|
||||
|
||||
dofile "src/preferences/editor.lua"
|
||||
dofile "src/preferences/project.lua"
|
||||
|
||||
-- load rest of settings
|
||||
SettingsRestoreEditorSettings()
|
||||
SettingsRestoreFramePosition(ide.frame, "MainFrame")
|
||||
SettingsRestoreView()
|
||||
SettingsRestoreFileSession(SetOpenFiles)
|
||||
SettingsRestoreFileHistory(UpdateFileHistoryUI)
|
||||
SettingsRestoreProjectSession(SetProjects)
|
||||
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Load the filenames
|
||||
|
||||
do
|
||||
local notebook = ide.frame.vsplitter.splitter.notebook
|
||||
local loaded
|
||||
|
||||
for i,fileName in ipairs(filenames) do
|
||||
if fileName ~= "--" then
|
||||
LoadFile(fileName, nil, true)
|
||||
loaded = true
|
||||
end
|
||||
end
|
||||
|
||||
if notebook:GetPageCount() > 0 then
|
||||
|
||||
else
|
||||
local editor = CreateEditor("untitled.lua")
|
||||
SetupKeywords(editor, "lua")
|
||||
end
|
||||
end
|
||||
|
||||
ide.frame:Show(true)
|
||||
|
||||
app.postinit()
|
||||
|
||||
-- Call wx.wxGetApp():MainLoop() last to start the wxWidgets event loop,
|
||||
-- otherwise the wxLua program will exit immediately.
|
||||
-- Does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit since the
|
||||
-- MainLoop is already running or will be started by the C++ program.
|
||||
wx.wxGetApp():MainLoop()
|
||||
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
package.cpath = package.cpath..';bin/?.dll;bin/clibs/?.dll;bin/clibs/?/?.dll;bin/clibs/?/?/?.dll'
|
||||
package.cpath = package.cpath..';bin/?.so;bin/clibs/?.so;bin/clibs/?/?.so;bin/clibs/?/?/?.so'
|
||||
package.path = package.path..'lualibs/?.lua;lualibs/?/?.lua;lualibs/?/init.lua;lualibs/?/?/?.lua;lualibs/?/?/init.lua'
|
||||
|
||||
require("wx")
|
||||
require("bit")
|
||||
|
||||
dofile "src/misc/util.lua"
|
||||
|
||||
-----------
|
||||
-- IDE
|
||||
--
|
||||
-- Setup important defaults
|
||||
dofile "src/editor/ids.lua"
|
||||
dofile "src/editor/style.lua"
|
||||
|
||||
ide = {
|
||||
config = {
|
||||
path = {
|
||||
projectdir = "",
|
||||
app = nil,
|
||||
},
|
||||
editor = {
|
||||
usetabs = true,
|
||||
autotabs = true,
|
||||
},
|
||||
debugger = {
|
||||
verbose = false,
|
||||
},
|
||||
outputshell = {},
|
||||
|
||||
styles = StylesGetDefault(),
|
||||
stylesoutshell = StylesGetDefault(),
|
||||
interpreter = "_undefined_",
|
||||
|
||||
autocomplete = true,
|
||||
acandtip = {
|
||||
shorttip = false,
|
||||
ignorecase = false,
|
||||
strategy = 2,
|
||||
},
|
||||
|
||||
filehistorylength = 20,
|
||||
projecthistorylength = 15,
|
||||
savebak = false,
|
||||
singleinstance = false,
|
||||
singleinstanceport = 0xe493,
|
||||
},
|
||||
specs = {
|
||||
none = {
|
||||
linecomment = ">",
|
||||
sep = "\1",
|
||||
}
|
||||
},
|
||||
tools = {
|
||||
},
|
||||
iofilters = {
|
||||
},
|
||||
interpreters = {
|
||||
},
|
||||
|
||||
app = nil, -- application engine
|
||||
interpreter = nil, -- current Lua interpreter
|
||||
frame = nil, -- gui related
|
||||
debugger = {}, -- debugger related info
|
||||
filetree = nil, -- filetree
|
||||
findReplace = nil, -- find & replace handling
|
||||
settings = nil, -- user settings (window pos, last files..)
|
||||
|
||||
-- misc
|
||||
exitingProgram = false, -- are we currently exiting, ID_EXIT
|
||||
editorApp = wx.wxGetApp(),
|
||||
editorFilename = nil,
|
||||
openDocuments = {},-- open notebook editor documents[winId] = {
|
||||
-- editor = wxStyledTextCtrl,
|
||||
-- index = wxNotebook page index,
|
||||
-- filePath = full filepath, nil if not saved,
|
||||
-- fileName = just the filename,
|
||||
-- modTime = wxDateTime of disk file or nil,
|
||||
-- isModified = bool is the document modified? }
|
||||
ignoredFilesList = {},
|
||||
font = nil,
|
||||
fontItalic = nil,
|
||||
ofont = nil,
|
||||
ofontItalic = nil,
|
||||
}
|
||||
|
||||
---------------
|
||||
-- process args
|
||||
local filenames = {}
|
||||
local configs = {}
|
||||
do
|
||||
local arg = {...}
|
||||
ide.arg = arg
|
||||
-- first argument must be the application name
|
||||
assert(type(arg[1]) == "string","first argument must be application name")
|
||||
ide.editorFilename = arg[1]
|
||||
ide.config.path.app = arg[1]:match("([%w_-]+)%.?[^%.]*$")
|
||||
assert(ide.config.path.app, "no application path defined")
|
||||
for index = 2, #arg do
|
||||
if (arg[index] == "-cfg" and index+1 <= #arg) then
|
||||
local str = arg[index+1]
|
||||
if #str < 4 then
|
||||
print("Comandline: -cfg arg data not passed as string")
|
||||
else
|
||||
table.insert(configs,str)
|
||||
end
|
||||
index = index+1
|
||||
else
|
||||
table.insert(filenames,arg[index])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- load config
|
||||
local function addConfig(filename,showerror,isstring)
|
||||
local cfgfn,err = isstring and loadstring(filename) or loadfile(filename)
|
||||
if not cfgfn then
|
||||
if (showerror) then
|
||||
print(("Error while loading configuration file: %s\n%s"):format(filename,err))
|
||||
end
|
||||
else
|
||||
ide.config.os = os
|
||||
ide.config.wxstc = wxstc
|
||||
setfenv(cfgfn,ide.config)
|
||||
xpcall(function()cfgfn(assert(_G))end,
|
||||
function(err)
|
||||
print("Error while executing configuration file: \n",
|
||||
debug.traceback(err))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
addConfig(ide.config.path.app.."/config.lua",true)
|
||||
addConfig("cfg/user.lua",false)
|
||||
for i,v in ipairs(configs) do
|
||||
addConfig(v,true,true)
|
||||
end
|
||||
configs = nil
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- process application
|
||||
|
||||
ide.app = dofile(ide.config.path.app.."/app.lua")
|
||||
local app = ide.app
|
||||
assert(app)
|
||||
|
||||
do
|
||||
local app = ide.app
|
||||
function GetIDEString(keyword, default)
|
||||
return app.stringtable[keyword] or default or keyword
|
||||
end
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- process plugins
|
||||
|
||||
local function addToTab(tab,file)
|
||||
local cfgfn,err = loadfile(file)
|
||||
if not cfgfn then
|
||||
print(("Error while loading configuration file (%s): \n%s"):format(file,err))
|
||||
else
|
||||
local name = file:match("([a-zA-Z_0-9]+)%.lua$")
|
||||
|
||||
local success,result
|
||||
success, result = xpcall(
|
||||
function()return cfgfn(_G)end,
|
||||
function(err)
|
||||
print(("Error while executing configuration file (%s): \n%s"):
|
||||
format(file,debug.traceback(err)))
|
||||
end)
|
||||
if (name and success) then
|
||||
if (tab[name]) then
|
||||
local out = tab[name]
|
||||
for i,v in pairs(result) do
|
||||
out[i] = v
|
||||
end
|
||||
else
|
||||
tab[name] = result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- load interpreters
|
||||
local function loadInterpreters()
|
||||
|
||||
local files = FileSysGet(".\\interpreters\\*.*",wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
if file:match "%.lua$" and app.loadfilters.interpreters(file) then
|
||||
addToTab(ide.interpreters,file)
|
||||
end
|
||||
end
|
||||
end
|
||||
loadInterpreters()
|
||||
|
||||
-- load specs
|
||||
local function loadSpecs()
|
||||
|
||||
local files = FileSysGet(".\\spec\\*.*",wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
if file:match "%.lua$" and app.loadfilters.specs(file) then
|
||||
addToTab(ide.specs,file)
|
||||
end
|
||||
end
|
||||
|
||||
for n,spec in pairs(ide.specs) do
|
||||
spec.sep = spec.sep or ""
|
||||
spec.iscomment = {}
|
||||
spec.iskeyword0 = {}
|
||||
if (spec.lexerstyleconvert) then
|
||||
if (spec.lexerstyleconvert.comment) then
|
||||
for i,s in pairs(spec.lexerstyleconvert.comment) do
|
||||
spec.iscomment[s] = true
|
||||
end
|
||||
end
|
||||
if (spec.lexerstyleconvert.keywords0) then
|
||||
for i,s in pairs(spec.lexerstyleconvert.keywords0) do
|
||||
spec.iskeyword0[s] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
loadSpecs()
|
||||
|
||||
-- load tools
|
||||
local function loadTools()
|
||||
|
||||
local files = FileSysGet(".\\tools\\*.*",wx.wxFILE)
|
||||
for i,file in ipairs(files) do
|
||||
if file:match "%.lua$" and app.loadfilters.tools(file) then
|
||||
addToTab(ide.tools,file)
|
||||
end
|
||||
end
|
||||
end
|
||||
loadTools()
|
||||
|
||||
if app.preinit then app.preinit() end
|
||||
|
||||
---------------
|
||||
-- Load App
|
||||
|
||||
dofile "src/editor/settings.lua"
|
||||
dofile "src/editor/singleinstance.lua"
|
||||
dofile "src/editor/iofilters.lua"
|
||||
|
||||
dofile "src/editor/gui.lua"
|
||||
dofile "src/editor/filetree.lua"
|
||||
dofile "src/editor/output.lua"
|
||||
dofile "src/editor/debugger.lua"
|
||||
dofile "src/editor/preferences.lua"
|
||||
|
||||
dofile "src/editor/editor.lua"
|
||||
dofile "src/editor/autocomplete.lua"
|
||||
dofile "src/editor/findreplace.lua"
|
||||
dofile "src/editor/commands.lua"
|
||||
|
||||
dofile "src/editor/shellbox.lua"
|
||||
|
||||
dofile "src/editor/menu.lua"
|
||||
|
||||
dofile "src/preferences/editor.lua"
|
||||
dofile "src/preferences/project.lua"
|
||||
|
||||
dofile "src/version.lua"
|
||||
|
||||
-- load rest of settings
|
||||
SettingsRestoreEditorSettings()
|
||||
SettingsRestoreFramePosition(ide.frame, "MainFrame")
|
||||
SettingsRestoreFileSession(SetOpenFiles)
|
||||
SettingsRestoreFileHistory(UpdateFileHistoryUI)
|
||||
SettingsRestoreProjectSession(FileTreeSetProjects)
|
||||
SettingsRestoreView()
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Load the filenames
|
||||
|
||||
do
|
||||
local notebook = ide.frame.notebook
|
||||
local loaded
|
||||
|
||||
for i,fileName in ipairs(filenames) do
|
||||
if fileName ~= "--" then
|
||||
LoadFile(fileName, nil, true)
|
||||
loaded = true
|
||||
end
|
||||
end
|
||||
|
||||
if notebook:GetPageCount() == 0 then
|
||||
local editor = CreateEditor("untitled.lua")
|
||||
SetupKeywords(editor, "lua")
|
||||
end
|
||||
end
|
||||
|
||||
if app.postinit then app.postinit() end
|
||||
|
||||
ide.frame:Show(true)
|
||||
|
||||
-- Call wx.wxGetApp():MainLoop() last to start the wxWidgets event loop,
|
||||
-- otherwise the wxLua program will exit immediately.
|
||||
-- Does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit since the
|
||||
-- MainLoop is already running or will be started by the C++ program.
|
||||
wx.wxGetApp():MainLoop()
|
||||
|
||||
@@ -1,175 +1,175 @@
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
-- David Manura
|
||||
---------------------------------------------------------
|
||||
|
||||
-- Equivalent to C's "cond ? a : b", all terms will be evaluated
|
||||
function iff(cond, a, b) if cond then return a else return b end end
|
||||
|
||||
-- Does the num have all the bits in value
|
||||
function HasBit(value, num)
|
||||
for n = 32, 0, -1 do
|
||||
local b = 2^n
|
||||
local num_b = num - b
|
||||
local value_b = value - b
|
||||
if num_b >= 0 then
|
||||
num = num_b
|
||||
else
|
||||
return true -- already tested bits in num
|
||||
end
|
||||
if value_b >= 0 then
|
||||
value = value_b
|
||||
end
|
||||
if (num_b >= 0) and (value_b < 0) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- ASCII values for common chars
|
||||
char_CR = string.byte("\r")
|
||||
char_LF = string.byte("\n")
|
||||
char_Tab = string.byte("\t")
|
||||
char_Sp = string.byte(" ")
|
||||
|
||||
string_Pathsep = string.char(wx.wxFileName.GetPathSeparator())
|
||||
stringset_File = '[^"%?%*:\\/<>|]'
|
||||
|
||||
function StripCommentsC(tx)
|
||||
local out = ""
|
||||
local lastc = ""
|
||||
local skip
|
||||
local skipline
|
||||
local skipmulti
|
||||
local tx = string.gsub(tx, "\r\n", "\n")
|
||||
for c in tx:gmatch(".") do
|
||||
local oc = c
|
||||
local tu = lastc..c
|
||||
skip = c == '/'
|
||||
|
||||
if ( not (skipmulti or skipline)) then
|
||||
if (tu == "//") then
|
||||
skipline = true
|
||||
elseif (tu == "/*") then
|
||||
skipmulti = true
|
||||
c = ""
|
||||
elseif (lastc == '/') then
|
||||
oc = tu
|
||||
end
|
||||
elseif (skipmulti and tu == "*/") then
|
||||
skipmulti = false
|
||||
c = ""
|
||||
elseif (skipline and lastc == "\n") then
|
||||
out = out.."\n"
|
||||
skipline = false
|
||||
end
|
||||
|
||||
lastc = c
|
||||
if (not (skip or skipline or skipmulti)) then
|
||||
out = out..oc
|
||||
end
|
||||
end
|
||||
|
||||
return out..lastc
|
||||
end
|
||||
|
||||
|
||||
-- http://lua-users.org/wiki/EnhancedFileLines
|
||||
function FileLines(f)
|
||||
local CHUNK_SIZE = 1024
|
||||
local buffer = ""
|
||||
local pos_beg = 1
|
||||
return function()
|
||||
local pos, chars
|
||||
while 1 do
|
||||
pos, chars = buffer:match('()([\r\n].)', pos_beg)
|
||||
if pos or not f then
|
||||
break
|
||||
elseif f then
|
||||
local chunk = f:read(CHUNK_SIZE)
|
||||
if chunk then
|
||||
buffer = buffer:sub(pos_beg) .. chunk
|
||||
pos_beg = 1
|
||||
else
|
||||
f = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if not pos then
|
||||
pos = #buffer
|
||||
elseif chars == '\r\n' then
|
||||
pos = pos + 1
|
||||
end
|
||||
local line = buffer:sub(pos_beg, pos)
|
||||
pos_beg = pos + 1
|
||||
if #line > 0 then
|
||||
return line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PrependStringToArray(t, s, maxstrings)
|
||||
if string.len(s) == 0 then return end
|
||||
for i, v in ipairs(t) do
|
||||
if v == s then
|
||||
table.remove(t, i) -- remove old copy
|
||||
break
|
||||
end
|
||||
end
|
||||
table.insert(t, 1, s)
|
||||
if #t > (maxstrings or 15) then table.remove(t, #t) end -- keep reasonable length
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Get file modification time, returns a wxDateTime (check IsValid) or nil if
|
||||
-- the file doesn't exist
|
||||
function GetFileModTime(filePath)
|
||||
if filePath and (string.len(filePath) > 0) then
|
||||
local fn = wx.wxFileName(filePath)
|
||||
if fn:FileExists() then
|
||||
return fn:GetModificationTime()
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function GetFileExt(filePath)
|
||||
local match = filePath and filePath:match("%.([a-zA-Z_0-9]+)$")
|
||||
return match and (string.lower(match))
|
||||
end
|
||||
|
||||
function IsLuaFile(filePath)
|
||||
return filePath and (string.len(filePath) > 4) and
|
||||
(string.lower(string.sub(filePath, -4)) == ".lua")
|
||||
end
|
||||
|
||||
function GetFileNameExt(filePath)
|
||||
if (not filePath) then return end
|
||||
local wxn = wx.wxFileName(filePath)
|
||||
return (wxn:GetName()..(wxn:HasExt() and ("."..wxn:GetExt()) or ""))
|
||||
end
|
||||
|
||||
|
||||
function GetPathWithSep(wxfn)
|
||||
return wxfn:GetPath(bit.bor(wx.wxPATH_GET_VOLUME, wx.wxPATH_GET_SEPARATOR))
|
||||
end
|
||||
|
||||
function FileSysHasContent(dir)
|
||||
local f = wx.wxFindFirstFile(dir,wx.wxFILE + wx.wxDIR)
|
||||
return #f>0
|
||||
end
|
||||
|
||||
function FileSysGet(dir,spec)
|
||||
local content = {}
|
||||
local browse = wx.wxFileSystem()
|
||||
local f = browse:FindFirst(dir,spec)
|
||||
while #f>0 do
|
||||
table.insert(content,f)
|
||||
f = browse:FindNext()
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
-- David Manura
|
||||
---------------------------------------------------------
|
||||
|
||||
-- Equivalent to C's "cond ? a : b", all terms will be evaluated
|
||||
function iff(cond, a, b) if cond then return a else return b end end
|
||||
|
||||
-- Does the num have all the bits in value
|
||||
function HasBit(value, num)
|
||||
for n = 32, 0, -1 do
|
||||
local b = 2^n
|
||||
local num_b = num - b
|
||||
local value_b = value - b
|
||||
if num_b >= 0 then
|
||||
num = num_b
|
||||
else
|
||||
return true -- already tested bits in num
|
||||
end
|
||||
if value_b >= 0 then
|
||||
value = value_b
|
||||
end
|
||||
if (num_b >= 0) and (value_b < 0) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- ASCII values for common chars
|
||||
char_CR = string.byte("\r")
|
||||
char_LF = string.byte("\n")
|
||||
char_Tab = string.byte("\t")
|
||||
char_Sp = string.byte(" ")
|
||||
|
||||
string_Pathsep = string.char(wx.wxFileName.GetPathSeparator())
|
||||
stringset_File = '[^"%?%*:\\/<>|]'
|
||||
|
||||
function StripCommentsC(tx)
|
||||
local out = ""
|
||||
local lastc = ""
|
||||
local skip
|
||||
local skipline
|
||||
local skipmulti
|
||||
local tx = string.gsub(tx, "\r\n", "\n")
|
||||
for c in tx:gmatch(".") do
|
||||
local oc = c
|
||||
local tu = lastc..c
|
||||
skip = c == '/'
|
||||
|
||||
if ( not (skipmulti or skipline)) then
|
||||
if (tu == "//") then
|
||||
skipline = true
|
||||
elseif (tu == "/*") then
|
||||
skipmulti = true
|
||||
c = ""
|
||||
elseif (lastc == '/') then
|
||||
oc = tu
|
||||
end
|
||||
elseif (skipmulti and tu == "*/") then
|
||||
skipmulti = false
|
||||
c = ""
|
||||
elseif (skipline and lastc == "\n") then
|
||||
out = out.."\n"
|
||||
skipline = false
|
||||
end
|
||||
|
||||
lastc = c
|
||||
if (not (skip or skipline or skipmulti)) then
|
||||
out = out..oc
|
||||
end
|
||||
end
|
||||
|
||||
return out..lastc
|
||||
end
|
||||
|
||||
-- http://lua-users.org/wiki/EnhancedFileLines
|
||||
function FileLines(f)
|
||||
local CHUNK_SIZE = 1024
|
||||
local buffer = ""
|
||||
local pos_beg = 1
|
||||
return function()
|
||||
local pos, chars
|
||||
while 1 do
|
||||
pos, chars = buffer:match('()([\r\n].)', pos_beg)
|
||||
if pos or not f then
|
||||
break
|
||||
elseif f then
|
||||
local chunk = f:read(CHUNK_SIZE)
|
||||
if chunk then
|
||||
buffer = buffer:sub(pos_beg) .. chunk
|
||||
pos_beg = 1
|
||||
else
|
||||
f = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if not pos then
|
||||
pos = #buffer
|
||||
elseif chars == '\r\n' then
|
||||
pos = pos + 1
|
||||
end
|
||||
local line = buffer:sub(pos_beg, pos)
|
||||
pos_beg = pos + 1
|
||||
if #line > 0 then
|
||||
return line
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PrependStringToArray(t, s, maxstrings)
|
||||
if string.len(s) == 0 then return end
|
||||
for i, v in ipairs(t) do
|
||||
if v == s then
|
||||
table.remove(t, i) -- remove old copy
|
||||
break
|
||||
end
|
||||
end
|
||||
table.insert(t, 1, s)
|
||||
if #t > (maxstrings or 15) then table.remove(t, #t) end -- keep reasonable length
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Get file modification time, returns a wxDateTime (check IsValid) or nil if
|
||||
-- the file doesn't exist
|
||||
function GetFileModTime(filePath)
|
||||
if filePath and (string.len(filePath) > 0) then
|
||||
local fn = wx.wxFileName(filePath)
|
||||
if fn:FileExists() then
|
||||
return fn:GetModificationTime()
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function GetFileExt(filePath)
|
||||
local match = filePath and filePath:match("%.([a-zA-Z_0-9]+)$")
|
||||
return match and (string.lower(match))
|
||||
end
|
||||
|
||||
function IsLuaFile(filePath)
|
||||
return filePath and (string.len(filePath) > 4) and
|
||||
(string.lower(string.sub(filePath, -4)) == ".lua")
|
||||
end
|
||||
|
||||
function GetFileNameExt(filePath)
|
||||
if (not filePath) then return end
|
||||
local wxn = wx.wxFileName(filePath)
|
||||
return (wxn:GetName()..(wxn:HasExt() and ("."..wxn:GetExt()) or ""))
|
||||
end
|
||||
|
||||
function GetPathWithSep(wxfn)
|
||||
return wxfn:GetPath(bit.bor(wx.wxPATH_GET_VOLUME, wx.wxPATH_GET_SEPARATOR))
|
||||
end
|
||||
|
||||
function FileSysHasContent(dir)
|
||||
local f = wx.wxFindFirstFile(dir,wx.wxFILE + wx.wxDIR)
|
||||
return #f>0
|
||||
end
|
||||
|
||||
function FileSysGet(dir,spec)
|
||||
local content = {}
|
||||
local browse = wx.wxFileSystem()
|
||||
if not wx.wxFileName(dir):DirExists() then
|
||||
return content
|
||||
end
|
||||
local f = browse:FindFirst(dir,spec)
|
||||
while #f>0 do
|
||||
table.insert(content,f)
|
||||
f = browse:FindNext()
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
@@ -2,25 +2,22 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
preferencesDialog.addCategory {
|
||||
category = "editor";
|
||||
title = "Editor";
|
||||
category = "editor";
|
||||
title = "Editor";
|
||||
}
|
||||
|
||||
preferencesDialog.addPage {
|
||||
title = "Basic preferences";
|
||||
category = "editor";
|
||||
layout = {
|
||||
{type = 'group',title="Sessions"; minheight = 100; minwidth = 100};
|
||||
{type = "checkbox"; title = "Reopen files";name = 'session_restore'};
|
||||
{type = 'finishgroup'};
|
||||
{type = 'space'; space = 4};
|
||||
|
||||
|
||||
};
|
||||
onload = function ()
|
||||
return {testbox = true}
|
||||
end;
|
||||
onsave = function (values)
|
||||
end
|
||||
title = "Basic preferences";
|
||||
category = "editor";
|
||||
layout = {
|
||||
{type = 'group',title="Sessions"; minheight = 100; minwidth = 100};
|
||||
{type = "checkbox"; title = "Reopen files";name = 'session_restore'};
|
||||
{type = 'finishgroup'};
|
||||
{type = 'space'; space = 4};
|
||||
};
|
||||
onload = function ()
|
||||
return {testbox = true}
|
||||
end;
|
||||
onsave = function (values)
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
@@ -2,36 +2,36 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
preferencesDialog.addCategory {
|
||||
category = "project";
|
||||
title = "Project";
|
||||
category = "project";
|
||||
title = "Project";
|
||||
}
|
||||
|
||||
preferencesDialog.addPage {
|
||||
title = "Project settings";
|
||||
category = "project";
|
||||
layout = {
|
||||
{type = 'group',title="Visible menus"; minheight = 100; minwidth = 100};
|
||||
{type = "checkbox"; title = "Tools";name = 'tools'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "checkbox"; title = "Help";name = 'help'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
--{type='static'; title = "foo"};
|
||||
{type = 'finishgroup'};
|
||||
{type = "space"; space = 4};
|
||||
{type = 'group',title="Interpreter"; minheight = 100; minwidth = 100};
|
||||
{type = "static"; title = "Interpreter"};
|
||||
{type = "space"; space = 4};
|
||||
{type = "combobox"; name = "interpreterlist"};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "static";title = "Working directory"};
|
||||
{type = "dirpicker"; name = "workingdir", title='Working directory'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "static"; title = "Argument"};
|
||||
{type = "edit"; name = "argument"};
|
||||
{type = 'finishgroup'};
|
||||
};
|
||||
onload = function () return {
|
||||
interpreterlist = {"1","2"}
|
||||
} end;
|
||||
onsave = function (values) end;
|
||||
title = "Project settings";
|
||||
category = "project";
|
||||
layout = {
|
||||
{type = 'group',title="Visible menus"; minheight = 100; minwidth = 100};
|
||||
{type = "checkbox"; title = "Tools";name = 'tools'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "checkbox"; title = "Help";name = 'help'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
--{type='static'; title = "foo"};
|
||||
{type = 'finishgroup'};
|
||||
{type = "space"; space = 4};
|
||||
{type = 'group',title="Interpreter"; minheight = 100; minwidth = 100};
|
||||
{type = "static"; title = "Interpreter"};
|
||||
{type = "space"; space = 4};
|
||||
{type = "combobox"; name = "interpreterlist"};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "static";title = "Working directory"};
|
||||
{type = "dirpicker"; name = "workingdir", title='Working directory'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "static"; title = "Argument"};
|
||||
{type = "edit"; name = "argument"};
|
||||
{type = 'finishgroup'};
|
||||
};
|
||||
onload = function () return {
|
||||
interpreterlist = {"1","2"}
|
||||
} end;
|
||||
onsave = function (values) end;
|
||||
}
|
||||
|
||||
1
src/version.lua
Normal file
@@ -0,0 +1 @@
|
||||
ide.VERSION = [[devel]]
|
||||
1061
tools/cg.lua
@@ -2,59 +2,58 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
fninit = function(frame,menuBar)
|
||||
local myMenu = wx.wxMenu{
|
||||
{ ID "cl.allplatforms", "&All", "Compiled with all available platforms (otherwise only first)", wx.wxITEM_CHECK },
|
||||
{ ID "cl.output", "&Output", "Generates output files", wx.wxITEM_CHECK },
|
||||
{ ID "cl.info", "&Info", "Prints Info", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "cl.compile", "&Compile", "Compile Kernels in File" },
|
||||
}
|
||||
menuBar:Append(myMenu, "&OpenCL")
|
||||
fninit = function(frame,menuBar)
|
||||
local myMenu = wx.wxMenu{
|
||||
{ ID "cl.allplatforms", "&All", "Compiled with all available platforms (otherwise only first)", wx.wxITEM_CHECK },
|
||||
{ ID "cl.output", "&Output", "Generates output files", wx.wxITEM_CHECK },
|
||||
{ ID "cl.info", "&Info", "Prints Info", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "cl.compile", "&Compile", "Compile Kernels in File" },
|
||||
}
|
||||
menuBar:Append(myMenu, "&OpenCL")
|
||||
|
||||
local data = {
|
||||
allplatforms = false,
|
||||
output = false,
|
||||
info = false,
|
||||
}
|
||||
|
||||
-- Compile Arg
|
||||
frame:Connect(ID "cl.allplatforms",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.allplatforms = event:IsChecked()
|
||||
end)
|
||||
frame:Connect(ID "cl.output",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.output = event:IsChecked()
|
||||
end)
|
||||
frame:Connect(ID "cl.info",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.info = event:IsChecked()
|
||||
end)
|
||||
-- Compile
|
||||
local function evCompile(event)
|
||||
local filename,info = GetEditorFileAndCurInfo()
|
||||
local editor = GetEditor()
|
||||
local data = {
|
||||
allplatforms = false,
|
||||
output = false,
|
||||
info = false,
|
||||
}
|
||||
|
||||
if (not (filename)) then
|
||||
DisplayOutput("Error: OpenCL Compile: Insufficient parameters (nofile)!\n")
|
||||
return
|
||||
end
|
||||
-- Compile Arg
|
||||
frame:Connect(ID "cl.allplatforms",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.allplatforms = event:IsChecked()
|
||||
end)
|
||||
frame:Connect(ID "cl.output",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.output = event:IsChecked()
|
||||
end)
|
||||
frame:Connect(ID "cl.info",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.info = event:IsChecked()
|
||||
end)
|
||||
-- Compile
|
||||
local function evCompile(event)
|
||||
local filename,info = GetEditorFileAndCurInfo()
|
||||
local editor = GetEditor()
|
||||
|
||||
local fullname = filename:GetFullPath()
|
||||
local cmdline = " "
|
||||
cmdline = cmdline..(data.allplatforms and "--platform -1 " or "")
|
||||
cmdline = cmdline..(data.info and "--info " or "")
|
||||
cmdline = cmdline..(data.output and "--output " or "")
|
||||
cmdline = cmdline..'"'..fullname..'"'
|
||||
if (not (filename)) then
|
||||
DisplayOutput("Error: OpenCL Compile: Insufficient parameters (nofile)!\n")
|
||||
return
|
||||
end
|
||||
|
||||
cmdline = "bin/clcc.exe"..cmdline
|
||||
|
||||
-- run compiler process
|
||||
CommandLineRun(cmdline,nil,true,nil,nil)
|
||||
end
|
||||
|
||||
frame:Connect(ID "cl.compile",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
end,
|
||||
local fullname = filename:GetFullPath()
|
||||
local cmdline = " "
|
||||
cmdline = cmdline..(data.allplatforms and "--platform -1 " or "")
|
||||
cmdline = cmdline..(data.info and "--info " or "")
|
||||
cmdline = cmdline..(data.output and "--output " or "")
|
||||
cmdline = cmdline..'"'..fullname..'"'
|
||||
|
||||
cmdline = "bin/clcc.exe"..cmdline
|
||||
|
||||
-- run compiler process
|
||||
CommandLineRun(cmdline,nil,true,nil,nil)
|
||||
end
|
||||
|
||||
frame:Connect(ID "cl.compile",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -18,4 +18,4 @@ return {
|
||||
description = "stringifys the content for use in C",
|
||||
fn = cstringify,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
213
tools/dx.lua
@@ -5,125 +5,122 @@ local dxpath = os.getenv("DXSDK_DIR")
|
||||
local dxprofile = ide.config.dxprofile or "dx_4"
|
||||
|
||||
return dxpath and {
|
||||
fninit = function(frame,menuBar)
|
||||
fninit = function(frame,menuBar)
|
||||
|
||||
local myMenu = wx.wxMenu{
|
||||
{ ID "dx.profile.dx_2x", "DX SM&2_x", "DirectX sm2_x profile", wx.wxITEM_CHECK },
|
||||
{ ID "dx.profile.dx_3", "DX SM&3_0", "DirectX sm3_0 profile", wx.wxITEM_CHECK },
|
||||
{ ID "dx.profile.dx_4", "DX SM&4_0", "DirectX sm4_0 profile", wx.wxITEM_CHECK },
|
||||
{ ID "dx.profile.dx_5", "DX SM&5_0", "DirectX sm5_0 profile", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "dx.compile.input", "&Custom Args", "when set a popup for custom compiler args will be envoked", wx.wxITEM_CHECK },
|
||||
{ ID "dx.compile.legacy", "&Legacy", "when set compiles in legacy mode", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "dx.compile.vertex", "Compile &Vertex", "Compile Vertex shader (select entry word)" },
|
||||
{ ID "dx.compile.fragment", "Compile &Fragment", "Compile pixel shader (select entry word)" },
|
||||
{ ID "dx.compile.geometry", "Compile &Geometry", "Compile Geometry shader (select entry word)" },
|
||||
{ ID "dx.compile.domain", "Compile &Domain", "Compile Domain shader (select entry word)" },
|
||||
{ ID "dx.compile.hull", "Compile &Hull", "Compile Hull shader (select entry word)" },
|
||||
}
|
||||
menuBar:Append(myMenu, "&Dx")
|
||||
local myMenu = wx.wxMenu{
|
||||
{ ID "dx.profile.dx_2x", "DX SM&2_x", "DirectX sm2_x profile", wx.wxITEM_CHECK },
|
||||
{ ID "dx.profile.dx_3", "DX SM&3_0", "DirectX sm3_0 profile", wx.wxITEM_CHECK },
|
||||
{ ID "dx.profile.dx_4", "DX SM&4_0", "DirectX sm4_0 profile", wx.wxITEM_CHECK },
|
||||
{ ID "dx.profile.dx_5", "DX SM&5_0", "DirectX sm5_0 profile", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "dx.compile.input", "&Custom Args", "when set a popup for custom compiler args will be envoked", wx.wxITEM_CHECK },
|
||||
{ ID "dx.compile.legacy", "&Legacy", "when set compiles in legacy mode", wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID "dx.compile.vertex", "Compile &Vertex", "Compile Vertex shader (select entry word)" },
|
||||
{ ID "dx.compile.fragment", "Compile &Fragment", "Compile pixel shader (select entry word)" },
|
||||
{ ID "dx.compile.geometry", "Compile &Geometry", "Compile Geometry shader (select entry word)" },
|
||||
{ ID "dx.compile.domain", "Compile &Domain", "Compile Domain shader (select entry word)" },
|
||||
{ ID "dx.compile.hull", "Compile &Hull", "Compile Hull shader (select entry word)" },
|
||||
}
|
||||
menuBar:Append(myMenu, "&Dx")
|
||||
|
||||
local data = {}
|
||||
data.customarg = false
|
||||
data.legacy = false
|
||||
data.profid = ID ("dx.profile."..dxprofile)
|
||||
data.domains = {
|
||||
[ID "dx.compile.vertex"] = 1,
|
||||
[ID "dx.compile.fragment"] = 2,
|
||||
[ID "dx.compile.geometry"] = 3,
|
||||
[ID "dx.compile.domain"] = 4,
|
||||
[ID "dx.compile.hull"] = 5,
|
||||
}
|
||||
data.profiles = {
|
||||
[ID "dx.profile.dx_2x"] = {"vs_2_0","ps_2_x",false,false,false,ext=".fxc.txt"},
|
||||
[ID "dx.profile.dx_3"] = {"vs_3_0","ps_3_0",false,false,false,ext=".fxc.txt"},
|
||||
[ID "dx.profile.dx_4"] = {"vs_4_0","ps_4_0","gs_4_0",false,false,ext=".fxc.txt"},
|
||||
[ID "dx.profile.dx_5"] = {"vs_5_0","ps_5_0","gs_5_0","ds_5_0","hs_5_0",ext=".fxc.txt"},
|
||||
}
|
||||
data.domaindefs = {
|
||||
" /D _VERTEX_=1 /D _DX_=1 ",
|
||||
" /D _FRAGMENT_=1 /D _DX_=1 ",
|
||||
" /D _GEOMETRY_=1 /D _DX_=1 ",
|
||||
" /D _TESS_CONTROL_=1 /D _DX_=1 ",
|
||||
" /D _TESS_EVAL_=1 /D _DX_=1 ",
|
||||
}
|
||||
-- Profile related
|
||||
menuBar:Check(data.profid, true)
|
||||
local data = {}
|
||||
data.customarg = false
|
||||
data.legacy = false
|
||||
data.profid = ID ("dx.profile."..dxprofile)
|
||||
data.domains = {
|
||||
[ID "dx.compile.vertex"] = 1,
|
||||
[ID "dx.compile.fragment"] = 2,
|
||||
[ID "dx.compile.geometry"] = 3,
|
||||
[ID "dx.compile.domain"] = 4,
|
||||
[ID "dx.compile.hull"] = 5,
|
||||
}
|
||||
data.profiles = {
|
||||
[ID "dx.profile.dx_2x"] = {"vs_2_0","ps_2_x",false,false,false,ext=".fxc.txt"},
|
||||
[ID "dx.profile.dx_3"] = {"vs_3_0","ps_3_0",false,false,false,ext=".fxc.txt"},
|
||||
[ID "dx.profile.dx_4"] = {"vs_4_0","ps_4_0","gs_4_0",false,false,ext=".fxc.txt"},
|
||||
[ID "dx.profile.dx_5"] = {"vs_5_0","ps_5_0","gs_5_0","ds_5_0","hs_5_0",ext=".fxc.txt"},
|
||||
}
|
||||
data.domaindefs = {
|
||||
" /D _VERTEX_=1 /D _DX_=1 ",
|
||||
" /D _FRAGMENT_=1 /D _DX_=1 ",
|
||||
" /D _GEOMETRY_=1 /D _DX_=1 ",
|
||||
" /D _TESS_CONTROL_=1 /D _DX_=1 ",
|
||||
" /D _TESS_EVAL_=1 /D _DX_=1 ",
|
||||
}
|
||||
-- Profile related
|
||||
menuBar:Check(data.profid, true)
|
||||
|
||||
local function selectProfile (id)
|
||||
for id,profile in pairs(data.profiles) do
|
||||
menuBar:Check(id, false)
|
||||
end
|
||||
menuBar:Check(id, true)
|
||||
data.profid = id
|
||||
end
|
||||
local function selectProfile (id)
|
||||
for id,profile in pairs(data.profiles) do
|
||||
menuBar:Check(id, false)
|
||||
end
|
||||
menuBar:Check(id, true)
|
||||
data.profid = id
|
||||
end
|
||||
|
||||
local function evSelectProfile (event)
|
||||
local chose = event:GetId()
|
||||
selectProfile(chose)
|
||||
end
|
||||
local function evSelectProfile (event)
|
||||
local chose = event:GetId()
|
||||
selectProfile(chose)
|
||||
end
|
||||
|
||||
for id,profile in pairs(data.profiles) do
|
||||
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectProfile)
|
||||
end
|
||||
for id,profile in pairs(data.profiles) do
|
||||
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectProfile)
|
||||
end
|
||||
|
||||
|
||||
-- Compile Arg
|
||||
frame:Connect(ID "dx.compile.input",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.customarg = event:IsChecked()
|
||||
end)
|
||||
frame:Connect(ID "dx.compile.legacy",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.legacy = event:IsChecked()
|
||||
end)
|
||||
-- Compile
|
||||
local function evCompile(event)
|
||||
local filename,info = GetEditorFileAndCurInfo()
|
||||
local editor = GetEditor()
|
||||
-- Compile Arg
|
||||
frame:Connect(ID "dx.compile.input",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.customarg = event:IsChecked()
|
||||
end)
|
||||
frame:Connect(ID "dx.compile.legacy",wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
data.legacy = event:IsChecked()
|
||||
end)
|
||||
-- Compile
|
||||
local function evCompile(event)
|
||||
local filename,info = GetEditorFileAndCurInfo()
|
||||
local editor = GetEditor()
|
||||
|
||||
if (not (filename and info.selword and dxpath)) then
|
||||
DisplayOutput("Error: Dx Compile: Insufficient parameters (nofile / not selected entry function!\n")
|
||||
return
|
||||
end
|
||||
|
||||
if (not (filename and info.selword and dxpath)) then
|
||||
DisplayOutput("Error: Dx Compile: Insufficient parameters (nofile / not selected entry function!\n")
|
||||
return
|
||||
end
|
||||
local domain = data.domains[event:GetId()]
|
||||
local profile = data.profiles[data.profid]
|
||||
if (not profile[domain]) then return end
|
||||
|
||||
local domain = data.domains[event:GetId()]
|
||||
local profile = data.profiles[data.profid]
|
||||
if (not profile[domain]) then return end
|
||||
|
||||
-- popup for custom input
|
||||
local args = data.customarg and wx.wxGetTextFromUser("Compiler Args") or ""
|
||||
args = args:len() > 0 and args or nil
|
||||
-- popup for custom input
|
||||
local args = data.customarg and wx.wxGetTextFromUser("Compiler Args") or ""
|
||||
args = args:len() > 0 and args or nil
|
||||
|
||||
local fullname = filename:GetFullPath()
|
||||
local fullname = filename:GetFullPath()
|
||||
|
||||
local outname = fullname.."."..info.selword.."^"
|
||||
outname = args and outname..args:gsub("%s+%-",";-")..";^" or outname
|
||||
outname = outname..profile[domain]..profile.ext
|
||||
outname = '"'..outname..'"'
|
||||
|
||||
local cmdline = " /T "..profile[domain].." "
|
||||
cmdline = cmdline..(args and args.." " or "")
|
||||
cmdline = cmdline..(data.legacy and "/LD " or "")
|
||||
cmdline = cmdline..data.domaindefs[domain]
|
||||
cmdline = cmdline.."/Fc "..outname.." "
|
||||
cmdline = cmdline.."/E "..info.selword.." "
|
||||
cmdline = cmdline.."/nologo "
|
||||
cmdline = cmdline..' "'..fullname..'"'
|
||||
local outname = fullname.."."..info.selword.."^"
|
||||
outname = args and outname..args:gsub("%s+%-",";-")..";^" or outname
|
||||
outname = outname..profile[domain]..profile.ext
|
||||
outname = '"'..outname..'"'
|
||||
|
||||
cmdline = dxpath.."/Utilities/bin/x86/fxc.exe"..cmdline
|
||||
|
||||
-- run compiler process
|
||||
CommandLineRun(cmdline,nil,true,nil,nil)
|
||||
end
|
||||
|
||||
frame:Connect(ID "dx.compile.vertex",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.fragment",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.geometry",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.domain",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.hull",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
end,
|
||||
local cmdline = " /T "..profile[domain].." "
|
||||
cmdline = cmdline..(args and args.." " or "")
|
||||
cmdline = cmdline..(data.legacy and "/LD " or "")
|
||||
cmdline = cmdline..data.domaindefs[domain]
|
||||
cmdline = cmdline.."/Fc "..outname.." "
|
||||
cmdline = cmdline.."/E "..info.selword.." "
|
||||
cmdline = cmdline.."/nologo "
|
||||
cmdline = cmdline..' "'..fullname..'"'
|
||||
|
||||
cmdline = dxpath.."/Utilities/bin/x86/fxc.exe"..cmdline
|
||||
|
||||
-- run compiler process
|
||||
CommandLineRun(cmdline,nil,true,nil,nil)
|
||||
end
|
||||
|
||||
frame:Connect(ID "dx.compile.vertex",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.fragment",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.geometry",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.domain",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
frame:Connect(ID "dx.compile.hull",wx.wxEVT_COMMAND_MENU_SELECTED,evCompile)
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ local function ffiToApi(ffidef)
|
||||
str = ffidef:match("(%-%-%[%[.+%]%])")
|
||||
local header = ffidef:match("[^\r\n]+")
|
||||
ffidef = StripCommentsC(ffidef)
|
||||
|
||||
|
||||
local description = header:match("|%s*(.*)")
|
||||
local descrprefixes = header:match("(.-)%s*|")
|
||||
local prefixes = {}
|
||||
@@ -14,20 +14,19 @@ local function ffiToApi(ffidef)
|
||||
table.insert(prefixes,prefix)
|
||||
end
|
||||
if (not prefixes[1]) then return end
|
||||
|
||||
|
||||
local ns = prefixes[1]
|
||||
|
||||
|
||||
|
||||
local lktypes = {
|
||||
["string"] = "string",
|
||||
}
|
||||
|
||||
|
||||
local function gencontent(tx)
|
||||
local enums = {}
|
||||
local funcs = {}
|
||||
local values = {}
|
||||
local classes = {}
|
||||
|
||||
|
||||
-- extract function names
|
||||
local curfunc
|
||||
local function registerfunc()
|
||||
@@ -35,7 +34,7 @@ local function ffiToApi(ffidef)
|
||||
-- parse args
|
||||
local args = fn.ARGS:match("%(%s*(.-)%s*%)%s*;") or ""
|
||||
fn.ARGS = "("..args..")"
|
||||
|
||||
|
||||
-- skip return void types
|
||||
local what = fn.RET == "void" and "" or fn.RET
|
||||
what = what:match("%s*(.-)%s*$")
|
||||
@@ -44,15 +43,15 @@ local function ffiToApi(ffidef)
|
||||
if (what ~= "") then
|
||||
fn.TYPE = what
|
||||
end
|
||||
|
||||
|
||||
table.insert(funcs,curfunc)
|
||||
curfunc = nil
|
||||
end
|
||||
|
||||
|
||||
local outer = tx:gsub("(%b{})","{}")
|
||||
|
||||
|
||||
-- FIXME pattern doesnt recognize multiline defs
|
||||
for l in outer:gmatch("[^\r\n]+") do
|
||||
for l in outer:gmatch("[^\r\n]+") do
|
||||
-- extern void func(blubb);
|
||||
-- extern void ( * func )(blubb);
|
||||
-- void func(blubb);
|
||||
@@ -60,8 +59,8 @@ local function ffiToApi(ffidef)
|
||||
-- void * ( * func )(blubb);
|
||||
local typedef = l:match("typedef")
|
||||
local ret,name,args = string.match(typedef and "" or l,
|
||||
"%s*([_%w%*%s]+)%s+%(?[%s%*]*([_%w]+)%s*%)?%s*(%([^%(]*;)")
|
||||
|
||||
"%s*([_%w%*%s]+)%s+%(?[%s%*]*([_%w]+)%s*%)?%s*(%([^%(]*;)")
|
||||
|
||||
if (not (curfunc or typedef) and (ret and name and args)) then
|
||||
ret = ret:gsub("^%s*extern%s*","")
|
||||
curfunc = {RET=ret,NAME=name,ARGS=args}
|
||||
@@ -69,7 +68,7 @@ local function ffiToApi(ffidef)
|
||||
elseif (not typedef) then
|
||||
local typ,names,val = l:match("%s*([_%w%s%*]+)%s+([_%w%[%]]+)[\r\n%s]*=[\r\n%s]*([_%w]+)[\r\n%s]*;")
|
||||
if (not (typ and names and val)) then
|
||||
typ,names = l:match("%s*([_%w%s%*]+)%s+([_%w%[%]%:%s,]+)[\r\n%s]*;")
|
||||
typ,names = l:match("%s*([_%w%s%*]+)%s+([_%w%[%]%:%s,]+)[\r\n%s]*;")
|
||||
end
|
||||
if (typ and names) then
|
||||
for name,rest in names:gmatch("([_%w]+)([^,]*)") do
|
||||
@@ -79,7 +78,7 @@ local function ffiToApi(ffidef)
|
||||
end
|
||||
end
|
||||
elseif(typedef) then
|
||||
-- typedef struct lxgTextureUpdate_s * lxgTextureUpdatePTR;
|
||||
-- typedef struct lxgTextureUpdate_s * lxgTextureUpdatePTR;
|
||||
-- typedef float lxVector2[2];
|
||||
local what,name = l:match("typedef%s+([_%w%s%*]-)%s+([_%w%[%]]+)%s*;")
|
||||
if (what and name) then
|
||||
@@ -94,15 +93,15 @@ local function ffiToApi(ffidef)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- search for enums
|
||||
for def in tx:gmatch("enum[_%w%s\r\n]*(%b{})[_%w%s\r\n]*;") do
|
||||
for enum in def:gmatch("([_%w]+).-[,}]") do
|
||||
table.insert(enums,{NAME=enum})
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- search for classes
|
||||
for class,def,final in tx:gmatch("struct%s+([_%w]*)[%s\r\n]*(%b{})([_%w%s\r\n]*);") do
|
||||
final = final:match("[_%w]+")
|
||||
@@ -117,8 +116,8 @@ local function ffiToApi(ffidef)
|
||||
table.insert(classes,{NAME= final or class,DESCR = "",content = gencontent(def:sub(2,-2))})
|
||||
end
|
||||
|
||||
return (#classes > 0 or #funcs > 0 or #enums > 0 or #values > 0) and
|
||||
{classes=classes,funcs=funcs, enums=enums, values=values}
|
||||
return (#classes > 0 or #funcs > 0 or #enums > 0 or #values > 0) and
|
||||
{classes=classes,funcs=funcs, enums=enums, values=values}
|
||||
end
|
||||
|
||||
local content = gencontent(ffidef)
|
||||
@@ -154,59 +153,59 @@ local function ffiToApi(ffidef)
|
||||
end
|
||||
end
|
||||
fixcontent(content)
|
||||
|
||||
|
||||
str = str..[[
|
||||
|
||||
--auto-generated api from ffi headers
|
||||
local api =
|
||||
]]
|
||||
|
||||
|
||||
--auto-generated api from ffi headers
|
||||
local api =
|
||||
]]
|
||||
|
||||
-- serialize api string
|
||||
local function serialize(str,id,tab,lvl)
|
||||
lvl = string.rep(" ",lvl or 1)
|
||||
lvl = string.rep(" ",lvl or 1)
|
||||
for i,k in ipairs(tab) do
|
||||
str = str..string.gsub(id,"%$([%w]+)%$",k):gsub("##",lvl)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
|
||||
local function genapi(str,content,lvl)
|
||||
lvl = lvl or 1
|
||||
str = str..string.gsub([[
|
||||
##{
|
||||
]],"##",string.rep(" ",lvl))
|
||||
##{
|
||||
]],"##",string.rep(" ",lvl))
|
||||
|
||||
local value =
|
||||
[[##["$NAME$"] = { type ='value', description = "$DESCR$", valuetype = $TYPE$, },
|
||||
]]
|
||||
local enum =
|
||||
[[##["$NAME$"] = { type ='value', },
|
||||
]]
|
||||
local funcdef =
|
||||
[[##["$NAME$"] = { type ='function',
|
||||
## description = "$DESCR$",
|
||||
## returns = "$RET$",
|
||||
## valuetype = $TYPE$,
|
||||
## args = "$ARGS$", },
|
||||
]]
|
||||
str = serialize(str,value,content.values or {},lvl)
|
||||
str = serialize(str,enum,content.enums or {},lvl)
|
||||
str = serialize(str,funcdef,content.funcs or {},lvl)
|
||||
|
||||
local classdef =
|
||||
[[##["$NAME$"] = { type ='class',
|
||||
## description = "$DESCR$",
|
||||
## $CHILDS$
|
||||
##},
|
||||
]]
|
||||
for i,v in pairs(content.classes or {}) do
|
||||
v.CHILDS = v.content and genapi("childs = ",v.content,lvl+1) or ""
|
||||
end
|
||||
|
||||
str = serialize(str,classdef,content.classes or {},lvl)
|
||||
local value =
|
||||
[[##["$NAME$"] = { type ='value', description = "$DESCR$", valuetype = $TYPE$, },
|
||||
]]
|
||||
local enum =
|
||||
[[##["$NAME$"] = { type ='value', },
|
||||
]]
|
||||
local funcdef =
|
||||
[[##["$NAME$"] = { type ='function',
|
||||
## description = "$DESCR$",
|
||||
## returns = "$RET$",
|
||||
## valuetype = $TYPE$,
|
||||
## args = "$ARGS$", },
|
||||
]]
|
||||
str = serialize(str,value,content.values or {},lvl)
|
||||
str = serialize(str,enum,content.enums or {},lvl)
|
||||
str = serialize(str,funcdef,content.funcs or {},lvl)
|
||||
|
||||
str = str..string.gsub([[
|
||||
##}]],"##",string.rep(" ",lvl))
|
||||
local classdef =
|
||||
[[##["$NAME$"] = { type ='class',
|
||||
## description = "$DESCR$",
|
||||
## $CHILDS$
|
||||
##},
|
||||
]]
|
||||
for i,v in pairs(content.classes or {}) do
|
||||
v.CHILDS = v.content and genapi("childs = ",v.content,lvl+1) or ""
|
||||
end
|
||||
|
||||
str = serialize(str,classdef,content.classes or {},lvl)
|
||||
|
||||
str = str..string.gsub([[
|
||||
##}]],"##",string.rep(" ",lvl))
|
||||
|
||||
return str
|
||||
end
|
||||
@@ -215,28 +214,28 @@ local api =
|
||||
|
||||
str = str..[[
|
||||
|
||||
return {
|
||||
]]
|
||||
return {
|
||||
]]
|
||||
|
||||
local lib =
|
||||
[[
|
||||
$NAME$ = {
|
||||
type = 'lib',
|
||||
description = "$DESCR$",
|
||||
childs = $API$,
|
||||
},
|
||||
]]
|
||||
|
||||
local libs = {}
|
||||
for i,prefix in ipairs(prefixes) do
|
||||
local p = {NAME=prefix, DESCR = description, API="api"}
|
||||
table.insert(libs,p)
|
||||
end
|
||||
local lib =
|
||||
[[
|
||||
$NAME$ = {
|
||||
type = 'lib',
|
||||
description = "$DESCR$",
|
||||
childs = $API$,
|
||||
},
|
||||
]]
|
||||
|
||||
str = serialize(str,lib,libs)
|
||||
str = str..[[
|
||||
}
|
||||
]]
|
||||
local libs = {}
|
||||
for i,prefix in ipairs(prefixes) do
|
||||
local p = {NAME=prefix, DESCR = description, API="api"}
|
||||
table.insert(libs,p)
|
||||
end
|
||||
|
||||
str = serialize(str,lib,libs)
|
||||
str = str..[[
|
||||
}
|
||||
]]
|
||||
|
||||
return str
|
||||
end
|
||||
@@ -261,4 +260,4 @@ return {
|
||||
description = "converts current file to api",
|
||||
fn = exec,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exec = {
|
||||
name = "Luxinia Viewer",
|
||||
description = "sends current file to luxinia viewer",
|
||||
fn = function(wxfname,projectdir)
|
||||
local endstr = projectdir and projectdir:len()>0
|
||||
and " -p "..projectdir or ""
|
||||
|
||||
local cmd = ide.config.path.luxinia.."luxinia.exe --nologo"..endstr
|
||||
cmd = cmd.." -v "..wxfname:GetFullPath()
|
||||
|
||||
CommandLineRun(cmd,nil,nil,true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exec = {
|
||||
name = "Luxinia Viewer",
|
||||
description = "sends current file to luxinia viewer",
|
||||
fn = function(wxfname,projectdir)
|
||||
local endstr = projectdir and projectdir:len()>0
|
||||
and " -p "..projectdir or ""
|
||||
|
||||
local cmd = ide.config.path.luxinia.."luxinia.exe --nologo"..endstr
|
||||
cmd = cmd.." -v "..wxfname:GetFullPath()
|
||||
|
||||
CommandLineRun(cmd,nil,nil,true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exec = {
|
||||
name = "Perforce edit",
|
||||
description = "does p4 edit",
|
||||
fn = function(wxfname,projectdir)
|
||||
local cmd = 'p4 edit "'..wxfname:GetFullPath()..'"'
|
||||
|
||||
CommandLineRun(cmd,nil,true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
exec = {
|
||||
name = "Perforce edit",
|
||||
description = "does p4 edit",
|
||||
fn = function(wxfname,projectdir)
|
||||
local cmd = 'p4 edit "'..wxfname:GetFullPath()..'"'
|
||||
|
||||
CommandLineRun(cmd,nil,true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
return {
|
||||
exec = {
|
||||
name = "Perforce revert",
|
||||
description = "does p4 revert",
|
||||
fn = function(wxfname,projectdir)
|
||||
local cmd = 'p4 revert "'..wxfname:GetFullPath()..'"'
|
||||
|
||||
CommandLineRun(cmd,nil,true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
exec = {
|
||||
name = "Perforce revert",
|
||||
description = "does p4 revert",
|
||||
fn = function(wxfname,projectdir)
|
||||
local cmd = 'p4 revert "'..wxfname:GetFullPath()..'"'
|
||||
|
||||
CommandLineRun(cmd,nil,true)
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
BIN
zbstudio.exe
105
zbstudio/MANIFEST
Normal file
@@ -0,0 +1,105 @@
|
||||
LICENSE
|
||||
README
|
||||
api/lua/baselib.lua
|
||||
api/readme.txt
|
||||
bin/clibs/lfs.dll
|
||||
bin/clibs/mojoshader.dll
|
||||
bin/clibs/socket/core.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindadv.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindaui.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindbase.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindcore.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindgl.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindhtml.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindmedia.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindnet.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindstc.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindxml.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxbindxrc.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxlua.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxluadebug.dll
|
||||
bin/clibs/wx/wxlua_msw28_wxluasocket.dll
|
||||
bin/clibs/zmq.dll
|
||||
bin/libzmq.dll
|
||||
bin/lua.exe
|
||||
bin/lua5.1.dll
|
||||
bin/winapi.dll
|
||||
bin/wx.dll
|
||||
bin/wxbase28_net_vc_custom.dll
|
||||
bin/wxbase28_vc_custom.dll
|
||||
bin/wxbase28_xml_vc_custom.dll
|
||||
bin/wxmsw28_adv_vc_custom.dll
|
||||
bin/wxmsw28_aui_vc_custom.dll
|
||||
bin/wxmsw28_core_vc_custom.dll
|
||||
bin/wxmsw28_gl_vc_custom.dll
|
||||
bin/wxmsw28_html_vc_custom.dll
|
||||
bin/wxmsw28_media_vc_custom.dll
|
||||
bin/wxmsw28_qa_vc_custom.dll
|
||||
bin/wxmsw28_richtext_vc_custom.dll
|
||||
bin/wxmsw28_stc_vc_custom.dll
|
||||
bin/wxmsw28_xrc_vc_custom.dll
|
||||
cfg/user.lua_for_custom_settings.txt
|
||||
interpreters/luadeb.lua
|
||||
lualibs/copas/copas.lua
|
||||
lualibs/coxpcall/coxpcall.lua
|
||||
lualibs/mobdebug/mobdebug.lua
|
||||
lualibs/socket/ltn12.lua
|
||||
lualibs/socket/mime.lua
|
||||
lualibs/socket/socket.lua
|
||||
lualibs/socket/socket/ftp.lua
|
||||
lualibs/socket/socket/http.lua
|
||||
lualibs/socket/socket/smtp.lua
|
||||
lualibs/socket/socket/tp.lua
|
||||
lualibs/socket/socket/url.lua
|
||||
spec/lua.lua
|
||||
src/defs.lua
|
||||
src/editor/autocomplete.lua
|
||||
src/editor/commands.lua
|
||||
src/editor/debugger.lua
|
||||
src/editor/editor.lua
|
||||
src/editor/filetree.lua
|
||||
src/editor/findreplace.lua
|
||||
src/editor/gui.lua
|
||||
src/editor/ids.lua
|
||||
src/editor/iofilters.lua
|
||||
src/editor/menu.lua
|
||||
src/editor/menu_edit.lua
|
||||
src/editor/menu_file.lua
|
||||
src/editor/menu_project.lua
|
||||
src/editor/menu_search.lua
|
||||
src/editor/menu_tools.lua
|
||||
src/editor/menu_view.lua
|
||||
src/editor/output.lua
|
||||
src/editor/preferences.lua
|
||||
src/editor/settings.lua
|
||||
src/editor/shellbox.lua
|
||||
src/editor/singleinstance.lua
|
||||
src/editor/style.lua
|
||||
src/main.lua
|
||||
src/misc/util.lua
|
||||
src/preferences/editor.lua
|
||||
src/preferences/project.lua
|
||||
src/version.lua
|
||||
zbstudio.exe
|
||||
zbstudio/app.lua
|
||||
zbstudio/config.lua
|
||||
zbstudio/menu_help.lua
|
||||
zbstudio/res/16.ico
|
||||
zbstudio/res/16/LICENSE
|
||||
zbstudio/res/16/wxART_COPY.png
|
||||
zbstudio/res/16/wxART_CUT.png
|
||||
zbstudio/res/16/wxART_FILE_OPEN.png
|
||||
zbstudio/res/16/wxART_FILE_SAVE.png
|
||||
zbstudio/res/16/wxART_FIND.png
|
||||
zbstudio/res/16/wxART_FIND_AND_REPLACE.png
|
||||
zbstudio/res/16/wxART_FOLDER.png
|
||||
zbstudio/res/16/wxART_GO_DIR_UP.png
|
||||
zbstudio/res/16/wxART_HELP_PAGE.png
|
||||
zbstudio/res/16/wxART_NEW_DIR.png
|
||||
zbstudio/res/16/wxART_NORMAL_FILE-wxART_OTHER_C.png
|
||||
zbstudio/res/16/wxART_NORMAL_FILE.png
|
||||
zbstudio/res/16/wxART_PASTE.png
|
||||
zbstudio/res/16/wxART_REDO.png
|
||||
zbstudio/res/16/wxART_UNDO.png
|
||||
zbstudio/res/32.ico
|
||||
zbstudio/res/zerobrane.png
|
||||
@@ -7,10 +7,53 @@ local app = {
|
||||
interpreters = function(file) return true end,
|
||||
},
|
||||
|
||||
preinit = function ()
|
||||
local artProvider = wx.wxLuaArtProvider()
|
||||
local icons = {}
|
||||
artProvider.CreateBitmap = function(self, id, client, size)
|
||||
local width = size:GetWidth()
|
||||
local key = width .. "/" .. id
|
||||
local fileClient = "zbstudio/res/" .. key .. "-" .. client .. ".png"
|
||||
local fileKey = "zbstudio/res/" .. key .. ".png"
|
||||
local file
|
||||
if wx.wxFileName(fileClient):FileExists() then file = fileClient
|
||||
elseif wx.wxFileName(fileKey):FileExists() then file = fileKey
|
||||
else return wx.wxNullBitmap end
|
||||
local icon = icons[file] or wx.wxBitmap(file)
|
||||
icons[file] = icon
|
||||
return icon
|
||||
end
|
||||
wx.wxArtProvider.Push(artProvider)
|
||||
|
||||
ide.config.interpreter = "luadeb";
|
||||
end,
|
||||
|
||||
postinit = function ()
|
||||
local icon = wx.wxIcon()
|
||||
icon:LoadFile("zbstudio/res/zbstudio.ico",wx.wxBITMAP_TYPE_ICO)
|
||||
ide.frame:SetIcon(icon)
|
||||
dofile("zbstudio/menu_help.lua")
|
||||
|
||||
local bundle = wx.wxIconBundle()
|
||||
local files = FileSysGet("zbstudio/res/", wx.wxFILE)
|
||||
local icons = 0
|
||||
for i,file in ipairs(files) do
|
||||
if GetFileExt(file) == "ico" then
|
||||
icons = icons + 1
|
||||
bundle:AddIcon(file, wx.wxBITMAP_TYPE_ICO)
|
||||
end
|
||||
end
|
||||
if icons > 0 then ide.frame:SetIcons(bundle) end
|
||||
|
||||
local menuBar = ide.frame.menuBar
|
||||
local menu = menuBar:GetMenu(menuBar:FindMenu("&Project"))
|
||||
local itemid = menu:FindItem("Lua &interpreter")
|
||||
if itemid ~= wx.wxNOT_FOUND then menu:Destroy(itemid) end
|
||||
itemid = menu:FindItem("Project directory")
|
||||
if itemid ~= wx.wxNOT_FOUND then menu:Destroy(itemid) end
|
||||
|
||||
menu = menuBar:GetMenu(menuBar:FindMenu("&View"))
|
||||
itemid = menu:FindItem("&Load Config Style...")
|
||||
if itemid ~= wx.wxNOT_FOUND then menu:Destroy(itemid) end
|
||||
|
||||
menuBar:Check(ID_CLEAROUTPUT, true)
|
||||
end,
|
||||
|
||||
stringtable = {
|
||||
|
||||
53
zbstudio/config.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
editor.fontname = "Courier New"
|
||||
editor.caretline = true
|
||||
editor.showfncall = true
|
||||
editor.autotabs = false
|
||||
editor.usetabs = false
|
||||
editor.tabwidth = 2
|
||||
editor.usewrap = true
|
||||
|
||||
filehistorylength = 20
|
||||
|
||||
singleinstance = true
|
||||
singleinstanceport = 0xe493
|
||||
|
||||
acandtip.shorttip = true
|
||||
|
||||
styles = {
|
||||
-- lexer specific (inherit fg/bg from text)
|
||||
lexerdef = {fg = {128, 128, 128},},
|
||||
comment = {fg = {0, 127, 0 },bg = {240, 240, 220}, fill= true,},
|
||||
stringtxt = {fg = {127, 0, 127},},
|
||||
stringeol = {fg = {0, 0, 0 },bg = {224, 192, 224}, fill = true, },
|
||||
preprocessor = {fg = {127, 127, 0 },},
|
||||
operator = {fg = {0, 0, 0 },},
|
||||
number = {fg = {90, 100, 0 },},
|
||||
|
||||
keywords0 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords1 = {fg = {127, 0, 0}, b = true,},
|
||||
keywords2 = {fg = {0, 127, 0}, b = true,},
|
||||
keywords3 = {fg = {0, 0, 127}, b = true,},
|
||||
keywords4 = {fg = {127, 0, 95}, b = true,},
|
||||
keywords5 = {fg = {35, 95, 175}, b = true,},
|
||||
keywords6 = {fg = {0, 127, 127}, b = true,},
|
||||
keywords7 = {fg = {240, 255, 255}, b = true,},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
text = nil, -- let os pick
|
||||
linenumber = {fg = {90, 90, 80},},
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {192, 192, 192},bg = {255, 255, 255},},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
calltipbg = nil,
|
||||
sel = nil,
|
||||
caret = nil,
|
||||
caretlinebg = nil,
|
||||
fold = nil,
|
||||
whitespace = nil,
|
||||
|
||||
fncall = {fg = {175,175,255}, st= wxstc.wxSTC_INDIC_BOX},
|
||||
}
|
||||
84
zbstudio/menu_help.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
-- author: Paul Kulchenko
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Create the Help menu and attach the callback functions
|
||||
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
|
||||
local helpMenu = wx.wxMenu{
|
||||
{ ID_ABOUT, "&About\tF1", "About ZeroBrane Studio" },
|
||||
}
|
||||
menuBar:Append(helpMenu, "&Help")
|
||||
|
||||
local function DisplayAbout(event)
|
||||
local page = [[
|
||||
<html>
|
||||
<body text="#777777">
|
||||
<table border="0" width="100%">
|
||||
<tr><td><img src="zbstudio/res/zerobrane.png"></center></td></tr>
|
||||
<tr><td>
|
||||
<table cellspacing="3" cellpadding="3">
|
||||
<tr>
|
||||
<td>
|
||||
<b>ZeroBrane Studio (]]..ide.VERSION..[[; using MobDebug ]]..mobdebug._VERSION..[[)</b><br>
|
||||
<b>Copyright © 2011-2012 ZeroBrane LLC</b><br>
|
||||
Paul Kulchenko<br>
|
||||
Licensed under The MIT License.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Based on Estrela Editor</b><br>
|
||||
<b>Copyright © 2008-2011 Luxinia DevTeam</b><br>
|
||||
Christoph Kubisch, Eike Decker<br>
|
||||
Licensed under The MIT License.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Based on wxLua editor sample (]]..wxlua.wxLUA_VERSION_STRING..[[)</b><br>
|
||||
<b>Copyright © 2002-2005 Lomtick Software</b><br>
|
||||
J. Winwood, John Labenski<br>
|
||||
Licensed under wxWindows Library License, Version 3.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Built with ]]..wx.wxVERSION_STRING..[[</b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>]]
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, "About ZeroBane Studio")
|
||||
local html = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(440, 270),
|
||||
wx.wxHW_SCROLLBAR_NEVER)
|
||||
local line = wx.wxStaticLine(dlg, wx.wxID_ANY)
|
||||
local button = wx.wxButton(dlg, wx.wxID_OK, "OK")
|
||||
|
||||
button:SetDefault()
|
||||
|
||||
html:SetBorders(0)
|
||||
html:SetPage(page)
|
||||
html:SetSize(html:GetInternalRepresentation():GetWidth(),
|
||||
html:GetInternalRepresentation():GetHeight())
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(html, 1, wx.wxALL, 10)
|
||||
topsizer:Add(line, 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(button, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
|
||||
dlg:SetAutoLayout(true)
|
||||
dlg:SetSizer(topsizer)
|
||||
topsizer:Fit(dlg)
|
||||
|
||||
dlg:ShowModal()
|
||||
dlg:Destroy()
|
||||
end
|
||||
|
||||
frame:Connect(ID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, DisplayAbout)
|
||||
@@ -1,18 +0,0 @@
|
||||
ZeroBrane Studio
|
||||
-----------------
|
||||
ZeroBrane Studio is a wxLua based IDE. It supports multiple
|
||||
fileformats, "api" for autocompletion and tooltips, and custom
|
||||
commandline tools. Focus is extensibility for target applications
|
||||
using Lua. Its main purpose is as IDE for the ZeroBrane project.
|
||||
|
||||
|
||||
Commandline:
|
||||
------------
|
||||
|
||||
Open File(s):
|
||||
<exe> <filename> [<filename>...]
|
||||
any non-option will be treated as filename
|
||||
|
||||
Overriding Config:
|
||||
<exe> [...] -cfg "<luacode overriding config>" [...]
|
||||
e.g.: zbstudio.exe -cfg "singleinstance=false;" somefile.lua
|
||||
BIN
zbstudio/res/16.ico
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
28
zbstudio/res/16/LICENSE
Normal file
@@ -0,0 +1,28 @@
|
||||
Icons are based on the icon set used in LuaEdit. Some of the icons
|
||||
have been modified to avoid using the last line that is not displayed
|
||||
correctly in wxLua.
|
||||
|
||||
These icons are licenced under MIT license by permission from
|
||||
Jean-Francois Goulet (granted on 2012/01/02).
|
||||
|
||||
LuaEdit
|
||||
|
||||
Copyright © 2004-2009 Jean-Francois Goulet
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
BIN
zbstudio/res/16/wxART_COPY.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
zbstudio/res/16/wxART_CUT.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
zbstudio/res/16/wxART_FILE_OPEN.png
Normal file
|
After Width: | Height: | Size: 642 B |
BIN
zbstudio/res/16/wxART_FILE_SAVE.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
zbstudio/res/16/wxART_FIND.png
Normal file
|
After Width: | Height: | Size: 635 B |