Compare commits
364 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb6aa586af | ||
|
|
04d2ef75dc | ||
|
|
46e4704b07 | ||
|
|
eb614b5ea6 | ||
|
|
87d3e4abcd | ||
|
|
428572cf7c | ||
|
|
1b65580088 | ||
|
|
be16e47a36 | ||
|
|
b76a58cb8c | ||
|
|
19f4ebed6f | ||
|
|
4ab661bb8b | ||
|
|
1729aa25b8 | ||
|
|
687ccb3256 | ||
|
|
baad9cf946 | ||
|
|
e662970cc8 | ||
|
|
ea927292f8 | ||
|
|
e90d403bc6 | ||
|
|
01afd985df | ||
|
|
1ef2b3e0e9 | ||
|
|
7f80f36486 | ||
|
|
91ccdd9679 | ||
|
|
4da379693c | ||
|
|
c1cbd949e7 | ||
|
|
10b1e34504 | ||
|
|
df0824d274 | ||
|
|
33b1f79bb8 | ||
|
|
7f2744c4f5 | ||
|
|
1c4de98f98 | ||
|
|
9f392382a7 | ||
|
|
f704baa004 | ||
|
|
762babaaba | ||
|
|
7ae515e6db | ||
|
|
456347e371 | ||
|
|
b82b2782d7 | ||
|
|
933aacc2c9 | ||
|
|
c94b5e9e2e | ||
|
|
61976d2a25 | ||
|
|
996a706c97 | ||
|
|
371dd269b0 | ||
|
|
c16f26a7d9 | ||
|
|
18757f393b | ||
|
|
ca3b2de447 | ||
|
|
929615a7b8 | ||
|
|
689cd8cf85 | ||
|
|
80eab46c3e | ||
|
|
7a40fb8f7f | ||
|
|
813844d052 | ||
|
|
06620745f3 | ||
|
|
1f51d803db | ||
|
|
b7d9c7d2b0 | ||
|
|
d3ce3fb93d | ||
|
|
85418cce0f | ||
|
|
87594dc7e5 | ||
|
|
c68d60a6e9 | ||
|
|
4993b3c20e | ||
|
|
e7ddadedb1 | ||
|
|
b4987b74ab | ||
|
|
52c1133c42 | ||
|
|
e9b345476b | ||
|
|
2594a679f3 | ||
|
|
446dec6768 | ||
|
|
cd926d617e | ||
|
|
d40427155f | ||
|
|
d52a6c155f | ||
|
|
6c300cda97 | ||
|
|
f28d4da053 | ||
|
|
3b4f5c4c0a | ||
|
|
858742bf05 | ||
|
|
d559afd9e2 | ||
|
|
9acec71c7a | ||
|
|
8568f61ba4 | ||
|
|
19133b5a03 | ||
|
|
9a2c161328 | ||
|
|
5c6f2ffae3 | ||
|
|
6714f29302 | ||
|
|
f0b7cff06a | ||
|
|
25589fc45a | ||
|
|
6a7c8e78c0 | ||
|
|
443f936ac6 | ||
|
|
12525ad189 | ||
|
|
69fae9a36c | ||
|
|
725a38b182 | ||
|
|
13c4ca1a2f | ||
|
|
3e68447415 | ||
|
|
63e1e56c28 | ||
|
|
3ace5133bf | ||
|
|
f8491464bd | ||
|
|
01b8eea47b | ||
|
|
e9a42f724a | ||
|
|
63861614c7 | ||
|
|
4bd5b5d329 | ||
|
|
91455261c9 | ||
|
|
3a7df5f5af | ||
|
|
0419e6812b | ||
|
|
cd1b9d7cd2 | ||
|
|
d63dda5e6a | ||
|
|
32f4b8694b | ||
|
|
2dbb6644cb | ||
|
|
649e3c620a | ||
|
|
0e7bb32024 | ||
|
|
96f0f876bf | ||
|
|
58a494931c | ||
|
|
f04160fad1 | ||
|
|
671c62871a | ||
|
|
6a6e7ec770 | ||
|
|
eff4eb8b05 | ||
|
|
2781c0ea00 | ||
|
|
fa507450e4 | ||
|
|
a4f069afc0 | ||
|
|
f3b84edc24 | ||
|
|
ba1c1a678e | ||
|
|
267deea3df | ||
|
|
1089f2619e | ||
|
|
e8c5e7fd78 | ||
|
|
ff6deedf79 | ||
|
|
52c7150e51 | ||
|
|
24555a3b3d | ||
|
|
cc432b65b0 | ||
|
|
8d1cca26a3 | ||
|
|
c077c94371 | ||
|
|
1ba300213d | ||
|
|
3fbf0ef81b | ||
|
|
aced5d1bc3 | ||
|
|
bf072c1685 | ||
|
|
4215054b87 | ||
|
|
cd85d6f2e8 | ||
|
|
6fc448b87c | ||
|
|
d6cda0d677 | ||
|
|
5355234b85 | ||
|
|
700dfe1765 | ||
|
|
1c068c221f | ||
|
|
5679d90bcd | ||
|
|
9b5f6fa67f | ||
|
|
a8060b63cd | ||
|
|
7324afb8e3 | ||
|
|
e209f3f440 | ||
|
|
08ef16a42d | ||
|
|
4fafcff592 | ||
|
|
6e0e3d07e3 | ||
|
|
fb9c0ba0a6 | ||
|
|
1b4f707232 | ||
|
|
1749c54f71 | ||
|
|
e4201b745c | ||
|
|
9c810b3520 | ||
|
|
93d3b69335 | ||
|
|
35617caa0e | ||
|
|
e07ed0a817 | ||
|
|
aeb35ebf6f | ||
|
|
c84bd3222b | ||
|
|
e398a216a8 | ||
|
|
4137b9d88d | ||
|
|
a630dd95c7 | ||
|
|
0b748d6389 | ||
|
|
790f9d5b45 | ||
|
|
43513c9153 | ||
|
|
f58f185850 | ||
|
|
ebbeb107a7 | ||
|
|
e0674f9c9a | ||
|
|
89cafbec45 | ||
|
|
e0f543c262 | ||
|
|
b73526586c | ||
|
|
cc177264f6 | ||
|
|
2f98bc30a6 | ||
|
|
b9374894c9 | ||
|
|
17a995a810 | ||
|
|
35d1bc0f03 | ||
|
|
6f044d8b2e | ||
|
|
735f8492e2 | ||
|
|
4eb57fcbda | ||
|
|
c882b8d0e0 | ||
|
|
ce8552f044 | ||
|
|
6968364c58 | ||
|
|
9ab72209c2 | ||
|
|
c872934157 | ||
|
|
ea2d7c289a | ||
|
|
19ab4df922 | ||
|
|
7dda2c00fd | ||
|
|
3d3ae5ca00 | ||
|
|
28c3b79b8b | ||
|
|
a91bba8bd0 | ||
|
|
ed874063ea | ||
|
|
6259918648 | ||
|
|
0995c5a061 | ||
|
|
f07e42c4b4 | ||
|
|
7e62939df6 | ||
|
|
b57bf55ef0 | ||
|
|
8ed91f76cc | ||
|
|
9e6ec10be9 | ||
|
|
115924d567 | ||
|
|
cc9f9bb49d | ||
|
|
418aef7065 | ||
|
|
0f2e74a098 | ||
|
|
2bc125e616 | ||
|
|
6b349bbef0 | ||
|
|
7fbcb0b6c7 | ||
|
|
adb49b8007 | ||
|
|
fb381eaadb | ||
|
|
8ad9e83b92 | ||
|
|
b8d331b8a9 | ||
|
|
76f6fdade6 | ||
|
|
2fd08a751a | ||
|
|
d5d6247286 | ||
|
|
1af5b5e10c | ||
|
|
4eda473d9f | ||
|
|
58c416e148 | ||
|
|
5787dae35c | ||
|
|
ec1a87f219 | ||
|
|
e9728b2a4a | ||
|
|
a9c7e247fe | ||
|
|
0b0d95b2bf | ||
|
|
32c3723bcc | ||
|
|
9d11df3ebe | ||
|
|
14b6568eb5 | ||
|
|
4d8e5647a6 | ||
|
|
6a3aafc6fa | ||
|
|
8ee608c761 | ||
|
|
120bc5b48b | ||
|
|
f23ca203ca | ||
|
|
a390825676 | ||
|
|
baa76790e5 | ||
|
|
344835bf28 | ||
|
|
b9ecfd9284 | ||
|
|
9175bdd3ed | ||
|
|
e07ac2109a | ||
|
|
77588aa757 | ||
|
|
065a6f933c | ||
|
|
dee316094f | ||
|
|
30bb8c29a6 | ||
|
|
4e66f20078 | ||
|
|
a4c503027a | ||
|
|
3a5ef4b5e4 | ||
|
|
666024a77a | ||
|
|
501ba761a9 | ||
|
|
66cc79a3fe | ||
|
|
a5d5fd729a | ||
|
|
6ad74e09a9 | ||
|
|
87dd7edf61 | ||
|
|
06356f6940 | ||
|
|
a4d423c685 | ||
|
|
32e828088b | ||
|
|
dcfc212bf4 | ||
|
|
790d1a6516 | ||
|
|
bc660522d5 | ||
|
|
3cc29e1301 | ||
|
|
7b87bc3d88 | ||
|
|
837a242bbd | ||
|
|
c2ddc72829 | ||
|
|
045b9ad932 | ||
|
|
f0b007ff75 | ||
|
|
c2022a2d33 | ||
|
|
0c1ef8870e | ||
|
|
22716e9d20 | ||
|
|
34f4564ec0 | ||
|
|
e26db06ede | ||
|
|
7384afa325 | ||
|
|
209756349c | ||
|
|
294d19806b | ||
|
|
2dc5f85dbb | ||
|
|
f2aeebb8f6 | ||
|
|
63cc789959 | ||
|
|
bf19bf7e39 | ||
|
|
776888838b | ||
|
|
29738092e7 | ||
|
|
c8b669bb80 | ||
|
|
398f3dee55 | ||
|
|
54db8d28f0 | ||
|
|
6531ff3c66 | ||
|
|
cd27b14152 | ||
|
|
3da05c2a7e | ||
|
|
df58fadd15 | ||
|
|
48b596af01 | ||
|
|
dc36a0f6da | ||
|
|
a9488870b3 | ||
|
|
924f1ad89a | ||
|
|
bcf0b2ee7b | ||
|
|
74572a9765 | ||
|
|
b445ab7810 | ||
|
|
52e9b1764b | ||
|
|
bcabcc7ea6 | ||
|
|
e0dcf5448a | ||
|
|
f6877667bf | ||
|
|
de491e1876 | ||
|
|
103fdb553c | ||
|
|
575107c2ae | ||
|
|
7dc69a8959 | ||
|
|
3fce412df1 | ||
|
|
d6e1a2f8dd | ||
|
|
b21864a974 | ||
|
|
6108865ed2 | ||
|
|
cb2cb9ff3c | ||
|
|
099f9f92fa | ||
|
|
5449ed237a | ||
|
|
fae664ac0d | ||
|
|
71b4f47159 | ||
|
|
347b53659c | ||
|
|
16f32e0df5 | ||
|
|
171287fac6 | ||
|
|
9d05cd6931 | ||
|
|
a9e847372a | ||
|
|
1eba53cc0e | ||
|
|
c5a0077a01 | ||
|
|
2b07dd1db4 | ||
|
|
28b3380a45 | ||
|
|
564338656d | ||
|
|
29b2e4f5ec | ||
|
|
c7ab3aeb32 | ||
|
|
4b771dafe4 | ||
|
|
71393bd35a | ||
|
|
f7e2697e56 | ||
|
|
608644bd83 | ||
|
|
7563e52aba | ||
|
|
039dde0ccb | ||
|
|
abbde79ab0 | ||
|
|
ead958e603 | ||
|
|
6b7f310cd7 | ||
|
|
451186ac4e | ||
|
|
b8b3b7f0af | ||
|
|
5ee71feac4 | ||
|
|
a2e65e2bbd | ||
|
|
e8ad508021 | ||
|
|
aa2a4fac2b | ||
|
|
d5fda558c1 | ||
|
|
171b98717a | ||
|
|
da07ef0e2c | ||
|
|
6c9e226d67 | ||
|
|
d3884358be | ||
|
|
0ebeee3641 | ||
|
|
bd190d5a4e | ||
|
|
b1f09b9ef0 | ||
|
|
ac556aea34 | ||
|
|
87ab3702fe | ||
|
|
83556f9ab2 | ||
|
|
43c18552c1 | ||
|
|
dc54c76435 | ||
|
|
9a16cd026f | ||
|
|
e4710a16b0 | ||
|
|
ae2e99f6d3 | ||
|
|
c182a19fa5 | ||
|
|
2ddeaf4eb8 | ||
|
|
b4fd071efb | ||
|
|
9344280d5b | ||
|
|
ad037536cd | ||
|
|
d8e8af00b6 | ||
|
|
1e651a97b7 | ||
|
|
c2e49e169f | ||
|
|
6662cb0f5e | ||
|
|
c00d85890a | ||
|
|
c42c9ffb3d | ||
|
|
b5661976eb | ||
|
|
c1e66f8fc2 | ||
|
|
c2715040fe | ||
|
|
fc17dac2a5 | ||
|
|
0dfd8e3ba1 | ||
|
|
acbfd6d81d | ||
|
|
0d268a01e1 | ||
|
|
1e9cbb4633 | ||
|
|
7d3683df98 | ||
|
|
3b10bbbcd2 | ||
|
|
3ea40683c9 | ||
|
|
e6b789131a | ||
|
|
613dec0571 | ||
|
|
36b3692e9e | ||
|
|
59cde2fc8c | ||
|
|
e8027b3b95 |
353
CHANGELOG.md
353
CHANGELOG.md
@@ -1,5 +1,356 @@
|
||||
# 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
|
||||
- Added source code debugging (to support LuaJava and other engines).
|
||||
- Added scope-aware global/local/masked/masking variable highlighting.
|
||||
- Added 'Go To Definition' and 'Rename All Instances'.
|
||||
- Added package/plugin API.
|
||||
- Added Retina display support (can be enabled with `hidpi` option).
|
||||
- Improved auto-complete API with inheritance and table index support.
|
||||
|
||||
### Special thanks
|
||||
- To George Pimm for line of code navigation in the Stack Window.
|
||||
- To Fringale for updated French translation.
|
||||
- To Tom Burgel for LuaForWindows interpreter.
|
||||
|
||||
### Improvements
|
||||
- Added sorting of file lists on Linux (used in the filetree and file search).
|
||||
- Added LuaForWindows interpreter (thanks to Tom Burgel).
|
||||
- Added package onEditorCharAdded/onEditorKeyDown events (ref #166).
|
||||
- Added support for changing the Corona simulator skin (closes #151).
|
||||
- Added inheritance support for auto-complete API.
|
||||
- Added package onEditor* events (closes #166).
|
||||
- Added package onInterpreterLoad/onInterpreterClose events (ref #166).
|
||||
- Added package onProjectLoad/onProjectClose events (ref #166).
|
||||
- Added package onMenu* events (ref #166).
|
||||
- Added package onRegister/onUnRegister events (ref #166).
|
||||
- Added 'Show Location' to the Project/Filetree menu.
|
||||
- Added `hidpi` option to enable HiDPI/Retina display support (closes #160).
|
||||
- Added breakpoint support for unnamed code fragments.
|
||||
- Added support for debugging (stepping through) unnamed code fragments.
|
||||
- Added LuaSec to win32 build script.
|
||||
- Added package/plugin processing.
|
||||
- Added support for 'silent' execution of shell commands in markup.
|
||||
- Added `Find Next/Previous` over selected variable instances (ref #163).
|
||||
- Added `debugger.allowediting` option to allow editing while debugging.
|
||||
- Added skiping binary files during file search (ref #162).
|
||||
- Added yield to update search results during file search (ref #162).
|
||||
- Added showing default extensions in the file search (ref #162).
|
||||
- Added support for multiple file extensions in the file search (ref #162).
|
||||
- Added saving folder to search files in (ref #162).
|
||||
- Added selecting all instances with a double-click on a variable.
|
||||
- Added `autoanalizer` option for dynamic static analysis.
|
||||
- Added 'Go To Definition' and 'Rename All Instances'.
|
||||
- Added initial support for indicating local/global variables.
|
||||
- Added showing tooltip in any position over a term and showing 'values' (ref #101).
|
||||
- Added disabling tooltip when context menu is shown.
|
||||
- Added 'fixing' path returned by wxDirDialog; may be incorrect in 2.9.x.
|
||||
- Added constant initialization missing on ArchLinux with wxlua 2.8.12.2 (fixes #155; ref #128).
|
||||
- Added support for table valuetypes in auto-complete for `foo[index]:` (ref #101).
|
||||
- Added navigation to the line of code in the Stack Window (thanks to George Pimm; closes #134).
|
||||
- Added `Show Location` to the editor tab menu.
|
||||
- Added support for absolute filenames in Markdown links.
|
||||
- Allowed tab width and indentation to be set independently.
|
||||
- Allowed closing editor tabs while debugger is running.
|
||||
- Disabled following symlinks during directory scanning to avoid infinite loops.
|
||||
- Disabled showing tooltip when the app is in the background (fixes #158).
|
||||
- Disabled 'value' tooltip over variables that match known function names (ref #101).
|
||||
- Improved error reporting in interpreters on failures to copy the debugger.
|
||||
- Improved focus on the debugger when a breakpoint hits on OSX (fixes #141).
|
||||
- Removed sorting in the Stack view to keep the order of table elements.
|
||||
- Set default directory for Find in Files opened from a new file (#ref 162).
|
||||
- Updated configuration example for variable indicators.
|
||||
- Updated Stack view navigation to use clicked on instead of active item.
|
||||
- Updated Gideros API/auto-complete reference.
|
||||
- Updated markup to allow opening files from new buffers ('untitled').
|
||||
- Updated build scripts to use luasocket 2.0.3.
|
||||
- Updated linux build files to use latest zlib/libpng to fix png load on Gentoo.
|
||||
- Updated 'Find in Files' to start in the project folder by default.
|
||||
- Updated French translation with latest string changes (mostly for find/replace dialogs).
|
||||
- Updated Marmalade Quick auto-complete API to use class inheritance.
|
||||
- Updated Gideros auto-complete API to use class inheritance.
|
||||
- Upgraded Mobdebug to 0.534 for debugging of source code fragments.
|
||||
|
||||
### Fixes
|
||||
- Fixed looping in auto-complete when indexes are used (fixes #143).
|
||||
- Fixed possible duplicate paths in the filetree.
|
||||
- Fixed missing numerical keys in serialized tables (upgraded Mobdebug to 0.535).
|
||||
- Fixed styling of markup that can be affected by folded lines.
|
||||
- Fixed value selection with multiple active selections.
|
||||
- Fixed style compatibility with wxwidgets 2.8 (ref #128).
|
||||
- Fixed error reporting by (internal) file operations.
|
||||
- Fixed styling comments that start with markup symbols.
|
||||
- Fixed restoring a session with one of the files deleted on disk (fixes #161).
|
||||
- Fixed reporting variable instances for comment/string fragments.
|
||||
- Fixed 'Rename Instances' to always reset previous selection.
|
||||
- Fixed auto-complete error for '%dddd' strings (fixes #156).
|
||||
- Fixed an issue with showing filenames that include '"?*:<>' on OSX/Linux.
|
||||
- Fixed current line marker being shown using 'Run as Scratchpad' with 'runonstart' option.
|
||||
- Fixed looping in auto-complete (fixes #151).
|
||||
- Fixed incorrect localization that led to an error in 'Save' from tab menu.
|
||||
|
||||
## v0.37 (May 09 2013)
|
||||
|
||||
### Highlights
|
||||
- Added Marmalade Quick auto-complete support and API documentation.
|
||||
- Added full Marmalade Quick debugging support (requires Quick 1.1+).
|
||||
- Improved Find/Replace behavior and functionality.
|
||||
- Added Recent File history navigation.
|
||||
- Added Preferences menu to simplify access to system/user settings.
|
||||
|
||||
### Special thanks
|
||||
- To Samuel Dionne-Riel for wxwidgets 2.8 compatibility updates.
|
||||
- To Mat Hopwood for assistance with Marmalade Quick integration.
|
||||
|
||||
### Improvements
|
||||
- Added Preferences menu to simplify access to system/user settings.
|
||||
- Added Russian translation for Find/Replace dialog and (ref #70).
|
||||
- Added Russian translation for the Preferences menu (ref #70).
|
||||
- Added 'shaking' Find/Replace window when text is not found (closes #146).
|
||||
- Added 'wlua' to the list of recognized Lua extensions.
|
||||
- Added disabling Recent Files menu if the list is empty.
|
||||
- Added TomorrowContrast color scheme (thanks to Sergey Lerg).
|
||||
- Added detaching a child process to avoid crash when exiting during debugging.
|
||||
- Added Recent File history navigation (closes #66).
|
||||
- Added Marmalade auto-complete support and API documentation.
|
||||
- Added processing of `runonstart` when using remote debugging (closes #138).
|
||||
- Added suggesting proper extension after 'Save/Save As' based on current spec.
|
||||
- Added translation setup for Find/Replace dialog (closes #133).
|
||||
- Added `nomousezoom` option to disable zoom with mouse wheel in the editor.
|
||||
- Added selecting text and Cmd-F shortcut in Find dialog on OSX (ref #127).
|
||||
- Improved file activation when debugging is started (closes #137).
|
||||
- Reduced the minimum size of the Output/Console panel.
|
||||
- Refactored Recent Files history to make it faster and simpler.
|
||||
- Refactored and optimized directory scanning when loading IDE files.
|
||||
- Separated settings for function dropdown and project tree fonts (fixes #148).
|
||||
- Updated documentation about default EOL on OSX (ref #102).
|
||||
- Updated highlighting in Watch windows to not use editor styles.
|
||||
- Updated documentation for user settings (ref #113, #55).
|
||||
- Updated Monokai color scheme to fix current line color.
|
||||
|
||||
### Incompatibilities
|
||||
- (dev) `FileSysGet` has been replaced with `FileSysGetRecursive` with a different signature.
|
||||
|
||||
### Fixes
|
||||
- Fixed hiding all panels when switching to Full Screen mode.
|
||||
- Fixed loading a non-existing file.
|
||||
- Fixed activation of non-existing files/folders in the Project tree.
|
||||
- Fixed search results for lines without newline.
|
||||
- Fixed Find/Replace in folders with Unicode names (fixes #147); improved performance.
|
||||
- Fixed Un/Comment commands executed for empty lines.
|
||||
- Fixed fold/unfold for files starting with block/comment.
|
||||
- Fixed history after activating non-existing file in Recent Files.
|
||||
- Fixed scrolling to restored cursor position on OSX (when `usewrap` = false).
|
||||
- Fixed Find/Replace dialog to take Enter on OSX (fixes #140).
|
||||
- Fixed 'breaking' after executing OUT command that never reaches the target level.
|
||||
- Fixed stopping at a breakpoint at the initial line when `startwith` option is specified.
|
||||
- Fixed activation of a file loaded into active tab.
|
||||
- Fixed incorrect tab activation on OSX after using 'Open File'.
|
||||
- Fixed editor activation when file is loaded into an existing tab.
|
||||
- Fixed an error after opening non-existing file from 'Recent Files'.
|
||||
- Fixed blocking on reading app output without processing other events.
|
||||
- Fixed an issue with duplicate lines shown in the editor.
|
||||
- Fixed 'Replace All' to take 'Wrap Around' into account (fixes #132).
|
||||
- Fixed off-by-one error in searching consecutive matches.
|
||||
- Fixed 'Quick Find' not working without current selection (fixes #131).
|
||||
- Fixed looping in auto-complete on mistyped class (fixes #130).
|
||||
- Fixed compatibility with wx2.8 (thanks to Samuel Dionne-Riel; closes #128).
|
||||
- Fixed replacement logic in Find/Replace that could replace selected fragment (ref #127).
|
||||
- Fixed an error caused by allowing multiple Search/Replace windows (fixes #127).
|
||||
|
||||
## v0.361 (Apr 12 2013)
|
||||
|
||||
### Improvements
|
||||
- Added handling of Ctrl-Home and Ctrl-End on OSX (ref #89).
|
||||
- Added line copy/cut for Ctrl-C/Ctrl-X with no selection.
|
||||
- Updated About screen to be more configurable and flexible.
|
||||
- Updated Russian translation (thanks to toiffel).
|
||||
|
||||
### Fixes
|
||||
- Fixed launch command for Corona debugging on Windows.
|
||||
- Fixed 'control' check on OSX that changed with wx2.9.2+ (ref #89).
|
||||
- Fixed wrong tab activated on OSX after using New file in some cases.
|
||||
- Fixed cursor not being visible in some cases after file is loaded (ref #116).
|
||||
|
||||
## v0.36 (Apr 08 2013)
|
||||
|
||||
### Highlights
|
||||
@@ -252,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
64
LICENSE
@@ -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 ]]---------------------------------------------------
|
||||
|
||||
|
||||
25
README.md
25
README.md
@@ -20,6 +20,12 @@ MobileLua, GSL-shell, and others). It originated from the [Estrela Editor](http:
|
||||
- config (cfg/): contains style and basic editor settings;
|
||||
- tools (tools/): additional tools (e.g. DirectX/Cg shader compiler...).
|
||||
|
||||
## Documentation
|
||||
|
||||
* A [short and simple overview](http://studio.zerobrane.com/doc-getting-started.html) for those who are new to this development environment.
|
||||
* A list of [frequently asked questions](http://studio.zerobrane.com/doc-faq.html) about the IDE.
|
||||
* [Tutorials and demos](http://studio.zerobrane.com/tutorials.html) that cover debugging and live coding for different environments.
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||
@@ -31,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
|
||||
```
|
||||
|
||||
@@ -52,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
|
||||
|
||||
|
||||
@@ -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
60
api/hlsl/dx11.lua
Normal 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
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
2014
api/lua/gideros.lua
2014
api/lua/gideros.lua
File diff suppressed because it is too large
Load Diff
4467
api/lua/glewgl.lua
4467
api/lua/glewgl.lua
File diff suppressed because it is too large
Load Diff
2506
api/lua/marmalade.lua
Normal file
2506
api/lua/marmalade.lua
Normal file
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
BIN
bin/clibs52/mime/core.dll
Normal file
Binary file not shown.
BIN
bin/clibs52/mime/core.dylib
Normal file
BIN
bin/clibs52/mime/core.dylib
Normal file
Binary file not shown.
BIN
bin/clibs52/socket/core.dll
Normal file
BIN
bin/clibs52/socket/core.dll
Normal file
Binary file not shown.
BIN
bin/clibs52/socket/core.dylib
Normal file
BIN
bin/clibs52/socket/core.dylib
Normal file
Binary file not shown.
BIN
bin/liblua.dylib
BIN
bin/liblua.dylib
Binary file not shown.
BIN
bin/liblua52.dylib
Normal file
BIN
bin/liblua52.dylib
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/linux/x64/clibs52/mime/core.so
Normal file
BIN
bin/linux/x64/clibs52/mime/core.so
Normal file
Binary file not shown.
BIN
bin/linux/x64/clibs52/socket/core.so
Normal file
BIN
bin/linux/x64/clibs52/socket/core.so
Normal file
Binary file not shown.
Binary file not shown.
BIN
bin/linux/x64/lua52
Executable file
BIN
bin/linux/x64/lua52
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/linux/x86/clibs52/mime/core.so
Normal file
BIN
bin/linux/x86/clibs52/mime/core.so
Normal file
Binary file not shown.
BIN
bin/linux/x86/clibs52/socket/core.so
Normal file
BIN
bin/linux/x86/clibs52/socket/core.so
Normal file
Binary file not shown.
Binary file not shown.
BIN
bin/linux/x86/lua52
Executable file
BIN
bin/linux/x86/lua52
Executable file
Binary file not shown.
@@ -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
BIN
bin/lua.app/Contents/MacOS/lua52
Executable file
Binary file not shown.
BIN
bin/lua.exe
BIN
bin/lua.exe
Binary file not shown.
BIN
bin/lua51.dll
BIN
bin/lua51.dll
Binary file not shown.
BIN
bin/lua52.dll
Normal file
BIN
bin/lua52.dll
Normal file
Binary file not shown.
BIN
bin/lua52.exe
Normal file
BIN
bin/lua52.exe
Normal file
Binary file not shown.
@@ -24,20 +24,20 @@ BUILD_FLAGS="-O2 -shared -s -I $INSTALL_DIR/include -L $INSTALL_DIR/lib $FPIC"
|
||||
WXWIDGETS_BASENAME="wxWidgets"
|
||||
WXWIDGETS_URL="http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk"
|
||||
|
||||
LIBPNG_BASENAME="libpng-1.6.0"
|
||||
LIBPNG_BASENAME="libpng-1.6.2"
|
||||
LIBPNG_FILENAME="$LIBPNG_BASENAME.tar.gz"
|
||||
LIBPNG_URL="http://sourceforge.net/projects/libpng/files/libpng16/1.6.0/libpng-1.6.0.tar.gz/download"
|
||||
LIBPNG_URL="http://sourceforge.net/projects/libpng/files/libpng16/1.6.2/libpng-1.6.2.tar.gz/download"
|
||||
|
||||
LUA_BASENAME="lua-5.1.5"
|
||||
LUA_FILENAME="$LUA_BASENAME.tar.gz"
|
||||
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
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"
|
||||
|
||||
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.2"
|
||||
LUASOCKET_FILENAME="$LUASOCKET_BASENAME.tar.gz"
|
||||
LUASOCKET_URL="http://files.luaforge.net/releases/luasocket/luasocket/luasocket-2.0.2/$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
|
||||
@@ -48,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
|
||||
;;
|
||||
@@ -100,23 +106,52 @@ 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
|
||||
wget -c "$LIBPNG_URL" -O "$LIBPNG_FILENAME" || { echo "Error: failed to download lbpng"; exit 1; }
|
||||
wget -c "$LIBPNG_URL" -O "$LIBPNG_FILENAME" || { echo "Error: failed to download libpng"; exit 1; }
|
||||
tar -xzf "$LIBPNG_FILENAME"
|
||||
(cd "$LIBPNG_BASENAME"; ./configure --with-libpng-prefix=wxpng_; make $MAKEFLAGS)
|
||||
|
||||
wget -c "$ZLIB_URL" -O "$ZLIB_FILENAME" || { echo "Error: failed to download zlib"; exit 1; }
|
||||
tar -xzf "$ZLIB_FILENAME"
|
||||
(cd "$ZLIB_BASENAME"; ./configure; make $MAKEFLAGS)
|
||||
|
||||
svn co "$WXWIDGETS_URL" "$WXWIDGETS_BASENAME" || { echo "Error: failed to checkout wxWidgets"; exit 1; }
|
||||
# replace src/png with the libpng folder
|
||||
rm -rf "$WXWIDGETS_BASENAME/src/png"
|
||||
mv "$LIBPNG_BASENAME" "$WXWIDGETS_BASENAME/src/png"
|
||||
|
||||
# replace src/zlib with the zlib folder
|
||||
rm -rf "$WXWIDGETS_BASENAME/src/zlib"
|
||||
mv "$ZLIB_BASENAME" "$WXWIDGETS_BASENAME/src/zlib"
|
||||
|
||||
cd "$WXWIDGETS_BASENAME"
|
||||
./configure --prefix="$INSTALL_DIR" --disable-debug --disable-shared --enable-unicode \
|
||||
--with-libjpeg=builtin --with-libpng=builtin --with-libtiff=no --with-expat=no \
|
||||
--with-zlib=builtin --disable-richtext --with-gtk=2 \
|
||||
CFLAGS="-Os -fPIC" CXXFLAGS="-Os -fPIC"
|
||||
# update gzio to gzlib as this has changed between zlib 1.2.3 to 1.2.8
|
||||
sed -i 's/gzio.c/gzlib.c/' Makefile
|
||||
make $MAKEFLAGS || { echo "Error: failed to build wxWidgets"; exit 1; }
|
||||
make install
|
||||
cd ..
|
||||
@@ -128,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
|
||||
@@ -143,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 \
|
||||
@@ -157,34 +203,33 @@ fi
|
||||
|
||||
# build LuaSocket
|
||||
if [ $BUILD_LUASOCKET ]; then
|
||||
wget -c "$LUASOCKET_URL" -O "$LUASOCKET_FILENAME" || { echo "Error: failed to download LuaSocket"; exit 1; }
|
||||
tar -xzf "$LUASOCKET_FILENAME"
|
||||
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
|
||||
|
||||
@@ -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.2"
|
||||
LUASOCKET_FILENAME="$LUASOCKET_BASENAME.tar.gz"
|
||||
LUASOCKET_URL="http://files.luaforge.net/releases/luasocket/luasocket/luasocket-2.0.2/$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"
|
||||
@@ -151,39 +194,41 @@ fi
|
||||
|
||||
# build LuaSocket
|
||||
if [ $BUILD_LUASOCKET ]; then
|
||||
wget -c "$LUASOCKET_URL" -O "$LUASOCKET_FILENAME" || { echo "Error: failed to download LuaSocket"; exit 1; }
|
||||
tar -xzf "$LUASOCKET_FILENAME"
|
||||
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
|
||||
|
||||
@@ -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,20 @@ 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.2"
|
||||
LUASOCKET_FILENAME="$LUASOCKET_BASENAME.tar.gz"
|
||||
LUASOCKET_URL="http://files.luaforge.net/releases/luasocket/luasocket/luasocket-2.0.2/$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"
|
||||
OPENSSL_URL="http://www.openssl.org/source/$OPENSSL_FILENAME"
|
||||
|
||||
LUASEC_BASENAME="luasec-0.4.1"
|
||||
LUASEC_FILENAME="$LUASEC_BASENAME.zip"
|
||||
LUASEC_URL="https://github.com/brunoos/luasec/archive/$LUASEC_FILENAME"
|
||||
|
||||
WINAPI_BASENAME="winapi"
|
||||
WINAPI_URL="https://github.com/stevedonovan/winapi.git"
|
||||
@@ -36,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
|
||||
;;
|
||||
@@ -51,12 +65,20 @@ for ARG in "$@"; do
|
||||
luasocket)
|
||||
BUILD_LUASOCKET=true
|
||||
;;
|
||||
luasec)
|
||||
BUILD_LUASEC=true
|
||||
;;
|
||||
winapi)
|
||||
BUILD_WINAPI=true
|
||||
;;
|
||||
zbstudio)
|
||||
BUILD_ZBSTUDIO=true
|
||||
;;
|
||||
debug)
|
||||
WXLUASTRIP=""
|
||||
WXWIDGETSDEBUG="--enable-debug=max --enable-debug_gdb"
|
||||
WXLUABUILD="Debug"
|
||||
;;
|
||||
all)
|
||||
BUILD_WXWIDGETS=true
|
||||
BUILD_LUA=true
|
||||
@@ -105,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"
|
||||
@@ -125,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
|
||||
@@ -140,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"
|
||||
@@ -159,24 +219,51 @@ fi
|
||||
|
||||
# build LuaSocket
|
||||
if [ $BUILD_LUASOCKET ]; then
|
||||
wget -c "$LUASOCKET_URL" -O "$LUASOCKET_FILENAME" || { echo "Error: failed to download LuaSocket"; exit 1; }
|
||||
tar -xzf "$LUASOCKET_FILENAME"
|
||||
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
|
||||
|
||||
# build LuaSec
|
||||
if [ $BUILD_LUASEC ]; then
|
||||
# build openSSL
|
||||
wget --no-check-certificate -c "$OPENSSL_URL" -O "$OPENSSL_FILENAME" || { echo "Error: failed to download OpenSSL"; exit 1; }
|
||||
tar -xzf "$OPENSSL_FILENAME"
|
||||
cd "$OPENSSL_BASENAME"
|
||||
bash Configure mingw
|
||||
make
|
||||
make install_sw INSTALLTOP="$INSTALL_DIR"
|
||||
cd ..
|
||||
rm -rf "$OPENSSL_FILENAME" "$OPENSSL_BASENAME"
|
||||
|
||||
# build LuaSec
|
||||
wget --no-check-certificate -c "$LUASEC_URL" -O "$LUASEC_FILENAME" || { echo "Error: failed to download LuaSec"; exit 1; }
|
||||
unzip "$LUASEC_FILENAME"
|
||||
# the folder in the archive is "luasec-luasec-....", so need to fix
|
||||
mv "luasec-$LUASEC_BASENAME" $LUASEC_BASENAME
|
||||
cd "$LUASEC_BASENAME"
|
||||
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/ssl.dll" \
|
||||
src/{timeout.c,buffer.c,io.c,context.c,ssl.c,wsocket.c} -lssl -lcrypto -lws2_32 -lgdi32 -llua51 \
|
||||
|| { echo "Error: failed to build LuaSec"; exit 1; }
|
||||
cp src/{ssl.lua,https.lua} "$INSTALL_DIR/share/lua/5.1"
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/ssl.dll" ] || { echo "Error: luasec.dll isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$LUASEC_FILENAME" "$LUASEC_BASENAME"
|
||||
fi
|
||||
|
||||
# build winapi
|
||||
if [ $BUILD_WINAPI ]; then
|
||||
git clone "$WINAPI_URL" "$WINAPI_BASENAME"
|
||||
@@ -198,19 +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
231
cfg/i18n/cn.lua
Normal 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
236
cfg/i18n/de.lua
Normal 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
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
return {
|
||||
[0] = function(c) return c == 1 and 1 or 2 end, -- plural
|
||||
["traced %d instruction"] = {"traced %d instruction", "traced %d instructions"}, -- src\editor\debugger.lua
|
||||
["%d instance"] = {"%d instance", "%d instances"}, -- src\editor\findreplace.lua
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ return {
|
||||
["&Undo"] = "Deshacer", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&View"] = "Ver", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "Ventana de observaciones", -- src\editor\menu_view.lua
|
||||
["About ZeroBrane Studio"] = "Acerca de ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["About %s"] = "Acerca de %s", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Añadir expresión de observación", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Añadir al borrador", -- src\editor\editor.lua
|
||||
["Add To Scratchpad"] = "Añadir al borrador", -- src\editor\editor.lua
|
||||
["All files"] = "Todos los archivos", -- src\editor\commands.lua
|
||||
["Allow external process to start debugging"] = "Permitir proceso externo para iniciar depuración", -- src\editor\menu_project.lua
|
||||
["Analyze the source code"] = "Analizar el código fuente", -- src\editor\inspect.lua
|
||||
@@ -86,7 +86,7 @@ return {
|
||||
["Error while processing API file: %s"] = "Error mientras se procesaba el archivo de API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while processing configuration file: %s"] = nil, -- src\editor\style.lua
|
||||
["Error"] = "Error", -- src\editor\commands.lua
|
||||
["Evaluate in Console"] = "Evaluar en consola", -- src\editor\editor.lua
|
||||
["Evaluate In Console"] = "Evaluar en consola", -- src\editor\editor.lua
|
||||
["Execute the current project/file and keep updating the code to see immediate results"] = "Ejecutar el proyecto/archivo actual y manteniendo actualizado el código para ver resultados en tiempo real", -- src\editor\menu_project.lua
|
||||
["Execute the current project/file"] = "Ejecutar el proyecto/archivo actual", -- src\editor\menu_project.lua
|
||||
["Execution error"] = "Error de ejecución", -- src\editor\debugger.lua
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
return {
|
||||
[0] = function(c) return c == 1 and 1 or 2 end, -- plural
|
||||
["%d instance"] = {"%d occurrence", "%d occurrences"}, -- src\editor\findreplace.lua
|
||||
["%s event failed: %s"] = "L'événement %s a échoué : %s", -- src\editor\package.lua
|
||||
["&About"] = "À &propos", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "&Ajouter une expression", -- src\editor\debugger.lua
|
||||
["&Break"] = "&Interrompre", -- src\editor\menu_project.lua
|
||||
@@ -8,12 +10,15 @@ return {
|
||||
["&Copy"] = "Co&pier", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Default Layout"] = "Affichage par &défaut", -- src\editor\menu_view.lua
|
||||
["&Delete Watch"] = "&Supprimer une expression", -- src\editor\debugger.lua
|
||||
["&Down"] = "Vers le &bas", -- src\editor\findreplace.lua
|
||||
["&Edit Watch"] = "&Modifier une expression", -- src\editor\debugger.lua
|
||||
["&Edit"] = "É&dition", -- src\editor\menu_edit.lua
|
||||
["&File"] = "&Fichier", -- src\editor\menu_file.lua
|
||||
["&Find"] = "&Rechercher...", -- src\editor\menu_search.lua
|
||||
["&Find All"] = "&Rechercher tout", -- src\editor\findreplace.lua
|
||||
["&Find Next"] = "&Rechercher", -- src\editor\findreplace.lua
|
||||
["&Find"] = "&Rechercher", -- src\editor\menu_search.lua
|
||||
["&Fold/Unfold All"] = "Re&plier/Déplier tout", -- src\editor\menu_edit.lua
|
||||
["&Goto Line"] = "&Aller à la ligne...", -- src\editor\menu_search.lua
|
||||
["&Goto Line"] = "&Aller à la ligne", -- src\editor\menu_search.lua
|
||||
["&Help"] = "Aid&e", -- src\editor\menu_help.lua
|
||||
["&New"] = "&Nouveau", -- src\editor\menu_file.lua
|
||||
["&Open..."] = "&Ouvrir...", -- src\editor\menu_file.lua
|
||||
@@ -21,19 +26,23 @@ return {
|
||||
["&Paste"] = "Co&ller", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Project"] = "&Projet", -- src\editor\menu_project.lua, src\editor\inspect.lua
|
||||
["&Redo"] = "&Rétablir", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Replace"] = "Re&mplacer...", -- src\editor\menu_search.lua
|
||||
["&Replace All"] = "Remplacer &tout", -- src\editor\findreplace.lua
|
||||
["&Replace"] = "Re&mplacer", -- src\editor\findreplace.lua, src\editor\menu_search.lua
|
||||
["&Run"] = "&Exécuter", -- src\editor\menu_project.lua
|
||||
["&Save"] = "&Enregistrer", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Search"] = "&Recherche", -- src\editor\menu_search.lua
|
||||
["&Sort"] = "&Trier", -- src\editor\menu_search.lua
|
||||
["&Stack Window"] = "&Pile d'exécution", -- src\editor\menu_view.lua
|
||||
["&Start Debugger Server"] = "Lancer le &serveur de débogage", -- src\editor\menu_project.lua
|
||||
["&Subdirectories"] = "&Sous-répertoires", -- src\editor\findreplace.lua
|
||||
["&Undo"] = "&Annuler", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Up"] = "Vers le &haut", -- src\editor\findreplace.lua
|
||||
["&View"] = "&Affichage", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "&Expressions espionnes", -- src\editor\menu_view.lua
|
||||
["About ZeroBrane Studio"] = "À propos de ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
[".&bak on Replace"] = ".&bak avant remplacement", -- src\editor\findreplace.lua
|
||||
["About %s"] = "À propos de %s", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Ajouter une expression", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Ajouter au brouillon", -- src\editor\editor.lua
|
||||
["Add To Scratchpad"] = "Ajouter au brouillon", -- src\editor\editor.lua
|
||||
["All files"] = "Tous les fichiers", -- src\editor\commands.lua
|
||||
["Allow external process to start debugging"] = "Autoriser les processus externes à lancer le débogage", -- src\editor\menu_project.lua
|
||||
["Analyze the source code"] = "Analyser le code source", -- src\editor\inspect.lua
|
||||
@@ -49,8 +58,9 @@ return {
|
||||
["Can't run the entry point script ('%s')."] = "Impossible d'exécuter le point d'entrée du script ('%s').", -- src\editor\debugger.lua
|
||||
["Can't start debugging session due to internal error '%s'."] = "Impossible de lancer la session de débogage : erreur interne '%s'.", -- src\editor\debugger.lua
|
||||
["Can't start debugging without an opened file or with the current file not being saved ('%s')."] = "Impossible de lancer le débogage si aucun fichier n'est ouvert ou si le fichier courant n'a pas été enregistré ('%s').", -- src\editor\debugger.lua
|
||||
["Cancel"] = "Annuler", -- src\editor\findreplace.lua
|
||||
["Choose ..."] = "Choisir...", -- src\editor\menu_project.lua
|
||||
["Choose a project directory"] = "Choisissez un répertoire de projet", -- src\editor\menu_project.lua
|
||||
["Choose a project directory"] = "Choisissez un répertoire de projet", -- src\editor\findreplace.lua, src\editor\menu_project.lua
|
||||
["Clear &Dynamic Words"] = "Effacer les mots &dynamiques", -- src\editor\menu_edit.lua
|
||||
["Clear the output window before compiling or debugging"] = "Effacer la fenêtre de sortie avant compilation ou débogage", -- src\editor\menu_project.lua
|
||||
["Close &Other Pages"] = "Fermer les &autres pages", -- src\editor\gui.lua
|
||||
@@ -73,6 +83,7 @@ return {
|
||||
["Debugging session completed (%s)."] = "Session de débogage terminée (%s).", -- src\editor\debugger.lua
|
||||
["Debugging session started in '%s'."] = "Session de débogage démarrée dans '%s'.", -- src\editor\debugger.lua
|
||||
["Debugging suspended at %s:%s (couldn't activate the file)."] = "Débogage interrompu à %s:%s (impossible d'activer le fichier).", -- src\editor\debugger.lua
|
||||
["Directory"] = "Répertoire ", -- src\editor\findreplace.lua
|
||||
["Do you want to reload it?"] = "Voulez-vous le recharger ?", -- src\editor\editor.lua
|
||||
["Do you want to save the changes to '%s'?"] = "Voulez-vous enregistrer les modifications dans '%s' ?", -- src\editor\commands.lua
|
||||
["E&xit"] = "&Quitter", -- src\editor\menu_file.lua
|
||||
@@ -83,7 +94,7 @@ return {
|
||||
["Error while processing API file: %s"] = "Erreur lors de la lecture du fichier d'API : %s", -- src\editor\autocomplete.lua
|
||||
["Error while processing configuration file: %s"] = "Erreur lors de la lecture du fichier de configuration : %s", -- src\editor\style.lua
|
||||
["Error"] = "Erreur", -- src\editor\commands.lua
|
||||
["Evaluate in Console"] = "Évaluer dans la console", -- src\editor\editor.lua
|
||||
["Evaluate In Console"] = "Évaluer dans la console", -- src\editor\editor.lua
|
||||
["Execute the current project/file and keep updating the code to see immediate results"] = "Exécuter le projet/fichier courant en mettant le code à jour afin de voir les résultats en temps réel", -- src\editor\menu_project.lua
|
||||
["Execute the current project/file"] = "Exécuter le projet/fichier courant", -- src\editor\menu_project.lua
|
||||
["Execution error"] = "Erreur d'exécution", -- src\editor\debugger.lua
|
||||
@@ -92,36 +103,46 @@ return {
|
||||
["Expression"] = "Expression", -- src\editor\debugger.lua
|
||||
["File '%s' has been modified on disk."] = "Le fichier '%s' a été modifié sur le disque.", -- src\editor\editor.lua
|
||||
["File '%s' has more recent timestamp than restored '%s'; please review before saving."] = "Le fichier '%s' a un horodatage plus récent que celui restauré '%s' ; veuillez vérifier avant d'enregistrer.", -- src\editor\commands.lua
|
||||
["File '%s' no longer exists."] = "Le fichier '%s' n'existe plus.", -- src\editor\editor.lua
|
||||
["File '%s' no longer exists."] = "Le fichier '%s' n'existe plus.", -- src\editor\editor.lua, src\editor\menu_file.lua
|
||||
["File Type"] = "Type de fichier ", -- src\editor\findreplace.lua
|
||||
["File history"] = "Historique de fichier", -- src\editor\menu_file.lua
|
||||
["Find &In Files"] = "Rec&hercher dans les fichiers...", -- src\editor\menu_search.lua
|
||||
["Find &In Files"] = "Rec&hercher dans les fichiers", -- src\editor\menu_search.lua
|
||||
["Find &Next"] = "Rechercher l'occurrence &suivante", -- src\editor\menu_search.lua
|
||||
["Find &Previous"] = "Rechercher l'occurrence &précédente", -- src\editor\menu_search.lua
|
||||
["Find In Files"] = "Rechercher dans les fichiers", -- src\editor\findreplace.lua
|
||||
["Find and replace text in files"] = "Rechercher et remplacer le texte dans les fichiers", -- src\editor\menu_search.lua
|
||||
["Find and replace text"] = "Rechercher et remplacer le texte", -- src\editor\menu_search.lua, src\editor\gui.lua
|
||||
["Find text in files"] = "Rechercher le texte dans les fichiers", -- src\editor\menu_search.lua
|
||||
["Find text"] = "Rechercher le texte", -- src\editor\menu_search.lua, src\editor\gui.lua
|
||||
["Find the earlier text occurence"] = "Recherche l'occurrence précédente du texte", -- src\editor\menu_search.lua
|
||||
["Find the next text occurrence"] = "Recherche l'occurrence suivante du texte", -- src\editor\menu_search.lua
|
||||
["Find"] = "Rechercher ", -- src\editor\findreplace.lua
|
||||
["Fold or unfold all code folds"] = "Replier ou déplier tous les blocs de code", -- src\editor\menu_edit.lua
|
||||
["Found auto-recovery record and restored saved session."] = "Une récupération automatique a été trouvé et la session a été restaurée.", -- src\editor\commands.lua
|
||||
["Found"] = "Occurrences trouvées :", -- src\editor\findreplace.lua
|
||||
["Full &Screen"] = "&Plein écran", -- src\editor\menu_view.lua
|
||||
["Go To Definition"] = "Aller à la définition", -- src\editor\editor.lua
|
||||
["Go to a selected line"] = "Aller à la ligne sélectionnée", -- src\editor\menu_search.lua
|
||||
["Goto Line"] = "Aller à la ligne", -- src\editor\menu_search.lua
|
||||
["INS"] = "INS", -- src\editor\editor.lua
|
||||
["In Files"] = "Dans les fichiers", -- src\editor\findreplace.lua
|
||||
["Jump to a function definition..."] = "Aller à la définition de fonction...", -- src\editor\editor.lua
|
||||
["Known Files"] = "Fichiers connus", -- src\editor\commands.lua
|
||||
["Ln: %d"] = "Lig : %d", -- src\editor\editor.lua
|
||||
["Local console"] = "Console locale", -- src\editor\shellbox.lua, src\editor\gui.lua
|
||||
["Lua &Interpreter"] = "Interpréteur L&ua", -- src\editor\menu_project.lua
|
||||
["Mapped remote request for '%s' to '%s'."] = "La requête distante pour '%s' a été associée à '%s'.", -- src\editor\debugger.lua
|
||||
["Match &case"] = "Respecter la &casse", -- src\editor\findreplace.lua
|
||||
["Match &whole word"] = "&Mot entier uniquement", -- src\editor\findreplace.lua
|
||||
["Mixed end-of-line encodings detected."] = "Plusieurs codages de fin de ligne détectés.", -- src\editor\commands.lua
|
||||
["OVR"] = "OVR", -- src\editor\editor.lua
|
||||
["Open an existing document"] = "Ouvrir un document existant", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Open file"] = "Ouvrir un fichier", -- src\editor\commands.lua
|
||||
["Options"] = "Options", -- src\editor\findreplace.lua
|
||||
["Output (running)"] = "Sortie (en cours d'exécution)", -- src\editor\output.lua
|
||||
["Output"] = "Sortie", -- src\editor\output.lua, src\editor\settings.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Coller le texte depuis le presse-papiers", -- src\editor\menu_edit.lua
|
||||
["Preferences"] = "Préférences", -- src\editor\menu_edit.lua
|
||||
["Prepend '=' to show complex values on multiple lines."] = "Préfixez par '=' pour afficher les valeurs complexes sur plusieurs lignes.", -- src\editor\shellbox.lua
|
||||
["Press cancel to abort."] = "Cliquez sur Annuler pour annuler.", -- src\editor\commands.lua
|
||||
["Program '%s' started in '%s' (pid: %d)."] = "Programme '%s' démarré dans '%s' (pid : %d).", -- src\editor\output.lua
|
||||
@@ -135,12 +156,18 @@ return {
|
||||
["Project/&FileTree Window"] = "&Explorateur de projet", -- 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"] = "Remp&lacer dans les fichiers...", -- src\editor\menu_search.lua
|
||||
["Re&place In Files"] = "Remp&lacer dans les fichiers", -- src\editor\menu_search.lua
|
||||
["Recent Files"] = "Fichiers récents", -- src\editor\menu_file.lua
|
||||
["Redo last edit undone"] = "Rétablir la dernière modification", -- src\editor\menu_edit.lua
|
||||
["Refused a request to start a new debugging session as there is one in progress already."] = "Une requête de lancement de débogage a été refusée car une session de débogage est déjà en cours.", -- src\editor\debugger.lua
|
||||
["Regular &expression"] = "&Expression régulière", -- src\editor\findreplace.lua
|
||||
["Remote console"] = "Console à distance", -- src\editor\shellbox.lua
|
||||
["Rename All Instances"] = "Renommer toutes les occurrences", -- src\editor\editor.lua
|
||||
["Replace &All"] = "Remplacer &tout", -- src\editor\findreplace.lua
|
||||
["Replace"] = "Remplacer par ", -- src\editor\findreplace.lua
|
||||
["Replaced an invalid UTF8 character with %s."] = "Un caractère UTF8 invalide a été remplacé par %s.", -- src\editor\commands.lua
|
||||
["Replaced"] = "Occurrences remplacées :", -- src\editor\findreplace.lua
|
||||
["Replacing"] = "Remplacement de", -- src\editor\findreplace.lua
|
||||
["Reset to default layout"] = "Restaurer l'affichage par défaut", -- src\editor\menu_view.lua
|
||||
["Resets the dynamic word list for autocompletion"] = "Réinitialiser la liste des mots dynamiques pour l'auto-complétion", -- src\editor\menu_edit.lua
|
||||
["Run as Scratchpad"] = "Exécuter comme brouillon", -- src\editor\menu_project.lua
|
||||
@@ -155,14 +182,19 @@ return {
|
||||
["Save the current document to a file with a new name"] = "Enregistrer le document courant sous un nouveau nom", -- src\editor\menu_file.lua
|
||||
["Save the current document"] = "Enregistrer le document courant", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Saved auto-recover at %s."] = "Récup. auto enregistrée à %s.", -- src\editor\commands.lua
|
||||
["Scope"] = "Direction", -- src\editor\findreplace.lua
|
||||
["Scratchpad error"] = "Erreur dans le brouillon", -- src\editor\debugger.lua
|
||||
["Searching for"] = "Recherche de", -- src\editor\findreplace.lua
|
||||
["Select &All"] = "Sélectionner &tout", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Select all text in the editor"] = "Sélectionner tout le texte dans l'éditeur", -- src\editor\menu_edit.lua
|
||||
["Set From Current File"] = "Définir depuis le fichier courant", -- src\editor\menu_project.lua
|
||||
["Set project directory from current file"] = "Définir le répertoire de projet depuis le fichier courant", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Set the interpreter to be used"] = "Définir l'interpréteur à utiliser", -- src\editor\menu_project.lua
|
||||
["Set the project directory to be used"] = "Définir le répertoire de projet à utiliser", -- src\editor\menu_project.lua
|
||||
["Settings: System"] = "Paramètres : Système", -- src\editor\menu_edit.lua
|
||||
["Settings: User"] = "Paramètres : Utilisateur", -- src\editor\menu_edit.lua
|
||||
["Show &Tooltip"] = "Afficher l'info-&bulle", -- src\editor\menu_edit.lua
|
||||
["Show Location"] = "Afficher l'emplacement", -- src\editor\gui.lua, src\editor\filetree.lua
|
||||
["Show tooltip for current position; place cursor after opening bracket of function"] = "Afficher l'info-bulle pour la position actuelle ; placez le curseur après la parenthèse ouvrante de la fonction", -- src\editor\menu_edit.lua
|
||||
["Sort selected lines"] = "Trier les lignes sélectionnées", -- src\editor\menu_search.lua
|
||||
["Stack"] = "Pile d'exécution", -- src\editor\debugger.lua
|
||||
@@ -176,6 +208,7 @@ return {
|
||||
["Step over"] = "Enjamber l'instruction suivante", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Stop the currently running process"] = "Arrêter le processus en cours d'exécution", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Switch to or from full screen mode"] = "Activer ou désactiver le mode plein écran", -- src\editor\menu_view.lua
|
||||
["Text not found."] = "Texte non trouvé.", -- src\editor\findreplace.lua
|
||||
["The API file must be located in a subdirectory of the API directory."] = "Le fichier d'API doit être placé dans un sous-répertoire du répertoire d'API.", -- src\editor\autocomplete.lua
|
||||
["Toggle Break&point"] = "Créer/Supprimer un &point d'arrêt", -- src\editor\menu_project.lua
|
||||
["Toggle breakpoint"] = "Créer ou supprimer un point d'arrêt", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
@@ -196,7 +229,8 @@ return {
|
||||
["View the watch window"] = "Afficher la fenêtre d'expressions espionnes", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["Watch"] = "Expressions espionnes", -- src\editor\debugger.lua
|
||||
["Welcome to the interactive Lua interpreter."] = "Bienvenue dans l´interpréteur interactif Lua.", -- src\editor\shellbox.lua
|
||||
["Wrap ar&ound"] = "B&oucler", -- src\editor\findreplace.lua
|
||||
["You must save the program first."] = "Vous devez d'abord enregistrer le programme.", -- src\editor\commands.lua
|
||||
["on line %d"] = "à la ligne %d", -- src\editor\debugger.lua, src\editor\commands.lua
|
||||
["on line %d"] = "à la ligne %d", -- src\editor\debugger.lua, src\editor\commands.lua, src\editor\editor.lua
|
||||
["traced %d instruction"] = {"%d instruction tracée", "%d instructions tracées"} -- src\editor\debugger.lua
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ return {
|
||||
["&Undo"] = "Annulla", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&View"] = "Visualizza", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "Finestra Espressioni di Controllo", -- src\editor\menu_view.lua
|
||||
["About ZeroBrane Studio"] = "Informazioni su ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["About %s"] = "Informazioni su %s", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Aggiungi Espressione di Controllo", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Aggiungi a Scratchpad ", -- src\editor\editor.lua
|
||||
["Add To Scratchpad"] = "Aggiungi a Scratchpad ", -- src\editor\editor.lua
|
||||
["All files"] = "Tutti i files", -- src\editor\commands.lua
|
||||
["Allow external process to start debugging"] = "Permetti a processi esterni di avviare il debug", -- src\editor\menu_project.lua
|
||||
["Analyze the source code"] = "Analizza il codice", -- src\editor\inspect.lua
|
||||
@@ -83,7 +83,7 @@ return {
|
||||
["Error while processing API file: %s"] = "Errore durante l'elaborazione del file API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while processing configuration file: %s"] = "Errore durante l'elaborazione del file di configurazione: %s", -- src\editor\style.lua
|
||||
["Error"] = "Errore", -- src\editor\commands.lua
|
||||
["Evaluate in Console"] = "Elabora in console", -- src\editor\editor.lua
|
||||
["Evaluate In Console"] = "Elabora in console", -- src\editor\editor.lua
|
||||
["Execute the current project/file and keep updating the code to see immediate results"] = "Esegue il progetto/file corrente e permette di modificare il codice per vedere i risultati in tempo reale", -- src\editor\menu_project.lua
|
||||
["Execute the current project/file"] = "Esegue il progetto/file corrente", -- src\editor\menu_project.lua
|
||||
["Execution error"] = "Errore di esecuzione", -- src\editor\debugger.lua
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
return {
|
||||
[0] = function(c) return (c%10 == 1 and c%100 ~= 11) and 1 or (c%10 >= 2 and c%10 <= 4 and (c%100 < 10 or c%100 >= 20) and 2) or 3 end, -- plural
|
||||
[0] = function(c) c = (c-9)%100 < 9 and 9 or (c-1)%10 return c == 0 and 1 or c < 4 and 2 or 3 end, -- plural
|
||||
["%d instance"] = {"%d совпадение", "%d совпадения", "%d совпадений"}, -- src\editor\findreplace.lua
|
||||
["&About"] = "&О программе", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "&Добавить выражение", -- src\editor\debugger.lua
|
||||
["&Break"] = "Пр&ервать", -- src\editor\menu_project.lua
|
||||
@@ -8,9 +9,12 @@ return {
|
||||
["&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
|
||||
@@ -21,19 +25,23 @@ return {
|
||||
["&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"] = "За&менить", -- src\editor\menu_search.lua
|
||||
["&Replace All"] = "Заменить всe", -- 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"] = "&Cортировать", -- 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 ZeroBrane Studio"] = "О ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Добавить в окно наблюдения", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Добавить в черновик", -- src\editor\editor.lua
|
||||
["&Watch Window"] = "Окно &выражений", -- src\editor\menu_view.lua
|
||||
[".&bak on Replace"] = ".&bak после замены", -- src\editor\findreplace.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
|
||||
@@ -49,8 +57,9 @@ return {
|
||||
["Can't run the entry point script ('%s')."] = "Ошибка выполнения стартового скрипта ('%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\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
|
||||
@@ -73,6 +82,7 @@ return {
|
||||
["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
|
||||
@@ -83,7 +93,7 @@ return {
|
||||
["Error while processing API file: %s"] = "Ошибка обработки файла определений API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while processing configuration file: %s"] = "Ошибка обработки файла конфигурации: %s", -- src\editor\style.lua
|
||||
["Error"] = "Ошибка", -- src\editor\commands.lua
|
||||
["Evaluate in Console"] = "Выполнить в консоли", -- src\editor\editor.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
|
||||
@@ -92,36 +102,45 @@ return {
|
||||
["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
|
||||
["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"] = "Найти и заменить текст в файлах", -- src\editor\menu_search.lua
|
||||
["Find and replace text"] = "Найти и заменить текст", -- src\editor\menu_search.lua, src\editor\gui.lua
|
||||
["Find text in files"] = "Найти текст в файлах", -- src\editor\menu_search.lua
|
||||
["Find text"] = "Найти текст", -- src\editor\menu_search.lua, src\editor\gui.lua
|
||||
["Find the earlier text occurence"] = "Найти предыдущее вхождение текста", -- src\editor\menu_search.lua
|
||||
["Find the next text occurrence"] = "Найти следующее вхождение текста", -- 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"] = "ВСТ", -- src\editor\editor.lua
|
||||
["In Files"] = "Установки файлов", -- src\editor\findreplace.lua
|
||||
["Jump to a function definition..."] = "Перейти к определению функции...", -- src\editor\editor.lua
|
||||
["Known Files"] = "Файлы Lua", -- 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'."] = nil, -- src\editor\debugger.lua
|
||||
["Mixed end-of-line encodings detected."] = nil, -- src\editor\commands.lua
|
||||
["Mapped remote request for '%s' to '%s'."] = "Удаленный запрос для '%s' отображен на '%s'.", -- src\editor\debugger.lua
|
||||
["Match &case"] = "Совпадение регистра", -- src\editor\findreplace.lua
|
||||
["Match &whole word"] = "Совпадение целого слова", -- src\editor\findreplace.lua
|
||||
["Mixed end-of-line encodings detected."] = "Обнаружены смешанные символы конца строки.", -- src\editor\commands.lua
|
||||
["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"] = "Вставить текст из буфера обмена", -- 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."] = "Нажмите Отмена для завершения.", -- src\editor\commands.lua
|
||||
["Program '%s' started in '%s' (pid: %d)."] = "Программа '%s' запущена в '%s' (pid: %d).", -- src\editor\output.lua
|
||||
@@ -130,7 +149,7 @@ return {
|
||||
["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 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"] = "R/O", -- src\editor\editor.lua
|
||||
@@ -139,8 +158,13 @@ return {
|
||||
["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
|
||||
["Replaced an invalid UTF8 character with %s."] = nil, -- src\editor\commands.lua
|
||||
["Replace &All"] = "Заменить все", -- src\editor\findreplace.lua
|
||||
["Replace"] = "Заменить", -- src\editor\findreplace.lua
|
||||
["Replaced an invalid UTF8 character with %s."] = "Некорректный символ UTF8 заменен на %s.", -- 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"] = "Очистить список динамических слов для автодополнения", -- src\editor\menu_edit.lua
|
||||
["Run as Scratchpad"] = "Запустить как черновик", -- src\editor\menu_project.lua
|
||||
@@ -155,13 +179,17 @@ return {
|
||||
["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"] = "Выделить весь текст в редакторе", -- 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 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
|
||||
["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"] = "Показать &подсказку", -- src\editor\menu_edit.lua
|
||||
["Show tooltip for current position; place cursor after opening bracket of function"] = "Показать подсказку в текущей позиции; переместите курсор в позицию после открывающей скобки функции", -- src\editor\menu_edit.lua
|
||||
["Sort selected lines"] = "Отсортировать выделенные строки", -- src\editor\menu_search.lua
|
||||
@@ -176,7 +204,8 @@ return {
|
||||
["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
|
||||
["The API file must be located in a subdirectory of the API directory."] = "Файл определений API должен быть расположен в подкаталоге каталога API.", -- src\editor\autocomplete.lua
|
||||
["Text not found."] = "Текст не найден.", -- src\editor\findreplace.lua
|
||||
["The API file must be located in a subdirectory of the API directory."] = "Файл определений API должен быть расположен внутри папки 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
|
||||
@@ -186,16 +215,17 @@ return {
|
||||
["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."] = nil, -- src\editor\commands.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' для очистки содержимого окна и истории.", -- 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"] = nil, -- src\editor\debugger.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.", -- 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 инструкция", "выполнено %d инструкции", "выполнено %d инструкций"}, -- src\editor\debugger.lua
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
--[[
|
||||
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')))
|
||||
- [TomorrowNightBlue](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNightBlue')))
|
||||
- [TomorrowNightBright](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNightBright')))
|
||||
- [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()))
|
||||
|
||||
|
||||
@@ -37,6 +37,20 @@ local colors = {
|
||||
Blue = H'4271ae',
|
||||
Purple = H'8959a8',
|
||||
},
|
||||
TomorrowContrast = { -- contributed by Sergey Lerg
|
||||
Background = H'f7f7f7',
|
||||
CurrentLine = H'efefef',
|
||||
Selection = H'd6d6d6',
|
||||
Foreground = H'202020',
|
||||
Comment = H'8e908c',
|
||||
Red = H'4669ff', --numbers
|
||||
Orange = H'f5871f',
|
||||
Yellow = H'eab700',
|
||||
Green = H'108010', --strings
|
||||
Aqua = H'4060b0', --built in functions
|
||||
Blue = H'101080', --keywords
|
||||
Purple = H'a01090',
|
||||
},
|
||||
TomorrowNight = {
|
||||
Background = H'1d1f21',
|
||||
CurrentLine = H'282a2e',
|
||||
@@ -109,7 +123,7 @@ local colors = {
|
||||
},
|
||||
Monokai = {
|
||||
Background = H'272822',
|
||||
CurrentLine = H'49483E',
|
||||
CurrentLine = H'2D2F29',
|
||||
Selection = H'49483E',
|
||||
Foreground = H'F8F8F2',
|
||||
Comment = H'75715E',
|
||||
@@ -121,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',
|
||||
@@ -149,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)
|
||||
@@ -182,15 +224,15 @@ return {
|
||||
-- wxstc.wxSTC_LUA_NUMBER
|
||||
number = {fg = C.Red},
|
||||
|
||||
-- wxstc.wxSTC_LUA_WORD, wxstc.wxSTC_LUA_WORD#
|
||||
-- wxstc.wxSTC_LUA_WORD, wxstc.wxSTC_LUA_WORD2-8
|
||||
keywords0 = {fg = C.Blue, b = true},
|
||||
keywords1 = {fg = C.Aqua, b = false},
|
||||
keywords2 = {fg = C.Aqua, b = true},
|
||||
keywords3 = {fg = C.Purple, b = true},
|
||||
keywords4 = {fg = C.Purple, b = true},
|
||||
keywords5 = {fg = C.Purple, b = true},
|
||||
keywords6 = {fg = C.Purple, b = true},
|
||||
keywords7 = {fg = C.Purple, b = true},
|
||||
keywords3 = {fg = C.Purple, b = false},
|
||||
keywords4 = {fg = C.Purple, b = false},
|
||||
keywords5 = {fg = C.Purple, b = false},
|
||||
keywords6 = {fg = C.Purple, b = false},
|
||||
keywords7 = {fg = C.Purple, b = false},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
-- wxstc.wxSTC_LUA_IDENTIFIER
|
||||
@@ -207,19 +249,26 @@ 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},
|
||||
|
||||
fncall = {fg = C.Purple, st = wxstc.wxSTC_INDIC_PLAIN},
|
||||
--[[ other possible values are:
|
||||
wxSTC_INDIC_PLAIN Single-line underline
|
||||
wxSTC_INDIC_SQUIGGLE Squiggly underline
|
||||
wxSTC_INDIC_TT Line of small T-shapes
|
||||
wxSTC_INDIC_DIAGONAL Diagonal hatching
|
||||
wxSTC_INDIC_STRIKE Strike-out
|
||||
wxSTC_INDIC_BOX Box
|
||||
wxSTC_INDIC_ROUNDBOX Rounded Box
|
||||
--]]
|
||||
indicator = {
|
||||
fncall = {fg = C.Purple, st = wxstc.wxSTC_INDIC_ROUNDBOX},
|
||||
--[[ other possible values are:
|
||||
wxSTC_INDIC_PLAIN Single-line underline
|
||||
wxSTC_INDIC_SQUIGGLE Squiggly underline
|
||||
wxSTC_INDIC_TT Line of small T-shapes
|
||||
wxSTC_INDIC_DIAGONAL Diagonal hatching
|
||||
wxSTC_INDIC_STRIKE Strike-out
|
||||
wxSTC_INDIC_BOX Box
|
||||
wxSTC_INDIC_ROUNDBOX Rounded Box
|
||||
--]]
|
||||
-- these indicators have all different default styles
|
||||
varlocal = {fg = C.Foreground},
|
||||
varglobal = {fg = C.Foreground},
|
||||
varmasked = {fg = C.Foreground},
|
||||
varmasking = {fg = C.Foreground},
|
||||
},
|
||||
|
||||
-- markup
|
||||
['['] = {hs = mixer(C.Comment, 3, 64)},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--[[-- Copy required content from this file to `user.lua`
|
||||
--[[-- This file shows examples of settings you can adjust.
|
||||
|
||||
Configuration files are loaded in the following order:
|
||||
Configuration files with preferences are loaded in the following order:
|
||||
1. cfg/user.lua (system-wide configuration)
|
||||
2. HOME/.zbstudio/user.lua (per-user configuration)
|
||||
3. -cfg <lua code fragment|filename> (command line configuration)
|
||||
@@ -47,7 +47,7 @@ path.lua = 'd:/lua/lua'
|
||||
path.gslshell = [[D:\Lua\gsl-shell\gsl-shell.exe]]
|
||||
|
||||
-- to provide output filter for those engines that support redirecting
|
||||
-- of "print" output to the IDE (like Corona SDK and Gideros)
|
||||
-- of "print" output to the IDE (like Corona SDK or Gideros)
|
||||
debugger.outputfilter = function(m) return #m < 124 and m or m:sub(1,120).."...\n" end
|
||||
|
||||
-- to fix an issue with 0d0d0a line endings in MOAI examples,
|
||||
@@ -95,13 +95,13 @@ styles.marker.prompt = {ch = wxstc.wxSTC_MARK_CHARACTER+('>'):byte(), {0, 0, 0},
|
||||
stylesoutshell = styles
|
||||
|
||||
-- to disable indicators (underlining) on function calls
|
||||
editor.showfncall = false
|
||||
styles.indicator.fncall = nil
|
||||
|
||||
-- to change the color of the indicator used for function calls
|
||||
styles.fncall.fg = {240,0,0}
|
||||
styles.indicator.fncall.fg = {240,0,0}
|
||||
|
||||
-- to change the type of the indicator used for function calls
|
||||
styles.fncall.st = wxstc.wxSTC_INDIC_PLAIN
|
||||
styles.indicator.fncall.st = wxstc.wxSTC_INDIC_PLAIN
|
||||
--[[ other possible values are:
|
||||
wxSTC_INDIC_PLAIN Single-line underline
|
||||
wxSTC_INDIC_SQUIGGLE Squiggly underline
|
||||
@@ -117,8 +117,8 @@ load.specs(function(file) return file:find('spec[/\\]cpp%.lua$') end)
|
||||
|
||||
-- to specify a default EOL encoding to be used for new files:
|
||||
-- `wxstc.wxSTC_EOL_CRLF` or `wxstc.wxSTC_EOL_LF`;
|
||||
-- `nil` means OS default: CRLF on Windows and OSX and LF on Linux/Unix.
|
||||
-- CRLF as a default on OSX is a bug and is likely to change in future versions.
|
||||
-- `nil` means OS default: CRLF on Windows and LF on Linux/Unix and OSX.
|
||||
-- (OSX had CRLF as a default until v0.36, which fixed it).
|
||||
editor.defaulteol = wxstc.wxSTC_EOL_LF
|
||||
|
||||
-- to turn off checking for mixed end-of-line encodings in loaded files
|
||||
@@ -132,3 +132,11 @@ debugger.runonstart = true
|
||||
|
||||
-- to set compact fold that doesn't include empty lines after a block
|
||||
editor.foldcompact = true
|
||||
|
||||
-- to disable zoom with mouse wheel as it may be too sensitive on OSX
|
||||
editor.nomousezoom = true
|
||||
|
||||
-- to specify a skin for Corona simulator (OSX only);
|
||||
-- you can also change it between runs from Local Console by executing
|
||||
-- `ide.config.corona = {skin = 'iPad'}`
|
||||
corona = { skin = "iPad" }
|
||||
|
||||
73
cfg/user-snippet.lua
Normal file
73
cfg/user-snippet.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
--[[-- Copy snippets from this file to `user.lua` --]]--
|
||||
|
||||
--[[ Add a shortcut to generate `~` if your keyboard doesn't have one
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local ide, wx, TR, ID = G.ide, G.wx, G.TR, G.ID
|
||||
local postinit = ide.app.postinit
|
||||
ide.app.postinit = function()
|
||||
if postinit then postinit() end
|
||||
local menu = ide.frame.menuBar:GetMenu(ide.frame.menuBar:FindMenu(TR("&Edit")))
|
||||
menu:Append(ID "tilde", "Tilde\tAlt-'")
|
||||
ide.frame:Connect(ID "tilde", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():AddText("~") end)
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ Add `Evaluate in Console` option to the Edit menu
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local ide, wx, TR, ID = G.ide, G.wx, G.TR, G.ID
|
||||
local postinit = ide.app.postinit
|
||||
ide.app.postinit = function()
|
||||
if postinit then postinit() end
|
||||
local menu = ide.frame.menuBar:GetMenu(ide.frame.menuBar:FindMenu(TR("&Edit")))
|
||||
menu:Append(ID "eval", "Evaluate in Console\tCtrl-E")
|
||||
ide.frame:Connect(ID "eval", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () ShellExecuteCode(GetEditor():GetSelectedText()) end)
|
||||
ide.frame:Connect(ID "eval", wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(GetEditor() and #GetEditor():GetSelectedText() > 0) end)
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ Add `Zoom` menu to increase/decrease/reset font in the editor
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local ide, wx, TR, ID = G.ide, G.wx, G.TR, G.ID
|
||||
local postinit = ide.app.postinit
|
||||
ide.app.postinit = function()
|
||||
if postinit then postinit() end
|
||||
|
||||
local zoomMenu = wx.wxMenu{
|
||||
{ID "zoomreset", "Zoom to 100%\tCtrl-0"},
|
||||
{ID "zoomin", "Zoom In\tCtrl-+"},
|
||||
{ID "zoomout", "Zoom Out\tCtrl--"},
|
||||
}
|
||||
local menu = ide.frame.menuBar:GetMenu(ide.frame.menuBar:FindMenu(TR("&View")))
|
||||
menu:Append(ID "zoom", "Zoom", zoomMenu)
|
||||
|
||||
ide.frame:Connect(ID "zoomreset", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():SetZoom(1) end)
|
||||
ide.frame:Connect(ID "zoomin", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():SetZoom(GetEditor():GetZoom()+1) end)
|
||||
ide.frame:Connect(ID "zoomout", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():SetZoom(GetEditor():GetZoom()-1) end)
|
||||
|
||||
-- only enable if there is an editor
|
||||
for _, m in G.ipairs({"zoomreset", "zoomin", "zoomout"}) do
|
||||
ide.frame:Connect(ID(m), wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(GetEditor() ~= nil) end)
|
||||
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}
|
||||
--]]
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Copyright 2011-12 Paul Kulchenko, ZeroBrane LLC
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
local corona
|
||||
local win = ide.osname == "Windows"
|
||||
@@ -45,19 +45,42 @@ 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
|
||||
FileCopy(mdbl, mdbc)
|
||||
DisplayOutput(("Copied ZeroBrane Studio debugger ('mobdebug.lua') to '%s' folder.\n"):format(mdbc))
|
||||
local needed = needRefresh(mdbl, mdbc)
|
||||
if needed then
|
||||
local copied = FileCopy(mdbl, mdbc)
|
||||
-- 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
|
||||
|
||||
local cmd = ('"%s" %s"%s"'):format(corona, rundebug and "-debug 1 -project " or "", file)
|
||||
local debugopt = mac and "-debug 1 -project " or "-debug "
|
||||
local skin = ide.config.corona and ide.config.corona.skin
|
||||
and (" -skin "..ide.config.corona.skin) or ""
|
||||
local cmd = ('"%s" %s"%s"%s')
|
||||
:format(corona, rundebug and debugopt or "", file, skin)
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
|
||||
function() ide.debugger.pid = nil end)
|
||||
|
||||
@@ -65,7 +65,7 @@ return {
|
||||
|
||||
-- find *.gproj file in the project directory
|
||||
local file
|
||||
for _, proj in ipairs(FileSysGet(self:fworkdir(wfilename).."/*.gproj", wx.wxFILE)) do
|
||||
for _, proj in ipairs(FileSysGetRecursive(self:fworkdir(wfilename), false, "*.gproj")) do
|
||||
if file then
|
||||
DisplayOutputLn("Found multiple .gproj files in the project directory; ignored '"..proj.."'.")
|
||||
end
|
||||
|
||||
63
interpreters/lfw.lua
Normal file
63
interpreters/lfw.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
if ide.osname ~= "Windows" or not os.getenv("LUA_DEV") then return end
|
||||
|
||||
local exe
|
||||
|
||||
local function exePath()
|
||||
local defaultPath = ide.config.path.lfw or os.getenv("LUA_DEV")
|
||||
return MergeFullPath(defaultPath, 'lua.exe')
|
||||
end
|
||||
|
||||
return {
|
||||
name = "LuaForWindows",
|
||||
description = "Lua For Windows interpreter with debugger",
|
||||
api = {"baselib"},
|
||||
frun = function(self,wfilename,rundebug)
|
||||
exe = exe or exePath()
|
||||
local filepath = wfilename:GetFullPath()
|
||||
local script
|
||||
if rundebug then
|
||||
DebuggerAttachDefault({basedir = self:fworkdir(wfilename),
|
||||
runstart = ide.config.debugger.runonstart == true})
|
||||
script = rundebug
|
||||
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
|
||||
|
||||
script = ('dofile [[%s]]'):format(filepath)
|
||||
end
|
||||
local code = ([[xpcall(function() io.stdout:setvbuf('no'); %s end,function(err) print(debug.traceback(err)) end)]]):format(script)
|
||||
local cmd = '"'..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)
|
||||
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)
|
||||
end,
|
||||
fworkdir = function (self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
hasdebugger = true,
|
||||
fattachdebug = function(self) DebuggerAttachDefault() end,
|
||||
scratchextloop = false,
|
||||
unhideanywindow = true,
|
||||
}
|
||||
67
interpreters/luabase.lua
Normal file
67
interpreters/luabase.lua
Normal 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
|
||||
@@ -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()
|
||||
|
||||
2
interpreters/luadeb52.lua
Normal file
2
interpreters/luadeb52.lua
Normal file
@@ -0,0 +1,2 @@
|
||||
dofile 'interpreters/luabase.lua'
|
||||
return MakeLuaInterpreter('52', ' 5.2')
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Copyright 2011-12 Paul Kulchenko, ZeroBrane LLC
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
local quick
|
||||
local win = ide.osname == "Windows"
|
||||
@@ -9,7 +9,7 @@ local s3e = os.getenv("S3E_DIR")
|
||||
return {
|
||||
name = "Marmalade Quick",
|
||||
description = "Marmalade Quick mobile framework",
|
||||
api = {"baselib"},
|
||||
api = {"baselib", "marmalade"},
|
||||
frun = function(self,wfilename,rundebug)
|
||||
quick = quick or ide.config.path.quick or (s3e and GetFullPathIfExists(s3e, exe))
|
||||
if not quick then
|
||||
@@ -25,7 +25,7 @@ return {
|
||||
local candidates, paths = {}, {}
|
||||
for p in path:gmatch("[^"..sep.."]+") do
|
||||
table.insert(paths, p)
|
||||
for _, candidate in ipairs(FileSysGet(p.."/*.*", wx.wxDIR)) do
|
||||
for _, candidate in ipairs(FileSysGetRecursive(p, false, "*")) do
|
||||
if GetFullPathIfExists(candidate, exe) then table.insert(candidates, candidate) end
|
||||
if GetFullPathIfExists(candidate.."/s3e", exe) then table.insert(candidates, candidate.."/s3e") end
|
||||
end
|
||||
@@ -52,10 +52,10 @@ return {
|
||||
|
||||
-- check for *.mkb file; it can be in the same or in the parent folder
|
||||
local mproj, mfile = MergeFullPath(projdir, "./")
|
||||
for _, file in ipairs(FileSysGet(mproj.."*.mkb", wx.wxFILE)) do mfile = file end
|
||||
for _, file in ipairs(FileSysGetRecursive(mproj, false, "*.mkb")) do mfile = file end
|
||||
if not mfile then
|
||||
mproj, mfile = MergeFullPath(projdir, "../")
|
||||
for _, file in ipairs(FileSysGet(mproj.."*.mkb", wx.wxFILE)) do mfile = file end
|
||||
for _, file in ipairs(FileSysGetRecursive(mproj, false, "*.mkb")) do mfile = file end
|
||||
end
|
||||
if not mfile then
|
||||
DisplayOutputLn(("Can't find '%s' project file."):format(mproj))
|
||||
@@ -85,12 +85,18 @@ return {
|
||||
local mdbl = MergeFullPath(GetPathWithSep(ide.editorFilename), "lualibs/mobdebug/mobdebug.lua")
|
||||
if not wx.wxFileExists(mdbc)
|
||||
or GetFileModTime(mdbc):GetTicks() < GetFileModTime(mdbl):GetTicks() then
|
||||
FileCopy(mdbl, mdbc)
|
||||
DisplayOutputLn("Copied ZeroBrane Studio debugger ('mobdebug.lua') to the project folder.")
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
local dll = MergeFullPath(s3e, "../quick/target/quick_prebuilt_d.s86")
|
||||
local dll = GetFullPathIfExists(s3e, "../quick/target/quick_prebuilt_d.s86")
|
||||
or MergeFullPath(s3e, ("../quick/target/%s/quick_prebuilt_d.s86"):format(mac and 'osx' or 'win'))
|
||||
local options = table.concat({
|
||||
([[--dll="%s"]]):format(dll),
|
||||
(datadir and ([[--data="%s"]]):format(datadir) or ''),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
local moai
|
||||
local win = ide.osname == "Windows"
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 }
|
||||
@@ -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
|
||||
|
||||
188
lualibs/lua_lexer_loose.lua
Normal file
188
lualibs/lua_lexer_loose.lua
Normal file
@@ -0,0 +1,188 @@
|
||||
--[[
|
||||
lua_lexer_loose.lua.
|
||||
Loose lexing of Lua code. See README.
|
||||
|
||||
WARNING: This code is preliminary and may have errors
|
||||
in its current form.
|
||||
|
||||
(c) 2013 David Manura. MIT License.
|
||||
--]]
|
||||
|
||||
local M = {}
|
||||
|
||||
-- based on LuaBalanced
|
||||
local function match_string(s, pos)
|
||||
pos = pos or 1
|
||||
local posa = pos
|
||||
local c = s:sub(pos,pos)
|
||||
if c == '"' or c == "'" then
|
||||
pos = pos + 1
|
||||
while 1 do
|
||||
pos = s:find("[" .. c .. "\\]", pos)
|
||||
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
|
||||
else
|
||||
pos = pos + 2
|
||||
end
|
||||
end
|
||||
else
|
||||
local sc = s:match("^%[(=*)%[", pos)
|
||||
if sc then
|
||||
local _; _, pos = s:find("%]" .. sc .. "%]", pos)
|
||||
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
|
||||
return nil, pos
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- based on LuaBalanced
|
||||
local function match_comment(s, pos)
|
||||
pos = pos or 1
|
||||
if s:sub(pos, pos+1) ~= '--' then
|
||||
return nil, pos
|
||||
end
|
||||
pos = pos + 2
|
||||
if s:sub(pos,pos) == '[' then
|
||||
local partt, post = match_string(s, pos)
|
||||
if partt then
|
||||
return '--' .. partt, post
|
||||
end
|
||||
end
|
||||
local part; part, pos = s:match('^([^\n]*\n?)()', pos)
|
||||
return '--' .. part, pos
|
||||
end
|
||||
|
||||
-- note: matches invalid numbers too
|
||||
local function match_numberlike(s, pos)
|
||||
local tok = s:match('^0[xX][0-9A-Fa-f]*', pos)
|
||||
if tok then return tok end
|
||||
local tok = s:match('^[0-9%.]+', pos)
|
||||
if tok then
|
||||
local tok2 = s:match('^[eE][+-]?[0-9]*', pos + #tok)
|
||||
if tok2 then tok = tok .. tok2 end
|
||||
return tok
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function newset(s)
|
||||
local t = {}
|
||||
for c in s:gmatch'.' do t[c] = true end
|
||||
return t
|
||||
end
|
||||
local function qws(s)
|
||||
local t = {}
|
||||
for k in s:gmatch'%S+' do t[k] = true end
|
||||
return t
|
||||
end
|
||||
|
||||
local sym = newset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")
|
||||
local dig = newset('0123456789')
|
||||
local op = newset('=~<>.+-*/%^#=<>;:,.{}[]()')
|
||||
|
||||
op['=='] = true
|
||||
op['<='] = true
|
||||
op['>='] = true
|
||||
op['~='] = true
|
||||
op['..'] = true
|
||||
|
||||
local is_keyword = qws[[
|
||||
and break do else elseif end false for function if
|
||||
in local nil not or repeat return
|
||||
then true until while]]
|
||||
|
||||
function M.lex(code, f, pos)
|
||||
local pos = pos or 1
|
||||
local tok = code:match('^#![^\n]*\n', pos) -- shebang
|
||||
if tok then f('Shebang', tok, 1) pos = pos + #tok end
|
||||
while pos <= #code do
|
||||
local p2, n2, n1 = code:match('^%s*()((%S)%S?)', pos)
|
||||
if not p2 then assert(code:sub(pos):match('^%s*$')); break end
|
||||
pos = p2
|
||||
|
||||
if sym[n1] then
|
||||
local tok = code:match('^([_A-Za-z][_A-Za-z0-9]*)', pos)
|
||||
assert(tok)
|
||||
if is_keyword[tok] then
|
||||
f('Keyword', tok, pos)
|
||||
else
|
||||
f('Id', tok, pos)
|
||||
end
|
||||
pos = pos + #tok
|
||||
elseif n2 == '--' then
|
||||
local tok, pos2 = match_comment(code, pos)
|
||||
assert(tok)
|
||||
f('Comment', tok, pos)
|
||||
pos = pos2
|
||||
elseif n1 == '\'' or n1 == '\"' or n2 == '[[' or n2 == '[=' then
|
||||
local tok = match_string(code, pos)
|
||||
if tok then
|
||||
f('String', tok, pos)
|
||||
pos = pos + #tok
|
||||
else
|
||||
f('Unknown', code:sub(pos), pos) -- unterminated string
|
||||
pos = #code + 1
|
||||
end
|
||||
elseif dig[n1] then
|
||||
local tok = match_numberlike(code, pos)
|
||||
assert(tok)
|
||||
f('Number', tok, pos)
|
||||
pos = pos + #tok
|
||||
elseif op[n2] then
|
||||
if n2 == '..' and code:match('^%.', pos+2) then
|
||||
tok = '...'
|
||||
else
|
||||
tok = n2
|
||||
end
|
||||
f('Keyword', tok, pos)
|
||||
pos = pos + #tok
|
||||
elseif op[n1] then
|
||||
local tok = n1
|
||||
f('Keyword', tok, pos)
|
||||
pos = pos + #tok
|
||||
else
|
||||
f('Unknown', n1, pos)
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local Stream = {}
|
||||
Stream.__index = Stream
|
||||
function Stream:next(val)
|
||||
if self._next then
|
||||
local _next = self._next
|
||||
self._next = nil
|
||||
return _next
|
||||
else
|
||||
self._next = nil
|
||||
return self.f()
|
||||
end
|
||||
end
|
||||
function Stream:peek()
|
||||
if self._next then
|
||||
return self._next
|
||||
else
|
||||
local _next = self.f()
|
||||
self._next = _next
|
||||
return _next
|
||||
end
|
||||
end
|
||||
|
||||
function M.lexc(code, f, pos)
|
||||
local yield = coroutine.yield
|
||||
local func = coroutine.wrap(f or function()
|
||||
M.lex(code, function(tag, name, pos)
|
||||
yield {tag=tag, name, lineinfo=pos}
|
||||
end, pos)
|
||||
yield {tag='Eof'}
|
||||
end)
|
||||
return setmetatable({f=func}, Stream)
|
||||
end
|
||||
|
||||
return M
|
||||
303
lualibs/lua_parser_loose.lua
Normal file
303
lualibs/lua_parser_loose.lua
Normal file
@@ -0,0 +1,303 @@
|
||||
--[[
|
||||
lua_parser_loose.lua.
|
||||
Loose parsing of Lua code. See README.
|
||||
(c) 2013 David Manura. MIT License.
|
||||
--]]
|
||||
|
||||
local PARSE = {}
|
||||
|
||||
local LEX = require 'lua_lexer_loose'
|
||||
|
||||
local function warn(message, position)
|
||||
io.stderr:write('WARNING: ', tostring(position), ': ', message, '\n')
|
||||
end
|
||||
|
||||
--[[
|
||||
Loose parser.
|
||||
|
||||
lx - lexer stream of Lua tokens.
|
||||
f(event...) - callback function to send events to.
|
||||
|
||||
Events generated:
|
||||
'Var', name, lineinfo - variable declaration that immediately comes into scope.
|
||||
'VarSelf', name, lineinfo - same as 'Var' but for implicit 'self' parameter
|
||||
in method definitions. lineinfo is zero-width space after '('
|
||||
'VarNext', name, lineinfo - variable definition that comes into scope
|
||||
upon next statement.
|
||||
'VarInside', name, lineinfo - variable definition that comes into scope
|
||||
inside following block. Used for control variables in 'for' statements.
|
||||
'Id', name, lineinfo - reference to variable.
|
||||
'String', name - string or table field.
|
||||
'Scope', opt - beginning of scope block.
|
||||
'EndScope', nil, lineinfo - end of scope block.
|
||||
'FunctionCall', name, lineinfo - function call (in addition to other events).
|
||||
--]]
|
||||
function PARSE.parse_scope(lx, f, level)
|
||||
local cprev = {tag='Eof'}
|
||||
|
||||
-- stack of scopes.
|
||||
local scopes = {{}}
|
||||
for l = 2, (level or 1) do scopes[l] = {} end
|
||||
|
||||
local function scope_begin(opt, lineinfo)
|
||||
scopes[#scopes+1] = {}
|
||||
f('Scope', opt, lineinfo)
|
||||
end
|
||||
local function scope_end(opt, lineinfo)
|
||||
if #scopes <= 1 then
|
||||
warn("'end' without opening block", lineinfo)
|
||||
else
|
||||
table.remove(scopes)
|
||||
end
|
||||
f('EndScope', opt, lineinfo)
|
||||
end
|
||||
|
||||
local function parse_function_list(has_self)
|
||||
local c = lx:next(); assert(c[1] == '(')
|
||||
f('Statement', c[1], c.lineinfo) -- generate Statement for function definition
|
||||
scope_begin(c[1], c.lineinfo)
|
||||
if has_self then
|
||||
local lineinfo = c.lineinfo+1 -- zero size
|
||||
f('VarSelf', 'self', lineinfo)
|
||||
end
|
||||
while lx:peek().tag == 'Id' do
|
||||
local c = lx:next()
|
||||
f('Var', c[1], c.lineinfo)
|
||||
if lx:peek()[1] == ',' then lx:next() end
|
||||
end
|
||||
if lx:peek()[1] == ')' then lx:next() end
|
||||
end
|
||||
|
||||
while 1 do
|
||||
local c = lx:next()
|
||||
|
||||
-- Detect end of previous statement
|
||||
if c.tag == 'Eof' -- trigger 'Statement' at the end of file
|
||||
or c.tag == 'Keyword' and (
|
||||
c[1] == 'break' or c[1] == 'goto' or c[1] == 'do' or c[1] == 'while' or
|
||||
c[1] == 'repeat' or c[1] == 'if' or c[1] == 'for' or c[1] == 'function' and lx:peek().tag == 'Id' or
|
||||
c[1] == 'local' or c[1] == ';' or c[1] == 'until' or c[1] == 'return' or c[1] == 'end') or
|
||||
c.tag == 'Id' and
|
||||
(cprev.tag == 'Id' or
|
||||
cprev.tag == 'Keyword' and
|
||||
(cprev[1] == ']' or cprev[1] == ')' or cprev[1] == '}' or
|
||||
cprev[1] == '...' or cprev[1] == 'end' or
|
||||
cprev[1] == 'true' or cprev[1] == 'false' or
|
||||
cprev[1] == 'nil') or
|
||||
cprev.tag == 'Number' or cprev.tag == 'String')
|
||||
then
|
||||
if scopes[#scopes].inside_until then scope_end(nil, c.lineinfo) end
|
||||
f('Statement', c[1], c.lineinfo)
|
||||
end
|
||||
|
||||
if c.tag == 'Eof' then break end
|
||||
|
||||
-- Process token(s)
|
||||
if c.tag == 'Keyword' then
|
||||
|
||||
if c[1] == 'local' and lx:peek().tag == 'Keyword' and lx:peek()[1] == 'function' then
|
||||
-- local function
|
||||
local c = lx:next(); assert(c[1] == 'function')
|
||||
if lx:peek().tag == 'Id' then
|
||||
c = lx:next()
|
||||
f('Var', c[1], c.lineinfo)
|
||||
if lx:peek()[1] == '(' then parse_function_list() end
|
||||
end
|
||||
elseif c[1] == 'function' then
|
||||
if lx:peek()[1] == '(' then -- inline function
|
||||
parse_function_list()
|
||||
elseif lx:peek().tag == 'Id' then -- function definition statement
|
||||
c = lx:next(); assert(c.tag == 'Id')
|
||||
f('Id', c[1], c.lineinfo)
|
||||
local has_self
|
||||
while lx:peek()[1] ~= '(' and lx:peek().tag ~= 'Eof' do
|
||||
c = lx:next()
|
||||
if c.tag == 'Id' then
|
||||
f('String', c[1], c.lineinfo)
|
||||
elseif c.tag == 'Keyword' and c[1] == ':' then
|
||||
has_self = true
|
||||
end
|
||||
end
|
||||
if lx:peek()[1] == '(' then parse_function_list(has_self) end
|
||||
end
|
||||
elseif c[1] == 'local' and lx:peek().tag == 'Id' then
|
||||
c = lx:next()
|
||||
f('VarNext', c[1], c.lineinfo)
|
||||
while lx:peek().tag == 'Keyword' and lx:peek()[1] == ',' do
|
||||
c = lx:next(); if lx:peek().tag ~= 'Id' then break end
|
||||
c = lx:next()
|
||||
f('VarNext', c[1], c.lineinfo)
|
||||
end
|
||||
elseif c[1] == 'for' and lx:peek().tag == 'Id' then
|
||||
c = lx:next()
|
||||
f('VarInside', c[1], c.lineinfo)
|
||||
while lx:peek().tag == 'Keyword' and lx:peek()[1] == ',' do
|
||||
c = lx:next(); if lx:peek().tag ~= 'Id' then break end
|
||||
c = lx:next()
|
||||
f('VarInside', c[1], c.lineinfo)
|
||||
end
|
||||
elseif c[1] == 'do' then
|
||||
scope_begin('do', c.lineinfo)
|
||||
-- note: do/while/for statement scopes all begin at 'do'.
|
||||
elseif c[1] == 'repeat' or c[1] == 'then' then
|
||||
scope_begin(c[1], c.lineinfo)
|
||||
elseif c[1] == 'end' or c[1] == 'elseif' then
|
||||
scope_end(c[1], c.lineinfo)
|
||||
elseif c[1] == 'else' then
|
||||
scope_end(nil, c.lineinfo)
|
||||
scope_begin(c[1], c.lineinfo)
|
||||
elseif c[1] == 'until' then
|
||||
scopes[#scopes].inside_until = true
|
||||
elseif c[1] == '{' then
|
||||
scopes[#scopes].inside_table = (scopes[#scopes].inside_table or 0) + 1
|
||||
elseif c[1] == '}' then
|
||||
local newval = (scopes[#scopes].inside_table or 0) - 1
|
||||
newval = newval >= 1 and newval or nil
|
||||
scopes[#scopes].inside_table = newval
|
||||
end
|
||||
elseif c.tag == 'Id' then
|
||||
local cnext = lx:peek()
|
||||
if cnext.tag == 'Keyword' and (cnext[1] == '(' or cnext[1] == '{')
|
||||
or cnext.tag == 'String' then
|
||||
f('FunctionCall', c[1], c.lineinfo)
|
||||
end
|
||||
if scopes[#scopes].inside_table and cnext.tag == 'Keyword' and cnext[1] == '=' then
|
||||
-- table field
|
||||
f('String', c[1], c.lineinfo)
|
||||
elseif cprev.tag == 'Keyword' and (cprev[1] == ':' or cprev[1] == '.') then
|
||||
f('String', c[1], c.lineinfo)
|
||||
else
|
||||
f('Id', c[1], c.lineinfo)
|
||||
end
|
||||
end
|
||||
|
||||
if c.tag ~= 'Comment' then cprev = c end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
This is similar to parse_scope but determines if variables are local or global.
|
||||
|
||||
lx - lexer stream of Lua tokens.
|
||||
f(event...) - callback function to send events to.
|
||||
|
||||
Events generated:
|
||||
'Id', name, lineinfo, 'local'|'global'
|
||||
(plus all events in parse_scope)
|
||||
--]]
|
||||
function PARSE.parse_scope_resolve(lx, f, vars)
|
||||
local NEXT = {} -- unique key
|
||||
local INSIDE = {} -- unique key
|
||||
local function newscope(vars, opt, lineinfo)
|
||||
local newvars = opt=='do' and vars[INSIDE] or {}
|
||||
if newvars == vars[INSIDE] then vars[INSIDE] = false end
|
||||
newvars[INSIDE]=false
|
||||
newvars[NEXT]=false
|
||||
local level = (vars[0] or 0) + 1
|
||||
newvars[0] = level -- keep the current level
|
||||
newvars[-1] = lineinfo -- keep the start of the scope
|
||||
newvars[level] = newvars -- reference the current vars table
|
||||
return setmetatable(newvars, {__index=vars})
|
||||
end
|
||||
|
||||
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 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
|
||||
if op == 'Var' or op == 'VarSelf' then
|
||||
vars[name] = var
|
||||
elseif op == 'VarNext' then
|
||||
vars[NEXT] = vars[NEXT] or {}
|
||||
vars[NEXT][name] = var
|
||||
elseif op == 'VarInside' then
|
||||
vars[INSIDE] = vars[INSIDE] or {}
|
||||
vars[INSIDE][name] = var
|
||||
elseif op == 'Scope' then
|
||||
vars = newscope(vars, name, lineinfo)
|
||||
elseif op == 'EndScope' then
|
||||
local mt = getmetatable(vars)
|
||||
if mt == nil then
|
||||
warn("'end' without opening block.", lineinfo)
|
||||
else
|
||||
vars = mt.__index
|
||||
end
|
||||
elseif op == 'Id' then
|
||||
-- Just make callback
|
||||
elseif op == 'String' or op == 'FunctionCall' then
|
||||
-- Just make callback
|
||||
elseif op == 'Statement' then -- beginning of statement
|
||||
-- Apply vars that come into scope upon beginning of statement.
|
||||
if vars[NEXT] then
|
||||
for k,v in pairs(vars[NEXT]) do
|
||||
vars[k] = v; vars[NEXT][k] = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
assert(false)
|
||||
end
|
||||
f(op, name, lineinfo, vars)
|
||||
end, vars[0])
|
||||
end
|
||||
|
||||
function PARSE.extract_vars(code, f)
|
||||
local lx = LEX.lexc(code)
|
||||
|
||||
local char0 = 1 -- next char offset to write
|
||||
local function gen(char1, nextchar0)
|
||||
char0 = nextchar0
|
||||
end
|
||||
|
||||
PARSE.parse_scope_resolve(lx, function(op, name, lineinfo, other)
|
||||
if op == 'Id' then
|
||||
f('Id', name, other, lineinfo)
|
||||
elseif op == 'Var' or op == 'VarNext' or op == 'VarInside' then
|
||||
gen(lineinfo, lineinfo+#name)
|
||||
f('Var', name, "local", lineinfo)
|
||||
end -- ignore 'VarSelf' and others
|
||||
end)
|
||||
gen(#code+1, nil)
|
||||
end
|
||||
|
||||
--[[
|
||||
Converts 5.2 code to 5.1 style code with explicit _ENV variables.
|
||||
Example: "function f(_ENV, x) print(x, y)" -->
|
||||
"function _ENV.f(_ENV, x) _ENV.print(x, _ENV.y) end"
|
||||
|
||||
code - string of Lua code. Assumed to be valid Lua (FIX: 5.1 or 5.2?)
|
||||
f(s) - call back function to send chunks of Lua code output to. Example: io.stdout.
|
||||
--]]
|
||||
function PARSE.replace_env(code, f)
|
||||
if not f then return PARSE.accumulate(PARSE.replace_env, code) end
|
||||
PARSE.extract_vars(code, function(op, name, other)
|
||||
if op == 'Id' then
|
||||
f(other == 'global' and '_ENV.' .. name or name)
|
||||
elseif op == 'Var' or op == 'Other' then
|
||||
f(name)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- helper function. Can be passed as argument `f` to functions
|
||||
-- like `replace_env` above to accumulate fragments into a single string.
|
||||
function PARSE.accumulator()
|
||||
local ts = {}
|
||||
local mt = {}
|
||||
mt.__index = mt
|
||||
function mt:__call(s) ts[#ts+1] = s end
|
||||
function mt:result() return table.concat(ts) end
|
||||
return setmetatable({}, mt)
|
||||
end
|
||||
|
||||
-- helper function
|
||||
function PARSE.accumulate(g, code)
|
||||
local accum = PARSE.accumulator()
|
||||
g(code, accum)
|
||||
return accum:result()
|
||||
end
|
||||
|
||||
return PARSE
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -1,12 +1,12 @@
|
||||
--
|
||||
-- MobDebug 0.525
|
||||
-- MobDebug 0.542
|
||||
-- Copyright 2011-13 Paul Kulchenko
|
||||
-- Based on RemDebug 1.0 Copyright Kepler Project 2005
|
||||
--
|
||||
|
||||
local mobdebug = {
|
||||
_NAME = "mobdebug",
|
||||
_VERSION = 0.525,
|
||||
_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.23 -- (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,9 +151,9 @@ 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 mt and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
|
||||
if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
|
||||
seen[t] = insref or spath
|
||||
if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end
|
||||
ttype = type(t) end -- new value falls through to be serialized
|
||||
@@ -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] 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)
|
||||
@@ -277,9 +283,9 @@ local function remove_breakpoint(file, line)
|
||||
if breakpoints[line] then breakpoints[line][file] = nil end
|
||||
end
|
||||
|
||||
-- this file name is already converted to lower case on windows.
|
||||
local function has_breakpoint(file, line)
|
||||
return breakpoints[line] and breakpoints[line][file]
|
||||
return breakpoints[line]
|
||||
and breakpoints[line][iscasepreserving and string.lower(file) or file]
|
||||
end
|
||||
|
||||
local function restore_vars(vars)
|
||||
@@ -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
|
||||
|
||||
@@ -425,6 +446,8 @@ local function debug_hook(event, line)
|
||||
or is_pending(server)
|
||||
) then checkcount = checkcount + 1; return end
|
||||
|
||||
checkcount = mobdebug.checkcount -- force check on the next command
|
||||
|
||||
-- this is needed to check if the stack got shorter or longer.
|
||||
-- unfortunately counting call/return calls is not reliable.
|
||||
-- the discrepancy may happen when "pcall(load, '')" call is made
|
||||
@@ -444,23 +467,27 @@ local function debug_hook(event, line)
|
||||
local file = lastfile
|
||||
if (lastsource ~= caller.source) then
|
||||
file, lastsource = caller.source, caller.source
|
||||
-- the easiest/fastest way would be to check for file names starting
|
||||
-- with '@', but users can supply names that may not use '@',
|
||||
-- technically, users can supply names that may not use '@',
|
||||
-- for example when they call loadstring('...', 'filename.lua').
|
||||
-- so we handle all sources as filenames
|
||||
file = file:gsub("^@", ""):gsub("\\", "/")
|
||||
-- need this conversion to be applied to relative and absolute
|
||||
-- file names as you may write "require 'Foo'" to
|
||||
-- load "foo.lua" (on a case insensitive file system) and breakpoints
|
||||
-- set on foo.lua will not work if not converted to the same case.
|
||||
if iscasepreserving then file = string.lower(file) end
|
||||
if file:find("%./") == 1 then file = file:sub(3)
|
||||
else file = file:gsub('^'..q(basedir), '') end
|
||||
|
||||
-- fix filenames for loaded strings that may contain scripts with newlines;
|
||||
-- some filesystems may allow "\n" in filenames, which is not supported here.
|
||||
if file:find("\n") then
|
||||
file = file:gsub("\n", ' '):sub(1, 32) -- limit to 32 chars
|
||||
-- Unfortunately, there is no reliable/quick way to figure out
|
||||
-- what is the filename and what is the source code.
|
||||
-- The following will work if the supplied filename uses Unix path.
|
||||
if file:find("^@") then
|
||||
file = file:gsub("^@", ""):gsub("\\", "/")
|
||||
-- need this conversion to be applied to relative and absolute
|
||||
-- file names as you may write "require 'Foo'" to
|
||||
-- load "foo.lua" (on a case insensitive file system) and breakpoints
|
||||
-- set on foo.lua will not work if not converted to the same case.
|
||||
if iscasepreserving then file = string.lower(file) end
|
||||
if file:find("%./") == 1 then file = file:sub(3)
|
||||
else file = file:gsub('^'..q(basedir), '') end
|
||||
-- some file systems allow newlines in file names; remove these.
|
||||
file = file:gsub("\n", ' ')
|
||||
else
|
||||
-- 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
|
||||
@@ -511,7 +538,7 @@ local function debug_hook(event, line)
|
||||
-- need to recheck once more as resume after 'stack' command may
|
||||
-- return something else (for example, 'exit'), which needs to be handled
|
||||
if status and res and res ~= 'stack' then
|
||||
if abort == nil and res == "exit" then os.exit(1) end
|
||||
if abort == nil and res == "exit" then os.exit(1); return end
|
||||
abort = res
|
||||
-- only abort if safe; if not, there is another (earlier) check inside
|
||||
-- debug_hook, which will abort execution at the first safe opportunity
|
||||
@@ -641,7 +668,8 @@ local function debugger_loop(sev, svars, sfile, sline)
|
||||
server:send("200 OK 0\n")
|
||||
coroutine.yield("load")
|
||||
else
|
||||
local chunk = server:receive(size)
|
||||
-- receiving 0 bytes blocks (at least in luasocket 2.0.2), so skip reading
|
||||
local chunk = size == 0 and "" or server:receive(size)
|
||||
if chunk then -- LOAD a new script for debugging
|
||||
local func, res = loadstring(chunk, "@"..name)
|
||||
if func then
|
||||
@@ -806,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
|
||||
@@ -847,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
|
||||
|
||||
@@ -858,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
|
||||
@@ -909,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
|
||||
@@ -926,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
|
||||
@@ -940,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
|
||||
|
||||
@@ -1007,8 +1065,11 @@ local function handle(params, client, options)
|
||||
elseif command == "setb" then
|
||||
_, _, _, file, line = string.find(params, "^([a-z]+)%s+(.-)%s+(%d+)%s*$")
|
||||
if file and line then
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = removebasedir(file, basedir)
|
||||
-- if this is a file name, and not a file source
|
||||
if not file:find('^".*"$') then
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = removebasedir(file, basedir)
|
||||
end
|
||||
client:send("SETB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
set_breakpoint(file, line)
|
||||
@@ -1042,8 +1103,11 @@ local function handle(params, client, options)
|
||||
elseif command == "delb" then
|
||||
_, _, _, file, line = string.find(params, "^([a-z]+)%s+(.-)%s+(%d+)%s*$")
|
||||
if file and line then
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = removebasedir(file, basedir)
|
||||
-- if this is a file name, and not a file source
|
||||
if not file:find('^".*"$') then
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = removebasedir(file, basedir)
|
||||
end
|
||||
client:send("DELB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
remove_breakpoint(file, line)
|
||||
@@ -1121,7 +1185,7 @@ local function handle(params, client, options)
|
||||
local file = string.gsub(exp, "\\", "/") -- convert slash
|
||||
file = removebasedir(file, basedir)
|
||||
client:send("LOAD " .. #lines .. " " .. file .. "\n")
|
||||
client:send(lines)
|
||||
if #lines > 0 then client:send(lines) end
|
||||
end
|
||||
while true do
|
||||
local params, err = client:receive()
|
||||
@@ -1148,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
|
||||
@@ -1344,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(...)
|
||||
@@ -1370,6 +1436,10 @@ local function done()
|
||||
|
||||
debug.sethook()
|
||||
server:close()
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
104
lualibs/socket/headers.lua
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
117
packages/sample.lua
Normal file
117
packages/sample.lua
Normal file
@@ -0,0 +1,117 @@
|
||||
local G = ...
|
||||
local id = G.ID("sample.samplemenu")
|
||||
|
||||
local P = {
|
||||
name = "Sample plugin",
|
||||
description = "Sample plugin to demonstrate various event types.",
|
||||
author = "Paul Kulchenko",
|
||||
}
|
||||
|
||||
-- Events that are marked with "return false" can return `false` to
|
||||
-- abort further processing.
|
||||
-- For `onEditorPreSave` event it means that file saving will be aborted.
|
||||
-- For `onEditorKeyDown` event it means that the key will be "eaten".
|
||||
-- For `onEditorCharAdded` event it means that no further processing is done
|
||||
-- (but the character is still added to the editor).
|
||||
|
||||
local events = {
|
||||
onRegister = function(self) end,
|
||||
onUnRegister = function(self) end,
|
||||
onEditorLoad = function(self, editor) end,
|
||||
onEditorClose = function(self, editor) end,
|
||||
onEditorNew = function(self, editor) end,
|
||||
onEditorPreSave = function(self, editor, filepath) end, -- return false
|
||||
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, 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)
|
||||
-- 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
|
||||
|
||||
P.onMenuEditor = function(self, menu, editor, event)
|
||||
local point = editor:ScreenToClient(event:GetPosition())
|
||||
pos = editor:PositionFromPointClose(point.x, point.y)
|
||||
menu:Append(id, ">> Sample item; pos "..pos)
|
||||
menu:Enable(id, true)
|
||||
|
||||
editor:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function() DisplayOutputLn("Selected "..pos) end)
|
||||
|
||||
DisplayOutputLn(self:GetFileName(), "onMenuEditor")
|
||||
end
|
||||
|
||||
P.onMenuEditorTab = function(self, menu, notebook, event, index)
|
||||
menu:Append(id, ">> Sample item; tab "..index)
|
||||
menu:Enable(id, true)
|
||||
|
||||
notebook:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function() DisplayOutputLn("Selected "..index) end)
|
||||
|
||||
DisplayOutputLn(self:GetFileName(), "onMenuEditorTab")
|
||||
end
|
||||
|
||||
P.onMenuFiletree = function(self, menu, tree, event)
|
||||
local item_id = event:GetItem()
|
||||
local name = tree:GetItemFullName(item_id)
|
||||
menu:Append(id, ">> Sample item; name "..name)
|
||||
menu:Enable(id, true)
|
||||
|
||||
tree:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function() DisplayOutputLn("Selected "..name) end)
|
||||
|
||||
DisplayOutputLn(self:GetFileName(), "onMenuFiletree")
|
||||
end
|
||||
|
||||
P.onInterpreterLoad = function(self, interpreter)
|
||||
DisplayOutputLn(self:GetFileName(), "onInterpreterLoad", interpreter:GetFileName())
|
||||
end
|
||||
|
||||
P.onInterpreterClose = function(self, interpreter)
|
||||
DisplayOutputLn(self:GetFileName(), "onInterpreterClose", interpreter:GetFileName())
|
||||
end
|
||||
|
||||
P.onEditorPreSave = function(self, editor, filepath)
|
||||
if filepath:find("%.txt$") then
|
||||
DisplayOutputLn(self:GetFileName(), "onEditorPreSave", "Aborted saving a .txt file")
|
||||
return false
|
||||
else
|
||||
DisplayOutputLn(self:GetFileName(), "onEditorPreSave", filepath)
|
||||
end
|
||||
end
|
||||
|
||||
P.onEditorCharAdded = function(self, editor, event)
|
||||
DisplayOutputLn(self:GetFileName(), "onEditorCharAdded", event:GetKey())
|
||||
end
|
||||
|
||||
P.onEditorKeyDown = function(self, editor, event)
|
||||
DisplayOutputLn(self:GetFileName(), "onEditorKeyDown", event:GetKeyCode())
|
||||
end
|
||||
|
||||
--]]
|
||||
|
||||
return P
|
||||
16
spec/cg.lua
16
spec/cg.lua
@@ -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,},
|
||||
|
||||
@@ -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
95
spec/hlsl.lua
Normal 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
|
||||
]],
|
||||
|
||||
},
|
||||
}
|
||||
69
spec/lua.lua
69
spec/lua.lua
@@ -27,7 +27,7 @@ local function isfndef(str)
|
||||
end
|
||||
|
||||
return {
|
||||
exts = {"lua", "rockspec"},
|
||||
exts = {"lua", "rockspec", "wlua"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "lua",
|
||||
linecomment = "--",
|
||||
@@ -49,20 +49,48 @@ 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,
|
||||
markvars = function(code, pos, vars)
|
||||
local PARSE = require 'lua_parser_loose'
|
||||
local LEX = require 'lua_lexer_loose'
|
||||
local lx = LEX.lexc(code, nil, pos)
|
||||
return coroutine.wrap(function()
|
||||
local varnext = {}
|
||||
PARSE.parse_scope_resolve(lx, function(op, name, lineinfo, vars)
|
||||
if not(op == 'Id' or op == 'Statement' or op == 'Var'
|
||||
or op == 'VarNext' or op == 'VarInside' or op == 'VarSelf'
|
||||
or op == 'FunctionCall' or op == 'Scope' or op == 'EndScope') then
|
||||
return end -- "normal" return; not interested in other events
|
||||
|
||||
-- level needs to be adjusted for VarInside as it comes into scope
|
||||
-- only after next block statement
|
||||
local at = vars[0] and (vars[0] + (op == 'VarInside' and 1 or 0))
|
||||
if op == 'Statement' then
|
||||
for _, token in pairs(varnext) do coroutine.yield(unpack(token)) end
|
||||
varnext = {}
|
||||
elseif op == 'VarNext' or op == 'VarInside' then
|
||||
table.insert(varnext, {'Var', name, lineinfo, vars, at})
|
||||
end
|
||||
|
||||
coroutine.yield(op, name, lineinfo, vars, at)
|
||||
end, vars)
|
||||
end)
|
||||
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"}
|
||||
@@ -73,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)
|
||||
|
||||
@@ -82,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
|
||||
@@ -115,13 +143,32 @@ return {
|
||||
|
||||
var = var and var:gsub("local","")
|
||||
var = var and var:gsub("%s","")
|
||||
typ = typ and typ:gsub("%b[]","")
|
||||
typ = typ and typ:gsub("%b()","")
|
||||
typ = typ and typ:gsub("%b{}","")
|
||||
typ = typ and typ
|
||||
:gsub("%b()","")
|
||||
:gsub("%b{}","")
|
||||
:gsub("%b[]",".0")
|
||||
-- remove comments; they may be in strings, but that's okay here
|
||||
:gsub("%-%-.*","")
|
||||
if (typ and (typ:match(",") or typ:match("%sor%s") or typ:match("%sand%s"))) then
|
||||
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
|
||||
|
||||
@@ -100,16 +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 = {
|
||||
@@ -118,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
|
||||
@@ -140,6 +146,7 @@ config = {
|
||||
interpreter = "luadeb", -- the default "project" lua interpreter
|
||||
|
||||
autocomplete = true, -- whether autocomplete is on by default
|
||||
autoanalizer = true, -- whether auto syntax analizer is on by default
|
||||
|
||||
acandtip = {
|
||||
shorttip = false, -- tooltips are compact during typing
|
||||
@@ -167,6 +174,7 @@ config = {
|
||||
allowinteractivescript = false, -- allow interaction in the output window
|
||||
projectautoopen = false, -- allow auto open/close files on a project switch
|
||||
autorecoverinactivity = nil, -- period of inactivity (s) for autorecover
|
||||
hidpi = false, -- HiDPI/Retina display support
|
||||
}
|
||||
|
||||
-- application engine
|
||||
|
||||
@@ -36,61 +36,73 @@ 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 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)
|
||||
for _, dir in ipairs(FileSysGet("api/*", wx.wxDIR)) do
|
||||
for _, file in ipairs(FileSysGet(dir.."/*.*", wx.wxFILE)) do
|
||||
if file:match "%.lua$" then
|
||||
addAPI(file,only,subapis,known)
|
||||
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 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
|
||||
|
||||
---------
|
||||
-- ToolTip and reserved words list
|
||||
-- also fixes function descriptions
|
||||
@@ -119,7 +131,7 @@ local function fillTips(api,apibasename,apiname)
|
||||
if not tab.childs then return end
|
||||
for key,info in pairs(tab.childs) do
|
||||
traverse(info,key)
|
||||
if info.type == "function" or info.type == "method" then
|
||||
if info.type == "function" or info.type == "method" or info.type == "value" then
|
||||
local libstr = libname ~= "" and libname.."." or ""
|
||||
|
||||
-- fix description
|
||||
@@ -129,15 +141,17 @@ local function fillTips(api,apibasename,apiname)
|
||||
:gsub("\t","")
|
||||
:gsub("("..widthmask..")[ \t]([^%)])","%1\n %2")
|
||||
|
||||
info.description = info.description
|
||||
info.description = (info.description or "")
|
||||
:gsub("\n\n","<br>"):gsub("\n"," "):gsub("<br>","\n")
|
||||
:gsub("[ \t]+"," ")
|
||||
:gsub("("..widthmask..") ","%1\n")
|
||||
|
||||
-- build info
|
||||
local inf = frontname.."\n"..info.description
|
||||
local inf = (info.type == "value" and "" or frontname.."\n")
|
||||
..info.description
|
||||
local sentence = info.description:match("^(.-)%. ?\n")
|
||||
local infshort = frontname.."\n"..(sentence and sentence.."..." or info.description)
|
||||
local infshort = (info.type == "value" and "" or frontname.."\n")
|
||||
..(sentence and sentence.."..." or info.description)
|
||||
local infshortbatch = (info.returns and info.args) and frontname or infshort
|
||||
|
||||
-- add to infoclass
|
||||
@@ -197,6 +211,7 @@ local function resolveAssign(editor,tx)
|
||||
local assigns = editor.assignscache and editor.assignscache.assigns
|
||||
local function getclass(tab,a)
|
||||
local key,rest = a:match("([%w_]+)[%.:](.*)")
|
||||
key = tonumber(key) or key -- make this work for childs[0]
|
||||
if (key and rest and tab.childs and tab.childs[key]) then
|
||||
return getclass(tab.childs[key],rest)
|
||||
end
|
||||
@@ -214,16 +229,24 @@ local function resolveAssign(editor,tx)
|
||||
local classname = nil
|
||||
c = ""
|
||||
change = false
|
||||
for w,s in tx:gmatch("([%w_]*)([%.:]?)") do
|
||||
for w,s in tx:gmatch("([%w_]+)([%.:]?)") do
|
||||
local old = classname
|
||||
classname = classname or (assigns[c..w])
|
||||
-- check if what we have so far can be matched with a class name
|
||||
-- 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
|
||||
-- continue checking unless this can lead to recursive substitution
|
||||
change = not classname:find("^"..w) and not classname:find("^"..c..w)
|
||||
c = classname..s
|
||||
change = true
|
||||
else
|
||||
c = c..w..s
|
||||
end
|
||||
end
|
||||
-- abort if the same or recursive value is returned; no need to continue.
|
||||
-- this can happen after typing "smth = smth:new(); smth:" or
|
||||
-- "line = line:gsub(...); line:" as the current algorithm attempts to
|
||||
-- replace "line" with the value that also includes "line"
|
||||
if change and c:find("^"..(tx:gsub("[.:]","[.:]"))) then break end
|
||||
tx = c
|
||||
end
|
||||
else
|
||||
@@ -234,22 +257,33 @@ local function resolveAssign(editor,tx)
|
||||
return getclass(ac,c)
|
||||
end
|
||||
|
||||
function GetTipInfo(editor, content, short)
|
||||
local caller = content:match("([%w_]+)%(%s*$")
|
||||
local class = caller and content:match("([%w_]+)[%.:]"..caller.."%(%s*$") or ""
|
||||
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 = (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
|
||||
end
|
||||
|
||||
return caller and (class and classtab[class]) and classtab[class][caller] or funcstab[caller]
|
||||
local res = (caller and (class and classtab[class]) and classtab[class][caller]
|
||||
or (not fullmatch and funcstab[caller] or nil))
|
||||
-- some values may not have descriptions (for example, true/false);
|
||||
-- don't return empty strings as they are displayed as empty tooltips.
|
||||
return res and #res > 0 and res or nil
|
||||
end
|
||||
|
||||
local function reloadAPI(only,subapis)
|
||||
@@ -281,6 +315,7 @@ do
|
||||
-- by defaul load every known api except lua
|
||||
known.lua = false
|
||||
|
||||
scanAPIs()
|
||||
loadallAPIs(nil,nil,known)
|
||||
generateAPIInfo()
|
||||
end
|
||||
@@ -341,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)
|
||||
@@ -394,9 +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") 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
|
||||
@@ -426,9 +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") 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()
|
||||
@@ -469,8 +507,9 @@ function CreateAutoCompList(editor,key)
|
||||
local api = editor.api
|
||||
local tip = api.tip
|
||||
local ac = api.ac
|
||||
local sep = editor.spec.sep
|
||||
|
||||
local method = key:match(":[^:%.]*$") ~= nil
|
||||
local method = key:match(":[^"..sep.."]*$") ~= nil
|
||||
|
||||
-- ignore keywords
|
||||
if tip.keys[key] then return end
|
||||
@@ -483,10 +522,9 @@ function CreateAutoCompList(editor,key)
|
||||
if not (progress) then return end
|
||||
|
||||
if (tab == ac) then
|
||||
local _, krest = rest:match("([%w_]+)[:%.]([%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_]","")
|
||||
@@ -501,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]
|
||||
@@ -525,6 +563,27 @@ function CreateAutoCompList(editor,key)
|
||||
|
||||
-- list from api
|
||||
local apilist = getAutoCompApiList(tab.childs or tab,rest,method)
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
@@ -565,11 +624,19 @@ function CreateAutoCompList(editor,key)
|
||||
else
|
||||
table.sort(apilist)
|
||||
end
|
||||
|
||||
local prev = apilist[#apilist]
|
||||
for i = #apilist-1,1,-1 do
|
||||
if prev == apilist[i] then
|
||||
table.remove(apilist, i+1)
|
||||
else prev = apilist[i] end
|
||||
end
|
||||
|
||||
compstr = table.concat(apilist," ")
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
@@ -11,17 +11,21 @@ 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")
|
||||
AddEditor(editor, ide.config.default.fullname)
|
||||
SetEditorSelection()
|
||||
SetupKeywords(editor, GetFileExt(filename))
|
||||
local doc = AddEditor(editor, filename)
|
||||
if doc then
|
||||
PackageEventHandle("onEditorNew", editor)
|
||||
SetEditorSelection(doc.index)
|
||||
end
|
||||
return editor
|
||||
end
|
||||
|
||||
-- Find an editor page that hasn't been used at all, eg. an untouched NewFile()
|
||||
local function findDocumentToReuse()
|
||||
local editor = nil
|
||||
local function findUnusedEditor()
|
||||
local editor
|
||||
for id, document in pairs(openDocuments) do
|
||||
if (document.editor:GetLength() == 0) and
|
||||
(not document.isModified) and (not document.filePath) and
|
||||
@@ -41,7 +45,10 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
if (not editor) then
|
||||
for id, doc in pairs(openDocuments) do
|
||||
if doc.filePath and filePath:SameAs(wx.wxFileName(doc.filePath)) then
|
||||
if not skipselection then notebook:SetSelection(doc.index) end
|
||||
if not skipselection and doc.index ~= notebook:GetSelection() then
|
||||
-- selecting the same tab doesn't trigger PAGE_CHANGE event,
|
||||
-- but moves the focus to the tab bar, which needs to be avoided.
|
||||
notebook:SetSelection(doc.index) end
|
||||
return doc.editor
|
||||
end
|
||||
end
|
||||
@@ -59,22 +66,20 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
end
|
||||
|
||||
local current = editor and editor:GetCurrentPos()
|
||||
editor = editor or findDocumentToReuse() or CreateEditor()
|
||||
editor = editor or findUnusedEditor() or CreateEditor()
|
||||
|
||||
editor:Freeze()
|
||||
editor:Clear()
|
||||
editor:ClearAll()
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
editor:MarkerDeleteAll(BREAKPOINT_MARKER)
|
||||
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
|
||||
editor:MarkerDeleteAll(-1)
|
||||
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
|
||||
@@ -93,12 +98,12 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
editor:Thaw()
|
||||
|
||||
if current then editor:GotoPos(current) end
|
||||
if (ide.config.editor.autotabs) then
|
||||
if (file_text and ide.config.editor.autotabs) then
|
||||
local found = string.find(file_text,"\t") ~= nil
|
||||
editor:SetUseTabs(found)
|
||||
end
|
||||
|
||||
if (ide.config.editor.checkeol) then
|
||||
if (file_text and ide.config.editor.checkeol) then
|
||||
-- Auto-detect CRLF/LF line-endings
|
||||
local foundcrlf = string.find(file_text,"\r\n") ~= nil
|
||||
local foundlf = (string.find(file_text,"[^\r]\n") ~= nil)
|
||||
@@ -118,16 +123,19 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
|
||||
editor:EmptyUndoBuffer()
|
||||
local id = editor:GetId()
|
||||
if not openDocuments[id] then -- the editor has not been added to notebook
|
||||
if openDocuments[id] then -- existing editor; switch to the tab
|
||||
notebook:SetSelection(openDocuments[id].index)
|
||||
else -- the editor has not been added to notebook
|
||||
AddEditor(editor, wx.wxFileName(filePath):GetFullName()
|
||||
or ide.config.default.fullname)
|
||||
end
|
||||
openDocuments[id].filePath = filePath
|
||||
openDocuments[id].fileName = wx.wxFileName(filePath):GetFullName()
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
|
||||
SettingsAppendFileToHistory(filePath)
|
||||
PackageEventHandle("onEditorLoad", editor)
|
||||
|
||||
SetDocumentModified(id, false)
|
||||
|
||||
-- activate the editor; this is needed for those cases when the editor is
|
||||
-- created from some other element, for example, from a project tree.
|
||||
@@ -148,9 +156,7 @@ local function getExtsString()
|
||||
knownexts = knownexts:len() > 0 and knownexts:sub(1,-2) or nil
|
||||
|
||||
local exts = knownexts and TR("Known Files").." ("..knownexts..")|"..knownexts.."|" or ""
|
||||
exts = exts..TR("All files").." (*)|*"
|
||||
|
||||
return exts
|
||||
return exts..TR("All files").." (*)|*"
|
||||
end
|
||||
|
||||
function OpenFile(event)
|
||||
@@ -175,6 +181,11 @@ function SaveFile(editor, filePath)
|
||||
if not filePath then
|
||||
return SaveFileAs(editor)
|
||||
else
|
||||
-- this event can be aborted
|
||||
if PackageEventHandle("onEditorPreSave", editor, filePath) == false then
|
||||
return false
|
||||
end
|
||||
|
||||
if (ide.config.savebak) then FileRename(filePath, filePath..".bak") end
|
||||
|
||||
local st = editor:GetText()
|
||||
@@ -182,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()
|
||||
@@ -191,6 +207,9 @@ function SaveFile(editor, filePath)
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
SetAutoRecoveryMark()
|
||||
|
||||
PackageEventHandle("onEditorSave", editor)
|
||||
|
||||
return true
|
||||
else
|
||||
wx.wxMessageBox(TR("Unable to save file '%s': %s"):format(filePath, err),
|
||||
@@ -205,36 +224,61 @@ 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
|
||||
|
||||
local ext = fn:GetExt()
|
||||
if (not ext or #ext == 0) and editor.spec and editor.spec.exts then
|
||||
ext = editor.spec.exts[1]
|
||||
-- set the extension on the file if assigned as this is used by OSX/Linux
|
||||
-- to present the correct default "save as type" choice.
|
||||
if ext then fn:SetExt(ext) end
|
||||
end
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, TR("Save file as"),
|
||||
fn:GetPath(wx.wxPATH_GET_VOLUME),
|
||||
fn:GetFullName(),
|
||||
"*."..(ext and #ext > 0 and ext or "*"),
|
||||
-- specify the current extension plus all other extensions based on specs
|
||||
(ext and #ext > 0 and "*."..ext.."|*."..ext.."|" or "")..getExtsString(),
|
||||
wx.wxFD_SAVE)
|
||||
|
||||
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
|
||||
FileTreeRefresh() -- refresh the tree to reflect the new file
|
||||
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))
|
||||
IndicateFunctions(editor)
|
||||
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
|
||||
|
||||
@@ -242,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
|
||||
@@ -312,14 +357,13 @@ function ClosePage(selection)
|
||||
and debugger.scratchpad.editors[editor] then
|
||||
DebuggerScratchpadOff()
|
||||
end
|
||||
-- check if the debugger is running and is using the current window
|
||||
-- check if the debugger is running and is using the current window;
|
||||
-- abort the debugger if the current marker is in the window being closed
|
||||
-- also abort the debugger if it is running, as we don't know what
|
||||
-- window will need to be activated when the debugger is paused
|
||||
if debugger and debugger.server and
|
||||
(debugger.running or editor:MarkerNext(0, CURRENT_LINE_MARKER_VALUE) >= 0) then
|
||||
(editor:MarkerNext(0, CURRENT_LINE_MARKER_VALUE) >= 0) then
|
||||
debugger.terminate()
|
||||
end
|
||||
PackageEventHandle("onEditorClose", editor)
|
||||
removePage(ide.openDocuments[id].index)
|
||||
|
||||
-- disable full screen if the last tab is closed
|
||||
@@ -387,50 +431,47 @@ function SaveOnExit(allow_cancel)
|
||||
return true
|
||||
end
|
||||
|
||||
-- circle through "fold all" => "hide base lines" => "unfold all"
|
||||
function FoldSome()
|
||||
local editor = GetEditor()
|
||||
editor:Colourise(0, -1) -- update doc's folding info
|
||||
local visible, baseFound, expanded, folded
|
||||
for ln = 2, editor.LineCount - 1 do
|
||||
local foldall = false -- at least on header unfolded => fold all
|
||||
local hidebase = false -- at least one base is visible => hide all
|
||||
|
||||
for ln = 0, editor.LineCount - 1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if not baseFound and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
baseFound = true
|
||||
visible = editor:GetLineVisible(ln)
|
||||
end
|
||||
if foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
expanded = true
|
||||
else
|
||||
folded = true
|
||||
end
|
||||
end
|
||||
if expanded and folded and baseFound then break end
|
||||
end
|
||||
local show = not visible or (not baseFound and expanded) or (expanded and folded)
|
||||
local hide = visible and folded
|
||||
|
||||
if show then
|
||||
editor:ShowLines(1, editor.LineCount-1)
|
||||
-- at least one header is expanded
|
||||
foldall = foldall or (foldHdr and editor:GetFoldExpanded(ln))
|
||||
|
||||
-- at least one base can be hidden
|
||||
hidebase = hidebase or (
|
||||
not foldHdr
|
||||
and ln > 1 -- first line can't be hidden, so ignore it
|
||||
and foldLvl == wxstc.wxSTC_FOLDLEVELBASE
|
||||
and bit.band(foldRaw, wxstc.wxSTC_FOLDLEVELWHITEFLAG) == 0
|
||||
and editor:GetLineVisible(ln))
|
||||
end
|
||||
|
||||
for ln = 1, editor.LineCount - 1 do
|
||||
-- shows lines; this doesn't change fold status for folded lines
|
||||
if not foldall and not hidebase then editor:ShowLines(0, editor.LineCount-1) end
|
||||
|
||||
for ln = 0, editor.LineCount-1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if show then
|
||||
if foldHdr then
|
||||
if not editor:GetFoldExpanded(ln) then editor:ToggleFold(ln) end
|
||||
end
|
||||
elseif hide and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
if not foldHdr then
|
||||
editor:HideLines(ln, ln)
|
||||
end
|
||||
elseif foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln)
|
||||
end
|
||||
|
||||
if foldall then
|
||||
if foldHdr and editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln) end
|
||||
elseif hidebase then
|
||||
if not foldHdr and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
editor:HideLines(ln, ln) end
|
||||
else -- unfold all
|
||||
if foldHdr and not editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln) end
|
||||
end
|
||||
end
|
||||
editor:EnsureCaretVisible()
|
||||
@@ -546,22 +587,10 @@ function GetOpenFiles()
|
||||
return opendocs, {index = (id and openDocuments[id].index or 0)}
|
||||
end
|
||||
|
||||
local function scrollToPos(editor, pos)
|
||||
editor:GotoPos(pos)
|
||||
-- GotoPos should work by itself, but it doesn't (wx 2.9.5).
|
||||
-- It's off by one line on Windows and by two lines on OSX.
|
||||
-- This code corrects for that discrepancy. The horizontal scrollbar
|
||||
-- is still off, so the scrolling is always moved to the zero offset.
|
||||
local nowline = editor:DocLineFromVisible(editor:GetFirstVisibleLine())
|
||||
local wantline = editor:LineFromPosition(pos)
|
||||
editor:LineScroll(0, wantline-nowline)
|
||||
editor:SetXOffset(0)
|
||||
end
|
||||
|
||||
function SetOpenFiles(nametab,params)
|
||||
for i,doc in ipairs(nametab) do
|
||||
local editor = LoadFile(doc.filename,nil,true,true) -- skip selection
|
||||
if editor then scrollToPos(editor, doc.cursorpos or 0) end
|
||||
if editor then editor:GotoPosDelayed(doc.cursorpos or 0) end
|
||||
end
|
||||
notebook:SetSelection(params and params.index or 0)
|
||||
SetEditorSelection()
|
||||
@@ -571,8 +600,12 @@ local beforeFullScreenPerspective
|
||||
function ShowFullScreen(setFullScreen)
|
||||
if setFullScreen then
|
||||
beforeFullScreenPerspective = uimgr:SavePerspective()
|
||||
uimgr:GetPane("bottomnotebook"):Show(false)
|
||||
uimgr:GetPane("projpanel"):Show(false)
|
||||
|
||||
local panes = frame.uimgr:GetAllPanes()
|
||||
for index = 0, panes:GetCount()-1 do
|
||||
local name = panes:Item(index).name
|
||||
if name ~= "notebook" then frame.uimgr:GetPane(name):Hide() end
|
||||
end
|
||||
uimgr:Update()
|
||||
SetEditorSelection() -- make sure the focus is on the editor
|
||||
elseif beforeFullScreenPerspective then
|
||||
@@ -617,12 +650,12 @@ function SetOpenTabs(params)
|
||||
if doc.content then
|
||||
notebook:SetPageText(opendoc.index, doc.tabname)
|
||||
editor:SetText(doc.content)
|
||||
if doc.filename and doc.modified < opendoc.modTime:GetTicks() then
|
||||
if doc.filename and opendoc.modTime and doc.modified < opendoc.modTime:GetTicks() then
|
||||
DisplayOutputLn(TR("File '%s' has more recent timestamp than restored '%s'; please review before saving.")
|
||||
:format(doc.filename, doc.tabname))
|
||||
end
|
||||
end
|
||||
scrollToPos(editor, doc.cursorpos or 0)
|
||||
editor:GotoPosDelayed(doc.cursorpos or 0)
|
||||
end
|
||||
notebook:SetSelection(params and params.index or 0)
|
||||
SetEditorSelection()
|
||||
@@ -671,14 +704,12 @@ local function saveAutoRecovery(event)
|
||||
end
|
||||
|
||||
local function fastWrap(func, ...)
|
||||
-- open files, but ignore some functions that are not needed;
|
||||
-- as we may be opening multiple files, it doesn't make sense to
|
||||
-- select editor and do some other similar work after each file.
|
||||
local noop = function() end
|
||||
local SES, SAFTH = SetEditorSelection, SettingsAppendFileToHistory
|
||||
SetEditorSelection, SettingsAppendFileToHistory = noop, noop
|
||||
-- ignore SetEditorSelection that is not needed as `func` may work on
|
||||
-- multipe files, but editor needs to be selected once.
|
||||
local SES = SetEditorSelection
|
||||
SetEditorSelection = function() end
|
||||
func(...)
|
||||
SetEditorSelection, SettingsAppendFileToHistory = SES, SAFTH
|
||||
SetEditorSelection = SES
|
||||
end
|
||||
|
||||
function StoreRestoreProjectTabs(curdir, newdir)
|
||||
@@ -694,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
|
||||
@@ -762,6 +796,8 @@ local function closeWindow(event)
|
||||
|
||||
ShowFullScreen(false)
|
||||
|
||||
PackageEventHandle("onAppClose")
|
||||
|
||||
SettingsSaveAll()
|
||||
ide.settings:Flush()
|
||||
|
||||
@@ -776,7 +812,12 @@ local function closeWindow(event)
|
||||
frame.uimgr:UnInit()
|
||||
frame:Hide() -- hide the main frame while the IDE exits
|
||||
|
||||
if DebuggerShutdown then DebuggerShutdown() end
|
||||
-- first need to detach all processes IDE has launched as the current
|
||||
-- process is likely to terminate before child processes are terminated,
|
||||
-- which may lead to a crash when EVT_END_PROCESS event is called.
|
||||
DetachChildProcess()
|
||||
DebuggerShutdown()
|
||||
|
||||
if ide.session.timer then ide.session.timer:Stop() end
|
||||
|
||||
event:Skip()
|
||||
@@ -785,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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
-- Integration with MobDebug
|
||||
-- Copyright 2011-12 Paul Kulchenko, ZeroBrane LLC
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
-- Original authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
|
||||
@@ -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
|
||||
@@ -31,13 +28,37 @@ local CURRENT_LINE_MARKER_VALUE = 2^CURRENT_LINE_MARKER
|
||||
local BREAKPOINT_MARKER = StylesGetMarker("breakpoint")
|
||||
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),
|
||||
math.floor(bgcl:Green()*.9), math.floor(bgcl:Blue()*.9))
|
||||
for idx = 0, watchCtrl:GetItemCount() - 1 do
|
||||
if not num or idx == num then
|
||||
local expression = watchCtrl:GetItemText(idx)
|
||||
@@ -54,9 +75,7 @@ local function updateWatchesSync(num)
|
||||
watchCtrl:GetItem(litem)
|
||||
watchCtrl:SetItemBackgroundColour(idx,
|
||||
watchCtrl:GetItem(litem) and newval ~= litem:GetText()
|
||||
and ide.config.styles.caretlinebg
|
||||
and wx.wxColour(unpack(ide.config.styles.caretlinebg.bg))
|
||||
or watchCtrl:GetBackgroundColour())
|
||||
and hicl or bgcl)
|
||||
end
|
||||
|
||||
watchCtrl:SetItem(idx, 1, newval)
|
||||
@@ -67,6 +86,7 @@ end
|
||||
|
||||
local simpleType = {['nil'] = true, ['string'] = true, ['number'] = true, ['boolean'] = true}
|
||||
local stackItemValue = {}
|
||||
local callData = {}
|
||||
local function checkIfExpandable(value, item)
|
||||
local expandable = type(value) == 'table' and next(value) ~= nil
|
||||
and not stackItemValue[value] -- only expand first time
|
||||
@@ -79,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
|
||||
@@ -92,47 +113,65 @@ 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
|
||||
for _,frame in ipairs(stack) do
|
||||
-- "main chunk at line 24"
|
||||
-- "foo() at line 13 (defined at foobar.lua:11)"
|
||||
-- call = { source.name, source.source, source.linedefined,
|
||||
-- source.currentline, source.what, source.namewhat, source.short_src }
|
||||
local call = frame[1]
|
||||
|
||||
-- format the function name to a readable user string
|
||||
local func = call[5] == "main" and "main chunk"
|
||||
or call[5] == "C" and (call[1] or "C function")
|
||||
or call[5] == "tail" and "tail call"
|
||||
or (call[1] or "anonymous function")
|
||||
|
||||
-- format the function treeitem text string, including the function name
|
||||
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)
|
||||
|
||||
-- register call data to provide stack navigation
|
||||
callData[callitem:GetValue()] = { call[2], call[4] }
|
||||
|
||||
-- add the local variables to the call stack item
|
||||
for name,val in pairs(frame[2]) do
|
||||
-- format the variable name, value as a single line and,
|
||||
-- if not a simple type, the string value.
|
||||
|
||||
-- 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
|
||||
stackCtrl:SetItemHasChildren(item, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- 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
|
||||
stackCtrl:SetItemHasChildren(item, true)
|
||||
end
|
||||
end
|
||||
|
||||
stackCtrl:SortChildren(callitem)
|
||||
stackCtrl:Expand(callitem)
|
||||
end
|
||||
@@ -198,24 +237,40 @@ local function killClient()
|
||||
end
|
||||
end
|
||||
|
||||
local function activateDocument(file, line, skipauto)
|
||||
local function activateDocument(file, line, activatehow)
|
||||
if not file then return end
|
||||
|
||||
if not wx.wxIsAbsolutePath(file) and debugger.basedir then
|
||||
-- file can be a filename or serialized file content; deserialize first.
|
||||
-- check if the filename starts with '"' and is deserializable
|
||||
-- to avoid showing filenames that may look like valid lua code
|
||||
-- (for example: 'mobdebug.lua').
|
||||
local content
|
||||
if not wx.wxFileName(file):FileExists() and file:find('^"') then
|
||||
local ok, res = LoadSafe("return "..file)
|
||||
if ok then content = res end
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
local activated
|
||||
local indebugger = file:find('mobdebug%.lua$')
|
||||
local fileName = wx.wxFileName(file)
|
||||
|
||||
for _, document in pairs(ide.openDocuments) do
|
||||
-- skip those tabs that may have file without names (untitled.lua)
|
||||
if document.filePath and fileName:SameAs(wx.wxFileName(document.filePath)) then
|
||||
local editor = document.editor
|
||||
local selection = document.index
|
||||
RequestAttention()
|
||||
notebook:SetSelection(selection)
|
||||
SetEditorSelection(selection)
|
||||
local editor = document.editor
|
||||
-- either the file name matches, or the content;
|
||||
-- when checking for the content remove all newlines as they may be
|
||||
-- reported differently from the original by the Lua engine.
|
||||
if document.filePath and fileName:SameAs(wx.wxFileName(document.filePath))
|
||||
or content and content:gsub("[\n\r]","") == editor:GetText():gsub("[\n\r]","") then
|
||||
ClearAllCurrentLineMarkers()
|
||||
if line then
|
||||
if line == 0 then -- special case; find the first executable line
|
||||
@@ -230,6 +285,11 @@ local function activateDocument(file, line, skipauto)
|
||||
end
|
||||
local line = line - 1 -- editor line operations are zero-based
|
||||
editor:MarkerAdd(line, CURRENT_LINE_MARKER)
|
||||
|
||||
-- found and marked what we are looking for;
|
||||
-- don't need to activate with CHECKONLY (this assumes line is given)
|
||||
if activatehow == activate.CHECKONLY then return editor end
|
||||
|
||||
local firstline = editor:DocLineFromVisible(editor:GetFirstVisibleLine())
|
||||
local lastline = math.min(editor:GetLineCount(),
|
||||
editor:DocLineFromVisible(editor:GetFirstVisibleLine() + editor:LinesOnScreen()))
|
||||
@@ -238,21 +298,49 @@ local function activateDocument(file, line, skipauto)
|
||||
editor:EnsureVisibleEnforcePolicy(line)
|
||||
end
|
||||
end
|
||||
|
||||
local selection = document.index
|
||||
RequestAttention()
|
||||
notebook:SetSelection(selection)
|
||||
SetEditorSelection(selection)
|
||||
|
||||
if content then
|
||||
-- it's possible that the current editor tab already has
|
||||
-- breakpoints that have been set based on its filepath;
|
||||
-- if the content has been matched, then existing breakpoints
|
||||
-- need to be removed and new ones set, based on the content.
|
||||
if not debugger.editormap[editor] and document.filePath then
|
||||
local filePath = document.filePath
|
||||
local line = editor:MarkerNext(0, BREAKPOINT_MARKER_VALUE)
|
||||
while filePath and line ~= -1 do
|
||||
debugger.handle("delb " .. filePath .. " " .. (line+1))
|
||||
debugger.handle("setb " .. file .. " " .. (line+1))
|
||||
line = editor:MarkerNext(line + 1, BREAKPOINT_MARKER_VALUE)
|
||||
end
|
||||
end
|
||||
|
||||
-- keep track of those editors that have been activated based on
|
||||
-- content rather than file names as their breakpoints have to be
|
||||
-- specified in a different way
|
||||
debugger.editormap[editor] = file
|
||||
end
|
||||
|
||||
activated = editor
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not (activated or indebugger or debugger.loop or skipauto)
|
||||
and ide.config.editor.autoactivate then
|
||||
if not (activated or indebugger or debugger.loop or activatehow == activate.CHECKONLY)
|
||||
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 co-routine), so schedule pending activation.
|
||||
if wx.wxFileName(file):FileExists() then
|
||||
debugger.activate = {file, line}
|
||||
-- in a different coroutine), so schedule pending activation.
|
||||
if content or wx.wxFileName(file):FileExists() then
|
||||
debugger.activate = {file, line, content}
|
||||
return true -- report successful activation, even though it's pending
|
||||
end
|
||||
|
||||
if not debugger.missing[file] then -- only report files once per session
|
||||
-- only report files once per session and if not asked to skip
|
||||
if not debugger.missing[file] and activatehow ~= activate.NOREPORT then
|
||||
debugger.missing[file] = true
|
||||
DisplayOutputLn(TR("Couldn't activate file '%s' for debugging; continuing without it.")
|
||||
:format(file))
|
||||
@@ -274,7 +362,7 @@ local function reSetBreakpoints()
|
||||
local editor = document.editor
|
||||
local filePath = document.filePath
|
||||
local line = editor:MarkerNext(0, BREAKPOINT_MARKER_VALUE)
|
||||
while line ~= -1 do
|
||||
while filePath and line ~= -1 do
|
||||
debugger.handle("setb " .. filePath .. " " .. (line+1))
|
||||
line = editor:MarkerNext(line + 1, BREAKPOINT_MARKER_VALUE)
|
||||
end
|
||||
@@ -317,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
|
||||
@@ -328,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)
|
||||
@@ -338,6 +426,16 @@ debugger.shell = function(expression, isstatement)
|
||||
end
|
||||
end
|
||||
|
||||
local function stoppedAtBreakpoint(file, line)
|
||||
-- if this document can be activated and the current line has a breakpoint
|
||||
local editor = activateDocument(file, line, activate.CHECKONLY)
|
||||
if not editor then return false end
|
||||
|
||||
local current = editor:MarkerNext(0, CURRENT_LINE_MARKER_VALUE)
|
||||
local breakpoint = editor:MarkerNext(current, BREAKPOINT_MARKER_VALUE)
|
||||
return breakpoint > -1 and breakpoint == current
|
||||
end
|
||||
|
||||
debugger.listen = function()
|
||||
local server = socket.bind("*", debugger.portnumber)
|
||||
DisplayOutputLn(TR("Debugger server started at %s:%d.")
|
||||
@@ -350,12 +448,24 @@ 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)
|
||||
|
||||
local options = debugger.options or {}
|
||||
if not debugger.scratchpad then SetAllEditorsReadOnly(true) end
|
||||
-- this may be a remote call without using an interpreter and as such
|
||||
-- debugger.options may not be set, but runonstart is still configured.
|
||||
if not options.runstart then options.runstart = ide.config.debugger.runonstart end
|
||||
|
||||
-- support allowediting as set in the interpreter or config
|
||||
if not options.allowediting then options.allowediting = ide.config.debugger.allowediting end
|
||||
|
||||
if not debugger.scratchpad and not options.allowediting then
|
||||
SetAllEditorsReadOnly(true) end
|
||||
|
||||
debugger.server = copas.wrap(skt)
|
||||
debugger.socket = skt
|
||||
@@ -363,6 +473,7 @@ debugger.listen = function()
|
||||
debugger.scratchable = false
|
||||
debugger.stats = {line = 0}
|
||||
debugger.missing = {}
|
||||
debugger.editormap = {}
|
||||
|
||||
local wxfilepath = GetEditorFileAndCurInfo()
|
||||
local startfile = options.startfile or options.startwith
|
||||
@@ -385,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
|
||||
@@ -402,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"
|
||||
@@ -419,6 +535,10 @@ debugger.listen = function()
|
||||
.." "..TR("Compilation error")
|
||||
..":\n"..err)
|
||||
return debugger.terminate()
|
||||
elseif options.runstart and not debugger.scratchpad
|
||||
and stoppedAtBreakpoint(file, line) then
|
||||
activateDocument(file, line)
|
||||
options.runstart = false
|
||||
end
|
||||
elseif not (options.run or debugger.scratchpad) then
|
||||
local file, line, err = debugger.loadfile(startfile)
|
||||
@@ -432,20 +552,16 @@ debugger.listen = function()
|
||||
..":\n"..err)
|
||||
return debugger.terminate()
|
||||
elseif options.runstart then
|
||||
-- check if this document can be activated and if the first line
|
||||
-- has a breakpoint, then don't run immediately
|
||||
if activateDocument(file or startfile, line or 0, true) then
|
||||
local editor = GetEditor()
|
||||
local current = editor:MarkerNext(0, CURRENT_LINE_MARKER_VALUE)
|
||||
local breakpoint = editor:MarkerNext(current, BREAKPOINT_MARKER_VALUE)
|
||||
if current > -1 and current == breakpoint then options.runstart = false end
|
||||
if stoppedAtBreakpoint(file or startfile, line or 0) then
|
||||
activateDocument(file or startfile, line or 0)
|
||||
options.runstart = false
|
||||
end
|
||||
elseif file and line then
|
||||
local activated = activateDocument(file, line, true)
|
||||
local activated = activateDocument(file, line, activate.NOREPORT)
|
||||
|
||||
-- if not found, check using full file path and reset basedir
|
||||
if not activated and not wx.wxIsAbsolutePath(file) then
|
||||
activated = activateDocument(startpath..file, line, true)
|
||||
activated = activateDocument(startpath..file, line, activate.NOREPORT)
|
||||
if activated then
|
||||
debugger.basedir = startpath
|
||||
debugger.handle("basedir " .. debugger.basedir)
|
||||
@@ -455,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
|
||||
@@ -479,7 +598,7 @@ debugger.listen = function()
|
||||
end
|
||||
|
||||
-- if found a local mapping under basedir
|
||||
activated = longestpath and activateDocument(longestpath, line, true)
|
||||
activated = longestpath and activateDocument(longestpath, line, activate.NOREPORT)
|
||||
if activated then
|
||||
-- find remote basedir by removing the tail from remote file
|
||||
debugger.handle("basedir " .. debugger.basedir .. "\t" .. remotedir)
|
||||
@@ -624,15 +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 = (table.unpack or unpack)(debugger.activate)
|
||||
if LoadFile(file) then activateDocument(file, line) end
|
||||
debugger.activate = nil
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
debugger.terminate = function()
|
||||
if debugger.server then
|
||||
if debugger.pid then -- if there is PID, try local kill
|
||||
@@ -707,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),
|
||||
@@ -716,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)
|
||||
@@ -725,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)
|
||||
@@ -734,30 +900,39 @@ function debuggerCreateStackWindow()
|
||||
stackCtrl:SetItemHasChildren(item, true)
|
||||
end
|
||||
num = num + 1
|
||||
if num > stackmaxnum then break end
|
||||
end
|
||||
|
||||
stackCtrl:SortChildren(item_id)
|
||||
return true
|
||||
end)
|
||||
stackCtrl:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED,
|
||||
function() return true end)
|
||||
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
|
||||
notebook:AddPage(stackCtrl, TR("Stack"), true)
|
||||
-- register navigation callback
|
||||
stackCtrl:Connect(wx.wxEVT_LEFT_DCLICK, function (event)
|
||||
local item_id = stackCtrl:HitTest(event:GetPosition())
|
||||
if not item_id or not item_id:IsOk() then event:Skip() return end
|
||||
|
||||
local mgr = ide.frame.uimgr
|
||||
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
|
||||
Name("stackpanel"):Float():
|
||||
MinSize(height,height):FloatingSize(width,height):
|
||||
PinButton(true):Hide())
|
||||
mgr.defaultPerspective = mgr:SavePerspective() -- resave default perspective
|
||||
local coords = callData[item_id:GetValue()]
|
||||
if not coords then event:Skip() return end
|
||||
|
||||
local file, line = coords[1], coords[2]
|
||||
if file:match("@") then file = string.sub(file, 2) end
|
||||
file = GetFullPathIfExists(debugger.basedir, file)
|
||||
if file then
|
||||
local editor = LoadFile(file,nil,true)
|
||||
editor:SetFocus()
|
||||
if line then editor:GotoPos(editor:PositionFromLine(line-1)) end
|
||||
end
|
||||
end)
|
||||
|
||||
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()
|
||||
local watchCtrl = wx.wxListCtrl(frame, wx.wxID_ANY,
|
||||
local watchCtrl = wx.wxListCtrl(ide.frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxLC_REPORT + wx.wxLC_EDIT_LABELS)
|
||||
|
||||
@@ -809,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)
|
||||
@@ -833,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()
|
||||
@@ -847,18 +1023,12 @@ local function debuggerCreateWatchWindow()
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
|
||||
notebook:AddPage(watchCtrl, TR("Watch"), true)
|
||||
|
||||
local mgr = ide.frame.uimgr
|
||||
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
|
||||
Name("watchpanel"):Float():
|
||||
MinSize(height,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()
|
||||
@@ -872,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
|
||||
@@ -932,7 +1102,8 @@ function DebuggerToggleBreakpoint(editor, line)
|
||||
markers = markers - CURRENT_LINE_MARKER_VALUE
|
||||
end
|
||||
local id = editor:GetId()
|
||||
local filePath = DebuggerMakeFileName(editor, ide.openDocuments[id].filePath)
|
||||
local filePath = debugger.editormap and debugger.editormap[editor]
|
||||
or DebuggerMakeFileName(editor, ide.openDocuments[id].filePath)
|
||||
if markers >= BREAKPOINT_MARKER_VALUE then
|
||||
editor:MarkerDelete(line, BREAKPOINT_MARKER)
|
||||
if debugger.server then
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,27 +6,15 @@ local ide = ide
|
||||
--
|
||||
|
||||
ide.filetree = {
|
||||
dirdriveText = "",
|
||||
dirdriveTextArray = {},
|
||||
|
||||
projdirText = "",
|
||||
projdirTextArray = {},
|
||||
|
||||
showroot = true,
|
||||
|
||||
dirdata = {
|
||||
root_id = nil,
|
||||
rootdir = "",
|
||||
},
|
||||
|
||||
projdata = {
|
||||
root_id = nil,
|
||||
rootdir = "",
|
||||
},
|
||||
projdir = "",
|
||||
projdirlist = {},
|
||||
projdirmap = {},
|
||||
projdirpartmap = {},
|
||||
}
|
||||
local filetree = ide.filetree
|
||||
|
||||
local iscaseinsensitive = wx.wxFileName("A"):SameAs(wx.wxFileName("a"))
|
||||
local pathsep = GetPathSeparator()
|
||||
|
||||
-- generic tree
|
||||
-- ------------
|
||||
@@ -57,7 +45,7 @@ local function treeAddDir(tree,parent_id,rootdir)
|
||||
local curr
|
||||
|
||||
for _, file in ipairs(FileSysGetRecursive(rootdir)) do
|
||||
local name, dir = file:match("("..stringset_File.."+)("..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]
|
||||
@@ -97,72 +85,80 @@ local function treeAddDir(tree,parent_id,rootdir)
|
||||
tree:GetChildrenCount(parent_id, false) > 0)
|
||||
end
|
||||
|
||||
local function treeGetItemFullName(tree,treedata,item_id)
|
||||
local str = tree:GetItemText(item_id)
|
||||
local cur = str
|
||||
|
||||
while (#cur > 0) do
|
||||
item_id = tree:GetItemParent(item_id)
|
||||
cur = tree:GetItemText(item_id)
|
||||
if cur and string.len(cur) > 0 then str = cur..string_Pathsep..str end
|
||||
end
|
||||
-- as root may already include path separator, normalize the path
|
||||
local fullPath = wx.wxFileName(
|
||||
filetree.showroot and str or filetree.projdata.rootdir .. str)
|
||||
fullPath:Normalize()
|
||||
return fullPath:GetFullPath()
|
||||
end
|
||||
|
||||
local function treeSetRoot(tree,treedata,rootdir)
|
||||
local function treeSetRoot(tree,rootdir)
|
||||
tree:DeleteAllItems()
|
||||
if (not wx.wxDirExists(rootdir)) then
|
||||
treedata.root_id = nil
|
||||
return
|
||||
end
|
||||
if (not wx.wxDirExists(rootdir)) then return end
|
||||
|
||||
local root_id = tree:AddRoot(rootdir, IMG_DIRECTORY)
|
||||
treedata.root_id = root_id
|
||||
treedata.rootdir = rootdir
|
||||
|
||||
-- make sure that the item can expand
|
||||
tree:SetItemHasChildren(root_id, true)
|
||||
tree:SetItemHasChildren(root_id, true) -- make sure that the item can expand
|
||||
tree:Expand(root_id) -- this will also populate the tree
|
||||
end
|
||||
|
||||
local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
local function treeSetConnectorsAndIcons(tree)
|
||||
tree:SetImageList(filetree.imglist)
|
||||
|
||||
-- connect to some events from the wxTreeCtrl
|
||||
function tree:GetItemFullName(item_id)
|
||||
local tree = self
|
||||
local str = tree:GetItemText(item_id)
|
||||
local cur = str
|
||||
|
||||
while (#cur > 0) do
|
||||
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..pathsep..str end
|
||||
end
|
||||
-- as root may already include path separator, normalize the path
|
||||
local fullPath = wx.wxFileName(str)
|
||||
fullPath:Normalize()
|
||||
return fullPath:GetFullPath()
|
||||
end
|
||||
|
||||
local function refreshAncestors(node)
|
||||
while node:IsOk() do
|
||||
local dir = tree:GetItemFullName(node)
|
||||
treeAddDir(tree,node,dir)
|
||||
node = tree:GetItemParent(node)
|
||||
end
|
||||
end
|
||||
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
local dir = treeGetItemFullName(tree,treedata,item_id)
|
||||
treeAddDir(tree,item_id,dir)
|
||||
local dir = tree:GetItemFullName(item_id)
|
||||
|
||||
if wx.wxDirExists(dir) then treeAddDir(tree,item_id,dir) -- refresh folder
|
||||
else refreshAncestors(tree:GetItemParent(item_id)) end -- stale content
|
||||
return true
|
||||
end)
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED,
|
||||
function() return true end)
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
|
||||
local name = treeGetItemFullName(tree,treedata,item_id)
|
||||
local name = tree:GetItemFullName(item_id)
|
||||
-- refresh the folder
|
||||
if (tree:GetItemImage(item_id) == IMG_DIRECTORY) then
|
||||
if wx.wxFileName(name):DirExists() then
|
||||
treeAddDir(tree,item_id,name) -- refresh the content
|
||||
else -- stale filetree information; rescan
|
||||
treeAddDir(tree,tree:GetItemParent(item_id),name)
|
||||
end
|
||||
if wx.wxDirExists(name) then treeAddDir(tree,item_id,name)
|
||||
else refreshAncestors(tree:GetItemParent(item_id)) end -- stale content
|
||||
else -- open file
|
||||
if wx.wxFileName(name):FileExists() then
|
||||
LoadFile(name,nil,true)
|
||||
else -- stale filetree information; rescan
|
||||
treeAddDir(tree,tree:GetItemParent(item_id),name)
|
||||
end
|
||||
if wx.wxFileExists(name) then LoadFile(name,nil,true)
|
||||
else refreshAncestors(tree:GetItemParent(item_id)) end -- stale content
|
||||
end
|
||||
end)
|
||||
-- toggle a folder on
|
||||
-- handle context menu
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_MENU,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
tree:SelectItem(item_id)
|
||||
local menu = wx.wxMenu()
|
||||
menu:Append(ID_SHOWLOCATION, TR("Show Location"))
|
||||
tree:Connect(ID_SHOWLOCATION, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function() ShowLocation(tree:GetItemFullName(item_id)) end)
|
||||
|
||||
PackageEventHandle("onMenuFiletree", menu, tree, event)
|
||||
|
||||
tree:PopupMenu(menu)
|
||||
end)
|
||||
-- toggle a folder on a single click
|
||||
tree:Connect( wx.wxEVT_LEFT_DOWN,
|
||||
function( event )
|
||||
local item_id = tree:HitTest(event:GetPosition())
|
||||
@@ -183,18 +179,16 @@ end
|
||||
-- (treectrl)
|
||||
local projpanel = ide.frame.projpanel
|
||||
local projcombobox = wx.wxComboBox(projpanel, ID "filetree.proj.drivecb",
|
||||
filetree.projdirText,
|
||||
filetree.projdir,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
filetree.projdirTextArray, wx.wxTE_PROCESS_ENTER)
|
||||
filetree.projdirlist, wx.wxTE_PROCESS_ENTER)
|
||||
|
||||
local projbutton = wx.wxButton(projpanel, ID_PROJECTDIRCHOOSE,
|
||||
"...",wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
"...", wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
|
||||
local projtree = wx.wxTreeCtrl(projpanel, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
filetree.showroot
|
||||
and (wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE)
|
||||
or (wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT))
|
||||
wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_LINES_AT_ROOT)
|
||||
|
||||
-- use the same font in the combobox as is used in the filetree
|
||||
projtree:SetFont(ide.font.fNormal)
|
||||
@@ -217,51 +211,80 @@ 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
|
||||
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_COMBOBOX_SELECTED, projcomboboxUpdate)
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_TEXT_ENTER, projcomboboxUpdate)
|
||||
|
||||
treeSetConnectorsAndIcons(projtree,filetree.projdata)
|
||||
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)
|
||||
|
||||
if filetree.projdirText and #filetree.projdirText > 0
|
||||
and dirname:SameAs(wx.wxFileName.DirName(filetree.projdirText)) then return end
|
||||
if filetree.projdir and #filetree.projdir > 0
|
||||
and dirname:SameAs(wx.wxFileName.DirName(filetree.projdir)) then return end
|
||||
|
||||
-- strip the last path separator if any
|
||||
local newdir = dirname:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
|
||||
if ide.config.projectautoopen and filetree.projdirText then
|
||||
StoreRestoreProjectTabs(filetree.projdirText, newdir)
|
||||
if filetree.projdir and #filetree.projdir > 0 then
|
||||
PackageEventHandle("onProjectClose", filetree.projdir) end
|
||||
|
||||
if ide.config.projectautoopen and filetree.projdir then
|
||||
StoreRestoreProjectTabs(filetree.projdir, newdir)
|
||||
end
|
||||
|
||||
filetree.projdirText = newdir
|
||||
filetree.projdir = newdir
|
||||
filetree.projdirpartmap = {}
|
||||
|
||||
PrependStringToArray(filetree.projdirTextArray,newdir,ide.config.projecthistorylength)
|
||||
PackageEventHandle("onProjectLoad", filetree.projdir)
|
||||
|
||||
PrependStringToArray(
|
||||
filetree.projdirlist,
|
||||
newdir,
|
||||
ide.config.projecthistorylength,
|
||||
function(s1, s2) return dirname:SameAs(wx.wxFileName.DirName(s2)) end)
|
||||
projcombobox:Clear()
|
||||
projcombobox:Append(filetree.projdirTextArray)
|
||||
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,filetree.projdata,newdir)
|
||||
treeSetRoot(projtree,newdir)
|
||||
|
||||
-- sync with the current editor window and activate selected file
|
||||
local editor = GetEditor()
|
||||
@@ -278,19 +301,19 @@ projpanel.projcombobox = projcombobox
|
||||
projpanel.projtree = projtree
|
||||
|
||||
function FileTreeGetDir()
|
||||
return projpanel:IsShown() and filetree.projdata.rootdir
|
||||
and wx.wxFileName.DirName(filetree.projdata.rootdir):GetFullPath()
|
||||
return filetree.projdir and #filetree.projdir > 0
|
||||
and wx.wxFileName.DirName(filetree.projdir):GetFullPath()
|
||||
end
|
||||
|
||||
function FileTreeSetProjects(tab)
|
||||
filetree.projdirTextArray = tab
|
||||
filetree.projdirlist = tab
|
||||
if (tab and tab[1]) then
|
||||
filetree:updateProjectDir(tab[1])
|
||||
end
|
||||
end
|
||||
|
||||
function FileTreeGetProjects()
|
||||
return filetree.projdirTextArray
|
||||
return filetree.projdirlist
|
||||
end
|
||||
|
||||
local function findItem(tree, match)
|
||||
@@ -305,14 +328,14 @@ 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
|
||||
node = cache[iscaseinsensitive and token:lower() or token]
|
||||
else
|
||||
-- token is missing; may need to re-scan the folder; maybe new file
|
||||
local dir = treeGetItemFullName(tree,filetree.projdata,node)
|
||||
local dir = tree:GetItemFullName(node)
|
||||
treeAddDir(tree,node,dir)
|
||||
|
||||
local item, cookie = tree:GetFirstChild(node)
|
||||
@@ -333,7 +356,7 @@ end
|
||||
|
||||
local curr_file
|
||||
function FileTreeMarkSelected(file)
|
||||
if not file or not filetree.projdirText or #filetree.projdirText == 0 then return end
|
||||
if not file or not filetree.projdir or #filetree.projdir == 0 then return end
|
||||
|
||||
local item_id = findItem(projtree, file)
|
||||
|
||||
@@ -359,6 +382,20 @@ function FileTreeMarkSelected(file)
|
||||
end
|
||||
end
|
||||
|
||||
function FileTreeRefresh()
|
||||
treeSetRoot(projtree,filetree.projdata,filetree.projdirText)
|
||||
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
|
||||
|
||||
@@ -13,14 +13,14 @@ 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
|
||||
findText = "", -- string to find
|
||||
replaceTextArray = {}, -- array of last entered replace text
|
||||
replaceText = "", -- string to replace find string with
|
||||
filemaskText = "*.*",
|
||||
filemaskText = nil,
|
||||
filemaskTextArray= {},
|
||||
filedirText = "",
|
||||
filedirTextArray = {},
|
||||
@@ -46,26 +46,30 @@ 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)
|
||||
end
|
||||
|
||||
local function setTarget(editor, fDown, fInclude)
|
||||
local function setTarget(editor, fDown, fAll, fWrap)
|
||||
local selStart = editor:GetSelectionStart()
|
||||
local selEnd = editor:GetSelectionEnd()
|
||||
local len = editor:GetLength()
|
||||
local s, e
|
||||
if fDown then
|
||||
e= len
|
||||
s = iff(fInclude, selStart, selEnd +1)
|
||||
s = iff(fAll, selStart, selEnd)
|
||||
e = len
|
||||
else
|
||||
s = 0
|
||||
e = iff(fInclude, selEnd, selStart-1)
|
||||
e = iff(fAll, selEnd, selStart)
|
||||
end
|
||||
if not fDown and not fInclude then s, e = e, s end
|
||||
-- if going up and not search/replace All, then switch the range to
|
||||
-- allow the next match to be properly marked
|
||||
if not fDown and not fAll then s, e = e, s end
|
||||
-- if wrap around and search all requested, then search the entire document
|
||||
if fAll and fWrap then s, e = 0, len end
|
||||
editor:SetTargetStart(s)
|
||||
editor:SetTargetEnd(e)
|
||||
return e
|
||||
@@ -92,17 +96,35 @@ function findReplace:GetSelectedString()
|
||||
local endSel = editor:GetSelectionEnd()
|
||||
if (startSel ~= endSel) and (editor:LineFromPosition(startSel) == editor:LineFromPosition(endSel)) then
|
||||
findReplace.findText = editor:GetSelectedText()
|
||||
findReplace.foundString = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
return editor and findReplace.foundString
|
||||
return false
|
||||
end
|
||||
|
||||
local function shake(window, shakes, duration, vigour)
|
||||
shakes = shakes or 4
|
||||
duration = duration or 0.5
|
||||
vigour = vigour or 0.05
|
||||
|
||||
if not window then return end
|
||||
|
||||
local delay = math.floor(duration/shakes/2)
|
||||
local position = window:GetPosition() -- get current position
|
||||
local deltax = window:GetSize():GetWidth()*vigour
|
||||
for s = 1, shakes do
|
||||
window:Move(position:GetX()-deltax, position:GetY())
|
||||
wx.wxMilliSleep(delay)
|
||||
window:Move(position:GetX()+deltax, position:GetY())
|
||||
wx.wxMilliSleep(delay)
|
||||
end
|
||||
window:Move(position) -- restore position
|
||||
end
|
||||
|
||||
function findReplace:FindString(reverse)
|
||||
if findReplace:HasText() then
|
||||
local editor = findReplace:GetEditor()
|
||||
local fDown = iff(reverse, not findReplace.fDown, findReplace.fDown)
|
||||
local lenFind = string.len(findReplace.findText)
|
||||
setSearchFlags(editor)
|
||||
setTarget(editor, fDown)
|
||||
local posFind = editor:SearchInTarget(findReplace.findText)
|
||||
@@ -113,13 +135,15 @@ function findReplace:FindString(reverse)
|
||||
end
|
||||
if posFind == -1 then
|
||||
findReplace.foundString = false
|
||||
ide.frame:SetStatusText("Text not found.")
|
||||
ide.frame:SetStatusText(TR("Text not found."))
|
||||
shake(findReplace.dialog)
|
||||
else
|
||||
findReplace.foundString = true
|
||||
local start = editor:GetTargetStart()
|
||||
local finish = editor:GetTargetEnd()
|
||||
EnsureRangeVisible(start, finish)
|
||||
editor:SetSelection(start, finish)
|
||||
ide.frame:SetStatusText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -157,39 +181,58 @@ end
|
||||
-- registers every position item was found
|
||||
-- supposed for "Search/Replace in Files"
|
||||
|
||||
function findReplace:ReplaceString(fReplaceAll,inFileRegister)
|
||||
function findReplace:ReplaceString(fReplaceAll, inFileRegister)
|
||||
local replaced = false
|
||||
|
||||
if findReplace:HasText() then
|
||||
local replaceLen = string.len(findReplace.replaceText)
|
||||
local findLen = string.len(findReplace.findText)
|
||||
local editor = findReplace:GetEditor()
|
||||
local endTarget = inFileRegister and setTargetAll(editor) or
|
||||
setTarget(editor, findReplace.fDown, fReplaceAll)
|
||||
setTarget(editor, findReplace.fDown, fReplaceAll, findReplace.fWrap)
|
||||
|
||||
if fReplaceAll then
|
||||
setSearchFlags(editor)
|
||||
local occurrences = 0
|
||||
local posFind = editor:SearchInTarget(findReplace.findText)
|
||||
if (posFind ~= -1) then
|
||||
if(not inFileRegister) then editor:BeginUndoAction() end
|
||||
if (not inFileRegister) then editor:BeginUndoAction() end
|
||||
while posFind ~= -1 do
|
||||
if(inFileRegister) then inFileRegister(posFind) end
|
||||
if (inFileRegister) then inFileRegister(posFind) end
|
||||
|
||||
editor:ReplaceTarget(findReplace.replaceText)
|
||||
editor:SetTargetStart(posFind + replaceLen)
|
||||
endTarget = endTarget + replaceLen - findLen
|
||||
local length = editor:GetLength()
|
||||
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)
|
||||
editor:SetTargetEnd(endTarget)
|
||||
posFind = editor:SearchInTarget(findReplace.findText)
|
||||
occurrences = occurrences + 1
|
||||
end
|
||||
if(not inFileRegister) then editor:EndUndoAction() end
|
||||
if (not inFileRegister) then editor:EndUndoAction() end
|
||||
|
||||
replaced = true
|
||||
end
|
||||
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
|
||||
@@ -206,36 +249,50 @@ local function onFileRegister(pos)
|
||||
local line = editor:LineFromPosition(pos)
|
||||
local linepos = pos - editor:PositionFromLine(line)
|
||||
local result = "("..(line+1)..","..(linepos+1).."): "..editor:GetLine(line)
|
||||
DisplayOutput(findReplace.curfilename..result)
|
||||
DisplayOutputLn(findReplace.curfilename..result:gsub("\r?\n$",""))
|
||||
findReplace.occurrences = findReplace.occurrences + 1
|
||||
end
|
||||
|
||||
local function ProcInFiles(startdir,mask,subdirs,replace)
|
||||
if (subdirs) then
|
||||
local dirs = FileSysGet(startdir..string_Pathsep.."*",wx.wxDIR)
|
||||
for _,dir in ipairs(dirs) do
|
||||
ProcInFiles(dir,mask,true,replace)
|
||||
end
|
||||
end
|
||||
local files = FileSysGetRecursive(startdir,subdirs,"*")
|
||||
local start = TimeGet()
|
||||
|
||||
local files = FileSysGet(startdir..string_Pathsep..mask,wx.wxFILE)
|
||||
-- mask could be a list, so generate a table with matching patterns
|
||||
-- accept "*.lua; .txt;.wlua" combinations
|
||||
local masks = {}
|
||||
for m in mask:gmatch("[^%s;]+") do
|
||||
table.insert(masks, m:gsub("%.", "%%."):gsub("%*", ".*").."$")
|
||||
end
|
||||
for _,file in ipairs(files) do
|
||||
-- ignore .bak files when replacing and asked to store .bak files
|
||||
if not (replace and findReplace.fMakeBak and file:find('.bak$')) then
|
||||
findReplace.curfilename = file
|
||||
-- and skip folders as these are included in the list as well
|
||||
if not (replace and findReplace.fMakeBak and file:find('.bak$'))
|
||||
and not IsDirectory(file) then
|
||||
local match = false
|
||||
for _, mask in ipairs(masks) do match = match or file:find(mask) end
|
||||
if match then
|
||||
findReplace.curfilename = file
|
||||
|
||||
local filetext = FileRead(file)
|
||||
if filetext then
|
||||
findReplace.oveditor:SetText(filetext)
|
||||
local filetext = FileRead(file)
|
||||
if filetext and not isBinary(filetext:sub(1, 2048)) then
|
||||
findReplace.oveditor:SetText(filetext)
|
||||
|
||||
if replace then
|
||||
-- check if anything replaced, store changed content, make .bak
|
||||
if findReplace:ReplaceString(true,onFileRegister)
|
||||
and findReplace.fMakeBak and FileWrite(file..".bak",filetext) then
|
||||
FileWrite(file,findReplace.oveditor:GetText())
|
||||
if replace then
|
||||
-- check if anything replaced, store changed content, make .bak
|
||||
if findReplace:ReplaceString(true,onFileRegister)
|
||||
and findReplace.fMakeBak and FileWrite(file..".bak",filetext) then
|
||||
FileWrite(file,findReplace.oveditor:GetText())
|
||||
end
|
||||
else
|
||||
findReplace:FindStringAll(onFileRegister)
|
||||
end
|
||||
|
||||
-- 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
|
||||
else
|
||||
findReplace:FindStringAll(onFileRegister)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -243,46 +300,71 @@ local function ProcInFiles(startdir,mask,subdirs,replace)
|
||||
end
|
||||
|
||||
function findReplace:RunInFiles(replace)
|
||||
if (not findReplace:HasText()) then
|
||||
return
|
||||
end
|
||||
if not findReplace:HasText() then return end
|
||||
|
||||
findReplace.oveditor = wxstc.wxStyledTextCtrl(findReplace.dialog, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(1,1), wx.wxBORDER_STATIC)
|
||||
findReplace.occurrences = 0
|
||||
|
||||
local fname = wx.wxFileName(findReplace.filedirText)
|
||||
ActivateOutput()
|
||||
|
||||
local startdir = findReplace.filedirText
|
||||
DisplayOutput("FindInFiles: "..(replace and "Replacing" or "Searching for").." '"..findReplace.findText.."'.\n")
|
||||
DisplayOutputLn(("%s '%s'."):format(
|
||||
(replace and TR("Replacing") or TR("Searching for")),
|
||||
findReplace.findText))
|
||||
|
||||
ProcInFiles(startdir, findReplace.filemaskText, findReplace.fSubDirs, replace)
|
||||
|
||||
DisplayOutput("FindInFiles: "..findReplace.occurrences.." instance(s) have been "..
|
||||
(replace and "replaced" or "found")..".\n")
|
||||
DisplayOutputLn(("%s %s."):format(
|
||||
(replace and TR("Replaced") or TR("Found")),
|
||||
TR("%d instance", findReplace.occurrences):format(findReplace.occurrences)))
|
||||
|
||||
findReplace.oveditor = nil
|
||||
end
|
||||
|
||||
local function createFindReplaceDialog(replace,infiles)
|
||||
local function getExts()
|
||||
local knownexts = {}
|
||||
for i,spec in pairs(ide.specs) do
|
||||
if (spec.exts) then
|
||||
for n,ext in ipairs(spec.exts) do
|
||||
table.insert(knownexts, "*."..ext)
|
||||
end
|
||||
end
|
||||
end
|
||||
return #knownexts > 0 and table.concat(knownexts, "; ") or nil
|
||||
end
|
||||
|
||||
function findReplace:createDialog(replace,infiles)
|
||||
local ID_FIND_NEXT = 1
|
||||
local ID_REPLACE = 2
|
||||
local ID_REPLACE_ALL = 3
|
||||
local ID_SETDIR = 4
|
||||
|
||||
local mac = ide.osname == 'Macintosh'
|
||||
|
||||
local findReplace = self
|
||||
|
||||
local position = wx.wxDefaultPosition
|
||||
if findReplace.dialog then
|
||||
-- grab current position before destroying the dialog
|
||||
position = findReplace.dialog:GetPosition()
|
||||
findReplace.dialog:Destroy()
|
||||
end
|
||||
|
||||
local findDialog = wx.wxDialog(ide.frame, wx.wxID_ANY, infiles and TR("Find In Files") or TR("Find"),
|
||||
position, wx.wxDefaultSize, wx.wxDEFAULT_DIALOG_STYLE)
|
||||
|
||||
findReplace.replace = replace
|
||||
findReplace.infiles = infiles
|
||||
|
||||
local findDialog = wx.wxDialog(ide.frame, wx.wxID_ANY, infiles and "Find In Files" or "Find",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxDEFAULT_DIALOG_STYLE)
|
||||
|
||||
-- Create right hand buttons and sizer
|
||||
local findButton = wx.wxButton(findDialog, ID_FIND_NEXT, infiles and "&Find All" or "&Find Next")
|
||||
findButton:SetDefault()
|
||||
local replaceButton = wx.wxButton(findDialog, ID_REPLACE, infiles and replace and "&Replace All" or "&Replace")
|
||||
local findButton = wx.wxButton(findDialog, ID_FIND_NEXT, infiles and TR("&Find All") or TR("&Find Next"))
|
||||
local replaceButton = wx.wxButton(findDialog, ID_REPLACE, infiles and replace and TR("&Replace All") or TR("&Replace"))
|
||||
local replaceAllButton = nil
|
||||
if (replace and not infiles) then
|
||||
replaceAllButton = wx.wxButton(findDialog, ID_REPLACE_ALL, "Replace &All")
|
||||
replaceAllButton = wx.wxButton(findDialog, ID_REPLACE_ALL, TR("Replace &All"))
|
||||
end
|
||||
local cancelButton = wx.wxButton(findDialog, wx.wxID_CANCEL, "Cancel")
|
||||
local cancelButton = wx.wxButton(findDialog, wx.wxID_CANCEL, TR("Cancel"))
|
||||
|
||||
local buttonsSizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
buttonsSizer:Add(findButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
|
||||
@@ -293,32 +375,39 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
buttonsSizer:Add(cancelButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
|
||||
|
||||
-- Create find/replace text entry sizer
|
||||
local findStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Find: ")
|
||||
local findStatText = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("Find")..": ")
|
||||
local findTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.findText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.findTextArray, wx.wxCB_DROPDOWN)
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.findTextArray,
|
||||
wx.wxCB_DROPDOWN + (mac and wx.wxTE_PROCESS_ENTER or 0))
|
||||
findTextCombo:SetFocus()
|
||||
|
||||
local infilesMaskStat,infilesMaskCombo
|
||||
local infilesDirStat,infilesDirCombo,infilesDirButton
|
||||
if (infiles) then
|
||||
infilesMaskStat = wx.wxStaticText( findDialog, wx.wxID_ANY, "File Type: ")
|
||||
infilesMaskCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filemaskText,
|
||||
infilesMaskStat = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("File Type")..": ")
|
||||
infilesMaskCombo = wx.wxComboBox(findDialog, wx.wxID_ANY,
|
||||
findReplace.filemaskText or getExts() or "*.*",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filemaskTextArray)
|
||||
|
||||
local fname = GetEditorFileAndCurInfo(true)
|
||||
if (fname) then
|
||||
findReplace.filedirText = fname:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
if #(findReplace.filedirText) == 0 then
|
||||
findReplace.filedirText = ide.config.path.projectdir
|
||||
or fname and fname:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
or ""
|
||||
end
|
||||
|
||||
infilesDirStat = wx.wxStaticText( findDialog, wx.wxID_ANY, "Directory: ")
|
||||
infilesDirCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filedirText, wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filedirTextArray)
|
||||
infilesDirButton = wx.wxButton(findDialog, ID_SETDIR, "...",wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
infilesDirStat = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("Directory")..": ")
|
||||
infilesDirCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filedirText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filedirTextArray)
|
||||
infilesDirButton = wx.wxButton(findDialog, ID_SETDIR, "...", wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
end
|
||||
|
||||
local replaceStatText, replaceTextCombo
|
||||
if (replace) then
|
||||
replaceStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Replace: ")
|
||||
replaceTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.replaceText, wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.replaceTextArray)
|
||||
replaceStatText = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("Replace")..": ")
|
||||
replaceTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.replaceText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.replaceTextArray,
|
||||
wx.wxCB_DROPDOWN + (mac and wx.wxTE_PROCESS_ENTER or 0))
|
||||
end
|
||||
|
||||
local findReplaceSizer = wx.wxFlexGridSizer(2, 3, 0, 0)
|
||||
@@ -345,13 +434,13 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
-- the StaticBox(Sizer) needs to be created before checkboxes, otherwise
|
||||
-- checkboxes don't get any clicks on OSX (ide.osname == 'Macintosh')
|
||||
-- as the z-order for event traversal appears to be incorrect.
|
||||
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "Options" )
|
||||
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, TR("Options"))
|
||||
|
||||
-- Create find/replace option checkboxes
|
||||
local wholeWordCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match &whole word")
|
||||
local matchCaseCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match &case")
|
||||
local wrapAroundCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Wrap ar&ound")
|
||||
local regexCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Regular &expression")
|
||||
local wholeWordCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Match &whole word"))
|
||||
local matchCaseCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Match &case"))
|
||||
local wrapAroundCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Wrap ar&ound"))
|
||||
local regexCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Regular &expression"))
|
||||
wholeWordCheckBox:SetValue(findReplace.fWholeWord)
|
||||
matchCaseCheckBox:SetValue(findReplace.fMatchCase)
|
||||
wrapAroundCheckBox:SetValue(findReplace.fWrap)
|
||||
@@ -373,10 +462,10 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
local scopeSizer
|
||||
if (infiles) then
|
||||
-- the StaticBox(Sizer) needs to be created before checkboxes
|
||||
scopeSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "In Files")
|
||||
scopeSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, TR("In Files"))
|
||||
|
||||
subDirCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "&Subdirectories")
|
||||
makeBakCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, ".&bak on Replace")
|
||||
subDirCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("&Subdirectories"))
|
||||
makeBakCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR(".&bak on Replace"))
|
||||
subDirCheckBox:SetValue(findReplace.fSubDirs)
|
||||
makeBakCheckBox:SetValue(findReplace.fMakeBak)
|
||||
|
||||
@@ -386,7 +475,8 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
|
||||
scopeSizer:Add(optionSizer, 0, 0, 5)
|
||||
else
|
||||
scopeRadioBox = wx.wxRadioBox(findDialog, wx.wxID_ANY, "Scope", wx.wxDefaultPosition, wx.wxDefaultSize, {"&Up", "&Down"}, 1, wx.wxRA_SPECIFY_COLS)
|
||||
scopeRadioBox = wx.wxRadioBox(findDialog, wx.wxID_ANY, TR("Scope"), wx.wxDefaultPosition,
|
||||
wx.wxDefaultSize, {TR("&Up"), TR("&Down")}, 1, wx.wxRA_SPECIFY_COLS)
|
||||
scopeRadioBox:SetSelection(iff(findReplace.fDown, 1, 0))
|
||||
|
||||
scopeSizer = wx.wxBoxSizer(wx.wxVERTICAL, findDialog)
|
||||
@@ -406,7 +496,7 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
mainSizer:Add(leftSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 10)
|
||||
mainSizer:Add(buttonsSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 10)
|
||||
|
||||
mainSizer:SetSizeHints( findDialog )
|
||||
mainSizer:SetSizeHints(findDialog)
|
||||
findDialog:SetSizer(mainSizer)
|
||||
|
||||
local function TransferDataFromWindow()
|
||||
@@ -437,12 +527,26 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
return true
|
||||
end
|
||||
|
||||
-- this is a workaround for Enter issue in wxComboBox on OSX:
|
||||
-- https://groups.google.com/d/msg/wx-users/EVJr8GqyNUA/CUALp585E78J
|
||||
if (mac and ide.wxver >= "2.9.5") then
|
||||
local function simulateEnter()
|
||||
findDialog:AddPendingEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_BUTTON_CLICKED, ID_FIND_NEXT))
|
||||
end
|
||||
findTextCombo:Connect(wx.wxEVT_COMMAND_TEXT_ENTER, simulateEnter)
|
||||
if replace then
|
||||
replaceTextCombo:Connect(wx.wxEVT_COMMAND_TEXT_ENTER, simulateEnter)
|
||||
end
|
||||
end
|
||||
|
||||
findDialog:Connect(ID_FIND_NEXT, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function()
|
||||
TransferDataFromWindow()
|
||||
if (findReplace.infiles) then
|
||||
findReplace:RunInFiles()
|
||||
findReplace.dialog:Destroy()
|
||||
findReplace.dialog = nil
|
||||
else
|
||||
findReplace:FindString()
|
||||
end
|
||||
@@ -456,13 +560,12 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
if (findReplace.infiles) then
|
||||
findReplace:RunInFiles(true)
|
||||
findReplace.dialog:Destroy()
|
||||
findReplace.dialog = nil
|
||||
else
|
||||
findReplace:ReplaceString()
|
||||
end
|
||||
else
|
||||
findReplace.dialog:Destroy()
|
||||
findReplace.dialog = createFindReplaceDialog(true,infiles)
|
||||
findReplace.dialog:Show(true)
|
||||
findReplace:createDialog(true,infiles)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -478,30 +581,34 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
if infilesDirButton then
|
||||
findDialog:Connect(ID_SETDIR, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function()
|
||||
local filePicker = wx.wxDirDialog(findDialog, "Choose a project directory",
|
||||
local filePicker = wx.wxDirDialog(findDialog, TR("Choose a project directory"),
|
||||
findReplace.filedirText~="" and findReplace.filedirText or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
|
||||
|
||||
local res = filePicker:ShowModal(true)
|
||||
if res == wx.wxID_OK then
|
||||
infilesDirCombo:SetValue(filePicker:GetPath())
|
||||
infilesDirCombo:SetValue(FixDir(filePicker:GetPath()))
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
findDialog:Connect(wx.wxID_ANY, wx.wxEVT_CLOSE_WINDOW,
|
||||
function (event)
|
||||
TransferDataFromWindow()
|
||||
event:Skip()
|
||||
findDialog:Show(false)
|
||||
findDialog:Destroy()
|
||||
end)
|
||||
-- if on OSX then select the current value of the default dropdown
|
||||
-- and don't set the default as it doesn't make Enter to work, but
|
||||
-- prevents associated hotkey (Cmd-F) from working (wx2.9.5).
|
||||
if ide.osname == 'Macintosh' then
|
||||
findTextCombo:SetSelection(0, #findTextCombo:GetValue())
|
||||
else
|
||||
findButton:SetDefault()
|
||||
end
|
||||
|
||||
-- reset search when re-creating dialog to avoid modifying selected
|
||||
-- fragment after successful search and updated replacement
|
||||
findReplace.foundString = false
|
||||
findReplace.dialog = findDialog
|
||||
findDialog:Show(true)
|
||||
return findDialog
|
||||
end
|
||||
|
||||
function findReplace:Show(replace,infiles)
|
||||
self.dialog = nil
|
||||
self.dialog = createFindReplaceDialog(replace,infiles)
|
||||
self.dialog:Show(true)
|
||||
self:GetSelectedString()
|
||||
self:createDialog(replace,infiles)
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ local ide = ide
|
||||
|
||||
-- Pick some reasonable fixed width fonts to use for the editor
|
||||
local function setFont(style, config)
|
||||
return wx.wxFont(config.fontsize or size or 10, wx.wxFONTFAMILY_MODERN, style,
|
||||
return wx.wxFont(config.fontsize or 10, wx.wxFONTFAMILY_MODERN, style,
|
||||
wx.wxFONTWEIGHT_NORMAL, false, config.fontname or "",
|
||||
config.fontencoding or wx.wxFONTENCODING_DEFAULT)
|
||||
end
|
||||
@@ -16,16 +16,24 @@ ide.font.oNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.outputshell)
|
||||
ide.font.oItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.outputshell)
|
||||
|
||||
-- treeCtrl font requires slightly different handling
|
||||
local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.filetree
|
||||
if config.fontsize then gui:SetPointSize(config.fontsize) end
|
||||
if config.fontname then gui:SetFaceName(config.fontname) end
|
||||
ide.font.fNormal = gui
|
||||
do local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.filetree
|
||||
if config.fontsize then gui:SetPointSize(config.fontsize) end
|
||||
if config.fontname then gui:SetFaceName(config.fontname) end
|
||||
ide.font.fNormal = gui
|
||||
end
|
||||
|
||||
-- funcList font requires similar handling
|
||||
do local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.funclist
|
||||
if config.fontsize then gui:SetPointSize(config.fontsize) end
|
||||
if config.fontname then gui:SetFaceName(config.fontname) end
|
||||
ide.font.dNormal = gui
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Create the wxFrame
|
||||
-- ----------------------------------------------------------------------------
|
||||
local function createFrame()
|
||||
frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, GetIDEString("editor"),
|
||||
local frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, GetIDEString("editor"),
|
||||
wx.wxDefaultPosition, wx.wxSize(1000, 700))
|
||||
-- wrap into protected call as DragAcceptFiles fails on MacOS with
|
||||
-- wxwidgets 2.8.12 even though it should work according to change notes
|
||||
@@ -113,11 +121,23 @@ local function createNotebook(frame)
|
||||
-- wxEVT_SET_FOCUS could be used, but it only works on Windows with wx2.9.5+
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED,
|
||||
function (event)
|
||||
-- if there is no document yet, the editor tab was just added,
|
||||
-- so no changes needed as there will be a proper later call
|
||||
local ed = GetEditor(notebook:GetSelection())
|
||||
local doc = ed and ed:GetId() and ide.openDocuments[ed:GetId()]
|
||||
if doc then SetEditorSelection(notebook:GetSelection()) end
|
||||
|
||||
-- skip activation when any of the following is true:
|
||||
-- (1) there is no document yet, the editor tab was just added,
|
||||
-- so no changes needed as there will be a proper later call;
|
||||
-- (2) the page change event was triggered after a tab is closed;
|
||||
-- (3) on OSX from AddPage event when changing from the last tab
|
||||
-- (this is to work around a duplicate event generated in this case
|
||||
-- that first activates the added tab and then some other tab (2.9.5)).
|
||||
|
||||
local double = (ide.osname == 'Macintosh'
|
||||
and event:GetOldSelection() == notebook:GetPageCount()
|
||||
and debug:traceback():find("'AddPage'"))
|
||||
|
||||
if doc and event:GetOldSelection() ~= -1 and not double then
|
||||
SetEditorSelection(notebook:GetSelection()) end
|
||||
end)
|
||||
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE,
|
||||
@@ -144,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"))
|
||||
@@ -152,15 +180,25 @@ local function createNotebook(frame)
|
||||
menu:AppendSeparator()
|
||||
menu:Append(ID_SAVE, TR("&Save"))
|
||||
menu:Append(ID_SAVEAS, TR("Save &As..."))
|
||||
menu:AppendSeparator()
|
||||
menu:Append(ID_SHOWLOCATION, TR("Show Location"))
|
||||
|
||||
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 ()
|
||||
local editor = GetEditor(selection)
|
||||
SaveFile(editor, openDocuments[editor:GetId()].filePath)
|
||||
SaveFile(editor, ide.openDocuments[editor:GetId()].filePath)
|
||||
end)
|
||||
notebook:Connect(ID_SAVE, wx.wxEVT_UPDATE_UI, IfModified)
|
||||
notebook:Connect(ID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED, function()
|
||||
@@ -181,6 +219,10 @@ local function createNotebook(frame)
|
||||
notebook:Connect(ID_CLOSEOTHER, wx.wxEVT_UPDATE_UI, function (event)
|
||||
event:Enable(notebook:GetPageCount() > 1)
|
||||
end)
|
||||
notebook:Connect(ID_SHOWLOCATION, wx.wxEVT_COMMAND_MENU_SELECTED, function()
|
||||
ShowLocation(ide:GetDocument(GetEditor(selection)):GetFilePath())
|
||||
end)
|
||||
notebook:Connect(ID_SHOWLOCATION, wx.wxEVT_UPDATE_UI, IfAtLeastOneTab)
|
||||
|
||||
frame.notebook = notebook
|
||||
return notebook
|
||||
@@ -193,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)
|
||||
|
||||
@@ -239,7 +376,7 @@ do
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true))
|
||||
mgr:AddPane(frame.bottomnotebook, wxaui.wxAuiPaneInfo():
|
||||
Name("bottomnotebook"):
|
||||
MinSize(200,200):FloatingSize(400,250):
|
||||
MinSize(100,100):BestSize(200,200):FloatingSize(400,200):
|
||||
Bottom():Layer(1):Position(1):
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true))
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
-- Generate a unique new wxWindowID
|
||||
local ID_IDCOUNTER = wx.wxID_HIGHEST + 1
|
||||
function NewID()
|
||||
ID_IDCOUNTER = ID_IDCOUNTER + 1
|
||||
return ID_IDCOUNTER
|
||||
ID_IDCOUNTER = ID_IDCOUNTER + 1
|
||||
return ID_IDCOUNTER
|
||||
end
|
||||
|
||||
-- File menu
|
||||
@@ -15,10 +15,13 @@ ID_OPEN = wx.wxID_OPEN
|
||||
ID_CLOSE = NewID()
|
||||
ID_CLOSEALL = NewID()
|
||||
ID_CLOSEOTHER = NewID()
|
||||
ID_SHOWLOCATION = NewID()
|
||||
ID_SAVE = wx.wxID_SAVE
|
||||
ID_SAVEAS = wx.wxID_SAVEAS
|
||||
ID_SAVEALL = NewID()
|
||||
ID_RECENTFILES = NewID()
|
||||
ID_RECENTFILESPREV = NewID()
|
||||
ID_RECENTFILESNEXT = NewID()
|
||||
ID_EXIT = wx.wxID_EXIT
|
||||
-- Edit menu
|
||||
ID_CUT = wx.wxID_CUT
|
||||
@@ -33,6 +36,11 @@ ID_AUTOCOMPLETEENABLE = NewID()
|
||||
ID_COMMENT = NewID()
|
||||
ID_FOLD = NewID()
|
||||
ID_CLEARDYNAMICWORDS = NewID()
|
||||
-- don't use wx.wxID_PREFERENCES to avoid merging with OSX app menu, because
|
||||
-- Apple guidelines describe Preferences as a "normal" item without submenus.
|
||||
ID_PREFERENCES = NewID()
|
||||
ID_PREFERENCESSYSTEM = NewID()
|
||||
ID_PREFERENCESUSER = NewID()
|
||||
-- Search menu
|
||||
ID_FIND = wx.wxID_FIND
|
||||
ID_FINDNEXT = NewID()
|
||||
@@ -70,11 +78,19 @@ 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()
|
||||
ID_DELETEWATCH = NewID()
|
||||
-- Editor popup menu items
|
||||
ID_GOTODEFINITION = NewID()
|
||||
ID_RENAMEALLINSTANCES = NewID()
|
||||
ID_QUICKADDWATCH = NewID()
|
||||
ID_QUICKEVAL = NewID()
|
||||
ID_ADDTOSCRATCHPAD = NewID()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -32,6 +32,8 @@ ide.config.keymap = {
|
||||
[ID_SAVEAS] = "Alt-Shift-S",
|
||||
[ID_SAVEALL] = "",
|
||||
[ID_RECENTFILES] = "",
|
||||
[ID_RECENTFILESPREV] = "Ctrl-<",
|
||||
[ID_RECENTFILESNEXT] = "Ctrl->",
|
||||
[ID_EXIT] = "Ctrl-Q",
|
||||
-- Edit menu
|
||||
[ID_CUT] = "Ctrl-X",
|
||||
|
||||
@@ -41,7 +41,7 @@ end
|
||||
local function q(s) return s:gsub('(.)','%%%1') end
|
||||
|
||||
local MD_MARK_PTRN = '' -- combination of all markup marks that can start styling
|
||||
for key,value in pairs(markup) do
|
||||
for key in pairs(markup) do
|
||||
if key ~= MD_MARK_MARK then MD_MARK_PTRN = MD_MARK_PTRN .. q(key) end
|
||||
end
|
||||
MarkupAddStyles(ide.config.styles)
|
||||
@@ -61,11 +61,15 @@ function MarkupHotspotClick(pos, editor)
|
||||
if text then
|
||||
text = text:gsub("^"..q(MD_MARK_LINA), ""):gsub(q(MD_MARK_LINT).."$", "")
|
||||
local filepath = ide.openDocuments[editor:GetId()].filePath
|
||||
local _,_,shell = string.find(text, [[^macro:shell%((.*%S)%)$]])
|
||||
or FileTreeGetDir()
|
||||
local _,_,http = string.find(text, [[^(https?:%S+)$]])
|
||||
local _,_,command = string.find(text, [[^macro:(%w+)$]])
|
||||
if shell then
|
||||
ShellExecuteCode(shell)
|
||||
local _,_,command,code = string.find(text, [[^macro:(%w+)%((.*%S)%)$]])
|
||||
if not command then _,_,command = string.find(text, [[^macro:(%w+)$]]) end
|
||||
|
||||
if command == 'shell' then
|
||||
ShellExecuteCode(code)
|
||||
elseif command == 'inline' then
|
||||
ShellExecuteInline(code)
|
||||
elseif command == 'run' then -- run the current file
|
||||
ProjectRun()
|
||||
elseif command == 'debug' then -- debug the current file
|
||||
@@ -76,12 +80,9 @@ function MarkupHotspotClick(pos, editor)
|
||||
-- check if requested to open in a new window
|
||||
local newwindow = string.find(text, MD_LINK_NEWWINDOW, 1, true) -- plain search
|
||||
if newwindow then text = string.gsub(text, "^%" .. MD_LINK_NEWWINDOW, "") end
|
||||
local name = wx.wxFileName(filepath):GetPath(wx.wxPATH_GET_VOLUME
|
||||
+ wx.wxPATH_GET_SEPARATOR) .. text
|
||||
-- load/activate file
|
||||
local filename = wx.wxFileName(name)
|
||||
filename:Normalize() -- remove .., ., and other similar elements
|
||||
if filename:FileExists() and
|
||||
local filename = GetFullPathIfExists(
|
||||
wx.wxFileName(filepath):GetPath(wx.wxPATH_GET_VOLUME), text)
|
||||
if filename and
|
||||
(newwindow or SaveModifiedDialog(editor, true) ~= wx.wxID_CANCEL) then
|
||||
if not newwindow and ide.osname == 'Macintosh' then editor:GotoPos(0) end
|
||||
LoadFile(filename,not newwindow and editor or nil,true)
|
||||
@@ -132,17 +133,23 @@ 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
|
||||
local linee = linee or editor:GetLineCount()
|
||||
local linec = editor:GetLineCount()
|
||||
local linee = linee or linec
|
||||
|
||||
local linecomment = editor.spec.linecomment
|
||||
local iscomment = {}
|
||||
for i,v in pairs(editor.spec.iscomment) do
|
||||
iscomment[i] = v
|
||||
end
|
||||
|
||||
local es = editor:GetEndStyled()
|
||||
local needfix = false
|
||||
|
||||
for line=lines,linee do
|
||||
local tx = editor:GetLine(line)
|
||||
@@ -151,6 +158,10 @@ function MarkupStyle(editor, lines, linee)
|
||||
local from = 1
|
||||
local off = -1
|
||||
|
||||
-- doing WrapCount(line) when line == linec (which may be beyond
|
||||
-- the last line) occasionally crashes the application on OSX.
|
||||
local wrapped = line < linec and editor:WrapCount(line) or 0
|
||||
|
||||
while from do
|
||||
tx = string.sub(tx,from)
|
||||
local f,t,w,mark = ismarkup(tx)
|
||||
@@ -160,7 +171,8 @@ function MarkupStyle(editor, lines, linee)
|
||||
local s = bit.band(editor:GetStyleAt(p), 31)
|
||||
-- only style comments and only those that are not at the beginning
|
||||
-- of the file to avoid styling shebang (#!) lines
|
||||
if iscomment[s] and p > 0 then
|
||||
-- also ignore matches for line comments (as defined in the spec)
|
||||
if iscomment[s] and p > 0 and mark ~= linecomment then
|
||||
local smark = #mark
|
||||
local emark = #mark -- assumes end mark is the same length as start mark
|
||||
if mark == MD_MARK_HEAD then
|
||||
@@ -181,6 +193,19 @@ function MarkupStyle(editor, lines, linee)
|
||||
end
|
||||
from = t and (t+1)
|
||||
end
|
||||
|
||||
-- has this line changed its wrapping because of invisible styling?
|
||||
if wrapped > 1 and editor:WrapCount(line) < wrapped then needfix = true end
|
||||
end
|
||||
editor:StartStyling(es, 31)
|
||||
|
||||
-- if any wrapped lines have changed, then reset WrapMode to fix the drawing
|
||||
if needfix then
|
||||
-- this fixes an issue with duplicate lines in Scintilla when
|
||||
-- invisible styles hide some of the content that would be wrapped.
|
||||
local wrapmode = editor:GetWrapMode()
|
||||
if wrapmode ~= wxstc.wxSTC_WRAP_NONE then editor:SetWrapMode(wrapmode) end
|
||||
-- if some of the lines have folded, this can make not styled lines visible
|
||||
MarkupStyle(editor, linee+1) -- style to the end in this case
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,7 +25,15 @@ 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") },
|
||||
{ },
|
||||
}
|
||||
|
||||
local preferencesMenu = wx.wxMenu{
|
||||
{ID_PREFERENCESSYSTEM, TR("Settings: System")..KSC(ID_PREFERENCESSYSTEM)},
|
||||
{ID_PREFERENCESUSER, TR("Settings: User")..KSC(ID_PREFERENCESUSER)},
|
||||
}
|
||||
editMenu:Append(ID_PREFERENCES, TR("Preferences"), preferencesMenu)
|
||||
menuBar:Append(editMenu, TR("&Edit"))
|
||||
|
||||
editMenu:Check(ID_AUTOCOMPLETEENABLE, ide.config.autocomplete)
|
||||
@@ -46,13 +54,12 @@ function OnUpdateUIEditMenu(event)
|
||||
local editor = getControlWithFocus()
|
||||
if editor == nil then event:Enable(false); return end
|
||||
|
||||
local alwaysOn = { [ID_SELECTALL] = true, [ID_FOLD] = true,
|
||||
[ID_COMMENT] = true, [ID_AUTOCOMPLETE] = 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_SORT] = true}
|
||||
local menu_id = event:GetId()
|
||||
local enable =
|
||||
((menu_id == ID_COPY or menu_id == ID_CUT) and
|
||||
(editor:GetClassInfo():GetClassName() ~= 'wxStyledTextCtrl'
|
||||
or editor:GetSelectionStart() ~= editor:GetSelectionEnd())) or
|
||||
menu_id == ID_PASTE and editor:CanPaste() or
|
||||
menu_id == ID_UNDO and editor:CanUndo() or
|
||||
menu_id == ID_REDO and editor:CanRedo() or
|
||||
@@ -74,8 +81,12 @@ function OnEditMenu(event)
|
||||
then event:Skip(); return end
|
||||
|
||||
local menu_id = event:GetId()
|
||||
if menu_id == ID_CUT then editor:Cut()
|
||||
elseif menu_id == ID_COPY then editor:Copy()
|
||||
if menu_id == ID_CUT then
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd()
|
||||
then editor:LineCut() else editor:Cut() end
|
||||
elseif menu_id == ID_COPY then
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd()
|
||||
then editor:LineCopy() else editor:Copy() end
|
||||
elseif menu_id == ID_PASTE then editor:Paste()
|
||||
elseif menu_id == ID_SELECTALL then editor:SelectAll()
|
||||
elseif menu_id == ID_UNDO then editor:Undo()
|
||||
@@ -88,6 +99,32 @@ for _, event in pairs({ID_CUT, ID_COPY, ID_PASTE, ID_SELECTALL, ID_UNDO, ID_REDO
|
||||
frame:Connect(event, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
end
|
||||
|
||||
local function generateConfigMessage(type)
|
||||
return ([==[--[[--
|
||||
Use this file to specify %s preferences.
|
||||
Review [examples](+%s) or check [online documentation](%s) for details.
|
||||
--]]--
|
||||
]==])
|
||||
:format(type, MergeFullPath(ide.editorFilename, "../cfg/user-sample.lua"),
|
||||
"http://studio.zerobrane.com/documentation.html")
|
||||
end
|
||||
|
||||
frame:Connect(ID_PREFERENCESSYSTEM, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local editor = LoadFile(ide.configs.system)
|
||||
if editor and #editor:GetText() == 0 then
|
||||
editor:AddText(generateConfigMessage("System")) end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_PREFERENCESUSER, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local editor = LoadFile(ide.configs.user)
|
||||
if editor and #editor:GetText() == 0 then
|
||||
editor:AddText(generateConfigMessage("User")) end
|
||||
end)
|
||||
frame:Connect(ID_PREFERENCESUSER, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(ide.configs.user ~= nil) end)
|
||||
|
||||
frame:Connect(ID_CLEARDYNAMICWORDS, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () DynamicWordsReset() end)
|
||||
|
||||
@@ -119,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,2) == lc then
|
||||
line = string.sub(line,3)
|
||||
else
|
||||
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()
|
||||
|
||||
@@ -25,29 +25,136 @@ local filehistorymenu = wx.wxMenu({})
|
||||
local filehistory = wx.wxMenuItem(fileMenu, ID_RECENTFILES,
|
||||
TR("Recent Files")..KSC(ID_RECENTFILES), TR("File history"), wx.wxITEM_NORMAL, filehistorymenu)
|
||||
fileMenu:Insert(8,filehistory)
|
||||
function UpdateFileHistoryUI(list)
|
||||
-- remove all at first
|
||||
for i=1,filehistorymenu:GetMenuItemCount() do
|
||||
filehistorymenu:Delete( ID("file.recentfiles."..i))
|
||||
end
|
||||
for i=1,#list do
|
||||
local file = list[i].filename
|
||||
local item = wx.wxMenuItem(filehistorymenu, ID("file.recentfiles."..i),file,"")
|
||||
filehistorymenu:Append(item)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,ide.config.filehistorylength do
|
||||
frame:Connect(ID("file.recentfiles."..i), wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local item = filehistorymenu:FindItemByPosition(i-1)
|
||||
local filename = item:GetLabel()
|
||||
LoadFile(filename)
|
||||
do -- recent file history
|
||||
local iscaseinsensitive = wx.wxFileName("A"):SameAs(wx.wxFileName("a"))
|
||||
local function isSameAs(f1, f2)
|
||||
return f1 == f2 or iscaseinsensitive and f1:lower() == f2:lower()
|
||||
end
|
||||
|
||||
local filehistory = {[0] = 1}
|
||||
|
||||
-- add file to the file history removing duplicates
|
||||
local function addFileHistory(filename)
|
||||
-- a new (empty) tab is opened; don't change the history
|
||||
if not filename then return end
|
||||
|
||||
local fn = wx.wxFileName(filename)
|
||||
if fn:Normalize() then filename = fn:GetFullPath() end
|
||||
|
||||
local index = filehistory[0]
|
||||
|
||||
-- special case: selecting the current file (or moving through the history)
|
||||
if filehistory[index] and isSameAs(filename, filehistory[index].filename) then return end
|
||||
|
||||
-- something else is selected
|
||||
-- (1) flip the history from 1 to the current index
|
||||
for i = 1, math.floor(index/2) do
|
||||
filehistory[i], filehistory[index-i+1] = filehistory[index-i+1], filehistory[i]
|
||||
end
|
||||
)
|
||||
|
||||
-- (2) if the file is in the history, remove it
|
||||
for i = #filehistory, 1, -1 do
|
||||
if isSameAs(filename, filehistory[i].filename) then
|
||||
table.remove(filehistory, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- (3) add the file to the top and update the index
|
||||
table.insert(filehistory, 1, {filename=filename})
|
||||
filehistory[0] = 1
|
||||
|
||||
-- (4) remove all entries that are no longer needed
|
||||
while #filehistory>ide.config.filehistorylength do table.remove(filehistory) end
|
||||
end
|
||||
|
||||
local function remFileHistory(filename)
|
||||
if not filename then return end
|
||||
|
||||
local fn = wx.wxFileName(filename)
|
||||
if fn:Normalize() then filename = fn:GetFullPath() end
|
||||
|
||||
local index = filehistory[0]
|
||||
|
||||
-- special case: removing the current file
|
||||
if filehistory[index] and isSameAs(filename, filehistory[index].filename) then
|
||||
-- (1) flip the history from 1 to the current index
|
||||
for i = 1, math.floor(index/2) do
|
||||
filehistory[i], filehistory[index-i+1] = filehistory[index-i+1], filehistory[i]
|
||||
end
|
||||
end
|
||||
|
||||
-- (2) if the file is in the history, remove it
|
||||
for i = #filehistory, 1, -1 do
|
||||
if isSameAs(filename, filehistory[i].filename) then
|
||||
table.remove(filehistory, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- (3) update index
|
||||
filehistory[0] = 1
|
||||
end
|
||||
|
||||
local updateRecentFiles -- need forward declaration because of recursive refs
|
||||
|
||||
local function loadRecent(event)
|
||||
local id = event:GetId()
|
||||
local item = filehistorymenu:FindItem(id)
|
||||
local filename = item:GetLabel()
|
||||
local index = filehistory[0]
|
||||
filehistory[0] = (
|
||||
(index > 1 and id == ID("file.recentfiles."..(index-1)) and index-1) or
|
||||
(index < #filehistory) and id == ID("file.recentfiles."..(index+1)) and index+1 or
|
||||
1)
|
||||
if not LoadFile(filename, nil, true) then
|
||||
wx.wxMessageBox(
|
||||
TR("File '%s' no longer exists."):format(filename),
|
||||
GetIDEString("editormessage"),
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
remFileHistory(filename)
|
||||
updateRecentFiles(filehistory)
|
||||
end
|
||||
end
|
||||
|
||||
updateRecentFiles = function (list)
|
||||
local items = filehistorymenu:GetMenuItemCount()
|
||||
for i=1, #list do
|
||||
local file = list[i].filename
|
||||
local id = ID("file.recentfiles."..i)
|
||||
local label = file..(
|
||||
i == list[0]-1 and KSC(ID_RECENTFILESNEXT) or
|
||||
i == list[0]+1 and KSC(ID_RECENTFILESPREV) or
|
||||
"")
|
||||
if i <= items then -- this is an existing item; update the label
|
||||
filehistorymenu:FindItem(id):SetItemLabel(label)
|
||||
else -- need to add an item
|
||||
local item = wx.wxMenuItem(filehistorymenu, id, label, "")
|
||||
filehistorymenu:Append(item)
|
||||
frame:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED, loadRecent)
|
||||
end
|
||||
end
|
||||
for i=items, #list+1, -1 do -- delete the rest if the list got shorter
|
||||
filehistorymenu:Delete(filehistorymenu:FindItemByPosition(i-1))
|
||||
end
|
||||
|
||||
-- enable if there are any recent files
|
||||
fileMenu:Enable(ID_RECENTFILES, #list > 0)
|
||||
end
|
||||
|
||||
-- public methods
|
||||
function GetFileHistory() return filehistory end
|
||||
function SetFileHistory(fh)
|
||||
filehistory = fh
|
||||
filehistory[0] = 1
|
||||
updateRecentFiles(filehistory)
|
||||
end
|
||||
function AddToFileHistory(filename)
|
||||
addFileHistory(filename)
|
||||
updateRecentFiles(filehistory)
|
||||
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 ()
|
||||
|
||||
@@ -8,23 +8,42 @@ 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 ZeroBrane Studio") },
|
||||
{ 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"))
|
||||
|
||||
local function DisplayAbout(event)
|
||||
local page = [[
|
||||
local logo = ide.config.path.app.."/"..GetIDEString("logo")
|
||||
local logoimg = wx.wxFileName(logo):FileExists() and
|
||||
([[<tr><td><img src="%s"></td></tr>]]):format(logo) or ""
|
||||
local page = ([[
|
||||
<html>
|
||||
<body text="#777777">
|
||||
<table border="0" width="100%">
|
||||
<tr><td><img src="zbstudio/res/zerobrane.png"></td></tr>
|
||||
<table border="0" width="100%%">
|
||||
%s
|
||||
<tr><td>
|
||||
<table cellspacing="3" cellpadding="3" width="100%">
|
||||
<table cellspacing="3" cellpadding="3" width="100%%">
|
||||
<tr>
|
||||
<td>
|
||||
<b>ZeroBrane Studio (]]..ide.VERSION..[[; MobDebug ]]..mobdebug._VERSION..[[)</b><br>
|
||||
<b>ZeroBrane Studio (%s; MobDebug %s)</b><br>
|
||||
<b>Copyright © 2011-2013 ZeroBrane LLC</b><br>
|
||||
Paul Kulchenko<br>
|
||||
Licensed under the MIT License.
|
||||
@@ -41,7 +60,7 @@ local function DisplayAbout(event)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Based on wxLua editor (]]..wxlua.wxLUA_VERSION_STRING..[[)</b><br>
|
||||
<b>Based on wxLua editor (%s)</b><br>
|
||||
<b>Copyright © 2002-2005 Lomtick Software</b><br>
|
||||
J. Winwood, John Labenski<br>
|
||||
Licensed under wxWindows Library License, v3.
|
||||
@@ -49,37 +68,49 @@ local function DisplayAbout(event)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Built with ]]..wx.wxVERSION_STRING..[[</b>
|
||||
<b>Built with %s</b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>]]
|
||||
</html>]])
|
||||
:format(logoimg, ide.VERSION, mobdebug._VERSION,
|
||||
wxlua.wxLUA_VERSION_STRING, wx.wxVERSION_STRING)
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, TR("About %s"):format(GetIDEString("editor")))
|
||||
|
||||
-- this is needed because wxLuaHtmlWindow only seems to take into account
|
||||
-- the initial size, but not the one set with SetSize using
|
||||
-- wxlua 2.8.12.2 and wxwidgets 2.9.5+.
|
||||
local tmp = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxSize(450, 260))
|
||||
tmp:SetPage(page)
|
||||
local w = tmp:GetInternalRepresentation():GetWidth()
|
||||
local h = tmp:GetInternalRepresentation():GetHeight()
|
||||
tmp:Destroy()
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, TR("About ZeroBrane Studio"))
|
||||
local html = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(450, 520),
|
||||
wx.wxHW_SCROLLBAR_NEVER)
|
||||
wx.wxDefaultPosition, wx.wxSize(w, h), wx.wxHW_SCROLLBAR_NEVER)
|
||||
|
||||
html:SetBorders(0)
|
||||
html:SetPage(page)
|
||||
|
||||
local line = wx.wxStaticLine(dlg, wx.wxID_ANY)
|
||||
local button = wx.wxButton(dlg, wx.wxID_OK, "OK")
|
||||
button:SetDefault()
|
||||
|
||||
html:SetBorders(0)
|
||||
html:SetPage(page)
|
||||
html:SetSize(html:GetInternalRepresentation():GetWidth(),
|
||||
html:GetInternalRepresentation():GetHeight())
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(html, 1, wx.wxALL, 10)
|
||||
topsizer:Add(html, 1, wx.wxEXPAND + wx.wxALL, 10)
|
||||
topsizer:Add(line, 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(button, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
topsizer:Fit(dlg)
|
||||
|
||||
dlg:SetAutoLayout(true)
|
||||
dlg:SetSizer(topsizer)
|
||||
dlg:SetSizerAndFit(topsizer)
|
||||
dlg:ShowModal()
|
||||
dlg:Destroy()
|
||||
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
|
||||
|
||||
@@ -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,20 +45,81 @@ 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
|
||||
|
||||
function ProjectUpdateProjectDir(projdir,skiptree)
|
||||
local dir = wx.wxFileName.DirName(projdir)
|
||||
|
||||
-- wxwidgets 2.9.x may report the last folder twice (depending on how the
|
||||
-- user selects the folder), which makes the selected folder incorrect.
|
||||
-- check if the last segment is repeated and drop it.
|
||||
if not wx.wxDirExists(projdir) then
|
||||
local dirs = dir:GetDirs()
|
||||
if #dirs > 1 and dirs[-1] == dirs[-2] then dir:RemoveLastDir() end
|
||||
if not wx.wxDirExists(dir:GetFullPath()) then return end
|
||||
end
|
||||
local dir = wx.wxFileName.DirName(FixDir(projdir))
|
||||
if not wx.wxDirExists(dir:GetFullPath()) then return end
|
||||
|
||||
projdir = dir:GetPath(wx.wxPATH_GET_VOLUME) -- no trailing slash
|
||||
|
||||
@@ -126,46 +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)
|
||||
|
||||
ide.interpreter = interpreters[id]
|
||||
|
||||
if DebuggerShutdown then DebuggerShutdown() end
|
||||
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()
|
||||
@@ -183,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
|
||||
@@ -312,9 +313,9 @@ frame:Connect(ID_STARTDEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((ide.interpreter) and (ide.interpreter.hasdebugger) and
|
||||
((debugger.server == nil and debugger.pid == nil) or
|
||||
((debugger.server == nil and debugger.pid == nil and editor ~= nil) or
|
||||
(debugger.server ~= nil and not debugger.running)) and
|
||||
(editor ~= nil) and (not debugger.scratchpad or debugger.scratchpad.paused))
|
||||
(not debugger.scratchpad or debugger.scratchpad.paused))
|
||||
local label = (debugger.server ~= nil)
|
||||
and debugMenuRun.continue or debugMenuRun.start
|
||||
if debugMenu:GetLabel(ID_STARTDEBUG) ~= label then
|
||||
@@ -326,8 +327,7 @@ frame:Connect(ID_STOPDEBUG, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () DebuggerShutdown() end)
|
||||
frame:Connect(ID_STOPDEBUG, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil or debugger.pid ~= nil) and (editor ~= nil))
|
||||
event:Enable(debugger.server ~= nil or debugger.pid ~= nil)
|
||||
local label = (debugger.server == nil and debugger.pid ~= nil)
|
||||
and debugMenuStop.process or debugMenuStop.debugging
|
||||
if debugMenu:GetLabel(ID_STOPDEBUG) ~= label then
|
||||
@@ -391,8 +391,7 @@ frame:Connect(ID_BREAK, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
end)
|
||||
frame:Connect(ID_BREAK, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable((debugger.server ~= nil) and (editor ~= nil)
|
||||
event:Enable(debugger.server ~= nil
|
||||
and (debugger.running
|
||||
or (debugger.scratchpad and not debugger.scratchpad.paused)))
|
||||
end)
|
||||
@@ -401,5 +400,7 @@ frame:Connect(wx.wxEVT_IDLE,
|
||||
function(event)
|
||||
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)
|
||||
|
||||
@@ -19,46 +19,63 @@ 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
|
||||
|
||||
frame:Connect(ID_FIND, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false)
|
||||
end)
|
||||
frame:Connect(ID_FIND, wx.wxEVT_UPDATE_UI, OnUpdateUISearchMenu)
|
||||
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_UPDATE_UI, OnUpdateUISearchMenu)
|
||||
|
||||
frame:Connect(ID_FINDINFILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false,true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACEINFILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true,true)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event) findReplace:GetSelectedString() findReplace:FindString() end)
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if editor and ide.wxver >= "2.9.5" and editor:GetSelections() > 1 then
|
||||
local selection = editor:GetMainSelection() + 1
|
||||
if selection >= editor:GetSelections() then selection = 0 end
|
||||
editor:SetMainSelection(selection)
|
||||
editor:EnsureCaretVisible()
|
||||
else
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:FindString()
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(findReplace:GetSelectedString() and findReplace:HasText()) end)
|
||||
function (event) event:Enable(findReplace:GetSelectedString() or findReplace:HasText()) end)
|
||||
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event) findReplace:GetSelectedString() findReplace:FindString(true) end)
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
if editor and ide.wxver >= "2.9.5" and editor:GetSelections() > 1 then
|
||||
local selection = editor:GetMainSelection() - 1
|
||||
if selection < 0 then selection = editor:GetSelections() - 1 end
|
||||
editor:SetMainSelection(selection)
|
||||
editor:EnsureCaretVisible()
|
||||
else
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:FindString(true)
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(findReplace:GetSelectedString() and findReplace:HasText()) end)
|
||||
function (event) event:Enable(findReplace:GetSelectedString() or findReplace:HasText()) end)
|
||||
|
||||
-------------------- Find replace end
|
||||
|
||||
@@ -77,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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user