Compare commits
215 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f28d4da053 | ||
|
|
858742bf05 | ||
|
|
d559afd9e2 | ||
|
|
9acec71c7a | ||
|
|
8568f61ba4 | ||
|
|
6714f29302 | ||
|
|
f0b7cff06a | ||
|
|
25589fc45a | ||
|
|
6a7c8e78c0 | ||
|
|
443f936ac6 | ||
|
|
12525ad189 | ||
|
|
69fae9a36c | ||
|
|
725a38b182 | ||
|
|
13c4ca1a2f | ||
|
|
3e68447415 | ||
|
|
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 |
201
CHANGELOG.md
201
CHANGELOG.md
@@ -1,10 +1,201 @@
|
||||
# ZeroBrane Studio Changelog
|
||||
|
||||
## v0.37 (May 09 2013)
|
||||
## Current master (Aug 29 2013)
|
||||
|
||||
### Special thanks
|
||||
- To Samuel Dionne-Riel for wxwidgets 2.8 compatibility updates.
|
||||
- To Mat Hopwood for assistance with Marmalade Quick integration.
|
||||
- To Chow CheeWen for Chinese translation.
|
||||
- To [Riidom](https://github.com/Riidom) for German translation.
|
||||
- To [ardente](https://github.com/ardente) for user home patch for Windows.
|
||||
- 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.
|
||||
|
||||
### Improvements
|
||||
- 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.
|
||||
- Changed `un/comment` to act from the beginning of the line for multi-line selection.
|
||||
- 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).
|
||||
- Enabled support for xml/html folding.
|
||||
- Enabled path remapping for local debugging.
|
||||
- Enabled slower and more thorough static analysis (ref #149; ref #168).
|
||||
- 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 line count calculation for dynamic words when text is deleted.
|
||||
- Optimized dynamic word processing for large files.
|
||||
- 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 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 `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).
|
||||
- windows: adopt native user home (thanks to [ardente](https://github.com/ardente))
|
||||
|
||||
### Fixes
|
||||
- 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.
|
||||
@@ -13,6 +204,10 @@
|
||||
- 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).
|
||||
|
||||
21
README.md
21
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
|
||||
|
||||

|
||||
@@ -36,7 +42,7 @@ Overriding default configuration:
|
||||
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 +58,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
|
||||
|
||||
@@ -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
@@ -1,4 +1,4 @@
|
||||
-- Copyright 2011-12 Paul Kulchenko, ZeroBrane LLC
|
||||
-- Copyright 2013 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
return {
|
||||
ads = {
|
||||
@@ -324,6 +324,7 @@ return {
|
||||
description = "The radius of the circle.",
|
||||
},
|
||||
},
|
||||
inherits = "vector",
|
||||
},
|
||||
color = {
|
||||
type = "class",
|
||||
@@ -786,6 +787,7 @@ return {
|
||||
description = "The y coordinate (bottom) of the minimal bounding box around the rendered text.",
|
||||
},
|
||||
},
|
||||
inherits = "node",
|
||||
},
|
||||
lines = {
|
||||
type = "class",
|
||||
@@ -797,6 +799,7 @@ return {
|
||||
returns = "()",
|
||||
},
|
||||
},
|
||||
inherits = "vector",
|
||||
},
|
||||
location = {
|
||||
type = "class",
|
||||
@@ -1227,6 +1230,7 @@ return {
|
||||
returns = "()",
|
||||
},
|
||||
},
|
||||
inherits = "node",
|
||||
},
|
||||
contact = {
|
||||
type = "class",
|
||||
@@ -1648,6 +1652,7 @@ return {
|
||||
description = "The natural length of the joint, in display coordinates.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointfriction = {
|
||||
type = "class",
|
||||
@@ -1661,6 +1666,7 @@ return {
|
||||
description = "The maximum friction torque, in Newton-metres.\nJointWeld Properties\n========================\n* :c:member:`jointweld.frequency`\n* :c:member:`jointweld.dampingRatio`",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointgear = {
|
||||
type = "class",
|
||||
@@ -1678,6 +1684,7 @@ return {
|
||||
description = "The gear ratio.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointprismatic = {
|
||||
type = "class",
|
||||
@@ -1719,6 +1726,7 @@ return {
|
||||
description = "The upper distance limit for the joint (should be positive). Only effective if limitEnabled is true.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointpulley = {
|
||||
type = "class",
|
||||
@@ -1736,6 +1744,7 @@ return {
|
||||
description = "The pulley ratio, used to simulate a block-and-tackle.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointrevolute = {
|
||||
type = "class",
|
||||
@@ -1777,6 +1786,7 @@ return {
|
||||
description = "The upper angle for the joint limit (degrees). Only effective if limitEnabled is true.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointrope = {
|
||||
type = "class",
|
||||
@@ -1786,6 +1796,7 @@ return {
|
||||
description = "The maximum length of the rope.\nJointWheel Properties\n========================\n* :c:member:`jointwheel.motorEnabled`\n* :c:member:`jointwheel.motorSpeed`\n* :c:member:`jointwheel.maxMotorTorque`\n* :c:member:`jointwheel.springFrequency`\n* :c:member:`jointwheel.springDampingRatio`\n* :c:member:`jointwheel.motorTorque`\n* :c:member:`jointwheel.jointSpeed`\n* :c:member:`jointwheel.jointTranslation`",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointtouch = {
|
||||
type = "class",
|
||||
@@ -1809,6 +1820,7 @@ return {
|
||||
returns = "()",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointweld = {
|
||||
type = "class",
|
||||
@@ -1822,6 +1834,7 @@ return {
|
||||
description = "The mass-spring-damper frequency in Hertz. Rotation only. Disable softness with a value of 0.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
jointwheel = {
|
||||
type = "class",
|
||||
@@ -1859,6 +1872,7 @@ return {
|
||||
description = "Suspension frequency, zero indicates no suspension. Default value is 2.",
|
||||
},
|
||||
},
|
||||
inherits = "joint",
|
||||
},
|
||||
sprite = {
|
||||
type = "class",
|
||||
@@ -1918,6 +1932,7 @@ return {
|
||||
description = "True only if the sprite should be flipped along its local y axis.",
|
||||
},
|
||||
},
|
||||
inherits = "node",
|
||||
},
|
||||
system = {
|
||||
type = "class",
|
||||
@@ -2061,6 +2076,7 @@ return {
|
||||
description = "The size of each tile, in pixels.\nThe value is a Vec2 object: the x property represents the tile\nwidth, and the y property represents the tile height.",
|
||||
},
|
||||
},
|
||||
inherits = "node",
|
||||
},
|
||||
tiledmaplayer = {
|
||||
type = "class",
|
||||
@@ -2120,6 +2136,7 @@ return {
|
||||
returns = "()",
|
||||
},
|
||||
},
|
||||
inherits = "node",
|
||||
},
|
||||
tiledmapobject = {
|
||||
type = "class",
|
||||
@@ -2360,6 +2377,7 @@ return {
|
||||
description = "The width, in display coordinates, of the shape outline.\nIf 0, no outline is drawn. The default value is 1.",
|
||||
},
|
||||
},
|
||||
inherits = "node",
|
||||
},
|
||||
video = {
|
||||
type = "class",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -24,9 +24,13 @@ 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"
|
||||
|
||||
ZLIB_BASENAME="zlib-1.2.8"
|
||||
ZLIB_FILENAME="$ZLIB_BASENAME.tar.gz"
|
||||
ZLIB_URL="https://github.com/madler/zlib/archive/v1.2.8.tar.gz"
|
||||
|
||||
LUA_BASENAME="lua-5.1.5"
|
||||
LUA_FILENAME="$LUA_BASENAME.tar.gz"
|
||||
@@ -35,9 +39,9 @@ LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
WXLUA_BASENAME="wxlua"
|
||||
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/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-2.0.3"
|
||||
LUASOCKET_FILENAME="$LUASOCKET_BASENAME-rc2.zip"
|
||||
LUASOCKET_URL="https://github.com/downloads/diegonehab/luasocket/$LUASOCKET_FILENAME"
|
||||
|
||||
# exit if the command line is empty
|
||||
if [ $# -eq 0 ]; then
|
||||
@@ -103,20 +107,30 @@ mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR";
|
||||
# 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 ..
|
||||
@@ -157,8 +171,8 @@ 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 \
|
||||
|
||||
@@ -29,9 +29,9 @@ LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
WXLUA_BASENAME="wxlua"
|
||||
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/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-2.0.3"
|
||||
LUASOCKET_FILENAME="$LUASOCKET_BASENAME-rc2.zip"
|
||||
LUASOCKET_URL="https://github.com/downloads/diegonehab/luasocket/$LUASOCKET_FILENAME"
|
||||
|
||||
# exit if the command line is empty
|
||||
if [ $# -eq 0 ]; then
|
||||
@@ -151,8 +151,8 @@ 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 \
|
||||
|
||||
@@ -23,9 +23,17 @@ LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
WXLUA_BASENAME="wxlua"
|
||||
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/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-2.0.3"
|
||||
LUASOCKET_FILENAME="$LUASOCKET_BASENAME-rc2.zip"
|
||||
LUASOCKET_URL="https://github.com/downloads/diegonehab/luasocket/$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,6 +44,10 @@ if [ $# -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
WXLUASTRIP="/strip"
|
||||
WXLUABUILD="MinSizeRel"
|
||||
WXWIDGETSDEBUG="--disable-debug"
|
||||
|
||||
# iterate through the command line arguments
|
||||
for ARG in "$@"; do
|
||||
case $ARG in
|
||||
@@ -51,12 +63,19 @@ 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"
|
||||
;;
|
||||
all)
|
||||
BUILD_WXWIDGETS=true
|
||||
BUILD_LUA=true
|
||||
@@ -110,7 +129,7 @@ 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"
|
||||
@@ -140,18 +159,26 @@ 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
|
||||
|
||||
# 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
|
||||
|
||||
cp "$INSTALL_DIR/lib/libwxscintilla-2.9.a" "$INSTALL_DIR/lib/libwx_mswu_scintilla-2.9.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" -DBUILD_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,8 +186,8 @@ 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 \
|
||||
@@ -177,6 +204,33 @@ if [ $BUILD_LUASOCKET ]; then
|
||||
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"
|
||||
@@ -201,6 +255,7 @@ 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_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"
|
||||
|
||||
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
|
||||
}
|
||||
@@ -36,7 +36,7 @@ return {
|
||||
["&Watch Window"] = "Ventana de observaciones", -- src\editor\menu_view.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
|
||||
[".&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
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ return {
|
||||
["&Watch Window"] = "Finestra Espressioni di Controllo", -- src\editor\menu_view.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
|
||||
|
||||
@@ -41,7 +41,7 @@ return {
|
||||
[".&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
|
||||
["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
|
||||
@@ -93,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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--[[
|
||||
1. Pick a color scheme by clicking on a link:
|
||||
1. Pick a color scheme by clicking on its name:
|
||||
- [Tomorrow](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Tomorrow')))
|
||||
- [TomorrowContrast](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowContrast')))
|
||||
- [TomorrowNight](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNight')))
|
||||
@@ -8,8 +8,10 @@
|
||||
- [TomorrowNightEighties](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNightEighties')))
|
||||
- [Zenburn](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Zenburn')))
|
||||
- [Monokai](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Monokai')))
|
||||
- [Molokai](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Molokai')))
|
||||
- [SolarizedDark](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','SolarizedDark')))
|
||||
- [SolarizedLight](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','SolarizedLight')))
|
||||
- [Notepad++](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','NotepadPlusPlus')))
|
||||
|
||||
- [ZeroBrane Studio](macro:shell(ide.config.styles = StylesGetDefault(); ReApplySpecAndStyles()))
|
||||
|
||||
|
||||
@@ -135,6 +135,20 @@ local colors = {
|
||||
Blue = H'F92672',
|
||||
Purple = H'A6E22E',
|
||||
},
|
||||
Molokai = { -- based on https://github.com/tomasr/molokai/blob/master/colors/molokai.vim
|
||||
Background = H'1B1D1E',
|
||||
CurrentLine = H'293739',
|
||||
Selection = H'49483E',
|
||||
Foreground = H'F8F8F2',
|
||||
Comment = H'7E8E91',
|
||||
Red = H'AE81FF',
|
||||
Orange = H'AE81FF',
|
||||
Yellow = H'F8F8F2',
|
||||
Green = H'E6DB74',
|
||||
Aqua = H'66D9EF',
|
||||
Blue = H'F92672',
|
||||
Purple = H'A6E22E',
|
||||
},
|
||||
SolarizedDark = {
|
||||
Background = H'042029',
|
||||
CurrentLine = H'0A2933',
|
||||
@@ -163,6 +177,20 @@ local colors = {
|
||||
Blue = H'859900',
|
||||
Purple = H'268BD2',
|
||||
},
|
||||
NotepadPlusPlus = { -- contributed by Florian (https://github.com/SiENcE)
|
||||
Background = H'FFFFFF',
|
||||
CurrentLine = H'E9E2FF',
|
||||
Selection = H'ADADA1',
|
||||
Foreground = H'000000',
|
||||
Comment = H'008000',
|
||||
Red = H'FF6900',
|
||||
Orange = H'00FF00',
|
||||
Yellow = H'FF4E00',
|
||||
Green = H'808080',
|
||||
Aqua = H'260099',
|
||||
Blue = H'2123FF',
|
||||
Purple = H'FFFFFF',
|
||||
},
|
||||
}
|
||||
|
||||
-- add more of the specified color (keeping all in 0-255 range)
|
||||
@@ -221,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)},
|
||||
|
||||
@@ -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
|
||||
@@ -135,3 +135,8 @@ 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" }
|
||||
|
||||
@@ -57,3 +57,17 @@ ide.app.postinit = function()
|
||||
end
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ An example of how individual keywords can be styled
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local luaspec = G.ide.specs['lua']
|
||||
|
||||
local num = #luaspec.keywords
|
||||
-- take a new slot in the list of keywords (starting from 1)
|
||||
luaspec.keywords[num+1] = 'return'
|
||||
-- remove 'return' from the list of "regular" keywords
|
||||
luaspec.keywords[1] = luaspec.keywords[1]:gsub(' return', '')
|
||||
|
||||
-- assign new style to the added slot (starting from 0)
|
||||
styles["keywords"..num] = {fg = {240, 0, 0}, b = true}
|
||||
--]]
|
||||
|
||||
@@ -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"
|
||||
@@ -52,13 +52,21 @@ 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)
|
||||
DisplayOutput(("Copied ZeroBrane Studio debugger ('mobdebug.lua') to '%s' folder.\n"):format(mdbc))
|
||||
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 debugopt = mac and "-debug 1 -project " or "-debug "
|
||||
local cmd = ('"%s" %s"%s"'):format(corona, rundebug and debugopt or "", file)
|
||||
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)
|
||||
|
||||
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,
|
||||
}
|
||||
@@ -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"
|
||||
@@ -85,8 +85,13 @@ 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
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
local moai
|
||||
local win = ide.osname == "Windows"
|
||||
|
||||
|
||||
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
|
||||
@@ -1,12 +1,12 @@
|
||||
--
|
||||
-- MobDebug 0.526
|
||||
-- MobDebug 0.5401
|
||||
-- Copyright 2011-13 Paul Kulchenko
|
||||
-- Based on RemDebug 1.0 Copyright Kepler Project 2005
|
||||
--
|
||||
|
||||
local mobdebug = {
|
||||
_NAME = "mobdebug",
|
||||
_VERSION = 0.526,
|
||||
_VERSION = 0.5401,
|
||||
_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.24 -- (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}
|
||||
@@ -151,7 +153,7 @@ local function s(t, opts)
|
||||
if seen[t] then -- already seen this element
|
||||
table.insert(sref, 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
|
||||
@@ -161,7 +163,7 @@ local function s(t, opts)
|
||||
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
|
||||
for key in pairs(t) do if not o[key] or key > maxn then table.insert(o, key) end end
|
||||
if opts.sortkeys then alphanumsort(o, t, opts.sortkeys) end
|
||||
for n, key in ipairs(o) do
|
||||
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
|
||||
@@ -277,9 +279,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 +304,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 +318,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 +344,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
|
||||
@@ -446,23 +459,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
|
||||
@@ -513,7 +530,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
|
||||
@@ -643,7 +660,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
|
||||
@@ -808,13 +826,18 @@ 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
|
||||
|
||||
controller_host = lasthost or "localhost"
|
||||
controller_port = lastport or mobdebug.port
|
||||
|
||||
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
|
||||
if server then
|
||||
@@ -849,6 +872,7 @@ 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
|
||||
@@ -860,8 +884,11 @@ 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)
|
||||
@@ -1009,8 +1036,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)
|
||||
@@ -1044,8 +1074,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)
|
||||
@@ -1123,7 +1156,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()
|
||||
@@ -1150,7 +1183,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
|
||||
@@ -1372,6 +1405,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
|
||||
|
||||
118
packages/sample.lua
Normal file
118
packages/sample.lua
Normal file
@@ -0,0 +1,118 @@
|
||||
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) 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)
|
||||
local index = event:GetSelection()
|
||||
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
|
||||
@@ -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
|
||||
|
||||
48
spec/lua.lua
48
spec/lua.lua
@@ -49,16 +49,44 @@ 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()
|
||||
@@ -115,13 +143,21 @@ 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)
|
||||
if (var and typ) then
|
||||
class,func = typ:match(varname.."[%.:]"..varname)
|
||||
if (assigns[typ]) then
|
||||
|
||||
@@ -100,17 +100,21 @@ config = {
|
||||
calltipdelay = nil, -- delay to show calltip (in ms)
|
||||
autoactivate = false, -- auto-activate/open files during debugging
|
||||
smartindent = false, -- use smart indentation if spec allows
|
||||
fold = true, -- enable code folding
|
||||
foldcompact = true, -- use compact fold that includes empty lines
|
||||
checkeol = true, -- check for eol encoding on loaded files and use it
|
||||
-- also report mixed eol encodings
|
||||
defaulteol = nil, -- default line-endings for new files; valid values are
|
||||
-- wxstc.wxSTC_EOL_CRLF, wxstc.wxSTC_EOL_LF and nil (OS default)
|
||||
nomousezoom = nil, -- disable zooming using mouse wheel
|
||||
autoreload = nil, -- trigger auto-reload when file is updated
|
||||
saveallonrun = nil, -- save all modified files before Run/Debug
|
||||
},
|
||||
|
||||
default = {
|
||||
name = 'untitled',
|
||||
fullname = 'untitled.lua',
|
||||
interpreter = 'luadeb',
|
||||
},
|
||||
|
||||
debugger = {
|
||||
@@ -119,6 +123,7 @@ config = {
|
||||
port = nil, -- port number to use
|
||||
runonstart = nil, -- if debugger should run immediately after starting
|
||||
-- default values are different for different interpreters
|
||||
redirect = nil, -- "d", "c", or "r" values for default, copy, or redirect
|
||||
}
|
||||
|
||||
outputshell = { -- output and shell settings
|
||||
@@ -141,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
|
||||
@@ -168,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,54 +36,70 @@ local apis = {
|
||||
lua = newAPI(),
|
||||
}
|
||||
|
||||
function GetApi(apitype)
|
||||
return apis[apitype] or apis["none"]
|
||||
end
|
||||
function GetApi(apitype) return apis[apitype] or apis.none end
|
||||
|
||||
----------
|
||||
-- API loading
|
||||
|
||||
local function addAPI(apifile,only,subapis,known) -- relative to API directory
|
||||
local ftype, fname = apifile:match("api[/\\]([^/\\]+)[/\\](.*)%.")
|
||||
if not ftype or not fname then
|
||||
DisplayOutputLn(TR("The API file must be located in a subdirectory of the API directory."))
|
||||
return
|
||||
end
|
||||
if ((only and ftype ~= only) or (known and not known[ftype])) then
|
||||
return
|
||||
end
|
||||
if (subapis and not subapis[fname]) then return end
|
||||
|
||||
local fn,err = loadfile(apifile)
|
||||
if err then
|
||||
DisplayOutputLn(TR("Error while loading API file: %s"):format(err))
|
||||
return
|
||||
end
|
||||
local env = apis[ftype] or newAPI()
|
||||
apis[ftype] = env
|
||||
env = env.ac.childs
|
||||
local suc,res = pcall(function()return fn(env) end)
|
||||
if (not suc) then
|
||||
DisplayOutputLn(TR("Error while processing API file: %s"):format(res))
|
||||
elseif (res) then
|
||||
local function gennames(tab,prefix)
|
||||
for i,v in pairs(tab) do
|
||||
v.classname = (prefix and (prefix..".") or "")..i
|
||||
if(v.childs) then
|
||||
gennames(v.childs,v.classname)
|
||||
end
|
||||
end
|
||||
end
|
||||
gennames(res)
|
||||
for i,v in pairs(res) do
|
||||
env[i] = v
|
||||
local function gennames(tab, prefix)
|
||||
for i,v in pairs(tab) do
|
||||
v.classname = (prefix and (prefix..".") or "")..i
|
||||
if (v.childs) then
|
||||
gennames(v.childs,v.classname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function loadallAPIs (only,subapis,known)
|
||||
local function addAPI(ftype, fname) -- relative to API directory
|
||||
local env = apis[ftype] or newAPI()
|
||||
|
||||
local res
|
||||
local api = ide.apis[ftype][fname]
|
||||
|
||||
if type(api) == 'table' then
|
||||
res = api
|
||||
else
|
||||
local fn, err = loadfile(api)
|
||||
if err then
|
||||
DisplayOutputLn(TR("Error while loading API file: %s"):format(err))
|
||||
return
|
||||
end
|
||||
local suc
|
||||
suc, res = pcall(function() return fn(env.ac.childs) end)
|
||||
if (not suc) then
|
||||
DisplayOutputLn(TR("Error while processing API file: %s"):format(res))
|
||||
return
|
||||
end
|
||||
-- cache the result
|
||||
ide.apis[ftype][fname] = res
|
||||
end
|
||||
apis[ftype] = env
|
||||
|
||||
gennames(res)
|
||||
for i,v in pairs(res) do env.ac.childs[i] = v end
|
||||
end
|
||||
|
||||
local function loadallAPIs(only, subapis, known)
|
||||
for ftype, v in pairs(only and {[only] = ide.apis[only]} or ide.apis) do
|
||||
if (not known or known[ftype]) then
|
||||
for fname in pairs(v) do
|
||||
if (not subapis or subapis[fname]) then addAPI(ftype, fname) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function scanAPIs()
|
||||
for _, file in ipairs(FileSysGetRecursive("api", true, "*.lua")) do
|
||||
if not file:match(string_Pathsep.."$") then addAPI(file,only,subapis,known) end
|
||||
if not IsDirectory(file) then
|
||||
local ftype, fname = file:match("api[/\\]([^/\\]+)[/\\](.*)%.")
|
||||
if not ftype or not fname then
|
||||
DisplayOutputLn(TR("The API file must be located in a subdirectory of the API directory."))
|
||||
return
|
||||
end
|
||||
ide.apis[ftype] = ide.apis[ftype] or {}
|
||||
ide.apis[ftype][fname] = file
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,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
|
||||
@@ -125,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
|
||||
@@ -193,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
|
||||
@@ -216,15 +235,18 @@ local function resolveAssign(editor,tx)
|
||||
-- this can happen if it's a reference to a value with a known type
|
||||
classname = classname or assigns[c..w]
|
||||
if (s ~= "" and old ~= classname) then
|
||||
-- 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 value is returned; no need to continue.
|
||||
-- this can happen after typing "smth = smth:new(); smth:"
|
||||
if tx == c then break 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
|
||||
@@ -235,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)
|
||||
@@ -282,6 +315,7 @@ do
|
||||
-- by defaul load every known api except lua
|
||||
known.lua = false
|
||||
|
||||
scanAPIs()
|
||||
loadallAPIs(nil,nil,known)
|
||||
generateAPIInfo()
|
||||
end
|
||||
@@ -342,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)
|
||||
@@ -397,7 +428,8 @@ local function getAutoCompApiList(childs,fragment,method)
|
||||
for i,v in pairs(childs) do
|
||||
-- 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 ((method and v.type ~= "value") or (not method and v.type ~= "method"))
|
||||
and v.type then
|
||||
wlist = wlist..i.." "
|
||||
end
|
||||
end
|
||||
@@ -429,7 +461,8 @@ local function getAutoCompApiList(childs,fragment,method)
|
||||
for key,v in pairs(childs) do
|
||||
-- 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 ((method and v.type ~= "value") or (not method and v.type ~= "method"))
|
||||
and v.type then
|
||||
local used = {}
|
||||
--
|
||||
local kl = key:lower()
|
||||
@@ -470,8 +503,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
|
||||
@@ -484,7 +518,7 @@ 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
|
||||
@@ -526,6 +560,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
|
||||
@@ -566,6 +621,14 @@ 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
|
||||
|
||||
|
||||
@@ -11,11 +11,15 @@ local CURRENT_LINE_MARKER = StylesGetMarker("currentline")
|
||||
local CURRENT_LINE_MARKER_VALUE = 2^CURRENT_LINE_MARKER
|
||||
local BREAKPOINT_MARKER = StylesGetMarker("breakpoint")
|
||||
|
||||
function NewFile(event)
|
||||
function NewFile(filename)
|
||||
filename = filename or ide.config.default.fullname
|
||||
local editor = CreateEditor()
|
||||
SetupKeywords(editor, "lua")
|
||||
local doc = AddEditor(editor, ide.config.default.fullname)
|
||||
if doc then SetEditorSelection(doc.index) end
|
||||
SetupKeywords(editor, GetFileExt(filename))
|
||||
local doc = AddEditor(editor, filename)
|
||||
if doc then
|
||||
PackageEventHandle("onEditorNew", editor)
|
||||
SetEditorSelection(doc.index)
|
||||
end
|
||||
return editor
|
||||
end
|
||||
|
||||
@@ -70,9 +74,10 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
editor:SetText(file_text or "")
|
||||
|
||||
-- check the editor as it can be empty if the file has malformed UTF8;
|
||||
-- skip binary files as they may have any sequences; can't show them anyway.
|
||||
-- skip binary files with unknown extensions as they may have any sequences;
|
||||
-- can't show them anyway.
|
||||
if file_text and #file_text > 0 and #(editor:GetText()) == 0
|
||||
and not isBinary(file_text) then
|
||||
and (editor.spec ~= ide.specs.none or not isBinary(file_text)) then
|
||||
local replacement, invalid = "\022"
|
||||
file_text, invalid = fixUTF8(file_text, replacement)
|
||||
if #invalid > 0 then
|
||||
@@ -127,6 +132,9 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
openDocuments[id].filePath = filePath
|
||||
openDocuments[id].fileName = wx.wxFileName(filePath):GetFullName()
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
|
||||
PackageEventHandle("onEditorLoad", editor)
|
||||
|
||||
SetDocumentModified(id, false)
|
||||
|
||||
-- activate the editor; this is needed for those cases when the editor is
|
||||
@@ -173,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()
|
||||
@@ -180,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()
|
||||
@@ -189,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),
|
||||
@@ -203,11 +224,9 @@ end
|
||||
function SaveFileAs(editor)
|
||||
local id = editor:GetId()
|
||||
local saved = false
|
||||
local filePath = openDocuments[id].filePath
|
||||
if (not filePath) then
|
||||
filePath = FileTreeGetDir()
|
||||
filePath = (filePath or "")..ide.config.default.name
|
||||
end
|
||||
local filePath = (openDocuments[id].filePath
|
||||
or ((FileTreeGetDir() or "")
|
||||
..(openDocuments[id].fileName or ide.config.default.name)))
|
||||
|
||||
local fn = wx.wxFileName(filePath)
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
@@ -231,15 +250,30 @@ function SaveFileAs(editor)
|
||||
|
||||
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
|
||||
|
||||
-- check if there is another tab with the same name and close it
|
||||
local fileName = wx.wxFileName(filePath)
|
||||
for _, document in pairs(ide.openDocuments) do
|
||||
if document.filePath and fileName:SameAs(wx.wxFileName(document.filePath)) then
|
||||
-- save the current selection as it may change after closing
|
||||
local current = notebook:GetSelection()
|
||||
ClosePage(document.index)
|
||||
-- restore the selection if it changed
|
||||
if current ~= notebook:GetSelection() then
|
||||
notebook:SetSelection(current)
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -247,12 +281,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
|
||||
@@ -317,14 +352,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
|
||||
@@ -611,7 +645,7 @@ 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
|
||||
@@ -686,11 +720,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
|
||||
@@ -754,6 +791,8 @@ local function closeWindow(event)
|
||||
|
||||
ShowFullScreen(false)
|
||||
|
||||
PackageEventHandle("onAppClose")
|
||||
|
||||
SettingsSaveAll()
|
||||
ide.settings:Flush()
|
||||
|
||||
@@ -782,6 +821,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
|
||||
@@ -70,6 +67,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
|
||||
@@ -98,23 +96,38 @@ local function updateStackSync()
|
||||
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]..")"))
|
||||
|
||||
-- create the new tree item for this level of the call stack
|
||||
local callitem = stackCtrl:AppendItem(root, text, 0)
|
||||
|
||||
-- registed call data to added item
|
||||
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])
|
||||
@@ -126,6 +139,8 @@ local function updateStackSync()
|
||||
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 text = ("%s = %s%s"):
|
||||
@@ -136,6 +151,7 @@ local function updateStackSync()
|
||||
stackCtrl:SetItemHasChildren(item, true)
|
||||
end
|
||||
end
|
||||
|
||||
stackCtrl:SortChildren(callitem)
|
||||
stackCtrl:Expand(callitem)
|
||||
end
|
||||
@@ -204,18 +220,37 @@ end
|
||||
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
|
||||
|
||||
for _, document in pairs(ide.openDocuments) do
|
||||
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
|
||||
@@ -249,17 +284,38 @@ local function activateDocument(file, line, activatehow)
|
||||
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 activatehow == activate.CHECKONLY)
|
||||
and ide.config.editor.autoactivate then
|
||||
and (ide.config.editor.autoactivate or content and activatehow == activate.NOREPORT) then
|
||||
-- found file, but can't activate yet (because this part may be executed
|
||||
-- in a different coroutine), so schedule pending activation.
|
||||
if wx.wxFileName(file):FileExists() then
|
||||
debugger.activate = {file, line}
|
||||
if content or wx.wxFileName(file):FileExists() then
|
||||
debugger.activate = {file, line, content}
|
||||
return true -- report successful activation, even though it's pending
|
||||
end
|
||||
|
||||
@@ -286,7 +342,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
|
||||
@@ -372,7 +428,11 @@ debugger.listen = function()
|
||||
end
|
||||
|
||||
copas.setErrorHandler(function(error)
|
||||
DisplayOutputLn(TR("Can't start debugging session due to internal error '%s'."):format(error))
|
||||
-- ignore errors that happen because debugging session is
|
||||
-- terminated during handshake (server == nil in this case).
|
||||
if debugger.server then
|
||||
DisplayOutputLn(TR("Can't start debugging session due to internal error '%s'."):format(error))
|
||||
end
|
||||
debugger.terminate()
|
||||
end)
|
||||
|
||||
@@ -381,7 +441,11 @@ debugger.listen = function()
|
||||
-- debugger.options may not be set, but runonstart is still configured.
|
||||
if not options.runstart then options.runstart = ide.config.debugger.runonstart end
|
||||
|
||||
if not debugger.scratchpad then SetAllEditorsReadOnly(true) 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
|
||||
@@ -389,6 +453,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
|
||||
@@ -411,11 +476,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
|
||||
@@ -445,7 +509,8 @@ debugger.listen = function()
|
||||
.." "..TR("Compilation error")
|
||||
..":\n"..err)
|
||||
return debugger.terminate()
|
||||
elseif options.runstart and stoppedAtBreakpoint(file, line) then
|
||||
elseif options.runstart and not debugger.scratchpad
|
||||
and stoppedAtBreakpoint(file, line) then
|
||||
activateDocument(file, line)
|
||||
options.runstart = false
|
||||
end
|
||||
@@ -480,8 +545,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
|
||||
@@ -653,8 +721,18 @@ 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
|
||||
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
|
||||
@@ -760,12 +838,28 @@ function debuggerCreateStackWindow()
|
||||
end
|
||||
num = num + 1
|
||||
end
|
||||
|
||||
stackCtrl:SortChildren(item_id)
|
||||
return true
|
||||
end)
|
||||
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
-- 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 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 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)
|
||||
@@ -781,7 +875,7 @@ function debuggerCreateStackWindow()
|
||||
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)
|
||||
|
||||
@@ -871,7 +965,7 @@ local function debuggerCreateWatchWindow()
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
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)
|
||||
@@ -957,7 +1051,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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
-- authors: Lomtik Software (J. Winwood & John Labenski)
|
||||
-- Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
@@ -10,6 +11,7 @@ local statusBar = ide.frame.statusBar
|
||||
local notebook = ide.frame.notebook
|
||||
local funclist = ide.frame.toolBar.funclist
|
||||
local edcfg = ide.config.editor
|
||||
local styles = ide.config.styles
|
||||
local projcombobox = ide.frame.projpanel.projcombobox
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
@@ -107,11 +109,12 @@ local function isFileAlteredOnDisk(editor)
|
||||
GetIDEString("editormessage"),
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
elseif not editor:GetReadOnly() and modTime:IsValid() and oldModTime:IsEarlierThan(modTime) then
|
||||
local ret = wx.wxMessageBox(
|
||||
TR("File '%s' has been modified on disk."):format(fileName)
|
||||
.."\n"..TR("Do you want to reload it?"),
|
||||
GetIDEString("editormessage"),
|
||||
wx.wxYES_NO + wx.wxCENTRE, ide.frame)
|
||||
local ret = (edcfg.autoreload and (not EditorIsModified(editor)) and wx.wxYES)
|
||||
or wx.wxMessageBox(
|
||||
TR("File '%s' has been modified on disk."):format(fileName)
|
||||
.."\n"..TR("Do you want to reload it?"),
|
||||
GetIDEString("editormessage"),
|
||||
wx.wxYES_NO + wx.wxCENTRE, ide.frame)
|
||||
|
||||
if ret ~= wx.wxYES or LoadFile(filePath, editor, true) then
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
@@ -148,6 +151,7 @@ function SetEditorSelection(selection)
|
||||
|
||||
editor:SetFocus()
|
||||
editor:SetSTCFocus(true)
|
||||
|
||||
local id = editor:GetId()
|
||||
FileTreeMarkSelected(openDocuments[id] and openDocuments[id].filePath or '')
|
||||
AddToFileHistory(openDocuments[id] and openDocuments[id].filePath)
|
||||
@@ -214,36 +218,32 @@ function EditorAutoComplete(editor)
|
||||
lt = lt:gsub("%s*(["..editor.spec.sep.."])%s*", "%1")
|
||||
-- strip closed brace scopes
|
||||
lt = lt:gsub("%b()","")
|
||||
lt = lt:gsub("%b[]","")
|
||||
lt = lt:gsub("%b{}","")
|
||||
lt = lt:gsub("%b[]",".0")
|
||||
-- match from starting brace
|
||||
lt = lt:match("[^%[%(%{%s]*$")
|
||||
lt = lt:match("[^%[%(%{%s,]*$")
|
||||
|
||||
-- know now which string is to be completed
|
||||
local userList = CreateAutoCompList(editor,lt)
|
||||
-- don't show the list if the only option is what's already typed
|
||||
if userList and #userList > 0 and userList ~= lt then
|
||||
-- don't show the list if it only suggests what's already typed
|
||||
if userList and #userList > 0 and not lt:find(userList.."$") then
|
||||
editor:UserListShow(1, userList)
|
||||
elseif editor:AutoCompActive() then
|
||||
editor:AutoCompCancel()
|
||||
end
|
||||
end
|
||||
|
||||
local ident = "([a-zA-Z_][a-zA-Z_0-9%.%:]*)"
|
||||
local function getValAtPosition(editor, pos)
|
||||
local line = editor:LineFromPosition(pos)
|
||||
local linetx = editor:GetLine(line)
|
||||
local linestart = editor:PositionFromLine(line)
|
||||
local localpos = pos-linestart
|
||||
|
||||
local ident = "([a-zA-Z_][a-zA-Z_0-9%.%:]*)"
|
||||
local linetxtopos = linetx:sub(1,localpos)
|
||||
linetxtopos = linetxtopos..")"
|
||||
linetxtopos = linetxtopos:match(ident .. "%b()$")
|
||||
|
||||
local selected = editor:GetSelectionStart() ~= editor:GetSelectionEnd()
|
||||
and pos >= editor:GetSelectionStart() and pos <= editor:GetSelectionEnd()
|
||||
|
||||
-- check if we have a selected text or an identifier
|
||||
-- check if we have a selected text or an identifier.
|
||||
-- for an identifier, check fragments on the left and on the right.
|
||||
-- this is to match 'io' in 'i^o.print' and 'io.print' in 'io.pr^int'.
|
||||
-- remove square brackets to make tbl[index].x show proper values.
|
||||
@@ -251,8 +251,22 @@ local function getValAtPosition(editor, pos)
|
||||
:gsub("%b[]", function(s) return ("."):rep(#s) end)
|
||||
:find(ident.."$")
|
||||
|
||||
local right, funccall = linetx:sub(localpos+1,#linetx):match("^([a-zA-Z_0-9]*)%s*(['\"{%(]?)")
|
||||
local var = selected
|
||||
-- GetSelectedText() returns concatenated text when multiple instances
|
||||
-- are selected, so get the selected text based on start/end
|
||||
and editor:GetTextRange(editor:GetSelectionStart(), editor:GetSelectionEnd())
|
||||
or (start and linetx:sub(start,localpos):gsub(":",".")..right or nil)
|
||||
|
||||
-- since this function can be called in different contexts, we need
|
||||
-- to detect function call of different types:
|
||||
-- 1. foo.b^ar(... -- the cursor (pos) is on the function name
|
||||
-- 2. foo.bar(..^. -- the cursor (pos) is on the parameter list
|
||||
-- "var" has value for #1 and the following fragment checks for #2
|
||||
|
||||
-- check if the style is the right one; this is to ignore
|
||||
-- comments, strings, numbers (to avoid '1 = 1'), keywords, and such
|
||||
local goodpos = true
|
||||
if start and not selected then
|
||||
local style = bit.band(editor:GetStyleAt(linestart+start),31)
|
||||
if editor.spec.iscomment[style]
|
||||
@@ -260,25 +274,37 @@ local function getValAtPosition(editor, pos)
|
||||
or editor.spec.isstring[style]
|
||||
or style == wxstc.wxSTC_LUA_NUMBER
|
||||
or style == wxstc.wxSTC_LUA_WORD then
|
||||
-- don't do anything for strings or comments or numbers
|
||||
return nil, linetxtopos
|
||||
goodpos = false
|
||||
end
|
||||
end
|
||||
|
||||
local right = linetx:sub(localpos+1,#linetx):match("^[a-zA-Z_0-9]*")
|
||||
local var = selected and editor:GetSelectedText()
|
||||
or (start and linetx:sub(start,localpos):gsub(":",".")..right or nil)
|
||||
local linetxtopos = linetx:sub(1,localpos)
|
||||
funccall = (#funccall > 0) and goodpos and var
|
||||
or (linetxtopos..")"):match(ident .. "%s*%b()$")
|
||||
or (linetxtopos.."}"):match(ident .. "%s*%b{}$")
|
||||
or (linetxtopos.."'"):match(ident .. "%s*'[^']*'$")
|
||||
or (linetxtopos..'"'):match(ident .. '%s*"[^"]*"$')
|
||||
or nil
|
||||
|
||||
return var, linetxtopos
|
||||
-- don't do anything for strings or comments or numbers
|
||||
if not goodpos then return nil, funccall end
|
||||
|
||||
return var, funccall
|
||||
end
|
||||
|
||||
function EditorCallTip(editor, pos, x, y)
|
||||
-- don't show anything if the calltip is active; this may happen after
|
||||
-- typing function name, while the mouse is over a different function.
|
||||
if editor:CallTipActive() then return end
|
||||
-- don't show anything if the calltip/auto-complete is active;
|
||||
-- this may happen after typing function name, while the mouse is over
|
||||
-- a different function or when auto-complete is on for a parameter.
|
||||
if editor:CallTipActive() or editor:AutoCompActive() then return end
|
||||
|
||||
local var, linetxtopos = getValAtPosition(editor, pos)
|
||||
local tip = linetxtopos and GetTipInfo(editor,linetxtopos.."(",false)
|
||||
-- don't activate if the window itself is not active (in the background)
|
||||
if not ide.frame:IsActive() then return end
|
||||
|
||||
local var, funccall = getValAtPosition(editor, pos)
|
||||
-- if this is a value type rather than a function/method call, then use
|
||||
-- full match to avoid calltip about coroutine.status for "status" vars
|
||||
local tip = GetTipInfo(editor, funccall or var, false, not funccall)
|
||||
if ide.debugger and ide.debugger.server then
|
||||
if var then
|
||||
local limit = 128
|
||||
@@ -315,6 +341,234 @@ function EditorIsModified(editor)
|
||||
return modified
|
||||
end
|
||||
|
||||
-- Indicator handling for functions and local/global variables
|
||||
local function indicateFunctions28(editor, lines, linee)
|
||||
if not (edcfg.showfncall and editor.spec and editor.spec.isfncall)
|
||||
or not (styles.indicator and styles.indicator.fncall) then return end
|
||||
|
||||
local es = editor:GetEndStyled()
|
||||
local lines = lines or 0
|
||||
local linee = linee or editor:GetLineCount()-1
|
||||
|
||||
if (lines < 0) then return end
|
||||
|
||||
local isfncall = editor.spec.isfncall
|
||||
local isinvalid = {}
|
||||
for i,v in pairs(editor.spec.iscomment) do isinvalid[i] = v end
|
||||
for i,v in pairs(editor.spec.iskeyword0) do isinvalid[i] = v end
|
||||
for i,v in pairs(editor.spec.isstring) do isinvalid[i] = v end
|
||||
|
||||
local INDICS_MASK = wxstc.wxSTC_INDICS_MASK
|
||||
local INDIC0_MASK = wxstc.wxSTC_INDIC0_MASK
|
||||
|
||||
for line=lines,linee do
|
||||
local tx = editor:GetLine(line)
|
||||
local ls = editor:PositionFromLine(line)
|
||||
|
||||
local from = 1
|
||||
local off = -1
|
||||
|
||||
editor:StartStyling(ls,INDICS_MASK)
|
||||
editor:SetStyling(#tx,0)
|
||||
while from do
|
||||
tx = from==1 and tx or string.sub(tx,from)
|
||||
|
||||
local f,t,w = isfncall(tx)
|
||||
|
||||
if (f) then
|
||||
local p = ls+f+off
|
||||
local s = bit.band(editor:GetStyleAt(p),31)
|
||||
editor:StartStyling(p,INDICS_MASK)
|
||||
editor:SetStyling(#w,isinvalid[s] and 0 or (INDIC0_MASK + 1))
|
||||
off = off + t
|
||||
end
|
||||
from = t and (t+1)
|
||||
end
|
||||
end
|
||||
editor:StartStyling(es,31)
|
||||
end
|
||||
|
||||
local delayed = {}
|
||||
local tokenlists = {}
|
||||
|
||||
-- indicator.MASKED is handled separately, so don't include in MAX
|
||||
local indicator = {FNCALL = 0, LOCAL = 1, GLOBAL = 2, MASKING = 3, MASKED = 4, MAX = 3}
|
||||
|
||||
function IndicateIfNeeded()
|
||||
local editor = GetEditor()
|
||||
-- do the current one first
|
||||
if delayed[editor] then return IndicateAll(editor) end
|
||||
for editor in pairs(delayed) do return IndicateAll(editor) end
|
||||
end
|
||||
|
||||
-- find all instances of a symbol at pos
|
||||
-- return table with [0] as the definition position (if local)
|
||||
local function indicateFindInstances(editor, name, pos)
|
||||
local tokens = tokenlists[editor] or {}
|
||||
local instances = {{[-1] = 1}}
|
||||
local this
|
||||
for _, token in ipairs(tokens) do
|
||||
local op = token[1]
|
||||
|
||||
if op == 'EndScope' then -- EndScope has "new" level, so need +1
|
||||
if this and token.fpos > pos and this == token.at+1 then break end
|
||||
|
||||
if #instances > 1 and instances[#instances][-1] == token.at+1 then
|
||||
table.remove(instances) end
|
||||
elseif token.name == name then
|
||||
if op == 'Id' then
|
||||
table.insert(instances[#instances], token.fpos)
|
||||
elseif op:find("^Var") then
|
||||
if this and this == token.at then break end
|
||||
|
||||
-- if new Var is defined at the same level, replace the current frame;
|
||||
-- if not, add a new one; skip implicit definition of "self" variable.
|
||||
instances[#instances + (token.at > instances[#instances][-1] and 1 or 0)]
|
||||
= {[0] = (not token.self and token.fpos or nil), [-1] = token.at}
|
||||
end
|
||||
if token.fpos <= pos and pos <= token.fpos+#name then this = instances[#instances][-1] end
|
||||
end
|
||||
end
|
||||
instances[#instances][-1] = nil -- remove the current level
|
||||
-- only return the list if "this" instance has been found;
|
||||
-- this is to avoid reporting (improper) instances when checking for
|
||||
-- comments, strings, table fields, etc.
|
||||
return this and instances[#instances] or {}
|
||||
end
|
||||
|
||||
function IndicateAll(editor, lines, linee)
|
||||
local d = delayed[editor]
|
||||
delayed[editor] = nil -- assume this can be finished for now
|
||||
|
||||
-- this function can be called for an editor tab that is already closed
|
||||
-- when there are still some pending events for it, so handle it.
|
||||
if not pcall(function() return editor:GetId() end) then return end
|
||||
|
||||
if not (editor.spec and editor.spec.markvars) then return end
|
||||
local indic = styles.indicator or {}
|
||||
|
||||
local pos, vars = d and d[1] or 1, d and d[2] or nil
|
||||
local start = lines and editor:PositionFromLine(lines)+1 or nil
|
||||
if d and start and pos >= start then
|
||||
-- ignore delayed processing as the change is earlier in the text
|
||||
pos, vars = 1, nil
|
||||
end
|
||||
|
||||
tokenlists[editor] = tokenlists[editor] or {}
|
||||
local tokens = tokenlists[editor]
|
||||
|
||||
if start then -- if the range is specified
|
||||
local curindic = editor:GetIndicatorCurrent()
|
||||
editor:SetIndicatorCurrent(indicator.MASKED)
|
||||
for n = #tokens, 1, -1 do
|
||||
local token = tokens[n]
|
||||
-- find the last token before the range
|
||||
if token[1] == 'EndScope' and token.name and token.fpos+#token.name < start then
|
||||
pos, vars = token.fpos+#token.name, token.context
|
||||
break
|
||||
end
|
||||
-- unmask all variables from the rest of the list
|
||||
if token[1] == 'Masked' then
|
||||
editor:IndicatorClearRange(token.fpos-1, #token.name)
|
||||
end
|
||||
-- trim the list as it will be re-generated
|
||||
table.remove(tokens, n)
|
||||
end
|
||||
|
||||
-- Clear masked indicators from the current position to the end as these
|
||||
-- will be re-calculated and re-applied based on masking variables.
|
||||
-- This step is needed as some positions could have shifted after updates.
|
||||
editor:IndicatorClearRange(pos-1, editor:GetLength()-pos+1)
|
||||
|
||||
editor:SetIndicatorCurrent(curindic)
|
||||
|
||||
-- need to cleanup vars as they may include variables from later
|
||||
-- fragments (because the cut-point was arbitrary). Also need
|
||||
-- to clean variables in other scopes, hence getmetatable use.
|
||||
local vars = vars
|
||||
while vars do
|
||||
for name, var in pairs(vars) do
|
||||
-- remove all variables that are created later than the current pos
|
||||
while type(var) == 'table' and var.fpos and (var.fpos > pos) do
|
||||
var = var.masked -- restored a masked var
|
||||
vars[name] = var
|
||||
end
|
||||
end
|
||||
vars = getmetatable(vars) and getmetatable(vars).__index
|
||||
end
|
||||
else
|
||||
if pos == 1 then -- if not continuing, then trim the list
|
||||
tokens = {}
|
||||
tokenlists[editor] = tokens
|
||||
end
|
||||
end
|
||||
|
||||
local cleared = {}
|
||||
for indic = 0, indicator.MAX do cleared[indic] = pos end
|
||||
|
||||
local function IndicateOne(indic, pos, length)
|
||||
editor:SetIndicatorCurrent(indic)
|
||||
editor:IndicatorClearRange(cleared[indic]-1, pos-cleared[indic])
|
||||
editor:IndicatorFillRange(pos-1, length)
|
||||
cleared[indic] = pos+length
|
||||
end
|
||||
|
||||
local s = TimeGet()
|
||||
local canwork = start and 0.010 or 0.100 -- use shorter interval when typing
|
||||
local f = editor.spec.markvars(editor:GetText(), pos, vars)
|
||||
|
||||
while true do
|
||||
local op, name, lineinfo, vars, at = f()
|
||||
if not op then break end
|
||||
local var = vars and vars[name]
|
||||
local token = {op, name=name, fpos=lineinfo, at=at, context=vars,
|
||||
self = (op == 'VarSelf') or nil }
|
||||
if op == 'FunctionCall' then
|
||||
if indic.fncall and edcfg.showfncall then
|
||||
IndicateOne(indicator.FNCALL, lineinfo, #name)
|
||||
end
|
||||
elseif op ~= 'VarNext' and op ~= 'VarInside' and op ~= 'Statement' then
|
||||
table.insert(tokens, token)
|
||||
end
|
||||
|
||||
-- indicate local/global variables
|
||||
if op == 'Id'
|
||||
and (var and indic.varlocal or not var and indic.varglobal) then
|
||||
IndicateOne(var and indicator.LOCAL or indicator.GLOBAL, lineinfo, #name)
|
||||
end
|
||||
|
||||
-- indicate masked values at the same level
|
||||
if op == 'Var' and var and (var.masked and at == var.masked.at) then
|
||||
local fpos = var.masked.fpos
|
||||
-- indicate masked if it's not implicit self
|
||||
if indic.varmasked and not var.masked.self then
|
||||
editor:SetIndicatorCurrent(indicator.MASKED)
|
||||
editor:IndicatorFillRange(fpos-1, #name)
|
||||
table.insert(tokens, {"Masked", name=name, fpos=fpos})
|
||||
end
|
||||
|
||||
if indic.varmasking then IndicateOne(indicator.MASKING, lineinfo, #name) end
|
||||
end
|
||||
if op == 'EndScope' and name and TimeGet()-s > canwork then
|
||||
delayed[editor] = {lineinfo+#name, vars}
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- clear indicators till the end of processed fragment
|
||||
local pos = delayed[editor] and delayed[editor][1] or editor:GetLength()+1
|
||||
|
||||
-- don't clear "masked" indicators as those can be set out of order (so
|
||||
-- last updated fragment is not always the last in terms of its position);
|
||||
-- these indicators should be up-to-date to the end of the code fragment.
|
||||
for indic = 0, indicator.MAX do IndicateOne(indic, pos, 0) end
|
||||
|
||||
return delayed[editor] ~= nil -- request more events if still need to work
|
||||
end
|
||||
|
||||
if ide.wxver < "2.9.5" or not ide.config.autoanalizer then
|
||||
IndicateAll = indicateFunctions28 end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Create an editor
|
||||
function CreateEditor()
|
||||
@@ -327,14 +581,14 @@ function CreateEditor()
|
||||
editor.matchon = false
|
||||
editor.assignscache = false
|
||||
|
||||
editor:SetBufferedDraw(true)
|
||||
editor:SetBufferedDraw(not ide.config.hidpi and true or false)
|
||||
editor:StyleClearAll()
|
||||
|
||||
editor:SetFont(ide.font.eNormal)
|
||||
editor:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.font.eNormal)
|
||||
|
||||
editor:SetTabWidth(ide.config.editor.tabwidth or 4)
|
||||
editor:SetIndent(ide.config.editor.tabwidth or 4)
|
||||
editor:SetTabWidth(ide.config.editor.tabwidth or 2)
|
||||
editor:SetIndent(ide.config.editor.tabwidth or 2)
|
||||
editor:SetUseTabs(ide.config.editor.usetabs and true or false)
|
||||
editor:SetIndentationGuides(true)
|
||||
editor:SetViewWhiteSpace(ide.config.editor.whitespace and true or false)
|
||||
@@ -364,10 +618,12 @@ function CreateEditor()
|
||||
editor:MarkerDefine(StylesGetMarker("currentline"))
|
||||
editor:MarkerDefine(StylesGetMarker("breakpoint"))
|
||||
|
||||
editor:SetMarginWidth(2, 16) -- fold margin
|
||||
editor:SetMarginType(2, wxstc.wxSTC_MARGIN_SYMBOL)
|
||||
editor:SetMarginMask(2, wxstc.wxSTC_MASK_FOLDERS)
|
||||
editor:SetMarginSensitive(2, true)
|
||||
if ide.config.editor.fold then
|
||||
editor:SetMarginWidth(2, 16) -- fold margin
|
||||
editor:SetMarginType(2, wxstc.wxSTC_MARGIN_SYMBOL)
|
||||
editor:SetMarginMask(2, wxstc.wxSTC_MASK_FOLDERS)
|
||||
editor:SetMarginSensitive(2, true)
|
||||
end
|
||||
|
||||
editor:SetFoldFlags(wxstc.wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED +
|
||||
wxstc.wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED)
|
||||
@@ -468,8 +724,7 @@ function CreateEditor()
|
||||
if ide.config.acandtip.nodynwords then return end
|
||||
-- only required to track changes
|
||||
if (bit.band(evtype,wxstc.wxSTC_MOD_BEFOREDELETE) ~= 0) then
|
||||
local numlines = 0
|
||||
event:GetText():gsub("(\r?\n)",function() numlines = numlines + 1 end)
|
||||
local _, numlines = event:GetText():gsub("\r?\n","%1")
|
||||
DynamicWordsRem("pre",editor,nil,editor:LineFromPosition(event:GetPosition()), numlines)
|
||||
end
|
||||
if (bit.band(evtype,wxstc.wxSTC_MOD_BEFOREINSERT) ~= 0) then
|
||||
@@ -480,6 +735,7 @@ function CreateEditor()
|
||||
editor:Connect(wxstc.wxEVT_STC_CHARADDED,
|
||||
function (event)
|
||||
-- auto-indent
|
||||
local LF = string.byte("\n")
|
||||
local ch = event:GetKey()
|
||||
local eol = editor:GetEOLMode()
|
||||
local pos = editor:GetCurrentPos()
|
||||
@@ -489,7 +745,9 @@ function CreateEditor()
|
||||
local localpos = pos-linestart
|
||||
local linetxtopos = linetx:sub(1,localpos)
|
||||
|
||||
if (ch == char_LF) then
|
||||
if PackageEventHandle("onEditorCharAdded", editor, event) == false then
|
||||
-- this event has already been handled
|
||||
elseif (ch == LF) then
|
||||
if (line > 0) then
|
||||
local indent = editor:GetLineIndentation(line - 1)
|
||||
local linedone = editor:GetLine(line - 1)
|
||||
@@ -502,8 +760,8 @@ function CreateEditor()
|
||||
indent = editor:GetLineIndentation(line)
|
||||
end
|
||||
|
||||
local tw = editor:GetTabWidth()
|
||||
local ut = editor:GetUseTabs()
|
||||
local tw = ut and editor:GetTabWidth() or editor:GetIndent()
|
||||
|
||||
if ide.config.editor.smartindent
|
||||
and editor.spec.isdecindent and editor.spec.isincindent then
|
||||
@@ -577,18 +835,54 @@ function CreateEditor()
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
editor:Connect(wx.wxEVT_SET_FOCUS,
|
||||
function (event)
|
||||
PackageEventHandle("onEditorFocusSet", editor)
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
editor:Connect(wx.wxEVT_KILL_FOCUS,
|
||||
function (event)
|
||||
if editor:AutoCompActive() then editor:AutoCompCancel() end
|
||||
PackageEventHandle("onEditorFocusLost", editor)
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
editor:Connect(wxstc.wxEVT_STC_USERLISTSELECTION,
|
||||
function (event)
|
||||
local pos = editor:GetCurrentPos()
|
||||
local start_pos = editor:WordStartPosition(pos, true)
|
||||
editor:SetSelection(start_pos, pos)
|
||||
editor:ReplaceSelection(event:GetText())
|
||||
if ide.wxver >= "2.9.5" and editor:GetSelections() > 1 then
|
||||
local text = event:GetText()
|
||||
-- capture all positions as the selection may change
|
||||
local positions = {}
|
||||
for s = 0, editor:GetSelections()-1 do
|
||||
table.insert(positions, editor:GetSelectionNCaret(s))
|
||||
end
|
||||
-- process all selections from last to first
|
||||
table.sort(positions)
|
||||
local mainpos = editor:GetSelectionNCaret(editor:GetMainSelection())
|
||||
|
||||
editor:BeginUndoAction()
|
||||
for s = #positions, 1, -1 do
|
||||
local pos = positions[s]
|
||||
local start_pos = editor:WordStartPosition(pos, true)
|
||||
editor:SetSelection(start_pos, pos)
|
||||
editor:ReplaceSelection(text)
|
||||
-- if this is the main position, save new cursor position to restore
|
||||
if pos == mainpos then mainpos = editor:GetCurrentPos()
|
||||
elseif pos < mainpos then
|
||||
-- adjust main position as earlier changes may affect it
|
||||
mainpos = mainpos + #text - (pos - start_pos)
|
||||
end
|
||||
end
|
||||
editor:EndUndoAction()
|
||||
|
||||
editor:GotoPos(mainpos)
|
||||
else
|
||||
local pos = editor:GetCurrentPos()
|
||||
local start_pos = editor:WordStartPosition(pos, true)
|
||||
editor:SetSelection(start_pos, pos)
|
||||
editor:ReplaceSelection(event:GetText())
|
||||
end
|
||||
end)
|
||||
|
||||
editor:Connect(wxstc.wxEVT_STC_SAVEPOINTREACHED,
|
||||
@@ -622,11 +916,15 @@ function CreateEditor()
|
||||
for _,iv in ipairs(editor.ev) do
|
||||
local line = editor:LineFromPosition(iv[1])
|
||||
if not minupdated or line < minupdated then minupdated = line end
|
||||
IndicateFunctions(editor,line,line+iv[2])
|
||||
local ok, res = pcall(IndicateAll, editor,line,line+iv[2])
|
||||
if not ok then DisplayOutputLn("Internal error: ",res,line,line+iv[2]) end
|
||||
end
|
||||
local firstline = editor:DocLineFromVisible(editor:GetFirstVisibleLine())
|
||||
local firstvisible = editor:DocLineFromVisible(editor:GetFirstVisibleLine())
|
||||
local lastline = math.min(editor:GetLineCount(),
|
||||
editor:DocLineFromVisible(editor:GetFirstVisibleLine() + editor:LinesOnScreen()))
|
||||
firstvisible + editor:LinesOnScreen())
|
||||
-- lastline - editor:LinesOnScreen() can get negative; fix it
|
||||
local firstline = math.min(math.max(0, lastline - editor:LinesOnScreen()),
|
||||
firstvisible)
|
||||
MarkupStyle(editor,minupdated or firstline,lastline)
|
||||
editor.ev = {}
|
||||
end)
|
||||
@@ -667,7 +965,9 @@ function CreateEditor()
|
||||
local keycode = event:GetKeyCode()
|
||||
local mod = event:GetModifiers()
|
||||
local first, last = 0, notebook:GetPageCount()-1
|
||||
if keycode == wx.WXK_ESCAPE and frame:IsFullScreen() then
|
||||
if PackageEventHandle("onEditorKeyDown", editor, event) == false then
|
||||
-- this event has already been handled
|
||||
elseif keycode == wx.WXK_ESCAPE and ide.frame:IsFullScreen() then
|
||||
ShowFullScreen(false)
|
||||
-- Ctrl-Home and Ctrl-End don't work on OSX with 2.9.5+; fix it
|
||||
elseif ide.osname == 'Macintosh' and ide.wxver >= "2.9.5"
|
||||
@@ -726,9 +1026,56 @@ function CreateEditor()
|
||||
end
|
||||
end)
|
||||
|
||||
local value
|
||||
local function selectAllInstances(instances, name, curpos)
|
||||
local this
|
||||
local idx = 0
|
||||
for i, pos in pairs(instances) do
|
||||
pos = pos - 1 -- positions are 0-based in Scintilla
|
||||
if idx == 0 then
|
||||
-- clear selections first as there seems to be a bug (Scintilla 3.2.3)
|
||||
-- that doesn't reset selection after right mouse click.
|
||||
editor:ClearSelections()
|
||||
editor:SetSelection(pos, pos+#name)
|
||||
else
|
||||
editor:AddSelection(pos+#name, pos)
|
||||
end
|
||||
|
||||
-- check if this is the current selection
|
||||
if curpos >= pos and curpos <= pos+#name then this = idx end
|
||||
idx = idx + 1
|
||||
end
|
||||
if this then editor:SetMainSelection(this) end
|
||||
end
|
||||
|
||||
editor:Connect(wxstc.wxEVT_STC_DOUBLECLICK,
|
||||
function(event)
|
||||
-- only activate selection of instances on Ctrl/Cmd-DoubleClick
|
||||
if event:GetModifiers() == wx.wxMOD_CONTROL then
|
||||
local pos = event:GetPosition()
|
||||
local value = pos ~= wxstc.wxSTC_INVALID_POSITION and getValAtPosition(editor, pos) or nil
|
||||
local instances = value and indicateFindInstances(editor, value, pos+1)
|
||||
if instances and (instances[0] or #instances > 0) then
|
||||
selectAllInstances(instances, value, pos)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
local pos, value, instances
|
||||
editor:Connect(wx.wxEVT_CONTEXT_MENU,
|
||||
function (event)
|
||||
local point = editor:ScreenToClient(event:GetPosition())
|
||||
pos = editor:PositionFromPointClose(point.x, point.y)
|
||||
value = pos ~= wxstc.wxSTC_INVALID_POSITION and getValAtPosition(editor, pos) or nil
|
||||
instances = value and indicateFindInstances(editor, value, pos+1)
|
||||
|
||||
local occurrences = (not instances or #instances == 0) and ""
|
||||
or (" (%d)"):format(#instances+(instances[0] and 1 or 0))
|
||||
local line = instances and instances[0] and editor:LineFromPosition(instances[0]-1)+1
|
||||
local def = line and " ("..TR("on line %d"):format(line)..")" or ""
|
||||
|
||||
local menu = wx.wxMenu()
|
||||
menu:Append(ID_UNDO, TR("&Undo"))
|
||||
menu:Append(ID_REDO, TR("&Redo"))
|
||||
@@ -738,13 +1085,15 @@ function CreateEditor()
|
||||
menu:Append(ID_PASTE, TR("&Paste"))
|
||||
menu:Append(ID_SELECTALL, TR("Select &All"))
|
||||
menu:AppendSeparator()
|
||||
menu:Append(ID_GOTODEFINITION, TR("Go To Definition")..def)
|
||||
menu:Append(ID_RENAMEALLINSTANCES, TR("Rename All Instances")..occurrences)
|
||||
menu:AppendSeparator()
|
||||
menu:Append(ID_QUICKADDWATCH, TR("Add Watch Expression"))
|
||||
menu:Append(ID_QUICKEVAL, TR("Evaluate in Console"))
|
||||
menu:Append(ID_ADDTOSCRATCHPAD, TR("Add to Scratchpad"))
|
||||
menu:Append(ID_QUICKEVAL, TR("Evaluate In Console"))
|
||||
menu:Append(ID_ADDTOSCRATCHPAD, TR("Add To Scratchpad"))
|
||||
|
||||
local point = editor:ScreenToClient(event:GetPosition())
|
||||
local pos = editor:PositionFromPointClose(point.x, point.y)
|
||||
value = pos ~= wxstc.wxSTC_INVALID_POSITION and getValAtPosition(editor, pos) or nil
|
||||
menu:Enable(ID_GOTODEFINITION, instances and instances[0])
|
||||
menu:Enable(ID_RENAMEALLINSTANCES, instances and (instances[0] or #instances > 0))
|
||||
menu:Enable(ID_QUICKADDWATCH, value ~= nil)
|
||||
menu:Enable(ID_QUICKEVAL, value ~= nil)
|
||||
|
||||
@@ -752,9 +1101,32 @@ function CreateEditor()
|
||||
menu:Enable(ID_ADDTOSCRATCHPAD, debugger.scratchpad
|
||||
and debugger.scratchpad.editors and not debugger.scratchpad.editors[editor])
|
||||
|
||||
-- cancel calltip as it interferes with popup menu
|
||||
-- disable calltips that could open over the menu
|
||||
local dwelltime = editor:GetMouseDwellTime()
|
||||
editor:SetMouseDwellTime(0) -- disable dwelling
|
||||
|
||||
-- cancel calltip if it's already shown as it interferes with popup menu
|
||||
if editor:CallTipActive() then editor:CallTipCancel() end
|
||||
|
||||
PackageEventHandle("onMenuEditor", menu, editor, event)
|
||||
|
||||
editor:PopupMenu(menu)
|
||||
editor:SetMouseDwellTime(dwelltime) -- restore dwelling
|
||||
end)
|
||||
|
||||
editor:Connect(ID_GOTODEFINITION, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
if value and instances[0] then
|
||||
editor:GotoPos(instances[0]-1)
|
||||
editor:SetAnchor(instances[0]-1+#value)
|
||||
end
|
||||
end)
|
||||
|
||||
editor:Connect(ID_RENAMEALLINSTANCES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function(event)
|
||||
if value and pos then
|
||||
selectAllInstances(instances, value, pos)
|
||||
end
|
||||
end)
|
||||
|
||||
editor:Connect(ID_QUICKADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
@@ -774,10 +1146,10 @@ end
|
||||
function AddEditor(editor, name)
|
||||
if notebook:AddPage(editor, name, true) then
|
||||
local id = editor:GetId()
|
||||
local document = {}
|
||||
local document = setmetatable({}, ide.proto.Document)
|
||||
document.editor = editor
|
||||
document.index = notebook:GetPageIndex(editor)
|
||||
document.fileName = nil
|
||||
document.fileName = name
|
||||
document.filePath = nil
|
||||
document.modTime = nil
|
||||
document.isModified = false
|
||||
@@ -811,51 +1183,6 @@ function GetSpec(ext,forcespec)
|
||||
return spec
|
||||
end
|
||||
|
||||
function IndicateFunctions(editor, lines, linee)
|
||||
if (not (edcfg.showfncall and editor.spec and editor.spec.isfncall)) then return end
|
||||
|
||||
local es = editor:GetEndStyled()
|
||||
local lines = lines or 0
|
||||
local linee = linee or editor:GetLineCount()-1
|
||||
|
||||
if (lines < 0) then return end
|
||||
|
||||
local isfncall = editor.spec.isfncall
|
||||
local isinvalid = {}
|
||||
for i,v in pairs(editor.spec.iscomment) do isinvalid[i] = v end
|
||||
for i,v in pairs(editor.spec.iskeyword0) do isinvalid[i] = v end
|
||||
for i,v in pairs(editor.spec.isstring) do isinvalid[i] = v end
|
||||
|
||||
local INDICS_MASK = wxstc.wxSTC_INDICS_MASK
|
||||
local INDIC0_MASK = wxstc.wxSTC_INDIC0_MASK
|
||||
|
||||
for line=lines,linee do
|
||||
local tx = editor:GetLine(line)
|
||||
local ls = editor:PositionFromLine(line)
|
||||
|
||||
local from = 1
|
||||
local off = -1
|
||||
|
||||
editor:StartStyling(ls,INDICS_MASK)
|
||||
editor:SetStyling(#tx,0)
|
||||
while from do
|
||||
tx = from==1 and tx or string.sub(tx,from)
|
||||
|
||||
local f,t,w = isfncall(tx)
|
||||
|
||||
if (f) then
|
||||
local p = ls+f+off
|
||||
local s = bit.band(editor:GetStyleAt(p),31)
|
||||
editor:StartStyling(p,INDICS_MASK)
|
||||
editor:SetStyling(#w,isinvalid[s] and 0 or (INDIC0_MASK + 1))
|
||||
off = off + t
|
||||
end
|
||||
from = t and (t+1)
|
||||
end
|
||||
end
|
||||
editor:StartStyling(es,31)
|
||||
end
|
||||
|
||||
function SetupKeywords(editor, ext, forcespec, styles, font, fontitalic)
|
||||
local lexerstyleconvert = nil
|
||||
local spec = forcespec or GetSpec(ext)
|
||||
@@ -901,9 +1228,12 @@ function SetupKeywords(editor, ext, forcespec, styles, font, fontitalic)
|
||||
|
||||
-- need to set folding property after lexer is set, otherwise
|
||||
-- the folds are not shown (wxwidgets 2.9.5)
|
||||
editor:SetProperty("fold", "1")
|
||||
editor:SetProperty("fold.compact", ide.config.editor.foldcompact and "1" or "0")
|
||||
editor:SetProperty("fold.comment", "1")
|
||||
if ide.config.editor.fold then
|
||||
editor:SetProperty("fold", "1")
|
||||
editor:SetProperty("fold.html", "1")
|
||||
editor:SetProperty("fold.compact", ide.config.editor.foldcompact and "1" or "0")
|
||||
editor:SetProperty("fold.comment", "1")
|
||||
end
|
||||
|
||||
-- quickfix to prevent weird looks, otherwise need to update styling mechanism for cpp
|
||||
-- cpp "greyed out" styles are styleid + 64
|
||||
|
||||
@@ -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,66 +85,56 @@ 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)
|
||||
if not item_id:IsOk() then break end
|
||||
cur = tree:GetItemText(item_id)
|
||||
if cur and string.len(cur) > 0 then str = cur..string_Pathsep..str end
|
||||
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)
|
||||
|
||||
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 = treeGetItemFullName(tree,treedata,node)
|
||||
local dir = tree:GetItemFullName(node)
|
||||
treeAddDir(tree,node,dir)
|
||||
node = tree:GetItemParent(node)
|
||||
end
|
||||
end
|
||||
|
||||
-- connect to some events from the wxTreeCtrl
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
local dir = treeGetItemFullName(tree,treedata,item_id)
|
||||
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.wxDirExists(name) then treeAddDir(tree,item_id,name)
|
||||
@@ -166,7 +144,21 @@ local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
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())
|
||||
@@ -187,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)
|
||||
@@ -221,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()
|
||||
@@ -282,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)
|
||||
@@ -309,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)
|
||||
@@ -337,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)
|
||||
|
||||
@@ -363,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("^%.%.%.","")).."$"
|
||||
|
||||
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,8 +46,8 @@ end
|
||||
-------------------- Find replace dialog
|
||||
|
||||
local function setSearchFlags(editor)
|
||||
local flags = 0
|
||||
if findReplace.fWholeWord then flags = wxstc.wxSTC_FIND_WHOLEWORD end
|
||||
local flags = wxstc.wxSTC_FIND_POSIX
|
||||
if findReplace.fWholeWord then flags = flags + wxstc.wxSTC_FIND_WHOLEWORD end
|
||||
if findReplace.fMatchCase then flags = flags + wxstc.wxSTC_FIND_MATCHCASE end
|
||||
if findReplace.fRegularExpr then flags = flags + wxstc.wxSTC_FIND_REGEXP end
|
||||
editor:SetSearchFlags(flags)
|
||||
@@ -107,6 +107,8 @@ local function shake(window, shakes, duration, vigour)
|
||||
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
|
||||
@@ -183,7 +185,6 @@ function findReplace:ReplaceString(fReplaceAll, inFileRegister)
|
||||
local replaced = false
|
||||
|
||||
if findReplace:HasText() then
|
||||
local replaceLen = string.len(findReplace.replaceText)
|
||||
local editor = findReplace:GetEditor()
|
||||
local endTarget = inFileRegister and setTargetAll(editor) or
|
||||
setTarget(editor, findReplace.fDown, fReplaceAll, findReplace.fWrap)
|
||||
@@ -198,8 +199,11 @@ function findReplace:ReplaceString(fReplaceAll, inFileRegister)
|
||||
if (inFileRegister) then inFileRegister(posFind) end
|
||||
|
||||
local length = editor:GetLength()
|
||||
editor:ReplaceTarget(findReplace.replaceText)
|
||||
editor:SetTargetStart(posFind + replaceLen)
|
||||
local replaced = findReplace.fRegularExpr
|
||||
and editor:ReplaceTargetRE(findReplace.replaceText)
|
||||
or editor:ReplaceTarget(findReplace.replaceText)
|
||||
|
||||
editor:SetTargetStart(posFind + replaced)
|
||||
-- adjust the endTarget as the position could have changed;
|
||||
-- can't simply subtract findText length as it could be a regexp
|
||||
endTarget = endTarget + (editor:GetLength() - length)
|
||||
@@ -214,10 +218,21 @@ function findReplace:ReplaceString(fReplaceAll, inFileRegister)
|
||||
ide.frame:SetStatusText(("%s %s."):format(
|
||||
TR("Replaced"), TR("%d instance", occurrences):format(occurrences)))
|
||||
else
|
||||
if findReplace.foundString then
|
||||
-- check if there is anything selected as well as the user can
|
||||
-- move the cursor after successful search
|
||||
if findReplace.foundString
|
||||
and editor:GetSelectionStart() ~= editor:GetSelectionEnd() then
|
||||
local start = editor:GetSelectionStart()
|
||||
editor:ReplaceSelection(findReplace.replaceText)
|
||||
editor:SetSelection(start, start + replaceLen)
|
||||
|
||||
-- convert selection to target as we need TargetRE support
|
||||
editor:TargetFromSelection()
|
||||
|
||||
local length = editor:GetLength()
|
||||
local replaced = findReplace.fRegularExpr
|
||||
and editor:ReplaceTargetRE(findReplace.replaceText)
|
||||
or editor:ReplaceTarget(findReplace.replaceText)
|
||||
|
||||
editor:SetSelection(start, start + replaced)
|
||||
findReplace.foundString = false
|
||||
|
||||
replaced = true
|
||||
@@ -239,26 +254,45 @@ local function onFileRegister(pos)
|
||||
end
|
||||
|
||||
local function ProcInFiles(startdir,mask,subdirs,replace)
|
||||
local files = FileSysGetRecursive(startdir,subdirs,mask)
|
||||
local files = FileSysGetRecursive(startdir,subdirs,"*")
|
||||
local start = TimeGet()
|
||||
|
||||
-- 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
|
||||
-- and skip folders as these are included in the list as well
|
||||
if not (replace and findReplace.fMakeBak and file:find('.bak$'))
|
||||
and not file:match(string_Pathsep.."$") then
|
||||
findReplace.curfilename = file
|
||||
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
|
||||
@@ -266,14 +300,14 @@ 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
|
||||
|
||||
ActivateOutput()
|
||||
|
||||
local startdir = findReplace.filedirText
|
||||
DisplayOutputLn(("%s '%s'."):format(
|
||||
(replace and TR("Replacing") or TR("Searching for")),
|
||||
@@ -288,6 +322,18 @@ function findReplace:RunInFiles(replace)
|
||||
findReplace.oveditor = nil
|
||||
end
|
||||
|
||||
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
|
||||
@@ -339,18 +385,21 @@ function findReplace:createDialog(replace,infiles)
|
||||
local infilesDirStat,infilesDirCombo,infilesDirButton
|
||||
if (infiles) then
|
||||
infilesMaskStat = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("File Type")..": ")
|
||||
infilesMaskCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filemaskText,
|
||||
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, 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))
|
||||
infilesDirButton = wx.wxButton(findDialog, ID_SETDIR, "...", wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
end
|
||||
|
||||
local replaceStatText, replaceTextCombo
|
||||
@@ -537,7 +586,7 @@ function findReplace:createDialog(replace,infiles)
|
||||
|
||||
local res = filePicker:ShowModal(true)
|
||||
if res == wx.wxID_OK then
|
||||
infilesDirCombo:SetValue(filePicker:GetPath())
|
||||
infilesDirCombo:SetValue(FixDir(filePicker:GetPath()))
|
||||
end
|
||||
end)
|
||||
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
|
||||
@@ -33,7 +33,7 @@ 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
|
||||
@@ -172,15 +172,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)
|
||||
|
||||
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()
|
||||
@@ -201,6 +211,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
|
||||
|
||||
@@ -15,6 +15,7 @@ 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()
|
||||
@@ -77,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()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- (C) 2012 Paul Kulchenko
|
||||
|
||||
local M, LA, LI, T = {}
|
||||
local FAST = true
|
||||
local FAST = false
|
||||
|
||||
local function init()
|
||||
if LA then return end
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -129,12 +133,16 @@ 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 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
|
||||
@@ -163,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
|
||||
@@ -196,5 +205,7 @@ function MarkupStyle(editor, lines, linee)
|
||||
-- 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,6 +25,7 @@ local editMenu = wx.wxMenu{
|
||||
{ },
|
||||
{ ID_FOLD, TR("&Fold/Unfold All")..KSC(ID_FOLD), TR("Fold or unfold all code folds") },
|
||||
{ ID_CLEARDYNAMICWORDS, TR("Clear &Dynamic Words")..KSC(ID_CLEARDYNAMICWORDS), TR("Resets the dynamic word list for autocompletion") },
|
||||
{ ID_SORT, TR("&Sort")..KSC(ID_SORT), TR("Sort selected lines") },
|
||||
{ },
|
||||
}
|
||||
|
||||
@@ -53,10 +54,10 @@ function OnUpdateUIEditMenu(event)
|
||||
local editor = getControlWithFocus()
|
||||
if editor == nil then event:Enable(false); return end
|
||||
|
||||
local alwaysOn = { [ID_SELECTALL] = true, [ID_FOLD] = true,
|
||||
local alwaysOn = { [ID_SELECTALL] = true, [ID_FOLD] = ide.config.editor.fold,
|
||||
-- allow Cut and Copy commands as these work on a line if no selection
|
||||
[ID_COPY] = true, [ID_CUT] = true,
|
||||
[ID_COMMENT] = true, [ID_AUTOCOMPLETE] = true}
|
||||
[ID_COMMENT] = true, [ID_AUTOCOMPLETE] = true, [ID_SORT] = true}
|
||||
local menu_id = event:GetId()
|
||||
local enable =
|
||||
menu_id == ID_PASTE and editor:CanPaste() or
|
||||
@@ -155,24 +156,82 @@ frame:Connect(ID_AUTOCOMPLETEENABLE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
frame:Connect(ID_COMMENT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local buf = {}
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd() then
|
||||
local lineNumber = editor:GetCurrentLine()
|
||||
editor:SetSelection(editor:PositionFromLine(lineNumber), editor:GetLineEndPosition(lineNumber))
|
||||
end
|
||||
|
||||
-- capture the current position in line to restore later
|
||||
local curline = editor:GetCurrentLine()
|
||||
local curlen = #editor:GetLine(curline)
|
||||
local curpos = editor:GetCurrentPos()-editor:PositionFromLine(curline)
|
||||
|
||||
-- for multi-line selection, always start the first line at the beginning
|
||||
local ssel, esel = editor:GetSelectionStart(), editor:GetSelectionEnd()
|
||||
local sline = editor:LineFromPosition(ssel)
|
||||
local eline = editor:LineFromPosition(esel)
|
||||
local sel = ssel ~= esel
|
||||
local rect = editor:SelectionIsRectangle()
|
||||
local lc = editor.spec.linecomment
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
if string.sub(line,1,#lc) == lc then
|
||||
line = string.sub(line,#lc+1)
|
||||
elseif #line > 0 then
|
||||
line = lc..line
|
||||
local qlc = lc:gsub(".", "%%%1")
|
||||
|
||||
-- figure out how to toggle comments; if there is at least one non-empty
|
||||
-- line that doesn't start with a comment, need to comment
|
||||
local comment = false
|
||||
for line = sline, eline do
|
||||
local pos = sel and (sline == eline or rect)
|
||||
and ssel-editor:PositionFromLine(sline)+1 or 1
|
||||
local text = editor:GetLine(line)
|
||||
local _, cpos = text:find("^%s*"..qlc, pos)
|
||||
if not cpos and text:find("%S")
|
||||
-- ignore last line when the end of selection is at the first position
|
||||
and (line == sline or line < eline or esel-editor:PositionFromLine(line) > 0) then
|
||||
comment = true
|
||||
break
|
||||
end
|
||||
table.insert(buf, line)
|
||||
end
|
||||
editor:ReplaceSelection(table.concat(buf,"\n"))
|
||||
|
||||
editor:BeginUndoAction()
|
||||
-- go last to first as selection positions we captured may be affected
|
||||
-- by text changes
|
||||
for line = eline, sline, -1 do
|
||||
local pos = sel and (sline == eline or rect)
|
||||
and ssel-editor:PositionFromLine(sline)+1 or 1
|
||||
local text = editor:GetLine(line)
|
||||
local _, cpos = text:find("^%s*"..qlc, pos)
|
||||
if not comment and cpos then
|
||||
editor:DeleteRange(cpos-#lc+editor:PositionFromLine(line), #lc)
|
||||
elseif comment and text:find("%S")
|
||||
and (line == sline or line < eline or esel-editor:PositionFromLine(line) > 0) then
|
||||
editor:InsertText(pos+editor:PositionFromLine(line)-1, lc)
|
||||
end
|
||||
end
|
||||
editor:EndUndoAction()
|
||||
|
||||
-- fix position if it was after where the selection started
|
||||
if editor:PositionFromLine(curline)+curpos > ssel then
|
||||
-- position the cursor exactly where its position was, which
|
||||
-- could have shifted depending on whether the text was added or removed.
|
||||
editor:GotoPos(editor:PositionFromLine(curline)
|
||||
+ math.max(0, curpos+#editor:GetLine(curline)-curlen))
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_COMMENT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_SORT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local buf = {}
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
table.insert(buf, line)
|
||||
end
|
||||
if #buf > 0 then
|
||||
local newline
|
||||
if #(buf[#buf]) == 0 then newline = table.remove(buf) end
|
||||
table.sort(buf)
|
||||
-- add new line at the end if it was there
|
||||
if newline then table.insert(buf, newline) end
|
||||
editor:ReplaceSelection(table.concat(buf,"\n"))
|
||||
end
|
||||
end)
|
||||
frame:Connect(ID_SORT, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
|
||||
frame:Connect(ID_FOLD, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
FoldSome()
|
||||
|
||||
@@ -154,7 +154,7 @@ do -- recent file history
|
||||
end
|
||||
end
|
||||
|
||||
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, NewFile)
|
||||
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, function() return NewFile() end)
|
||||
frame:Connect(ID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, OpenFile)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
|
||||
@@ -8,8 +8,24 @@ local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local mobdebug = require "mobdebug"
|
||||
|
||||
local url = "http://download.zerobrane.com/zerobranestudio-"
|
||||
local urls = {
|
||||
[ID_HELPPROJECT] = "main",
|
||||
[ID_HELPDOCUMENTATION] = "documentation",
|
||||
[ID_HELPGETTINGSTARTED] = "gettingstarted",
|
||||
[ID_HELPTUTORIALS] = "tutorials",
|
||||
[ID_HELPFAQ] = "faq",
|
||||
[ID_HELPCOMMUNITY] = "community",
|
||||
}
|
||||
|
||||
local helpMenu = wx.wxMenu{
|
||||
{ ID_ABOUT, TR("&About")..KSC(ID_ABOUT), TR("About %s"):format(GetIDEString("editor")) },
|
||||
{ ID_HELPPROJECT, TR("&Project Page")..KSC(ID_HELPPROJECT) },
|
||||
{ ID_HELPDOCUMENTATION, TR("&Documentation")..KSC(ID_HELPDOCUMENTATION) },
|
||||
{ ID_HELPGETTINGSTARTED, TR("&Getting Started Guide")..KSC(ID_HELPGETTINGSTARTED) },
|
||||
{ ID_HELPTUTORIALS, TR("&Tutorials")..KSC(ID_HELPTUTORIALS) },
|
||||
{ ID_HELPFAQ, TR("&Frequently Asked Questions")..KSC(ID_HELPFAQ) },
|
||||
{ ID_HELPCOMMUNITY, TR("&Community")..KSC(ID_HELPCOMMUNITY) },
|
||||
}
|
||||
-- do not translate Help menu on Mac as it won't merge with "standard" menus
|
||||
menuBar:Append(helpMenu, ide.osname == 'Macintosh' and "&Help" or TR("&Help"))
|
||||
@@ -94,3 +110,7 @@ local function DisplayAbout(event)
|
||||
end
|
||||
|
||||
frame:Connect(ID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED, DisplayAbout)
|
||||
for item, page in pairs(urls) do
|
||||
frame:Connect(item, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function() wx.wxLaunchDefaultBrowser(url..page, 0) end)
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
ide.interpreter = interpreters[id]
|
||||
|
||||
PackageEventHandle("onInterpreterLoad", ide.interpreter)
|
||||
|
||||
DebuggerShutdown()
|
||||
|
||||
ide.frame.statusBar:SetStatusText(ide.interpreter.name or "", 5)
|
||||
ReloadLuaAPI()
|
||||
end
|
||||
|
||||
function ProjectSetInterpreter(name)
|
||||
local id = IDget("debug.interpreter."..name)
|
||||
if (not interpreters[id]) then return end
|
||||
selectInterpreter(id)
|
||||
end
|
||||
|
||||
local function evSelectInterpreter(event)
|
||||
selectInterpreter(event:GetId())
|
||||
end
|
||||
|
||||
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,47 +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]
|
||||
|
||||
DebuggerShutdown()
|
||||
|
||||
ide.frame.statusBar:SetStatusText(ide.interpreter.name or "", 5)
|
||||
ReloadLuaAPI()
|
||||
end
|
||||
|
||||
function ProjectSetInterpreter(name)
|
||||
local id = IDget("debug.interpreter."..name)
|
||||
if (not interpreters[id]) then return end
|
||||
selectInterpreter(id)
|
||||
end
|
||||
|
||||
local function evSelectInterpreter(event)
|
||||
selectInterpreter(event:GetId())
|
||||
end
|
||||
|
||||
for id in pairs(interpreters) do
|
||||
frame:Connect(id,wx.wxEVT_COMMAND_MENU_SELECTED,evSelectInterpreter)
|
||||
end
|
||||
|
||||
do
|
||||
local defaultid = (
|
||||
IDget("debug.interpreter."..ide.config.interpreter) or
|
||||
ID("debug.interpreter."..lastinterpreter)
|
||||
)
|
||||
ide.interpreter = interpreters[defaultid]
|
||||
menuBar:Check(defaultid, true)
|
||||
end
|
||||
----------------------
|
||||
-- Interpreter Running
|
||||
|
||||
local function getNameToRun(skipcheck)
|
||||
local editor = GetEditor()
|
||||
@@ -184,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
|
||||
@@ -313,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
|
||||
@@ -327,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
|
||||
@@ -392,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)
|
||||
@@ -402,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,8 +19,7 @@ local findMenu = wx.wxMenu{
|
||||
{ ID_REPLACEINFILES, TR("Re&place In Files")..KSC(ID_REPLACEINFILES), TR("Find and replace text in files") },
|
||||
{ },
|
||||
{ ID_GOTOLINE, TR("&Goto Line")..KSC(ID_GOTOLINE), TR("Go to a selected line") },
|
||||
{ },
|
||||
{ ID_SORT, TR("&Sort")..KSC(ID_SORT), TR("Sort selected lines") }}
|
||||
}
|
||||
menuBar:Append(findMenu, TR("&Search"))
|
||||
|
||||
function OnUpdateUISearchMenu(event) event:Enable(GetEditor() ~= nil) end
|
||||
@@ -47,12 +46,34 @@ frame:Connect(ID_REPLACEINFILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
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() 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() or findReplace:HasText()) end)
|
||||
|
||||
@@ -73,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)
|
||||
|
||||
@@ -16,9 +16,10 @@ local PROMPT_MARKER_VALUE = 2^PROMPT_MARKER
|
||||
errorlog:Show(true)
|
||||
errorlog:SetFont(ide.font.oNormal)
|
||||
errorlog:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.font.oNormal)
|
||||
errorlog:SetBufferedDraw(not ide.config.hidpi and true or false)
|
||||
errorlog:StyleClearAll()
|
||||
errorlog:SetMarginWidth(1, 16) -- marker margin
|
||||
errorlog:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL);
|
||||
errorlog:SetMarginType(1, wxstc.wxSTC_MARGIN_SYMBOL)
|
||||
errorlog:MarkerDefine(StylesGetMarker("message"))
|
||||
errorlog:MarkerDefine(StylesGetMarker("prompt"))
|
||||
errorlog:SetReadOnly(true)
|
||||
@@ -67,18 +68,18 @@ function DetachChildProcess()
|
||||
end
|
||||
|
||||
function CommandLineRunning(uid)
|
||||
for pid,custom in pairs(customprocs) do
|
||||
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(tostring(pid)))) then
|
||||
return true
|
||||
for pid, custom in pairs(customprocs) do
|
||||
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(pid))) then
|
||||
return pid, custom.proc
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
return
|
||||
end
|
||||
|
||||
function CommandLineToShell(uid,state)
|
||||
for pid,custom in pairs(customprocs) do
|
||||
if ((pid == uid or custom.uid == uid) and custom.proc and custom.proc.Exists(tonumber(tostring(pid))) )then
|
||||
if (pid == uid or custom.uid == uid) and custom.proc and custom.proc.Exists(tonumber(pid)) then
|
||||
if (streamins[pid]) then streamins[pid].toshell = state end
|
||||
if (streamerrs[pid]) then streamerrs[pid].toshell = state end
|
||||
return true
|
||||
@@ -304,33 +305,41 @@ local jumptopatterns = {
|
||||
}
|
||||
|
||||
errorlog:Connect(wxstc.wxEVT_STC_DOUBLECLICK,
|
||||
function()
|
||||
function(event)
|
||||
local line = errorlog:GetCurrentLine()
|
||||
local linetx = errorlog:GetLine(line)
|
||||
-- try to detect a filename + line
|
||||
-- in linetx
|
||||
|
||||
local fname
|
||||
local jumpline
|
||||
local jumplinepos
|
||||
|
||||
-- try to detect a filename and line in linetx
|
||||
local fname, jumpline, jumplinepos
|
||||
for _,pattern in ipairs(jumptopatterns) do
|
||||
fname,jumpline,jumplinepos = linetx:match(pattern)
|
||||
if (fname and jumpline) then
|
||||
break
|
||||
end
|
||||
if (fname and jumpline) then break end
|
||||
end
|
||||
|
||||
if (fname and jumpline) then
|
||||
LoadFile(fname,nil,true)
|
||||
local editor = GetEditor()
|
||||
local name = GetFullPathIfExists(FileTreeGetDir(), fname)
|
||||
or FileTreeFindByPartialName(fname)
|
||||
|
||||
-- fname may include name of executable, as in "path/to/lua: file.lua";
|
||||
-- strip it and try to find match again if needed
|
||||
local fixedname = fname:match(": (.+)")
|
||||
if not name and fixedname then
|
||||
name = GetFullPathIfExists(FileTreeGetDir(), fixedname)
|
||||
or FileTreeFindByPartialName(fixedname)
|
||||
end
|
||||
|
||||
local editor = LoadFile(name or fname,nil,true)
|
||||
if (editor) then
|
||||
jumpline = tonumber(jumpline)
|
||||
jumplinepos = tonumber(jumplinepos)
|
||||
|
||||
--editor:ScrollToLine(jumpline)
|
||||
editor:GotoPos(editor:PositionFromLine(math.max(0,jumpline-1)) + (jumplinepos and (math.max(0,jumplinepos-1)) or 0))
|
||||
editor:GotoPos(editor:PositionFromLine(math.max(0,jumpline-1))
|
||||
+ (jumplinepos and (math.max(0,jumplinepos-1)) or 0))
|
||||
editor:SetFocus()
|
||||
|
||||
-- doubleclick can set selection, so reset it
|
||||
errorlog:SetSelection(event:GetPosition(), event:GetPosition())
|
||||
event:Skip()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
90
src/editor/package.lua
Normal file
90
src/editor/package.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
-- Copyright 2013 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
local ide = ide
|
||||
|
||||
function PackageEventHandle(event, ...)
|
||||
local success
|
||||
for _, package in pairs(ide.packages) do
|
||||
if type(package[event]) == 'function' then
|
||||
local ok, res = pcall(package[event], package, ...)
|
||||
if ok then
|
||||
if res == false then success = false end
|
||||
else
|
||||
DisplayOutputLn(TR("%s event failed: %s"):format(event, res))
|
||||
end
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
function PackageEventHandleOnce(event, ...)
|
||||
local success = PackageEventHandle(event, ...)
|
||||
-- remove all handlers as they need to be called only once
|
||||
-- this allows them to be re-installed if needed
|
||||
for _, package in pairs(ide.packages) do
|
||||
if type(package[event]) == 'function' then
|
||||
package[event] = nil
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
local function PackageEventHandleOne(file, event, ...)
|
||||
local package = ide.packages[file]
|
||||
if package and type(package[event]) == 'function' then
|
||||
local ok, res = pcall(package[event], package, ...)
|
||||
if ok then
|
||||
if res == false then return false end
|
||||
else
|
||||
DisplayOutputLn(TR("%s event failed: %s"):format(event, res))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PackageUnRegister(file, ...)
|
||||
PackageEventHandleOne(file, "onUnRegister", ...)
|
||||
-- remove from the list of installed packages
|
||||
ide.packages[file] = nil
|
||||
end
|
||||
|
||||
function PackageRegister(file, ...)
|
||||
if not ide.packages[file] then
|
||||
local packages = {}
|
||||
local package = MergeFullPath(
|
||||
GetPathWithSep(ide.editorFilename), "packages/"..file..".lua")
|
||||
LoadLuaFileExt(packages, package, ide.proto.Plugin)
|
||||
packages[file].fname = file
|
||||
ide.packages[file] = packages[file]
|
||||
end
|
||||
return PackageEventHandleOne(file, "onRegister", ...)
|
||||
end
|
||||
|
||||
function ide:GetEditor(index) return GetEditor(index) end
|
||||
function ide:GetMenuBar() return self.frame.menuBar end
|
||||
function ide:GetMainFrame() return self.frame end
|
||||
function ide:GetDocument(ed) return self.openDocuments[ed:GetId()] end
|
||||
function ide:GetInterpreter() return self.interpreter end
|
||||
function ide:GetConfig() return self.config end
|
||||
function ide:GetOutput() return self.frame.bottomnotebook.errorlog end
|
||||
function ide:GetEditorNotebook() return self.frame.notebook end
|
||||
|
||||
function ide:AddInterpreter(name, interpreter)
|
||||
self.interpreters[name] = setmetatable(interpreter, ide.proto.Interpreter)
|
||||
UpdateInterpreters()
|
||||
end
|
||||
function ide:RemoveInterpreter(name)
|
||||
self.interpreters[name] = nil
|
||||
UpdateInterpreters()
|
||||
end
|
||||
|
||||
function ide:AddSpec(name, spec)
|
||||
self.specs[name] = spec
|
||||
UpdateSpecs()
|
||||
end
|
||||
function ide:RemoveSpec(name) self.specs[name] = nil end
|
||||
|
||||
function ide:AddAPI(type, name, api)
|
||||
self.apis[type] = self.apis[type] or {}
|
||||
self.apis[type][name] = api
|
||||
end
|
||||
function ide:RemoveAPI(type, name) self.apis[type][name] = nil end
|
||||
21
src/editor/proto.lua
Normal file
21
src/editor/proto.lua
Normal file
@@ -0,0 +1,21 @@
|
||||
-- Copyright 2013 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
ide.proto.Document = {__index = {
|
||||
GetFileName = function(self) return self.fileName end,
|
||||
GetFilePath = function(self) return self.filePath end,
|
||||
GetModTime = function(self) return self.modTime end,
|
||||
IsModified = function(self) return self.isModified end,
|
||||
}}
|
||||
|
||||
ide.proto.Plugin = {__index = {
|
||||
GetName = function(self) return self.name end,
|
||||
GetFileName = function(self) return self.fname end,
|
||||
GetConfig = function(self) return ide.config[self.fname] or {} end,
|
||||
GetSettings = function(self) return SettingsRestorePackage(self.fname) end,
|
||||
SetSettings = function(self, settings) SettingsSavePackage(self.fname, settings) end,
|
||||
}}
|
||||
|
||||
ide.proto.Interpreter = {__index = {
|
||||
GetName = function(self) return self.name end,
|
||||
GetFileName = function(self) return self.fname end,
|
||||
}}
|
||||
@@ -212,7 +212,7 @@ function SettingsSaveProjectSession(projdirs)
|
||||
settings:Write(tostring(i), dir)
|
||||
|
||||
local opendocs, params = ProjectConfig(dir)
|
||||
if opendocs and #opendocs > 0 then
|
||||
if opendocs then
|
||||
SettingsSaveFileSession(opendocs, params, listname .. "/" .. tostring(i))
|
||||
end
|
||||
end
|
||||
@@ -220,6 +220,38 @@ function SettingsSaveProjectSession(projdirs)
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
function SettingsRestorePackage(package)
|
||||
local packagename = "/package/"..package
|
||||
local path = settings:GetPath()
|
||||
settings:SetPath(packagename)
|
||||
local outtab = {}
|
||||
local ismore, key, index = settings:GetFirstEntry("", 0)
|
||||
while (ismore) do
|
||||
local couldread, value = settings:Read(key, "")
|
||||
if couldread then
|
||||
local ok, res = LoadSafe("return "..value)
|
||||
if ok then outtab[key] = res
|
||||
else outtab[key] = nil end
|
||||
end
|
||||
ismore, key, index = settings:GetNextEntry(index)
|
||||
end
|
||||
settings:SetPath(path)
|
||||
return outtab
|
||||
end
|
||||
|
||||
function SettingsSavePackage(package, values)
|
||||
local packagename = "/package/"..package
|
||||
local path = settings:GetPath()
|
||||
local mdb = require('mobdebug')
|
||||
|
||||
settings:DeleteGroup(packagename)
|
||||
settings:SetPath(packagename)
|
||||
for k,v in pairs(values or {}) do
|
||||
settings:Write(k, mdb.line(v, {comment = false, nocode = true}))
|
||||
end
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
-----------------------------------
|
||||
|
||||
local function saveNotebook(nb)
|
||||
@@ -253,8 +285,8 @@ local function saveNotebook(nb)
|
||||
return t
|
||||
end
|
||||
|
||||
sortedX = sortedPages(pagesX)
|
||||
sortedY = sortedPages(pagesY)
|
||||
local sortedX = sortedPages(pagesX)
|
||||
local sortedY = sortedPages(pagesY)
|
||||
|
||||
-- for now only support "1D" splits and prefer
|
||||
-- dimension which has more, anything else
|
||||
|
||||
@@ -17,8 +17,8 @@ local MESSAGE_MARKER = StylesGetMarker("message")
|
||||
|
||||
out:SetFont(ide.font.oNormal)
|
||||
out:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, ide.font.oNormal)
|
||||
out:SetBufferedDraw(not ide.config.hidpi and true or false)
|
||||
out:StyleClearAll()
|
||||
out:SetBufferedDraw(true)
|
||||
|
||||
out:SetTabWidth(ide.config.editor.tabwidth or 2)
|
||||
out:SetIndent(ide.config.editor.tabwidth or 2)
|
||||
@@ -75,10 +75,11 @@ end
|
||||
|
||||
local function getInput(line)
|
||||
local nextMarker = line
|
||||
local count = out:GetLineCount()
|
||||
|
||||
repeat
|
||||
repeat -- check until we find at least some marker
|
||||
nextMarker = nextMarker+1
|
||||
until out:MarkerGet(nextMarker) > 0 -- check until we find at least some marker
|
||||
until out:MarkerGet(nextMarker) > 0 or nextMarker > count-1
|
||||
return chomp(out:GetTextRange(out:PositionFromLine(line),
|
||||
out:PositionFromLine(nextMarker)))
|
||||
end
|
||||
@@ -97,7 +98,6 @@ local function getNextHistoryLine(forward, promptText)
|
||||
else
|
||||
currentHistory = out:MarkerPrevious(currentHistory-1, PROMPT_MARKER_VALUE)
|
||||
if currentHistory == -1 then
|
||||
currentHistory = -1
|
||||
return ""
|
||||
end
|
||||
end
|
||||
@@ -110,6 +110,26 @@ local function getNextHistoryLine(forward, promptText)
|
||||
return getInput(currentHistory)
|
||||
end
|
||||
|
||||
local function getNextHistoryMatch(promptText)
|
||||
local count = out:GetLineCount()
|
||||
if currentHistory == nil then currentHistory = count end
|
||||
|
||||
local current = currentHistory
|
||||
while true do
|
||||
currentHistory = out:MarkerPrevious(currentHistory-1, PROMPT_MARKER_VALUE)
|
||||
if currentHistory == -1 then -- restart search from the last item
|
||||
currentHistory = count
|
||||
elseif currentHistory ~= getPromptLine() then -- skip current prompt
|
||||
local input = getInput(currentHistory)
|
||||
if input:find(promptText, 1, true) == 1 then return input end
|
||||
end
|
||||
-- couldn't find anything and made a loop; get out
|
||||
if currentHistory == current then return end
|
||||
end
|
||||
|
||||
assert(false, "getNextHistoryMatch coudn't find a proper match")
|
||||
end
|
||||
|
||||
local function shellPrint(marker, ...)
|
||||
local cnt = select('#',...)
|
||||
if cnt == 0 then return end -- return if nothing to print
|
||||
@@ -264,6 +284,7 @@ local function executeShellCode(tx)
|
||||
|
||||
local addedret, forceexpression = true, tx:match("^%s*=%s*")
|
||||
tx = tx:gsub("^%s*=%s*","")
|
||||
local fn
|
||||
fn, err = loadstring("return "..tx)
|
||||
if not forceexpression and err and
|
||||
(err:find("'?<eof>'? expected near '") or
|
||||
@@ -331,6 +352,7 @@ function ShellExecuteFile(wfilename)
|
||||
ShellExecuteCode(cmd)
|
||||
end
|
||||
|
||||
ShellExecuteInline = executeShellCode
|
||||
function ShellExecuteCode(code)
|
||||
local index = bottomnotebook:GetPageIndex(bottomnotebook.shellbox)
|
||||
if ide.config.activateoutput and bottomnotebook:GetSelection() ~= index then
|
||||
@@ -378,6 +400,28 @@ out:Connect(wx.wxEVT_KEY_DOWN,
|
||||
local promptText = getPromptText()
|
||||
setPromptText(getNextHistoryLine(true, promptText))
|
||||
return
|
||||
elseif key == wx.WXK_TAB then
|
||||
-- if we are above the prompt line, then don't move
|
||||
local promptline = getPromptLine()
|
||||
if out:GetCurrentLine() < promptline then return end
|
||||
|
||||
local promptText = getPromptText()
|
||||
-- save the position in the prompt text to restore
|
||||
local pos = out:GetCurrentPos()
|
||||
local text = promptText:sub(1, positionInLine(promptline))
|
||||
if #text == 0 then return end
|
||||
|
||||
-- find the next match and set the prompt text
|
||||
local match = getNextHistoryMatch(text)
|
||||
if match then
|
||||
setPromptText(match)
|
||||
-- restore the position to make it easier to find the next match
|
||||
out:GotoPos(pos)
|
||||
end
|
||||
return
|
||||
elseif key == wx.WXK_ESCAPE then
|
||||
setPromptText("")
|
||||
return
|
||||
elseif key == wx.WXK_LEFT or key == wx.WXK_NUMPAD_LEFT then
|
||||
if not caretOnPromptLine(true) then return end
|
||||
elseif key == wx.WXK_BACK then
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
-- Copyright 2011-13 Paul Kulchenko, ZeroBrane LLC
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
----------
|
||||
@@ -7,12 +8,13 @@
|
||||
-- ---------------------------
|
||||
-- fg foreground - {r,g,b} 0-255
|
||||
-- bg background - {r,g,b} 0-255
|
||||
-- sel color of the selected block - {r,g,b} 0-255 (only applies to folds)
|
||||
-- u underline - boolean
|
||||
-- b bold - boolean
|
||||
-- i italic - boolean
|
||||
-- fill fill to end - boolean
|
||||
-- fn font Face Name - string ("Lucida Console")
|
||||
-- fx font size - number (11)
|
||||
-- fs font size - number (11)
|
||||
-- hs turn hotspot on - true or {r,g,b} 0-255
|
||||
-- v visibility for symbols of the current style - boolean
|
||||
|
||||
@@ -50,11 +52,12 @@ function StylesGetDefault()
|
||||
sel = {bg = {192, 192, 192}},
|
||||
caret = {fg = {0, 0, 0}},
|
||||
caretlinebg = {bg = {240, 240, 230}},
|
||||
fold = {fg = {90, 90, 80}, bg = {250, 250, 250}},
|
||||
fold = {fg = {90, 90, 80}, bg = {250, 250, 250}, sel = {90+96, 90, 80}},
|
||||
whitespace = nil,
|
||||
|
||||
fncall = {fg = {128, 128, 255},
|
||||
st = ide.wxver >= "2.9.5" and wxstc.wxSTC_INDIC_ROUNDBOX or wxstc.wxSTC_INDIC_TT},
|
||||
-- deprecated; allowed for backward compatibility in case someone does
|
||||
-- fncall.fg = {...}
|
||||
fncall = {},
|
||||
|
||||
-- markup
|
||||
['|'] = {fg = {127, 0, 127}},
|
||||
@@ -69,7 +72,16 @@ function StylesGetDefault()
|
||||
output = {},
|
||||
prompt = {},
|
||||
error = {},
|
||||
}
|
||||
},
|
||||
|
||||
-- indicators
|
||||
indicator = {
|
||||
fncall = {},
|
||||
varlocal = {},
|
||||
varglobal = {},
|
||||
varmasking = {},
|
||||
varmasked = {},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -83,13 +95,10 @@ local markers = {
|
||||
}
|
||||
function StylesGetMarker(marker) return unpack(markers[marker] or {}) end
|
||||
|
||||
local function applymarker(editor,marker,clrfg,clrbg)
|
||||
if (clrfg) then
|
||||
editor:MarkerSetForeground(marker,clrfg)
|
||||
end
|
||||
if (clrbg) then
|
||||
editor:MarkerSetBackground(marker,clrbg)
|
||||
end
|
||||
local function applymarker(editor,marker,clrfg,clrbg,clrsel)
|
||||
if (clrfg) then editor:MarkerSetForeground(marker,clrfg) end
|
||||
if (clrbg) then editor:MarkerSetBackground(marker,clrbg) end
|
||||
if (ide.wxver >= "2.9.5" and clrsel) then editor:MarkerSetBackgroundSelected(marker,clrsel) end
|
||||
end
|
||||
local specialmapping = {
|
||||
sel = function(editor,style)
|
||||
@@ -103,6 +112,8 @@ local specialmapping = {
|
||||
else
|
||||
editor:SetSelBackground(0,wx.wxWHITE)
|
||||
end
|
||||
-- set alpha for additional selecton: 0 - transparent, 255 - opaque
|
||||
if ide.wxver >= "2.9.5" then editor:SetAdditionalSelAlpha(127) end
|
||||
end,
|
||||
|
||||
caret = function(editor,style)
|
||||
@@ -139,21 +150,25 @@ local specialmapping = {
|
||||
fold = function(editor,style)
|
||||
local clrfg = style.fg and wx.wxColour(unpack(style.fg))
|
||||
local clrbg = style.bg and wx.wxColour(unpack(style.bg))
|
||||
local clrsel = style.sel and wx.wxColour(unpack(style.sel))
|
||||
|
||||
if (clrfg or clrbg) then
|
||||
-- if selected background is set then enable support for it
|
||||
if ide.wxver >= "2.9.5" and clrsel then editor:MarkerEnableHighlight(true) end
|
||||
|
||||
if (clrfg or clrbg or clrsel) then
|
||||
-- foreground and background are defined as opposite to what I'd expect
|
||||
-- for fold markers in Scintilla's terminilogy:
|
||||
-- background is the color of fold lines/boxes and foreground is the color
|
||||
-- of everything around fold lines or inside fold boxes.
|
||||
-- in the following code fg and bg are simply reversed
|
||||
local clrfg, clrbg = clrbg, clrfg
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPEN, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDER, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERSUB, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERTAIL, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEREND, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPENMID, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, clrfg, clrbg)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPEN, clrfg, clrbg, clrsel)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDER, clrfg, clrbg, clrsel)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERSUB, clrfg, clrbg, clrsel)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERTAIL, clrfg, clrbg, clrsel)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEREND, clrfg, clrbg, clrsel)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDEROPENMID, clrfg, clrbg, clrsel)
|
||||
applymarker(editor,wxstc.wxSTC_MARKNUM_FOLDERMIDTAIL, clrfg, clrbg, clrsel)
|
||||
end
|
||||
if clrbg then
|
||||
-- the earlier calls only color the actual markers, but not the
|
||||
@@ -248,8 +263,24 @@ function StylesApplyToEditor(styles,editor,font,fontitalic,lexerconvert)
|
||||
end
|
||||
|
||||
do
|
||||
editor:IndicatorSetStyle(0,styles.fncall and styles.fncall.st or wxstc.wxSTC_INDIC_BOX)
|
||||
editor:IndicatorSetForeground(0,wx.wxColour(unpack(styles.fncall and styles.fncall.fg or {128,128,128})))
|
||||
local defaultfg = styles.text and styles.text.fg or {127,127,127}
|
||||
local indic = styles.indicator or {}
|
||||
|
||||
-- use styles.fncall if not empty and if indic.fncall is empty
|
||||
-- for backward compatibility
|
||||
if type(styles.fncall) == 'table' and next(styles.fncall)
|
||||
and not (type(indic.fncall) == 'table' and next(indic.fncall)) then indic.fncall = styles.fncall end
|
||||
|
||||
editor:IndicatorSetStyle(0, indic.fncall and indic.fncall.st or ide.wxver >= "2.9.5" and wxstc.wxSTC_INDIC_ROUNDBOX or wxstc.wxSTC_INDIC_TT)
|
||||
editor:IndicatorSetForeground(0, wx.wxColour(unpack(indic.fncall and indic.fncall.fg or {128, 128, 255})))
|
||||
editor:IndicatorSetStyle(1, indic.varlocal and indic.varlocal.st or wxstc.wxSTC_INDIC_DOTS or wxstc.wxSTC_INDIC_TT)
|
||||
editor:IndicatorSetForeground(1, wx.wxColour(unpack(indic.varlocal and indic.varlocal.fg or defaultfg)))
|
||||
editor:IndicatorSetStyle(2, indic.varglobal and indic.varglobal.st or wxstc.wxSTC_INDIC_PLAIN)
|
||||
editor:IndicatorSetForeground(2, wx.wxColour(unpack(indic.varglobal and indic.varglobal.fg or defaultfg)))
|
||||
editor:IndicatorSetStyle(3, indic.varmasking and indic.varmasking.st or wxstc.wxSTC_INDIC_DASH or wxstc.wxSTC_INDIC_DIAGONAL)
|
||||
editor:IndicatorSetForeground(3, wx.wxColour(unpack(indic.varmasking and indic.varmasking.fg or defaultfg)))
|
||||
editor:IndicatorSetStyle(4, indic.varmasked and indic.varmasked.st or wxstc.wxSTC_INDIC_STRIKE)
|
||||
editor:IndicatorSetForeground(4, wx.wxColour(unpack(indic.varmasked and indic.varmasked.fg or defaultfg)))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
132
src/main.lua
132
src/main.lua
@@ -45,10 +45,13 @@ ide = {
|
||||
verbose = false,
|
||||
hostname = nil,
|
||||
port = nil,
|
||||
runonstart = nil,
|
||||
redirect = nil,
|
||||
},
|
||||
default = {
|
||||
name = 'untitled',
|
||||
fullname = 'untitled.lua',
|
||||
interpreter = 'luadeb',
|
||||
},
|
||||
outputshell = {},
|
||||
filetree = {},
|
||||
@@ -60,9 +63,9 @@ ide = {
|
||||
|
||||
styles = nil,
|
||||
stylesoutshell = nil,
|
||||
interpreter = "_undefined_",
|
||||
|
||||
autocomplete = true,
|
||||
autoanalizer = true,
|
||||
acandtip = {
|
||||
shorttip = false,
|
||||
ignorecase = false,
|
||||
@@ -78,19 +81,22 @@ ide = {
|
||||
savebak = false,
|
||||
singleinstance = false,
|
||||
singleinstanceport = 0xe493,
|
||||
-- HiDPI/Retina display support;
|
||||
-- `false` by default because of issues with indicators with alpha setting
|
||||
hidpi = false,
|
||||
},
|
||||
specs = {
|
||||
none = {
|
||||
linecomment = ">",
|
||||
sep = "\1",
|
||||
}
|
||||
},
|
||||
tools = {
|
||||
},
|
||||
iofilters = {
|
||||
},
|
||||
interpreters = {
|
||||
},
|
||||
tools = {},
|
||||
iofilters = {},
|
||||
interpreters = {},
|
||||
packages = {},
|
||||
apis = {},
|
||||
|
||||
proto = {}, -- prototypes for various classes
|
||||
|
||||
app = nil, -- application engine
|
||||
interpreter = nil, -- current Lua interpreter
|
||||
@@ -138,10 +144,32 @@ if not wx.wxMOD_CONTROL then wx.wxMOD_CONTROL = 0x02 end
|
||||
if not wx.wxMOD_RAW_CONTROL then
|
||||
wx.wxMOD_RAW_CONTROL = ide.osname == 'Macintosh' and 0x10 or wx.wxMOD_CONTROL
|
||||
end
|
||||
-- ArchLinux running 2.8.12.2 doesn't have wx.wxMOD_SHIFT defined
|
||||
if not wx.wxMOD_SHIFT then wx.wxMOD_SHIFT = 0x04 end
|
||||
-- wxDIR_NO_FOLLOW is missing in wxlua 2.8.12 as well
|
||||
if not wx.wxDIR_NO_FOLLOW then wx.wxDIR_NO_FOLLOW = 0x10 end
|
||||
|
||||
dofile "src/editor/ids.lua"
|
||||
dofile "src/editor/style.lua"
|
||||
dofile "src/editor/keymap.lua"
|
||||
if not setfenv then -- Lua 5.2
|
||||
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
|
||||
-- this assumes f is a function
|
||||
local function findenv(f)
|
||||
local level = 1
|
||||
repeat
|
||||
local name, value = debug.getupvalue(f, level)
|
||||
if name == '_ENV' then return level, value end
|
||||
level = level + 1
|
||||
until name == nil
|
||||
return nil end
|
||||
getfenv = function (f) return(select(2, findenv(f)) or _G) end
|
||||
setfenv = function (f, t)
|
||||
local level = findenv(f)
|
||||
if level then debug.setupvalue(f, level, t) end
|
||||
return f end
|
||||
end
|
||||
|
||||
for _, file in ipairs({"ids", "style", "keymap", "proto"}) do
|
||||
dofile("src/editor/"..file..".lua")
|
||||
end
|
||||
|
||||
ide.config.styles = StylesGetDefault()
|
||||
ide.config.stylesoutshell = StylesGetDefault()
|
||||
@@ -149,12 +177,12 @@ ide.config.stylesoutshell = StylesGetDefault()
|
||||
local function setLuaPaths(mainpath, osname)
|
||||
-- use LUA_DEV to setup paths for Lua for Windows modules if installed
|
||||
local luadev = osname == "Windows" and os.getenv('LUA_DEV')
|
||||
local luadev_path = (luadev
|
||||
local luadev_path = (luadev and wx.wxDirExists(luadev)
|
||||
and ('LUA_DEV/?.lua;LUA_DEV/?/init.lua;LUA_DEV/lua/?.lua;LUA_DEV/lua/?/init.lua')
|
||||
:gsub('LUA_DEV', (luadev:gsub('[\\/]$','')))
|
||||
or "")
|
||||
local luadev_cpath = (luadev
|
||||
and ('LUA_DEV/?.dll;LUA_DEV/clibs/?.dll')
|
||||
local luadev_cpath = (luadev and wx.wxDirExists(luadev)
|
||||
and ('LUA_DEV/?.dll;LUA_DEV/?51.dll;LUA_DEV/clibs/?.dll;LUA_DEV/clibs/?51.dll')
|
||||
:gsub('LUA_DEV', (luadev:gsub('[\\/]$','')))
|
||||
or "")
|
||||
|
||||
@@ -221,45 +249,33 @@ end
|
||||
ide.app = dofile(ide.config.path.app.."/app.lua")
|
||||
local app = assert(ide.app)
|
||||
|
||||
local function addToTab(tab,file)
|
||||
local cfgfn,err = loadfile(file)
|
||||
if not cfgfn then
|
||||
print(("Error while loading configuration file: '%s'."):format(err))
|
||||
else
|
||||
local name = file:match("([a-zA-Z_0-9]+)%.lua$")
|
||||
local success, result = pcall(function()return cfgfn(assert(_G or _ENV))end)
|
||||
if not success then
|
||||
print(("Error while processing configuration file: '%s'."):format(result))
|
||||
elseif name then
|
||||
if (tab[name]) then
|
||||
local out = tab[name]
|
||||
for i,v in pairs(result) do
|
||||
out[i] = v
|
||||
end
|
||||
else
|
||||
tab[name] = result
|
||||
end
|
||||
local function loadToTab(filter, folder, tab, recursive, proto)
|
||||
filter = filter and type(filter) ~= 'function' and app.loadfilters[filter] or nil
|
||||
for _, file in ipairs(FileSysGetRecursive(folder, recursive, "*.lua")) do
|
||||
if not filter or filter(file) then
|
||||
LoadLuaFileExt(tab, file, proto)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- load interpreters
|
||||
local function loadInterpreters(filter)
|
||||
for _, file in ipairs(FileSysGetRecursive("interpreters", true, "*.lua")) do
|
||||
if (filter or app.loadfilters.interpreters)(file) then
|
||||
addToTab(ide.interpreters,file)
|
||||
end
|
||||
end
|
||||
loadToTab(filter or "interpreters", "interpreters", ide.interpreters, false,
|
||||
ide.proto.Interpreter)
|
||||
end
|
||||
|
||||
-- load specs
|
||||
local function loadSpecs(filter)
|
||||
for _, file in ipairs(FileSysGetRecursive("spec", true, "*.lua")) do
|
||||
if (filter or app.loadfilters.specs)(file) then
|
||||
addToTab(ide.specs,file)
|
||||
end
|
||||
end
|
||||
-- load tools
|
||||
local function loadTools(filter)
|
||||
loadToTab(filter or "tools", "tools", ide.tools, false)
|
||||
end
|
||||
|
||||
-- load packages
|
||||
local function loadPackages(filter)
|
||||
loadToTab(filter, "packages", ide.packages, false, ide.proto.Plugin)
|
||||
-- assign file names to each package
|
||||
for fname, package in pairs(ide.packages) do package.fname = fname end
|
||||
end
|
||||
|
||||
function UpdateSpecs()
|
||||
for _, spec in pairs(ide.specs) do
|
||||
spec.sep = spec.sep or "\1" -- default separator doesn't match anything
|
||||
spec.iscomment = {}
|
||||
@@ -285,13 +301,10 @@ local function loadSpecs(filter)
|
||||
end
|
||||
end
|
||||
|
||||
-- load tools
|
||||
local function loadTools(filter)
|
||||
for _, file in ipairs(FileSysGetRecursive("tools", false, "*.lua")) do
|
||||
if (filter or app.loadfilters.tools)(file) then
|
||||
addToTab(ide.tools,file)
|
||||
end
|
||||
end
|
||||
-- load specs
|
||||
local function loadSpecs(filter)
|
||||
loadToTab(filter or "specs", "spec", ide.specs, true)
|
||||
UpdateSpecs()
|
||||
end
|
||||
|
||||
-- temporarily replace print() to capture reported error messages to show
|
||||
@@ -370,7 +383,7 @@ loadSpecs()
|
||||
loadTools()
|
||||
|
||||
do
|
||||
local home = os.getenv("HOME")
|
||||
local home = os.getenv("HOME") or (iswindows and (os.getenv('HOMEDRIVE')..os.getenv('HOMEPATH')))
|
||||
ide.configs = {
|
||||
system = MergeFullPath("cfg", "user.lua"),
|
||||
user = home and MergeFullPath(home, ".zbstudio/user.lua"),
|
||||
@@ -384,18 +397,20 @@ do
|
||||
for _, v in ipairs(configs) do addConfig(v, true) end
|
||||
|
||||
configs = nil
|
||||
local sep = string_Pathsep
|
||||
local sep = GetPathSeparator()
|
||||
if ide.config.language then
|
||||
addToTab(ide.config.messages, "cfg"..sep.."i18n"..sep..ide.config.language..".lua")
|
||||
LoadLuaFileExt(ide.config.messages, "cfg"..sep.."i18n"..sep..ide.config.language..".lua")
|
||||
end
|
||||
end
|
||||
|
||||
loadPackages()
|
||||
|
||||
---------------
|
||||
-- Load App
|
||||
|
||||
for _, file in ipairs({
|
||||
"markup", "settings", "singleinstance", "iofilters",
|
||||
"gui", "filetree", "output", "debugger",
|
||||
"gui", "filetree", "output", "debugger", "package",
|
||||
"editor", "findreplace", "commands", "autocomplete", "shellbox",
|
||||
"menu_file", "menu_edit", "menu_search",
|
||||
"menu_view", "menu_project", "menu_tools", "menu_help",
|
||||
@@ -405,6 +420,9 @@ end
|
||||
|
||||
dofile "src/version.lua"
|
||||
|
||||
-- register all the plugins
|
||||
PackageEventHandle("onRegister")
|
||||
|
||||
-- load rest of settings
|
||||
SettingsRestoreEditorSettings()
|
||||
SettingsRestoreFramePosition(ide.frame, "MainFrame")
|
||||
@@ -443,6 +461,8 @@ end
|
||||
|
||||
resumePrint()
|
||||
|
||||
PackageEventHandle("onAppLoad")
|
||||
|
||||
ide.frame:Show(true)
|
||||
wx.wxGetApp():MainLoop()
|
||||
|
||||
|
||||
140
src/util.lua
140
src/util.lua
@@ -28,14 +28,14 @@ function HasBit(value, num)
|
||||
return true
|
||||
end
|
||||
|
||||
-- ASCII values for common chars
|
||||
char_CR = string.byte("\r")
|
||||
char_LF = string.byte("\n")
|
||||
char_Tab = string.byte("\t")
|
||||
char_Sp = string.byte(" ")
|
||||
function GetPathSeparator()
|
||||
return string.char(wx.wxFileName.GetPathSeparator())
|
||||
end
|
||||
|
||||
string_Pathsep = string.char(wx.wxFileName.GetPathSeparator())
|
||||
stringset_File = '[^"%?%*:\\/<>|]'
|
||||
do
|
||||
local sep = GetPathSeparator()
|
||||
function IsDirectory(dir) return dir:find(sep.."$") end
|
||||
end
|
||||
|
||||
function StripCommentsC(tx)
|
||||
local out = ""
|
||||
@@ -109,21 +109,19 @@ function FileLines(f)
|
||||
end
|
||||
end
|
||||
|
||||
function PrependStringToArray(t, s, maxstrings)
|
||||
function PrependStringToArray(t, s, maxstrings, issame)
|
||||
if string.len(s) == 0 then return end
|
||||
for i, v in ipairs(t) do
|
||||
if v == s then
|
||||
for i = #t, 1, -1 do
|
||||
local v = t[i]
|
||||
if v == s or issame and issame(s, v) then
|
||||
table.remove(t, i) -- remove old copy
|
||||
break
|
||||
-- don't break here in case there are multiple copies to remove
|
||||
end
|
||||
end
|
||||
table.insert(t, 1, s)
|
||||
if #t > (maxstrings or 15) then table.remove(t, #t) end -- keep reasonable length
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Get file modification time, returns a wxDateTime (check IsValid) or nil if
|
||||
-- the file doesn't exist
|
||||
function GetFileModTime(filePath)
|
||||
if filePath and #filePath > 0 then
|
||||
local fn = wx.wxFileName(filePath)
|
||||
@@ -174,7 +172,7 @@ function FileSysGetRecursive(path, recursive, spec, skip)
|
||||
local dir = wx.wxDir(path)
|
||||
if not dir:IsOpened() then return end
|
||||
|
||||
local found, file = dir:GetFirst("*", wx.wxDIR_DIRS)
|
||||
local found, file = dir:GetFirst("*", wx.wxDIR_DIRS + wx.wxDIR_NO_FOLLOW)
|
||||
while found do
|
||||
if not skip or not file:find(skip) then
|
||||
local fname = wx.wxFileName(path, file):GetFullPath()
|
||||
@@ -194,6 +192,17 @@ function FileSysGetRecursive(path, recursive, spec, skip)
|
||||
end
|
||||
getDir(path, spec)
|
||||
|
||||
-- explicitly sort files on Linux; directories first
|
||||
if ide.osname == 'Unix' then
|
||||
table.sort(content, function(a,b)
|
||||
local ad, bd = a:sub(-1) == sep, b:sub(-1) == sep
|
||||
-- both are folders or both are files
|
||||
if ad and bd or not ad and not bd then return a < b
|
||||
-- only one is folder; return true if it's the first one
|
||||
else return ad end
|
||||
end)
|
||||
end
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
@@ -218,7 +227,7 @@ function MergeFullPath(p, f)
|
||||
or nil)
|
||||
end
|
||||
|
||||
function FileWrite(file,content)
|
||||
function FileWrite(file, content)
|
||||
local log = wx.wxLogNull() -- disable error reporting; will report as needed
|
||||
local file = wx.wxFile(file, wx.wxFile.write)
|
||||
if not file:IsOpened() then return nil, wx.wxSysErrorMsg() end
|
||||
@@ -229,9 +238,12 @@ function FileWrite(file,content)
|
||||
end
|
||||
|
||||
function FileRead(file)
|
||||
-- on OSX "Open" dialog allows to open applications, which are folders
|
||||
if wx.wxDirExists(file) then return nil, "Can't read directory as file." end
|
||||
|
||||
local log = wx.wxLogNull() -- disable error reporting; will report as needed
|
||||
local file = wx.wxFile(file, wx.wxFile.read)
|
||||
if not file:IsOpened() then return end
|
||||
if not file:IsOpened() then return nil, wx.wxSysErrorMsg() end
|
||||
|
||||
local _, content = file:Read(file:Length())
|
||||
file:Close()
|
||||
@@ -282,7 +294,29 @@ end
|
||||
|
||||
function RequestAttention()
|
||||
local frame = ide.frame
|
||||
if not frame:IsActive() then frame:RequestUserAttention() end
|
||||
if not frame:IsActive() then
|
||||
frame:RequestUserAttention()
|
||||
if ide.osname == "Macintosh" then
|
||||
local cmd = [[osascript -e 'tell application "%s" to activate']]
|
||||
wx.wxExecute(cmd:format(ide.editorApp:GetAppName()), wx.wxEXEC_ASYNC)
|
||||
elseif ide.osname == "Windows" then
|
||||
local winapi = require 'winapi'
|
||||
if winapi then
|
||||
local pid = winapi.get_current_pid()
|
||||
local wins = winapi.find_all_windows(function(w)
|
||||
return w:get_process():get_pid() == pid
|
||||
and w:get_class_name() == 'wxWindowNR'
|
||||
end)
|
||||
if wins and #wins > 0 then
|
||||
-- found the window, now need to activate it:
|
||||
-- send Alt key to the current window and then
|
||||
-- bring our window to foreground (doesn't work without Alt pressed)
|
||||
winapi.send_to_window(307)
|
||||
wins[1]:set_foreground()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local messages, lang, counter
|
||||
@@ -294,3 +328,73 @@ function TR(msg, count)
|
||||
return count and counter and message and type(message) == 'table'
|
||||
and message[counter(count)] or message or msg
|
||||
end
|
||||
|
||||
-- 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.
|
||||
function FixDir(path)
|
||||
if wx.wxDirExists(path) then return path end
|
||||
|
||||
local dir = wx.wxFileName.DirName(path)
|
||||
local dirs = dir:GetDirs()
|
||||
if #dirs > 1 and dirs[#dirs] == dirs[#dirs-1] then dir:RemoveLastDir() end
|
||||
return dir:GetFullPath()
|
||||
end
|
||||
|
||||
function ShowLocation(fname)
|
||||
local osxcmd = [[osascript -e 'tell application "Finder" to reveal POSIX file "%s"']]
|
||||
.. [[ -e 'tell application "Finder" to activate']]
|
||||
local wincmd = [[explorer /select,"%s"]]
|
||||
local lnxcmd = [[xdg-open "%s"]] -- takes path, not a filename
|
||||
local cmd =
|
||||
ide.osname == "Windows" and wincmd:format(fname) or
|
||||
ide.osname == "Macintosh" and osxcmd:format(fname) or
|
||||
ide.osname == "Unix" and lnxcmd:format(wx.wxFileName(fname):GetPath())
|
||||
if cmd then wx.wxExecute(cmd, wx.wxEXEC_ASYNC) end
|
||||
end
|
||||
|
||||
function LoadLuaFileExt(tab, file, proto)
|
||||
local cfgfn,err = loadfile(file)
|
||||
if not cfgfn then
|
||||
print(("Error while loading file: '%s'."):format(err))
|
||||
else
|
||||
local name = file:match("([a-zA-Z_0-9%-]+)%.lua$")
|
||||
if not name then return end
|
||||
|
||||
-- check if os/arch matches to allow packages for different systems
|
||||
local os, arch = name:match("-(%w+)-?(%w*)")
|
||||
if os and os:lower() ~= ide.osname:lower()
|
||||
or arch and #arch > 0 and arch:lower() ~= ide.osarch:lower()
|
||||
then return end
|
||||
if os then name = name:gsub("-.*","") end
|
||||
|
||||
local success, result = pcall(function()return cfgfn(assert(_G or _ENV))end)
|
||||
if not success then
|
||||
print(("Error while processing file: '%s'."):format(result))
|
||||
else
|
||||
if (tab[name]) then
|
||||
local out = tab[name]
|
||||
for i,v in pairs(result) do
|
||||
out[i] = v
|
||||
end
|
||||
else
|
||||
tab[name] = proto and result and setmetatable(result, proto) or result
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LoadSafe(data)
|
||||
local f, res = loadstring(data)
|
||||
if not f then return f, res end
|
||||
|
||||
local count = 0
|
||||
debug.sethook(function ()
|
||||
count = count + 1
|
||||
if count >= 3 then error("cannot call functions") end
|
||||
end, "c")
|
||||
local ok, res = pcall(f)
|
||||
count = 0
|
||||
debug.sethook()
|
||||
return ok, res
|
||||
end
|
||||
|
||||
69
t/2-autocomplete.lua
Normal file
69
t/2-autocomplete.lua
Normal file
@@ -0,0 +1,69 @@
|
||||
local editor = NewFile()
|
||||
ok(editor, "Open New file.")
|
||||
ok(editor.assignscache ~= nil, "Auto-complete cache is assigned.")
|
||||
|
||||
editor:AddText([[
|
||||
local line = '123'
|
||||
line = line:gsub('1','4')
|
||||
line:]])
|
||||
|
||||
ok(limit(10000, function() CreateAutoCompList(editor, "line:") end),
|
||||
"Auto-complete doesn't loop for 'line:' after 'line:gsub'.")
|
||||
|
||||
ok(limit(10000, function() CreateAutoCompList(editor, "line.") end),
|
||||
"Auto-complete doesn't loop for 'line.' after 'line:gsub'.")
|
||||
|
||||
editor:SetText('') -- use Set/Add to position cursor after added text
|
||||
editor:AddText([[
|
||||
smth = smth:new()
|
||||
smth:]])
|
||||
|
||||
ok(limit(10000, function() CreateAutoCompList(editor, "smth:") end),
|
||||
"Auto-complete doesn't loop for 'smth:'.")
|
||||
|
||||
ok(pcall(CreateAutoCompList, editor, "%1000"),
|
||||
"Auto-complete doesn't trigger 'invalid capture index' on '%...'.")
|
||||
|
||||
editor:SetText('')
|
||||
editor:AddText([[
|
||||
result = result.list[1] --> "does the test" test
|
||||
result.1
|
||||
]])
|
||||
|
||||
ok(limit(10000, function() CreateAutoCompList(editor, "result.1") end),
|
||||
"Auto-complete doesn't loop for table index reference 1/2.")
|
||||
|
||||
editor:SetText('')
|
||||
editor:AddText([[
|
||||
self.popUpObjs = self.undoBuffer[0].sub
|
||||
self.undoBuffer = self.undoBuffer[0]
|
||||
self.popUpObjs[popUpNo].]])
|
||||
|
||||
ok(limit(10000, function() EditorAutoComplete(editor) end),
|
||||
"Auto-complete doesn't loop for table index reference 2/2.")
|
||||
|
||||
local interpreter = ide:GetInterpreter():GetFileName()
|
||||
ProjectSetInterpreter("gideros")
|
||||
|
||||
local ac = CreateAutoCompList(editor, "Bitmap.n")
|
||||
local _, c = ac:gsub("new", "new")
|
||||
ok(c == 1,
|
||||
("Auto-complete doesn't offer duplicates with the same name ('%s').")
|
||||
:format(ac))
|
||||
|
||||
ProjectSetInterpreter(interpreter)
|
||||
|
||||
editor:SetText('')
|
||||
editor:AddText('print(1,io.')
|
||||
|
||||
local value
|
||||
local ULS = editor.UserListShow
|
||||
editor.UserListShow = function(editor, pos, list) value = list end
|
||||
EditorAutoComplete(editor)
|
||||
editor.UserListShow = ULS
|
||||
|
||||
ok(value and value:find("close"), "Auto-complete is shown after comma.")
|
||||
|
||||
-- cleanup
|
||||
ide:GetDocument(editor).isModified = false
|
||||
ClosePage()
|
||||
18
t/3-tooltip.lua
Normal file
18
t/3-tooltip.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
local editor = NewFile()
|
||||
|
||||
editor:SetText('print("select")')
|
||||
-- this is to set proper styles, which are needed for EditorCallTip
|
||||
editor:Colourise(0, -1)
|
||||
|
||||
local value
|
||||
local CTS = editor.CallTipShow
|
||||
editor.CallTipShow = function(editor, pos, tip) value = tip end
|
||||
EditorCallTip(editor, 10)
|
||||
editor.CallTipShow = CTS
|
||||
|
||||
ok(value:find("print") and not value:find("select"),
|
||||
"Tooltip ignores values in strings.")
|
||||
|
||||
-- cleanup
|
||||
ide:GetDocument(editor).isModified = false
|
||||
ClosePage()
|
||||
54
t/4-comment.lua
Normal file
54
t/4-comment.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
local editor = NewFile()
|
||||
local line = "246"
|
||||
local comment = "%-%-"
|
||||
|
||||
editor:AddText(([[
|
||||
1
|
||||
%s
|
||||
3]]):format(line))
|
||||
|
||||
local findReplace = ide.findReplace
|
||||
findReplace.findText = line
|
||||
findReplace:FindString()
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
|
||||
|
||||
local text = editor:GetText()
|
||||
ok(text:find(comment..line) and not text:find(comment.."3"),
|
||||
"One-line selection is commented.")
|
||||
|
||||
findReplace.findText = "--"..line
|
||||
findReplace:FindString()
|
||||
editor:SetCurrentPos(editor:GetLength())
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
|
||||
|
||||
text = editor:GetText()
|
||||
ok(text:find(comment.." "..comment..line) and text:find(comment.."3"),
|
||||
"Commented and uncommented lines are commented.")
|
||||
|
||||
findReplace:FindString()
|
||||
editor:SetCurrentPos(editor:GetLength())
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
|
||||
|
||||
text = editor:GetText()
|
||||
ok(not text:find(comment.." "..comment..line) and not text:find(comment.."3"),
|
||||
"Multi-line commented text is uncommented.")
|
||||
|
||||
editor:SetAnchor(0)
|
||||
editor:SetCurrentPos(editor:PositionFromLine(2))
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_MENU_SELECTED, ID_COMMENT))
|
||||
|
||||
text = editor:GetText()
|
||||
ok(text:find(comment.." "..comment..line) and text:find(comment.."1") and not text:find(comment.."3"),
|
||||
"Selection that ends at the beginning of the line doesn't comment line.")
|
||||
|
||||
-- cleanup
|
||||
ide:GetDocument(editor).isModified = false
|
||||
ClosePage()
|
||||
@@ -16,6 +16,14 @@ ide.app.postinit = function()
|
||||
setfenv(testwell, env)
|
||||
testwell()
|
||||
|
||||
-- add a test function to detect loops
|
||||
function limit (limit, func)
|
||||
debug.sethook(function() error("exceeded") end, "", limit)
|
||||
local ok, res = pcall(func)
|
||||
debug.sethook()
|
||||
return ok, res
|
||||
end
|
||||
|
||||
-- find all test files and load them
|
||||
local files = FileSysGetRecursive("t", true, "*.lua")
|
||||
for k, v in ipairs(files) do
|
||||
|
||||
BIN
zbstudio.exe
BIN
zbstudio.exe
Binary file not shown.
@@ -11,6 +11,8 @@ cfg/i18n/*.lua
|
||||
interpreters/*.lua
|
||||
lualibs/copas/copas.lua
|
||||
lualibs/coxpcall/coxpcall.lua
|
||||
lualibs/lua_lexer_loose.lua
|
||||
lualibs/lua_parser_loose.lua
|
||||
lualibs/luainspect/ast.lua
|
||||
lualibs/luainspect/compat_env.lua
|
||||
lualibs/luainspect/dump.lua
|
||||
@@ -49,10 +51,12 @@ lualibs/socket/url.lua
|
||||
lualibs/ssl.lua
|
||||
lualibs/ssl/https.lua
|
||||
lualibs/testwell.lua
|
||||
packages/sample.lua
|
||||
spec/*.lua
|
||||
src/defs.lua
|
||||
src/editor/autocomplete.lua
|
||||
src/editor/commands.lua
|
||||
src/editor/proto.lua
|
||||
src/editor/debugger.lua
|
||||
src/editor/editor.lua
|
||||
src/editor/filetree.lua
|
||||
@@ -71,6 +75,7 @@ src/editor/menu_search.lua
|
||||
src/editor/menu_tools.lua
|
||||
src/editor/menu_view.lua
|
||||
src/editor/output.lua
|
||||
src/editor/package.lua
|
||||
src/editor/settings.lua
|
||||
src/editor/shellbox.lua
|
||||
src/editor/singleinstance.lua
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>zbstudio.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string></string>
|
||||
<string>com.ZeroBrane.ZeroBraneStudio</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
|
||||
@@ -6,6 +6,7 @@ editor.tabwidth = 2
|
||||
editor.usewrap = true
|
||||
editor.calltipdelay = 500
|
||||
editor.smartindent = true
|
||||
editor.fold = true
|
||||
|
||||
local G = ... -- this now points to the global environment
|
||||
if G.ide.osname == 'Macintosh' then
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
icon ICON "zbstudio.ico"
|
||||
1 RT_MANIFEST zbstudio.manifest
|
||||
1 24 zbstudio.manifest
|
||||
|
||||
Reference in New Issue
Block a user