Compare commits

...

140 Commits
0.20 ... 0.26

Author SHA1 Message Date
Paul Kulchenko
e4e5e82660 Disabled attaching debugger by default as this triggers warning to open firewall on the first start, which is inconvenient 2012-01-18 14:00:48 -08:00
Paul Kulchenko
c5f2d3cf18 Merge branch 'master' of git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor 2012-01-18 10:44:46 -08:00
crazybutcher
017049f473 updated lua.exe to 5.1.4 as well 2012-01-18 19:41:33 +01:00
Paul Kulchenko
75ce8116ca Merge branch 'master' of git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor 2012-01-18 10:19:20 -08:00
crazybutcher
73dc7ca2ed Merge remote-tracking branch 'zbstudio/master' 2012-01-18 18:54:52 +01:00
crazybutcher
8c6e111e13 updated lua to 5.1.4 2012-01-18 18:54:22 +01:00
Paul Kulchenko
305cafbfcf Added About page for zbstudio 2012-01-17 20:38:02 -08:00
Paul Kulchenko
8c3d927820 Fixed typos in the About page 2012-01-17 19:45:13 -08:00
Paul Kulchenko
b83138c127 Added version file 2012-01-17 19:44:11 -08:00
Paul Kulchenko
e7a789e466 Moved 'Watch Window' to 'View' menu for consistency and changed to always enable; disabled 'Compile' menu while debugging 2012-01-17 12:51:35 -08:00
Paul Kulchenko
d5f448c952 Updated settings to allow each window to set its default size avoid one-size-fits-all default 2012-01-17 12:35:58 -08:00
Paul Kulchenko
f43babc491 Disabled autotabs/usetabs by default in zbstudio 2012-01-16 22:34:30 -08:00
Paul Kulchenko
6a78042869 Removed duplicate call 2012-01-16 22:33:50 -08:00
Paul Kulchenko
4984cf7a4b Added ability to attach to a debugger from an arbitrary process running MobDebug; upgraded to MobDebug v0.43 2012-01-16 15:28:53 -08:00
Paul Kulchenko
6693a6cd96 Added 'pid' text 2012-01-16 14:13:57 -08:00
Paul Kulchenko
2909eeb0c3 Fixed reference to projpanel to use a local variable as the global is not guaranteed to be correct in the calling context 2012-01-16 14:13:13 -08:00
Paul Kulchenko
61260f6e48 Added reporting of the folder in which the external program is run 2012-01-16 13:08:27 -08:00
Paul Kulchenko
c741d35c67 Updated local/remote shell to handle expressions ('1+2'), accept '=' to show values, and remove 'return ' from error messages where needed 2012-01-16 11:13:45 -08:00
Paul Kulchenko
18e06631bf Fixed an issue with saving a new file when project filetree is open 2012-01-15 19:18:24 -08:00
Paul Kulchenko
efd78f57b9 Fixed issue with autocomplete that caused an error when a substring of an earlier word is typed 2012-01-15 19:09:36 -08:00
Paul Kulchenko
e366377d64 Added display of nil values for variables in the shell (local and remote) 2012-01-15 15:26:43 -08:00
Paul Kulchenko
4b334a0d40 Updated spec list for zbstudio to limit specs to lua 2012-01-15 13:32:11 -08:00
Paul Kulchenko
c3471d0077 Added logic to unhide wx window while debugging or running wxwidget application 2012-01-15 10:47:58 -08:00
Paul Kulchenko
7c7a45d99d Fix to make display of errors with and without stack trace consistent in the shellbox/console 2012-01-14 23:53:00 -08:00
Paul Kulchenko
c57215aeeb Fixed a bug in shell that prevented some of the errors from being displayed 2012-01-14 23:27:09 -08:00
Paul Kulchenko
66e0e04f45 Fixed filetree selection when 'untitled' window is active 2012-01-14 23:21:02 -08:00
Paul Kulchenko
9d1d3256c8 Fixed project browse dialog when no editor window is open 2012-01-14 23:10:42 -08:00
Paul Kulchenko
d61a0d64fc Added manifest for zbstudio 2012-01-12 23:16:02 -08:00
Paul Kulchenko
796e793902 Fixed fields left from the replaced shellbox panel 2012-01-12 23:15:32 -08:00
Paul Kulchenko
adfc4d98a7 Made default windows larger for the first run 2012-01-11 21:54:27 -08:00
Paul Kulchenko
cb28bb1b97 Fixed hiding 'load style' menu for zbstudio 2012-01-10 23:44:28 -08:00
Paul Kulchenko
77ae45ef8b Disabled maximized buttons for output/console and project windows as those are not useful and don't work correctly in all cases 2012-01-10 23:43:31 -08:00
Paul Kulchenko
d64b44943b Renamed 'View' menu items 2012-01-10 23:42:26 -08:00
Paul Kulchenko
8fb808d75f Added winapi module to be able to (optionally) show wx windows under running/debugging 2012-01-10 23:25:49 -08:00
crazybutcher
81e92eec88 changed defaults a bit, disabled autocomplete dynword engine by default 2012-01-08 14:47:21 +01:00
crazybutcher
7d763054b7 improved dynamic word ac engine (counts words active and handles delete/insert ops) 2012-01-08 14:45:38 +01:00
crazybutcher
6b39babf34 bugfix nblayout loader: assure openDocuments[id].index is correct 2012-01-08 14:44:45 +01:00
crazybutcher
214c598a85 added rudimentary notebook layout saving (cannot cope with complex splits yet) 2012-01-07 23:06:35 +01:00
crazybutcher
a297104017 bugfix in filetree for "save path" due to ui restructure 2012-01-07 23:05:36 +01:00
crazybutcher
f6e72fc9ce shell execute: prefer direct string over "return" version 2012-01-06 23:40:24 +01:00
crazybutcher
631ca23a97 main frame now managed through wxAUI, more customizeable layout 2012-01-06 23:25:00 +01:00
crazybutcher
c2d9a0dbac Merge remote branch 'zbstudio/master'
Conflicts:
	src/editor/shellbox.lua
2012-01-06 19:49:13 +01:00
Paul Kulchenko
cec4eb869d Merge branch 'simplified-shellbox' 2012-01-06 09:36:49 -08:00
crazybutcher
7602facb7a Merge remote branch 'zbstudio/master' 2012-01-06 18:32:49 +01:00
crazybutcher
d5827e233c bugfix for luxinia interpreters (do not prepend directory for exe)
bugfix when creating an error in the shell
2012-01-06 14:26:33 +01:00
crazybutcher
d59a92e0bf bugfix in filetree and loadfile when starting from empty sessions 2012-01-06 13:51:55 +01:00
crazybutcher
65d460452b luxinia interpreters should only load when found on system 2012-01-06 09:37:43 +01:00
Paul Kulchenko
867de8f3e4 Fixed localization of 'next' variable, which was causing debugger failure 2012-01-05 23:11:49 -08:00
crazybutcher
ec756721c2 bring back stack traceback on shell execute but filter traces 2012-01-06 00:04:15 +01:00
crazybutcher
3b554526c6 bugfix with file execution in shell 2012-01-05 19:03:16 +01:00
Paul Kulchenko
4246d7683a Updated resources for zbstudio with a new logo 2012-01-04 22:32:20 -08:00
Paul Kulchenko
b7c922e253 Updated prompt symbol in the shell; redirected local shell output back to the shell window 2012-01-04 19:08:09 -08:00
Paul Kulchenko
beaeb9a65d Updated icon license to MIT license and added permission reference 2012-01-04 14:55:34 -08:00
Paul Kulchenko
b3d0f40519 Redirected all shell output (print and such) to the output window 2012-01-04 14:07:24 -08:00
Paul Kulchenko
c64906d09a Added 'clear' command to the shell to clear shell window 2012-01-04 13:34:05 -08:00
Paul Kulchenko
2d993203f8 Added ability for the shell to handle async output; the output is inserted before the prompt. Fixed a bug in the debugger that wasn't redirecting the shell output to the shell 2012-01-04 13:25:50 -08:00
crazybutcher
3fdc605d36 Merge remote branch 'zbstudio/master' 2012-01-04 22:05:15 +01:00
Paul Kulchenko
393c0703a6 Added re-scanning of folders in the filetree to keep the data up-to-date. The re-scanning is done on expanding a node or on activation of a file/folder 2012-01-04 00:31:40 -08:00
Paul Kulchenko
2c396b775e Fixed loading icons when no ico file is present 2012-01-03 22:21:33 -08:00
Paul Kulchenko
d14c4b544a Updated marker for the current line in the console 2012-01-03 22:19:40 -08:00
crazybutcher
730835a04d bugfix when deleting editor tab via middlemouse, the third try ;) this time should delete proper tab and preserve current selected tab 2012-01-03 19:12:04 +01:00
crazybutcher
db315532ed Merge remote branch 'zbstudio/master'
Conflicts:
	src/editor/commands.lua
2012-01-03 18:57:09 +01:00
crazybutcher
cc9128ad73 bugfix, filename loaded multiple times, also fixes bug with selection not updated on new file loads 2012-01-03 18:52:12 +01:00
Paul Kulchenko
99763ce992 Simplified the interactive shell to use a single one-page control for everything; included history of commands and dynamic switching between local/remote shell 2012-01-03 00:21:43 -08:00
Paul Kulchenko
c735b7476d Added configuration and support for word wrap in the editor 2012-01-02 12:02:59 -08:00
Paul Kulchenko
932274fbbe Re-applied and simplified handling of editor tab close event 2012-01-01 20:16:31 -08:00
Paul Kulchenko
7fed63512d Removed Estrela references 2012-01-01 18:09:11 -08:00
Paul Kulchenko
14cf94f3bb Enabled 'Clear Output' menu by default for zbstudio 2012-01-01 18:04:32 -08:00
Paul Kulchenko
14665f57dd Added ability to break applications under debugging; upgraded to mobdebug v0.42 2011-12-30 12:17:52 -08:00
Paul Kulchenko
414f44b6f5 Merge branch 'master' of git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor 2011-12-29 14:22:32 -08:00
Paul Kulchenko
0c1a335aa0 Moved wx.dll file to allow execution and debugging of wx applications 2011-12-29 14:22:07 -08:00
Paul Kulchenko
ae04d6e1aa Fixed logic of loading application .ico files to allow icons of different sizes to be correctly used 2011-12-29 13:16:53 -08:00
CrazyButcher
6fb6c73495 Merge remote-tracking branch 'zbstudio/master'
Conflicts:
	src/editor/gui.lua
2011-12-29 16:51:48 +01:00
CrazyButcher
5083d561d2 bugfix with middle mouse close file tab 2011-12-29 16:00:45 +01:00
CrazyButcher
2a2bfa69a2 autcomplete bugfix for non-lua specs 2011-12-29 13:39:48 +01:00
CrazyButcher
56f05aa5fe luxinia1 api loading bugfix 2011-12-29 13:02:15 +01:00
Paul Kulchenko
4607721020 Moved wx.dll file to allow debugging of wx applications 2011-12-27 18:28:40 -08:00
Paul Kulchenko
329baf4b82 Added killing a debugger client on exit from IDE 2011-12-27 18:26:31 -08:00
Paul Kulchenko
ed30c2399d Fixed an issue with the filetree when a new file is saved 2011-12-27 08:32:09 -08:00
Paul Kulchenko
7663cbbf0c Removed slash conversion in debugger as it is no longer needed with mobdebug v0.41. Normalized use of slashes in file names 2011-12-24 18:58:06 -08:00
Paul Kulchenko
c48182b902 Added logic to populate and expand nodes in the project filetree to correctly mark active files in subfolders.
Removed code to delete and repopulate tree nodes as this logic was recreating all tree objects (which made them lost their content, marks, open/close state and everything else). This change makes the list (potentially) stale if the directory content changes, but this issue will be addressed later.
2011-12-23 19:01:12 -08:00
Paul Kulchenko
9297a18b8d Added handling of editor tab close event to fix the issue with closing notebook tab with middle mouse button.
Added close button on an active notebook tab.
2011-12-23 18:58:51 -08:00
Paul Kulchenko
4fdeccdbc1 Removed commented out code 2011-12-23 18:46:46 -08:00
Paul Kulchenko
5c76dbabd6 Upgraded mobdebug module to v0.41 to include changes with handling path conversion 2011-12-23 13:55:08 -08:00
Paul Kulchenko
b6176efd07 Improved project filetree display
Fixed expanding empty folder; now removes expand item on it.
Fixed marking an item in subfolders; now markes those files that are open
in the editor (but only if the subfolder has been expanded).
Removed slash from folder names; simplified file/folder handling logic.
2011-12-22 21:51:34 -08:00
Paul Kulchenko
5327916817 Modified logic for 'jump to function' list to recognize 'local foo = function' and 'foo.bar = function' syntax; added default message to the function list 2011-12-22 19:32:06 -08:00
CrazyButcher
78e52ac04a bugfix for default interpreter setup 2011-12-22 18:17:21 +01:00
CrazyButcher
a9b1729057 do not put user.lua under source control 2011-12-22 18:05:46 +01:00
Paul Kulchenko
a226c6e432 Documentation clean-up: added README, updated LICENSE, moved doc/ files 2011-12-19 22:37:13 -08:00
Paul Kulchenko
79af98d75b Added marking of current file in the project file tree; disabled slash conversion in file load 2011-12-18 16:21:47 -08:00
Paul Kulchenko
ab26ded71a Tweaks to the filetree control to set the font and to better align the browse button 2011-12-18 10:43:41 -08:00
Paul Kulchenko
defba4f767 Added a new set of icons and handling of custom icons in zbstudio 2011-12-18 10:23:20 -08:00
Paul Kulchenko
585c5c0f9c Updated GetBitmap calls to reference correct client (TOOLBAR/OTHER); moved filetree.lua call to be after gui.lua to make ArtProvider.GetBitmap call to work 2011-12-18 10:18:22 -08:00
crazybutcher
047165b6aa bugfix on debugger.pid boolean behavior, clear all markers prior actions 2011-12-17 15:50:13 +01:00
Paul Kulchenko
3d0e52bdbe Added killing the debugee process for real when debugging is stopped by the user 2011-12-13 23:03:46 -08:00
Paul Kulchenko
2e1a512f00 Another end-of-line conversion to fix CRLF endings that were added by the beautification process 2011-12-12 17:01:37 -08:00
crazybutcher
09dbdc1cb1 rename Start Debugging to Continue if debugger.server is present 2011-12-12 23:40:29 +01:00
Paul Kulchenko
a9835c25cb Added Trace command to show execution path in debugger.
Added reporting of error in Watch window and fixed a bug in the Watch
window that made Trace to stop on errors in Watch expressions.
2011-12-12 13:18:17 -08:00
Paul Kulchenko
dab674be91 Split Run and Continue commands 2011-12-12 11:53:59 -08:00
Paul Kulchenko
8e5a6bc284 Returned back wx*.dll as wxLua dll don't draw folds correctly and have tendency to crash in autocomplete 2011-12-12 11:37:56 -08:00
Paul Kulchenko
fe53414868 Ran tools/ and spec/ files through a beautifier 2011-12-12 09:33:35 -08:00
Paul Kulchenko
6f675b60cb Ran files with preferences through a beautifier 2011-12-11 22:03:54 -08:00
Paul Kulchenko
85be275590 Ran most of the lua files (except tools, specs, apis, and lualibs) through a beautifier 2011-12-11 21:14:18 -08:00
crazybutcher
378fe2818e minor refactoring and speedup to modebug and debugging for luxinia2 :) 2011-12-11 15:26:15 +01:00
Paul Kulchenko
20ed88665a Fixed incorrect method name for debugging termination 2011-12-10 18:29:33 -08:00
Paul Kulchenko
31759939f2 Fixed issue with displaying errors in local shell;
Added markers to multi-line expressions
2011-12-10 18:27:58 -08:00
Paul Kulchenko
03b63b491e Updated icon in the executable 2011-12-10 16:55:07 -08:00
Paul Kulchenko
409f1f4214 Enabled singleinstance for zbstudio to check that only one instance is running 2011-12-10 16:54:43 -08:00
Paul Kulchenko
caf9db40b1 Fixed method name in the debugger 2011-12-10 15:12:41 -08:00
Paul Kulchenko
fc7e075a01 Added back all zbstudio files that got removed in the merge 2011-12-10 15:11:44 -08:00
crazybutcher
c956350dc2 minor changes to allow interpreter controlled debugging 2011-12-10 15:36:40 +01:00
crazybutcher
8273b622e9 added missing doc info about app.preinit 2011-12-10 15:04:56 +01:00
crazybutcher
85b016457b sync with zbstudio issue 2011-12-10 14:55:22 +01:00
crazybutcher
15154050f9 Merge remote branch 'zbstudio/master'
Conflicts:
	cfg/config.lua
	doc/defs.lua
	estrela/config.lua
	src/editor/commands.lua
	src/editor/debugger.lua
	src/editor/filetree.lua
	src/editor/gui.lua
	src/editor/menu_file.lua
	src/editor/menu_project.lua
	src/editor/menu_tools.lua
	src/editor/menu_view.lua
	src/editor/output.lua
	src/editor/shellbox.lua
	src/editor/style.lua
	src/main.lua
2011-12-10 14:53:08 +01:00
Paul Kulchenko
d6472a2fd5 Switched from wxNotebook to wxAuiNotebook as it has better looking UI 2011-12-09 23:08:00 -08:00
Paul Kulchenko
3d452e3092 Updated wx dlls to use ones from http://code.google.com/p/luaforwindows/, which have smaller size 2011-12-09 22:59:40 -08:00
Paul Kulchenko
bc2a15915c Added missing config for one of the applications 2011-12-09 21:45:07 -08:00
crazybutcher
6cdecea47c moving default config to application path, and changed config load order:
1) internal defaults
2) app/config.lua
3) cfg/user.lua
4) commandline -cfg

Conflicts:

	src/main.lua
2011-12-09 21:41:05 -08:00
crazybutcher
4967a0a68b removed dead meat 2011-12-09 21:35:05 -08:00
Paul Kulchenko
2428b66add Refactored and normalized interfaces to use Debugger*, Project*, FileTree* convention for public methods; updated local methods in debugger 2011-12-09 21:33:10 -08:00
Paul Kulchenko
0a550c1d25 Convert CRLF that were inherited with original clone to LF 2011-12-07 20:20:22 -08:00
crazybutcher
43e0566cb6 DebuggerFileAction should return true on success 2011-12-07 21:41:07 +01:00
crazybutcher
8739e37faa improve async debugger behavior 2011-12-07 21:31:12 +01:00
crazybutcher
fcc11f7dff moving default config to application path, and changed config load order:
1) internal defaults
2) app/config.lua
3) cfg/user.lua
4) commandline -cfg
2011-12-07 21:10:21 +01:00
crazybutcher
705b5f939c removed dead meat 2011-12-07 19:17:34 +01:00
Paul Kulchenko
af27ef7682 Refactored debugger commands to match debugserver interface in defs.lua 2011-12-07 09:38:26 -08:00
Paul Kulchenko
863f2780b3 Refactored interpreter/debugger interface to move the logic into the interpreter 2011-12-06 22:46:14 -08:00
Paul Kulchenko
790191a681 Added handling of .hasdebugger attribute 2011-12-06 22:38:25 -08:00
Paul Kulchenko
ca0fda0bee Fixed using projectdir from interpreter with debugger 2011-12-06 19:20:22 -08:00
Paul Kulchenko
81e4048754 Added 'Start debugger server' menu; updated starting debugger server automatically to be application-based 2011-12-06 17:53:45 -08:00
Paul Kulchenko
353336796d Fixed an issue with LoadStyle dialog and style processing 2011-12-06 15:30:55 -08:00
Paul Kulchenko
c39ee8fb2f Fixed issue with closing an editor window and then canceling Save dialog 2011-12-06 15:16:07 -08:00
Paul Kulchenko
fbcc555f4e Fixed issue with running/debugging an 'untitled' file 2011-12-06 15:15:37 -08:00
Paul Kulchenko
43237b1b1d Added logic to remove menu items not used in zbstudio 2011-12-06 09:15:53 -08:00
Paul Kulchenko
5f8ee5ce63 Added 'Lua with debugger' interpreter and reverted changes to 'Lua' interpreter back;
Registered 'Lua with debugger' with zbstudio by default;
Added logic to load custom icons
2011-12-05 12:16:32 -08:00
crazybutcher
edd82b8a4a Fix CRLF 2011-12-05 20:21:43 +01:00
Paul Kulchenko
d710fdb4a9 Added preinit callback; moved postinit before frame:Show 2011-12-04 23:43:59 -08:00
Paul Kulchenko
b7124a26ba Fixed shortcuts in Project menu 2011-12-04 23:28:40 -08:00
Paul Kulchenko
fba27ba1b0 Added logic to only enable Tools menu if it is not empty 2011-12-04 16:47:28 -08:00
crazybutcher
1a2a3ac721 abstract debugger interface (untested) 2011-12-04 20:54:30 +01:00
114 changed files with 18942 additions and 17949 deletions

View File

@@ -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
View 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

View 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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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.

Binary file not shown.

Binary file not shown.

BIN
bin/winapi.dll Normal file

Binary file not shown.

View 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},
}

View File

@@ -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},
}

View File

@@ -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},
}

View File

@@ -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},
}

View File

@@ -0,0 +1,9 @@
--[[--
estrela loads configs in the following order
1. <application>\config.lua
2. cfg\user.lua
3. -cfg commandline strings
--]]--

View File

@@ -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},},
}
]]

View File

@@ -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},},
}
]]

View File

@@ -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,
}

View File

@@ -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
View 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},
}

View File

@@ -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 &copy; 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 &copy; 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 &copy; 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 &copy; 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)

View File

@@ -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

View File

@@ -1 +1 @@
icon ICON "../res/estrela.ico"
icon ICON "../res/estrela.ico"

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -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

View File

@@ -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;
}

View File

@@ -1 +0,0 @@
git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor

View File

@@ -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,
}

View File

@@ -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,
}

View File

@@ -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
View 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,
}

View File

@@ -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,
}

View File

@@ -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,
}

View File

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

View File

@@ -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

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

@@ -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

View File

@@ -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
]],
},
}

View File

@@ -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 ]],
},
}

View File

@@ -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
""
},
}

View File

@@ -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]],
},
}

View File

@@ -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 ]],
},
}

View File

@@ -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 ]],
},
}

View File

@@ -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,
},
}

View File

@@ -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]]
},
}
]==]

View File

@@ -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
View 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
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

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

View File

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

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -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")

View File

@@ -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
]=]

View File

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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
View File

@@ -0,0 +1 @@
ide.VERSION = [[devel]]

File diff suppressed because it is too large Load Diff

View File

@@ -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,
}

View File

@@ -18,4 +18,4 @@ return {
description = "stringifys the content for use in C",
fn = cstringify,
},
}
}

View File

@@ -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,
}

View File

@@ -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,
},
}
}

View File

@@ -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,
},
}

View File

@@ -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,
},
}

View File

@@ -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,
},
}

Binary file not shown.

105
zbstudio/MANIFEST Normal file
View 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

View File

@@ -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
View 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
View 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 &copy; 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 &copy; 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 &copy; 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)

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

28
zbstudio/res/16/LICENSE Normal file
View 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Some files were not shown because too many files have changed in this diff Show More