Compare commits

...

188 Commits
0.38 ... 0.39

Author SHA1 Message Date
Paul Kulchenko
eb6aa586af Updated CHANGELOG for 0.39. 2013-10-06 14:27:51 -07:00
Paul Kulchenko
04d2ef75dc Updated README with passing directory as a parameter. 2013-10-05 22:54:54 -07:00
Paul Kulchenko
46e4704b07 Updated LICENSE information. 2013-10-05 22:50:47 -07:00
Paul Kulchenko
eb614b5ea6 Updated Windows build file for wxwidgets 3.0. 2013-10-03 17:25:29 -07:00
Paul Kulchenko
87d3e4abcd Fixed Lua 5.2 crash on OSX (added -O1). 2013-10-02 18:21:25 -07:00
Paul Kulchenko
428572cf7c Merge branch 'stack-limit' 2013-10-02 18:17:26 -07:00
Paul Kulchenko
1b65580088 Fixed onInterpreterLoad to only be called when interpreter changes. 2013-10-02 18:14:12 -07:00
Paul Kulchenko
be16e47a36 Added setting project directory when passed as a parameter. 2013-10-02 16:56:43 -07:00
Paul Kulchenko
b76a58cb8c Fixed missing keys in 'mixed' tables. 2013-10-01 20:46:16 -07:00
kikito
19f4ebed6f fix the fixutf8 function 2013-10-01 12:51:27 +02:00
Paul Kulchenko
4ab661bb8b Fixed handling of source code fragments in the Stack view. 2013-09-30 21:46:58 -07:00
Paul Kulchenko
1729aa25b8 Optimized handling of large tables in stack results. 2013-09-30 21:21:01 -07:00
Paul Kulchenko
687ccb3256 Disabled refreshing Watch/Stack windows when they get focus (corrects 91ccdd96).
This happens too frequently, including when clicked on stack elements,
which refreshes the stack instead of expanding/collapsing elements.
2013-09-28 19:40:40 -07:00
Paul Kulchenko
baad9cf946 Fixed Watch/Stack windows to refresh when shown (corrects 4da37969). 2013-09-27 19:39:19 -07:00
Paul Kulchenko
e662970cc8 Updated CHANGELOG with recent changes. 2013-09-26 21:22:39 -07:00
Paul Kulchenko
ea927292f8 Updated luasocket to patch connection reset issue (ref diegonehab/luasocket#81). 2013-09-26 15:15:35 -07:00
Paul Kulchenko
e90d403bc6 Added activation of windows with SDL_app class name (Moai support). 2013-09-25 17:53:41 -07:00
Paul Kulchenko
01afd985df Merge branch 'dockable-stack-watch-tabs' 2013-09-25 17:40:25 -07:00
Paul Kulchenko
1ef2b3e0e9 Added workaround for combined windows after dragging a tab on top of active tab. 2013-09-25 17:08:32 -07:00
Paul Kulchenko
7f80f36486 Fixed dragging tabs out of split notebooks. 2013-09-25 14:42:40 -07:00
Paul Kulchenko
91ccdd9679 Updated Watch/Stack tabs to refresh when they get focus. 2013-09-25 12:49:19 -07:00
Paul Kulchenko
4da379693c Updated Watch/Stack tabs to refresh only when shown. 2013-09-25 12:47:36 -07:00
Paul Kulchenko
c1cbd949e7 Added dragging Watch/Stack tabs out of docked panes. 2013-09-24 20:00:42 -07:00
Paul Kulchenko
10b1e34504 Added support for joining/splitting Watch/Stack with Output/Console tabs. 2013-09-24 13:35:42 -07:00
Paul Kulchenko
df0824d274 Updated settings restore to activate Output pane and set focus on the editor. 2013-09-24 13:15:43 -07:00
Paul Kulchenko
33b1f79bb8 Added disabling View menu for non-existing panes. 2013-09-24 10:41:28 -07:00
Paul Kulchenko
7f2744c4f5 Added package GetSetting method (ref #166). 2013-09-23 21:08:26 -07:00
Paul Kulchenko
1c4de98f98 Added selected index to package onMenuEditorTab event (ref #166). 2013-09-21 21:16:01 -07:00
Paul Kulchenko
9f392382a7 Fixed incorrect editor tab acted upon in split notebook situations. 2013-09-21 21:10:54 -07:00
Paul Kulchenko
f704baa004 Updated support for MOAI coroutine debugging (Mobdebug 0.541). 2013-09-21 18:15:34 -07:00
Paul Kulchenko
762babaaba Reorganized auto-complete handling; should fix #164. 2013-09-21 13:57:53 -07:00
Paul Kulchenko
7ae515e6db Removed duplicate KILL_FOCUS handlers. 2013-09-21 13:41:33 -07:00
Paul Kulchenko
456347e371 Added activation of windows with FREEGLUT class name (Moai support). 2013-09-20 23:07:29 -07:00
Paul Kulchenko
b82b2782d7 Fixed auto-complete suggestions for indentifiers matching partial function names. 2013-09-20 16:10:41 -07:00
Paul Kulchenko
933aacc2c9 Updated type assignment logic to remove spurious types. 2013-09-20 16:10:32 -07:00
Paul Kulchenko
c94b5e9e2e Improved file/debugger activation on Windows (ref #199).
File activation has been inconsistent, because IsActive() returns `true`,
when it shouldn't, so I changed the logic to request attention first and
then to load file.

Also, this caused a symbol to appear in the loaded file and it turned out
that 307 code we used to enable bringing the window to foreground, was not
correct.
2013-09-19 15:31:31 -07:00
Paul Kulchenko
61976d2a25 Reduced CPU usage while idle (ref #204, #206). 2013-09-19 15:29:44 -07:00
Paul Kulchenko
996a706c97 Added hiding console window for Corona (2013.8.28+) applications (Windows). 2013-09-18 16:29:38 -07:00
Paul Kulchenko
371dd269b0 Fixed hiding launched windows when running/debugging (Windows). 2013-09-18 16:26:10 -07:00
Paul Kulchenko
c16f26a7d9 Added suggesting dynamic words as fields in auto-complete. 2013-09-18 16:20:40 -07:00
Paul Kulchenko
18757f393b Fixed showing known functions in auto-complete. 2013-09-18 13:52:29 -07:00
Paul Kulchenko
ca3b2de447 Upgraded copas and coxpcall libraries (closes #144). 2013-09-18 13:47:41 -07:00
Paul Kulchenko
929615a7b8 Enabled faster static analysis; partially reverted 89cafbec (ref #149, #168).
The slower setting was too slow and too verbose.
2013-09-18 13:39:40 -07:00
Paul Kulchenko
689cd8cf85 Added socket.connect for compatibility with socket.core <3.0 (fixes #208). 2013-09-17 17:17:45 -07:00
Paul Kulchenko
80eab46c3e Added recalculating line number margin width after zooming (fixes #207). 2013-09-17 15:35:09 -07:00
Paul Kulchenko
7a40fb8f7f Added margin constants and removed unused variables. 2013-09-17 15:34:03 -07:00
Paul Kulchenko
813844d052 Updated Windows build script to enable gdb debugging. 2013-09-16 15:20:20 -07:00
Paul Kulchenko
06620745f3 Updated OSX build script to not strip debug builds. 2013-09-16 15:19:27 -07:00
Paul Kulchenko
1f51d803db Added reporting of socket error for initial debugger calls (Mobdebug 0.5403). 2013-09-15 14:29:23 -07:00
Paul Kulchenko
b7d9c7d2b0 Improved file activation for abbreviated file names in error messages. 2013-09-15 14:16:40 -07:00
Paul Kulchenko
d3ce3fb93d Added error handling/reporting for debugger.outputfilter. 2013-09-14 23:24:13 -07:00
Paul Kulchenko
85418cce0f Enabled editing watches with doubleclick or Enter. 2013-09-14 10:22:40 -07:00
Paul Kulchenko
87594dc7e5 Updated Corona interpreter to handle failure to copy debugger to Resources/ folder. 2013-09-13 10:01:47 -07:00
Paul Kulchenko
c68d60a6e9 Fixed showing output with invalid UTF8 characters in Stack and Console windows. 2013-09-12 23:55:11 -07:00
Paul Kulchenko
4993b3c20e Added 'debug' option to OSX build script. 2013-09-11 13:33:22 -07:00
Paul Kulchenko
e7ddadedb1 Updated build scripts with proper INSTALL_PREFIX option. 2013-09-11 13:29:44 -07:00
Christoph Kubisch
b4987b74ab Merge remote-tracking branch 'zbstudio/master' 2013-09-11 09:48:02 +02:00
Christoph Kubisch
52c1133c42 dx11 and glslc updates 2013-09-11 09:47:18 +02:00
Paul Kulchenko
e9b345476b Fixed saving new files (broken by f28d4da053). 2013-09-10 18:24:16 -07:00
Paul Kulchenko
2594a679f3 Fixed debugging on/off handling in 'main' thread for LuaJIT (MobDebug 0.5402). 2013-09-10 16:22:12 -07:00
Paul Kulchenko
446dec6768 Merge branch 'lua52-jit-support' 2013-09-10 13:59:45 -07:00
Paul Kulchenko
cd926d617e Merge branch 'goto-definition-and-back' 2013-09-10 13:58:49 -07:00
Paul Kulchenko
d40427155f Updated build scripts with new wxlua source URL and revision number. 2013-09-09 17:00:52 -07:00
Paul Kulchenko
d52a6c155f Added ability to modify exe path in base interpreter (ref #197). 2013-09-08 17:55:31 -07:00
Paul Kulchenko
6c300cda97 Changed 'go to definition' to Ctrl/Cmd+Alt+Click (ref #203).
Ctrl/Cmd+Click conflicts with both selection using Ctrl+selection (when
doing multiple selection) and with Ctrl/Cmd+DblClick when selecting all
instances of a variable. As there is no (straightforward) way to separate
single from double clicks, 'go to definition' is moved to avoid the
conflict.
2013-09-08 16:10:22 -07:00
Paul Kulchenko
f28d4da053 Fixed having duplicate tabs after SaveAs with existing file name. 2013-09-08 14:38:59 -07:00
Michal Kottman
3b4f5c4c0a Enable Ctrl+Click and Alt+Left navigation on local variables 2013-09-08 13:32:58 +02:00
Paul Kulchenko
858742bf05 Fixed showing redirected 'print' messages after debugging is terminated. 2013-09-06 21:29:33 -07:00
Paul Kulchenko
d559afd9e2 Updated CFBundleIdentifier in plist files to allow references from OSX programs. 2013-09-06 15:07:43 -07:00
Paul Kulchenko
9acec71c7a Added package GetEditorNotebook method (ref #166). 2013-09-06 15:01:34 -07:00
Paul Kulchenko
8568f61ba4 Added 'molokai' color scheme (ref #200). 2013-09-05 22:23:28 -07:00
Paul Kulchenko
19133b5a03 Fixed a (regression) issue with running the default interpreter (ref #201). 2013-09-05 10:10:17 -07:00
Christoph Kubisch
9a2c161328 added hlsl spec and basic api (note: currently autocomplete doesn't work on object functions, need fix). also fixed cg syntax lexer settings 2013-09-05 17:45:13 +02:00
ardente
5c6f2ffae3 allow to define separate lua 5.1 and 5.2 paths in user config 2013-09-05 16:16:52 +04:00
Paul Kulchenko
6714f29302 Updated un/comment to toggle selection as a group rather than line by line. 2013-09-04 19:09:28 -07:00
Paul Kulchenko
f0b7cff06a Added file activation for abbreviated file names in error messages. 2013-09-04 15:26:54 -07:00
Paul Kulchenko
25589fc45a Reorganized path separator handling to minimize use of global variables. 2013-09-04 12:00:57 -07:00
Paul Kulchenko
6a7c8e78c0 Added abbreviation of project directories to keep unique parts visible. 2013-09-03 22:35:33 -07:00
Paul Kulchenko
443f936ac6 Added debugger.redirect configuration option. 2013-09-02 21:07:48 -07:00
Paul Kulchenko
12525ad189 Added editor.saveallonrun configuration option. 2013-09-02 10:43:03 -07:00
Paul Kulchenko
69fae9a36c Fixed using default interpreter when no interpreter is selected. 2013-09-02 10:32:47 -07:00
Paul Kulchenko
725a38b182 Improved IDE activation during debugging on Windows (closes #199); thanks to jpoag. 2013-09-01 22:28:04 -07:00
Paul Kulchenko
13c4ca1a2f Fixed stepping through blocks with undefined variables when 'strict' is in effect (upgraded Mobdebug to 0.5401). 2013-09-01 21:17:47 -07:00
Paul Kulchenko
3e68447415 Updated CHANGELOG with recent changes. 2013-08-29 19:19:42 -07:00
Paul Kulchenko
63e1e56c28 Updated OSX/Windows manifests with new binaries (closes #197). 2013-08-29 12:42:28 -07:00
Paul Kulchenko
3ace5133bf Updated Linux files with LuaJIT, Lua5.2 and lua socket libraries (ref #197). 2013-08-29 12:37:28 -07:00
Paul Kulchenko
f8491464bd Updated OSX files with LuaJIT, Lua5.2 and lua socket libraries (ref #197). 2013-08-29 09:25:13 -07:00
Paul Kulchenko
01b8eea47b Replaced Lua 5.1 with LuaJIT as the default interpreter on Windows (ref #197). 2013-08-28 22:23:13 -07:00
Paul Kulchenko
e9a42f724a Updated build script for Lua JIT (Win) to enable LUA52COMPAT option (ref #197). 2013-08-28 22:12:44 -07:00
Paul Kulchenko
63861614c7 Added Lua 5.2 (Win) library and luasocket (ref #197). 2013-08-27 19:26:41 -07:00
Paul Kulchenko
4bd5b5d329 Reorganized Lua interpreter to allow for different Lua versions (ref #197). 2013-08-27 19:24:55 -07:00
Paul Kulchenko
91455261c9 Updated luasocket to 3.0rc1 to use with Lua 5.1 and 5.2 (ref #197). 2013-08-27 17:55:08 -07:00
Paul Kulchenko
3a7df5f5af Added luasocket, lua5.2, and luaJIT build support (ref #197). 2013-08-27 17:49:26 -07:00
Paul Kulchenko
0419e6812b Added package GetOutput method (ref #166). 2013-08-27 14:15:36 -07:00
Paul Kulchenko
cd1b9d7cd2 Added package onAppLoad/onAppClose events (ref #166). 2013-08-27 14:14:36 -07:00
Paul Kulchenko
d63dda5e6a Cleaned up code. 2013-08-27 14:12:29 -07:00
Paul Kulchenko
32f4b8694b Updated NewFile to accept a file name. 2013-08-27 11:19:50 -07:00
Paul Kulchenko
2dbb6644cb Fixed loading of files with incorrect UTF-8 encoding and control characters (fixes #198). 2013-08-27 10:11:32 -07:00
Paul Kulchenko
649e3c620a Added package onIdleOnce event (ref #166). 2013-08-26 20:22:16 -07:00
Paul Kulchenko
0e7bb32024 Fixed package sample to take into account new documents. 2013-08-25 19:19:30 -07:00
Paul Kulchenko
96f0f876bf Renamed package onEditorPostSave event to onEditorSave for consistency (ref #166). 2013-08-24 17:02:06 -07:00
Paul Kulchenko
58a494931c Added manifest to the Windows executable and re-signed. 2013-08-23 16:04:08 -07:00
Paul Kulchenko
f04160fad1 Updated 'get hostname' logic to avoid using non-resolvable names (mostly on OSX). 2013-08-22 20:38:02 -07:00
Paul Kulchenko
671c62871a Added Notepad++ color scheme (thanks to Florian/SiENcE; closes #193). 2013-08-21 08:54:03 -07:00
Paul Kulchenko
6a6e7ec770 Fixed crash on OSX after opening 'application' in 'Open File' dialog. 2013-08-20 14:55:09 -07:00
Paul Kulchenko
eff4eb8b05 Disabled markup styling for specs without comment styles. 2013-08-20 12:09:02 -07:00
Paul Kulchenko
2781c0ea00 Removed comment from default spec as it forces undesired markup styling. 2013-08-20 12:08:27 -07:00
Paul Kulchenko
fa507450e4 Added clearing document styles after saving file with a different extension. 2013-08-20 12:04:11 -07:00
Paul Kulchenko
a4f069afc0 Fixed windows resource file to properly reference the manifest. 2013-08-17 22:24:50 -07:00
Paul Kulchenko
f3b84edc24 Fixed missing default api for files with unknown extensions. 2013-08-16 21:59:17 -07:00
Paul Kulchenko
ba1c1a678e Added workaround to avoid crash on OSX after Close All Pages (closes #190).
The issue is with wxwidgets (filed as ticket 15417); the only workaround I
have been able to find is to disable this functionality on OSX (as there
are other alternatives to closing tabs in groups). The issue only happens
when the last tab is closed from the drop down menu linked to editor tabs.
2013-08-15 15:54:43 -07:00
Paul Kulchenko
267deea3df Merge branch 'master' of git://git.code.sf.net/p/estrelaeditor/code into estrela-new 2013-08-15 15:36:18 -07:00
Paul Kulchenko
1089f2619e Added return type for string.* functions to assist in auto-complete (ref #189). 2013-08-14 12:43:55 -07:00
Paul Kulchenko
e8c5e7fd78 Added handling of string literals in type assignments (closes #189). 2013-08-14 12:37:49 -07:00
Christoph Kubisch
ff6deedf79 OpenGL 4.4 and ARB extensions added as well as NV_gpu_shader5 functions 2013-08-14 14:19:50 +02:00
Paul Kulchenko
52c7150e51 Switched to using POSIX compatible regexp with '()' used for captures. 2013-08-13 14:50:21 -07:00
Paul Kulchenko
24555a3b3d Fix spurious replacement after 'search, clear selection, replace' actions. 2013-08-13 14:47:01 -07:00
Paul Kulchenko
cc432b65b0 Added support for captures in regexp replacement (\1-\9). 2013-08-13 14:39:06 -07:00
Paul Kulchenko
8d1cca26a3 Fixed using auto-complete with multiple selections (fixes #188). 2013-08-11 15:04:42 -07:00
Paul Kulchenko
c077c94371 Fixed looping in auto-complete with array references (ref #143). 2013-08-11 15:00:32 -07:00
Paul Kulchenko
1ba300213d Added ability to cancel FindInFiles search by closing search dialog (ref #162). 2013-08-10 21:38:50 -07:00
Paul Kulchenko
3fbf0ef81b Added activating Output window before showing search results (ref #162). 2013-08-10 21:38:11 -07:00
Paul Kulchenko
aced5d1bc3 Changed un/comment to act from the beginning of the line for multi-line selection.
Fixed handling of EOL markers (un/commenting doesn't modify them anymore).
Added processing of rectangular selections.
2013-08-09 14:52:25 -07:00
Paul Kulchenko
bf072c1685 Added support for packages from different platforms to co-exist (ref #166). 2013-08-07 23:23:14 -07:00
Paul Kulchenko
4215054b87 Improved logic to jump to file/line indicated in error messages. 2013-08-06 09:20:15 -07:00
Paul Kulchenko
cd85d6f2e8 Added ability to save complex data in package settings (ref #166). 2013-08-05 19:12:05 -07:00
Paul Kulchenko
6fc448b87c Fixed incorrect change for line count calculation for dynamic words.
Fixed commit d6cda0d677.
2013-08-04 22:20:59 -07:00
Paul Kulchenko
d6cda0d677 Optimized line count calculation for dynamic words when text is deleted. 2013-08-04 22:12:13 -07:00
Paul Kulchenko
5355234b85 Fixed showing auto-complete after comma. 2013-08-04 21:37:26 -07:00
Paul Kulchenko
700dfe1765 Optimized dynamic word processing for large files. 2013-08-04 20:29:41 -07:00
Paul Kulchenko
1c068c221f Merge branch 'master' of git://git.code.sf.net/p/estrelaeditor/code into estrela-changes 2013-08-04 17:51:53 -07:00
Paul Kulchenko
5679d90bcd Added support for multiple inheritance in auto-complete (ref #101). 2013-08-03 15:38:24 -07:00
Paul Kulchenko
9b5f6fa67f Added ability to add/remove API descriptions from plugins (ref #166). 2013-08-02 11:05:00 -07:00
Christoph Kubisch
a8060b63cd updated glewgl api for OpenGL4.4 and removed non-core duplicate functions/enums 2013-08-02 10:23:52 +02:00
Paul Kulchenko
7324afb8e3 Reorganized API processing to allow loading API description from a plugin. 2013-08-01 11:03:23 -07:00
Paul Kulchenko
e209f3f440 Added package GetSettings/SetSettings methods (ref #166). 2013-07-28 22:24:44 -07:00
Paul Kulchenko
08ef16a42d Added methods to save/restore package settings (ref #166). 2013-07-27 22:23:41 -07:00
Paul Kulchenko
4fafcff592 Fixed 'cannot get official hostname' message on low privilege accounts (fixes #183). 2013-07-26 08:15:53 -07:00
Paul Kulchenko
6e0e3d07e3 Updated Estrela reference in README. 2013-07-25 14:49:03 -07:00
Paul Kulchenko
fb9c0ba0a6 Disabled showing tooltip when auto-complete suggestions are shown. 2013-07-25 14:48:27 -07:00
Paul Kulchenko
1b4f707232 Updated build script on Windows to enable debugging (ref #164). 2013-07-24 09:50:49 -07:00
Paul Kulchenko
1749c54f71 Updated build script with a (temporary) fix for wxlua issue (mingw32). 2013-07-24 09:48:51 -07:00
Paul Kulchenko
e4201b745c Fixed displaying variable instances when code has invalid blocks (fixes #182). 2013-07-23 14:50:29 -07:00
Paul Kulchenko
9c810b3520 Fixed tooltip to ignore string parameters (ref #101). 2013-07-23 10:07:29 -07:00
Paul Kulchenko
93d3b69335 Removed auto-complete suggestion when it is already typed (ref #101). 2013-07-22 18:45:44 -07:00
Paul Kulchenko
35617caa0e Updated tooltip to use the same type inference as auto-complete (ref #101). 2013-07-22 18:21:52 -07:00
Paul Kulchenko
e07ed0a817 Fixed tooltip display between empty brackets (ref #101). 2013-07-22 17:49:39 -07:00
Paul Kulchenko
aeb35ebf6f Added ability to add/remove specs from plugins (ref #166). 2013-07-22 16:11:18 -07:00
Paul Kulchenko
c84bd3222b Enabled support for xml/html folding. 2013-07-21 22:22:30 -07:00
Paul Kulchenko
e398a216a8 Added ability to add/remove interpreters from plugins (ref #166). 2013-07-20 23:21:44 -07:00
Paul Kulchenko
4137b9d88d Added wxlua patch for twoface compatibility. 2013-07-20 15:17:09 -07:00
Paul Kulchenko
a630dd95c7 Added setfenv for Lua 5.2 compatibility. 2013-07-19 12:51:53 -07:00
Paul Kulchenko
0b748d6389 Updated static analyzer to report only first instance of 'unknown field'. 2013-07-18 16:28:12 -07:00
Paul Kulchenko
790f9d5b45 Added links to project page and documentation (closes #180). 2013-07-18 15:26:00 -07:00
Paul Kulchenko
43513c9153 Updated filename/source code heuristic in the debugger (Mobdebug 0.5362).
If the "chunkname" has no newline, it's treated as a file name.
This helps with handling cases when the application engine reports
filenames without @ (for example, when they are loaded using
loadstring("chunk", "file") instead of loadstring("chunk", "@file"));
also helps with debugging cocos2dx apps that load Lua files.
2013-07-18 15:20:59 -07:00
Paul Kulchenko
f58f185850 Enabled path remapping for local debugging.
This helps in local debugging when project files are copied to a temporary
location, but need to be debugged from the project folder (for example,
with debugging of cocos2d-x apps in iOS simulator).
2013-07-18 14:10:54 -07:00
Paul Kulchenko
ebbeb107a7 Disabled error reporting after debugging has been terminated. 2013-07-17 16:54:12 -07:00
Paul Kulchenko
e0674f9c9a Limited activation of code fragments to the beginning of debugging session.
This can still be configured using `editor.autoactivate` option.
2013-07-16 16:52:31 -07:00
Paul Kulchenko
89cafbec45 Enabled slower and more thorough static analysis (ref #149; ref #168). 2013-07-15 22:02:30 -07:00
Paul Kulchenko
e0f543c262 Updated CHANGELOG with recent changes. 2013-07-14 20:27:24 -07:00
Paul Kulchenko
b73526586c Fixed indentation after lines with brackets in strings. 2013-07-13 09:14:12 -07:00
Paul Kulchenko
cc177264f6 Fixed indentation after lines with anonymous functions. 2013-07-12 22:49:55 -07:00
Paul Kulchenko
2f98bc30a6 Added German translation (thanks to Riidom; ref #70). 2013-07-11 16:38:32 -07:00
Paul Kulchenko
b9374894c9 Set search in subdirectories as default in Find in Files dialog (ref #162). 2013-07-10 16:32:26 -07:00
Paul Kulchenko
17a995a810 Fixed indicator showing at the end of not terminated long comment. 2013-07-09 22:54:23 -07:00
Paul Kulchenko
35d1bc0f03 Fixed an issue with LUA_DEV including files instead of directories. 2013-07-07 23:35:15 -07:00
Paul Kulchenko
6f044d8b2e Added default value to package config (ref #176). 2013-07-06 15:27:31 -07:00
Paul Kulchenko
735f8492e2 Fixed project switching to close all files when switching to a subdirectory.
Some of the files could have been left open if the name starts with
the name of a subdirectory the project is being switched to.
2013-07-05 16:52:22 -07:00
Paul Kulchenko
4eb57fcbda Fixed saving projects that do not have any open files. 2013-07-04 16:48:12 -07:00
Paul Kulchenko
c882b8d0e0 Added handling of ?51.dll and required DLLs for LuaForWindows interpreter. 2013-07-03 17:40:01 -07:00
Paul Kulchenko
ce8552f044 Added plugin::GetConfig method (ref #166). 2013-07-03 14:25:06 -07:00
ardente
6968364c58 windows: adopt native user home 2013-07-03 16:39:57 +04:00
Paul Kulchenko
9ab72209c2 Added erasing current line in Console (ref #173). 2013-07-01 18:46:31 -07:00
Paul Kulchenko
c872934157 Added search/completion in the local and remote console (closes #173). 2013-06-30 20:41:42 -07:00
Paul Kulchenko
ea2d7c289a Replaced package onEditorActivated event with onEditorFocus* events (ref #166). 2013-06-30 13:09:44 -07:00
Paul Kulchenko
19ab4df922 Updated SaveAll to allow saving (only) files with filenames (ref #172).
This is useful when `SaveAll` is called from a plugin and user interaction
(asking for a file name) is not desired.
2013-06-30 10:06:19 -07:00
Paul Kulchenko
7dda2c00fd Added package onAppFocus* events (ref #166; ref #172). 2013-06-30 09:27:16 -07:00
Paul Kulchenko
3d3ae5ca00 Fixed debugger to accept filenames without '@'; thanks to Tim Mensch (closes #174). 2013-06-28 21:55:27 -07:00
Paul Kulchenko
28c3b79b8b Added Chinese translation (thanks to Chow CheeWen; ref #70). 2013-06-28 21:37:05 -07:00
Paul Kulchenko
a91bba8bd0 Added editor.autoreload to enable reload of updated files (ref #172).
Thanks for Tim Mensch for suggestion and implementation.
2013-06-26 23:27:31 -07:00
Paul Kulchenko
ed874063ea Added creating (missing) folders when saving a file (fixes #171). 2013-06-25 17:10:57 -07:00
Paul Kulchenko
6259918648 Added an example of styling individual keywords. 2013-06-24 21:03:07 -07:00
Paul Kulchenko
0995c5a061 Added fold indication of a current block (ref #168). 2013-06-24 21:01:49 -07:00
Paul Kulchenko
f07e42c4b4 Fixed sorting when the sorted fragment ends with a newline. 2013-06-24 17:15:02 -07:00
Paul Kulchenko
7e62939df6 Moved 'Sort' menu to 'Edit'. 2013-06-24 17:12:26 -07:00
Paul Kulchenko
b57bf55ef0 Added reporting of process id for a conflicting process. 2013-06-23 21:58:40 -07:00
Paul Kulchenko
8ed91f76cc Disabled 'Fold' menu instead of removing when no folding is allowed (ref #169). 2013-06-22 22:14:20 -07:00
Mika Attila
9e6ec10be9 Make code folding optional
Some users might consider code folding a needless distraction.
Several editors offer the option to turn code folding off.

This commit adds the editor.fold option, which is a boolean.
true enables code folding (default)
false disables code folding
2013-06-22 12:02:31 +02:00
108 changed files with 5320 additions and 3488 deletions

View File

@@ -1,5 +1,182 @@
# ZeroBrane Studio Changelog
## v0.39 (Oct 06 2013)
### Highlights
- Added Lua 5.2 support out of the box.
- Added suggesting dynamic words as fields in auto-complete.
- Added 'go to definition' (Ctrl/Cmd+Alt+Click) and 'jump to previous location' (Alt+Left).
- Added abbreviation of project directories to keep unique parts visible.
- Fixed breakpoints with Marmalade Quick.
- Switched to using LuaJIT interpreter by default.
- Upgraded Luasocket (3.0-rc1), copas, and coxpcall libraries.
### Special thanks
- To Chow CheeWen for Chinese translation.
- To [Enrique García](https://github.com/kikito) for fixing `fixutf8` function.
- To [Riidom](https://github.com/Riidom) for German translation.
- To [ardente](https://github.com/ardente) for user home patch for Windows and separating Lua 5.1 and 5.2 paths in user config.
- To [Mika Attila](https://github.com/crumblingstatue) for code folding patch.
- To [Tim Mensch](https://github.com/TimMensch) for auto-save, auto-reload, and debugger improvements.
- To [Florian](https://github.com/SiENcE) for Notepad++ color scheme.
- To [Michal Kottman](https://github.com/mkottman) for 'go to definition' and Alt+Left navigation patch.
- To [Christoph Kubisch](https://github.com/CrazyButcher) for dx11 and glslc updates.
- To [jpoag](https://github.com/jpoag) for improved activation during debugging on Windows.
### Improvements
- Added setting project directory when passed as a parameter.
- Added activation of windows with SDL_app class name (Moai support).
- Added support for joining/splitting Watch/Stack with Output/Console tabs.
- Added package GetSetting method (ref #166).
- Added selected index to package onMenuEditorTab event (ref #166).
- Added activation of windows with FREEGLUT class name (Moai support).
- Added hiding console window for Corona (2013.8.28+) applications (Windows).
- Added suggesting dynamic words as fields in auto-complete.
- Added socket.connect for compatibility with socket.core <3.0 (fixes #208).
- Added recalculating line number margin width after zooming (fixes #207).
- Added margin constants and removed unused variables.
- Added reporting of socket error for initial debugger calls (Mobdebug 0.5403).
- Added error handling/reporting for `debugger.outputfilter`.
- Added 'debug' option to OSX build script.
- Added ability to modify exe path in base interpreter (ref #197).
- Added package GetEditorNotebook method (ref #166).
- Added 'molokai' color scheme (ref #200).
- added hlsl spec and basic api (note: currently autocomplete doesn't work on object functions, need fix). also fixed cg syntax lexer settings
- Added file activation for abbreviated file names in error messages.
- Added abbreviation of project directories to keep unique parts visible.
- Added `debugger.redirect` configuration option.
- Added `editor.saveallonrun` configuration option.
- Added package GetOutput method (ref #166).
- Added package onAppLoad/onAppClose events (ref #166).
- Added package onIdleOnce event (ref #166).
- Added manifest to the Windows executable and re-signed.
- Added Notepad++ color scheme (thanks to Florian/SiENcE; closes #193).
- Added clearing document styles after saving file with a different extension.
- Added workaround to avoid crash on OSX after `Close All Pages` (closes #190).
- Added return type for string.* functions to assist in auto-complete (ref #189).
- Added handling of string literals in type assignments (closes #189).
- Added support for captures in regexp replacement (\1-\9).
- Added ability to cancel FindInFiles search by closing search dialog (ref #162).
- Added activating Output window before showing search results (ref #162).
- Added support for packages from different platforms to co-exist (ref #166).
- Added ability to save complex data in package settings (ref #166).
- Added support for multiple inheritance in auto-complete (ref #101).
- Added ability to add/remove API descriptions from plugins (ref #166).
- Added package GetSettings/SetSettings methods (ref #166).
- Added methods to save/restore package settings (ref #166).
- Added ability to add/remove specs from plugins (ref #166).
- Added ability to add/remove interpreters from plugins (ref #166).
- Added wxlua patch for twoface compatibility.
- Added `setfenv` for Lua 5.2 compatibility.
- Added links to project page and documentation (closes #180).
- Added German translation (thanks to Riidom; ref #70).
- Added default value to package config (ref #176).
- Added handling of ?51.dll and required DLLs for LuaForWindows interpreter.
- Added plugin::GetConfig method (ref #166).
- Added erasing current line in Console (ref #173).
- Added search/completion in the local and remote console (closes #173).
- Added package onAppFocus* events (ref #166; ref #172).
- Added Chinese translation (thanks to Chow CheeWen; ref #70).
- Added `editor.autoreload` to enable reload of updated files (ref #172).
- Added creating (missing) folders when saving a file (fixes #171).
- Added an example of styling individual keywords.
- Added fold indication of a current block (ref #168).
- Added reporting of process id for a conflicting process.
- allow to define separate lua 5.1 and 5.2 paths in user config
- Changed 'go to definition' to Ctrl/Cmd+Alt+Click (ref #203).
- Changed `un/comment` to act from the beginning of the line for multi-line selection.
- Disabled refreshing Watch/Stack windows when they get focus.
- Disabled markup styling for specs without comment styles.
- Disabled showing tooltip when auto-complete suggestions are shown.
- Disabled error reporting after debugging has been terminated.
- Disabled 'Fold' menu instead of removing when no folding is allowed (ref #169).
- dx11 and glslc updates
- Enabled editing watches with doubleclick or Enter.
- Enable Ctrl+Click and Alt+Left navigation on local variables
- Enabled support for xml/html folding.
- Enabled path remapping for local debugging.
- Enabled slower and more thorough static analysis (ref #149; ref #168).
- Improved file/debugger activation on Windows (ref #199).
- Improved IDE activation during debugging on Windows (closes #199); thanks to jpoag.
- Improved logic to jump to file/line indicated in error messages.
- Limited activation of code fragments to the beginning of debugging session.
- Make code folding optional (thanks to [Mika Attila](https://github.com/crumblingstatue))
- Moved 'Sort' menu to 'Edit'.
- OpenGL 4.4 and ARB extensions added as well as NV_gpu_shader5 functions
- Optimized handling of large tables in stack results.
- Optimized line count calculation for dynamic words when text is deleted.
- Optimized dynamic word processing for large files.
- Reduced CPU usage while idle (ref #204, #206).
- Renamed package onEditorPostSave event to onEditorSave for consistency (ref #166).
- Removed comment from default spec as it forces undesired markup styling.
- Removed auto-complete suggestion when it is already typed (ref #101).
- Reorganized auto-complete handling; should fix #164.
- Reorganized path separator handling to minimize use of global variables.
- Reorganized API processing to allow loading API description from a plugin.
- Replaced package onEditorActivated event with onEditorFocus* events (ref #166).
- Set search in subdirectories as default in Find in Files dialog (ref #162).
- Switched to using POSIX compatible regexp with '()' used for captures.
- Updated LICENSE information.
- Updated Windows build file for wxwidgets 3.0.
- Updated support for MOAI coroutine debugging (Mobdebug 0.541).
- Updated type assignment logic to remove spurious types.
- Updated Windows build script to enable gdb debugging.
- Updated OSX build script to not strip debug builds.
- Updated Corona interpreter to handle failure to copy debugger to Resources/ folder.
- Updated build scripts with proper INSTALL_PREFIX option.
- Updated CFBundleIdentifier in plist files to allow references from OSX programs.
- Updated un/comment to toggle selection as a group rather than line by line.
- Updated `NewFile` to accept a file name.
- Updated 'get hostname' logic to avoid using non-resolvable names (mostly on OSX).
- Updated tooltip to use the same type inference as auto-complete (ref #101).
- Updated Estrela reference in README.
- Updated build script on Windows to enable debugging (ref #164).
- Updated build script with a (temporary) fix for wxlua issue (mingw32).
- updated glewgl api for OpenGL4.4 and removed non-core duplicate functions/enums
- Updated static analyzer to report only first instance of 'unknown field'.
- Updated filename/source code heuristic in the debugger (Mobdebug 0.5362).
- Updated `SaveAll` to allow saving (only) files with filenames (ref #172).
- Upgraded copas and coxpcall libraries (closes #144).
- windows: adopt native user home (thanks to [ardente](https://github.com/ardente))
### Fixes
- Fixed Lua 5.2 crash on OSX (added -O1).
- Fixed onInterpreterLoad to only be called when interpreter changes.
- fix the fixutf8 function (thanks to Enrique García).
- Fixed handling of source code fragments in the Stack view.
- Fixed Watch/Stack windows to refresh when shown.
- Fixed incorrect editor tab acted upon in split notebook situations.
- Fixed auto-complete suggestions for indentifiers matching partial function names.
- Fixed hiding launched windows when running/debugging (Windows).
- Fixed showing known functions in auto-complete.
- Fixed showing output with invalid UTF8 characters in Stack and Console windows.
- Fixed debugging on/off handling in 'main' thread for LuaJIT (MobDebug 0.5402).
- Fixed having duplicate tabs after SaveAs with existing file name.
- Fixed showing redirected 'print' messages after debugging is terminated.
- Fixed using default interpreter when no interpreter is selected.
- Fixed stepping through blocks with undefined variables when 'strict' is in effect (upgraded Mobdebug to 0.5401).
- Fixed loading of files with incorrect UTF-8 encoding and control characters (fixes #198).
- Fixed package sample to take into account new documents.
- Fixed crash on OSX after opening 'application' in 'Open File' dialog.
- Fixed windows resource file to properly reference the manifest.
- Fixed missing default api for files with unknown extensions.
- Fix spurious replacement after 'search, clear selection, replace' actions.
- Fixed using auto-complete with multiple selections (fixes #188).
- Fixed looping in auto-complete with array references (ref #143).
- Fixed showing auto-complete after comma.
- Fixed 'cannot get official hostname' message on low privilege accounts (fixes #183).
- Fixed displaying variable instances when code has invalid blocks (fixes #182).
- Fixed tooltip to ignore string parameters (ref #101).
- Fixed tooltip display between empty brackets (ref #101).
- Fixed indentation after lines with brackets in strings.
- Fixed indentation after lines with anonymous functions.
- Fixed indicator showing at the end of not terminated long comment.
- Fixed an issue with LUA_DEV including files instead of directories.
- Fixed project switching to close all files when switching to a subdirectory.
- Fixed saving projects that do not have any open files.
- Fixed debugger to accept filenames without '@'; thanks to Tim Mensch (closes #174).
- Fixed sorting when the sorted fragment ends with a newline.
## v0.38 (Jun 21 2013)
### Highlights
@@ -426,7 +603,7 @@
### Special thanks
- To Andy Bower and Atilim Cetin for their assistance with Gideros integration and live coding.
- To toiffel for Linux/OSX/Windows CMake-based launcher build.
- To Christoph Kubisch for help with Estrela merge.
- To [Christoph Kubisch](https://github.com/CrazyButcher) for help with Estrela merge.
### Improvements
- Added configuration option to specify hostname when the default one is not reachable (fixes #68).

64
LICENSE
View File

@@ -136,43 +136,59 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--[[ LuaFileSystem License ]]----------------------------------------------
LuaFileSystem was designed by Roberto Ierusalimschy, André Carregal and Tomás
Guisasola as part of the Kepler Project, which holds its copyright.
Homepage: http://www.keplerproject.org/luafilesystem/index.html
License: http://www.keplerproject.org/luafilesystem/license.html
--[[ LuaSockets License ]]-------------------------------------------------
Copyright: © 2004-2006 Diego Nehab. All rights reserved.
Homepage: http://www.cs.princeton.edu/~diego/professional/luasocket/
License: http://www.lua.org/copyright.html (same as LUA)
--[[ ZMQ License ]]--------------------------------------------------------
--[[ Serpent License ]]----------------------------------------------------
Copyright: © 2007-2011 iMatix Corporation and Contributors
Homepage: http://www.zeromq.org/
License: http://www.zeromq.org/area:licensing
Copyright (c) 2011-2013 Paul Kulchenko (paul@kulchenko.com)
LuaZMQ
Copyright: © 2011 by Robert G. Jakabosky
Homepage: https://github.com/Neopallium/lua-zmq
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
--[[ MojoShader License ]]-------------------------------------------------
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Copyright: © 2008-2010 Ryan C. Gordon
Homepage: http://icculus.org/mojoshader/
License: http://hg.icculus.org/icculus/mojoshader/raw-file/tip/LICENSE.txt
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--[[ CLCC License ]]-------------------------------------------------------
--[[ LuaJIT License ]]-----------------------------------------------------
Copyright: © 2009 Organic Vectory B.V.
Homepage: http://clcc.sourceforge.net/
License: boost
Copyright © 2005-2013 Mike Pall, released under the MIT open source license.
CLCC was modified by Christoph Kubisch to support multiple platforms and
output file generation.
--[[ WinAPI License ]]-----------------------------------------------------
Copyright (C) 2011 Steve Donovan.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--[[ MobDebug License ]]---------------------------------------------------

View File

@@ -37,12 +37,16 @@ Open file(s):
zbstudio <filename> [<filename>...]
any non-option will be treated as filename
Set project directory:
zbstudio <project directory> [<filename>...]
(0.39+) a directory passed as a parameter will be set as the project directory
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>]
zbstudio -cfg path/file.lua [<filename>]
e.g.: zbstudio -cfg cfg/estrela.lua
```
@@ -58,12 +62,13 @@ Loading custom configuration:
## Where is Estrela?
The projects have been merged and zbstudio will lead the future.
Please reassociate files with zbstudio. To keep your history of files and
projects copy the contents of the `EstrelaEditor.ini` in your HOME directory
to `ZeroBraneStudio.ini`. If you have used Estrela for graphics shader
authoring or luxinia, create/modify the `cfg/user.lua` to include the content
of `cfg/estrela.lua` to load all tools and specifications by default again.
The projects have been merged and ZeroBrane Studio will lead the future.
Please reassociate files with ZeroBrane Studio. To keep your history of files
and projects copy the contents of the `EstrelaEditor.ini` in your HOME
directory to `ZeroBraneStudio.ini`. If you have used Estrela for graphics
shader authoring or luxinia, create/modify the `cfg/user.lua` to include the
content of `cfg/estrela.lua` to load all tools and specifications by default
again.
## License

View File

@@ -64,6 +64,11 @@ smoothstep = fn "clip and smooth blend [a,b]. - (vecN)(vecN a, b, x)",
floatBitsToInt = fn "returns the 32-bit integer representation of an IEEE 754 floating-point scalar or vector - (uintN/intN)(floatN)",
intBitsToFloat = fn "returns the float value corresponding to a given bit represention.of a scalar int value or vector of int values. - (floatN)(intN)",
uintBitsToFloat = fn "returns the float value corresponding to a given bit represention.of a scalar int value or vector of int values. - (floatN)(uintN)",
doubleBitsToInt64 = fn "returns the 64-bit integer representation of an IEEE 754 double precision floating-point scalar or vector - (int64N)(doubleN)",
doubleBitsToUint64 = fn "returns the 64-bit integer representation of an IEEE 754 double precision floating-point scalar or vector - (uint64N)(doubleN)",
int64BitsToDouble = fn "returns the double value corresponding to a given bit represention.of a scalar int value or vector of int values. - (doubleN)(uint64N)",
uint64BitsToDouble = fn "returns the double value corresponding to a given bit represention.of a scalar int value or vector of int values. - (doubleN)(uint64N)",
fma = fn "return a*b + c, treated as single operation when using precise - (vecN a, vecN b, vecN c)",
frexp = fn "splits scalars and vectors into normalized fraction [0.5,1.0) and a power of 2. - (vecN)(vecN x, out vecN e)",
ldexp = fn "build floating point number from x and the corresponding integral exponen of 2 in exp. - (vecN)(vecN x, exp)",
@@ -73,12 +78,19 @@ packUnorm4x8 = fn "Converts each comp. of v into 8-bit ints, packs results into
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)",
packInt2x32 = fn "Packs two 32 bit into one 64-bit value. - (int64_t)(ivec2)",
packUint2x32 = fn "Packs two 32 bit into one 64-bit value. - (uint64_t)(uvec2)",
packFloat2x16 = fn "returns an unsigned integer obtained by interpreting the components of a two-component 16-bit floating-point as integers and packing them into 32 bit. - (uint)(f16vec2 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)",
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)",
unpackInt2x32 = fn "Unpacks 64-bit into two 32-bit values. - (ivec2)(int64_t)",
unpackUint2x32 = fn "Unpacks 64-bit into two 32-bit values. - (uvec2)(uint64_t)",
unpackFloat2x16 = fn "returns a two-component vector with 16-bit floating-point components obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values. - (f16vec2)(uint)",
length = fn "return scalar Euclidean length of a vector. - (type)(vecN)",
distance = fn "return the Euclidean distance between two points. - (vecN)(vecN a, b)",
@@ -170,6 +182,10 @@ textureGather = fn "gather lookup (pixel quad of 4 single channel samples at onc
textureGatherOffset = fn "gather lookup (pixel quad of 4 single channel samples at once) with offset. Component 0: x, 1: y ... is ignored for shadow samplers instead reference value must be passed. Only 2D/Cube. Illegal for MS. - (vec4)(samplerN, vecN coord, [float shadowRefZ], intN offset / intN offset[4] , [int comp])",
texelFetch = fn "integer coordinate lookup for a single texel. No lod parameter for Buffer, MS, Rect. Illegal for Cube - (vec4)(samplerN, intN coord, [int lod/sample])",
texelFetchOffset = fn "integer coordinate lookup for a single texel with offset. No lod parameter for Buffer, MS, Rect. Illegal for Cube, Buffer, MS. - (vec4)(samplerN, intN coord, [int lod/sample], intN offset)",
anyInvocationARB = fn "returns true if and only if <value> is true for at least one active invocation in the group. - (bool)(bool value)",
allInvocationsARB = fn "returns true if and only if <value> is true for all active invocations in the group - (bool)(bool value)",
allInvocationsEqualARB = fn "returns true if <value> is the same for all active invocation in the group. - (bool)(bool value)",
}
local keyw =
@@ -178,6 +194,18 @@ local keyw =
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
float16_t f16vec2 f16vec3 f16vec4
float32_t f32vec2 f32vec3 f32vec4
float64_t f64vec2 f64vec3 f64vec4
int8_t i8vec2 i8vec3 i8vec4
int8_t i8vec2 i8vec3 i8vec4
int16_t i16vec2 i16vec3 i16vec4
int32_t i32vec2 i32vec3 i32vec4
int64_t i64vec2 i64vec3 i64vec4
uint8_t u8vec2 u8vec3 u8vec4
uint16_t u16vec2 u16vec3 u16vec4
uint32_t u32vec2 u32vec3 u32vec4
uint64_t u64vec2 u64vec3 u64vec4
struct typedef void
usampler1D usampler2D usampler3D usampler2DRect usamplerCube isampler1DArray usampler2DARRAY usamplerCubeArray usampler2DMS usampler2DMSArray
isampler1D isampler2D isampler3D isampler2DRect isamplerCube isampler1DArray isampler2DARRAY isamplerCubeArray isampler2DMS isampler2DMSArray
@@ -189,7 +217,7 @@ local keyw =
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
invocations offset align xfb_offset xfb_buffer
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
@@ -205,6 +233,7 @@ local keyw =
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
gl_BaseVertexARB gl_BaseInstanceARB gl_DrawIDARB
coherent volatile restrict readonly writeonly
image1D image2D image3D image2DRect imageCube imageBuffer image1DArray image2DArray imageCubeArray image2DMS image2DMSArray

60
api/hlsl/dx11.lua Normal file
View File

@@ -0,0 +1,60 @@
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
---------------------------------------------------------
local function fn (description)
local description2,returns,args = description:match("(.+)%-%s*(%b())%s*(%b())")
if not description2 then
return {type="function",description=description,
returns="(?)"}
end
return {type="function",description=description2,
returns=returns:gsub("^%s+",""):gsub("%s+$",""), args = args}
end
local api = {}
local funcs = [[
abs acos all AllMemoryBarrier AllMemoryBarrierWithGroupSync any asdouble asfloat asin asint asuint atan atan2 ceil clamp clip cos cosh countbits cross ddx ddx_coarse ddx_fine ddy ddy_coards ddy_fine degrees determinant DeviceMemoryBarrier DeviceMemoryBarrierWithGroupSync distance dot dst EvaluateAttributeAtCentroid EvaluateAttributeAtSample EvaluateAttributeSnapped exp exp2 f16tof32 f32tof16 faceforward firstbithigh firstbitlow floor fmod frac frexp fwidth GetRenderTargetSampleCount GetRenderTargetSamplePosition GroupMemoryBarrier GroupMemoryBarrierWithGroupSync InterlockedAdd InterlockedAnd InterlockedCompareExchange InterlockedExchange InterlockedMax InterlockedMin IntterlockedOr InterlockedXor isfinite isinf isnan ldexp length lerp lit log log10 log2 mad max min modf mul normalize pow Process2DQuadTessFactorsAvg Process2DQuadTessFactorsMax Process2DQuadTessFactorsMin ProcessIsolineTessFactors ProcessQuadTessFactorsAvg ProcessQuadTessFactorsMax ProcessQuadTessFactorsMin ProcessTriTessFactorsAvg ProcessTriTessFactorsMax ProcessTriTessFactorsMin radians rcp reflect refract reversebits round rsqrt saturate sign sin sincos sinh smoothstep sqrt step tan tanh transpose trunc
]]
for w in funcs:gmatch("([_%w]+)") do
api[w] = {type="function",returns="(?)"}
end
local objfuncs = [[
Append RestartStrip CalculateLevelOfDetail CalculateLevelOfDetailUnclamped GetDimensions GetSamplePosition Load Sample SampleBias SampleCmp SampleCmpLevelZero SampleGrad SampleLevel Load2 Load3 Load4 Consume Store Store2 Store3 Store4 DecrementCounter IncrementCounter mips Gather GatherRed GatherGreen GatherBlue GatherAlpha GatherCmp GatherCmpRed GatherCmpGreen GatherCmpBlue GatherCmpAlpha
]]
for w in objfuncs:gmatch("([_%w]+)") do
api[w] = {type="function",returns="(?)"}
end
local keyw =
[[break continue if else switch return for while do typedef namespace true false compile
const void struct static extern register volatile inline target nointerpolation shared uniform row_major column_major snorm unorm
bool bool1 bool2 bool3 bool4 int int1 int2 int3 int4 uint uint1 uint2 uint3 uint4 half half1 half2 half3 half4 float float1 float2 float3 float4 double double1 double2 double3 double4
matrix bool1x1 bool1x2 bool1x3 bool1x4 bool2x1 bool2x2 bool2x3 bool2x4 bool3x1 bool3x2 bool3x3 bool3x4 bool4x1 bool4x2 bool4x3 bool4x4
int1x1 int1x2 int1x3 int1x4 int2x1 int2x2 int2x3 int2x4 int3x1 int3x2 int3x3 int3x4 int4x1 int4x2 int4x3 int4x4 uint1x1 uint1x2 uint1x3 uint1x4
uint2x1 uint2x2 uint2x3 uint2x4 uint3x1 uint3x2 uint3x3 uint3x4 uint4x1 uint4x2 uint4x3 uint4x4 half1x1 half1x2 half1x3 half1x4 half2x1 half2x2
half2x3 half2x4 half3x1 half3x2 half3x3 half3x4 half4x1 half4x2 half4x3 half4x4 float1x1 float1x2 float1x3 float1x4 float2x1 float2x2 float2x3
float2x4 float3x1 float3x2 float3x3 float3x4 float4x1 float4x2 float4x3 float4x4 double1x1 double1x2 double1x3 double1x4 double2x1 double2x2
double2x3 double2x4 double3x1 double3x2 double3x3 double3x4 double4x1 double4x2 double4x3 double4x4 cbuffer groupshared SamplerState
in out inout vector matrix interface class point triangle line lineadj triangleadj
Texture Texture1D Texture1DArray Texture2D Texture2DArray Texture2DMS Texture2DMSArray Texture3D TextureCube RWTexture1D RWTexture1DArray RWTexture2D RWTexture2DArray RWTexture3D
Buffer StructuredBuffer AppendStructuredBuffer ConsumeStructuredBuffer RWBuffer RWStructuredBuffer ByteAddressBuffer RWByteAddressBuffer PointStream TriangleStream LineStream InputPatch OutputPatch
unroll loop flatten branch earlydepthstencil allow_uav_condition domain instance maxtessfactor outputcontrolpoints outputtopology partitioning patchconstantfunc numthreads maxvertexcount precise
SV_DispatchThreadID SV_DomainLocation SV_GroupID SV_GroupIndex SV_GroupThreadID SV_GSInstanceID SV_InsideTessFactor SV_OutputControlPointID SV_Coverage SV_Depth SV_Position SV_IsFrontFace SV_RenderTargetArrayIndex SV_SampleIndex SV_ViewportArrayIndex SV_InstanceID SV_PrimitiveID SV_VertexID
SV_ClipDistance SV_CullDistance SV_Target
]]
-- keywords - shouldn't be left out
for w in keyw:gmatch("([_%w]+)") do
api[w] = {type="keyword"}
end
return api

View File

@@ -324,12 +324,14 @@ return {
description = "Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument.\n\nNumerical codes are not necessarily portable across platforms.",
args = "(...)",
returns = "(string)",
valuetype = "string",
},
dump = {
type = "function",
description = "Returns a string containing a binary representation of the given function, so that a later load on this string returns a copy of the function (but with new upvalues).",
args = "(function: function)",
returns = "(string)",
valuetype = "string",
},
find = {
type = "function",
@@ -342,6 +344,7 @@ return {
description = "Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string).\n\nThe format string follows the same rules as the C function sprintf. The only differences are that the options/modifiers *, h, L, l, n, and p are not supported and that there is an extra option, q. The q option formats a string between double quotes, using escape sequences when necessary to ensure that it can safely be read back by the Lua interpreter.\n\nOptions A and a (when available) (VALUES ADDED IN Lua 5.2), E, e, f, G, and g all expect a number as argument. Options c, d, i, o, u, X, and x also expect a number, but the range of that number may be limited by the underlying C implementation. For options o, u, X, and x, the number cannot be negative. Option q expects a string; option s expects a string without embedded zeros. If the argument to option s is not a string, it is converted to one following the same rules of tostring (BEHAVIOR ADDED IN Lua 5.2).",
args = "(formatstring, ...)",
returns = "(string)",
valuetype = "string",
},
gmatch = {
type = "function",
@@ -354,6 +357,7 @@ return {
description = "Returns a copy of s in which all (or the first n, if given) occurrences of the pattern have been replaced by a replacement string specified by repl, which can be a string, a table, or a function.\n\ngsub also returns, as its second value, the total number of matches that occurred. The name gsub comes from Global SUBstitution.\n\nIf repl is a string, then its value is used for replacement. The character % works as an escape character: any sequence in repl of the form %d, with d between 1 and 9, stands for the value of the d-th captured substring. The sequence %0 stands for the whole match. The sequence %% stands for a single %.\n\nIf repl is a table, then the table is queried for every match, using the first capture as the key.\n\nIf repl is a function, then this function is called every time a match occurs, with all captured substrings passed as arguments, in order.\n\nIn any case, if the pattern specifies no captures, then it behaves as if the whole pattern was inside a capture.\n\nIf the value returned by the table query or by the function call is a string or a number, then it is used as the replacement string; otherwise, if it is false or nil, then there is no replacement (that is, the original match is kept in the string).",
args = "(s: string, pattern: string, repl: string|table|function [, n: number])",
returns = "(string, number)",
valuetype = "string",
},
len = {
type = "function",
@@ -366,36 +370,42 @@ return {
description = "Receives a string and returns a copy of this string with all uppercase letters changed to lowercase.\n\nAll other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale.",
args = "(s: string)",
returns = "(string)",
valuetype = "string",
},
match = {
type = "function",
description = "Looks for the first match of pattern in the string s.\n\nIf it finds one, then match returns the captures from the pattern; otherwise it returns nil.\n\nIf pattern specifies no captures, then the whole match is returned. A third, optional numerical argument init specifies where to start the search; its default value is 1 and can be negative.",
args = "(s: string, pattern: string [, init: number])",
returns = "(string|nil [,...])",
valuetype = "string",
},
rep = {
type = "function",
description = "Returns a string that is the concatenation of n copies of the string s separated by the string sep.\n\nThe default value for sep is the empty string (that is, no separator). ARGUMENT ADDED IN Lua 5.2.",
args = "(s: string, n: number [, sep: string])",
returns = "(string)",
valuetype = "string",
},
reverse = {
type = "function",
description = "Returns a string that is the string s reversed.",
args = "(s: string)",
returns = "(string)",
valuetype = "string",
},
sub = {
type = "function",
description = "Returns the substring of s that starts at i and continues until j; i and j can be negative.\n\nIf j is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s, -i) returns a suffix of s with length i.\n\nIf, after the translation of negative indices, i is less than 1, it is corrected to 1. If j is greater than the string length, it is corrected to that length. If, after these corrections, i is greater than j, the function returns the empty string.",
args = "(s: string, i: number [, j: number])",
returns = "(string)",
valuetype = "string",
},
upper = {
type = "function",
description = "Receives a string and returns a copy of this string with all lowercase letters changed to uppercase.\n\nAll other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale.",
args = "(s: string)",
returns = "(string)",
valuetype = "string",
},
},
},
@@ -410,6 +420,7 @@ return {
description = "Given a list where all elements are strings or numbers, returns list[i]..sep..list[i+1] ··· sep..list[j].\n\nThe default value for sep is the empty string, the default for i is 1, and the default for j is #list. If i is greater than j, returns the empty string.",
args = "(list: table [, sep: string [, i: number [, j: number]]])",
returns = "(string)",
valuetype = "string",
},
insert = {
type = "function",

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/clibs52/mime/core.dll Normal file

Binary file not shown.

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

Binary file not shown.

BIN
bin/clibs52/socket/core.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/liblua52.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.

BIN
bin/linux/x64/lua52 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.

BIN
bin/linux/x86/lua52 Executable file

Binary file not shown.

BIN
bin/lua

Binary file not shown.

1
bin/lua Symbolic link
View File

@@ -0,0 +1 @@
lua.app/Contents/MacOS/lua

View File

@@ -13,7 +13,7 @@
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string></string>
<string>org.Lua.LuaInterpreter</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
bin/lua52 Symbolic link
View File

@@ -0,0 +1 @@
lua.app/Contents/MacOS/lua52

BIN
bin/lua52.dll Normal file

Binary file not shown.

BIN
bin/lua52.exe Normal file

Binary file not shown.

View File

@@ -32,16 +32,12 @@ ZLIB_BASENAME="zlib-1.2.8"
ZLIB_FILENAME="$ZLIB_BASENAME.tar.gz"
ZLIB_URL="https://github.com/madler/zlib/archive/v1.2.8.tar.gz"
LUA_BASENAME="lua-5.1.5"
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
WXLUA_BASENAME="wxlua"
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/trunk"
WXLUA_URL="https://svn.code.sf.net/p/wxlua/svn/trunk"
LUASOCKET_BASENAME="luasocket-2.0.3"
LUASOCKET_FILENAME="$LUASOCKET_BASENAME-rc2.zip"
LUASOCKET_URL="https://github.com/downloads/diegonehab/luasocket/$LUASOCKET_FILENAME"
LUASOCKET_BASENAME="luasocket-3.0-rc1"
LUASOCKET_FILENAME="v3.0-rc1.zip"
LUASOCKET_URL="https://github.com/diegonehab/luasocket/archive/$LUASOCKET_FILENAME"
# exit if the command line is empty
if [ $# -eq 0 ]; then
@@ -52,6 +48,12 @@ fi
# iterate through the command line arguments
for ARG in "$@"; do
case $ARG in
5.2)
BUILD_52=true
;;
jit)
BUILD_JIT=true
;;
wxwidgets)
BUILD_WXWIDGETS=true
;;
@@ -104,6 +106,25 @@ fi
# create the installation directory
mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR"; exit 1; }
LUAV="51"
LUAS=""
LUA_BASENAME="lua-5.1.5"
if [ $BUILD_52 ]; then
LUAV="52"
LUAS=$LUAV
LUA_BASENAME="lua-5.2.2"
fi
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
if [ $BUILD_JIT ]; then
LUA_BASENAME="LuaJIT-2.0.2"
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://luajit.org/download/$LUA_FILENAME"
fi
# build wxWidgets
if [ $BUILD_WXWIDGETS ]; then
# first build get/configure libpng as v1.6 is needed
@@ -142,10 +163,21 @@ if [ $BUILD_LUA ]; then
wget -c "$LUA_URL" -O "$LUA_FILENAME" || { echo "Error: failed to download Lua"; exit 1; }
tar -xzf "$LUA_FILENAME"
cd "$LUA_BASENAME"
# use POSIX as it has minimum dependencies (no readline and no ncurses required)
# LUA_USE_DLOPEN is required for loading libraries
(cd src; make all MYCFLAGS="$FPIC -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E -ldl") || { echo "Error: failed to build Lua"; exit 1; }
make install INSTALL_TOP="$INSTALL_DIR"
if [ $BUILD_JIT ]; then
make CCOPT="-DLUAJIT_ENABLE_LUA52COMPAT" || { echo "Error: failed to build Lua"; exit 1; }
make install PREFIX="$INSTALL_DIR"
cp "$INSTALL_DIR/bin/luajit" "$INSTALL_DIR/bin/lua"
# move luajit to lua as it's expected by luasocket and other components
cp "$INSTALL_DIR"/include/luajit*/* "$INSTALL_DIR/include/"
else
# use POSIX as it has minimum dependencies (no readline and no ncurses required)
# LUA_USE_DLOPEN is required for loading libraries
(cd src; make all MYCFLAGS="$FPIC -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E -ldl") || { echo "Error: failed to build Lua"; exit 1; }
make install INSTALL_TOP="$INSTALL_DIR"
fi
cp "$INSTALL_DIR/bin/lua" "$INSTALL_DIR/bin/lua$LUAV"
cd ..
rm -rf "$LUA_FILENAME" "$LUA_BASENAME"
fi
@@ -157,7 +189,7 @@ if [ $BUILD_WXLUA ]; then
# the following patches wxlua source to fix live coding support in wxlua apps
# http://www.mail-archive.com/wxlua-users@lists.sourceforge.net/msg03225.html
sed -i 's/\(m_wxlState = wxLuaState(wxlState.GetLuaState(), wxLUASTATE_GETSTATE|wxLUASTATE_ROOTSTATE);\)/\/\/ removed by ZBS build process \/\/ \1/' modules/wxlua/wxlcallb.cpp
cmake -G "Unix Makefiles" -DBUILD_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_SHARED_LIBS=FALSE \
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_SHARED_LIBS=FALSE \
-DwxWidgets_CONFIG_EXECUTABLE="$INSTALL_DIR/bin/wx-config" \
-DwxWidgets_COMPONENTS="stc;html;aui;adv;core;net;base" \
-DwxLuaBind_COMPONENTS="stc;html;aui;adv;core;net;base" -DwxLua_LUA_LIBRARY_USE_BUILTIN=FALSE \
@@ -174,31 +206,30 @@ if [ $BUILD_LUASOCKET ]; then
wget --no-check-certificate -c "$LUASOCKET_URL" -O "$LUASOCKET_FILENAME" || { echo "Error: failed to download LuaSocket"; exit 1; }
unzip "$LUASOCKET_FILENAME"
cd "$LUASOCKET_BASENAME"
mkdir -p "$INSTALL_DIR/lib/lua/5.1/"{mime,socket}
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/mime/core.so" src/mime.c -llua \
mkdir -p "$INSTALL_DIR/lib/lua/$LUAV/"{mime,socket}
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/$LUAV/mime/core.so" src/mime.c -llua \
|| { echo "Error: failed to build LuaSocket"; exit 1; }
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/socket/core.so" \
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/$LUAV/socket/core.so" \
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,usocket.c} -llua \
|| { echo "Error: failed to build LuaSocket"; exit 1; }
mkdir -p "$INSTALL_DIR/share/lua/5.1/socket"
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/5.1/socket"
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/5.1"
[ -f "$INSTALL_DIR/lib/lua/5.1/mime/core.so" ] || { echo "Error: mime/core.so isn't found"; exit 1; }
[ -f "$INSTALL_DIR/lib/lua/5.1/socket/core.so" ] || { echo "Error: socket/core.so isn't found"; exit 1; }
mkdir -p "$INSTALL_DIR/share/lua/$LUAV/socket"
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/$LUAV/socket"
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/$LUAV"
[ -f "$INSTALL_DIR/lib/lua/$LUAV/mime/core.so" ] || { echo "Error: mime/core.so isn't found"; exit 1; }
[ -f "$INSTALL_DIR/lib/lua/$LUAV/socket/core.so" ] || { echo "Error: socket/core.so isn't found"; exit 1; }
cd ..
rm -rf "$LUASOCKET_FILENAME" "$LUASOCKET_BASENAME"
fi
# now copy the compiled dependencies to ZBS binary directory
mkdir -p "$BIN_DIR" || { echo "Error: cannot create directory $BIN_DIR"; exit 1; }
[ $BUILD_LUA ] && cp "$INSTALL_DIR/bin/lua" "$BIN_DIR"
[ $BUILD_LUA ] && cp "$INSTALL_DIR/bin/lua$LUAS" "$BIN_DIR"
[ $BUILD_WXLUA ] && cp "$INSTALL_DIR/lib/libwx.so" "$BIN_DIR"
if [ $BUILD_LUASOCKET ]; then
mkdir -p "$BIN_DIR/clibs/"{mime,socket}
cp "$INSTALL_DIR/lib/lua/5.1/mime/core.so" "$BIN_DIR/clibs/mime"
cp "$INSTALL_DIR/lib/lua/5.1/socket/core.so" "$BIN_DIR/clibs/socket"
mkdir -p "$BIN_DIR/clibs$LUAS/"{mime,socket}
cp "$INSTALL_DIR/lib/lua/$LUAV/mime/core.so" "$BIN_DIR/clibs$LUAS/mime"
cp "$INSTALL_DIR/lib/lua/$LUAV/socket/core.so" "$BIN_DIR/clibs$LUAS/socket"
fi
# show a message about successful completion
echo "*** Build has been successfully completed ***"
exit 0

View File

@@ -22,16 +22,12 @@ BUILD_FLAGS="-O2 -arch x86_64 -dynamiclib -undefined dynamic_lookup $MACOSX_FLAG
WXWIDGETS_BASENAME="wxWidgets"
WXWIDGETS_URL="http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk"
LUA_BASENAME="lua-5.1.5"
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
WXLUA_BASENAME="wxlua"
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/trunk"
WXLUA_URL="https://svn.code.sf.net/p/wxlua/svn/trunk"
LUASOCKET_BASENAME="luasocket-2.0.3"
LUASOCKET_FILENAME="$LUASOCKET_BASENAME-rc2.zip"
LUASOCKET_URL="https://github.com/downloads/diegonehab/luasocket/$LUASOCKET_FILENAME"
LUASOCKET_BASENAME="luasocket-3.0-rc1"
LUASOCKET_FILENAME="v3.0-rc1.zip"
LUASOCKET_URL="https://github.com/diegonehab/luasocket/archive/$LUASOCKET_FILENAME"
# exit if the command line is empty
if [ $# -eq 0 ]; then
@@ -39,9 +35,19 @@ if [ $# -eq 0 ]; then
exit 0
fi
WXLUASTRIP="/strip"
WXWIDGETSDEBUG="--disable-debug"
WXLUABUILD="MinSizeRel"
# iterate through the command line arguments
for ARG in "$@"; do
case $ARG in
5.2)
BUILD_52=true
;;
jit)
BUILD_JIT=true
;;
wxwidgets)
BUILD_WXWIDGETS=true
;;
@@ -54,6 +60,11 @@ for ARG in "$@"; do
luasocket)
BUILD_LUASOCKET=true
;;
debug)
WXLUASTRIP=""
WXWIDGETSDEBUG="--enable-debug=max"
WXLUABUILD="Debug"
;;
all)
BUILD_WXWIDGETS=true
BUILD_LUA=true
@@ -94,11 +105,30 @@ fi
# create the installation directory
mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR"; exit 1; }
LUAV="51"
LUAS=""
LUA_BASENAME="lua-5.1.5"
if [ $BUILD_52 ]; then
LUAV="52"
LUAS=$LUAV
LUA_BASENAME="lua-5.2.2"
fi
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
if [ $BUILD_JIT ]; then
LUA_BASENAME="LuaJIT-2.0.2"
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://luajit.org/download/$LUA_FILENAME"
fi
# build wxWidgets
if [ $BUILD_WXWIDGETS ]; then
svn co "$WXWIDGETS_URL" "$WXWIDGETS_BASENAME" || { echo "Error: failed to checkout wxWidgets"; exit 1; }
cd "$WXWIDGETS_BASENAME"
./configure --prefix="$INSTALL_DIR" --disable-debug --disable-shared --enable-unicode \
./configure --prefix="$INSTALL_DIR" $WXWIDGETSDEBUG --disable-shared --enable-unicode \
--with-libjpeg=builtin --with-libpng=builtin --with-libtiff=no --with-expat=no \
--with-zlib=builtin --disable-richtext \
--enable-macosx_arch=$MACOSX_ARCH --with-macosx-version-min=$MACOSX_VERSION --with-macosx-sdk="$MACOSX_SDK_PATH" \
@@ -114,16 +144,29 @@ if [ $BUILD_LUA ]; then
wget -c "$LUA_URL" -O "$LUA_FILENAME" || { echo "Error: failed to download Lua"; exit 1; }
tar -xzf "$LUA_FILENAME"
cd "$LUA_BASENAME"
sed -i "" 's/PLATS=/& macosx_dylib/' Makefile
printf "macosx_dylib:\n" >> src/Makefile
printf "\t\$(MAKE) LUA_A=\"liblua.dylib\" AR=\"\$(CC) -dynamiclib $MACOSX_FLAGS -o\" RANLIB=\"strip -u -r\" \\\\\n" >> src/Makefile
printf "\tMYCFLAGS=\"-DLUA_USE_LINUX $MACOSX_FLAGS\" MYLDFLAGS=\"$MACOSX_FLAGS\" MYLIBS=\"-lreadline\" lua\n" >> src/Makefile
printf "\t\$(MAKE) MYCFLAGS=\"-DLUA_USE_LINUX $MACOSX_FLAGS\" MYLDFLAGS=\"$MACOSX_FLAGS\" luac\n" >> src/Makefile
make macosx_dylib || { echo "Error: failed to build Lua"; exit 1; }
make install INSTALL_TOP="$INSTALL_DIR"
strip -u -r "$INSTALL_DIR/bin/lua"
cp src/liblua.dylib "$INSTALL_DIR/lib"
[ -f "$INSTALL_DIR/lib/liblua.dylib" ] || { echo "Error: liblua.dylib isn't found"; exit 1; }
if [ $BUILD_JIT ]; then
make BUILDMODE=dynamic LUAJIT_SO=liblua.dylib TARGET_DYLIBPATH=liblua.dylib CC="gcc -m32" CCOPT="$MACOSX_FLAGS -DLUAJIT_ENABLE_LUA52COMPAT" || { echo "Error: failed to build Lua"; exit 1; }
make install PREFIX="$INSTALL_DIR"
cp "src/luajit" "$INSTALL_DIR/bin/lua"
cp "src/liblua.dylib" "$INSTALL_DIR/lib"
# move luajit to lua as it's expected by luasocket and other components
cp "$INSTALL_DIR"/include/luajit*/* "$INSTALL_DIR/include/"
else
sed -i "" 's/PLATS=/& macosx_dylib/' Makefile
# -O1 fixes this issue with for Lua 5.2 with i386: http://lua-users.org/lists/lua-l/2013-05/msg00070.html
printf "macosx_dylib:\n" >> src/Makefile
printf "\t\$(MAKE) LUA_A=\"liblua$LUAS.dylib\" AR=\"\$(CC) -dynamiclib $MACOSX_FLAGS -o\" RANLIB=\"strip -u -r\" \\\\\n" >> src/Makefile
printf "\tMYCFLAGS=\"-O1 -DLUA_USE_LINUX $MACOSX_FLAGS\" MYLDFLAGS=\"$MACOSX_FLAGS\" MYLIBS=\"-lreadline\" lua\n" >> src/Makefile
printf "\t\$(MAKE) MYCFLAGS=\"-DLUA_USE_LINUX $MACOSX_FLAGS\" MYLDFLAGS=\"$MACOSX_FLAGS\" luac\n" >> src/Makefile
make macosx_dylib || { echo "Error: failed to build Lua"; exit 1; }
make install INSTALL_TOP="$INSTALL_DIR"
mv "$INSTALL_DIR/bin/lua" "$INSTALL_DIR/bin/lua$LUAS"
cp src/liblua$LUAS.dylib "$INSTALL_DIR/lib"
fi
strip -u -r "$INSTALL_DIR/bin/lua$LUAS"
[ -f "$INSTALL_DIR/lib/liblua$LUAS.dylib" ] || { echo "Error: liblua$LUAS.dylib isn't found"; exit 1; }
cd ..
rm -rf "$LUA_FILENAME" "$LUA_BASENAME"
fi
@@ -135,15 +178,15 @@ if [ $BUILD_WXLUA ]; then
# the following patches wxlua source to fix live coding support in wxlua apps
# http://www.mail-archive.com/wxlua-users@lists.sourceforge.net/msg03225.html
sed -i "" 's/\(m_wxlState = wxLuaState(wxlState.GetLuaState(), wxLUASTATE_GETSTATE|wxLUASTATE_ROOTSTATE);\)/\/\/ removed by ZBS build process \/\/ \1/' modules/wxlua/wxlcallb.cpp
cmake -G "Unix Makefiles" -DBUILD_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_SHARED_LIBS=FALSE \
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=$WXLUABUILD -DBUILD_SHARED_LIBS=FALSE \
-DCMAKE_OSX_ARCHITECTURES=$MACOSX_ARCH -DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOSX_VERSION CMAKE_OSX_SYSROOT="$MACOSX_SDK_PATH" \
-DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DwxWidgets_CONFIG_EXECUTABLE="$INSTALL_DIR/bin/wx-config" \
-DwxWidgets_COMPONENTS="stc;html;aui;adv;core;net;base" \
-DwxLuaBind_COMPONENTS="stc;html;aui;adv;core;net;base" -DwxLua_LUA_LIBRARY_USE_BUILTIN=FALSE \
-DwxLua_LUA_INCLUDE_DIR="$INSTALL_DIR/include" -DwxLua_LUA_LIBRARY="$INSTALL_DIR/lib/liblua.dylib" .
(cd modules/luamodule; make $MAKEFLAGS) || { echo "Error: failed to build wxLua"; exit 1; }
(cd modules/luamodule; make install/strip)
strip -u -r "$INSTALL_DIR/lib/libwx.dylib"
(cd modules/luamodule; make install$WXLUASTRIP)
if [ $WXLUASTRIP ]; then strip -u -r "$INSTALL_DIR/lib/libwx.dylib"; fi
[ -f "$INSTALL_DIR/lib/libwx.dylib" ] || { echo "Error: libwx.dylib isn't found"; exit 1; }
cd ../..
rm -rf "$WXLUA_BASENAME"
@@ -154,36 +197,38 @@ if [ $BUILD_LUASOCKET ]; then
wget --no-check-certificate -c "$LUASOCKET_URL" -O "$LUASOCKET_FILENAME" || { echo "Error: failed to download LuaSocket"; exit 1; }
unzip "$LUASOCKET_FILENAME"
cd "$LUASOCKET_BASENAME"
mkdir -p "$INSTALL_DIR/lib/lua/5.1/"{mime,socket}
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" src/mime.c \
mkdir -p "$INSTALL_DIR/lib/lua/$LUAV/"{mime,socket}
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dylib" src/mime.c \
|| { echo "Error: failed to build LuaSocket"; exit 1; }
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib" \
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dylib" \
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,usocket.c} \
|| { echo "Error: failed to build LuaSocket"; exit 1; }
strip -u -r "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib"
mkdir -p "$INSTALL_DIR/share/lua/5.1/socket"
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/5.1/socket"
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/5.1"
[ -f "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" ] || { echo "Error: mime/core.dylib isn't found"; exit 1; }
[ -f "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib" ] || { echo "Error: socket/core.dylib isn't found"; exit 1; }
strip -u -r "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dylib" "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dylib"
install_name_tool -id core.dylib "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dylib"
install_name_tool -id core.dylib "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dylib"
mkdir -p "$INSTALL_DIR/share/lua/$LUAV/socket"
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/$LUAV/socket"
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/$LUAV"
[ -f "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dylib" ] || { echo "Error: mime/core.dylib isn't found"; exit 1; }
[ -f "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dylib" ] || { echo "Error: socket/core.dylib isn't found"; exit 1; }
cd ..
rm -rf "$LUASOCKET_FILENAME" "$LUASOCKET_BASENAME"
fi
# now copy the compiled dependencies to ZBS binary directory
mkdir -p "$BIN_DIR" || { echo "Error: cannot create directory $BIN_DIR"; exit 1; }
if [ $BUILD_LUA ]; then
mkdir -p "$BIN_DIR/lua.app/Contents/MacOS"
cp "$INSTALL_DIR/bin/lua" "$BIN_DIR/lua.app/Contents/MacOS"
cp "$INSTALL_DIR/bin/lua" "$INSTALL_DIR/lib/liblua.dylib" "$BIN_DIR"
cp "$INSTALL_DIR/bin/lua$LUAS" "$BIN_DIR/lua.app/Contents/MacOS"
cp "$INSTALL_DIR/bin/lua$LUAS" "$INSTALL_DIR/lib/liblua$LUAS.dylib" "$BIN_DIR"
fi
[ $BUILD_WXLUA ] && cp "$INSTALL_DIR/lib/libwx.dylib" "$BIN_DIR"
if [ $BUILD_LUASOCKET ]; then
mkdir -p "$BIN_DIR/clibs/"{mime,socket}
cp "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" "$BIN_DIR/clibs/mime"
cp "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib" "$BIN_DIR/clibs/socket"
mkdir -p "$BIN_DIR/clibs$LUAS/"{mime,socket}
cp "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dylib" "$BIN_DIR/clibs$LUAS/mime"
cp "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dylib" "$BIN_DIR/clibs$LUAS/socket"
fi
# show a message about successful completion
echo "*** Build has been successfully completed ***"
exit 0

View File

@@ -7,7 +7,7 @@ BIN_DIR="$(dirname "$PWD")/bin"
INSTALL_DIR="$PWD/deps"
# number of parallel jobs used for building
MAKEFLAGS="-j4"
MAKEFLAGS="-j1" # some make may hang on Windows with j4 or j7
# flags for manual building with gcc
BUILD_FLAGS="-O2 -shared -s -I $INSTALL_DIR/include -L $INSTALL_DIR/lib"
@@ -16,16 +16,12 @@ BUILD_FLAGS="-O2 -shared -s -I $INSTALL_DIR/include -L $INSTALL_DIR/lib"
WXWIDGETS_BASENAME="wxWidgets"
WXWIDGETS_URL="http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk"
LUA_BASENAME="lua-5.1.5"
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
WXLUA_BASENAME="wxlua"
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/trunk"
WXLUA_URL="https://svn.code.sf.net/p/wxlua/svn/trunk"
LUASOCKET_BASENAME="luasocket-2.0.3"
LUASOCKET_FILENAME="$LUASOCKET_BASENAME-rc2.zip"
LUASOCKET_URL="https://github.com/downloads/diegonehab/luasocket/$LUASOCKET_FILENAME"
LUASOCKET_BASENAME="luasocket-3.0-rc1"
LUASOCKET_FILENAME="v3.0-rc1.zip"
LUASOCKET_URL="https://github.com/diegonehab/luasocket/archive/$LUASOCKET_FILENAME"
OPENSSL_BASENAME="openssl-1.0.1e"
OPENSSL_FILENAME="$OPENSSL_BASENAME.tar.gz"
@@ -44,9 +40,19 @@ if [ $# -eq 0 ]; then
exit 0
fi
WXLUASTRIP="/strip"
WXWIDGETSDEBUG="--disable-debug"
WXLUABUILD="MinSizeRel"
# iterate through the command line arguments
for ARG in "$@"; do
case $ARG in
5.2)
BUILD_52=true
;;
jit)
BUILD_JIT=true
;;
wxwidgets)
BUILD_WXWIDGETS=true
;;
@@ -68,6 +74,11 @@ for ARG in "$@"; do
zbstudio)
BUILD_ZBSTUDIO=true
;;
debug)
WXLUASTRIP=""
WXWIDGETSDEBUG="--enable-debug=max --enable-debug_gdb"
WXLUABUILD="Debug"
;;
all)
BUILD_WXWIDGETS=true
BUILD_LUA=true
@@ -116,12 +127,31 @@ fi
# create the installation directory
mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR"; exit 1; }
LUAV="51"
LUAS=""
LUA_BASENAME="lua-5.1.5"
if [ $BUILD_52 ]; then
LUAV="52"
LUAS=$LUAV
LUA_BASENAME="lua-5.2.2"
fi
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
if [ $BUILD_JIT ]; then
LUA_BASENAME="LuaJIT-2.0.2"
LUA_FILENAME="$LUA_BASENAME.tar.gz"
LUA_URL="http://luajit.org/download/$LUA_FILENAME"
fi
# build wxWidgets
if [ $BUILD_WXWIDGETS ]; then
svn co "$WXWIDGETS_URL" "$WXWIDGETS_BASENAME" || { echo "Error: failed to checkout wxWidgets"; exit 1; }
svn revert -R "$WXWIDGETS_BASENAME"
cd "$WXWIDGETS_BASENAME"
./configure --prefix="$INSTALL_DIR" --disable-debug --disable-shared --enable-unicode \
./configure --prefix="$INSTALL_DIR" $WXWIDGETSDEBUG --disable-shared --enable-unicode \
--with-libjpeg=builtin --with-libpng=builtin --with-libtiff=no --with-expat=no \
--with-zlib=builtin --disable-richtext \
CFLAGS="-Os -fno-keep-inline-dllexport" CXXFLAGS="-Os -fno-keep-inline-dllexport"
@@ -136,10 +166,19 @@ if [ $BUILD_LUA ]; then
wget -c "$LUA_URL" -O "$LUA_FILENAME" || { echo "Error: failed to download Lua"; exit 1; }
tar -xzf "$LUA_FILENAME"
cd "$LUA_BASENAME"
make mingw || { echo "Error: failed to build Lua"; exit 1; }
make install INSTALL_TOP="$INSTALL_DIR"
cp src/lua51.dll "$INSTALL_DIR/lib"
[ -f "$INSTALL_DIR/lib/lua51.dll" ] || { echo "Error: lua51.dll isn't found"; exit 1; }
if [ $BUILD_JIT ]; then
make CCOPT="-DLUAJIT_ENABLE_LUA52COMPAT" || { echo "Error: failed to build Lua"; exit 1; }
make install PREFIX="$INSTALL_DIR"
cp "$INSTALL_DIR/bin/luajit.exe" "$INSTALL_DIR/bin/lua.exe"
# move luajit to lua as it's expected by luasocket and other components
cp "$INSTALL_DIR"/include/luajit*/* "$INSTALL_DIR/include/"
else
make mingw || { echo "Error: failed to build Lua"; exit 1; }
make install INSTALL_TOP="$INSTALL_DIR"
fi
cp src/lua$LUAV.dll "$INSTALL_DIR/lib"
cp "$INSTALL_DIR/bin/lua.exe" "$INSTALL_DIR/bin/lua$LUAV.exe"
[ -f "$INSTALL_DIR/lib/lua$LUAV.dll" ] || { echo "Error: lua$LUAV.dll isn't found"; exit 1; }
cd ..
rm -rf "$LUA_FILENAME" "$LUA_BASENAME"
fi
@@ -151,18 +190,28 @@ if [ $BUILD_WXLUA ]; then
cd "$WXLUA_BASENAME/wxLua"
sed -i 's|:-/\(.\)/|:-\1:/|' "$INSTALL_DIR/bin/wx-config"
sed -i 's/execute_process(COMMAND/& sh/' build/CMakewxAppLib.cmake modules/wxstedit/build/CMakewxAppLib.cmake
# the following patches wxlua source to fix live coding support in wxlua apps
# http://www.mail-archive.com/wxlua-users@lists.sourceforge.net/msg03225.html
sed -i 's/\(m_wxlState = wxLuaState(wxlState.GetLuaState(), wxLUASTATE_GETSTATE|wxLUASTATE_ROOTSTATE);\)/\/\/ removed by ZBS build process \/\/ \1/' modules/wxlua/wxlcallb.cpp
cp "$INSTALL_DIR/lib/libwxscintilla-2.9.a" "$INSTALL_DIR/lib/libwx_mswu_scintilla-2.9.a"
# remove check for Lua 5.2 as it doesn't work with Twoface ABI mapper
sed -i 's/LUA_VERSION_NUM < 502/0/' modules/wxlua/wxlcallb.cpp
# (temporary) fix for compilation issue in wxlua in Windows using mingw (r184)
sed -i 's/defined(__MINGW32__) || defined(__GNUWIN32__)/0/' modules/wxbind/src/wxcore_bind.cpp
[ -f "$INSTALL_DIR/lib/libwxscintilla-2.9.a" ] && cp "$INSTALL_DIR/lib/libwxscintilla-2.9.a" "$INSTALL_DIR/lib/libwx_mswu_scintilla-2.9.a"
[ -f "$INSTALL_DIR/lib/libwxscintilla-3.0.a" ] && cp "$INSTALL_DIR/lib/libwxscintilla-3.0.a" "$INSTALL_DIR/lib/libwx_mswu_scintilla-3.0.a"
echo "set_target_properties(wxLuaModule PROPERTIES LINK_FLAGS -static)" >> modules/luamodule/CMakeLists.txt
cmake -G "MSYS Makefiles" -DBUILD_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_SHARED_LIBS=FALSE \
cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=$WXLUABUILD -DBUILD_SHARED_LIBS=FALSE \
-DwxWidgets_CONFIG_EXECUTABLE="$INSTALL_DIR/bin/wx-config" \
-DwxWidgets_COMPONENTS="stc;html;aui;adv;core;net;base" \
-DwxLuaBind_COMPONENTS="stc;html;aui;adv;core;net;base" -DwxLua_LUA_LIBRARY_USE_BUILTIN=FALSE \
-DwxLua_LUA_INCLUDE_DIR="$INSTALL_DIR/include" -DwxLua_LUA_LIBRARY="$INSTALL_DIR/lib/lua51.dll" .
(cd modules/luamodule; make $MAKEFLAGS) || { echo "Error: failed to build wxLua"; exit 1; }
(cd modules/luamodule; make install/strip)
(cd modules/luamodule; make install$WXLUASTRIP)
[ -f "$INSTALL_DIR/bin/libwx.dll" ] || { echo "Error: libwx.dll isn't found"; exit 1; }
cd ../..
rm -rf "$WXLUA_BASENAME"
@@ -173,17 +222,17 @@ if [ $BUILD_LUASOCKET ]; then
wget --no-check-certificate -c "$LUASOCKET_URL" -O "$LUASOCKET_FILENAME" || { echo "Error: failed to download LuaSocket"; exit 1; }
unzip "$LUASOCKET_FILENAME"
cd "$LUASOCKET_BASENAME"
mkdir -p "$INSTALL_DIR/lib/lua/5.1/"{mime,socket}
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/mime/core.dll" src/mime.c -llua51 \
mkdir -p "$INSTALL_DIR/lib/lua/$LUAV/"{mime,socket}
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dll" src/mime.c -llua$LUAV \
|| { echo "Error: failed to build LuaSocket"; exit 1; }
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/socket/core.dll" \
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,wsocket.c} -lwsock32 -llua51 \
gcc $BUILD_FLAGS -DLUASOCKET_INET_PTON -D_WIN32_WINNT=0x0501 -o "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dll" \
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,wsocket.c} -lwsock32 -lws2_32 -llua$LUAV \
|| { echo "Error: failed to build LuaSocket"; exit 1; }
mkdir -p "$INSTALL_DIR/share/lua/5.1/socket"
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/5.1/socket"
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/5.1"
[ -f "$INSTALL_DIR/lib/lua/5.1/mime/core.dll" ] || { echo "Error: mime/core.dll isn't found"; exit 1; }
[ -f "$INSTALL_DIR/lib/lua/5.1/socket/core.dll" ] || { echo "Error: socket/core.dll isn't found"; exit 1; }
mkdir -p "$INSTALL_DIR/share/lua/$LUAV/socket"
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/$LUAV/socket"
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/$LUAV"
[ -f "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dll" ] || { echo "Error: mime/core.dll isn't found"; exit 1; }
[ -f "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dll" ] || { echo "Error: socket/core.dll isn't found"; exit 1; }
cd ..
rm -rf "$LUASOCKET_FILENAME" "$LUASOCKET_BASENAME"
fi
@@ -236,20 +285,21 @@ fi
# now copy the compiled dependencies to ZBS binary directory
mkdir -p "$BIN_DIR" || { echo "Error: cannot create directory $BIN_DIR"; exit 1; }
[ $BUILD_LUA ] && cp "$INSTALL_DIR/bin/lua.exe" "$INSTALL_DIR/lib/lua51.dll" "$BIN_DIR"
[ $BUILD_LUA ] && cp "$INSTALL_DIR/bin/lua$LUAS.exe" "$INSTALL_DIR/lib/lua$LUAV.dll" "$BIN_DIR"
[ $BUILD_WXLUA ] && cp "$INSTALL_DIR/bin/libwx.dll" "$BIN_DIR/wx.dll"
[ $BUILD_WINAPI ] && cp "$INSTALL_DIR/lib/lua/5.1/winapi.dll" "$BIN_DIR"
[ $BUILD_LUASEC ] && cp "$INSTALL_DIR/lib/lua/5.1/ssl.dll" "$BIN_DIR"
if [ $BUILD_LUASOCKET ]; then
mkdir -p "$BIN_DIR/clibs/"{mime,socket}
cp "$INSTALL_DIR/lib/lua/5.1/mime/core.dll" "$BIN_DIR/clibs/mime"
cp "$INSTALL_DIR/lib/lua/5.1/socket/core.dll" "$BIN_DIR/clibs/socket"
mkdir -p "$BIN_DIR/clibs$LUAS/"{mime,socket}
cp "$INSTALL_DIR/lib/lua/$LUAV/mime/core.dll" "$BIN_DIR/clibs$LUAS/mime"
cp "$INSTALL_DIR/lib/lua/$LUAV/socket/core.dll" "$BIN_DIR/clibs$LUAS/socket"
fi
# To build lua5.1.dll proxy:
# (1) get mkforwardlib-gcc.lua from http://lua-users.org/wiki/LuaProxyDllThree
# (2) run it as "lua mkforwardlib-gcc.lua lua51 lua5.1 X86"
# show a message about successful completion
echo "*** Build has been successfully completed ***"
exit 0

231
cfg/i18n/cn.lua Normal file
View File

@@ -0,0 +1,231 @@
return {
["%d instance"] = "%d 个体", -- src\editor\findreplace.lua
["&About"] = "关于(&A)", -- src\editor\menu_help.lua
["&Add Watch"] = "添加监视(&A)", -- src\editor\debugger.lua
["&Break"] = "中断", -- src\editor\menu_project.lua
["&Close Page"] = "关闭页面", -- src\editor\menu_file.lua, src\editor\gui.lua
["&Compile"] = "编译", -- src\editor\menu_project.lua
["&Copy"] = "复制", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Default Layout"] = "布局", -- src\editor\menu_view.lua
["&Delete Watch"] = "删除监视", -- src\editor\debugger.lua
["&Down"] = "往下", -- src\editor\findreplace.lua
["&Edit Watch"] = "编辑监视", -- src\editor\debugger.lua
["&Edit"] = "编辑", -- src\editor\menu_edit.lua
["&File"] = "文件", -- src\editor\menu_file.lua
["&Find All"] = "查找全部", -- src\editor\findreplace.lua
["&Find Next"] = "查找下一个", -- src\editor\findreplace.lua
["&Find"] = "查找", -- src\editor\menu_search.lua
["&Fold/Unfold All"] = "全 折叠/展开", -- src\editor\menu_edit.lua
["&Goto Line"] = "到...行", -- src\editor\menu_search.lua
["&Help"] = "帮助", -- src\editor\menu_help.lua
["&New"] = "新建", -- src\editor\menu_file.lua
["&Open..."] = "打开...", -- src\editor\menu_file.lua
["&Output/Console Window"] = "输出/主控台视窗", -- src\editor\menu_view.lua
["&Paste"] = "粘贴", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Project"] = "项目", -- src\editor\menu_project.lua, src\editor\inspect.lua
["&Redo"] = "重做", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Replace All"] = "全替换", -- src\editor\findreplace.lua
["&Replace"] = "替换", -- src\editor\findreplace.lua, src\editor\menu_search.lua
["&Run"] = "执行", -- src\editor\menu_project.lua
["&Save"] = "保存", -- src\editor\menu_file.lua, src\editor\gui.lua
["&Search"] = "搜索", -- src\editor\menu_search.lua
["&Sort"] = "分类", -- src\editor\menu_search.lua
["&Stack Window"] = "叠视窗/堆栈视窗", -- src\editor\menu_view.lua
["&Start Debugger Server"] = "开启除错器伺服机", -- src\editor\menu_project.lua
["&Subdirectories"] = "子文件夹", -- src\editor\findreplace.lua
["&Undo"] = "撤消", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Up"] = "往上", -- src\editor\findreplace.lua
["&View"] = "视图", -- src\editor\menu_view.lua
["&Watch Window"] = "监视视窗", -- src\editor\menu_view.lua
["About %s"] = "关于 %s", -- src\editor\menu_help.lua
["Add Watch Expression"] = "添加监视表达式", -- src\editor\editor.lua
["Add to Scratchpad"] = "添加至暂存器", -- src\editor\editor.lua
["All files"] = "全部文件", -- src\editor\commands.lua
["Allow external process to start debugging"] = "允许外部进程开启除错", -- src\editor\menu_project.lua
["Analyze the source code"] = "分析源代码", -- src\editor\inspect.lua
["Analyze"] = "分析", -- src\editor\inspect.lua
["Auto Complete Identifiers"] = "自动补全标识符", -- src\editor\menu_edit.lua
["Auto complete while typing"] = "当输入时自动补全", -- src\editor\menu_edit.lua
["Break execution at the next executed line of code"] = "执行下一语句之后中断执行", -- src\editor\menu_project.lua, src\editor\gui.lua
["C&lear Output Window"] = "清除输出视窗", -- src\editor\menu_project.lua
["C&omment/Uncomment"] = "注释/消除注释", -- src\editor\menu_edit.lua
["Can't debug the script in the active editor window."] = "不能在现行编辑视窗对脚本进行除错", -- src\editor\debugger.lua
["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."] = "在当前项目中寻找不到文件 '%s' 以进行激活然后除错, 更新项目或是在编辑器里开启文件后再除错", -- src\editor\debugger.lua
["Can't process auto-recovery record; invalid format: %s."] = "不能处理自动恢复存档: %s", -- src\editor\commands.lua
["Can't run the entry point script ('%s')."] = "不能执行entry point脚本 ('%s')", -- src\editor\debugger.lua
["Can't start debugging session due to internal error '%s'."] = "除错动作失败 '%s'.", -- src\editor\debugger.lua
["Can't start debugging without an opened file or with the current file not being saved ('%s')."] = "不能启动除错,没有文档被开启或当前更改过的文档还没保存('%s')", -- src\editor\debugger.lua
["Cancel"] = "取消", -- src\editor\findreplace.lua
["Choose ..."] = "请选 ...", -- src\editor\menu_project.lua
["Choose a project directory"] = "选择项目文件夹", -- src\editor\findreplace.lua, src\editor\menu_project.lua
["Clear &Dynamic Words"] = "清除动态词汇", -- src\editor\menu_edit.lua
["Clear the output window before compiling or debugging"] = "编译或除错前清除输出视窗", -- src\editor\menu_project.lua
["Close &Other Pages"] = "关闭其他页面", -- src\editor\gui.lua
["Close A&ll Pages"] = "关闭全部页面", -- src\editor\gui.lua
["Close the current editor window"] = "关闭当前编译视窗", -- src\editor\menu_file.lua
["Co&ntinue"] = "继续", -- src\editor\menu_project.lua
["Col: %d"] = "列: %d", -- src\editor\editor.lua
["Comment or uncomment current or selected lines"] = "注释/消除注释 当前或被选的语句", -- src\editor\menu_edit.lua
["Compilation error"] = "编译错误", -- src\editor\debugger.lua, src\editor\commands.lua
["Compilation successful; %.0f%% success rate (%d/%d)."] = "编译成功; 成功率: %.0f%% (%d/%d).", -- src\editor\commands.lua
["Compile the current file"] = "编译当前的文档", -- src\editor\menu_project.lua
["Complete &Identifier"] = "补全标识符", -- src\editor\menu_edit.lua
["Complete the current identifier"] = "补全当前标识符", -- src\editor\menu_edit.lua
["Copy selected text to clipboard"] = "复制被选的text到clipboard", -- src\editor\menu_edit.lua
["Couldn't activate file '%s' for debugging; continuing without it."] = "不能激活 '%s' 以除错; 省略后继续进行", -- src\editor\debugger.lua
["Create an empty document"] = "新建空文档", -- src\editor\menu_file.lua, src\editor\gui.lua
["Cu&t"] = "剪切", -- src\editor\editor.lua, src\editor\menu_edit.lua
["Cut selected text to clipboard"] = "剪切被选的text到clipboard", -- src\editor\menu_edit.lua
["Debugger server started at %s:%d."] = "除错伺服器起始于 %s:%d.", -- src\editor\debugger.lua
["Debugging session completed (%s)."] = "除错会话完成 (%s)", -- src\editor\debugger.lua
["Debugging session started in '%s'."] = "除错会话于 '%s' 起始", -- src\editor\debugger.lua
["Debugging suspended at %s:%s (couldn't activate the file)."] = "除错挂起于 %s:%s (不能激活文档).", -- src\editor\debugger.lua
["Directory"] = "文件夹", -- src\editor\findreplace.lua
["Do you want to reload it?"] = "需要重新导入吗?", -- src\editor\editor.lua
["Do you want to save the changes to '%s'?"] = "需要把更改保存于 '%s'?", -- src\editor\commands.lua
["E&xit"] = "离开", -- src\editor\menu_file.lua
["Enter Lua code and press Enter to run it."] = "输入Lua代码然后按 <Enter> 以执行", -- src\editor\shellbox.lua
["Enter line number"] = "输入行号码", -- src\editor\menu_search.lua
["Error while loading API file: %s"] = "导入API档时出错误: %s", -- src\editor\autocomplete.lua
["Error while loading configuration file: %s"] = "导入configuration档时出错误: %s", -- src\editor\style.lua
["Error while processing API file: %s"] = "处理API档时出错误: %s", -- src\editor\autocomplete.lua
["Error while processing configuration file: %s"] = "处理configuration档时出错误: %s", -- src\editor\style.lua
["Error"] = "错误", -- src\editor\commands.lua
["Evaluate in Console"] = "在主控台中估值", -- src\editor\editor.lua
["Execute the current project/file and keep updating the code to see immediate results"] = "执行当前项目/文档和更新代码以便得到执行结果", -- src\editor\menu_project.lua
["Execute the current project/file"] = "执行当前项目/文档", -- src\editor\menu_project.lua
["Execution error"] = "执行出错误", -- src\editor\debugger.lua
["Exit program"] = "离开程式", -- src\editor\menu_file.lua
["Expr"] = "表达式", -- src\editor\debugger.lua
["Expression"] = "表达式", -- src\editor\debugger.lua
["File '%s' has been modified on disk."] = "磁碟上的文档 '%s' 已被更改", -- src\editor\editor.lua
["File '%s' has more recent timestamp than restored '%s'; please review before saving."] =
"文档 '%s' 的时间戳比 '%s' 更新近; 请检验后再保存", -- src\editor\commands.lua
["File '%s' no longer exists."] = "文档 '%s' 已不存在", -- src\editor\editor.lua, src\editor\menu_file.lua
["File Type"] = "文档类", -- src\editor\findreplace.lua
["File history"] = "文档历史", -- src\editor\menu_file.lua
["Find &In Files"] = "在文档中查找", -- src\editor\menu_search.lua
["Find &Next"] = "查找下一个", -- src\editor\menu_search.lua
["Find &Previous"] = "查找上一个", -- src\editor\menu_search.lua
["Find In Files"] = "在文档中查找", -- src\editor\findreplace.lua
["Find and replace text in files"] = "在文档中查找text然后更换", -- src\editor\menu_search.lua
["Find and replace text"] = "查找text然后更换", -- src\editor\menu_search.lua, src\editor\gui.lua
["Find text in files"] = "在文档中查找text", -- src\editor\menu_search.lua
["Find text"] = "查找text", -- src\editor\menu_search.lua, src\editor\gui.lua
["Find the earlier text occurence"] = "查找之前出现的text", -- src\editor\menu_search.lua
["Find the next text occurrence"] = "查找之後将出现的text", -- src\editor\menu_search.lua
["Find"] = "查找", -- src\editor\findreplace.lua
["Fold or unfold all code folds"] = "折叠/展开所有代码折叠", -- src\editor\menu_edit.lua
["Found auto-recovery record and restored saved session."] = "找到自动恢复存档和恢复已存对话", -- src\editor\commands.lua
["Found"] = "找到", -- src\editor\findreplace.lua
["Full &Screen"] = "全屏", -- src\editor\menu_view.lua
["Go to a selected line"] = "到所选的行", -- src\editor\menu_search.lua
["Goto Line"] = "到...行", -- src\editor\menu_search.lua
["INS"] = "INS", -- src\editor\editor.lua
["In Files"] = "在档案里", -- src\editor\findreplace.lua
["Jump to a function definition..."] = "跳到函数定义", -- src\editor\editor.lua
["Known Files"] = "所知的文档", -- src\editor\commands.lua
["Ln: %d"] = "行: %d", -- src\editor\editor.lua
["Local console"] = "本地主控台", -- src\editor\shellbox.lua, src\editor\gui.lua
["Lua &Interpreter"] = "Lua 解释器", -- src\editor\menu_project.lua
["Mapped remote request for '%s' to '%s'."] = "映射远程请求 '%s' 至 '%s'", -- src\editor\debugger.lua
["Match &case"] = "case匹配", -- src\editor\findreplace.lua
["Match &whole word"] = "全句匹配", -- src\editor\findreplace.lua
["Mixed end-of-line encodings detected."] = "发现混杂的EOL编码", -- src\editor\commands.lua
["OVR"] = "OVR", -- src\editor\editor.lua
["Open an existing document"] = "打开现存文档", -- src\editor\menu_file.lua, src\editor\gui.lua
["Open file"] = "打开文档", -- src\editor\commands.lua
["Options"] = "选项", -- src\editor\findreplace.lua
["Output (running)"] = "输出 (进行中)", -- src\editor\output.lua
["Output"] = "输出", -- src\editor\output.lua, src\editor\settings.lua, src\editor\gui.lua
["Paste text from the clipboard"] = "从clipboard粘贴text", -- src\editor\menu_edit.lua
["Preferences"] = "首选项", -- src\editor\menu_edit.lua
["Prepend '=' to show complex values on multiple lines."] = "在多行展现复杂值请前置 '='", -- src\editor\shellbox.lua
["Press cancel to abort."] = "按 <cancel> 以退出", -- src\editor\commands.lua
["Program '%s' started in '%s' (pid: %d)."] = "程式 '%s' 执行于 '%s' (pid: %d).", -- src\editor\output.lua
["Program can't start because conflicting process is running as '%s'."] = "程序不能启动因为有名为 '%s' 的冲突进程", -- src\editor\output.lua
["Program completed in %.2f seconds (pid: %d)."] = "程序于 %.2f 秒完成 (pid: %d).", -- src\editor\output.lua
["Program starting as '%s'."] = "程式以 '%s' 执行", -- src\editor\output.lua
["Program stopped (pid: %d)."] = "程式停止 (pid: %d).", -- src\editor\debugger.lua
["Program unable to run as '%s'."] = "程式不能以 '%s' 执行", -- src\editor\output.lua
["Project Directory"] = "项目文件夹", -- src\editor\menu_project.lua
["Project"] = "项目", -- src\editor\settings.lua, src\editor\gui.lua
["Project/&FileTree Window"] = "项目/文档树 视窗", -- src\editor\menu_view.lua
["R/O"] = "唯读", -- src\editor\editor.lua
["R/W"] = "读写", -- src\editor\editor.lua
["Re&place In Files"] = "在文档中替换", -- src\editor\menu_search.lua
["Recent Files"] = "最近的文档", -- src\editor\menu_file.lua
["Redo last edit undone"] = "重做最后被取消的编辑", -- src\editor\menu_edit.lua
["Refused a request to start a new debugging session as there is one in progress already."] = "因为有另一个除错在进行,拒绝开启新的除错对话", -- src\editor\debugger.lua
["Regular &expression"] = "正则表达式", -- src\editor\findreplace.lua
["Remote console"] = "远程主控台", -- src\editor\shellbox.lua
["Replace &All"] = "更换全部", -- src\editor\findreplace.lua
["Replace"] = "更换", -- src\editor\findreplace.lua
["Replaced an invalid UTF8 character with %s."] = "以%s更换无效的UTF8字元", -- src\editor\commands.lua
["Replaced"] = "更换", -- src\editor\findreplace.lua
["Replacing"] = "更换中", -- src\editor\findreplace.lua
["Reset to default layout"] = "重置缺省布局", -- src\editor\menu_view.lua
["Resets the dynamic word list for autocompletion"] = "为自动补全重置动态word list", -- src\editor\menu_edit.lua
["Run as Scratchpad"] = "以Scratchpad执行", -- src\editor\menu_project.lua
["S&top Debugging"] = "停止除错", -- src\editor\menu_project.lua
["S&top Process"] = "停止进程", -- src\editor\menu_project.lua
["Save &As..."] = "另存为...", -- src\editor\menu_file.lua, src\editor\gui.lua
["Save A&ll"] = "全部存档", -- src\editor\menu_file.lua
["Save Changes?"] = "存档更新?", -- src\editor\commands.lua
["Save all open documents"] = "保存所有开启的文档", -- src\editor\menu_file.lua, src\editor\gui.lua
["Save file as"] = "文档另存为", -- src\editor\commands.lua
["Save file?"] = "保存文档?", -- src\editor\commands.lua
["Save the current document to a file with a new name"] = "用新档案名称保存当前文档", -- src\editor\menu_file.lua
["Save the current document"] = "保存当前文档", -- src\editor\menu_file.lua, src\editor\gui.lua
["Saved auto-recover at %s."] = "在 %s 存档自动恢复", -- src\editor\commands.lua
["Scope"] = "范围", -- src\editor\findreplace.lua
["Scratchpad error"] = "暂存器错误", -- src\editor\debugger.lua
["Searching for"] = "搜索", -- src\editor\findreplace.lua
["Select &All"] = "选全部", -- src\editor\editor.lua, src\editor\menu_edit.lua
["Select all text in the editor"] = "选编辑器内的所有text", -- src\editor\menu_edit.lua
["Set From Current File"] = "从当前文档设置", -- src\editor\menu_project.lua
["Set project directory from current file"] = "从当前文档设置项目文件夹", -- src\editor\menu_project.lua, src\editor\gui.lua
["Set the interpreter to be used"] = "设置解释器", -- src\editor\menu_project.lua
["Set the project directory to be used"] = "设置项目文件夹", -- src\editor\menu_project.lua
["Settings: System"] = "设置: 系统", -- src\editor\menu_edit.lua
["Settings: User"] = "设置: 用户", -- src\editor\menu_edit.lua
["Show &Tooltip"] = "展现tooltip", -- src\editor\menu_edit.lua
["Show tooltip for current position; place cursor after opening bracket of function"] = "在当前的位置展现tooltip; 把游标放置于函数的开括号之后", -- src\editor\menu_edit.lua
["Sort selected lines"] = "对被选的行进行排列", -- src\editor\menu_search.lua
["Stack"] = "堆栈", -- src\editor\debugger.lua
["Start &Debugging"] = "开始除错", -- src\editor\menu_project.lua
["Start debugging"] = "开始除错", -- src\editor\menu_project.lua, src\editor\gui.lua
["Step &Into"] = "除错运行 进入子程序/函数", -- src\editor\menu_project.lua
["Step &Over"] = "除错运行 掠过子程序/函数", -- src\editor\menu_project.lua
["Step O&ut"] = "除错运行 离开子程序/函数", -- src\editor\menu_project.lua
["Step into"] = "除错运行 进入子程序/函数", -- src\editor\menu_project.lua, src\editor\gui.lua
["Step out of the current function"] = "除错运行 离开当前的函数", -- src\editor\menu_project.lua, src\editor\gui.lua
["Step over"] = "除错运行 掠过子程序/函数", -- src\editor\menu_project.lua, src\editor\gui.lua
["Stop the currently running process"] = "终止目前进行着的进程", -- src\editor\menu_project.lua, src\editor\gui.lua
["Switch to or from full screen mode"] = "切换全屏模式", -- src\editor\menu_view.lua
["Text not found."] = "寻找不到text", -- src\editor\findreplace.lua
["The API file must be located in a subdirectory of the API directory."] = "API file必须存放在API文件夹中的子文件夹", -- src\editor\autocomplete.lua
["Toggle Break&point"] = "切换中断点", -- src\editor\menu_project.lua
["Toggle breakpoint"] = "切换中断点", -- src\editor\menu_project.lua, src\editor\gui.lua
["Tr&ace"] = "追踪", -- src\editor\menu_project.lua
["Trace execution showing each executed line"] = "执行追踪展示每一执行过的语句", -- src\editor\menu_project.lua
["Unable to load file '%s'."] = "导出文件失败 '%s'.", -- src\editor\commands.lua
["Unable to save file '%s': %s"] = "保存文件失败 '%s': %s", -- src\editor\commands.lua
["Unable to stop program (pid: %d), code %d."] = "停止程序失败 (pid: %d), 代码 %d.", -- src\editor\debugger.lua
["Undo last edit"] = "清除前编辑动作", -- src\editor\menu_edit.lua
["Use '%s' to see full description."] = "用 '%s' 来看全解析", -- src\editor\editor.lua
["Use '%s' to show line endings and '%s' to convert them."] = "用 '%s' 来显示语句的终结和 '%s' 来进行转换", -- src\editor\commands.lua
["Use 'clear' to clear the shell output and the history."] = "用 'clear' 来清除shell的输出和历史", -- src\editor\shellbox.lua
["Use Shift-Enter for multiline code."] = "用 <Shift-Enter> 来处理多行代码", -- src\editor\shellbox.lua
["Value"] = "数值", -- src\editor\debugger.lua
["View the output/console window"] = "查看输出/主控台视窗", -- src\editor\menu_view.lua
["View the project/filetree window"] = "查看项目/文件树视窗", -- src\editor\menu_view.lua
["View the stack window"] = "查看堆栈视窗", -- src\editor\menu_view.lua, src\editor\gui.lua
["View the watch window"] = "查看监视视窗", -- src\editor\menu_view.lua, src\editor\gui.lua
["Watch"] = "监视", -- src\editor\debugger.lua
["Welcome to the interactive Lua interpreter."] = "欢迎来到互动 Lua interpreter.", -- src\editor\shellbox.lua
["Wrap ar&ound"] = "卷绕", -- src\editor\findreplace.lua
["You must save the program first."] = "必须先保存程序", -- src\editor\commands.lua
["on line %d"] = "在 %d 行", -- src\editor\debugger.lua, src\editor\commands.lua
["traced %d instruction"] = "追踪 %d 指令", -- src\editor\debugger.lua
}

236
cfg/i18n/de.lua Normal file
View File

@@ -0,0 +1,236 @@
return {
[0] = function(c) return c == 1 and 1 or 2 end, -- plural
["%d instance"] = {"%d Instanz", "%d Instanzen"}, -- src\editor\findreplace.lua
["%s event failed: %s"] = "Ereignis fehlgeschlagen : %s", -- src\editor\package.lua
["&About"] = "&Über", -- src\editor\menu_help.lua
["&Add Watch"] = "&Beobachtungspunkt hinzufügen", -- src\editor\debugger.lua
["&Break"] = "&Unterbrechung", -- src\editor\menu_project.lua
["&Close Page"] = "S&eite schließen", -- src\editor\menu_file.lua, src\editor\gui.lua
["&Compile"] = "&Compiler", -- src\editor\menu_project.lua
["&Copy"] = "&Kopieren", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Default Layout"] = "Standard-&Layout", -- src\editor\menu_view.lua
["&Delete Watch"] = "&Beobachtungspunkt entfernen", -- src\editor\debugger.lua
["&Down"] = "&Runter", -- src\editor\findreplace.lua
["&Edit Watch"] = "&Beobachtungspunkt bearbeiten", -- src\editor\debugger.lua
["&Edit"] = "&Bearbeiten", -- src\editor\menu_edit.lua
["&File"] = "&Datei", -- src\editor\menu_file.lua
["&Find All"] = "&Alle finden", -- src\editor\findreplace.lua
["&Find Next"] = "&Nächsten finden", -- src\editor\findreplace.lua
["&Find"] = "&Finden", -- src\editor\menu_search.lua
["&Fold/Unfold All"] = "A&lles ein-/ausklappen", -- src\editor\menu_edit.lua
["&Goto Line"] = "&Gehe zu Zeile", -- src\editor\menu_search.lua
["&Help"] = "&Hilfe", -- src\editor\menu_help.lua
["&New"] = "&Neu", -- src\editor\menu_file.lua
["&Open..."] = "&Öffnen...", -- src\editor\menu_file.lua
["&Output/Console Window"] = "&Ausgabefenster/Konsole", -- src\editor\menu_view.lua
["&Paste"] = "&Einfügen", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Project"] = "&Projekt", -- src\editor\menu_project.lua, src\editor\inspect.lua
["&Redo"] = "&Wiederholen", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Replace All"] = "&Alles ersetzen", -- src\editor\findreplace.lua
["&Replace"] = "&Ersetzen", -- src\editor\findreplace.lua, src\editor\menu_search.lua
["&Run"] = "&Starten", -- src\editor\menu_project.lua
["&Save"] = "&Speichern", -- src\editor\menu_file.lua, src\editor\gui.lua
["&Search"] = "&Suchen", -- src\editor\menu_search.lua
["&Sort"] = "&Sortieren", -- src\editor\menu_search.lua
["&Stack Window"] = "&Stapel/Stack", -- src\editor\menu_view.lua
["&Start Debugger Server"] = "De&bugserver starten", -- src\editor\menu_project.lua
["&Subdirectories"] = "&Unterverzeichnisse", -- src\editor\findreplace.lua
["&Undo"] = "&Rückgängig", -- src\editor\editor.lua, src\editor\menu_edit.lua
["&Up"] = "&Hoch", -- src\editor\findreplace.lua
["&View"] = "&Ansicht", -- src\editor\menu_view.lua
["&Watch Window"] = "&Beobachtungspunkte", -- src\editor\menu_view.lua
[".&bak on Replace"] = ".&bak bei Ersetzen", -- src\editor\findreplace.lua
["About %s"] = "Über %s", -- src\editor\menu_help.lua
["Add Watch Expression"] = "Beobachtungspunkt hinzufügen", -- src\editor\editor.lua
["Add To Scratchpad"] = "Zu Entwurf hinzufügen", -- src\editor\editor.lua
["All files"] = "Alle Dateien", -- src\editor\commands.lua
["Allow external process to start debugging"] = "Externem Prozeß erlauben, den Debugger zu starten", -- src\editor\menu_project.lua
["Analyze the source code"] = "Quellcode analysieren", -- src\editor\inspect.lua
["Analyze"] = "&Analyseroutine", -- src\editor\inspect.lua
["Auto Complete Identifiers"] = "Auto-Vervollständigen von Bezeichnern", -- src\editor\menu_edit.lua
["Auto complete while typing"] = "Auto-Vervollständigen beim Tippen", -- src\editor\menu_edit.lua
["Break execution at the next executed line of code"] = "Programmausführung bei der nächsten ausgeführten Zeile stoppen", -- src\editor\menu_project.lua, src\editor\gui.lua
["C&lear Output Window"] = "Ausgabefenster &löschen", -- src\editor\menu_project.lua
["C&omment/Uncomment"] = "(Aus-)/&Kommentieren", -- src\editor\menu_edit.lua
["Can't debug the script in the active editor window."] = "Script kann im aktiven Editorfenster nicht gedebuggt werden.", -- src\editor\debugger.lua
["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."] = "Kann Datei '%s' zwecks Debugging im aktuellen Projekt nicht finden. Bitte Projekt aktualisieren oder Datei in den Editor laden.", -- src\editor\debugger.lua
["Can't process auto-recovery record; invalid format: %s."] = "Auto-Wiederherstellen nicht möglich; ungültiges Format: %s.", -- src\editor\commands.lua
["Can't run the entry point script ('%s')."] = "Kann Script für Einsprungspunkt ('%s') nicht ausführen.", -- src\editor\debugger.lua
["Can't start debugging session due to internal error '%s'."] = "Debugging kann nicht gestartet werden wegen internem Fehler '%s'.", -- src\editor\debugger.lua
["Can't start debugging without an opened file or with the current file not being saved ('%s')."] = "Debugging kann nicht gestartet werden ohne geöffnete Datei oder wenn die aktuelle Datei nicht gespeichert ist ('%s').", -- src\editor\debugger.lua
["Cancel"] = "Abbrechen", -- src\editor\findreplace.lua
["Choose ..."] = "Wählen...", -- src\editor\menu_project.lua
["Choose a project directory"] = "Projektverzeichnis auswählen", -- src\editor\findreplace.lua, src\editor\menu_project.lua
["Clear &Dynamic Words"] = "&Dynamic Words löschen", -- src\editor\menu_edit.lua
["Clear the output window before compiling or debugging"] = "Vor Kompilieren oder Debuggen das Ausgabefenster löschen", -- src\editor\menu_project.lua
["Close &Other Pages"] = "A&ndere Seiten schließen", -- src\editor\gui.lua
["Close A&ll Pages"] = "&Alle Seiten schließen", -- src\editor\gui.lua
["Close the current editor window"] = "Aktuelles Editorfenster schließen", -- src\editor\menu_file.lua
["Co&ntinue"] = "&Fortsetzen", -- src\editor\menu_project.lua
["Col: %d"] = "Spalte: %d", -- src\editor\editor.lua
["Comment or uncomment current or selected lines"] = "Ausgewählte bzw. aktive Zeile (un-)kommentieren", -- src\editor\menu_edit.lua
["Compilation error"] = "Fehler beim Kompilieren", -- src\editor\debugger.lua, src\editor\commands.lua
["Compilation successful; %.0f%% success rate (%d/%d)."] = "Kompilieren erfolgreich; Erfolgsquote von %.0f%% (%d/%d).", -- src\editor\commands.lua
["Compile the current file"] = "Aktuelle Datei kompilieren", -- src\editor\menu_project.lua
["Complete &Identifier"] = "&Bezeichner vervollständigen", -- src\editor\menu_edit.lua
["Complete the current identifier"] = " Aktuellen Bezeichner vervollständigen", -- src\editor\menu_edit.lua
["Copy selected text to clipboard"] = "Text in Zwischenablage kopieren", -- src\editor\menu_edit.lua
["Couldn't activate file '%s' for debugging; continuing without it."] = "Konnte Datei '%s' zwecks nicht Debugging aktivieren; fahre ohne die Datei fort.", -- src\editor\debugger.lua
["Create an empty document"] = "Leeres Dokument anlegen", -- src\editor\menu_file.lua, src\editor\gui.lua
["Cu&t"] = "A&usschneiden", -- src\editor\editor.lua, src\editor\menu_edit.lua
["Cut selected text to clipboard"] = "Schneide ausgewählten Text in die Zwischenablage hinein", -- src\editor\menu_edit.lua
["Debugger server started at %s:%d."] = "Debugserver gestartet an %s:%d.", -- src\editor\debugger.lua
["Debugging session completed (%s)."] = "Debugging Session beendet (%s).", -- src\editor\debugger.lua
["Debugging session started in '%s'."] = "Debugging Session gestartet '%s'.", -- src\editor\debugger.lua
["Debugging suspended at %s:%s (couldn't activate the file)."] = "Debugging angehalten bei %s:%s (konnte Datei nicht aktivieren).", -- src\editor\debugger.lua
["Directory"] = "Verzeichnis", -- src\editor\findreplace.lua
["Do you want to reload it?"] = "Neu laden?", -- src\editor\editor.lua
["Do you want to save the changes to '%s'?"] = "Änderungen an '%s' speichern?", -- src\editor\commands.lua
["E&xit"] = "&Beenden", -- src\editor\menu_file.lua
["Enter Lua code and press Enter to run it."] = "Lua-Code eingeben und Enter drücken zum Ausführen.", -- src\editor\shellbox.lua
["Enter line number"] = "Zeilennummer eingeben", -- src\editor\menu_search.lua
["Error while loading API file: %s"] = "Fehler beim Laden von API-Datei: %s", -- src\editor\autocomplete.lua
["Error while loading configuration file: %s"] = "Fehler beim Laden von Konfigurationsdatei: %s", -- src\editor\style.lua
["Error while processing API file: %s"] = "Fehler beim Lesen von API-Datei: %s", -- src\editor\autocomplete.lua
["Error while processing configuration file: %s"] = "Fehler beim Lesen von Konfiguratonsdatei: %s", -- src\editor\style.lua
["Error"] = "Fehler", -- src\editor\commands.lua
["Evaluate In Console"] = "In Konsole auswerten", -- src\editor\editor.lua
["Execute the current project/file and keep updating the code to see immediate results"] = "Aktuelles Projekt/ aktuelle Datei ausführen und Quellcode ändern, um Ergebnisse in Echtzeit zu sehen", -- src\editor\menu_project.lua
["Execute the current project/file"] = "Aktuelles Projekt/ aktuelle Datei ausführen", -- src\editor\menu_project.lua
["Execution error"] = "Fehler bei Ausführung", -- src\editor\debugger.lua
["Exit program"] = "Programm beenden", -- src\editor\menu_file.lua
["Expr"] = "Ausdr.", -- src\editor\debugger.lua
["Expression"] = "Ausdruck", -- src\editor\debugger.lua
["File '%s' has been modified on disk."] = "Datei '%s' wurde auf der Festplatte geändert.", -- src\editor\editor.lua
["File '%s' has more recent timestamp than restored '%s'; please review before saving."] = "Datei '%s' hat neueren Zeitstempel als wiederhergestellte Datei '%s'; bitte vor dem Speichern kontrollieren.", -- src\editor\commands.lua
["File '%s' no longer exists."] = "Datei '%s' existiert nicht mehr.", -- src\editor\editor.lua, src\editor\menu_file.lua
["File Type"] = "Dateityp", -- src\editor\findreplace.lua
["File history"] = "Dateiverlauf", -- src\editor\menu_file.lua
["Find &In Files"] = "Finde &in Dateien", -- src\editor\menu_search.lua
["Find &Next"] = "Finde &Nächste", -- src\editor\menu_search.lua
["Find &Previous"] = "Finde &Vorherige", -- src\editor\menu_search.lua
["Find In Files"] = "Finde in Dateien", -- src\editor\findreplace.lua
["Find and replace text in files"] = "Finde und ersetze Text in Dateien", -- src\editor\menu_search.lua
["Find and replace text"] = "Finde und ersetze Text", -- src\editor\menu_search.lua, src\editor\gui.lua
["Find text in files"] = "Finde Text in Dateien", -- src\editor\menu_search.lua
["Find text"] = "Finde Text", -- src\editor\menu_search.lua, src\editor\gui.lua
["Find the earlier text occurence"] = "Finde vorheriges Auftreten des Textes", -- src\editor\menu_search.lua
["Find the next text occurrence"] = "Finde nächstes Auftreten des Textes", -- src\editor\menu_search.lua
["Find"] = "Finden", -- src\editor\findreplace.lua
["Fold or unfold all code folds"] = "Alle Stellen im Code ein-/ausklappen ", -- src\editor\menu_edit.lua
["Found auto-recovery record and restored saved session."] = "Autowiederherstellen-Aufzeichnung gefunden und vorherige Sitzung wiederhergestellt.", -- src\editor\commands.lua
["Found"] = "Gefunden", -- src\editor\findreplace.lua
["Full &Screen"] = "&Vollbild", -- src\editor\menu_view.lua
["Go To Definition"] = "Gehe zu Definition", -- src\editor\editor.lua
["Go to a selected line"] = "Gehe zu ausgewählter Zeile", -- src\editor\menu_search.lua
["Goto Line"] = "Gehe zu Zeile", -- src\editor\menu_search.lua
["INS"] = "INS", -- src\editor\editor.lua
["In Files"] = "In Dateien", -- src\editor\findreplace.lua
["Jump to a function definition..."] = "Springe zu Funktions-Definition...", -- src\editor\editor.lua
["Known Files"] = "Bekannte Dateien", -- src\editor\commands.lua
["Ln: %d"] = "Zeile: %d", -- src\editor\editor.lua
["Local console"] = "Lokale Konsole", -- src\editor\shellbox.lua, src\editor\gui.lua
["Lua &Interpreter"] = "&Lua Interpreter", -- src\editor\menu_project.lua
["Mapped remote request for '%s' to '%s'."] = "Mapped remote request for '%s' to '%s'.", -- src\editor\debugger.lua
["Match &case"] = "&Groß-/Kleinschreibung", -- src\editor\findreplace.lua
["Match &whole word"] = "Ganzes &Wort", -- src\editor\findreplace.lua
["Mixed end-of-line encodings detected."] = "Gemischte End-of-Line Kodierung entdeckt.", -- src\editor\commands.lua
["OVR"] = "OVR", -- src\editor\editor.lua
["Open an existing document"] = "Öffne existierendes Dokument", -- src\editor\menu_file.lua, src\editor\gui.lua
["Open file"] = "Öffne Datei", -- src\editor\commands.lua
["Options"] = "Optionen", -- src\editor\findreplace.lua
["Output (running)"] = "Ausgabe (ausgeführt)", -- src\editor\output.lua
["Output"] = "Ausgabe", -- src\editor\output.lua, src\editor\settings.lua, src\editor\gui.lua
["Paste text from the clipboard"] = "Text aus Zwischenablage einfügen", -- src\editor\menu_edit.lua
["Preferences"] = "Einstellungen", -- src\editor\menu_edit.lua
["Prepend '=' to show complex values on multiple lines."] = "'=' voranstellen, um komplexe Ausdrücke auf mehrere Zeilen zu verteilen.", -- src\editor\shellbox.lua
["Press cancel to abort."] = "Abbrechen Drücken zum Beenden.", -- src\editor\commands.lua
["Program '%s' started in '%s' (pid: %d)."] = "Programm '%s' gestartet in '%s' (pid : %d).", -- src\editor\output.lua
["Program can't start because conflicting process is running as '%s'."] = "Programm kann nicht starten, da blockierender Prozeß als '%s' läuft.", -- src\editor\output.lua
["Program completed in %.2f seconds (pid: %d)."] = "Programm beendet nach %.2f Sekunden (pid : %d).", -- src\editor\output.lua
["Program starting as '%s'."] = "Programm gestartet als '%s'.", -- src\editor\output.lua
["Program stopped (pid: %d)."] = "Programm gestoppt (pid: %d).", -- src\editor\debugger.lua
["Program unable to run as '%s'."] = "Programm kann nicht als '%s' laufen.", -- src\editor\output.lua
["Project Directory"] = "&Projektverzeichnis", -- src\editor\menu_project.lua
["Project"] = "Projekt", -- src\editor\settings.lua, src\editor\gui.lua
["Project/&FileTree Window"] = "&Projekt/Datei Fenster", -- src\editor\menu_view.lua
["R/O"] = "R/O", -- src\editor\editor.lua
["R/W"] = "R/W", -- src\editor\editor.lua
["Re&place In Files"] = "Ersetze in &Dateien", -- src\editor\menu_search.lua
["Recent Files"] = "Letzte Dateien", -- src\editor\menu_file.lua
["Redo last edit undone"] = "Stelle letzte rückgängig gemachte Bearbeitung wieder her", -- src\editor\menu_edit.lua
["Refused a request to start a new debugging session as there is one in progress already."] = "Starten einer neuen Debuggingsession abgelehnt, da bereits eine läuft.", -- src\editor\debugger.lua
["Regular &expression"] = "&Regulärer Ausdruck", -- src\editor\findreplace.lua
["Remote console"] = "Fensteuerungs-Konsole", -- src\editor\shellbox.lua
["Rename All Instances"] = "Umbenennen aller Instanzen", -- src\editor\editor.lua
["Replace &All"] = "&Alles ersetzen", -- src\editor\findreplace.lua
["Replace"] = "Ersetzen", -- src\editor\findreplace.lua
["Replaced an invalid UTF8 character with %s."] = "Unbekanntes UTF8-Symbol ersetzt mit %s.", -- src\editor\commands.lua
["Replaced"] = "Ersetzt:", -- src\editor\findreplace.lua
["Replacing"] = "Am Ersetzen", -- src\editor\findreplace.lua
["Reset to default layout"] = "Standard-Layout wiederherstellen", -- src\editor\menu_view.lua
["Resets the dynamic word list for autocompletion"] = "Zurücksetzen der Liste der dynamischen Wörter für Autovervollständigung", -- src\editor\menu_edit.lua
["Run as Scratchpad"] = "Als &Entwurf starten", -- src\editor\menu_project.lua
["S&top Debugging"] = "Debugging a&nhalten", -- src\editor\menu_project.lua
["S&top Process"] = "Prozeß &anhalten", -- src\editor\menu_project.lua
["Save &As..."] = "S&peichern als...", -- src\editor\menu_file.lua, src\editor\gui.lua
["Save A&ll"] = "&Alle Speichern", -- src\editor\menu_file.lua
["Save Changes?"] = "Änderungen speichern?", -- src\editor\commands.lua
["Save all open documents"] = "Alle offenen Dokumente speichern", -- src\editor\menu_file.lua, src\editor\gui.lua
["Save file as"] = "Datei speichern als", -- src\editor\commands.lua
["Save file?"] = "Datei speichern?", -- src\editor\commands.lua
["Save the current document to a file with a new name"] = "Aktuelles Dokument unter neuem Namen speichern", -- src\editor\menu_file.lua
["Save the current document"] = "Aktuelles Dokument speichern", -- src\editor\menu_file.lua, src\editor\gui.lua
["Saved auto-recover at %s."] = "Autowiederherstellen gespeichert unter %s.", -- src\editor\commands.lua
["Scope"] = "Richtung", -- src\editor\findreplace.lua
["Scratchpad error"] = "Fehler im Entwurf", -- src\editor\debugger.lua
["Searching for"] = "Suchen nach", -- src\editor\findreplace.lua
["Select &All"] = "&Alles Auswählen", -- src\editor\editor.lua, src\editor\menu_edit.lua
["Select all text in the editor"] = "Kompletten Text im Editor auswählen", -- src\editor\menu_edit.lua
["Set From Current File"] = "Anhand der aktuellen Datei festlegen", -- src\editor\menu_project.lua
["Set project directory from current file"] = "Lege Projektverzeichnis anhand der aktuellen Datei fest", -- src\editor\menu_project.lua, src\editor\gui.lua
["Set the interpreter to be used"] = "Wähle zu benutzenden Interpreter aus", -- src\editor\menu_project.lua
["Set the project directory to be used"] = "Lege zu benutzendes Projektverzeichnis fest", -- src\editor\menu_project.lua
["Settings: System"] = "Einstellungen: System", -- src\editor\menu_edit.lua
["Settings: User"] = "Einstellungen: Nutzer", -- src\editor\menu_edit.lua
["Show &Tooltip"] = "&Tooltip zeigen", -- src\editor\menu_edit.lua
["Show Location"] = "Ordner öffnen", -- src\editor\gui.lua, src\editor\filetree.lua
["Show tooltip for current position; place cursor after opening bracket of function"] = "Zeige Tooltip für aktuelle Position; setze Cursor hinter die öffnende Klammer der Funktion", -- src\editor\menu_edit.lua
["Sort selected lines"] = "Ausgewählte Zeilen sortieren", -- src\editor\menu_search.lua
["Stack"] = "Stack", -- src\editor\debugger.lua
["Start &Debugging"] = "&Debugging starten", -- src\editor\menu_project.lua
["Start debugging"] = "Debugging starten", -- src\editor\menu_project.lua, src\editor\gui.lua
["Step &Into"] = "Schritt h&inein", -- src\editor\menu_project.lua
["Step &Over"] = "&Überspringen", -- src\editor\menu_project.lua
["Step O&ut"] = "Schritt &raus", -- src\editor\menu_project.lua
["Step into"] = "Schritt hinein", -- src\editor\menu_project.lua, src\editor\gui.lua
["Step out of the current function"] = "Schritt aus der aktuellen Funktion heraus", -- src\editor\menu_project.lua, src\editor\gui.lua
["Step over"] = "Überspringen", -- src\editor\menu_project.lua, src\editor\gui.lua
["Stop the currently running process"] = "Aktuell laufenden Prozeß stoppen", -- src\editor\menu_project.lua, src\editor\gui.lua
["Switch to or from full screen mode"] = "Vollbild an/aus", -- src\editor\menu_view.lua
["Text not found."] = "Text nicht gefunden.", -- src\editor\findreplace.lua
["The API file must be located in a subdirectory of the API directory."] = "Die API-Datei muß sich in einem Unterverzeichnis des API-Vereichnisses befinden.", -- src\editor\autocomplete.lua
["Toggle Break&point"] = "&Haltepunkt an/aus", -- src\editor\menu_project.lua
["Toggle breakpoint"] = "Haltepunkt an/aus", -- src\editor\menu_project.lua, src\editor\gui.lua
["Tr&ace"] = "Ablauf &verfolgen", -- src\editor\menu_project.lua
["Trace execution showing each executed line"] = "Ablaufverfolgung zeigt jede ausgeführte Zeile an", -- src\editor\menu_project.lua
["Unable to load file '%s'."] = "Scheitern beim Laden von Datei '%s'.", -- src\editor\commands.lua
["Unable to save file '%s': %s"] = "Scheitern beim Speichern von Datei '%s' : %s", -- src\editor\commands.lua
["Unable to stop program (pid: %d), code %d."] = "Scheitern beim Stoppen des Prozesses (pid : %d), code %d.", -- src\editor\debugger.lua
["Undo last edit"] = "Letzte Änderung rückgängig machen", -- src\editor\menu_edit.lua
["Use '%s' to see full description."] = "'%s' für eine komplette Beschreibung.", -- src\editor\editor.lua
["Use '%s' to show line endings and '%s' to convert them."] = "'%s' um Zeilenende-Codes zu sehen, und '%s' um sie zu konvertieren.", -- src\editor\commands.lua
["Use 'clear' to clear the shell output and the history."] = "'clear' um Ausgabefenster und Verlauf zu löschen.", -- src\editor\shellbox.lua
["Use Shift-Enter for multiline code."] = "<Umsch-Eingabetaste> für Code in mehreren Zeilen.", -- src\editor\shellbox.lua
["Value"] = "Wert", -- src\editor\debugger.lua
["View the output/console window"] = "Ausgabe-/Konsolenfenster ansehen", -- src\editor\menu_view.lua
["View the project/filetree window"] = "Projekt-/Dateifenster ansehen", -- src\editor\menu_view.lua
["View the stack window"] = "Stapel/Stack-Fenster ansehen", -- src\editor\menu_view.lua, src\editor\gui.lua
["View the watch window"] = "Fenster für Beobachtungspunkte ansehen", -- src\editor\menu_view.lua, src\editor\gui.lua
["Watch"] = "Beobachtungspunkte", -- src\editor\debugger.lua
["Welcome to the interactive Lua interpreter."] = "Willkommen zum interaktiven Lua-Interpretr!", -- src\editor\shellbox.lua
["Wrap ar&ound"] = "Am Anfang fortsetzen", -- src\editor\findreplace.lua
["You must save the program first."] = "Erst das Programm speichern.", -- src\editor\commands.lua
["on line %d"] = "in Zeile %d", -- src\editor\debugger.lua, src\editor\commands.lua, src\editor\editor.lua
["traced %d instruction"] = {"%d Anweisung verfolgt", "%d Anweisungen verfolgt"} -- src\editor\debugger.lua
}

View File

@@ -1,5 +1,5 @@
--[[
1. Pick a color scheme by clicking on a link:
1. Pick a color scheme by clicking on its name:
- [Tomorrow](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Tomorrow')))
- [TomorrowContrast](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowContrast')))
- [TomorrowNight](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNight')))
@@ -8,8 +8,10 @@
- [TomorrowNightEighties](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNightEighties')))
- [Zenburn](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Zenburn')))
- [Monokai](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Monokai')))
- [Molokai](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Molokai')))
- [SolarizedDark](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','SolarizedDark')))
- [SolarizedLight](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','SolarizedLight')))
- [Notepad++](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','NotepadPlusPlus')))
- [ZeroBrane Studio](macro:shell(ide.config.styles = StylesGetDefault(); ReApplySpecAndStyles()))

View File

@@ -135,6 +135,20 @@ local colors = {
Blue = H'F92672',
Purple = H'A6E22E',
},
Molokai = { -- based on https://github.com/tomasr/molokai/blob/master/colors/molokai.vim
Background = H'1B1D1E',
CurrentLine = H'293739',
Selection = H'49483E',
Foreground = H'F8F8F2',
Comment = H'7E8E91',
Red = H'AE81FF',
Orange = H'AE81FF',
Yellow = H'F8F8F2',
Green = H'E6DB74',
Aqua = H'66D9EF',
Blue = H'F92672',
Purple = H'A6E22E',
},
SolarizedDark = {
Background = H'042029',
CurrentLine = H'0A2933',
@@ -163,6 +177,20 @@ local colors = {
Blue = H'859900',
Purple = H'268BD2',
},
NotepadPlusPlus = { -- contributed by Florian (https://github.com/SiENcE)
Background = H'FFFFFF',
CurrentLine = H'E9E2FF',
Selection = H'ADADA1',
Foreground = H'000000',
Comment = H'008000',
Red = H'FF6900',
Orange = H'00FF00',
Yellow = H'FF4E00',
Green = H'808080',
Aqua = H'260099',
Blue = H'2123FF',
Purple = H'FFFFFF',
},
}
-- add more of the specified color (keeping all in 0-255 range)
@@ -221,7 +249,7 @@ return {
sel = {bg = C.Selection},
caret = {fg = C.Foreground},
caretlinebg = {bg = C.CurrentLine},
fold = {fg = C.Comment, bg = C.Background},
fold = {fg = C.Comment, bg = C.Background, sel = mixer(C.Comment, 1, 96)},
whitespace = {fg = C.Comment, bg = C.Background},
indicator = {

View File

@@ -57,3 +57,17 @@ ide.app.postinit = function()
end
end
--]]
--[[ An example of how individual keywords can be styled
local G = ... -- this now points to the global environment in the script
local luaspec = G.ide.specs['lua']
local num = #luaspec.keywords
-- take a new slot in the list of keywords (starting from 1)
luaspec.keywords[num+1] = 'return'
-- remove 'return' from the list of "regular" keywords
luaspec.keywords[1] = luaspec.keywords[1]:gsub(' return', '')
-- assign new style to the added slot (starting from 0)
styles["keywords"..num] = {fg = {240, 0, 0}, b = true}
--]]

View File

@@ -45,20 +45,34 @@ return {
DebuggerAttachDefault({startwith = file, redirect = mac and "r" or "c",
runstart = ide.config.debugger.runonstart ~= false})
local function needRefresh(mdbl, mdbc)
return not wx.wxFileExists(mdbc)
or GetFileModTime(mdbc):GetTicks() < GetFileModTime(mdbl):GetTicks()
end
-- copy mobdebug.lua to Resources/ folder on Win and to the project folder on OSX
-- as copying it to Resources/ folder seems to break the signature of the app.
local mdbc = mac and MergeFullPath(self:fworkdir(wfilename), "mobdebug.lua")
or MergeFullPath(GetPathWithSep(corona), "Resources/mobdebug.lua")
local mdbl = MergeFullPath(GetPathWithSep(ide.editorFilename), "lualibs/mobdebug/mobdebug.lua")
if not wx.wxFileExists(mdbc)
or GetFileModTime(mdbc):GetTicks() < GetFileModTime(mdbl):GetTicks() then
local needed = needRefresh(mdbl, mdbc)
if needed then
local copied = FileCopy(mdbl, mdbc)
local message = copied
and ("Copied debugger ('mobdebug.lua') to '%s'."):format(mdbc)
or ("Failed to copy debugger ('mobdebug.lua') to '%s': %s")
:format(mdbc, wx.wxSysErrorMsg())
DisplayOutputLn(message)
if not copied then return end
-- couldn't copy to the Resources/ folder; not have permissions?
if not copied and win then
mdbc = MergeFullPath(wx.wxStandardPaths.Get():GetUserLocalDataDir(),
"../../Roaming/Corona Labs/Corona Simulator/Plugins/mobdebug.lua")
needed = needRefresh(mdbl, mdbc)
copied = needed and FileCopy(mdbl, mdbc)
end
if needed then
local message = copied
and ("Copied debugger ('mobdebug.lua') to '%s'."):format(mdbc)
or ("Failed to copy debugger ('mobdebug.lua') to '%s': %s")
:format(mdbc, wx.wxSysErrorMsg())
DisplayOutputLn(message)
if not copied then return end
end
end
end

View File

@@ -34,9 +34,21 @@ return {
end
local code = ([[xpcall(function() io.stdout:setvbuf('no'); %s end,function(err) print(debug.traceback(err)) end)]]):format(script)
local cmd = '"'..exe..'" -e "'..code..'"'
-- add "LUA_DEV\clibs" to PATH to allow required DLLs to load
local _, path = wx.wxGetEnv("PATH")
local clibs = MergeFullPath(GetPathWithSep(exe), 'clibs')
if path and not path:find(clibs, 1, true) then
wx.wxSetEnv("PATH", path..';'..clibs)
end
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
local pid = CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
function() ide.debugger.pid = nil end)
-- restore PATH
wx.wxSetEnv("PATH", path)
return pid
end,
fprojdir = function(self,wfilename)
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)

67
interpreters/luabase.lua Normal file
View File

@@ -0,0 +1,67 @@
function MakeLuaInterpreter(version, name)
local exe
local function exePath(self, version)
local mainpath = ide.editorFilename:gsub("[^/\\]+$","")
local macExe = mainpath..([[bin/lua.app/Contents/MacOS/lua%s]]):format(version)
return ide.config.path['lua'..version]
or (ide.osname == "Windows" and mainpath..([[bin\lua%s.exe]]):format(version))
or (ide.osname == "Unix" and mainpath..([[bin/linux/%s/lua%s]]):format(ide.osarch, version))
or (wx.wxFileExists(macExe) and macExe or mainpath..([[bin/lua%s]]):format(version))
end
return {
name = ("Lua%s"):format(name or version or ""),
description = ("Lua%s interpreter with debugger"):format(name or version or ""),
api = {"wxwidgets","baselib"},
fexepath = exePath,
frun = function(self,wfilename,rundebug)
exe = exe or self:fexepath(version or "")
local filepath = wfilename:GetFullPath()
if rundebug then
DebuggerAttachDefault({runstart = ide.config.debugger.runonstart == true})
else
-- 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
end
local code = rundebug
and ([[-e "io.stdout:setvbuf('no'); %s"]]):format(rundebug)
or ([[-e "io.stdout:setvbuf('no')" "%s"]]):format(filepath)
local cmd = '"'..exe..'" '..code
-- modify CPATH to work with other Lua versions
local _, cpath = wx.wxGetEnv("LUA_CPATH")
if version and cpath and not cpath:find('clibs'..version, 1, true) then
wx.wxSetEnv("LUA_CPATH", cpath:gsub('clibs', 'clibs'..version))
end
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
local pid = CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
function() ide.debugger.pid = nil end)
if version then wx.wxSetEnv("LUA_CPATH", cpath) 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 = false,
unhideanywindow = true,
}
end
return nil -- as this is not a real interpreter

View File

@@ -1,50 +1,2 @@
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 mainpath..([[bin/linux/%s/lua]]):format(ide.osarch))
or (wx.wxFileExists(macExe) and macExe or mainpath..[[bin/lua]]))
end
return {
name = "Lua",
description = "Lua interpreter with debugger",
api = {"wxwidgets","baselib"},
frun = function(self,wfilename,rundebug)
exe = exe or exePath()
local filepath = wfilename:GetFullPath()
if rundebug then
DebuggerAttachDefault({runstart = ide.config.debugger.runonstart == true})
else
-- 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
end
local code = rundebug
and ([[-e "io.stdout:setvbuf('no'); %s"]]):format(rundebug)
or ([[-e "io.stdout:setvbuf('no')" "%s"]]):format(filepath)
local cmd = '"'..exe..'" '..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)
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 = false,
unhideanywindow = true,
}
dofile 'interpreters/luabase.lua'
return MakeLuaInterpreter()

View File

@@ -0,0 +1,2 @@
dofile 'interpreters/luabase.lua'
return MakeLuaInterpreter('52', ' 5.2')

View File

@@ -19,9 +19,10 @@ end
local socket = require "socket"
require "coxpcall"
local coxpcall = require "coxpcall"
local WATCH_DOG_TIMEOUT = 120
local UDP_DATAGRAM_MAX = 8192
-- Redefines LuaSocket functions with coroutine safe versions
-- (this allows the use of socket.http from within copas)
@@ -37,7 +38,7 @@ end
function socket.protect(func)
return function (...)
return statusHandler(copcall(func, ...))
return statusHandler(coxpcall.pcall(func, ...))
end
end
@@ -45,7 +46,7 @@ function socket.newtry(finalizer)
return function (...)
local status = (...)
if not status then
copcall(finalizer, select(2, ...))
coxpcall.pcall(finalizer, select(2, ...))
error({ (select(2, ...)) }, 0)
end
return ...
@@ -54,16 +55,15 @@ end
-- end of LuaSocket redefinitions
module ("copas", package.seeall)
local copas = {}
-- Meta information is public even if beginning with an "_"
_COPYRIGHT = "Copyright (C) 2005-2010 Kepler Project"
_DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services"
_VERSION = "Copas 1.1.7"
copas._COPYRIGHT = "Copyright (C) 2005-2010 Kepler Project"
copas._DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services"
copas._VERSION = "Copas 1.1.7"
-- Close the socket associated with the current connection after the handler finishes
autoclose = true
copas.autoclose = true
-------------------------------------------------------------------------------
-- Simple set implementation based on LuaSocket's tinyirc.lua example
@@ -128,7 +128,10 @@ local _writing = newset() -- sockets currently being written
-- Coroutine based socket I/O functions.
-------------------------------------------------------------------------------
-- reads a pattern from a client and yields to the reading set on timeouts
function receive(client, pattern, part)
-- UDP: a UDP socket expects a second argument to be a number, so it MUST
-- be provided as the 'pattern' below defaults to a string. Will throw a
-- 'bad argument' error if omitted.
function copas.receive(client, pattern, part)
local s, err
pattern = pattern or "*l"
repeat
@@ -142,9 +145,25 @@ function receive(client, pattern, part)
until false
end
-- receives data from a client over UDP. Not available for TCP.
-- (this is a copy of receive() method, adapted for receivefrom() use)
function copas.receivefrom(client, size)
local s, err, port
size = size or UDP_DATAGRAM_MAX
repeat
s, err, port = client:receivefrom(size) -- upon success err holds ip address
if s or err ~= "timeout" then
_reading_log[client] = nil
return s, err, port
end
_reading_log[client] = os.time()
coroutine.yield(client, _reading)
until false
end
-- same as above but with special treatment when reading chunks,
-- unblocks on any data received.
function receivePartial(client, pattern)
function copas.receivePartial(client, pattern)
local s, err, part
pattern = pattern or "*l"
repeat
@@ -161,7 +180,8 @@ end
-- sends data to a client. The operation is buffered and
-- yields to the writing set on timeouts
function send(client,data, from, to)
-- Note: from and to parameters will be ignored by/for UDP sockets
function copas.send(client, data, from, to)
local s, err,sent
from = from or 1
local lastIndex = from - 1
@@ -183,8 +203,30 @@ function send(client,data, from, to)
until false
end
-- sends data to a client over UDP. Not available for TCP.
-- (this is a copy of send() method, adapted for sendto() use)
function copas.sendto(client, data, ip, port)
local s, err,sent
repeat
s, err = client:sendto(data, ip, port)
-- adds extra corrotine swap
-- garantees that high throuput dont take other threads to starvation
if (math.random(100) > 90) then
_writing_log[client] = os.time()
coroutine.yield(client, _writing)
end
if s or err ~= "timeout" then
_writing_log[client] = nil
return s, err
end
_writing_log[client] = os.time()
coroutine.yield(client, _writing)
until false
end
-- waits until connection is completed
function connect(skt, host, port)
function copas.connect(skt, host, port)
skt:settimeout(0)
local ret, err
repeat
@@ -200,24 +242,24 @@ function connect(skt, host, port)
end
-- flushes a client write buffer (deprecated)
function flush(client)
function copas.flush(client)
end
-- wraps a socket to use Copas methods (send, receive, flush and settimeout)
-- wraps a TCP socket to use Copas methods (send, receive, flush and settimeout)
local _skt_mt = {__index = {
send = function (self, data, from, to)
return send (self.socket, data, from, to)
return copas.send (self.socket, data, from, to)
end,
receive = function (self, pattern)
if (self.timeout==0) then
return receivePartial(self.socket, pattern)
return copas.receivePartial(self.socket, pattern)
end
return receive (self.socket, pattern)
return copas.receive(self.socket, pattern)
end,
flush = function (self)
return flush (self.socket)
return copas.flush(self.socket)
end,
settimeout = function (self,time)
@@ -226,8 +268,41 @@ local _skt_mt = {__index = {
end,
}}
function wrap (skt)
return setmetatable ({socket = skt}, _skt_mt)
-- wraps a UDP socket, copy of TCP one adapted for UDP.
-- Mainly adds sendto() and receivefrom()
local _skt_mt_udp = {__index = {
send = function (self, data)
return copas.send (self.socket, data)
end,
sendto = function (self, data, ip, port)
return copas.sendto (self.socket, data, ip, port)
end,
receive = function (self, size)
return copas.receive (self.socket, (size or UDP_DATAGRAM_MAX))
end,
receivefrom = function (self, size)
return copas.receivefrom (self.socket, (size or UDP_DATAGRAM_MAX))
end,
flush = function (self)
return copas.flush (self.socket)
end,
settimeout = function (self,time)
self.timeout=time
return
end,
}}
function copas.wrap (skt)
if string.sub(tostring(skt),1,3) == "udp" then
return setmetatable ({socket = skt}, _skt_mt_udp)
else
return setmetatable ({socket = skt}, _skt_mt)
end
end
--------------------------------------------------
@@ -236,7 +311,7 @@ end
local _errhandlers = {} -- error handler per coroutine
function setErrorHandler (err)
function copas.setErrorHandler (err)
local co = coroutine.running()
if co then
_errhandlers [co] = err
@@ -260,8 +335,8 @@ local function _doTick (co, skt, ...)
new_q:insert (res)
new_q:push (res, co)
else
if not ok then copcall (_errhandlers [co] or _deferror, res, co, skt) end
if skt and autoclose then skt:close() end
if not ok then coxpcall.pcall (_errhandlers [co] or _deferror, res, co, skt) end
if skt and copas.autoclose then skt:close() end
_errhandlers [co] = nil
end
end
@@ -303,7 +378,7 @@ local function addUDPserver(server, handler, timeout)
_doTick (co, server)
end
function addserver(server, handler, timeout)
function copas.addserver(server, handler, timeout)
if string.sub(tostring(server),1,3) == "udp" then
addUDPserver(server, handler, timeout)
else
@@ -313,7 +388,7 @@ end
-------------------------------------------------------------------------------
-- Adds an new courotine thread to Copas dispatcher
-------------------------------------------------------------------------------
function addthread(thread, ...)
function copas.addthread(thread, ...)
if type(thread) ~= "thread" then
thread = coroutine.create(thread)
end
@@ -397,10 +472,6 @@ local last_cleansing = 0
-------------------------------------------------------------------------------
local function _select (timeout)
local err
local readable={}
local writable={}
local r={}
local w={}
local now = os.time()
local duration = os.difftime
@@ -437,10 +508,12 @@ end
-------------------------------------------------------------------------------
-- Dispatcher loop step.
-- Listen to client requests and handles them
-- Returns false if no data was handled (timeout), or true if there was data
-- handled (or nil + error message)
-------------------------------------------------------------------------------
function step(timeout)
function copas.step(timeout)
local err = _select (timeout)
if err == "timeout" then return end
if err == "timeout" then return false end
if err then
error(err)
@@ -451,14 +524,17 @@ function step(timeout)
tsk:tick (ev)
end
end
return true
end
-------------------------------------------------------------------------------
-- Dispatcher endless loop.
-- Listen to client requests and handles them forever
-------------------------------------------------------------------------------
function loop(timeout)
function copas.loop(timeout)
while true do
step(timeout)
copas.step(timeout)
end
end
return copas

View File

@@ -5,31 +5,19 @@
-- be dealed without the usual Lua 5.x pcall/xpcall issues with coroutines
-- yielding inside the call to pcall or xpcall.
--
-- Authors: Roberto Ierusalimschy and Andre Carregal
-- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fábio Mascarenhas
-- Authors: Roberto Ierusalimschy and Andre Carregal
-- Contributors: Thomas Harning Jr., Ignacio Burgueño, Fabio Mascarenhas
--
-- Copyright 2005 - Kepler Project (www.keplerproject.org)
--
-- $Id: coxpcall.lua,v 1.13 2008/05/19 19:20:02 mascarenhas Exp $
-------------------------------------------------------------------------------
-- This version has been modified to handle the case where a child coroutine
-- (created by copcall or coxpcall) is directly resumed, instead of resuming
-- its parent coroutine, because the coroutine reference was obtained by
-- calling coroutine.running from the child coroutine. The modification
-- implemented here is to override coroutine.running so that it returns the
-- parent coroutine instead of the child one.
local oldrunning = coroutine.running
local parents = {}
setmetatable( parents, { __mode = "kv" } )
local function getRoot( co )
return parents[co] or co
end
coroutine.running = function()
return getRoot( oldrunning() )
-- Lua 5.2 makes this module a no-op
if _VERSION == "Lua 5.2" then
copcall = pcall
coxpcall = xpcall
return { pcall = pcall, xpcall = xpcall }
end
-------------------------------------------------------------------------------
@@ -37,7 +25,9 @@ end
-------------------------------------------------------------------------------
local performResume, handleReturnValue
local oldpcall, oldxpcall = pcall, xpcall
local pack = table.pack or function(...) return {n = select("#", ...), ...} end
local unpack = table.unpack or unpack
function handleReturnValue(err, co, status, ...)
if not status then
return false, err(debug.traceback(co, (...)), ...)
@@ -51,16 +41,15 @@ end
function performResume(err, co, ...)
return handleReturnValue(err, co, coroutine.resume(co, ...))
end
end
function coxpcall(f, err, ...)
local res, co = oldpcall(coroutine.create, f)
if not res then
local params = {...}
local newf = function() return f(unpack(params)) end
local params = pack(...)
local newf = function() return f(unpack(params, 1, params.n)) end
co = coroutine.create(newf)
end
parents[co] = getRoot( oldrunning() )
return performResume(err, co, ...)
end
@@ -76,6 +65,4 @@ function copcall(f, ...)
return coxpcall(f, id, ...)
end
-------------------------------------------------------------------------------
-- Override coroutine.running
-------------------------------------------------------------------------------
return { pcall = copcall, xpcall = coxpcall }

View File

@@ -2,7 +2,6 @@
-- LTN12 - Filters, sources, sinks and pumps.
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: ltn12.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -11,15 +10,20 @@
local string = require("string")
local table = require("table")
local base = _G
module("ltn12")
local _M = {}
if module then -- heuristic for exporting a global package table
ltn12 = _M
end
local filter,source,sink,pump = {},{},{},{}
filter = {}
source = {}
sink = {}
pump = {}
_M.filter = filter
_M.source = source
_M.sink = sink
_M.pump = pump
-- 2048 seems to be better in windows...
BLOCKSIZE = 2048
_M.BLOCKSIZE = 2048
_M._VERSION = "LTN12 1.0.3"
-----------------------------------------------------------------------------
-- Filter stuff
@@ -37,7 +41,8 @@ end
-- chains a bunch of filters together
-- (thanks to Wim Couwenberg)
function filter.chain(...)
local n = table.getn(arg)
local arg = {...}
local n = select('#',...)
local top, index = 1, 1
local retry = ""
return function(chunk)
@@ -88,7 +93,7 @@ end
function source.file(handle, io_err)
if handle then
return function()
local chunk = handle:read(BLOCKSIZE)
local chunk = handle:read(_M.BLOCKSIZE)
if not chunk then handle:close() end
return chunk
end
@@ -111,8 +116,8 @@ function source.string(s)
if s then
local i = 1
return function()
local chunk = string.sub(s, i, i+BLOCKSIZE-1)
i = i + BLOCKSIZE
local chunk = string.sub(s, i, i+_M.BLOCKSIZE-1)
i = i + _M.BLOCKSIZE
if chunk ~= "" then return chunk
else return nil end
end
@@ -185,6 +190,7 @@ end
-- other, as if they were concatenated
-- (thanks to Wim Couwenberg)
function source.cat(...)
local arg = {...}
local src = table.remove(arg, 1)
return function()
while src do
@@ -289,3 +295,4 @@ function pump.all(src, snk, step)
end
end
return _M

View File

@@ -19,7 +19,7 @@ local function match_string(s, pos)
pos = pos + 1
while 1 do
pos = s:find("[" .. c .. "\\]", pos)
if not pos then return s:sub(posa), #s end -- not terminated string
if not pos then return s:sub(posa), #s + 1 end -- not terminated string
if s:sub(pos,pos) == c then
local part = s:sub(posa, pos)
return part, pos + 1
@@ -31,7 +31,7 @@ local function match_string(s, pos)
local sc = s:match("^%[(=*)%[", pos)
if sc then
local _; _, pos = s:find("%]" .. sc .. "%]", pos)
if not pos then return s:sub(posa), #s end -- not terminated string
if not pos then return s:sub(posa), #s + 1 end -- not terminated string
local part = s:sub(posa, pos)
return part, pos + 1
else
@@ -120,7 +120,7 @@ function M.lex(code, f, pos)
f('Comment', tok, pos)
pos = pos2
elseif n1 == '\'' or n1 == '\"' or n2 == '[[' or n2 == '[=' then
local tok, _pos2 = match_string(code, pos)
local tok = match_string(code, pos)
if tok then
f('String', tok, pos)
pos = pos + #tok

View File

@@ -200,12 +200,12 @@ function PARSE.parse_scope_resolve(lx, f, vars)
return setmetatable(newvars, {__index=vars})
end
vars = vars or newscope({}, nil, 1)
vars = vars or newscope({[0] = 0}, nil, 1)
vars[NEXT] = false -- vars that come into scope upon next statement
vars[INSIDE] = false -- vars that come into scope upon entering block
PARSE.parse_scope(lx, function(op, name, lineinfo)
-- in some (rare) cases VarNext can follow Statement event (which copies
-- vars[NEXT]). This may case vars[0] to be `nil`, so default to 1.
-- vars[NEXT]). This may cause vars[0] to be `nil`, so default to 1.
local var = op:find("^Var") and
{fpos = lineinfo, at = (vars[0] or 1) + (op == 'VarInside' and 1 or 0),
masked = vars[name], self = (op == 'VarSelf') or nil } or nil

View File

@@ -281,7 +281,7 @@ luaP.OpCode = {} -- lookup name -> number
luaP.ROpCode = {} -- lookup number -> name
local i = 0
for v in string.gfind([[
for v in string.gmatch([[
MOVE -- 0
LOADK
LOADBOOL

View File

@@ -2,7 +2,6 @@
-- MIME support for the Lua language.
-- Author: Diego Nehab
-- Conforming to RFCs 2045-2049
-- RCS ID: $Id: mime.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -13,12 +12,14 @@ local ltn12 = require("ltn12")
local mime = require("mime.core")
local io = require("io")
local string = require("string")
module("mime")
local _M = mime
-- encode, decode and wrap algorithm tables
encodet = {}
decodet = {}
wrapt = {}
local encodet, decodet, wrapt = {},{},{}
_M.encodet = encodet
_M.decodet = decodet
_M.wrapt = wrapt
-- creates a function that chooses a filter by name from a given table
local function choose(table)
@@ -27,28 +28,29 @@ local function choose(table)
name, opt1, opt2 = "default", name, opt1
end
local f = table[name or "nil"]
if not f then error("unknown key (" .. base.tostring(name) .. ")", 3)
if not f then
base.error("unknown key (" .. base.tostring(name) .. ")", 3)
else return f(opt1, opt2) end
end
end
-- define the encoding filters
encodet['base64'] = function()
return ltn12.filter.cycle(b64, "")
return ltn12.filter.cycle(_M.b64, "")
end
encodet['quoted-printable'] = function(mode)
return ltn12.filter.cycle(qp, "",
return ltn12.filter.cycle(_M.qp, "",
(mode == "binary") and "=0D=0A" or "\r\n")
end
-- define the decoding filters
decodet['base64'] = function()
return ltn12.filter.cycle(unb64, "")
return ltn12.filter.cycle(_M.unb64, "")
end
decodet['quoted-printable'] = function()
return ltn12.filter.cycle(unqp, "")
return ltn12.filter.cycle(_M.unqp, "")
end
local function format(chunk)
@@ -61,26 +63,28 @@ end
-- define the line-wrap filters
wrapt['text'] = function(length)
length = length or 76
return ltn12.filter.cycle(wrp, length, length)
return ltn12.filter.cycle(_M.wrp, length, length)
end
wrapt['base64'] = wrapt['text']
wrapt['default'] = wrapt['text']
wrapt['quoted-printable'] = function()
return ltn12.filter.cycle(qpwrp, 76, 76)
return ltn12.filter.cycle(_M.qpwrp, 76, 76)
end
-- function that choose the encoding, decoding or wrap algorithm
encode = choose(encodet)
decode = choose(decodet)
wrap = choose(wrapt)
_M.encode = choose(encodet)
_M.decode = choose(decodet)
_M.wrap = choose(wrapt)
-- define the end-of-line normalization filter
function normalize(marker)
return ltn12.filter.cycle(eol, 0, marker)
function _M.normalize(marker)
return ltn12.filter.cycle(_M.eol, 0, marker)
end
-- high level stuffing filter
function stuff()
return ltn12.filter.cycle(dot, 2)
function _M.stuff()
return ltn12.filter.cycle(_M.dot, 2)
end
return _M

View File

@@ -1,12 +1,12 @@
--
-- MobDebug 0.535
-- MobDebug 0.542
-- Copyright 2011-13 Paul Kulchenko
-- Based on RemDebug 1.0 Copyright Kepler Project 2005
--
local mobdebug = {
_NAME = "mobdebug",
_VERSION = 0.535,
_VERSION = 0.542,
_COPYRIGHT = "Paul Kulchenko",
_DESCRIPTION = "Mobile Remote Debugger for the Lua programming language",
port = os and os.getenv and os.getenv("MOBDEBUG_PORT") or 8172,
@@ -26,6 +26,8 @@ local require = require
local setmetatable = setmetatable
local string = string
local tonumber = tonumber
local unpack = table.unpack or unpack
local rawget = rawget
-- if strict.lua is used, then need to avoid referencing some global
-- variables, as they can be undefined;
@@ -103,7 +105,7 @@ end
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
local serpent = (function() ---- include Serpent module for serialization
local n, v = "serpent", 0.24 -- (C) 2012-13 Paul Kulchenko; MIT License
local n, v = "serpent", 0.25 -- (C) 2012-13 Paul Kulchenko; MIT License
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
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, cdata = true}
@@ -116,7 +118,7 @@ for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'})
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 name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
@@ -149,7 +151,7 @@ local function s(t, opts)
((type(name) == "number") and '' or name..space..'='..space) or
(name ~= nil and sname..space..'='..space or '')
if seen[t] then -- already seen this element
table.insert(sref, spath..space..'='..space..seen[t])
sref[#sref+1] = spath..space..'='..space..seen[t]
return tag..'nil'..comment('ref', level) end
if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
seen[t] = insref or spath
@@ -159,10 +161,14 @@ local function s(t, opts)
if level >= maxl then return tag..'{}'..comment('max', level) end
seen[t] = insref or 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] or key > maxn then table.insert(o, key) end end
if opts.sortkeys then alphanumsort(o, t, opts.sortkeys) end
local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
for key = 1, maxn do o[key] = key end
if not maxnum or #o < maxnum then
local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end end
if maxnum and #o > maxnum then o[maxnum+1] = nil end
if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end
local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
for n, key in ipairs(o) do
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
@@ -171,14 +177,14 @@ local function s(t, opts)
or sparse and value == nil then -- skipping nils; do nothing
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
if not seen[key] and not globals[key] then
table.insert(sref, 'placeholder')
sref[#sref+1] = 'placeholder'
local sname = safename(iname, gensym(key)) -- iname is table for local variables
sref[#sref] = val2str(key,sname,indent,sname,iname,true) end
table.insert(sref, 'placeholder')
sref[#sref+1] = '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
table.insert(out,val2str(value,key,indent,insref,seen[t],plainindex,level+1))
out[#out+1] = val2str(value,key,indent,insref,seen[t],plainindex,level+1)
end
end
local prefix = string.rep(indent or '', level)
@@ -302,7 +308,9 @@ local function restore_vars(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
if string.sub(name, 1, 1) ~= '(' then
debug.setlocal(3, i, rawget(vars, name))
end
written_vars[name] = true
end
i = i - 1
@@ -314,7 +322,9 @@ local function restore_vars(vars)
local name = debug.getupvalue(func, i)
if not name then break end
if not written_vars[name] then
if string.sub(name, 1, 1) ~= '(' then debug.setupvalue(func, i, vars[name]) end
if string.sub(name, 1, 1) ~= '(' then
debug.setupvalue(func, i, rawget(vars, name))
end
written_vars[name] = true
end
i = i + 1
@@ -338,6 +348,13 @@ local function capture_vars(level)
if string.sub(name, 1, 1) ~= '(' then vars[name] = value end
i = i + 1
end
-- returned 'vars' table plays a dual role: (1) it captures local values
-- and upvalues to be restored later (in case they are modified in "eval"),
-- and (2) it provides an environment for evaluated chunks.
-- getfenv(func) is needed to provide proper environment for functions,
-- including access to globals, but this causes vars[name] to fail in
-- restore_vars on local variables or upvalues with `nil` values when
-- 'strict' is in effect. To avoid this `rawget` is used in restore_vars.
setmetatable(vars, { __index = getfenv(func), __newindex = getfenv(func) })
return vars
end
@@ -395,9 +412,13 @@ local function debug_hook(event, line)
-- 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 then
local coro = coroutine.running()
if coro_debugee and coro ~= coro_debugee and not coroutines[coro]
or not coro_debugee and (in_debugger() or coro and not coroutines[coro])
-- when luajit is compiled with LUAJIT_ENABLE_LUA52COMPAT,
-- coroutine.running() returns non-nil for the main thread.
local coro, main = coroutine.running()
if not coro or main then coro = 'main' end
local disabled = coroutines[coro] == false
or coroutines[coro] == nil and coro ~= (coro_debugee or 'main')
if coro_debugee and disabled or not coro_debugee and (disabled or in_debugger())
then return end
end
@@ -463,9 +484,10 @@ local function debug_hook(event, line)
-- some file systems allow newlines in file names; remove these.
file = file:gsub("\n", ' ')
else
-- serialize and return the source code; need serialization as scripts
-- may include newlines, but the names are expected to one one line.
file = serpent.line(file) -- serialize file content as a string
-- this is either a file name coming from loadstring("chunk", "file"),
-- or the actual source code that needs to be serialized (as it may
-- include newlines); assume it's a file name if it's all on one line.
file = file:find("[\r\n]") and serpent.line(file) or file
end
-- set to true if we got here; this only needs to be done once per
@@ -812,15 +834,21 @@ local function isrunning()
return coro_debugger and coroutine.status(coro_debugger) == 'suspended'
end
local lasthost, lastport
-- Starts a debug session by connecting to a controller
local function start(controller_host, controller_port)
-- only one debugging session can be run (as there is only one debug hook)
if isrunning() then return end
controller_host = controller_host or "localhost"
controller_port = controller_port or mobdebug.port
lasthost = controller_host or lasthost
lastport = controller_port or lastport
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
controller_host = lasthost or "localhost"
controller_port = lastport or mobdebug.port
local err
server, err = (socket.connect4 or socket.connect)(controller_host, controller_port)
if server then
-- correct stack depth which already has some calls on it
-- so it doesn't go into negative when those calls return
@@ -853,10 +881,12 @@ local function start(controller_host, controller_port)
end
coro_debugger = coroutine.create(debugger_loop)
debug.sethook(debug_hook, "lcr")
seen_hook = nil -- reset in case the last start() call was refused
step_into = true -- start with step command
return true
else
print("Could not connect to " .. controller_host .. ":" .. controller_port)
print(("Could not connect to %s:%s: %s")
:format(controller_host, controller_port, err or "unknown error"))
end
end
@@ -864,11 +894,15 @@ local function controller(controller_host, controller_port, scratchpad)
-- only one debugging session can be run (as there is only one debug hook)
if isrunning() then return end
controller_host = controller_host or "localhost"
controller_port = controller_port or mobdebug.port
lasthost = controller_host or lasthost
lastport = controller_port or lastport
controller_host = lasthost or "localhost"
controller_port = lastport or mobdebug.port
local exitonerror = not scratchpad
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
local err
server, err = (socket.connect4 or socket.connect)(controller_host, controller_port)
if server then
local function report(trace, err)
local msg = err .. "\n" .. trace
@@ -915,7 +949,8 @@ local function controller(controller_host, controller_port, scratchpad)
end
end
else
print("Could not connect to " .. controller_host .. ":" .. controller_port)
print(("Could not connect to %s:%s: %s")
:format(controller_host, controller_port, err or "unknown error"))
return false
end
return true
@@ -932,13 +967,15 @@ end
local function on()
if not (isrunning() and server) then return end
local co = coroutine.running()
-- main is set to true under Lua5.2 for the "main" chunk.
-- Lua5.1 returns co as `nil` in that case.
local co, main = coroutine.running()
if main then co = nil end
if co then
if not coroutines[co] then
coroutines[co] = true
debug.sethook(co, debug_hook, "lcr")
end
coroutines[co] = true
debug.sethook(co, debug_hook, "lcr")
else
if jit then coroutines.main = true end
debug.sethook(debug_hook, "lcr")
end
end
@@ -946,13 +983,28 @@ end
local function off()
if not (isrunning() and server) then return end
local co = coroutine.running()
-- main is set to true under Lua5.2 for the "main" chunk.
-- Lua5.1 returns co as `nil` in that case.
local co, main = coroutine.running()
if main then co = nil end
-- don't remove coroutine hook under LuaJIT as there is only one (global) hook
if co then
if coroutines[co] then coroutines[co] = false end
-- don't remove coroutine hook under LuaJIT as there is only one (global) hook
coroutines[co] = false
if not jit then debug.sethook(co) end
else
debug.sethook()
if jit then coroutines.main = false end
if not jit then debug.sethook() end
end
-- check if there is any thread that is still being debugged under LuaJIT;
-- if not, turn the debugging off
if jit then
local remove = true
for co, debugged in pairs(coroutines) do
if debugged then remove = false; break end
end
if remove then debug.sethook() end
end
end
@@ -1160,7 +1212,7 @@ local function handle(params, client, options)
print("Error in processing results: " .. err)
return nil, nil, "Error in processing results: " .. err
end
print((table.unpack or unpack)(res))
print(unpack(res))
return res[1], res
end
elseif status == "201" then
@@ -1356,7 +1408,9 @@ local function moai()
if not moconew then return end
MOAICoroutine.new = function(...)
local thread = moconew(...)
local mt = getmetatable(thread)
-- need to support both thread.run and getmetatable(thread).run, which
-- was used in earlier MOAI versions
local mt = thread.run and thread or getmetatable(thread)
local patched = mt.run
mt.run = function(self, f, ...)
return patched(self, function(...)
@@ -1383,8 +1437,9 @@ local function done()
debug.sethook()
server:close()
coro_debugger = nil -- this is to make sure isrunning() returns `false`
seen_hook = nil -- this is to make sure that the next start() call works
coro_debugger = nil -- to make sure isrunning() returns `false`
seen_hook = nil -- to make sure that the next start() call works
abort = nil -- to make sure that callback calls use proper "abort" value
end
-- make public functions available

View File

@@ -1,7 +1,6 @@
-----------------------------------------------------------------------------
-- LuaSocket helper module
-- Author: Diego Nehab
-- RCS ID: $Id: socket.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -11,12 +10,13 @@ local base = _G
local string = require("string")
local math = require("math")
local socket = require("socket.core")
module("socket")
-----------------------------------------------------------------------------
-- Exported auxiliar functions
-----------------------------------------------------------------------------
function connect(address, port, laddress, lport)
local _M = socket
-- this is needed in case this library is used when "socket.core" is loaded,
-- but has an older version of luasocket that does not include `connect`.
if not socket.connect then
socket.connect = function (address, port, laddress, lport)
local sock, err = socket.tcp()
if not sock then return nil, err end
if laddress then
@@ -26,22 +26,52 @@ function connect(address, port, laddress, lport)
local res, err = sock:connect(address, port)
if not res then return nil, err end
return sock
end
end
function bind(host, port, backlog)
local sock, err = socket.tcp()
if not sock then return nil, err end
sock:setoption("reuseaddr", true)
local res, err = sock:bind(host, port)
if not res then return nil, err end
res, err = sock:listen(backlog)
if not res then return nil, err end
return sock
-----------------------------------------------------------------------------
-- Exported auxiliar functions
-----------------------------------------------------------------------------
function _M.connect4(address, port, laddress, lport)
return socket.connect(address, port, laddress, lport, "inet")
end
try = newtry()
function _M.connect6(address, port, laddress, lport)
return socket.connect(address, port, laddress, lport, "inet6")
end
function choose(table)
function _M.bind(host, port, backlog)
if host == "*" then host = "0.0.0.0" end
local addrinfo, err = socket.dns.getaddrinfo(host);
if not addrinfo then return nil, err end
local sock, res
err = "no info on address"
for i, alt in base.ipairs(addrinfo) do
if alt.family == "inet" then
sock, err = socket.tcp()
else
sock, err = socket.tcp6()
end
if not sock then return nil, err end
sock:setoption("reuseaddr", true)
res, err = sock:bind(alt.addr, port)
if not res then
sock:close()
else
res, err = sock:listen(backlog)
if not res then
sock:close()
else
return sock
end
end
end
return nil, err
end
_M.try = _M.newtry()
function _M.choose(table)
return function(name, opt1, opt2)
if base.type(name) ~= "string" then
name, opt1, opt2 = "default", name, opt1
@@ -56,10 +86,11 @@ end
-- Socket sources and sinks, conforming to LTN12
-----------------------------------------------------------------------------
-- create namespaces inside LuaSocket namespace
sourcet = {}
sinkt = {}
local sourcet, sinkt = {}, {}
_M.sourcet = sourcet
_M.sinkt = sinkt
BLOCKSIZE = 2048
_M.BLOCKSIZE = 2048
sinkt["close-when-done"] = function(sock)
return base.setmetatable({
@@ -89,7 +120,7 @@ end
sinkt["default"] = sinkt["keep-open"]
sink = choose(sinkt)
_M.sink = _M.choose(sinkt)
sourcet["by-length"] = function(sock, length)
return base.setmetatable({
@@ -129,5 +160,6 @@ end
sourcet["default"] = sourcet["until-closed"]
source = choose(sourcet)
_M.source = _M.choose(sourcet)
return _M

View File

@@ -2,7 +2,6 @@
-- FTP support for the Lua language
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: ftp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -16,27 +15,27 @@ local socket = require("socket")
local url = require("socket.url")
local tp = require("socket.tp")
local ltn12 = require("ltn12")
module("socket.ftp")
socket.ftp = {}
local _M = socket.ftp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
-- timeout in seconds before the program gives up on a connection
TIMEOUT = 60
_M.TIMEOUT = 60
-- default port for ftp service
PORT = 21
_M.PORT = 21
-- this is the default anonymous password. used when no password is
-- provided in url. should be changed to your e-mail.
USER = "ftp"
PASSWORD = "anonymous@anonymous.org"
_M.USER = "ftp"
_M.PASSWORD = "anonymous@anonymous.org"
-----------------------------------------------------------------------------
-- Low level FTP API
-----------------------------------------------------------------------------
local metat = { __index = {} }
function open(server, port, create)
local tp = socket.try(tp.connect(server, port or PORT, create, TIMEOUT))
function _M.open(server, port, create)
local tp = socket.try(tp.connect(server, port or _M.PORT, _M.TIMEOUT, create))
local f = base.setmetatable({ tp = tp }, metat)
-- make sure everything gets closed in an exception
f.try = socket.newtry(function() f:close() end)
@@ -44,22 +43,22 @@ function open(server, port, create)
end
function metat.__index:portconnect()
self.try(self.server:settimeout(TIMEOUT))
self.try(self.server:settimeout(_M.TIMEOUT))
self.data = self.try(self.server:accept())
self.try(self.data:settimeout(TIMEOUT))
self.try(self.data:settimeout(_M.TIMEOUT))
end
function metat.__index:pasvconnect()
self.data = self.try(socket.tcp())
self.try(self.data:settimeout(TIMEOUT))
self.try(self.data:settimeout(_M.TIMEOUT))
self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
end
function metat.__index:login(user, password)
self.try(self.tp:command("user", user or USER))
self.try(self.tp:command("user", user or _M.USER))
local code, reply = self.try(self.tp:check{"2..", 331})
if code == 331 then
self.try(self.tp:command("pass", password or PASSWORD))
self.try(self.tp:command("pass", password or _M.PASSWORD))
self.try(self.tp:check("2.."))
end
return 1
@@ -88,7 +87,7 @@ function metat.__index:port(ip, port)
ip, port = self.try(self.tp:getcontrol():getsockname())
self.server = self.try(socket.bind(ip, 0))
ip, port = self.try(self.server:getsockname())
self.try(server:settimeout(TIMEOUT))
self.try(self.server:settimeout(_M.TIMEOUT))
end
local pl = math.mod(port, 256)
local ph = (port - pl)/256
@@ -116,10 +115,11 @@ function metat.__index:send(sendt)
if not self.pasvt then self:portconnect() end
-- get the sink, source and step for the transfer
local step = sendt.step or ltn12.pump.step
local readt = {self.tp.c}
local checkstep = function(src, snk)
-- check status in control connection while downloading
local readyt = socket.select(readt, nil, 0)
if readyt[tp] then self.try(self.tp:check("2..")) end
if readyt[tp] then code = self.try(self.tp:check("2..")) end
return step(src, snk)
end
local sink = socket.sink("close-when-done", self.data)
@@ -142,7 +142,11 @@ function metat.__index:receive(recvt)
if argument == "" then argument = nil end
local command = recvt.command or "retr"
self.try(self.tp:command(command, argument))
local code = self.try(self.tp:check{"1..", "2.."})
local code,reply = self.try(self.tp:check{"1..", "2.."})
if (code >= 200) and (code <= 299) then
recvt.sink(reply)
return 1
end
if not self.pasvt then self:portconnect() end
local source = socket.source("until-closed", self.data)
local step = recvt.step or ltn12.pump.step
@@ -186,9 +190,9 @@ end
-----------------------------------------------------------------------------
-- High level FTP API
-----------------------------------------------------------------------------
function override(t)
local function override(t)
if t.url then
u = url.parse(t.url)
local u = url.parse(t.url)
for i,v in base.pairs(t) do
u[i] = v
end
@@ -199,7 +203,7 @@ end
local function tput(putt)
putt = override(putt)
socket.try(putt.host, "missing hostname")
local f = open(putt.host, putt.port, putt.create)
local f = _M.open(putt.host, putt.port, putt.create)
f:greet()
f:login(putt.user, putt.password)
if putt.type then f:type(putt.type) end
@@ -211,8 +215,8 @@ local function tput(putt)
end
local default = {
path = "/",
scheme = "ftp"
path = "/",
scheme = "ftp"
}
local function parse(u)
@@ -234,7 +238,7 @@ local function sput(u, body)
return tput(putt)
end
put = socket.protect(function(putt, body)
_M.put = socket.protect(function(putt, body)
if base.type(putt) == "string" then return sput(putt, body)
else return tput(putt) end
end)
@@ -242,7 +246,7 @@ end)
local function tget(gett)
gett = override(gett)
socket.try(gett.host, "missing hostname")
local f = open(gett.host, gett.port, gett.create)
local f = _M.open(gett.host, gett.port, gett.create)
f:greet()
f:login(gett.user, gett.password)
if gett.type then f:type(gett.type) end
@@ -260,7 +264,7 @@ local function sget(u)
return table.concat(t)
end
command = socket.protect(function(cmdt)
_M.command = socket.protect(function(cmdt)
cmdt = override(cmdt)
socket.try(cmdt.host, "missing hostname")
socket.try(cmdt.command, "missing command")
@@ -273,8 +277,9 @@ command = socket.protect(function(cmdt)
return f:close()
end)
get = socket.protect(function(gett)
_M.get = socket.protect(function(gett)
if base.type(gett) == "string" then return sget(gett)
else return tget(gett) end
end)
return _M

104
lualibs/socket/headers.lua Normal file
View File

@@ -0,0 +1,104 @@
-----------------------------------------------------------------------------
-- Canonic header field capitalization
-- LuaSocket toolkit.
-- Author: Diego Nehab
-----------------------------------------------------------------------------
local socket = require("socket")
socket.headers = {}
local _M = socket.headers
_M.canonic = {
["accept"] = "Accept",
["accept-charset"] = "Accept-Charset",
["accept-encoding"] = "Accept-Encoding",
["accept-language"] = "Accept-Language",
["accept-ranges"] = "Accept-Ranges",
["action"] = "Action",
["alternate-recipient"] = "Alternate-Recipient",
["age"] = "Age",
["allow"] = "Allow",
["arrival-date"] = "Arrival-Date",
["authorization"] = "Authorization",
["bcc"] = "Bcc",
["cache-control"] = "Cache-Control",
["cc"] = "Cc",
["comments"] = "Comments",
["connection"] = "Connection",
["content-description"] = "Content-Description",
["content-disposition"] = "Content-Disposition",
["content-encoding"] = "Content-Encoding",
["content-id"] = "Content-ID",
["content-language"] = "Content-Language",
["content-length"] = "Content-Length",
["content-location"] = "Content-Location",
["content-md5"] = "Content-MD5",
["content-range"] = "Content-Range",
["content-transfer-encoding"] = "Content-Transfer-Encoding",
["content-type"] = "Content-Type",
["cookie"] = "Cookie",
["date"] = "Date",
["diagnostic-code"] = "Diagnostic-Code",
["dsn-gateway"] = "DSN-Gateway",
["etag"] = "ETag",
["expect"] = "Expect",
["expires"] = "Expires",
["final-log-id"] = "Final-Log-ID",
["final-recipient"] = "Final-Recipient",
["from"] = "From",
["host"] = "Host",
["if-match"] = "If-Match",
["if-modified-since"] = "If-Modified-Since",
["if-none-match"] = "If-None-Match",
["if-range"] = "If-Range",
["if-unmodified-since"] = "If-Unmodified-Since",
["in-reply-to"] = "In-Reply-To",
["keywords"] = "Keywords",
["last-attempt-date"] = "Last-Attempt-Date",
["last-modified"] = "Last-Modified",
["location"] = "Location",
["max-forwards"] = "Max-Forwards",
["message-id"] = "Message-ID",
["mime-version"] = "MIME-Version",
["original-envelope-id"] = "Original-Envelope-ID",
["original-recipient"] = "Original-Recipient",
["pragma"] = "Pragma",
["proxy-authenticate"] = "Proxy-Authenticate",
["proxy-authorization"] = "Proxy-Authorization",
["range"] = "Range",
["received"] = "Received",
["received-from-mta"] = "Received-From-MTA",
["references"] = "References",
["referer"] = "Referer",
["remote-mta"] = "Remote-MTA",
["reply-to"] = "Reply-To",
["reporting-mta"] = "Reporting-MTA",
["resent-bcc"] = "Resent-Bcc",
["resent-cc"] = "Resent-Cc",
["resent-date"] = "Resent-Date",
["resent-from"] = "Resent-From",
["resent-message-id"] = "Resent-Message-ID",
["resent-reply-to"] = "Resent-Reply-To",
["resent-sender"] = "Resent-Sender",
["resent-to"] = "Resent-To",
["retry-after"] = "Retry-After",
["return-path"] = "Return-Path",
["sender"] = "Sender",
["server"] = "Server",
["smtp-remote-recipient"] = "SMTP-Remote-Recipient",
["status"] = "Status",
["subject"] = "Subject",
["te"] = "TE",
["to"] = "To",
["trailer"] = "Trailer",
["transfer-encoding"] = "Transfer-Encoding",
["upgrade"] = "Upgrade",
["user-agent"] = "User-Agent",
["vary"] = "Vary",
["via"] = "Via",
["warning"] = "Warning",
["will-retry-until"] = "Will-Retry-Until",
["www-authenticate"] = "WWW-Authenticate",
["x-mailer"] = "X-Mailer",
}
return _M

View File

@@ -2,7 +2,6 @@
-- HTTP/1.1 client support for the Lua language.
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: http.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -13,9 +12,11 @@ local url = require("socket.url")
local ltn12 = require("ltn12")
local mime = require("mime")
local string = require("string")
local headers = require("socket.headers")
local base = _G
local table = require("table")
module("socket.http")
socket.http = {}
local _M = socket.http
-----------------------------------------------------------------------------
-- Program constants
@@ -23,9 +24,9 @@ module("socket.http")
-- connection timeout in seconds
TIMEOUT = 60
-- default port for document retrieval
PORT = 80
_M.PORT = 80
-- user agent field sent in request
USERAGENT = socket._VERSION
_M.USERAGENT = socket._VERSION
-----------------------------------------------------------------------------
-- Reads MIME headers from a connection, unfolding where needed
@@ -105,15 +106,15 @@ end
-----------------------------------------------------------------------------
local metat = { __index = {} }
function open(host, port, create)
function _M.open(host, port, create)
-- create socket with user connect function, or with default
local c = socket.try(create or socket.tcp)()
local c = socket.try((create or socket.tcp)())
local h = base.setmetatable({ c = c }, metat)
-- create finalized try
h.try = socket.newtry(function() h:close() end)
-- set timeout before connecting
h.try(c:settimeout(TIMEOUT))
h.try(c:connect(host, port or PORT))
h.try(c:settimeout(_M.TIMEOUT))
h.try(c:connect(host, port or _M.PORT))
-- here everything worked
return h
end
@@ -123,10 +124,11 @@ function metat.__index:sendrequestline(method, uri)
return self.try(self.c:send(reqline))
end
function metat.__index:sendheaders(headers)
function metat.__index:sendheaders(tosend)
local canonic = headers.canonic
local h = "\r\n"
for i, v in base.pairs(headers) do
h = i .. ": " .. v .. "\r\n" .. h
for f, v in base.pairs(tosend) do
h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h
end
self.try(self.c:send(h))
return 1
@@ -142,7 +144,12 @@ function metat.__index:sendbody(headers, source, step)
end
function metat.__index:receivestatusline()
local status = self.try(self.c:receive())
local status = self.try(self.c:receive(5))
-- identify HTTP/0.9 responses, which do not contain a status line
-- this is just a heuristic, but is what the RFC recommends
if status ~= "HTTP/" then return nil, status end
-- otherwise proceed reading a status line
status = self.try(self.c:receive("*l", status))
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
return self.try(base.tonumber(code), status)
end
@@ -163,6 +170,12 @@ function metat.__index:receivebody(headers, sink, step)
sink, step))
end
function metat.__index:receive09body(status, sink, step)
local source = ltn12.source.rewind(socket.source("until-closed", self.c))
source(status)
return self.try(ltn12.pump.all(source, sink, step))
end
function metat.__index:close()
return self.c:close()
end
@@ -194,16 +207,21 @@ local function adjustproxy(reqt)
end
end
local function adjustheaders(headers, host)
local function adjustheaders(reqt)
-- default headers
local lower = {
["user-agent"] = USERAGENT,
["host"] = host,
["user-agent"] = _M.USERAGENT,
["host"] = reqt.host,
["connection"] = "close, TE",
["te"] = "trailers"
}
-- if we have authentication information, pass it along
if reqt.user and reqt.password then
lower["authorization"] =
"Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
end
-- override with user headers
for i,v in base.pairs(headers or lower) do
for i,v in base.pairs(reqt.headers or lower) do
lower[string.lower(i)] = v
end
return lower
@@ -212,7 +230,7 @@ end
-- default url parts
local default = {
host = "",
port = PORT,
port = _M.PORT,
path ="/",
scheme = "http"
}
@@ -220,16 +238,17 @@ local default = {
local function adjustrequest(reqt)
-- parse url if provided
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
local t = url.parse(reqt.url, default)
-- explicit components override url
for i,v in base.pairs(reqt) do nreqt[i] = v end
socket.try(nreqt.host, "invalid host '" .. base.tostring(nreqt.host) .. "'")
if nreqt.port == "" then nreqt.port = 80 end
socket.try(nreqt.host and nreqt.host ~= "",
"invalid host '" .. base.tostring(nreqt.host) .. "'")
-- compute uri if user hasn't overriden
nreqt.uri = reqt.uri or adjusturi(nreqt)
-- ajust host and port if there is a proxy
nreqt.host, nreqt.port = adjustproxy(nreqt)
-- adjust headers in request
nreqt.headers = adjustheaders(nreqt.headers, nreqt.host)
nreqt.headers = adjustheaders(nreqt)
return nreqt
end
@@ -237,19 +256,11 @@ local function shouldredirect(reqt, code, headers)
return headers.location and
string.gsub(headers.location, "%s", "") ~= "" and
(reqt.redirect ~= false) and
(code == 301 or code == 302) and
(code == 301 or code == 302 or code == 303 or code == 307) and
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
and (not reqt.nredirects or reqt.nredirects < 5)
end
local function shouldauthorize(reqt, code)
-- if there has been an authorization attempt, it must have failed
if reqt.headers and reqt.headers["authorization"] then return nil end
-- if last attempt didn't fail due to lack of authentication,
-- or we don't have authorization information, we can't retry
return code == 401 and reqt.user and reqt.password
end
local function shouldreceivebody(reqt, code)
if reqt.method == "HEAD" then return nil end
if code == 204 or code == 304 then return nil end
@@ -258,69 +269,86 @@ local function shouldreceivebody(reqt, code)
end
-- forward declarations
local trequest, tauthorize, tredirect
local trequest, tredirect
function tauthorize(reqt)
local auth = "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
reqt.headers["authorization"] = auth
return trequest(reqt)
end
function tredirect(reqt, location)
--[[local]] function tredirect(reqt, location)
local result, code, headers, status = trequest {
-- the RFC says the redirect URL has to be absolute, but some
-- servers do not respect that
url = url.absolute(reqt, location),
url = url.absolute(reqt.url, location),
source = reqt.source,
sink = reqt.sink,
headers = reqt.headers,
proxy = reqt.proxy,
proxy = reqt.proxy,
nredirects = (reqt.nredirects or 0) + 1,
connect = reqt.connect
}
create = reqt.create
}
-- pass location header back as a hint we redirected
headers = headers or {}
headers.location = headers.location or location
return result, code, headers, status
end
function trequest(reqt)
reqt = adjustrequest(reqt)
local h = open(reqt.host, reqt.port, reqt.create)
h:sendrequestline(reqt.method, reqt.uri)
h:sendheaders(reqt.headers)
if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end
local code, headers, status
code, status = h:receivestatusline()
--[[local]] function trequest(reqt)
-- we loop until we get what we want, or
-- until we are sure there is no way to get it
local nreqt = adjustrequest(reqt)
local h = _M.open(nreqt.host, nreqt.port, nreqt.create)
-- send request line and headers
h:sendrequestline(nreqt.method, nreqt.uri)
h:sendheaders(nreqt.headers)
-- if there is a body, send it
if nreqt.source then
h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
end
local code, status = h:receivestatusline()
-- if it is an HTTP/0.9 server, simply get the body and we are done
if not code then
h:receive09body(status, nreqt.sink, nreqt.step)
return 1, 200
end
local headers
-- ignore any 100-continue messages
while code == 100 do
headers = h:receiveheaders()
code, status = h:receivestatusline()
end
headers = h:receiveheaders()
if shouldredirect(reqt, code, headers) then
-- at this point we should have a honest reply from the server
-- we can't redirect if we already used the source, so we report the error
if shouldredirect(nreqt, code, headers) and not nreqt.source then
h:close()
return tredirect(reqt, headers.location)
elseif shouldauthorize(reqt, code) then
h:close()
return tauthorize(reqt)
elseif shouldreceivebody(reqt, code) then
h:receivebody(headers, reqt.sink, reqt.step)
end
-- here we are finally done
if shouldreceivebody(nreqt, code) then
h:receivebody(headers, nreqt.sink, nreqt.step)
end
h:close()
return 1, code, headers, status
end
local function srequest(u, body)
local function srequest(u, b)
local t = {}
local reqt = {
url = u,
sink = ltn12.sink.table(t)
}
if body then
reqt.source = ltn12.source.string(body)
reqt.headers = { ["content-length"] = string.len(body) }
if b then
reqt.source = ltn12.source.string(b)
reqt.headers = {
["content-length"] = string.len(b),
["content-type"] = "application/x-www-form-urlencoded"
}
reqt.method = "POST"
end
local code, headers, status = socket.skip(1, trequest(reqt))
return table.concat(t), code, headers, status
end
request = socket.protect(function(reqt, body)
_M.request = socket.protect(function(reqt, body)
if base.type(reqt) == "string" then return srequest(reqt, body)
else return trequest(reqt) end
end)
return _M

View File

@@ -2,7 +2,6 @@
-- SMTP client support for the Lua language.
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: smtp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -16,23 +15,26 @@ local os = require("os")
local socket = require("socket")
local tp = require("socket.tp")
local ltn12 = require("ltn12")
local headers = require("socket.headers")
local mime = require("mime")
module("socket.smtp")
socket.smtp = {}
local _M = socket.smtp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
-- timeout for connection
TIMEOUT = 60
_M.TIMEOUT = 60
-- default server used to send e-mails
SERVER = "localhost"
_M.SERVER = "localhost"
-- default port
PORT = 25
_M.PORT = 25
-- domain used in HELO command and default sendmail
-- If we are under a CGI, try to get from environment
DOMAIN = os.getenv("SERVER_NAME") or "localhost"
_M.DOMAIN = os.getenv("SERVER_NAME") or "localhost"
-- default time zone (means we don't know)
ZONE = "-0000"
_M.ZONE = "-0000"
---------------------------------------------------------------------------
-- Low level SMTP API
@@ -41,7 +43,7 @@ local metat = { __index = {} }
function metat.__index:greet(domain)
self.try(self.tp:check("2.."))
self.try(self.tp:command("EHLO", domain or DOMAIN))
self.try(self.tp:command("EHLO", domain or _M.DOMAIN))
return socket.skip(1, self.try(self.tp:check("2..")))
end
@@ -75,9 +77,9 @@ end
function metat.__index:login(user, password)
self.try(self.tp:command("AUTH", "LOGIN"))
self.try(self.tp:check("3.."))
self.try(self.tp:command(mime.b64(user)))
self.try(self.tp:send(mime.b64(user) .. "\r\n"))
self.try(self.tp:check("3.."))
self.try(self.tp:command(mime.b64(password)))
self.try(self.tp:send(mime.b64(password) .. "\r\n"))
return self.try(self.tp:check("2.."))
end
@@ -111,9 +113,9 @@ function metat.__index:send(mailt)
self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
end
function open(server, port, create)
local tp = socket.try(tp.connect(server or SERVER, port or PORT,
create, TIMEOUT))
function _M.open(server, port, create)
local tp = socket.try(tp.connect(server or _M.SERVER, port or _M.PORT,
_M.TIMEOUT, create))
local s = base.setmetatable({tp = tp}, metat)
-- make sure tp is closed if we get an exception
s.try = socket.newtry(function()
@@ -122,6 +124,15 @@ function open(server, port, create)
return s
end
-- convert headers to lowercase
local function lower_headers(headers)
local lower = {}
for i,v in base.pairs(headers or lower) do
lower[string.lower(i)] = v
end
return lower
end
---------------------------------------------------------------------------
-- Multipart message source
-----------------------------------------------------------------------------
@@ -137,10 +148,11 @@ end
local send_message
-- yield the headers all at once, it's faster
local function send_headers(headers)
local function send_headers(tosend)
local canonic = headers.canonic
local h = "\r\n"
for i,v in base.pairs(headers) do
h = i .. ': ' .. v .. "\r\n" .. h
for f,v in base.pairs(tosend) do
h = (canonic[f] or f) .. ': ' .. v .. "\r\n" .. h
end
coroutine.yield(h)
end
@@ -149,7 +161,7 @@ end
local function send_multipart(mesgt)
-- make sure we have our boundary and send headers
local bd = newboundary()
local headers = mesgt.headers or {}
local headers = lower_headers(mesgt.headers or {})
headers['content-type'] = headers['content-type'] or 'multipart/mixed'
headers['content-type'] = headers['content-type'] ..
'; boundary="' .. bd .. '"'
@@ -176,7 +188,7 @@ end
-- yield message body from a source
local function send_source(mesgt)
-- make sure we have a content-type
local headers = mesgt.headers or {}
local headers = lower_headers(mesgt.headers or {})
headers['content-type'] = headers['content-type'] or
'text/plain; charset="iso-8859-1"'
send_headers(headers)
@@ -192,7 +204,7 @@ end
-- yield message body from a string
local function send_string(mesgt)
-- make sure we have a content-type
local headers = mesgt.headers or {}
local headers = lower_headers(mesgt.headers or {})
headers['content-type'] = headers['content-type'] or
'text/plain; charset="iso-8859-1"'
send_headers(headers)
@@ -209,20 +221,17 @@ end
-- set defaul headers
local function adjust_headers(mesgt)
local lower = {}
for i,v in base.pairs(mesgt.headers or lower) do
lower[string.lower(i)] = v
end
local lower = lower_headers(mesgt.headers)
lower["date"] = lower["date"] or
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE)
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
-- this can't be overriden
lower["mime-version"] = "1.0"
mesgt.headers = lower
return lower
end
function message(mesgt)
adjust_headers(mesgt)
function _M.message(mesgt)
mesgt.headers = adjust_headers(mesgt)
-- create and return message source
local co = coroutine.create(function() send_message(mesgt) end)
return function()
@@ -235,11 +244,13 @@ end
---------------------------------------------------------------------------
-- High level SMTP API
-----------------------------------------------------------------------------
send = socket.protect(function(mailt)
local s = open(mailt.server, mailt.port, mailt.create)
_M.send = socket.protect(function(mailt)
local s = _M.open(mailt.server, mailt.port, mailt.create)
local ext = s:greet(mailt.domain)
s:auth(mailt.user, mailt.password, ext)
s:send(mailt)
s:quit()
return s:close()
end)
return _M

View File

@@ -2,7 +2,6 @@
-- Unified SMTP/FTP subsystem
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: tp.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -12,12 +11,14 @@ local base = _G
local string = require("string")
local socket = require("socket")
local ltn12 = require("ltn12")
module("socket.tp")
socket.tp = {}
local _M = socket.tp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
TIMEOUT = 60
_M.TIMEOUT = 60
-----------------------------------------------------------------------------
-- Implementation
@@ -64,6 +65,7 @@ function metat.__index:check(ok)
end
function metat.__index:command(cmd, arg)
cmd = string.upper(cmd)
if arg then
return self.c:send(cmd .. " " .. arg.. "\r\n")
else
@@ -105,14 +107,14 @@ end
-- closes the underlying c
function metat.__index:close()
self.c:close()
return 1
return 1
end
-- connect with server and return c object
function connect(host, port, create, timeout)
local c, e = (create or socket.tcp())
function _M.connect(host, port, timeout, create)
local c, e = (create or socket.tcp)()
if not c then return nil, e end
c:settimeout(timeout or TIMEOUT)
c:settimeout(timeout or _M.TIMEOUT)
local r, e = c:connect(host, port)
if not r then
c:close()
@@ -121,3 +123,4 @@ function connect(host, port, create, timeout)
return base.setmetatable({c = c}, metat)
end
return _M

View File

@@ -2,7 +2,6 @@
-- URI parsing, composition and relative URL resolution
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- RCS ID: $Id: url.lua 1418 2006-04-25 09:38:15Z 3rdparty $
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
@@ -11,12 +10,15 @@
local string = require("string")
local base = _G
local table = require("table")
module("socket.url")
local socket = require("socket")
socket.url = {}
local _M = socket.url
-----------------------------------------------------------------------------
-- Module version
-----------------------------------------------------------------------------
_VERSION = "URL 1.0"
_M._VERSION = "URL 1.0.3"
-----------------------------------------------------------------------------
-- Encodes a string into its escaped hexadecimal representation
@@ -25,10 +27,10 @@ _VERSION = "URL 1.0"
-- Returns
-- escaped representation of string binary
-----------------------------------------------------------------------------
function escape(s)
return string.gsub(s, "([^A-Za-z0-9_])", function(c)
function _M.escape(s)
return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
return string.format("%%%02x", string.byte(c))
end)
end))
end
-----------------------------------------------------------------------------
@@ -40,25 +42,25 @@ end
-- escaped representation of string binary
-----------------------------------------------------------------------------
local function make_set(t)
local s = {}
for i,v in base.ipairs(t) do
s[t[i]] = 1
end
return s
local s = {}
for i,v in base.ipairs(t) do
s[t[i]] = 1
end
return s
end
-- these are allowed withing a path segment, along with alphanum
-- other characters must be escaped
local segment_set = make_set {
"-", "_", ".", "!", "~", "*", "'", "(",
")", ":", "@", "&", "=", "+", "$", ",",
")", ":", "@", "&", "=", "+", "$", ",",
}
local function protect_segment(s)
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
if segment_set[c] then return c
else return string.format("%%%02x", string.byte(c)) end
end)
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
if segment_set[c] then return c
else return string.format("%%%02x", string.byte(c)) end
end)
end
-----------------------------------------------------------------------------
@@ -68,10 +70,10 @@ end
-- Returns
-- escaped representation of string binary
-----------------------------------------------------------------------------
function unescape(s)
return string.gsub(s, "%%(%x%x)", function(hex)
function _M.unescape(s)
return (string.gsub(s, "%%(%x%x)", function(hex)
return string.char(base.tonumber(hex, 16))
end)
end))
end
-----------------------------------------------------------------------------
@@ -121,7 +123,7 @@ end
-- Obs:
-- the leading '/' in {/<path>} is considered part of <path>
-----------------------------------------------------------------------------
function parse(url, default)
function _M.parse(url, default)
-- initialize default parameters
local parsed = {}
for i,v in base.pairs(default or parsed) do parsed[i] = v end
@@ -142,7 +144,7 @@ function parse(url, default)
parsed.authority = n
return ""
end)
-- get query stringing
-- get query string
url = string.gsub(url, "%?(.*)", function(q)
parsed.query = q
return ""
@@ -158,9 +160,12 @@ function parse(url, default)
if not authority then return parsed end
authority = string.gsub(authority,"^([^@]*)@",
function(u) parsed.userinfo = u; return "" end)
authority = string.gsub(authority, ":([^:]*)$",
authority = string.gsub(authority, ":([^:%]]*)$",
function(p) parsed.port = p; return "" end)
if authority ~= "" then parsed.host = authority end
if authority ~= "" then
-- IPv6?
parsed.host = string.match(authority, "^%[(.+)%]$") or authority
end
local userinfo = parsed.userinfo
if not userinfo then return parsed end
userinfo = string.gsub(userinfo, ":([^:]*)$",
@@ -177,24 +182,27 @@ end
-- Returns
-- a stringing with the corresponding URL
-----------------------------------------------------------------------------
function build(parsed)
local ppath = parse_path(parsed.path or "")
local url = build_path(ppath)
function _M.build(parsed)
local ppath = _M.parse_path(parsed.path or "")
local url = _M.build_path(ppath)
if parsed.params then url = url .. ";" .. parsed.params end
if parsed.query then url = url .. "?" .. parsed.query end
local authority = parsed.authority
if parsed.host then
authority = parsed.host
if parsed.port then authority = authority .. ":" .. parsed.port end
local userinfo = parsed.userinfo
if parsed.user then
userinfo = parsed.user
if parsed.password then
userinfo = userinfo .. ":" .. parsed.password
end
end
if userinfo then authority = userinfo .. "@" .. authority end
end
local authority = parsed.authority
if parsed.host then
authority = parsed.host
if string.find(authority, ":") then -- IPv6?
authority = "[" .. authority .. "]"
end
if parsed.port then authority = authority .. ":" .. parsed.port end
local userinfo = parsed.userinfo
if parsed.user then
userinfo = parsed.user
if parsed.password then
userinfo = userinfo .. ":" .. parsed.password
end
end
if userinfo then authority = userinfo .. "@" .. authority end
end
if authority then url = "//" .. authority .. url end
if parsed.scheme then url = parsed.scheme .. ":" .. url end
if parsed.fragment then url = url .. "#" .. parsed.fragment end
@@ -210,14 +218,14 @@ end
-- Returns
-- corresponding absolute url
-----------------------------------------------------------------------------
function absolute(base_url, relative_url)
function _M.absolute(base_url, relative_url)
if base.type(base_url) == "table" then
base_parsed = base_url
base_url = build(base_parsed)
base_url = _M.build(base_parsed)
else
base_parsed = parse(base_url)
base_parsed = _M.parse(base_url)
end
local relative_parsed = parse(relative_url)
local relative_parsed = _M.parse(relative_url)
if not base_parsed then return relative_url
elseif not relative_parsed then return base_url
elseif relative_parsed.scheme then return relative_url
@@ -238,7 +246,7 @@ function absolute(base_url, relative_url)
relative_parsed.path)
end
end
return build(relative_parsed)
return _M.build(relative_parsed)
end
end
@@ -249,17 +257,17 @@ end
-- Returns
-- segment: a table with one entry per segment
-----------------------------------------------------------------------------
function parse_path(path)
local parsed = {}
path = path or ""
--path = string.gsub(path, "%s", "")
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
for i = 1, table.getn(parsed) do
parsed[i] = unescape(parsed[i])
end
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
return parsed
function _M.parse_path(path)
local parsed = {}
path = path or ""
--path = string.gsub(path, "%s", "")
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
for i = 1, #parsed do
parsed[i] = _M.unescape(parsed[i])
end
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
return parsed
end
-----------------------------------------------------------------------------
@@ -270,28 +278,30 @@ end
-- Returns
-- path: corresponding path stringing
-----------------------------------------------------------------------------
function build_path(parsed, unsafe)
local path = ""
local n = table.getn(parsed)
if unsafe then
for i = 1, n-1 do
path = path .. parsed[i]
path = path .. "/"
end
if n > 0 then
path = path .. parsed[n]
if parsed.is_directory then path = path .. "/" end
end
else
for i = 1, n-1 do
path = path .. protect_segment(parsed[i])
path = path .. "/"
end
if n > 0 then
path = path .. protect_segment(parsed[n])
if parsed.is_directory then path = path .. "/" end
end
end
if parsed.is_absolute then path = "/" .. path end
return path
function _M.build_path(parsed, unsafe)
local path = ""
local n = #parsed
if unsafe then
for i = 1, n-1 do
path = path .. parsed[i]
path = path .. "/"
end
if n > 0 then
path = path .. parsed[n]
if parsed.is_directory then path = path .. "/" end
end
else
for i = 1, n-1 do
path = path .. protect_segment(parsed[i])
path = path .. "/"
end
if n > 0 then
path = path .. protect_segment(parsed[n])
if parsed.is_directory then path = path .. "/" end
end
end
if parsed.is_absolute then path = "/" .. path end
return path
end
return _M

View File

@@ -21,25 +21,35 @@ local events = {
onEditorClose = function(self, editor) end,
onEditorNew = function(self, editor) end,
onEditorPreSave = function(self, editor, filepath) end, -- return false
onEditorPostSave = function(self, editor) end,
onEditorActivated = function(self, editor) end,
onEditorSave = function(self, editor) end,
onEditorFocusLost = function(self, editor) end,
onEditorFocusSet = function(self, editor) end,
onEditorKeyDown = function(self, editor, event) end, -- return false
onEditorCharAdded = function(self, editor, event) end, -- return false
onMenuEditor = function(self, menu, editor, event) end,
onMenuEditorTab = function(self, menu, notebook, event) end,
onMenuEditorTab = function(self, menu, notebook, event, index) end,
onMenuFiletree = function(self, menu, tree, event) end,
onProjectLoad = function(self, project) end,
onProjectClose = function(self, project) end,
onInterpreterLoad = function(self, interpreter) end,
onInterpreterClose = function(self, interpreter) end,
onIdleOnce = function(self, event) end,
onAppFocusLost = function(self, app) end,
onAppFocusSet = function(self, app) end,
onAppLoad = function(self, app) end,
onAppClose = function(self, app) end,
}
--[[ Uncomment this to see event names printed in the Output window
for k in pairs(events) do
if k:find("^on") then
P[k] = k:find("^onEditor")
and function(self, ed) DisplayOutputLn(self:GetFileName(), k, ide:GetDocument(ed):GetFilePath()) end
or function(self, ...) DisplayOutputLn(self:GetFileName(), k, ...) end
and function(self, ed)
-- document can be empty for newly added documents
local doc = ide:GetDocument(ed)
DisplayOutputLn(self:GetFileName(), k, doc and doc:GetFilePath() or "new document") end
or function(self, ...)
DisplayOutputLn(self:GetFileName(), k, ...) end
end
end
@@ -55,8 +65,7 @@ local events = {
DisplayOutputLn(self:GetFileName(), "onMenuEditor")
end
P.onMenuEditorTab = function(self, menu, notebook, event)
local index = event:GetSelection()
P.onMenuEditorTab = function(self, menu, notebook, event, index)
menu:Append(id, ">> Sample item; tab "..index)
menu:Enable(id, true)

View File

@@ -19,27 +19,19 @@ return {
end,
lexerstyleconvert = {
text = {wxstc.wxSTC_C_IDENTIFIER,
wxstc.wxSTC_C_VERBATIM,
wxstc.wxSTC_C_REGEX,
wxstc.wxSTC_C_REGEX,
wxstc.wxSTC_C_GLOBALCLASS,},
text = {wxstc.wxSTC_C_IDENTIFIER,},
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
comment = {wxstc.wxSTC_C_COMMENT,
wxstc.wxSTC_C_COMMENTLINE,
wxstc.wxSTC_C_COMMENTDOC,
wxstc.wxSTC_C_COMMENTLINEDOC,
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
wxstc.wxSTC_C_COMMENTDOC,},
stringtxt = {wxstc.wxSTC_C_STRING,
wxstc.wxSTC_C_CHARACTER,
wxstc.wxSTC_C_UUID,},
wxstc.wxSTC_C_VERBATIM,},
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
operator = {wxstc.wxSTC_C_OPERATOR,},
number = {wxstc.wxSTC_C_NUMBER,
wxstc.wxSTC_C_WORD},
number = {wxstc.wxSTC_C_NUMBER,},
keywords0 = {wxstc.wxSTC_C_WORD,},
keywords1 = {wxstc.wxSTC_C_WORD2,},

View File

@@ -43,6 +43,18 @@ return {
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
float16_t f16vec2 f16vec3 f16vec4
float32_t f32vec2 f32vec3 f32vec4
float64_t f64vec2 f64vec3 f64vec4
int8_t i8vec2 i8vec3 i8vec4
int8_t i8vec2 i8vec3 i8vec4
int16_t i16vec2 i16vec3 i16vec4
int32_t i32vec2 i32vec3 i32vec4
int64_t i64vec2 i64vec3 i64vec4
uint8_t u8vec2 u8vec3 u8vec4
uint16_t u16vec2 u16vec3 u16vec4
uint32_t u32vec2 u32vec3 u32vec4
uint64_t u64vec2 u64vec3 u64vec4
struct typedef void
usampler1D usampler2D usampler3D usampler2DRect usamplerCube isampler1DArray usampler2DARRAY usamplerCubeArray usampler2DMS usampler2DMSArray
isampler1D isampler2D isampler3D isampler2DRect isamplerCube isampler1DArray isampler2DARRAY isamplerCubeArray isampler2DMS isampler2DMSArray
@@ -51,10 +63,10 @@ return {
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
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
invocations offset align xfb_offset xfb_buffer
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
@@ -70,6 +82,7 @@ return {
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
gl_BaseVertexARB gl_BaseInstanceARB gl_DrawIDARB
coherent volatile restrict readonly writeonly
image1D image2D image3D image2DRect imageCube imageBuffer image1DArray image2DArray imageCubeArray image2DMS image2DMSArray
@@ -88,6 +101,10 @@ return {
packUnorm2x16 packUnorm4x8 packSnorm4x8
unpackUnorm2x16 unpackUnorm4x8 unpackSnorm4x8
packDouble2x32 unpackDouble2x32 packHalf2x16 unpackHalf2x16
packInt2x32 packUint2x32 unpackInt2x32 unpackUint2x32
packFloat2x16 unpackFloat2x16 doubleBitsToInt64
doubleBitsToUint64 int64BitsToDouble uint64BitsToDouble
length distance dot cross normalize ftransform faceforward
reflect refract
matrixCompMult outerProduct transpose determinant inverse
@@ -140,6 +157,8 @@ return {
atomicCounterIncrement atomicCounterDecrement atomicCounter
atomicMin atomicMax atomicAdd atomicAnd atomicOr atomicXor atomicExchange atomicCompSwap
anyInvocationARB allInvocationsARB allInvocationsEqualARB
x y z w
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy

95
spec/hlsl.lua Normal file
View File

@@ -0,0 +1,95 @@
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
---------------------------------------------------------
return {
exts = {"hlsl",},
lexer = wxstc.wxSTC_LEX_CPP,
apitype = "hlsl",
sep = "%.",
linecomment = "//",
isfndef = function(str)
local l
local s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+%s*%(.+%))")
if (not s) then
s,e,cap = string.find(str,"^%s*([A-Za-z0-9_]+%s+[A-Za-z0-9_]+)%s*%(")
end
if (cap and (string.find(cap,"^return") or string.find(cap,"else"))) then return end
return s,e,cap,l
end,
lexerstyleconvert = {
text = {wxstc.wxSTC_C_IDENTIFIER,},
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
comment = {wxstc.wxSTC_C_COMMENT,
wxstc.wxSTC_C_COMMENTLINE,
wxstc.wxSTC_C_COMMENTDOC,},
stringtxt = {wxstc.wxSTC_C_STRING,
wxstc.wxSTC_C_CHARACTER,
wxstc.wxSTC_C_VERBATIM,},
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
operator = {wxstc.wxSTC_C_OPERATOR,},
number = {wxstc.wxSTC_C_NUMBER,},
keywords0 = {wxstc.wxSTC_C_WORD,},
keywords1 = {wxstc.wxSTC_C_WORD2,},
},
keywords = {
[[break continue if else switch return for while do typedef namespace true false compile
const void struct static extern register volatile inline target nointerpolation shared uniform row_major column_major snorm unorm
bool bool1 bool2 bool3 bool4 int int1 int2 int3 int4 uint uint1 uint2 uint3 uint4 half half1 half2 half3 half4 float float1 float2 float3 float4 double double1 double2 double3 double4
matrix bool1x1 bool1x2 bool1x3 bool1x4 bool2x1 bool2x2 bool2x3 bool2x4 bool3x1 bool3x2 bool3x3 bool3x4 bool4x1 bool4x2 bool4x3 bool4x4
int1x1 int1x2 int1x3 int1x4 int2x1 int2x2 int2x3 int2x4 int3x1 int3x2 int3x3 int3x4 int4x1 int4x2 int4x3 int4x4 uint1x1 uint1x2 uint1x3 uint1x4
uint2x1 uint2x2 uint2x3 uint2x4 uint3x1 uint3x2 uint3x3 uint3x4 uint4x1 uint4x2 uint4x3 uint4x4 half1x1 half1x2 half1x3 half1x4 half2x1 half2x2
half2x3 half2x4 half3x1 half3x2 half3x3 half3x4 half4x1 half4x2 half4x3 half4x4 float1x1 float1x2 float1x3 float1x4 float2x1 float2x2 float2x3
float2x4 float3x1 float3x2 float3x3 float3x4 float4x1 float4x2 float4x3 float4x4 double1x1 double1x2 double1x3 double1x4 double2x1 double2x2
double2x3 double2x4 double3x1 double3x2 double3x3 double3x4 double4x1 double4x2 double4x3 double4x4 cbuffer groupshared SamplerState
in out inout vector matrix interface class point triangle line lineadj triangleadj
Texture Texture1D Texture1DArray Texture2D Texture2DArray Texture2DMS Texture2DMSArray Texture3D TextureCube RWTexture1D RWTexture1DArray RWTexture2D RWTexture2DArray RWTexture3D
Buffer StructuredBuffer AppendStructuredBuffer ConsumeStructuredBuffer RWBuffer RWStructuredBuffer ByteAddressBuffer RWByteAddressBuffer PointStream TriangleStream LineStream InputPatch OutputPatch
]],
[[unroll loop flatten branch allow_uav_condition earlydepthstencil domain instance maxtessfactor outputcontrolpoints outputtopology partitioning patchconstantfunc numthreads maxvertexcount precise
SV_DispatchThreadID SV_DomainLocation SV_GroupID SV_GroupIndex SV_GroupThreadID SV_GSInstanceID SV_InsideTessFactor SV_OutputControlPointID SV_Coverage SV_Depth SV_Position SV_IsFrontFace SV_RenderTargetArrayIndex SV_SampleIndex SV_ViewportArrayIndex SV_InstanceID SV_PrimitiveID SV_VertexID
SV_ClipDistance SV_CullDistance SV_Target
abs acos all AllMemoryBarrier AllMemoryBarrierWithGroupSync any asdouble asfloat asin asint asuint atan atan2 ceil clamp clip cos cosh countbits cross ddx ddx_coarse ddx_fine ddy ddy_coards ddy_fine degrees determinant DeviceMemoryBarrier DeviceMemoryBarrierWithGroupSync distance dot dst EvaluateAttributeAtCentroid EvaluateAttributeAtSample EvaluateAttributeSnapped exp exp2 f16tof32 f32tof16 faceforward firstbithigh firstbitlow floor fmod frac frexp fwidth GetRenderTargetSampleCount GetRenderTargetSamplePosition GroupMemoryBarrier GroupMemoryBarrierWithGroupSync InterlockedAdd InterlockedAnd InterlockedCompareExchange InterlockedExchange InterlockedMax InterlockedMin IntterlockedOr InterlockedXor isfinite isinf isnan ldexp length lerp lit log log10 log2 mad max min modf mul normalize pow Process2DQuadTessFactorsAvg Process2DQuadTessFactorsMax Process2DQuadTessFactorsMin ProcessIsolineTessFactors ProcessQuadTessFactorsAvg ProcessQuadTessFactorsMax ProcessQuadTessFactorsMin ProcessTriTessFactorsAvg ProcessTriTessFactorsMax ProcessTriTessFactorsMin radians rcp reflect refract reversebits round rsqrt saturate sign sin sincos sinh smoothstep sqrt step tan tanh transpose trunc
Append RestartStrip CalculateLevelOfDetail CalculateLevelOfDetailUnclamped GetDimensions GetSamplePosition Load Sample SampleBias SampleCmp SampleCmpLevelZero SampleGrad SampleLevel Load2 Load3 Load4 Consume Store Store2 Store3 Store4 DecrementCounter IncrementCounter mips Gather GatherRed GatherGreen GatherBlue GatherAlpha GatherCmp GatherCmpRed GatherCmpGreen GatherCmpBlue GatherCmpAlpha
x y z w
xxxx xxxy xxxz xxxw xxyx xxyy xxyz xxyw xxzx xxzy
xxzz xxzw xxwx xxwy xxwz xxww xyxx xyxy xyxz xyxw
xyyx xyyy xyyz xyyw xyzx xyzy xyzz xyzw xywx xywy
xywz xyww xzxx xzxy xzxz xzxw xzyx xzyy xzyz xzyw
xzzx xzzy xzzz xzzw xzwx xzwy xzwz xzww xwxx xwxy
xwxz xwxw xwyx xwyy xwyz xwyw xwzx xwzy xwzz xwzw
xwwx xwwy xwwz xwww yxxx yxxy yxxz yxxw yxyx yxyy
yxyz yxyw yxzx yxzy yxzz yxzw yxwx yxwy yxwz yxww
yyxx yyxy yyxz yyxw yyyx yyyy yyyz yyyw yyzx yyzy
yyzz yyzw yywx yywy yywz yyww yzxx yzxy yzxz yzxw
yzyx yzyy yzyz yzyw yzzx yzzy yzzz yzzw yzwx yzwy
yzwz yzww ywxx ywxy ywxz ywxw ywyx ywyy ywyz ywyw
ywzx ywzy ywzz ywzw ywwx ywwy ywwz ywww zxxx zxxy
zxxz zxxw zxyx zxyy zxyz zxyw zxzx zxzy zxzz zxzw
zxwx zxwy zxwz zxww zyxx zyxy zyxz zyxw zyyx zyyy
zyyz zyyw zyzx zyzy zyzz zyzw zywx zywy zywz zyww
zzxx zzxy zzxz zzxw zzyx zzyy zzyz zzyw zzzx zzzy
zzzz zzzw zzwx zzwy zzwz zzww zwxx zwxy zwxz zwxw
zwyx zwyy zwyz zwyw zwzx zwzy zwzz zwzw zwwx zwwy
zwwz zwww wxxx wxxy wxxz wxxw wxyx wxyy wxyz wxyw
wxzx wxzy wxzz wxzw wxwx wxwy wxwz wxww wyxx wyxy
wyxz wyxw wyyx wyyy wyyz wyyw wyzx wyzy wyzz wyzw
wywx wywy wywz wyww wzxx wzxy wzxz wzxw wzyx wzyy
wzyz wzyw wzzx wzzy wzzz wzzw wzwx wzwy wzwz wzww
wwxx wwxy wwxz wwxw wwyx wwyy wwyz wwyw wwzx wwzy
wwzz wwzw wwwx wwwy wwwz wwww xy xz yz xyz
xw yw xyw zw xzw yzw xyzw
]],
},
}

View File

@@ -49,13 +49,15 @@ return {
return match and 1 or 0, match and term and 1 or 0
end,
isincindent = function(str)
local term = str:match("^%s*(%w+)[^%w]*")
local term = str:match("^%s*(%w+)%W*")
term = term and incindent[term] and 1 or 0
str = str:gsub("'.-'",""):gsub('".-"','')
local _, opened = str:gsub("([%{%(])", "%1")
local _, closed = str:gsub("([%}%)])", "%1")
local func = (isfndef(str) or str:match("[^%w]+function%s*%(")) and 1 or 0
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
local anon = str:match("%W+function%s*%(.+%Wend%W")
local ended = (term + func > 0) and (str:match("%W+end%s*$") or anon) and 1 or 0
return opened - closed + func + term - ended
end,
@@ -87,8 +89,8 @@ return {
end,
typeassigns = function(editor)
local line = editor:GetCurrentLine()
line = line-1
local line = editor:GetCurrentLine()-1
local maxlines = 48 -- scan up to this many lines back
local scopestart = {"if","do","while","function", "local%s+function", "for", "else", "elseif"}
local scopeend = {"end"}
@@ -99,7 +101,7 @@ return {
-- iterate up until a line starts with scopestart
-- always ignore lines whose first symbol is styled as comment
local endline = line
while (line >= 0) do
while (line > math.max(endline-maxlines, 0)) do
local ls = editor:PositionFromLine(line)
local s = bit.band(editor:GetStyleAt(ls),31)
@@ -108,7 +110,7 @@ return {
local leftscope
for i,v in ipairs(scopestart) do
if (tx:match("^"..v)) then
if (tx:match("^%s*"..v)) then
leftscope = true
end
end
@@ -151,6 +153,22 @@ return {
typ = nil
end
typ = typ and typ:gsub("%s","")
typ = typ and typ:gsub(".+", function(s)
return (s:find("^'[^']*'$")
or s:find('^"[^"]*"$')
or s:find('^%[=*%[.*%]=*%]$')) and 'string' or s
end)
-- filter out everything that is not needed
if typ
and (not typ:match('^'..identifier..'$') -- not an identifier
or typ:match('^%d') -- not an identifier
or editor.api.tip.keys[typ] -- or a keyword
or editor.api.tip.staticnames[typ] -- or a static name
) then
typ = nil
end
if (var and typ) then
class,func = typ:match(varname.."[%.:]"..varname)
if (assigns[typ]) then

View File

@@ -100,17 +100,21 @@ config = {
calltipdelay = nil, -- delay to show calltip (in ms)
autoactivate = false, -- auto-activate/open files during debugging
smartindent = false, -- use smart indentation if spec allows
fold = true, -- enable code folding
foldcompact = true, -- use compact fold that includes empty lines
checkeol = true, -- check for eol encoding on loaded files and use it
-- also report mixed eol encodings
defaulteol = nil, -- default line-endings for new files; valid values are
-- wxstc.wxSTC_EOL_CRLF, wxstc.wxSTC_EOL_LF and nil (OS default)
nomousezoom = nil, -- disable zooming using mouse wheel
autoreload = nil, -- trigger auto-reload when file is updated
saveallonrun = nil, -- save all modified files before Run/Debug
},
default = {
name = 'untitled',
fullname = 'untitled.lua',
interpreter = 'luadeb',
},
debugger = {
@@ -119,6 +123,7 @@ config = {
port = nil, -- port number to use
runonstart = nil, -- if debugger should run immediately after starting
-- default values are different for different interpreters
redirect = nil, -- "d", "c", or "r" values for default, copy, or redirect
}
outputshell = { -- output and shell settings

View File

@@ -36,54 +36,70 @@ local apis = {
lua = newAPI(),
}
function GetApi(apitype)
return apis[apitype] or apis["none"]
end
function GetApi(apitype) return apis[apitype] or apis.none end
----------
-- API loading
local function addAPI(apifile,only,subapis,known) -- relative to API directory
local ftype, fname = apifile:match("api[/\\]([^/\\]+)[/\\](.*)%.")
if not ftype or not fname then
DisplayOutputLn(TR("The API file must be located in a subdirectory of the API directory."))
return
end
if ((only and ftype ~= only) or (known and not known[ftype])) then
return
end
if (subapis and not subapis[fname]) then return end
local fn,err = loadfile(apifile)
if err then
DisplayOutputLn(TR("Error while loading API file: %s"):format(err))
return
end
local env = apis[ftype] or newAPI()
apis[ftype] = env
env = env.ac.childs
local suc,res = pcall(function()return fn(env) end)
if (not suc) then
DisplayOutputLn(TR("Error while processing API file: %s"):format(res))
elseif (res) then
local function gennames(tab,prefix)
for i,v in pairs(tab) do
v.classname = (prefix and (prefix..".") or "")..i
if(v.childs) then
gennames(v.childs,v.classname)
end
end
end
gennames(res)
for i,v in pairs(res) do
env[i] = v
local function gennames(tab, prefix)
for i,v in pairs(tab) do
v.classname = (prefix and (prefix..".") or "")..i
if (v.childs) then
gennames(v.childs,v.classname)
end
end
end
local function loadallAPIs (only,subapis,known)
local function addAPI(ftype, fname) -- relative to API directory
local env = apis[ftype] or newAPI()
local res
local api = ide.apis[ftype][fname]
if type(api) == 'table' then
res = api
else
local fn, err = loadfile(api)
if err then
DisplayOutputLn(TR("Error while loading API file: %s"):format(err))
return
end
local suc
suc, res = pcall(function() return fn(env.ac.childs) end)
if (not suc) then
DisplayOutputLn(TR("Error while processing API file: %s"):format(res))
return
end
-- cache the result
ide.apis[ftype][fname] = res
end
apis[ftype] = env
gennames(res)
for i,v in pairs(res) do env.ac.childs[i] = v end
end
local function loadallAPIs(only, subapis, known)
for ftype, v in pairs(only and {[only] = ide.apis[only]} or ide.apis) do
if (not known or known[ftype]) then
for fname in pairs(v) do
if (not subapis or subapis[fname]) then addAPI(ftype, fname) end
end
end
end
end
local function scanAPIs()
for _, file in ipairs(FileSysGetRecursive("api", true, "*.lua")) do
if not file:match(string_Pathsep.."$") then addAPI(file,only,subapis,known) end
if not IsDirectory(file) then
local ftype, fname = file:match("api[/\\]([^/\\]+)[/\\](.*)%.")
if not ftype or not fname then
DisplayOutputLn(TR("The API file must be located in a subdirectory of the API directory."))
return
end
ide.apis[ftype] = ide.apis[ftype] or {}
ide.apis[ftype][fname] = file
end
end
end
@@ -219,9 +235,9 @@ local function resolveAssign(editor,tx)
-- this can happen if it's a reference to a value with a known type
classname = classname or assigns[c..w]
if (s ~= "" and old ~= classname) then
c = classname..s
-- continue checking unless this can lead to recursive substitution
change = not classname:find("^"..w)
change = not classname:find("^"..w) and not classname:find("^"..c..w)
c = classname..s
else
c = c..w..s
end
@@ -243,15 +259,21 @@ end
function GetTipInfo(editor, content, short, fullmatch)
if not content then return end
UpdateAssignCache(editor)
-- try to resolve the class
content = content:gsub("%b[]",".0")
local tab, rest = resolveAssign(editor, content)
local caller = content:match("([%w_]+)%(?%s*$")
local class = caller and content:match("([%w_]+)[%.:]"..caller.."%(?%s*$") or ""
local class = (tab and tab.classname
or caller and content:match("([%w_]+)[%.:]"..caller.."%(?%s*$") or "")
local tip = editor.api.tip
local classtab = short and tip.shortfinfoclass or tip.finfoclass
local funcstab = short and tip.shortfinfo or tip.finfo
UpdateAssignCache(editor)
if (editor.assignscache and not (class and classtab[class])) then
local assigns = editor.assignscache.assigns
class = assigns and assigns[class] or class
@@ -293,6 +315,7 @@ do
-- by defaul load every known api except lua
known.lua = false
scanAPIs()
loadallAPIs(nil,nil,known)
generateAPIInfo()
end
@@ -353,11 +376,8 @@ function DynamicWordsReset ()
end
local function getEditorLines(editor,line,numlines)
local tx = ""
for i=0,numlines do
tx = tx..editor:GetLine(line + i)
end
return tx
return editor:GetTextRange(
editor:PositionFromLine(line),editor:PositionFromLine(line+numlines+1))
end
function DynamicWordsAdd(ev,editor,content,line,numlines)
@@ -406,10 +426,12 @@ local function getAutoCompApiList(childs,fragment,method)
if not wlist then
wlist = " "
for i,v in pairs(childs) do
-- in some cases (tip.finfo), v may be a string; check for that first.
-- if a:b typed, then value (type == "value") not allowed
-- if a.b typed, then method (type == "method") not allowed
if ((method and v.type ~= "value") or (not method and v.type ~= "method"))
and v.type then
if type(v) ~= 'table' or (v.type and
((method and v.type ~= "value")
or (not method and v.type ~= "method"))) then
wlist = wlist..i.." "
end
end
@@ -439,10 +461,12 @@ local function getAutoCompApiList(childs,fragment,method)
local sub = strategy == 1
for key,v in pairs(childs) do
-- in some cases (tip.finfo), v may be a string; check for that first.
-- if a:b typed, then value (type == "value") not allowed
-- if a.b typed, then method (type == "method") not allowed
if ((method and v.type ~= "value") or (not method and v.type ~= "method"))
and v.type then
if type(v) ~= 'table' or (v.type and
((method and v.type ~= "value")
or (not method and v.type ~= "method"))) then
local used = {}
--
local kl = key:lower()
@@ -498,10 +522,9 @@ function CreateAutoCompList(editor,key)
if not (progress) then return end
if (tab == ac) then
local _, krest = rest:match("([%w_]+)["..sep.."]([%w_]+)%s*$")
local _, krest = rest:match("([%w_]+)["..sep.."]([%w_]*)%s*$")
if (krest) then
if (#krest < 3) then return end
tab = tip.finfo
tab = #krest >= (ide.config.acandtip.startat or 2) and tip.finfo or {}
rest = krest:gsub("[^%w_]","")
else
rest = rest:gsub("[^%w_]","")
@@ -516,7 +539,7 @@ function CreateAutoCompList(editor,key)
-- only if api search couldnt descend
-- ie we couldnt find matching sub items
local dw = ""
if (tab == ac and last and #last >= (ide.config.acandtip.startat or 2)) then
if (last and #last >= (ide.config.acandtip.startat or 2)) then
last = last:lower()
if dynamicwords[last] then
local list = dynamicwords[last]
@@ -541,21 +564,26 @@ function CreateAutoCompList(editor,key)
-- list from api
local apilist = getAutoCompApiList(tab.childs or tab,rest,method)
-- handle inheritance; add matches from the parent class/lib
local seen = {tab = true}
while tab.inherits do
local base = tab.inherits
tab = ac
-- map "a.b.c" to class hierarchy (a.b.c)
for class in base:gmatch("[%w_]+") do tab = tab.childs[class] end
if not tab or seen[tab] then break end
seen[tab] = true
local function addInheritance(tab, apilist, seen)
if not tab.inherits then return end
for base in tab.inherits:gmatch("[%w_"..sep.."]+") do
local tab = ac
-- map "a.b.c" to class hierarchy (a.b.c)
for class in base:gmatch("[%w_]+") do tab = tab.childs[class] end
for _,v in pairs(getAutoCompApiList(tab.childs,rest,method)) do
table.insert(apilist, v)
if tab and not seen[tab] then
seen[tab] = true
for _,v in pairs(getAutoCompApiList(tab.childs,rest,method)) do
table.insert(apilist, v)
end
addInheritance(tab, apilist, seen)
end
end
end
-- handle (multiple) inheritance; add matches from the parent class/lib
addInheritance(tab, apilist, {[tab] = true})
local compstr = ""
if apilist then
if (#rest > 0) then
@@ -610,5 +638,5 @@ function CreateAutoCompList(editor,key)
-- concat final, list complete first
local li = (compstr .. dw)
return li ~= "" and (#li > 1024 and li:sub(1,1024).."..." or li)
return li ~= "" and (#li > 1024 and li:sub(1,1024).."..." or li) or nil
end

View File

@@ -11,12 +11,15 @@ local CURRENT_LINE_MARKER = StylesGetMarker("currentline")
local CURRENT_LINE_MARKER_VALUE = 2^CURRENT_LINE_MARKER
local BREAKPOINT_MARKER = StylesGetMarker("breakpoint")
function NewFile(event)
function NewFile(filename)
filename = filename or ide.config.default.fullname
local editor = CreateEditor()
SetupKeywords(editor, "lua")
local doc = AddEditor(editor, ide.config.default.fullname)
if doc then PackageEventHandle("onEditorNew", editor) end
if doc then SetEditorSelection(doc.index) end
SetupKeywords(editor, GetFileExt(filename))
local doc = AddEditor(editor, filename)
if doc then
PackageEventHandle("onEditorNew", editor)
SetEditorSelection(doc.index)
end
return editor
end
@@ -71,11 +74,12 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
editor:SetText(file_text or "")
-- check the editor as it can be empty if the file has malformed UTF8;
-- skip binary files as they may have any sequences; can't show them anyway.
-- skip binary files with unknown extensions as they may have any sequences;
-- can't show them anyway.
if file_text and #file_text > 0 and #(editor:GetText()) == 0
and not isBinary(file_text) then
and (editor.spec ~= ide.specs.none or not isBinary(file_text)) then
local replacement, invalid = "\022"
file_text, invalid = fixUTF8(file_text, replacement)
file_text, invalid = FixUTF8(file_text, replacement)
if #invalid > 0 then
editor:AppendText(file_text)
local lastline = nil
@@ -189,6 +193,11 @@ function SaveFile(editor, filePath)
st = GetConfigIOFilter("output")(filePath,st)
end
local file = wx.wxFileName(filePath)
if not file:FileExists() then
file:Mkdir(tonumber(755,8), wx.wxPATH_MKDIR_FULL)
end
local ok, err = FileWrite(filePath, st)
if ok then
editor:SetSavePoint()
@@ -199,7 +208,7 @@ function SaveFile(editor, filePath)
SetDocumentModified(id, false)
SetAutoRecoveryMark()
PackageEventHandle("onEditorPostSave", editor)
PackageEventHandle("onEditorSave", editor)
return true
else
@@ -215,11 +224,9 @@ end
function SaveFileAs(editor)
local id = editor:GetId()
local saved = false
local filePath = openDocuments[id].filePath
if (not filePath) then
filePath = FileTreeGetDir()
filePath = (filePath or "")..ide.config.default.name
end
local filePath = (openDocuments[id].filePath
or ((FileTreeGetDir() or "")
..(openDocuments[id].fileName or ide.config.default.name)))
local fn = wx.wxFileName(filePath)
fn:Normalize() -- want absolute path for dialog
@@ -241,16 +248,37 @@ function SaveFileAs(editor)
if fileDialog:ShowModal() == wx.wxID_OK then
local filePath = fileDialog:GetPath()
-- first check if there is another tab with the same name and close it
local existing
local fileName = wx.wxFileName(filePath)
for _, document in pairs(ide.openDocuments) do
if document.filePath and fileName:SameAs(wx.wxFileName(document.filePath)) then
existing = document.index
break
end
end
if SaveFile(editor, filePath) then
SetEditorSelection() -- update title of the editor
FileTreeMarkSelected(filePath)
if ext ~= GetFileExt(filePath) then
-- new extension, so setup new keywords and re-apply indicators
editor:ClearDocumentStyle() -- remove styles from the document
SetupKeywords(editor, GetFileExt(filePath))
IndicateAll(editor)
MarkupStyle(editor)
end
saved = true
if existing then
-- save the current selection as it may change after closing
local current = notebook:GetSelection()
ClosePage(existing)
-- restore the selection if it changed
if current ~= notebook:GetSelection() then
notebook:SetSelection(current)
end
end
end
end
@@ -258,12 +286,13 @@ function SaveFileAs(editor)
return saved
end
function SaveAll()
function SaveAll(quiet)
for id, document in pairs(openDocuments) do
local editor = document.editor
local filePath = document.filePath
if document.isModified or not document.filePath then
if (document.isModified or not document.filePath) -- need to save
and (document.filePath or not quiet) then -- have path or can ask user
SaveFile(editor, filePath) -- will call SaveFileAs if necessary
end
end
@@ -696,11 +725,14 @@ function StoreRestoreProjectTabs(curdir, 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
-- check if the filename is in the same folder
if dpath:find(lowcurdir, 1, true) == 1
and dpath:find("^[\\/]", #lowcurdir+1) 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
if not dpath:find(lownewdir, 1, true)
or not dpath:find("^[\\/]", #lownewdir+1) then
table.insert(closdocs, document)
end
elseif document.id == current then restore = true end
@@ -764,6 +796,8 @@ local function closeWindow(event)
ShowFullScreen(false)
PackageEventHandle("onAppClose")
SettingsSaveAll()
ide.settings:Flush()
@@ -792,6 +826,15 @@ frame:Connect(wx.wxEVT_CLOSE_WINDOW, closeWindow)
frame:Connect(wx.wxEVT_TIMER, saveAutoRecovery)
ide.editorApp:Connect(wx.wxEVT_ACTIVATE_APP,
function(event)
if not ide.exitingProgram then
local event = event:GetActive() and "onAppFocusSet" or "onAppFocusLost"
PackageEventHandle(event, ide.editorApp)
end
event:Skip()
end)
if ide.config.autorecoverinactivity then
ide.session.timer = wx.wxTimer(frame)
-- check at least 5s to be never more than 5s off

View File

@@ -17,11 +17,8 @@ debugger.watchCtrl = nil -- the watch ctrl that shows watch information
debugger.stackCtrl = nil -- the stack ctrl that shows stack information
debugger.toggleview = { stackpanel = false, watchpanel = false }
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 host and #host > 0 and addr:Hostname(host) then return host end
end
return "localhost" -- last resort; no known good hostname
local hostname = socket.dns.gethostname()
return hostname and socket.dns.toip(hostname) and hostname or "localhost"
end)()
local notebook = ide.frame.notebook
@@ -33,12 +30,31 @@ local BREAKPOINT_MARKER_VALUE = 2^BREAKPOINT_MARKER
local activate = {CHECKONLY = 1, NOREPORT = 2}
local function serialize(value, options) return mobdebug.line(value, options) end
local stackmaxlength = ide.config.debugger.stackmaxlength or 400
local stackmaxnum = ide.config.debugger.stackmaxnum or 400
local stackmaxlevel = ide.config.debugger.stackmaxlevel or 3
local params = {comment = false, nocode = true, maxlevel = stackmaxlevel, maxnum = stackmaxnum}
function fixUTF8(...)
local t = {...}
-- convert to escaped decimal code as these can only appear in strings
local function fix(s) return '\\'..string.byte(s) end
for i = 1, #t do
local text = t[i]:sub(1, stackmaxlength)..(#t[i] > stackmaxlength and '...' or '')
t[i] = FixUTF8(text, fix)
end
return (table.unpack or unpack)(t)
end
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
local function updateWatchesSync(num)
local watchCtrl = debugger.watchCtrl
if watchCtrl and debugger.server and not debugger.running
and ide.frame.uimgr:GetPane("watchpanel"):IsShown()
local pane = ide.frame.uimgr:GetPane("watchpanel")
local shown = watchCtrl and (pane:IsOk() and pane:IsShown() or not pane:IsOk() and watchCtrl:IsShown())
if shown and debugger.server and not debugger.running
and not debugger.scratchpad and not (debugger.options or {}).noeval then
local bgcl = watchCtrl:GetBackgroundColour()
local hicl = wx.wxColour(math.floor(bgcl:Red()*.9),
@@ -83,8 +99,9 @@ end
local function updateStackSync()
local stackCtrl = debugger.stackCtrl
if stackCtrl and debugger.server and not debugger.running
and ide.frame.uimgr:GetPane("stackpanel"):IsShown()
local pane = ide.frame.uimgr:GetPane("stackpanel")
local shown = stackCtrl and (pane:IsOk() and pane:IsShown() or not pane:IsOk() and stackCtrl:IsShown())
if shown and debugger.server and not debugger.running
and not debugger.scratchpad then
local stack, _, err = debugger.stack()
if not stack or #stack == 0 then
@@ -96,7 +113,7 @@ local function updateStackSync()
end
stackCtrl:Freeze()
stackCtrl:DeleteAllItems()
local params = {comment = false, nocode = true}
local root = stackCtrl:AddRoot("Stack")
stackItemValue = {} -- reset cache of items in the stack
callData = {} -- reset call cache
@@ -117,13 +134,13 @@ local function updateStackSync()
local text = func ..
(call[4] == -1 and '' or " at line "..call[4]) ..
(call[5] ~= "main" and call[5] ~= "Lua" and ''
or (call[3] > 0 and " (defined at "..call[2]..":"..call[3]..")"
or " (defined in "..call[2]..")"))
or (call[3] > 0 and " (defined at "..call[7]..":"..call[3]..")"
or " (defined in "..call[7]..")"))
-- create the new tree item for this level of the call stack
local callitem = stackCtrl:AppendItem(root, text, 0)
-- registed call data to added item
-- register call data to provide stack navigation
callData[callitem:GetValue()] = { call[2], call[4] }
-- add the local variables to the call stack item
@@ -133,9 +150,9 @@ local function updateStackSync()
-- comment can be not necessarily a string for tables with metatables
-- that provide its own __tostring method
local value, comment = val[1], tostring(val[2])
local value, comment = val[1], fixUTF8(tostring(val[2]))
local text = ("%s = %s%s"):
format(name, mobdebug.line(value, params),
format(name, fixUTF8(serialize(value, params)),
simpleType[type(value)] and "" or (" --[["..comment.."]]"))
local item = stackCtrl:AppendItem(callitem, text, 1)
if checkIfExpandable(value, item) then
@@ -145,9 +162,9 @@ local function updateStackSync()
-- add the upvalues for this call stack level to the tree item
for name,val in pairs(frame[3]) do
local value, comment = val[1], tostring(val[2])
local value, comment = val[1], fixUTF8(tostring(val[2]))
local text = ("%s = %s%s"):
format(name, mobdebug.line(value, params),
format(name, fixUTF8(serialize(value, params)),
simpleType[type(value)] and "" or (" --[["..comment.."]]"))
local item = stackCtrl:AppendItem(callitem, text, 2)
if checkIfExpandable(value, item) then
@@ -220,21 +237,6 @@ local function killClient()
end
end
local function loadsafe(data)
local f, res = loadstring(data)
if not f then return f, res end
local count = 0
debug.sethook(function ()
count = count + 1
if count >= 3 then error("cannot call functions") end
end, "c")
local ok, res = pcall(f)
count = 0
debug.sethook()
return ok, res
end
local function activateDocument(file, line, activatehow)
if not file then return end
@@ -244,11 +246,17 @@ local function activateDocument(file, line, activatehow)
-- (for example: 'mobdebug.lua').
local content
if not wx.wxFileName(file):FileExists() and file:find('^"') then
local ok, res = loadsafe("return "..file)
local ok, res = LoadSafe("return "..file)
if ok then content = res end
end
if not content and not wx.wxIsAbsolutePath(file) and debugger.basedir then
-- in some cases filename can be returned quoted if the chunk is loaded with
-- loadstring(chunk, "filename") instead of loadstring(chunk, "@filename")
if content then
-- if the returned content can be matched with a file, it's a file name
local fname = GetFullPathIfExists(debugger.basedir, content) or content
if wx.wxFileName(fname):FileExists() then file, content = fname, nil end
elseif not wx.wxIsAbsolutePath(file) and debugger.basedir then
file = debugger.basedir .. file
end
@@ -323,7 +331,7 @@ local function activateDocument(file, line, activatehow)
end
if not (activated or indebugger or debugger.loop or activatehow == activate.CHECKONLY)
and (ide.config.editor.autoactivate or content) then
and (ide.config.editor.autoactivate or content and activatehow == activate.NOREPORT) then
-- found file, but can't activate yet (because this part may be executed
-- in a different coroutine), so schedule pending activation.
if content or wx.wxFileName(file):FileExists() then
@@ -397,7 +405,7 @@ debugger.shell = function(expression, isstatement)
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,
serialize(func(), {nocode = true, comment = 0,
-- if '=' is used, then use multi-line serialized output
indent = forceexpression and ' ' or nil})
end
@@ -408,7 +416,7 @@ debugger.shell = function(expression, isstatement)
if #values == 0 and (forceexpression or not isstatement) then
values = {'nil'}
end
DisplayShell((table.unpack or unpack)(values))
DisplayShell(fixUTF8((table.unpack or unpack)(values)))
end
-- refresh Stack and Watch windows if executed a statement (and no err)
@@ -440,7 +448,11 @@ debugger.listen = function()
end
copas.setErrorHandler(function(error)
DisplayOutputLn(TR("Can't start debugging session due to internal error '%s'."):format(error))
-- ignore errors that happen because debugging session is
-- terminated during handshake (server == nil in this case).
if debugger.server then
DisplayOutputLn(TR("Can't start debugging session due to internal error '%s'."):format(error))
end
debugger.terminate()
end)
@@ -484,11 +496,10 @@ debugger.listen = function()
reSetBreakpoints()
if options.redirect then
debugger.handle("output stdout " .. options.redirect, nil,
local redirect = ide.config.debugger.redirect or options.redirect
if redirect then
debugger.handle("output stdout " .. redirect, nil,
{ handler = function(m)
if not debugger.server then return end
-- if it's an error returned, then handle the error
if m and m:find("stack traceback:", 1, true) then
-- this is an error message sent remotely
@@ -501,7 +512,13 @@ debugger.listen = function()
end
if ide.config.debugger.outputfilter then
m = ide.config.debugger.outputfilter(m)
local ok, res = pcall(ide.config.debugger.outputfilter, m)
if ok then
m = res
else
DisplayOutputLn("Output filter failed: "..res)
return
end
elseif m then
local max = 240
m = #m < max+4 and m or m:sub(1,max) .. "...\n"
@@ -554,8 +571,11 @@ debugger.listen = function()
end
-- if not found and the files doesn't exist, it may be
-- a remote call; try to map it to the project folder
if not activated and not wx.wxFileName(file):FileExists() then
-- a remote call; try to map it to the project folder.
-- also check for absolute path as it may need to be remapped
-- when autoactivation is disabled.
if not activated and (not wx.wxFileName(file):FileExists()
or wx.wxIsAbsolutePath(file)) then
-- file is /foo/bar/my.lua; basedir is d:\local\path\
-- check for d:\local\path\my.lua, d:\local\path\bar\my.lua, ...
-- wxwidgets on Windows handles \\ and / as separators, but on OSX
@@ -723,25 +743,35 @@ end
debugger.loadstring = function(file, string)
return debugger.handle("loadstring '" .. file .. "' " .. string)
end
debugger.update = function()
copas.step(0)
-- if there are any pending activations
if debugger.activate then
local file, line, content = (table.unpack or unpack)(debugger.activate)
if content then
local editor = NewFile()
editor:SetText(content)
if not ide.config.debugger.allowediting
and not (debugger.options or {}).allowediting then
editor:SetReadOnly(true)
end
activateDocument(file, line)
elseif LoadFile(file) then
activateDocument(file, line)
do
local nextupdatedelta = 0.250
local nextupdate = TimeGet() + nextupdatedelta
debugger.update = function()
if debugger.server or debugger.listening and TimeGet() > nextupdate then
copas.step(0)
nextupdate = TimeGet() + nextupdatedelta
end
-- if there are any pending activations
if debugger.activate then
local file, line, content = (table.unpack or unpack)(debugger.activate)
if content then
local editor = NewFile()
editor:SetText(content)
if not ide.config.debugger.allowediting
and not (debugger.options or {}).allowediting then
editor:SetReadOnly(true)
end
activateDocument(file, line)
elseif LoadFile(file) then
activateDocument(file, line)
end
debugger.activate = nil
end
debugger.activate = nil
end
end
debugger.terminate = function()
if debugger.server then
if debugger.pid then -- if there is PID, try local kill
@@ -816,6 +846,33 @@ do
end
local width, height = 360, 200
function debuggerAddWindow(ctrl, panel, name)
local notebook = wxaui.wxAuiNotebook(ide.frame, wx.wxID_ANY,
wx.wxDefaultPosition, wx.wxDefaultSize,
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
notebook:AddPage(ctrl, TR(name), true)
local mgr = ide.frame.uimgr
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
Name(panel):Float():
MinSize(width/2,height/2):
BestSize(width,height):FloatingSize(width,height):
PinButton(true):Hide())
mgr.defaultPerspective = mgr:SavePerspective() -- resave default perspective
return notebook
end
function DebuggerAddStackWindow()
return debuggerAddWindow(debugger.stackCtrl, "stackpanel", "Stack")
end
function DebuggerAddWatchWindow()
return debuggerAddWindow(debugger.watchCtrl, "watchpanel", "Watch")
end
function debuggerCreateStackWindow()
local stackCtrl = wx.wxTreeCtrl(ide.frame, wx.wxID_ANY,
wx.wxDefaultPosition, wx.wxSize(width, height),
@@ -825,7 +882,7 @@ function debuggerCreateStackWindow()
stackCtrl:SetImageList(imglist)
stackCtrl:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
stackCtrl:Connect(wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
function (event)
local item_id = event:GetItem()
local count = stackCtrl:GetChildrenCount(item_id, false)
@@ -834,7 +891,7 @@ function debuggerCreateStackWindow()
local image = stackCtrl:GetItemImage(item_id)
local num = 1
for name,value in pairs(stackItemValue[item_id:GetValue()]) do
local strval = mobdebug.line(value, {comment = false, nocode = true})
local strval = fixUTF8(serialize(value, params))
local text = type(name) == "number"
and (num == name and strval or ("[%s] = %s"):format(name, strval))
or ("%s = %s"):format(tostring(name), strval)
@@ -843,6 +900,7 @@ function debuggerCreateStackWindow()
stackCtrl:SetItemHasChildren(item, true)
end
num = num + 1
if num > stackmaxnum then break end
end
return true
end)
@@ -865,19 +923,12 @@ function debuggerCreateStackWindow()
end
end)
local notebook = wxaui.wxAuiNotebook(ide.frame, wx.wxID_ANY,
wx.wxDefaultPosition, wx.wxDefaultSize,
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
notebook:AddPage(stackCtrl, TR("Stack"), true)
local mgr = ide.frame.uimgr
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
Name("stackpanel"):Float():
MinSize(width/2,height/2):
BestSize(width,height):FloatingSize(width,height):
PinButton(true):Hide())
mgr.defaultPerspective = mgr:SavePerspective() -- resave default perspective
local layout = ide:GetSetting("/view", "uimgrlayout")
if layout and not layout:find("stackpanel") then
ide.frame.bottomnotebook:AddPage(stackCtrl, TR("Stack"), true)
return
end
DebuggerAddStackWindow()
end
local function debuggerCreateWatchWindow()
@@ -933,9 +984,7 @@ local function debuggerCreateWatchWindow()
end
watchCtrl:Connect(wx.wxEVT_CONTEXT_MENU,
function (event)
watchCtrl:PopupMenu(watchMenu)
end)
function (event) watchCtrl:PopupMenu(watchMenu) end)
watchCtrl:Connect(wx.wxEVT_KEY_DOWN,
function (event)
@@ -957,6 +1006,9 @@ local function debuggerCreateWatchWindow()
watchCtrl:Connect(ID_DELETEWATCH, wx.wxEVT_UPDATE_UI,
function (event) event:Enable(watchCtrl:GetSelectedItemCount() > 0) end)
watchCtrl:Connect(wx.wxEVT_COMMAND_LIST_ITEM_ACTIVATED,
function (event) watchCtrl:EditLabel(event:GetIndex()) end)
watchCtrl:Connect(wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT,
function (event)
local row = event:GetIndex()
@@ -971,19 +1023,12 @@ local function debuggerCreateWatchWindow()
event:Skip()
end)
local notebook = wxaui.wxAuiNotebook(ide.frame, wx.wxID_ANY,
wx.wxDefaultPosition, wx.wxDefaultSize,
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
notebook:AddPage(watchCtrl, TR("Watch"), true)
local mgr = ide.frame.uimgr
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
Name("watchpanel"):Float():
MinSize(width/2,height/2):
BestSize(width,height):FloatingSize(width,height):
PinButton(true):Hide())
mgr.defaultPerspective = mgr:SavePerspective() -- resave default perspective
local layout = ide:GetSetting("/view", "uimgrlayout")
if layout and not layout:find("watchpanel") then
ide.frame.bottomnotebook:AddPage(watchCtrl, TR("Watch"), true)
return
end
DebuggerAddWatchWindow()
end
debuggerCreateStackWindow()
@@ -997,7 +1042,7 @@ DebuggerRefreshPanels = updateStackAndWatches
function DebuggerAddWatch(watch)
local mgr = ide.frame.uimgr
local pane = mgr:GetPane("watchpanel")
if (not pane:IsShown()) then
if (pane:IsOk() and not pane:IsShown()) then
pane:Show()
mgr:Update()
end

View File

@@ -12,7 +12,9 @@ local notebook = ide.frame.notebook
local funclist = ide.frame.toolBar.funclist
local edcfg = ide.config.editor
local styles = ide.config.styles
local projcombobox = ide.frame.projpanel.projcombobox
local DEFAULT_STYLE = 32
local margin = { LINENUMBER = 0, MARKER = 1, FOLD = 2 }
-- ----------------------------------------------------------------------------
-- Update the statusbar text of the frame using the given editor.
@@ -109,11 +111,12 @@ local function isFileAlteredOnDisk(editor)
GetIDEString("editormessage"),
wx.wxOK + wx.wxCENTRE, ide.frame)
elseif not editor:GetReadOnly() and modTime:IsValid() and oldModTime:IsEarlierThan(modTime) then
local ret = wx.wxMessageBox(
TR("File '%s' has been modified on disk."):format(fileName)
.."\n"..TR("Do you want to reload it?"),
GetIDEString("editormessage"),
wx.wxYES_NO + wx.wxCENTRE, ide.frame)
local ret = (edcfg.autoreload and (not EditorIsModified(editor)) and wx.wxYES)
or wx.wxMessageBox(
TR("File '%s' has been modified on disk."):format(fileName)
.."\n"..TR("Do you want to reload it?"),
GetIDEString("editormessage"),
wx.wxYES_NO + wx.wxCENTRE, ide.frame)
if ret ~= wx.wxYES or LoadFile(filePath, editor, true) then
openDocuments[id].modTime = GetFileModTime(filePath)
@@ -123,6 +126,20 @@ local function isFileAlteredOnDisk(editor)
end
end
local function navigateToPosition(editor, fromPosition, toPosition, length)
table.insert(editor.jumpstack, fromPosition)
editor:GotoPos(toPosition)
if length then
editor:SetAnchor(toPosition + length)
end
end
local function navigateBack(editor)
if #editor.jumpstack == 0 then return end
local pos = table.remove(editor.jumpstack)
editor:GotoPos(pos)
end
-- ----------------------------------------------------------------------------
-- Get/Set notebook editor page, use nil for current page, returns nil if none
function GetEditor(selection)
@@ -151,8 +168,6 @@ function SetEditorSelection(selection)
editor:SetFocus()
editor:SetSTCFocus(true)
PackageEventHandle("onEditorActivated", editor)
local id = editor:GetId()
FileTreeMarkSelected(openDocuments[id] and openDocuments[id].filePath or '')
AddToFileHistory(openDocuments[id] and openDocuments[id].filePath)
@@ -222,12 +237,12 @@ function EditorAutoComplete(editor)
lt = lt:gsub("%b{}","")
lt = lt:gsub("%b[]",".0")
-- match from starting brace
lt = lt:match("[^%[%(%{%s]*$")
lt = lt:match("[^%[%(%{%s,]*$")
-- know now which string is to be completed
local userList = CreateAutoCompList(editor,lt)
-- don't show the list if the only option is what's already typed
if userList and #userList > 0 and userList ~= lt then
-- don't show the list if it only suggests what's already typed
if userList and #userList > 0 and not lt:find(userList.."$") then
editor:UserListShow(1, userList)
elseif editor:AutoCompActive() then
editor:AutoCompCancel()
@@ -239,12 +254,12 @@ local function getValAtPosition(editor, pos)
local line = editor:LineFromPosition(pos)
local linetx = editor:GetLine(line)
local linestart = editor:PositionFromLine(line)
local localpos = pos-linestart+1
local localpos = pos-linestart
local selected = editor:GetSelectionStart() ~= editor:GetSelectionEnd()
and pos >= editor:GetSelectionStart() and pos <= editor:GetSelectionEnd()
-- check if we have a selected text or an identifier
-- 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.
@@ -265,16 +280,9 @@ local function getValAtPosition(editor, pos)
-- 2. foo.bar(..^. -- the cursor (pos) is on the parameter list
-- "var" has value for #1 and the following fragment checks for #2
local linetxtopos = linetx:sub(1,localpos)
funccall = (#funccall > 0) and var
or (linetxtopos..")"):match(ident .. "%s*%b()$")
or (linetxtopos.."}"):match(ident .. "%s*%b{}$")
or (linetxtopos.."'"):match(ident .. "%s*'[^']*'$")
or (linetxtopos..'"'):match(ident .. '%s*"[^"]*"$')
or nil
-- check if the style is the right one; this is to ignore
-- comments, strings, numbers (to avoid '1 = 1'), keywords, and such
local goodpos = true
if start and not selected then
local style = bit.band(editor:GetStyleAt(linestart+start),31)
if editor.spec.iscomment[style]
@@ -282,18 +290,29 @@ local function getValAtPosition(editor, pos)
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, funccall
goodpos = false
end
end
local linetxtopos = linetx:sub(1,localpos)
funccall = (#funccall > 0) and goodpos and var
or (linetxtopos..")"):match(ident .. "%s*%b()$")
or (linetxtopos.."}"):match(ident .. "%s*%b{}$")
or (linetxtopos.."'"):match(ident .. "%s*'[^']*'$")
or (linetxtopos..'"'):match(ident .. '%s*"[^"]*"$')
or nil
-- don't do anything for strings or comments or numbers
if not goodpos then return nil, funccall end
return var, funccall
end
function EditorCallTip(editor, pos, x, y)
-- don't show anything if the calltip is active; this may happen after
-- typing function name, while the mouse is over a different function.
if editor:CallTipActive() then return end
-- don't show anything if the calltip/auto-complete is active;
-- this may happen after typing function name, while the mouse is over
-- a different function or when auto-complete is on for a parameter.
if editor:CallTipActive() or editor:AutoCompActive() then return end
-- don't activate if the window itself is not active (in the background)
if not ide.frame:IsActive() then return end
@@ -577,6 +596,8 @@ function CreateEditor()
editor.matchon = false
editor.assignscache = false
editor.autocomplete = false
editor.jumpstack = {}
editor:SetBufferedDraw(not ide.config.hidpi and true or false)
editor:StyleClearAll()
@@ -606,19 +627,21 @@ function CreateEditor()
editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_STRICT, 3)
editor:SetMarginWidth(0, editor:TextWidth(32, "99999_")) -- line # margin
editor:SetMarginWidth(margin.LINENUMBER, editor:TextWidth(DEFAULT_STYLE, "99999_"))
editor:SetMarginWidth(1, 16) -- marker margin
editor:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginSensitive(1, true)
editor:SetMarginWidth(margin.MARKER, 16)
editor:SetMarginType(margin.MARKER, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginSensitive(margin.MARKER, true)
editor:MarkerDefine(StylesGetMarker("currentline"))
editor:MarkerDefine(StylesGetMarker("breakpoint"))
editor:SetMarginWidth(2, 16) -- fold margin
editor:SetMarginType(2, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginMask(2, wxstc.wxSTC_MASK_FOLDERS)
editor:SetMarginSensitive(2, true)
if ide.config.editor.fold then
editor:SetMarginWidth(margin.FOLD, 16)
editor:SetMarginType(margin.FOLD, wxstc.wxSTC_MARGIN_SYMBOL)
editor:SetMarginMask(margin.FOLD, wxstc.wxSTC_MASK_FOLDERS)
editor:SetMarginSensitive(margin.FOLD, true)
end
editor:SetFoldFlags(wxstc.wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED +
wxstc.wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED)
@@ -719,8 +742,7 @@ function CreateEditor()
if ide.config.acandtip.nodynwords then return end
-- only required to track changes
if (bit.band(evtype,wxstc.wxSTC_MOD_BEFOREDELETE) ~= 0) then
local numlines = 0
event:GetText():gsub("(\r?\n)",function() numlines = numlines + 1 end)
local _, numlines = event:GetText():gsub("\r?\n","%1")
DynamicWordsRem("pre",editor,nil,editor:LineFromPosition(event:GetPosition()), numlines)
end
if (bit.band(evtype,wxstc.wxSTC_MOD_BEFOREINSERT) ~= 0) then
@@ -731,8 +753,8 @@ function CreateEditor()
editor:Connect(wxstc.wxEVT_STC_CHARADDED,
function (event)
-- auto-indent
local LF = string.byte("\n")
local ch = event:GetKey()
local eol = editor:GetEOLMode()
local pos = editor:GetCurrentPos()
local line = editor:GetCurrentLine()
local linetx = editor:GetLine(line)
@@ -742,7 +764,7 @@ function CreateEditor()
if PackageEventHandle("onEditorCharAdded", editor, event) == false then
-- this event has already been handled
elseif (ch == char_LF) then
elseif (ch == LF) then
if (line > 0) then
local indent = editor:GetLineIndentation(line - 1)
local linedone = editor:GetLine(line - 1)
@@ -790,8 +812,7 @@ function CreateEditor()
elseif ide.config.autocomplete then -- code completion prompt
local trigger = linetxtopos:match("["..editor.spec.sep.."%w_]+$")
if (trigger and (#trigger > 1 or trigger:match("["..editor.spec.sep.."]"))) then
ide.frame:AddPendingEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_AUTOCOMPLETE))
editor.autocomplete = true
end
end
end)
@@ -833,15 +854,45 @@ function CreateEditor()
editor:Connect(wx.wxEVT_KILL_FOCUS,
function (event)
if editor:AutoCompActive() then editor:AutoCompCancel() end
PackageEventHandle("onEditorFocusLost", editor)
event:Skip()
end)
editor:Connect(wxstc.wxEVT_STC_USERLISTSELECTION,
function (event)
local pos = editor:GetCurrentPos()
local start_pos = editor:WordStartPosition(pos, true)
editor:SetSelection(start_pos, pos)
editor:ReplaceSelection(event:GetText())
if ide.wxver >= "2.9.5" and editor:GetSelections() > 1 then
local text = event:GetText()
-- capture all positions as the selection may change
local positions = {}
for s = 0, editor:GetSelections()-1 do
table.insert(positions, editor:GetSelectionNCaret(s))
end
-- process all selections from last to first
table.sort(positions)
local mainpos = editor:GetSelectionNCaret(editor:GetMainSelection())
editor:BeginUndoAction()
for s = #positions, 1, -1 do
local pos = positions[s]
local start_pos = editor:WordStartPosition(pos, true)
editor:SetSelection(start_pos, pos)
editor:ReplaceSelection(text)
-- if this is the main position, save new cursor position to restore
if pos == mainpos then mainpos = editor:GetCurrentPos()
elseif pos < mainpos then
-- adjust main position as earlier changes may affect it
mainpos = mainpos + #text - (pos - start_pos)
end
end
editor:EndUndoAction()
editor:GotoPos(mainpos)
else
local pos = editor:GetCurrentPos()
local start_pos = editor:WordStartPosition(pos, true)
editor:SetSelection(start_pos, pos)
editor:ReplaceSelection(event:GetText())
end
end)
editor:Connect(wxstc.wxEVT_STC_SAVEPOINTREACHED,
@@ -886,6 +937,12 @@ function CreateEditor()
firstvisible)
MarkupStyle(editor,minupdated or firstline,lastline)
editor.ev = {}
-- show auto-complete if needed
if editor.autocomplete then
EditorAutoComplete(editor)
editor.autocomplete = false
end
end)
editor:Connect(wx.wxEVT_LEFT_DOWN,
@@ -896,6 +953,19 @@ function CreateEditor()
if MarkupHotspotClick(position, editor) then return end
end
end
if event:ControlDown() and event:AltDown()
-- ide.wxver >= "2.9.5"; fix after GetModifiers is added to wxMouseEvent in wxlua
and not event:ShiftDown() and not event:MetaDown() then
local point = event:GetPosition()
local pos = editor:PositionFromPointClose(point.x, point.y)
local value = pos ~= wxstc.wxSTC_INVALID_POSITION and getValAtPosition(editor, pos) or nil
local instances = value and indicateFindInstances(editor, value, pos+1)
if instances and instances[0] then
navigateToPosition(editor, pos, instances[0]-1, #value)
return
end
end
event:Skip()
end)
@@ -915,6 +985,7 @@ function CreateEditor()
event:Skip()
if inhandler or ide.exitingProgram then return end
inhandler = true
PackageEventHandle("onEditorFocusSet", editor)
isFileAlteredOnDisk(editor)
inhandler = false
end)
@@ -977,6 +1048,8 @@ function CreateEditor()
and keycode == ('T'):byte() and mod == wx.wxMOD_CONTROL then
ide.frame:AddPendingEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_SHOWTOOLTIP))
elseif mod == wx.wxMOD_ALT and keycode == wx.WXK_LEFT then
navigateBack(editor)
else
if ide.osname == 'Macintosh' and mod == wx.wxMOD_META then
return -- ignore a key press if Command key is also pressed
@@ -1022,6 +1095,12 @@ function CreateEditor()
event:Skip()
end)
editor:Connect(wxstc.wxEVT_STC_ZOOM,
function(event)
editor:SetMarginWidth(margin.LINENUMBER, editor:TextWidth(DEFAULT_STYLE, "99999_"))
event:Skip()
end)
local pos, value, instances
editor:Connect(wx.wxEVT_CONTEXT_MENU,
function (event)
@@ -1076,8 +1155,7 @@ function CreateEditor()
editor:Connect(ID_GOTODEFINITION, wx.wxEVT_COMMAND_MENU_SELECTED,
function(event)
if value and instances[0] then
editor:GotoPos(instances[0]-1)
editor:SetAnchor(instances[0]-1+#value)
navigateToPosition(editor, editor:GetCurrentPos(), instances[0]-1, #value)
end
end)
@@ -1108,7 +1186,7 @@ function AddEditor(editor, name)
local document = setmetatable({}, ide.proto.Document)
document.editor = editor
document.index = notebook:GetPageIndex(editor)
document.fileName = nil
document.fileName = name
document.filePath = nil
document.modTime = nil
document.isModified = false
@@ -1187,9 +1265,12 @@ function SetupKeywords(editor, ext, forcespec, styles, font, fontitalic)
-- need to set folding property after lexer is set, otherwise
-- the folds are not shown (wxwidgets 2.9.5)
editor:SetProperty("fold", "1")
editor:SetProperty("fold.compact", ide.config.editor.foldcompact and "1" or "0")
editor:SetProperty("fold.comment", "1")
if ide.config.editor.fold then
editor:SetProperty("fold", "1")
editor:SetProperty("fold.html", "1")
editor:SetProperty("fold.compact", ide.config.editor.foldcompact and "1" or "0")
editor:SetProperty("fold.comment", "1")
end
-- quickfix to prevent weird looks, otherwise need to update styling mechanism for cpp
-- cpp "greyed out" styles are styleid + 64

View File

@@ -8,10 +8,13 @@ local ide = ide
ide.filetree = {
projdir = "",
projdirlist = {},
projdirmap = {},
projdirpartmap = {},
}
local filetree = ide.filetree
local iscaseinsensitive = wx.wxFileName("A"):SameAs(wx.wxFileName("a"))
local pathsep = GetPathSeparator()
-- generic tree
-- ------------
@@ -42,7 +45,7 @@ local function treeAddDir(tree,parent_id,rootdir)
local curr
for _, file in ipairs(FileSysGetRecursive(rootdir)) do
local name, dir = file:match("([^"..string_Pathsep.."]+)("..string_Pathsep.."?)$")
local name, dir = file:match("([^"..pathsep.."]+)("..pathsep.."?)$")
local known = GetSpec(GetFileExt(name))
local icon = #dir>0 and IMG_DIRECTORY or known and IMG_FILE_KNOWN or IMG_FILE_OTHER
local item = items[name .. icon]
@@ -103,7 +106,7 @@ local function treeSetConnectorsAndIcons(tree)
item_id = tree:GetItemParent(item_id)
if not item_id:IsOk() then break end
cur = tree:GetItemText(item_id)
if cur and string.len(cur) > 0 then str = cur..string_Pathsep..str end
if cur and string.len(cur) > 0 then str = cur..pathsep..str end
end
-- as root may already include path separator, normalize the path
local fullPath = wx.wxFileName(str)
@@ -208,14 +211,14 @@ local inupdate = false
local function projcomboboxUpdate(event)
if inupdate then return end
local cur = projcombobox:GetValue()
local fn = wx.wxFileName(cur)
local fn = wx.wxFileName(filetree.projdirmap[cur] or cur)
fn:Normalize()
-- on Windows, wxwidgets (2.9.5+) generates two COMMAND_COMBOBOX_SELECTED
-- events when the selection is done with ENTER, which causes recursive
-- call of updateProjectDir. To prevent this the second call is ignored.
inupdate = true
filetree:updateProjectDir(fn:GetFullPath(), event:GetEventType() == wx.wxEVT_COMMAND_COMBOBOX_SELECTED)
filetree:updateProjectDir(fn:GetFullPath())
inupdate = false
end
@@ -227,7 +230,29 @@ treeSetConnectorsAndIcons(projtree)
-- proj functions
-- ---------------
function filetree:updateProjectDir(newdir, cboxsel)
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
local function abbreviateProjList(projdirlist)
filetree.projdirmap = {}
local sep = "\t"
local dirs = table.concat(projdirlist, sep)..sep
local projlist = {}
for _, v in ipairs(projdirlist) do
-- using FileName because the path doesn't have trailing slash
local parts = wx.wxFileName(v..pathsep):GetDirs()
local name = table.remove(parts, #parts) or v
while #parts > 0
and select(2, dirs:gsub("%f[^".. pathsep .."]"..q(name)..sep, "")) > 1 do
name = table.remove(parts, #parts) .. pathsep .. name
end
local abbrev = ("%s (%s)"):format(name, v)
filetree.projdirmap[abbrev] = v
table.insert(projlist, abbrev)
end
return projlist
end
function filetree:updateProjectDir(newdir)
if (not newdir) or not wx.wxDirExists(newdir) then return end
local dirname = wx.wxFileName.DirName(newdir)
@@ -245,6 +270,7 @@ function filetree:updateProjectDir(newdir, cboxsel)
end
filetree.projdir = newdir
filetree.projdirpartmap = {}
PackageEventHandle("onProjectLoad", filetree.projdir)
@@ -254,12 +280,8 @@ function filetree:updateProjectDir(newdir, cboxsel)
ide.config.projecthistorylength,
function(s1, s2) return dirname:SameAs(wx.wxFileName.DirName(s2)) end)
projcombobox:Clear()
projcombobox:Append(filetree.projdirlist)
if (not cboxsel) then
projcombobox:SetValue(newdir)
else
projcombobox:Select(0)
end
projcombobox:Append(abbreviateProjList(filetree.projdirlist))
projcombobox:Select(0)
ProjectUpdateProjectDir(newdir,true)
treeSetRoot(projtree,newdir)
@@ -306,7 +328,7 @@ local function findItem(tree, match)
end
if not s or s ~= 1 then return end
for token in string.gmatch(string.sub(match,e+1), "[^%"..string_Pathsep.."]+") do
for token in string.gmatch(string.sub(match,e+1), "[^%"..pathsep.."]+") do
local data = tree:GetItemData(node)
local cache = data and data:GetData()
if cache and cache[iscaseinsensitive and token:lower() or token] then
@@ -359,3 +381,21 @@ function FileTreeMarkSelected(file)
projtree:Refresh() end
end
end
function FileTreeFindByPartialName(name)
-- check if it's already cached
if filetree.projdirpartmap[name] then return filetree.projdirpartmap[name] end
-- this function may get a partial name that starts with ... and has
-- an abbreviated path (as generated by stack traces);
-- remove starting "..." if any and escape
local pattern = q(name:gsub("^%.%.%.","")):gsub("[\\/]", "[\\/]").."$"
for _, file in ipairs(FileSysGetRecursive(filetree.projdir, true)) do
if file:find(pattern) then
filetree.projdirpartmap[name] = file
return file
end
end
return
end

View File

@@ -13,7 +13,7 @@ ide.findReplace = {
fWrap = true, -- search wraps around
fDown = true, -- search downwards in doc
fSubDirs = false, -- search in subdirectories
fSubDirs = true, -- search in subdirectories
fMakeBak = true, -- make bak files for replace in files
findTextArray = {}, -- array of last entered find text
@@ -46,8 +46,8 @@ end
-------------------- Find replace dialog
local function setSearchFlags(editor)
local flags = 0
if findReplace.fWholeWord then flags = wxstc.wxSTC_FIND_WHOLEWORD end
local flags = wxstc.wxSTC_FIND_POSIX
if findReplace.fWholeWord then flags = flags + wxstc.wxSTC_FIND_WHOLEWORD end
if findReplace.fMatchCase then flags = flags + wxstc.wxSTC_FIND_MATCHCASE end
if findReplace.fRegularExpr then flags = flags + wxstc.wxSTC_FIND_REGEXP end
editor:SetSearchFlags(flags)
@@ -185,7 +185,6 @@ function findReplace:ReplaceString(fReplaceAll, inFileRegister)
local replaced = false
if findReplace:HasText() then
local replaceLen = string.len(findReplace.replaceText)
local editor = findReplace:GetEditor()
local endTarget = inFileRegister and setTargetAll(editor) or
setTarget(editor, findReplace.fDown, fReplaceAll, findReplace.fWrap)
@@ -200,8 +199,11 @@ function findReplace:ReplaceString(fReplaceAll, inFileRegister)
if (inFileRegister) then inFileRegister(posFind) end
local length = editor:GetLength()
editor:ReplaceTarget(findReplace.replaceText)
editor:SetTargetStart(posFind + replaceLen)
local replaced = findReplace.fRegularExpr
and editor:ReplaceTargetRE(findReplace.replaceText)
or editor:ReplaceTarget(findReplace.replaceText)
editor:SetTargetStart(posFind + replaced)
-- adjust the endTarget as the position could have changed;
-- can't simply subtract findText length as it could be a regexp
endTarget = endTarget + (editor:GetLength() - length)
@@ -216,10 +218,21 @@ function findReplace:ReplaceString(fReplaceAll, inFileRegister)
ide.frame:SetStatusText(("%s %s."):format(
TR("Replaced"), TR("%d instance", occurrences):format(occurrences)))
else
if findReplace.foundString then
-- check if there is anything selected as well as the user can
-- move the cursor after successful search
if findReplace.foundString
and editor:GetSelectionStart() ~= editor:GetSelectionEnd() then
local start = editor:GetSelectionStart()
editor:ReplaceSelection(findReplace.replaceText)
editor:SetSelection(start, start + replaceLen)
-- convert selection to target as we need TargetRE support
editor:TargetFromSelection()
local length = editor:GetLength()
local replaced = findReplace.fRegularExpr
and editor:ReplaceTargetRE(findReplace.replaceText)
or editor:ReplaceTarget(findReplace.replaceText)
editor:SetSelection(start, start + replaced)
findReplace.foundString = false
replaced = true
@@ -254,7 +267,7 @@ local function ProcInFiles(startdir,mask,subdirs,replace)
-- ignore .bak files when replacing and asked to store .bak files
-- and skip folders as these are included in the list as well
if not (replace and findReplace.fMakeBak and file:find('.bak$'))
and not file:match(string_Pathsep.."$") then
and not IsDirectory(file) then
local match = false
for _, mask in ipairs(masks) do match = match or file:find(mask) end
if match then
@@ -276,6 +289,10 @@ local function ProcInFiles(startdir,mask,subdirs,replace)
-- give time to the UI to refresh
if TimeGet() - start > 0.25 then wx.wxYield() end
if not findReplace.dialog:IsShown() then
DisplayOutputLn(TR("Cancelled by the user."))
break
end
end
end
end
@@ -289,6 +306,8 @@ function findReplace:RunInFiles(replace)
wx.wxDefaultPosition, wx.wxSize(1,1), wx.wxBORDER_STATIC)
findReplace.occurrences = 0
ActivateOutput()
local startdir = findReplace.filedirText
DisplayOutputLn(("%s '%s'."):format(
(replace and TR("Replacing") or TR("Searching for")),

View File

@@ -164,7 +164,15 @@ local function createNotebook(frame)
local selection
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP,
function (event)
selection = event:GetSelection() -- save tab index the event is for
-- event:GetSelection() returns the index *inside the current tab*;
-- for split notebooks, this may not be the same as the index
-- in the notebook we are interested in here
local idx = event:GetSelection()
local tabctrl = event:GetEventObject():DynamicCast("wxAuiTabCtrl")
-- save tab index the event is for
selection = notebook:GetPageIndex(tabctrl:GetPage(idx).window)
local menu = wx.wxMenu()
menu:Append(ID_CLOSE, TR("&Close Page"))
menu:Append(ID_CLOSEALL, TR("Close A&ll Pages"))
@@ -175,12 +183,17 @@ local function createNotebook(frame)
menu:AppendSeparator()
menu:Append(ID_SHOWLOCATION, TR("Show Location"))
PackageEventHandle("onMenuEditorTab", menu, notebook, event)
PackageEventHandle("onMenuEditorTab", menu, notebook, event, selection)
notebook:PopupMenu(menu)
end)
local function IfAtLeastOneTab(event) event:Enable(notebook:GetPageCount() > 0) end
local function IfAtLeastOneTab(event)
event:Enable(notebook:GetPageCount() > 0)
if ide.osname == 'Macintosh' and (event:GetId() == ID_CLOSEALL
or event:GetId() == ID_CLOSE and notebook:GetPageCount() <= 1)
then event:Enable(false) end
end
local function IfModified(event) event:Enable(EditorIsModified(GetEditor(selection))) end
notebook:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED, function ()
@@ -222,6 +235,101 @@ local function createBottomNotebook(frame)
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
-- this handler allows dragging tabs into this bottom notebook
bottomnotebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND,
function (event)
local notebookfrom = event:GetDragSource()
if notebookfrom ~= ide.frame.notebook then
local mgr = ide.frame.uimgr
local pane = mgr:GetPane(notebookfrom)
if not pane:IsOk() then return end -- not a managed window
if pane:IsFloating() then
notebookfrom:GetParent():Hide()
else
pane:Hide()
mgr:Update()
end
mgr:DetachPane(notebookfrom)
-- this is a workaround for wxwidgets bug (2.9.5+) that combines
-- content from two windows when tab is dragged over an active tab.
local mouse = wx.wxGetMouseState()
local mouseatpoint = wx.wxPoint(mouse:GetX(), mouse:GetY())
local ok, tabs = pcall(function() return wx.wxFindWindowAtPoint(mouseatpoint):DynamicCast("wxAuiTabCtrl") end)
tabs:SetNoneActive()
event:Allow()
end
end)
-- these handlers allow dragging tabs out of this bottom notebook.
-- I couldn't find a good way to stop dragging event as it's not known
-- where the event is going to end when it's started, so we manipulate
-- the flag that allows splits and disable it when needed.
-- It is then enabled in BEGIN_DRAG event.
bottomnotebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
function (event)
event:Skip()
-- allow dragging if it was disabled earlier
local flags = bottomnotebook:GetWindowStyleFlag()
if bit.band(flags, wxaui.wxAUI_NB_TAB_SPLIT) == 0 then
bottomnotebook:SetWindowStyleFlag(flags + wxaui.wxAUI_NB_TAB_SPLIT)
end
end)
-- there is currently no support in wxAuiNotebook for dragging tabs out.
-- This is implemented as removing a tab that was dragged out and
-- recreating it with the right control. This is complicated by the fact
-- that tabs can be split, so if the destination is withing the area where
-- splits happen, the tab is not removed.
bottomnotebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
function (event)
event:Skip()
local mgr = ide.frame.uimgr
local win = mgr:GetPane(bottomnotebook).window
local x = win:GetScreenPosition():GetX()
local y = win:GetScreenPosition():GetY()
local w, h = win:GetSize():GetWidth(), win:GetSize():GetHeight()
local mouse = wx.wxGetMouseState()
local mx, my = mouse:GetX(), mouse:GetY()
if mx >= x and mx <= x + w and my >= y and my <= y + h then return end
-- disallow split as the target is outside the notebook
local flags = bottomnotebook:GetWindowStyleFlag()
if bit.band(flags, wxaui.wxAUI_NB_TAB_SPLIT) ~= 0 then
bottomnotebook:SetWindowStyleFlag(flags - wxaui.wxAUI_NB_TAB_SPLIT)
end
-- don't allow any dragging to the are of the pane header as it
-- splits already split notebooks incorrectly (wxwidgets bug).
if my >= y - 30 then return end
-- don't allow dragging out single tabs from tab ctrl
-- as wxwidgets doesn't like removing pages from split notebooks.
local tabctrl = event:GetEventObject():DynamicCast("wxAuiTabCtrl")
if tabctrl:GetPageCount() == 1 then return end
local idx = event:GetSelection() -- index within the current tab ctrl
local selection = bottomnotebook:GetPageIndex(tabctrl:GetPage(idx).window)
local label = bottomnotebook:GetPageText(selection)
-- names are translated on labels, so need to translate here as well
local dragout = ({[TR("Watch")] = DebuggerAddWatchWindow,
[TR("Stack")] = DebuggerAddStackWindow})[label]
if not dragout then return end
bottomnotebook:RemovePage(selection)
local pane = mgr:GetPane(dragout())
pane:FloatingPosition(mx-10, my-10)
pane:Show()
mgr:Update()
end)
local errorlog = wxstc.wxStyledTextCtrl(bottomnotebook, wx.wxID_ANY,
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxBORDER_STATIC)

View File

@@ -78,6 +78,12 @@ ID_PROJECTDIRFROMFILE = NewID()
ID_PROJECTDIRCHOOSE = NewID()
-- Help menu
ID_ABOUT = wx.wxID_ABOUT
ID_HELPPROJECT = NewID()
ID_HELPDOCUMENTATION = NewID()
ID_HELPGETTINGSTARTED = NewID()
ID_HELPTUTORIALS = NewID()
ID_HELPFAQ = NewID()
ID_HELPCOMMUNITY = NewID()
-- Watch window menu items
ID_ADDWATCH = NewID()
ID_EDITWATCH = NewID()

View File

@@ -44,7 +44,7 @@ function M.show_warnings(top_ast)
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 = {}, {}
local isseen, globseen, fieldseen = {}, {}, {}
LA.walk(top_ast, function(ast)
local line = ast.lineinfo and ast.lineinfo.first[1] or 0
local path = ast.lineinfo and ast.lineinfo.first[4] or '?'
@@ -105,7 +105,14 @@ function M.show_warnings(top_ast)
-- added check for FAST as ast.seevalue relies on value evaluation,
-- which is very slow even on simple and short scripts
if not FAST and ast.isfield and not(known(ast.seevalue.value) and ast.seevalue.value ~= nil) then
warn("unknown field " .. name, ast.lineinfo.first[1], path)
if not fieldseen[name] then
fieldseen[name] = true
local parent = ast.parent
and (" in '"..index(ast.parent):gsub("%."..name.."$","").."'")
or ""
warn("first use of unknown field '" .. name .."'"..parent,
ast.lineinfo.first[1], path)
end
elseif ast.tag == 'Id' and not ast.localdefinition and not ast.definedglobal then
if not globseen[name] then
globseen[name] = true
@@ -136,7 +143,7 @@ function M.show_warnings(top_ast)
local note = vast.parent
and (vast.parent.tag == 'Call' or vast.parent.tag == 'Invoke')
and vast.parent.note
if note and not isseen[vast.parent] then
if note and not isseen[vast.parent] and type(name) == "string" then
isseen[vast.parent] = true
warn("function '" .. name .. "': " .. note, line, path)
end

View File

@@ -133,6 +133,9 @@ function MarkupStyle(editor, lines, linee)
local lines = lines or 0
if (lines < 0) then return end
-- if the current spec doesn't have any comments, nothing to style
if not next(editor.spec.iscomment) then return end
-- always style to the end as there may be comments that need re-styling
-- technically, this should be GetLineCount()-1, but we want to style
-- beyond the last line to make sure it is styled correctly

View File

@@ -25,6 +25,7 @@ local editMenu = wx.wxMenu{
{ },
{ ID_FOLD, TR("&Fold/Unfold All")..KSC(ID_FOLD), TR("Fold or unfold all code folds") },
{ ID_CLEARDYNAMICWORDS, TR("Clear &Dynamic Words")..KSC(ID_CLEARDYNAMICWORDS), TR("Resets the dynamic word list for autocompletion") },
{ ID_SORT, TR("&Sort")..KSC(ID_SORT), TR("Sort selected lines") },
{ },
}
@@ -53,10 +54,10 @@ function OnUpdateUIEditMenu(event)
local editor = getControlWithFocus()
if editor == nil then event:Enable(false); return end
local alwaysOn = { [ID_SELECTALL] = true, [ID_FOLD] = true,
local alwaysOn = { [ID_SELECTALL] = true, [ID_FOLD] = ide.config.editor.fold,
-- allow Cut and Copy commands as these work on a line if no selection
[ID_COPY] = true, [ID_CUT] = true,
[ID_COMMENT] = true, [ID_AUTOCOMPLETE] = true}
[ID_COMMENT] = true, [ID_AUTOCOMPLETE] = true, [ID_SORT] = true}
local menu_id = event:GetId()
local enable =
menu_id == ID_PASTE and editor:CanPaste() or
@@ -155,24 +156,82 @@ frame:Connect(ID_AUTOCOMPLETEENABLE, wx.wxEVT_COMMAND_MENU_SELECTED,
frame:Connect(ID_COMMENT, wx.wxEVT_COMMAND_MENU_SELECTED,
function (event)
local editor = GetEditor()
local buf = {}
if editor:GetSelectionStart() == editor:GetSelectionEnd() then
local lineNumber = editor:GetCurrentLine()
editor:SetSelection(editor:PositionFromLine(lineNumber), editor:GetLineEndPosition(lineNumber))
end
-- capture the current position in line to restore later
local curline = editor:GetCurrentLine()
local curlen = #editor:GetLine(curline)
local curpos = editor:GetCurrentPos()-editor:PositionFromLine(curline)
-- for multi-line selection, always start the first line at the beginning
local ssel, esel = editor:GetSelectionStart(), editor:GetSelectionEnd()
local sline = editor:LineFromPosition(ssel)
local eline = editor:LineFromPosition(esel)
local sel = ssel ~= esel
local rect = editor:SelectionIsRectangle()
local lc = editor.spec.linecomment
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
if string.sub(line,1,#lc) == lc then
line = string.sub(line,#lc+1)
elseif #line > 0 then
line = lc..line
local qlc = lc:gsub(".", "%%%1")
-- figure out how to toggle comments; if there is at least one non-empty
-- line that doesn't start with a comment, need to comment
local comment = false
for line = sline, eline do
local pos = sel and (sline == eline or rect)
and ssel-editor:PositionFromLine(sline)+1 or 1
local text = editor:GetLine(line)
local _, cpos = text:find("^%s*"..qlc, pos)
if not cpos and text:find("%S")
-- ignore last line when the end of selection is at the first position
and (line == sline or line < eline or esel-editor:PositionFromLine(line) > 0) then
comment = true
break
end
table.insert(buf, line)
end
editor:ReplaceSelection(table.concat(buf,"\n"))
editor:BeginUndoAction()
-- go last to first as selection positions we captured may be affected
-- by text changes
for line = eline, sline, -1 do
local pos = sel and (sline == eline or rect)
and ssel-editor:PositionFromLine(sline)+1 or 1
local text = editor:GetLine(line)
local _, cpos = text:find("^%s*"..qlc, pos)
if not comment and cpos then
editor:DeleteRange(cpos-#lc+editor:PositionFromLine(line), #lc)
elseif comment and text:find("%S")
and (line == sline or line < eline or esel-editor:PositionFromLine(line) > 0) then
editor:InsertText(pos+editor:PositionFromLine(line)-1, lc)
end
end
editor:EndUndoAction()
-- fix position if it was after where the selection started
if editor:PositionFromLine(curline)+curpos > ssel then
-- position the cursor exactly where its position was, which
-- could have shifted depending on whether the text was added or removed.
editor:GotoPos(editor:PositionFromLine(curline)
+ math.max(0, curpos+#editor:GetLine(curline)-curlen))
end
end)
frame:Connect(ID_COMMENT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
frame:Connect(ID_SORT, wx.wxEVT_COMMAND_MENU_SELECTED,
function (event)
local editor = GetEditor()
local buf = {}
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
table.insert(buf, line)
end
if #buf > 0 then
local newline
if #(buf[#buf]) == 0 then newline = table.remove(buf) end
table.sort(buf)
-- add new line at the end if it was there
if newline then table.insert(buf, newline) end
editor:ReplaceSelection(table.concat(buf,"\n"))
end
end)
frame:Connect(ID_SORT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
frame:Connect(ID_FOLD, wx.wxEVT_COMMAND_MENU_SELECTED,
function (event)
FoldSome()

View File

@@ -154,7 +154,7 @@ do -- recent file history
end
end
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, NewFile)
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, function() return NewFile() end)
frame:Connect(ID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, OpenFile)
frame:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,
function ()

View File

@@ -8,8 +8,24 @@ local frame = ide.frame
local menuBar = frame.menuBar
local mobdebug = require "mobdebug"
local url = "http://download.zerobrane.com/zerobranestudio-"
local urls = {
[ID_HELPPROJECT] = "main",
[ID_HELPDOCUMENTATION] = "documentation",
[ID_HELPGETTINGSTARTED] = "gettingstarted",
[ID_HELPTUTORIALS] = "tutorials",
[ID_HELPFAQ] = "faq",
[ID_HELPCOMMUNITY] = "community",
}
local helpMenu = wx.wxMenu{
{ ID_ABOUT, TR("&About")..KSC(ID_ABOUT), TR("About %s"):format(GetIDEString("editor")) },
{ ID_HELPPROJECT, TR("&Project Page")..KSC(ID_HELPPROJECT) },
{ ID_HELPDOCUMENTATION, TR("&Documentation")..KSC(ID_HELPDOCUMENTATION) },
{ ID_HELPGETTINGSTARTED, TR("&Getting Started Guide")..KSC(ID_HELPGETTINGSTARTED) },
{ ID_HELPTUTORIALS, TR("&Tutorials")..KSC(ID_HELPTUTORIALS) },
{ ID_HELPFAQ, TR("&Frequently Asked Questions")..KSC(ID_HELPFAQ) },
{ ID_HELPCOMMUNITY, TR("&Community")..KSC(ID_HELPCOMMUNITY) },
}
-- do not translate Help menu on Mac as it won't merge with "standard" menus
menuBar:Append(helpMenu, ide.osname == 'Macintosh' and "&Help" or TR("&Help"))
@@ -94,3 +110,7 @@ local function DisplayAbout(event)
end
frame:Connect(ID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, DisplayAbout)
for item, page in pairs(urls) do
frame:Connect(item, wx.wxEVT_COMMAND_MENU_SELECTED,
function() wx.wxLaunchDefaultBrowser(url..page, 0) end)
end

View File

@@ -11,30 +11,6 @@ local uimgr = frame.uimgr
------------------------
-- Interpreters and Menu
local targetMenu
local interpreters = {}
local lastinterpreter
do
local interpreternames = {}
local lkinterpreters = {}
for i,v in pairs(ide.interpreters) do
interpreters[ID ("debug.interpreter."..i)] = v
v.fname = i
lastinterpreter = i
table.insert(interpreternames,v.name)
lkinterpreters[v.name] = i
end
assert(lastinterpreter,"no interpreters defined")
table.sort(interpreternames)
local targetargs = {}
for _,v in ipairs(interpreternames) do
local id = ID("debug.interpreter."..lkinterpreters[v])
local inter = interpreters[id]
table.insert(targetargs,{id,inter.name,inter.description,wx.wxITEM_CHECK})
end
targetMenu = wx.wxMenu(targetargs)
end
local debugTab = {
{ ID_RUN, TR("&Run")..KSC(ID_RUN), TR("Execute the current project/file") },
@@ -59,6 +35,7 @@ local targetDirMenu = wx.wxMenu{
{ID_PROJECTDIRCHOOSE, TR("Choose ...")..KSC(ID_PROJECTDIRCHOOSE), TR("Choose a project directory")},
{ID_PROJECTDIRFROMFILE, TR("Set From Current File")..KSC(ID_PROJECTDIRFROMFILE), TR("Set project directory from current file")},
}
local targetMenu = wx.wxMenu({})
local debugMenu = wx.wxMenu(debugTab)
local debugMenuRun = {
start=TR("Start &Debugging")..KSC(ID_STARTDEBUG), continue=TR("Co&ntinue")..KSC(ID_STARTDEBUG)}
@@ -68,6 +45,75 @@ debugMenu:Append(ID_PROJECTDIR, TR("Project Directory"), targetDirMenu, TR("Set
debugMenu:Append(ID_INTERPRETER, TR("Lua &Interpreter"), targetMenu, TR("Set the interpreter to be used"))
menuBar:Append(debugMenu, TR("&Project"))
local interpreters
local function selectInterpreter(id)
for id in pairs(interpreters) do
menuBar:Check(id, false)
menuBar:Enable(id, true)
end
menuBar:Check(id, true)
menuBar:Enable(id, false)
if ide.interpreter and ide.interpreter ~= interpreters[id] then
PackageEventHandle("onInterpreterClose", ide.interpreter) end
if interpreters[id] and ide.interpreter ~= interpreters[id] then
PackageEventHandle("onInterpreterLoad", interpreters[id]) end
ide.interpreter = interpreters[id]
DebuggerShutdown()
ide.frame.statusBar:SetStatusText(ide.interpreter.name or "", 5)
ReloadLuaAPI()
end
function ProjectSetInterpreter(name)
local id = IDget("debug.interpreter."..name)
if (not interpreters[id]) then return end
selectInterpreter(id)
end
local function evSelectInterpreter(event)
selectInterpreter(event:GetId())
end
function UpdateInterpreters()
assert(ide.interpreters, "no interpreters defined")
-- delete all existing items (if any)
local items = targetMenu:GetMenuItemCount()
for i = items, 1, -1 do
targetMenu:Delete(targetMenu:FindItemByPosition(i-1))
end
local names = {}
for file in pairs(ide.interpreters) do table.insert(names, file) end
table.sort(names)
interpreters = {}
for i, file in ipairs(names) do
local inter = ide.interpreters[file]
local id = ID("debug.interpreter."..file)
inter.fname = file
interpreters[id] = inter
targetMenu:Append(
wx.wxMenuItem(targetMenu, id, inter.name, inter.description, wx.wxITEM_CHECK))
frame:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED, evSelectInterpreter)
end
local id = (
-- interpreter is set and is (still) on the list of known interpreters
IDget("debug.interpreter."
..(ide.interpreter and ide.interpreters[ide.interpreter.fname]
and ide.interpreter.fname or ide.config.interpreter)) or
-- otherwise use default interpreter
ID("debug.interpreter."..ide.config.default.interpreter)
)
selectInterpreter(id)
end
UpdateInterpreters()
-----------------------------
-- Project directory handling
@@ -118,52 +164,8 @@ local function projFromFile(event)
end
frame:Connect(ID_PROJECTDIRFROMFILE, wx.wxEVT_COMMAND_MENU_SELECTED, projFromFile)
------------------------------------
-- Interpreter Selection and Running
local function selectInterpreter(id)
for id in pairs(interpreters) do
menuBar:Check(id, false)
menuBar:Enable(id, true)
end
menuBar:Check(id, true)
menuBar:Enable(id, false)
if ide.interpreter and ide.interpreter ~= interpreters[id] then
PackageEventHandle("onInterpreterClose", ide.interpreter) end
ide.interpreter = interpreters[id]
PackageEventHandle("onInterpreterLoad", ide.interpreter)
DebuggerShutdown()
ide.frame.statusBar:SetStatusText(ide.interpreter.name or "", 5)
ReloadLuaAPI()
end
function ProjectSetInterpreter(name)
local id = IDget("debug.interpreter."..name)
if (not interpreters[id]) then return end
selectInterpreter(id)
end
local function evSelectInterpreter(event)
selectInterpreter(event:GetId())
end
for id in pairs(interpreters) do
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectInterpreter)
end
do
local defaultid = (
IDget("debug.interpreter."..ide.config.interpreter) or
ID("debug.interpreter."..lastinterpreter)
)
ide.interpreter = interpreters[defaultid]
menuBar:Check(defaultid, true)
end
----------------------
-- Interpreter Running
local function getNameToRun(skipcheck)
local editor = GetEditor()
@@ -181,6 +183,7 @@ local function getNameToRun(skipcheck)
local id = editor:GetId()
if not openDocuments[id].filePath then SetDocumentModified(id, true) end
if not SaveIfModified(editor) then return end
if ide.config.editor.saveallonrun then SaveAll(true) end
return wx.wxFileName(openDocuments[id].filePath)
end
@@ -398,5 +401,6 @@ frame:Connect(wx.wxEVT_IDLE,
if (debugger.update) then debugger.update() end
if (debugger.scratchpad) then DebuggerRefreshScratchpad() end
if IndicateIfNeeded() then event:RequestMore(true) end
PackageEventHandleOnce("onIdleOnce", event)
event:Skip() -- let other EVT_IDLE handlers to work on the event
end)

View File

@@ -19,8 +19,7 @@ local findMenu = wx.wxMenu{
{ ID_REPLACEINFILES, TR("Re&place In Files")..KSC(ID_REPLACEINFILES), TR("Find and replace text in files") },
{ },
{ ID_GOTOLINE, TR("&Goto Line")..KSC(ID_GOTOLINE), TR("Go to a selected line") },
{ },
{ ID_SORT, TR("&Sort")..KSC(ID_SORT), TR("Sort selected lines") }}
}
menuBar:Append(findMenu, TR("&Search"))
function OnUpdateUISearchMenu(event) event:Enable(GetEditor() ~= nil) end
@@ -95,17 +94,3 @@ frame:Connect(ID_GOTOLINE, wx.wxEVT_COMMAND_MENU_SELECTED,
end
end)
frame:Connect(ID_GOTOLINE, wx.wxEVT_UPDATE_UI, OnUpdateUISearchMenu)
frame:Connect(ID_SORT, wx.wxEVT_COMMAND_MENU_SELECTED,
function (event)
local editor = GetEditor()
local buf = {}
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
table.insert(buf, line)
end
if #buf > 0 then
table.sort(buf)
editor:ReplaceSelection(table.concat(buf,"\n"))
end
end)
frame:Connect(ID_SORT, wx.wxEVT_UPDATE_UI, OnUpdateUISearchMenu)

View File

@@ -35,11 +35,10 @@ local function togglePanel(event)
end
local function checkPanel(event)
local panel = panels[event:GetId()]
local shown = ide.frame.uimgr:GetPane(panel):IsShown()
if ide.frame.menuBar:IsChecked(event:GetId()) ~= shown then
ide.frame.menuBar:Check(event:GetId(), shown)
end
local menubar = ide.frame.menuBar
local pane = ide.frame.uimgr:GetPane(panels[event:GetId()])
menubar:Enable(event:GetId(), pane:IsOk()) -- disable if doesn't exist
menubar:Check(event:GetId(), pane:IsOk() and pane:IsShown())
end
frame:Connect(ID_VIEWDEFAULTLAYOUT, wx.wxEVT_COMMAND_MENU_SELECTED,

View File

@@ -19,7 +19,7 @@ errorlog:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.font.oNormal)
errorlog:SetBufferedDraw(not ide.config.hidpi and true or false)
errorlog:StyleClearAll()
errorlog:SetMarginWidth(1, 16) -- marker margin
errorlog:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL);
errorlog:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL)
errorlog:MarkerDefine(StylesGetMarker("message"))
errorlog:MarkerDefine(StylesGetMarker("prompt"))
errorlog:SetReadOnly(true)
@@ -68,18 +68,18 @@ function DetachChildProcess()
end
function CommandLineRunning(uid)
for pid,custom in pairs(customprocs) do
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(tostring(pid)))) then
return true
for pid, custom in pairs(customprocs) do
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(pid))) then
return pid, custom.proc
end
end
return false
return
end
function CommandLineToShell(uid,state)
for pid,custom in pairs(customprocs) do
if ((pid == uid or custom.uid == uid) and custom.proc and custom.proc.Exists(tonumber(tostring(pid))) )then
if (pid == uid or custom.uid == uid) and custom.proc and custom.proc.Exists(tonumber(pid)) then
if (streamins[pid]) then streamins[pid].toshell = state end
if (streamerrs[pid]) then streamerrs[pid].toshell = state end
return true
@@ -111,9 +111,8 @@ local function unHideWindow(pidAssign)
or action == hide and win:is_visible() then
-- use show_async call (ShowWindowAsync) to avoid blocking the IDE
-- if the app is busy or is being debugged
win:show_async(show and winapi.SW_SHOW or winapi.SW_HIDE)
notebook:SetFocus() -- set focus back to the IDE window
pid = nil
win:show_async(action == show and winapi.SW_SHOW or winapi.SW_HIDE)
pid = nil -- indicate that unhiding is done
end
end
end
@@ -305,33 +304,41 @@ local jumptopatterns = {
}
errorlog:Connect(wxstc.wxEVT_STC_DOUBLECLICK,
function()
function(event)
local line = errorlog:GetCurrentLine()
local linetx = errorlog:GetLine(line)
-- try to detect a filename + line
-- in linetx
local fname
local jumpline
local jumplinepos
-- try to detect a filename and line in linetx
local fname, jumpline, jumplinepos
for _,pattern in ipairs(jumptopatterns) do
fname,jumpline,jumplinepos = linetx:match(pattern)
if (fname and jumpline) then
break
end
if (fname and jumpline) then break end
end
if (fname and jumpline) then
LoadFile(fname,nil,true)
local editor = GetEditor()
local name = GetFullPathIfExists(FileTreeGetDir(), fname)
or FileTreeFindByPartialName(fname)
-- fname may include name of executable, as in "path/to/lua: file.lua";
-- strip it and try to find match again if needed
local fixedname = fname:match(": (.+)")
if not name and fixedname then
name = GetFullPathIfExists(FileTreeGetDir(), fixedname)
or FileTreeFindByPartialName(fixedname)
end
local editor = LoadFile(name or fname,nil,true)
if (editor) then
jumpline = tonumber(jumpline)
jumplinepos = tonumber(jumplinepos)
--editor:ScrollToLine(jumpline)
editor:GotoPos(editor:PositionFromLine(math.max(0,jumpline-1)) + (jumplinepos and (math.max(0,jumplinepos-1)) or 0))
editor:GotoPos(editor:PositionFromLine(math.max(0,jumpline-1))
+ (jumplinepos and (math.max(0,jumplinepos-1)) or 0))
editor:SetFocus()
-- doubleclick can set selection, so reset it
errorlog:SetSelection(event:GetPosition(), event:GetPosition())
event:Skip()
end
end
end)

View File

@@ -17,6 +17,18 @@ function PackageEventHandle(event, ...)
return success
end
function PackageEventHandleOnce(event, ...)
local success = PackageEventHandle(event, ...)
-- remove all handlers as they need to be called only once
-- this allows them to be re-installed if needed
for _, package in pairs(ide.packages) do
if type(package[event]) == 'function' then
package[event] = nil
end
end
return success
end
local function PackageEventHandleOne(file, event, ...)
local package = ide.packages[file]
if package and type(package[event]) == 'function' then
@@ -47,9 +59,41 @@ function PackageRegister(file, ...)
return PackageEventHandleOne(file, "onRegister", ...)
end
function ide:GetEditor() return GetEditor() end
function ide:GetEditor(index) return GetEditor(index) end
function ide:GetMenuBar() return self.frame.menuBar end
function ide:GetMainFrame() return self.frame end
function ide:GetDocument(ed) return self.openDocuments[ed:GetId()] end
function ide:GetInterpreter() return self.interpreter end
function ide:GetConfig() return self.config end
function ide:GetOutput() return self.frame.bottomnotebook.errorlog end
function ide:GetEditorNotebook() return self.frame.notebook end
function ide:GetSetting(path, setting)
local settings = self.settings
local curpath = settings:GetPath()
settings:SetPath(path)
local ok, value = settings:Read(setting)
settings:SetPath(curpath)
return ok and value or nil
end
function ide:AddInterpreter(name, interpreter)
self.interpreters[name] = setmetatable(interpreter, ide.proto.Interpreter)
UpdateInterpreters()
end
function ide:RemoveInterpreter(name)
self.interpreters[name] = nil
UpdateInterpreters()
end
function ide:AddSpec(name, spec)
self.specs[name] = spec
UpdateSpecs()
end
function ide:RemoveSpec(name) self.specs[name] = nil end
function ide:AddAPI(type, name, api)
self.apis[type] = self.apis[type] or {}
self.apis[type][name] = api
end
function ide:RemoveAPI(type, name) self.apis[type][name] = nil end

View File

@@ -10,6 +10,9 @@ ide.proto.Document = {__index = {
ide.proto.Plugin = {__index = {
GetName = function(self) return self.name end,
GetFileName = function(self) return self.fname end,
GetConfig = function(self) return ide.config[self.fname] or {} end,
GetSettings = function(self) return SettingsRestorePackage(self.fname) end,
SetSettings = function(self, settings) SettingsSavePackage(self.fname, settings) end,
}}
ide.proto.Interpreter = {__index = {

View File

@@ -212,7 +212,7 @@ function SettingsSaveProjectSession(projdirs)
settings:Write(tostring(i), dir)
local opendocs, params = ProjectConfig(dir)
if opendocs and #opendocs > 0 then
if opendocs then
SettingsSaveFileSession(opendocs, params, listname .. "/" .. tostring(i))
end
end
@@ -220,6 +220,38 @@ function SettingsSaveProjectSession(projdirs)
settings:SetPath(path)
end
function SettingsRestorePackage(package)
local packagename = "/package/"..package
local path = settings:GetPath()
settings:SetPath(packagename)
local outtab = {}
local ismore, key, index = settings:GetFirstEntry("", 0)
while (ismore) do
local couldread, value = settings:Read(key, "")
if couldread then
local ok, res = LoadSafe("return "..value)
if ok then outtab[key] = res
else outtab[key] = nil end
end
ismore, key, index = settings:GetNextEntry(index)
end
settings:SetPath(path)
return outtab
end
function SettingsSavePackage(package, values)
local packagename = "/package/"..package
local path = settings:GetPath()
local mdb = require('mobdebug')
settings:DeleteGroup(packagename)
settings:SetPath(packagename)
for k,v in pairs(values or {}) do
settings:Write(k, mdb.line(v, {comment = false, nocode = true}))
end
settings:SetPath(path)
end
-----------------------------------
local function saveNotebook(nb)
@@ -363,7 +395,7 @@ function SettingsRestoreView()
local panes = frame.uimgr:GetAllPanes()
for _, name in pairs({"stackpanel", "watchpanel"}) do
local pane = frame.uimgr:GetPane(name)
if not layout:find(name) then pane:Float() end
if pane:IsOk() and not layout:find(name) then pane:Float() end
end
-- unfortunately need to explicitly (re-)assign the caption,
-- as it's going to be restored from the config regardless of how
@@ -372,6 +404,20 @@ function SettingsRestoreView()
end
uimgr:Update()
local layoutcur = saveNotebook(frame.bottomnotebook)
local layout = settingsReadSafe(settings,"nbbtmlayout",layoutcur)
if (layout ~= layoutcur) then
loadNotebook(ide.frame.bottomnotebook,layout,
-- treat "Output (running)" same as "Output"
function(name) return
name:match(TR("Output")) or name:match("Output") or name end)
end
-- always select Output tab
local bottomnotebook = frame.bottomnotebook
local index = bottomnotebook:GetPageIndex(bottomnotebook.errorlog)
if index >= 0 then bottomnotebook:SetSelection(index) end
local layoutcur = saveNotebook(frame.notebook)
local layout = settingsReadSafe(settings,"nblayout",layoutcur)
if (layout ~= layoutcur) then
@@ -383,15 +429,9 @@ function SettingsRestoreView()
openDocuments[nb:GetPage(i):GetId()].index = i
end
end
local layoutcur = saveNotebook(frame.bottomnotebook)
local layout = settingsReadSafe(settings,"nbbtmlayout",layoutcur)
if (layout ~= layoutcur) then
loadNotebook(ide.frame.bottomnotebook,layout,
-- treat "Output (running)" same as "Output"
function(name) return
name:match(TR("Output")) or name:match("Output") or name end)
end
local editor = GetEditor()
if editor then editor:SetFocus() end
settings:SetPath(path)
end

View File

@@ -75,10 +75,11 @@ end
local function getInput(line)
local nextMarker = line
local count = out:GetLineCount()
repeat
repeat -- check until we find at least some marker
nextMarker = nextMarker+1
until out:MarkerGet(nextMarker) > 0 -- check until we find at least some marker
until out:MarkerGet(nextMarker) > 0 or nextMarker > count-1
return chomp(out:GetTextRange(out:PositionFromLine(line),
out:PositionFromLine(nextMarker)))
end
@@ -97,7 +98,6 @@ local function getNextHistoryLine(forward, promptText)
else
currentHistory = out:MarkerPrevious(currentHistory-1, PROMPT_MARKER_VALUE)
if currentHistory == -1 then
currentHistory = -1
return ""
end
end
@@ -110,6 +110,26 @@ local function getNextHistoryLine(forward, promptText)
return getInput(currentHistory)
end
local function getNextHistoryMatch(promptText)
local count = out:GetLineCount()
if currentHistory == nil then currentHistory = count end
local current = currentHistory
while true do
currentHistory = out:MarkerPrevious(currentHistory-1, PROMPT_MARKER_VALUE)
if currentHistory == -1 then -- restart search from the last item
currentHistory = count
elseif currentHistory ~= getPromptLine() then -- skip current prompt
local input = getInput(currentHistory)
if input:find(promptText, 1, true) == 1 then return input end
end
-- couldn't find anything and made a loop; get out
if currentHistory == current then return end
end
assert(false, "getNextHistoryMatch coudn't find a proper match")
end
local function shellPrint(marker, ...)
local cnt = select('#',...)
if cnt == 0 then return end -- return if nothing to print
@@ -380,6 +400,28 @@ out:Connect(wx.wxEVT_KEY_DOWN,
local promptText = getPromptText()
setPromptText(getNextHistoryLine(true, promptText))
return
elseif key == wx.WXK_TAB then
-- if we are above the prompt line, then don't move
local promptline = getPromptLine()
if out:GetCurrentLine() < promptline then return end
local promptText = getPromptText()
-- save the position in the prompt text to restore
local pos = out:GetCurrentPos()
local text = promptText:sub(1, positionInLine(promptline))
if #text == 0 then return end
-- find the next match and set the prompt text
local match = getNextHistoryMatch(text)
if match then
setPromptText(match)
-- restore the position to make it easier to find the next match
out:GotoPos(pos)
end
return
elseif key == wx.WXK_ESCAPE then
setPromptText("")
return
elseif key == wx.WXK_LEFT or key == wx.WXK_NUMPAD_LEFT then
if not caretOnPromptLine(true) then return end
elseif key == wx.WXK_BACK then

View File

@@ -18,7 +18,7 @@ if not ide.config.singleinstance then return end
require "socket"
local port = ide.config.singleinstanceport
local delay = tonumber(ide.config.singleinstance) or 1000 -- in ms
local svr = socket.udp()
local success, errmsg = svr:setsockname("127.0.0.1",port) -- bind on local host
@@ -33,7 +33,7 @@ protocol.server.answerok = "Sure. You may now leave."
if success then -- ok, server was started, we are solo
--TODO: if multiple files are to be opened, each file is handled one by one - we could create a single string instead...
ide.idletimer = wx.wxTimer(wx.wxGetApp())
ide.idletimer:Start(200,false)
ide.idletimer:Start(delay,false)
svr:settimeout(0) -- don't block
wx.wxGetApp():Connect(wx.wxEVT_TIMER,function (evt)
if ide.exitingProgram then -- if exiting, terminate the timer loop
@@ -50,9 +50,10 @@ if success then -- ok, server was started, we are solo
svr:sendto(protocol.server.answerok,ip,port)
local filename = msg:match(protocol.client.requestloading:gsub("%%s","(.+)$"))
if filename then
if LoadFile(filename, nil, true)
then RequestAttention()
else DisplayOutput("Can't open requested file '"..filename.."'.\n") end
RequestAttention()
if not LoadFile(filename, nil, true) then
DisplayOutputLn("Can't open requested file '"..filename.."'.")
end
end
end
end

View File

@@ -8,6 +8,7 @@
-- ---------------------------
-- fg foreground - {r,g,b} 0-255
-- bg background - {r,g,b} 0-255
-- sel color of the selected block - {r,g,b} 0-255 (only applies to folds)
-- u underline - boolean
-- b bold - boolean
-- i italic - boolean
@@ -51,7 +52,7 @@ function StylesGetDefault()
sel = {bg = {192, 192, 192}},
caret = {fg = {0, 0, 0}},
caretlinebg = {bg = {240, 240, 230}},
fold = {fg = {90, 90, 80}, bg = {250, 250, 250}},
fold = {fg = {90, 90, 80}, bg = {250, 250, 250}, sel = {90+96, 90, 80}},
whitespace = nil,
-- deprecated; allowed for backward compatibility in case someone does
@@ -94,13 +95,10 @@ local markers = {
}
function StylesGetMarker(marker) return unpack(markers[marker] or {}) end
local function applymarker(editor,marker,clrfg,clrbg)
if (clrfg) then
editor:MarkerSetForeground(marker,clrfg)
end
if (clrbg) then
editor:MarkerSetBackground(marker,clrbg)
end
local function applymarker(editor,marker,clrfg,clrbg,clrsel)
if (clrfg) then editor:MarkerSetForeground(marker,clrfg) end
if (clrbg) then editor:MarkerSetBackground(marker,clrbg) end
if (ide.wxver >= "2.9.5" and clrsel) then editor:MarkerSetBackgroundSelected(marker,clrsel) end
end
local specialmapping = {
sel = function(editor,style)
@@ -152,21 +150,25 @@ local specialmapping = {
fold = function(editor,style)
local clrfg = style.fg and wx.wxColour(unpack(style.fg))
local clrbg = style.bg and wx.wxColour(unpack(style.bg))
local clrsel = style.sel and wx.wxColour(unpack(style.sel))
if (clrfg or clrbg) then
-- if selected background is set then enable support for it
if ide.wxver >= "2.9.5" and clrsel then editor:MarkerEnableHighlight(true) end
if (clrfg or clrbg or clrsel) then
-- foreground and background are defined as opposite to what I'd expect
-- for fold markers in Scintilla's terminilogy:
-- background is the color of fold lines/boxes and foreground is the color
-- of everything around fold lines or inside fold boxes.
-- in the following code fg and bg are simply reversed
local clrfg, clrbg = clrbg, clrfg
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPEN, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDER, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERSUB, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERTAIL, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEREND, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPENMID, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, clrfg, clrbg)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPEN, clrfg, clrbg, clrsel)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDER, clrfg, clrbg, clrsel)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERSUB, clrfg, clrbg, clrsel)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERTAIL, clrfg, clrbg, clrsel)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEREND, clrfg, clrbg, clrsel)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPENMID, clrfg, clrbg, clrsel)
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, clrfg, clrbg, clrsel)
end
if clrbg then
-- the earlier calls only color the actual markers, but not the

View File

@@ -45,10 +45,13 @@ ide = {
verbose = false,
hostname = nil,
port = nil,
runonstart = nil,
redirect = nil,
},
default = {
name = 'untitled',
fullname = 'untitled.lua',
interpreter = 'luadeb',
},
outputshell = {},
filetree = {},
@@ -60,7 +63,6 @@ ide = {
styles = nil,
stylesoutshell = nil,
interpreter = "_undefined_",
autocomplete = true,
autoanalizer = true,
@@ -85,7 +87,6 @@ ide = {
},
specs = {
none = {
linecomment = ">",
sep = "\1",
}
},
@@ -93,6 +94,7 @@ ide = {
iofilters = {},
interpreters = {},
packages = {},
apis = {},
proto = {}, -- prototypes for various classes
@@ -147,6 +149,24 @@ if not wx.wxMOD_SHIFT then wx.wxMOD_SHIFT = 0x04 end
-- wxDIR_NO_FOLLOW is missing in wxlua 2.8.12 as well
if not wx.wxDIR_NO_FOLLOW then wx.wxDIR_NO_FOLLOW = 0x10 end
if not setfenv then -- Lua 5.2
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
-- this assumes f is a function
local function findenv(f)
local level = 1
repeat
local name, value = debug.getupvalue(f, level)
if name == '_ENV' then return level, value end
level = level + 1
until name == nil
return nil end
getfenv = function (f) return(select(2, findenv(f)) or _G) end
setfenv = function (f, t)
local level = findenv(f)
if level then debug.setupvalue(f, level, t) end
return f end
end
for _, file in ipairs({"ids", "style", "keymap", "proto"}) do
dofile("src/editor/"..file..".lua")
end
@@ -157,12 +177,12 @@ ide.config.stylesoutshell = StylesGetDefault()
local function setLuaPaths(mainpath, osname)
-- use LUA_DEV to setup paths for Lua for Windows modules if installed
local luadev = osname == "Windows" and os.getenv('LUA_DEV')
local luadev_path = (luadev
local luadev_path = (luadev and wx.wxDirExists(luadev)
and ('LUA_DEV/?.lua;LUA_DEV/?/init.lua;LUA_DEV/lua/?.lua;LUA_DEV/lua/?/init.lua')
:gsub('LUA_DEV', (luadev:gsub('[\\/]$','')))
or "")
local luadev_cpath = (luadev
and ('LUA_DEV/?.dll;LUA_DEV/clibs/?.dll')
local luadev_cpath = (luadev and wx.wxDirExists(luadev)
and ('LUA_DEV/?.dll;LUA_DEV/?51.dll;LUA_DEV/clibs/?.dll;LUA_DEV/clibs/?51.dll')
:gsub('LUA_DEV', (luadev:gsub('[\\/]$','')))
or "")
@@ -255,10 +275,7 @@ local function loadPackages(filter)
for fname, package in pairs(ide.packages) do package.fname = fname end
end
-- load specs
local function loadSpecs(filter)
loadToTab(filter or "specs", "spec", ide.specs, true)
function UpdateSpecs()
for _, spec in pairs(ide.specs) do
spec.sep = spec.sep or "\1" -- default separator doesn't match anything
spec.iscomment = {}
@@ -284,6 +301,12 @@ local function loadSpecs(filter)
end
end
-- load specs
local function loadSpecs(filter)
loadToTab(filter or "specs", "spec", ide.specs, true)
UpdateSpecs()
end
-- temporarily replace print() to capture reported error messages to show
-- them later in the Output window after everything is loaded.
local resumePrint do
@@ -360,7 +383,7 @@ loadSpecs()
loadTools()
do
local home = os.getenv("HOME")
local home = os.getenv("HOME") or (iswindows and (os.getenv('HOMEDRIVE')..os.getenv('HOMEPATH')))
ide.configs = {
system = MergeFullPath("cfg", "user.lua"),
user = home and MergeFullPath(home, ".zbstudio/user.lua"),
@@ -374,7 +397,7 @@ do
for _, v in ipairs(configs) do addConfig(v, true) end
configs = nil
local sep = string_Pathsep
local sep = GetPathSeparator()
if ide.config.language then
LoadLuaFileExt(ide.config.messages, "cfg"..sep.."i18n"..sep..ide.config.language..".lua")
end
@@ -387,7 +410,7 @@ loadPackages()
for _, file in ipairs({
"markup", "settings", "singleinstance", "iofilters",
"gui", "filetree", "output", "debugger", "package",
"package", "gui", "filetree", "output", "debugger",
"editor", "findreplace", "commands", "autocomplete", "shellbox",
"menu_file", "menu_edit", "menu_search",
"menu_view", "menu_project", "menu_tools", "menu_help",
@@ -418,7 +441,13 @@ SettingsRestoreView()
do
for _, fileName in ipairs(filenames) do
if fileName ~= "--" then
LoadFile(fileName, nil, true)
if wx.wxDirExists(fileName) then
local dir = wx.wxFileName.DirName(fileName)
dir:Normalize() -- turn into absolute path if needed
ProjectUpdateProjectDir(dir:GetFullPath())
else
LoadFile(fileName, nil, true)
end
end
end
@@ -438,6 +467,8 @@ end
resumePrint()
PackageEventHandle("onAppLoad")
ide.frame:Show(true)
wx.wxGetApp():MainLoop()

View File

@@ -28,13 +28,14 @@ function HasBit(value, num)
return true
end
-- ASCII values for common chars
char_CR = string.byte("\r")
char_LF = string.byte("\n")
char_Tab = string.byte("\t")
char_Sp = string.byte(" ")
function GetPathSeparator()
return string.char(wx.wxFileName.GetPathSeparator())
end
string_Pathsep = string.char(wx.wxFileName.GetPathSeparator())
do
local sep = GetPathSeparator()
function IsDirectory(dir) return dir:find(sep.."$") end
end
function StripCommentsC(tx)
local out = ""
@@ -121,9 +122,6 @@ function PrependStringToArray(t, s, maxstrings, issame)
if #t > (maxstrings or 15) then table.remove(t, #t) end -- keep reasonable length
end
-- ----------------------------------------------------------------------------
-- Get file modification time, returns a wxDateTime (check IsValid) or nil if
-- the file doesn't exist
function GetFileModTime(filePath)
if filePath and #filePath > 0 then
local fn = wx.wxFileName(filePath)
@@ -240,6 +238,9 @@ function FileWrite(file, content)
end
function FileRead(file)
-- on OSX "Open" dialog allows to open applications, which are folders
if wx.wxDirExists(file) then return nil, "Can't read directory as file." end
local log = wx.wxLogNull() -- disable error reporting; will report as needed
local file = wx.wxFile(file, wx.wxFile.read)
if not file:IsOpened() then return nil, wx.wxSysErrorMsg() end
@@ -251,7 +252,10 @@ end
function FileRename(file1, file2) return wx.wxRenameFile(file1, file2) end
function FileCopy(file1, file2) return wx.wxCopyFile(file1, file2) end
function FileCopy(file1, file2)
local log = wx.wxLogNull() -- disable error reporting; will report as needed
return wx.wxCopyFile(file1, file2)
end
TimeGet = pcall(require, "socket") and socket.gettime or os.clock
@@ -271,7 +275,7 @@ function pairsSorted(t, f)
return iter
end
function fixUTF8(s, replacement)
function FixUTF8(s, repl)
local p, len, invalid = 1, #s, {}
while p <= len do
if p == s:find("[%z\1-\127]", p) then p = p + 1
@@ -279,13 +283,17 @@ function fixUTF8(s, replacement)
elseif p == s:find( "\224[\160-\191][\128-\191]", p)
or p == s:find("[\225-\236][\128-\191][\128-\191]", p)
or p == s:find( "\237[\128-\159][\128-\191]", p)
or p == s:find("[\238-\239][\128-\191][\128-\191]", p)
or p == s:find( "\240[\144-\191][\128-\191]", p) then p = p + 3
elseif p == s:find("[\241-\243][\128-\191][\128-\191][\128-\191]", p)
or p == s:find("[\238-\239][\128-\191][\128-\191]", p) then p = p + 3
elseif p == s:find( "\240[\144-\191][\128-\191][\128-\191]", p)
or p == s:find("[\241-\243][\128-\191][\128-\191][\128-\191]", p)
or p == s:find( "\244[\128-\143][\128-\191][\128-\191]", p) then p = p + 4
else
s = s:sub(1, p-1)..replacement..s:sub(p+1)
local repl = type(repl) == 'function' and repl(s:sub(p,p)) or repl
s = s:sub(1, p-1)..repl..s:sub(p+1)
table.insert(invalid, p)
-- adjust position/length as the replacement may be longer than one char
p = p + #repl
len = len + #repl - 1
end
end
return s, invalid
@@ -298,6 +306,24 @@ function RequestAttention()
if ide.osname == "Macintosh" then
local cmd = [[osascript -e 'tell application "%s" to activate']]
wx.wxExecute(cmd:format(ide.editorApp:GetAppName()), wx.wxEXEC_ASYNC)
elseif ide.osname == "Windows" then
frame:Raise() -- raise the window
local winapi = require 'winapi'
if winapi then
local pid = winapi.get_current_pid()
local wins = winapi.find_all_windows(function(w)
return w:get_process():get_pid() == pid
and w:get_class_name() == 'wxWindowNR'
end)
if wins and #wins > 0 then
-- found the window, now need to activate it:
-- send some input to the window and then
-- bring our window to foreground (doesn't work without some input)
winapi.send_to_window(0x1B)
for _, w in ipairs(wins) do w:set_foreground() end
end
end
end
end
end
@@ -341,11 +367,20 @@ function LoadLuaFileExt(tab, file, proto)
if not cfgfn then
print(("Error while loading file: '%s'."):format(err))
else
local name = file:match("([a-zA-Z_0-9]+)%.lua$")
local name = file:match("([a-zA-Z_0-9%-]+)%.lua$")
if not name then return end
-- check if os/arch matches to allow packages for different systems
local os, arch = name:match("-(%w+)-?(%w*)")
if os and os:lower() ~= ide.osname:lower()
or arch and #arch > 0 and arch:lower() ~= ide.osarch:lower()
then return end
if os then name = name:gsub("-.*","") end
local success, result = pcall(function()return cfgfn(assert(_G or _ENV))end)
if not success then
print(("Error while processing file: '%s'."):format(result))
elseif name then
else
if (tab[name]) then
local out = tab[name]
for i,v in pairs(result) do
@@ -357,3 +392,18 @@ function LoadLuaFileExt(tab, file, proto)
end
end
end
function LoadSafe(data)
local f, res = loadstring(data)
if not f then return f, res end
local count = 0
debug.sethook(function ()
count = count + 1
if count >= 3 then error("cannot call functions") end
end, "c")
local ok, res = pcall(f)
count = 0
debug.sethook()
return ok, res
end

View File

@@ -2,6 +2,7 @@ local editor = NewFile()
ok(editor, "Open New file.")
ok(editor.assignscache ~= nil, "Auto-complete cache is assigned.")
editor:SetText('') -- use Set/Add to position cursor after added text
editor:AddText([[
local line = '123'
line = line:gsub('1','4')
@@ -24,14 +25,23 @@ ok(limit(10000, function() CreateAutoCompList(editor, "smth:") end),
ok(pcall(CreateAutoCompList, editor, "%1000"),
"Auto-complete doesn't trigger 'invalid capture index' on '%...'.")
editor:SetText('') -- use Set/Add to position cursor after added text
editor:SetText('')
editor:AddText([[
result = result.list[1] --> "does the test" test
result.1
]])
ok(limit(10000, function() CreateAutoCompList(editor, "result.1") end),
"Auto-complete doesn't loop for table index reference.")
"Auto-complete doesn't loop for table index reference 1/2.")
editor:SetText('')
editor:AddText([[
self.popUpObjs = self.undoBuffer[0].sub
self.undoBuffer = self.undoBuffer[0]
self.popUpObjs[popUpNo].]])
ok(limit(10000, function() EditorAutoComplete(editor) end),
"Auto-complete doesn't loop for table index reference 2/2.")
local interpreter = ide:GetInterpreter():GetFileName()
ProjectSetInterpreter("gideros")
@@ -44,6 +54,20 @@ ok(c == 1,
ProjectSetInterpreter(interpreter)
editor:SetText('')
editor:AddText('print(1,io.')
local value
local ULS = editor.UserListShow
editor.UserListShow = function(editor, pos, list) value = list end
EditorAutoComplete(editor)
editor.UserListShow = ULS
ok(value and value:find("close"), "Auto-complete is shown after comma.")
ok(not (CreateAutoCompList(editor, "pri.") or ""):match('print'),
"Auto-complete doesn't offer 'print' after 'pri.'.")
-- cleanup
ide:GetDocument(editor).isModified = false
ClosePage()

18
t/3-tooltip.lua Normal file
View File

@@ -0,0 +1,18 @@
local editor = NewFile()
editor:SetText('print("select")')
-- this is to set proper styles, which are needed for EditorCallTip
editor:Colourise(0, -1)
local value
local CTS = editor.CallTipShow
editor.CallTipShow = function(editor, pos, tip) value = tip end
EditorCallTip(editor, 10)
editor.CallTipShow = CTS
ok(value:find("print") and not value:find("select"),
"Tooltip ignores values in strings.")
-- cleanup
ide:GetDocument(editor).isModified = false
ClosePage()

54
t/4-comment.lua Normal file
View File

@@ -0,0 +1,54 @@
local editor = NewFile()
local line = "246"
local comment = "%-%-"
editor:AddText(([[
1
%s
3]]):format(line))
local findReplace = ide.findReplace
findReplace.findText = line
findReplace:FindString()
ide.frame:ProcessEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
local text = editor:GetText()
ok(text:find(comment..line) and not text:find(comment.."3"),
"One-line selection is commented.")
findReplace.findText = "--"..line
findReplace:FindString()
editor:SetCurrentPos(editor:GetLength())
ide.frame:ProcessEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
text = editor:GetText()
ok(text:find(comment.." "..comment..line) and text:find(comment.."3"),
"Commented and uncommented lines are commented.")
findReplace:FindString()
editor:SetCurrentPos(editor:GetLength())
ide.frame:ProcessEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
text = editor:GetText()
ok(not text:find(comment.." "..comment..line) and not text:find(comment.."3"),
"Multi-line commented text is uncommented.")
editor:SetAnchor(0)
editor:SetCurrentPos(editor:PositionFromLine(2))
ide.frame:ProcessEvent(wx.wxCommandEvent(
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
text = editor:GetText()
ok(text:find(comment.." "..comment..line) and text:find(comment.."1") and not text:find(comment.."3"),
"Selection that ends at the beginning of the line doesn't comment line.")
-- cleanup
ide:GetDocument(editor).isModified = false
ClosePage()

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