Compare commits

...

218 Commits
0.30 ... 0.33

Author SHA1 Message Date
Paul Kulchenko
a7797f9d9a Updated CHANGELOG and MANIFEST for v0.33. 2012-10-22 17:52:36 -07:00
Paul Kulchenko
78e1f176a5 Updated OSX build script to include 'myprograms' folder if exists. 2012-10-22 17:44:36 -07:00
Paul Kulchenko
a592893b4d Updated Gideros interpreter to extend wait time for Gideros player to start. 2012-10-22 15:59:01 -07:00
Paul Kulchenko
1a1f25c135 Added configuration option to specify hostname when the default one is not reachable (fixes #68). 2012-10-21 13:53:42 -07:00
Paul Kulchenko
00692634a8 Updated text and added timestamp to auto-recover message. 2012-10-20 21:24:13 -07:00
Paul Kulchenko
1037389ce0 Added search for Moai and Love2d executables in default locations on OSX and Windows. 2012-10-20 21:17:34 -07:00
Paul Kulchenko
cc645ebb69 Added values from package.path to LUA_PATH that is used for processes started from the IDE. 2012-10-20 20:29:34 -07:00
Paul Kulchenko
544ada09e2 Restored animation of closing tabs when switching projects.
Using Freeze/Thaw to disable animation didn't work well as it was
interfering with popup messages (for example, when a file is modified) and
was not consistent with the behavior of opening files.
2012-10-20 20:18:36 -07:00
Paul Kulchenko
85d14ca6fd Added conversion of relative filenames to absolute when used in command line. 2012-10-20 11:37:15 -07:00
Paul Kulchenko
1d33dd6482 Added handling of command line parameters on OSX and Linux; updated documentation. 2012-10-20 10:42:04 -07:00
Paul Kulchenko
faa0e0e16d Added auto-recovery to save/restore editor content (fixes #23). 2012-10-19 13:59:55 -07:00
Paul Kulchenko
bb60b9421c Updated configuration example to avoid using ide.spec that is not available (fixes #67). 2012-10-19 12:43:11 -07:00
Paul Kulchenko
ab44438859 Updated CMake build script to handle wildcards in the MANIFEST. 2012-10-17 12:37:54 -07:00
Paul Kulchenko
a463b5fd28 Moved all Estrela features into a separate bundle that can be loaded using cfg/estrela.lua config. 2012-10-17 12:37:26 -07:00
Paul Kulchenko
d021bfa986 Fixed an issue with the current file name not showing in the title bar after startup. 2012-10-17 11:43:49 -07:00
Paul Kulchenko
beeee9e32f Removed multiple file types offered in Save As dialog.
All known types have been listed previously, which created problems
with different extensions assigned by default on different platforms.
Only the current extension is now being offered.
If the current file has no extension, then "*.*" is used as a mask.
2012-10-17 11:39:15 -07:00
Paul Kulchenko
dd682791e1 Updated changelog and documentation on configuration options. 2012-10-17 11:07:50 -07:00
Paul Kulchenko
dddcd96755 Fixed opening a non-existing file from the Recent Files list. 2012-10-16 15:09:57 -07:00
Paul Kulchenko
cb56311090 Fixed Find/Replace checkboxes on OSX (closes #63).
Fixed formatting/alignment of fields in Find/Replace dialog on OSX.
2012-10-16 15:08:14 -07:00
Paul Kulchenko
952f8325c0 Fixed Find/Replace dialog checkboxes that didn't react to clicks on OSX
(fixes #63).

It turned out that StaticBox(Sizer) needs to be created before checkboxes,
otherwise checkboxes don't get any clicks on OSX as the z-order for event
traversal appears to be incorrect.
2012-10-16 12:58:10 -07:00
Paul Kulchenko
0526fd4069 Improved reporting of compilation and run-time errors when running as scratchpad. 2012-10-14 13:54:09 -07:00
Paul Kulchenko
c0e369b175 Fixed an issue with restoring sessions with more than 9 files.
The indexes were sorted alphabetically, instead of numerically, which
caused files with indexes 1x to appear after index 1, instead of 9.
2012-10-14 09:59:01 -07:00
Paul Kulchenko
8e1d823eea Fixed an error when switching to a new project folder. 2012-10-12 17:34:24 -07:00
Paul Kulchenko
b73ef167bc Disabled closing files when switching projects if they are present in both projects. 2012-10-11 15:15:41 -07:00
Paul Kulchenko
7c889880d8 Updated autoindent rules to minimize de-indenting on already indented lines. 2012-10-11 15:13:32 -07:00
Paul Kulchenko
0387e32072 Made debugger strict.lua and LuaJIT friendly (upgraded to MobDebug v0.502). 2012-10-11 11:38:16 -07:00
Paul Kulchenko
e0c18c189a Disabled auto-complete in comments and strings. 2012-10-09 13:13:08 -07:00
Paul Kulchenko
489aaa3e8e Fixed transparency on toolbar search buttons. 2012-10-09 13:10:18 -07:00
Paul Kulchenko
fd92861998 Updated configuration examples to add editor settings and fix user.lua path. 2012-10-09 12:57:36 -07:00
Paul Kulchenko
bba9790a2a Added syntax aware indentation. 2012-10-09 12:04:44 -07:00
Paul Kulchenko
d68985c4a9 Added re/storing open files and interpreter when switching project folders. 2012-10-09 11:02:56 -07:00
Paul Kulchenko
4463cbd327 Updated changelog. 2012-10-07 21:24:46 -07:00
Paul Kulchenko
0d619b1326 Enable scratchpad support in the debugger when interpreter is capable of providing it. 2012-10-03 14:33:12 -07:00
Paul Kulchenko
8c2a4792f6 Added Gideros auto-complete and live coding support (closes #62). 2012-10-03 13:29:50 -07:00
Paul Kulchenko
0f71d4b9a0 Updated MANIFEST to add new debugger buttons. 2012-10-03 12:44:22 -07:00
Paul Kulchenko
30863a3dcc Added stopping gideros player when no connection can be made. 2012-10-02 23:32:17 -07:00
Paul Kulchenko
f74f56b917 Fixed an auto-complete issue with mixed case dynamic words (fixes #60). 2012-10-02 14:22:38 -07:00
Paul Kulchenko
a236d299de Added debugging-related buttons to the toolbar. 2012-10-02 11:57:11 -07:00
Paul Kulchenko
be54763f7e Disabled toggling breakpoints while debugger is running (as they wouldn't be changed anyway). 2012-10-02 11:52:57 -07:00
Paul Kulchenko
663b7cab8b Fixed 'Trying to solve a NULL hostname' warning message. 2012-10-02 11:51:41 -07:00
Paul Kulchenko
c68d45d697 Changed path for user.lua from .ZeroBraneStudio to .zbstudio to avoid name conflict on Linux (helps #44). 2012-10-02 11:49:37 -07:00
Paul Kulchenko
8b7407c3f2 Updated gideros integration to avoid blocking the IDE when the bridge does not respond; enabled debug output on OSX. 2012-10-02 11:46:13 -07:00
Paul Kulchenko
1b29f2e05f Added Gideros integration on OSX; added search for gideros in default locations on Windows and OSX. 2012-10-01 10:40:52 -07:00
Paul Kulchenko
8d4ce56619 Added Gideros integration and debugging support. 2012-09-30 21:49:52 -07:00
Paul Kulchenko
67da97f32f Disabled 'Run as Scratchpad' in the menu for those intepreters that don't support scratchpad. 2012-09-30 21:47:39 -07:00
Paul Kulchenko
46aa3575cf Merge branch 'linux' of https://github.com/toiffel/ZeroBraneStudio 2012-09-29 17:20:43 -07:00
Paul Kulchenko
acc635b9b5 Updated readme with screenshot and changelog with recent changes. 2012-09-29 16:47:02 -07:00
toiffel
99e64f51cd Sort files by name in project filetree only on Linux 2012-09-29 11:39:03 +07:00
toiffel
9002286bcf Fixed mouse cursor behavior in scratchpad mode on Linux (for real this time) 2012-09-29 11:39:03 +07:00
Paul Kulchenko
72b5690689 Added zbstudio.sh script to run on OSX/Linux; updated permissions (closes #15). 2012-09-28 15:13:41 -07:00
Paul Kulchenko
e488ed095c Disabled 'not activated file for debugging' message when auto-activation is disabled. 2012-09-28 14:32:07 -07:00
Paul Kulchenko
9c54fb6507 Fixed a typo that prevented a corner case in autocomplete from working. 2012-09-28 14:16:25 -07:00
Paul Kulchenko
065422fa2d Fixed inconsistent error messages about various config files. Changed searching for user config in '$HOME/.ZeroBraneStudio' from '$HOME/.zbs'. 2012-09-28 10:32:20 -07:00
Paul Kulchenko
0c2d6b6d48 Added variable ratio for sliders in scratchpad.
The ratio depends on the number being adjusted. 1 will change to 2, but
1.1 will change to 1.2 and 1.01 will change to 1.02. 0.99 will change to
1.00 to preserve the ratio.
2012-09-27 10:59:19 -07:00
Paul Kulchenko
89cc631a58 Added editor.autoactivate parameter (false by default) to specify if files should be opened by the debugger. 2012-09-27 09:18:01 -07:00
Paul Kulchenko
83e725ef97 Fixed an issue with auto-complete when dot or colon is used (fixes #56). 2012-09-27 09:15:16 -07:00
Paul Kulchenko
76ec0de7ab Reorganized files and removed those that are no longer needed. 2012-09-26 20:00:58 -07:00
Paul Kulchenko
38a176d84f Updated a warning message about single instance communication. 2012-09-25 22:15:49 -07:00
Paul Kulchenko
3bb22f4c48 Added auto-activation of files requested during debugging. 2012-09-25 22:15:07 -07:00
Paul Kulchenko
7b60461787 Fixed an issue with debugging scripts started using absolute file path. 2012-09-25 22:02:28 -07:00
Paul Kulchenko
843024ec1d Fixed setting working directory for interpreters to the file path when the project directory is not set. 2012-09-25 10:22:24 -07:00
Paul Kulchenko
b4e1dda0d9 Fixed an issue with Backspace not closing auto-complete suggestions. 2012-09-25 10:20:29 -07:00
Paul Kulchenko
394c93e9e6 Merge branch 'linux' of https://github.com/toiffel/ZeroBraneStudio 2012-09-24 22:43:25 -07:00
toiffel
ded66391ac CMakeLists.txt moved to build folder 2012-09-25 11:22:35 +07:00
Paul Kulchenko
d81de133a9 Updated MobDebug to v0.497 to fix issues and improve performance.
Performance improvements.
Added conversion of file names on windows to lower case to make
breakpoints work.
Added reporting errors in deserializing stack data.
Fixed an issue with returning stack values with circular references.
Fixed an issue with wx IDLE event on Linux.
2012-09-24 17:03:56 -07:00
Paul Kulchenko
0f6316619f Added configuration parameter for the number of characters typed before displaying auto-complete suggestions for dynamic words. 2012-09-24 17:01:23 -07:00
Paul Kulchenko
ab8a38fd79 Added proper closing of the application after Shutdown/Logoff events (fixes #57). 2012-09-23 21:37:29 -07:00
Paul Kulchenko
c91d287025 Fixed enabling items in the Edit menu (fixes #56). 2012-09-23 20:30:18 -07:00
toiffel
9fa8c7a972 Small regex fixes 2012-09-24 07:53:18 +07:00
toiffel
ce90e7898f Support for MANIFEST files 2012-09-24 07:10:53 +07:00
toiffel
4cafb3c201 Removed estrela frontend, disabled system mobdebug 2012-09-24 01:29:54 +07:00
toiffel
60bc64283d OS X port of CMakeLists.txt 2012-09-22 22:42:37 +07:00
toiffel
83dc1c5065 unix_starter.cpp replaced with shell script 2012-09-22 01:24:16 +07:00
toiffel
124f70d342 Windows port of CMakeLists.txt 2012-09-22 01:24:16 +07:00
toiffel
1400bf6b3d Added icons of different sizes for Linux hicolor theme 2012-09-22 01:24:16 +07:00
toiffel
8f26e2df17 Added Linux .desktop file 2012-09-22 01:24:16 +07:00
toiffel
49b9b66394 Support for install in CMakeLists.txt 2012-09-22 01:24:16 +07:00
toiffel
ee9fe71657 Added system introspection to CMakeLists.txt 2012-09-22 01:24:16 +07:00
toiffel
ba0efe224a Implemented unix_starter.cpp 2012-09-22 01:24:16 +07:00
toiffel
96516c9454 Added initial CMakeLists.txt and unix_starter.cpp stub 2012-09-22 01:24:16 +07:00
toiffel
e6b8533cf9 - Fixed small UI issues with toolbar buttons
- Sort items by name in file tree
2012-09-22 01:24:15 +07:00
Paul Kulchenko
185ebb5bbf Added Moai auto-complete (closes #52). 2012-09-20 17:26:19 -07:00
Paul Kulchenko
f8b447425e Fixed function list in the toolbar on Mac (helps #14). 2012-09-20 11:12:57 -07:00
Paul Kulchenko
7330ac21ad Disabled tooltip when scratchpad is on (fixes #51). 2012-09-19 15:56:43 -07:00
Paul Kulchenko
e6bd7af1d7 Fixed deleting of comment blocks with hidden markup (fixes #40). 2012-09-19 15:54:28 -07:00
Paul Kulchenko
979b318647 Added hiding auto-complete suggestions on losing focus in the editor. 2012-09-18 17:57:29 -07:00
Paul Kulchenko
16a5934c52 Fixed an issue with function list when all editor tabs are closed. 2012-09-18 17:52:05 -07:00
Paul Kulchenko
2d22060e2c Disabled showing calltip when the editor is not in focus. 2012-09-14 21:59:41 -07:00
Paul Kulchenko
82071e6ce1 Added proper reporting of errors in the stack window. 2012-09-13 16:34:55 -07:00
Paul Kulchenko
6a23d09821 Fixed multiple calltips shown on Linux (helps #15).
On Linux DWELLSTART event seems to be generated even for those editor
windows that are not active. What's worse, when generated the event
seems to report "old" position when retrieved using event:GetX and
event:GetY, so instead we use wxGetMousePosition.
2012-09-12 18:04:48 -07:00
Paul Kulchenko
c4b9d3e31c Disabled showing calltip over markup in comments. 2012-09-12 17:45:13 -07:00
Paul Kulchenko
9b50cb3525 Fixed an issue with mouse cursor in scratchpad not properly updated on Linux (fixes #49; helps #15). 2012-09-11 20:06:15 -07:00
Paul Kulchenko
49e56f8f3c Fixed an issue with static analyzer that failes on function names like a.b.c (fixes #50). 2012-09-11 20:03:29 -07:00
Paul Kulchenko
a84f362c1f Fixed disabling Paste menu on Linux when needed (fixes #46; helps #15). 2012-09-11 11:23:29 -07:00
Paul Kulchenko
cfe5b37041 Fixed an issue with context menu on Linux (fixes #47; helps #15). 2012-09-11 11:21:25 -07:00
Paul Kulchenko
e9351c7fde Resolved conflict between lua executable names on Windows and Mac. 2012-09-11 11:17:32 -07:00
Paul Kulchenko
305f48ef6f Added wxlua.deb file and install script that pull and build all required dependencies on Linux (covers most of #15). 2012-09-10 22:27:08 -07:00
Paul Kulchenko
5ccafe93a8 Added osx executables and build files. 2012-09-10 22:20:46 -07:00
Paul Kulchenko
0f14a54843 Updated configuring toolbar size to improve Linux compatibility. 2012-09-10 21:04:42 -07:00
Paul Kulchenko
ac4a2598a3 Fixed debugger failure when debugging is initiated externally and there is an unsaved file in one of editor tabs. 2012-09-10 21:03:37 -07:00
Paul Kulchenko
66fdef6088 Fixed stopping the debugger when an editor tab where debugging happens is closed.
Closing tab didn't work when the debugging session was initiated
externally and not by the IDE.
2012-09-08 23:33:56 -07:00
Paul Kulchenko
4685fed4bb Updated cpath processing to allow Linux version to run side-by-side with Windows and Mac. 2012-09-07 23:36:02 -07:00
Paul Kulchenko
c4a3036794 Added disabling full screen mode when the last editor tab is closed. 2012-09-07 23:13:39 -07:00
Paul Kulchenko
fa5c31a7ec Fixed enabling of several menu items with no editor tab (fixes #42).
Fixed saveAll to allow saving of untitled.lua files;
  Disabled show tooltip if there is no editor tab;
  Disabled save if there is no editor tab;
  Disabled show prev/next in search if there is no editor tab;
  Enabled search/replace in files even if there is no editor tab;
  Disabled switching to fullscreen if there is no editor tab.
2012-09-07 22:34:24 -07:00
Paul Kulchenko
985b2c288b Fixed an issue with loading stock icons on Linux. 2012-09-07 12:15:35 -07:00
Paul Kulchenko
722378debb Added proper reporting of errors in config files. 2012-09-07 12:14:22 -07:00
Paul Kulchenko
4c37b51ae1 Added toggling folders in project pane by single click (fixes #41). 2012-09-07 12:13:12 -07:00
Paul Kulchenko
3e5f0ebf4d Added examples for configuring tabs and moai entry points. 2012-09-07 09:11:01 -07:00
Paul Kulchenko
fa522ae36b Added reporting compilation success rate (fixes #39) 2012-09-06 13:22:36 -07:00
Paul Kulchenko
6b85e36fd6 Updated licensing information. 2012-09-06 11:58:22 -07:00
Paul Kulchenko
fc420943b2 Added shortcuts for adding and removing watches. 2012-09-05 16:21:13 -07:00
Paul Kulchenko
989603655a Added highlighting rows with updated values in the Watch window. 2012-09-05 15:21:38 -07:00
Paul Kulchenko
543c0d7fad Added 'Add Watch Expression' and 'Evaluate in Console' context menu items in the editor. 2012-09-05 15:19:30 -07:00
Paul Kulchenko
cfd0d98270 Added handling of canceling editing in adding a watch. 2012-09-05 15:15:45 -07:00
Paul Kulchenko
e802e38dc2 Fixed Cut/Copy menu items to reflect proper status in the editor. 2012-09-05 11:34:28 -07:00
Paul Kulchenko
ac566de0ba Fixed typo in the static analyzer output 2012-09-04 16:31:17 -07:00
Paul Kulchenko
8419287316 Updated changelog for v0.32 2012-09-03 16:53:50 -07:00
Paul Kulchenko
27d1d159f6 Added configuration option for specifying entry points for moai projects (moai.entrypoints). 2012-09-02 21:21:05 -07:00
Paul Kulchenko
491d37038a Added changelog. 2012-09-02 19:58:16 -07:00
Paul Kulchenko
67eee4f9ef Corrected an image with Lua files used in the project tree 2012-09-02 14:23:40 -07:00
Paul Kulchenko
552a7373ca Switched moai to starting debugging right away without stopping on the first line. 2012-09-01 22:54:06 -07:00
Paul Kulchenko
376a25dfdd Added option to start debugging without stopping on the first line. 2012-09-01 22:53:38 -07:00
Paul Kulchenko
7945a09811 Fixed an issue with debugger not activating files with relative path information 2012-08-31 16:20:56 -07:00
Paul Kulchenko
327f650121 Fixed 'break' command to work after coming from debugger calls (like on()) 2012-08-31 15:58:10 -07:00
Paul Kulchenko
9bceb449e8 Added an IO filter to fix an issue with 0d0d0a line endings on Windows.
Scintilla doesn't strictly follow SetEOLMode setting and accepts both 0d
and 0d0a (and possibly 0a too) as line endings on Windows. Unfortunately,
the standard Lua interpreter does the right thing and only recognizes 0d0a
as the valid marker. This means line numbers are going to be different in
two cases, which creates a problem for breakpoints during debugging.
2012-08-31 15:48:37 -07:00
Paul Kulchenko
4278c25c60 Fixed an issue with highlighting selected item in the project tree.
An attempt to unhighlight the current item (that could have been
removed from the tree when the project directory is changed) led to
a crash of the application on OSX (but not on Windows).
2012-08-31 15:13:33 -07:00
Paul Kulchenko
7f47506eae Upgraded to mobdebug v0.489 to add support for debugging moai callbacks 2012-08-30 12:20:44 -07:00
Paul Kulchenko
b0b137eaf1 Added refresh of Stack and Watch windows to show updated values after executing a statement in remote shell 2012-08-30 12:13:32 -07:00
Paul Kulchenko
d1d29ced43 Added display of complex values on multiple lines in shell with '=' 2012-08-30 11:40:47 -07:00
Paul Kulchenko
2795d4d9ce Added rockspec to the list of extensions for lua (fixes #37) 2012-08-29 14:17:56 -07:00
Paul Kulchenko
02845f2e87 Added a check to avoid evaluating keywords in tooltip 2012-08-29 11:54:54 -07:00
Paul Kulchenko
ec46531c55 Merge branch 'master' of git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor 2012-08-28 23:00:22 -07:00
Paul Kulchenko
9895f06f97 Added correctly stripped version of wx.dll (used --strip-unneded instead of --strip-all) 2012-08-28 22:39:31 -07:00
Paul Kulchenko
a67feb86aa Added current interpreter to the status bar; adding closing debugger when the interpreter is changed 2012-08-28 21:57:52 -07:00
Paul Kulchenko
6b990b652c Updated status bar style to make it consistent across platforms 2012-08-28 21:56:21 -07:00
Paul Kulchenko
7a2326cc9e Fixed evaluation of foo:bar in tooltip (now evaluates as foo.bar) 2012-08-28 21:26:59 -07:00
crazybutcher
e129f486d9 Merge remote-tracking branch 'zbstudio/master'
Conflicts:
	bin/lua51.dll
2012-08-25 15:48:54 +02:00
Paul Kulchenko
c09d9fc143 Updated wx.dll to include missing dependencies: libstdc++-6.dll and libgcc_s_dw2-1.dll (fixes #33) 2012-08-22 22:45:37 -07:00
crazybutcher
52ef014941 updated GLSL to 4.3 status
cg tool: glsl compilation no longer requires a selected word (main is always entry)
2012-08-22 16:53:45 +02:00
Paul Kulchenko
e79fedf764 Added aborting scratchpad processing when an interpreter can't start or report a fatal error 2012-08-20 21:25:34 -07:00
Paul Kulchenko
b7544577df Refactored LUA_PATH/CPATH processing to set it for all interpreters 2012-08-20 21:23:33 -07:00
Paul Kulchenko
53110b3b2f Updated wx.dll to fix scratchpad processing.
Partially reverted wxlua commit r104
(http://wxlua.svn.sourceforge.net/viewvc/wxlua?view=revision&revision=104).
2012-08-20 21:18:54 -07:00
Paul Kulchenko
d6ee3d1278 Added calltip on mouseover for functions during editing and for variables/expressions during debugging 2012-08-20 11:18:15 -07:00
Paul Kulchenko
c0109a26d1 Added a workaround for GetExecutablePath() reporting 'wx.dll' instead of a proper exe name with wxlua 2.8.12.2 on Windows 2012-08-20 10:47:57 -07:00
Paul Kulchenko
2a706f5bf3 Updated test module to use stringified values for comparison 2012-08-20 08:55:49 -07:00
Paul Kulchenko
1f266e04ab Added moai to the manifest 2012-08-19 23:25:13 -07:00
Paul Kulchenko
f45d6f84a3 Changed reporting of program execution time from CPU time to user time 2012-08-18 23:24:53 -07:00
Paul Kulchenko
76b8b7b07b Reassigned hotkeys in the Project menu to minimize conflicts on Mac 2012-08-18 23:22:20 -07:00
Paul Kulchenko
d45f893943 Fixed debugger termination after internal errors 2012-08-18 16:54:14 -07:00
Paul Kulchenko
53e725cf03 Removed .bak files from being replaced in when backup copies are saved 2012-08-18 16:41:12 -07:00
Paul Kulchenko
8a66df19fa Added support for unicode path files on Windows (fixes #30).
Replaced GetCwd() with wx.wxStandardPaths.Get():GetExecutablePath() as the
former doesn't return proper unicode path (at least in wxlua 2.8.12.2).
Replaced io.open with wxFile operations and disabled default error reporting.
Replaced os.rename with wxRenameFile.
Added support for unicode in dofile for Lua (replaced unicode names with
short names using winapi).
Fixed navigation in the Output window to recognize unicode file names.
Upgraded to MobDebug v0.485 to make debugging/breakpoints/step work for
files with unicode paths.
2012-08-17 22:14:27 -07:00
Paul Kulchenko
13be57ae39 Added an option to set path to lua executable 2012-08-16 17:32:43 -07:00
Paul Kulchenko
684150714f Updated love2d interpreter to use the project folder to check for
main.lua.

This allows Run/Debug project with any project file being currently active.
2012-08-11 22:27:41 -07:00
Paul Kulchenko
01e23f448e Fixed activating current file in the project tree on Mac (closes #29) 2012-08-11 22:25:38 -07:00
crazybutcher
036ec3534a modified slightly so ffitoapi can be run standalone 2012-08-11 15:37:51 +02:00
crazybutcher
af57806c69 updated luxinia2's glewgl and added anttweakbar 2012-08-11 15:36:19 +02:00
Paul Kulchenko
a4773563e9 Fixed running scripts with single quotes in path names 2012-08-07 20:10:52 -07:00
Paul Kulchenko
195c463a60 Added error handler to trap and display debugger errors 2012-08-07 19:56:07 -07:00
Paul Kulchenko
8cbf20ae42 Removed explicit path conversions and comparisons 2012-08-07 19:54:36 -07:00
Paul Kulchenko
a11bd6f0d3 Added search in PATH for love2d executable 2012-08-07 18:14:57 -07:00
Paul Kulchenko
1fc12a8a76 Fixed an issue with Run/Debug commands when IDE path includes exclamation mark ('!') 2012-08-07 17:01:26 -07:00
Paul Kulchenko
9a1e681569 Updated moai support to use full path to executable and to search for config.lua 2012-08-07 12:38:08 -07:00
Paul Kulchenko
43083742e6 Updated coroutine debugging to allow stepping through coroutine.resume/.yield calls 2012-08-06 16:40:29 -07:00
Paul Kulchenko
9a5b481189 Changed the call to unhide windows to the async version (ShowWindowAsync) to avoid blocking the IDE when the application doesn't respond 2012-08-05 21:07:22 -07:00
Paul Kulchenko
565f8e74fb Signed zbstudio executable to avoid issues with files not being saved without admin privileges and to remove warning about 'unknown publisher' on windows (fixes #25) 2012-08-05 18:05:17 -07:00
Paul Kulchenko
b1b87e9013 Fixed an issue with the app not starting on those systems that don't have HOME environment variable; fixes #28 2012-08-05 18:00:02 -07:00
Paul Kulchenko
539eddbf9d Fixed an issue with showing/hiding GUI windows that was occasionally causing a runtime error when the window disappears before it is manipulated 2012-08-03 12:43:58 -07:00
Paul Kulchenko
0abcff015e Added moai interpreter 2012-08-02 17:51:32 -07:00
Paul Kulchenko
7bb74b5fb4 Fixed returning proper name for unsaved files in reporting compilation and static analysis results; moved default names to ide.config (fixes #26) 2012-08-01 16:30:35 -07:00
Paul Kulchenko
b9bc6454b4 Added reporting of function name of the form a.b and a:b in static analysis (fixes #27) 2012-08-01 15:49:37 -07:00
Paul Kulchenko
5734455818 Merge branch 'master' of github.com:pkulchenko/ZeroBraneStudio 2012-08-01 15:07:06 -07:00
Paul Kulchenko
e6e0870a11 Merge pull request #24 from Odie/master
Added ability for user to keep their settings file in their home directory
2012-08-01 15:06:07 -07:00
Paul Kulchenko
2c45207436 Fixed pasting text into the Find dialog and project path box on Mac (fixes #22) 2012-08-01 15:02:36 -07:00
Jonathan Shieh
bf09d3748c Added per user settings file.
Users can now move their settings file to ~/.zbs/user.lua
2012-08-01 10:54:40 +08:00
Paul Kulchenko
452f99826e Upgraded to wxlua 2.8.12.2 (wxwidgets 2.8.12; unicode version); added
lua51.dll proxy (fixes #10 and #7)
2012-07-30 23:11:30 -07:00
Paul Kulchenko
bbfc1c3624 Reorganized handling of automcomplete event (to use AddPendingEvent instead of PostEvent) to avoid runtime application error 2012-07-30 23:02:47 -07:00
Paul Kulchenko
429bb24cb4 Upgraded to mobdebug 0.479 to fix bugs with localization of variables during debugging and handling dashes in paths; added support for coroutine debugging and on/off methods to enable debugging for selected code fragments (to improve performance under the debugger) 2012-07-25 23:10:23 -07:00
Paul Kulchenko
2a8e7fe423 Added ignoring Cmd-key combinations on Mac as this should be handled by wxwidgets, but is not (fixes #19) 2012-07-25 16:19:13 -07:00
Paul Kulchenko
cf1a657b80 Updated manifest to add testwell module 2012-07-23 21:13:52 -07:00
crazybutcher
cf6b328a52 lua51 dll forwards to lua5.1.dll 2012-07-22 10:42:05 +02:00
crazybutcher
b0f98f30dc bugfix in interpreter setting 2012-07-21 11:51:56 +02:00
crazybutcher
5c0bf93d9c Merge remote-tracking branch 'zbstudio/master'
Conflicts:
	interpreters/luxinia2.lua
2012-07-21 10:45:23 +02:00
Paul Kulchenko
7b2241085d Added refresh of filetree on MacOS to get it displayed correctly when the app is started 2012-07-14 11:45:57 -07:00
Paul Kulchenko
c9cfd42d34 Corrected resetting of project directory when it's already set and doesn't need to be changed 2012-07-13 23:30:13 -07:00
Paul Kulchenko
c25c56069d Added handling of balanced brackets in markup links 2012-07-13 22:43:27 -07:00
Paul Kulchenko
a68e8f7bd3 Added unit test module 2012-07-13 22:42:35 -07:00
Paul Kulchenko
fc6de036e0 Reorganized handling of font configuration and added font config for filetree (with a different size default on MacOS) 2012-07-13 09:54:52 -07:00
Paul Kulchenko
08d42a2501 Removed setting the editor font in the config as the default font is different on different platforms 2012-07-12 22:07:10 -07:00
Paul Kulchenko
da32878984 Added reporting the number of traced lines during debugging 2012-07-12 14:21:56 -07:00
Paul Kulchenko
3fd5d88656 Reset project directory if the current one doesn't exist 2012-07-11 23:16:33 -07:00
Paul Kulchenko
7d9ad5100c Fixed markup styling and file tree drawing on MacOS 2012-07-11 16:11:11 -07:00
Paul Kulchenko
6bff634446 Added explicit calls to CreateBitmap as wxArtProvider.GetBitmap doesn't alway call a custom art provider on MacOS (2.8.12) and in some cases on msWin (2.8.7) 2012-07-11 13:24:45 -07:00
Paul Kulchenko
b0de487bf0 Fixed detecting executable name in commands with spaces 2012-07-11 13:21:22 -07:00
Paul Kulchenko
560d56835a Fixed typo 2012-07-11 13:20:35 -07:00
Paul Kulchenko
3c6a06f537 Added setting of PATH and CPATH to find proper libs on windows and mac os platforms 2012-07-11 11:24:33 -07:00
Paul Kulchenko
b1f3bf0bd9 Fixed incorrect folders reported in the file tree when no project directory is set and a file is open 2012-07-10 23:32:38 -07:00
Paul Kulchenko
6ea3a4708d Fixed incorrect filename reported in compile errors when the file is not saved 2012-07-10 22:31:06 -07:00
Paul Kulchenko
4de0eb1dc0 Made 'View Stack Window' and 'View Watch Window' refresh window content if it's already shown 2012-07-07 15:08:58 -07:00
Paul Kulchenko
c2f6ed6338 Removed extension from the template to match folders to make it more portable 2012-07-07 11:49:30 -07:00
Paul Kulchenko
fad7ff0cc3 Updated matching of links to make them less greedy (to avoid capturing link terminators) 2012-07-07 11:46:41 -07:00
Paul Kulchenko
9afa35f9b2 Upgraded deprecated constants and logic for compatibility with wxwidgets 2.9.x 2012-07-06 20:54:11 -07:00
Paul Kulchenko
3a5b46f65e Fixed an error thrown when a window with debugging is closed before the application being debugged is terminated 2012-07-06 20:51:01 -07:00
Paul Kulchenko
26d0908c89 Added scratchpad support for love2d 2012-07-03 13:00:18 -07:00
Paul Kulchenko
770db579d9 Added reset of 'modified' status to keep tab names and their config settings correct upon exit 2012-07-03 12:47:18 -07:00
Paul Kulchenko
8e09ed1658 Fixed incorrect storing of settings for editor tabs with the same text (filename). This was causing only one tab displayed for multiple StyledText controls with interesting effects 2012-07-02 11:53:24 -07:00
Paul Kulchenko
25ac96d39a Removed styling of function calls and capturing definitions in strings and comments (fixed #18) 2012-07-01 22:11:03 -07:00
Paul Kulchenko
22fda661ec Updated matching logic for function definitions to allow for a.b.c() definitions (fixes #17) 2012-07-01 21:59:13 -07:00
Paul Kulchenko
529a0e8c9e Added window title update and filetree refresh after SaveAs command 2012-07-01 15:13:12 -07:00
Paul Kulchenko
7cc061e18d Fixed an issue with launching a process when its output is not redirected to the IDE (fixes #16). Added callback for all started processes to make them call OnTerminate event upon completion 2012-07-01 09:44:00 -07:00
Paul Kulchenko
5f2226bac2 Fixed console to evaluate 'function a() ... end' without errors 2012-06-30 11:12:30 -07:00
Paul Kulchenko
37795c2480 Added tooltip to display variable/expression values during debugging 2012-06-30 11:04:48 -07:00
Paul Kulchenko
5e934dfd69 Added checks around ShowFullScreen() calls to avoid failures on those systems that don't provide it (linux/GTK) 2012-06-29 23:39:53 -07:00
Paul Kulchenko
f970ba38a0 Removed setting focus to the Output window when output is processed as it interfered with Run as Scratchpad 2012-06-29 23:35:35 -07:00
Paul Kulchenko
8af6c1b5b6 Fixed a compilation error caused by shebang in scripts 2012-06-29 16:58:25 -07:00
Paul Kulchenko
0777a5fbd8 Added check for debugger calls to avoid errors when debugger is not loaded 2012-06-29 15:31:09 -07:00
Paul Kulchenko
942681e246 Fixed an issue with love2d path with spaces 2012-06-28 20:05:35 -07:00
crazybutcher
46da5b6697 Merge remote-tracking branch 'zbstudio/master'
Conflicts:
	src/editor/debugger.lua
2012-06-25 22:34:07 +02:00
crazybutcher
80f83d781e fix regression, make luxinia2 debuggable again (still issues left with breaking and adding breakpoints when none were active) 2012-06-23 12:02:42 +02:00
149 changed files with 26875 additions and 14982 deletions

329
CHANGELOG.md Normal file
View File

@@ -0,0 +1,329 @@
# ZeroBrane Studio Changelog
## v0.33 (Oct 22 2012)
### Highlights
- Added **Linux support**.
- Added **Moai auto-complete**.
- Added **Gideros debugging, auto-complete, and live coding**.
- Added **syntax aware indentation**.
- Added **re/storing open files and interpreter** when switching project folders.
### Improvements
- Added configuration option to specify hostname when the default one is not reachable (fixes #68).
- Added search for Moai and Love2d executables in default locations on OSX and Windows.
- Added handling of command line parameters on OSX and Linux; updated documentation.
- Added auto-recovery to save/restore editor content (fixes #23).
- Added syntax aware indentation.
- Added re/storing open files and interpreter when switching project folders.
- Added auto-activation of files requested during debugging.
- Added editor.autoactivate parameter (false by default) to enable activation.
- Added zbstudio.sh script to run on OSX/Linux; updated permissions (closes #15).
- Added variable ratio for sliders in scratchpad.
- Added Linux/OSX/Windows CMake-based launcher build (thanks to toiffel).
- Added configuration parameter for the number of characters typed before displaying auto-complete suggestions for dynamic words.
- Added proper closing of the application after Shutdown/Logoff events (fixes #57).
- Added Moai auto-complete (closes #52).
- Added hiding auto-complete suggestions on losing focus in the editor.
- Added proper reporting of errors in the stack window.
- Added wxlua.deb file and install script that pull and build all required dependencies on Linux (covers most of #15).
- Added osx executables and build files.
- Added disabling full screen mode when the last editor tab is closed.
- Added proper reporting of errors in config files.
- Added toggling folders in project pane by single click (fixes #41).
- Added examples for configuring tabs and moai entry points.
- Added reporting compilation success rate (fixes #39)
- Added shortcuts for adding and removing watches.
- Added highlighting rows with updated values in the Watch window.
- Added 'Add Watch Expression' and 'Evaluate in Console' context menu items in the editor.
- Added handling of canceling editing in adding a watch.
- Added Gideros auto-complete and live coding support (closes #62).
- Added Gideros integration on OSX; added search for gideros in default locations on Windows and OSX.
- Added Gideros integration and debugging support.
- Added debugging-related buttons to the toolbar.
- Improved reporting of compilation and run-time errors when running as scratchpad.
- Made debugger strict.lua and LuaJIT friendly (upgraded to MobDebug v0.502).
- Updated configuration example to avoid using ide.spec that is not available (fixes #67).
- Updated CMake build script to handle wildcards in the MANIFEST.
- Updated configuring toolbar size to improve Linux compatibility.
- Updated MobDebug to v0.497 to fix issues and improve performance.
- Updated a warning message about single instance communication.
- Updated cpath processing to allow Linux version to run side-by-side with Windows and Mac.
- Updated licensing information.
- Enabled scratchpad support in the debugger when interpreter is capable of providing it.
- Disabled auto-complete in comments and strings.
- Disabled toggling breakpoints while debugger is running (as they wouldn't be changed anyway).
- Disabled 'not activated file for debugging' message when auto-activation is disabled.
- Disabled tooltip when scratchpad is on (fixes #51).
- Disabled showing calltip when the editor is not in focus.
- Disabled showing calltip over markup in comments.
- Disabled 'Run as Scratchpad' in the menu for those intepreters that don't support scratchpad.
- Updated configuration examples to add editor settings and fix user.lua path.
- Moved all Estrela features into a separate bundle that can be loaded using cfg/estrela.lua config.
- Removed multiple file types offered in Save As dialog.
### Incompatibilities
- Changed searching for user config in '$HOME/.zbstudio' from '$HOME/.zbs'.
- Temporarily removed the ability to modify spec-related configuration parameters from configuration files.
### Fixes
- Fixed opening a non-existing file from the Recent Files list.
- Fixed Find/Replace dialog checkboxes that didn't react to clicks on OSX (fixes #63).
- Fixed an auto-complete issue with mixed case dynamic words (fixes #60).
- Fixed 'Trying to solve a NULL hostname' warning message.
- Fixed a typo that prevented a corner case in autocomplete from working.
- Fixed inconsistent error messages about various config files.
- Fixed an issue with auto-complete when dot or colon is used (fixes #56).
- Fixed an issue with debugging scripts started using absolute file path.
- Fixed setting working directory for interpreters to the file path when the project directory is not set.
- Fixed an issue with Backspace not closing auto-complete suggestions.
- Fixed enabling items in the Edit menu (fixes #56).
- Fixed function list in the toolbar on Mac (helps #14).
- Fixed deleting of comment blocks with hidden markup (fixes #40).
- Fixed an issue with function list when all editor tabs are closed.
- Fixed multiple calltips shown on Linux (helps #15).
- Fixed an issue with mouse cursor in scratchpad not properly updated on Linux (fixes #49; helps #15).
- Fixed an issue with static analyzer that failes on function names like a.b.c (fixes #50).
- Fixed disabling Paste menu on Linux when needed (fixes #46; helps #15).
- Fixed an issue with context menu on Linux (fixes #47; helps #15).
- Fixed debugger failure when debugging is initiated externally and there is an unsaved file in one of editor tabs.
- Fixed stopping the debugger when an editor tab where debugging happens is closed.
- Fixed enabling of several menu items with no editor tab (fixes #42).
- Fixed an issue with loading stock icons on Linux.
- Fixed Cut/Copy menu items to reflect proper status in the editor.
- Fixed typo in the static analyzer output.
- Resolved conflict between lua executable names on Windows and Mac.
## v0.32 (Sep 03 2012)
### Highlights
- Added **Unicode support** for file encoding and file paths on Windows (fixes #30).
- Added **Moai integration and debugging** (including debugging of Moai threads and callbacks).
- Added refresh of Stack and Watch windows after executing a statement in remote shell.
- Added **display of complex values** on multiple lines in shell with '='.
- Added calltip on mouseover for functions during editing and for variables/expressions during debugging.
- Added configuration options to set paths to lua and love2d executables.
- Added support for **coroutine debugging** with stepping through coroutine.resume/.yield calls.
- Updated wx.dll to wxlua 2.8.12.2 and wxwidgets 2.8.12.
- Signed zbstudio app and executable to avoid issues with files not being saved without admin privileges and to remove warning about 'unknown publisher' on windows (fixes #25).
### Improvements
- Added calltip on mouseover for functions during editing and for variables/expressions during debugging.
- Added an IO filter to fix an issue with 0d0d0a line endings on Windows.
- Added support for debugging moai callbacks (upgraded to mobdebug v0.489).
- Added refresh of Stack and Watch windows to show updated values after executing a statement in remote shell.
- Added display of complex values on multiple lines in shell with '='.
- Added rockspec to the list of extensions for lua (fixes #37).
- Added a check to avoid evaluating keywords in tooltip.
- Added current interpreter to the status bar; adding closing debugger when the interpreter is changed.
- Added aborting scratchpad processing when an interpreter can't start or report a fatal error.
- Added support for unicode path files on Windows (fixes #30).
- Added an option to set path to lua executable.
- Added error handler to trap and display debugger errors.
- Added search in PATH for love2d executable.
- Added a workaround for GetExecutablePath() reporting 'wx.dll' instead of a proper exe name with wxlua 2.8.12.2 on Windows.
- Added reporting of function name of the form a.b and a:b in static analysis (fixes #27).
- Added ability for user to keep their settings file in their home directory.
- Added per user settings file. Users can now move their settings file to ~/.zbs/user.lua.
- Added ignoring Cmd-key combinations on Mac as this should be handled by wxwidgets, but is not (fixes #19).
- Added support for coroutine debugging with stepping through coroutine.resume/.yield calls.
- Changed reporting of program execution time from CPU time to user time.
- Changed the call to unhide windows to the async version (ShowWindowAsync) to avoid blocking the IDE when the application doesn't respond.
- Upgraded to wxlua 2.8.12.2 (wxwidgets 2.8.12; unicode version); added lua51.dll proxy (fixes #10 and #7).
- Updated love2d interpreter to use the project folder to check for main.lua.
- Updated test module to use stringified values for comparison.
- Updated status bar style to make it consistent across platforms.
- Removed .bak files from being replaced in when backup copies are saved.
- Removed explicit path conversions and comparisons.
- Refactored LUA_PATH/CPATH processing to set it for all interpreters.
- Signed zbstudio app and executable to avoid issues with files not being saved without admin privileges and to remove warning about 'unknown publisher' on windows (fixes #25).
### Incompatibilities
- Reassigned hotkeys in the Project menu to minimize conflicts on Mac (reassigned Shift-F12 and F11).
### Fixes
- Fixed an issue with double click on analylsis results being out-of-sync when the editor switched to another file (fixes #38)
- Fixed an issue with debugger not activating files with relative path information.
- Fixed 'break' command to work after coming from debugger calls (like on()).
- Fixed an issue with highlighting selected item in the project tree.
- Fixed evaluation of foo:bar in tooltip (now evaluates as foo.bar).
- Fixed debugger termination after internal errors.
- Fixed activating current file in the project tree on Mac (closes #29).
- Fixed running scripts with single quotes in path names.
- Fixed an issue with Run/Debug commands when IDE path includes exclamation mark ('!').
- Fixed an issue with the app not starting on those systems that don't have HOME environment variable; fixes #28.
- Fixed an issue with showing/hiding GUI windows that was occasionally causing a runtime error when the window disappears before it is manipulated.
- Fixed returning proper name for unsaved files in reporting compilation and static analysis results; moved default names to ide.config (fixes #26).
- Fixed pasting text into the Find dialog and project path box on Mac (fixes #22).
- Fixed handling of dashes in paths (upgraded to mobdebug 0.479).
- Reorganized handling of automcomplete event (to use AddPendingEvent instead of PostEvent) to avoid runtime application error.
## v0.31 (Jul 14 2012)
### Highlights
- Added **scratchpad support for love2d**.
- Added tooltip to display variable/expression values during debugging.
- Added **MacOS support**.
### Improvements
- Added handling of balanced brackets in markup links.
- Added unit test module.
- Added reporting the number of traced lines during debugging.
- Added setting of PATH and CPATH to find proper libs on windows and mac os platforms.
- Added scratchpad support for love2d.
- Added reset of 'modified' status to keep tab names and their config settings correct upon exit.
- Added window title update and filetree refresh after SaveAs command.
- Added tooltip to display variable/expression values during debugging.
- Made 'View Stack Window' and 'View Watch Window' refresh window content if it's already shown.
- Removed setting the editor font in the config as the default font is different on different platforms.
- Removed extension from the template to match folders to make it more portable.
- Reorganized handling of font configuration and added font config for filetree (with a different size default on MacOS).
- Updated matching logic for function definitions to allow for a.b.c() definitions (fixes #17).
### Fixes
- Fixed markup styling and file tree drawing on MacOS.
- Fixed detecting executable name in commands with spaces.
- Fixed incorrect folders reported in the file tree when no project directory is set and a file is open.
- Fixed incorrect filename reported in compile errors when the file is not saved.
- Fixed refresh of filetree on MacOS to get it displayed correctly when the app is started.
- Fixed an error thrown when a window with debugging is closed before the application being debugged is terminated.
- Fixed incorrect storing of settings for editor tabs with the same text (filename). This was causing only one tab displayed for multiple StyledText controls with interesting effects.
- Fixed an issue with launching a process when its output is not redirected to the IDE (fixes #16).
- Fixed console to evaluate 'function a() ... end' without errors.
- Fixed a compilation error caused by shebang in scripts.
- Fixed an issue with love2d path with spaces.
- Corrected resetting of project directory when it's already set and doesn't need to be changed.
- Added checks around ShowFullScreen() calls to avoid failures on those systems that don't provide it (linux/GTK).
- Added check for debugger calls to avoid errors when debugger is not loaded.
- Updated matching of links to make them less greedy (to avoid capturing link terminators).
- Upgraded deprecated constants and logic for compatibility with wxwidgets 2.9.x.
- Reset project directory if the current one doesn't exist.
- Removed styling of function calls and capturing definitions in strings and comments (fixed #18).
- Removed setting focus to the Output window when output is processed as it interfered with Run as Scratchpad.
## v0.30 (Jun 27 2012)
### Highlights
- Added **love2d support**.
- Added auto complete for love2d API.
- Added support for debugging processes running under LuaJIT.
- Added display of **hierarchical data in Stack window**.
- Added **pretty printing in Watch and Console** (local and remote) windows and handling of multiple results in Console.
- Added **Stack window to display stack information** and local/upvalue values for each stack frame.
- Added ability to **interact with scripts** by allowing text to be entered in the 'Output' window.
### Improvements
- Added love2d support.
- Added auto complete for love2d API.
- Added support for debugging processes running under LuaJIT.
- Added display of hierarchical data in Stack window.
- Added execution time and updated messages in the Output window to be more consistent.
- Added displaying 'nil' values in local console when no result is returned by an expression.
- Added a check to refuse starting a new debugging session if there is one in progress already.
- Added handling of tail calls in the Stack window.
- Added pretty printing in Watch and Console (local and remote) windows and handling of multiple results in Console.
- Added Stack window to display stack information and local/upvalue values for each stack frame.
- Added ability to set font encoding in the config.
- Added restoring cursor position when a modified file is reloaded in the editor.
- Added ability to interact with scripts by allowing text to be entered in the 'Output' window.
- Improved logic in love2d integration to distinguish Debug and Run commands (closes #13).
- Improved reporting in static analysis for functions and global variables.
- Updated menus to avoid conflicts with MacOS shortcuts.
- Updated logic creating menubar to make it work correctly on MacOS with special Help/About items.
- Updated path handling to better detect how the app is started and to avoid loading dlls on non-windows platforms.
- Updated logic for detecting hostname (used in the debugger) to make sure it is resolvable.
- Changed order of lualibs/ and bin/ directories in package.path and package.cpath to load included modules first.
- Removed extensions from launch commands and updated display logic in the Output window.
### Fixes
- Fixed aborting running/debugged programs on MacOS by adding MAKE_GROUP_LEADER option to wxExecute.
- Fixed an issue in the logic for setting breakpoints, which ignored breakpoints in luxinia2 debug sessions.
- Fixed logic in the local/remote console that returned incorrect error message on executing code like '%s':format(1).
- Fixed IDs for Project menu items to allow them to be removed from the menu if needed.
- Fixed an issue with remote application not terminating when IDE is closed while debugging is in progress.
- Fixed refreshing a modified file when the editor is set to read-only mode.
- Fixed saving/restoring configuration of 'Output'/'Console' tabs when IDE is closed while debugging is in progress.
- Fixed removing variable name in Watch window after escaping editing.
- Fixed #9 as it had incorrect logic in one of UTF filters.
- Fixed edit menu shortcuts to work in the 'Output' window (when allowed).
- Fixed reporting of processes that failed to start after 'Run' or 'Debug' commands.
- Fixed executable path matching to work on systems that don't have file extensions.
- Fixed #3 'unused parameter...' check not to fail on anonymous functions that are part of an expression.
- Moved processing of `user.lua` to a later phase after tools and specs are already loaded to allow modification of IDE configuration from `user.lua`. Closes #5.
- Added checks to prevent text modification in 'Output' and 'Console' windows. Fixes #8.
- Disabled 'Run as Scratchpad' if there is no debugger registered capable of running it.
- Disabled Stack and Watch updates when scratchpad is active as they interfere with application execution.
## v0.29 (May 31 2012)
### Highlights
- Added **scratchpad** (running live) functionality.
- Added **code analyzer** based on lua-inspect.
- Updated **comment styling** to follow markdown syntax.
### Improvements
- Added scratchpad (running live) functionality.
- Added code analyzer based on lua-inspect.
- Added Ctrl(-Shift)-TAB navigation between tabs in the editor.
- Added navigation between editor tabs using Ctrl-PgUp and Ctrl-PgDn.
- Added reporting of assignment to global variables in the code analyzer.
- Added ability to turn external processes that connect to debugger into a scratchpad.
- Added exit from full screen mode using ESC key.
- Added reporting of compilation errors during debugging sessions.
- Added handling of more errors in the shell to allow calculations like '(1+2)' to be executed correctly.
- Added moving focus back to the notebook after unhiding/activating a wx window.
- Added missing mime/code.dll and reorganized socket module files (socket.*) to load correctly with require.
- Added stopping the debugger when a debugged program exits.
- Added to static analysis reporting of unused parameters in functions.
- Disabled warning in static analysis about unused 'self' in methods.
- Removed 'error during pre-compilation' message from compile errors.
- Updated comment styling to follow markdown syntax.
### Fixes
- Fixed handling of scripts with comments in the remote shell.
- Fixed an issue with Analyze process when the analyzed script has compilation errors.
- Fixed an issue with scratchpad being on after Save dialog is canceled.
- Fixed about screen.
## v0.28 (Mar 21 2012)
### Highlights
- Added full screen mode.
### Improvements
- Added option to activate output/console when Run/Debug/Compile commands are executed.
- Added full screen mode.
- Added killing a running process on IDE exit.
- Added killing a running process with Shift-F12.
- Disabled buffering of the output for scripts run from IDE.
### Fixes
- Fixed 'Trace' command to continue working when a debugged file is not activated.
- Fixed an issue with saving a file when no project directory is set.
- Fixed missing semicolon in lualibs path; added path for debugger to search under lualibs.
- Fixed an issue with a missing path separator, which prevented debugging from executing step commands in some cases.
- Fixed missing slash on SaveAs by enforcing trailing slash for the project path.
## v0.27 (Feb 14 2012)
### Highlights
- Added markup formatting in the comments.
### Improvements
- Added markup formatting in the comments.
- Added Debug and Run methods to simulate menu commands.
- Added setting a project folder on initial start.
- Added style processing for font name, font size, visibility and hotspot attributes.
- Added setting the current project directory for the shell to allow 'require' commands to work with local modules.
- Updated markup processing with run and debug commands, http link processing, and opening local files in a new window.
- Enforced visibility for shell prompt.
### Fixes
- Fixed activation of a correct tab when one of the editor tabs is closed.
- Fixed an issue with file activation from a debugger.
- Fixed the issue of ClosePage method being called with two different parameters.
- Fixed the issue of the project dir being returned with two trailing slashes.
- Fixed an issue with activating the currenly edited file in the file tree.
- Wrapped DragAcceptFiles into a protected call to make it not fail on MacOS (compiled with wxwidgets 2.8.12).
## v0.26 (Jan 18 2012)

View File

@@ -49,7 +49,7 @@ 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 ]]----------------------------------------------
--[[ wxLua License ]]------------------------------------------------------
http://wxlua.sourceforge.net/
@@ -61,7 +61,7 @@ Original wxLua Lua sample IDE:
luascript at thersgb.net
wxLua is based on
wxWindows Library Licence, Version 3
wxWindows Library License, Version 3
Copyright (c) 1998 Julian Smart, Robert Roebling et al
@@ -178,7 +178,7 @@ output file generation.
MobDebug sources are released under the MIT License
Copyright (c) 2011 Paul Kulchenko (paul@kulchenko.com)
Copyright (c) 2011-2012 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

View File

@@ -1,70 +1,56 @@
# Project Description
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.
[ZeroBrane Studio](http://studio.zerobrane.com/) is a lightweight Lua IDE with code completion, syntax
highlighting, remote debugger, code analyzer, live coding, and debugging
support for several Lua engines (LuaJIT, Löve 2D, Moai, Gideros, MobileLua,
and others).
## 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)
* Written in Lua, so easily customizable.
* Small, portable, and cross-platform (Windows, Mac OSX, and Linux).
* Auto-completion for functions, keywords, and custom APIs.
* Interactive console to directly test code snippets with local and remote execution.
* Integrated debugger (with support for local and remote debugging).
* Live coding with Lua ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-in-lua-bret-victor-style)), Löve 2D ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-with-love)), and Gideros ([demo](http://notebook.kulchenko.com/zerobrane/gideros-live-coding-with-zerobrane-studio-ide)).
* Support for plugin-like components:
- 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.
## Frontends
## Screenshot
There is currently two front-ends using the same editor engine. The original
one is `Estrela`, which has a focus on 3d graphics related usage of Lua,
especially in combination with the luxinia engine or luxinia2 framework.
The second front-end is `ZeroBrane Studio` (zbstudio) which has a focus
on using Lua in education, mobile development, and robotics.
Both are part of the standard distribution.
## Installation
```bash
$ git clone git://github.com/pkulchenko/ZeroBraneStudio.git zbstudio
or
$ git clone git://estrelaeditor.git.sourceforge.net/gitroot/estrelaeditor/estrelaeditor estrelaeditor
```
![ZeroBrane Studio debugger screenshot](http://studio.zerobrane.com/images/debugging.png)
## Usage
```
Open File(s):
<exe> <filename> [<filename>...]
Open file(s):
<zbstudio> <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
Overriding default configuration:
<zbstudio> -cfg "<luacode overriding config>" [<filename>]
e.g.: zbstudio -cfg "editor.fontsize=12" somefile.lua
Loading custom configuration:
<zbstudio> -cfg "config/file.lua" [<filename>]
e.g.: zbstudio -cfg cfg/estrela.lua
```
## Author
### Estrela Editor
**Luxinia Dev:** Christoph Kubisch (crazybutcher@luxinia.de)
### ZeroBrane Studio and MobDebug
**ZeroBrane LLC:** Paul Kulchenko (paul@kulchenko.com)
### Estrela Editor
**Luxinia Dev:** Christoph Kubisch (crazybutcher@luxinia.de)
## License
See LICENSE file.

View File

@@ -71,13 +71,14 @@ ldexp = fn "build floating point number from x and the corresponding integral ex
packUnorm2x16 = fn "Converts each comp. of v into 16-bit ints, packs results into the returned 32-bit uint. - (uint)(vec2 v)",
packUnorm4x8 = fn "Converts each comp. of v into 8-bit ints, packs results into the returned 32-bit uint. - (uint)(vec4 v)",
packSnorm4x8 = fn "Converts each comp. of v into 8-bit ints, packs results into the returned 32-bit uint. - (uint)(vec4 v)",
packDouble2x32 = fn "Packs components of v into a 64-bit value and returns a double-prec value. - (double)(uvec2 v)",
packHalf2x16 = fn "Converts each comp. of v into 16-bit half float, packs results into the returned 32-bit uint. - (uint)(vec2 v)",
unpackUnorm2x16 = fn "Unpacks 32-bit p into two 16-bit uints and converts them to normalized float. - (vec2)(uint p)",
unpackUnorm4x8 = fn "Unpacks 32-bit p into four 8-bit uints and converts them to normalized float. - (vec4)(uint p)",
unpackSnorm4x8 = fn "Unpacks 32-bit p into four 8-bit uints and converts them to normalized float. - (vec4)(uint p)",
packDouble2x32 = fn "Packs components of v into a 64-bit value and returns a double-prec value. - (double)(uvec2 v)",
unpackDouble2x32 = fn "Returns a 2 component vector representation of v. - (uvec2)(double v)",
unpackHalf2x16 = fn "Interprets p as two 16-bit half floats and returns them as vector. - (vec2)(uint p)",
length = fn "return scalar Euclidean length of a vector. - (type)(vecN)",
distance = fn "return the Euclidean distance between two points. - (vecN)(vecN a, b)",
@@ -135,6 +136,11 @@ EndPrimitive = fn "Completes current output primitive and starts a new one. - ()
barrier = fn "Synchronizes across shader invocations. - ()()",
memoryBarrier = fn "control ordering of memory transactions issued by shader thread. - ()()",
memoryBarrierAtomicCounter = fn "control ordering of memory transactions issued by shader thread. - ()()",
memoryBarrierShared = fn "control ordering of memory transactions issued by shader thread. - ()()",
memoryBarrierBuffer = fn "control ordering of memory transactions issued by shader thread. - ()()",
memoryBarrierImage = fn "control ordering of memory transactions issued by shader thread. - ()()",
groupMemoryBarrier = fn "control ordering of memory transactions issued by shader thread. - ()()",
imageAtomicAdd = fn "performs atomic operation on individual texels returns new value. - (uint)(imageN, intN coord, [int sample], uint data)",
imageAtomicMin = fn "performs atomic operation on individual texels returns new value. - (uint)(imageN, intN coord, [int sample], uint data)",
imageAtomicMax = fn "performs atomic operation on individual texels returns new value. - (uint)(imageN, intN coord, [int sample], uint data)",
@@ -167,41 +173,51 @@ texelFetchOffset = fn "integer coordinate lookup for a single texel with offset.
}
local keyw =
[[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
in out inout uniform const centroid sample attribute varying patch
return switch case for do while if else break continue
layout location vertices line_strip triangle_strip max_vertices stream
triangles quads equal_spacing isolines fractional_even_spacing
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_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
[[ int uint half float bool double atomic_uint binding offset
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 depth_greater depth_greater depth_greater depth_unchanged
smooth flat noperspective highp mediump lowp shared packed std140 std430 row_major column_major buffer
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
gl_NumWorkGroups gl_WorkGroupSize gl_WorkGroupID gl_LocalInvocationID gl_GlobalInvocationID gl_LocalInvocationIndex
local_size_x local_size_y local_size_z
coherent volatile restrict readonly writeonly
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 rgba32f rgba16f rg32f rg16f r32f r16f rgba8 rgba16 r11f_g11f_b10f rgb10_a2ui
rgb10_a2i rg16 rg8 r16 r8 rgba32i rgba16i rgba8i rg32i rg16i rg8i r32i r16i r8i rgba32ui rgba16ui rgba8ui rg32ui rg16ui rg8ui
r32ui r16ui r8ui rgba16_snorm rgba8_snorm rg16_snorm rg8_snorm r16_snorm r8_snorm
]]
-- keywords - shouldn't be left out
for w in keyw:gmatch("([a-zA-Z_0-9]+)") do
api[w] = {type="keyword"}
api[w] = {type="keyword"}
end
return api

553
api/lua/anttweakbar.lua Normal file
View File

@@ -0,0 +1,553 @@
--[[// tw tweakbar | AntTweakBar UI
enum { TW_VERSION = 114 }
typedef enum ETwType {
TW_TYPE_UNDEF,
TW_TYPE_BOOLCPP,
TW_TYPE_BOOL8,
TW_TYPE_BOOL16,
TW_TYPE_BOOL32,
TW_TYPE_CHAR,
TW_TYPE_INT8,
TW_TYPE_UINT8,
TW_TYPE_INT16,
TW_TYPE_UINT16,
TW_TYPE_INT32,
TW_TYPE_UINT32,
TW_TYPE_FLOAT,
TW_TYPE_DOUBLE,
TW_TYPE_COLOR32, // 32 bits color. Order is RGBA if API is OpenGL or Direct3D10, and inversed if API is Direct3D9 (can be modified by defining 'colorOrder=...', see doc)
TW_TYPE_COLOR3F, // 3 floats color. Order is RGB.
TW_TYPE_COLOR4F, // 4 floats color. Order is RGBA.
TW_TYPE_CDSTRING, // Null-terminated C Dynamic String (pointer to an array of char dynamically allocated with malloc/realloc/strdup)
TW_TYPE__TEMP1, //
TW_TYPE_QUAT4F, // 4 floats encoding a quaternion {qx,qy,qz,qs}
TW_TYPE_QUAT4D, // 4 doubles encoding a quaternion {qx,qy,qz,qs}
TW_TYPE_DIR3F, // direction vector represented by 3 floats
TW_TYPE_DIR3D, // direction vector represented by 3 doubles
TW_TYPE_CSSTRING_LEN0 = 0x30000000,
TW_TYPE_CSSTRING_LEN256 = 0x30000000 + 256,
} TwType;
typedef struct CTwEnumVal {
int Value;
const char * Label;
} TwEnumVal;
typedef struct CTwStructMember {
const char * Name;
TwType Type;
size_t Offset;
const char * DefString;
} TwStructMember;
typedef enum ETwParamValueType {
TW_PARAM_INT32,
TW_PARAM_FLOAT,
TW_PARAM_DOUBLE,
TW_PARAM_CSTRING // Null-terminated array of char (ie, c-string)
} TwParamValueType;
typedef enum ETwGraphAPI {
TW_OPENGL = 1,
TW_DIRECT3D9 = 2,
TW_DIRECT3D10 = 3,
TW_DIRECT3D11 = 4
} TwGraphAPI;
typedef enum ETwKeyModifier {
TW_KMOD_NONE = 0x0000, // same codes as SDL keysym.mod
TW_KMOD_SHIFT = 0x0003,
TW_KMOD_CTRL = 0x00c0,
TW_KMOD_ALT = 0x0100,
TW_KMOD_META = 0x0c00
} TwKeyModifier;
typedef enum EKeySpecial {
TW_KEY_BACKSPACE = '\b',
TW_KEY_TAB = '\t',
TW_KEY_CLEAR = 0x0c,
TW_KEY_RETURN = '\r',
TW_KEY_PAUSE = 0x13,
TW_KEY_ESCAPE = 0x1b,
TW_KEY_SPACE = ' ',
TW_KEY_DELETE = 0x7f,
TW_KEY_UP = 273,
TW_KEY_DOWN,
TW_KEY_RIGHT,
TW_KEY_LEFT,
TW_KEY_INSERT,
TW_KEY_HOME,
TW_KEY_END,
TW_KEY_PAGE_UP,
TW_KEY_PAGE_DOWN,
TW_KEY_F1,
TW_KEY_F2,
TW_KEY_F3,
TW_KEY_F4,
TW_KEY_F5,
TW_KEY_F6,
TW_KEY_F7,
TW_KEY_F8,
TW_KEY_F9,
TW_KEY_F10,
TW_KEY_F11,
TW_KEY_F12,
TW_KEY_F13,
TW_KEY_F14,
TW_KEY_F15,
TW_KEY_LAST
} TwKeySpecial;
typedef enum ETwMouseAction {
TW_MOUSE_RELEASED,
TW_MOUSE_PRESSED
} TwMouseAction;
typedef enum ETwMouseButtonID {
TW_MOUSE_LEFT = 1,
TW_MOUSE_MIDDLE = 2,
TW_MOUSE_RIGHT = 3
} TwMouseButtonID;
typedef void (*TwSetVarCallback) ( const void *value, void *clientData );
typedef void (*TwGetVarCallback) ( void *value, void *clientData );
typedef void (*TwButtonCallback) ( void *clientData );
typedef void (*TwSummaryCallback) ( char *summaryString, size_t summaryMaxLength, const void *value, void *clientData );
typedef void (*TwCopyCDStringToClient) ( char **destinationClientStringPtr, const char *sourceString );
typedef void (*TwErrorHandler) ( const char *errorMessage );
typedef void (*TwGLUTmousebuttonfun) ( int glutButton, int glutState, int mouseX, int mouseY );
typedef void (*TwGLUTmousemotionfun) ( int mouseX, int mouseY );
typedef void (*TwGLUTkeyboardfun) ( unsigned char glutKey, int mouseX, int mouseY );
typedef void (*TwGLUTspecialfun) ( int glutKey, int mouseX, int mouseY );
typedef struct CTwBar TwBar;
TwBar* TwNewBar( const char *barName );
int TwDeleteBar( TwBar *bar );
int TwDeleteAllBars( );
int TwSetTopBar( const TwBar *bar );
TwBar* TwGetTopBar( );
int TwSetBottomBar( const TwBar *bar );
TwBar* TwGetBottomBar( );
const char* TwGetBarName( TwBar *bar );
int TwGetBarCount( );
TwBar* TwGetBarByIndex( int barIndex );
TwBar* TwGetBarByName( const char *barName );
int TwRefreshBar( TwBar *bar );
int TwAddVarRW( TwBar *bar, const char *name, TwType type, void *var, const char *def );
int TwAddVarRO( TwBar *bar, const char *name, TwType type, const void *var, const char *def );
int TwAddVarCB( TwBar *bar, const char *name, TwType type, TwSetVarCallback setCallback, TwGetVarCallback getCallback, void *clientData, const char *def );
int TwAddButton( TwBar *bar, const char *name, TwButtonCallback callback, void *clientData, const char *def );
int TwAddSeparator( TwBar *bar, const char *name, const char *def );
int TwRemoveVar( TwBar *bar, const char *name );
int TwRemoveAllVars( TwBar *bar );
int TwDefine( const char *def );
TwType TwDefineEnum( const char *name, const TwEnumVal *enumValues, unsigned int nbValues );
TwType TwDefineEnumFromString( const char *name, const char *enumString );
TwType TwDefineStruct( const char *name, const TwStructMember *structMembers, unsigned int nbMembers, size_t structSize, TwSummaryCallback summaryCallback, void *summaryClientData );
void TwCopyCDStringToClientFunc( TwCopyCDStringToClient copyCDStringFunc );
void TwCopyCDStringToLibrary( char **destinationLibraryStringPtr, const char *sourceClientString );
int TwGetParam( TwBar *bar, const char *varName, const char *paramName, TwParamValueType paramValueType, unsigned int outValueMaxCount, void *outValues );
int TwSetParam( TwBar *bar, const char *varName, const char *paramName, TwParamValueType paramValueType, unsigned int inValueCount, const void *inValues );
int TwInit( TwGraphAPI graphAPI, void *device );
int TwTerminate();
int TwDraw();
int TwWindowSize( int width, int height);
int TwSetCurrentWindow( int windowID); // multi-windows support
int TwGetCurrentWindow();
int TwWindowExists( int windowID);
int TwKeyPressed( int key, int modifiers);
int TwKeyTest( int key, int modifiers);
int TwMouseButton( TwMouseAction action, TwMouseButtonID button);
int TwMouseMotion( int mouseX, int mouseY);
int TwMouseWheel( int pos);
const char* TwGetLastError( );
void TwHandleErrors( TwErrorHandler errorHandler);
int TwEventSDL( const void *sdlEvent, unsigned char sdlMajorVersion, unsigned char sdlMinorVersion);
int TwEventSDL12( const void *sdlEvent);
int TwEventSDL13( const void *sdlEvent);
int TwEventMouseButtonGLFW( int glfwButton, int glfwAction );
int TwEventKeyGLFW( int glfwKey, int glfwAction );
int TwEventCharGLFW( int glfwChar, int glfwAction );
int TwEventMouseButtonGLUT( int glutButton, int glutState, int mouseX, int mouseY);
int TwEventMouseMotionGLUT( int mouseX, int mouseY);
int TwEventKeyboardGLUT( unsigned char glutKey, int mouseX, int mouseY );
int TwEventSpecialGLUT( int glutKey, int mouseX, int mouseY );
int TwGLUTModifiersFunc( int (*glutGetModifiersFunc)(void) );
int TwEventSFML( const void *sfmlEvent, unsigned char sfmlMajorVersion, unsigned char sfmlMinorVersion);
]]
--auto-generated api from ffi headers
local api =
{
["TW_TYPE_UNDEF"] = { type ='value', },
["TW_TYPE_BOOLCPP"] = { type ='value', },
["TW_TYPE_BOOL8"] = { type ='value', },
["TW_TYPE_BOOL16"] = { type ='value', },
["TW_TYPE_BOOL32"] = { type ='value', },
["TW_TYPE_CHAR"] = { type ='value', },
["TW_TYPE_INT8"] = { type ='value', },
["TW_TYPE_UINT8"] = { type ='value', },
["TW_TYPE_INT16"] = { type ='value', },
["TW_TYPE_UINT16"] = { type ='value', },
["TW_TYPE_INT32"] = { type ='value', },
["TW_TYPE_UINT32"] = { type ='value', },
["TW_TYPE_FLOAT"] = { type ='value', },
["TW_TYPE_DOUBLE"] = { type ='value', },
["TW_TYPE_COLOR32"] = { type ='value', },
["TW_TYPE_COLOR3F"] = { type ='value', },
["TW_TYPE_COLOR4F"] = { type ='value', },
["TW_TYPE_CDSTRING"] = { type ='value', },
["TW_TYPE__TEMP1"] = { type ='value', },
["TW_TYPE_QUAT4F"] = { type ='value', },
["TW_TYPE_QUAT4D"] = { type ='value', },
["TW_TYPE_DIR3F"] = { type ='value', },
["TW_TYPE_DIR3D"] = { type ='value', },
["TW_TYPE_CSSTRING_LEN0"] = { type ='value', },
["TW_TYPE_CSSTRING_LEN256"] = { type ='value', },
["TW_PARAM_INT32"] = { type ='value', },
["TW_PARAM_FLOAT"] = { type ='value', },
["TW_PARAM_DOUBLE"] = { type ='value', },
["TW_PARAM_CSTRING"] = { type ='value', },
["TW_OPENGL"] = { type ='value', },
["TW_DIRECT3D9"] = { type ='value', },
["TW_DIRECT3D10"] = { type ='value', },
["TW_DIRECT3D11"] = { type ='value', },
["TW_KMOD_NONE"] = { type ='value', },
["TW_KMOD_SHIFT"] = { type ='value', },
["TW_KMOD_CTRL"] = { type ='value', },
["TW_KMOD_ALT"] = { type ='value', },
["TW_KMOD_META"] = { type ='value', },
["TW_KEY_BACKSPACE"] = { type ='value', },
["TW_KEY_TAB"] = { type ='value', },
["TW_KEY_CLEAR"] = { type ='value', },
["TW_KEY_RETURN"] = { type ='value', },
["TW_KEY_PAUSE"] = { type ='value', },
["TW_KEY_ESCAPE"] = { type ='value', },
["TW_KEY_SPACE"] = { type ='value', },
["TW_KEY_DELETE"] = { type ='value', },
["TW_KEY_UP"] = { type ='value', },
["TW_KEY_DOWN"] = { type ='value', },
["TW_KEY_RIGHT"] = { type ='value', },
["TW_KEY_LEFT"] = { type ='value', },
["TW_KEY_INSERT"] = { type ='value', },
["TW_KEY_HOME"] = { type ='value', },
["TW_KEY_END"] = { type ='value', },
["TW_KEY_PAGE_UP"] = { type ='value', },
["TW_KEY_PAGE_DOWN"] = { type ='value', },
["TW_KEY_F1"] = { type ='value', },
["TW_KEY_F2"] = { type ='value', },
["TW_KEY_F3"] = { type ='value', },
["TW_KEY_F4"] = { type ='value', },
["TW_KEY_F5"] = { type ='value', },
["TW_KEY_F6"] = { type ='value', },
["TW_KEY_F7"] = { type ='value', },
["TW_KEY_F8"] = { type ='value', },
["TW_KEY_F9"] = { type ='value', },
["TW_KEY_F10"] = { type ='value', },
["TW_KEY_F11"] = { type ='value', },
["TW_KEY_F12"] = { type ='value', },
["TW_KEY_F13"] = { type ='value', },
["TW_KEY_F14"] = { type ='value', },
["TW_KEY_F15"] = { type ='value', },
["TW_KEY_LAST"] = { type ='value', },
["TW_MOUSE_RELEASED"] = { type ='value', },
["TW_MOUSE_PRESSED"] = { type ='value', },
["TW_MOUSE_LEFT"] = { type ='value', },
["TW_MOUSE_MIDDLE"] = { type ='value', },
["TW_MOUSE_RIGHT"] = { type ='value', },
["TwNewBar"] = { type ='function',
description = "",
returns = "(TwBar*)",
valuetype = nil,
args = "(const char *barName)", },
["TwDeleteBar"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar)", },
["TwDeleteAllBars"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "()", },
["TwSetTopBar"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const TwBar *bar)", },
["TwGetTopBar"] = { type ='function',
description = "",
returns = "(TwBar*)",
valuetype = nil,
args = "()", },
["TwSetBottomBar"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const TwBar *bar)", },
["TwGetBottomBar"] = { type ='function',
description = "",
returns = "(TwBar*)",
valuetype = nil,
args = "()", },
["TwGetBarName"] = { type ='function',
description = "",
returns = "(const char*)",
valuetype = "string",
args = "(TwBar *bar)", },
["TwGetBarCount"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "()", },
["TwGetBarByIndex"] = { type ='function',
description = "",
returns = "(TwBar*)",
valuetype = nil,
args = "(int barIndex)", },
["TwGetBarByName"] = { type ='function',
description = "",
returns = "(TwBar*)",
valuetype = nil,
args = "(const char *barName)", },
["TwRefreshBar"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar)", },
["TwAddVarRW"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *name, TwType type, void *var, const char *def)", },
["TwAddVarRO"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *name, TwType type, const void *var, const char *def)", },
["TwAddVarCB"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *name, TwType type, TwSetVarCallback setCallback, TwGetVarCallback getCallback, void *clientData, const char *def)", },
["TwAddButton"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *name, TwButtonCallback callback, void *clientData, const char *def)", },
["TwAddSeparator"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *name, const char *def)", },
["TwRemoveVar"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *name)", },
["TwRemoveAllVars"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar)", },
["TwDefine"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const char *def)", },
["TwDefineEnum"] = { type ='function',
description = "",
returns = "(TwType)",
valuetype = nil,
args = "(const char *name, const TwEnumVal *enumValues, unsigned int nbValues)", },
["TwDefineEnumFromString"] = { type ='function',
description = "",
returns = "(TwType)",
valuetype = nil,
args = "(const char *name, const char *enumString)", },
["TwDefineStruct"] = { type ='function',
description = "",
returns = "(TwType)",
valuetype = nil,
args = "(const char *name, const TwStructMember *structMembers, unsigned int nbMembers, size_t structSize, TwSummaryCallback summaryCallback, void *summaryClientData)", },
["TwCopyCDStringToClientFunc"] = { type ='function',
description = "",
returns = "(void)",
valuetype = nil,
args = "(TwCopyCDStringToClient copyCDStringFunc)", },
["TwCopyCDStringToLibrary"] = { type ='function',
description = "",
returns = "(void)",
valuetype = nil,
args = "(char **destinationLibraryStringPtr, const char *sourceClientString)", },
["TwGetParam"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *varName, const char *paramName, TwParamValueType paramValueType, unsigned int outValueMaxCount, void *outValues)", },
["TwSetParam"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwBar *bar, const char *varName, const char *paramName, TwParamValueType paramValueType, unsigned int inValueCount, const void *inValues)", },
["TwInit"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwGraphAPI graphAPI, void *device)", },
["TwTerminate"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "()", },
["TwDraw"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "()", },
["TwWindowSize"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int width, int height)", },
["TwSetCurrentWindow"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int windowID)", },
["TwGetCurrentWindow"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "()", },
["TwWindowExists"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int windowID)", },
["TwKeyPressed"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int key, int modifiers)", },
["TwKeyTest"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int key, int modifiers)", },
["TwMouseButton"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(TwMouseAction action, TwMouseButtonID button)", },
["TwMouseMotion"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int mouseX, int mouseY)", },
["TwMouseWheel"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int pos)", },
["TwGetLastError"] = { type ='function',
description = "",
returns = "(const char*)",
valuetype = "string",
args = "()", },
["TwHandleErrors"] = { type ='function',
description = "",
returns = "(void)",
valuetype = nil,
args = "(TwErrorHandler errorHandler)", },
["TwEventSDL"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const void *sdlEvent, unsigned char sdlMajorVersion, unsigned char sdlMinorVersion)", },
["TwEventSDL12"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const void *sdlEvent)", },
["TwEventSDL13"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const void *sdlEvent)", },
["TwEventMouseButtonGLFW"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int glfwButton, int glfwAction)", },
["TwEventKeyGLFW"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int glfwKey, int glfwAction)", },
["TwEventCharGLFW"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int glfwChar, int glfwAction)", },
["TwEventMouseButtonGLUT"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int glutButton, int glutState, int mouseX, int mouseY)", },
["TwEventMouseMotionGLUT"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int mouseX, int mouseY)", },
["TwEventKeyboardGLUT"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(unsigned char glutKey, int mouseX, int mouseY)", },
["TwEventSpecialGLUT"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(int glutKey, int mouseX, int mouseY)", },
["glutGetModifiersFunc"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(void))", },
["TwEventSFML"] = { type ='function',
description = "",
returns = "(int)",
valuetype = nil,
args = "(const void *sfmlEvent, unsigned char sfmlMajorVersion, unsigned char sfmlMinorVersion)", },
["TwEnumVal"] = { type ='class',
description = "",
childs = {
["Value"] = { type ='value', description = "int ", valuetype = nil, },
["Label"] = { type ='value', description = "const char * ", valuetype = "string", },
}
},
["TwStructMember"] = { type ='class',
description = "",
childs = {
["Name"] = { type ='value', description = "const char * ", valuetype = "string", },
["Type"] = { type ='value', description = "TwType ", valuetype = nil, },
["Offset"] = { type ='value', description = "size_t ", valuetype = nil, },
["DefString"] = { type ='value', description = "const char * ", valuetype = "string", },
}
},
}
return {
tw = {
type = 'lib',
description = "AntTweakBar UI",
childs = api,
},
tweakbar = {
type = 'lib',
description = "AntTweakBar UI",
childs = api,
},
}

2577
api/lua/gideros.lua Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

6828
api/lua/moai.lua Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

0
bin/clibs/mime/core.dll Normal file → Executable file
View File

BIN
bin/clibs/mime/core.dylib Normal file

Binary file not shown.

0
bin/clibs/socket/core.dll Normal file → Executable file
View File

BIN
bin/clibs/socket/core.dylib Normal file

Binary file not shown.

Binary file not shown.

BIN
bin/libjpeg.8.dylib Normal file

Binary file not shown.

BIN
bin/libwx.dylib Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/lua Executable file

Binary file not shown.

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>lua</string>
<key>CFBundleDisplayName</key>
<string>Lua</string>
<key>CFBundleGetInfoString</key>
<string></string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string></string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string></string>
<key>CFBundleName</key>
<string>Lua</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string></string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string></string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string></string>
</dict>
</plist>

BIN
bin/lua.app/Contents/MacOS/lua Executable file

Binary file not shown.

0
bin/lua.exe Normal file → Executable file
View File

0
bin/lua5.1.dll Normal file → Executable file
View File

BIN
bin/lua51.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
bin/wx.dll Normal file → Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

142
build/CMakeLists.txt Normal file
View File

@@ -0,0 +1,142 @@
# setup the minimum allowed CMake version
cmake_minimum_required(VERSION 2.8)
# set the default build type (this needs to be done *before* project command)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo" "MinSizeRel")
endif()
# restrict configuration types to the selected build type
set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE INTERNAL "" FORCE)
# set the project name
project("zbstudio")
# set the top-level project directory relative to CMakeLists.txt location
set(TOPDIR ..)
# checks if the Lua module is available
function(check_lua_module MODULE)
if(NOT ${MODULE}_FOUND)
# find Lua executable at first
find_program(LUA_EXECUTABLE "lua")
if(NOT LUA_EXECUTABLE)
message(FATAL_ERROR "Lua executable is not found")
endif()
# run a short script with "require" statement to determine if the Lua module is available
execute_process(COMMAND "${LUA_EXECUTABLE}" -e "require(\"${MODULE}\")"
RESULT_VARIABLE EXIT_CODE OUTPUT_QUIET ERROR_QUIET)
if(EXIT_CODE EQUAL 0)
set(${MODULE}_FOUND TRUE CACHE INTERNAL "")
message(STATUS "Found Lua module: ${MODULE}")
elseif(ARGV1)
message(FATAL_ERROR "Lua module \"${MODULE}\" is not found")
endif()
endif()
endfunction()
# adds an user option to select between system-wide and bundled Lua module
function(add_system_lua_module_option MODULE)
string(TOUPPER ${MODULE} UPPERCASE_MODULE)
if(NOT DEFINED USE_SYSTEM_${UPPERCASE_MODULE})
option(USE_SYSTEM_${UPPERCASE_MODULE}
"Use a system-wide \"${MODULE}\" Lua module instead of the bundled one." ${${MODULE}_FOUND})
endif()
endfunction()
# installs all files listed in the manifest
function(install_from_manifest TYPE MANIFEST DESTDIR EXCLUDE_REGEX)
file(STRINGS ${MANIFEST} PATTERN_LIST)
foreach(PATTERN ${PATTERN_LIST})
string(STRIP ${PATTERN} PATTERN)
if(NOT PATTERN MATCHES ${EXCLUDE_REGEX})
file(GLOB FILELIST RELATIVE "${CMAKE_SOURCE_DIR}/${TOPDIR}" "${CMAKE_SOURCE_DIR}/${TOPDIR}/${PATTERN}")
foreach(FILENAME ${FILELIST})
get_filename_component(FILEPATH ${FILENAME} PATH)
install(${TYPE} ${TOPDIR}/${FILENAME} DESTINATION ${DESTDIR}/${FILEPATH})
endforeach()
endif()
endforeach()
endfunction()
if(WIN32)
# add the executable file to our project
add_executable(zbstudio WIN32 ${TOPDIR}/build/win32_starter.c ${TOPDIR}/zbstudio/res/zbstudio.rc)
# link to the static multi-threaded CRT under MSVC
if(MSVC)
string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE)
foreach(FLAGS_VAR CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_C_FLAGS_${BUILD_TYPE} CMAKE_CXX_FLAGS_${BUILD_TYPE})
string(REGEX REPLACE "/MD" "/MT" ${FLAGS_VAR} ${${FLAGS_VAR}})
string(REGEX REPLACE "/MDd" "/MTd" ${FLAGS_VAR} ${${FLAGS_VAR}})
endforeach()
endif()
# setup the data directory
set(DATADIR .)
# install IDE executable
install(TARGETS zbstudio DESTINATION ${DATADIR})
# install files from manifest
install_from_manifest(FILES ${TOPDIR}/zbstudio/MANIFEST ${DATADIR} "^$")
install_from_manifest(FILES ${TOPDIR}/zbstudio/MANIFEST-bin-win32 ${DATADIR} "^zbstudio.exe$")
elseif(APPLE)
# setup the data directory
set(ROOTDIR ZeroBraneStudio.app/Contents)
set(DATADIR ${ROOTDIR}/ZeroBraneStudio)
# install IDE shell script
install(PROGRAMS ${TOPDIR}/zbstudio/ZeroBraneStudio.app/Contents/MacOS/ZeroBraneStudio DESTINATION ${ROOTDIR}/MacOS)
# install icon pack and .plist file
install(DIRECTORY ${TOPDIR}/zbstudio/ZeroBraneStudio.app/Contents/Resources DESTINATION ${ROOTDIR})
install(FILES ${TOPDIR}/zbstudio/ZeroBraneStudio.app/Contents/Info.plist DESTINATION ${ROOTDIR})
# install files from manifest
install_from_manifest(FILES ${TOPDIR}/zbstudio/MANIFEST ${DATADIR} "^$")
install_from_manifest(PROGRAMS ${TOPDIR}/zbstudio/MANIFEST-bin-macos ${DATADIR} "^$")
else()
# check the available Lua modules
check_lua_module(wx TRUE)
check_lua_module(socket TRUE)
check_lua_module(copas ${USE_SYSTEM_COPAS})
check_lua_module(luainspect ${USE_SYSTEM_LUAINSPECT})
#check_lua_module(mobdebug ${USE_SYSTEM_MOBDEBUG})
# add user options to select between system-wide and bundled Lua modules
add_system_lua_module_option(copas)
add_system_lua_module_option(luainspect)
#add_system_lua_module_option(mobdebug)
# setup the data directory
set(DATADIR share/zbstudio)
# install IDE shell script
set(IDE_DATADIR "${CMAKE_INSTALL_PREFIX}/${DATADIR}")
configure_file(${TOPDIR}/zbstudio/zbstudio.in "${CMAKE_BINARY_DIR}/zbstudio")
install(PROGRAMS "${CMAKE_BINARY_DIR}/zbstudio" DESTINATION bin)
# install bundled Lua modules
if(NOT USE_SYSTEM_COPAS)
install(DIRECTORY ${TOPDIR}/lualibs/copas ${TOPDIR}/lualibs/coxpcall DESTINATION ${DATADIR}/lualibs)
endif()
if(NOT USE_SYSTEM_LUAINSPECT)
install(DIRECTORY ${TOPDIR}/lualibs/luainspect ${TOPDIR}/lualibs/metalua DESTINATION ${DATADIR}/lualibs)
endif()
if(NOT USE_SYSTEM_MOBDEBUG)
install(DIRECTORY ${TOPDIR}/lualibs/mobdebug DESTINATION ${DATADIR}/lualibs)
endif()
# install .desktop file and hicolor icon theme
install(DIRECTORY ${TOPDIR}/zbstudio/res/icons/ DESTINATION share/icons/hicolor)
install(FILES ${TOPDIR}/zbstudio/res/zbstudio.desktop DESTINATION share/applications)
# install miscellaneous documentation files
install(FILES ${TOPDIR}/CHANGELOG.md ${TOPDIR}/LICENSE ${TOPDIR}/README.md DESTINATION share/doc/zbstudio)
# install files from manifest
install_from_manifest(FILES ${TOPDIR}/zbstudio/MANIFEST ${DATADIR} "^(CHANGELOG.md|LICENSE|README.md)$|^lualibs/")
endif()

Binary file not shown.

42
build/build-dmg.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
set -x
TEMPLATE_DMG=/tmp/ZeroBraneStudio-template.dmg
BUILT_DMG=ZeroBraneStudio.dmg
WKDIR=/tmp/zbs-build
# remove problematic symlink
rm ../zbstudio/ZeroBraneStudio.app/Contents/ZeroBraneStudio
bunzip2 -kf ZeroBraneStudio.dmg.bz2
mv ZeroBraneStudio.dmg $TEMPLATE_DMG
hdiutil attach "${TEMPLATE_DMG}" -noautoopen -quiet -mountpoint "${WKDIR}"
rm -rf "${WKDIR}/ZeroBraneStudio.app"
# copy the app to where it should be
cp -pr "../zbstudio/ZeroBraneStudio.app" "${WKDIR}/ZeroBraneStudio.app"
mkdir "${WKDIR}/ZeroBraneStudio.app/Contents/ZeroBraneStudio"
# only pick the files listed in manifests and 'myprograms' (if exists)
if [[ -d ../myprograms ]]; then MYPROGRAMS=$(cd ..; find myprograms -iname *.lua); fi
(cd ".."; tar cf - $MYPROGRAMS $(< zbstudio/MANIFEST) $(< zbstudio/MANIFEST-bin-macos) | (cd "${WKDIR}/ZeroBraneStudio.app/Contents/ZeroBraneStudio/"; tar xf -))
codesign -s "ZeroBrane LLC" ${WKDIR}/ZeroBraneStudio.app
codesign --signature-size 6400 -s "ZeroBrane LLC" ${WKDIR}/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/lua.app
# clean up
sudo rm -rf "${WKDIR}/.Trashes"
sudo rm -rf "${WKDIR}/.fseventsd"
hdiutil detach "${WKDIR}" -quiet -force
hdiutil convert "${TEMPLATE_DMG}" -quiet -format UDZO -imagekey zlib-level=9 -o "${BUILT_DMG}"
rm -f "${TEMPLATE_DMG}"
cd ../zbstudio/ZeroBraneStudio.app/Contents
ln -s ../../.. ZeroBraneStudio
echo Built ${BUILT_DMG}.

4
build/install-deb.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
sudo apt-get install gdebi
sudo gdebi wxlua*.deb

View File

@@ -4,7 +4,7 @@
// (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 */
#ifdef __MINGW32__
#define _WIN32_WINNT 0x0502
#endif

Binary file not shown.

View File

@@ -1,9 +1,15 @@
local G = ... -- point to the global environment in the script
-- update app configuration to load all tools, specs, and interpreters
G.ide.app.loadfilters.tools = function() return true end
G.ide.app.loadfilters.specs = function() return true end
G.ide.app.loadfilters.interpreters = function() return true end
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"
interpreter = "luadeb"
editor.fontname = "Courier New"
editor.caretline = true

View File

@@ -1,27 +1,53 @@
--[[-- Rename this file to `user.lua` to get loaded
--[[-- Copy required content from this file to `user.lua`
Configuration files are loaded in the following order
1. <application>\config.lua
2. cfg\user.lua
3. -cfg commandline strings
3. ~\.zbstudio\user.lua
4. -cfg commandline strings
--]]--
-- an example of how loaded configuration can be modified from this file
local G = ... -- this now points to the global environment in the script
local luaspec = G.ide.specs['lua']
luaspec.exts[2] = "luaz"
luaspec.keywords[1] = luaspec.keywords[1] .. ' foo'
-- change font size to 12
editor.fontsize = 12 -- this is mapped to ide.config.editor.fontsize
editor.fontname = "Courier New"
filehistorylength = 20 -- this is mapped to ide.config.filehistorylength
-- these changes are going to be mapped to ide.config.editor...
-- change encoding to Cyrillic
editor.fontencoding = G.wx.wxFONTENCODING_ISO8859_5
-- or WinCyrillic
editor.fontencoding = G.wx.wxFONTENCODING_CP1251
outputshell.fontencoding = G.wx.wxFONTENCODING_CP1251
-- specify full path to love2d executable; this is only needed
-- specify full path to love2d *executable*; this is only needed
-- if the game folder and the executable are NOT in the same folder.
path.love2d = 'd:/lua/love/love' -- set the path of love executable
path.love2d = 'd:/lua/love/love'
--]]--
-- specify full path to moai *executable* if it's not in one of PATH folders
path.moai = 'd:/lua/moai/moai'
-- specify full path to gideros *executable* if it's not in one of PATH folders
path.gideros = 'd:/Program Files/Gideros/GiderosPlayer.exe'
-- specify full path to lua interpreter if you need to use your own version
path.lua = 'd:/lua/lua'
-- fix an issue with 0d0d0a line endings in MOAI examples,
-- which may negatively affect breakpoints during debugging
editor.iofilter = "0d0d0aFix"
-- to have 4 spaces when TAB is used in the editor
editor.tabwidth = 4
-- to have TABs stored in the file (to allow mixing tabs and spaces)
editor.usetabs = true
-- to disable wrapping of long lines in the editor
editor.usewrap = false
-- to turn dynamic words on and to start suggestions after 4 characters
acandtip.nodynwords = false
acandtip.startat = 4
-- to automatically open files requested during debugging
editor.autoactivate = true
-- specify a list of MOAI entrypoints
moai = { entrypoints = { "main.lua", "source/main.lua" } }

Binary file not shown.

View File

@@ -1,29 +0,0 @@
local ide = ide
local app = {
loadfilters = {
tools = function(file) return true end,
specs = function(file) return true end,
interpreters = function(file) return true end,
},
postinit = function ()
dofile("estrela/menu_help.lua")
local icon = wx.wxIcon()
icon:LoadFile("estrela/res/estrela.ico",wx.wxBITMAP_TYPE_ICO)
ide.frame:SetIcon(icon)
end,
stringtable = {
editor = "Estrela Editor",
about = "About Estrela Editor",
editormessage = "Estrela Editor Message",
statuswelcome = "Welcome to Estrela Editor",
settingsapp = "EstrelaEditor",
settingsvendor = "LuxiniaDev",
},
}
return app

View File

@@ -1,54 +0,0 @@
<?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>

View File

@@ -1,212 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="estrela_editor"
ProjectGUID="{065C5DC6-EAE4-4A57-9069-39810D816C41}"
RootNamespace="luxinia_glfw"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories=""
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=""
OutputFile="../../estrela.exe"
LinkIncremental="2"
AdditionalLibraryDirectories=""
IgnoreDefaultLibraryNames="libc"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(TargetPath).pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories=""
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=""
OutputFile="../../estrela.exe"
LinkIncremental="1"
AdditionalLibraryDirectories=""
GenerateManifest="true"
IgnoreAllDefaultLibraries="false"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
ProgramDatabaseFile="$(TargetPath).pdb"
SubSystem="2"
OptimizeReferences="0"
EnableCOMDATFolding="0"
RandomizedBaseAddress="0"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Sources"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\win32_starter.c"
>
</File>
</Filter>
<Filter
Name="Ressourcendateien"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\..\res\estrela.rc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,113 +0,0 @@
-- 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 +0,0 @@
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

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

View File

@@ -1,706 +0,0 @@
<?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"
id="svg2178"
sodipodi:version="0.32"
inkscape:version="0.46+devel"
width="146"
height="146"
version="1.0"
sodipodi:docname="idelogo.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="36.990002"
inkscape:export-ydpi="36.990002">
<metadata
id="metadata2183">
<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>
<defs
id="defs2181">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 73 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="146 : 73 : 1"
inkscape:persp3d-origin="73 : 48.666667 : 1"
id="perspective86" />
<linearGradient
id="linearGradient4596">
<stop
style="stop-color:#5151ac;stop-opacity:1;"
offset="0"
id="stop4598" />
<stop
style="stop-color:#000055;stop-opacity:1;"
offset="1"
id="stop4600" />
</linearGradient>
<linearGradient
id="linearGradient4588">
<stop
style="stop-color:#62769d;stop-opacity:1;"
offset="0"
id="stop4590" />
<stop
style="stop-color:#ff0000;stop-opacity:0;"
offset="1"
id="stop4592" />
</linearGradient>
<linearGradient
id="linearGradient5185">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5187" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop5189" />
</linearGradient>
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#0d0d3f;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
id="stop3702"
offset="0.33628318"
style="stop-color:#12127a;stop-opacity:1;" />
<stop
style="stop-color:#3e3e80;stop-opacity:1"
offset="1"
id="stop2241" />
</linearGradient>
<filter
inkscape:collect="always"
x="-0.13963953"
width="1.279279"
y="-0.14821953"
height="1.2964391"
id="filter3840">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="6.5521521"
id="feGaussianBlur3842" />
</filter>
<filter
inkscape:collect="always"
id="filter6278">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.214876"
id="feGaussianBlur6280" />
</filter>
<mask
maskUnits="userSpaceOnUse"
id="mask6290">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
id="rect6292"
width="128"
height="128"
x="0"
y="-8.5265128e-014"
ry="13.206349"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
</mask>
<mask
maskUnits="userSpaceOnUse"
id="mask6295">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
id="rect6297"
width="128"
height="128"
x="0"
y="-8.5265128e-014"
ry="13.206349"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
</mask>
<filter
inkscape:collect="always"
id="filter6316">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.6425"
id="feGaussianBlur6318" />
</filter>
<filter
inkscape:collect="always"
x="-0.096865753"
width="1.1937315"
y="-0.13864499"
height="1.27729"
id="filter6400">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="5.3595156"
id="feGaussianBlur6402" />
</filter>
<filter
inkscape:collect="always"
x="-0.091426807"
width="1.1828536"
y="-0.21857401"
height="1.437148"
id="filter6510">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="4.3854492"
id="feGaussianBlur6512" />
</filter>
<filter
inkscape:collect="always"
x="-0.065166176"
width="1.1303324"
y="-0.14160248"
height="1.283205"
id="filter6588">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="3.0129427"
id="feGaussianBlur6590" />
</filter>
<filter
inkscape:collect="always"
x="-0.10324995"
width="1.2064999"
y="-0.19036609"
height="1.3807322"
id="filter6628">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="5.1083162"
id="feGaussianBlur6630" />
</filter>
<filter
inkscape:collect="always"
x="-0.66312472"
width="2.3262494"
y="-0.13057123"
height="1.2611425"
id="filter6690">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.059841"
id="feGaussianBlur6692" />
</filter>
<filter
inkscape:collect="always"
x="-0.75290101"
width="2.505802"
y="-0.11094242"
height="1.2218848"
id="filter6776">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.1015794"
id="feGaussianBlur6778" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4596"
id="linearGradient4602"
x1="63.296463"
y1="141"
x2="63.296463"
y2="-5.0469656"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(13.788582,2.1213203)" />
<filter
inkscape:collect="always"
id="filter3377"
x="-0.1015625"
width="1.203125"
y="-0.087053571"
height="1.1741071">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.7929688"
id="feGaussianBlur3379" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4596"
id="linearGradient3381"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.89166667,0,0,0.89166667,19.638582,9.162987)"
x1="63.296463"
y1="141"
x2="63.296463"
y2="-5.0469656" />
<filter
inkscape:collect="always"
id="filter3419"
x="-0.10422356"
width="1.2084471"
y="-0.093260085"
height="1.1865202">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="4.0324593"
id="feGaussianBlur3421" />
</filter>
<filter
inkscape:collect="always"
id="filter3425"
x="-0.12187501"
width="1.24375"
y="-0.10446428"
height="1.2089286">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.9431967"
id="feGaussianBlur3427" />
</filter>
<filter
inkscape:collect="always"
id="filter3451"
x="-0.1187245"
width="1.237449"
y="-0.12130321"
height="1.2426064">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="7.6549135"
id="feGaussianBlur3453" />
</filter>
<filter
height="1.3165256"
y="-0.15826278"
width="1.3097967"
x="-0.15489837"
id="filter3467"
inkscape:collect="always">
<feGaussianBlur
id="feGaussianBlur3469"
stdDeviation="9.98727"
inkscape:collect="always" />
</filter>
<filter
inkscape:collect="always"
id="filter3483"
x="-0.27362286"
width="1.5472457"
y="-0.27956598"
height="1.559132">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="17.642184"
id="feGaussianBlur3485" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4596"
id="linearGradient3497"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9558335,0,0,0.9558335,16.173573,4.9921428)"
x1="63.296463"
y1="141"
x2="63.296463"
y2="-5.0469656" />
<filter
inkscape:collect="always"
id="filter3499"
x="-0.059528317"
width="1.1190566"
y="-0.10133829"
height="1.2026766">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.667066"
id="feGaussianBlur3501" />
</filter>
<filter
inkscape:collect="always"
id="filter3509"
x="-0.0309375"
width="1.061875"
y="-2.0109374"
height="5.0218749">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.3472814"
id="feGaussianBlur3511" />
</filter>
</defs>
<sodipodi:namedview
inkscape:window-height="719"
inkscape:window-width="1024"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
inkscape:zoom="1"
inkscape:cx="74.122861"
inkscape:cy="61.737644"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:current-layer="layer2"
showborder="true"
inkscape:showpageshadow="false"
showgrid="false" />
<g
inkscape:groupmode="layer"
id="layer1"
style="opacity:0.34615383;display:none"
transform="translate(6,5)">
<image
xlink:href="c:\temp\luxlogo.png"
sodipodi:absref="c:\temp\luxlogo.png"
width="128"
height="128"
id="image2185"
x="0"
y="0" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
style="display:inline"
transform="translate(6,5)">
<rect
y="4.7046537"
x="14.288583"
height="124.83334"
width="107"
id="rect3423"
style="opacity:1;fill:url(#linearGradient3381);fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter3425)"
transform="matrix(1.0719628,0,0,1.0719628,-4.8782561,-4.8302384)"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587" />
<rect
style="opacity:1;fill:url(#linearGradient3497);fill-opacity:1;fill-rule:evenodd;stroke:none"
id="rect4586"
width="114.70002"
height="133.8167"
x="10.438573"
y="0.21297537"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587" />
<g
id="g3227"
transform="matrix(0.36255137,0,0,0.36255137,43.548278,21.953343)"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587">
<g
id="g2599"
transform="matrix(0.73621364,0,0,0.73621364,15.540372,-36.334537)">
<path
sodipodi:nodetypes="csscssc"
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 19.37247,3.0246539 C -16.608082,20.649318 -41.404147,57.657551 -41.404147,100.40056 c 0,59.80351 48.5400427,108.34356 108.343566,108.34356 40.892381,0 76.510811,-22.69984 94.952061,-56.1714 -15.59146,8.96867 -33.63299,14.11858 -52.89924,14.11858 C 50.276054,166.69131 2.5877015,119.06356 2.5877015,60.347369 c 0,-21.110232 6.1656802,-40.772917 16.7847685,-57.3227151 z"
id="path2193"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none"
d="m 46.59366,22.910342 11.81888,0 9.19246,-10.505671 5.252837,14.445294 11.818878,1.969814 -11.818878,9.192463 0.656603,13.132087 -11.81888,-9.849067 -11.818877,3.939627 4.59623,-11.818877 -7.879253,-10.50567 z"
id="path2205"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none"
d="m 113.62886,82.661339 13.7887,-14.445296 -5.25284,-19.69813 18.38488,8.535854 15.10187,-10.505668 -1.9698,19.698131 15.1019,12.475482 -19.04153,4.596232 -7.87924,15.758505 -8.53582,-16.41511 -19.69812,0 z"
id="path2207"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline"
d="m 84.710796,92.101734 3.261705,-2.372978 0.427566,-4.744945 4.349957,2.931871 3.6572,-1.829365 -1.416054,4.909864 2.817849,3.492287 -5.239188,-0.345107 -2.470713,3.460214 -1.104536,-4.184532 -4.283786,-1.317309 z"
id="path2209"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
</g>
</g>
<text
xml:space="preserve"
style="font-size:29.89867401px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Palatino Linotype;-inkscape-font-specification:Palatino Linotype"
x="66.859642"
y="95.922615"
id="text2585"
sodipodi:linespacing="100%"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587"><tspan
sodipodi:role="line"
id="tspan2587"
x="66.859642"
y="95.922615">Estrela</tspan><tspan
sodipodi:role="line"
x="66.859642"
y="125.82129"
id="tspan2589">Editor</tspan></text>
<rect
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;"
id="rect3383"
width="104.51637"
height="1.6079443"
x="15.530396"
y="99.936134"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587" />
<g
transform="matrix(0.36255137,0,0,0.36255137,43.548278,21.953343)"
id="g3439"
style="filter:url(#filter3451)"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587">
<g
transform="matrix(0.73621364,0,0,0.73621364,15.540372,-36.334537)"
id="g3441">
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3443"
d="M 19.37247,3.0246539 C -16.608082,20.649318 -41.404147,57.657551 -41.404147,100.40056 c 0,59.80351 48.5400427,108.34356 108.343566,108.34356 40.892381,0 76.510811,-22.69984 94.952061,-56.1714 -15.59146,8.96867 -33.63299,14.11858 -52.89924,14.11858 C 50.276054,166.69131 2.5877015,119.06356 2.5877015,60.347369 c 0,-21.110232 6.1656802,-40.772917 16.7847685,-57.3227151 z"
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
sodipodi:nodetypes="csscssc" />
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3445"
d="m 46.59366,22.910342 11.81888,0 9.19246,-10.505671 5.252837,14.445294 11.818878,1.969814 -11.818878,9.192463 0.656603,13.132087 -11.81888,-9.849067 -11.818877,3.939627 4.59623,-11.818877 -7.879253,-10.50567 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none" />
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3447"
d="m 113.62886,82.661339 13.7887,-14.445296 -5.25284,-19.69813 18.38488,8.535854 15.10187,-10.505668 -1.9698,19.698131 15.1019,12.475482 -19.04153,4.596232 -7.87924,15.758505 -8.53582,-16.41511 -19.69812,0 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none" />
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3449"
d="m 84.710796,92.101734 3.261705,-2.372978 0.427566,-4.744945 4.349957,2.931871 3.6572,-1.829365 -1.416054,4.909864 2.817849,3.492287 -5.239188,-0.345107 -2.470713,3.460214 -1.104536,-4.184532 -4.283786,-1.317309 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline" />
</g>
</g>
<g
style="filter:url(#filter3467)"
id="g3455"
transform="matrix(0.36255137,0,0,0.36255137,43.548278,21.953343)"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587">
<g
id="g3457"
transform="matrix(0.73621364,0,0,0.73621364,15.540372,-36.334537)">
<path
sodipodi:nodetypes="csscssc"
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 19.37247,3.0246539 C -16.608082,20.649318 -41.404147,57.657551 -41.404147,100.40056 c 0,59.80351 48.5400427,108.34356 108.343566,108.34356 40.892381,0 76.510811,-22.69984 94.952061,-56.1714 -15.59146,8.96867 -33.63299,14.11858 -52.89924,14.11858 C 50.276054,166.69131 2.5877015,119.06356 2.5877015,60.347369 c 0,-21.110232 6.1656802,-40.772917 16.7847685,-57.3227151 z"
id="path3459"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none"
d="m 46.59366,22.910342 11.81888,0 9.19246,-10.505671 5.252837,14.445294 11.818878,1.969814 -11.818878,9.192463 0.656603,13.132087 -11.81888,-9.849067 -11.818877,3.939627 4.59623,-11.818877 -7.879253,-10.50567 z"
id="path3461"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none"
d="m 113.62886,82.661339 13.7887,-14.445296 -5.25284,-19.69813 18.38488,8.535854 15.10187,-10.505668 -1.9698,19.698131 15.1019,12.475482 -19.04153,4.596232 -7.87924,15.758505 -8.53582,-16.41511 -19.69812,0 z"
id="path3463"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline"
d="m 84.710796,92.101734 3.261705,-2.372978 0.427566,-4.744945 4.349957,2.931871 3.6572,-1.829365 -1.416054,4.909864 2.817849,3.492287 -5.239188,-0.345107 -2.470713,3.460214 -1.104536,-4.184532 -4.283786,-1.317309 z"
id="path3465"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
</g>
</g>
<g
transform="matrix(0.36255137,0,0,0.36255137,43.548278,21.953343)"
id="g3471"
style="filter:url(#filter3483)"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587">
<g
transform="matrix(0.73621364,0,0,0.73621364,15.540372,-36.334537)"
id="g3473">
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3475"
d="M 19.37247,3.0246539 C -16.608082,20.649318 -41.404147,57.657551 -41.404147,100.40056 c 0,59.80351 48.5400427,108.34356 108.343566,108.34356 40.892381,0 76.510811,-22.69984 94.952061,-56.1714 -15.59146,8.96867 -33.63299,14.11858 -52.89924,14.11858 C 50.276054,166.69131 2.5877015,119.06356 2.5877015,60.347369 c 0,-21.110232 6.1656802,-40.772917 16.7847685,-57.3227151 z"
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
sodipodi:nodetypes="csscssc" />
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3477"
d="m 46.59366,22.910342 11.81888,0 9.19246,-10.505671 5.252837,14.445294 11.818878,1.969814 -11.818878,9.192463 0.656603,13.132087 -11.81888,-9.849067 -11.818877,3.939627 4.59623,-11.818877 -7.879253,-10.50567 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none" />
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3479"
d="m 113.62886,82.661339 13.7887,-14.445296 -5.25284,-19.69813 18.38488,8.535854 15.10187,-10.505668 -1.9698,19.698131 15.1019,12.475482 -19.04153,4.596232 -7.87924,15.758505 -8.53582,-16.41511 -19.69812,0 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none" />
<path
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="c:\temp\logotest"
id="path3481"
d="m 84.710796,92.101734 3.261705,-2.372978 0.427566,-4.744945 4.349957,2.931871 3.6572,-1.829365 -1.416054,4.909864 2.817849,3.492287 -5.239188,-0.345107 -2.470713,3.460214 -1.104536,-4.184532 -4.283786,-1.317309 z"
style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline" />
</g>
</g>
<text
sodipodi:linespacing="100%"
id="text3487"
y="93.989136"
x="66.922005"
style="font-size:27.89152144999999900px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:100%;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Palatino Linotype;-inkscape-font-specification:Palatino Linotype;filter:url(#filter3499);opacity:1"
xml:space="preserve"
transform="matrix(1.0719628,0,0,1.0719628,-4.8782561,-4.8302384)"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587"><tspan
y="93.989136"
x="66.922005"
id="tspan3489"
sodipodi:role="line">Estrela</tspan><tspan
id="tspan3491"
y="121.88066"
x="66.922005"
sodipodi:role="line">Editor</tspan></text>
<rect
y="99.936134"
x="15.530396"
height="1.6079443"
width="104.51637"
id="rect3507"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3509)"
inkscape:export-xdpi="181.25587"
inkscape:export-ydpi="181.25587"
inkscape:export-filename="D:\dev\c\tools\wxide\res\estrela.png" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="uninstall"
style="opacity:0.87179488;display:none">
<path
style="opacity:0.90909095;fill:#ff0000;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6628)"
d="M 14,129.5 C 14.336023,78.681123 10.223888,102.29852 28,126 C 30.459675,129.27957 31.666667,118.66667 33.5,115 C 34.280157,113.43969 60.370804,77.40912 51.5,105.5 C 50.690734,108.06268 52.166667,110.83333 52.5,113.5 C 53.627928,122.52343 58.069819,95.430181 64.5,89 C 77.260993,76.239007 72.034223,53.027263 77.5,84 C 81.920823,109.05133 73.638657,88.715336 86.5,85.5 C 115.4259,78.268526 69.170508,123.74712 95.5,104 C 128.78796,79.03403 116,64.235283 116,113.5 C 116,117.62311 118,105.5 119,101.5 C 121.13437,92.962501 126.33333,117.5 130,125.5 C 130.87839,127.41648 131.33333,121.5 132,119.5 C 133.424,115.228 131.66667,128.5 131.5,133"
id="path6594"
transform="matrix(1,0,0,1.6987359,0,-92.931881)" />
<path
style="opacity:0.81404952;fill:#ff0000;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6400)"
d="M 9.5,127 C 9.3333333,127 9.1666667,127 9,127 C 5.1450826,127 5,115.26288 5,113 C 5,108.88399 4.5,104.31286 4.5,100 C 4.5,90.729345 9.3911698,86.181384 14,78.5 C 16.525846,74.290257 21.294069,70.176551 23.5,66.5 C 24.010025,65.649958 19.12736,72.1816 18,75 C 16.175585,79.561038 16.938863,85.255452 18,89.5 C 19.417577,95.17031 20.550245,97.050245 24.5,101 C 27.204082,103.70408 28.564013,105.87197 30.5,102 C 32.717007,97.565986 32.821681,88.213274 34,83.5 C 36.21779,74.628838 33.5,60.648945 33.5,51.5 C 33.5,51.084452 43.746631,33.513476 40.5,46.5 C 37.526688,58.393246 42.328731,65.743097 48.5,75 C 57.52302,88.53453 51.657407,61.728395 65.5,52.5 C 75.452786,45.864809 69.5,56.563364 69.5,63.5 C 69.5,97.806907 73.726993,52.544988 80,63 C 104.74932,104.24887 98.5,68.637999 98.5,48 C 98.5,43.548461 105.9654,52.637713 112,63.5 C 131.67898,98.922169 101.60755,95.392446 125.5,71.5 C 131.39727,65.602731 126.5,88.160003 126.5,96.5 C 126.5,103.50198 126.00977,110.56839 127,117.5 C 127.95497,124.1848 139.22574,81.791102 137,108.5 C 136.48054,114.73353 136,120.29333 136,126.5 C 136,131.40801 136.45529,134 131,134 C 124.83333,134 118.66667,134 112.5,134 C 106.66667,134 100.83333,134 95,134 C 87.666667,134 80.333333,134 73,134 C 59.815481,134 46.676285,134.5 33.5,134.5 C 29,134.5 24.5,134.5 20,134.5 C 17.560468,134.5 15.299427,130.79943 14.5,130 C 12.881524,128.38152 11.876707,127.47534 9.5,127 z "
id="path6360" />
<path
style="opacity:0.7892562;fill:#ffff00;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6510)"
d="M 18,133 C 17.666667,128.16667 17.333333,123.33333 17,118.5 C 16.12131,105.759 12.392768,108.83915 20.5,121 C 26.928487,130.64273 27.121348,121.87865 34.5,114.5 C 40.14466,108.85534 28.809035,133.69097 46.5,116 C 69.437036,93.062964 57.251105,73.257733 62,106.5 C 62.141421,107.48995 62,108.5 62,109.5 C 62,116.18839 65.961948,99.019026 77,93.5 C 84.016889,89.991555 79.782388,94.911939 82,106 C 84.489642,118.44821 104.6601,90.259847 107.5,86 C 108.99663,83.755053 110.63899,106.80503 109.5,112.5 C 107.85301,120.73495 118.5,80.922943 118.5,109 C 118.5,136.59389 130.5,113.97346 130.5,123.5 C 130.5,126.59415 130.47115,131.64424 130,134"
id="path6404" />
<path
style="opacity:0.47107436;fill:#ffff00;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6588)"
d="M 23,129.5 C 23,132.18128 23.707157,117.52684 20.5,105.5 C 18.755021,98.956331 22.5,82.949866 22.5,98 C 22.5,101.13302 26.815124,126.46219 32,113.5 C 37.373635,100.06591 49.880495,78.048761 46.5,86.5 C 45.909734,87.975665 37.7573,136.7281 47.5,107.5 C 47.857122,106.42863 51.414918,124.58508 58,118 C 68.456644,107.54336 70,50.914151 70,100.5 C 70,131.81187 78.663987,96.334003 94,92.5 C 101.72907,90.567732 88.111037,107.55652 87.5,115.5 C 87.384247,117.00479 87.833333,118.5 88,120 C 89.236992,131.13293 100.98113,100.50944 111,95.5 C 121.54122,90.229389 111.5,106.05757 111.5,112 C 111.5,113.79505 112.83333,115.33333 113.5,117 C 114.6363,119.84076 116.5,111.66667 118,109 C 127.18664,92.668192 120.25003,138.81244 129.5,118 C 129.81325,117.2952 131,128.12728 131,131.5"
id="path6514"
transform="matrix(1,0,0,1.558102,0,-73.390417)" />
<path
style="opacity:0.73966944;fill:#ffa500;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6690)"
d="M 98.5,75 C 103.15482,68.57691 90.320092,24.848129 101.5,40.5 C 102.88049,42.432688 106.61962,69.035283 102,72.5 C 100.85302,73.360232 99.666667,74.166667 98.5,75 z "
id="path6632" />
<path
style="opacity:0.94214872;fill:#ffba00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6776)"
d="M 51,68 C 45.233621,73.766379 50.387595,36.449622 50.5,36 C 53.115126,25.539495 57.714899,13.962753 49.5,34.5 C 44.403872,47.24032 50.084923,57.754768 53.5,68 C 53.763523,68.790569 51.833333,68 51,68 z "
id="path6696" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="border"
style="display:none">
<rect
transform="translate(6,5)"
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline;filter:url(#filter6316)"
id="rect6282"
width="128"
height="128"
x="0"
y="-8.5265128e-014"
ry="13.206349"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300" />
<rect
transform="translate(6,5)"
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline;filter:url(#filter6278)"
id="rect4190"
width="128"
height="128"
x="0"
y="-8.5265128e-014"
ry="13.206349"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300"
mask="url(#mask6290)" />
<rect
transform="translate(6,5)"
style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
id="rect5203"
width="128"
height="128"
x="0"
y="-8.5265128e-014"
ry="13.206349"
inkscape:export-filename="c:\temp\logotest"
inkscape:export-xdpi="300"
inkscape:export-ydpi="300"
mask="url(#mask6295)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -1,132 +0,0 @@
<?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: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -1,12 +0,0 @@
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,
}

121
interpreters/gideros.lua Normal file
View File

@@ -0,0 +1,121 @@
local gideros
local win = ide.osname == "Windows"
local mac = ide.osname == "Macintosh"
return {
name = "Gideros",
description = "Gideros mobile platform",
api = {"baselib", "gideros"},
frun = function(self,wfilename,rundebug)
gideros = gideros or ide.config.path.gideros -- check if the path is configured
if not gideros then
local sep = win and ';' or ':'
local default =
win and ([[C:\Program Files\Gideros]]..sep..[[D:\Program Files\Gideros]]..sep)
or mac and ('/Applications/Gideros Studio/Gideros Player.app/Contents/MacOS'..sep)
or ''
local path = default
..(os.getenv('PATH') or '')..sep
..(os.getenv('HOME') and os.getenv('HOME') .. '/bin' or '')
local paths = {}
for p in path:gmatch("[^"..sep.."]+") do
gideros = gideros or GetFullPathIfExists(p, win and 'GiderosPlayer.exe' or 'Gideros Player')
table.insert(paths, p)
end
if not gideros then
DisplayOutput("Can't find gideros executable in any of the folders in PATH: "
..table.concat(paths, ", ").."\n")
return
end
end
if gideros and not wx.wxFileName(gideros):FileExists() then
DisplayOutput("Can't find the specified gideros executable '"..gideros.."'.\n")
return
end
local giderostools = wx.wxFileName.DirName(wx.wxFileName(gideros)
:GetPath(wx.wxPATH_GET_VOLUME)
..(win and '/Tools' or '/../../../Gideros Studio.app/Contents/Tools'))
giderostools:Normalize()
local giderospath = giderostools:GetPath(wx.wxPATH_GET_VOLUME)
local gdrbridge = GetFullPathIfExists(giderospath, win and 'gdrbridge.exe' or 'gdrbridge')
if not gdrbridge then
DisplayOutput("Can't find gideros bridge executable in '"..giderospath.."'.\n")
return
end
-- find *.gproj file in the project directory
local file
for _, proj in ipairs(FileSysGet(self:fworkdir(wfilename).."/*.gproj", wx.wxFILE)) do
if file then
DisplayOutput("Found multiple .gproj files in the project directory; ignored '"..proj.."'\n")
end
file = proj
end
if not file then
DisplayOutput("Can't find gideros project file in the project directory.\n")
return
end
if rundebug then DebuggerAttachDefault() end
local cmd = ('"%s"'):format(gideros)
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
local pid = CommandLineRun(cmd,self:fworkdir(wfilename),not mac,true,nil,nil,
function() ide.debugger.pid = nil end)
do
DisplayOutput("Starting the player and waiting for the bridge to connect at '"..gdrbridge.."'.\n")
local cmd = ('"%s" %s'):format(gdrbridge, 'isconnected')
local attempts, connected = 12
for _ = 1, attempts do
local proc = wx.wxProcess()
proc:Redirect()
proc:Connect(wx.wxEVT_END_PROCESS, function(event) proc = nil end)
local bid = wx.wxExecute(cmd, wx.wxEXEC_ASYNC + wx.wxEXEC_MAKE_GROUP_LEADER, proc)
if not bid or bid == -1 or bid == 0 then
DisplayOutput(("Program unable to run as '%s'\n"):format(cmd))
return
end
local streamin = proc:GetInputStream()
for _ = 1, 20 do
if streamin:CanRead() then
connected = tonumber(streamin:Read(4096)) == 1
break end
wx.wxSafeYield()
wx.wxWakeUpIdle()
wx.wxMilliSleep(250)
end
if connected then break end
if connected == nil and proc then
wx.wxProcess.Kill(bid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
wx.wxProcess.Kill(pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
DisplayOutput("Couldn't connect to the player. Try again or check starting the player and the bridge manually.\n")
return
end
end
if not connected then
wx.wxProcess.Kill(pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
DisplayOutput("Couldn't connect after "..attempts.." attempts. Try again or check starting the player manually.\n")
return
end
DisplayOutput("Starting project file '"..file.."'.\n")
cmd = ('"%s" %s "%s"'):format(gdrbridge, 'play', file)
wx.wxExecute(cmd, wx.wxEXEC_ASYNC)
end
return pid
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,
scratchextloop = true,
}

View File

@@ -1,14 +1,44 @@
local love2d
local win = ide.osname == "Windows"
local mac = ide.osname == "Macintosh"
return {
name = "Love2d",
description = "Love2d game engine",
api = {"baselib", "love2d"},
frun = function(self,wfilename,rundebug)
love2d = love2d or ide.config.path.love2d -- check if the path is configured
if not love2d then
local sep = win and ';' or ':'
local default =
win and ([[C:\Program Files\love]]..sep..[[D:\Program Files\love]]..sep)
or mac and ('/Applications/love.app/Contents/MacOS'..sep)
or ''
local path = default
..(os.getenv('PATH') or '')..sep
..(GetPathWithSep(self:fworkdir(wfilename)))..sep
..(os.getenv('HOME') and GetPathWithSep(os.getenv('HOME'))..'bin' or '')
local paths = {}
for p in path:gmatch("[^"..sep.."]+") do
love2d = love2d or GetFullPathIfExists(p, win and 'love.exe' or 'love')
table.insert(paths, p)
end
if not love2d then
DisplayOutput("Can't find love2d executable in any of the following folders: "
..table.concat(paths, ", ").."\n")
return
end
end
if not GetFullPathIfExists(self:fworkdir(wfilename), 'main.lua') then
DisplayOutput("Can't find 'main.lua' file in the current project folder.\n")
return
end
if rundebug then DebuggerAttachDefault() end
local love2d = ide.config.path.love2d
or wx.wxFileName(self:fprojdir(wfilename)):GetPath(wx.wxPATH_GET_VOLUME)
.. '/love'
local cmd = string.gsub(love2d, "\\","/") .. ' "' .. self:fprojdir(wfilename) .. '"'
.. (rundebug and ' -debug' or '')
local cmd = ('"%s" "%s"%s'):format(love2d,
self:fworkdir(wfilename), rundebug and ' -debug' or '')
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
function() ide.debugger.pid = nil end)
@@ -16,12 +46,10 @@ return {
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)
fworkdir = function(self,wfilename)
return ide.config.path.projectdir or wfilename:GetPath(wx.wxPATH_GET_VOLUME)
end,
hasdebugger = true,
fattachdebug = function(self)
DebuggerAttachDefault()
end,
fattachdebug = function(self) DebuggerAttachDefault() end,
scratchextloop = true,
}

View File

@@ -1,23 +1,40 @@
local exe
local function exePath()
local mainpath = ide.editorFilename:gsub("[^/\\]+$","")
local macExe = mainpath..'bin/lua.app/Contents/MacOS/lua'
return ide.config.path.lua or
(ide.osname == "Windows" and mainpath..[[bin\lua.exe]]
or (ide.osname == "Unix" and [[lua]]) -- using installed lua
or (wx.wxFileExists(macExe) and macExe or mainpath..[[bin/lua]]))
end
return {
name = "Lua with Debugger",
name = "Lua",
description = "Lua interpreter with debugger",
api = {"wxwidgets","baselib"},
frun = function(self,wfilename,rundebug)
local mainpath = string.gsub(ide.editorFilename:gsub("[^/\\]+$",""),"\\","/")
local filepath = string.gsub(wfilename:GetFullPath(), "\\","/")
exe = exe or exePath()
local filepath = wfilename:GetFullPath()
local script
if rundebug then
DebuggerAttachDefault()
script = (
"package.path=package.path..';"..mainpath.."lualibs/?/?.lua;"..mainpath.."lualibs/?.lua';"..
"package.cpath=package.cpath..';"..mainpath.."bin/clibs/?.dll';"..
rundebug
)
script = rundebug
else
script = ([[dofile '%s']]):format(filepath)
-- if running on Windows and can't open the file, this may mean that
-- the file path includes unicode characters that need special handling
local fh = io.open(filepath, "r")
if fh then fh:close() end
if ide.osname == 'Windows' and pcall(require, "winapi")
and wfilename:FileExists() and not fh then
winapi.set_encoding(winapi.CP_UTF8)
filepath = winapi.short_path(filepath)
end
script = ('dofile [[%s]]'):format(filepath)
end
local code = ([[xpcall(function() io.stdout:setvbuf('no'); %s end,function(err) print(debug.traceback(err)) end)]]):format(script)
local cmd = '"'..mainpath..'bin/lua" -e "'..code..'"'
local cmd = '"'..exe..'" -e "'..code..'"'
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
function() ide.debugger.pid = nil end)
@@ -26,11 +43,9 @@ return {
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
end,
fworkdir = function (self,wfilename)
return ide.config.path.projectdir
or wfilename:GetPath(wx.wxPATH_GET_VOLUME)
return ide.config.path.projectdir or wfilename:GetPath(wx.wxPATH_GET_VOLUME)
end,
hasdebugger = true,
fattachdebug = function(self)
DebuggerAttachDefault()
end,
fattachdebug = function(self) DebuggerAttachDefault() end,
scratchextloop = false,
}

View File

@@ -77,6 +77,7 @@ return {
if not rundebug then
local client = self:finitclient()
ShellSupportRemote(client,self:fuid(wfilename))
pid = nil
end
return pid

88
interpreters/moai.lua Normal file
View File

@@ -0,0 +1,88 @@
local moai
local win = ide.osname == "Windows"
return {
name = "Moai",
description = "Moai mobile platform",
api = {"baselib", "moai"},
frun = function(self,wfilename,rundebug)
moai = moai or ide.config.path.moai -- check if the path is configured
if not moai then
local sep = win and ';' or ':'
local default =
win and ([[C:\Program Files\moai]]..sep..[[D:\Program Files\moai]]..sep)
or ''
local path = default
..(os.getenv('PATH') or '')..sep
..(os.getenv('MOAI_BIN') or '')..sep
..(os.getenv('HOME') and os.getenv('HOME') .. '/bin' or '')
local paths = {}
for p in path:gmatch("[^"..sep.."]+") do
moai = moai or GetFullPathIfExists(p, win and 'moai.exe' or 'moai')
table.insert(paths, p)
end
if not moai then
DisplayOutput("Can't find moai executable in any of the folders in PATH or MOAI_BIN: "
..table.concat(paths, ", ").."\n")
return
end
end
local file
local epoints = ide.config.moai and ide.config.moai.entrypoints
if epoints then
epoints = type(epoints) == 'table' and epoints or {epoints}
for _,entry in pairs(epoints) do
file = GetFullPathIfExists(self:fworkdir(wfilename), entry)
if file then break end
end
if not file then
DisplayOutput("Can't find any of the specified entry points ("
..table.concat(epoints, ", ")
..") in the current project; continuing with the current file...\n")
end
end
if rundebug then
-- start running the application right away
DebuggerAttachDefault({runstart=true, startwith = file})
local code = (
[[xpcall(function()
io.stdout:setvbuf('no')
require("mobdebug").moai() -- enable debugging for coroutines
%s
end, function(err) print(debug.traceback(err)) end)]]):format(rundebug)
local tmpfile = wx.wxFileName()
tmpfile:AssignTempFileName(".")
file = tmpfile:GetFullPath()
local f = io.open(file, "w")
if not f then
DisplayOutput("Can't open temporary file '"..file.."' for writing\n")
return
end
f:write(code)
f:close()
end
file = file or wfilename:GetFullPath()
-- try to find a config file: (1) MOAI_CONFIG, (2) project directory,
-- (3) folder with the current file, (4) folder with moai executable
local config = GetFullPathIfExists(os.getenv('MOAI_CONFIG') or self:fworkdir(wfilename), 'config.lua')
or GetFullPathIfExists(wfilename:GetPath(wx.wxPATH_GET_VOLUME), 'config.lua')
or GetFullPathIfExists(wx.wxFileName(moai):GetPath(wx.wxPATH_GET_VOLUME), 'config.lua')
local cmd = config and ('"%s" "%s" "%s"'):format(moai, config, file)
or ('"%s" "%s"'):format(moai, file)
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
function() ide.debugger.pid = nil if rundebug then wx.wxRemoveFile(file) end end)
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,12 +1,12 @@
--
-- MobDebug 0.467
-- MobDebug 0.502
-- Copyright 2011-12 Paul Kulchenko
-- Based on RemDebug 1.0 Copyright Kepler Project 2005
--
local mobdebug = {
_NAME = "mobdebug",
_VERSION = 0.467,
_VERSION = 0.502,
_COPYRIGHT = "Paul Kulchenko",
_DESCRIPTION = "Mobile Remote Debugger for the Lua programming language",
port = 8171
@@ -23,7 +23,25 @@ local require = require
local setmetatable = setmetatable
local string = string
local tonumber = tonumber
local mosync = mosync
-- if strict.lua is used, then need to avoid referencing some global
-- variables, as they can be undefined;
-- use rawget to to avoid complaints from strict.lua at run-time.
-- it's safe to do the initialization here as all these variables
-- should get defined values (of any) before the debugging starts.
-- there is also global 'wx' variable, which is checked as part of
-- the debug loop as 'wx' can be loaded at any time during debugging.
local genv = _G or _ENV
local jit = rawget(genv, "jit")
local mosync = rawget(genv, "mosync")
local MOAICoroutine = rawget(genv, "MOAICoroutine")
-- check for OS and convert file names to lower case on windows
-- (its file system is case insensitive, but case preserving), as setting a
-- breakpoint on x:\Foo.lua will not work if the file was loaded as X:\foo.lua.
local iswindows = os.getenv('WINDIR')
or (os.getenv('OS') or ''):match('[Ww]indows')
or pcall(require, "winapi")
-- this is a socket class that implements maConnect interface
local function socketMobileLua()
@@ -161,6 +179,12 @@ if mosync and mosync.EventMonitor then
mosync.EventMonitor.RunEventLoop = function(self) end
end
-- turn jit off based on Mike Pall's comment in this discussion:
-- http://www.freelists.org/post/luajit/Debug-hooks-and-JIT,2
-- "You need to turn it off at the start if you plan to receive
-- reliable hook calls at any later point in time."
if jit and jit.off then jit.off() end
local socket = mosync and socketMobileLua() or (require "socket")
local debug = require "debug"
@@ -180,15 +204,18 @@ local step_over = false
local step_level = 0
local stack_level = 0
local server
local rset
local basedir = ""
local deferror = "execution aborted at default debugee"
local debugee = function ()
local a = 1
for _ = 1, 10 do a = a + 1 end
error(deferror)
end
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
local serpent = (function() ---- include Serpent module for serialization
local n, v = "serpent", 0.15 -- (C) 2012 Paul Kulchenko; MIT License
local n, v = "serpent", 0.18 -- (C) 2012 Paul Kulchenko; MIT License
local c, d = "Paul Kulchenko", "Serializer and pretty printer of Lua data types"
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
local badtype = {thread = true, userdata = true}
@@ -206,14 +233,14 @@ local function s(t, opts)
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
local comm = opts.comment and (tonumber(opts.comment) or math.huge)
local seen, sref, syms, symn = {}, {}, {}, 0
local function gensym(val) return tostring(val):gsub("[^%w]",""):gsub("(%d%w+)",
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return syms[s] end) end
local function gensym(val) return (tostring(val):gsub("[^%w]",""):gsub("(%d%w+)",
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return syms[s] end)) end
local function safestr(s) return type(s) == "number" and (huge and snum[tostring(s)] or s)
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
local function comment(s,l) return comm and (l or 0) < comm and ' --[['..tostring(s)..']]' or '' end
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
and safestr(tostring(s))..comment('err',l) or error("Can't serialize "..tostring(s)) end
and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
local n = name == nil and '' or name
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
@@ -225,25 +252,28 @@ local function s(t, opts)
table.sort(o, function(a,b)
return (o[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
< (o[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
local function val2str(t, name, indent, path, plainindex, level)
local function val2str(t, name, indent, insref, path, plainindex, level)
local ttype, level = type(t), (level or 0)
local spath, sname = safename(path, name)
local tag = plainindex and
((type(name) == "number") and '' or name..space..'='..space) or
(name ~= nil and sname..space..'='..space or '')
if seen[t] then
if seen[t] then -- if already seen and in sref processing,
if insref then return tag..seen[t] end -- then emit right away
table.insert(sref, spath..space..'='..space..seen[t])
return tag..'nil'..comment('ref', level)
elseif badtype[ttype] then return tag..globerr(t, level)
elseif badtype[ttype] then
seen[t] = spath
return tag..globerr(t, level)
elseif ttype == 'function' then
seen[t] = spath
local ok, res = pcall(string.dump, t)
local func = ok and ((opts.nocode and "function() end" or
local func = ok and ((opts.nocode and "function() --[[..skipped..]] end" or
"loadstring("..safestr(res)..",'@serialized')")..comment(t, level))
return tag..(func or globerr(t, level))
elseif ttype == "table" then
if level >= maxl then return tag..'{}'..comment('max', level) end
seen[t] = spath
seen[t] = insref or spath -- set path to use as reference
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
local maxn, o, out = #t, {}, {}
for key = 1, maxn do table.insert(o, key) end
@@ -253,14 +283,15 @@ local function s(t, opts)
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
if opts.ignore and opts.ignore[value] -- skip ignored values; do nothing
or sparse and value == nil then -- skipping nils; do nothing
elseif ktype == 'table' or ktype == 'function' then
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
if not seen[key] and not globals[key] then
table.insert(sref, 'local '..val2str(key,gensym(key),indent)) end
table.insert(sref, seen[t]..'['..(seen[key] or globals[key] or gensym(key))
..']'..space..'='..space..(seen[value] or val2str(value,nil,indent)))
table.insert(sref, 'placeholder')
sref[#sref] = 'local '..val2str(key,gensym(key),indent,gensym(key)) end
table.insert(sref, 'placeholder')
local path = seen[t]..'['..(seen[key] or globals[key] or gensym(key))..']'
sref[#sref] = path..space..'='..space..(seen[value] or val2str(value,nil,indent,path))
else
if badtype[ktype] then plainindex, key = true, '['..globerr(key, level+1)..']' end
table.insert(out,val2str(value,key,indent,spath,plainindex,level+1))
table.insert(out,val2str(value,key,indent,insref,seen[t],plainindex,level+1))
end
end
local prefix = string.rep(indent or '', level)
@@ -320,36 +351,48 @@ end
local function set_breakpoint(file, line)
if file == '-' and lastfile then file = lastfile end
if not breakpoints[file] then
breakpoints[file] = {}
end
if not breakpoints[file] then breakpoints[file] = {} end
breakpoints[file][line] = true
end
local function remove_breakpoint(file, line)
if file == '-' and lastfile then file = lastfile end
if breakpoints[file] then
breakpoints[file][line] = nil
end
if breakpoints[file] then breakpoints[file][line] = nil end
end
-- this file name is already converted to lower case on windows.
local function has_breakpoint(file, line)
return breakpoints[file] and breakpoints[file][line]
end
local function restore_vars(vars)
if type(vars) ~= 'table' then return end
local func = debug.getinfo(3, "f").func
-- locals need to be processed in the reverse order, starting from
-- the inner block out, to make sure that the localized variables
-- are correctly updated with only the closest variable with
-- the same name being changed
-- first loop find how many local variables there is, while
-- the second loop processes them from i to 1
local i = 1
local written_vars = {}
while true do
local name = debug.getlocal(3, i)
if not name then break end
if string.sub(name, 1, 1) ~= '(' then debug.setlocal(3, i, vars[name]) end
written_vars[name] = true
i = i + 1
end
i = i - 1
local written_vars = {}
while i > 0 do
local name = debug.getlocal(3, i)
if not written_vars[name] then
if string.sub(name, 1, 1) ~= '(' then debug.setlocal(3, i, vars[name]) end
written_vars[name] = true
end
i = i - 1
end
i = 1
local func = debug.getinfo(3, "f").func
while true do
local name = debug.getupvalue(func, i)
if not name then break end
@@ -417,7 +460,7 @@ end
local function debug_hook(event, line)
if abort and is_safe(stack_level) then error(abort) end
-- LuaJIT needs special treatment. Because debug_hook is set for
-- (1) LuaJIT needs special treatment. Because debug_hook is set for
-- *all* coroutines, and not just the one being debugged as in regular Lua
-- (http://lua-users.org/lists/lua-l/2011-06/msg00513.html),
-- need to avoid debugging mobdebug's own code as LuaJIT doesn't
@@ -427,7 +470,10 @@ local function debug_hook(event, line)
-- 'tail return' events are not generated by LuaJIT).
-- the next line checks if the debugger is run under LuaJIT and if
-- one of debugger methods is present in the stack, it simply returns.
if jit and in_debugger() then return end
-- (2) also check if this debug hook has not been visited for any reason.
-- this check is needed to avoid stepping in too early
-- (for example, when coroutine.resume() is executed inside start()).
if (jit or not seen_hook) and in_debugger() then return end
if event == "call" then
stack_level = stack_level + 1
@@ -442,13 +488,18 @@ local function debug_hook(event, line)
skipcount = 0
end
-- this is needed to check if the stack got shorter.
-- this may happen when "pcall(load, '')" is called
-- this is needed to check if the stack got shorter or longer.
-- unfortunately counting call/return calls is not reliable.
-- the discrepancy may happen when "pcall(load, '')" call is made
-- or when "error()" is called in a function.
-- in either case there are more "call" than "return" events reported.
-- this validation is done for every "line" event, but should be
-- "cheap" as it only checks for the stack to get shorter
stack_level = stack_depth(stack_level)
-- this validation is done for every "line" event, but should be "cheap"
-- as it checks for the stack to get shorter (or longer by one call).
-- start from one level higher just in case we need to grow the stack.
-- this may happen after coroutine.resume call to a function that doesn't
-- have any other instructions to execute. it triggers three returns:
-- "return, tail return, return", which needs to be accounted for.
stack_level = stack_depth(stack_level+1)
local caller = debug.getinfo(2, "S")
-- grab the filename and fix it if needed
@@ -457,56 +508,69 @@ local function debug_hook(event, line)
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
if iswindows then file = string.lower(file) end
file = string.gsub(file, "\\", "/") -- convert slash
-- remove references to the current folder (./)
if string.find(file, "%./") == 1 then file = string.sub(file, 3)
else file = string.gsub(file, '^'..q(basedir), '') 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
-- set to true if we got here; this only needs to be done once per
-- session, so do it here to at least avoid setting it for every line.
seen_hook = true
lastfile = file
end
local vars
local vars, status, res
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)
local ok, fired = pcall(value)
if ok and fired then
status, res = coroutine.resume(coro_debugger, events.WATCH, vars, file, line, index)
break -- any one watch is enough; don't check multiple times
end
end
end
if step_into
or (step_over and stack_level <= step_level)
or has_breakpoint(file, line)
or (socket.select({server}, {}, 0))[server] then
-- need to get into the "regular" debug handler, but only if there was
-- no watch that was fired. If there was a watch, handle its result.
local getin = (status == nil) and
(step_into
or (step_over and stack_level <= step_level)
or has_breakpoint(file, line)
or (socket.select(rset, nil, 0))[server])
if getin then
vars = vars or capture_vars()
seen_hook = true
step_into = false
step_over = false
local status, res = coroutine.resume(coro_debugger, events.BREAK, vars, file, line)
-- handle 'stack' command that provides stack() information to the debugger
if status and res == 'stack' then
while status and res == 'stack' do
-- resume with the stack trace and variables
status, res = coroutine.resume(coro_debugger, events.STACK, stack(3), file, line)
end
end
-- need to recheck once more as resume after 'stack' command may
-- return something else (for example, 'exit'), which needs to be handled
if status and res and res ~= 'stack' then
if abort == nil and res == "exit" then os.exit(1) end
abort = res
-- only abort if safe; if not, there is another (earlier) check inside
-- debug_hook, which will abort execution at the first safe opportunity
if is_safe(stack_level) then error(abort) end
end -- abort execution if requested
status, res = coroutine.resume(coro_debugger, events.BREAK, vars, file, line)
end
-- handle 'stack' command that provides stack() information to the debugger
if status and res == 'stack' then
while status and res == 'stack' do
-- resume with the stack trace and variables
if vars then restore_vars(vars) end -- restore vars so they are reflected in stack values
status, res = coroutine.resume(coro_debugger, events.STACK, stack(3), file, line)
end
end
-- need to recheck once more as resume after 'stack' command may
-- return something else (for example, 'exit'), which needs to be handled
if status and res and res ~= 'stack' then
if abort == nil and res == "exit" then os.exit(1) end
abort = res
-- only abort if safe; if not, there is another (earlier) check inside
-- debug_hook, which will abort execution at the first safe opportunity
if is_safe(stack_level) then error(abort) end
end
if vars then restore_vars(vars) end
end
end
@@ -526,7 +590,7 @@ end
local function debugger_loop(sfile, sline)
local command
local app
local app, osname
local eval_env = {}
local function emptyWatch () return false end
local loaded = {}
@@ -534,6 +598,7 @@ local function debugger_loop(sfile, sline)
while true do
local line, err
local wx = rawget(genv, "wx") -- use rawread to make strict.lua happy
if wx and server.settimeout then server:settimeout(0.1) end
while true do
line, err = server:receive()
@@ -542,13 +607,19 @@ local function debugger_loop(sfile, sline)
app = app or (wx and wx.wxGetApp and wx.wxGetApp())
if app then
local win = app:GetTopWindow()
if win then
local inloop = app:IsMainLoopRunning()
osname = osname or wx.wxPlatformInfo.Get():GetOperatingSystemFamilyName()
if win and not inloop then
-- process messages in a regular way
-- and exit as soon as the event loop is idle
win:Connect(wx.wxEVT_IDLE, function()
if osname == 'Unix' then wx.wxTimer(app):Start(10, true) end
local exitLoop = function()
win:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_IDLE)
win:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_TIMER)
app:ExitMainLoop()
end)
end
win:Connect(wx.wxEVT_IDLE, exitLoop)
win:Connect(wx.wxEVT_TIMER, exitLoop)
app:MainLoop()
end
end
@@ -559,7 +630,7 @@ local function debugger_loop(sfile, sline)
if server.settimeout then server:settimeout() end -- back to blocking
command = string.sub(line, string.find(line, "^[A-Z]+"))
if command == "SETB" then
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+(.-)%s+(%d+)%s*$")
if file and line then
set_breakpoint(file, tonumber(line))
server:send("200 OK\n")
@@ -567,7 +638,7 @@ local function debugger_loop(sfile, sline)
server:send("400 Bad Request\n")
end
elseif command == "DELB" then
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
local _, _, _, file, line = string.find(line, "^([A-Z]+)%s+(.-)%s+(%d+)%s*$")
if file and line then
remove_breakpoint(file, tonumber(line))
server:send("200 OK\n")
@@ -594,7 +665,7 @@ local function debugger_loop(sfile, sline)
server:send("400 Bad Request\n")
end
elseif command == "LOAD" then
local _, _, size, name = string.find(line, "^[A-Z]+%s+(%d+)%s+([%w%p%s]*[%w%p]+)%s*$")
local _, _, size, name = string.find(line, "^[A-Z]+%s+(%d+)%s+(%S.-)%s*$")
size = tonumber(size)
if abort == nil then -- no LOAD/RELOAD allowed inside start()
@@ -634,14 +705,15 @@ local function debugger_loop(sfile, sline)
elseif command == "SETW" then
local _, _, exp = string.find(line, "^[A-Z]+%s+(.+)%s*$")
if exp then
local func = loadstring("return(" .. exp .. ")")
local func, res = loadstring("return(" .. exp .. ")")
if func then
watchescnt = watchescnt + 1
local newidx = #watches + 1
watches[newidx] = func
server:send("200 OK " .. newidx .. "\n")
else
server:send("400 Bad Request\n")
server:send("401 Error in Expression " .. string.len(res) .. "\n")
server:send(res)
end
else
server:send("400 Bad Request\n")
@@ -708,6 +780,14 @@ local function debugger_loop(sfile, sline)
server:send("401 Error in Execution " .. string.len(file) .. "\n")
server:send(file)
end
elseif command == "BASEDIR" then
local _, _, dir = string.find(line, "^[A-Z]+%s+(.+)%s*$")
if dir then
basedir = dir
server:send("200 OK\n")
else
server:send("400 Bad Request\n")
end
elseif command == "SUSPEND" then
-- do nothing; it already fulfilled its role
elseif command == "STACK" then
@@ -754,7 +834,13 @@ local function start(controller_host, controller_port)
server = socket.connect(controller_host, controller_port)
if server then
rset = {server} -- store hash to avoid recreating it later
-- check if we are called from the debugger as this may happen
-- when another debugger function calls start(); only check one level deep
local this = debug.getinfo(1, "S").source
local info = debug.getinfo(2, "Sl")
if info.source == this then info = debug.getinfo(3, "Sl") end
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
@@ -765,14 +851,15 @@ local function start(controller_host, controller_port)
-- start from 16th frame, which is sufficiently large for this check.
stack_level = stack_depth(16)
debug.sethook(debug_hook, "lcr")
coro_debugger = coroutine.create(debugger_loop)
debug.sethook(debug_hook, "lcr")
return coroutine.resume(coro_debugger, file, info.currentline)
else
print("Could not connect to " .. controller_host .. ":" .. controller_port)
end
end
local coro_debugee
local function controller(controller_host, controller_port)
-- only one debugging session can be run (as there is only one debug hook)
if isrunning() then return end
@@ -783,6 +870,8 @@ local function controller(controller_host, controller_port)
local exitonerror = not skip -- exit if not running a scratchpad
server = socket.connect(controller_host, controller_port)
if server then
rset = {server} -- store hash to avoid recreating it later
local function report(trace, err)
local msg = err .. "\n" .. trace
server:send("401 Error in Execution " .. string.len(msg) .. "\n")
@@ -790,14 +879,15 @@ local function controller(controller_host, controller_port)
return err
end
seen_hook = true -- allow to accept all commands
coro_debugger = coroutine.create(debugger_loop)
while true do
step_into = true
abort = false
if skip then skipcount = skip end -- to force suspend right away
while true do
step_into = true -- start with step command
abort = false -- reset abort flag from the previous loop
if skip then skipcount = skip end -- force suspend right away
local coro_debugee = coroutine.create(debugee)
coro_debugee = coroutine.create(debugee)
debug.sethook(coro_debugee, debug_hook, "lcr")
local status, err = coroutine.resume(coro_debugee)
@@ -819,7 +909,6 @@ local function controller(controller_host, controller_port)
end
end
end
server:close()
else
print("Could not connect to " .. controller_host .. ":" .. controller_port)
return false
@@ -837,7 +926,34 @@ local function loop(controller_host, controller_port)
return controller(controller_host, controller_port)
end
local basedir = ""
local coroutines = {}
setmetatable(coroutines, {__mode = "k"}) -- "weak" keys
local function on()
if not (isrunning() and server) then return end
local co = coroutine.running()
if co then
if not coroutines[co] then
coroutines[co] = true
debug.sethook(co, debug_hook, "lcr")
end
else
debug.sethook(debug_hook, "lcr")
end
end
local function off()
if not (isrunning() and server) then return end
local co = coroutine.running()
if co then
if coroutines[co] then coroutines[co] = false end
debug.sethook(co)
else
debug.sethook()
end
end
-- Handles server debugging commands
local function handle(params, client)
@@ -857,12 +973,12 @@ local function handle(params, client)
if status == "200" then
-- don't need to do anything
elseif status == "202" then
_, _, file, line = string.find(breakpoint, "^202 Paused%s+([%w%p%s]+)%s+(%d+)%s*$")
_, _, file, line = string.find(breakpoint, "^202 Paused%s+(.-)%s+(%d+)%s*$")
if file and line then
print("Paused at file " .. file .. " line " .. line)
end
elseif status == "203" then
_, _, file, line, watch_idx = string.find(breakpoint, "^203 Paused%s+([%w%p%s]+)%s+(%d+)%s+(%d+)%s*$")
_, _, file, line, watch_idx = string.find(breakpoint, "^203 Paused%s+(.-)%s+(%d+)%s+(%d+)%s*$")
if file and line and watch_idx then
print("Paused at file " .. file .. " line " .. line .. " (watch expression " .. watch_idx .. ": [" .. watches[watch_idx] .. "])")
end
@@ -881,10 +997,11 @@ local function handle(params, client)
return nil, nil, "Debugger error: unexpected response '" .. breakpoint .. "'"
end
elseif command == "setb" then
_, _, _, file, line = string.find(params, "^([a-z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
_, _, _, file, line = string.find(params, "^([a-z]+)%s+(.-)%s+(%d+)%s*$")
if file and line then
if iswindows then file = string.lower(file) end
file = string.gsub(file, "\\", "/") -- convert slash
file = string.gsub(file, basedir, '') -- remove basedir
file = string.gsub(file, '^'..q(basedir), '') -- remove basedir
if not breakpoints[file] then breakpoints[file] = {} end
client:send("SETB " .. file .. " " .. line .. "\n")
if client:receive() == "200 OK" then
@@ -905,16 +1022,23 @@ local function handle(params, client)
watches[watch_idx] = exp
print("Inserted watch exp no. " .. watch_idx)
else
print("Error: Watch expression not inserted")
local _, _, size = string.find(answer, "^401 Error in Expression (%d+)$")
if size then
local err = client:receive(tonumber(size)):gsub(".-:%d+:%s*","")
print("Error: watch expression not set: " .. err)
else
print("Error: watch expression not set")
end
end
else
print("Invalid command")
end
elseif command == "delb" then
_, _, _, file, line = string.find(params, "^([a-z]+)%s+([%w%p%s]+)%s+(%d+)%s*$")
_, _, _, file, line = string.find(params, "^([a-z]+)%s+(.-)%s+(%d+)%s*$")
if file and line then
if iswindows then file = string.lower(file) end
file = string.gsub(file, "\\", "/") -- convert slash
file = string.gsub(file, basedir, '') -- remove basedir
file = string.gsub(file, '^'..q(basedir), '') -- remove basedir
if not breakpoints[file] then breakpoints[file] = {} end
client:send("DELB " .. file .. " " .. line .. "\n")
if client:receive() == "200 OK" then
@@ -979,12 +1103,19 @@ local function handle(params, client)
client:send(lines)
else
local file = io.open(exp, "r")
if not file then print("Cannot open file " .. exp); return end
local lines = file:read("*all")
if not file and pcall(require, "winapi") then
-- if file is not open and winapi is there, try with a short path;
-- this may be needed for unicode paths on windows
winapi.set_encoding(winapi.CP_UTF8)
file = io.open(winapi.short_path(exp), "r")
end
if not file then error("Cannot open file " .. exp) end
-- read the file and remove the shebang line as it causes a compilation error
local lines = file:read("*all"):gsub("^#!.-\n", "\n")
file:close()
local file = string.gsub(exp, "\\", "/") -- convert slash
file = string.gsub(file, basedir, '') -- remove basedir
file = string.gsub(file, '^'..q(basedir), '') -- remove basedir
client:send("LOAD " .. string.len(lines) .. " " .. file .. "\n")
client:send(lines)
end
@@ -992,7 +1123,7 @@ local function handle(params, client)
if not params then
return nil, nil, "Debugger error: missing response after EXEC/LOAD"
end
local _, _, status, len = string.find(params, "^(%d+)[%w%p%s]+%s+(%d+)%s*$")
local _, _, status, len = string.find(params, "^(%d+).-%s+(%d+)%s*$")
if status == "200" then
len = tonumber(len)
if len > 0 then
@@ -1015,7 +1146,7 @@ local function handle(params, client)
return res[1], res
end
elseif status == "201" then
_, _, file, line = string.find(params, "^201 Started%s+([%w%p%s]+)%s+(%d+)%s*$")
_, _, file, line = string.find(params, "^201 Started%s+(.-)%s+(%d+)%s*$")
elseif status == "202" or params == "200 OK" then
-- do nothing; this only happens when RE/LOAD command gets the response
-- that was for the original command that was aborted
@@ -1055,13 +1186,18 @@ local function handle(params, client)
print("Error in stack information: " .. err)
return nil, nil, err
end
local stack = func()
local ok, stack = pcall(func)
if not ok then
print("Error in stack information: " .. stack)
return nil, nil, stack
end
for _,frame in ipairs(stack) do
-- remove basedir from short_src or source
local src = string.gsub(frame[1][2], "\\", "/") -- convert slash
if string.find(src, "@") == 1 then src = string.sub(src, 2) end
if string.find(src, "%./") == 1 then src = string.sub(src, 3) end
frame[1][2] = string.gsub(src, basedir, '') -- remove basedir
if iswindows then src = string.lower(src) end
frame[1][2] = string.gsub(src, '^'..q(basedir), '') -- remove basedir
print(serpent.line(frame[1], {comment = false}))
end
return stack
@@ -1076,10 +1212,20 @@ local function handle(params, client)
elseif command == "basedir" then
local _, _, dir = string.find(params, "^[a-z]+%s+(.+)$")
if dir then
if iswindows then dir = string.lower(dir) end
dir = string.gsub(dir, "\\", "/") -- convert slash
if not string.find(dir, "/$") then dir = dir .. "/" end
basedir = dir
print("New base directory is " .. basedir)
client:send("BASEDIR "..dir.."\n")
local resp = client:receive()
local _, _, status = string.find(resp, "^(%d+)%s+%w+%s*$")
if status == "200" then
print("New base directory is " .. basedir)
else
print("Unknown error")
return nil, nil, "Debugger error: unexpected response after BASEDIR"
end
else
print(basedir)
end
@@ -1130,7 +1276,7 @@ local function listen(host, port)
client:receive()
local breakpoint = client:receive()
local _, _, file, line = string.find(breakpoint, "^202 Paused%s+([%w%p%s]+)%s+(%d+)%s*$")
local _, _, file, line = string.find(breakpoint, "^202 Paused%s+(.-)%s+(%d+)%s*$")
if file and line then
print("Paused at file " .. file )
print("Type 'help' for commands")
@@ -1149,6 +1295,37 @@ local function listen(host, port)
end
end
local cocreate
local function coro()
if cocreate then return end -- only set once
cocreate = cocreate or coroutine.create
coroutine.create = function(f, ...)
return cocreate(function(...)
require("mobdebug").on()
return f(...)
end, ...)
end
end
local moconew
local function moai()
if moconew then return end -- only set once
moconew = moconew or (MOAICoroutine and MOAICoroutine.new)
if not moconew then return end
MOAICoroutine.new = function(...)
local thread = moconew(...)
local mt = getmetatable(thread)
local patched = mt.run
mt.run = function(self, f, ...)
return patched(self, function(...)
require("mobdebug").on()
return f(...)
end, ...)
end
return thread
end
end
-- make public functions available
mobdebug.listen = listen
mobdebug.loop = loop
@@ -1156,6 +1333,10 @@ mobdebug.scratchpad = scratchpad
mobdebug.handle = handle
mobdebug.connect = connect
mobdebug.start = start
mobdebug.on = on
mobdebug.off = off
mobdebug.moai = moai
mobdebug.coro = coro
mobdebug.line = serpent.line
mobdebug.dump = serpent.dump

315
lualibs/testwell.lua Normal file
View File

@@ -0,0 +1,315 @@
--
-- Copyright (C) 2012 Paul Kulchenko
-- A simple testing library
-- Based on lua-TestMore : <http://fperrad.github.com/lua-TestMore/>
-- Copyright (c) 2009-2011 Francois Perrad
-- This library is licensed under the terms of the MIT/X11 license,
-- like Lua itself.
--
local pairs = pairs
local tostring = tostring
local type = type
local _G = _G or _ENV
-----------------------------------------------------------
local tb = {
curr_test = 0,
good_test = 0,
skip_test = 0,
}
function tb:print(...)
print(...)
end
function tb:note(...)
self:print(...)
end
function tb:diag(...)
local arg = {...}
for k, v in pairs(arg) do
arg[k] = tostring(v)
end
local msg = table.concat(arg)
msg = msg:gsub("\n", "\n# ")
msg = msg:gsub("\n# \n", "\n#\n")
msg = msg:gsub("\n# $", '')
self:print("# " .. msg)
end
function tb:ok(test, name, more)
self.curr_test = self.curr_test + 1
self.good_test = self.good_test + (test and 1 or 0)
self.skip_test = self.skip_test + (test == nil and 1 or 0)
name = tostring(name or '')
local out = ''
if not test then
out = "not "
end
out = out .. "ok " .. self.curr_test
if name ~= '' then
out = out .. " - " .. name
end
self:print(out)
if test == false then
self:diag(" Failed test " .. (name and ("'" .. name .. "'") or ''))
if debug then
local info = debug.getinfo(3)
local file = info.short_src
local line = info.currentline
self:diag(" in " .. file .. " at line " .. line .. ".")
end
self:diag(more)
end
end
function tb:done_testing(reset)
local c, g, s = self.curr_test, self.good_test, self.skip_test
if reset then
self.curr_test = 0
self.good_test = 0
self.skip_test = 0
end
return c, g, s
end
-----------------------------------------------------------
local serpent = (function() ---- include Serpent module for serialization
local n, v = "serpent", 0.15 -- (C) 2012 Paul Kulchenko; MIT License
local c, d = "Paul Kulchenko", "Serializer and pretty printer of Lua data types"
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
local badtype = {thread = true, userdata = true}
local keyword, globals, G = {}, {}, (_G or _ENV)
for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end
for k,v in pairs(G) do globals[v] = k end -- build func to name mapping
for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do
for k,v in pairs(G[g]) do globals[v] = g..'.'..k end end
local function s(t, opts)
local name, indent, fatal = opts.name, opts.indent, opts.fatal
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
local comm = opts.comment and (tonumber(opts.comment) or math.huge)
local seen, sref, syms, symn = {}, {}, {}, 0
local function gensym(val) return tostring(val):gsub("[^%w]",""):gsub("(%d%w+)",
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return syms[s] end) end
local function safestr(s) return type(s) == "number" and (huge and snum[tostring(s)] or s)
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
local function comment(s,l) return comm and (l or 0) < comm and ' --[['..tostring(s)..']]' or '' end
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
and safestr(tostring(s))..comment('err',l) or error("Can't serialize "..tostring(s)) end
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
local n = name == nil and '' or name
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
local safe = plain and n or '['..safestr(n)..']'
return (path or '')..(plain and path and '.' or '')..safe, safe end
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(o, n)
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
table.sort(o, function(a,b)
return (o[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
< (o[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
local function val2str(t, name, indent, path, plainindex, level)
local ttype, level = type(t), (level or 0)
local spath, sname = safename(path, name)
local tag = plainindex and
((type(name) == "number") and '' or name..space..'='..space) or
(name ~= nil and sname..space..'='..space or '')
if seen[t] then
table.insert(sref, spath..space..'='..space..seen[t])
return tag..'nil'..comment('ref', level)
elseif badtype[ttype] then return tag..globerr(t, level)
elseif ttype == 'function' then
seen[t] = spath
local ok, res = pcall(string.dump, t)
local func = ok and ((opts.nocode and "function() end" or
"loadstring("..safestr(res)..",'@serialized')")..comment(t, level))
return tag..(func or globerr(t, level))
elseif ttype == "table" then
if level >= maxl then return tag..'{}'..comment('max', level) end
seen[t] = spath
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
local maxn, o, out = #t, {}, {}
for key = 1, maxn do table.insert(o, key) end
for key in pairs(t) do if not o[key] then table.insert(o, key) end end
if opts.sortkeys then alphanumsort(o, opts.sortkeys) end
for n, key in ipairs(o) do
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
if opts.ignore and opts.ignore[value] -- skip ignored values; do nothing
or sparse and value == nil then -- skipping nils; do nothing
elseif ktype == 'table' or ktype == 'function' then
if not seen[key] and not globals[key] then
table.insert(sref, 'local '..val2str(key,gensym(key),indent)) end
table.insert(sref, seen[t]..'['..(seen[key] or globals[key] or gensym(key))
..']'..space..'='..space..(seen[value] or val2str(value,nil,indent)))
else
if badtype[ktype] then plainindex, key = true, '['..globerr(key, level+1)..']' end
table.insert(out,val2str(value,key,indent,spath,plainindex,level+1))
end
end
local prefix = string.rep(indent or '', level)
local head = indent and '{\n'..prefix..indent or '{'
local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
local tail = indent and "\n"..prefix..'}' or '}'
return (custom and custom(tag,head,body,tail) or tag..head..body..tail)..comment(t, level)
else return tag..safestr(t) end -- handle all other types
end
local sepr = indent and "\n" or ";"..space
local body = val2str(t, name, indent) -- this call also populates sref
local tail = #sref>0 and table.concat(sref, sepr)..sepr or ''
return not name and body or "do local "..body..sepr..tail.."return "..name..sepr.."end"
end
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }
end)() ---- end of Serpent module
-----------------------------------------------------------
local m = {}
function m.ok(test, name)
tb:ok(test, name)
end
local parms = {comment = false}
function m.is(got, expected, name)
local tgot, texp = type(got), type(expected)
local vgot, vexp = serpent.line(got, parms), serpent.line(expected, parms)
local pass = vgot == vexp
if got == nil then pass = nil end
tb:ok(pass, name, not pass and
" got: " .. vgot .. " (" .. tgot .. ")" ..
"\n expected: " .. vexp .. " (" .. texp .. ")")
end
function m.isnt(got, expected, name)
local tgot, texp = type(got), type(expected)
local vgot, vexp = serpent.line(got, parms), serpent.line(expected, parms)
local pass = vgot ~= vexp
if got == nil then pass = nil end
tb:ok(pass, name, not pass and
" got: " .. vgot .. " (" .. tgot .. ")" ..
"\n expected: anything else")
end
function m.like(got, pattern, name)
if type(pattern) ~= 'string' then
return tb:ok(false, name, "pattern isn't a string : " .. tostring(pattern))
end
local pass = tostring(got):match(pattern)
if got == nil then pass = nil end
tb:ok(pass, name, not pass and
" '" .. tostring(got) .. "'" ..
"\n doesn't match '" .. pattern .. "'")
end
function m.unlike(got, pattern, name)
if type(pattern) ~= 'string' then
return tb:ok(false, name, "pattern isn't a string : " .. tostring(pattern))
end
local pass = not tostring(got):match(pattern)
if got == nil then pass = nil end
tb:ok(pass, name, not pass and
" '" .. tostring(got) .. "'" ..
"\n matches '" .. pattern .. "'")
end
local cmp = {
['<'] = function (a, b) return a < b end,
['<='] = function (a, b) return a <= b end,
['>'] = function (a, b) return a > b end,
['>='] = function (a, b) return a >= b end,
['=='] = function (a, b) return a == b end,
['~='] = function (a, b) return a ~= b end,
}
function m.cmp_ok(this, op, that, name)
local f = cmp[op]
if not f then
return tb:ok(false, name, "unknown operator : " .. tostring(op))
end
local pass = f(this, that)
if this == nil then pass = nil end
tb:ok(pass, name, not pass and
" " .. tostring(this) ..
"\n " .. op ..
"\n " .. tostring(that))
end
function m.type_ok(val, t, name)
if type(t) ~= 'string' then
return tb:ok(false, name, "type isn't a string : " .. tostring(t))
end
if type(val) == t then
tb:ok(true, name)
else
tb:ok(false, name,
" " .. tostring(val) .. " isn't a '" .. t .."', it's a '" .. type(val) .. "'")
end
end
function m.diag(...)
tb:diag(...)
end
function m.report()
local total, good, skipped = tb:done_testing(true)
if total == 0 then return end
local failed = total - good - skipped
local sum = ("(%d/%d/%d)."):format(good, skipped, total)
local num, msg = 0, ""
if good > 0 then
num, msg = good, msg .. "passed " .. good
end
if failed > 0 then
num, msg = failed, msg .. (#msg > 0 and (skipped > 0 and ", " or " and ") or "")
.. "failed " .. failed
end
if skipped > 0 then
num, msg = skipped, msg .. (#msg > 0 and ((good > 0 and failed > 0 and ',' or '') .." and ") or "")
.. "skipped " .. skipped
end
msg = ("Looks like you %s test%s of %d %s"):format(msg, (num > 1 and 's' or ''), total, sum)
if skipped == total then msg = "Looks like you skipped all tests " .. sum end
if good == total then msg = "All tests passed " .. sum end
tb:note(("1..%d # %s"):format(total, msg))
end
function m.ismain()
for l = 3, 64 do -- only check up to 64 level; no more needed
local info = debug.getinfo(l)
if not info then return true end
if info.func == require then return false end
end
return true
end
-- this is needed to call report() when the test object is destroyed
if _VERSION >= "Lua 5.2" then
setmetatable(m, {__gc = m.report})
else
-- keep sentinel alive until 'm' is garbage collected
m.sentinel = newproxy(true)
getmetatable(m.sentinel).__gc = m.report
end
for k, v in pairs(m) do -- injection
_G[k] = v
end
return m

View File

@@ -46,7 +46,7 @@ return {
},
keywords = {
[[int uint half float bool double
[[int uint half float bool double atomic_uint binding offset
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
@@ -63,8 +63,8 @@ return {
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
origin_upper_left pixel_center_integer depth_greater depth_greater depth_greater depth_unchanged
smooth flat noperspective highp mediump lowp shared packed std140 std430 row_major column_major buffer
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
@@ -76,22 +76,26 @@ return {
gl_InvocationID gl_PrimitiveIDIn gl_Layer gl_ViewportIndex gl_FrontFacing
gl_PointCoord gl_SampleID gl_SamplePosition gl_FragColor
gl_FragData gl_FragDepth gl_SampleMask
gl_NumWorkGroups gl_WorkGroupSize gl_WorkGroupID gl_LocalInvocationID gl_GlobalInvocationID gl_LocalInvocationIndex
local_size_x local_size_y local_size_z
coherent volatile restrict
coherent volatile restrict readonly writeonly
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
size1x8 size1x16 size1x32 size2x32 size4x32 rgba32f rgba16f rg32f rg16f r32f r16f rgba8 rgba16 r11f_g11f_b10f rgb10_a2ui
rgb10_a2i rg16 rg8 r16 r8 rgba32i rgba16i rgba8i rg32i rg16i rg8i r32i r16i r8i rgba32ui rgba16ui rgba8ui rg32ui rg16ui rg8ui
r32ui r16ui r8ui rgba16_snorm rgba8_snorm rg16_snorm rg8_snorm r16_snorm r8_snorm
]],
[[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
floatBitsToInt floatBitsToUint intBitsToFloat uintBitsToFloat fma frexp ldexp
packUnorm2x16 packUnorm4x8 packSnorm4x8
unpackUnorm2x16 unpackUnorm4x8 unpackSnorm4x8
packDouble2x32 unpackDouble2x32
packDouble2x32 unpackDouble2x32 packHalf2x16 unpackHalf2x16
length distance dot cross normalize ftransform faceforward
reflect refract
matrixCompMult outerProduct transpose determinant inverse
@@ -138,7 +142,12 @@ return {
imageAtomicAdd imageAtomicMin imageAtomicMax
imageAtomicIncWrap imageAtomicDecWrap imageAtomicAnd
imageAtomicOr imageAtomixXor imageAtomicExchange
imageCompSwap memoryBarrier
imageCompSwap
memoryBarrier groupMemoryBarrier memoryBarrierAtomicCounter memoryBarrierShared memoryBarrierBuffer memoryBarrierImage
atomicCounterIncrement atomicCounterDecrement atomicCounter
atomicMin atomicMax atomicAdd atomicAnd atomicOr atomicXor atomicExchange atomicCompSwap
x y z w
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy

View File

@@ -1,36 +1,63 @@
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
---------------------------------------------------------
local funcdef = "([A-Za-z_][A-Za-z0-9_%.%:]*)%s*"
local funccall = "([A-Za-z_][A-Za-z0-9_]*)%s*"
local decindent = {
['else'] = true, ['elseif'] = true, ['end'] = true}
local incindent = {
['else'] = true, ['elseif'] = true, ['for'] = true, ['do'] = true,
['if'] = true, ['repeat'] = true, ['until'] = true, ['while'] = true}
local function isfndef(str)
local l
local s,e,cap,par = string.find(str, "function%s+" .. funcdef .. "(%(.-%))")
-- 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+" .. funcdef)
end
-- try to match "foo = function()"
if (not s) then
s,e,cap,par = string.find(str, funcdef .. "=%s*function%s*(%(.-%))")
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
return {
exts = {"lua"},
exts = {"lua", "rockspec"},
lexer = wxstc.wxSTC_LEX_LUA,
apitype = "lua",
linecomment = "--",
sep = "%.:",
isfncall = function(str)
return string.find(str,"([A-Za-z0-9_]+)%s*%(")
return string.find(str, funccall .. "%(")
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
isfndef = isfndef,
isdecindent = function(str)
-- this handles three different cases:
local term = str:match("^%s*(%w+)%s*$")
-- (1) 'end', 'elseif', 'else'
local match = term and decindent[term]
-- (2) 'end)' and 'end}'
if not term then term, match = str:match("^%s*(end)%s*([%)%}]+)%s*[,;]?") end
-- (3) '},', '};', '),' and ');'
if not term then match = str:match("^%s*[%)%}]+%s*[,;]?%s*$") end
return match and 1 or 0, match and term and 1 or 0
end,
isincindent = function(str)
local term = str:match("^%s*(%w+)[^%w]*")
term = term and incindent[term] and 1 or 0
local _, opened = str:gsub("([%{%(])", "%1")
local _, closed = str:gsub("([%}%)])", "%1")
local func = (isfndef(str) or str:match("[^%w]+function%s*%(")) and 1 or 0
-- ended should only be used to negate term and func effects
local ended = (term + func > 0) and str:match("[^%w]+end%s*$") and 1 or 0
return opened - closed + func + term - ended
end,
typeassigns = function(editor)

View File

@@ -79,7 +79,7 @@ style = {
-- content is optional
-- config is loaded into existing config table
config = {
appname = "estrela", -- by default the launcher name
appname = "zbstudio", -- by default the launcher name
path = {
-- path for tools/interpreters
@@ -91,31 +91,30 @@ config = {
-- 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,
fontname = "Courier New", -- default font
fontsize = 10, -- default size
caretline = true, -- show active line
iofilter = nil, -- input/output filtering of strings
showfncall = true, -- use indicator to show function calls if spec allows
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
-- sets "usetabs" to true for this file
calltipdelay = nil, -- delay to show calltip (in ms)
autoactivate = false, -- auto-activate/open files during debugging
smartindent = false, -- use smart indentation if spec allows
},
default = {
name = 'untitled',
fullname = 'untitled.lua',
},
debugger = {
verbose = false,
hostname = nil, -- hostname to use when the detected one is incorrect
}
outputshell = {
@@ -126,25 +125,28 @@ config = {
-- defult size
}
filetree = { -- filetree settings
fontname = nil, -- no default font as it is system dependent
fontsize = nil, -- no default size as it is system dependent
}
styles = {},
-- styles table as above for editor
stylesoutshell = {},
-- styles for output/shell
interpreter = "EstrelaEditor",
interpreter = "luadeb",
-- 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
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
startat = 2, -- start suggesting dynamic words after 2 characters
strategy = 0,
-- 0: is string comparison
-- 1: substring leading characters (camel case or _ separated)
@@ -168,8 +170,10 @@ config = {
-- UDP port for single instance communication
activateoutput = false, -- activate output/console on Run/Debug/Compile
unhidewxwindow = false, -- try to unhide a wx window
unhidewindow = false, -- to unhide a gui window
allowinteractivescript = false, -- allow interaction in the output window
projectautoopen = false, -- allow auto open/close files on a project switch
autorecoverinactivity = nil, -- period of inactivity (s) for autorecover
}
-- application engine
@@ -301,21 +305,21 @@ debuginterface = {
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
evaluate = function(self, expressions, fnSetValues) end, -- for watches tables
stack = function(self) 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
api = {"apifile_without_extension"} -- (opt) to limit loaded lua apis
frun = function(self,wfilename,withdebugger) end,
fprojdir = function(self,wfilename) return "projpath_from_filename" end, -- (opt)
fattachdebug = function(self) end, -- (opt)
hasdebugger = false, -- if debugging is available
scratchextloop = nil, -- (opt) indicates scratchpad support
-- nil, no support for scratchpad;
-- false, scratchpad supported;
-- true, scratchpad supported and requires handling for external loop.
}

View File

@@ -11,7 +11,7 @@ local statusBar = ide.frame.statusBar
local function newAPI(api)
api = api or {}
for i,v in pairs(api) do
for i in pairs(api) do
api[i] = nil
end
-- tool tip info and reserved names
@@ -36,8 +36,6 @@ local apis = {
lua = newAPI(),
}
local config = ide.config.ac
function GetApi(apitype)
return apis[apitype] or apis["none"]
end
@@ -58,20 +56,16 @@ local function addAPI(apifile,only,subapis,known) -- relative to API directory
local fn,err = loadfile(apifile)
if err then
print("API file '"..apifile.."' could not be loaded: "..err.."\n")
DisplayOutput("Error while loading API file: "..err.."\n")
return
end
local mt
local env = apis[ftype] or newAPI()
apis[ftype] = env
env = env.ac.childs
local suc,res = xpcall(function()return fn(env)end, function(err)
DisplayOutput("Error while loading API file: "..apifile..":\n")
DisplayOutput(debug.traceback(err))
DisplayOutput("\n")
end)
if (suc and res) then
local suc,res = pcall(function()return fn(env)end)
if (not suc) then
DisplayOutput("Error while processing API file: "..res.."\n")
elseif (res) then
local function gennames(tab,prefix)
for i,v in pairs(tab) do
v.classname = (prefix and (prefix..".") or "")..i
@@ -89,9 +83,8 @@ local function addAPI(apifile,only,subapis,known) -- relative to API directory
end
local function loadallAPIs (only,subapis,known)
for i,dir in ipairs(FileSysGet(".\\api\\*.*",wx.wxDIR)) do
local files = FileSysGet(dir.."\\*.*",wx.wxFILE)
for i,file in ipairs(files) do
for _, dir in ipairs(FileSysGet("api/*", wx.wxDIR)) do
for _, file in ipairs(FileSysGet(dir.."/*.*", wx.wxFILE)) do
if file:match "%.lua$" then
addAPI(file,only,subapis,known)
end
@@ -146,7 +139,7 @@ local function fillTips(api,apibasename,apiname)
-- build info
local inf = frontname.."\n"..info.description
local sentence = info.description:match("^([^\n]+)\n.*")
local sentence = sentence and sentence:match("([^%.]+)%..*$")
sentence = sentence and sentence:match("([^%.]+)%..*$")
local infshort = frontname.."\n"..(sentence and sentence.."..." or info.description)
local infshortbatch = (info.returns and info.args) and frontname or infshort
@@ -266,7 +259,7 @@ function ReloadLuaAPI()
interpreterapi = interpreterapi and interpreterapi.api
if (interpreterapi) then
local apinames = {}
for i,v in ipairs(interpreterapi) do
for _, v in ipairs(interpreterapi) do
apinames[v] = true
end
interpreterapi = apinames
@@ -276,7 +269,7 @@ end
do
local known = {}
for n,spec in pairs(ide.specs) do
for _, spec in pairs(ide.specs) do
if (spec.apitype) then
known[spec.apitype] = true
end
@@ -388,7 +381,7 @@ local function getAutoCompApiList(childs,fragment)
local wlist = cache[childs]
if not wlist then
wlist = " "
for i,v in pairs(childs) do
for i in pairs(childs) do
wlist = wlist..i.." "
end
cache[childs] = wlist
@@ -415,8 +408,8 @@ local function getAutoCompApiList(childs,fragment)
local t = {}
cache[childs] = t
local sub = strat == 1
for key, info in pairs(childs) do
local sub = strategy == 1
for key in pairs(childs) do
local used = {}
--
local kl = key:lower()
@@ -468,7 +461,7 @@ function CreateAutoCompList(editor,key)
if not (progress) then return end
if (tab == ac) then
local obj,krest = rest:match("([%w_]+)[:%.]([%w_]+)%s*$")
local _, krest = rest:match("([%w_]+)[:%.]([%w_]+)%s*$")
if (krest) then
if (#krest < 3) then return end
tab = tip.finfo
@@ -480,13 +473,14 @@ function CreateAutoCompList(editor,key)
rest = rest:gsub("[^%w_]","")
end
local last = key:match "([%w_]+)%s*$"
local last = key:match("([%w_]+)%s*$")
-- build dynamic word list
-- only if api search couldnt descend
-- ie we couldnt find matching sub items
local dw = ""
if (tab == ac) then
if (tab == ac and last and #last >= (ide.config.acandtip.startat or 2)) then
last = last:lower()
if dynamicwords[last] then
local list = dynamicwords[last]
table.sort(list,function(a,b)
@@ -496,7 +490,7 @@ function CreateAutoCompList(editor,key)
end)
-- ignore if word == last and sole user
for i,v in ipairs(list) do
if (v == last and dywordentries[v] == 1) then
if (v:lower() == last and dywordentries[v] == 1) then
table.remove(list,i)
break
end
@@ -504,7 +498,6 @@ function CreateAutoCompList(editor,key)
local res = table.concat(list," ")
dw = res ~= "" and " "..res or ""
end
end
@@ -526,13 +519,13 @@ function CreateAutoCompList(editor,key)
local ma,mb = 0,0
g(a,pat,function(...)
local l = {...}
for i,v in ipairs(l) do
for _, v in ipairs(l) do
ma = ma + ((v=="") and 0 or 1)
end
end)
g(b,pat,function(...)
local l = {...}
for i,v in ipairs(l) do
for _, v in ipairs(l) do
mb = mb + ((v=="") and 0 or 1)
end
end)

View File

@@ -8,8 +8,10 @@ local openDocuments = ide.openDocuments
local uimgr = frame.uimgr
function NewFile(event)
local editor = CreateEditor("untitled.lua")
local editor = CreateEditor()
SetupKeywords(editor, "lua")
AddEditor(editor, ide.config.default.fullname)
return editor
end
-- Find an editor page that hasn't been used at all, eg. an untouched NewFile()
@@ -26,45 +28,44 @@ local function findDocumentToReuse()
return editor
end
function LoadFile(filePath, editor, file_must_exist)
filePath = wx.wxFileName(filePath):GetFullPath()
local cmpName = string.lower(string.gsub(filePath, "\\", "/"))
function LoadFile(filePath, editor, file_must_exist, skipselection)
local filePath = wx.wxFileName(filePath)
filePath:Normalize() -- make it absolute and remove all .. and . if possible
-- 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)
if doc.filePath and filePath:SameAs(wx.wxFileName(doc.filePath)) then
if not skipselection then notebook:SetSelection(doc.index) end
return doc.editor
end
end
end
filePath = filePath:GetFullPath()
-- if not opened yet, try open now
local file_text = ""
local handle = io.open(filePath, "rb")
if handle then
file_text = handle:read("*a")
local file_text = FileRead(filePath)
if file_text then
if GetConfigIOFilter("input") then
file_text = GetConfigIOFilter("input")(filePath,file_text)
end
handle:close()
elseif file_must_exist then
return nil
end
local current = editor and editor:GetCurrentPos()
editor = editor
or findDocumentToReuse()
or CreateEditor(wx.wxFileName(filePath):GetFullName() or "untitled.lua")
editor = editor or findDocumentToReuse() or CreateEditor()
editor:Freeze()
editor:Clear()
editor:ClearAll()
SetupKeywords(editor, GetFileExt(filePath))
editor:MarkerDeleteAll(BREAKPOINT_MARKER)
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
editor:AppendText(file_text)
editor:AppendText(file_text or "")
editor:Colourise(0, -1)
editor:Thaw()
if current then editor:GotoPos(current) end
if (ide.config.editor.autotabs) then
local found = string.find(file_text,"\t") ~= nil
@@ -73,19 +74,22 @@ function LoadFile(filePath, editor, file_must_exist)
editor:EmptyUndoBuffer()
local id = editor:GetId()
if not openDocuments[id] then -- the editor has not been added to notebook
AddEditor(editor, wx.wxFileName(filePath):GetFullName()
or ide.config.default.fullname)
end
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)
-- activate the editor; this is needed for those cases when the editor is
-- created from some other element, for example, from a project tree.
SetEditorSelection()
if not skipselection then SetEditorSelection() end
return editor
end
@@ -108,14 +112,12 @@ local function getExtsString()
end
function OpenFile(event)
local exts = getExtsString()
local fileDialog = wx.wxFileDialog(ide.frame, "Open file",
"",
"",
exts,
wx.wxOPEN + wx.wxFILE_MUST_EXIST)
wx.wxFD_OPEN + wx.wxFD_FILE_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().."'.",
@@ -131,33 +133,27 @@ function SaveFile(editor, filePath)
if not filePath then
return SaveFileAs(editor)
else
if (ide.config.savebak) then
local backPath = filePath..".bak"
os.remove(backPath)
os.rename(filePath, backPath)
if (ide.config.savebak) then FileRename(filePath, filePath..".bak") end
local st = editor:GetText()
if GetConfigIOFilter("output") then
st = GetConfigIOFilter("output")(filePath,st)
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()
local ok, err = FileWrite(filePath, st)
if ok then
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)
SetAutoRecoveryMark()
return true
else
wx.wxMessageBox("Unable to save file '"..filePath.."'.",
wx.wxMessageBox("Unable to save file '"..filePath.."': "..err,
"Error",
wx.wxOK + wx.wxCENTRE, ide.frame)
wx.wxICON_ERROR + wx.wxOK + wx.wxCENTRE, ide.frame)
end
end
@@ -170,24 +166,26 @@ function SaveFileAs(editor)
local filePath = openDocuments[id].filePath
if (not filePath) then
filePath = FileTreeGetDir()
filePath = (filePath or "").."untitled"
filePath = (filePath or "")..ide.config.default.name
end
local fn = wx.wxFileName(filePath)
fn:Normalize() -- want absolute path for dialog
local exts = getExtsString()
local ext = fn:GetExt()
local fileDialog = wx.wxFileDialog(ide.frame, "Save file as",
fn:GetPath(wx.wxPATH_GET_VOLUME),
fn:GetFullName(),
exts,
wx.wxSAVE)
"*."..(ext and #ext > 0 and ext or "*"),
wx.wxFD_SAVE)
if fileDialog:ShowModal() == wx.wxID_OK then
local filePath = fileDialog:GetPath()
if SaveFile(editor, filePath) then
SetEditorSelection() -- update title of the editor
FileTreeRefresh() -- refresh the tree to reflect the new file
FileTreeMarkSelected(filePath)
SetupKeywords(editor, GetFileExt(filePath))
IndicateFunctions(editor)
if MarkupStyle then MarkupStyle(editor) end
@@ -204,7 +202,7 @@ function SaveAll()
local editor = document.editor
local filePath = document.filePath
if document.isModified then
if document.isModified or not document.filePath then
SaveFile(editor, filePath) -- will call SaveFileAs if necessary
end
end
@@ -271,11 +269,14 @@ function ClosePage(selection)
-- abort the debugger if the current marker is in the window being closed
-- also abort the debugger if it is running, as we don't know what
-- window will need to be activated when the debugger is paused
if debugger and debugger.pid and
if debugger and debugger.server and
(debugger.running or editor:MarkerNext(0, CURRENT_LINE_MARKER_VALUE) >= 0) then
debugger.terminate()
end
removePage(ide.openDocuments[id].index)
-- disable full screen if the last tab is closed
if not (notebook:GetSelection() >= 0) then ShowFullScreen(false) end
end
end
@@ -288,7 +289,8 @@ function SaveModifiedDialog(editor, allow_cancel)
local filePath = document.filePath
local fileName = document.fileName
if document.isModified then
local message = "Do you want to save the changes to '"..(fileName or 'untitled').."'?"
local message = "Do you want to save the changes to '"
..(fileName or ide.config.default.name).."'?"
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,
@@ -311,8 +313,13 @@ function SaveOnExit(allow_cancel)
if (SaveModifiedDialog(document.editor, allow_cancel) == wx.wxID_CANCEL) then
return false
end
end
document.isModified = false
-- if all documents have been saved or refused to save, then mark those that
-- are still modified as not modified (they don't need to be saved)
-- to keep their tab names correct
for id, document in pairs(openDocuments) do
if document.isModified then SetDocumentModified(id, false) end
end
return true
@@ -397,23 +404,35 @@ function ClearAllCurrentLineMarkers()
end
end
local compileOk, compileTotal = 0, 0
function CompileProgram(editor, quiet)
local editorText = editor:GetText()
-- remove shebang line (#!) as it throws a compilation error as
-- loadstring() doesn't allow it even though lua/loadfile accepts it.
-- replace with a new line to keep the number of lines the same.
local editorText = editor:GetText():gsub("^#!.-\n", "\n")
local id = editor:GetId()
local filePath = DebuggerMakeFileName(editor, openDocuments[id].filePath)
local _, errMsg, line_num = wxlua.CompileLuaScript(editorText, filePath)
local func, line_num, errMsg, _ = loadstring(editorText, filePath), -1
if not func then
_, errMsg, line_num = wxlua.CompileLuaScript(editorText, filePath)
end
if ide.frame.menuBar:IsChecked(ID_CLEAROUTPUT) then ClearOutput() end
compileTotal = compileTotal + 1
if line_num > -1 then
DisplayOutput("Compilation error on line "..tostring(line_num)..":\n"..
errMsg:gsub("Lua:.-\n", "").."\n")
if not quiet then editor:GotoLine(line_num-1) end
else
if not quiet then DisplayOutput("Compilation successful.\n") end
compileOk = compileOk + 1
if not quiet then
DisplayOutput(("Compilation successful; %.0f%% success rate (%d/%d).\n")
:format(compileOk/compileTotal*100, compileOk, compileTotal))
end
end
return line_num == -1 -- return true if it compiled ok
return line_num == -1, editorText -- return true if it compiled ok
end
------------------
@@ -450,28 +469,22 @@ function GetOpenFiles()
local wxfname = wx.wxFileName(document.filePath)
wxfname:Normalize()
table.insert(opendocs,{fname=wxfname:GetFullPath(),id=document.index,
cursorpos = document.editor:GetCurrentPos()})
table.insert(opendocs, {filename=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
return opendocs, {index = (id and openDocuments[id].index or 0)}
end
function SetOpenFiles(nametab,index)
function SetOpenFiles(nametab,params)
for i,doc in ipairs(nametab) do
local editor = LoadFile(doc.filename,nil,true)
local editor = LoadFile(doc.filename,nil,true,true) -- skip selection
if editor then
editor:SetCurrentPos(doc.cursorpos or 0)
editor:SetSelectionStart(doc.cursorpos or 0)
@@ -479,7 +492,8 @@ function SetOpenFiles(nametab,index)
editor:EnsureCaretVisible()
end
end
notebook:SetSelection(index or 0)
notebook:SetSelection(params and params.index or 0)
SetEditorSelection()
end
local beforeFullScreenPerspective
@@ -496,10 +510,162 @@ function ShowFullScreen(setFullScreen)
uimgr:GetPane("toolBar"):Show(not setFullScreen)
uimgr:Update()
frame:ShowFullScreen(setFullScreen)
-- protect from systems that don't have ShowFullScreen (GTK on linux?)
pcall(function() frame:ShowFullScreen(setFullScreen) end)
end
local function restoreFiles(files)
-- open files, but ignore some functions that are not needed;
-- as we may be opening multiple files, it doesn't make sense to
-- select editor and do some other similar work after each file.
local noop, func = function() end, LoadFile
local genv = {SetEditorSelection = noop, SettingsAppendFileToHistory = noop}
setmetatable(genv, {__index = _G})
local env = getfenv(func)
setfenv(func, genv)
-- provide fake index so that it doesn't activate it as the index may be not
-- quite correct if some of the existing files are already open in the IDE.
SetOpenFiles(files, {index = #files + notebook:GetPageCount()})
setfenv(func, env)
end
function ProjectConfig(dir, config)
if config then ide.session.projects[dir] = config
else return unpack(ide.session.projects[dir] or {}) end
end
function SetOpenTabs(params)
local recovery, nametab = loadstring("return "..params.recovery)
if recovery then recovery, nametab = pcall(recovery) end
if not recovery then
DisplayOutput("Can't process auto-recovery record; invalid format: "..nametab.."\n")
return
end
DisplayOutput("Found auto-recovery record and restored saved session.\n")
for _,doc in ipairs(nametab) do
local editor = doc.filename and LoadFile(doc.filename,nil,true,true) or NewFile()
local opendoc = openDocuments[editor:GetId()]
if doc.content then
notebook:SetPageText(opendoc.index, doc.tabname)
editor:SetText(doc.content)
if doc.filename and doc.modified < opendoc.modTime:GetTicks() then
DisplayOutput("File '"..doc.filename.."' has more recent timestamp than restored '"..doc.tabname.."'."
.." Please review before saving.\n")
end
end
editor:SetCurrentPos(doc.cursorpos or 0)
editor:SetSelectionStart(doc.cursorpos or 0)
editor:SetSelectionEnd(doc.cursorpos or 0)
editor:EnsureCaretVisible()
end
notebook:SetSelection(params and params.index or 0)
SetEditorSelection()
end
local function getOpenTabs()
local opendocs = {}
for id, document in pairs(ide.openDocuments) do
table.insert(opendocs, {
filename = document.filePath,
tabname = notebook:GetPageText(document.index),
modified = document.modTime and document.modTime:GetTicks(), -- get number of seconds
content = document.isModified and document.editor:GetText() or nil,
id = document.index, cursorpos = document.editor:GetCurrentPos()})
end
-- to keep tab order
table.sort(opendocs, function(a,b) return (a.id < b.id) end)
local id = GetEditor()
id = id and id:GetId()
return opendocs, {index = (id and openDocuments[id].index or 0)}
end
function SetAutoRecoveryMark()
ide.session.lastupdated = os.time()
end
local function saveAutoRecovery(event)
if not ide.config.autorecoverinactivity or not ide.session.lastupdated then return end
if ide.session.lastupdated < (ide.session.lastsaved or 0)
or ide.session.lastupdated + ide.config.autorecoverinactivity > os.time()
then return end
-- find all open modified files and save them
local opentabs, params = getOpenTabs()
if #opentabs > 0 then
params.recovery = require('mobdebug').line(opentabs, {comment = false})
SettingsSaveAll()
SettingsSaveFileSession({}, params)
ide.settings:Flush()
end
ide.session.lastsaved = os.time()
ide.frame.statusBar:SetStatusText("Saved auto-recover at "..os.date("%H:%M:%S")..".", 1)
end
function StoreRestoreProjectTabs(curdir, newdir)
local win = ide.osname == 'Windows'
local interpreter = ide.interpreter.fname
local current, closing, restore = notebook:GetSelection(), 0, false
if curdir and #curdir > 0 then
local lowcurdir = win and string.lower(curdir) or curdir
local lownewdir = win and string.lower(newdir) or newdir
local projdocs, closdocs = {}, {}
for _, document in ipairs(GetOpenFiles()) do
local dpath = win and string.lower(document.filename) or document.filename
if dpath:find(lowcurdir, 1, true) then
table.insert(projdocs, document)
closing = closing + (document.id < current and 1 or 0)
-- only close if the file is not in new project as it would be reopened
if not dpath:find(lownewdir, 1, true) then
table.insert(closdocs, document)
end
elseif document.id == current then restore = true end
end
-- adjust for the number of closing tabs on the left from the current one
current = current - closing
-- save opened files from this project
ProjectConfig(curdir, {projdocs,
{index = notebook:GetSelection() - current, interpreter = interpreter}})
-- close pages for those files that match the project in the reverse order
-- (as ids shift when pages are closed)
for i = #closdocs, 1, -1 do ClosePage(closdocs[i].id) end
end
local files, params = ProjectConfig(newdir)
if files then restoreFiles(files) end
if params and params.interpreter and ide.interpreter.fname ~= params.interpreter then
ProjectSetInterpreter(params.interpreter) -- set the interpreter
end
local index = params and params.index
if notebook:GetPageCount() == 0 then NewFile()
elseif restore and current >= 0 then notebook:SetSelection(current)
elseif index and index >= 0 and files[index+1] then
-- move the editor tab to the front with the file from the config
LoadFile(files[index+1].filename, nil, true)
SetEditorSelection() -- activate the editor in the active tab
end
-- remove current config as it may change; the current configuration is
-- stored with the general config.
-- The project configuration will be updated when the project is changed.
ProjectConfig(newdir, {})
end
function CloseWindow(event)
-- if the app is already exiting, then help it exit; wxwidgets on Windows
-- is supposed to report Shutdown/logoff events by setting CanVeto() to
-- false, but it doesn't happen. We simply leverage the fact that
-- CloseWindow is called several times in this case and exit. Similar
-- behavior has been also seen on Linux, so this logic applies everywhere.
if ide.exitingProgram then os.exit() end
ide.exitingProgram = true -- don't handle focus events
if not SaveOnExit(event:CanVeto()) then
@@ -509,15 +675,24 @@ function CloseWindow(event)
end
ShowFullScreen(false)
SettingsSaveProjectSession(FileTreeGetProjects())
SettingsSaveFileSession(GetOpenFiles())
SettingsSaveView()
SettingsSaveFramePosition(ide.frame, "MainFrame")
SettingsSaveEditorSettings()
DebuggerCloseWatchWindow()
DebuggerCloseStackWindow()
DebuggerShutdown()
SettingsSaveAll()
if DebuggerCloseWatchWindow then DebuggerCloseWatchWindow() end
if DebuggerCloseStackWindow then DebuggerCloseStackWindow() end
if DebuggerShutdown then DebuggerShutdown() end
ide.settings:delete() -- always delete the config
if ide.session.timer then ide.session.timer:Stop() end
event:Skip()
-- without explicit exit() the IDE crashes with SIGILL exception when closed
-- on MacOS compiled under 64bit with wxwidgets 2.9.3
if ide.osname == "Macintosh" then os.exit() end
end
frame:Connect(wx.wxEVT_CLOSE_WINDOW, CloseWindow)
frame:Connect(wx.wxEVT_TIMER, saveAutoRecovery)
if ide.config.autorecoverinactivity then
ide.session.timer = wx.wxTimer(frame)
-- check at least 5s to be never more than 5s off
ide.session.timer:Start(math.min(5, ide.config.autorecoverinactivity)*1000)
end

View File

@@ -17,26 +17,43 @@ debugger.watchWindow = nil -- the watchWindow, nil when not created
debugger.watchCtrl = nil -- the child ctrl in the watchWindow
debugger.stackWindow = nil -- the stackWindow, nil when not created
debugger.stackCtrl = nil -- the child ctrl in the stackWindow
debugger.hostname = (function() -- check what address is resolvable
local addr = wx.wxIPV4address()
debugger.hostname = ide.config.debugger.hostname or (function()
local addr = wx.wxIPV4address() -- check what address is resolvable
for _, host in ipairs({wx.wxGetHostName(), wx.wxGetFullHostName()}) do
if addr:Hostname(host) then return host end
if host and #host > 0 and addr:Hostname(host) then return host end
end
return "localhost" -- last resort; no known good hostname
end)()
local notebook = ide.frame.notebook
local function updateWatchesSync()
local function updateWatchesSync(num)
local watchCtrl = debugger.watchCtrl
if watchCtrl and debugger.server
and not debugger.running and not debugger.scratchpad then
for idx = 0, watchCtrl:GetItemCount() - 1 do
local expression = watchCtrl:GetItemText(idx)
local _, values, error = debugger.evaluate(expression)
if error then error = error:gsub("%[.-%]:%d+:%s+","")
elseif #values == 0 then values = {'nil'} end
watchCtrl:SetItem(idx, 1, error and ('error: '..error) or values[1])
if not num or idx == num then
local expression = watchCtrl:GetItemText(idx)
local _, values, error = debugger.evaluate(expression)
if error then error = error:gsub("%[.-%]:%d+:%s+","")
elseif #values == 0 then values = {'nil'} end
local newval = error and ('error: '..error) or values[1]
-- get the current value from a list item
do local litem = wx.wxListItem()
litem:SetMask(wx.wxLIST_MASK_TEXT)
litem:SetId(idx)
litem:SetColumn(1)
watchCtrl:GetItem(litem)
watchCtrl:SetItemBackgroundColour(idx,
watchCtrl:GetItem(litem) and newval ~= litem:GetText()
and ide.config.styles.caretlinebg
and wx.wxColour(unpack(ide.config.styles.caretlinebg.bg))
or watchCtrl:GetBackgroundColour())
end
watchCtrl:SetItem(idx, 1, newval)
end
end
end
end
@@ -57,8 +74,14 @@ local function updateStackSync()
local stackCtrl = debugger.stackCtrl
if stackCtrl and debugger.server
and not debugger.running and not debugger.scratchpad then
local stack = debugger.stack()
if not stack or #stack == 0 then stackCtrl:DeleteAllItems(); return end
local stack, _, err = debugger.stack()
if not stack or #stack == 0 then
stackCtrl:DeleteAllItems()
if err then -- report an error if any
stackCtrl:AppendItem(stackCtrl:AddRoot("Stack"), "Error: " .. err, 0)
end
return
end
stackCtrl:Freeze()
stackCtrl:DeleteAllItems()
local params = {comment = false, nocode = true}
@@ -109,14 +132,20 @@ local function updateStackSync()
end
local function updateStackAndWatches()
-- check if the debugger is running and may be waiting for a response.
-- allow that request to finish, otherwise updateWatchesSync() does nothing.
if debugger.running then debugger.update() end
if debugger.server and not debugger.running then
copas.addthread(function() updateStackSync() updateWatchesSync() end)
end
end
local function updateWatches()
local function updateWatches(num)
-- check if the debugger is running and may be waiting for a response.
-- allow that request to finish, otherwise updateWatchesSync() does nothing.
if debugger.running then debugger.update() end
if debugger.server and not debugger.running then
copas.addthread(function() updateWatchesSync() end)
copas.addthread(function() updateWatchesSync(num) end)
end
end
@@ -136,24 +165,20 @@ local function killClient()
end
end
local function activateDocument(fileName, line)
if not fileName then return end
local function activateDocument(file, line)
if not file then return end
if not wx.wxIsAbsolutePath(fileName) then
fileName = wx.wxGetCwd().."/"..fileName
end
if wx.__WXMSW__ then
fileName = wx.wxUnix2DosFilename(fileName)
if not wx.wxIsAbsolutePath(file) and debugger.basedir then
file = debugger.basedir .. file
end
local activated
local indebugger = file:find('mobdebug%.lua$')
local fileName = wx.wxFileName(file)
for _, document in pairs(ide.openDocuments) do
local editor = document.editor
-- for running in cygwin, use same type of separators
local filePath = string.gsub(document.filePath, "\\", "/")
local fileName = string.gsub(fileName, "\\", "/")
if string.upper(filePath) == string.upper(fileName) then
-- skip those tabs that may have file without names (untitled.lua)
if document.filePath and fileName:SameAs(wx.wxFileName(document.filePath)) then
local editor = document.editor
local selection = document.index
notebook:SetSelection(selection)
SetEditorSelection(selection)
@@ -167,7 +192,22 @@ local function activateDocument(fileName, line)
end
end
return activated ~= nil, activated
if not activated and not indebugger and ide.config.editor.autoactivate then
-- found file, but can't activate yet (because this part may be executed
-- in a different co-routine), so schedule pending activation.
if wx.wxFileName(file):FileExists() then
debugger.activate = {file, line}
return true -- report successful activation, even though it's pending
end
if not debugger.missing[file] then -- only report files once per session
debugger.missing[file] = true
DisplayOutput(("Couldn't activate file '%s' for debugging; continuing without it.\n")
:format(file))
end
end
return activated ~= nil
end
local function reSetBreakpoints()
@@ -191,13 +231,16 @@ local function reSetBreakpoints()
end
debugger.shell = function(expression, isstatement)
if debugger.server and not debugger.running then
-- check if the debugger is running and may be waiting for a response.
-- allow that request to finish, otherwise updateWatchesSync() does nothing.
if debugger.running then debugger.update() end
if debugger.server and not debugger.running and not debugger.scratchpad then
copas.addthread(function ()
-- exec command is not expected to return anything.
-- eval command returns 0 or more results.
-- 'values' has a list of serialized results returned.
-- as it is not possible to distinguish between 0 and nil returned,
-- 'nil' is always returned in this case.
-- as it is not possible to distinguish between 0 results and one
-- 'nil' value returned, 'nil' is always returned in this case.
-- the first value returned by eval command is not used;
-- this may need to be taken into account by other debuggers.
local addedret, forceexpression = true, expression:match("^%s*=%s*")
@@ -205,6 +248,7 @@ debugger.shell = function(expression, isstatement)
local _, values, err = debugger.evaluate(expression)
if not forceexpression and err and
(err:find("'<eof>' expected near '") or
err:find("'%(' expected near") or
err:find("unexpected symbol near '")) then
_, values, err = debugger.execute(expression)
addedret = false
@@ -214,12 +258,29 @@ debugger.shell = function(expression, isstatement)
if addedret then err = err:gsub('^%[string "return ', '[string "') end
DisplayShellErr(err)
elseif addedret or #values > 0 then
if forceexpression then -- display elements as multi-line
local mobdebug = require "mobdebug"
for i,v in pairs(values) do -- stringify each of the returned values
local func = loadstring('return '..v) -- deserialize the value first
if func then -- if it's deserialized correctly
values[i] = (forceexpression and i > 1 and '\n' or '') ..
mobdebug.line(func(), {nocode = true, comment = 0,
-- if '=' is used, then use multi-line serialized output
indent = forceexpression and ' ' or nil})
end
end
end
-- if empty table is returned, then show nil if this was an expression
if #values == 0 and (forceexpression or not isstatement) then
values = {'nil'}
end
DisplayShell((table.unpack or unpack)(values))
end
-- refresh Stack and Watch windows if executed a statement (and no err)
if isstatement and not err and not addret and #values == 0 then
updateStackSync() updateWatchesSync() end
end)
end
end
@@ -235,19 +296,34 @@ debugger.listen = function()
return
end
copas.setErrorHandler(function(error)
DisplayOutput("Can't start debugging session due to internal error '" .. error .. "'.\n")
debugger.terminate()
end)
local options = debugger.options or {}
if not debugger.scratchpad then SetAllEditorsReadOnly(true) end
local wxfilepath = GetEditorFileAndCurInfo()
local startfile = options.startfile or wxfilepath:GetFullPath()
local basedir = options.basedir
or FileTreeGetDir()
or wxfilepath:GetPath(wx.wxPATH_GET_VOLUME + wx.wxPATH_GET_SEPARATOR)
-- guarantee that the path has a trailing separator
debugger.basedir = wx.wxFileName.DirName(basedir):GetFullPath()
debugger.server = copas.wrap(skt)
debugger.socket = skt
debugger.loop = false
debugger.scratchable = false
debugger.stats = {line = 0}
debugger.missing = {}
local wxfilepath = GetEditorFileAndCurInfo()
local startfile = options.startfile or options.startwith
or (wxfilepath and wxfilepath:GetFullPath())
if not startfile then
DisplayOutput("Can't start debugging without an opened file or with the current file not being saved ('untitled.lua').\n")
return debugger.terminate()
end
local startpath = wx.wxFileName(startfile):GetPath(wx.wxPATH_GET_VOLUME + wx.wxPATH_GET_SEPARATOR)
local basedir = options.basedir or FileTreeGetDir() or startpath
-- guarantee that the path has a trailing separator
debugger.basedir = wx.wxFileName.DirName(basedir):GetFullPath()
-- load the remote file into the debugger
-- set basedir first, before loading to make sure that the path is correct
@@ -255,9 +331,15 @@ debugger.listen = function()
reSetBreakpoints()
if (options.run) then
local file, line = debugger.handle("run")
activateDocument(file, line)
if (options.startwith) then
local file, line, err = debugger.loadfile(options.startwith)
if err then
DisplayOutput(("Can't run the entry point script (%s). Compilation error:\n%s\n")
:format(options.startwith, err))
return debugger.terminate()
end
elseif (options.run) then
-- do nothing here
elseif (debugger.scratchpad) then
debugger.scratchpad.updated = true
else
@@ -267,35 +349,28 @@ debugger.listen = function()
-- 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 activated then
activated = activateDocument(debugger.basedir..file, line)
end
local activated = activateDocument(file, line)
-- if not found, check using full file path and reset basedir
if not activated then
local path = wxfilepath:GetPath(wx.wxPATH_GET_VOLUME + wx.wxPATH_GET_SEPARATOR)
activated = activateDocument(path..file, line)
if activated then
debugger.basedir = path
debugger.handle("basedir " .. debugger.basedir)
-- reset breakpoints again as basedir has changed
reSetBreakpoints()
end
-- if not found, check using full file path and reset basedir
if not activated and not wx.wxIsAbsolutePath(file) then
activated = activateDocument(startpath..file, line)
if activated then
debugger.basedir = startpath
debugger.handle("basedir " .. debugger.basedir)
-- reset breakpoints again as basedir has changed
reSetBreakpoints()
end
end
if not activated then
DisplayOutput(("Can't find file '%s' to activate for debugging; open the file in the editor before debugging.\n")
DisplayOutput(("Can't find file '%s' in the current project to activate for debugging. Update the project or open the file in the editor before debugging.\n")
:format(file))
return debugger.terminate()
end
-- debugger may still be available for scratchpad,
-- if the interpreter signals scratchpad support, so enable it.
debugger.scratchable = ide.interpreter.scratchextloop ~= nil
elseif err then
DisplayOutput(("Can't debug the script in the active editor window. Compilation error:\n%s\n")
:format(err))
@@ -315,6 +390,16 @@ debugger.listen = function()
DisplayOutput(("Debugging session started in '%s'.\n")
:format(debugger.basedir))
if (options.runstart) then
ClearAllCurrentLineMarkers()
debugger.run()
end
if (options.run) then
local file, line = debugger.handle("run")
activateDocument(file, line)
end
end)
debugger.listening = true
end
@@ -349,10 +434,8 @@ debugger.exec = function(command)
DebuggerStop()
return
else
if debugger.basedir and not wx.wxIsAbsolutePath(file) then
file = debugger.basedir .. file
end
if activateDocument(file, line) then
debugger.stats.line = debugger.stats.line + 1
if debugger.loop then
updateStackSync()
updateWatchesSync()
@@ -361,7 +444,15 @@ debugger.exec = function(command)
return
end
else
out = "out" -- redo now trying to get out of this file
-- redo now; if the call is from the debugger, then repeat
-- the same command, except when it was "run" (switch to 'step');
-- this is needed to "break" execution that happens in on() call.
-- in all other cases get out of this file.
-- don't get out of "mobdebug", because it may happen with
-- start() or on() call, which will get us out of the current
-- file, which is not what we want.
out = (file:find('mobdebug%.lua$')
and (command == 'run' and 'step' or command) or "out")
end
end
end
@@ -381,7 +472,15 @@ end
debugger.loadstring = function(file, string)
return debugger.handle("loadstring '" .. file .. "' " .. string)
end
debugger.update = function() copas.step(0) end
debugger.update = function()
copas.step(0)
-- if there are any pending activations
if debugger.activate then
local file, line = (table.unpack or unpack)(debugger.activate)
if LoadFile(file) then activateDocument(file, line) end
debugger.activate = nil
end
end
debugger.terminate = function()
if debugger.server then
if debugger.pid then -- if there is PID, try local kill
@@ -427,6 +526,17 @@ end
debugger.breakpoint = function(file, line, state)
debugger.handleAsync((state and "setb " or "delb ") .. file .. " " .. line)
end
debugger.quickeval = function(var, callback)
if debugger.server and not debugger.running and not debugger.scratchpad then
copas.addthread(function ()
local _, values, err = debugger.evaluate(var)
local val = err
and err:gsub("%[.-%]:%d+:%s*","error: ")
or (var .. " = " .. (#values > 0 and values[1] or 'nil'))
if callback then callback(val) end
end)
end
end
----------------------------------------------
-- public api
@@ -450,7 +560,13 @@ function DebuggerStop()
ShellSupportRemote(nil)
ClearAllCurrentLineMarkers()
DebuggerScratchpadOff()
DisplayOutput("Debugging session completed.\n")
DisplayOutput(("Debugging session completed (traced %d instruction%s).\n")
:format(debugger.stats.line, debugger.stats.line == 1 and '' or 's'))
else
-- it's possible that the application couldn't start, or that the
-- debugger in the application didn't start, which means there is
-- no debugger.server, but scratchpad may still be on. Turn it off.
DebuggerScratchpadOff()
end
end
@@ -474,17 +590,18 @@ end
-- of it and if done inside a function, icons do not work as expected
local imglist = wx.wxImageList(16,16)
do
local getBitmap = (ide.app.createbitmap or wx.wxArtProvider.GetBitmap)
local size = wx.wxSize(16,16)
-- 0 = stack call
imglist:Add((ide.app.createbitmap or wx.wxArtProvider.GetBitmap)(wx.wxART_GO_FORWARD, wx.wxART_OTHER, size))
imglist:Add(getBitmap(wx.wxART_GO_FORWARD, wx.wxART_OTHER, size))
-- 1 = local variables
imglist:Add((ide.app.createbitmap or wx.wxArtProvider.GetBitmap)(wx.wxART_LIST_VIEW, wx.wxART_OTHER, size))
imglist:Add(getBitmap(wx.wxART_LIST_VIEW, wx.wxART_OTHER, size))
-- 2 = upvalues
imglist:Add((ide.app.createbitmap or wx.wxArtProvider.GetBitmap)(wx.wxART_REPORT_VIEW, wx.wxART_OTHER, size))
imglist:Add(getBitmap(wx.wxART_REPORT_VIEW, wx.wxART_OTHER, size))
end
function DebuggerCreateStackWindow()
if (debugger.stackWindow) then return end
if (debugger.stackWindow) then return updateStackAndWatches() end
local width = 360
local stackWindow = wx.wxFrame(ide.frame, wx.wxID_ANY,
"Stack Window",
@@ -524,7 +641,7 @@ function DebuggerCreateStackWindow()
local strval = mobdebug.line(value, {comment = false, nocode = true})
local text = type(name) == "number"
and (num == name and strval or ("[%s] = %s"):format(name, strval))
or ("%s = %s"):format(name, strval)
or ("%s = %s"):format(tostring(name), strval)
local item = stackCtrl:AppendItem(item_id, text, image)
if checkIfExpandable(value, item) then
stackCtrl:SetItemHasChildren(item, true)
@@ -542,7 +659,7 @@ function DebuggerCreateStackWindow()
end
function DebuggerCreateWatchWindow()
if (debugger.watchWindow) then return end
if (debugger.watchWindow) then return updateWatches() end
local width = 360
local watchWindow = wx.wxFrame(ide.frame, wx.wxID_ANY,
"Watch Window",
@@ -552,9 +669,9 @@ function DebuggerCreateWatchWindow()
debugger.watchWindow = watchWindow
local watchMenu = wx.wxMenu{
{ ID_ADDWATCH, "&Add Watch" },
{ ID_ADDWATCH, "&Add Watch\tIns" },
{ ID_EDITWATCH, "&Edit Watch\tF2" },
{ ID_REMOVEWATCH, "&Remove Watch" },
{ ID_REMOVEWATCH, "&Remove Watch\tDel" },
{ ID_EVALUATEWATCH, "Evaluate &Watches" }}
local watchMenuBar = wx.wxMenuBar()
@@ -593,6 +710,8 @@ function DebuggerCreateWatchWindow()
return -1
end
local defaultExpr = ""
watchWindow:Connect(wx.wxEVT_CLOSE_WINDOW,
function (event)
DebuggerCloseWatchWindow()
@@ -604,7 +723,7 @@ function DebuggerCreateWatchWindow()
watchWindow:Connect(ID_ADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
function ()
local row = watchCtrl:InsertItem(watchCtrl:GetItemCount(), "Expr")
watchCtrl:SetItem(row, 0, "Expr")
watchCtrl:SetItem(row, 0, defaultExpr)
watchCtrl:SetItem(row, 1, "Value")
watchCtrl:EditLabel(row)
end)
@@ -642,22 +761,42 @@ function DebuggerCreateWatchWindow()
watchCtrl:Connect(wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT,
function (event)
if #(event:GetText()) > 0 then
watchCtrl:SetItem(event:GetIndex(), 0, event:GetText())
updateWatches()
local row = event:GetIndex()
if event:IsEditCancelled() then
if watchCtrl:GetItemText(row) == defaultExpr then
watchCtrl:DeleteItem(row)
end
else
watchCtrl:SetItem(row, 0, event:GetText())
updateWatches(row)
end
event:Skip()
end)
end
function DebuggerMakeFileName(editor, filePath)
if not filePath then
filePath = "file"..tostring(editor)
function DebuggerAddWatch(watch)
if (not debugger.watchWindow) then DebuggerCreateWatchWindow() end
local watchCtrl = debugger.watchCtrl
-- check if this expression is already on the list
for idx = 0, watchCtrl:GetItemCount() - 1 do
if watchCtrl:GetItemText(idx) == watch then return end
end
return filePath
local row = watchCtrl:InsertItem(watchCtrl:GetItemCount(), "Expr")
watchCtrl:SetItem(row, 0, watch)
watchCtrl:SetItem(row, 1, "Value")
updateWatches(row)
end
function DebuggerMakeFileName(editor, filePath)
return filePath or ide.config.default.fullname
end
function DebuggerToggleBreakpoint(editor, line)
-- ignore requests to toggle when the debugger is running
if debugger.server and debugger.running then return end
local markers = editor:MarkerGet(line)
if markers >= CURRENT_LINE_MARKER_VALUE then
markers = markers - CURRENT_LINE_MARKER_VALUE
@@ -679,51 +818,68 @@ end
-- scratchpad functions
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
function DebuggerRefreshScratchpad()
if debugger.scratchpad and debugger.scratchpad.updated then
local scratchpadEditor = debugger.scratchpad.editor
local compiled, code = CompileProgram(scratchpadEditor, true)
if not compiled then return end
if debugger.scratchpad.running then
-- break the current execution first
-- don't try too frequently to avoid overwhelming the debugger
local now = os.clock()
local now = TimeGet()
if now - debugger.scratchpad.running > 0.250 then
debugger.breaknow()
debugger.scratchpad.running = now
end
else
local clear = ide.frame.menuBar:IsChecked(ID_CLEAROUTPUT)
local scratchpadEditor = debugger.scratchpad.editor
local code = scratchpadEditor:GetText()
local filePath = DebuggerMakeFileName(scratchpadEditor,
ide.openDocuments[scratchpadEditor:GetId()].filePath)
-- this is a special error message that is generated at the very end
-- of each script to avoid exiting the (debugee) scratchpad process.
-- these errors are handled and not reported to the user
local errormsg = 'execution suspended at ' .. os.clock()
local errormsg = 'execution suspended at ' .. TimeGet()
local stopper = "\ndo error('" .. errormsg .. "') end"
-- store if interpreter requires a special handling for external loop
local extloop = ide.interpreter.scratchextloop
local function reloadScratchpadCode()
debugger.scratchpad.running = os.clock()
debugger.scratchpad.running = TimeGet()
debugger.scratchpad.updated = false
local _, _, err = debugger.loadstring(filePath, code .. stopper)
local prefix = "Compilation error"
debugger.scratchpad.runs = (debugger.scratchpad.runs or 0) + 1
if clear then ClearOutput() end
-- the code can be running in two ways under scratchpad:
-- 1. controlled by the application, requires stopper (most apps)
-- 2. controlled by some external loop (for example, love2d).
-- in the first case we need to reload the app after each change
-- in the second case, we need to load the app once and then
-- "execute" new code to reflect the changes (with some limitations).
local _, _, err
if extloop then -- if the execution is controlled by an external loop
if debugger.scratchpad.runs == 1
then _, _, err = debugger.loadstring(filePath, code)
else _, _, err = debugger.execute(code) end
else _, _, err = debugger.loadstring(filePath, code .. stopper) end
-- when execute() is used, it's not possible to distinguish between
-- compilation and run-time error, so just report as "Scratchpad error"
local prefix = extloop and "Scratchpad error" or "Compilation error"
if not err then
_, _, err = debugger.handle("run")
prefix = "Execution error"
end
if err and not err:find(errormsg) then
local line = err:match('.*%[string "[%w:/%\\_%-%.]+"%]:(%d+)%s*:')
-- check if the line number in the error matches the line we added
-- to stop the script; if so, compile it the usual way and report.
-- the usual way is not used all the time because it is slow
if prefix == "Compilation error" and
tonumber(line) == scratchpadEditor:GetLineCount()+1 then
_, err, line = wxlua.CompileLuaScript(code, filePath)
err = err:gsub("Lua:.-\n", "") -- remove "syntax error" part
local fragment, line = err:match('.-%[string "([^\010\013]+)"%]:(%d+)%s*:')
-- make the code shorter to better see the error message
if prefix == "Scratchpad error" and fragment and #fragment > 30 then
err = err:gsub(q(fragment), function(s) return s:sub(1,30)..'...' end)
end
DisplayOutput(prefix .. (line and " on line " .. line or "") .. ":\n"
.. err:gsub('stack traceback:.+', ''):gsub('\n+$', '') .. "\n")
@@ -756,6 +912,8 @@ function DebuggerScratchpadOn(editor)
local scratchpadEditor = editor
scratchpadEditor:StyleSetUnderline(numberStyle, true)
debugger.scratchpad.margin = scratchpadEditor:GetMarginWidth(0) +
scratchpadEditor:GetMarginWidth(1) + scratchpadEditor:GetMarginWidth(2)
scratchpadEditor:Connect(wxstc.wxEVT_STC_MODIFIED, function(event)
local evtype = event:GetModificationType()
@@ -800,8 +958,8 @@ function DebuggerScratchpadOn(editor)
end
scratchpad.start = nstart + 1
scratchpad.length = nend - nstart - 1
scratchpad.origin = tonumber(scratchpadEditor:GetTextRange(nstart+1,nend))
if scratchpad.origin then
scratchpad.origin = scratchpadEditor:GetTextRange(nstart+1,nend)
if tonumber(scratchpad.origin) then
scratchpad.point = point
scratchpadEditor:CaptureMouse()
end
@@ -823,31 +981,52 @@ function DebuggerScratchpadOn(editor)
-- record the fact that we are over a number or dragging slider
scratchpad.over = scratchpad and
(ipoint or (bit.band(scratchpadEditor:GetStyleAt(pos),31) == numberStyle))
(ipoint ~= nil or (bit.band(scratchpadEditor:GetStyleAt(pos),31) == numberStyle))
if ipoint then
-- calculate difference in point position
local dx = point.x - ipoint.x
local dy = - (point.y - ipoint.y) -- invert dy as y increases down
-- re-calculate the value
local startpos = scratchpad.start
local endpos = scratchpad.start+scratchpad.length
local num = tonumber(scratchpad.origin) + dx/10
-- calculate difference in point position
local dx = point.x - ipoint.x
-- calculate the number of decimal digits after the decimal point
local origin = scratchpad.origin
local decdigits = #(origin:match('%.(%d+)') or '')
-- calculate new value
local value = tonumber(origin) + dx * 10^-decdigits
-- convert new value back to string to check the number of decimal points
-- this is needed because the rate of change is determined by the
-- current value. For example, for number 1, the next value is 2,
-- but for number 1.1, the next is 1.2 and for 1.01 it is 1.02.
-- But if 1.01 becomes 1.00, the both zeros after the decimal point
-- need to be preserved to keep the increment ratio the same when
-- the user wants to release the slider and start again.
origin = tostring(value)
local newdigits = #(origin:match('%.(%d+)') or '')
if decdigits ~= newdigits then
origin = origin .. (origin:find('%.') and '' or '.') .. ("0"):rep(decdigits-newdigits)
end
-- update length
scratchpad.length = string.len(num)
scratchpad.length = #origin
-- update the value in the document
scratchpadEditor:SetTargetStart(startpos)
scratchpadEditor:SetTargetEnd(endpos)
scratchpadEditor:ReplaceTarget("" .. num)
scratchpadEditor:ReplaceTarget(origin)
else event:Skip() end
end)
scratchpadEditor:Connect(wx.wxEVT_SET_CURSOR, function(event)
if (debugger.scratchpad and debugger.scratchpad.over) then
event:SetCursor(wx.wxCursor(wx.wxCURSOR_SIZEWE))
elseif debugger.scratchpad and ide.osname == 'Unix' then
-- restore the cursor manually on Linux since event:Skip() doesn't reset it
local ibeam = event:GetX() > debugger.scratchpad.margin
event:SetCursor(wx.wxCursor(ibeam and wx.wxCURSOR_IBEAM or wx.wxCURSOR_RIGHT_ARROW))
else event:Skip() end
end)
@@ -865,6 +1044,8 @@ function DebuggerScratchpadOff()
scratchpadEditor:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_LEFT_UP)
scratchpadEditor:Disconnect(wx.wxID_ANY, wx.wxID_ANY, wx.wxEVT_SET_CURSOR)
wx.wxSetCursor(wx.wxNullCursor) -- restore cursor
debugger.scratchpad = nil
debugger.terminate()

View File

@@ -18,7 +18,7 @@ local projcombobox = ide.frame.projpanel.projcombobox
local statusTextTable = { "OVR?", "R/O?", "Cursor Pos" }
-- set funclist font to be the same as the combobox in the project dropdown
funclist:SetFont(projcombobox:GetFont())
funclist:SetFont(ide.font.fNormal)
local function updateStatusText(editor)
local texts = { "", "", "" }
@@ -27,9 +27,10 @@ local function updateStatusText(editor)
local line = editor:LineFromPosition(pos)
local col = 1 + pos - editor:PositionFromLine(line)
texts = { iff(editor:GetOvertype(), "OVR", "INS"),
texts = {
iff(editor:GetOvertype(), "OVR", "INS"),
iff(editor:GetReadOnly(), "R/O", "R/W"),
"Ln "..tostring(line + 1).." Col "..tostring(col) }
"Ln: "..tostring(line + 1).." Col: "..tostring(col) }
end
if ide.frame then
@@ -139,8 +140,6 @@ function SetEditorSelection(selection)
statusBar:SetStatusText("",1)
ide.frame:SetTitle(getFileTitle(editor))
FileTreeMarkSelected('')
if editor then
if funclist:IsEmpty() then funclist:Append('Jump to a function definition...', 0) end
funclist:SetSelection(0)
@@ -151,7 +150,11 @@ function SetEditorSelection(selection)
if openDocuments[id] and openDocuments[id].filePath then
FileTreeMarkSelected(openDocuments[id].filePath)
end
else
FileTreeMarkSelected('')
end
SetAutoRecoveryMark()
end
function GetEditorFileAndCurInfo(nochecksave)
@@ -162,9 +165,7 @@ function GetEditorFileAndCurInfo(nochecksave)
local id = editor:GetId()
local filepath = openDocuments[id].filePath
if (nochecksave and not filepath) then
return
end
if not filepath then return end
local fn = wx.wxFileName(filepath)
fn:Normalize()
@@ -181,7 +182,8 @@ end
-- Set if the document is modified and update the notebook page text
function SetDocumentModified(id, modified)
local pageText = openDocuments[id].fileName or "untitled.lua"
if not openDocuments[id] then return end
local pageText = openDocuments[id].fileName or ide.config.default.fullname
if modified then
pageText = "* "..pageText
@@ -191,11 +193,108 @@ function SetDocumentModified(id, modified)
notebook:SetPageText(openDocuments[id].index, pageText)
end
function EditorAutoComplete(editor)
if not (editor and editor.spec) then return end
local pos = editor:GetCurrentPos()
-- don't do auto-complete in comments or strings.
-- the current position and the previous one have default style (0),
-- so we need to check two positions back.
local style = pos >= 2 and bit.band(editor:GetStyleAt(pos-2),31) or 0
if editor.spec.iscomment[style] or editor.spec.isstring[style] then return end
-- retrieve the current line and get a string to the current cursor position in the line
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)
elseif editor:AutoCompActive() then
editor:AutoCompCancel()
end
end
local function getValAtPosition(editor, pos)
local line = editor:LineFromPosition(pos)
local linetx = editor:GetLine(line)
local linestart = editor:PositionFromLine(line)
local localpos = pos-linestart
local ident = "([a-zA-Z_][a-zA-Z_0-9%.%:]*)"
local linetxtopos = linetx:sub(1,localpos)
linetxtopos = linetxtopos..")"
linetxtopos = linetxtopos:match(ident .. "%b()$")
local selected = editor:GetSelectionStart() ~= editor:GetSelectionEnd()
and pos >= editor:GetSelectionStart() and pos <= editor:GetSelectionEnd()
-- check if we have a selected text or an identifier
-- for an identifier, check fragments on the left and on the right.
-- this is to match 'io' in 'i^o.print' and 'io.print' in 'io.pr^int'.
-- remove square brackets to make tbl[index].x show proper values.
local start = linetx:sub(1,localpos)
:gsub("%b[]", function(s) return ("."):rep(#s) end)
:find(ident.."$")
-- check if the style is the right one; this is to ignore
-- comments, strings, numbers (to avoid '1 = 1'), keywords, and such
if start and not selected then
local style = bit.band(editor:GetStyleAt(linestart+start),31)
if editor.spec.iscomment[style]
or (MarkupIsAny and MarkupIsAny(style)) -- markup in comments
or editor.spec.isstring[style]
or style == wxstc.wxSTC_LUA_NUMBER
or style == wxstc.wxSTC_LUA_WORD then
-- don't do anything for strings or comments or numbers
return nil, linetxtopos
end
end
local right = linetx:sub(localpos+1,#linetx):match("^[a-zA-Z_0-9]*")
local var = selected and editor:GetSelectedText()
or (start and linetx:sub(start,localpos):gsub(":",".")..right or nil)
return var, linetxtopos
end
function EditorCallTip(editor, pos, x, y)
local var, linetxtopos = getValAtPosition(editor, pos)
local tip = linetxtopos and GetTipInfo(editor,linetxtopos.."(",false)
if ide.debugger and ide.debugger.server then
if var then
local limit = 128
ide.debugger.quickeval(var, function(val)
if #val > limit then val = val:sub(1, limit-3).."..." end
-- check if the mouse position is specified and the mouse has moved,
-- then don't show the tooltip as it's already too late for it.
if x and y then
local mpos = wx.wxGetMousePosition()
if mpos.x ~= x or mpos.y ~= y then return end
end
editor:CallTipShow(pos, val) end)
end
elseif tip then
editor:CallTipShow(pos, tip)
end
end
-- ----------------------------------------------------------------------------
-- Create an editor and add it to the notebook
function CreateEditor(name)
-- Create an editor
function CreateEditor()
local editor = wxstc.wxStyledTextCtrl(notebook, editorID,
wx.wxDefaultPosition, wx.wxDefaultSize,
wx.wxDefaultPosition, wx.wxSize(0, 0),
wx.wxBORDER_STATIC)
editorID = editorID + 1 -- increment so they're always unique
@@ -206,8 +305,8 @@ function CreateEditor(name)
editor:SetBufferedDraw(true)
editor:StyleClearAll()
editor:SetFont(ide.font)
editor:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.font)
editor:SetFont(ide.font.eNormal)
editor:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.font.eNormal)
editor:SetTabWidth(ide.config.editor.tabwidth or 4)
editor:SetIndent(ide.config.editor.tabwidth or 4)
@@ -224,8 +323,6 @@ function CreateEditor(name)
editor:SetCaretLineVisible(ide.config.editor.caretline and 1 or 0)
editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_SLOP, 3)
--editor:SetXCaretPolicy(wxstc.wxSTC_CARET_SLOP, 10)
--editor:SetYCaretPolicy(wxstc.wxSTC_CARET_SLOP, 3)
editor:SetMarginWidth(0, editor:TextWidth(32, "99999_")) -- line # margin
@@ -258,6 +355,10 @@ function CreateEditor(name)
editor:MarkerDefine(wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, wxstc.wxSTC_MARK_TCORNER, wx.wxWHITE, grey)
grey:delete()
if ide.config.editor.calltipdelay and ide.config.editor.calltipdelay > 0 then
editor:SetMouseDwellTime(ide.config.editor.calltipdelay)
end
editor:AutoCompSetIgnoreCase(ide.config.acandtip.ignorecase)
if (ide.config.acandtip.strategy > 0) then
editor:AutoCompSetAutoHide(0)
@@ -285,6 +386,8 @@ function CreateEditor(name)
editor:Connect(wxstc.wxEVT_STC_MODIFIED,
function (event)
SetAutoRecoveryMark()
if (editor.assignscache and editor:GetCurrentLine() ~= editor.assignscache.line) then
editor.assignscache = false
end
@@ -320,40 +423,97 @@ function CreateEditor(name)
local linetx = editor:GetLine(line)
local linestart = editor:PositionFromLine(line)
local localpos = pos-linestart
local linetxtopos = linetx:sub(1,localpos)
if (ch == char_CR and eol==2) or (ch == char_LF and eol==0) then
if (line > 0) then
local indent = editor:GetLineIndentation(line - 1)
if indent > 0 then
editor:SetLineIndentation(line, indent)
local tw = editor:GetTabWidth()
local ut = editor:GetUseTabs()
local indent = ut and (indent / tw) or indent
editor:GotoPos(pos+indent)
end
end
elseif ch == ("("):byte() then
local linedone = editor:GetLine(line - 1)
-- if the indentation is 0 and the current line is not empty
-- then take indentation from the current line (instead of the
-- previous one). This may happen when CR is hit at the beginning
-- of a line (rather than at the end).
if indent == 0 and not linetx:match("^[\010\013]*$") then
indent = editor:GetLineIndentation(line)
end
local tw = editor:GetTabWidth()
local ut = editor:GetUseTabs()
if ide.config.editor.smartindent
and editor.spec.isdecindent and editor.spec.isincindent then
local closed, blockend = editor.spec.isdecindent(linedone)
local opened = editor.spec.isincindent(linedone)
-- if the current block is already indented, skip reverse indenting
if (line > 1) and (closed > 0 or blockend > 0)
and editor:GetLineIndentation(line-2) > indent then
-- adjust opened first; this is needed when use ENTER after })
if blockend == 0 then opened = opened + closed end
closed, blockend = 0, 0
end
editor:SetLineIndentation(line-1, indent - tw * closed)
indent = indent + tw * (opened - blockend)
if indent < 0 then indent = 0 end
end
editor:SetLineIndentation(line, indent)
indent = ut and (indent / tw) or indent
editor:GotoPos(editor:GetCurrentPos()+indent)
end
elseif ch == ("("):byte() then
local tip = GetTipInfo(editor,linetxtopos,ide.config.acandtip.shorttip)
if tip then
editor:CallTipShow(pos,tip)
end
elseif ide.config.autocomplete then -- code completion prompt
local trigger = linetxtopos:match("["..editor.spec.sep.."%w_]+$")
if (trigger and (#trigger > 1 or trigger:match("[%.:]"))) then
-- defined in menu_edit.lua
local commandEvent = wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED,
ID_AUTOCOMPLETE)
wx.wxPostEvent(ide.frame, commandEvent)
ide.frame:AddPendingEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_AUTOCOMPLETE))
end
end
end)
editor:Connect(wxstc.wxEVT_STC_DWELLSTART,
function (event)
-- on Linux DWELLSTART event seems to be generated even for those
-- editor windows that are not active. What's worse, when generated
-- the event seems to report "old" position when retrieved using
-- event:GetX and event:GetY, so instead we use wxGetMousePosition.
local linux = ide.osname == 'Unix'
if linux and editor ~= GetEditor() then return end
-- check if this editor has focus; it may not when Stack/Watch window
-- is on top, but DWELL events are still triggered in this case.
-- Don't want to show calltip as it is still shown when the focus
-- is switched to a different application.
local focus = editor:FindFocus()
if focus and focus:GetId() ~= editor:GetId() then return end
local mpos = wx.wxGetMousePosition()
local cpos = editor:ScreenToClient(mpos)
local position = editor:PositionFromPointClose(
linux and cpos.x or event:GetX(), linux and cpos.y or event:GetY())
if position ~= wxstc.wxSTC_INVALID_POSITION then
EditorCallTip(editor, position, mpos.x, mpos.y)
end
event:Skip()
end)
editor:Connect(wxstc.wxEVT_STC_DWELLEND,
function (event)
if editor:CallTipActive() then editor:CallTipCancel() end
event:Skip()
end)
editor:Connect(wx.wxEVT_KILL_FOCUS,
function (event)
if editor:AutoCompActive() then editor:AutoCompCancel() end
event:Skip()
end)
editor:Connect(wxstc.wxEVT_STC_USERLISTSELECTION,
function (event)
local pos = editor:GetCurrentPos()
@@ -363,17 +523,17 @@ function CreateEditor(name)
end)
editor:Connect(wxstc.wxEVT_STC_SAVEPOINTREACHED,
function (event)
function ()
SetDocumentModified(editor:GetId(), false)
end)
editor:Connect(wxstc.wxEVT_STC_SAVEPOINTLEFT,
function (event)
function ()
SetDocumentModified(editor:GetId(), true)
end)
editor:Connect(wxstc.wxEVT_STC_UPDATEUI,
function (event)
function ()
updateStatusText(editor)
updateBraceMatch(editor)
for _,iv in ipairs(editor.ev) do
@@ -389,7 +549,7 @@ function CreateEditor(name)
function (event)
if MarkupHotspotClick then
local position = editor:PositionFromPointClose(event:GetX(),event:GetY())
if position ~= wx.wxSTC_INVALID_POSITION then
if position ~= wxstc.wxSTC_INVALID_POSITION then
if MarkupHotspotClick(position, editor) then return end
end
end
@@ -422,11 +582,81 @@ function CreateEditor(name)
if notebook:GetSelection() == last
then notebook:SetSelection(first)
else notebook:AdvanceSelection(true) end
elseif (keycode == wx.WXK_DELETE or keycode == wx.WXK_BACK)
-- ide.osname == 'Macintosh' has wx.wxMOD_NONE not defined
-- for some reason (at least in wxlua 2.8.12.1)
and (event:GetModifiers() == (wx.wxMOD_NONE or 0)) then
-- Delete and Backspace behave the same way for selected text
if #(editor:GetSelectedText()) > 0 then
editor:SetTargetStart(editor:GetSelectionStart())
editor:SetTargetEnd(editor:GetSelectionEnd())
else
local pos = editor:GetCurrentPos()
if keycode == wx.WXK_BACK then
pos = pos - 1
if pos < 0 then return end
end
-- check if the modification is to one of "invisible" characters.
-- if not, proceed with "normal" processing as there are other
-- events that may depend on Backspace, for example, re-calculating
-- auto-complete suggestions.
local style = bit.band(editor:GetStyleAt(pos), 31)
if not MarkupIsSpecial or not MarkupIsSpecial(style) then
event:Skip()
return
end
editor:SetTargetStart(pos)
editor:SetTargetEnd(pos+1)
end
editor:ReplaceTarget("")
else
if ide.osname == 'Macintosh' and event:CmdDown() then
return -- ignore a key press if Command key is also pressed
end
event:Skip()
end
end)
local value
editor:Connect(wx.wxEVT_CONTEXT_MENU,
function (event)
local menu = wx.wxMenu()
menu:Append(wx.wxID_UNDO, "&Undo")
menu:Append(wx.wxID_REDO, "&Redo")
menu:AppendSeparator()
menu:Append(wx.wxID_CUT, "Cu&t")
menu:Append(wx.wxID_COPY, "&Copy")
menu:Append(wx.wxID_PASTE, "&Paste")
menu:Append(wx.wxID_SELECTALL, "Select &All")
menu:AppendSeparator()
menu:Append(ID_QUICKADDWATCH, "Add Watch Expression")
menu:Append(ID_QUICKEVAL, "Evaluate in Console")
local point = editor:ScreenToClient(event:GetPosition())
local pos = editor:PositionFromPointClose(point.x, point.y)
value = pos ~= wxstc.wxSTC_INVALID_POSITION and getValAtPosition(editor, pos) or nil
menu:Enable(ID_QUICKADDWATCH, value ~= nil)
menu:Enable(ID_QUICKEVAL, value ~= nil)
-- cancel calltip as it interferes with popup menu
if editor:CallTipActive() then editor:CallTipCancel() end
editor:PopupMenu(menu)
end)
editor:Connect(ID_QUICKADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
function(event) DebuggerAddWatch(value) end)
editor:Connect(ID_QUICKEVAL, wx.wxEVT_COMMAND_MENU_SELECTED,
function(event) ShellExecuteCode(value) end)
return editor
end
-- ----------------------------------------------------------------------------
-- Add an editor to the notebook
function AddEditor(editor, name)
if notebook:AddPage(editor, name, true) then
local id = editor:GetId()
local document = {}
@@ -437,9 +667,9 @@ function CreateEditor(name)
document.modTime = nil
document.isModified = false
openDocuments[id] = document
return document
end
return editor
return
end
function GetSpec(ext,forcespec)
@@ -448,10 +678,10 @@ function GetSpec(ext,forcespec)
-- search proper spec
-- allow forcespec for "override"
if ext and not spec then
for i,curspec in pairs(ide.specs) do
for _,curspec in pairs(ide.specs) do
local exts = curspec.exts
if (exts) then
for n,curext in ipairs(exts) do
for _,curext in ipairs(exts) do
if (curext == ext) then
spec = curspec
break
@@ -475,16 +705,11 @@ function IndicateFunctions(editor, lines, linee)
if (lines < 0) then return end
local isfunc = editor.spec.isfncall
local iscomment = editor.spec.iscomment
local iskeyword0 = editor.spec.iskeyword0
local isfncall = editor.spec.isfncall
local isinvalid = {}
for i,v in pairs(iscomment) do
isinvalid[i] = v
end
for i,v in pairs(iskeyword0) do
isinvalid[i] = v
end
for i,v in pairs(editor.spec.iscomment) do isinvalid[i] = v end
for i,v in pairs(editor.spec.iskeyword0) do isinvalid[i] = v end
for i,v in pairs(editor.spec.isstring) do isinvalid[i] = v end
local INDICS_MASK = wxstc.wxSTC_INDICS_MASK
local INDIC0_MASK = wxstc.wxSTC_INDIC0_MASK
@@ -501,13 +726,13 @@ function IndicateFunctions(editor, lines, linee)
while from do
tx = from==1 and tx or string.sub(tx,from)
local f,t,w = isfunc(tx)
local f,t,w = isfncall(tx)
if (f) then
local p = ls+f+off
local s = bit.band(editor:GetStyleAt(p),31)
editor:StartStyling(p,INDICS_MASK)
editor:SetStyling(t-f,isinvalid[s] and 0 or (INDIC0_MASK + 1))
editor:SetStyling(#w,isinvalid[s] and 0 or (INDIC0_MASK + 1))
off = off + t
end
from = t and (t+1)
@@ -534,11 +759,11 @@ function SetupKeywords(editor, ext, forcespec, styles, font, fontitalic)
-- Get the items in the global "wx" table for autocompletion
if not wxkeywords then
local keyword_table = {}
for index, value in pairs(wx) do
for index in pairs(wx) do
table.insert(keyword_table, "wx."..index.." ")
end
for index, value in pairs(wxstc) do
for index in pairs(wxstc) do
table.insert(keyword_table, "wxstc."..index.." ")
end
@@ -560,21 +785,22 @@ function SetupKeywords(editor, ext, forcespec, styles, font, fontitalic)
end
StylesApplyToEditor(styles or ide.config.styles, editor,
font or ide.font,fontitalic or ide.fontItalic,lexerstyleconvert)
font or ide.font.eNormal,fontitalic or ide.font.eItalic,lexerstyleconvert)
end
----------------------------------------------------
-- function list for current file
funclist:Connect(wx.wxEVT_SET_FOCUS,
-- wx.wxEVT_SET_FOCUS is not triggered for wxChoice on Mac (wx 2.8.12),
-- so use wx.wxEVT_LEFT_DOWN instead
funclist:Connect(ide.osname == 'Macintosh' and wx.wxEVT_LEFT_DOWN or wx.wxEVT_SET_FOCUS,
function (event)
event:Skip()
-- parse current file and update list
local editor = GetEditor()
if (editor and not (editor.spec and editor.spec.isfndef)) then return end
if (not (editor and editor.spec and editor.spec.isfndef)) then return end
-- parse current file and update list
-- first populate with the current label to minimize flicker
-- then populate the list and update the label
local current = funclist:GetCurrentSelection()
@@ -585,12 +811,16 @@ funclist:Connect(wx.wxEVT_SET_FOCUS,
funclist:SetSelection(0)
local lines = 0
local linee = editor:GetLineCount()-1
local linee = (editor and editor:GetLineCount() or 0)-1
for line=lines,linee do
local tx = editor:GetLine(line)
local s,e,cap,l = editor.spec.isfndef(tx)
local s,_,cap,l = editor.spec.isfndef(tx)
if (s) then
funclist:Append((l and " " or "")..cap,line)
local ls = editor:PositionFromLine(line)
local style = bit.band(editor:GetStyleAt(ls+s),31)
if not (editor.spec.iscomment[style] or editor.spec.isstring[style]) then
funclist:Append((l and " " or "")..cap,line)
end
end
end

View File

@@ -30,14 +30,15 @@ local filetree = ide.filetree
-- ------------
do
local getBitmap = (ide.app.createbitmap or wx.wxArtProvider.GetBitmap)
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))
filetree.imglist:Add(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))
filetree.imglist:Add(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))
filetree.imglist:Add(getBitmap(wx.wxART_NORMAL_FILE, wx.wxART_OTHER, size))
end
local function treeAddDir(tree,parent_id,rootdir)
@@ -46,15 +47,14 @@ local function treeAddDir(tree,parent_id,rootdir)
while true do
if not item:IsOk() then break end
items[tree:GetItemText(item) .. tree:GetItemImage(item)] = item
item, cookie = tree:GetNextChild(item, cookie)
item, cookie = tree:GetNextChild(parent_id, cookie)
end
local curr
local search = rootdir..string_Pathsep.."*.*"
local dirs = FileSysGet(search,wx.wxDIR)
local search = rootdir..string_Pathsep.."*"
-- append directories
for _,dir in ipairs(dirs) do
for _,dir in ipairs(FileSysGet(search,wx.wxDIR)) do
local name = dir:match("%"..string_Pathsep.."("..stringset_File.."+)$")
local icon = 0
local item = items[name .. icon]
@@ -78,8 +78,7 @@ local function treeAddDir(tree,parent_id,rootdir)
end
-- then append files
local files = FileSysGet(search,wx.wxFILE)
for _,file in ipairs(files) do
for _,file in ipairs(FileSysGet(search,wx.wxFILE)) do
local name = file:match("%"..string_Pathsep.."("..stringset_File.."+)$")
local known = GetSpec(GetFileExt(name))
local icon = known and 1 or 2
@@ -122,15 +121,17 @@ local function treeGetItemFullName(tree,treedata,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
-- as root may already include path separate, normalize the path
local fullPath = wx.wxFileName(
filetree.showroot and str or filetree.projdata.rootdir .. str)
fullPath:Normalize()
return fullPath:GetFullPath()
end
local function treeSetRoot(tree,treedata,rootdir)
tree:DeleteAllItems()
if (not wx.wxDirExists(rootdir)) then
treedata.root_id = nil
tree:AddRoot("Invalid")
return
end
@@ -154,9 +155,9 @@ local function treeSetConnectorsAndIcons(tree,treedata)
local dir = treeGetItemFullName(tree,treedata,item_id)
treeAddDir(tree,item_id,dir)
return true
end )
end)
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED,
function() return true end )
function() return true end)
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
function( event )
local item_id = event:GetItem()
@@ -172,12 +173,24 @@ local function treeSetConnectorsAndIcons(tree,treedata)
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 )
end)
-- toggle a folder on
tree:Connect( wx.wxEVT_LEFT_DOWN,
function( event )
local item_id = tree:HitTest(event:GetPosition())
-- only toggle if this is a folder and the click is on the label
if item_id and tree:GetItemImage(item_id) == 0 then
tree:Toggle(item_id)
tree:SelectItem(item_id)
else
event:Skip()
end
return true
end)
end
-- project
@@ -199,7 +212,8 @@ local projtree = wx.wxTreeCtrl(projpanel, ID "filetree.projtree",
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())
projtree:SetFont(ide.font.fNormal)
projcombobox:SetFont(ide.font.fNormal)
local projTopSizer = wx.wxBoxSizer( wx.wxHORIZONTAL );
projTopSizer:Add(projcombobox, 1, wx.wxALL + wx.wxALIGN_LEFT + wx.wxGROW, 0)
@@ -236,6 +250,11 @@ function filetree:updateProjectDir(newdir, cboxsel)
end
if ((not newdir) or filetree.projdirText == newdir or not wx.wxDirExists(newdir)) then return end
if ide.config.projectautoopen and filetree.projdirText then
StoreRestoreProjectTabs(filetree.projdirText, newdir)
end
filetree.projdirText = newdir
PrependStringToArray(filetree.projdirTextArray,newdir,ide.config.projecthistorylength)
@@ -284,7 +303,7 @@ local function findItem(tree, match)
local node = projtree:GetRootItem()
local label = tree:GetItemText(node)
local s, e = string.find(match, label)
local s, e = string.find(match, label, 1, true)
if not s or s ~= 1 then return end
for token in string.gmatch(string.sub(match,e+1), "[^%"..string_Pathsep.."]+") do
@@ -298,7 +317,7 @@ local function findItem(tree, match)
node = item
break
end
item, cookie = tree:GetNextChild(item, cookie)
item, cookie = tree:GetNextChild(node, cookie)
end
end
@@ -306,18 +325,32 @@ local function findItem(tree, match)
return node
end
local curr_id
local curr_file
function FileTreeMarkSelected(file)
if not file then return end
if not file or not filetree.projdirText or #filetree.projdirText == 0 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)
-- if the select item is different from the current one
-- or the current one is the same, but not bold (which may happen when
-- the project is changed to one that includes the current item)
if curr_file ~= file
or item_id and not projtree:IsBold(item_id) then
if curr_file then
local curr_id = findItem(projtree, curr_file)
if curr_id and projtree:IsBold(curr_id) then
projtree:SetItemBold(curr_id, false)
end
end
if item_id then
projtree:EnsureVisible(item_id)
projtree:SetItemBold(item_id, true)
curr_id = item_id
end
curr_file = file
projtree:Refresh() -- to force refresh on Mac (ide.osname == 'Macintosh')
end
end
function FileTreeRefresh()
treeSetRoot(projtree,filetree.projdata,filetree.projdirText)
end

View File

@@ -95,6 +95,7 @@ function findReplace:GetSelectedString()
findReplace.foundString = true
end
end
return editor and findReplace.foundString
end
function findReplace:FindString(reverse)
@@ -112,7 +113,7 @@ function findReplace:FindString(reverse)
end
if posFind == -1 then
findReplace.foundString = false
ide.frame:SetStatusText("Find text not found.")
ide.frame:SetStatusText("Text not found.")
else
findReplace.foundString = true
local start = editor:GetTargetStart()
@@ -209,48 +210,36 @@ local function onFileRegister(pos)
findReplace.occurrences = findReplace.occurrences + 1
end
local function storefile(file,content)
local handle = io.open(file, "wb")
if (handle) then
handle:write(content)
handle:close()
end
end
local function ProcInFiles(startdir,mask,subdirs,replace)
if (subdirs) then
local dirs = FileSysGet(startdir..string_Pathsep.."*.*",wx.wxDIR)
for i,dir in ipairs(dirs) do
--DisplayOutput(dir.."\n")
local dirs = FileSysGet(startdir..string_Pathsep.."*",wx.wxDIR)
for _,dir in ipairs(dirs) do
ProcInFiles(dir,mask,true,replace)
end
end
local files = FileSysGet(startdir..string_Pathsep..mask,wx.wxFILE)
for i,file in ipairs(files) do
findReplace.curfilename = file
for _,file in ipairs(files) do
-- ignore .bak files when replacing and asked to store .bak files
if not (replace and findReplace.fMakeBak and file:find('.bak$')) then
findReplace.curfilename = file
--DisplayOutput(file.."\n")
local filetext = FileRead(file)
if filetext then
findReplace.oveditor:SetText(filetext)
-- load file
local handle = io.open(file, "rb")
if handle then
local filetext = handle:read("*a")
handle:close()
findReplace.oveditor:SetText(filetext)
if (replace and findReplace:ReplaceString(true,onFileRegister)) then
-- store changed content, make .bak
if (findReplace.fMakeBak) then
storefile(file..".bak",filetext)
if replace then
-- check if anything replaced, store changed content, make .bak
if findReplace:ReplaceString(true,onFileRegister)
and findReplace.fMakeBak and FileWrite(file..".bak",filetext) then
FileWrite(file,findReplace.oveditor:GetText())
end
else
findReplace:FindStringAll(onFileRegister)
end
storefile(file,findReplace.oveditor:GetText())
else
findReplace:FindStringAll(onFileRegister)
end
end
end
end
function findReplace:RunInFiles(replace)
@@ -259,17 +248,17 @@ function findReplace:RunInFiles(replace)
end
findReplace.oveditor = wxstc.wxStyledTextCtrl(findReplace.dialog, wx.wxID_ANY,
wx.wxDefaultPosition, wx.wxSize(1,1),
wx.wxBORDER_STATIC)
wx.wxDefaultPosition, wx.wxSize(1,1), wx.wxBORDER_STATIC)
findReplace.occurrences = 0
local fname = wx.wxFileName(findReplace.filedirText)
local startdir = findReplace.filedirText
DisplayOutput("> FindInFiles "..(replace and "Replacing" or "Searching")..": '"..findReplace.findText.."'\n")
DisplayOutput("FindInFiles: "..(replace and "Replacing" or "Searching for").." '"..findReplace.findText.."'.\n")
ProcInFiles(startdir, findReplace.filemaskText,findReplace.fSubDirs, replace)
ProcInFiles(startdir, findReplace.filemaskText, findReplace.fSubDirs, replace)
DisplayOutput("> FindInFiles: "..findReplace.occurrences.." occurrence(s) have been found\n\n")
DisplayOutput("FindInFiles: "..findReplace.occurrences.." instance(s) have been "..
(replace and "replaced" or "found")..".\n")
findReplace.oveditor = nil
end
@@ -282,8 +271,8 @@ local function createFindReplaceDialog(replace,infiles)
findReplace.replace = replace
findReplace.infiles = infiles
local findDialog = wx.wxDialog(ide.frame, wx.wxID_ANY, infiles and "Find In Files" or "Find", wx.wxDefaultPosition, wx.wxDefaultSize,
wx.wxDEFAULT_DIALOG_STYLE)
local findDialog = wx.wxDialog(ide.frame, wx.wxID_ANY, infiles and "Find In Files" or "Find",
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxDEFAULT_DIALOG_STYLE)
-- Create right hand buttons and sizer
local findButton = wx.wxButton(findDialog, ID_FIND_NEXT, infiles and "&Find All" or "&Find Next")
@@ -305,14 +294,16 @@ local function createFindReplaceDialog(replace,infiles)
-- Create find/replace text entry sizer
local findStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Find: ")
local findTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.findText, wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.findTextArray, wx.wxCB_DROPDOWN)
local findTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.findText,
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.findTextArray, wx.wxCB_DROPDOWN)
findTextCombo:SetFocus()
local infilesMaskStat,infilesMaskCombo
local infilesDirStat,infilesDirCombo,infilesDirButton
if (infiles) then
infilesMaskStat = wx.wxStaticText( findDialog, wx.wxID_ANY, "File Type: ")
infilesMaskCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filemaskText, wx.wxDefaultPosition, wx.wxSize(250,20), findReplace.filemaskTextArray)
infilesMaskCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filemaskText,
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filemaskTextArray)
local fname = GetEditorFileAndCurInfo(true)
if (fname) then
@@ -332,25 +323,30 @@ local function createFindReplaceDialog(replace,infiles)
local findReplaceSizer = wx.wxFlexGridSizer(2, 3, 0, 0)
findReplaceSizer:AddGrowableCol(1)
findReplaceSizer:Add(findStatText, 0, wx.wxALL + wx.wxALIGN_LEFT, 0)
findReplaceSizer:Add(findTextCombo, 1, wx.wxALL + wx.wxGROW + wx.wxCENTER, 0)
findReplaceSizer:Add(16,8, 0, wx.wxALL + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE,0)
findReplaceSizer:Add(findStatText, 0, wx.wxALL + wx.wxALIGN_RIGHT + wx.wxALIGN_CENTER_VERTICAL, 0)
findReplaceSizer:Add(findTextCombo, 1, wx.wxALL + wx.wxGROW + wx.wxCENTER+ wx.wxALIGN_CENTER_VERTICAL, 0)
findReplaceSizer:Add(16, 8, 0, wx.wxALL + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE,0)
if (infiles) then
findReplaceSizer:Add(infilesMaskStat, 0, wx.wxTOP + wx.wxALIGN_CENTER, 5)
findReplaceSizer:Add(infilesMaskCombo, 1, wx.wxTOP + wx.wxGROW + wx.wxCENTER, 5)
findReplaceSizer:Add(16,8, 0, wx.wxTOP + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE ,5)
findReplaceSizer:Add(infilesMaskStat, 0, wx.wxTOP + wx.wxALIGN_RIGHT + wx.wxALIGN_CENTER_VERTICAL, 5)
findReplaceSizer:Add(infilesMaskCombo, 1, wx.wxTOP + wx.wxGROW + wx.wxCENTER+ wx.wxALIGN_CENTER_VERTICAL, 5)
findReplaceSizer:Add(16, 8, 0, wx.wxTOP, 5)
findReplaceSizer:Add(infilesDirStat, 0, wx.wxTOP + wx.wxALIGN_CENTER, 5)
findReplaceSizer:Add(infilesDirCombo, 1, wx.wxTOP + wx.wxGROW + wx.wxCENTER, 5)
findReplaceSizer:Add(infilesDirButton, 0, wx.wxTOP + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE, 5)
findReplaceSizer:Add(infilesDirStat, 0, wx.wxTOP + wx.wxALIGN_RIGHT + wx.wxALIGN_CENTER_VERTICAL, 5)
findReplaceSizer:Add(infilesDirCombo, 1, wx.wxTOP + wx.wxGROW + wx.wxCENTER+ wx.wxALIGN_CENTER_VERTICAL, 5)
findReplaceSizer:Add(infilesDirButton, 0, wx.wxTOP + wx.wxALIGN_RIGHT + wx.wxADJUST_MINSIZE+ wx.wxALIGN_CENTER_VERTICAL, 5)
end
if (replace) then
findReplaceSizer:Add(replaceStatText, 0, wx.wxTOP + wx.wxALIGN_CENTER, 5)
findReplaceSizer:Add(replaceTextCombo, 1, wx.wxTOP + wx.wxGROW + wx.wxCENTER, 5)
findReplaceSizer:Add(replaceStatText, 0, wx.wxTOP + wx.wxALIGN_RIGHT + wx.wxALIGN_CENTER_VERTICAL, 5)
findReplaceSizer:Add(replaceTextCombo, 1, wx.wxTOP + wx.wxGROW + wx.wxCENTER+ wx.wxALIGN_CENTER_VERTICAL, 5)
end
-- the StaticBox(Sizer) needs to be created before checkboxes, otherwise
-- checkboxes don't get any clicks on OSX (ide.osname == 'Macintosh')
-- as the z-order for event traversal appears to be incorrect.
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "Options" )
-- Create find/replace option checkboxes
local wholeWordCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match &whole word")
local matchCaseCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match &case")
@@ -366,7 +362,7 @@ local function createFindReplaceDialog(replace,infiles)
optionSizer:Add(matchCaseCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
optionSizer:Add(wrapAroundCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
optionSizer:Add(regexCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "Options" );
optionsSizer:Add(optionSizer, 0, 0, 5)
-- Create scope radiobox
@@ -376,6 +372,9 @@ local function createFindReplaceDialog(replace,infiles)
local scopeSizer
if (infiles) then
-- the StaticBox(Sizer) needs to be created before checkboxes
scopeSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "In Files")
subDirCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "&Subdirectories")
makeBakCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, ".&bak on Replace")
subDirCheckBox:SetValue(findReplace.fSubDirs)
@@ -385,13 +384,12 @@ local function createFindReplaceDialog(replace,infiles)
optionSizer:Add(subDirCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
optionSizer:Add(makeBakCheckBox, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
scopeSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "In Files" );
scopeSizer:Add(optionSizer, 0, 0, 5)
else
scopeRadioBox = wx.wxRadioBox(findDialog, wx.wxID_ANY, "Scope", wx.wxDefaultPosition, wx.wxDefaultSize, {"&Up", "&Down"}, 1, wx.wxRA_SPECIFY_COLS)
scopeRadioBox:SetSelection(iff(findReplace.fDown, 1, 0))
scopeSizer = wx.wxBoxSizer(wx.wxVERTICAL, findDialog );
scopeSizer = wx.wxBoxSizer(wx.wxVERTICAL, findDialog)
scopeSizer:Add(scopeRadioBox, 0, 0, 0)
end
@@ -440,7 +438,7 @@ local function createFindReplaceDialog(replace,infiles)
end
findDialog:Connect(ID_FIND_NEXT, wx.wxEVT_COMMAND_BUTTON_CLICKED,
function(event)
function()
TransferDataFromWindow()
if (findReplace.infiles) then
findReplace:RunInFiles()
@@ -479,8 +477,8 @@ local function createFindReplaceDialog(replace,infiles)
if infilesDirButton then
findDialog:Connect(ID_SETDIR, wx.wxEVT_COMMAND_BUTTON_CLICKED,
function(event)
local filePicker = wx.wxDirDialog(findDialog, "Chose a project directory",
function()
local filePicker = wx.wxDirDialog(findDialog, "Choose a project directory",
findReplace.filedirText~="" and findReplace.filedirText or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
local res = filePicker:ShowModal(true)

View File

@@ -10,41 +10,23 @@ 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", ide.config.editor.fontencoding or wx.wxFONTENCODING_DEFAULT)
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", ide.config.editor.fontencoding or wx.wxFONTENCODING_DEFAULT)
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 "", ide.config.editor.fontencoding or wx.wxFONTENCODING_DEFAULT)
fontItalic = wx.wxFont(ide.config.editor.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC,
wx.wxFONTWEIGHT_NORMAL, false, ide.config.editor.fontname or "", ide.config.editor.fontencoding or wx.wxFONTENCODING_DEFAULT)
local function setFont(style, config, name, size)
return wx.wxFont(config.fontsize or size or 10, wx.wxFONTFAMILY_MODERN, style,
wx.wxFONTWEIGHT_NORMAL, false, config.fontname or name,
config.fontencoding or wx.wxFONTENCODING_DEFAULT)
end
ide.font.eNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.editor, wx.__WXMSW__ and "Courier New" or "")
ide.font.eItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.editor, wx.__WXMSW__ and "Courier New" or "")
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", ide.config.outputshell.fontencoding or wx.wxFONTENCODING_DEFAULT)
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", ide.config.outputshell.fontencoding or wx.wxFONTENCODING_DEFAULT)
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 "", ide.config.outputshell.fontencoding or wx.wxFONTENCODING_DEFAULT)
ofontItalic = wx.wxFont(ide.config.outputshell.fontsize or 10, wx.wxFONTFAMILY_MODERN, wx.wxFONTSTYLE_ITALIC,
wx.wxFONTWEIGHT_NORMAL, false, ide.config.outputshell.fontname or "", ide.config.outputshell.fontencoding or wx.wxFONTENCODING_DEFAULT)
end
ide.font.oNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.outputshell, wx.__WXMSW__ and "Courier New" or "")
ide.font.oItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.outputshell, wx.__WXMSW__ and "Courier New" or "")
ide.font = font
ide.fontItalic = fontItalic
ide.ofont = ofont
ide.ofontItalic = ofontItalic
-- treeCtrl font requires slightly different handling
local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.filetree
if config.fontsize then gui:SetPointSize(config.fontsize) end
if config.fontname then gui:SetFaceName(config.fontname) end
ide.font.fNormal = gui
-- ----------------------------------------------------------------------------
-- Create the wxFrame
@@ -65,44 +47,65 @@ local function createFrame()
end)
local menuBar = wx.wxMenuBar()
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})
local statusBar = frame:CreateStatusBar(6)
local section_width = statusBar:GetTextExtent("OVRW")
statusBar:SetStatusStyles({wx.wxSB_RAISED, wx.wxSB_RAISED, wx.wxSB_RAISED,
wx.wxSB_RAISED, wx.wxSB_RAISED, wx.wxSB_RAISED})
statusBar:SetStatusWidths(
{-1, section_width*6, section_width, section_width, section_width*4, section_width*4})
statusBar:SetStatusText(GetIDEString("statuswelcome"))
local mgr = wxaui.wxAuiManager()
frame.uimgr = mgr
mgr:SetManagedWindow(frame)
frame.menuBar = menuBar
frame.statusBar = statusBar
frame.uimgr = mgr
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))
local funclist = wx.wxChoice.new(toolBar,ID "toolBar.funclist",
-- Linux requires a bit larger size for the function list in the toolbar.
-- Mac also requires a bit larger size, but setting it to 20 resets
-- back to 16 when the toolbar is refreshed.
wx.wxDefaultPosition, wx.wxSize.new(240,ide.osname == "Unix" and 24 or 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")
-- usually the bmp size isn't necessary, but the HELP icon is not the right size in MSW
local getBitmap = (ide.app.createbitmap or wx.wxArtProvider.GetBitmap)
local toolBmpSize = wx.wxSize(16, 16)
toolBar:AddTool(ID_NEW, "New", getBitmap(wx.wxART_NORMAL_FILE, wx.wxART_TOOLBAR, toolBmpSize), "Create an empty document")
toolBar:AddTool(ID_OPEN, "Open", getBitmap(wx.wxART_FILE_OPEN, wx.wxART_TOOLBAR, toolBmpSize), "Open an existing document")
toolBar:AddTool(ID_SAVE, "Save", getBitmap(wx.wxART_FILE_SAVE, wx.wxART_TOOLBAR, toolBmpSize), "Save the current document")
toolBar:AddTool(ID_SAVEALL, "Save All", 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:AddTool(ID_CUT, "Cut", getBitmap(wx.wxART_CUT, wx.wxART_TOOLBAR, toolBmpSize), "Cut the selection")
toolBar:AddTool(ID_COPY, "Copy", getBitmap(wx.wxART_COPY, wx.wxART_TOOLBAR, toolBmpSize), "Copy the selection")
toolBar:AddTool(ID_PASTE, "Paste", 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:AddTool(ID_UNDO, "Undo", getBitmap(wx.wxART_UNDO, wx.wxART_TOOLBAR, toolBmpSize), "Undo last edit")
toolBar:AddTool(ID_REDO, "Redo", 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:AddTool(ID_FIND, "Find", getBitmap(wx.wxART_FIND, wx.wxART_TOOLBAR, toolBmpSize), "Find text")
toolBar:AddTool(ID_REPLACE, "Replace", getBitmap(wx.wxART_FIND_AND_REPLACE, wx.wxART_TOOLBAR, toolBmpSize), "Find and replace text")
if ide.app.createbitmap then -- custom handler should handle all bitmaps
toolBar:AddSeparator()
toolBar:AddTool(ID_START_DEBUG, "Start Debugging", getBitmap("wxART_DEBUG_START", wx.wxART_TOOLBAR, toolBmpSize), "Start debugging")
toolBar:AddTool(ID_STOP_DEBUG, "Stop Debugging", getBitmap("wxART_DEBUG_STOP", wx.wxART_TOOLBAR, toolBmpSize), "Stop debugging")
toolBar:AddTool(ID_BREAK, "Break", getBitmap("wxART_DEBUG_BREAK", wx.wxART_TOOLBAR, toolBmpSize), "Break running process")
toolBar:AddTool(ID_STEP, "Step into", getBitmap("wxART_DEBUG_STEP_INTO", wx.wxART_TOOLBAR, toolBmpSize), "Step into")
toolBar:AddTool(ID_STEP_OVER, "Step over", getBitmap("wxART_DEBUG_STEP_OVER", wx.wxART_TOOLBAR, toolBmpSize), "Step over")
toolBar:AddTool(ID_STEP_OUT, "Step out", getBitmap("wxART_DEBUG_STEP_OUT", wx.wxART_TOOLBAR, toolBmpSize), "Step out")
toolBar:AddSeparator()
toolBar:AddTool(ID_TOGGLEBREAKPOINT, "Toggle breakpoint", getBitmap("wxART_DEBUG_BREAKPOINT_TOGGLE", wx.wxART_TOOLBAR, toolBmpSize), "Toggle breakpoint")
toolBar:AddTool(ID_VIEWCALLSTACK, "Stack window", getBitmap("wxART_DEBUG_CALLSTACK", wx.wxART_TOOLBAR, toolBmpSize), "View stack window")
toolBar:AddTool(ID_VIEWWATCHWINDOW, "Watch window", getBitmap("wxART_DEBUG_WATCH", wx.wxART_TOOLBAR, toolBmpSize), "View watch window")
end
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:AddTool(ID "debug.projectdir.fromfile", "Update", getBitmap(wx.wxART_GO_DIR_UP , wx.wxART_TOOLBAR, toolBmpSize), "Set project directory from current file")
toolBar:AddSeparator()
toolBar:AddControl(funclist)
toolBar:Realize()

View File

@@ -53,6 +53,7 @@ ID_BREAK = NewID()
ID_TRACE = NewID()
ID_VIEWCALLSTACK = NewID()
ID_VIEWWATCHWINDOW = NewID()
ID_FULLSCREEN = NewID()
ID_CLEAROUTPUT = NewID()
ID_PROJECTDIR = NewID()
ID_INTERPRETER = NewID()
@@ -64,6 +65,9 @@ ID_ADDWATCH = NewID()
ID_EDITWATCH = NewID()
ID_REMOVEWATCH = NewID()
ID_EVALUATEWATCH = NewID()
-- Editor popup menu items
ID_QUICKADDWATCH = NewID()
ID_QUICKEVAL = NewID()
local ids = {}
function ID (name)

View File

@@ -42,6 +42,8 @@ function M.show_warnings(top_ast)
warnings[#warnings+1] = (path or "?") .. "(" .. (linenum or 0) .. "): " .. msg
end
local function known(o) return not T.istype[o] end
local function index(f) -- build abc.def.xyz name recursively
return (f[1].tag == 'Id' and f[1][1] or index(f[1])) .. '.' .. f[2][1] end
local isseen, globseen = {}, {}
LA.walk(top_ast, function(ast)
local line = ast.lineinfo and ast.lineinfo.first[1] or 0
@@ -66,11 +68,18 @@ function M.show_warnings(top_ast)
if name ~= 'self' then
local func = parent.parent and parent.parent.parent
local assignment = not func.tag or func.tag == 'Set' or func.tag == 'Localrec'
local fname = assignment and type(func[1][1][1]) == 'string' and func[1][1][1]
local func1 = func[1][1]
local fname = assignment and func1 and type(func1[1]) == 'string' and func1[1]
or (func1.tag == 'Index' and index(func1))
-- "function foo(bar)" => func.tag == 'Set'
-- `Set{{`Id{"foo"}},{`Function{{`Id{"bar"}},{}}}}
-- "local function foo(bar)" => func.tag == 'Localrec'
-- "local _, foo = 1, function(bar)" => func.tag == 'Local'
-- "print(function(bar) end)" => func.tag == nil
-- "function tbl:foo(bar)" => func.tag == 'Set'
-- `Set{{`Index{`Id{"tbl"},`String{"foo"}}},{`Function{{`Id{"self"},`Id{"bar"}},{}}}}
-- "function tbl.abc:foo(bar)" => func.tag == 'Set'
-- `Set{{`Index{`Index{`Id{"tbl"},`String{"abc"}},`String{"foo"}}},{`Function{{`Id{"self"},`Id{"bar"}},{}}}},
warn("unused parameter '" .. name .. "'" ..
(func and assignment
and (fname and func.tag
@@ -151,7 +160,7 @@ local function analyzeProgram(editor)
local filePath = DebuggerMakeFileName(editor, openDocuments[id].filePath)
if frame.menuBar:IsChecked(ID_CLEAROUTPUT) then ClearOutput() end
DisplayOutput("Analizing the source code")
DisplayOutput("Analyzing the source code")
frame:Update()
local warn, err = M.warnings_from_string(editorText, filePath)

View File

@@ -46,10 +46,20 @@ ide.iofilters["GermanUtf8Ascii"] = {
}
ide.iofilters["0d0d0aFix"] = {
-- this function converts 0d0d0a line ending to 0d0a
input = function(fpath, content)
return content:gsub("\013\013\010","\013\010")
end,
}
--üäß
for i,filter in pairs(ide.iofilters) do
assert(filter.output("",filter.input("","äöüÄÖÜß")),"„”äöüÄÖÜß","UTF8-ANSI conversion failed: "..(i))
if filter.input and filter.output then
assert(filter.output("",filter.input("","äöüÄÖÜß")),
"„”äöüÄÖÜß","UTF8-ANSI conversion failed: "..(i))
end
end
-- which: "input" or "output"

View File

@@ -5,12 +5,13 @@ local styles = ide.config.styles
local comment = styles.comment
local MD_MARK_ITAL = '_' -- italic
local MD_MARK_BOLD = '**' -- bold
local MD_MARK_LINK = '[' -- link
local MD_MARK_LINT = ')' -- link terminator
local MD_MARK_LINK = '[' -- link description start
local MD_MARK_LINZ = ']' -- link description end
local MD_MARK_LINA = '(' -- link URL start
local MD_MARK_LINT = ')' -- link URL end
local MD_MARK_HEAD = '#' -- header
local MD_MARK_CODE = '`' -- code
local MD_MARK_BOXD = '|' -- highlight
local MD_MARK_LSEP = '](' -- link separator (between text and link)
local MD_MARK_MARK = ' ' -- separator
local MD_LINK_NEWWINDOW = '+' -- indicator to open a new window for links
local markup = {
@@ -25,6 +26,7 @@ local markup = {
-- allow other editor features to recognize this special markup
function MarkupIsSpecial(style) return style == 31 end
function MarkupIsAny(style) return style >= 25 and style <= 31 end
local function q(s) return s:gsub('(.)','%%%1') end
@@ -45,11 +47,12 @@ function MarkupHotspotClick(pos, editor)
pos = pos + #MD_MARK_LINK - editor:PositionFromLine(line) -- turn into relative position
-- extract the URL/command on the right side of the separator
local _,_,text = string.find(tx, q(MD_MARK_LSEP).."([^%s]+)"..q(MD_MARK_LINT), pos)
local _,_,text = string.find(tx, q(MD_MARK_LINZ).."(%b"..MD_MARK_LINA..MD_MARK_LINT..")", pos)
if text then
text = text:gsub("^"..q(MD_MARK_LINA), ""):gsub(q(MD_MARK_LINT).."$", "")
local filepath = ide.openDocuments[editor:GetId()].filePath
local _,_,shell = string.find(text, [[^macro:shell%((.*%S)%)$]])
local _,_,http = string.find(text, [[^(http:%S+)$]])
local _,_,http = string.find(text, [[^(https?:%S+)$]])
local _,_,command = string.find(text, [[^macro:(%w+)$]])
if shell then
ShellExecuteCode(shell)
@@ -59,7 +62,7 @@ function MarkupHotspotClick(pos, editor)
ProjectDebug()
elseif http then -- open the URL in a new browser window
wx.wxLaunchDefaultBrowser(http, 0)
else
elseif filepath then -- only check for saved files
-- check if requested to open in a new window
local newwindow = string.find(text, MD_LINK_NEWWINDOW, 1, true) -- plain search
if newwindow then text = string.gsub(text, "^%" .. MD_LINK_NEWWINDOW, "") end
@@ -70,6 +73,7 @@ function MarkupHotspotClick(pos, editor)
filename:Normalize() -- remove .., ., and other similar elements
if filename:FileExists() and
(newwindow or SaveModifiedDialog(editor, true) ~= wx.wxID_CANCEL) then
if not newwindow and ide.osname == 'Macintosh' then editor:GotoPos(0) end
LoadFile(filename,not newwindow and editor or nil,true)
end
end
@@ -96,10 +100,10 @@ local function ismarkup (tx)
-- [%w%p] set is needed to avoid continuing this markup to the next line
s,e,cap = string.find(tx,"^("..q(MD_MARK_HEAD)..".+[%w%p])")
elseif sep == MD_MARK_LINK then
-- allow everything except spaces in the second part
s,e,cap = string.find(tx,"^("..q(MD_MARK_LINK)..nonspace..".-"..nonspace
..q(MD_MARK_LSEP).."[^%s]+"
..q(MD_MARK_LINT)..")", st)
-- allow everything based on balanced link separators
s,e,cap = string.find(tx,
"^(%b"..MD_MARK_LINK..MD_MARK_LINZ
.."%b"..MD_MARK_LINA..MD_MARK_LINT..")", st)
elseif markup[sep] then
-- try 2+ characters between separators first
-- if not found, try a single character
@@ -144,7 +148,9 @@ function MarkupStyle(editor, lines, linee)
if (f) then
local p = ls+f+off
local s = bit.band(editor:GetStyleAt(p), 31)
if iscomment[s] then
-- only style comments and only those that are not at the beginning
-- of the file to avoid styling shebang (#!) lines
if iscomment[s] and p > 0 then
local smark = #mark
local emark = #mark -- assumes end mark is the same length as start mark
if mark == MD_MARK_HEAD then
@@ -152,7 +158,7 @@ function MarkupStyle(editor, lines, linee)
local _,_,full = string.find(w,"^("..q(MD_MARK_HEAD).."+)")
smark,emark = #full,0
elseif mark == MD_MARK_LINK then
local lsep = w:find(q(MD_MARK_LSEP))
local lsep = w:find(q(MD_MARK_LINZ)..q(MD_MARK_LINA))
if lsep then emark = #w-lsep+#MD_MARK_LINT end
end
editor:StartStyling(p, 31)

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